From 32574118ea05fa038f5f2e110b41bebd27c5037b Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Fri, 6 Jul 2018 13:28:33 +0100 Subject: [PATCH] Implemented Mending enchantment (#2257) --- src/pocketmine/entity/Human.php | 37 +++++++++++++++++++ .../entity/object/ExperienceOrb.php | 5 +-- .../item/enchantment/Enchantment.php | 2 + 3 files changed, 40 insertions(+), 4 deletions(-) diff --git a/src/pocketmine/entity/Human.php b/src/pocketmine/entity/Human.php index a58d64ac1..1a84e6c1e 100644 --- a/src/pocketmine/entity/Human.php +++ b/src/pocketmine/entity/Human.php @@ -34,6 +34,7 @@ use pocketmine\inventory\EntityInventoryEventProcessor; use pocketmine\inventory\InventoryHolder; use pocketmine\inventory\PlayerInventory; use pocketmine\item\Consumable; +use pocketmine\item\Durable; use pocketmine\item\enchantment\Enchantment; use pocketmine\item\FoodSource; use pocketmine\item\Item; @@ -516,6 +517,42 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{ return $this->xpCooldown === 0; } + public function onPickupXp(int $xpValue) : void{ + static $mainHandIndex = -1; + + //TODO: replace this with a more generic equipment getting/setting interface + /** @var Durable[] $equipment */ + $equipment = []; + + if(($item = $this->inventory->getItemInHand()) instanceof Durable and $item->hasEnchantment(Enchantment::MENDING)){ + $equipment[$mainHandIndex] = $item; + } + //TODO: check offhand + foreach($this->armorInventory->getContents() as $k => $item){ + if($item instanceof Durable and $item->hasEnchantment(Enchantment::MENDING)){ + $equipment[$k] = $item; + } + } + + if(!empty($equipment)){ + $repairItem = $equipment[$k = array_rand($equipment)]; + if($repairItem->getDamage() > 0){ + $repairAmount = min($repairItem->getDamage(), $xpValue * 2); + $repairItem->setDamage($repairItem->getDamage() - $repairAmount); + $xpValue -= (int) ceil($repairAmount / 2); + + if($k === $mainHandIndex){ + $this->inventory->setItemInHand($repairItem); + }else{ + $this->armorInventory->setItem($k, $repairItem); + } + } + } + + $this->addXp($xpValue); //this will still get fired even if the value is 0 due to mending, to play sounds + $this->resetXpCooldown(); + } + /** * Sets the duration in ticks until the human can pick up another XP orb. * diff --git a/src/pocketmine/entity/object/ExperienceOrb.php b/src/pocketmine/entity/object/ExperienceOrb.php index 729f9509c..93cd69256 100644 --- a/src/pocketmine/entity/object/ExperienceOrb.php +++ b/src/pocketmine/entity/object/ExperienceOrb.php @@ -200,10 +200,7 @@ class ExperienceOrb extends Entity{ if($currentTarget->canPickupXp() and $this->boundingBox->intersectsWith($currentTarget->getBoundingBox())){ $this->flagForDespawn(); - $currentTarget->addXp($this->getXpValue()); - $currentTarget->resetXpCooldown(); - - //TODO: check Mending enchantment + $currentTarget->onPickupXp($this->getXpValue()); } } diff --git a/src/pocketmine/item/enchantment/Enchantment.php b/src/pocketmine/item/enchantment/Enchantment.php index 8deb17f40..7531cecfb 100644 --- a/src/pocketmine/item/enchantment/Enchantment.php +++ b/src/pocketmine/item/enchantment/Enchantment.php @@ -132,6 +132,8 @@ class Enchantment{ self::registerEnchantment(new Enchantment(self::FLAME, "%enchantment.arrowFire", self::RARITY_RARE, self::SLOT_BOW, self::SLOT_NONE, 1)); self::registerEnchantment(new Enchantment(self::INFINITY, "%enchantment.arrowInfinite", self::RARITY_MYTHIC, self::SLOT_BOW, self::SLOT_NONE, 1)); + self::registerEnchantment(new Enchantment(self::MENDING, "%enchantment.mending", self::RARITY_RARE, self::SLOT_NONE, self::SLOT_ALL, 1)); + self::registerEnchantment(new Enchantment(self::VANISHING, "%enchantment.curse.vanishing", self::RARITY_MYTHIC, self::SLOT_NONE, self::SLOT_ALL, 1)); }