How to programmatically move items inside an inventory?
I'll start with the simplest example, a chest created with the command:
/setblock ~ ~ ~ chest{Items:[{Slot:0,id:"stone",Count:1}]}
That command places a chest at your position that contains 1 stone in the first slot (slot numbers start with 0).
First create a scoreboard to hold the target slot number. Not only is it required, it also gives the additional bonus that you can make the target slot depend on something without needing more commands.
/scoreboard objectives add slot dummy
Set the scoreboard to the target slot number, this uses the executing player as score holder, but it might as well be a fake player (just enter a name instead of @s
) or any other selector, just use the same selector later for the movement.
/scoreboard players set @s slot 3
Now the actual movement: You just have to change the slot number of the item in the chest using /execute store
. That command allows defining a path and only writing to that path while keeping everything around it unchanged.
/execute store result block ~ ~ ~ Items[0].Slot byte 1 run scoreboard players get @s slot
Note that MC-123307 doesn't apply here, so you cannot use this for player inventories.
And here's an even bigger catch: You have to specify the current index of the item to be moved. Not the slot number, the index. If you for example have items in slot 0, 1, 2, 3 and 15, but nothing in 4-14, then the items in slot number 15 have the slot index 4, not 15, since there are no entries in the NBT array for empty slots.
So moving from slot 0 is the only safe one to do, all other ones would require you to check exactly which slots before your chosen slot are full and which ones empty. It might even be possible for the slots to be in the wrong order in the NBT (for example if you moved them backwards with this method), in which case you would have to check the slot number for all items in the chest and do some Maths on them.
It's not impossible, it's just much more complicated.
Special cases:
- Moving items onto a slot that already contains items deletes the old items.
- Moving items to negative slot numbers or other non-existent slots (e.g. too high) deletes them.
There is a new method in 1.14 and it does not have the downside of having to know which slots exist and which don't, to access the correct array indices. This method works completely with slot numbers and uses the new NBT Path syntax that can select matching entries in lists. It's also just one single command now.
Let's say you want to move a stack from the fifth to the ninth slot of a chest at the coordinates 12 34 56. There might also be other stacks in other slots (for example half a stack of dirt in the last slot and a single diamond in the first slot), but your commands don't need to know that, they work regardless.
This is the command:
/data modify block 12 34 56 Items[{Slot:4b}].Slot set value 8
(Note that slot numbers start with 0, so everything is one lower.)
If there is already an item in the ninth slot, this overwrites it, just like in the other answer. And if you enter a number higher than the maximum slot number (for example 5 for hoppers, which only have 0 to 4), the moved stack gets deleted.
If you want to use variable indices, the other answer is still preferable. You could also make it not rely on which slots are filled by combining it with my dynamically sized array answer.