surva network logo

surva network: development blog

Articles and news about Minecraft: Bedrock Edition / PocketMine server development

How to check if a player's position is next to a point or inside an area

Position checks and calculation with vectors can sometimes a bit complicated, so we've created an article describing the most common checks and how to solve them. There are different types of checks, e.g. if you want to check if a player is in an area created by two positions or next to a specific position.

Check if player is next to a position

That's an easy check because PocketMine already has a method to accomplish this.

First, we need the vector coordinates (x, y, z) of a position, this could be treasure chest a player must find, for example.

You would usually store those values in a config file:

treasure:
    pos:
        x: 15
        y: 81
        z: 63

Let's let those values:

$pos = new Vector3(
    $this->getConfig()->getNested("treasure.pos.x"),
    $this->getConfig()->getNested("treasure.pos.y"),
    $this->getConfig()->getNested("treasure.pos.z")
);

To check if a player is next to this position, use the distance() method of the player's position object:

if ($player->getPosition()->distance($pos) <= 5) {
    // player is next to position, not more than 5 blocks away, do something
}

When it comes to choose an event for checking, please keep in mind that checking at each PlayerMoveEvent would be bad for the performance. Instead, you could use a command the player should execute or PlayerInteractEvent to let the player interact with a button, for example.

Check if player is inside an area

This is a bit more complex, but also possible. To define an area, you need two vector coordinates which span up a square (imagine like a square in WorldEdit with position 1 and 2).

This could be the config file then:

area:
  pos1:
    x: 10
    y: 50
    z: 10
  pos2:
    x: 50
    y: 70
    z: 50

We need to create two variables to store the minimum and maximum coordinate values:

private Vector3 $minPos;
private Vector3 $maxPos;

This function is responsible for loading the coordinate values from the config file and find the minimum and maximum values:

/**
 * Read the area config into variables
 *
 * @return void
 */
private function readAreaConfig(): void
{
    $pos1 = new Vector3(
        $this->getConfig()->getNested("area.pos1.x"),
        $this->getConfig()->getNested("area.pos1.y"),
        $this->getConfig()->getNested("area.pos1.z")
    );
    $pos2 = new Vector3(
        $this->getConfig()->getNested("area.pos2.x"),
        $this->getConfig()->getNested("area.pos2.y"),
        $this->getConfig()->getNested("area.pos2.z")
    );

    $this->minPos = Vector3::minComponents($pos1, $pos2);
    $this->maxPos = Vector3::maxComponents($pos1, $pos2);
}

We'll use minPos and maxPos in the next step to check if the player's position is between those two (in the defined area).

/**
 * Check if a position is in the area
 *
 * @param  \pocketmine\math\Vector3  $pos
 *
 * @return bool
 */
public function isInArea(Vector3 $pos): bool
{
    return ($this->minPos->x <= $pos->x && $pos->x <= $this->maxPos->x)
            && ($this->minPos->y <= $pos->y
                && $pos->y <= $this->maxPos->y)
            && ($this->minPos->z <= $pos->z && $pos->z <= $this->maxPos->z);
}

This method checks for each vector coordinate (x, y, z) if it's between our minimum and maximum coordinate value.

Example on how to use the method above:

if ($this->isInArea($player->getPosition())) {
    $player->sendMessage("You're inside the area!");
}

What does this code do

We have this config as an example:

area:
  pos1:
    x: 10
    y: 20
    z: 30
  pos2:
    x: 5
    y: 40
    z: 5

Our code will create the minimum and maximum vector out of those two, so we can compare it easier later. It checks every vector coordinate (x, y and z) and chooses the minimum or maximum out of the two positions defined in the config file.

The minimum vector is (5, 20, 5) and the maximum one is (10, 40, 30).

Now we can easily compare if the player is in the area for each coordinate. If the x value is between 5 and 10, the y value between 20 and 40 and the z value between 5 and 30, the player is inside the defined area.