package mods.railcraft.common.blocks.signals;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.BitSet;
import java.util.EnumMap;
import java.util.Map;
import mods.railcraft.api.signals.IControllerTile;
import mods.railcraft.api.signals.SignalAspect;
import mods.railcraft.api.signals.SimpleSignalController;
import mods.railcraft.common.gui.EnumGui;
import mods.railcraft.common.gui.GuiHandler;
import mods.railcraft.common.plugins.forge.PowerPlugin;
import mods.railcraft.common.util.misc.Game;
import mods.railcraft.common.util.network.DataTools;
import mods.railcraft.common.util.network.IGuiReturnHandler;
import net.minecraft.block.Block;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraftforge.common.util.ForgeDirection;
public class TileBoxAnalogController extends TileBoxBase implements IControllerTile, IGuiReturnHandler {
private final SimpleSignalController controller = new SimpleSignalController(getLocalizationTag(), this);
private int strongestSignal;
public EnumMap<SignalAspect, BitSet> aspects = new EnumMap<SignalAspect, BitSet>(SignalAspect.class);
public TileBoxAnalogController() {
for (SignalAspect aspect : SignalAspect.VALUES) {
aspects.put(aspect, new BitSet());
}
}
@Override
public EnumSignal getSignalType() {
return EnumSignal.BOX_ANALOG_CONTROLLER;
}
@Override
public boolean blockActivated(int side, EntityPlayer player) {
if (player.isSneaking())
return false;
GuiHandler.openGui(EnumGui.BOX_ANALOG_CONTROLLER, player, worldObj, xCoord, yCoord, zCoord);
return true;
}
@Override
public void updateEntity() {
super.updateEntity();
if (Game.isNotHost(worldObj)) {
controller.tickClient();
return;
}
controller.tickServer();
SignalAspect prevAspect = controller.getAspect();
if (controller.isBeingPaired())
controller.setAspect(SignalAspect.BLINK_YELLOW);
else if (controller.isPaired())
controller.setAspect(determineAspect());
else
controller.setAspect(SignalAspect.BLINK_RED);
if (prevAspect != controller.getAspect())
sendUpdateToClient();
}
@Override
public void onNeighborBlockChange(Block block) {
super.onNeighborBlockChange(block);
if (Game.isNotHost(getWorld()))
return;
int s = getPowerLevel();
if (s != strongestSignal) {
strongestSignal = s;
sendUpdateToClient();
}
}
private int getPowerLevel() {
int p = 0, tmp;
for (ForgeDirection side : ForgeDirection.VALID_DIRECTIONS) {
if (side == ForgeDirection.UP)
continue;
if (tileCache.getTileOnSide(side) instanceof TileBoxBase)
continue;
if ((tmp = PowerPlugin.getBlockPowerLevel(worldObj, xCoord, yCoord, zCoord, side)) > p)
p = tmp;
if ((tmp = PowerPlugin.getBlockPowerLevel(worldObj, xCoord, yCoord - 1, zCoord, side)) > p)
p = tmp;
}
return p;
}
private SignalAspect determineAspect() {
SignalAspect aspect = SignalAspect.OFF;
for (Map.Entry<SignalAspect, BitSet> entry : aspects.entrySet()) {
SignalAspect current = entry.getKey();
if (entry.getValue().get(strongestSignal))
aspect = (aspect == SignalAspect.OFF) ? current : SignalAspect.mostRestrictive(aspect, current);
}
return aspect;
}
@Override
public void writeToNBT(NBTTagCompound data) {
super.writeToNBT(data);
data.setInteger("strongestSignal", strongestSignal);
for (Map.Entry<SignalAspect, BitSet> entry : aspects.entrySet()) {
String n = entry.getKey().name();
byte[] bytes = new byte[2];
DataTools.bitSet2ByteArray(entry.getValue(), bytes);
data.setByteArray("aspect_" + n, bytes);
}
controller.writeToNBT(data);
}
@Override
public void readFromNBT(NBTTagCompound data) {
super.readFromNBT(data);
strongestSignal = data.getInteger("strongestSignal");
try {
for (Map.Entry<SignalAspect, BitSet> entry : aspects.entrySet()) {
String n = entry.getKey().name();
byte[] bytes = data.getByteArray("aspect_" + n);
DataTools.byteArray2BitSet(entry.getValue(), bytes);
}
} catch (Exception ex) {
}
controller.readFromNBT(data);
// Legacy Support Code - remove in the future
for (Map.Entry<SignalAspect, BitSet> entry : aspects.entrySet()) {
String n = entry.getKey().toString();
boolean on = data.getBoolean("mode" + n);
if (on) {
int low = data.getInteger("low" + n);
int high = data.getInteger("high" + n);
entry.getValue().set(low, high);
}
}
}
@Override
public void writePacketData(DataOutputStream data) throws IOException {
super.writePacketData(data);
writeGuiData(data);
controller.writePacketData(data);
}
@Override
public void readPacketData(DataInputStream data) throws IOException {
super.readPacketData(data);
readGuiData(data, null);
controller.readPacketData(data);
markBlockForUpdate();
}
@Override
public void writeGuiData(DataOutputStream data) throws IOException {
for (Map.Entry<SignalAspect, BitSet> entry : aspects.entrySet()) {
byte[] bytes = new byte[2];
DataTools.bitSet2ByteArray(entry.getValue(), bytes);
data.write(bytes);
}
}
@Override
public void readGuiData(DataInputStream data, EntityPlayer sender) throws IOException {
for (Map.Entry<SignalAspect, BitSet> entry : aspects.entrySet()) {
byte[] bytes = new byte[2];
data.read(bytes);
DataTools.byteArray2BitSet(entry.getValue(), bytes);
}
}
@Override
public boolean isConnected(ForgeDirection side) {
return false;
}
@Override
public SignalAspect getBoxSignalAspect(ForgeDirection side) {
return controller.getAspect();
}
@Override
public SimpleSignalController getController() {
return controller;
}
}