Minecraft – Different commands select different entities (with the same target selector)

minecraft-commandsminecraft-java-edition

I was trying to set the scoreboard values of certain entities with a command like

/execute @e[type=ArmorStand] ~ ~ ~ detect ~ ~-1 ~ stone 0 scoreboard players set @e[c=1] myObj 1

and I noticed that it updated my score instead of the armor stand's.
It was my understanding that the selector @e[c=1] selected the nearest entity, which should be the armor stand that is executing the command. To test this, I used the command

/execute @e[type=ArmorStand] ~ ~ ~ detect ~ ~-1 ~ stone 0 say @e[c=1]

and it said "Armor Stand", not my name.

This seems inconsistent. Is there a reason for this behavior or is it a bug? Is there a way to reliably select the entity that is executing the command?


P.S.: The same thing happens if I place a command block next to the armor stand and let it execute the commands: scoreboard players set @e[c=1] myObj 1 targets me (even though I am further away), but say @e[c=1] says "Armor Stand".

Best Answer

In the source there are couple functions that attempt to obtain a target: one that selects players first (and if it fails, falls back to the other function), and one that does not have a bias towards any type. Every command must choose which one to use when it has a selector.

However, player bias will only occur if the selector itself is @p or @r (without c being changed) or the c parameter is set to value of exactly "1". If so, the selector won't be processed yet and the command class itself will use one of those functions to process it. Otherwise, the selector is processed first with no bias and then the command is processed for each target found, being handed the already-obtained target (and not a selector to process).

Almost all /scoreboard commands use the player bias function, except for /scoreboard players tag ... and /scoreboard teams join .... The stored selector for CommandStats also uses it.

The only way to prevent it from targeting players is to exclude players from selection:

/execute @e[type=ArmorStand] ~ ~ ~ detect ~ ~-1 ~ stone 0 scoreboard players set @e[type=!Player,c=1] myObj 1

This does mean that if you want a nested /scoreboard command or CommandStats to still target all entities including players, you'd have to create two copies: one for players and one for non-player entities:

/execute @e[type=!Player] ~ ~ ~ /scoreboard players set @e[type=!Player,c=1] OBJ 1
/execute @a ~ ~ ~ /scoreboard players set @a[c=1] OBJ 1

Or:

/stats entity @e[type=!Player] set SuccessCount @e[type=!Player,c=1] OBJ
/stats entity @a set SuccessCount @a[c=1] OBJ