mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-06-07 12:18:46 +00:00
Reduce global usage in world providers
This commit is contained in:
parent
499b29b53a
commit
c3a2199f0e
@ -24,6 +24,9 @@ declare(strict_types=1);
|
|||||||
namespace pocketmine\world\format\io;
|
namespace pocketmine\world\format\io;
|
||||||
|
|
||||||
use pocketmine\data\bedrock\block\BlockStateDeserializeException;
|
use pocketmine\data\bedrock\block\BlockStateDeserializeException;
|
||||||
|
use pocketmine\data\bedrock\block\BlockStateDeserializer;
|
||||||
|
use pocketmine\data\bedrock\block\BlockStateSerializer;
|
||||||
|
use pocketmine\data\bedrock\block\upgrade\BlockDataUpgrader;
|
||||||
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\PalettedBlockArray;
|
use pocketmine\world\format\PalettedBlockArray;
|
||||||
@ -33,6 +36,10 @@ use function file_exists;
|
|||||||
abstract class BaseWorldProvider implements WorldProvider{
|
abstract class BaseWorldProvider implements WorldProvider{
|
||||||
protected WorldData $worldData;
|
protected WorldData $worldData;
|
||||||
|
|
||||||
|
protected BlockStateDeserializer $blockStateDeserializer;
|
||||||
|
protected BlockDataUpgrader $blockDataUpgrader;
|
||||||
|
protected BlockStateSerializer $blockStateSerializer;
|
||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
protected string $path
|
protected string $path
|
||||||
){
|
){
|
||||||
@ -40,6 +47,11 @@ abstract class BaseWorldProvider implements WorldProvider{
|
|||||||
throw new WorldException("World does not exist");
|
throw new WorldException("World does not exist");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO: this should not rely on singletons
|
||||||
|
$this->blockStateDeserializer = GlobalBlockStateHandlers::getDeserializer();
|
||||||
|
$this->blockDataUpgrader = GlobalBlockStateHandlers::getUpgrader();
|
||||||
|
$this->blockStateSerializer = GlobalBlockStateHandlers::getSerializer();
|
||||||
|
|
||||||
$this->worldData = $this->loadLevelData();
|
$this->worldData = $this->loadLevelData();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -52,24 +64,20 @@ abstract class BaseWorldProvider implements WorldProvider{
|
|||||||
private function translatePalette(PalettedBlockArray $blockArray) : PalettedBlockArray{
|
private function translatePalette(PalettedBlockArray $blockArray) : PalettedBlockArray{
|
||||||
$palette = $blockArray->getPalette();
|
$palette = $blockArray->getPalette();
|
||||||
|
|
||||||
//TODO: this should be dependency-injected so it can be replaced, but that would break BC
|
|
||||||
//also, we want it to be lazy-loaded ...
|
|
||||||
$blockDataUpgrader = GlobalBlockStateHandlers::getUpgrader();
|
|
||||||
$blockStateDeserializer = GlobalBlockStateHandlers::getDeserializer();
|
|
||||||
$newPalette = [];
|
$newPalette = [];
|
||||||
foreach($palette as $k => $legacyIdMeta){
|
foreach($palette as $k => $legacyIdMeta){
|
||||||
$newStateData = $blockDataUpgrader->upgradeIntIdMeta($legacyIdMeta >> 4, $legacyIdMeta & 0xf);
|
$newStateData = $this->blockDataUpgrader->upgradeIntIdMeta($legacyIdMeta >> 4, $legacyIdMeta & 0xf);
|
||||||
if($newStateData === null){
|
if($newStateData === null){
|
||||||
//TODO: remember data for unknown states so we can implement them later
|
//TODO: remember data for unknown states so we can implement them later
|
||||||
$newStateData = GlobalBlockStateHandlers::getUnknownBlockStateData();
|
$newStateData = GlobalBlockStateHandlers::getUnknownBlockStateData();
|
||||||
}
|
}
|
||||||
|
|
||||||
try{
|
try{
|
||||||
$newPalette[$k] = $blockStateDeserializer->deserialize($newStateData);
|
$newPalette[$k] = $this->blockStateDeserializer->deserialize($newStateData);
|
||||||
}catch(BlockStateDeserializeException){
|
}catch(BlockStateDeserializeException){
|
||||||
//TODO: this needs to be logged
|
//TODO: this needs to be logged
|
||||||
//TODO: maybe we can remember unknown states for later saving instead of discarding them and destroying maps...
|
//TODO: maybe we can remember unknown states for later saving instead of discarding them and destroying maps...
|
||||||
$newPalette[$k] = $blockStateDeserializer->deserialize(GlobalBlockStateHandlers::getUnknownBlockStateData());
|
$newPalette[$k] = $this->blockStateDeserializer->deserialize(GlobalBlockStateHandlers::getUnknownBlockStateData());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,7 +27,6 @@ use pocketmine\block\Block;
|
|||||||
use pocketmine\block\BlockTypeIds;
|
use pocketmine\block\BlockTypeIds;
|
||||||
use pocketmine\data\bedrock\BiomeIds;
|
use pocketmine\data\bedrock\BiomeIds;
|
||||||
use pocketmine\data\bedrock\block\BlockStateDeserializeException;
|
use pocketmine\data\bedrock\block\BlockStateDeserializeException;
|
||||||
use pocketmine\data\bedrock\block\BlockStateSerializer;
|
|
||||||
use pocketmine\nbt\LittleEndianNbtSerializer;
|
use pocketmine\nbt\LittleEndianNbtSerializer;
|
||||||
use pocketmine\nbt\NbtDataException;
|
use pocketmine\nbt\NbtDataException;
|
||||||
use pocketmine\nbt\NbtException;
|
use pocketmine\nbt\NbtException;
|
||||||
@ -158,14 +157,12 @@ class LevelDB extends BaseWorldProvider implements WritableWorldProvider{
|
|||||||
|
|
||||||
$paletteSize = $bitsPerBlock === 0 ? 1 : $stream->getLInt();
|
$paletteSize = $bitsPerBlock === 0 ? 1 : $stream->getLInt();
|
||||||
|
|
||||||
$blockDataUpgrader = GlobalBlockStateHandlers::getUpgrader();
|
|
||||||
$blockStateDeserializer = GlobalBlockStateHandlers::getDeserializer();
|
|
||||||
for($i = 0; $i < $paletteSize; ++$i){
|
for($i = 0; $i < $paletteSize; ++$i){
|
||||||
try{
|
try{
|
||||||
$offset = $stream->getOffset();
|
$offset = $stream->getOffset();
|
||||||
|
|
||||||
$blockStateNbt = $nbt->read($stream->getBuffer(), $offset)->mustGetCompoundTag();
|
$blockStateNbt = $nbt->read($stream->getBuffer(), $offset)->mustGetCompoundTag();
|
||||||
$blockStateData = $blockDataUpgrader->upgradeBlockStateNbt($blockStateNbt);
|
$blockStateData = $this->blockDataUpgrader->upgradeBlockStateNbt($blockStateNbt);
|
||||||
if($blockStateData === null){
|
if($blockStateData === null){
|
||||||
//upgrading blockstates should always succeed, regardless of whether they've been implemented or not
|
//upgrading blockstates should always succeed, regardless of whether they've been implemented or not
|
||||||
throw new BlockStateDeserializeException("Invalid or improperly mapped legacy blockstate: " . $blockStateNbt->toString());
|
throw new BlockStateDeserializeException("Invalid or improperly mapped legacy blockstate: " . $blockStateNbt->toString());
|
||||||
@ -173,11 +170,11 @@ class LevelDB extends BaseWorldProvider implements WritableWorldProvider{
|
|||||||
$stream->setOffset($offset);
|
$stream->setOffset($offset);
|
||||||
|
|
||||||
try{
|
try{
|
||||||
$palette[] = $blockStateDeserializer->deserialize($blockStateData);
|
$palette[] = $this->blockStateDeserializer->deserialize($blockStateData);
|
||||||
}catch(BlockStateDeserializeException){
|
}catch(BlockStateDeserializeException){
|
||||||
//TODO: remember data for unknown states so we can implement them later
|
//TODO: remember data for unknown states so we can implement them later
|
||||||
//TODO: log this
|
//TODO: log this
|
||||||
$palette[] = $blockStateDeserializer->deserialize(GlobalBlockStateHandlers::getUnknownBlockStateData());
|
$palette[] = $this->blockStateDeserializer->deserialize(GlobalBlockStateHandlers::getUnknownBlockStateData());
|
||||||
}
|
}
|
||||||
}catch(NbtException | BlockStateDeserializeException $e){
|
}catch(NbtException | BlockStateDeserializeException $e){
|
||||||
throw new CorruptedChunkException("Invalid blockstate NBT at offset $i in paletted storage: " . $e->getMessage(), 0, $e);
|
throw new CorruptedChunkException("Invalid blockstate NBT at offset $i in paletted storage: " . $e->getMessage(), 0, $e);
|
||||||
@ -188,7 +185,7 @@ class LevelDB extends BaseWorldProvider implements WritableWorldProvider{
|
|||||||
return PalettedBlockArray::fromData($bitsPerBlock, $words, $palette);
|
return PalettedBlockArray::fromData($bitsPerBlock, $words, $palette);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static function serializeBlockPalette(BinaryStream $stream, PalettedBlockArray $blocks, BlockStateSerializer $blockStateSerializer) : void{
|
private function serializeBlockPalette(BinaryStream $stream, PalettedBlockArray $blocks) : void{
|
||||||
$stream->putByte($blocks->getBitsPerBlock() << 1);
|
$stream->putByte($blocks->getBitsPerBlock() << 1);
|
||||||
$stream->put($blocks->getWordArray());
|
$stream->put($blocks->getWordArray());
|
||||||
|
|
||||||
@ -198,7 +195,7 @@ class LevelDB extends BaseWorldProvider implements WritableWorldProvider{
|
|||||||
}
|
}
|
||||||
$tags = [];
|
$tags = [];
|
||||||
foreach($palette as $p){
|
foreach($palette as $p){
|
||||||
$tags[] = new TreeRoot($blockStateSerializer->serialize($p)->toNbt());
|
$tags[] = new TreeRoot($this->blockStateSerializer->serialize($p)->toNbt());
|
||||||
}
|
}
|
||||||
|
|
||||||
$stream->put((new LittleEndianNbtSerializer())->writeMultiple($tags));
|
$stream->put((new LittleEndianNbtSerializer())->writeMultiple($tags));
|
||||||
@ -327,8 +324,6 @@ class LevelDB extends BaseWorldProvider implements WritableWorldProvider{
|
|||||||
$binaryStream = new BinaryStream($extraRawData);
|
$binaryStream = new BinaryStream($extraRawData);
|
||||||
$count = $binaryStream->getLInt();
|
$count = $binaryStream->getLInt();
|
||||||
|
|
||||||
$blockDataUpgrader = GlobalBlockStateHandlers::getUpgrader();
|
|
||||||
$blockStateDeserializer = GlobalBlockStateHandlers::getDeserializer();
|
|
||||||
for($i = 0; $i < $count; ++$i){
|
for($i = 0; $i < $count; ++$i){
|
||||||
$key = $binaryStream->getLInt();
|
$key = $binaryStream->getLInt();
|
||||||
$value = $binaryStream->getLShort();
|
$value = $binaryStream->getLShort();
|
||||||
@ -340,13 +335,13 @@ class LevelDB extends BaseWorldProvider implements WritableWorldProvider{
|
|||||||
|
|
||||||
$blockId = $value & 0xff;
|
$blockId = $value & 0xff;
|
||||||
$blockData = ($value >> 8) & 0xf;
|
$blockData = ($value >> 8) & 0xf;
|
||||||
$blockStateData = $blockDataUpgrader->upgradeIntIdMeta($blockId, $blockData);
|
$blockStateData = $this->blockDataUpgrader->upgradeIntIdMeta($blockId, $blockData);
|
||||||
if($blockStateData === null){
|
if($blockStateData === null){
|
||||||
//TODO: we could preserve this in case it's supported in the future, but this was historically only
|
//TODO: we could preserve this in case it's supported in the future, but this was historically only
|
||||||
//used for grass anyway, so we probably don't need to care
|
//used for grass anyway, so we probably don't need to care
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
$blockStateId = $blockStateDeserializer->deserialize($blockStateData);
|
$blockStateId = $this->blockStateDeserializer->deserialize($blockStateData);
|
||||||
|
|
||||||
if(!isset($extraDataLayers[$ySub])){
|
if(!isset($extraDataLayers[$ySub])){
|
||||||
$extraDataLayers[$ySub] = new PalettedBlockArray(BlockTypeIds::AIR << Block::INTERNAL_STATE_DATA_BITS);
|
$extraDataLayers[$ySub] = new PalettedBlockArray(BlockTypeIds::AIR << Block::INTERNAL_STATE_DATA_BITS);
|
||||||
@ -693,9 +688,6 @@ class LevelDB extends BaseWorldProvider implements WritableWorldProvider{
|
|||||||
if($chunk->getTerrainDirtyFlag(Chunk::DIRTY_FLAG_BLOCKS)){
|
if($chunk->getTerrainDirtyFlag(Chunk::DIRTY_FLAG_BLOCKS)){
|
||||||
$subChunks = $chunk->getSubChunks();
|
$subChunks = $chunk->getSubChunks();
|
||||||
|
|
||||||
//TODO: this should not rely on globals, but in PM4 we have no other option, and it's not worse than what we
|
|
||||||
//were doing before anyway ...
|
|
||||||
$blockStateSerializer = GlobalBlockStateHandlers::getSerializer();
|
|
||||||
foreach($subChunks as $y => $subChunk){
|
foreach($subChunks as $y => $subChunk){
|
||||||
$key = $index . ChunkDataKey::SUBCHUNK . chr($y);
|
$key = $index . ChunkDataKey::SUBCHUNK . chr($y);
|
||||||
if($subChunk->isEmptyAuthoritative()){
|
if($subChunk->isEmptyAuthoritative()){
|
||||||
@ -707,7 +699,7 @@ class LevelDB extends BaseWorldProvider implements WritableWorldProvider{
|
|||||||
$layers = $subChunk->getBlockLayers();
|
$layers = $subChunk->getBlockLayers();
|
||||||
$subStream->putByte(count($layers));
|
$subStream->putByte(count($layers));
|
||||||
foreach($layers as $blocks){
|
foreach($layers as $blocks){
|
||||||
self::serializeBlockPalette($subStream, $blocks, $blockStateSerializer);
|
$this->serializeBlockPalette($subStream, $blocks);
|
||||||
}
|
}
|
||||||
|
|
||||||
$write->put($key, $subStream->getBuffer());
|
$write->put($key, $subStream->getBuffer());
|
||||||
|
Loading…
x
Reference in New Issue
Block a user