Posted August 6, 20169 yr I implemented an item when shift right clicked open a GUI with the inventory and 2 more slot using mainly https://github.com/coolAlias/Forge_Tutorials/blob/master/InventoryItemTutorial.java as inspiration. After a day of debugging I don't understand why when I put item inside my custom inventory the quantity is double and why when I try to retrieve from the custom inventory the item are deleted. Here is a part of the Container @Nullable @Override public ItemStack transferStackInSlot(EntityPlayer player, int fromSlotIndex) { ItemStack previous = null; Slot fromSlot = (Slot) this.inventorySlots.get(fromSlotIndex); if (fromSlot != null && fromSlot.getHasStack()) { ItemStack current = fromSlot.getStack(); previous = current.copy(); if (fromSlotIndex < INVENTORY_START) { // Player to inventory if (!this.mergeItemStack(current, HOTBAR_START, INVENTORY_START, false)) return null; } else { // Inventory to player if (!this.mergeItemStack(current, INVENTORY_START, INVENTORY_START + inventory.getSizeInventory(), false)) return null; } if (current.stackSize == 0) { fromSlot.putStack((ItemStack) null); } else { fromSlot.onSlotChanged(); } if (current.stackSize == previous.stackSize) { return null; } fromSlot.onPickupFromSlot(player, current); } return previous; } @Nullable @Override public ItemStack slotClick(int slotId, int dragType, ClickType clickTypeIn, EntityPlayer player) { if (slotId >= 0 && getSlot(slotId) != null && getSlot(slotId).getStack() == player.getHeldItem(EnumHand.MAIN_HAND)) { return null; } return super.slotClick(slotId, dragType, clickTypeIn, player); } and the IInventory @Nullable @Override public ItemStack decrStackSize(int index, int amount) { ItemStack stack = getStackInSlot(index); if (stack != null) { if (amount < stack.stackSize) { setInventorySlotContents(index, stack.splitStack(amount)); } else if (amount == stack.stackSize) { removeStackFromSlot(index); } else { throw new IllegalArgumentException("Cannot remove " + amount + " from a stack size of " + stack.stackSize); } } return stack; } // Remove an item from the inventory @Nullable @Override public ItemStack removeStackFromSlot(int index) { ItemStack removedStack = getStackInSlot(index); if (indexInRange(index)) { inventory[getLinkedIndex(index)] = null; } return removedStack; } // Add an item to the inventory @Override public void setInventorySlotContents(int index, @Nullable ItemStack stack) { if (isItemValidForSlot(index, stack)) { inventory[getLinkedIndex(index)] = stack; } markDirty(); } @Override public void markDirty() { for (int i = 0; i < getSizeInventory(); ++i) { if (inventory[i] != null && inventory[i].stackSize == 0) { inventory[i] = null; } } writeToNBT(inventoryItem.getTagCompound()); } // Get inventory content stored inside NBT tags on item stack public void readFromNBT(NBTTagCompound compound) { NBTTagList itemsList = compound.getTagList(NBT_TAG_LIST_KEY, Constants.NBT.TAG_COMPOUND); for (int i = 0; i < itemsList.tagCount(); ++i) { NBTTagCompound item = itemsList.getCompoundTagAt(i); int slot = item.getInteger(NBT_TAG_ITEM_SLOT_KEY); if (indexInRange(slot)) { inventory[slot] = ItemStack.loadItemStackFromNBT(item); } } } // Write inventory data to NBT tag list on item stack public void writeToNBT(NBTTagCompound compound) { NBTTagList itemsList = new NBTTagList(); for (int i = 0; i < getSizeInventory(); ++i) { if (inventory[i] != null) { NBTTagCompound item = new NBTTagCompound(); item.setInteger(NBT_TAG_ITEM_SLOT_KEY, i); inventory[i].writeToNBT(item); itemsList.appendTag(item); } } compound.setTag(NBT_TAG_LIST_KEY, itemsList); }
August 7, 20169 yr Author The duplication came from not overriding this method inside the Container @Override public boolean getCanCraft(EntityPlayer player) { return false; } But when I try to retrieve item from the additional inventory slots the amount is zero. So my second problem is still here.
August 7, 20169 yr Could you show your getStackInSlot method? VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect. Forge and vanilla BlockState generator.
August 7, 20169 yr Author @Nullable @Override public ItemStack getStackInSlot(int index) { return indexInRange(index) ? inventory[getLinkedIndex(index)] : null; } private boolean indexInRange(int index) { index = getLinkedIndex(index); if (index >= 0 && index < getSizeInventory()) { return true; } else { throw new IndexOutOfBoundsException("Access index " + index + " is outside inventory index range, max " + getSizeInventory()); } } private int getLinkedIndex(int index) { return index - ItemContainer.INVENTORY_START; }
August 7, 20169 yr What is ItemContainer.INVENTORY_START equal to? VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect. Forge and vanilla BlockState generator.
August 7, 20169 yr Author public static final int INVENTORY_START = 36; I use this in my custom Container to add the hotbar (0- next the player inventory (9-35) and next my two additional slots (36-37), since I need to calculate the corresponding index in my IInventory (0-1) I use a constant. Bad practice ?
August 7, 20169 yr Why do you need that? Does your inventory contain a copy of those slots? VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect. Forge and vanilla BlockState generator.
August 7, 20169 yr Author I use this in my custom Container to add the hotbar (0- next the player inventory (9-35) and next my two additional slots (36-37), since I need to calculate the corresponding index in my IInventory (0-1) I use a constant. Bad practice ? Maybe you miss my edit, sorry.
August 7, 20169 yr You don't need to correct it in the inventory. It was good practice in the container. VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect. Forge and vanilla BlockState generator.
August 7, 20169 yr Author Changed the getLinkedIndex to return the index parameter. Now isIndexInRange throw IndexOutOfBoundsException. Because the index given is 36 and 37 and is out side 0-1. private boolean isIndexInRange(int index) { index = getLinkedIndex(index); if (index >= 0 && index < getSizeInventory()) { return true; } else { throw new IndexOutOfBoundsException("Access index " + index + " is outside inventory index range, max " + getSizeInventory()); } } private int getLinkedIndex(int index) { return index; } It seems that the Container send the slot index and not the inventory index. Is there a problem in my Container ?
August 7, 20169 yr Post your whole container and IInventory classes in spoilers please. VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect. Forge and vanilla BlockState generator.
August 7, 20169 yr Author Container public class ItemContainer extends Container { public static final int HOTBAR_START = 0; public static final int PLAYER_INVENTORY_START = 9; public static final int PLAYER_ARMOR_INVENTORY_START = 36; public static final int INVENTORY_START = 36; private final ItemInventory inventory; private final IInventory playerInventory; public ItemContainer(IInventory playerInventory, ItemInventory inventory) { this.inventory = inventory; this.playerInventory = playerInventory; // Hotbar slots for (int x = 0; x < 9; x++) { addSlotToContainer(new Slot(playerInventory, x, 8 + x * 18, 142)); } // Player inventory slots for (int y = 0; y < 3; y++) { for (int x = 0; x < 9; x++) { addSlotToContainer(new Slot(playerInventory, x + y * 9 + PLAYER_INVENTORY_START, 8 + x * 18, 84 + y * 18)); } } // Player armor slots /*for (int y = 0; y < 4; y++) { addSlotToContainer(new Slot(playerInventory, y + PLAYER_ARMOR_INVENTORY_START, 8, 8 + y * 18)); }*/ // Inventory slots for (int y = 0; y < inventory.getSizeInventory(); y++) { addSlotToContainer(new SlotItemInventory(inventory, y + INVENTORY_START, 80, 8 + y * 18)); } } @Nullable @Override public ItemStack transferStackInSlot(EntityPlayer player, int fromSlotIndex) { ItemStack previous = null; Slot fromSlot = (Slot) this.inventorySlots.get(fromSlotIndex); if (fromSlot != null && fromSlot.getHasStack()) { ItemStack current = fromSlot.getStack(); previous = current.copy(); if (fromSlotIndex < INVENTORY_START) { // Inventory to player if (!this.mergeItemStack(current, INVENTORY_START, INVENTORY_START + inventory.getSizeInventory(), true)) { return null; } fromSlot.onSlotChange(current, previous); } else { // Player to inventory if (!this.mergeItemStack(current, HOTBAR_START, INVENTORY_START, false)) { return null; } } if (current.stackSize == 0) { fromSlot.putStack((ItemStack) null); } else { fromSlot.onSlotChanged(); } if (current.stackSize == previous.stackSize) { return null; } fromSlot.onPickupFromSlot(player, current); } return previous; } @Override public boolean canInteractWith(EntityPlayer player) { return inventory.isUseableByPlayer(player); } @Nullable @Override public ItemStack slotClick(int slotId, int dragType, ClickType clickType, EntityPlayer player) { if (slotId >= 0 && getSlot(slotId) != null && getSlot(slotId).getStack() == player.getHeldItem(EnumHand.MAIN_HAND)) { return null; } return super.slotClick(slotId, dragType, clickType, player); } public ItemInventory getItemInventory() { return inventory; } @Override public boolean getCanCraft(EntityPlayer player) { return false; } // Provide filtering ability on item inventory public class SlotItemInventory extends Slot { ItemInventory inventory; public SlotItemInventory(ItemInventory inventory, int index, int xPosition, int yPosition) { super(inventory, index, xPosition, yPosition); this.inventory = inventory; } @Override public boolean isItemValid(@Nullable ItemStack stack) { return stack != null ? inventory.isWhitelisted(stack.getItem()) && !inventory.isBlacklisted(stack.getItem()) : true; } } } IInventory public class ItemInventory implements IInventory { private static final String NBT_TAG_LIST_KEY = MYMOD.MODID + ":item_inventory_items_list"; private static final String NBT_TAG_ITEM_SLOT_KEY = MYMOD.MODID + ":item_inventory_item_slot"; private final String name; private final ItemStack inventoryItem; protected String ID; protected String IDTagKey; private ItemStack[] inventory; private Item[] whitelist; private Item[] blacklist; private boolean whitelistEnabled = true; public ItemInventory(ItemStack stack, int sizeInventory, String name) { this.inventoryItem = stack; this.inventory = new ItemStack[sizeInventory]; this.name = name; this.IDTagKey = MYMOD.MODID + ":" + name + "_ID"; if (!stack.hasTagCompound() || ID == null) { stack.setTagCompound(new NBTTagCompound()); this.ID = UUID.randomUUID().toString(); stack.getTagCompound().setString(IDTagKey, ID); } readFromNBT(stack.getTagCompound()); } @Override public int getSizeInventory() { return inventory.length; } @Nullable @Override public ItemStack getStackInSlot(int index) { return isIndexInRange(index) ? inventory[getLinkedIndex(index)] : null; } @Nullable @Override public ItemStack decrStackSize(int index, int amount) { ItemStack stack = getStackInSlot(index); if (stack != null) { if (amount <= stack.stackSize) { setInventorySlotContents(index, stack.splitStack(amount)); } else { throw new IllegalArgumentException("Cannot remove " + amount + " from a stack size of " + stack.stackSize); } } return stack; } // Remove an item from the inventory @Nullable @Override public ItemStack removeStackFromSlot(int index) { ItemStack stack = getStackInSlot(index); setInventorySlotContents(index, null); return stack; } // Add an item to the inventory @Override public void setInventorySlotContents(int index, @Nullable ItemStack stack) { inventory[getLinkedIndex(index)] = stack; if (stack != null && stack.stackSize > getInventoryStackLimit()) { stack.stackSize = getInventoryStackLimit(); } markDirty(); } @Override public int getInventoryStackLimit() { return 64; } @Override public void markDirty() { for (int i = 0; i < getSizeInventory(); ++i) { if (inventory[i] != null && inventory[i].stackSize == 0) { inventory[i] = null; } } writeToNBT(inventoryItem.getTagCompound()); } @Override public boolean isUseableByPlayer(EntityPlayer player) { return true; } @Override public void openInventory(EntityPlayer player) { } @Override public void closeInventory(EntityPlayer player) { } // Check if the new item is valid for this inventory @Override public boolean isItemValidForSlot(int index, ItemStack stack) { return isWhitelisted(stack.getItem()) && !isBlacklisted(stack.getItem()); } @Override public int getField(int id) { return 0; } @Override public void clear() { for (int i = 0; i < getSizeInventory(); i++) { removeStackFromSlot(i); } } @Override public String getName() { return name; } @Override public boolean hasCustomName() { return false; } @Override public ITextComponent getDisplayName() { return null; } @Override public void setField(int id, int value) { } @Override public int getFieldCount() { return 0; } public Item[] getWhitelist() { return whitelist; } public void setWhitelist(Item[] whitelist) { whitelistEnabled = true; this.whitelist = whitelist; } public boolean isWhitelisted(Item item) { if (whitelistEnabled && whitelist != null) { for (Item itemWhitelisted : whitelist) { if (itemWhitelisted == item) { return true; } } } return false; } public Item[] getBlacklist() { return blacklist; } public void setBlacklist(Item[] blacklist) { whitelistEnabled = false; this.blacklist = blacklist; } public boolean isBlacklisted(Item item) { if (!whitelistEnabled && blacklist != null) { for (Item itemBlackisted : blacklist) { if (itemBlackisted == item) { return true; } } } return false; } private boolean isIndexInRange(int index) { index = getLinkedIndex(index); if (index >= 0 && index < getSizeInventory()) { return true; } else { throw new IndexOutOfBoundsException("Access index " + index + " is outside inventory index range, max " + getSizeInventory()); } } private int getLinkedIndex(int index) { return index; } // Get inventory content stored inside NBT tags on item stack public void readFromNBT(NBTTagCompound compound) { NBTTagList itemsList = compound.getTagList(NBT_TAG_LIST_KEY, Constants.NBT.TAG_COMPOUND); for (int i = 0; i < itemsList.tagCount(); ++i) { NBTTagCompound item = itemsList.getCompoundTagAt(i); int slot = item.getInteger(NBT_TAG_ITEM_SLOT_KEY); if (isIndexInRange(slot)) { inventory[slot] = ItemStack.loadItemStackFromNBT(item); } } } // Write inventory data to NBT tag list on item stack public void writeToNBT(NBTTagCompound compound) { NBTTagList itemsList = new NBTTagList(); for (int i = 0; i < getSizeInventory(); ++i) { if (inventory[i] != null) { NBTTagCompound item = new NBTTagCompound(); item.setInteger(NBT_TAG_ITEM_SLOT_KEY, i); inventory[i].writeToNBT(item); itemsList.appendTag(item); } } compound.setTag(NBT_TAG_LIST_KEY, itemsList); } }
August 7, 20169 yr @Nullable @Override public ItemStack removeStackFromSlot(int index) { ItemStack stack = getStackInSlot(index); setInventorySlotContents(index, null); return stack; } Instead of ItemStack stack = getStackInSlot(index); // Do this ItemStack stack = itemstacks[index]; VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect. Forge and vanilla BlockState generator.
August 7, 20169 yr Have you tried shift clicking to see if that works? VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect. Forge and vanilla BlockState generator.
August 7, 20169 yr Put the ItemContainer.INVENTORY_START back and see if that works VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect. Forge and vanilla BlockState generator.
August 7, 20169 yr Try this for decrStackSize if (this.mainSlots[index].stackSize <= count) { itemstack = this.mainSlots[index]; this.mainSlots[index] = null; return itemstack; } else { itemstack = this.mainSlots[index].splitStack(count); if (this.mainSlots[index].stackSize == 0) { this.mainSlots[index] = null; } return itemstack; } VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect. Forge and vanilla BlockState generator.
August 7, 20169 yr Author Did this implementation (otherwise I was getting a out of bounds exception) @Nullable @Override public ItemStack decrStackSize(int index, int amount) { ItemStack stack; if (inventory[getLinkedIndex(index)].stackSize <= amount) { stack = inventory[getLinkedIndex(index)]; inventory[getLinkedIndex(index)] = null; } else { stack = inventory[getLinkedIndex(index)].splitStack(amount); if (inventory[getLinkedIndex(index)].stackSize == 0) { inventory[getLinkedIndex(index)] = null; } } return stack; } And it works. Thanks a lot !
August 7, 20169 yr Do look back at the difference I think you will find what you did wrong. Have fun :3 VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect. Forge and vanilla BlockState generator.
August 7, 20169 yr Author Yes ! Many hours were lost on this, I want, sadly, to spend even more and know why.
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.