package mods.eln.node; import cpw.mods.fml.common.FMLCommonHandler; import mods.eln.Eln; import mods.eln.GuiHandler; import mods.eln.ghost.GhostBlock; import mods.eln.misc.*; import mods.eln.node.six.SixNode; import mods.eln.sim.*; import net.minecraft.block.Block; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.item.EntityItem; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.init.Blocks; import net.minecraft.inventory.IInventory; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.server.MinecraftServer; import net.minecraft.server.management.PlayerManager; import net.minecraft.world.World; import net.minecraft.world.WorldServer; import java.io.ByteArrayOutputStream; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.util.ArrayList; public abstract class NodeBase { public static final int maskElectricalPower = 1 << 0; public static final int maskThermal = 1 << 1; public static final int maskElectricalGate = (1 << 2); public static final int maskElectricalAll = maskElectricalPower | maskElectricalGate; public static final int maskElectricalInputGate = maskElectricalGate; public static final int maskElectricalOutputGate = maskElectricalGate; public static final int maskWire = 0; public static final int maskElectricalWire = (1 << 3); public static final int maskThermalWire = maskWire + maskThermal; public static final int maskSignal = (1 << 9); public static final int maskRs485 = (1 << 10); public static final int maskColorData = 0xF << 16; public static final int maskColorShift = 16; public static final int maskColorCareShift = 20; public static final int maskColorCareData = 1 << 20; public static final double networkSerializeUFactor = 10.0; public static final double networkSerializeIFactor = 100.0; public static final double networkSerializeTFactor = 10.0; public byte neighborOpaque; public byte neighborWrapable; public static int teststatic; public Coordonate coordonate; public ArrayList<NodeConnection> nodeConnectionList = new ArrayList<NodeConnection>(4); private boolean initialized = false; private boolean isAdded = false; private boolean needPublish = false; // public static boolean canBePlacedOn(ItemStack itemStack,Direction side) public boolean mustBeSaved() { return true; } public int getBlockMetadata() { return 0; } public void networkUnserialize(DataInputStream stream, EntityPlayerMP player) { } public void notifyNeighbor() { coordonate.world().notifyBlockChange(coordonate.x, coordonate.y, coordonate.z, coordonate.getBlock()); } //public abstract Block getBlock(); public abstract String getNodeUuid(); public LRDUCubeMask lrduCubeMask = new LRDUCubeMask(); public void neighborBlockRead() { int[] vector = new int[3]; World world = coordonate.world(); neighborOpaque = 0; neighborWrapable = 0; for (Direction direction : Direction.values()) { vector[0] = coordonate.x; vector[1] = coordonate.y; vector[2] = coordonate.z; direction.applyTo(vector, 1); Block b = world.getBlock(vector[0], vector[1], vector[2]); if (b.isOpaqueCube()) ; neighborOpaque |= 1 << direction.getInt(); if (isBlockWrappable(b, world, coordonate.x, coordonate.y, coordonate.z)) neighborWrapable |= 1 << direction.getInt(); } } public boolean hasGui(Direction side) { return false; } public void onNeighborBlockChange() { neighborBlockRead(); if (isAdded) { reconnect(); } } public boolean isBlockWrappable(Direction direction) { return ((neighborWrapable >> direction.getInt()) & 1) != 0; } public boolean isBlockOpaque(Direction direction) { return ((neighborOpaque >> direction.getInt()) & 1) != 0; } public static boolean isBlockWrappable(Block block, World w, int x, int y, int z) { if (block.isReplaceable(w, x, y, z)) return true; if (block == Blocks.air) return true; if (block == Eln.sixNodeBlock) return true; if (block instanceof GhostBlock) return true; if (block == Blocks.torch) return true; if (block == Blocks.redstone_torch) return true; if (block == Blocks.unlit_redstone_torch) return true; if (block == Blocks.redstone_wire) return true; return false; } public NodeBase() { coordonate = new Coordonate(); } boolean destructed = false; public boolean isDestructing() { return destructed; } public void physicalSelfDestruction(float explosionStrength) { if (destructed == true) return; destructed = true; if (Eln.instance.explosionEnable == false) explosionStrength = 0; disconnect(); coordonate.world().setBlockToAir(coordonate.x, coordonate.y, coordonate.z); NodeManager.instance.removeNode(this); if (explosionStrength != 0) { coordonate.world().createExplosion((Entity) null, coordonate.x, coordonate.y, coordonate.z, explosionStrength, true); } } // NodeBaseTodo public void onBlockPlacedBy(Coordonate coordonate, Direction front, EntityLivingBase entityLiving, ItemStack itemStack) { // this.entity = entity; this.coordonate = coordonate; neighborBlockRead(); NodeManager.instance.addNode(this); initializeFromThat(front, entityLiving, itemStack); if (itemStack != null) Utils.println("Node::constructor( meta = " + itemStack.getItemDamage() + ")"); } abstract public void initializeFromThat(Direction front, EntityLivingBase entityLiving, ItemStack itemStack); public NodeBase getNeighbor(Direction direction) { int[] position = new int[3]; position[0] = coordonate.x; position[1] = coordonate.y; position[2] = coordonate.z; direction.applyTo(position, 1); Coordonate nodeCoordonate = new Coordonate(position[0], position[1], position[2], coordonate.dimention); return NodeManager.instance.getNodeFromCoordonate(nodeCoordonate); } // leaf public void onBreakBlock() { destructed = true; disconnect(); NodeManager.instance.removeNode(this); Utils.println("Node::onBreakBlock()"); } public boolean onBlockActivated(EntityPlayer entityPlayer, Direction side, float vx, float vy, float vz) { if (!entityPlayer.worldObj.isRemote && entityPlayer.getCurrentEquippedItem() != null) { if (Eln.multiMeterElement.checkSameItemStack(entityPlayer.getCurrentEquippedItem())) { String str = multiMeterString(side); if (str != null) Utils.addChatMessage(entityPlayer, str); return true; } if (Eln.thermometerElement.checkSameItemStack(entityPlayer.getCurrentEquippedItem())) { String str = thermoMeterString(side); if (str != null) Utils.addChatMessage(entityPlayer, str); return true; } if (Eln.allMeterElement.checkSameItemStack(entityPlayer.getCurrentEquippedItem())) { String str1 = multiMeterString(side); String str2 = thermoMeterString(side); String str = ""; if (str1 != null) str += str1; if (str2 != null) str += str2; if (str.equals("") == false) Utils.addChatMessage(entityPlayer, str); return true; } } if (hasGui(side)) { entityPlayer.openGui(Eln.instance, GuiHandler.nodeBaseOpen + side.getInt(), coordonate.world(), coordonate.x, coordonate.y, coordonate.z); return true; } return false; } public void reconnect() { disconnect(); connect(); } public static void tryConnectTwoNode(NodeBase nodeA, Direction directionA, LRDU lrduA, NodeBase nodeB, Direction directionB, LRDU lrduB) { if (compareConnectionMask(nodeA.getSideConnectionMask(directionA, lrduA), nodeB.getSideConnectionMask(directionB, lrduB))) { ElectricalConnection eCon = null; ThermalConnection tCon = null; nodeA.lrduCubeMask.set(directionA, lrduA, true); nodeB.lrduCubeMask.set(directionB, lrduB, true); nodeA.newConnectionAt(directionA, lrduA); nodeB.newConnectionAt(directionB, lrduB); ElectricalLoad eLoad; if ((eLoad = nodeA.getElectricalLoad(directionA, lrduA)) != null) { ElectricalLoad otherELoad = nodeB.getElectricalLoad(directionB, lrduB); if (otherELoad != null) { eCon = new ElectricalConnection(eLoad, otherELoad); Eln.simulator.addElectricalComponent(eCon); } } ThermalLoad tLoad; if ((tLoad = nodeA.getThermalLoad(directionA, lrduA)) != null) { ThermalLoad otherTLoad = nodeB.getThermalLoad(directionB, lrduB); if (otherTLoad != null) { tCon = new ThermalConnection(tLoad, otherTLoad); Eln.simulator.addThermalConnection(tCon); } } NodeConnection nodeConnection = new NodeConnection(nodeA, directionA, lrduA, nodeB, directionB, lrduB, eCon, tCon); nodeA.nodeConnectionList.add(nodeConnection); nodeB.nodeConnectionList.add(nodeConnection); nodeA.setNeedPublish(true); nodeB.setNeedPublish(true); } } public abstract int getSideConnectionMask(Direction directionA, LRDU lrduA); public abstract ThermalLoad getThermalLoad(Direction directionA, LRDU lrduA); public abstract ElectricalLoad getElectricalLoad(Direction directionB, LRDU lrduB); public void checkCanStay(boolean onCreate) { } public void connectJob() { // EXTERNAL OTHERS SIXNODE { int[] emptyBlockCoord = new int[3]; int[] otherBlockCoord = new int[3]; for (Direction direction : Direction.values()) { if (isBlockWrappable(direction)) { emptyBlockCoord[0] = coordonate.x; emptyBlockCoord[1] = coordonate.y; emptyBlockCoord[2] = coordonate.z; direction.applyTo(emptyBlockCoord, 1); for (LRDU lrdu : LRDU.values()) { Direction elementSide = direction.applyLRDU(lrdu); otherBlockCoord[0] = emptyBlockCoord[0]; otherBlockCoord[1] = emptyBlockCoord[1]; otherBlockCoord[2] = emptyBlockCoord[2]; elementSide.applyTo(otherBlockCoord, 1); NodeBase otherNode = NodeManager.instance.getNodeFromCoordonate(new Coordonate(otherBlockCoord[0], otherBlockCoord[1], otherBlockCoord[2], coordonate.dimention)); if (otherNode == null) continue; Direction otherDirection = elementSide.getInverse(); LRDU otherLRDU = otherDirection.getLRDUGoingTo(direction).inverse(); if (this instanceof SixNode || otherNode instanceof SixNode) { tryConnectTwoNode(this, direction, lrdu, otherNode, otherDirection, otherLRDU); } } } } } { for (Direction dir : Direction.values()) { NodeBase otherNode = getNeighbor(dir); if (otherNode != null && otherNode.isAdded) { for (LRDU lrdu : LRDU.values()) { tryConnectTwoNode(this, dir, lrdu, otherNode, dir.getInverse(), lrdu.inverseIfLR()); } } } } } public void disconnectJob() { for (NodeConnection c : nodeConnectionList) { if (c.N1 != this) { c.N1.nodeConnectionList.remove(c); c.N1.setNeedPublish(true); c.N1.lrduCubeMask.set(c.dir1, c.lrdu1, false); } else { c.N2.nodeConnectionList.remove(c); c.N2.setNeedPublish(true); c.N2.lrduCubeMask.set(c.dir2, c.lrdu2, false); } c.destroy(); } lrduCubeMask.clear(); nodeConnectionList.clear(); } public static boolean compareConnectionMask(int mask1, int mask2) { if (((mask1 & 0xFFFF) & (mask2 & 0xFFFF)) == 0) return false; if (((mask1 & maskColorCareData) & (mask2 & maskColorCareData)) == 0) return true; if ((mask1 & maskColorData) == (mask2 & maskColorData)) return true; return false; } public void externalDisconnect(Direction side, LRDU lrdu) { } public void newConnectionAt(Direction side, LRDU lrdu) { } public void connectInit() { lrduCubeMask.clear(); nodeConnectionList.clear(); } public void connect() { if (isAdded) { disconnect(); } connectInit(); connectJob(); isAdded = true; setNeedPublish(true); } public void disconnect() { if (!isAdded) { Utils.println("Node destroy error already destroy"); return; } disconnectJob(); isAdded = false; } public boolean nodeAutoSave() { return true; } public void readFromNBT(NBTTagCompound nbt) { coordonate.readFromNBT(nbt, "c"); neighborOpaque = nbt.getByte("NBOpaque"); neighborWrapable = nbt.getByte("NBWrap"); initialized = true; } public void writeToNBT(NBTTagCompound nbt) { coordonate.writeToNBT(nbt, "c"); int idx; nbt.setByte("NBOpaque", neighborOpaque); nbt.setByte("NBWrap", neighborWrapable); } public String multiMeterString(Direction side) { return ""; } public String thermoMeterString(Direction side) { return ""; } public void setNeedPublish(boolean needPublish) { this.needPublish = needPublish; } public boolean getNeedPublish() { return needPublish; } private boolean isINodeProcess(IProcess process) { for (Class c : process.getClass().getInterfaces()) { if (c == INBTTReady.class) return true; } return false; } boolean needNotify = false; public void publishSerialize(DataOutputStream stream) { } public void preparePacketForClient(DataOutputStream stream) { try { stream.writeByte(Eln.packetForClientNode); stream.writeInt(coordonate.x); stream.writeInt(coordonate.y); stream.writeInt(coordonate.z); stream.writeByte(coordonate.dimention); stream.writeUTF(getNodeUuid()); } catch (IOException e) { e.printStackTrace(); } } public void sendPacketToClient(ByteArrayOutputStream bos, EntityPlayerMP player) { Utils.sendPacketToClient(bos, player); } public void sendPacketToAllClient(ByteArrayOutputStream bos) { sendPacketToAllClient(bos, 100000); } public void sendPacketToAllClient(ByteArrayOutputStream bos, double range) { //Profiler p = new Profiler(); MinecraftServer server = FMLCommonHandler.instance().getMinecraftServerInstance(); for (Object obj : server.getConfigurationManager().playerEntityList) { EntityPlayerMP player = (EntityPlayerMP) obj; WorldServer worldServer = (WorldServer) MinecraftServer.getServer().worldServerForDimension(player.dimension); PlayerManager playerManager = worldServer.getPlayerManager(); if (player.dimension != this.coordonate.dimention) continue; if (!playerManager.isPlayerWatchingChunk(player, coordonate.x / 16, coordonate.z / 16)) continue; if (coordonate.distanceTo(player) > range) continue; Utils.sendPacketToClient(bos, player); } } public ByteArrayOutputStream getPublishPacket() { ByteArrayOutputStream bos = new ByteArrayOutputStream(64); DataOutputStream stream = new DataOutputStream(bos); try { stream.writeByte(Eln.packetNodeSingleSerialized); stream.writeInt(coordonate.x); stream.writeInt(coordonate.y); stream.writeInt(coordonate.z); stream.writeByte(coordonate.dimention); stream.writeUTF(getNodeUuid()); publishSerialize(stream); return bos; } catch (IOException e) { e.printStackTrace(); } return null; } public void publishToAllPlayer() { MinecraftServer server = FMLCommonHandler.instance().getMinecraftServerInstance(); for (Object obj : server.getConfigurationManager().playerEntityList) { EntityPlayerMP player = (EntityPlayerMP) obj; WorldServer worldServer = (WorldServer) MinecraftServer.getServer().worldServerForDimension(player.dimension); PlayerManager playerManager = worldServer.getPlayerManager(); if (player.dimension != this.coordonate.dimention) continue; if (!playerManager.isPlayerWatchingChunk(player, coordonate.x / 16, coordonate.z / 16)) continue; Utils.sendPacketToClient(getPublishPacket(), player); } if (needNotify) { needNotify = false; notifyNeighbor(); } needPublish = false; } public void publishToPlayer(EntityPlayerMP player) { Utils.sendPacketToClient(getPublishPacket(), player); } public void dropItem(ItemStack itemStack) { if (itemStack == null) return; if (coordonate.world().getGameRules().getGameRuleBooleanValue("doTileDrops")) { float var6 = 0.7F; double var7 = (double) (coordonate.world().rand.nextFloat() * var6) + (double) (1.0F - var6) * 0.5D; double var9 = (double) (coordonate.world().rand.nextFloat() * var6) + (double) (1.0F - var6) * 0.5D; double var11 = (double) (coordonate.world().rand.nextFloat() * var6) + (double) (1.0F - var6) * 0.5D; EntityItem var13 = new EntityItem(coordonate.world(), (double) coordonate.x + var7, (double) coordonate.y + var9, (double) coordonate.z + var11, itemStack); var13.delayBeforeCanPickup = 10; coordonate.world().spawnEntityInWorld(var13); } } public void dropInventory(IInventory inventory) { if (inventory == null) return; for (int idx = 0; idx < inventory.getSizeInventory(); idx++) { dropItem(inventory.getStackInSlot(idx)); } } public abstract void initializeFromNBT(); public void globalBoot() { } public void needPublish() { setNeedPublish(true); } public void unload() { disconnect(); } }