for some reason, the target and the sources cannot be removed here is my code PHP: public function onDragAndDrop(InventoryTransactionEvent $event) { $transaction = $event->getTransaction(); $player = $event->getTransaction()->getSource(); foreach ($transaction->getActions() as $action) { $source = $action->getSourceItem(); $target = $action->getTargetItem(); if ($target->getId() == 132 && $target->getDamage() == 1) { if ($source->getId() == 130) { switch ($source->getDamage()) { case 6: $unlockedtrasure = Item::get(130, 7, 1); $unlockedtrasure->setCustomName("§r§a§lBasic Treasure§r§7 (Right-Click)"); $unlockedtrasure->setLore([ "§r§a§lUnlocked§r", "§r", "§r§7This Ancient Treasure is said to contain", "§r§7many Lost Riches for those that can open it!", "", "§r§aPossible Rewards:" ]); $player->getInventory()->removeItem($source); $player->getInventory()->removeItem($target); $player->getInventory()->addItem($unlockedtrasure); break; } } } } }
does it give you the item? if so, var_dump() the removeItem function PHP: /** @var Item $source *//** @var Item $target *//** @var Player $player */var_dump($player->getInventory()->removeItem($source, $target));
The InventoryTransactionEvent like every other event[citation] is triggered before any changes are made. This means when the event is triggered, the $target may not be in the inventory. I'm assuming you're attempting to implement a "drag and drop $source onto $target to do something". As a precaution, you shouldn't assume $player->getInventory() is the only inventory where any such thing could happen. It is possible for $player->getInventory() and $action->getInventory() to not be the same and you'll end up with some unexpected behaviour. I have implemented something like that previously, but in somewhat of a limiting way. Firstly, verify whether there are only two actions happening, just to stay away from any weird behaviour. Well, that actually isn't the only reason why we're limiting to 2 actions. We also need to fetch the other inventory and it only gets simpler when there are two inventories to deal with (the two inventories could even be the same, and that's fine). PHP: if(count($actions) === 2){ // proceed} All actions must be filtered through an "instanceof SlotChangeAction" check. As the comment in the SlotChangeAction reads, it occurs when there's a change in an inventory slot. Without this check, your source and target validation code could be running over actions such as DropItemAction, causing unexpected behaviour. From these, you can fetch the "source" and "target" by just the source. PHP: foreach($actions as $key => $action){ if($action instanceof SlotChangeAction){ $source = $action->getSourceItem(); unset($actions[$key]); reset($actions); $other_action = current($actions); if($other_action instanceof SlotChangeAction){ // usually always true, but you can never trust players. $target = $other_action->getSourceItem(); // yes, getSourceItem of the other action is the target. // source = item that was selected. // target = item which source was clicked with. if(/*run your source-target check*/){ // DO NOT call removeItem() to remove the source item // during InventoryTransactionEvent. // Just call $source->pop() and $target->pop() // followed by the $inventory->addItem(a new item you want to add in the inventory). // You can alternatively $source->setCount(0); // and $target = new item that's the result of source and target. // And now, we set the $source and $target in their right slots. $event->setCancelled(); $action->getInventory()->setItem($action->getSlot(), $source); $other_action->getInventory()->setItem($other_action->getSlot(), $target); return; } } }}