2

I would like to test for players 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 players 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.

  • FYI they're called just "tags", not "scoreboard tags" (although I understood what you meant) – pppery Jun 21 at 16:45
  • No, tags using the /tag command are called scoreboard tags. See the very first line of this Minecraft Wiki article. – ExpertCoder14 Jun 21 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", … – Fabian Röling Sep 6 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. – Fabian Röling Sep 6 at 16:20
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.

| improve this answer | |
  • Nice job simplifying the previous answer! This will be much better when using scoreboard tags. – ExpertCoder14 Sep 6 at 18:31
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
...
| improve this answer | |
  • (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. – ExpertCoder14 Jun 27 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. – Fabian Röling Sep 6 at 16:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.