Minecraft – How to calculate the distance to the closest player

minecraft-commandsminecraft-java-edition

How do I calculate distance to the closest player and show it via a scoreboard on a vanilla server?

Best Answer

Just in case anyone tried to look up how this problem could be accomplished, because this is the first result from google search. And I happened to work it out.

You can do this in 1.13+ now, with the /execute store command

The steps are as follows: store player coordinates > calculate the differences > square the differences > sum up > calculate the sqrt values. I'm using euclidean distance as the metric.

1. Store Player Coordinates:
You'd need to define objectives to store the values, I defined them as "X", "Y", and "Z"

execute as @a run execute store result score @s X run data get entity @s Pos[0]
execute as @a run execute store result score @s Y run data get entity @s Pos[1]
execute as @a run execute store result score @s Z run data get entity @s Pos[2]


2. Calculate the Differences:
I defined another set of objectives to store the results "X_difference", "Y_difference", "Z_difference", but you don't have to.

execute as @a run scoreboard players operation @s X_difference = @s X
execute at @a run scoreboard players operation @s X_difference -= @p[sort=nearest] X
execute as @a run scoreboard players operation @s Y_difference = @s Y
execute at @a run scoreboard players operation @s Y_difference -= @p[sort=nearest] Y
execute as @a run scoreboard players operation @s Z_difference = @s Z
execute at @a run scoreboard players operation @s Z_difference -= @p[sort=nearest] Z
  1. Square the Differences:
execute as @a run scoreboard players operation @s X_difference *= @s X_difference
execute as @a run scoreboard players operation @s Y_difference *= @s Y_difference
execute as @a run scoreboard players operation @s Z_difference *= @s Z_difference
  1. Sum Up:
    I defined another objective "distance" to store the sum of the squared values from 3.
execute as @a run scoreboard players operation @s distance = @s X_difference
execute as @a run scoreboard players operation @s distance += @s Y_difference
execute as @a run scoreboard players operation @s distance += @s Z_difference
  1. Approximate the Square Root Values:
    We can use a simple algorithm to calculate the square root values. You can find more info on how it works here. We need to create three new objectives: sqrtI, sqrtX and realDistance. I highly recommend using a datapack to implement this, as we need to recursively get closer to the real square.

Once you have your distance value, run the following to reset the sqrt algorithm:

# ... every tick, after calculating distance, do:
scoreboard players set @a sqrtI 1
scoreboard players set @a sqrtX 0
scoreboard players set @a realDistance 0
# then we start the algorithm by running another function:
execute as @a if score @s distance > @s sqrtX run function mydatapack:sqrt

mydatapack:sqrt.mcfunction contains the following commands:

scoreboard players operation @s sqrtX += @s sqrtI
scoreboard players add @s realDistance 1
scoreboard players add @s sqrtI 2
execute as @s if score @s distance > @s sqrtX run function mydatapack:sqrt

The realDistance objective then contains the real distance that every single player is away from you in blocks.