Posted November 18, 20168 yr Here is my first attempt at using Capability and IItemHandler. The tile seems to work fine, but I would like someone's review to verify that I did this right or if something can be improved. public class TileStrongChest extends GeneralTileEntity implements IItemHandlerModifiable { final static public String CHESTTYPE="Chest type",ITEMSTACK="Item stack"; public int type; ItemStack[] storage; static public Capability<IItemHandler> iItemHandler=CapabilityItemHandler.ITEM_HANDLER_CAPABILITY; public ItemStackHandler itemStackHandler; public TileStrongChest(){super();} public TileStrongChest(int metadata) { super(); type=metadata; storage=new ItemStack[metadata==0 ? 54 : metadata==1 ? 81 : 108]; itemStackHandler=new ItemStackHandler(storage); } @Override public boolean hasCapability(Capability<?> capability, EnumFacing facing) { if(capability==iItemHandler) return true; return super.hasCapability(capability, facing); } @Override public <T> T getCapability(Capability<T> capability, EnumFacing facing) { if(capability==iItemHandler) return (T) this; return super.getCapability(capability, facing); } @Nullable @Override public ITextComponent getDisplayName() { int stacks=0; for (int i = 0; i < getSlots(); i++) { if(storage[i]!=null)stacks++; } return new TextComponentString(stacks+"/"+ getSlots()); } @Override public int getSlots() { return storage.length; } @Override public ItemStack getStackInSlot(int slot) { return storage[slot]; } @Override public ItemStack insertItem(int slot, ItemStack stack, boolean simulate) { return itemStackHandler.insertItem(slot,stack,simulate); } @Override public ItemStack extractItem(int slot, int amount, boolean simulate) { return itemStackHandler.extractItem(slot,amount,simulate); } @Override public void setStackInSlot(int slot, ItemStack stack) { storage[slot]=stack; } @Override public NBTTagCompound writeToNBT(NBTTagCompound compound) { NBTTagCompound nbtTagCompound=super.writeToNBT(compound); int number=0; for(ItemStack itemStack: storage) { if(itemStack!=null) { NBTTagCompound item=itemStack.writeToNBT(new NBTTagCompound()); compound.setTag(ITEMSTACK+number,item); } number++; } nbtTagCompound.setShort(CHESTTYPE, (short) type); return nbtTagCompound; } @Override public void readFromNBT(NBTTagCompound compound) { super.readFromNBT(compound); type=compound.getShort(CHESTTYPE); switch (type) { case 0: storage=new ItemStack[54];break; case 1: storage=new ItemStack[81];break; case 2: storage=new ItemStack[108];break; } for (int i = 0; i < storage.length; i++) { ItemStack itemStack=ItemStack.loadItemStackFromNBT(compound.getCompoundTag(ITEMSTACK+i)); if(itemStack!=null)storage[i]=itemStack; } itemStackHandler=new ItemStackHandler(storage); } }
November 18, 20168 yr The whole point of the Capability system is that you don't implement interfaces on your TileEntity , instead you store the objects in the TileEntity and override the ICapabilityProvider methods to return them. Forge's documentation explains this in more detail here. I also have a simple explanation here. Don't implement IItemHandler on your TileEntity . Either use the CapabilityItemHandler.ITEM_HANDLER_CAPABILITY field directly or annotate your own field with @CapabilityInject . Don't use the existing field to initialise your own. Don't store the ItemStack array, only interact with your inventory through the ItemStackHandler ItemStackHandler implements INBTSerializable , use this to write it to and read it from NBT Please don't PM me to ask for help. Asking your question in a public thread preserves it for people who are having the same problem in the future.
November 19, 20168 yr Author All right, I refactored it, now it looks like this: public class TileStrongChest extends GeneralTileEntity { final static public String CHESTTYPE = "Chest type", ITEMSTACKS = "Item stacks"; public int type; public ItemStackHandler itemStackHandler; public TileStrongChest() {super();} public TileStrongChest(int metadata) { super(); type = metadata; itemStackHandler=new ItemStackHandler(metadata==0 ? 54 : metadata==1 ? 81 : 108); } @Override public boolean hasCapability(Capability<?> capability, EnumFacing facing) { if (capability == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) return true; return super.hasCapability(capability, facing); } @Override public <T> T getCapability(Capability<T> capability, EnumFacing facing) { if (capability == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) return (T) itemStackHandler; return super.getCapability(capability, facing); } @Nullable @Override public ITextComponent getDisplayName() { int stacks=0; for (int i = 0; i < itemStackHandler.getSlots(); i++) { if(itemStackHandler.getStackInSlot(i)!=null)stacks++; } return new TextComponentString(stacks+"/"+ itemStackHandler.getSlots()); } @Override public NBTTagCompound writeToNBT(NBTTagCompound compound) { NBTTagCompound nbtTagCompound=super.writeToNBT(compound); NBTTagCompound handlernbt= itemStackHandler.serializeNBT(); nbtTagCompound.setTag(ITEMSTACKS,handlernbt); nbtTagCompound.setShort(CHESTTYPE, (short) type); return nbtTagCompound; } @Override public void readFromNBT(NBTTagCompound compound) { super.readFromNBT(compound); type=compound.getShort(CHESTTYPE); itemStackHandler=new ItemStackHandler(); itemStackHandler.deserializeNBT(compound.getCompoundTag(ITEMSTACKS)); } } Seems to be working. Although I have read the docs few times, I didn't understand it right away. I assert that it needs to show an example, or a link to one.
November 19, 20168 yr That looks correct. I believe LexManos is strongly against the Forge documentation containing any "copy-pasta" code, i.e. fully working code blocks with minimal explanation apart from "copy this code into your code to make it work". If you have some well-documented example code, it may be added (though I don't speak for the Forge team). Please don't PM me to ask for help. Asking your question in a public thread preserves it for people who are having the same problem in the future.
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.