So, the NSE Exception is being thrown by #getProperty
. My understand is that the SlotPos
property represents the position of the a Slot
in a higher Inventory
, and thus the Slot
is not aware of it’s SlotPos
because it can have multiple parents. If someone with a better understanding of the InventoryAPI can clarify what’s up, I’d be interested in knowing too.
However, you’re jumping through hoops to do something that’s relatively simply. When you’re iterating through Inventory#slots
, your Inventory i
is the Inventory representation of a given Slot
(to get a better idea for why, it’d be good to review this PR even though it’s a bit outdated).
Effectively, you’re trying to get an InventoryProperty
from your Inventory
, then query it again for the same property - which if it works, isn’t getting you anywhere.
Now, let me ask you this - what’s wrong with using player.getInventory().offer(ItemStack itemStack)
? The #offer
method checks to see if there are empty ItemStack
s or existing ones of the same type, and is generally sufficient for most use cases. If you don’t need to know exactly what slot it’s going to, why go through the hassle of iterating through all of them?
Anyways, I thought at first you were trying to set all empty slots, so I wrote this before the previous and I really don’t want to delete it. So, here’s a cleaner way you can do this if #offer
doesn’t suit your needs.
// Iterates through all Slots within this inventory. While the resulting
// Inventory should be an instanceof Slot, we don't need to identify it
// as such and can use the provided Inventory methods.
for (Inventory i : player.getInventory().slots()) {
// As per the API, #size returns the number of ItemStacks present
// within this Inventory. As it is also a Slot, it must return 0
// or 1, where 0 means there is no ItemStack in that slot (empty).
if (i.size() == 0) {
// It is possible to use either #offer or #set (see the API
// javadocs for the difference). I would personally use #offer
// in this case because it will not replace existing ItemStacks.
i.offer(ItemStack.of(ItemTypes.COOKED_FISH, 1));
// If you only wanted the first empty slot (poor me :/)
break;
}
}
I think the important thing to note is that your code should follow the principle of least astonishment. Avoid trying to do things like obtain a SlotPos
property and re-query it. You should also address cases where no empty slot is found, as well as handle the InventoryTransactionResult
if need be. Make sure your code is clear and easy to understand, and it’ll make your life much easier.