diff --git a/src/pocketmine/level/Level.php b/src/pocketmine/level/Level.php index b627f88ef..9eb5b96c7 100644 --- a/src/pocketmine/level/Level.php +++ b/src/pocketmine/level/Level.php @@ -48,6 +48,8 @@ use pocketmine\level\biome\Biome; use pocketmine\level\format\Chunk; use pocketmine\level\format\ChunkException; use pocketmine\level\format\EmptySubChunk; +use pocketmine\level\format\io\exception\CorruptedChunkException; +use pocketmine\level\format\io\exception\UnsupportedChunkFormatException; use pocketmine\level\format\io\LevelProvider; use pocketmine\level\generator\Generator; use pocketmine\level\generator\GeneratorManager; @@ -2652,10 +2654,9 @@ class Level implements ChunkManager, Metadatable{ try{ $chunk = $this->provider->loadChunk($x, $z); - }catch(\Exception $e){ + }catch(CorruptedChunkException | UnsupportedChunkFormatException $e){ $logger = $this->server->getLogger(); - $logger->critical("An error occurred while loading chunk x=$x z=$z: " . $e->getMessage()); - $logger->logException($e); + $logger->critical("Failed to load chunk x=$x z=$z: " . $e->getMessage()); } if($chunk === null and $create){ @@ -2736,23 +2737,17 @@ class Level implements ChunkManager, Metadatable{ return false; } - try{ - if($trySave and $this->getAutoSave() and $chunk->isGenerated()){ - if($chunk->hasChanged() or count($chunk->getTiles()) > 0 or count($chunk->getSavableEntities()) > 0){ - $this->provider->saveChunk($chunk); - } + if($trySave and $this->getAutoSave() and $chunk->isGenerated()){ + if($chunk->hasChanged() or count($chunk->getTiles()) > 0 or count($chunk->getSavableEntities()) > 0){ + $this->provider->saveChunk($chunk); } - - foreach($this->getChunkLoaders($x, $z) as $loader){ - $loader->onChunkUnloaded($chunk); - } - - $chunk->onUnload(); - }catch(\Throwable $e){ - $logger = $this->server->getLogger(); - $logger->error($this->server->getLanguage()->translateString("pocketmine.level.chunkUnloadError", [$e->getMessage()])); - $logger->logException($e); } + + foreach($this->getChunkLoaders($x, $z) as $loader){ + $loader->onChunkUnloaded($chunk); + } + + $chunk->onUnload(); } unset($this->chunks[$chunkHash]); diff --git a/src/pocketmine/level/format/io/BaseLevelProvider.php b/src/pocketmine/level/format/io/BaseLevelProvider.php index e74038d25..b59003264 100644 --- a/src/pocketmine/level/format/io/BaseLevelProvider.php +++ b/src/pocketmine/level/format/io/BaseLevelProvider.php @@ -24,6 +24,8 @@ declare(strict_types=1); namespace pocketmine\level\format\io; use pocketmine\level\format\Chunk; +use pocketmine\level\format\io\exception\CorruptedChunkException; +use pocketmine\level\format\io\exception\UnsupportedChunkFormatException; use pocketmine\level\LevelException; abstract class BaseLevelProvider implements LevelProvider{ @@ -54,6 +56,14 @@ abstract class BaseLevelProvider implements LevelProvider{ return $this->levelData; } + /** + * @param int $chunkX + * @param int $chunkZ + * + * @return Chunk|null + * @throws CorruptedChunkException + * @throws UnsupportedChunkFormatException + */ public function loadChunk(int $chunkX, int $chunkZ) : ?Chunk{ return $this->readChunk($chunkX, $chunkZ); } @@ -65,6 +75,14 @@ abstract class BaseLevelProvider implements LevelProvider{ $this->writeChunk($chunk); } + /** + * @param int $chunkX + * @param int $chunkZ + * + * @return Chunk|null + * @throws UnsupportedChunkFormatException + * @throws CorruptedChunkException + */ abstract protected function readChunk(int $chunkX, int $chunkZ) : ?Chunk; abstract protected function writeChunk(Chunk $chunk) : void; diff --git a/src/pocketmine/level/format/io/LevelProvider.php b/src/pocketmine/level/format/io/LevelProvider.php index cb5838b01..975ea7143 100644 --- a/src/pocketmine/level/format/io/LevelProvider.php +++ b/src/pocketmine/level/format/io/LevelProvider.php @@ -24,6 +24,8 @@ declare(strict_types=1); namespace pocketmine\level\format\io; use pocketmine\level\format\Chunk; +use pocketmine\level\format\io\exception\CorruptedChunkException; +use pocketmine\level\format\io\exception\UnsupportedChunkFormatException; interface LevelProvider{ @@ -80,8 +82,8 @@ interface LevelProvider{ * * @return null|Chunk * - * @throws \Exception any of a range of exceptions that could be thrown while reading chunks. See individual - * implementations for details. + * @throws CorruptedChunkException + * @throws UnsupportedChunkFormatException */ public function loadChunk(int $chunkX, int $chunkZ) : ?Chunk; diff --git a/src/pocketmine/level/format/io/region/LegacyAnvilChunkTrait.php b/src/pocketmine/level/format/io/region/LegacyAnvilChunkTrait.php index eca17c88c..759da6d9b 100644 --- a/src/pocketmine/level/format/io/region/LegacyAnvilChunkTrait.php +++ b/src/pocketmine/level/format/io/region/LegacyAnvilChunkTrait.php @@ -24,8 +24,8 @@ declare(strict_types=1); namespace pocketmine\level\format\io\region; use pocketmine\level\format\Chunk; -use pocketmine\level\format\ChunkException; use pocketmine\level\format\io\ChunkUtils; +use pocketmine\level\format\io\exception\CorruptedChunkException; use pocketmine\level\format\SubChunk; use pocketmine\nbt\BigEndianNBTStream; use pocketmine\nbt\NBT; @@ -99,7 +99,7 @@ trait LegacyAnvilChunkTrait{ $nbt = new BigEndianNBTStream(); $chunk = $nbt->readCompressed($data); if(!$chunk->hasTag("Level")){ - throw new ChunkException("Invalid NBT format"); + throw new CorruptedChunkException("'Level' key is missing from chunk NBT"); } $chunk = $chunk->getCompoundTag("Level"); diff --git a/src/pocketmine/level/format/io/region/McRegion.php b/src/pocketmine/level/format/io/region/McRegion.php index abae6c7f2..4a56dd809 100644 --- a/src/pocketmine/level/format/io/region/McRegion.php +++ b/src/pocketmine/level/format/io/region/McRegion.php @@ -24,8 +24,8 @@ declare(strict_types=1); namespace pocketmine\level\format\io\region; use pocketmine\level\format\Chunk; -use pocketmine\level\format\ChunkException; use pocketmine\level\format\io\ChunkUtils; +use pocketmine\level\format\io\exception\CorruptedChunkException; use pocketmine\level\format\SubChunk; use pocketmine\nbt\BigEndianNBTStream; use pocketmine\nbt\NBT; @@ -98,12 +98,13 @@ class McRegion extends RegionLevelProvider{ * @param string $data * * @return Chunk + * @throws CorruptedChunkException */ protected function deserializeChunk(string $data) : Chunk{ $nbt = new BigEndianNBTStream(); $chunk = $nbt->readCompressed($data); if(!$chunk->hasTag("Level")){ - throw new ChunkException("Invalid NBT format"); + throw new CorruptedChunkException("'Level' key is missing from chunk NBT"); } $chunk = $chunk->getCompoundTag("Level"); diff --git a/src/pocketmine/level/format/io/region/RegionLevelProvider.php b/src/pocketmine/level/format/io/region/RegionLevelProvider.php index 8e58ce2f5..8447a13d5 100644 --- a/src/pocketmine/level/format/io/region/RegionLevelProvider.php +++ b/src/pocketmine/level/format/io/region/RegionLevelProvider.php @@ -26,6 +26,7 @@ namespace pocketmine\level\format\io\region; use pocketmine\level\format\Chunk; use pocketmine\level\format\io\BaseLevelProvider; use pocketmine\level\format\io\data\JavaLevelData; +use pocketmine\level\format\io\exception\CorruptedChunkException; use pocketmine\level\format\io\LevelData; use pocketmine\level\Level; @@ -156,6 +157,12 @@ abstract class RegionLevelProvider extends BaseLevelProvider{ abstract protected function serializeChunk(Chunk $chunk) : string; + /** + * @param string $data + * + * @return Chunk + * @throws CorruptedChunkException + */ abstract protected function deserializeChunk(string $data) : Chunk; protected function readChunk(int $chunkX, int $chunkZ) : ?Chunk{