diff --git a/src/pocketmine/entity/Entity.php b/src/pocketmine/entity/Entity.php index 5961ece9e..7364654d7 100644 --- a/src/pocketmine/entity/Entity.php +++ b/src/pocketmine/entity/Entity.php @@ -508,7 +508,7 @@ abstract class Entity extends Location implements Metadatable, EntityIds{ $this->boundingBox = new AxisAlignedBB(0, 0, 0, 0, 0, 0); $this->recalculateBoundingBox(); - $this->chunk = $this->level->getChunk($this->getFloorX() >> 4, $this->getFloorZ() >> 4, false); + $this->chunk = $this->level->getChunkAtPosition($this, false); if($this->chunk === null){ throw new \InvalidStateException("Cannot create entities in unloaded chunks"); } @@ -1772,7 +1772,7 @@ abstract class Entity extends Location implements Metadatable, EntityIds{ $this->chunk = $this->level->getChunk($chunkX, $chunkZ, true); if(!$this->justCreated){ - $newChunk = $this->level->getChunkPlayers($chunkX, $chunkZ); + $newChunk = $this->level->getViewersForPosition($this); foreach($this->hasSpawned as $player){ if(!isset($newChunk[$player->getLoaderId()])){ $this->despawnFrom($player); @@ -1919,7 +1919,7 @@ abstract class Entity extends Location implements Metadatable, EntityIds{ * @param Player $player */ public function spawnTo(Player $player) : void{ - if(!isset($this->hasSpawned[$player->getLoaderId()]) and $this->chunk !== null and isset($player->usedChunks[Level::chunkHash($this->chunk->getX(), $this->chunk->getZ())])){ + if(!isset($this->hasSpawned[$player->getLoaderId()])){ $this->hasSpawned[$player->getLoaderId()] = $player; $this->sendSpawnPacket($player); @@ -1930,7 +1930,7 @@ abstract class Entity extends Location implements Metadatable, EntityIds{ if($this->chunk === null or $this->closed){ return; } - foreach($this->level->getChunkPlayers($this->chunk->getX(), $this->chunk->getZ()) as $player){ + foreach($this->level->getViewersForPosition($this) as $player){ if($player->isOnline()){ $this->spawnTo($player); } diff --git a/src/pocketmine/level/Level.php b/src/pocketmine/level/Level.php index 5ae154e17..14a777381 100644 --- a/src/pocketmine/level/Level.php +++ b/src/pocketmine/level/Level.php @@ -596,6 +596,16 @@ class Level implements ChunkManager, Metadatable{ return $this->chunkLoaders[Level::chunkHash($chunkX, $chunkZ)] ?? []; } + /** + * Returns an array of players who have the target position within their view distance. + * @param Vector3 $pos + * + * @return Player[] + */ + public function getViewersForPosition(Vector3 $pos) : array{ + return $this->getChunkPlayers($pos->getFloorX() >> 4, $pos->getFloorZ() >> 4); + } + /** * Queues a DataPacket to be sent to all players using the chunk at the specified X/Z coordinates at the end of the * current tick. @@ -1505,7 +1515,7 @@ class Level implements ChunkManager, Metadatable{ $this->timings->setBlock->startTiming(); - if($this->getChunk($pos->x >> 4, $pos->z >> 4, true)->setBlock($pos->x & 0x0f, $pos->y, $pos->z & 0x0f, $block->getId(), $block->getDamage())){ + if($this->getChunkAtPosition($pos, true)->setBlock($pos->x & 0x0f, $pos->y, $pos->z & 0x0f, $block->getId(), $block->getDamage())){ if(!($pos instanceof Position)){ $pos = $this->temporalPosition->setComponents($pos->x, $pos->y, $pos->z); } @@ -2268,6 +2278,18 @@ class Level implements ChunkManager, Metadatable{ return null; } + /** + * Returns the chunk containing the given Vector3 position. + * + * @param Vector3 $pos + * @param bool $create + * + * @return null|Chunk + */ + public function getChunkAtPosition(Vector3 $pos, bool $create = false) : ?Chunk{ + return $this->getChunk($pos->getFloorX() >> 4, $pos->getFloorZ() >> 4, $create); + } + /** * Returns the chunks adjacent to the specified chunk. * @@ -2787,7 +2809,7 @@ class Level implements ChunkManager, Metadatable{ $max = $this->worldHeight; $v = $spawn->floor(); - $chunk = $this->getChunk($v->x >> 4, $v->z >> 4, false); + $chunk = $this->getChunkAtPosition($v, false); $x = (int) $v->x; $z = (int) $v->z; if($chunk !== null and $chunk->isGenerated()){