Comprehensive Guide to CommandStats

This tutorial is complex.

You should be well acquainted with commands and scoreboard work before attempting to learn this. Advanced information will be covered on top of this already-advanced topic.

Some of this information may contain buggy behavior, but the goal is to be as accurate as possible.

Terms used:

  1. “stat” refers to CommandStats, not scoreboard statistics.
  2. “trigger” refers to a CommandStat trigger rather than the separate /trigger command.
  3. “sender” refers to the entity or block that executes the command.

Index

  1. What are CommandStats?
  2. How can I apply them?
  3. Triggering
  4. CommandStats

    4.1 SuccessCount
    4.2 AffectedBlocks
    4.3 AffectedItems
    4.4 AffectedEntities
    4.5 QueryResult

  5. Conclusion

What are CommandStats?

CommandStats are a set of triggers applied to entities/tile entities that await further data from executed commands in order to modify a score. When a command is activated, the command sender has their stored triggers activated relevant to the command. A /clear command would trigger the “AffectedItems” CommandStat while the /fill command would trigger the “AffectedBlocks” stat. Any irrelevant triggers will not be activated, meaning /fill will not trigger “AffectedItems”.

When a trigger activates, a specific target will have a specific score set equal to a value based on the return of the command. If /clear removed 50 items, the “AffectedItems” target will have their score set to 50. If /fill places 10 blocks, the “AffectedBlocks” target will have their score set to 10.

Put simply: CommandStats set a score based on the success of a command.

Click here for a resource table of all CommandStats and how their work with their types.

How can I apply them?

Command Blocks and Signs are the only tile entities which can have CommandStats. Every regular entity can have CommandStats.

The /stats command can be used to easily apply them, but because these triggers are stored in NBT data, they can also be applied during creation with /summon, /setblock, or /fill, and after-the-fact with the /entitydata
or /blockdata commands. The NBT structure is the same for all accepting targets.

Every sender can only hold one of each Commandstat type. Attempting to add the same type twice will overwrite the old one.

If a trigger is not applied then the return value of a command will simply not be used.

/stats with Entities:

/stats entity <target> set <CommandStat> <score target> <objective>

<target> – The entity to apply the trigger to. When the entity itself runs a command as a command sender, only the triggers stored on them relevant to the executed command will activate.

<CommandStat> – One of the triggers to apply (see below).

<score target> – The target whose score should be modified as a result of the trigger. Note that selectors are not parsed upon activation of /stats , but rather are stored as they are literally written and are internally parsed when the stat is triggered each time. If the score target is @p and a player named “Steve” is closest when the stat is triggered, their score is modified. If later on “Alex” is closest when the stat is triggered, their score is modified instead. Can only be a single target. If you want to affect the executing entity, you will always want to use the @s selector introduced in 1.12, which is much more efficient than the other selectors at selecting the command sender.

<objective> – The objective for the target.

/stats entity <target> clear <CommandStat>

<target> – The entity that has a trigger to be removed.

<CommandStat> – The trigger to remove.

/stats with Blocks:

/stats block X Y Z set <CommandStat> <score target> <objective>
/stats block X Y Z clear

NBT structure via /summon

/summon Creeper ~ ~1 ~ {
  CommandStats:{
    SuccessCountName:"@s",
    SuccessCountObjective:"OBJ",
    AffectedEntitiesName:"@s",
    AffectedEntitiesObjective:"OBJ",
    AffectedItemsName:"@s",
    AffectedItemsObjective:"OBJ",
    AffectedBlocksName:"@s",
    AffectedBlocksObjective:"OBJ",
    QueryResultName:"@s",
    QueryResultObjective:"OBJ"
  }
}

As a complete example of applying a trigger, the following assigns the “SuccessCount” stat to every player. The target the players affect will be themselves, as the @s selector always selects the command-sending entity. The objective modified will be “OBJ”. Refer to the CommandStats list for information on the “SuccessCount” stat.

/stats entity @a set SuccessCount @s OBJ

Prior to 1.12, you would use @a[c=1] for sender bias.

/stats entity @a set SuccessCount @a[c=1] OBJ

Triggering

The major prerequisite to triggering a CommandStat is for the stat’s target to already be tracked on the scoreboard. This is as easy as setting their score to 0, or adding 0 if you need this on a clock. Keep in mind that when the stat’s selector is parsed, it does not look for the closest matching entity that is also tracked. It simply looks for the closest matching entity and does not move beyond that, even if they could not have their score modified.

/scoreboard players add @a OBJ 0

The CommandStat that will eventually be triggered:

/stats entity @a set SuccessCount @s OBJ

In order to trigger the stored stat, the holder of that stat must run a command as a command sender. If the holder is a command block, then there’s no problem there. If the holder is a player, they can manually run a command themselves. However, if you want to remotely force an entity to run a command, you must use /execute . The following forces all players to run a command, which /testfor checking for the number of players within 10 blocks.

/execute X Y Z <command>
/execute @a ~ ~ ~ testfor @a[r=10]

Every time the command runs, the player will have their own “OBJ” score set equal to the number of players within 10 blocks of them. This includes themselves, of course, so the score will always be at least 1. If there are 2 other players within 10 blocks, the score is set to 3.


Consider the following command:

/stats entity @e[type=Creeper] set AffectedBlocks @e[type=Villager,c=1] OBJ

All creepers will have an “AffectedBlocks” trigger applied to them. When activated, the single closest villager to the creeper will have its “OBJ” score set equal to the value given to “AffectedBlocks”. The following command is then run, triggering “AffectedBlocks”.

/execute @e[type=Creeper] ~ ~1 ~ fill ~ ~ ~ ~ ~1 ~ minecraft:gold_block

The blue arrow represents the command sender executing a command. The command will fill in 2 total blocks. That value is passed on to the “AffectedBlocks” trigger, should the command sender have that trigger waiting.

The red arrow represents the result of the trigger activating from the sender. The villager closest to the sender has their “OBJ” score set to 2, because that is the number of affected blocks.


SuccessCount

For all examples for this CommandStat, assume there are 3 player entities total.

SuccessCount is the simplest of the stats. This is triggered when any command is activated and is set equal to the number of successfully iterated commands. The number of iterations is normally equal to the number of matching targets in a target selector. If there is no target selector, resulting values can only be 1 or 0.

The following will set the “SuccessCount” score equal to 3. This is because most commands run the same number of times as there are matching targets, which in this case is 3.

/testfor @a

Exceptions

/spreadplayers

The /spreadplayers command does not run the same number of times as there are targets. Instead, it only runs a maximum of one time, producing a “SuccessCount” value of only 1 or 0.

/scoreboard with * wildcard

The * wildcard is not a target selector, thus the command is only processed once. The “SuccessCount” value can only be 1 or 0.

/scoreboard players set * OBJ 0

/scoreboard players operation …

In the case of the ‘operation’ function, which accepts two targets, the number of iterations is equal to the selector that had the most matches. For example, all of the following would run 3 times since 3 is greater than 1 in all cases.

/scoreboard players operation @a OBJ = @p OBJ
/scoreboard players operation @p OBJ = @a OBJ
/scoreboard players operation * OBJ = @a OBJ
/scoreboard players operation @a OBJ = * OBJ

AffectedBlocks

This stat sets a score equal to the number of blocks modified. It will be 0 if no blocks were affected, with a varying maximum dependent on the command being run.

Maximum of 1

The following commands, when successful, can only return a value of 1.

1. /blockdata
2. /setblock
3. /testforblock

Varied maximum

The following commands, when successful, can have a varying return value. The values are equal to the total number of blocks cloned, filled, or detected. Note that with /testforblocks , it can only have a value other than 0 if it successfully matched the entire structure.

1. /clone
2. /fill
3. /testforblocks

AffectedItems

For all examples for this CommandStat, assume there are 3 player entities total.

This stat sets a score equal to the number of inventory items modified. Note that none of these are a total collective of items provided to all players. For example, if the following command activates, the final “AffectedItems” score is dependent on the success value of the very last target processed, as is the standard for processed commands. Instead of the final score being 30, it will be 10.

/give @a minecraft:stone 10

/clear

The “AffectedItems” score will be equal to the total number of items removed from the inventory. If the maximum amount provided is 0, the return value is the entire number of matched items that could have been cleared.

/clear <target> [item ID] [Damage] [maximum amount] {dataTags}
/clear @p minecraft:stone 0 0

/give

The “AffectedItems” score will be equal to the number of total items provided to the player. It will essentially be equal to the “Count” portion of the /give syntax.

/enchant

The value can only be either 1 or 0, and will only be 1 if the enchantment was successfully applied.

/replaceitem

The “AffectedItems” score will be equal to the number of items placed in the inventory slot. This does not consider items being replaced with the same kind of item. Just like /give , it is always equal to the “Count” portion of the /replaceitem syntax.

AffectedEntities / “TotalIterations”

For all examples for this CommandStat, assume there is 1 player entity and 2 non-player entities (3 entities total).

This is the most complicated trigger and its name might not be the most accurate. While the other triggers are based on the success of a command, this one is entirely based on the number of iterations of the command disregarding any possible success, including syntax errors, save for a few exceptions. The number of entities “affected” is essentially unrelated. Think of it as “TotalIterations” instead of “AffectedEntities”.

As an initial example: when the following command runs, it has to be processed 3 times in order to change all targets. The first time it runs it changes non-player entity A, then it runs a second time but instead to change non-player entity B, and then a third time to attempt changing player A. /entitydata does not allow targeting player entities, but the command must iterate anyway in order to determine that. The resulting score is 3, matching the total number of times the command is processed.

/entitydata @e {CustomName:"Test"}

If the selector itself can target more than one entity (@e, @p[c=2]), but has no possible targets, then the command is not processed at all (which also explains why you don’t always get error messages in failed commands). The “AffectedEntities” score will be set to 0 in these cases. Otherwise, if the selector can only target one entity (@e[c=1], @p, Skylinerw), but there are no possible targets, “AffectedEntities” is set to 1.

Advanced: Target Indexes

Commands that include a specific slot in its syntax for a target will provide the number of targets discovered from a parsed target selector. Prior to processing the command itself, the “AffectedEntities” score will be set equal to the number of total targets. This is why the success of the command, as well as its syntax, is irrelevant to the resulting score.

The order of operations relevant to this stat:

1. Determine if executed command exists.
2. Locate the target index of the expected command and check if there is a target specified in that slot in the executed command.
3. Process target selector to obtain the total number of potential targets. If it is not a selector that obtains multiple targets, or not a selector at all, the value is always 1 even the target doesn’t exist.
4. Set “AffectedEntities” equal to that number.
5. The command is then processed the same number of times as there are possible targets.

The /tellraw command has a target index at the very beginning, just after the command declaration (marked as “<target>”).

/tellraw <target> <JSON messages>

Using the following command would result in an “AffectedEntities” score of 3. This is because the target index has a selector specified and that selector targets all of our example entities. /tellraw cannot send a message to non-player entities, so it would normally be expected that the score returns a value of 1. But since the “AffectedEntities” score is set before processing the command, and because it targets all entities, it will be 3.

/tellraw @e "Hello"

The next command shows that bad syntax will still result in the “AffectedEntities” score being 3. The selector is in the correct target index location, thus the selector is processed first and the score is set before processing the command.

/give <player> [Count] [Damage] {dataTags}
/give @e

Commands that do not include a target index will always provide a score of 1, such as /say , /setblock , /defaultgamemode , and many other commands. Think of it as the command only iterating once, hence the made-up name “TotalIterations”. This can be seen by simply running any of these commands even when the syntax is incorrect.

/setblock X Y Z <block ID> [Damage] [replacement method] {dataTags}
/setblock

Furthermore, since there is no discernible target index in the following command, the resulting score is 1, essentially following the same rules as commands with no target index at all. There must be the word “entity” after “/stats” rather than @e in order for there to be a target index. This also shows that target selectors in incorrect locations in the command do not contribute to the score.

/stats <entity|block> ...
/stats @e

And finally, if a non-existent command is run, the score will simply not change from what it was before attempting to run the command.


Exceptions

There are a couple specific commands that override the target index process. Note that in these cases, “AffectedEntities” is still set prior but will be overwritten where necessary.

/spreadplayers

The /spreadplayers command does not actually include a “target index” as far as the source is concerned. The command is only processed a single time regardless of how many targets there are. As explained before, this means that its “AffectedEntities” is 1.

At the very end of processing the command, the “AffectedEntities” value will be set equal to the number of targets that /spreadplayers finally affected, staying true to the “AffectedEntities” name. If it did not find any matches, then the stat is not set a second time, remaining at 1 because that’s what it was set to beforehand.

/scoreboard with * wildcard

This is one of the rare cases in which you can get an “AffectedEntities” score of 0 even if there is only one “target”. When using a wildcard in place of targets, the command itself is actually only processed once because * is seen as a single target’s name. The following command would set “AffectedEntities” equal to the number of records modified on the scoreboard. If there is no objective named “OBJ”, then “AffectedEntities” is set to 0 because no record was affected.

/scoreboard players set * OBJ 1

/scoreboard players operation …

In the case of the ‘operation’ function, which accepts two targets, the number of iterations is equal to the selector that had the most matches. For example, all of the following would result in an “AffectedEntities” score of 3 since 3 is greater than 1 in all cases.

/scoreboard players operation @e OBJ = @p OBJ
/scoreboard players operation @p OBJ = @e OBJ
/scoreboard players operation * OBJ = @e OBJ
/scoreboard players operation @e OBJ = * OBJ

/scoreboard teams empty <team>

Same as before, since there are no target indexes, the command is only processed once and “AffectedEntities” is set to the initial value of 1. In this case, same as the other /scoreboard command, the value can be overridden completely. “AffectedEntities” is set equal to the number of players that were removed from the team, which can be 0. However, if the team does not exist, the value is not changed and will remain as the initial value of 1.

QueryResult

This is one of the more specialized stats. A very small number of commands have access to this and each returns very specific values.

/gamerule

When specifying a gamerule name but not a value, the “QueryResult” score is set equal to the gamerule’s value. For example, the following provides me with a “QueryResult” value of 3 (if using the default tick speed).

/gamerule randomTickSpeed

If the stored value is “true” or “false”, the scores become 1 or 0 respectively. If the value is not “true”, “false”, or an integer, the score will be set to 0. If the gamerule does not exist, “QueryResult” will not be triggered.

/list

/list can only be used in multiplayer. When used, the “QueryResult” score will be set to the number of online players.

/scoreboard

The /scoreboard command has numerous return values that the “QueryResult” score is set equal to.

Returns the number of teams.

/scoreboard teams list

Returns the number of players on a team, regardless of their online status. This means fake players will be counted. If the team does not exist, “QueryResult” is not triggered.

/scoreboard teams list TEAMNAME

Returns the total number of players tracked on the scoreboard, regardless of their online status.

/scoreboard players list

Returns the total number of objectives the specified player has a score in. If specified player does not exist, the return value is 0.

/scoreboard players list Skylinerw
/scoreboard players list @a

/time

/time has specific functions for “QueryResult”.

The following returns the daytime value, which essentially equals the current day in ticks.

/time query daytime

And the following returns the total time the world has been played.

/time query gametime

/worldborder

Provides the current width of the worldborder.

/worldborder get

/xp

By setting the experience to 0, “QueryResult” is given the number of experience points or levels of the player.

/xp 0 @p
/xp 0l @p

Conclusion

CommandStats are very powerful tools so it’s only natural that they’d be this complicated. Be sure to ask for clarification or help where needed.

[author] [author_image timthumb=’on’]https://pbs.twimg.com/profile_images/2362398582/rbdeu2dh48me1vijiqe0.png[/author_image] [author_info]Skylinerw is a moderator for Minecraft Forums and a command fanatic. Follow him on Twitter![/author_info] [/author]

7 comments
  1. Having a major problem using this command. It simply doesn’t work for me. I have an armor stand with the tag “spawn” and I want it to test for an item nearby. I added an objective named “item”.

    I used this command for the Armor Stand
    /stats entity @e[tag=spawn] set SuccessCount @e[tag=spawn,r=0] item

    This should set the item score of itself to the success count of the command it runs. Next I used:
    /execute tag[tag=spawn] ~ ~ ~ testfor [type=Item,r=0]

    The chat confirms that the Armor Stand finds the item, but the score stays at 0.

      1. Yes I already had this, but thanks for the reply. Still not working. I will also mention I’m using 16w03a, are there any known /stats bugs in that version?

        1. None that I know of.

          Although I see the issue now: the second selector in /stats must resolve to a single entity, without consideration of any targets to begin with. @e will target multiple entities alone, so even if there was only 1 final target, it will still fail.

          The fix is to use the “count” parameter instead of radius, which also ensures that the armor stand itself is the one receiving the score due to sender bias. There will be no need for any other parameters apart from “type” and “c”; “type” is only necessary because CommandStats have a player bias, so it needs to make sure to target the armor stand and not a player.

          /stats entity @e[type=ArmorStand,tag=spawn] set SuccessCount @e[type=ArmorStand,c=1] item

          1. Thanks, I will try this. And again, thanks so much 🙂 Me and friends are relying on this working to make our map a lot easier to create.

      2. I tried with a different command stat, AffectedBlocks with /fill, and it worked. I switched back to “SuccessCount” and testfor @e[type=Item], and it again, found the item but did not affect the score. There’s something wrong with it detecting items, it must not output any count for it 🙁

Comments are closed.