diff --git a/src/pocketmine/level/Level.php b/src/pocketmine/level/Level.php index b727da95b..46c3efb5d 100644 --- a/src/pocketmine/level/Level.php +++ b/src/pocketmine/level/Level.php @@ -127,7 +127,7 @@ class Level implements ChunkManager, Metadatable{ public $updateEntities = []; /** @var Tile[] */ public $updateTiles = []; - /** @var Block[] */ + /** @var Block[][] */ private $blockCache = []; /** @var BatchPacket[] */ @@ -1450,15 +1450,17 @@ class Level implements ChunkManager, Metadatable{ */ public function getBlockAt(int $x, int $y, int $z, bool $cached = true, bool $addToCache = true) : Block{ $fullState = 0; - $index = null; + $blockHash = null; + $chunkHash = Level::chunkHash($x >> 4, $z >> 4); if($this->isInWorld($x, $y, $z)){ - $index = Level::blockHash($x, $y, $z); - if($cached and isset($this->blockCache[$index])){ - return $this->blockCache[$index]; + $blockHash = Level::blockHash($x, $y, $z); + + if($cached and isset($this->blockCache[$chunkHash][$blockHash])){ + return $this->blockCache[$chunkHash][$blockHash]; } - $chunk = $this->chunks[$chunkIndex = Level::chunkHash($x >> 4, $z >> 4)] ?? null; + $chunk = $this->chunks[$chunkHash] ?? null; if($chunk !== null){ $fullState = $chunk->getFullBlock($x & 0x0f, $y, $z & 0x0f); }else{ @@ -1473,8 +1475,8 @@ class Level implements ChunkManager, Metadatable{ $block->z = $z; $block->level = $this; - if($addToCache and $index !== null){ - $this->blockCache[$index] = $block; + if($addToCache and $blockHash !== null){ + $this->blockCache[$chunkHash][$blockHash] = $block; } return $block; @@ -1612,19 +1614,21 @@ class Level implements ChunkManager, Metadatable{ $block->position($pos); $block->clearCaches(); - unset($this->blockCache[$blockHash = Level::blockHash($pos->x, $pos->y, $pos->z)]); - $index = Level::chunkHash($pos->x >> 4, $pos->z >> 4); + $chunkHash = Level::chunkHash($pos->x >> 4, $pos->z >> 4); + $blockHash = Level::blockHash($pos->x, $pos->y, $pos->z); + + unset($this->blockCache[$chunkHash][$blockHash]); if($direct === true){ $this->sendBlocks($this->getChunkPlayers($pos->x >> 4, $pos->z >> 4), [$block], UpdateBlockPacket::FLAG_ALL_PRIORITY); - unset($this->chunkCache[$index]); + unset($this->chunkCache[$chunkHash]); }else{ - if(!isset($this->changedBlocks[$index])){ - $this->changedBlocks[$index] = []; + if(!isset($this->changedBlocks[$chunkHash])){ + $this->changedBlocks[$chunkHash] = []; } - $this->changedBlocks[$index][$blockHash] = clone $block; + $this->changedBlocks[$chunkHash][$blockHash] = clone $block; } foreach($this->getChunkLoaders($pos->x >> 4, $pos->z >> 4) as $loader){ @@ -2146,13 +2150,13 @@ class Level implements ChunkManager, Metadatable{ * @param int $id 0-255 */ public function setBlockIdAt(int $x, int $y, int $z, int $id){ - unset($this->blockCache[$blockHash = Level::blockHash($x, $y, $z)]); + unset($this->blockCache[$chunkHash = Level::chunkHash($x >> 4, $z >> 4)][$blockHash = Level::blockHash($x, $y, $z)]); $this->getChunk($x >> 4, $z >> 4, true)->setBlockId($x & 0x0f, $y, $z & 0x0f, $id & 0xff); - if(!isset($this->changedBlocks[$index = Level::chunkHash($x >> 4, $z >> 4)])){ - $this->changedBlocks[$index] = []; + if(!isset($this->changedBlocks[$chunkHash])){ + $this->changedBlocks[$chunkHash] = []; } - $this->changedBlocks[$index][$blockHash] = $v = new Vector3($x, $y, $z); + $this->changedBlocks[$chunkHash][$blockHash] = $v = new Vector3($x, $y, $z); foreach($this->getChunkLoaders($x >> 4, $z >> 4) as $loader){ $loader->onBlockChanged($v); } @@ -2208,13 +2212,14 @@ class Level implements ChunkManager, Metadatable{ * @param int $data 0-15 */ public function setBlockDataAt(int $x, int $y, int $z, int $data){ - unset($this->blockCache[$blockHash = Level::blockHash($x, $y, $z)]); + unset($this->blockCache[$chunkHash = Level::chunkHash($x >> 4, $z >> 4)][$blockHash = Level::blockHash($x, $y, $z)]); + $this->getChunk($x >> 4, $z >> 4, true)->setBlockData($x & 0x0f, $y, $z & 0x0f, $data & 0x0f); - if(!isset($this->changedBlocks[$index = Level::chunkHash($x >> 4, $z >> 4)])){ - $this->changedBlocks[$index] = []; + if(!isset($this->changedBlocks[$chunkHash])){ + $this->changedBlocks[$chunkHash] = []; } - $this->changedBlocks[$index][$blockHash] = $v = new Vector3($x, $y, $z); + $this->changedBlocks[$chunkHash][$blockHash] = $v = new Vector3($x, $y, $z); foreach($this->getChunkLoaders($x >> 4, $z >> 4) as $loader){ $loader->onBlockChanged($v); } @@ -2396,7 +2401,7 @@ class Level implements ChunkManager, Metadatable{ if($chunk === null){ return; } - $index = Level::chunkHash($chunkX, $chunkZ); + $chunkHash = Level::chunkHash($chunkX, $chunkZ); $oldChunk = $this->getChunk($chunkX, $chunkZ, false); if($unload and $oldChunk !== null){ $this->unloadChunk($chunkX, $chunkZ, false, false); @@ -2418,9 +2423,10 @@ class Level implements ChunkManager, Metadatable{ } $this->provider->setChunk($chunkX, $chunkZ, $chunk); - $this->chunks[$index] = $chunk; + $this->chunks[$chunkHash] = $chunk; - unset($this->chunkCache[$index]); + unset($this->blockCache[$chunkHash]); + unset($this->chunkCache[$chunkHash]); $chunk->setChanged(); if(!$this->isChunkInUse($chunkX, $chunkZ)){ @@ -2662,7 +2668,7 @@ class Level implements ChunkManager, Metadatable{ * @throws \InvalidStateException */ public function loadChunk(int $x, int $z, bool $generate = true) : bool{ - if(isset($this->chunks[$index = Level::chunkHash($x, $z)])){ + if(isset($this->chunks[$chunkHash = Level::chunkHash($x, $z)])){ return true; } @@ -2678,7 +2684,9 @@ class Level implements ChunkManager, Metadatable{ return false; } - $this->chunks[$index] = $chunk; + $this->chunks[$chunkHash] = $chunk; + unset($this->blockCache[$chunkHash]); + $chunk->initChunk($this); $this->server->getPluginManager()->callEvent(new ChunkLoadEvent($this, $chunk, !$chunk->isGenerated())); @@ -2730,9 +2738,9 @@ class Level implements ChunkManager, Metadatable{ $this->timings->doChunkUnload->startTiming(); - $index = Level::chunkHash($x, $z); + $chunkHash = Level::chunkHash($x, $z); - $chunk = $this->chunks[$index] ?? null; + $chunk = $this->chunks[$chunkHash] ?? null; if($chunk !== null){ $this->server->getPluginManager()->callEvent($ev = new ChunkUnloadEvent($this, $chunk)); @@ -2762,9 +2770,10 @@ class Level implements ChunkManager, Metadatable{ $logger->logException($e); } - unset($this->chunks[$index]); - unset($this->chunkTickList[$index]); - unset($this->chunkCache[$index]); + unset($this->chunks[$chunkHash]); + unset($this->chunkTickList[$chunkHash]); + unset($this->chunkCache[$chunkHash]); + unset($this->blockCache[$chunkHash]); $this->timings->doChunkUnload->stopTiming();