icbm/src/main/java/icbm/zhapin/jiqi/TRadarTower.java

534 lines
18 KiB
Java

package icbm.zhapin.jiqi;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import calclavia.lib.TileEntityUniversalRunnable;
import dan200.computercraft.api.lua.ILuaContext;
import dan200.computercraft.api.lua.LuaException;
import dan200.computercraft.api.peripheral.IComputerAccess;
import dan200.computercraft.api.peripheral.IPeripheral;
import icbm.api.IItemFrequency;
import icbm.api.RadarRegistry;
import icbm.core.MainBase;
import icbm.zhapin.ICBMExplosion;
import icbm.zhapin.daodan.EMissile;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.Blocks;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.network.NetworkManager;
import net.minecraft.network.Packet;
import net.minecraft.network.play.server.S35PacketUpdateTileEntity;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.AxisAlignedBB;
import net.minecraft.util.ChatComponentText;
import net.minecraft.world.ChunkCoordIntPair;
import net.minecraftforge.common.ForgeChunkManager;
import net.minecraftforge.common.util.ForgeDirection;
import universalelectricity.core.electricity.ElectricityPack;
import universalelectricity.core.vector.Vector2;
import universalelectricity.core.vector.Vector3;
import universalelectricity.prefab.block.BlockAdvanced;
import universalelectricity.prefab.implement.IRedstoneProvider;
import universalelectricity.prefab.multiblock.IMultiBlock;
public class TRadarTower extends TileEntityUniversalRunnable
implements IRedstoneProvider, IMultiBlock, IPeripheral {
public static final int MAX_BIAN_JING = 500;
public float rotation;
public int alarmRadius;
public int safetyRadius;
private List<EMissile> missilesInRange;
public List<Entity> entitiesInRange;
public List<TileEntity> tileEntitiesInRange;
public boolean emitAll;
private ForgeChunkManager.Ticket ticket;
public double wattsForDisplay;
public TRadarTower() {
this.rotation = 0.0f;
this.alarmRadius = 100;
this.safetyRadius = 50;
this.missilesInRange = new ArrayList<>();
this.entitiesInRange = new ArrayList<>();
this.tileEntitiesInRange = new ArrayList<>();
this.emitAll = true;
RadarRegistry.register(this);
}
@Override
public void initiate() {
if (this.worldObj != null) {
this.worldObj.notifyBlocksOfNeighborChange(
this.xCoord,
this.yCoord,
this.zCoord,
this.worldObj.getBlock(this.xCoord, this.yCoord, this.zCoord)
);
}
if (this.ticket == null) {
this.ticket = ForgeChunkManager.requestTicket(
(Object) ICBMExplosion.instance,
this.worldObj,
ForgeChunkManager.Type.NORMAL
);
if (this.ticket != null) {
this.ticket.getModData();
}
}
ForgeChunkManager.forceChunk(
this.ticket, new ChunkCoordIntPair(this.xCoord >> 4, this.zCoord >> 4)
);
}
@Override
public void updateEntity() {
super.updateEntity();
try {
if (!this.worldObj.isRemote) {
this.wattsForDisplay = super.wattsReceived;
if (super.ticks % 40L == 0L) {
this.worldObj.markBlockForUpdate(
this.xCoord, this.yCoord, this.zCoord
);
}
}
if (!this.isDisabled()) {
if (this.canRun()) {
this.rotation += 0.05f;
if (this.rotation > 360.0f) {
this.rotation = 0.0f;
}
if (!this.worldObj.isRemote) {
super.wattsReceived = Math.max(
super.wattsReceived - this.getRequest().getWatts(), 0.0
);
}
final int prevShuMu = this.entitiesInRange.size();
this.doScan();
if (prevShuMu != this.entitiesInRange.size()) {
this.worldObj.notifyBlocksOfNeighborChange(
this.xCoord, this.yCoord, this.zCoord, this.getBlockType()
);
}
} else {
if (this.entitiesInRange.size() > 0) {
this.worldObj.notifyBlocksOfNeighborChange(
this.xCoord, this.yCoord, this.zCoord, this.getBlockType()
);
}
this.entitiesInRange.clear();
this.tileEntitiesInRange.clear();
}
}
if (super.ticks % 40L == 0L) {
this.worldObj.notifyBlocksOfNeighborChange(
this.xCoord, this.yCoord, this.zCoord, this.getBlockType()
);
}
} catch (final Exception e) {
e.printStackTrace();
}
}
private void doScan() {
this.missilesInRange.clear();
this.entitiesInRange.clear();
this.tileEntitiesInRange.clear();
final List<Entity> entities
= RadarRegistry.getEntitiesWithinRadius(new Vector3(this).toVector2(), 500);
for (final Entity entity : entities) {
if (entity instanceof EMissile) {
if (((EMissile) entity).flyingTicks <= -1) {
continue;
}
if (!this.entitiesInRange.contains(entity)) {
this.entitiesInRange.add(entity);
}
if (!this.isWeiXianDaoDan((EMissile) entity)) {
continue;
}
this.missilesInRange.add((EMissile) entity);
} else {
this.entitiesInRange.add(entity);
}
}
final List<EntityPlayer> players = this.worldObj.getEntitiesWithinAABB(
(Class) EntityPlayer.class,
AxisAlignedBB.getBoundingBox(
(double) (this.xCoord - 500),
(double) (this.yCoord - 500),
(double) (this.zCoord - 500),
(double) (this.xCoord + 500),
(double) (this.yCoord + 500),
(double) (this.zCoord + 500)
)
);
for (final EntityPlayer player : players) {
if (player != null) {
boolean youHuoLuan = false;
for (int i = 0; i < player.inventory.getSizeInventory(); ++i) {
final ItemStack itemStack = player.inventory.getStackInSlot(i);
if (itemStack != null
&& itemStack.getItem() instanceof IItemFrequency) {
youHuoLuan = true;
break;
}
}
if (youHuoLuan) {
continue;
}
this.entitiesInRange.add(player);
}
}
for (final TileEntity jiQi : RadarRegistry.getTileEntitiesInArea(
new Vector2(this.xCoord - 500, this.zCoord - 500),
new Vector2(this.xCoord + 500, this.zCoord + 500)
)) {
if (jiQi instanceof TRadarTower) {
if (((TRadarTower) jiQi).isDisabled()
|| ((TRadarTower) jiQi).prevWatts <= 0.0) {
continue;
}
this.tileEntitiesInRange.add(jiQi);
} else {
this.tileEntitiesInRange.add(jiQi);
}
}
}
public boolean isWeiXianDaoDan(final EMissile daoDan) {
return daoDan != null && daoDan.target != null
&& Vector2.distance(
new Vector3(daoDan).toVector2(), new Vector2(this.xCoord, this.zCoord)
)
< this.alarmRadius
&& Vector2.distance(
daoDan.target.toVector2(), new Vector2(this.xCoord, this.zCoord)
)
< this.safetyRadius;
}
@Override
public Packet getDescriptionPacket() {
NBTTagCompound nbt = new NBTTagCompound();
nbt.setDouble("wattsReceived", super.wattsReceived);
nbt.setDouble("wattsForDisplay", this.wattsForDisplay);
nbt.setInteger("disabledTicks", this.disabledTicks);
nbt.setInteger("safetyRadius", this.safetyRadius);
nbt.setInteger("alarmRadius", this.alarmRadius);
return new S35PacketUpdateTileEntity(
this.xCoord, this.yCoord, this.zCoord, this.getBlockMetadata(), nbt
);
}
@Override
public void onDataPacket(NetworkManager net, S35PacketUpdateTileEntity pkt) {
NBTTagCompound nbt = pkt.func_148857_g();
super.wattsReceived = nbt.getDouble("wattsReceived");
this.wattsForDisplay = nbt.getDouble("wattsForDisplay");
this.disabledTicks = nbt.getInteger("disabledTicks");
this.safetyRadius = nbt.getInteger("safetyRadius");
this.alarmRadius = nbt.getInteger("alarmRadius");
}
@Override
public boolean isPoweringTo(final ForgeDirection side) {
if ((super.prevWatts > 0.0 || super.wattsReceived > 0.0)
&& this.missilesInRange.size() > 0) {
if (this.emitAll) {
return true;
}
// This detects which direction a missile is coming from, and emits
// redstone on the other side.
for (final EMissile missile : this.missilesInRange) {
final Vector2 position = new Vector3(missile).toVector2();
ForgeDirection missileSide = ForgeDirection.UNKNOWN;
double closest = -1.0;
for (int i = 2; i < 6; ++i) {
final double dist = Vector2.distance(
position,
new Vector2(
this.xCoord + ForgeDirection.getOrientation(i).offsetX,
this.zCoord + ForgeDirection.getOrientation(i).offsetZ
)
);
if (dist < closest || closest < 0.0) {
missileSide = ForgeDirection.getOrientation(i);
closest = dist;
}
}
if (missileSide.getOpposite() == side) {
return true;
}
}
}
return false;
}
@Override
public boolean isIndirectlyPoweringTo(final ForgeDirection side) {
return this.isPoweringTo(side);
}
@Override
public void readFromNBT(final NBTTagCompound nbt) {
super.readFromNBT(nbt);
this.safetyRadius = nbt.getInteger("safetyRadius");
this.alarmRadius = nbt.getInteger("alarmRadius");
this.emitAll = nbt.getBoolean("emitAll");
}
@Override
public void writeToNBT(final NBTTagCompound par1NBTTagCompound) {
super.writeToNBT(par1NBTTagCompound);
par1NBTTagCompound.setInteger("safetyRadius", this.safetyRadius);
par1NBTTagCompound.setInteger("alarmRadius", this.alarmRadius);
par1NBTTagCompound.setBoolean("emitAll", this.emitAll);
}
@Override
public void onDestroy(final TileEntity callingBlock) {
this.worldObj.setBlock(this.xCoord, this.yCoord, this.zCoord, Blocks.air, 0, 3);
this.worldObj.setBlock(
this.xCoord, this.yCoord + 1, this.zCoord, Blocks.air, 0, 3
);
this.worldObj.setBlock(
this.xCoord + 1, this.yCoord + 1, this.zCoord, Blocks.air, 0, 3
);
this.worldObj.setBlock(
this.xCoord - 1, this.yCoord + 1, this.zCoord, Blocks.air, 0, 3
);
this.worldObj.setBlock(
this.xCoord, this.yCoord + 1, this.zCoord + 1, Blocks.air, 0, 3
);
this.worldObj.setBlock(
this.xCoord, this.yCoord + 1, this.zCoord - 1, Blocks.air, 0, 3
);
this.worldObj.setBlock(
this.xCoord + 1, this.yCoord + 1, this.zCoord + 1, Blocks.air, 0, 3
);
this.worldObj.setBlock(
this.xCoord - 1, this.yCoord + 1, this.zCoord - 1, Blocks.air, 0, 3
);
this.worldObj.setBlock(
this.xCoord + 1, this.yCoord + 1, this.zCoord - 1, Blocks.air, 0, 3
);
this.worldObj.setBlock(
this.xCoord - 1, this.yCoord + 1, this.zCoord + 1, Blocks.air, 0, 3
);
}
@Override
public boolean onActivated(final EntityPlayer entityPlayer) {
if (entityPlayer.inventory.getCurrentItem() != null
&& ((BlockAdvanced) this.getBlockType())
.isUsableWrench(
entityPlayer,
entityPlayer.inventory.getCurrentItem(),
this.xCoord,
this.yCoord,
this.zCoord
)) {
if (!this.worldObj.isRemote) {
this.emitAll = !this.emitAll;
entityPlayer.addChatMessage(new ChatComponentText(
"Radar redstone all side emission: " + this.emitAll
));
}
return true;
}
entityPlayer.openGui(
(Object) ICBMExplosion.instance,
3,
this.worldObj,
this.xCoord,
this.yCoord,
this.zCoord
);
return true;
}
@Override
public void onCreate(final Vector3 position) {
MainBase.bJia.makeFakeBlock(
this.worldObj,
Vector3.add(new Vector3(0.0, 1.0, 0.0), position),
new Vector3(this)
);
MainBase.bJia.makeFakeBlock(
this.worldObj,
Vector3.add(new Vector3(1.0, 1.0, 0.0), position),
new Vector3(this)
);
MainBase.bJia.makeFakeBlock(
this.worldObj,
Vector3.add(new Vector3(-1.0, 1.0, 0.0), position),
new Vector3(this)
);
MainBase.bJia.makeFakeBlock(
this.worldObj,
Vector3.add(new Vector3(0.0, 1.0, 1.0), position),
new Vector3(this)
);
MainBase.bJia.makeFakeBlock(
this.worldObj,
Vector3.add(new Vector3(0.0, 1.0, -1.0), position),
new Vector3(this)
);
MainBase.bJia.makeFakeBlock(
this.worldObj,
Vector3.add(new Vector3(1.0, 1.0, -1.0), position),
new Vector3(this)
);
MainBase.bJia.makeFakeBlock(
this.worldObj,
Vector3.add(new Vector3(-1.0, 1.0, 1.0), position),
new Vector3(this)
);
MainBase.bJia.makeFakeBlock(
this.worldObj,
Vector3.add(new Vector3(1.0, 1.0, 1.0), position),
new Vector3(this)
);
MainBase.bJia.makeFakeBlock(
this.worldObj,
Vector3.add(new Vector3(-1.0, 1.0, -1.0), position),
new Vector3(this)
);
}
public boolean canRun() {
if (this.worldObj.isRemote) {
return this.wattsForDisplay >= this.getRequest().getWatts();
} else {
return super.wattsReceived >= this.getRequest().getWatts();
}
}
@Override
public String getType() {
return "ICBMRadar";
}
@Override
public String[] getMethodNames() {
return new String[] { "getEntities", "getBlocks" };
}
@Override
public Object[] callMethod(
final IComputerAccess computer,
ILuaContext ctx,
final int method,
final Object[] arguments
) throws LuaException {
if (super.wattsReceived < this.getRequest().getWatts()) {
throw new LuaException("Radar has insufficient electricity!");
}
final HashMap<String, Double> returnArray = new HashMap<>();
int count = 0;
switch (method) {
case 0: {
final List<Entity> entities = RadarRegistry.getEntitiesWithinRadius(
new Vector3(this).toVector2(), this.alarmRadius
);
for (final Entity entity : entities) {
// TODO: completely retarded lua API
returnArray.put("x_" + count, entity.posX);
returnArray.put("y_" + count, entity.posY);
returnArray.put("z_" + count, entity.posZ);
++count;
}
return new Object[] { returnArray };
}
case 1: {
for (final TileEntity jiQi : RadarRegistry.getTileEntitiesInArea(
new Vector2(this.xCoord - 500, this.zCoord - 500),
new Vector2(this.xCoord + 500, this.zCoord + 500)
)) {
returnArray.put("x_" + count, (double) jiQi.xCoord);
returnArray.put("y_" + count, (double) jiQi.yCoord);
returnArray.put("z_" + count, (double) jiQi.zCoord);
++count;
}
return new Object[] { returnArray };
}
default: {
throw new LuaException("Invalid ICBM Radar Function.");
}
}
}
@Override
public void invalidate() {
ForgeChunkManager.releaseTicket(this.ticket);
RadarRegistry.unregister(this);
super.invalidate();
}
@Override
public void attach(final IComputerAccess computer) {}
@Override
public void detach(final IComputerAccess computer) {}
@Override
public ElectricityPack getRequest() {
return new ElectricityPack(15.0 / this.getVoltage(), this.getVoltage());
}
@Override
public AxisAlignedBB getRenderBoundingBox() {
return TileEntity.INFINITE_EXTENT_AABB;
}
@Override
public boolean equals(IPeripheral other) {
return this == other;
}
}