Posted September 17, 20223 yr PocketDimensionItemHandler public class PocketDimensionItemHandler implements IItemHandler, INBTSerializable<CompoundTag> { private static final String SLOT_COUNT = "slotCount"; private static final String STACK_SIZE = "stackSize"; private static final String POCKET_INVENTORY = "pocketInventory"; protected NonNullList<DimensionalStack> pocketInventory; private int slotCount; private long stackCapacity; private final ItemStack itemStack; public PocketDimensionItemHandler(ItemStack itemStack, int slotCount, long stackSize) { this.itemStack = itemStack; if (itemStack.hasTag()) { deserializeNBT(itemStack.getOrCreateTag()); } else { this.slotCount = slotCount; this.stackCapacity = stackSize; pocketInventory = NonNullList.create(); for (int i = 0; i < slotCount; i++) { pocketInventory.add(i, new DimensionalStack(ItemStack.EMPTY)); } } } @Override public int getSlots() { return 0; } @Override public @NotNull ItemStack getStackInSlot(int slot) { return null; } @Override public @NotNull ItemStack insertItem(int slot, @NotNull ItemStack addedStack, boolean simulate) { if (addedStack.isEmpty()) return ItemStack.EMPTY; if (slot < 0 || slot > slotCount) throw new IndexOutOfBoundsException("Slot is not available"); DimensionalStack dimensionalStack = pocketInventory.get(slot); ItemStack topStack = dimensionalStack.getTopStack(); if (topStack.isEmpty()) { dimensionalStack.setTopStack(addedStack); return ItemStack.EMPTY; } boolean isEligibleForNewStack = topStack.getCount() + addedStack.getCount() > topStack.getMaxStackSize(); long dimensionalStackSize = ((long) topStack.getMaxStackSize() * dimensionalStack.getFullStackCount()) + topStack.getCount(); long remainingCapacity = stackCapacity - dimensionalStackSize; if (isEligibleForNewStack) { if (remainingCapacity < topStack.getMaxStackSize()) { addedStack.shrink((int) remainingCapacity); topStack.setCount(topStack.getMaxStackSize()); dimensionalStack.setTopStack(topStack); return addedStack; } else { int spaceLeft = calculateAvailableSpace(topStack); addedStack.shrink(spaceLeft); // shrink added stack by amount left in topStack topStack = addedStack.copy(); // make what's left in addedStack to topStack dimensionalStack.setTopStack(topStack); dimensionalStack.setFullStackCount(dimensionalStack.getFullStackCount() + 1); // increment by 1 fullStackCount return ItemStack.EMPTY; } } else { topStack.setCount(topStack.getCount() + addedStack.getCount()); dimensionalStack.setTopStack(topStack); return ItemStack.EMPTY; } } @Override public @NotNull ItemStack extractItem(int slot, int amount, boolean simulate) { return null; } @Override public int getSlotLimit(int slot) { return 0; } @Override public boolean isItemValid(int slot, @NotNull ItemStack stack) { return false; } @Override public CompoundTag serializeNBT() { CompoundTag nbt = new CompoundTag(); CompoundTag inventoryNbt = new CompoundTag(); for (int i = 1; i <= slotCount; i++) { inventoryNbt.put(String.valueOf(i), pocketInventory.get(i - 1).saveNBTData()); } nbt.putInt(SLOT_COUNT, slotCount); nbt.putLong(STACK_SIZE, stackCapacity); nbt.put(POCKET_INVENTORY, inventoryNbt); return nbt; } @Override public void deserializeNBT(CompoundTag nbt) { this.slotCount = nbt.getInt(SLOT_COUNT); this.stackCapacity = nbt.getLong(STACK_SIZE); CompoundTag inventoryNbt; pocketInventory = NonNullList.create(); for (int i = 1; i <= slotCount; i++) { inventoryNbt = nbt.getCompound(String.valueOf(i)); pocketInventory.add(i - 1, new DimensionalStack()); pocketInventory.get(i - 1).loadNBTData(inventoryNbt); } } public static int calculateAvailableSpace(ItemStack stack) { return stack.getMaxStackSize() - stack.getCount(); } } PocketDimensionProvider public class PocketDimensionProvider implements ICapabilityProvider, INBTSerializable<CompoundTag> { private final ItemStack itemStack; public static final Capability<PocketDimensionItemHandler> POCKET_DIMENSION = CapabilityManager.get(new CapabilityToken<>() { }); private PocketDimensionItemHandler pocketDimension = null; private final LazyOptional<IItemHandler> optionalData = LazyOptional.of(this::createPocketDimension); public PocketDimensionProvider(ItemStack itemStack) { this.itemStack = itemStack; } private PocketDimensionItemHandler createPocketDimension() { if (pocketDimension == null) { pocketDimension = new PocketDimensionItemHandler(itemStack, 9, 2048); } return pocketDimension; } @Nonnull @Override public <T> LazyOptional<T> getCapability(@Nonnull Capability<T> cap) { if (cap == POCKET_DIMENSION) { return optionalData.cast(); } return LazyOptional.empty(); } @Nonnull @Override public <T> LazyOptional<T> getCapability(@Nonnull Capability<T> cap, @Nullable Direction side) { return getCapability(cap); } void invalidate() { this.optionalData.invalidate(); } @Override public CompoundTag serializeNBT() { return createPocketDimension().serializeNBT(); } @Override public void deserializeNBT(CompoundTag nbt) { createPocketDimension().deserializeNBT(nbt); } } PocketItem public class PocketItem extends Item implements MenuProvider { public PocketItem(Properties pProperties) { super(pProperties); } @Override public InteractionResult useOn(UseOnContext pContext) { Level pLevel = pContext.getLevel(); if (!pLevel.isClientSide) { Player pPlayer = pContext.getPlayer(); InteractionHand pUsedHand = pContext.getHand(); BlockPos pos = pContext.getClickedPos(); BlockState clickedBlock = pLevel.getBlockState(pos); ItemStack itemStack = new ItemStack(clickedBlock.getBlock(), 10); ItemStack heldItem = pPlayer.getItemInHand(pUsedHand); @NotNull LazyOptional<PocketDimensionItemHandler> pocketCap = heldItem.getCapability(PocketDimensionProvider.POCKET_DIMENSION); Random rand = new Random(); pocketCap.ifPresent((pocketDimension) -> { pocketDimension.insertItem(rand.nextInt(9), itemStack, false); }); } return InteractionResult.sidedSuccess(pLevel.isClientSide()); } @Override public Component getDisplayName() { return null; } @Nullable @Override public AbstractContainerMenu createMenu(int pContainerId, Inventory pPlayerInventory, Player pPlayer) { return null; } @Nullable @Override public ICapabilityProvider initCapabilities(ItemStack stack, @Nullable CompoundTag nbt) { return new PocketDimensionProvider(stack); } } DimensionalStack public class DimensionalStack { private ItemStack topStack; private int fullStackCount; public DimensionalStack() { topStack = ItemStack.EMPTY; } public DimensionalStack(ItemStack topStack) { this.topStack = topStack; fullStackCount = 0; } public DimensionalStack(ItemStack topStack, int fullStackCount) { this.topStack = topStack; this.fullStackCount = fullStackCount; } public ItemStack getTopStack() { return topStack; } public void setTopStack(ItemStack topStack) { this.topStack = topStack; } public int getFullStackCount() { return fullStackCount; } public void setFullStackCount(int fullStackCount) { this.fullStackCount = fullStackCount; } public CompoundTag saveNBTData() { CompoundTag nbt = new CompoundTag(); nbt.put("topStack", topStack.serializeNBT()); nbt.putInt("fullStackCount", fullStackCount); return nbt; } public void loadNBTData(CompoundTag nbt) { ItemStack deserializedItemStack = ItemStack.of(nbt.getCompound("topStack")); this.fullStackCount = nbt.getInt("fullStackCount"); } } Hello, I have a problem understanding why the item doesn't retain it's NBT data when dropped on the ground and picked back up, to my understanding I'm calling the method to insert items in server enviroment, but should I create and send sync packet server -> client? Please ignore quality of the code and it's nonsense I'm trying to understand things. Edited September 17, 20223 yr by xand3s indistinguishable code blocks
September 17, 20223 yr - Removed for bad formatting - Edited September 17, 20223 yr by warjort Boilerplate: If you don't post your logs/debug.log we can't help you. For curseforge you need to enable the forge debug.log in its minecraft settings. You should also post your crash report if you have one. If there is no error in the log file and you don't have a crash report then post the launcher_log.txt from the minecraft folder. Again for curseforge this will be in your curseforge/minecraft/Install Large files should be posted to a file sharing site like https://gist.github.com You should also read the support forum sticky post.
September 17, 20223 yr @Override public CompoundTag serializeNBT() { CompoundTag nbt = new CompoundTag(); CompoundTag inventoryNbt = new CompoundTag(); for (int i = 1; i <= slotCount; i++) { inventoryNbt.put(String.valueOf(i), pocketInventory.get(i - 1).saveNBTData()); } nbt.putInt(SLOT_COUNT, slotCount); nbt.putLong(STACK_SIZE, stackCapacity); // HERE you put your inventory in a subtag nbt.put(POCKET_INVENTORY, inventoryNbt); return nbt; } @Override public void deserializeNBT(CompoundTag nbt) { this.slotCount = nbt.getInt(SLOT_COUNT); this.stackCapacity = nbt.getLong(STACK_SIZE); CompoundTag inventoryNbt; pocketInventory = NonNullList.create(); for (int i = 1; i <= slotCount; i++) { // HERE you are trying to read the inventory from the top level tag? inventoryNbt = nbt.getCompound(String.valueOf(i)); pocketInventory.add(i - 1, new DimensionalStack()); pocketInventory.get(i - 1).loadNBTData(inventoryNbt); } } Boilerplate: If you don't post your logs/debug.log we can't help you. For curseforge you need to enable the forge debug.log in its minecraft settings. You should also post your crash report if you have one. If there is no error in the log file and you don't have a crash report then post the launcher_log.txt from the minecraft folder. Again for curseforge this will be in your curseforge/minecraft/Install Large files should be posted to a file sharing site like https://gist.github.com You should also read the support forum sticky post.
September 17, 20223 yr Author Yeah, I've basically just noticed these errors, I've screwed this deserialization hard
September 17, 20223 yr You can use the EntityJoinLevelEvent and check if it is an ItemEntity to see what NBT its ItemStack has. You can also see if your NBT survives saving and reloading the game. If it does not, you are not modifying the correct ItemStack on the server. Edited September 17, 20223 yr by warjort Boilerplate: If you don't post your logs/debug.log we can't help you. For curseforge you need to enable the forge debug.log in its minecraft settings. You should also post your crash report if you have one. If there is no error in the log file and you don't have a crash report then post the launcher_log.txt from the minecraft folder. Again for curseforge this will be in your curseforge/minecraft/Install Large files should be posted to a file sharing site like https://gist.github.com You should also read the support forum sticky post.
September 17, 20223 yr Author So, for future somebody who stumbles upon this, besides the error pointed out I've also didn't assign a value to class field in public void loadNBTData(CompoundTag nbt) { ItemStack deserializedItemStack = ItemStack.of(nbt.getCompound("topStack")); this.fullStackCount = nbt.getInt("fullStackCount"); }
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.