2

I would like to test for entities in a certain area and number them.

A target selector always returns a list of selected entities in the order of the sort parameter.

For example, the following target selector will return a list of players within 100 blocks of the running command block, in random order:

@a[distance=..100,sort=random]

I would like to be able to number the entities returned by the target selector in two ways: through scoreboard objectives, and through scoreboard tags. For example, if the target selector returns players Alice, Joe, Bob, I would like for Alice to get scoreboard value 1, Joe to get 2, and Bob to get 3. If it returns players Joe, Alice, Bob, Joe would get 1, Alice would get 2, and Bob would get 3.

Using scoreboard tags, a tag named Player1 would be added to the first player, Player2 for the 2nd, and so on.

What is the best way to construct a functioning command mechanism for this purpose? Note, I would like an answer for all 3 non-arbitrary sorting methods, meaning nearest, furthest, and random.

Use [distance=..100] as your target selector template argument so that everyone's answer is consistent in what part is their target selector.

4
  • FYI they're called just "tags", not "scoreboard tags" (although I understood what you meant)
    – pppery
    Jun 21, 2020 at 16:45
  • No, tags using the /tag command are called scoreboard tags. See the very first line of this Minecraft Wiki article. Jun 21, 2020 at 16:47
  • I think the name is fine, even though it's not really correct anymore, because tags got separated from scoreboards fully in 1.13. But you need to name them somehow, to differentiate them from NBT tags, nametags, the "tag" tag of items, block/… tags, the /tag command, the "Tags" NBT tag, the German word for "day", … Sep 6, 2020 at 16:19
  • I think we don't actually have a proper "custom ID system" question yet. I always tell people to google it, but being able to point to a gamingSE question is much better. Sep 6, 2020 at 16:20

2 Answers 2

2

pppery's answer already has the best method for doing this with tags, it requires one command per tag. That's because tags are not made for this, they're made for binary states like "does this player have this property".

The missing piece to do it better with scoreboards is /scoreboard players operation, which allows you to copy a score from one place to another.

Let's start with pppery's idea of giving everyone a score of -1 initially, it works better than a tag:

scoreboard players set @a[distance=..100] id -1

And you need a fake player (or anything) to hold the current number:

scoreboard players set #current id 0

Now you repeat increasing that and copying it to another player who doesn't have an ID yet:

scoreboard players add #current id 1
scoreboard players operation @p[scores={id=-1}] id = #current id

If you don't rely on it being done all in one tick, you can simply loop the last two commands. If you have access to the world save, you can put them into a function that then calls itself if there are players left to handle, for example like this:

execute if entity @p[scores={id=-1}] run function fabian:assign_id

If you don't have access to the server data, there are some tricks you can do with command blocks to make them loop by changing their directions around, it's a bit complicated. You could also just put more chain command blocks down, containing the same two commands many times. But in that case, you can just hard-code the ID and only use one command block per ID.

2
  • Does this take into account the sort? Where would you add a custom sort? Dec 10, 2020 at 18:13
  • @p does the sorting, it's the same as @a[type=player,sort=nearest,limit=1]. Dec 10, 2020 at 22:42
1

I've found one way of doing this, which is unfortunately a bit verbose (requires one command block for each player who needs to be identified), but works:

Using scoreboard objectives:

/scoreboard players set @a[distance=..100] Id -1
/scoreboard players set @a[scores={Id=-1},sort=...,limit=1] Id 1
/scoreboard players set @a[scores={Id=-1},sort=...,limit=1] Id 2
/scoreboard players set @a[scores={Id=-1},sort=...,limit=1] Id 3
...

Using tags:

/tag @a[distance=..100,sort=...,limit=1,tag=!Player1,tag=!Player2,tag=!Player3,...] add Player1
/tag @a[distance=..100,sort=...,limit=1,tag=!Player1,tag=!Player2,tag=!Player3,...] add Player2
/tag @a[distance=..100,sort=...,limit=1,tag=!Player1,tag=!Player2,tag=!Player3,...] add Player3
...
2
  • (REPOST (accidentally deleted comment)) You can use functions instead of command blocks to conserve space in your world. It does require slightly more setup though. Jun 27, 2020 at 3:25
  • 1
    Nice idea with ID -1. It works the same as first tagging people, which would be my idea, but only requires one command instead of two every time. Sep 6, 2020 at 16:29

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .