package advancedsystemsmanager.tileentities; import advancedsystemsmanager.api.tileentities.ITileFactory; import advancedsystemsmanager.api.tileentities.*; import advancedsystemsmanager.helpers.PlayerHelper; import advancedsystemsmanager.items.blocks.ItemTileElement; import advancedsystemsmanager.network.ASMPacket; import advancedsystemsmanager.network.PacketHandler; import advancedsystemsmanager.reference.Mods; import advancedsystemsmanager.registry.ClusterRegistry; import cofh.api.energy.IEnergyConnection; import cofh.api.energy.IEnergyProvider; import cofh.api.energy.IEnergyReceiver; import cpw.mods.fml.common.Optional; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiScreen; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.inventory.Container; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTBase; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.network.Packet; import net.minecraft.tileentity.TileEntity; import net.minecraftforge.common.util.ForgeDirection; import java.util.*; @Optional.InterfaceList({ @Optional.Interface(iface = "cofh.api.energy.IEnergyProvider", modid = Mods.COFH_ENERGY), @Optional.Interface(iface = "cofh.api.energy.IEnergyReceiver", modid = Mods.COFH_ENERGY) }) public class TileEntityCluster extends TileEntityElementRotation implements ITileInterfaceProvider, ICluster, IEnergyProvider, IEnergyReceiver, IActivateListener, IBUDListener, IRedstoneListener { private static final String NBT_SUB_BLOCKS = "SubBlocks"; private boolean requestedInfo; private Map<ITileFactory, ITileElement> pairs = new HashMap<ITileFactory, ITileElement>(); private List<ITileElement> elements = new ArrayList<ITileElement>(); private ITileInterfaceProvider interfaceObject; private TileEntityCamouflage camouflageObject; public static boolean hasSubBlocks(ItemStack stack) { return stack.hasTagCompound() && stack.getTagCompound().hasKey(NBT_SUB_BLOCKS) && !stack.getTagCompound().getCompoundTag(NBT_SUB_BLOCKS).tagMap.isEmpty(); } @SuppressWarnings("unchecked") public static List<ItemStack> getSubblocks(ItemStack stack) { List<ItemStack> result = new ArrayList<ItemStack>(); if (hasSubBlocks(stack)) { NBTTagCompound tag = stack.getTagCompound().getCompoundTag(NBT_SUB_BLOCKS); for (Object obj : tag.tagMap.entrySet()) { Map.Entry<String, NBTBase> entry = (Map.Entry<String, NBTBase>)obj; if (entry.getValue() instanceof NBTTagCompound) { ITileFactory factory = ClusterRegistry.get(entry.getKey()); if (factory != null) { result.add(factory.getItemStack(((NBTTagCompound) entry.getValue()).getByte(NBT_SUBTYPE))); } } } } return result; } public Set<Map.Entry<ITileFactory, ITileElement>> getPairs() { return pairs.entrySet(); } public List<ITileElement> getTiles() { return elements; } public void loadElements(ItemStack itemStack) { NBTTagCompound compound = itemStack.getTagCompound(); if (compound != null) { loadElements(compound); } } public static void saveSubBlocks(ItemStack cluster, List<ITileFactory> factories, List<ItemStack> stacks) { NBTTagCompound tagCompound = new NBTTagCompound(); for (int i = 0; i < factories.size(); i++) { factories.get(i).saveToClusterTag(stacks.get(i), tagCompound); } } @SuppressWarnings("unchecked") public void loadElements(NBTTagCompound tag) { for (Object obj : tag.tagMap.entrySet()) { Map.Entry<String, NBTBase> entry = (Map.Entry<String, NBTBase>)obj; if (entry.getValue() instanceof NBTTagCompound) { addElement(entry.getKey(), (NBTTagCompound)entry.getValue()); } } } private ITileElement addElement(String key, NBTTagCompound value) { ITileFactory factory = ClusterRegistry.get(key); if (factory != null) { return addElement(factory, value); } return null; } private ITileElement addElement(ITileFactory factory, NBTTagCompound value) { if (!factory.canBeAddedToCluster(pairs.keySet())) { return null; } TileEntity tile = factory.createTileEntity(getWorldObj(), 0); if (tile instanceof ITileElement) { ITileElement element = (ITileElement) tile; tile.readFromNBT(value); pairs.put(factory, element); elements.add(element); if (tile instanceof ITileInterfaceProvider) { interfaceObject = (ITileInterfaceProvider)tile; } else if (tile instanceof TileEntityCamouflage) { camouflageObject = (TileEntityCamouflage)tile; } tile.xCoord = xCoord; tile.yCoord = yCoord; tile.zCoord = zCoord; tile.setWorldObj(worldObj); element.setPartOfCluster(true); return element; } return null; } @Override public void onBlockPlacedBy(EntityLivingBase entity, ItemStack itemStack) { super.onBlockPlacedBy(entity, itemStack); for (ITileElement element : elements) { if (element instanceof IPlaceListener) { ((IPlaceListener) element).onBlockPlacedBy(entity, itemStack); } } } public void setWorld(ITileElement tile) { setWorldObject((TileEntity) tile); } public void setWorldObject(TileEntity te) { if (!te.hasWorldObj()) { te.setWorldObj(this.worldObj); } } @Override public void onNeighborBlockChange() { for (ITileElement element : elements) { if (element instanceof IBUDListener) { ((IBUDListener) element).onNeighborBlockChange(); } } } @Override public boolean canConnectRedstone(int side) { for (ITileElement element : elements) { if (element instanceof IRedstoneListener && ((IRedstoneListener) element).canConnectRedstone(side)) { return true; } } return false; } @Override public int getComparatorInputOverride(int side) { int output = 0; for (ITileElement element : elements) { if (element instanceof IRedstoneListener) { output = Math.max(output, ((IRedstoneListener) element).getComparatorInputOverride(side)); } } return output; } @Override public void validate() { super.validate(); for (ITileElement element : elements) { ((TileEntity)element).validate(); } } @Override public void invalidate() { for (ITileElement element : elements) { ((TileEntity)element).invalidate(); } super.invalidate(); } @Override public void onChunkUnload() { for (ITileElement element : elements) { ((TileEntity)element).onChunkUnload(); } super.onChunkUnload(); } @Override public boolean shouldCheckWeakPower(int side) { for (ITileElement element : elements) { if (element instanceof IRedstoneListener && ((IRedstoneListener) element).shouldCheckWeakPower(side)) { return true; } } return false; } @Override public int isProvidingWeakPower(int side) { int output = 0; for (ITileElement element : elements) { if (element instanceof IRedstoneListener) { output = Math.max(output, ((IRedstoneListener) element).isProvidingWeakPower(side)); } } return output; } @Override public int isProvidingStrongPower(int side) { int output = 0; for (ITileElement element : elements) { if (element instanceof IRedstoneListener) { output = Math.max(output, ((IRedstoneListener) element).isProvidingStrongPower(side)); } } return output; } @Override public boolean onBlockActivated(EntityPlayer player, int side, float hitX, float hitY, float hitZ) { ItemStack stack = player.getCurrentEquippedItem(); if (stack != null && stack.getItem() instanceof ItemTileElement) { ITileFactory factory = ((ItemTileElement)stack.getItem()).getTileFactory(stack); if (factory != null && addElement(player, factory, stack)) { PlayerHelper.consumeItem(player); return true; } } if (interfaceObject != null) { return interfaceObject.onBlockActivated(player, side, hitX, hitY, hitZ); } else { for (ITileElement element : elements) { if (element instanceof IActivateListener && ((IActivateListener) element).onBlockActivated(player, side, hitX, hitY, hitZ)) { return true; } } } return false; } public boolean addElement(EntityPlayer player, ITileFactory factory, ItemStack stack) { ITileElement element = addElement(factory, stack.getTagCompound()); if (element == null) return false; if (element instanceof IPlaceListener) { ((IPlaceListener) element).onBlockPlacedBy(player, stack); } if (element instanceof TileEntity) { ((TileEntity) element).validate(); } element.onAddedToCluster(this); return true; } @Override @Optional.Method(modid = Mods.COFH_ENERGY) public int receiveEnergy(ForgeDirection from, int maxReceive, boolean simulate) { int toReceive = 0; for (ITileElement element : elements) { if (element instanceof IEnergyReceiver) toReceive += ((IEnergyReceiver)element).receiveEnergy(from, maxReceive - toReceive, simulate); } return toReceive; } @Override @Optional.Method(modid = Mods.COFH_ENERGY) public int extractEnergy(ForgeDirection from, int maxExtract, boolean simulate) { int toExtract = maxExtract; for (ITileElement element : elements) { if (element instanceof IEnergyProvider) toExtract += ((IEnergyProvider)element).extractEnergy(from, maxExtract - toExtract, simulate); } return maxExtract - toExtract; } @Override @Optional.Method(modid = Mods.COFH_ENERGY) public int getEnergyStored(ForgeDirection from) { int stored = -1; for (ITileElement element : elements) { if (element instanceof IEnergyReceiver) stored += ((IEnergyReceiver)element).getEnergyStored(from); else if (element instanceof IEnergyProvider) stored += ((IEnergyProvider)element).getEnergyStored(from); } return stored; } @Override @Optional.Method(modid = Mods.COFH_ENERGY) public int getMaxEnergyStored(ForgeDirection from) { int max = -1; for (ITileElement element : elements) { if (element instanceof IEnergyReceiver) max += ((IEnergyReceiver)element).getMaxEnergyStored(from); else if (element instanceof IEnergyProvider) max += ((IEnergyProvider)element).getMaxEnergyStored(from); } return max; } @Override @Optional.Method(modid = Mods.COFH_ENERGY) public boolean canConnectEnergy(ForgeDirection from) { for (ITileElement element : elements) { if (element instanceof IEnergyConnection && ((IEnergyConnection) element).canConnectEnergy(from)) return true; } return false; } @Override public Container getContainer(EntityPlayer player) { return interfaceObject == null ? null : interfaceObject.getContainer(player); } @Override public GuiScreen getGui(EntityPlayer player) { return interfaceObject == null ? null : interfaceObject.getGui(player); } @Override public boolean readData(ASMPacket packet, EntityPlayer player) { return interfaceObject != null && interfaceObject.readData(packet, player); } @Override public void readItemNBT(NBTTagCompound tag) { super.readItemNBT(tag); loadElements(tag.getCompoundTag(NBT_SUB_BLOCKS)); } @Override public void writeItemNBT(NBTTagCompound tag) { super.writeItemNBT(tag); NBTTagCompound subBlocks = new NBTTagCompound(); for (Map.Entry<ITileFactory, ITileElement> entry : pairs.entrySet()) { NBTTagCompound elementData = new NBTTagCompound(); ((TileEntity)entry.getValue()).writeToNBT(elementData); subBlocks.setTag(entry.getKey().getKey(), elementData); } tag.setTag(NBT_SUB_BLOCKS, subBlocks); } @Override public void updateEntity() { for (ITileElement element : elements) { TileEntity te = (TileEntity)element; setWorldObject(te); te.updateEntity(); } if (!requestedInfo && worldObj.isRemote) { requestedInfo = true; requestData(); } } @SideOnly(Side.CLIENT) private void requestData() { PacketHandler.sendBlockPacket(this, Minecraft.getMinecraft().thePlayer, TILE_DATA); } @Override public void writeClientSyncData(ASMPacket packet) { super.writeClientSyncData(packet); if (camouflageObject != null) { camouflageObject.writeData(packet, CLIENT_SYNC); } } @Override public void writeTileData(ASMPacket packet) { super.writeTileData(packet); packet.writeByte(pairs.size()); for (Map.Entry<ITileFactory, ITileElement> entry : pairs.entrySet()) { packet.writeStringToBuffer(entry.getKey().getKey()); packet.writeByte(entry.getValue().getSubtype()); } if (camouflageObject != null) { camouflageObject.writeData(packet, CLIENT_SYNC); } } @Override public void readClientSyncData(ASMPacket packet) { super.readClientSyncData(packet); if (camouflageObject != null) { camouflageObject.readData(packet, CLIENT_SYNC); } } @Override public void readTileData(ASMPacket packet) { super.readTileData(packet); if (worldObj.isRemote) { clearElements(); int length = packet.readByte(); for (int i = 0; i < length; i++) { ITileElement element = addElement(packet.readStringFromBuffer(), null); if (element != null) { element.setSubtype(packet.readByte()); } } if (camouflageObject != null) { camouflageObject.readData(packet, CLIENT_SYNC); } } else { ASMPacket response = PacketHandler.constructBlockPacket(this, this, TILE_DATA); response.setPlayers(packet.getPlayers()); response.sendResponse(); } } private void clearElements() { elements.clear(); pairs.clear(); interfaceObject = null; camouflageObject = null; } @Override public Packet getDescriptionPacket() { return camouflageObject != null? camouflageObject.getDescriptionPacket() : super.getDescriptionPacket(); } public List<ItemStack> getStacks() { List<ItemStack> stacks = new ArrayList<ItemStack>(); for (Map.Entry<ITileFactory, ITileElement> entry : pairs.entrySet()) stacks.add(entry.getKey().getItemStack(entry.getValue().getSubtype())); return stacks; } @Override public boolean writeData(ASMPacket packet) { return interfaceObject != null && interfaceObject.writeData(packet); } public boolean isHidden(int sideHit) { return camouflageObject != null && camouflageObject.hasSideBlock(sideHit); } }