Fixed durability handling (ish)

This commit is contained in:
Dylan K. Taylor 2022-06-29 15:17:16 +01:00
parent dd63681f94
commit 2cb722b674
No known key found for this signature in database
GPG Key ID: 8927471A91CAFD3D
3 changed files with 20 additions and 28 deletions

View File

@ -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

View File

@ -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);
}
}

View File

@ -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;
}