The problem:
The argument "c" in selectors (e.g. "@e[c=1]") is supposed to limit the amount of entities targeted by the selector to the x closest (for c=x) or x furthest (for c=-x) entities, sorted by their distance. However, when used inside a scoreboard command (e.g. "scoreboard players set @e[c=1,r=10] something 0") the selector will first "fill" the available slots with all players that match the remaining criteria, regardless of their distance (compared to other matching entities). When the limit was not reached with player entities alone, other entities will be processed like expected (based on their distance that is).
How to reproduce:
Start by creating an objective
/scoreboard objectives add demo dummy
and set up the sidebar so you can see it
/scoreboard objectives setdisplay sidebar demo
Now just place a command block down and put in a command like
/scoreboard players add @e[c=1,r=3] demo 1
Finally, place down an entity (i recommend an Armor stand) next to the command block.
When you activate the cmd block outside the range (in my example 3), the entity will get a new score. As soon as you are near enough (again, 3 blocks in my example), you will be targeted instead, even if the entity you use is standing between you and the cmd block (which makes it clearly the closer one).
Affects:
Most
/scoreboard
commands (excluding/scoreboard teams <join|leave>
and/scoreboard players tag <target> <add|remove>
).The name shown in green from the results of
/scoreboard players tag <target> <list>
(though the list of tags shown in white is from the correct target).The stored selector for CommandStats.
Also note @unknown's comment and code analysis.
Linked issues
is duplicated by 7
Comments 16
Edit: Reason previously described in this comment is not the reason for this bug as @unknown pointed it out. The reason is now contained in the description of MC-80893 and removed from this comment to prevent any confusion.
@@unknown That is not actually the reason (did you mean to post it for MC-80893?). The root cause is from the command processor:
net.minecraft.command.CommandHandler.executeCommand()
int targetIndex = this.getUsernameIndex(icommand, astring);
...
if (targetIndex > -1)
{
List<Entity> list = EntitySelector.<Entity>matchEntities(sender, astring[targetIndex], Entity.class);
...
}
else
{
...
if (this.tryExecute(sender, astring, icommand, rawCommand))
{
++successCount;
}
}
The selector is processed (method matchEntities()
) if the getUsernameIndex()
method doesn't return -1. However:
net.minecraft.command.CommandHandler.getUsernameIndex()
for (int targetIndex = 0; targetIndex < args.length; ++targetIndex)
{
if (command.isUsernameIndex(args, targetIndex) && EntitySelector.matchesMultiplePlayers(args[targetIndex]))
{
return targetIndex;
}
}
return -1;
If the selector cannot potentially match multiple players (@p
, @a[c=1]
, @e[c=1]
), then -1 is returned, thus the selector is not processed yet.
At that point, the selector must be processed by the command classes themselves. Most command classes call the net.minecraft.command.CommandBase.getEntity()
method, which returns an entity without any subclass bias. But any commands that call getPlayer()
instead (those listed in the report) will have player bias, since the selector attempts to obtain targets from a list of players first.
Relates to or duplicates MC-79103
Confirmed for
1.8.4