Having an execute running as multiple entities will cancel for the rest of the entities if one of these fails.
Steps to reproduce:
Place down one stone block surrounded by two non-stone blocks
Place an armor stand on top of each block
Run the following command while standing on the left of the line:
execute as @e[type=armor_stand,sort=nearest] at @s run setblock ~ ~-1 ~ stone
The expected behavior would be, that it will place stone under the two armor stands on the sides and leave the stone in the middle as is. This is not the case, because a setblock, that doesn't change anything (stone->stone) will fail and cancel the execute. Only one of the two stones got set.
Furthermore, but this belongs to a separate bug-report, the order, that execute processes each entity is in my eyes in reverse. Even though nearest was specified, the further armor stand sets its block first, before the middle one canceled the rest of the execute.
Comments 4
It seems, like the if
gets evaluated for all armor stands first, and only if all conditions are met, the run part of the execute gets called (for each armor stand of course).
So I thought, if you put the block-detection into a separate, nested execute it would work, but it gives the exact same result. There might be either some faulty optimization, where the nested execute got optimized into the first execute or it was never supposed to be like this, and the if was meant to be checked for each selector-list item.
Put into commands, what I mean is, that
execute as @e[type=armor_stand] at @s if block ~ ~-1 ~ stone run setblock ~ ~-1 ~ dirt
does the exact same thing as
execute as @e[type=armor_stand] at @s run execute if block ~ ~-1 ~ stone run setblock ~ ~-1 ~ dirt
and they both only run the final command for each entity if the if
was true for each entity.
Dinnerbone should take a look at this, as to how he intended this in the first place. At the moment it seems like the system is somewhat flawed in either of those two ways.
A small followup:
If you create a function test:test
with the content:
execute if block ~ ~-1 ~ stone run setblock ~ ~-1 ~ dirt
and run it via
execute as @e[type=armor_stand] at @s run function test:test
it does work, as the the nested execute doesn't get merged with the parent execute and therefore handle the if for each separate function call.
Because the last few comments aren't actually related to the bug report completely, I created a new ticket: MC-121934
This ticket can be marked as closed again, as the bug described in this report is fixed and the comments are actually related to the new bug report.
So i tried this command
in theory it should replace every diamond in the dropper under the armor stand with 1 coal. And yes it does, but only if every armor stand has an diamond in the dropper below. What i expect is that only the armor stand wich hast the diamond in the dropper replaces the diamond with 1 coal and not every armor stand.