Islandil Posted August 6, 2016 Share Posted August 6, 2016 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); } Quote Link to comment Share on other sites More sharing options...
Islandil Posted August 7, 2016 Author Share Posted August 7, 2016 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. Quote Link to comment Share on other sites More sharing options...
Animefan8888 Posted August 7, 2016 Share Posted August 7, 2016 Could you show your getStackInSlot method? Quote 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. Link to comment Share on other sites More sharing options...
Islandil Posted August 7, 2016 Author Share Posted August 7, 2016 @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; } Quote Link to comment Share on other sites More sharing options...
Animefan8888 Posted August 7, 2016 Share Posted August 7, 2016 What is ItemContainer.INVENTORY_START equal to? Quote 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. Link to comment Share on other sites More sharing options...
Islandil Posted August 7, 2016 Author Share Posted August 7, 2016 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 ? Quote Link to comment Share on other sites More sharing options...
Animefan8888 Posted August 7, 2016 Share Posted August 7, 2016 Why do you need that? Does your inventory contain a copy of those slots? Quote 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. Link to comment Share on other sites More sharing options...
Islandil Posted August 7, 2016 Author Share Posted August 7, 2016 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. Quote Link to comment Share on other sites More sharing options...
Animefan8888 Posted August 7, 2016 Share Posted August 7, 2016 You don't need to correct it in the inventory. It was good practice in the container. Quote 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. Link to comment Share on other sites More sharing options...
Islandil Posted August 7, 2016 Author Share Posted August 7, 2016 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 ? Quote Link to comment Share on other sites More sharing options...
Animefan8888 Posted August 7, 2016 Share Posted August 7, 2016 Post your whole container and IInventory classes in spoilers please. Quote 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. Link to comment Share on other sites More sharing options...
Islandil Posted August 7, 2016 Author Share Posted August 7, 2016 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); } } Quote Link to comment Share on other sites More sharing options...
Animefan8888 Posted August 7, 2016 Share Posted August 7, 2016 @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]; Quote 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. Link to comment Share on other sites More sharing options...
Islandil Posted August 7, 2016 Author Share Posted August 7, 2016 No change. Quote Link to comment Share on other sites More sharing options...
Animefan8888 Posted August 7, 2016 Share Posted August 7, 2016 Have you tried shift clicking to see if that works? Quote 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. Link to comment Share on other sites More sharing options...
Islandil Posted August 7, 2016 Author Share Posted August 7, 2016 Shift click works ! Quote Link to comment Share on other sites More sharing options...
Animefan8888 Posted August 7, 2016 Share Posted August 7, 2016 Put the ItemContainer.INVENTORY_START back and see if that works Quote 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. Link to comment Share on other sites More sharing options...
Islandil Posted August 7, 2016 Author Share Posted August 7, 2016 No change. Shift click works, not left click pickup. Quote Link to comment Share on other sites More sharing options...
Animefan8888 Posted August 7, 2016 Share Posted August 7, 2016 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; } Quote 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. Link to comment Share on other sites More sharing options...
Islandil Posted August 7, 2016 Author Share Posted August 7, 2016 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 ! Quote Link to comment Share on other sites More sharing options...
Animefan8888 Posted August 7, 2016 Share Posted August 7, 2016 Do look back at the difference I think you will find what you did wrong. Have fun :3 Quote 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. Link to comment Share on other sites More sharing options...
Islandil Posted August 7, 2016 Author Share Posted August 7, 2016 Yes ! Many hours were lost on this, I want, sadly, to spend even more and know why. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
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.