package codechicken.translocator; import java.util.Collection; import java.util.LinkedList; import java.util.List; import codechicken.lib.math.MathHelper; import codechicken.lib.inventory.InventoryUtils; import codechicken.lib.packet.ICustomPacketTile; import codechicken.lib.packet.PacketCustom; import codechicken.lib.raytracer.IndexedCuboid6; import codechicken.lib.vec.Cuboid6; import codechicken.lib.vec.Vector3; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.Items; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.network.Packet; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.AxisAlignedBB; import static codechicken.lib.vec.Rotation.*; import static codechicken.lib.vec.Vector3.*; public abstract class TileTranslocator extends TileEntity implements ICustomPacketTile { public class Attachment { public final int side; public boolean a_eject; public boolean b_eject; public boolean redstone; public boolean invert_redstone; public boolean fast; public double a_insertpos; public double b_insertpos; public Attachment(int side) { this.side = side; a_eject = b_eject = invert_redstone = true; a_insertpos = b_insertpos = 1; } public void read(NBTTagCompound tag) { invert_redstone = tag.getBoolean("invert_redstone"); redstone = tag.getBoolean("redstone"); fast = tag.getBoolean("fast"); } public void update(boolean client) { b_insertpos = a_insertpos; a_insertpos = MathHelper.approachExp(a_insertpos, approachInsertPos(), 0.5, 0.1); if(!client) { b_eject = a_eject; a_eject = (redstone && gettingPowered()) != invert_redstone; if(a_eject != b_eject) markUpdate(); } } public double approachInsertPos() { return a_eject ? 1 : 0; } public void write(PacketCustom packet) { packet.writeBoolean(a_eject); packet.writeBoolean(redstone); packet.writeBoolean(fast); } public void read(PacketCustom packet, boolean described) { a_eject = packet.readBoolean(); redstone = packet.readBoolean(); fast = packet.readBoolean(); if(!described) a_insertpos = b_insertpos = approachInsertPos(); } public NBTTagCompound write(NBTTagCompound tag) { tag.setBoolean("invert_redstone", invert_redstone); tag.setBoolean("redstone", redstone); tag.setBoolean("fast", fast); return tag; } public boolean activate(EntityPlayer player, int subPart) { ItemStack held = player.inventory.getCurrentItem(); if(held == null && player.isSneaking()) { stripModifiers(); markUpdate(); } else if(held == null) { if(subPart == 1) invert_redstone = !invert_redstone; else openGui(player); } else if(held.getItem() == Items.redstone && !redstone) { redstone = true; if(!player.capabilities.isCreativeMode) held.stackSize--; if((gettingPowered() != invert_redstone) != a_eject) invert_redstone = !invert_redstone; markUpdate(); } else if(held.getItem() == Items.glowstone_dust && !fast) { fast = true; if(!player.capabilities.isCreativeMode) held.stackSize--; markUpdate(); } else openGui(player); return true; } public void stripModifiers() { if(redstone) { redstone = false; dropItem(new ItemStack(Items.redstone)); if(invert_redstone != a_eject) invert_redstone = !invert_redstone; } if(fast) { fast = false; dropItem(new ItemStack(Items.glowstone_dust)); } } public void openGui(EntityPlayer player) { } public void markUpdate() { worldObj.markBlockForUpdate(xCoord, yCoord, zCoord); markDirty(); } public Collection<ItemStack> getDrops() { LinkedList<ItemStack> items = new LinkedList<ItemStack>(); items.add(new ItemStack(getBlockType(), 1, getBlockMetadata())); if(redstone) items.add(new ItemStack(Items.redstone)); if(fast) items.add(new ItemStack(Items.glowstone_dust)); return items; } public int getIconIndex() { int i = 0; if(redstone) i|= gettingPowered() ? 2 : 1; if(fast) i|=4; return i; } } public Attachment[] attachments = new Attachment[6]; @Override public void updateEntity() { for(Attachment a : attachments) if(a != null) a.update(worldObj.isRemote); } @Override public Packet getDescriptionPacket() { PacketCustom packet = new PacketCustom(TranslocatorSPH.channel, 1); packet.writeCoord(xCoord, yCoord, zCoord); int attachmask = 0; for(int i = 0; i < 6; i++) if(attachments[i] != null) attachmask|= 1<<i; packet.writeByte(attachmask); for(Attachment a : attachments) if(a != null) a.write(packet); return packet.toPacket(); } @Override public void handleDescriptionPacket(PacketCustom packet) { if(packet.getType() == 1) { int attachmask = packet.readUByte(); for(int i = 0; i < 6; i++) { if((attachmask&1<<i) != 0) { boolean described = attachments[i] != null; if(!described) createAttachment(i); attachments[i].read(packet, described); } else attachments[i] = null; } worldObj.func_147479_m(xCoord, yCoord, zCoord); } } public void createAttachment(int side) { attachments[side] = new Attachment(side); } @Override public void writeToNBT(NBTTagCompound tag) { super.writeToNBT(tag); for(int i = 0; i < 6; i++) if(attachments[i] != null) tag.setTag("atmt" + i, attachments[i].write(new NBTTagCompound())); } @Override public void readFromNBT(NBTTagCompound tag) { super.readFromNBT(tag); for(int i = 0; i < 6; i++) if(tag.hasKey("atmt"+i)) { createAttachment(i); attachments[i].read(tag.getCompoundTag("atmt"+i)); } } public void addTraceableCuboids(List<IndexedCuboid6> cuboids) { Vector3 pos = Vector3.fromTileEntity(this); Cuboid6 base = new Cuboid6(3/16D, 0, 3/16D, 13/16D, 2/16D, 13/16D); for(int i = 0; i < 6; i++) { Attachment a = attachments[i]; if(a != null) { cuboids.add(new IndexedCuboid6(i, transformPart(base, pos, i))); cuboids.add(new IndexedCuboid6(i+6, transformPart( new Cuboid6(6/16D, 0, 6/16D, 10/16D, a.a_insertpos*2/16D+1/16D, 10/16D), pos, i))); } } } private Cuboid6 transformPart(Cuboid6 box, Vector3 pos, int i) { return box.copy() .apply(sideRotations[i].at(center)) .add(pos); } @Override public AxisAlignedBB getRenderBoundingBox() { return AxisAlignedBB.getBoundingBox(xCoord, yCoord, zCoord, xCoord+1, yCoord+1, zCoord+1); } public boolean harvestPart(int i, boolean drop) { Attachment a = attachments[i]; if(!worldObj.isRemote && drop) for(ItemStack stack : a.getDrops()) dropItem(stack); attachments[i] = null; worldObj.markBlockForUpdate(xCoord, yCoord, zCoord); for(Attachment a1 : attachments) if(a1 != null) return false; worldObj.setBlockToAir(xCoord, yCoord, zCoord); return true; } public void dropItem(ItemStack stack) { InventoryUtils.dropItem(stack, worldObj, Vector3.fromTileEntityCenter(this)); } public boolean gettingPowered() { return worldObj.isBlockIndirectlyGettingPowered(xCoord, yCoord, zCoord); } public boolean connectRedstone() { for(Attachment a : attachments) if(a != null && a.redstone) return true; return false; } public int strongPowerLevel(int side) { return 0; } }