Removing items from players invent problem

Discussion in 'Development' started by MC ATECH, Oct 18, 2019.

  1. MC ATECH

    MC ATECH Baby Zombie

    Messages:
    105
    GitHub:
    mcpeatech
    Hi,
    I've been coding a plugin which when an item is tapped using the "PlayerInteractEvent" it will be removed from the players inventory. The code below works perfectly except for one small problem.
    Upon clicking / tapping the item on the ground if you have more than one of the same item, (stacked or in different slots) more than one item is removed from the inventory.
    How can I prevent this? Thanks for your help :)
    Code:
    PHP:
        /**
         * @param PlayerInteractEvent $event
         */
        
    public function onTap(PlayerInteractEvent $event){
            
    $player $event->getPlayer();
            
    $name $player->getName();
            
    $item $player->getInventory()->getItemInHand();
            
    $damage $item->getDamage();
            switch(
    $damage) {
                case 
    "105":
                if (
    $item->getId() === 339){
                    
    $item1 Item::get(3391051);
                    
    $player->getInventory()->removeItem($item1);
                    
    $event->setCancelled();
                }
                break;
            }
        
        }
     
  2. Matrox

    Matrox Slime

    Messages:
    87
    https://github.com/pmmp/PocketMine-...c/src/pocketmine/inventory/Inventory.php#L110
    https://www.php.net/manual/fr/language.operators.comparison.php

    PHP:
    public function onTap(PlayerInteractEvent $event){
            
    $player $event->getPlayer();
            
    $name $player->getName();
            
    $item $player->getInventory()->getItemInHand();
            
    $damage $item->getDamage();
            switch(
    $damage) {
                case 
    "105":
                if (
    $item->getId() == 339){
                    
    $item1 Item::get(3391051);
                    
    $player->getInventory()->removeItem($item1);
                }
                break;
            }
     
        }
     
    Last edited: Oct 18, 2019
  3. MC ATECH

    MC ATECH Baby Zombie

    Messages:
    105
    GitHub:
    mcpeatech
    Didn't realize that pocketmine treat slots and items that way.
    Which operator should I be using?
     
  4. HimbeersaftLP

    HimbeersaftLP Chicken

    Messages:
    1,786
    GitHub:
    HimbeersaftLP
    Item->getId() returns a string so using the strict comparator is perfectly fine (and better practice).
    Your code doesn't solve the problem at all.
    The problem is that removeItem() doesn't care if it has already removed said item from a slot.
    To solve this you will need to write your own removeItem function that respects the total removed item count:
    PHP:
    private function removeItems(Item $itemBaseInventory $inventory){
         
    $checkDamage = !$item->hasAnyDamageValue();
         
    $checkTags $item->hasCompoundTag();
         
    $checkCount $item->getCount() === null false true;
         
    $count $item->getCount();
         foreach(
    $inventory->getContents() as $index => $i){
              if(
    $item->equals($i$checkDamage$checkTags)){
                   if(
    $checkCount && $i->getCount() > $item->getCount()) {
                        
    $i->setCount($i->getCount() - $count);
                        
    $inventory->setItem($index$i);
                        return;
                   } elseif(
    $checkCount && $i->getCount() < $item->getCount()) {
                        
    $count -= $i->getCount();
                        
    $inventory->clear($index);
                   } else {
                        
    $inventory->clear($index);
                   }
              }
         }
    }
     
    MC ATECH likes this.
  5. MC ATECH

    MC ATECH Baby Zombie

    Messages:
    105
    GitHub:
    mcpeatech
    Thank you for the explanation! I knew my code didn’t fix the problem that’s why I asked what was causing it
     
    HimbeersaftLP likes this.
  6. HimbeersaftLP

    HimbeersaftLP Chicken

    Messages:
    1,786
    GitHub:
    HimbeersaftLP
    No problem :)

    I was talking about Matrox's code
     
    MC ATECH likes this.
  7. MC ATECH

    MC ATECH Baby Zombie

    Messages:
    105
    GitHub:
    mcpeatech
    When using the custom function the code above removes every item with the same ID and damage? How can I make it so that it only clears one at a time?
     
  8. HimbeersaftLP

    HimbeersaftLP Chicken

    Messages:
    1,786
    GitHub:
    HimbeersaftLP
    The function I sent (I think @Ad5001 wrote it for CommandShop) will remove the exact amount of items that is given to it. It will also respect items in different slots.
     
  9. MC ATECH

    MC ATECH Baby Zombie

    Messages:
    105
    GitHub:
    mcpeatech
    Hmm, okay. Maybe each item needs it’s own unique compound tag?..
     
  10. HimbeersaftLP

    HimbeersaftLP Chicken

    Messages:
    1,786
    GitHub:
    HimbeersaftLP
    The code should do what you want as it is
     
  11. MC ATECH

    MC ATECH Baby Zombie

    Messages:
    105
    GitHub:
    mcpeatech
    If the Item i am removing is un-stack-able and i have more than 1 they all get removed.
     
  12. HimbeersaftLP

    HimbeersaftLP Chicken

    Messages:
    1,786
    GitHub:
    HimbeersaftLP
    It shouldn't do that, my I see your code?
     
  13. MC ATECH

    MC ATECH Baby Zombie

    Messages:
    105
    GitHub:
    mcpeatech
    Here: (thanks for the help)
    PHP:
    public function onTap(PlayerInteractEvent $event){
            
    $player $event->getPlayer();
            
    $name $player->getName();
            
    $item $player->getInventory()->getItemInHand();
            
    $damage $item->getDamage();
            switch(
    $damage) {
                case 
    "101":
                
    $testitemItem::get(4501011);
                
    $item1 Item::get(31001);       
                
    $item2 Item::get(31101);
                
    $item3 Item::get(31201);
                
    $item4 Item::get(31301);
                
    $pickaxe Item::get(27801);
                
    $axe Item::get(27901);
                
    $tobegiven1 = [$item1$item2$item4$item3$pickaxe$axe]; 
                
    $rand1 mt_rand(07);
                
    $player->getInventory()->addItem($tobegiven1[$rand1]);
                
    $player->sendPopup(TF::YELLOW"Opening..");
                
    $event->setCancelled();
                
    $this->removeItems($testitem$player->getInventory());
                break;
            }
        }
        
        
    /**
         * @param removeItems $item
         */
        
    private function removeItems(Item $itemBaseInventory $inventory){
         
    $checkDamage = !$item->hasAnyDamageValue();
         
    $checkTags $item->hasCompoundTag();
         
    $checkCount $item->getCount() === null false true;
         
    $count $item->getCount();
         foreach(
    $inventory->getContents() as $index => $i){
              if(
    $item->equals($i$checkDamage$checkTags)){
                   if(
    $checkCount && $i->getCount() > $item->getCount()) {
                        
    $i->setCount($i->getCount() - $count);
                        
    $inventory->setItem($index$i);
                        return;
                   } elseif(
    $checkCount && $i->getCount() < $item->getCount()) {
                        
    $count -= $i->getCount();
                        
    $inventory->clear($index);
                   } else {
                        
    $inventory->clear($index);
                   }
              }
         }
        }
     
  14. HimbeersaftLP

    HimbeersaftLP Chicken

    Messages:
    1,786
    GitHub:
    HimbeersaftLP
    Apparently that code was never tested and contains several bugs lol, try that one:
    PHP:
    private function removeItems(Item $itemBaseInventory $inventory){
         
    $checkDamage = !$item->hasAnyDamageValue();
         
    $checkTags $item->hasCompoundTag();
         
    $checkCount $item->getCount() === null false true;
         
    $count $item->getCount();
         foreach(
    $inventory->getContents() as $index => $i){
              if(
    $item->equals($i$checkDamage$checkTags)){
                   if(
    $checkCount && $i->getCount() > $count) {
                        
    $i->setCount($i->getCount() - $count);
                        
    $inventory->setItem($index$i);
                        return;
                   } elseif(
    $checkCount && $i->getCount() < $count) {
                        
    $count -= $i->getCount();
                        
    $inventory->clear($index);
                   } else {
                        
    $inventory->clear($index);
                        return;
                   }
              }
         }
    }

     
    MC ATECH likes this.
  15. MC ATECH

    MC ATECH Baby Zombie

    Messages:
    105
    GitHub:
    mcpeatech
    Will do thanks, again!
     
  16. MC ATECH

    MC ATECH Baby Zombie

    Messages:
    105
    GitHub:
    mcpeatech
    Update: this works perfectly as it should :) Thanks.
     
    HimbeersaftLP likes this.

Share This Page

  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.