mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-04-22 08:44:01 +00:00
RuntimeBlockMapping is now a singleton instead of static class
this prepares for a fully dynamic block mapper, as well as allowing a small performance improvement to chunk encoding by eliding the constant lazy-init checks.
This commit is contained in:
parent
f3fed60d57
commit
aa1828aa98
@ -111,7 +111,7 @@ class Block{
|
||||
* @internal
|
||||
*/
|
||||
public function getRuntimeId() : int{
|
||||
return RuntimeBlockMapping::toStaticRuntimeId($this->getId(), $this->getMeta());
|
||||
return RuntimeBlockMapping::getInstance()->toStaticRuntimeId($this->getId(), $this->getMeta());
|
||||
}
|
||||
|
||||
public function getMeta() : int{
|
||||
|
@ -289,7 +289,7 @@ class StartGamePacket extends DataPacket implements ClientboundPacket{
|
||||
if($this->blockTable === null){
|
||||
if(self::$blockTableCache === null){
|
||||
//this is a really nasty hack, but it'll do for now
|
||||
self::$blockTableCache = (new NetworkNbtSerializer())->write(new TreeRoot(new ListTag(RuntimeBlockMapping::getBedrockKnownStates())));
|
||||
self::$blockTableCache = (new NetworkNbtSerializer())->write(new TreeRoot(new ListTag(RuntimeBlockMapping::getInstance()->getBedrockKnownStates())));
|
||||
}
|
||||
$out->put(self::$blockTableCache);
|
||||
}else{
|
||||
|
@ -39,19 +39,25 @@ use function shuffle;
|
||||
* @internal
|
||||
*/
|
||||
final class RuntimeBlockMapping{
|
||||
/** @var self|null */
|
||||
private static $instance = null;
|
||||
|
||||
/** @var int[] */
|
||||
private static $legacyToRuntimeMap = [];
|
||||
/** @var int[] */
|
||||
private static $runtimeToLegacyMap = [];
|
||||
/** @var CompoundTag[]|null */
|
||||
private static $bedrockKnownStates = null;
|
||||
public static function getInstance() : self{
|
||||
if(self::$instance === null){
|
||||
self::$instance = new self;
|
||||
}
|
||||
|
||||
private function __construct(){
|
||||
//NOOP
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
public static function init() : void{
|
||||
/** @var int[] */
|
||||
private $legacyToRuntimeMap = [];
|
||||
/** @var int[] */
|
||||
private $runtimeToLegacyMap = [];
|
||||
/** @var CompoundTag[]|null */
|
||||
private $bedrockKnownStates = null;
|
||||
|
||||
private function __construct(){
|
||||
$tag = (new NetworkNbtSerializer())->read(file_get_contents(\pocketmine\RESOURCE_PATH . "vanilla/required_block_states.nbt"))->getTag();
|
||||
if(!($tag instanceof ListTag) or $tag->getTagType() !== NBT::TAG_Compound){ //this is a little redundant currently, but good for auto complete and makes phpstan happy
|
||||
throw new \RuntimeException("Invalid blockstates table, expected TAG_List<TAG_Compound> root");
|
||||
@ -59,12 +65,12 @@ final class RuntimeBlockMapping{
|
||||
|
||||
/** @var CompoundTag[] $list */
|
||||
$list = $tag->getValue();
|
||||
self::$bedrockKnownStates = self::randomizeTable($list);
|
||||
$this->bedrockKnownStates = self::randomizeTable($list);
|
||||
|
||||
self::setupLegacyMappings();
|
||||
$this->setupLegacyMappings();
|
||||
}
|
||||
|
||||
private static function setupLegacyMappings() : void{
|
||||
private function setupLegacyMappings() : void{
|
||||
$legacyIdMap = json_decode(file_get_contents(\pocketmine\RESOURCE_PATH . "vanilla/block_id_map.json"), true);
|
||||
$legacyStateMap = (new NetworkNbtSerializer())->read(file_get_contents(\pocketmine\RESOURCE_PATH . "vanilla/r12_to_current_block_map.nbt"))->getTag();
|
||||
if(!($legacyStateMap instanceof ListTag) or $legacyStateMap->getTagType() !== NBT::TAG_Compound){
|
||||
@ -75,7 +81,7 @@ final class RuntimeBlockMapping{
|
||||
* @var int[][] $idToStatesMap string id -> int[] list of candidate state indices
|
||||
*/
|
||||
$idToStatesMap = [];
|
||||
foreach(self::$bedrockKnownStates as $k => $state){
|
||||
foreach($this->bedrockKnownStates as $k => $state){
|
||||
$idToStatesMap[$state->getCompoundTag("block")->getString("name")][] = $k;
|
||||
}
|
||||
/** @var CompoundTag $pair */
|
||||
@ -93,9 +99,9 @@ final class RuntimeBlockMapping{
|
||||
throw new \RuntimeException("Mapped new state does not appear in network table");
|
||||
}
|
||||
foreach($idToStatesMap[$mappedName] as $k){
|
||||
$networkState = self::$bedrockKnownStates[$k];
|
||||
$networkState = $this->bedrockKnownStates[$k];
|
||||
if($mappedState->equals($networkState->getCompoundTag("block"))){
|
||||
self::registerMapping($k, $id, $data);
|
||||
$this->registerMapping($k, $id, $data);
|
||||
continue 2;
|
||||
}
|
||||
}
|
||||
@ -103,12 +109,6 @@ final class RuntimeBlockMapping{
|
||||
}
|
||||
}
|
||||
|
||||
private static function lazyInit() : void{
|
||||
if(self::$bedrockKnownStates === null){
|
||||
self::init();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Randomizes the order of the runtimeID table to prevent plugins relying on them.
|
||||
* Plugins shouldn't use this stuff anyway, but plugin devs have an irritating habit of ignoring what they
|
||||
@ -126,35 +126,32 @@ final class RuntimeBlockMapping{
|
||||
return $table;
|
||||
}
|
||||
|
||||
public static function toStaticRuntimeId(int $id, int $meta = 0) : int{
|
||||
self::lazyInit();
|
||||
public function toStaticRuntimeId(int $id, int $meta = 0) : int{
|
||||
/*
|
||||
* try id+meta first
|
||||
* if not found, try id+0 (strip meta)
|
||||
* if still not found, return update! block
|
||||
*/
|
||||
return self::$legacyToRuntimeMap[($id << 4) | $meta] ?? self::$legacyToRuntimeMap[$id << 4] ?? self::$legacyToRuntimeMap[BlockLegacyIds::INFO_UPDATE << 4];
|
||||
return $this->legacyToRuntimeMap[($id << 4) | $meta] ?? $this->legacyToRuntimeMap[$id << 4] ?? $this->legacyToRuntimeMap[BlockLegacyIds::INFO_UPDATE << 4];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int[] [id, meta]
|
||||
*/
|
||||
public static function fromStaticRuntimeId(int $runtimeId) : array{
|
||||
self::lazyInit();
|
||||
$v = self::$runtimeToLegacyMap[$runtimeId];
|
||||
public function fromStaticRuntimeId(int $runtimeId) : array{
|
||||
$v = $this->runtimeToLegacyMap[$runtimeId];
|
||||
return [$v >> 4, $v & 0xf];
|
||||
}
|
||||
|
||||
private static function registerMapping(int $staticRuntimeId, int $legacyId, int $legacyMeta) : void{
|
||||
self::$legacyToRuntimeMap[($legacyId << 4) | $legacyMeta] = $staticRuntimeId;
|
||||
self::$runtimeToLegacyMap[$staticRuntimeId] = ($legacyId << 4) | $legacyMeta;
|
||||
private function registerMapping(int $staticRuntimeId, int $legacyId, int $legacyMeta) : void{
|
||||
$this->legacyToRuntimeMap[($legacyId << 4) | $legacyMeta] = $staticRuntimeId;
|
||||
$this->runtimeToLegacyMap[$staticRuntimeId] = ($legacyId << 4) | $legacyMeta;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return CompoundTag[]
|
||||
*/
|
||||
public static function getBedrockKnownStates() : array{
|
||||
self::lazyInit();
|
||||
return self::$bedrockKnownStates;
|
||||
public function getBedrockKnownStates() : array{
|
||||
return $this->bedrockKnownStates;
|
||||
}
|
||||
}
|
||||
|
@ -53,6 +53,7 @@ final class ChunkSerializer{
|
||||
public static function serialize(Chunk $chunk, ?string $tiles = null) : string{
|
||||
$stream = new NetworkBinaryStream();
|
||||
$subChunkCount = self::getSubChunkCount($chunk);
|
||||
$blockMapper = RuntimeBlockMapping::getInstance();
|
||||
for($y = 0; $y < $subChunkCount; ++$y){
|
||||
$layers = $chunk->getSubChunk($y)->getBlockLayers();
|
||||
$stream->putByte(8); //version
|
||||
@ -69,7 +70,7 @@ final class ChunkSerializer{
|
||||
//zigzag and just shift directly.
|
||||
$stream->putUnsignedVarInt(count($palette) << 1); //yes, this is intentionally zigzag
|
||||
foreach($palette as $p){
|
||||
$stream->putUnsignedVarInt(RuntimeBlockMapping::toStaticRuntimeId($p >> 4, $p & 0xf) << 1);
|
||||
$stream->putUnsignedVarInt($blockMapper->toStaticRuntimeId($p >> 4, $p & 0xf) << 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user