Avoid bogus assumptions about block and item NBT on tiles

This commit is contained in:
Dylan K. Taylor 2022-07-17 21:23:41 +01:00
parent 4f2f9b4352
commit 012b668537
No known key found for this signature in database
GPG Key ID: 8927471A91CAFD3D
6 changed files with 31 additions and 4 deletions

View File

@ -31,6 +31,7 @@ use pocketmine\data\SavedDataLoadingException;
use pocketmine\nbt\tag\CompoundTag;
use pocketmine\nbt\tag\IntTag;
use pocketmine\nbt\tag\ShortTag;
use pocketmine\network\mcpe\convert\RuntimeBlockMapping;
use pocketmine\world\format\io\GlobalBlockStateHandlers;
/**
@ -88,7 +89,7 @@ class FlowerPot extends Spawnable{
protected function addAdditionalSpawnData(CompoundTag $nbt) : void{
if($this->plant !== null){
$nbt->setTag(self::TAG_PLANT_BLOCK, GlobalBlockStateHandlers::getSerializer()->serialize($this->plant->getStateId())->toNbt());
$nbt->setTag(self::TAG_PLANT_BLOCK, RuntimeBlockMapping::getInstance()->toStateData($this->plant->getStateId())->toNbt());
}
}
}

View File

@ -27,6 +27,7 @@ use pocketmine\item\Item;
use pocketmine\item\VanillaItems;
use pocketmine\math\Vector3;
use pocketmine\nbt\tag\CompoundTag;
use pocketmine\network\mcpe\convert\ItemTranslator;
use pocketmine\world\World;
/**
@ -99,7 +100,7 @@ class ItemFrame extends Spawnable{
$nbt->setFloat(self::TAG_ITEM_DROP_CHANCE, $this->itemDropChance);
$nbt->setByte(self::TAG_ITEM_ROTATION, $this->itemRotation);
if(!$this->item->isNull()){
$nbt->setTag(self::TAG_ITEM, $this->item->nbtSerialize());
$nbt->setTag(self::TAG_ITEM, ItemTranslator::getInstance()->toNetworkNbt($this->item));
}
}
}

View File

@ -26,6 +26,7 @@ namespace pocketmine\block\tile;
use pocketmine\item\Item;
use pocketmine\item\Record;
use pocketmine\nbt\tag\CompoundTag;
use pocketmine\network\mcpe\convert\ItemTranslator;
class Jukebox extends Spawnable{
private const TAG_RECORD = "RecordItem"; //Item CompoundTag
@ -58,7 +59,7 @@ class Jukebox extends Spawnable{
protected function addAdditionalSpawnData(CompoundTag $nbt) : void{
//this is needed for the note particles to show on the client side
if($this->record !== null){
$nbt->setTag(self::TAG_RECORD, $this->record->nbtSerialize());
$nbt->setTag(self::TAG_RECORD, ItemTranslator::getInstance()->toNetworkNbt($this->record));
}
}
}

View File

@ -26,6 +26,7 @@ namespace pocketmine\block\tile;
use pocketmine\item\Item;
use pocketmine\item\WritableBookBase;
use pocketmine\nbt\tag\CompoundTag;
use pocketmine\network\mcpe\convert\ItemTranslator;
use function count;
/**
@ -80,7 +81,7 @@ class Lectern extends Spawnable{
$nbt->setByte(self::TAG_HAS_BOOK, $this->book !== null ? 1 : 0);
$nbt->setInt(self::TAG_PAGE, $this->viewedPage);
if($this->book !== null){
$nbt->setTag(self::TAG_BOOK, $this->book->nbtSerialize());
$nbt->setTag(self::TAG_BOOK, ItemTranslator::getInstance()->toNetworkNbt($this->book));
$nbt->setInt(self::TAG_TOTAL_PAGES, count($this->book->getPages()));
}
}

View File

@ -28,6 +28,7 @@ use pocketmine\data\bedrock\item\ItemSerializer;
use pocketmine\data\bedrock\item\ItemTypeDeserializeException;
use pocketmine\data\bedrock\item\ItemTypeSerializeException;
use pocketmine\data\bedrock\item\SavedItemData;
use pocketmine\data\bedrock\item\SavedItemStackData;
use pocketmine\item\Item;
use pocketmine\network\mcpe\protocol\serializer\ItemTypeDictionary;
use pocketmine\utils\AssumptionFailedError;
@ -96,6 +97,16 @@ final class ItemTranslator{
return [$numericId, $itemData->getMeta(), $blockRuntimeId];
}
/**
* @throws ItemTypeSerializeException
*/
public function toNetworkNbt(Item $item) : SavedItemStackData{
//TODO: this relies on the assumption that network item NBT is the same as disk item NBT, which may not always
//be true - if we stick on an older world version while updating network version, this could be a problem (and
//may be a problem for multi version implementations)
return $this->itemSerializer->serializeStack($item);
}
/**
* @throws TypeConversionException
*/

View File

@ -94,6 +94,18 @@ final class RuntimeBlockMapping{
return $this->networkIdCache[$internalStateId] = $networkId;
}
/**
* Looks up the network state data associated with the given internal state ID.
*/
public function toStateData(int $internalStateId) : BlockStateData{
//we don't directly use the blockstate serializer here - we can't assume that the network blockstate NBT is the
//same as the disk blockstate NBT, in case we decide to have different world version than network version (or in
//case someone wants to implement multi version).
$networkRuntimeId = $this->toRuntimeId($internalStateId);
return $this->blockStateDictionary->getDataFromStateId($networkRuntimeId) ?? throw new AssumptionFailedError("We just looked up this state ID, so it must exist");
}
public function getBlockStateDictionary() : BlockStateDictionary{ return $this->blockStateDictionary; }
public function getFallbackStateData() : BlockStateData{ return $this->fallbackStateData; }