1. The forums will be archived and moved to a read only mode in about 2 weeks (mid march).

can't remove the source and target...

Discussion in 'Development' started by Astro, Mar 8, 2019.

  1. Astro

    Astro Slime

    Messages:
    78
    GitHub:
    RealAstro
    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(13071);
                                
    $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;
                        }
                    }
                }
            }
        }
     
  2. KielKing

    KielKing Zombie

    Messages:
    245
    GitHub:
    kielking
    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));
     
    Astro likes this.
  3. Astro

    Astro Slime

    Messages:
    78
    GitHub:
    RealAstro
    all it sends is this also the tripwire gets removed for a second then apears again
     
  4. Muqsit

    Muqsit Chicken

    Messages:
    1,548
    GitHub:
    muqsit
    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;
                }
            }
        }
    }
     
    Last edited: Mar 9, 2019
    HimbeersaftLP and Astro like this.
  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.