mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-06-10 21:45:35 +00:00
Enable various types of interaction to return items to the player, without needing to have a bunch of boilerplate creative mode and held item checks
it became glaringly obvious that this was needed because of #4827 and #4868. this is further needed with the addition of cauldrons.
This commit is contained in:
parent
4afd3dcabf
commit
d0ff6d2e36
@ -89,7 +89,7 @@ class Anvil extends Transparent implements Fallable{
|
||||
return SupportType::NONE();
|
||||
}
|
||||
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
|
||||
if($player instanceof Player){
|
||||
$player->setCurrentWindow(new AnvilInventory($this->position));
|
||||
}
|
||||
|
@ -149,7 +149,7 @@ class Bamboo extends Transparent{
|
||||
return $top;
|
||||
}
|
||||
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
|
||||
if($item instanceof Fertilizer){
|
||||
$top = $this->seekToTop();
|
||||
if($top->grow(self::getMaxHeight($top->position->getFloorX(), $top->position->getFloorZ()), mt_rand(1, 2), $player)){
|
||||
|
@ -73,7 +73,7 @@ final class BambooSapling extends Flowable{
|
||||
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
|
||||
}
|
||||
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
|
||||
if($item instanceof Fertilizer || $item instanceof ItemBamboo){
|
||||
if($this->grow($player)){
|
||||
$item->pop();
|
||||
|
@ -81,7 +81,7 @@ class Barrel extends Opaque{
|
||||
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
|
||||
}
|
||||
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
|
||||
if($player instanceof Player){
|
||||
$barrel = $this->position->getWorld()->getTile($this->position);
|
||||
if($barrel instanceof TileBarrel){
|
||||
|
@ -54,7 +54,7 @@ abstract class BaseCake extends Transparent implements FoodSource{
|
||||
}
|
||||
}
|
||||
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
|
||||
if($player !== null){
|
||||
return $player->consumeObject($this);
|
||||
}
|
||||
|
@ -130,7 +130,7 @@ class Bed extends Transparent{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
|
||||
if($player !== null){
|
||||
$other = $this->getOtherHalf();
|
||||
$playerPos = $player->getPosition();
|
||||
|
@ -139,7 +139,7 @@ final class Bell extends Transparent{
|
||||
}
|
||||
}
|
||||
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
|
||||
if($player !== null){
|
||||
$faceHit = Facing::opposite($player->getHorizontalFacing());
|
||||
if($this->attachmentType->equals(BellAttachmentType::CEILING())){
|
||||
|
@ -275,8 +275,10 @@ class Block{
|
||||
|
||||
/**
|
||||
* Do the actions needed so the block is broken with the Item
|
||||
*
|
||||
* @param Item[] &$returnedItems Items to be added to the target's inventory (or dropped, if full)
|
||||
*/
|
||||
public function onBreak(Item $item, ?Player $player = null) : bool{
|
||||
public function onBreak(Item $item, ?Player $player = null, array &$returnedItems = []) : bool{
|
||||
if(($t = $this->position->getWorld()->getTile($this->position)) !== null){
|
||||
$t->onBlockDestroyed();
|
||||
}
|
||||
@ -315,8 +317,10 @@ class Block{
|
||||
|
||||
/**
|
||||
* Do actions when interacted by Item. Returns if it has done anything
|
||||
*
|
||||
* @param Item[] &$returnedItems Items to be added to the target's inventory (or dropped, if the inventory is full)
|
||||
*/
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -118,7 +118,7 @@ class BrewingStand extends Transparent{
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
|
||||
if($player instanceof Player){
|
||||
$stand = $this->position->getWorld()->getTile($this->position);
|
||||
if($stand instanceof TileBrewingStand && $stand->canOpenWith($item->getCustomName())){
|
||||
|
@ -69,7 +69,7 @@ abstract class Button extends Flowable{
|
||||
|
||||
abstract protected function getActivationTime() : int;
|
||||
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
|
||||
if(!$this->pressed){
|
||||
$this->pressed = true;
|
||||
$this->position->getWorld()->setBlock($this->position, $this);
|
||||
|
@ -70,7 +70,7 @@ class Cake extends BaseCake{
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
|
||||
if($item instanceof ItemBlock){
|
||||
$block = $item->getBlock();
|
||||
$resultBlock = null;
|
||||
@ -87,7 +87,7 @@ class Cake extends BaseCake{
|
||||
}
|
||||
}
|
||||
|
||||
return parent::onInteract($item, $face, $clickVector, $player);
|
||||
return parent::onInteract($item, $face, $clickVector, $player, $returnedItems);
|
||||
}
|
||||
|
||||
public function getResidue() : Block{
|
||||
|
@ -51,12 +51,12 @@ class CakeWithCandle extends BaseCake{
|
||||
return VanillaBlocks::CANDLE();
|
||||
}
|
||||
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
if($this->onInteractCandle($item, $face, $clickVector, $player)){
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
|
||||
if($this->onInteractCandle($item, $face, $clickVector, $player, $returnedItems)){
|
||||
return true;
|
||||
}
|
||||
|
||||
return parent::onInteract($item, $face, $clickVector, $player);
|
||||
return parent::onInteract($item, $face, $clickVector, $player, $returnedItems);
|
||||
}
|
||||
|
||||
public function getDropsForCompatibleTool(Item $item) : array{
|
||||
|
@ -30,7 +30,7 @@ use pocketmine\player\Player;
|
||||
|
||||
final class CartographyTable extends Opaque{
|
||||
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
|
||||
if($player !== null){
|
||||
$player->setCurrentWindow(new CartographyTableInventory($this->position));
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ final class ChemistryTable extends Opaque{
|
||||
use FacesOppositePlacingPlayerTrait;
|
||||
use HorizontalFacingTrait;
|
||||
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
|
||||
//TODO
|
||||
return false;
|
||||
}
|
||||
|
@ -74,7 +74,7 @@ class Chest extends Transparent{
|
||||
}
|
||||
}
|
||||
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
|
||||
if($player instanceof Player){
|
||||
|
||||
$chest = $this->position->getWorld()->getTile($this->position);
|
||||
|
@ -101,7 +101,7 @@ class CocoaBlock extends Transparent{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
|
||||
if($item instanceof Fertilizer && $this->grow()){
|
||||
$item->pop();
|
||||
|
||||
|
@ -30,7 +30,7 @@ use pocketmine\player\Player;
|
||||
|
||||
class CraftingTable extends Opaque{
|
||||
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
|
||||
if($player instanceof Player){
|
||||
$player->setCurrentWindow(new CraftingTableInventory($this->position));
|
||||
}
|
||||
|
@ -68,7 +68,7 @@ abstract class Crops extends Flowable{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
|
||||
if($this->age < self::MAX_AGE && $item instanceof Fertilizer){
|
||||
$block = clone $this;
|
||||
$block->age += mt_rand(2, 5);
|
||||
|
@ -81,7 +81,7 @@ class DaylightSensor extends Transparent{
|
||||
return SupportType::NONE();
|
||||
}
|
||||
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
|
||||
$this->inverted = !$this->inverted;
|
||||
$this->signalStrength = $this->recalculateSignalStrength();
|
||||
$this->position->getWorld()->setBlock($this->position, $this);
|
||||
|
@ -53,7 +53,7 @@ class Dirt extends Opaque{
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
|
||||
if($face === Facing::UP && $item instanceof Hoe){
|
||||
$item->applyDamage(1);
|
||||
|
||||
|
@ -148,7 +148,7 @@ class Door extends Transparent{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
|
||||
$this->open = !$this->open;
|
||||
|
||||
$other = $this->getSide($this->top ? Facing::DOWN : Facing::UP);
|
||||
|
@ -48,7 +48,7 @@ class DragonEgg extends Transparent implements Fallable{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
|
||||
$this->teleport();
|
||||
return true;
|
||||
}
|
||||
|
@ -44,7 +44,7 @@ class EnchantingTable extends Transparent{
|
||||
return SupportType::NONE();
|
||||
}
|
||||
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
|
||||
if($player instanceof Player){
|
||||
//TODO lock
|
||||
|
||||
|
@ -54,7 +54,7 @@ class EnderChest extends Transparent{
|
||||
return SupportType::NONE();
|
||||
}
|
||||
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
|
||||
if($player instanceof Player){
|
||||
$enderChest = $this->position->getWorld()->getTile($this->position);
|
||||
if($enderChest instanceof TileEnderChest && $this->getSide(Facing::UP)->isTransparent()){
|
||||
|
@ -109,7 +109,7 @@ class FenceGate extends Transparent{
|
||||
}
|
||||
}
|
||||
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
|
||||
$this->open = !$this->open;
|
||||
if($this->open && $player !== null){
|
||||
$playerFacing = $player->getHorizontalFacing();
|
||||
|
@ -112,7 +112,7 @@ class FlowerPot extends Flowable{
|
||||
return $block->getSupportType(Facing::UP)->hasCenterSupport();
|
||||
}
|
||||
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
|
||||
$plant = $item->getBlock();
|
||||
if($this->plant !== null){
|
||||
if($this->isValidPlant($plant)){
|
||||
|
@ -67,7 +67,7 @@ class Furnace extends Opaque{
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
|
||||
if($player instanceof Player){
|
||||
$furnace = $this->position->getWorld()->getTile($this->position);
|
||||
if($furnace instanceof TileFurnace && $furnace->canOpenWith($item->getCustomName())){
|
||||
|
@ -87,7 +87,7 @@ class Grass extends Opaque{
|
||||
}
|
||||
}
|
||||
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
|
||||
if($face !== Facing::UP){
|
||||
return false;
|
||||
}
|
||||
|
@ -93,7 +93,7 @@ class Hopper extends Transparent{
|
||||
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
|
||||
}
|
||||
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
|
||||
if($player !== null){
|
||||
$tile = $this->position->getWorld()->getTile($this->position);
|
||||
if($tile instanceof TileHopper){ //TODO: find a way to have inventories open on click without this boilerplate in every block
|
||||
|
@ -38,12 +38,12 @@ class Ice extends Transparent{
|
||||
return 0.98;
|
||||
}
|
||||
|
||||
public function onBreak(Item $item, ?Player $player = null) : bool{
|
||||
public function onBreak(Item $item, ?Player $player = null, array &$returnedItems = []) : bool{
|
||||
if(($player === null || $player->isSurvival()) && !$item->hasEnchantment(VanillaEnchantments::SILK_TOUCH())){
|
||||
$this->position->getWorld()->setBlock($this->position, VanillaBlocks::WATER());
|
||||
return true;
|
||||
}
|
||||
return parent::onBreak($item, $player);
|
||||
return parent::onBreak($item, $player, $returnedItems);
|
||||
}
|
||||
|
||||
public function ticksRandomly() : bool{
|
||||
|
@ -153,7 +153,7 @@ class ItemFrame extends Flowable{
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
|
||||
if($this->framedItem !== null){
|
||||
$this->itemRotation = ($this->itemRotation + 1) % self::ROTATIONS;
|
||||
}elseif(!$item->isNull()){
|
||||
|
@ -39,7 +39,7 @@ class Jukebox extends Opaque{
|
||||
return 300;
|
||||
}
|
||||
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
|
||||
if($player instanceof Player){
|
||||
if($this->record !== null){
|
||||
$this->ejectRecord();
|
||||
@ -83,9 +83,9 @@ class Jukebox extends Opaque{
|
||||
$this->getPosition()->getWorld()->addSound($this->getPosition(), new RecordStopSound());
|
||||
}
|
||||
|
||||
public function onBreak(Item $item, ?Player $player = null) : bool{
|
||||
public function onBreak(Item $item, ?Player $player = null, array &$returnedItems = []) : bool{
|
||||
$this->stopSound();
|
||||
return parent::onBreak($item, $player);
|
||||
return parent::onBreak($item, $player, $returnedItems);
|
||||
}
|
||||
|
||||
public function getDropsForCompatibleTool(Item $item) : array{
|
||||
|
@ -127,7 +127,7 @@ class Lectern extends Transparent{
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
|
||||
if($this->book === null && $item instanceof WritableBookBase){
|
||||
$this->position->getWorld()->setBlock($this->position, $this->setBook($item));
|
||||
$this->position->getWorld()->addSound($this->position, new LecternPlaceBookSound());
|
||||
|
@ -106,7 +106,7 @@ class Lever extends Flowable{
|
||||
}
|
||||
}
|
||||
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
|
||||
$this->activated = !$this->activated;
|
||||
$this->position->getWorld()->setBlock($this->position, $this);
|
||||
$this->position->getWorld()->addSound(
|
||||
|
@ -63,7 +63,7 @@ final class Light extends Flowable{
|
||||
return $blockReplace->canBeReplaced() && $blockReplace->getTypeId() !== $this->getTypeId();
|
||||
}
|
||||
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
|
||||
$this->level = $this->level === self::MAX_LIGHT_LEVEL ?
|
||||
self::MIN_LIGHT_LEVEL :
|
||||
$this->level + 1;
|
||||
|
@ -34,7 +34,7 @@ final class Loom extends Opaque{
|
||||
use FacesOppositePlacingPlayerTrait;
|
||||
use HorizontalFacingTrait;
|
||||
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
|
||||
if($player !== null){
|
||||
$player->setCurrentWindow(new LoomInventory($this->position));
|
||||
return true;
|
||||
|
@ -33,7 +33,7 @@ use function in_array;
|
||||
|
||||
class Pumpkin extends Opaque{
|
||||
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
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->position->getWorld()->setBlock($this->position, VanillaBlocks::CARVED_PUMPKIN()->setFacing($face));
|
||||
|
@ -103,7 +103,7 @@ class RedstoneComparator extends Flowable{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
|
||||
$this->isSubtractMode = !$this->isSubtractMode;
|
||||
$this->position->getWorld()->setBlock($this->position, $this);
|
||||
return true;
|
||||
|
@ -60,7 +60,7 @@ class RedstoneOre extends Opaque{
|
||||
return $this->lit ? 9 : 0;
|
||||
}
|
||||
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
|
||||
if(!$this->lit){
|
||||
$this->lit = true;
|
||||
$this->position->getWorld()->setBlock($this->position, $this); //no return here - this shouldn't prevent block placement
|
||||
|
@ -88,7 +88,7 @@ class RedstoneRepeater extends Flowable{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
|
||||
if(++$this->delay > self::MAX_DELAY){
|
||||
$this->delay = self::MIN_DELAY;
|
||||
}
|
||||
|
@ -74,7 +74,7 @@ class Sapling extends Flowable{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
|
||||
if($item instanceof Fertilizer && $this->grow($player)){
|
||||
$item->pop();
|
||||
|
||||
|
@ -103,9 +103,9 @@ class SeaPickle extends Transparent{
|
||||
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
|
||||
}
|
||||
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
|
||||
//TODO: bonemeal logic (requires coral)
|
||||
return parent::onInteract($item, $face, $clickVector, $player);
|
||||
return parent::onInteract($item, $face, $clickVector, $player, $returnedItems);
|
||||
}
|
||||
|
||||
public function getDropsForCompatibleTool(Item $item) : array{
|
||||
|
@ -97,7 +97,7 @@ class ShulkerBox extends Opaque{
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
|
||||
if($player instanceof Player){
|
||||
|
||||
$shulker = $this->position->getWorld()->getTile($this->position);
|
||||
|
@ -30,7 +30,7 @@ use pocketmine\player\Player;
|
||||
|
||||
final class SmithingTable extends Opaque{
|
||||
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
|
||||
if($player !== null){
|
||||
$player->setCurrentWindow(new SmithingTableInventory($this->position));
|
||||
}
|
||||
|
@ -37,7 +37,7 @@ class Stonecutter extends Transparent{
|
||||
use FacesOppositePlacingPlayerTrait;
|
||||
use HorizontalFacingTrait;
|
||||
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
|
||||
if($player !== null){
|
||||
$player->setCurrentWindow(new StonecutterInventory($this->position));
|
||||
}
|
||||
|
@ -83,7 +83,7 @@ class Sugarcane extends Flowable{
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
|
||||
if($item instanceof Fertilizer){
|
||||
if(!$this->getSide(Facing::DOWN)->isSameType($this) && $this->grow()){
|
||||
$item->pop();
|
||||
|
@ -88,7 +88,7 @@ class SweetBerryBush extends Flowable{
|
||||
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
|
||||
}
|
||||
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
|
||||
if($this->age < self::STAGE_MATURE && $item instanceof Fertilizer){
|
||||
$block = clone $this;
|
||||
$block->age++;
|
||||
|
@ -81,15 +81,15 @@ class TNT extends Opaque{
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function onBreak(Item $item, ?Player $player = null) : bool{
|
||||
public function onBreak(Item $item, ?Player $player = null, array &$returnedItems = []) : bool{
|
||||
if($this->unstable){
|
||||
$this->ignite();
|
||||
return true;
|
||||
}
|
||||
return parent::onBreak($item, $player);
|
||||
return parent::onBreak($item, $player, $returnedItems);
|
||||
}
|
||||
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
|
||||
if($item instanceof FlintSteel || $item->hasEnchantment(VanillaEnchantments::FIRE_ASPECT())){
|
||||
if($item instanceof Durable){
|
||||
$item->applyDamage(1);
|
||||
|
@ -93,7 +93,7 @@ class Trapdoor extends Transparent{
|
||||
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
|
||||
}
|
||||
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
|
||||
$this->open = !$this->open;
|
||||
$this->position->getWorld()->setBlock($this->position, $this);
|
||||
$this->position->getWorld()->addSound($this->position, new DoorSound());
|
||||
|
@ -69,7 +69,7 @@ class Wood extends Opaque{
|
||||
return $this->woodType->isFlammable() ? 5 : 0;
|
||||
}
|
||||
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
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->stripped = true;
|
||||
|
@ -63,7 +63,7 @@ trait CandleTrait{
|
||||
}
|
||||
|
||||
/** @see Block::onInteract() */
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
|
||||
if($item->getTypeId() === ItemTypeIds::FLINT_AND_STEEL || $item->hasEnchantment(VanillaEnchantments::FIRE_ASPECT())){
|
||||
if($this->lit){
|
||||
return true;
|
||||
|
@ -68,7 +68,7 @@ trait CopperTrait{
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
|
||||
if(!$this->waxed && $item->getTypeId() === ItemTypeIds::HONEYCOMB){
|
||||
$this->waxed = true;
|
||||
$this->position->getWorld()->setBlock($this->position, $this);
|
||||
|
@ -129,16 +129,15 @@ class Armor extends Durable{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public function onClickAir(Player $player, Vector3 $directionVector) : ItemUseResult{
|
||||
public function onClickAir(Player $player, Vector3 $directionVector, array &$returnedItems) : ItemUseResult{
|
||||
$existing = $player->getArmorInventory()->getItem($this->getArmorSlot());
|
||||
$thisCopy = clone $this;
|
||||
$new = $thisCopy->pop();
|
||||
$player->getArmorInventory()->setItem($this->getArmorSlot(), $new);
|
||||
if($thisCopy->getCount() === 0){
|
||||
$player->getInventory()->setItemInHand($existing);
|
||||
}else{ //if the stack size was bigger than 1 (usually won't happen, but might be caused by plugins
|
||||
$player->getInventory()->setItemInHand($thisCopy);
|
||||
$player->getInventory()->addItem($existing);
|
||||
$player->getInventory()->setItemInHand($existing);
|
||||
if(!$thisCopy->isNull()){
|
||||
//if the stack size was bigger than 1 (usually won't happen, but might be caused by plugins)
|
||||
$returnedItems[] = $thisCopy;
|
||||
}
|
||||
return ItemUseResult::SUCCESS();
|
||||
}
|
||||
|
@ -41,14 +41,14 @@ class Axe extends TieredTool{
|
||||
return $this->tier->getBaseAttackPoints() - 1;
|
||||
}
|
||||
|
||||
public function onDestroyBlock(Block $block) : bool{
|
||||
public function onDestroyBlock(Block $block, array &$returnedItems) : bool{
|
||||
if(!$block->getBreakInfo()->breaksInstantly()){
|
||||
return $this->applyDamage(1);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function onAttackEntity(Entity $victim) : bool{
|
||||
public function onAttackEntity(Entity $victim, array &$returnedItems) : bool{
|
||||
return $this->applyDamage(2);
|
||||
}
|
||||
}
|
||||
|
@ -44,7 +44,7 @@ class Bow extends Tool implements Releasable{
|
||||
return 385;
|
||||
}
|
||||
|
||||
public function onReleaseUsing(Player $player) : ItemUseResult{
|
||||
public function onReleaseUsing(Player $player, array &$returnedItems) : ItemUseResult{
|
||||
$arrow = VanillaItems::ARROW();
|
||||
$inventory = match(true){
|
||||
$player->getOffHandInventory()->contains($arrow) => $player->getOffHandInventory(),
|
||||
|
@ -37,7 +37,7 @@ class Bucket extends Item{
|
||||
return 16;
|
||||
}
|
||||
|
||||
public function onInteractBlock(Player $player, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector) : ItemUseResult{
|
||||
public function onInteractBlock(Player $player, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, array &$returnedItems) : ItemUseResult{
|
||||
//TODO: move this to generic placement logic
|
||||
if($blockClicked instanceof Liquid && $blockClicked->isSource()){
|
||||
$stack = clone $this;
|
||||
@ -57,16 +57,9 @@ class Bucket extends Item{
|
||||
if(!$ev->isCancelled()){
|
||||
$player->getWorld()->setBlock($blockClicked->getPosition(), VanillaBlocks::AIR());
|
||||
$player->getWorld()->addSound($blockClicked->getPosition()->add(0.5, 0.5, 0.5), $blockClicked->getBucketFillSound());
|
||||
if($player->hasFiniteResources()){
|
||||
if($stack->getCount() === 0){
|
||||
$player->getInventory()->setItemInHand($ev->getItem());
|
||||
}else{
|
||||
$player->getInventory()->setItemInHand($stack);
|
||||
$player->getInventory()->addItem($ev->getItem());
|
||||
}
|
||||
}else{
|
||||
$player->getInventory()->addItem($ev->getItem());
|
||||
}
|
||||
|
||||
$this->pop();
|
||||
$returnedItems[] = $ev->getItem();
|
||||
return ItemUseResult::SUCCESS();
|
||||
}
|
||||
|
||||
|
@ -32,7 +32,7 @@ use pocketmine\world\sound\FlintSteelSound;
|
||||
|
||||
class FlintSteel extends Tool{
|
||||
|
||||
public function onInteractBlock(Player $player, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector) : ItemUseResult{
|
||||
public function onInteractBlock(Player $player, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, array &$returnedItems) : ItemUseResult{
|
||||
if($blockReplace->getTypeId() === BlockTypeIds::AIR){
|
||||
$world = $player->getWorld();
|
||||
$world->setBlock($blockReplace->getPosition(), VanillaBlocks::FIRE());
|
||||
|
@ -33,11 +33,11 @@ class Hoe extends TieredTool{
|
||||
return BlockToolType::HOE;
|
||||
}
|
||||
|
||||
public function onAttackEntity(Entity $victim) : bool{
|
||||
public function onAttackEntity(Entity $victim, array &$returnedItems) : bool{
|
||||
return $this->applyDamage(1);
|
||||
}
|
||||
|
||||
public function onDestroyBlock(Block $block) : bool{
|
||||
public function onDestroyBlock(Block $block, array &$returnedItems) : bool{
|
||||
if(!$block->getBreakInfo()->breaksInstantly()){
|
||||
return $this->applyDamage(1);
|
||||
}
|
||||
|
@ -513,38 +513,48 @@ class Item implements \JsonSerializable{
|
||||
|
||||
/**
|
||||
* Called when a player uses this item on a block.
|
||||
*
|
||||
* @param Item[] &$returnedItems Items to be added to the target's inventory (or dropped, if the inventory is full)
|
||||
*/
|
||||
public function onInteractBlock(Player $player, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector) : ItemUseResult{
|
||||
public function onInteractBlock(Player $player, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, array &$returnedItems) : ItemUseResult{
|
||||
return ItemUseResult::NONE();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a player uses the item on air, for example throwing a projectile.
|
||||
* Returns whether the item was changed, for example count decrease or durability change.
|
||||
*
|
||||
* @param Item[] &$returnedItems Items to be added to the target's inventory (or dropped, if the inventory is full)
|
||||
*/
|
||||
public function onClickAir(Player $player, Vector3 $directionVector) : ItemUseResult{
|
||||
public function onClickAir(Player $player, Vector3 $directionVector, array &$returnedItems) : ItemUseResult{
|
||||
return ItemUseResult::NONE();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a player is using this item and releases it. Used to handle bow shoot actions.
|
||||
* Returns whether the item was changed, for example count decrease or durability change.
|
||||
*
|
||||
* @param Item[] &$returnedItems Items to be added to the target's inventory (or dropped, if the inventory is full)
|
||||
*/
|
||||
public function onReleaseUsing(Player $player) : ItemUseResult{
|
||||
public function onReleaseUsing(Player $player, array &$returnedItems) : ItemUseResult{
|
||||
return ItemUseResult::NONE();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when this item is used to destroy a block. Usually used to update durability.
|
||||
*
|
||||
* @param Item[] &$returnedItems Items to be added to the target's inventory (or dropped, if the inventory is full)
|
||||
*/
|
||||
public function onDestroyBlock(Block $block) : bool{
|
||||
public function onDestroyBlock(Block $block, array &$returnedItems) : bool{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when this item is used to attack an entity. Usually used to update durability.
|
||||
*
|
||||
* @param Item[] &$returnedItems Items to be added to the target's inventory (or dropped, if the inventory is full)
|
||||
*/
|
||||
public function onAttackEntity(Entity $victim) : bool{
|
||||
public function onAttackEntity(Entity $victim, array &$returnedItems) : bool{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -54,7 +54,7 @@ class LiquidBucket extends Item{
|
||||
return VanillaItems::BUCKET();
|
||||
}
|
||||
|
||||
public function onInteractBlock(Player $player, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector) : ItemUseResult{
|
||||
public function onInteractBlock(Player $player, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, array &$returnedItems) : ItemUseResult{
|
||||
if(!$blockReplace->canBeReplaced()){
|
||||
return ItemUseResult::NONE();
|
||||
}
|
||||
@ -68,9 +68,8 @@ class LiquidBucket extends Item{
|
||||
$player->getWorld()->setBlock($blockReplace->getPosition(), $resultBlock->getFlowingForm());
|
||||
$player->getWorld()->addSound($blockReplace->getPosition()->add(0.5, 0.5, 0.5), $resultBlock->getBucketEmptySound());
|
||||
|
||||
if($player->hasFiniteResources()){
|
||||
$player->getInventory()->setItemInHand($ev->getItem());
|
||||
}
|
||||
$this->pop();
|
||||
$returnedItems[] = $ev->getItem();
|
||||
return ItemUseResult::SUCCESS();
|
||||
}
|
||||
|
||||
|
@ -37,7 +37,7 @@ use function count;
|
||||
|
||||
class PaintingItem extends Item{
|
||||
|
||||
public function onInteractBlock(Player $player, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector) : ItemUseResult{
|
||||
public function onInteractBlock(Player $player, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, array &$returnedItems) : ItemUseResult{
|
||||
if(Facing::axis($face) === Axis::Y){
|
||||
return ItemUseResult::NONE();
|
||||
}
|
||||
|
@ -41,14 +41,14 @@ class Pickaxe extends TieredTool{
|
||||
return $this->tier->getBaseAttackPoints() - 2;
|
||||
}
|
||||
|
||||
public function onDestroyBlock(Block $block) : bool{
|
||||
public function onDestroyBlock(Block $block, array &$returnedItems) : bool{
|
||||
if(!$block->getBreakInfo()->breaksInstantly()){
|
||||
return $this->applyDamage(1);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function onAttackEntity(Entity $victim) : bool{
|
||||
public function onAttackEntity(Entity $victim, array &$returnedItems) : bool{
|
||||
return $this->applyDamage(2);
|
||||
}
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ abstract class ProjectileItem extends Item{
|
||||
|
||||
abstract protected function createEntity(Location $location, Player $thrower) : Throwable;
|
||||
|
||||
public function onClickAir(Player $player, Vector3 $directionVector) : ItemUseResult{
|
||||
public function onClickAir(Player $player, Vector3 $directionVector, array &$returnedItems) : ItemUseResult{
|
||||
$location = $player->getLocation();
|
||||
|
||||
$projectile = $this->createEntity(Location::fromObject($player->getEyePos(), $player->getWorld(), $location->yaw, $location->pitch), $player);
|
||||
|
@ -44,7 +44,7 @@ class Shears extends Tool{
|
||||
return 15;
|
||||
}
|
||||
|
||||
public function onDestroyBlock(Block $block) : bool{
|
||||
public function onDestroyBlock(Block $block, array &$returnedItems) : bool{
|
||||
return $this->applyDamage(1);
|
||||
}
|
||||
}
|
||||
|
@ -41,14 +41,14 @@ class Shovel extends TieredTool{
|
||||
return $this->tier->getBaseAttackPoints() - 3;
|
||||
}
|
||||
|
||||
public function onDestroyBlock(Block $block) : bool{
|
||||
public function onDestroyBlock(Block $block, array &$returnedItems) : bool{
|
||||
if(!$block->getBreakInfo()->breaksInstantly()){
|
||||
return $this->applyDamage(1);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function onAttackEntity(Entity $victim) : bool{
|
||||
public function onAttackEntity(Entity $victim, array &$returnedItems) : bool{
|
||||
return $this->applyDamage(2);
|
||||
}
|
||||
}
|
||||
|
@ -34,7 +34,7 @@ abstract class SpawnEgg extends Item{
|
||||
|
||||
abstract protected function createEntity(World $world, Vector3 $pos, float $yaw, float $pitch) : Entity;
|
||||
|
||||
public function onInteractBlock(Player $player, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector) : ItemUseResult{
|
||||
public function onInteractBlock(Player $player, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, array &$returnedItems) : ItemUseResult{
|
||||
$entity = $this->createEntity($player->getWorld(), $blockReplace->getPosition()->add(0.5, 0, 0.5), lcg_value() * 360, 0);
|
||||
|
||||
if($this->hasCustomName()){
|
||||
|
@ -49,14 +49,14 @@ class Sword extends TieredTool{
|
||||
return 10;
|
||||
}
|
||||
|
||||
public function onDestroyBlock(Block $block) : bool{
|
||||
public function onDestroyBlock(Block $block, array &$returnedItems) : bool{
|
||||
if(!$block->getBreakInfo()->breaksInstantly()){
|
||||
return $this->applyDamage(2);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function onAttackEntity(Entity $victim) : bool{
|
||||
public function onAttackEntity(Entity $victim, array &$returnedItems) : bool{
|
||||
return $this->applyDamage(1);
|
||||
}
|
||||
}
|
||||
|
@ -54,6 +54,7 @@ use pocketmine\event\player\PlayerChatEvent;
|
||||
use pocketmine\event\player\PlayerCommandPreprocessEvent;
|
||||
use pocketmine\event\player\PlayerDeathEvent;
|
||||
use pocketmine\event\player\PlayerDisplayNameChangeEvent;
|
||||
use pocketmine\event\player\PlayerDropItemEvent;
|
||||
use pocketmine\event\player\PlayerEmoteEvent;
|
||||
use pocketmine\event\player\PlayerEntityInteractEvent;
|
||||
use pocketmine\event\player\PlayerExhaustEvent;
|
||||
@ -1443,6 +1444,39 @@ class Player extends Human implements CommandSender, ChunkListener, IPlayer{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Item[] $extraReturnedItems
|
||||
*/
|
||||
private function returnItemsFromAction(Item $oldHeldItem, Item $newHeldItem, array $extraReturnedItems) : void{
|
||||
$heldItemChanged = false;
|
||||
if($this->hasFiniteResources()){
|
||||
if(!$newHeldItem->equalsExact($oldHeldItem) && $oldHeldItem->equalsExact($this->inventory->getItemInHand())){
|
||||
if($newHeldItem instanceof Durable && $newHeldItem->isBroken()){
|
||||
$this->broadcastSound(new ItemBreakSound());
|
||||
}
|
||||
$this->inventory->setItemInHand($newHeldItem);
|
||||
$heldItemChanged = true;
|
||||
}
|
||||
}else{
|
||||
$newHeldItem = $oldHeldItem;
|
||||
}
|
||||
|
||||
if($heldItemChanged && count($extraReturnedItems) > 0 && $newHeldItem->isNull()){
|
||||
$this->inventory->setItemInHand(array_shift($extraReturnedItems));
|
||||
}
|
||||
foreach($this->inventory->addItem(...$extraReturnedItems) as $drop){
|
||||
//TODO: we can't generate a transaction for this since the items aren't coming from an inventory :(
|
||||
$ev = new PlayerDropItemEvent($this, $drop);
|
||||
if($this->isSpectator()){
|
||||
$ev->cancel();
|
||||
}
|
||||
$ev->call();
|
||||
if(!$ev->isCancelled()){
|
||||
$this->dropItem($drop);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Activates the item in hand, for example throwing a projectile.
|
||||
*
|
||||
@ -1464,18 +1498,14 @@ class Player extends Human implements CommandSender, ChunkListener, IPlayer{
|
||||
return false;
|
||||
}
|
||||
|
||||
$result = $item->onClickAir($this, $directionVector);
|
||||
$returnedItems = [];
|
||||
$result = $item->onClickAir($this, $directionVector, $returnedItems);
|
||||
if($result->equals(ItemUseResult::FAIL())){
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->resetItemCooldown($item);
|
||||
if($this->hasFiniteResources() && !$item->equalsExact($oldItem) && $oldItem->equalsExact($this->inventory->getItemInHand())){
|
||||
if($item instanceof Durable && $item->isBroken()){
|
||||
$this->broadcastSound(new ItemBreakSound());
|
||||
}
|
||||
$this->inventory->setItemInHand($item);
|
||||
}
|
||||
$this->returnItemsFromAction($oldItem, $item, $returnedItems);
|
||||
|
||||
$this->setUsingItem($item instanceof Releasable && $item->canStartUsingItem($this));
|
||||
|
||||
@ -1505,11 +1535,8 @@ class Player extends Human implements CommandSender, ChunkListener, IPlayer{
|
||||
$this->setUsingItem(false);
|
||||
$this->resetItemCooldown($slot);
|
||||
|
||||
if($this->hasFiniteResources() && $oldItem->equalsExact($this->inventory->getItemInHand())){
|
||||
$slot->pop();
|
||||
$this->inventory->setItemInHand($slot);
|
||||
$this->inventory->addItem($slot->getResidue());
|
||||
}
|
||||
$slot->pop();
|
||||
$this->returnItemsFromAction($oldItem, $slot, [$slot->getResidue()]);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -1531,15 +1558,11 @@ class Player extends Human implements CommandSender, ChunkListener, IPlayer{
|
||||
|
||||
$oldItem = clone $item;
|
||||
|
||||
$result = $item->onReleaseUsing($this);
|
||||
$returnedItems = [];
|
||||
$result = $item->onReleaseUsing($this, $returnedItems);
|
||||
if($result->equals(ItemUseResult::SUCCESS())){
|
||||
$this->resetItemCooldown($item);
|
||||
if(!$item->equalsExact($oldItem) && $oldItem->equalsExact($this->inventory->getItemInHand())){
|
||||
if($item instanceof Durable && $item->isBroken()){
|
||||
$this->broadcastSound(new ItemBreakSound());
|
||||
}
|
||||
$this->inventory->setItemInHand($item);
|
||||
}
|
||||
$this->returnItemsFromAction($oldItem, $item, $returnedItems);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1652,13 +1675,9 @@ class Player extends Human implements CommandSender, ChunkListener, IPlayer{
|
||||
$this->stopBreakBlock($pos);
|
||||
$item = $this->inventory->getItemInHand();
|
||||
$oldItem = clone $item;
|
||||
if($this->getWorld()->useBreakOn($pos, $item, $this, true)){
|
||||
if($this->hasFiniteResources() && !$item->equalsExact($oldItem) && $oldItem->equalsExact($this->inventory->getItemInHand())){
|
||||
if($item instanceof Durable && $item->isBroken()){
|
||||
$this->broadcastSound(new ItemBreakSound());
|
||||
}
|
||||
$this->inventory->setItemInHand($item);
|
||||
}
|
||||
$returnedItems = [];
|
||||
if($this->getWorld()->useBreakOn($pos, $item, $this, true, $returnedItems)){
|
||||
$this->returnItemsFromAction($oldItem, $item, $returnedItems);
|
||||
$this->hungerManager->exhaust(0.005, PlayerExhaustEvent::CAUSE_MINING);
|
||||
return true;
|
||||
}
|
||||
@ -1681,13 +1700,9 @@ class Player extends Human implements CommandSender, ChunkListener, IPlayer{
|
||||
$this->broadcastAnimation(new ArmSwingAnimation($this), $this->getViewers());
|
||||
$item = $this->inventory->getItemInHand(); //this is a copy of the real item
|
||||
$oldItem = clone $item;
|
||||
if($this->getWorld()->useItemOn($pos, $item, $face, $clickOffset, $this, true)){
|
||||
if($this->hasFiniteResources() && !$item->equalsExact($oldItem) && $oldItem->equalsExact($this->inventory->getItemInHand())){
|
||||
if($item instanceof Durable && $item->isBroken()){
|
||||
$this->broadcastSound(new ItemBreakSound());
|
||||
}
|
||||
$this->inventory->setItemInHand($item);
|
||||
}
|
||||
$returnedItems = [];
|
||||
if($this->getWorld()->useItemOn($pos, $item, $face, $clickOffset, $this, true, $returnedItems)){
|
||||
$this->returnItemsFromAction($oldItem, $item, $returnedItems);
|
||||
return true;
|
||||
}
|
||||
}else{
|
||||
@ -1762,12 +1777,9 @@ class Player extends Human implements CommandSender, ChunkListener, IPlayer{
|
||||
if($this->isAlive()){
|
||||
//reactive damage like thorns might cause us to be killed by attacking another mob, which
|
||||
//would mean we'd already have dropped the inventory by the time we reached here
|
||||
if($heldItem->onAttackEntity($entity) && $this->hasFiniteResources() && $oldItem->equalsExact($this->inventory->getItemInHand())){ //always fire the hook, even if we are survival
|
||||
if($heldItem instanceof Durable && $heldItem->isBroken()){
|
||||
$this->broadcastSound(new ItemBreakSound());
|
||||
}
|
||||
$this->inventory->setItemInHand($heldItem);
|
||||
}
|
||||
$returnedItems = [];
|
||||
$heldItem->onAttackEntity($entity, $returnedItems);
|
||||
$this->returnItemsFromAction($oldItem, $heldItem, $returnedItems);
|
||||
|
||||
$this->hungerManager->exhaust(0.1, PlayerExhaustEvent::CAUSE_ATTACK);
|
||||
}
|
||||
|
@ -1660,9 +1660,10 @@ class World implements ChunkManager{
|
||||
* Tries to break a block using a item, including Player time checks if available
|
||||
* It'll try to lower the durability if Item is a tool, and set it to Air if broken.
|
||||
*
|
||||
* @param Item $item reference parameter (if null, can break anything)
|
||||
* @param Item &$item reference parameter (if null, can break anything)
|
||||
* @param Item[] &$returnedItems Items to be added to the target's inventory (or dropped, if the inventory is full)
|
||||
*/
|
||||
public function useBreakOn(Vector3 $vector, Item &$item = null, ?Player $player = null, bool $createParticles = false) : bool{
|
||||
public function useBreakOn(Vector3 $vector, Item &$item = null, ?Player $player = null, bool $createParticles = false, array &$returnedItems = []) : bool{
|
||||
$vector = $vector->floor();
|
||||
|
||||
$chunkX = $vector->getFloorX() >> Chunk::COORD_BIT_SIZE;
|
||||
@ -1724,10 +1725,10 @@ class World implements ChunkManager{
|
||||
}
|
||||
|
||||
foreach($affectedBlocks as $t){
|
||||
$this->destroyBlockInternal($t, $item, $player, $createParticles);
|
||||
$this->destroyBlockInternal($t, $item, $player, $createParticles, $returnedItems);
|
||||
}
|
||||
|
||||
$item->onDestroyBlock($target);
|
||||
$item->onDestroyBlock($target, $returnedItems);
|
||||
|
||||
if(count($drops) > 0){
|
||||
$dropPos = $vector->add(0.5, 0.5, 0.5);
|
||||
@ -1745,12 +1746,15 @@ class World implements ChunkManager{
|
||||
return true;
|
||||
}
|
||||
|
||||
private function destroyBlockInternal(Block $target, Item $item, ?Player $player = null, bool $createParticles = false) : void{
|
||||
/**
|
||||
* @param Item[] &$returnedItems
|
||||
*/
|
||||
private function destroyBlockInternal(Block $target, Item $item, ?Player $player, bool $createParticles, array &$returnedItems) : void{
|
||||
if($createParticles){
|
||||
$this->addParticle($target->getPosition()->add(0.5, 0.5, 0.5), new BlockBreakParticle($target));
|
||||
}
|
||||
|
||||
$target->onBreak($item, $player);
|
||||
$target->onBreak($item, $player, $returnedItems);
|
||||
|
||||
$tile = $this->getTile($target->getPosition());
|
||||
if($tile !== null){
|
||||
@ -1761,10 +1765,11 @@ class World implements ChunkManager{
|
||||
/**
|
||||
* Uses a item on a position and face, placing it or activating the block
|
||||
*
|
||||
* @param Player|null $player default null
|
||||
* @param bool $playSound Whether to play a block-place sound if the block was placed successfully.
|
||||
* @param Player|null $player default null
|
||||
* @param bool $playSound Whether to play a block-place sound if the block was placed successfully.
|
||||
* @param Item[] &$returnedItems Items to be added to the target's inventory (or dropped if the inventory is full)
|
||||
*/
|
||||
public function useItemOn(Vector3 $vector, Item &$item, int $face, ?Vector3 $clickVector = null, ?Player $player = null, bool $playSound = false) : bool{
|
||||
public function useItemOn(Vector3 $vector, Item &$item, int $face, ?Vector3 $clickVector = null, ?Player $player = null, bool $playSound = false, array &$returnedItems = []) : bool{
|
||||
$blockClicked = $this->getBlock($vector);
|
||||
$blockReplace = $blockClicked->getSide($face);
|
||||
|
||||
@ -1794,18 +1799,18 @@ class World implements ChunkManager{
|
||||
|
||||
$ev->call();
|
||||
if(!$ev->isCancelled()){
|
||||
if((!$player->isSneaking() || $item->isNull()) && $blockClicked->onInteract($item, $face, $clickVector, $player)){
|
||||
if((!$player->isSneaking() || $item->isNull()) && $blockClicked->onInteract($item, $face, $clickVector, $player, $returnedItems)){
|
||||
return true;
|
||||
}
|
||||
|
||||
$result = $item->onInteractBlock($player, $blockReplace, $blockClicked, $face, $clickVector);
|
||||
$result = $item->onInteractBlock($player, $blockReplace, $blockClicked, $face, $clickVector, $returnedItems);
|
||||
if(!$result->equals(ItemUseResult::NONE())){
|
||||
return $result->equals(ItemUseResult::SUCCESS());
|
||||
}
|
||||
}else{
|
||||
return false;
|
||||
}
|
||||
}elseif($blockClicked->onInteract($item, $face, $clickVector, $player)){
|
||||
}elseif($blockClicked->onInteract($item, $face, $clickVector, $player, $returnedItems)){
|
||||
return true;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user