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?
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 $v, Level $lvl){ $areas = []; foreach($this->getAllAreasData() as $name){ $data = $this->getAreaData($name, true); 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->x and max($min->x, $max->x) >= $v->x and min($min->y,$max->y) <= $v->y and max($min->y,$max->x) >= $v->y and min($min->z,$max->z) <= $v->z and max($min->z,$max->z) >= $v->z ); if($isVecInside and $data->world === $lvl->getName()){ $areas[] = $name; }else{ $areas[] = null; } } return $areas; }
That will take longer time to execute than my AxisAlignBB code. Try for-looping it 100 times and check the performance
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->x and max($min->x, $max->x) >= $v->x and min($min->y,$max->y) <= $v->y and max($min->y,$max->x) >= $v->y and min($min->z,$max->z) <= $v->z and max($min->z,$max->z) >= $v->z );
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.
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.
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".
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
*cough* overloaded because of player count what? thats useless. will just add more strain to the server.
Maybe this will help: PHP: if($player->distanceSquared($this->getServer()->getDefaultLevel()->getSafeSpawn()) < 25){ // 5*5 = 25/* here goes your preventing code */}
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(); }}
iProtector does the traditional way. I'd prefer something unique. It would help if my spawn wasn't cuboidal.
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.
You could be slightly wrong with that.. 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.}
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.