mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-07-03 08:39:53 +00:00
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.
This commit is contained in:
parent
f5a1a0c9cb
commit
c10be0f346
@ -2702,25 +2702,25 @@ class World implements ChunkManager{
|
|||||||
|
|
||||||
$this->timings->syncChunkLoadData->startTiming();
|
$this->timings->syncChunkLoadData->startTiming();
|
||||||
|
|
||||||
$chunk = null;
|
$loadedChunkData = null;
|
||||||
|
|
||||||
try{
|
try{
|
||||||
$chunk = $this->provider->loadChunk($x, $z);
|
$loadedChunkData = $this->provider->loadChunk($x, $z);
|
||||||
}catch(CorruptedChunkException $e){
|
}catch(CorruptedChunkException $e){
|
||||||
$this->logger->critical("Failed to load chunk x=$x z=$z: " . $e->getMessage());
|
$this->logger->critical("Failed to load chunk x=$x z=$z: " . $e->getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->timings->syncChunkLoadData->stopTiming();
|
$this->timings->syncChunkLoadData->stopTiming();
|
||||||
|
|
||||||
if($chunk === null){
|
if($loadedChunkData === null){
|
||||||
$this->timings->syncChunkLoad->stopTiming();
|
$this->timings->syncChunkLoad->stopTiming();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->chunks[$chunkHash] = $chunk->getChunk();
|
$this->chunks[$chunkHash] = $loadedChunkData->getData()->getChunk();
|
||||||
unset($this->blockCache[$chunkHash]);
|
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();
|
(new ChunkLoadEvent($this, $x, $z, $this->chunks[$chunkHash], false))->call();
|
||||||
|
|
||||||
|
@ -140,10 +140,11 @@ class FormatConverter{
|
|||||||
|
|
||||||
$start = microtime(true);
|
$start = microtime(true);
|
||||||
$thisRound = $start;
|
$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;
|
[$chunkX, $chunkZ] = $coords;
|
||||||
$chunk->getChunk()->setTerrainDirty();
|
$chunkData = $loadedChunkData->getData();
|
||||||
$new->saveChunk($chunkX, $chunkZ, $chunk);
|
$chunkData->getChunk()->setTerrainDirty();
|
||||||
|
$new->saveChunk($chunkX, $chunkZ, $chunkData);
|
||||||
$counter++;
|
$counter++;
|
||||||
if(($counter % $this->chunksPerProgressUpdate) === 0){
|
if(($counter % $this->chunksPerProgressUpdate) === 0){
|
||||||
$time = microtime(true);
|
$time = microtime(true);
|
||||||
|
45
src/world/format/io/LoadedChunkData.php
Normal file
45
src/world/format/io/LoadedChunkData.php
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* ____ _ _ __ __ _ __ __ ____
|
||||||
|
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||||
|
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||||
|
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||||
|
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* @author PocketMine Team
|
||||||
|
* @link http://www.pocketmine.net/
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace pocketmine\world\format\io;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encapsulates information returned when loading a chunk. This includes more information than saving a chunk, since the
|
||||||
|
* data might have been upgraded or need post-processing.
|
||||||
|
*/
|
||||||
|
final class LoadedChunkData{
|
||||||
|
public const FIXER_FLAG_NONE = 0;
|
||||||
|
public const FIXER_FLAG_ALL = ~0;
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
private ChunkData $data,
|
||||||
|
private bool $upgraded,
|
||||||
|
private int $fixerFlags
|
||||||
|
){}
|
||||||
|
|
||||||
|
public function getData() : ChunkData{ return $this->data; }
|
||||||
|
|
||||||
|
public function isUpgraded() : bool{ return $this->upgraded; }
|
||||||
|
|
||||||
|
public function getFixerFlags() : int{ return $this->fixerFlags; }
|
||||||
|
}
|
@ -43,7 +43,7 @@ interface WorldProvider{
|
|||||||
*
|
*
|
||||||
* @throws CorruptedChunkException
|
* @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.
|
* 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.
|
* Returns a generator which yields all the chunks in this world.
|
||||||
*
|
*
|
||||||
* @return \Generator|ChunkData[]
|
* @return \Generator|LoadedChunkData[]
|
||||||
* @phpstan-return \Generator<array{int, int}, ChunkData, void, void>
|
* @phpstan-return \Generator<array{int, int}, LoadedChunkData, void, void>
|
||||||
* @throws CorruptedChunkException
|
* @throws CorruptedChunkException
|
||||||
*/
|
*/
|
||||||
public function getAllChunks(bool $skipCorrupted = false, ?\Logger $logger = null) : \Generator;
|
public function getAllChunks(bool $skipCorrupted = false, ?\Logger $logger = null) : \Generator;
|
||||||
|
@ -44,6 +44,7 @@ use pocketmine\world\format\io\exception\CorruptedChunkException;
|
|||||||
use pocketmine\world\format\io\exception\CorruptedWorldException;
|
use pocketmine\world\format\io\exception\CorruptedWorldException;
|
||||||
use pocketmine\world\format\io\exception\UnsupportedWorldFormatException;
|
use pocketmine\world\format\io\exception\UnsupportedWorldFormatException;
|
||||||
use pocketmine\world\format\io\GlobalBlockStateHandlers;
|
use pocketmine\world\format\io\GlobalBlockStateHandlers;
|
||||||
|
use pocketmine\world\format\io\LoadedChunkData;
|
||||||
use pocketmine\world\format\io\WorldData;
|
use pocketmine\world\format\io\WorldData;
|
||||||
use pocketmine\world\format\io\WritableWorldProvider;
|
use pocketmine\world\format\io\WritableWorldProvider;
|
||||||
use pocketmine\world\format\PalettedBlockArray;
|
use pocketmine\world\format\PalettedBlockArray;
|
||||||
@ -593,7 +594,7 @@ class LevelDB extends BaseWorldProvider implements WritableWorldProvider{
|
|||||||
/**
|
/**
|
||||||
* @throws CorruptedChunkException
|
* @throws CorruptedChunkException
|
||||||
*/
|
*/
|
||||||
public function loadChunk(int $chunkX, int $chunkZ) : ?ChunkData{
|
public function loadChunk(int $chunkX, int $chunkZ) : ?LoadedChunkData{
|
||||||
$index = LevelDB::chunkIndex($chunkX, $chunkZ);
|
$index = LevelDB::chunkIndex($chunkX, $chunkZ);
|
||||||
|
|
||||||
$chunkVersion = $this->readVersion($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
|
$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{
|
public function saveChunk(int $chunkX, int $chunkZ, ChunkData $chunkData) : void{
|
||||||
|
@ -36,6 +36,7 @@ use pocketmine\world\format\Chunk;
|
|||||||
use pocketmine\world\format\io\ChunkData;
|
use pocketmine\world\format\io\ChunkData;
|
||||||
use pocketmine\world\format\io\ChunkUtils;
|
use pocketmine\world\format\io\ChunkUtils;
|
||||||
use pocketmine\world\format\io\exception\CorruptedChunkException;
|
use pocketmine\world\format\io\exception\CorruptedChunkException;
|
||||||
|
use pocketmine\world\format\io\LoadedChunkData;
|
||||||
use pocketmine\world\format\PalettedBlockArray;
|
use pocketmine\world\format\PalettedBlockArray;
|
||||||
use pocketmine\world\format\SubChunk;
|
use pocketmine\world\format\SubChunk;
|
||||||
use function strlen;
|
use function strlen;
|
||||||
@ -54,7 +55,7 @@ trait LegacyAnvilChunkTrait{
|
|||||||
/**
|
/**
|
||||||
* @throws CorruptedChunkException
|
* @throws CorruptedChunkException
|
||||||
*/
|
*/
|
||||||
protected function deserializeChunk(string $data) : ?ChunkData{
|
protected function deserializeChunk(string $data) : ?LoadedChunkData{
|
||||||
$decompressed = @zlib_decode($data);
|
$decompressed = @zlib_decode($data);
|
||||||
if($decompressed === false){
|
if($decompressed === false){
|
||||||
throw new CorruptedChunkException("Failed to decompress chunk NBT");
|
throw new CorruptedChunkException("Failed to decompress chunk NBT");
|
||||||
@ -99,13 +100,17 @@ trait LegacyAnvilChunkTrait{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return new ChunkData(
|
return new LoadedChunkData(
|
||||||
new Chunk(
|
data: new ChunkData(
|
||||||
$subChunks,
|
new Chunk(
|
||||||
$chunk->getByte("TerrainPopulated", 0) !== 0
|
$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) : [],
|
upgraded: true,
|
||||||
($tilesTag = $chunk->getTag("TileEntities")) instanceof ListTag ? self::getCompoundList("TileEntities", $tilesTag) : [],
|
fixerFlags: LoadedChunkData::FIXER_FLAG_ALL
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,6 +37,7 @@ use pocketmine\world\format\Chunk;
|
|||||||
use pocketmine\world\format\io\ChunkData;
|
use pocketmine\world\format\io\ChunkData;
|
||||||
use pocketmine\world\format\io\ChunkUtils;
|
use pocketmine\world\format\io\ChunkUtils;
|
||||||
use pocketmine\world\format\io\exception\CorruptedChunkException;
|
use pocketmine\world\format\io\exception\CorruptedChunkException;
|
||||||
|
use pocketmine\world\format\io\LoadedChunkData;
|
||||||
use pocketmine\world\format\PalettedBlockArray;
|
use pocketmine\world\format\PalettedBlockArray;
|
||||||
use pocketmine\world\format\SubChunk;
|
use pocketmine\world\format\SubChunk;
|
||||||
use function strlen;
|
use function strlen;
|
||||||
@ -46,7 +47,7 @@ class McRegion extends RegionWorldProvider{
|
|||||||
/**
|
/**
|
||||||
* @throws CorruptedChunkException
|
* @throws CorruptedChunkException
|
||||||
*/
|
*/
|
||||||
protected function deserializeChunk(string $data) : ?ChunkData{
|
protected function deserializeChunk(string $data) : ?LoadedChunkData{
|
||||||
$decompressed = @zlib_decode($data);
|
$decompressed = @zlib_decode($data);
|
||||||
if($decompressed === false){
|
if($decompressed === false){
|
||||||
throw new CorruptedChunkException("Failed to decompress chunk NBT");
|
throw new CorruptedChunkException("Failed to decompress chunk NBT");
|
||||||
@ -98,13 +99,17 @@ class McRegion extends RegionWorldProvider{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return new ChunkData(
|
return new LoadedChunkData(
|
||||||
new Chunk(
|
data: new ChunkData(
|
||||||
$subChunks,
|
new Chunk(
|
||||||
$chunk->getByte("TerrainPopulated", 0) !== 0
|
$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) : [],
|
upgraded: true,
|
||||||
($tilesTag = $chunk->getTag("TileEntities")) instanceof ListTag ? self::getCompoundList("TileEntities", $tilesTag) : [],
|
fixerFlags: LoadedChunkData::FIXER_FLAG_ALL
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,9 +28,9 @@ use pocketmine\nbt\tag\ByteArrayTag;
|
|||||||
use pocketmine\nbt\tag\CompoundTag;
|
use pocketmine\nbt\tag\CompoundTag;
|
||||||
use pocketmine\nbt\tag\ListTag;
|
use pocketmine\nbt\tag\ListTag;
|
||||||
use pocketmine\world\format\io\BaseWorldProvider;
|
use pocketmine\world\format\io\BaseWorldProvider;
|
||||||
use pocketmine\world\format\io\ChunkData;
|
|
||||||
use pocketmine\world\format\io\data\JavaWorldData;
|
use pocketmine\world\format\io\data\JavaWorldData;
|
||||||
use pocketmine\world\format\io\exception\CorruptedChunkException;
|
use pocketmine\world\format\io\exception\CorruptedChunkException;
|
||||||
|
use pocketmine\world\format\io\LoadedChunkData;
|
||||||
use pocketmine\world\format\io\WorldData;
|
use pocketmine\world\format\io\WorldData;
|
||||||
use Symfony\Component\Filesystem\Path;
|
use Symfony\Component\Filesystem\Path;
|
||||||
use function assert;
|
use function assert;
|
||||||
@ -147,7 +147,7 @@ abstract class RegionWorldProvider extends BaseWorldProvider{
|
|||||||
/**
|
/**
|
||||||
* @throws CorruptedChunkException
|
* @throws CorruptedChunkException
|
||||||
*/
|
*/
|
||||||
abstract protected function deserializeChunk(string $data) : ?ChunkData;
|
abstract protected function deserializeChunk(string $data) : ?LoadedChunkData;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return CompoundTag[]
|
* @return CompoundTag[]
|
||||||
@ -189,7 +189,7 @@ abstract class RegionWorldProvider extends BaseWorldProvider{
|
|||||||
/**
|
/**
|
||||||
* @throws CorruptedChunkException
|
* @throws CorruptedChunkException
|
||||||
*/
|
*/
|
||||||
public function loadChunk(int $chunkX, int $chunkZ) : ?ChunkData{
|
public function loadChunk(int $chunkX, int $chunkZ) : ?LoadedChunkData{
|
||||||
$regionX = $regionZ = null;
|
$regionX = $regionZ = null;
|
||||||
self::getRegionIndex($chunkX, $chunkZ, $regionX, $regionZ);
|
self::getRegionIndex($chunkX, $chunkZ, $regionX, $regionZ);
|
||||||
assert(is_int($regionX) && is_int($regionZ));
|
assert(is_int($regionX) && is_int($regionZ));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user