mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-04-20 16:00:20 +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();
|
||||
|
||||
$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();
|
||||
|
||||
|
@ -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);
|
||||
|
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
|
||||
*/
|
||||
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<array{int, int}, ChunkData, void, void>
|
||||
* @return \Generator|LoadedChunkData[]
|
||||
* @phpstan-return \Generator<array{int, int}, LoadedChunkData, void, void>
|
||||
* @throws CorruptedChunkException
|
||||
*/
|
||||
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\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{
|
||||
|
@ -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
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -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));
|
||||
|
Loading…
x
Reference in New Issue
Block a user