package mcjty.rftools.blocks.storage; import mcjty.lib.container.InventoryHelper; import mcjty.lib.entity.GenericEnergyReceiverTileEntity; import mcjty.lib.network.Argument; import mcjty.lib.varia.Coordinate; import mcjty.lib.varia.GlobalCoordinate; import mcjty.rftools.items.storage.StorageModuleItem; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.inventory.ISidedInventory; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; import net.minecraftforge.common.util.Constants; import net.minecraftforge.common.util.ForgeDirection; import java.util.Map; public class RemoteStorageTileEntity extends GenericEnergyReceiverTileEntity implements ISidedInventory { public static final String CMD_SETGLOBAL = "setGlobal"; private InventoryHelper inventoryHelper = new InventoryHelper(this, RemoteStorageContainer.factory, 8); private ItemStack[][] slots = new ItemStack[][] { new ItemStack[0], new ItemStack[0], new ItemStack[0], new ItemStack[0] }; private int[] maxsize = { 0, 0, 0, 0 }; private int[] numStacks = { 0, 0, 0, 0 }; private boolean[] global = { false, false, false, false }; public RemoteStorageTileEntity() { super(ModularStorageConfiguration.REMOTE_MAXENERGY, ModularStorageConfiguration.REMOTE_RECEIVEPERTICK); } private int timer = 0; public boolean isPowerLow() { return getEnergyStored(ForgeDirection.DOWN) < ModularStorageConfiguration.remoteShareLocal; } @Override protected void checkStateServer() { timer--; if (timer > 0) { return; } timer = 5; int hasPower = isPowerLow() ? 0 : 8; int meta = worldObj.getBlockMetadata(xCoord, yCoord, zCoord); int newmeta = (meta & 0x7) | hasPower; if (newmeta != meta) { worldObj.setBlockMetadataWithNotify(xCoord, yCoord, zCoord, newmeta, 2); } RemoteStorageIdRegistry registry = RemoteStorageIdRegistry.getRegistry(worldObj); for (int i = 0 ; i < 4 ; i++) { if (inventoryHelper.containsItem(i)) { ItemStack stack = inventoryHelper.getStackInSlot(i); NBTTagCompound tagCompound = stack.getTagCompound(); if (tagCompound != null && tagCompound.hasKey("id")) { int rf; if (isGlobal(i)) { rf = ModularStorageConfiguration.remoteShareGlobal; } else { rf = ModularStorageConfiguration.remoteShareLocal; } rf = (int) (rf * (2.0f - getInfusedFactor()) / 2.0f); if (getEnergyStored(ForgeDirection.DOWN) < rf) { return; } consumeEnergy(rf); markDirty(); int id = tagCompound.getInteger("id"); registry.publishStorage(id, new GlobalCoordinate(new Coordinate(xCoord, yCoord, zCoord), worldObj.provider.dimensionId)); } } } } @Override public int[] getAccessibleSlotsFromSide(int side) { return RemoteStorageContainer.factory.getAccessibleSlots(); } @Override public boolean canInsertItem(int index, ItemStack item, int side) { return RemoteStorageContainer.factory.isInputSlot(index); } @Override public boolean canExtractItem(int index, ItemStack item, int side) { return RemoteStorageContainer.factory.isOutputSlot(index); } public boolean hasStorage(int index) { return inventoryHelper.containsItem(index); } @Override public int getSizeInventory() { return inventoryHelper.getCount(); } @Override public ItemStack getStackInSlot(int index) { return inventoryHelper.getStackInSlot(index); } @Override public ItemStack decrStackSize(int index, int amount) { worldObj.markBlockForUpdate(xCoord, yCoord, zCoord); return inventoryHelper.decrStackSize(index, amount); } @Override public ItemStack getStackInSlotOnClosing(int index) { return null; } // Compact slots. public void compact(int id) { int si = findRemoteIndex(id); if (si == -1) { return; } ItemStack[] s = findStacksForId(id); InventoryHelper.compactStacks(s, 0, maxsize[si]); updateStackCount(si); markDirty(); } // Find another storage on the same block. public int cycle(int id) { int si = findRemoteIndex(id); if (si == -1) { for (int i = 0 ; i < 4 ; i++) { ItemStack stack = getStackInSlot(i); if (stack != null && stack.getTagCompound() != null && stack.getTagCompound().hasKey("id")) { return stack.getTagCompound().getInteger("id"); } } return -1; } for (int i = si+1 ; i < si + 4 ; i++) { int ii = i % 4; ItemStack stack = getStackInSlot(ii); if (stack != null && stack.getTagCompound() != null && stack.getTagCompound().hasKey("id")) { return stack.getTagCompound().getInteger("id"); } } return id; } private void link(int index) { if (index >= RemoteStorageContainer.SLOT_LINKER) { index -= RemoteStorageContainer.SLOT_LINKER; } if (!inventoryHelper.containsItem(index)) { return; } if (!inventoryHelper.containsItem(index+4)) { return; } ItemStack source = inventoryHelper.getStackInSlot(index); ItemStack dest = inventoryHelper.getStackInSlot(index+4); if (dest.getItemDamage() != StorageModuleItem.STORAGE_REMOTE) { return; } NBTTagCompound tagCompound = source.getTagCompound(); if (tagCompound == null) { tagCompound = new NBTTagCompound(); source.setTagCompound(tagCompound); } int id; if (tagCompound.hasKey("id")) { id = tagCompound.getInteger("id"); } else { RemoteStorageIdRegistry registry = RemoteStorageIdRegistry.getRegistry(worldObj); id = registry.getNewId(); registry.save(worldObj); tagCompound.setInteger("id", id); } tagCompound = dest.getTagCompound(); if (tagCompound == null) { tagCompound = new NBTTagCompound(); dest.setTagCompound(tagCompound); } tagCompound.setInteger("id", id); } @Override public void setInventorySlotContents(int index, ItemStack stack) { inventoryHelper.setInventorySlotContents(getInventoryStackLimit(), index, stack); if (index < RemoteStorageContainer.SLOT_LINKER) { copyFromModule(stack, index); } worldObj.markBlockForUpdate(xCoord, yCoord, zCoord); if (!worldObj.isRemote) { link(index); } } @Override public String getInventoryName() { return "Remote Storage Inventory"; } @Override public boolean hasCustomInventoryName() { return false; } @Override public int getInventoryStackLimit() { return 1; } @Override public boolean isUseableByPlayer(EntityPlayer player) { return canPlayerAccess(player); } @Override public void openInventory() { } @Override public void closeInventory() { } @Override public boolean isItemValidForSlot(int index, ItemStack stack) { return true; } public int findRemoteIndex(int id) { for (int i = 0 ; i < 4 ; i++) { if (inventoryHelper.containsItem(i)) { ItemStack stack = inventoryHelper.getStackInSlot(i); if (stack.getItemDamage() != StorageModuleItem.STORAGE_REMOTE) { NBTTagCompound tagCompound = stack.getTagCompound(); if (tagCompound != null && tagCompound.hasKey("id")) { if (id == tagCompound.getInteger("id")) { return i; } } } } } return -1; } public boolean isGlobal(int index) { return global[index]; } public void setGlobal(int index, boolean global) { this.global[index] = global; markDirty(); worldObj.markBlockForUpdate(xCoord, yCoord, zCoord); } public ItemStack[] getRemoteStacks(int si) { return slots[si]; } public ItemStack getRemoteSlot(int si, int index) { if (index >= slots[si].length) { return null; } return slots[si][index]; } public void updateCount(int si, int cnt) { numStacks[si] = cnt; StorageModuleItem.updateStackSize(getStackInSlot(si), numStacks[si]); } public int getCount(int si) { return numStacks[si]; } public int getMaxStacks(int si) { return maxsize[si]; } public ItemStack decrStackSizeRemote(int si, int index, int amount) { if (index >= slots[si].length) { return null; } ItemStack[] stacks = slots[si]; boolean hasOld = stacks[index] != null; ItemStack its = null; if (stacks[index] != null) { if (stacks[index].stackSize <= amount) { ItemStack old = stacks[index]; stacks[index] = null; its = old; } else { its = stacks[index].splitStack(amount); if (stacks[index].stackSize == 0) { stacks[index] = null; } } } boolean hasNew = stacks[index] != null; if (hasOld && !hasNew) { numStacks[si]--; } else if (hasNew && !hasOld) { numStacks[si]++; } StorageModuleItem.updateStackSize(getStackInSlot(si), numStacks[si]); markDirty(); return its; } public boolean updateRemoteSlot(int si, int limit, int index, ItemStack stack) { if (index >= slots[si].length) { return false; } boolean hasOld = slots[si][index] != null; slots[si][index] = stack; if (stack != null && stack.stackSize > limit) { stack.stackSize = limit; } boolean hasNew = stack != null; if (hasOld && !hasNew) { numStacks[si]--; } else if (hasNew && !hasOld) { numStacks[si]++; } StorageModuleItem.updateStackSize(getStackInSlot(si), numStacks[si]); markDirty(); return true; } public ItemStack findStorageWithId(int id) { for (int i = 0 ; i < 4 ; i++) { if (inventoryHelper.containsItem(i)) { ItemStack stack = inventoryHelper.getStackInSlot(i); if (stack.getItemDamage() != StorageModuleItem.STORAGE_REMOTE) { NBTTagCompound tagCompound = stack.getTagCompound(); if (tagCompound != null && tagCompound.hasKey("id")) { if (id == tagCompound.getInteger("id")) { return stack; } } } } } return null; } public ItemStack[] findStacksForId(int id) { for (int i = 0 ; i < 4 ; i++) { if (inventoryHelper.containsItem(i)) { ItemStack stack = inventoryHelper.getStackInSlot(i); if (stack.getItemDamage() != StorageModuleItem.STORAGE_REMOTE) { NBTTagCompound tagCompound = stack.getTagCompound(); if (tagCompound != null && tagCompound.hasKey("id")) { if (id == tagCompound.getInteger("id")) { return slots[i]; } } } } } return null; } public void copyToModule(int si) { ItemStack stack = inventoryHelper.getStackInSlot(si); if (stack == null) { // Should be impossible. return; } if (stack.getItemDamage() == StorageModuleItem.STORAGE_REMOTE) { return; } NBTTagCompound tagCompound = stack.getTagCompound(); if (tagCompound == null) { tagCompound = new NBTTagCompound(); stack.setTagCompound(tagCompound); } int cnt = writeSlotsToNBT(tagCompound, "Items", si); tagCompound.setInteger("count", cnt); } public void copyFromModule(ItemStack stack, int si) { if (stack == null) { setMaxSize(si, 0); return; } if (stack.getItemDamage() == StorageModuleItem.STORAGE_REMOTE) { setMaxSize(si, 0); return; } setMaxSize(si, StorageModuleItem.MAXSIZE[stack.getItemDamage()]); NBTTagCompound tagCompound = stack.getTagCompound(); if (tagCompound != null) { readSlotsFromNBT(tagCompound, "Items", si); } updateStackCount(si); } private void setMaxSize(int si, int ms) { maxsize[si] = ms; slots[si] = new ItemStack[ms]; numStacks[si] = 0; } private void updateStackCount(int si) { numStacks[si] = 0; ItemStack[] stacks = slots[si]; for (ItemStack stack : stacks) { if (stack != null) { numStacks[si]++; } } } @Override public void readFromNBT(NBTTagCompound tagCompound) { super.readFromNBT(tagCompound); } @Override public void readRestorableFromNBT(NBTTagCompound tagCompound) { super.readRestorableFromNBT(tagCompound); readBufferFromNBT(tagCompound); for (int i = 0 ; i < 4 ; i++) { int max = tagCompound.getInteger("maxSize" + i); setMaxSize(i, max); readSlotsFromNBT(tagCompound, "Slots" + i, i); global[i] = tagCompound.getBoolean("global" + i); updateStackCount(i); } } private void readBufferFromNBT(NBTTagCompound tagCompound) { NBTTagList bufferTagList = tagCompound.getTagList("Items", Constants.NBT.TAG_COMPOUND); for (int i = 0 ; i < bufferTagList.tagCount() ; i++) { NBTTagCompound nbtTagCompound = bufferTagList.getCompoundTagAt(i); inventoryHelper.setStackInSlot(i, ItemStack.loadItemStackFromNBT(nbtTagCompound)); } } private void readSlotsFromNBT(NBTTagCompound tagCompound, String tagname, int index) { NBTTagList bufferTagList = tagCompound.getTagList(tagname, Constants.NBT.TAG_COMPOUND); for (int i = 0 ; i < Math.min(bufferTagList.tagCount(), slots[index].length) ; i++) { NBTTagCompound nbtTagCompound = bufferTagList.getCompoundTagAt(i); slots[index][i] = ItemStack.loadItemStackFromNBT(nbtTagCompound); } } @Override public void writeToNBT(NBTTagCompound tagCompound) { super.writeToNBT(tagCompound); } @Override public void writeRestorableToNBT(NBTTagCompound tagCompound) { super.writeRestorableToNBT(tagCompound); writeBufferToNBT(tagCompound); for (int i = 0 ; i < 4 ; i++) { writeSlotsToNBT(tagCompound, "Slots" + i, i); tagCompound.setInteger("maxSize" + i, maxsize[i]); tagCompound.setBoolean("global" + i, global[i]); } } private void writeBufferToNBT(NBTTagCompound tagCompound) { NBTTagList bufferTagList = new NBTTagList(); for (int i = 0 ; i < inventoryHelper.getCount() ; i++) { ItemStack stack = inventoryHelper.getStackInSlot(i); NBTTagCompound nbtTagCompound = new NBTTagCompound(); if (stack != null) { stack.writeToNBT(nbtTagCompound); } bufferTagList.appendTag(nbtTagCompound); } tagCompound.setTag("Items", bufferTagList); } private int writeSlotsToNBT(NBTTagCompound tagCompound, String tagname, int index) { NBTTagList bufferTagList = new NBTTagList(); int cnt = 0; for (int i = 0 ; i < slots[index].length ; i++) { ItemStack stack = slots[index][i]; NBTTagCompound nbtTagCompound = new NBTTagCompound(); if (stack != null) { stack.writeToNBT(nbtTagCompound); if (stack.stackSize > 0) { cnt++; } } bufferTagList.appendTag(nbtTagCompound); } tagCompound.setTag(tagname, bufferTagList); return cnt; } @Override public boolean execute(EntityPlayerMP playerMP, String command, Map<String, Argument> args) { boolean rc = super.execute(playerMP, command, args); if (rc) { return rc; } if (CMD_SETGLOBAL.equals(command)) { int index = args.get("index").getInteger(); boolean global = args.get("global").getBoolean(); setGlobal(index, global); return true; } return false; } }