package resonantinduction.electrical.wire.framed; import java.util.Collection; import java.util.HashSet; import java.util.Set; import net.minecraft.block.Block; import net.minecraft.client.particle.EffectRenderer; import net.minecraft.client.renderer.RenderBlocks; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.Icon; import net.minecraft.util.MovingObjectPosition; import net.minecraft.world.World; import net.minecraftforge.common.ForgeDirection; import resonantinduction.electrical.wire.EnumWireMaterial; import resonantinduction.electrical.wire.PartAdvancedWire; import universalelectricity.api.CompatibilityModule; import universalelectricity.api.energy.IConductor; import universalelectricity.api.vector.Vector3; import universalelectricity.api.vector.VectorHelper; import codechicken.lib.data.MCDataInput; import codechicken.lib.data.MCDataOutput; import codechicken.lib.lighting.LazyLightMatrix; import codechicken.lib.raytracer.IndexedCuboid6; import codechicken.lib.render.CCRenderState; import codechicken.lib.render.IconTransformation; import codechicken.lib.render.RenderUtils; import codechicken.lib.vec.BlockCoord; import codechicken.lib.vec.Cuboid6; import codechicken.lib.vec.Translation; import codechicken.microblock.IHollowConnect; import codechicken.multipart.IconHitEffects; import codechicken.multipart.JIconHitEffects; import codechicken.multipart.JNormalOcclusion; import codechicken.multipart.MultiPartRegistry; import codechicken.multipart.NormalOcclusionTest; import codechicken.multipart.PartMap; import codechicken.multipart.TMultiPart; import codechicken.multipart.TSlottedPart; import codechicken.multipart.TileMultipart; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; public class PartFramedWire extends PartAdvancedWire implements TSlottedPart, JNormalOcclusion, IHollowConnect, JIconHitEffects { /** Client Side Connection Check */ private ForgeDirection testingSide; public static IndexedCuboid6[] sides = new IndexedCuboid6[7]; public static IndexedCuboid6[] insulatedSides = new IndexedCuboid6[7]; /** * Bitmask connections */ public byte currentWireConnections = 0x00; public byte currentAcceptorConnections = 0x00; public PartFramedWire() { super(); } public PartFramedWire(int typeID) { this(EnumWireMaterial.values()[typeID]); } public PartFramedWire(EnumWireMaterial type) { super(); material = type; } static { sides[0] = new IndexedCuboid6(0, new Cuboid6(0.36, 0.000, 0.36, 0.64, 0.36, 0.64)); sides[1] = new IndexedCuboid6(1, new Cuboid6(0.36, 0.64, 0.36, 0.64, 1.000, 0.64)); sides[2] = new IndexedCuboid6(2, new Cuboid6(0.36, 0.36, 0.000, 0.64, 0.64, 0.36)); sides[3] = new IndexedCuboid6(3, new Cuboid6(0.36, 0.36, 0.64, 0.64, 0.64, 1.000)); sides[4] = new IndexedCuboid6(4, new Cuboid6(0.000, 0.36, 0.36, 0.36, 0.64, 0.64)); sides[5] = new IndexedCuboid6(5, new Cuboid6(0.64, 0.36, 0.36, 1.000, 0.64, 0.64)); sides[6] = new IndexedCuboid6(6, new Cuboid6(0.36, 0.36, 0.36, 0.64, 0.64, 0.64)); insulatedSides[0] = new IndexedCuboid6(0, new Cuboid6(0.3, 0.0, 0.3, 0.7, 0.3, 0.7)); insulatedSides[1] = new IndexedCuboid6(1, new Cuboid6(0.3, 0.7, 0.3, 0.7, 1.0, 0.7)); insulatedSides[2] = new IndexedCuboid6(2, new Cuboid6(0.3, 0.3, 0.0, 0.7, 0.7, 0.3)); insulatedSides[3] = new IndexedCuboid6(3, new Cuboid6(0.3, 0.3, 0.7, 0.7, 0.7, 1.0)); insulatedSides[4] = new IndexedCuboid6(4, new Cuboid6(0.0, 0.3, 0.3, 0.3, 0.7, 0.7)); insulatedSides[5] = new IndexedCuboid6(5, new Cuboid6(0.7, 0.3, 0.3, 1.0, 0.7, 0.7)); insulatedSides[6] = new IndexedCuboid6(6, new Cuboid6(0.3, 0.3, 0.3, 0.7, 0.7, 0.7)); } @Override public String getType() { return "resonant_induction_wire"; } @Override public boolean occlusionTest(TMultiPart other) { return NormalOcclusionTest.apply(this, other); } @Override public Iterable getSubParts() { Set subParts = new HashSet(); IndexedCuboid6[] currentSides = isInsulated() ? insulatedSides : sides; if (tile() != null) { for (ForgeDirection side : ForgeDirection.VALID_DIRECTIONS) { int ord = side.ordinal(); if (connectionMapContainsSide(getAllCurrentConnections(), side) || side == testingSide) subParts.add(currentSides[ord]); } } subParts.add(currentSides[6]); return subParts; } @Override public boolean activate(EntityPlayer player, MovingObjectPosition part, ItemStack item) { if (!world().isRemote) { System.out.println(this.getNetwork()); } if (item != null) { if (item.getItem().itemID == Block.lever.blockID) { TileMultipart tile = tile(); World w = world(); if (!w.isRemote) { PartFramedSwitchWire wire = (PartFramedSwitchWire) MultiPartRegistry.createPart("resonant_induction_switch_wire", false); wire.copyFrom(this); if (tile.canReplacePart(this, wire)) { tile.remPart(this); TileMultipart.addPart(w, new BlockCoord(tile), wire); if (!player.capabilities.isCreativeMode) { player.inventory.decrStackSize(player.inventory.currentItem, 1); } } } return true; } } return super.activate(player, part, item); } public void preparePlacement(int meta) { this.setMaterial(meta); } @Override public Iterable getCollisionBoxes() { Set collisionBoxes = new HashSet(); collisionBoxes.addAll((Collection) getSubParts()); return collisionBoxes; } @Override public float getStrength(MovingObjectPosition hit, EntityPlayer player) { return 10F; } @Override @SideOnly(Side.CLIENT) public void renderStatic(codechicken.lib.vec.Vector3 pos, LazyLightMatrix olm, int pass) { if (pass == 0) { RenderPartWire.INSTANCE.renderStatic(this); } } @Override @SideOnly(Side.CLIENT) public void renderDynamic(codechicken.lib.vec.Vector3 pos, float frame, int pass) { if (getMaterial() == EnumWireMaterial.SILVER) { RenderPartWire.INSTANCE.renderShine(this, pos.x, pos.y, pos.z, frame); } } @Override public void drawBreaking(RenderBlocks renderBlocks) { CCRenderState.reset(); RenderUtils.renderBlock(sides[6], 0, new Translation(x(), y(), z()), new IconTransformation(renderBlocks.overrideBlockTexture), null); } @Override public Iterable getOcclusionBoxes() { return getCollisionBoxes(); } @Override public int getSlotMask() { return PartMap.CENTER.mask; } @Override public int getHollowSize() { return isInsulated ? 8 : 6; } @Override public Cuboid6 getBounds() { return new Cuboid6(0.375, 0.375, 0.375, 0.625, 0.625, 0.625); } @Override public Icon getBreakingIcon(Object subPart, int side) { return RenderPartWire.breakIcon; } @Override public Icon getBrokenIcon(int side) { return RenderPartWire.breakIcon; } @Override public void addHitEffects(MovingObjectPosition hit, EffectRenderer effectRenderer) { IconHitEffects.addHitEffects(this, hit, effectRenderer); } @Override public void addDestroyEffects(EffectRenderer effectRenderer) { IconHitEffects.addDestroyEffects(this, effectRenderer, false); } @Override public void onPartChanged(TMultiPart part) { refresh(); } public boolean isBlockedOnSide(ForgeDirection side) { TMultiPart blocker = tile().partMap(side.ordinal()); testingSide = side; boolean expandable = NormalOcclusionTest.apply(this, blocker); testingSide = null; return !expandable; } public byte getAllCurrentConnections() { return (byte) (currentWireConnections | currentAcceptorConnections); } public static boolean connectionMapContainsSide(byte connections, ForgeDirection side) { byte tester = (byte) (1 << side.ordinal()); return ((connections & tester) > 0); } @Override public void bind(TileMultipart t) { if (tile() != null && this.getNetwork() != null) { getNetwork().getConnectors().remove(tile()); super.bind(t); getNetwork().getConnectors().add((IConductor) tile()); } else { super.bind(t); } } /** * CONNECTION LOGIC CODE */ public boolean canConnectBothSides(TileEntity tile, ForgeDirection side) { boolean notPrevented = !isConnectionPrevented(tile, side); if (tile instanceof IConductor) { notPrevented &= ((IConductor) tile).canConnect(side.getOpposite()); } return notPrevented; } /** * Override if there are ways of preventing a connection * * @param tile The TileEntity on the given side * @param side The side we're checking * @return Whether we're preventing connections on given side or to given tileEntity */ public boolean isConnectionPrevented(TileEntity tile, ForgeDirection side) { return (tile instanceof IConductor ? this.canConnectTo(tile) : false) || (isBlockedOnSide(side)); // || tile instanceof IBlockableConnection && ((IBlockableConnection) // tile).isBlockedOnSide(side.getOpposite()))*/; } public byte getPossibleWireConnections() { byte connections = 0x00; for (ForgeDirection side : ForgeDirection.VALID_DIRECTIONS) { TileEntity tileEntity = VectorHelper.getTileEntityFromSide(world(), new Vector3(tile()), side); if (tileEntity instanceof IConductor && canConnectBothSides(tileEntity, side)) { connections |= 1 << side.ordinal(); } } return connections; } public byte getPossibleAcceptorConnections() { byte connections = 0x00; for (ForgeDirection side : ForgeDirection.VALID_DIRECTIONS) { TileEntity tileEntity = VectorHelper.getTileEntityFromSide(world(), new Vector3(tile()), side); if (CompatibilityModule.canConnect(tileEntity, side.getOpposite()) && canConnectBothSides(tileEntity, side)) { connections |= 1 << side.ordinal(); } } return connections; } public void refresh() { if (!world().isRemote) { byte possibleWireConnections = getPossibleWireConnections(); byte possibleAcceptorConnections = getPossibleAcceptorConnections(); if (possibleWireConnections != this.currentWireConnections) { byte or = (byte) (possibleWireConnections | this.currentWireConnections); // Connections have been removed if (or != possibleWireConnections) { try { this.getNetwork().removeConnector(this); this.getNetwork().split((IConductor) tile()); } catch (NullPointerException e) { } this.setNetwork(null); } for (ForgeDirection side : ForgeDirection.VALID_DIRECTIONS) { if (connectionMapContainsSide(possibleWireConnections, side)) { TileEntity tileEntity = VectorHelper.getConnectorFromSide(world(), new Vector3(tile()), side); if (tileEntity instanceof IConductor) { this.getNetwork().merge(((IConductor) tileEntity).getNetwork()); } } } this.currentWireConnections = possibleWireConnections; } this.currentAcceptorConnections = possibleAcceptorConnections; this.getNetwork().reconstruct(); this.sendConnectionUpdate(); } tile().markRender(); } /** * Should include connections that are in the current connection maps even if those connections * aren't allowed any more. This is so that networks split correctly. */ @Override public TileEntity[] getConnections() { TileEntity[] connections = new TileEntity[6]; for (byte i = 0; i < 6; i++) { ForgeDirection side = ForgeDirection.getOrientation(i); TileEntity tileEntity = VectorHelper.getTileEntityFromSide(world(), new Vector3(tile()), side); if (isCurrentlyConnected(side)) { connections[i] = tileEntity; } } return connections; } public boolean isCurrentlyConnected(ForgeDirection side) { return connectionMapContainsSide(getAllCurrentConnections(), side); } /** * Shouldn't need to be overridden. Override connectionPrevented instead */ @Override public boolean canConnect(ForgeDirection direction) { if (world().isBlockIndirectlyGettingPowered(x(), y(), z())) { return false; } Vector3 connectPos = new Vector3(tile()).modifyPositionFromSide(direction); TileEntity connectTile = connectPos.getTileEntity(world()); return !isConnectionPrevented(connectTile, direction); } @Override public void onAdded() { super.onAdded(); refresh(); } @Override public void onMoved() { this.refresh(); } @Override public void onChunkLoad() { super.onChunkLoad(); refresh(); } @Override public void onNeighborChanged() { super.onNeighborChanged(); refresh(); } /** * Packets */ public void sendConnectionUpdate() { tile().getWriteStream(this).writeByte(0).writeByte(this.currentWireConnections).writeByte(this.currentAcceptorConnections); } @Override public void readDesc(MCDataInput packet) { super.readDesc(packet); this.currentWireConnections = packet.readByte(); this.currentAcceptorConnections = packet.readByte(); } @Override public void writeDesc(MCDataOutput packet) { super.writeDesc(packet); packet.writeByte(this.currentWireConnections); packet.writeByte(this.currentAcceptorConnections); } @Override public void read(MCDataInput packet) { read(packet, packet.readUByte()); } @Override public void read(MCDataInput packet, int packetID) { if (packetID == 0) { this.currentWireConnections = packet.readByte(); this.currentAcceptorConnections = packet.readByte(); tile().markRender(); } else { super.read(packet, packetID); } } public void copyFrom(PartFramedWire otherCable) { this.isInsulated = otherCable.isInsulated; this.color = otherCable.color; this.connections = otherCable.connections; this.material = otherCable.material; this.currentWireConnections = otherCable.currentWireConnections; this.currentAcceptorConnections = otherCable.currentAcceptorConnections; this.setNetwork(otherCable.getNetwork()); this.getNetwork().setBufferFor(this, otherCable.getNetwork().getBufferOf(otherCable)); } }