1. The forums will be archived and moved to a read only mode in about 2 weeks (mid march).

Best way to get a player in a defined region.

Discussion in 'Development' started by Muqsit, Dec 21, 2016.

  1. Muqsit

    Muqsit Chicken

    Messages:
    1,548
    GitHub:
    muqsit
    Hey everyone,
    I am trying (tried, and succeeded) to get players in a specific region (a cuboidal region).
    This was what I initially did.
    PHP:
    public function isAtSpawn($p) {
        
    $xx1 $this->coordinates['spawn']['x1'];
        
    $xx2 $this->coordinates['spawn']['x2'];
        
    $yy1 $this->coordinates['spawn']['y1'];
        
    $yy2 $this->coordinates['spawn']['y2'];
        
    $zz1 $this->coordinates['spawn']['z1'];
        
    $zz2 $this->coordinates['spawn']['z2'];
        if (
    $p->getX() >= $xx1 && $p->getX() <= $xx2 && $p->getY() >= $yy1 && $p->getY() <= $yy2 && $p->getZ() >= $zz1 && $p->getZ() <= $zz2) {
            return 
    true;
        } else {
            return 
    false;
        }
    }
    This code used to be executed every 20 ticks, and that caused a lot of strain on the server's performance. I found that code over here.
    Later, after going through the source, I found a better way (currently using this one).

    PHP:
    //onEnable()
    $spawnx = array($xx1$xx2); $spawny = array($yy1$yy2); $spawnz = array($zz1$zz2);//$xx1, $xx2, $yy1, $yy2, $zz1, $zz2 are coordinates.
    self::$spawnaxis = new AxisAlignedBB(min($spawnx), min($spawny), min($spawnz), max($spawnx), max($spawny), max($spawnz));

    public static function 
    isAtSpawn($p) : bool {
        return 
    self::$spawnaxis->isVectorInside($p);
    }
    To check whether the player is at spawn, I run that code every 20 ticks. I just want to know, what according to you would be the best way to do this?
     
    Last edited: Jul 13, 2017
  2. xBeastMode

    xBeastMode Shog Chips

    Messages:
    0
    Well, this code might help. You can tell that $v represents the player coordinates.

    PHP:
    /**
         * @param Vector3 $v
         * @param Level $lvl
         * @return array
         */
        
    public function getAreasByVector(Vector3 $vLevel $lvl){
            
    $areas = [];
            foreach(
    $this->getAllAreasData() as $name){
                
    $data $this->getAreaData($nametrue);
                if(
    $data === null) continue;
                
    $min = new Vector3($data->min[0], $data->min[1], $data->min[2]);
                
    $max = new Vector3($data->max[0], $data->max[1], $data->max[2]);
                
    $isVecInside =
                    (
    min($min->x,$max->x) <= $v->and max($min->x$max->x) >= $v->x
                        
    and min($min->y,$max->y) <= $v->and max($min->y,$max->x) >= $v->and
                        
    min($min->z,$max->z) <= $v->and max($min->z,$max->z) >= $v->z
                    
    );
                if(
    $isVecInside and $data->world === $lvl->getName()){
                    
    $areas[] = $name;
                }else{
                    
    $areas[] = null;
                }
            }
            return 
    $areas;
        }
     
  3. Muqsit

    Muqsit Chicken

    Messages:
    1,548
    GitHub:
    muqsit
    That will take longer time to execute than my AxisAlignBB code. Try for-looping it 100 times and check the performance :p
     
  4. xBeastMode

    xBeastMode Shog Chips

    Messages:
    0
    No, it's actually pretty fast. The code is from a plugin that I made before and it's pretty fast. Try this and see:
    PHP:
    $v = &$player;
    $isVecInside =
                    (
    min($min->x,$max->x) <= $v->and max($min->x$max->x) >= $v->x
                        
    and min($min->y,$max->y) <= $v->and max($min->y,$max->x) >= $v->and
                        
    min($min->z,$max->z) <= $v->and max($min->z,$max->z) >= $v->z
                    
    );
     
  5. Muqsit

    Muqsit Chicken

    Messages:
    1,548
    GitHub:
    muqsit
    It might be, but my is more reliable, well at least for me. I am executing my code every second. I've used the min, max way with 'and' previously, and wasn't suitable for what I was trying to do. TPS would be below 16.
    Your code is neat, i'm sure you're not executing it every second, so you won't face any overloading problems.
     
  6. xBeastMode

    xBeastMode Shog Chips

    Messages:
    0
    Well, why are you trying to get player in a cuboidal region? That might help us know what algorithm is best for what you are trying to do.
     
  7. Muqsit

    Muqsit Chicken

    Messages:
    1,548
    GitHub:
    muqsit
    If $object is at spawn:
    - Player cannot break blocks.
    - Player cannot place blocks.
    - If $object explodes, it won't destroy the blocks that are at spawn.
    - Players can open a rewarding chest.
    - Players can fly at spawn (radius <= 8 and y > 90 only).
    The task is currently responsible for 0.98% of the "lag".
     
  8. Junkdude

    Junkdude Zombie

    Messages:
    346
    GitHub:
    JunkDaCoder
    cough CosmicPE cough
     
  9. Junkdude

    Junkdude Zombie

    Messages:
    346
    GitHub:
    JunkDaCoder
    Could you try saving the area to a config then check to see if the player is inside of the area. https://github.com/LDX-MCPE/iProtector/blob/master/src/LDX/iProtector/Main.php may help
     
  10. Muqsit

    Muqsit Chicken

    Messages:
    1,548
    GitHub:
    muqsit
  11. Junkdude

    Junkdude Zombie

    Messages:
    346
    GitHub:
    JunkDaCoder
    Meant to take example of how iprotector does it
     
  12. imYannic

    imYannic Baby Zombie

    Messages:
    113
    Maybe this will help:
    PHP:
    if($player->distanceSquared($this->getServer()->getDefaultLevel()->getSafeSpawn()) < 25){ // 5*5 = 25

    /* here goes your preventing code */

    }

     
    [deleted] likes this.
  13. Jack Noordhuis

    Jack Noordhuis Zombie Pigman Poggit Reviewer

    Messages:
    618
    GitHub:
    JackNoordhuis
    You could check if a player is within spawn when they perform a certain action (on certain events) and you update a cache that you store the result in for a second.

    PHP:
    private $spawnCache = [];

    public function 
    onEnable() {
        
    $spawnx = array($xx1$xx2);
        
    $spawny = array($yy1$yy2);
        
    $spawnz = array($zz1$zz2);
    //$xx1, $xx2, $yy1, $yy2, $zz1, $zz2 are coordinates.
        
    self::$spawnaxis = new AxisAlignedBB(min($spawnx), min($spawny), min($spawnz), max($spawnx), max($spawny), max($spawnz));
    }

    public static function 
    isAtSpawn($p) : bool {
        if(isset(
    $this->spawnCache[$p->getName()]) {
            if(
    floor(microtime(true) - $this->spawnCache[$p->getName]) < 1) {
                return 
    $this->spawnCache[$p->getName();
            }
            unset(
    $this->spawnCache[$p->getName()]);
        }
        
    $result self::$spawnaxis->isVectorInside($p);
        if(
    $result) {
            
    $this->spawnCache[$p->getName()] = microtime(true);
        }
        return 
    $result;
    }

    public function 
    onBlockPlace(BlockPlaceEvent $event) {
        if(
    self::isAtSpawn($event->getPlayer()) {
            
    $event->setCancelled();
        }
    }
     
    Muqsit likes this.
  14. Muqsit

    Muqsit Chicken

    Messages:
    1,548
    GitHub:
    muqsit
    iProtector does the traditional way. I'd prefer something unique.

    It would help if my spawn wasn't cuboidal.
     
  15. SOFe

    SOFe Administrator Staff Member PMMP Team Poggit Admin

    Messages:
    1,968
    GitHub:
    sof3
    Using three direct min<=component<=max conditions (six conditions altogether) is theoretically the fastest way to check whether a vector is in a region bounded by a cuboid. Using AxisAlignedBB can only help prevent writing long code. It has negligible (and actually negative) effect on performance.
     
    eDroid, SalmonDE and Muqsit like this.
  16. Muqsit

    Muqsit Chicken

    Messages:
    1,548
    GitHub:
    muqsit
    You could be slightly wrong with that.. :shoghi:
    How about
    PHP:
    //$minX, $minY, $minZ, $maxX, $maxY, $maxZ, $player
    $x array_flip(range($minX$maxX));
    $y array_flip(range($minY$maxY));
    $z array_flip(range($minZ$maxZ));
    //Define $x, $y and $z on plugin enable as global variables.
    If (isset($x[$player->x], $y[$player->y], $z[$player->z])) {
        
    //$player is within the area.
    }
     
    Last edited: Dec 25, 2016
  17. xBeastMode

    xBeastMode Shog Chips

    Messages:
    0
    That only checks if the player x, y, or z are an index of the arrays x, y, or z which would only work if player is at 0 or 1 coordinates.
     
  18. Muqsit

    Muqsit Chicken

    Messages:
    1,548
    GitHub:
    muqsit
    True, updated now.
     
  19. SalmonDE

    SalmonDE Zombie Pigman

    Messages:
    739
    GitHub:
    SalmonDE
    I'm pretty sure you can combine every isset() into one isset().
     
    Muqsit likes this.
  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.