Minecraft – Functions – Prevent specific item from being put in chests

minecraft-commandsminecraft-java-edition

My idea is to not let a specific item be put in any chest of the world, if possible using /setblock or /fill (relative to each player's position.) with an oldBlockHandling of destroy. I'm avoiding using anything that isn't functions, and it doesn't matter if the solution is complex or long.

I tried with this:

scoreboard objectives add chesthasitem dummy 
stats entity @a set AffectedBlocks @a chesthasitem
execute @a ~ ~ ~ testforblock ~1 ~ ~ chest -1 {Items:[{id:"minecraft:writable_book",tag:{display:{Name:""}}}]} 
execute @a[score_chesthasitem_min=1] ~ ~ ~ setblock ~1 ~ ~ air 0 
destroy

The clean tags and selectors are unimportant, do not worry about it.
I got this to work for one chest, but when I repeated the same command with one different scoreboard and different coords, the chest was detected but not destroyed.

Best Answer

I built on what you had. You were very close. You mention another scoreboard objective, you do not need another.

I removed the first line from your function. (scoreboard objectives add chesthasitem dummy) You do not need to create the objective continuously. Manually type that line in chat one time to create the objective.

I added a line scoreboard players add @a chesthasitem 0. This is to make sure the stat's target is already tracked on the players scoreboard. Visit this website if you want learn more about CommandStats and why this is required. This may have been why your second scoreboard objective did not update and destroy a chest in a different direction.

The last two commands in your function I used multiple times, only editing the relative coordinates, to test 4 blocks (North, South, East, and West). You will have to add several iterations to this in order to test all possible accessible chest positions from a players position. Here is the contents of the function I was using:

#Set score for all players and set stats to record to all players
scoreboard players add @a chesthasitem 0
stats entity @a set AffectedBlocks @a chesthasitem

#Test x ~1 and destroy
execute @a ~ ~ ~ testforblock ~1 ~ ~ chest -1 {Items:[{id:"minecraft:writable_book",tag:{display:{Name:"test"}}}]} 
execute @a[score_chesthasitem_min=1] ~ ~ ~ setblock ~1 ~ ~ air 0 destroy

#Test x ~-1 and destroy
 execute @a ~ ~ ~ testforblock ~-1 ~ ~ chest -1 {Items:[{id:"minecraft:writable_book",tag:{display:{Name:"test"}}}]} 
 execute @a[score_chesthasitem_min=1] ~ ~ ~ setblock ~-1 ~ ~ air 0 destroy

#Test z ~1 and destroy
execute @a ~ ~ ~ testforblock ~ ~ ~1 chest -1 {Items:[{id:"minecraft:writable_book",tag:{display:{Name:"test"}}}]} 
execute @a[score_chesthasitem_min=1] ~ ~ ~ setblock ~ ~ ~1 air 0 destroy

#Test z ~-1 and destroy
execute @a ~ ~ ~ testforblock ~ ~ ~-1 chest -1 {Items:[{id:"minecraft:writable_book",tag:{display:{Name:"test"}}}]} 
execute @a[score_chesthasitem_min=1] ~ ~ ~ setblock ~ ~ ~-1 air 0 destroy

Note: I am detecting a Book and Quill renamed test in this example.

Then you can run the gamerule gameLoopFunction to run the function every tick. Here is the wiki on the subject. The sytax is:
/gamerule gameLoopFunction <namespace:path/to/function/file>