From c10be0f346b5cfc5ea2f3a1e2762ae103f787bc8 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Mon, 29 May 2023 17:03:39 +0100 Subject: [PATCH] WorldProvider: allow loadChunk() to return additional information about the loaded chunk data this will be needed for dealing with #5733. I don't plan to fix that before 5.0, but we need to make the appropriate BC breaks now, before release. --- src/world/World.php | 10 ++--- src/world/format/io/FormatConverter.php | 7 +-- src/world/format/io/LoadedChunkData.php | 45 +++++++++++++++++++ src/world/format/io/WorldProvider.php | 6 +-- src/world/format/io/leveldb/LevelDB.php | 9 +++- .../io/region/LegacyAnvilChunkTrait.php | 19 +++++--- src/world/format/io/region/McRegion.php | 19 +++++--- .../format/io/region/RegionWorldProvider.php | 6 +-- 8 files changed, 91 insertions(+), 30 deletions(-) create mode 100644 src/world/format/io/LoadedChunkData.php diff --git a/src/world/World.php b/src/world/World.php index 13101d50f..6942b732f 100644 --- a/src/world/World.php +++ b/src/world/World.php @@ -2702,25 +2702,25 @@ class World implements ChunkManager{ $this->timings->syncChunkLoadData->startTiming(); - $chunk = null; + $loadedChunkData = null; try{ - $chunk = $this->provider->loadChunk($x, $z); + $loadedChunkData = $this->provider->loadChunk($x, $z); }catch(CorruptedChunkException $e){ $this->logger->critical("Failed to load chunk x=$x z=$z: " . $e->getMessage()); } $this->timings->syncChunkLoadData->stopTiming(); - if($chunk === null){ + if($loadedChunkData === null){ $this->timings->syncChunkLoad->stopTiming(); return null; } - $this->chunks[$chunkHash] = $chunk->getChunk(); + $this->chunks[$chunkHash] = $loadedChunkData->getData()->getChunk(); unset($this->blockCache[$chunkHash]); - $this->initChunk($x, $z, $chunk); + $this->initChunk($x, $z, $loadedChunkData->getData()); (new ChunkLoadEvent($this, $x, $z, $this->chunks[$chunkHash], false))->call(); diff --git a/src/world/format/io/FormatConverter.php b/src/world/format/io/FormatConverter.php index 0a12432da..e318d7c62 100644 --- a/src/world/format/io/FormatConverter.php +++ b/src/world/format/io/FormatConverter.php @@ -140,10 +140,11 @@ class FormatConverter{ $start = microtime(true); $thisRound = $start; - foreach($this->oldProvider->getAllChunks(true, $this->logger) as $coords => $chunk){ + foreach($this->oldProvider->getAllChunks(true, $this->logger) as $coords => $loadedChunkData){ [$chunkX, $chunkZ] = $coords; - $chunk->getChunk()->setTerrainDirty(); - $new->saveChunk($chunkX, $chunkZ, $chunk); + $chunkData = $loadedChunkData->getData(); + $chunkData->getChunk()->setTerrainDirty(); + $new->saveChunk($chunkX, $chunkZ, $chunkData); $counter++; if(($counter % $this->chunksPerProgressUpdate) === 0){ $time = microtime(true); diff --git a/src/world/format/io/LoadedChunkData.php b/src/world/format/io/LoadedChunkData.php new file mode 100644 index 000000000..bb31a97e1 --- /dev/null +++ b/src/world/format/io/LoadedChunkData.php @@ -0,0 +1,45 @@ +data; } + + public function isUpgraded() : bool{ return $this->upgraded; } + + public function getFixerFlags() : int{ return $this->fixerFlags; } +} diff --git a/src/world/format/io/WorldProvider.php b/src/world/format/io/WorldProvider.php index 3d08df860..546ca1204 100644 --- a/src/world/format/io/WorldProvider.php +++ b/src/world/format/io/WorldProvider.php @@ -43,7 +43,7 @@ interface WorldProvider{ * * @throws CorruptedChunkException */ - public function loadChunk(int $chunkX, int $chunkZ) : ?ChunkData; + public function loadChunk(int $chunkX, int $chunkZ) : ?LoadedChunkData; /** * Performs garbage collection in the world provider, such as cleaning up regions in Region-based worlds. @@ -63,8 +63,8 @@ interface WorldProvider{ /** * Returns a generator which yields all the chunks in this world. * - * @return \Generator|ChunkData[] - * @phpstan-return \Generator + * @return \Generator|LoadedChunkData[] + * @phpstan-return \Generator * @throws CorruptedChunkException */ public function getAllChunks(bool $skipCorrupted = false, ?\Logger $logger = null) : \Generator; diff --git a/src/world/format/io/leveldb/LevelDB.php b/src/world/format/io/leveldb/LevelDB.php index 61ee88a06..17d0770b3 100644 --- a/src/world/format/io/leveldb/LevelDB.php +++ b/src/world/format/io/leveldb/LevelDB.php @@ -44,6 +44,7 @@ use pocketmine\world\format\io\exception\CorruptedChunkException; use pocketmine\world\format\io\exception\CorruptedWorldException; use pocketmine\world\format\io\exception\UnsupportedWorldFormatException; use pocketmine\world\format\io\GlobalBlockStateHandlers; +use pocketmine\world\format\io\LoadedChunkData; use pocketmine\world\format\io\WorldData; use pocketmine\world\format\io\WritableWorldProvider; use pocketmine\world\format\PalettedBlockArray; @@ -593,7 +594,7 @@ class LevelDB extends BaseWorldProvider implements WritableWorldProvider{ /** * @throws CorruptedChunkException */ - public function loadChunk(int $chunkX, int $chunkZ) : ?ChunkData{ + public function loadChunk(int $chunkX, int $chunkZ) : ?LoadedChunkData{ $index = LevelDB::chunkIndex($chunkX, $chunkZ); $chunkVersion = $this->readVersion($chunkX, $chunkZ); @@ -704,7 +705,11 @@ class LevelDB extends BaseWorldProvider implements WritableWorldProvider{ $chunk->setTerrainDirty(); //trigger rewriting chunk to disk if it was converted from an older format } - return new ChunkData($chunk, $entities, $tiles); + return new LoadedChunkData( + data: new ChunkData($chunk, $entities, $tiles), + upgraded: $hasBeenUpgraded, + fixerFlags: LoadedChunkData::FIXER_FLAG_ALL //TODO: fill this by version rather than just setting all flags + ); } public function saveChunk(int $chunkX, int $chunkZ, ChunkData $chunkData) : void{ diff --git a/src/world/format/io/region/LegacyAnvilChunkTrait.php b/src/world/format/io/region/LegacyAnvilChunkTrait.php index 05d4b0fb8..84bbb72f7 100644 --- a/src/world/format/io/region/LegacyAnvilChunkTrait.php +++ b/src/world/format/io/region/LegacyAnvilChunkTrait.php @@ -36,6 +36,7 @@ use pocketmine\world\format\Chunk; use pocketmine\world\format\io\ChunkData; use pocketmine\world\format\io\ChunkUtils; use pocketmine\world\format\io\exception\CorruptedChunkException; +use pocketmine\world\format\io\LoadedChunkData; use pocketmine\world\format\PalettedBlockArray; use pocketmine\world\format\SubChunk; use function strlen; @@ -54,7 +55,7 @@ trait LegacyAnvilChunkTrait{ /** * @throws CorruptedChunkException */ - protected function deserializeChunk(string $data) : ?ChunkData{ + protected function deserializeChunk(string $data) : ?LoadedChunkData{ $decompressed = @zlib_decode($data); if($decompressed === false){ throw new CorruptedChunkException("Failed to decompress chunk NBT"); @@ -99,13 +100,17 @@ trait LegacyAnvilChunkTrait{ } } - return new ChunkData( - new Chunk( - $subChunks, - $chunk->getByte("TerrainPopulated", 0) !== 0 + return new LoadedChunkData( + data: new ChunkData( + new Chunk( + $subChunks, + $chunk->getByte("TerrainPopulated", 0) !== 0 + ), + ($entitiesTag = $chunk->getTag("Entities")) instanceof ListTag ? self::getCompoundList("Entities", $entitiesTag) : [], + ($tilesTag = $chunk->getTag("TileEntities")) instanceof ListTag ? self::getCompoundList("TileEntities", $tilesTag) : [], ), - ($entitiesTag = $chunk->getTag("Entities")) instanceof ListTag ? self::getCompoundList("Entities", $entitiesTag) : [], - ($tilesTag = $chunk->getTag("TileEntities")) instanceof ListTag ? self::getCompoundList("TileEntities", $tilesTag) : [], + upgraded: true, + fixerFlags: LoadedChunkData::FIXER_FLAG_ALL ); } diff --git a/src/world/format/io/region/McRegion.php b/src/world/format/io/region/McRegion.php index f911d0043..3ed185b1f 100644 --- a/src/world/format/io/region/McRegion.php +++ b/src/world/format/io/region/McRegion.php @@ -37,6 +37,7 @@ use pocketmine\world\format\Chunk; use pocketmine\world\format\io\ChunkData; use pocketmine\world\format\io\ChunkUtils; use pocketmine\world\format\io\exception\CorruptedChunkException; +use pocketmine\world\format\io\LoadedChunkData; use pocketmine\world\format\PalettedBlockArray; use pocketmine\world\format\SubChunk; use function strlen; @@ -46,7 +47,7 @@ class McRegion extends RegionWorldProvider{ /** * @throws CorruptedChunkException */ - protected function deserializeChunk(string $data) : ?ChunkData{ + protected function deserializeChunk(string $data) : ?LoadedChunkData{ $decompressed = @zlib_decode($data); if($decompressed === false){ throw new CorruptedChunkException("Failed to decompress chunk NBT"); @@ -98,13 +99,17 @@ class McRegion extends RegionWorldProvider{ } } - return new ChunkData( - new Chunk( - $subChunks, - $chunk->getByte("TerrainPopulated", 0) !== 0 + return new LoadedChunkData( + data: new ChunkData( + new Chunk( + $subChunks, + $chunk->getByte("TerrainPopulated", 0) !== 0 + ), + ($entitiesTag = $chunk->getTag("Entities")) instanceof ListTag ? self::getCompoundList("Entities", $entitiesTag) : [], + ($tilesTag = $chunk->getTag("TileEntities")) instanceof ListTag ? self::getCompoundList("TileEntities", $tilesTag) : [], ), - ($entitiesTag = $chunk->getTag("Entities")) instanceof ListTag ? self::getCompoundList("Entities", $entitiesTag) : [], - ($tilesTag = $chunk->getTag("TileEntities")) instanceof ListTag ? self::getCompoundList("TileEntities", $tilesTag) : [], + upgraded: true, + fixerFlags: LoadedChunkData::FIXER_FLAG_ALL ); } diff --git a/src/world/format/io/region/RegionWorldProvider.php b/src/world/format/io/region/RegionWorldProvider.php index a5b6f54f7..a4a3055c6 100644 --- a/src/world/format/io/region/RegionWorldProvider.php +++ b/src/world/format/io/region/RegionWorldProvider.php @@ -28,9 +28,9 @@ use pocketmine\nbt\tag\ByteArrayTag; use pocketmine\nbt\tag\CompoundTag; use pocketmine\nbt\tag\ListTag; use pocketmine\world\format\io\BaseWorldProvider; -use pocketmine\world\format\io\ChunkData; use pocketmine\world\format\io\data\JavaWorldData; use pocketmine\world\format\io\exception\CorruptedChunkException; +use pocketmine\world\format\io\LoadedChunkData; use pocketmine\world\format\io\WorldData; use Symfony\Component\Filesystem\Path; use function assert; @@ -147,7 +147,7 @@ abstract class RegionWorldProvider extends BaseWorldProvider{ /** * @throws CorruptedChunkException */ - abstract protected function deserializeChunk(string $data) : ?ChunkData; + abstract protected function deserializeChunk(string $data) : ?LoadedChunkData; /** * @return CompoundTag[] @@ -189,7 +189,7 @@ abstract class RegionWorldProvider extends BaseWorldProvider{ /** * @throws CorruptedChunkException */ - public function loadChunk(int $chunkX, int $chunkZ) : ?ChunkData{ + public function loadChunk(int $chunkX, int $chunkZ) : ?LoadedChunkData{ $regionX = $regionZ = null; self::getRegionIndex($chunkX, $chunkZ, $regionX, $regionZ); assert(is_int($regionX) && is_int($regionZ));