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

regenerating blocks

Comments in 'Plugin Development' started by Creeperface, Jun 2, 2015.

  1. Creeperface
    Offline

    Creeperface Notable Member Plugin Developer

    Joined:
    Nov 8, 2014
    Posts:
    1,346
    Plugins:
    4
    Minecraft User:
    CreeperFace
    i need make when player destroyed specified block type so after 30 seconds block appear again at the same coordinates. I know i should use sheduleRepeatingTask but i dont know how to control unknown amount of blocks.

    so base code here:
    PHP:
        private $time;

        public function 
    onRun($ticks){
            if(
    $this->regenerate == true){
                
    $this->time++;
                if(
    $this->time == 30){
                    
    $level Server::getInstance()->getLevelByName("level");
                    
    $level->setBlockIdAt($x$y$z57);
                }
            }
        }
        public function 
    onBlockBreak(BlockBreakEvent $e){
            
    $b $e->getBlock();
            if(
    $b->getId() == 57){
                
    $this->regenerate true;
            }
        }
  2. Creeperface
    Offline

    Creeperface Notable Member Plugin Developer

    Joined:
    Nov 8, 2014
    Posts:
    1,346
    Plugins:
    4
    Minecraft User:
    CreeperFace
    nobody knows?
  3. PEMapModder
    Offline

    PEMapModder Notable Member Plugin Developer

    Joined:
    Oct 9, 2013
    Posts:
    7,294
    Plugins:
    11
    Minecraft User:
    PEMapModder
    Main class that extends pocketmine\plugin\PluginBase and implements pocketmine\event\Listener:
    PHP:
    /** @var BlockRestoreTask */
    private $task;
    public function 
    onEnable(){
        
    $this->getServer()->getScheduler()->scheduleRepeatingTask($this->task = new BlockRestoreTask($this), 20);
        
    $this->getServer()->getPluginManager()->registerEvents($this$this);
    }
    /**
    * @param BlockBreakEvent
    * @priority MONITOR
    * @ignoreCancelled true
    */
    public function onBreakBlock(BlockBreakEvent $ev){
        
    // MONITOR means the event has been finalized
        // you can do an if-check for the whole function if necessary
        
    $this->task->push($ev->getBlock());
    }
    BlockRestoreTask that extends pocketmine\scheduler\PluginTask:
    PHP:
    private $pool = [];
    public function 
    onRun($currentTick){
        while((
    $block $this->next($currentTick) !== null){
            if(
    $block->isValid()){ // don't do anything if the level is unloaded
                
    $block->getLevel()->setBlock($block$block); // add the $update parameter if needed
            
    }
        }
    }
    public function 
    onCancel(){ // restore everything changed when the plugin is disabled
        
    foreach($this->pool as $string){
            
    $block $this->unhashString($string);
            if(
    $block->isValid()){ // don't do anything if the level is unloaded
                
    $block->getLevel()->setBlock($block$block); // add the $update parameter if needed
            
    }
        }
    }
    public function 
    push(Block $block){
        
    $restoreTick $this->getOwner()->getServer()->getTick() + 600// 600 means 600 ticks, i.e. 30 seconds. Change it if you like
        
    $this->pool[] = "$restoreTick:$block->x:$block->y:$block->z:{$block->getId()}:{$block->getDamage()}:{$block->getLevel()->getName()}"// we do not want to hold the instances, especially those holding a Level instance, because it will cause server issues if the level is unloaded
    }
    public function 
    next($currentTick){
        
    $nextTick = (int) strstr($this->pool[0], ":"true);
        if(
    $nextTick <= $currentTick){
            return 
    $this->unhashBlock(array_shift($this->pool));
        }
        return 
    null;
    }
    private function 
    unhashBlock($string){
        list(, 
    $x$y$z$id$damage$lvName) = explode(":"$string);
        return 
    Block::get($id$damage, new Position($x$y$z$this->getOwner()->getServer()->getLevelByName($lvName)));
    }
    The above code is in the public domain, i.e. nobody has patent to use or own it, but please, don't use that code if you don't understand all of it. You are welcome to ask any questions about it, but don't copy it if you don't understand what I am doing.
  4. Tethered_
    Offline

    Tethered_ Active Member Plugin Developer

    Joined:
    Jun 24, 2014
    Posts:
    178
    Plugins:
    2
    Minecraft User:
    Frostbyte58
  5. Creeperface
    Offline

    Creeperface Notable Member Plugin Developer

    Joined:
    Nov 8, 2014
    Posts:
    1,346
    Plugins:
    4
    Minecraft User:
    CreeperFace
    THX
  6. Creeperface
    Offline

    Creeperface Notable Member Plugin Developer

    Joined:
    Nov 8, 2014
    Posts:
    1,346
    Plugins:
    4
    Minecraft User:
    CreeperFace
    Thanks to you, I better understand what makes a scheduler
  7. PEMapModder
    Offline

    PEMapModder Notable Member Plugin Developer

    Joined:
    Oct 9, 2013
    Posts:
    7,294
    Plugins:
    11
    Minecraft User:
    PEMapModder
    This is a good example of using classes.
  8. Creeperface
    Offline

    Creeperface Notable Member Plugin Developer

    Joined:
    Nov 8, 2014
    Posts:
    1,346
    Plugins:
    4
    Minecraft User:
    CreeperFace
    but you set scheduler only 1x per second so is it right? or should i set it to per each tick?
  9. Tethered_
    Offline

    Tethered_ Active Member Plugin Developer

    Joined:
    Jun 24, 2014
    Posts:
    178
    Plugins:
    2
    Minecraft User:
    Frostbyte58
    Calling it once per tick would make It check 20 times per second, possibly causing lag
    Creeperface likes this.
  10. Creeperface
    Offline

    Creeperface Notable Member Plugin Developer

    Joined:
    Nov 8, 2014
    Posts:
    1,346
    Plugins:
    4
    Minecraft User:
    CreeperFace
    yes but when lots of players are breaking blocks.. but i think it doesn´t metter if a check it per tick or per second.
  11. PEMapModder
    Offline

    PEMapModder Notable Member Plugin Developer

    Joined:
    Oct 9, 2013
    Posts:
    7,294
    Plugins:
    11
    Minecraft User:
    PEMapModder
    The task checks if it needs to restore, not if there are block breaks.
    After the block is broken, a string representing the information of the original block (coords, level name, id, damage, time/tick to restore) is pushed into the BlockRestoreTask->pool array. Every 20 ticks, the task checks if the next (i.e. first) block in the array should be restored. If yes, restore it and move to the next block (shift the restored one out of the array first, as is array_shift). (That's why I used while, such that multiple restores can be executed one task run) If no, exit the function and wait until the next task run.
    If the plugin is going to be disabled, let's not wait but restore all the pending changes in the pool all-in-once.
    Creeperface likes this.
  12. Creeperface
    Offline

    Creeperface Notable Member Plugin Developer

    Joined:
    Nov 8, 2014
    Posts:
    1,346
    Plugins:
    4
    Minecraft User:
    CreeperFace
    I know but i think it can restore only one block per second right?
  13. PEMapModder
    Offline

    PEMapModder Notable Member Plugin Developer

    Joined:
    Oct 9, 2013
    Posts:
    7,294
    Plugins:
    11
    Minecraft User:
    PEMapModder
    No. It is a while block, not an if block.
    If it is an if block, it will only run once or not run at all.
    If it is is a while block, if the condition is true, it will run the block, and check the condition again, and run again, keep looping until the condition is false.
    Creeperface likes this.

Share This Page

Advertisement