Tutorial How to close a Tile (automatically) when the player done doing FakeChest things

Discussion in 'Resources' started by instantlyta, Nov 29, 2017.

  1. instantlyta

    instantlyta Slime

    Messages:
    91
    GitHub:
    intagaming
    There was a problem with this thread: Remove tile
    PHP:
    /** @var InventoryCloseEvent $event */
    $tile $event->getInventory()->getHolder();
    $players $event->getInventory()->getViewers();
    $block Block::get(Block::AIR);
    $block->$tile->x;
    $block->$tile->y;
    $block->$tile->z;
    $block->level $tile->getLevel();
    $tile->getLevel()->sendBlocks($players, [$block]);
    $tile->close();
    If you look closely to the Player.php->handleContainerClose(), you see that the event called "InventoryCloseEvent" is triggered at these lines:
    PHP:
            if(isset($this->windowIndex[$packet->windowId])){
                
    $this->server->getPluginManager()->callEvent(new InventoryCloseEvent($this->windowIndex[$packet->windowId], $this));
                
    $this->removeWindow($this->windowIndex[$packet->windowId]);
                return 
    true;
    So, if you try to use $tile->close() like the code in the topic above, this happen:
    PHP:
    ErrorException"Undefined offset: 3" (EXCEPTIONin "src/pocketmine/Player" at line 2826
    Note: the number "3" and the line "2826" may vary. Basically this is the line 2826 and its neighbors:
    upload_2017-11-29_18-51-45.png
    Conclusion: The window had been removed. Where?
    Chest.php, an inheritance of Tile.php:
    PHP:
    public function close() : void{
            if(
    $this->closed === false){
                
    $this->inventory->removeAllViewers(true);
    Which triggers:
    upload_2017-11-29_18-54-36.png
    As you can see, the window had been removed in the close() function, which returns no error. But the code continues at the line 2826 on Player.php, causing the code to be broken and cancel itself. Although this error does not affect the functionality of the plugin.

    So, what do we do?
    I came up with the idea of removing the player from the viewers of the ChestInventory. Let me know if you have a better way to workaround this.

    PHP:
    //$event instanceof InventoryCloseEvent
    $tile->getInventory()->onClose($event->getPlayer());
    $tile->close();
    Which, in the end, triggers the unset function on BaseInventory.php:
    PHP:
    public function onClose(Player $who) : void{
        unset(
    $this->viewers[spl_object_hash($who)]);
    }
    Done. Good luck coding.
     
    Last edited: Nov 29, 2017
  2. SOFe

    SOFe Administrator Staff Member PMMP Team Poggit Admin

    Messages:
    1,869
    GitHub:
    sof3
    I haven't been playing for a long time, so I don't know if what you're saying is correct, but this is certainly a nice demonstration of debugging :)
     

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.