another vague commit restructuring stuff

This commit is contained in:
Dylan K. Taylor 2022-02-07 02:41:50 +00:00
parent 4e6fb4b12c
commit 1b48603d07
No known key found for this signature in database
GPG Key ID: 8927471A91CAFD3D
8 changed files with 254 additions and 12 deletions

View File

@ -0,0 +1,40 @@
<?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\data\bedrock\blockstate;
/**
* Implementors of this interface decide how a block should be deserialized and represented at runtime. This is used by
* world providers when decoding blockstates into block IDs.
*
* @phpstan-type BlockStateId int
*/
interface BlockStateDeserializer{
/**
* Deserializes blockstate NBT into an implementation-defined blockstate ID, for runtime paletted storage.
*
* @phpstan-return BlockStateId
* @throws BlockStateDeserializeException
*/
public function deserialize(BlockStateData $stateData) : int;
}

View File

@ -0,0 +1,40 @@
<?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\data\bedrock\blockstate;
/**
* Implementors of this interface decide how blockstate IDs will be represented as NBT.
*
* @phpstan-type BlockStateId int
*/
interface BlockStateSerializer{
/**
* Serializes an implementation-defined blockstate ID to NBT for storage.
*
* @phpstan-param BlockStateId $stateId
* @throws BlockStateSerializeException
*/
public function serialize(int $stateId) : BlockStateData;
}

View File

@ -0,0 +1,49 @@
<?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\data\bedrock\blockstate;
final class CachingBlockStateDeserializer implements BlockStateDeserializer{
/**
* @var int[]
* @phpstan-var array<string, int>
*/
private array $simpleCache = [];
public function __construct(
private BlockStateDeserializer $realDeserializer
){}
public function deserialize(BlockStateData $stateData) : int{
if($stateData->getStates()->count() === 0){
//if a block has zero properties, we can keep a map of string ID -> internal blockstate ID
return $this->simpleCache[$stateData->getName()] ??= $this->realDeserializer->deserialize($stateData);
}
//we can't cache blocks that have properties - go ahead and deserialize the slow way
return $this->realDeserializer->deserialize($stateData);
}
public function getRealDeserializer() : BlockStateDeserializer{ return $this->realDeserializer; }
}

View File

@ -0,0 +1,43 @@
<?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\data\bedrock\blockstate;
final class CachingBlockStateSerializer implements BlockStateSerializer{
/**
* @var BlockStateData[]
* @phpstan-var array<int, BlockStateData>
*/
private array $cache = [];
public function __construct(
private BlockStateSerializer $realSerializer
){}
public function serialize(int $stateId) : BlockStateData{
return $this->cache[$stateId] ??= $this->realSerializer->serialize($stateId);
}
public function getRealSerializer() : BlockStateSerializer{ return $this->realSerializer; }
}

View File

@ -0,0 +1,40 @@
<?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\data\bedrock\blockstate;
use pocketmine\data\bedrock\blockstate\upgrade\BlockStateUpgrader;
final class UpgradingBlockStateDeserializer implements BlockStateDeserializer{
public function __construct(
private BlockStateUpgrader $blockStateUpgrader,
private BlockStateDeserializer $realDeserializer
){}
public function deserialize(BlockStateData $stateData) : int{
return $this->realDeserializer->deserialize($this->blockStateUpgrader->upgrade($stateData));
}
public function getRealDeserializer() : BlockStateDeserializer{ return $this->realDeserializer; }
}

View File

@ -32,6 +32,7 @@ use pocketmine\block\Bed;
use pocketmine\block\Beetroot; use pocketmine\block\Beetroot;
use pocketmine\block\Bell; use pocketmine\block\Bell;
use pocketmine\block\Block; use pocketmine\block\Block;
use pocketmine\block\BlockFactory;
use pocketmine\block\BlockLegacyMetadata; use pocketmine\block\BlockLegacyMetadata;
use pocketmine\block\BoneBlock; use pocketmine\block\BoneBlock;
use pocketmine\block\BrewingStand; use pocketmine\block\BrewingStand;
@ -140,6 +141,7 @@ use pocketmine\block\Wool;
use pocketmine\data\bedrock\blockstate\BlockStateData; use pocketmine\data\bedrock\blockstate\BlockStateData;
use pocketmine\data\bedrock\blockstate\BlockStateNames as StateNames; use pocketmine\data\bedrock\blockstate\BlockStateNames as StateNames;
use pocketmine\data\bedrock\blockstate\BlockStateSerializeException; use pocketmine\data\bedrock\blockstate\BlockStateSerializeException;
use pocketmine\data\bedrock\blockstate\BlockStateSerializer;
use pocketmine\data\bedrock\blockstate\BlockStateStringValues as StringValues; use pocketmine\data\bedrock\blockstate\BlockStateStringValues as StringValues;
use pocketmine\data\bedrock\blockstate\BlockTypeNames as Ids; use pocketmine\data\bedrock\blockstate\BlockTypeNames as Ids;
use pocketmine\data\bedrock\blockstate\convert\BlockStateSerializerHelper as Helper; use pocketmine\data\bedrock\blockstate\convert\BlockStateSerializerHelper as Helper;
@ -150,7 +152,7 @@ use pocketmine\utils\AssumptionFailedError;
use function class_parents; use function class_parents;
use function get_class; use function get_class;
final class BlockStateSerializer{ final class BlockObjectToBlockStateSerializer implements BlockStateSerializer{
/** /**
* These callables actually accept Block, but for the sake of type completeness, it has to be never, since we can't * These callables actually accept Block, but for the sake of type completeness, it has to be never, since we can't
* describe the bottom type of a type hierarchy only containing Block. * describe the bottom type of a type hierarchy only containing Block.
@ -164,6 +166,11 @@ final class BlockStateSerializer{
$this->registerSerializers(); $this->registerSerializers();
} }
public function serialize(int $stateId) : BlockStateData{
//TODO: singleton usage not ideal
return $this->serializeBlock(BlockFactory::getInstance()->fromFullBlock($stateId));
}
/** /**
* @phpstan-template TBlockType of Block * @phpstan-template TBlockType of Block
* @phpstan-param TBlockType $block * @phpstan-param TBlockType $block
@ -181,7 +188,7 @@ final class BlockStateSerializer{
* @phpstan-template TBlockType of Block * @phpstan-template TBlockType of Block
* @phpstan-param TBlockType $blockState * @phpstan-param TBlockType $blockState
*/ */
public function serialize(Block $blockState) : BlockStateData{ public function serializeBlock(Block $blockState) : BlockStateData{
$typeId = $blockState->getTypeId(); $typeId = $blockState->getTypeId();
$locatedSerializer = $this->serializers[$typeId][get_class($blockState)] ?? null; $locatedSerializer = $this->serializers[$typeId][get_class($blockState)] ?? null;

View File

@ -34,6 +34,7 @@ use pocketmine\block\utils\SlabType;
use pocketmine\block\VanillaBlocks as Blocks; use pocketmine\block\VanillaBlocks as Blocks;
use pocketmine\data\bedrock\blockstate\BlockStateData; use pocketmine\data\bedrock\blockstate\BlockStateData;
use pocketmine\data\bedrock\blockstate\BlockStateDeserializeException; use pocketmine\data\bedrock\blockstate\BlockStateDeserializeException;
use pocketmine\data\bedrock\blockstate\BlockStateDeserializer;
use pocketmine\data\bedrock\blockstate\BlockStateNames as StateNames; use pocketmine\data\bedrock\blockstate\BlockStateNames as StateNames;
use pocketmine\data\bedrock\blockstate\BlockStateStringValues as StringValues; use pocketmine\data\bedrock\blockstate\BlockStateStringValues as StringValues;
use pocketmine\data\bedrock\blockstate\BlockTypeNames as Ids; use pocketmine\data\bedrock\blockstate\BlockTypeNames as Ids;
@ -44,7 +45,7 @@ use pocketmine\math\Facing;
use function array_key_exists; use function array_key_exists;
use function min; use function min;
final class BlockStateDeserializer{ final class BlockStateToBlockObjectDeserializer implements BlockStateDeserializer{
/** /**
* @var \Closure[] * @var \Closure[]
@ -52,6 +53,14 @@ final class BlockStateDeserializer{
*/ */
private array $deserializeFuncs = []; private array $deserializeFuncs = [];
public function __construct(){
$this->registerDeserializers();
}
public function deserialize(BlockStateData $stateData) : int{
return $this->deserializeBlock($stateData)->getFullId();
}
/** @phpstan-param \Closure(Reader) : Block $c */ /** @phpstan-param \Closure(Reader) : Block $c */
private function map(string $id, \Closure $c) : void{ private function map(string $id, \Closure $c) : void{
if(array_key_exists($id, $this->deserializeFuncs)){ if(array_key_exists($id, $this->deserializeFuncs)){
@ -60,7 +69,7 @@ final class BlockStateDeserializer{
$this->deserializeFuncs[$id] = $c; $this->deserializeFuncs[$id] = $c;
} }
public function __construct(){ private function registerDeserializers() : void{
$this->map(Ids::ACACIA_BUTTON, fn(Reader $in) => Helper::decodeButton(Blocks::ACACIA_BUTTON(), $in)); $this->map(Ids::ACACIA_BUTTON, fn(Reader $in) => Helper::decodeButton(Blocks::ACACIA_BUTTON(), $in));
$this->map(Ids::ACACIA_DOOR, fn(Reader $in) => Helper::decodeDoor(Blocks::ACACIA_DOOR(), $in)); $this->map(Ids::ACACIA_DOOR, fn(Reader $in) => Helper::decodeDoor(Blocks::ACACIA_DOOR(), $in));
$this->map(Ids::ACACIA_FENCE_GATE, fn(Reader $in) => Helper::decodeFenceGate(Blocks::ACACIA_FENCE_GATE(), $in)); $this->map(Ids::ACACIA_FENCE_GATE, fn(Reader $in) => Helper::decodeFenceGate(Blocks::ACACIA_FENCE_GATE(), $in));
@ -2502,7 +2511,7 @@ final class BlockStateDeserializer{
} }
/** @throws BlockStateDeserializeException */ /** @throws BlockStateDeserializeException */
public function deserialize(BlockStateData $blockStateData) : Block{ public function deserializeBlock(BlockStateData $blockStateData) : Block{
$id = $blockStateData->getName(); $id = $blockStateData->getName();
if(!array_key_exists($id, $this->deserializeFuncs)){ if(!array_key_exists($id, $this->deserializeFuncs)){
throw new BlockStateDeserializeException("Unknown block ID \"$id\""); throw new BlockStateDeserializeException("Unknown block ID \"$id\"");

View File

@ -24,27 +24,41 @@ declare(strict_types=1);
namespace pocketmine\data\bedrock\blockstate\upgrade; namespace pocketmine\data\bedrock\blockstate\upgrade;
use pocketmine\data\bedrock\blockstate\BlockStateData; use pocketmine\data\bedrock\blockstate\BlockStateData;
use pocketmine\data\bedrock\LegacyBlockIdToStringIdMap;
use pocketmine\errorhandler\ErrorToExceptionHandler;
use pocketmine\network\mcpe\protocol\serializer\NetworkNbtSerializer; use pocketmine\network\mcpe\protocol\serializer\NetworkNbtSerializer;
use pocketmine\utils\BinaryStream; use pocketmine\utils\BinaryStream;
use pocketmine\utils\SingletonTrait;
use Webmozart\PathUtil\Path;
use function file_get_contents;
use const pocketmine\BEDROCK_DATA_PATH;
/** /**
* Interface to an upgrade schema describing how to convert 1.12 id+meta into modern blockstate NBT. * Handles translating legacy 1.12 block ID/meta into modern blockstates.
*/ */
final class LegacyIdMetaToBlockStateDataMap{ final class LegacyBlockStateMapper{
/** /**
* @param BlockStateData[][] $mappingTable * @param BlockStateData[][] $mappingTable
* @phpstan-param array<string, array<int, BlockStateData>> $mappingTable * @phpstan-param array<string, array<int, BlockStateData>> $mappingTable
*/ */
public function __construct( public function __construct(
private array $mappingTable private array $mappingTable,
private LegacyBlockIdToStringIdMap $legacyNumericIdMap
){} ){}
public function getDataFromLegacyIdMeta(string $id, int $meta) : ?BlockStateData{ public function fromStringIdMeta(string $id, int $meta) : ?BlockStateData{
return $this->mappingTable[$id][$meta] ?? null; return $this->mappingTable[$id][$meta] ?? null;
} }
public static function loadFromString(string $data) : self{ public function fromIntIdMeta(int $id, int $meta) : ?BlockStateData{
$stringId = $this->legacyNumericIdMap->legacyToString($id);
if($stringId === null){
return null;
}
return $this->fromStringIdMeta($stringId, $meta);
}
public static function loadFromString(string $data, LegacyBlockIdToStringIdMap $idMap) : self{
$mappingTable = []; $mappingTable = [];
$legacyStateMapReader = new BinaryStream($data); $legacyStateMapReader = new BinaryStream($data);
@ -59,6 +73,6 @@ final class LegacyIdMetaToBlockStateDataMap{
$mappingTable[$id][$meta] = BlockStateData::fromNbt($state); $mappingTable[$id][$meta] = BlockStateData::fromNbt($state);
} }
return new self($mappingTable); return new self($mappingTable, $idMap);
} }
} }