From 2cb722b674ca2c88d6b30ff85ae1e0bfd3abc846 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Wed, 29 Jun 2022 15:17:16 +0100 Subject: [PATCH] Fixed durability handling (ish) --- src/data/bedrock/item/ItemDeserializer.php | 14 ++++++++++++- src/item/Durable.php | 11 +++++++---- src/network/mcpe/convert/TypeConverter.php | 23 ---------------------- 3 files changed, 20 insertions(+), 28 deletions(-) diff --git a/src/data/bedrock/item/ItemDeserializer.php b/src/data/bedrock/item/ItemDeserializer.php index 95db05d91..b48da118d 100644 --- a/src/data/bedrock/item/ItemDeserializer.php +++ b/src/data/bedrock/item/ItemDeserializer.php @@ -36,9 +36,12 @@ use pocketmine\data\bedrock\EntityLegacyIds; use pocketmine\data\bedrock\item\ItemTypeIds as Ids; use pocketmine\data\bedrock\item\SavedItemData as Data; use pocketmine\data\bedrock\PotionTypeIdMap; +use pocketmine\item\Durable; use pocketmine\item\Item; use pocketmine\item\VanillaItems as Items; +use pocketmine\nbt\NbtException; use pocketmine\utils\AssumptionFailedError; +use function min; final class ItemDeserializer{ /** @@ -91,7 +94,16 @@ final class ItemDeserializer{ $itemStack->setCount($data->getCount()); if(($tagTag = $data->getTypeData()->getTag()) !== null){ - $itemStack->setNamedTag(clone $tagTag); + try{ + $itemStack->setNamedTag(clone $tagTag); + }catch(NbtException $e){ + throw new ItemTypeDeserializeException("Invalid item saved NBT: " . $e->getMessage(), 0, $e); + } + } + + //TODO: this hack is necessary to get legacy tools working - we need a better way to handle this kind of stuff + if($itemStack instanceof Durable && $itemStack->getDamage() === 0 && ($damage = $data->getTypeData()->getMeta()) > 0){ + $itemStack->setDamage(min($damage, $itemStack->getMaxDurability())); } //TODO: canDestroy, canPlaceOn, wasPickedUp are currently unused diff --git a/src/item/Durable.php b/src/item/Durable.php index 0e1f202dc..a2300576b 100644 --- a/src/item/Durable.php +++ b/src/item/Durable.php @@ -32,10 +32,6 @@ abstract class Durable extends Item{ protected int $damage = 0; private bool $unbreakable = false; - public function getMeta() : int{ - return $this->damage; - } - /** * Returns whether this item will take damage when used. */ @@ -124,10 +120,17 @@ abstract class Durable extends Item{ protected function deserializeCompoundTag(CompoundTag $tag) : void{ parent::deserializeCompoundTag($tag); $this->unbreakable = $tag->getByte("Unbreakable", 0) !== 0; + + $damage = $tag->getInt("Damage", $this->damage); + if($damage !== $this->damage && $damage >= 0 && $damage <= $this->getMaxDurability()){ + //TODO: out-of-bounds damage should be an error + $this->setDamage($damage); + } } protected function serializeCompoundTag(CompoundTag $tag) : void{ parent::serializeCompoundTag($tag); $this->unbreakable ? $tag->setByte("Unbreakable", 1) : $tag->removeTag("Unbreakable"); + $tag->setInt("Damage", $this->damage); } } diff --git a/src/network/mcpe/convert/TypeConverter.php b/src/network/mcpe/convert/TypeConverter.php index ec699e62a..653ffed75 100644 --- a/src/network/mcpe/convert/TypeConverter.php +++ b/src/network/mcpe/convert/TypeConverter.php @@ -38,7 +38,6 @@ use pocketmine\inventory\transaction\action\DestroyItemAction; use pocketmine\inventory\transaction\action\DropItemAction; use pocketmine\inventory\transaction\action\InventoryAction; use pocketmine\inventory\transaction\action\SlotChangeAction; -use pocketmine\item\Durable; use pocketmine\item\Item; use pocketmine\item\ItemFactory; use pocketmine\item\ItemIds; @@ -62,8 +61,6 @@ use function get_class; class TypeConverter{ use SingletonTrait; - private const DAMAGE_TAG = "Damage"; //TAG_Int - private const DAMAGE_TAG_CONFLICT_RESOLUTION = "___Damage_ProtocolCollisionResolution___"; private const PM_ID_TAG = "___Id___"; private const PM_META_TAG = "___Meta___"; @@ -177,18 +174,6 @@ class TypeConverter{ $nbt->setInt(self::PM_META_TAG, $itemStack->getMeta()); }else{ [$id, $meta, $blockRuntimeId] = $idMeta; - - if($itemStack instanceof Durable && $itemStack->getDamage() > 0){ - if($nbt !== null){ - if(($existing = $nbt->getTag(self::DAMAGE_TAG)) !== null){ - $nbt->removeTag(self::DAMAGE_TAG); - $nbt->setTag(self::DAMAGE_TAG_CONFLICT_RESOLUTION, $existing); - } - }else{ - $nbt = new CompoundTag(); - } - $nbt->setInt(self::DAMAGE_TAG, $itemStack->getDamage()); - } } return new ItemStack( @@ -228,14 +213,6 @@ class TypeConverter{ $compound->removeTag(self::PM_META_TAG); } } - if(($damageTag = $compound->getTag(self::DAMAGE_TAG)) instanceof IntTag){ - $meta = $damageTag->getValue(); - $compound->removeTag(self::DAMAGE_TAG); - if(($conflicted = $compound->getTag(self::DAMAGE_TAG_CONFLICT_RESOLUTION)) !== null){ - $compound->removeTag(self::DAMAGE_TAG_CONFLICT_RESOLUTION); - $compound->setTag(self::DAMAGE_TAG, $conflicted); - } - } if($compound->count() === 0){ $compound = null; }