Minecraft – (Java Minecraft 1.14) How to detect multiple item entities which are stacks of the same size on a particular block

minecraft-commandsminecraft-java-edition

I have a function in a datapack which is supposed to check for the presence of four stacks of flesh and four stacks of bones on four soul sand and four quartz blocks respectively. To do this, I've been giving the first flesh the tag "flesh1", the second "flesh2", and so one, and same with the bones. Then, it gives the executing entity the tag 'fleshAndBonesPresent'.

Unfortunately, when I run this I don't get the tag, and when I try to kill the entity with the tag "flesh1" it says no entity is found. Trying to have an entity without the flesh1, flesh2, or flesh3 tags (but with the fourth one) say "hi" (or trying to kill them) also doesn't work. Here's the function. I'm putting in the whole thing because it's pretty short and having all of it will probably help you understand my question better:

execute if block ~ ~-1 ~ minecraft:soul_sand as @e[type=item,nbt={Item:{id:"minecraft:rotten_flesh",Count:64b}},distance=..4] run tag @s add flesh1
execute if block ~ ~-1 ~ minecraft:soul_sand as @e[type=item,nbt={Item:{id:"minecraft:rotten_flesh",Count:64b}},distance=..4,tag=!flesh1] run tag @s add flesh2
execute if block ~ ~-1 ~ minecraft:soul_sand as @e[type=item,nbt={Item:{id:"minecraft:rotten_flesh",Count:64b}},distance=..4,tag=!flesh1,tag=!flesh2] run tag @s add flesh3
execute if block ~ ~-1 ~ minecraft:soul_sand as @e[type=item,nbt={Item:{id:"minecraft:rotten_flesh",Count:64b}},distance=..4,tag=!flesh1,tag=!flesh2,tag=!flesh3] run tag @s add flesh4

execute if block ~ ~-1 ~ minecraft:quartz_block as @e[type=item,nbt={Item:{id:"minecraft:bone",Count:64b}},distance=..2] run tag @s add bone1
execute if block ~ ~-1 ~ minecraft:quartz_block as @e[type=item,nbt={Item:{id:"minecraft:bone",Count:64b}},distance=..2,tag=!bone1] run tag @s add bone2
execute if block ~ ~-1 ~ minecraft:quartz_block as @e[type=item,nbt={Item:{id:"minecraft:bone",Count:64b}},distance=..2,tag=!bone1,tag=!bone2] run tag @s add bone3
execute if block ~ ~-1 ~ minecraft:quartz_block as @e[type=item,nbt={Item:{id:"minecraft:bone",Count:64b}},distance=..2,tag=!bone1,tag=!bone2,tag=!bone3] run tag @s add bone4

execute if entity @e[tag=flesh1] if entity @e[tag=flesh2] if entity @e[tag=flesh3] if entity @e[tag=flesh4] if entity @e[tag=bone1] if entity @e[tag=bone2] if entity @e[tag=bone3] if entity @e[tag=bone4] run tag @s add fleshAndBonesPresent

I was trying to kill the entities from the chat after I ran the function. I've checked the wiki on tag use and it says that to select entities without a certain series of tags to use multiple tag=! selector arguments. I don't really know what's wrong but it's pretty frustrating so any help/advice is appreciated.
Here's a picture of the setup (yes it is a ritual):
My setup

Edit: As you can see in the comments, using execute store result score was promising, but didn't work.

Best Answer

Instead of trying to debug this complicated arrangement of tags, I basically rewrote your function, maybe that already fixes your problem:

scoreboard players set @s itemCounter 0
execute at @e[type=item,nbt={Item:{id:"minecraft:rotten_flesh",Count:64b}},distance=..4] if block ~ ~-0.5 ~ soul_sand run scoreboard players add @s itemCounter 1
execute if score @s itemCounter matches 4 run tag @s add fleshPresent

scoreboard players set @s itemCounter 0
execute at @e[type=item,nbt={Item:{id:"minecraft:bone",Count:64b}},distance=..2] if block ~ ~-0.5 ~ quartz_block run scoreboard players add @s itemCounter 1
execute if score @s itemCounter matches 4 run tag @s add bonesPresent

This uses the old method of making every entity you're testing for increase a shared score by 1 each. This is not as nice for performance as I would have hoped, usually 1.13 has nicer ways to do things like this, but maybe someone else has an idea how to do it better.

What I assume went wrong in your original function:

  • The items sink into soul sand, so you have to check for ~ ~ ~ instead of ~ ~-1 ~ to test for the block they are in, instead of the one they are on, which would be the one below the soul sand.
  • You started with if block …, which means that the block would be checked for whoever runs the function. Since you didn't mention who executes this function, I assume it's the player. But it actually doesn't matter much, because you're testing for being on quartz and also for being on soul sand, which one entity can't be both at the same time.