diff --git a/src/pocketmine/level/Level.php b/src/pocketmine/level/Level.php index 10a42c544..da6ef5cab 100644 --- a/src/pocketmine/level/Level.php +++ b/src/pocketmine/level/Level.php @@ -49,6 +49,8 @@ use pocketmine\level\format\ChunkException; use pocketmine\level\format\EmptySubChunk; use pocketmine\level\format\io\BaseLevelProvider; use pocketmine\level\format\io\ChunkRequestTask; +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; @@ -2750,10 +2752,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){ diff --git a/src/pocketmine/level/format/io/BaseLevelProvider.php b/src/pocketmine/level/format/io/BaseLevelProvider.php index 574c519a6..2ff6fd659 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; use pocketmine\math\Vector3; use pocketmine\nbt\BigEndianNBTStream; @@ -152,6 +154,14 @@ abstract class BaseLevelProvider implements LevelProvider{ file_put_contents($this->getPath() . "level.dat", $buffer); } + /** + * @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); } @@ -163,6 +173,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 e00d1c5e9..31a71bbe1 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; use pocketmine\math\Vector3; interface LevelProvider{ @@ -100,8 +102,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/Anvil.php b/src/pocketmine/level/format/io/region/Anvil.php index 9cd69599f..12b1cc965 100644 --- a/src/pocketmine/level/format/io/region/Anvil.php +++ b/src/pocketmine/level/format/io/region/Anvil.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 @@ class Anvil extends McRegion{ $nbt = new BigEndianNBTStream(); $chunk = $nbt->readCompressed($data); if(!($chunk instanceof CompoundTag) or !$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 c080b79a4..6b2920c95 100644 --- a/src/pocketmine/level/format/io/region/McRegion.php +++ b/src/pocketmine/level/format/io/region/McRegion.php @@ -24,9 +24,9 @@ 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\BaseLevelProvider; use pocketmine\level\format\io\ChunkUtils; +use pocketmine\level\format\io\exception\CorruptedChunkException; use pocketmine\level\format\SubChunk; use pocketmine\level\generator\GeneratorManager; use pocketmine\level\Level; @@ -107,12 +107,13 @@ class McRegion extends BaseLevelProvider{ * @param string $data * * @return Chunk + * @throws CorruptedChunkException */ protected function nbtDeserialize(string $data) : Chunk{ $nbt = new BigEndianNBTStream(); $chunk = $nbt->readCompressed($data); if(!($chunk instanceof CompoundTag) or !$chunk->hasTag("Level")){ - throw new ChunkException("Invalid NBT format"); + throw new CorruptedChunkException("'Level' key is missing from chunk NBT"); } $chunk = $chunk->getCompoundTag("Level"); @@ -348,6 +349,14 @@ class McRegion extends BaseLevelProvider{ } } + /** + * @param int $chunkX + * @param int $chunkZ + * + * @return Chunk|null + * + * @throws CorruptedChunkException + */ protected function readChunk(int $chunkX, int $chunkZ) : ?Chunk{ $regionX = $regionZ = null; self::getRegionIndex($chunkX, $chunkZ, $regionX, $regionZ);