Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions src/block/Block.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,14 @@
use pocketmine\data\runtime\RuntimeDataWriter;
use pocketmine\entity\Entity;
use pocketmine\entity\projectile\Projectile;
use pocketmine\event\item\ItemDamageEvent;
use pocketmine\item\enchantment\AvailableEnchantmentRegistry;
use pocketmine\item\enchantment\ItemEnchantmentTagRegistry;
use pocketmine\item\enchantment\ItemEnchantmentTags;
use pocketmine\item\enchantment\VanillaEnchantments;
use pocketmine\item\Durable;
use pocketmine\item\Item;
use pocketmine\item\ItemDamageContext;
use pocketmine\item\ItemBlock;
use pocketmine\math\AxisAlignedBB;
use pocketmine\math\Facing;
Expand Down Expand Up @@ -522,6 +525,19 @@ public function onScheduledUpdate() : void{

}

protected function damageHeldItem(Durable $item, ?Player $player) : void{
$item->applyDamageWithContext(
1,
new ItemDamageContext(
ItemDamageEvent::CAUSE_BLOCK_INTERACT,
$player,
$this,
$player?->getInventory(),
$player?->getInventory()?->getHeldItemIndex()
)
);
}

/**
* Do actions when interacted by Item. Returns if it has done anything
*
Expand Down
4 changes: 2 additions & 2 deletions src/block/Campfire.php
Original file line number Diff line number Diff line change
Expand Up @@ -193,13 +193,13 @@ public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player
return true;
}elseif($item->getTypeId() === ItemTypeIds::FLINT_AND_STEEL || $item->hasEnchantment(VanillaEnchantments::FIRE_ASPECT())){
if($item instanceof Durable){
$item->applyDamage(1);
$this->damageHeldItem($item, $player);
}
$this->ignite();
return true;
}
}elseif($item instanceof Shovel){
$item->applyDamage(1);
$this->damageHeldItem($item, $player);
$this->extinguish();
return true;
}
Expand Down
2 changes: 1 addition & 1 deletion src/block/Dirt.php
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player
return true;
}

$item->applyDamage(1);
$this->damageHeldItem($item, $player);

$newBlock = $this->dirtType === DirtType::NORMAL ? VanillaBlocks::FARMLAND() : VanillaBlocks::DIRT();
$center = $this->position->add(0.5, 0.5, 0.5);
Expand Down
4 changes: 2 additions & 2 deletions src/block/Grass.php
Original file line number Diff line number Diff line change
Expand Up @@ -96,14 +96,14 @@ public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player
}
if($face !== Facing::DOWN){
if($item instanceof Hoe){
$item->applyDamage(1);
$this->damageHeldItem($item, $player);
$newBlock = VanillaBlocks::FARMLAND();
$world->addSound($this->position->add(0.5, 0.5, 0.5), new ItemUseOnBlockSound($newBlock));
$world->setBlock($this->position, $newBlock);

return true;
}elseif($item instanceof Shovel){
$item->applyDamage(1);
$this->damageHeldItem($item, $player);
$newBlock = VanillaBlocks::GRASS_PATH();
$world->addSound($this->position->add(0.5, 0.5, 0.5), new ItemUseOnBlockSound($newBlock));
$world->setBlock($this->position, $newBlock);
Expand Down
2 changes: 1 addition & 1 deletion src/block/Pumpkin.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ class Pumpkin extends Opaque{

public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
if($item instanceof Shears && in_array($face, Facing::HORIZONTAL, true)){
$item->applyDamage(1);
$this->damageHeldItem($item, $player);
$world = $this->position->getWorld();
$world->setBlock($this->position, VanillaBlocks::CARVED_PUMPKIN()->setFacing($face));
$world->dropItem($this->position->add(0.5, 0.5, 0.5), VanillaItems::PUMPKIN_SEEDS()->setCount(1));
Expand Down
2 changes: 1 addition & 1 deletion src/block/TNT.php
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player
}
if($item instanceof FlintSteel || $item->hasEnchantment(VanillaEnchantments::FIRE_ASPECT())){
if($item instanceof Durable){
$item->applyDamage(1);
$this->damageHeldItem($item, $player);
}
$this->ignite();
return true;
Expand Down
2 changes: 1 addition & 1 deletion src/block/Wood.php
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ public function getFlammability() : int{

public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
if(!$this->stripped && $item instanceof Axe){
$item->applyDamage(1);
$this->damageHeldItem($item, $player);
$this->stripped = true;
$this->position->getWorld()->setBlock($this->position, $this);
$this->position->getWorld()->addSound($this->position, new ItemUseOnBlockSound($this));
Expand Down
2 changes: 1 addition & 1 deletion src/block/utils/CandleTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player
return true;
}
if($item instanceof Durable){
$item->applyDamage(1);
$this->damageHeldItem($item, $player);
}elseif($item->getTypeId() === ItemTypeIds::FIRE_CHARGE){
$item->pop();
//TODO: not sure if this is intentional, but it's what Bedrock currently does as of 1.20.10
Expand Down
4 changes: 2 additions & 2 deletions src/block/utils/CopperTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player
$this->position->getWorld()->setBlock($this->position, $this);
//TODO: white particles are supposed to appear when removing wax
$this->position->getWorld()->addSound($this->position, new CopperWaxRemoveSound());
$item->applyDamage(1);
$this->damageHeldItem($item, $player);
return true;
}

Expand All @@ -91,7 +91,7 @@ public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player
$this->position->getWorld()->setBlock($this->position, $this);
//TODO: turquoise particles are supposed to appear when removing oxidation
$this->position->getWorld()->addSound($this->position, new ScrapeSound());
$item->applyDamage(1);
$this->damageHeldItem($item, $player);
return true;
}
}
Expand Down
24 changes: 18 additions & 6 deletions src/entity/Living.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,13 @@
use pocketmine\event\entity\EntityDamageEvent;
use pocketmine\event\entity\EntityDeathEvent;
use pocketmine\event\entity\EntityFrostWalkerEvent;
use pocketmine\event\item\ItemDamageEvent;
use pocketmine\inventory\ArmorInventory;
use pocketmine\inventory\CallbackInventoryListener;
use pocketmine\inventory\Inventory;
use pocketmine\item\Armor;
use pocketmine\item\Durable;
use pocketmine\item\ItemDamageContext;
use pocketmine\item\enchantment\Enchantment;
use pocketmine\item\enchantment\VanillaEnchantments;
use pocketmine\item\Item;
Expand Down Expand Up @@ -495,10 +497,10 @@ protected function applyPostDamageEffects(EntityDamageEvent $source) : void{
foreach($this->armorInventory->getContents() as $k => $item){
if($item instanceof Armor && ($thornsLevel = $item->getEnchantmentLevel(VanillaEnchantments::THORNS())) > 0){
if(mt_rand(0, 99) < $thornsLevel * 15){
$this->damageItem($item, 3);
$this->damageItem($item, 3, ItemDamageEvent::CAUSE_THORNS, $attacker, $this->armorInventory, $k);
$damage += ($thornsLevel > 10 ? $thornsLevel - 10 : 1 + mt_rand(0, 3));
}else{
$this->damageItem($item, 1); //thorns causes an extra +1 durability loss even if it didn't activate
$this->damageItem($item, 1, ItemDamageEvent::CAUSE_THORNS, $attacker, $this->armorInventory, $k); //thorns causes an extra +1 durability loss even if it didn't activate
}

$this->armorInventory->setItem($k, $item);
Expand All @@ -513,7 +515,7 @@ protected function applyPostDamageEffects(EntityDamageEvent $source) : void{
$helmet = $this->armorInventory->getHelmet();
if($helmet instanceof Armor){
$finalDamage = $source->getFinalDamage();
$this->damageItem($helmet, (int) round($finalDamage * 4 + Utils::getRandomFloat() * $finalDamage * 2));
$this->damageItem($helmet, (int) round($finalDamage * 4 + Utils::getRandomFloat() * $finalDamage * 2), ItemDamageEvent::CAUSE_ARMOR_DAMAGE, null, $this->armorInventory, ArmorInventory::SLOT_HEAD);
$this->armorInventory->setHelmet($helmet);
}
}
Expand All @@ -531,16 +533,26 @@ public function damageArmor(float $damage) : void{
foreach($armor as $slotId => $item){
if($item instanceof Armor){
$oldItem = clone $item;
$this->damageItem($item, $durabilityRemoved);
$this->damageItem($item, $durabilityRemoved, ItemDamageEvent::CAUSE_ARMOR_DAMAGE, null, $this->armorInventory, $slotId);
if(!$item->equalsExact($oldItem)){
$this->armorInventory->setItem($slotId, $item);
}
}
}
}

private function damageItem(Durable $item, int $durabilityRemoved) : void{
$item->applyDamage($durabilityRemoved);
private function damageItem(
Durable $item,
int $durabilityRemoved,
int $cause,
Block|Entity|null $target = null,
?Inventory $inventory = null,
?int $slot = null
) : void{
$item->applyDamageWithContext(
$durabilityRemoved,
new ItemDamageContext($cause, $this, $target, $inventory, $slot)
);
if($item->isBroken()){
$this->broadcastSound(new ItemBreakSound());
}
Expand Down
102 changes: 102 additions & 0 deletions src/event/item/ItemDamageEvent.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
<?php

/*
*
* _ _ _
* / \ | | |_ __ _ _ _
* / _ \ | | __/ _` | | | |
* / ___ \| | || (_| | |_| |
* /_/ \_\_|\__\__,_|\__, |
* |___/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Original work by the PocketMine Team.
* https://www.pocketmine.net/
*
* @author Altay Team
* @link https://github.com/altayofficial
*/

declare(strict_types=1);

namespace pocketmine\event\item;

use pocketmine\block\Block;
use pocketmine\entity\Entity;
use pocketmine\entity\Living;
use pocketmine\event\Cancellable;
use pocketmine\event\CancellableTrait;
use pocketmine\event\Event;
use pocketmine\inventory\Inventory;
use pocketmine\item\Durable;

/**
* Called when an item is damaged
*/
class ItemDamageEvent extends Event implements Cancellable{
use CancellableTrait;

public const CAUSE_PLUGIN = 0;
public const CAUSE_BLOCK_BREAK = 1;
public const CAUSE_ENTITY_ATTACK = 2;
public const CAUSE_ARMOR_DAMAGE = 3;
public const CAUSE_THORNS = 4;
public const CAUSE_BLOCK_INTERACT = 5;
public const CAUSE_PROJECTILE = 6;

public function __construct(
private Durable $item,
private int $damage,
private int $unbreakingDamageReduction = 0,
private int $cause = self::CAUSE_PLUGIN,
private ?Living $entity = null,
private Block|Entity|null $target = null,
private ?Inventory $inventory = null,
private ?int $slot = null
){
}

public function getItem() : Durable{
return $this->item;
}

public function getDamage() : int{
return $this->damage;
}

public function setDamage(int $damage) : void{
$this->damage = $damage;
}

public function getUnbreakingDamageReduction() : int{
return $this->unbreakingDamageReduction;
}

public function setUnbreakingDamageReduction(int $unbreakingDamageReduction) : void{
$this->unbreakingDamageReduction = $unbreakingDamageReduction;
}

public function getCause() : int{
return $this->cause;
}

public function getEntity() : ?Living{
return $this->entity;
}

public function getTarget() : Block|Entity|null{
return $this->target;
}

public function getInventory() : ?Inventory{
return $this->inventory;
}

public function getSlot() : ?int{
return $this->slot;
}
}
3 changes: 2 additions & 1 deletion src/item/Bow.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
use pocketmine\entity\projectile\Projectile;
use pocketmine\event\entity\EntityShootBowEvent;
use pocketmine\event\entity\ProjectileLaunchEvent;
use pocketmine\event\item\ItemDamageEvent;
use pocketmine\item\enchantment\VanillaEnchantments;
use pocketmine\player\Player;
use pocketmine\world\sound\BowShootSound;
Expand Down Expand Up @@ -120,7 +121,7 @@ public function onReleaseUsing(Player $player, array &$returnedItems) : ItemUseR
if(!$infinity){ //TODO: tipped arrows are still consumed when Infinity is applied
$inventory?->removeItem($arrow);
}
$this->applyDamage(1);
$this->applyDamageWithContext(1, new ItemDamageContext(ItemDamageEvent::CAUSE_PROJECTILE, $player, null, $player->getInventory(), $player->getInventory()->getHeldItemIndex()));
}

return ItemUseResult::SUCCESS;
Expand Down
Loading
Loading