Modify items in inventory

Hello!

I would like to get only the slots of the player inventory that contain a specific ItemType and modify the data of that items.

My attempt(in Kotlin but you can definitly read it):


player.inventory.query<Inventory>(ItemTypes.SOME_ITEM_TYPE).slots<Slot>().forEach { slotWithItem ->
    slotWithItem.peek().get().offer(Keys.SOME_KEY, someData)
}

The plugin crashes with a NotImplementedException because iterating over slots seems not to be implemented yet. But that’s not my question. Instead I want to ask, is this the right way to do it once it is implemented?
I read the big PR but I am not smarter afterwards :confused:

I agree, a docs write-up for the inventory would be nice.

Inventory#slots() has never worked for me, as far as I know… I would try the different methods in something to see how far it is implemented (or just check SpongeCommon/Forge).

I’m also interested in other replies.

https://github.com/SocraticPhoenix/StarAPI/blob/master/src/main/java/com/gmail/socraticphoenix/sponge/star/enchantment/StarEnchantmentUtil.java#L210
Look into the above method and file, which iterates over various parts of the inventory. In the above file, I’m looking for certain items with special data, but AFAIK it works on the latest build. :slight_smile:

Also,

this will not work, items returned from querying are always copies, you have to set it back, so it’d be something like this:

slotWithItem.setItem(slotWithItem.peek().get().offer(Keys.SOME_KEY, someData)) //Not confident on set item method name...
1 Like

Thanks!

I had little success.

A todo since 1 Jan.

So instead of using the result of a query I query the Inventory myself. For now just the Hotbar:

       Sponge.getGame().server.onlinePlayers.forEach { player ->
            val targetPos = ...
            val inv = player.inventory.query<Hotbar>(Hotbar::class.java)
            if (inv is Hotbar) { //instanceof
                setCompassTargetedPos(inv, targetPos)
            }
        }
    /**
     * Try setting Keys.TARGETED_LOCATION on compasses in provided inventory
     */
    fun setCompassTargetedPos(inventory: Inventory2D, targetPos: Vector3d) {
        inventory.slots<Inventory>().forEach { slot ->
            val itemOpt = slot.peek()
            if (itemOpt.isPresent) {
                val item = itemOpt.get()
                if (item.item.equals(ItemTypes.COMPASS)) {
                    item.offer(Keys.TARGETED_LOCATION, targetPos)
                    slot.set(item)
                    log("Set pos to $targetPos")
                }
            }
        }
    }

The querying works! We just have to wait until iterating over query results is implemented(I think this is really needed soon!).

Just one thing that doesn’t work: The data. The result of set(item) is that the current item was replaced. So there everything went well. But in data offering something seems to fail. I don’t know why.

Edit: The DataTransactionResult says FAILURE… :confused:
Edit2: item.supports(Keys.TARGETED_LOCATION) is false but the item is definitely a compass.

I was sure I had addressed this, but I was mistaken.

Basically, the current javadocs for TargetedLocationData (and Keys.TARGETED_LOCATION) are completely and utterly wrong.The compass location can only be set on a per-player basis, not on a per-item basis.

I’ll be modifying the javadocs soon to address this.

1 Like

The javadocs are fixed in the latest SpongeAPI.

1 Like

Sorry for late asking but i tryng to modify a item on player inventory using the RandomByte example and i modified to this:

The even is ClickInventoryEvent and i tryng to modify an open custom inventory on click event, to change the lore of clicked item.

   for (Inventory slot:event.getTargetInventory().slots()){
		if (slot.peek().isPresent()){
			ItemStack itema = slot.poll().get();//remove the item
			if (itema.getItem().equals(item.getItem())){
				slot.set(item);//set the itemslot
				break;
			}
		}
	}

But item still the same and dont transform to item i is set. :frowning:

Some ideia what i doing wrong?

EDIT1:
I created a hashmap to store the SlotPosition that i used to create my inventory:

private HashMap<ItemType,SlotPos> itemPosition;

And populate with:

this.itemPosition.put(this.guiItens[slotc].getItem(), new SlotPos(slot,linha));

And when i try to set the new item based on last SlotPos get by itemtype:

event.getTargetInventory().query(this.itemPosition.get(item.getItem())).set(item);	

The item in open inventory dont changed.

My question about this is if i need to recreate the inventory and reopen to do this?

EDIT2: No, i cant recreate the inventory :frowning:

Most events are fired before the results of the action occur. In your case, you are changing the slot contents, then Sponge applies the changes from the event onto the inventory. Try cancelling the event so Sponge doesn’t make those changes.