Minecraft – ny way in Minecraft to detect who deposited a diamond into a chest using command blocks

minecraft-commandsminecraft-java-edition

So far, I've been able to detect when a diamond is placed into a chest's inventory but how can I detect who placed that diamond?

I'd prefer not to use the nearest player because someone else could potentially be falsely identified. (I have a command chain that trades players emeralds in exchange for experience levels and it also sometimes robs random nearby players.)

Some context: I'm making a race to be the first to deposit a diamond. I could constrain the player accessing the chest and just check who is standing on a block, but if I did that, I could also just test the player's inventory directly. But that seems boring. Adding the chest adds to the drama, I feel. Like, if someone fumbles last minute and deposits dirt on accident, someone else could easily win, which is fun.

My command chain is currently:

if block x y z chest{Items:[{id:"minecraft:diamond"}]}
say Diamond Detected

Edit: The diamonds are mined and as such, I will not necessarily be able to tag them for each player. Another user suggested I could scan the inventories of the users at every tick and tag the diamonds in their inventory with their name. I don't know how to do this, though I believe this is the direction where I will find my answer.

Best Answer

If you don't know who has each diamond

Step one

Give each player a unique scoreboard ID. See this related question for how to do that.

Step two

Run the following command in a repeating, always active command block:

execute as @e[type=item,nbt={Item:{id:"minecraft:diamond"}}] run data merge entity @s {Item:{tag:{Unclaimed:1b}}

This gives each diamond item on the ground a custom Unclaimed tag, allowing you implement Step 3 without 30+ command blocks per player

Step three

Once for each player who could be playing the map, run in a repeating command block:

clear @a[scores={Id=1}] diamond{Unclaimed:1b} 1

and then, in a conditional chain command block that the repeating command block is pointing to

give @a[scores={Id=1}] diamond{PlayerOwns:1b} 1

Repeat this for each player, using scores={Id=2} and PlayerOwns:2b for the second player and so on.

Step four

Now that each diamond has a tag describing whose it is, you can use the technique described in ExpertCoder14's answer to determine who put a diamond in the chest.

This has a known bug that if Alice puts a diamond in a container, and then Bob takes the diamond out of the container (and never drops and picks it up again), the diamond is still interpreted as belonging to Alice -- but I actually like that if I understand what you're doing correctly; if you stole someone else's diamond from a chest instead of mining your own, that means you're trying to cheat… karma!

If you want a more seamless experience, you may want to interest yourself in player inventory modification. With the method above, the diamond is visibly replaced by a different one, you can use this to make a seamless replacement.