1.16.5 Making Inventories Not Stack

Discussion in 'Spigot Plugin Development' started by abstractionAlpha, Mar 21, 2021.

  1. I'm trying to make a plugin that causes items not to stack. Handling tile drops and mobs were easy, but now I'm facing the issue of things like crafting tables, furnaces, and chests, whose generation is stacked by default. For starters, I'm trying to make furnaces work right.

    What I want: When I click on a stack of smelted something, such as 3 iron ingot, then immediately the iron ingot will go right into the first three available slots in my inventory with a random-generated lore. If I don't have 3 open inventory slots, then however many I do have will be filled up, and the original ItemStack will be set to however many should remain. (If I have 2 open inventory slots, the furnace's ItemStack will contain 1 after clicking.)

    The issue: I just can't make the event handler run this functionality. After implementing the below listener, when I try and move items out of the furnace they still move like in regular Minecraft and don't have edited lores. I'm pretty Java handy but I'm much less Spigot handy, and I'm not sure where to start with resolving this.

    The code:
    Code (Java):
    public void onInventoryMove(InventoryMoveItemEvent e) {
        // Reset Items ArrayList
        items = new ArrayList<ItemStack>();

        // Get Event ItemStack
        ItemStack eventItemStack = e.getItem();

        // Create New ItemStack
        ItemStack is = new ItemStack(eventItemStack.getType());
        is.setAmount(1);
        is.setData(eventItemStack.getData());
        is.setItemMeta(eventItemStack.getItemMeta());

        // Generate Items ArrayList
        for (int i = 1; i < eventItemStack.getAmount(); i++) {
            items.add(is);
        }

        // Set Event's ItemStack Amount to Zero
        eventItemStack.setAmount(0);
        e.setItem(eventItemStack);

        // Fill Destination Inventory
        int slot;
        for (ItemStack i : items) {
            i.setLore(StaticMethod.generateLore());

            try {
                slot = StaticMethod.getOpenInventorySlot(e.getDestination());
                e.getDestination().setItem(slot, i);
            } catch (IllegalArgumentException iae) {
                eventItemStack.setAmount(eventItemStack.getAmount() + 1);
            }
        }

        // Set Event's ItemStack Amount to Updated Amount
        e.setItem(eventItemStack);
    }
    Items is just a predefined field. StaticMethod#generateLore() generates a String of length 8 made up of digits 0-9 and puts it into an ArrayList that is returned. StaticMethod#getOpenInventorySlot() takes an Inventory and iterates from i=0 to getSize() until a slot containing null or Material.AIR is found, then returns i.

    Pointers appreciated. Thanks!
     
    #1 abstractionAlpha, Mar 21, 2021
    Last edited: Mar 21, 2021
  2. I'm not exactly sure what your problem is.

    Something you may wish to try is push the itemstack creation into the forloop that pushes them into the arraylist. That way they would each be unique objects and not be references to the same object. I'm not sure if that's something the API would fix up for you or not, but without knowing what exactly the problem is (you probably said and I missed it, sorry), that's the most likely thing I can think of to help.
     
  3. Thanks for your reply - I definitely should've clarified there. I edited this in my original post, but when I try and take smelted things out of the furnace (stacked in the furnace), they just move like vanilla Minecraft and stay stacked in my inventory.

    You're right about reference semantics being a potential problem later. I'll go ahead and fix that too.