Advertisement
  1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.

Solved __destruct is being called twice

Comments in 'Plugin Development' started by Tim // robske Büba, Mar 10, 2016.

  1. Tim // robske Büba
    Offline

    Tim // robske Büba Notable Member

    Joined:
    Feb 26, 2014
    Posts:
    606
    Minecraft User:
    robske_110
    PHP:
    class InventoryManager extends Main implements Listener{
        public 
    $WatchWorld;
        public 
    $savedInv;
        public 
    $savedExp//TODO
        
    public $savedHunger//TODO
        
    public $savedHealth//TODO

        
    public function __construct($WatchWorld NULL){
            if(
    $WatchWorld == NULL){
                
    InventoryManager::__destruct();
            }
            
    $this->WatchWorld $WatchWorld;
        }

        public function 
    __destruct(){
            echo(
    "E_InventoryManagerCalled_WithNoWorldToWatch \n");
        }
    Everything works, except that it (if i just do
    PHP:
     new InventoryManager() 
    ) it shows
    Code:
    E_InventoryManagerCalled_WithNoWorldToWatch
    E_InventoryManagerCalled_WithNoWorldToWatch
    
    on the console!
    Why twice?
  2. PEMapModder
    Offline

    PEMapModder Notable Member Plugin Developer

    Joined:
    Oct 9, 2013
    Posts:
    7,294
    Plugins:
    11
    Minecraft User:
    PEMapModder
    http://php.net/manual/en/language.oop5.decon.php#object.destruct
    If you are calling the __destruct() method yourself, why don't you call it something else? Otherwise, the __destruct() method will be implicitly called by the PHP engine at undefined time after no (strong) references to it remain.
    Tim // robske Büba likes this.
  3. Tim // robske Büba
    Offline

    Tim // robske Büba Notable Member

    Joined:
    Feb 26, 2014
    Posts:
    606
    Minecraft User:
    robske_110
    Lol i don't fully understand that
  4. Tim // robske Büba
    Offline

    Tim // robske Büba Notable Member

    Joined:
    Feb 26, 2014
    Posts:
    606
    Minecraft User:
    robske_110
    And just to clarify: I'm trying to completly DESTROY the class
  5. PEMapModder
    Offline

    PEMapModder Notable Member Plugin Developer

    Joined:
    Oct 9, 2013
    Posts:
    7,294
    Plugins:
    11
    Minecraft User:
    PEMapModder
    You do not need to destroy the classobject (you cannot destroy a class, you can only destroy an instance of the class! You can kill all dodo birds, but you can't wipe out the fact that dodo birds once existed on planet earth!). Just remove all your references to it. PHP will automatically collect this instance from memory when the time is right.
    minebuilder0110 likes this.
  6. Tim // robske Büba
    Offline

    Tim // robske Büba Notable Member

    Joined:
    Feb 26, 2014
    Posts:
    606
    Minecraft User:
    robske_110
    I don't like php to handle this...
    Because it is an listener class. And it would still have registered li
    LOL Now i know why php even removes it, because it doesn't do anything: I forgot to add register events
  7. PEMapModder
    Offline

    PEMapModder Notable Member Plugin Developer

    Joined:
    Oct 9, 2013
    Posts:
    7,294
    Plugins:
    11
    Minecraft User:
    PEMapModder
    No. As long as another object still holds (strong) reference to this object, it must not be destroyed. As long as no other objects hold reference to this object, it must be destroyed. (But whether it does or not, it makes no difference to you, because you don't have reference to it anyway)
  8. Tim // robske Büba
    Offline

    Tim // robske Büba Notable Member

    Joined:
    Feb 26, 2014
    Posts:
    606
    Minecraft User:
    robske_110
    Ok, so I have an problem here
    I will post full code now for better understandiation (DAFUC)
    PHP:
    <?php
    namespace robske_110\ServerCore;

    use 
    pocketmine\event\entity\EntityLevelChangeEvent;
    use 
    pocketmine\event\Listener;
    use 
    pocketmine\Player;
    use 
    pocketmine\utils\TextFormat;
    use 
    pocketmine\item\Item;

    class 
    InventoryManager extends Main implements Listener{
        public 
    $WatchWorld;
        public 
    $savedInv;
        public 
    $savedExp//TODO::WaitingForPMtoIMPLEMENTshit
        
    public $savedHunger//TODO::WaitingForPMtoIMPLEMENTshit
        
    public $savedHealth//TODO

        
    public function __construct($WatchWorld NULL){
           
    $this->getServer()->getPluginManager()->registerEvents($this$this);
            if(
    $WatchWorld == NULL){
                
    InventoryManager::__destruct();
            }
            
    $this->WatchWorld $WatchWorld;
        }

        public function 
    __destruct(){
            echo(
    "E_InventoryManagerCalled_WithNoWorldToWatch \n");
        }

        public function 
    LevelChangeEvent(EntityLevelChangeEvent $event){
            if(
    $event->getEntity() instanceof Player){
                
    $playerName $event->getEntity()->getName();
                
    $currentInv $this->getServer()->getPlayer($playerName)->getInventory();
                if(
    $event->getOrigin()->getName() == $this->WatchWorld){
                    
    $newCfgInv = [];

                    
    //Save current INV
                    
    foreach($currentInv->getContents() as $contents){
                            if(
    $contents->getId() !== and $contents->getCount() > 0){
                            
    $newCfgInv[] = [$contents->getId(), $contents->getDamage(), $contents->getCount()];
                        }
                    }

                    
    //Send blank INV
                    
    $savedInv[$playerName] = $newCfgInv;
                    
    $currentInv->setContents([]);
                    
    $this->saveCustomConfig();
                }
                if(
    $event->getTarget()->getName() == $this->WatchWorld{
                    
    $currentInv->setContents([]);
                    
    $setInv = [];

                    
    //CreateNewCfg
                    
    if(!isset($this->savedInv[$playerName])){
                        
    $this->savedInv[$playerName] = [];
                    }

                    foreach(
    $this->savedInv[$playerName] as $inv){
                        
    $setInv[] = Item::get($inv[0], $inv[1], $inv[2]);
                    }
                    
    $currentInv->setContents($setInv);
                }
            }
        }

        public function 
    saveCustomConfig(){}
        public function 
    readCustomConfig(){}
    }
    I just want to destroy the class if it has nothing to do! (It has nothing to do if $WatchWorld == NULL!)
  9. Tim // robske Büba
    Offline

    Tim // robske Büba Notable Member

    Joined:
    Feb 26, 2014
    Posts:
    606
    Minecraft User:
    robske_110
    Oh, and main
    class Main extends PluginBase implements Listener{
  10. PEMapModder
    Offline

    PEMapModder Notable Member Plugin Developer

    Joined:
    Oct 9, 2013
    Posts:
    7,294
    Plugins:
    11
    Minecraft User:
    PEMapModder
    Off-topic: you know that hunger is implemented on PocketMine, right?
  11. Tim // robske Büba
    Offline

    Tim // robske Büba Notable Member

    Joined:
    Feb 26, 2014
    Posts:
    606
    Minecraft User:
    robske_110
    No I didn't know it
  12. Tim // robske Büba
    Offline

    Tim // robske Büba Notable Member

    Joined:
    Feb 26, 2014
    Posts:
    606
    Minecraft User:
    robske_110
    Anyone gonna help me now?
  13. PEMapModder
    Offline

    PEMapModder Notable Member Plugin Developer

    Joined:
    Oct 9, 2013
    Posts:
    7,294
    Plugins:
    11
    Minecraft User:
    PEMapModder
    What are you trying to do at all? I am telling you that you cannot destroy an object if another class holds reference to the object.
  14. Tim // robske Büba
    Offline

    Tim // robske Büba Notable Member

    Joined:
    Feb 26, 2014
    Posts:
    606
    Minecraft User:
    robske_110
    No other object holds an reference to the class (Main does)
  15. Tim // robske Büba
    Offline

    Tim // robske Büba Notable Member

    Joined:
    Feb 26, 2014
    Posts:
    606
    Minecraft User:
    robske_110
    PHP:
    <?php
    namespace robske_110\ServerCore;

    use 
    pocketmine\event\entity\EntityLevelChangeEvent;
    use 
    pocketmine\event\Listener;
    use 
    pocketmine\Player;
    use 
    pocketmine\utils\TextFormat;
    use 
    pocketmine\item\Item;

    class 
    InventoryManager extends Main implements Listener{
        public 
    $WatchWorld;
        public 
    $savedInv;
        public 
    $savedExp//TODO::WaitingForPMtoIMPLEMENTshit
        
    public $savedHunger//TODO
        
    public $savedHealth//TODO

        
    public function __construct($WatchWorld NULL){

            if(
    $WatchWorld == NULL){
                
    #InventoryManager::__destruct(); //PHP will destruct this class by itself
            
    }
            else
            {
                
    $this->getServer()->getPluginManager()->registerEvents($this$this);
                
    $this->WatchWorld $WatchWorld;
            }
        }

        public function 
    __destruct(){
            echo(
    "E_InventoryManagerCalled_WithNoWorldToWatch \n");
        }

        public function 
    LevelChangeEvent(EntityLevelChangeEvent $event){
            if(
    $this->WatchWorld == NULL){
                
    self::__destruct(); //This line is not excepted to be reached!
            
    }
            if(
    $event->getEntity() instanceof Player){
                
    $playerName $event->getEntity()->getName();
                
    $currentInv $this->getServer()->getPlayer($playerName)->getInventory();
                if(
    $event->getOrigin()->getName() == $this->WatchWorld){
                    
    $newCfgInv = [];

                    
    //Save current INV
                    
    foreach($currentInv->getContents() as $contents){
                            if(
    $contents->getId() !== and $contents->getCount() > 0){
                            
    $newCfgInv[] = [$contents->getId(), $contents->getDamage(), $contents->getCount()];
                        }
                    }

                    
    //Send blank INV
                    
    $savedInv[$playerName] = $newCfgInv;
                    
    $currentInv->setContents([]);
                    
    $this->saveCustomConfig();
                }
                if(
    $event->getTarget()->getName() == $this->WatchWorld){
                    
    $currentInv->setContents([]);
                    
    $setInv = [];

                    
    //CreateNewCfg
                    
    if(!isset($this->savedInv[$playerName])){
                        
    $this->savedInv[$playerName] = [];
                    }

                    foreach(
    $this->savedInv[$playerName] as $inv){
                        
    $setInv[] = Item::get($inv[0], $inv[1], $inv[2]);
                    }
                    
    $currentInv->setContents($setInv);
                }
            }
        }

        public function 
    saveCustomConfig(){}
        public function 
    readCustomConfig(){}
    }
  16. Tim // robske Büba
    Offline

    Tim // robske Büba Notable Member

    Joined:
    Feb 26, 2014
    Posts:
    606
    Minecraft User:
    robske_110
    So, this is the updated code
  17. PEMapModder
    Offline

    PEMapModder Notable Member Plugin Developer

    Joined:
    Oct 9, 2013
    Posts:
    7,294
    Plugins:
    11
    Minecraft User:
    PEMapModder
    You registerEvents() right? Then PocketMine holds a reference to the object. If you really made that object null, PocketMine will crash because it already registered your Listener to event handler lists and expect to call them. Nulling the object after registering Listener is like issuing a cheque but then withdrawing all money from the bank account.
    jojoe77777 likes this.
  18. Tim // robske Büba
    Offline

    Tim // robske Büba Notable Member

    Joined:
    Feb 26, 2014
    Posts:
    606
    Minecraft User:
    robske_110
    Look clearly at the code in the __constuct
    It does only register the listeners if WatchWorlds != NULL and,if it is null, it will do nothing causing php to destruct the class
  19. Tim // robske Büba
    Offline

    Tim // robske Büba Notable Member

    Joined:
    Feb 26, 2014
    Posts:
    606
    Minecraft User:
    robske_110
    It is doing it now :) Look at the TITLE : SOLVED#
    The console show that:
    Code:
    [09:49:23] [Server thread/INFO]: Enabling ServerCore v1.3.3ALPHA-2.3b1
    E_InventoryManagerCalled_WithNoWorldToWatch
    
  20. Tim // robske Büba
    Offline

    Tim // robske Büba Notable Member

    Joined:
    Feb 26, 2014
    Posts:
    606
    Minecraft User:
    robske_110
    It is immediately destructing it
    PEMapModder likes this.

Share This Page

Advertisement