Tutorial Using tasks

Discussion in 'Resources' started by Jack Noordhuis, Feb 15, 2019.

  1. Jack Noordhuis

    Jack Noordhuis Zombie Pigman Poggit Reviewer Verified

    Messages:
    620
    GitHub:
    JackNoordhuis
    Introduction
    I've seen a lot of plugin developers confused with how to correctly use a task, and even more so since the recent changes where each plugin has its own scheduler. This post aims to demonstrate how to create and use each task type.

    When you register a task you need access to your main plugins context (the class extending pocketmine\plugin\PluginBase) or a reference to your plugins own scheduler. For the duration of this post, we'll assume we are working from within the main plugin class context.

    Repeating Tasks
    The most commonly used task (from my observations) is the repeating task. The method signature for scheduling a repeating task is as follows:
    PHP:
    TaskScheduler::scheduleRepeatingTask(\pocketmine\task\Task $taskint $period);
    PHP:
    public function onEnable(){
       
    $this->getScheduler()->scheduleRepeatingTask(new class extends \pocketmine\scheduler\Task{
          public function 
    onRun(int $currentTick) : void{
             
    //some code here to repeat every 20 ticks (1 second)
          
    }
       }, 
    20); //period/interval
    }
    This code will schedule a task to repeat every 20 ticks until cancelled, or the server stops. For a server running at 20 TPS, this means every second this task will be run. If your server is 'lagging' (below 20 TPS) then you will have to check within the task to get the real time between executions.

    Delayed Tasks
    A delayed task only runs once after a delay specified in ticks (same pitfall as repeating tasks if the server TPS is below 20). The method signature for scheduling a delayed task is as follows:
    PHP:
    TaskScheduler::scheduleDelayedTask(\pocketmine\task\Task $taskint $period);
    PHP:
    public function onEnable(){
       
    $this->getScheduler()->scheduleDelayedTask(new class extends \pocketmine\scheduler\Task{
          public function 
    onRun(int $currentTick) : void{
             
    //some code here to run after 20 ticks (1 second)
          
    }
       }, 
    20); //delay
    }
    This code schedules a task to execute once after 20 ticks have passed, the task will not execute if it is cancelled or the server stops before the number of ticks specified have passed.

    Instant Tasks
    An instant task (not really instant) is run at the next scheduler heartbeat, meaning it is not guaranteed it will be run on the current tick or the next tick. If you know your way around PocketMine's internals you can deliberately schedule the task before or after the current scheduler heartbeat has been executed to achieve the desired behaviour.

    This tasks usage has become more common in throughout the 3.x.x line of releases as it is currently not possible to kick players within events, you must kick players outside of the execution of events to avoid breaking the execution of the current tick. The method signature for scheduling an instant task is as follows:
    PHP:
    TaskScheduler::scheduleTask(\pocketmine\task\Task $task);
    PHP:
    public function onEnable(){
       
    $this->getScheduler()->scheduleTask(new class extends \pocketmine\scheduler\Task{
          public function 
    onRun(int $currentTick) : void{
             
    //some code here to run on the next scheduler heartbeat (this tick or the next tick)
          
    }
       });
    }
    The above code will schedule a task to run at the next scheduler heartbeat.

    Delayed Repeating Tasks
    A delayed repeating task does as you might imagine -- schedules a repeating task to start with a delay.
    The method signature for scheduling adelayed repeating task is as follows:
    PHP:
    TaskScheduler::scheduleDelayedRepeatingTask(\pocketmine\task\Task $taskint $delayint $period);
    PHP:
    public function onEnable(){
       
    $this->getScheduler()->scheduleDelayedRepeatingTask(new class extends \pocketmine\scheduler\Task{
          public function 
    onRun(int $currentTick) : void{
             
    //some code here to run after 20 ticks (1 second) have passed, every 20 ticks (1 second)
          
    }
       }, 
    20,20); //delay, period/interval
    }
    This code schedules a task to start repeating every 20 ticks ONCE 20 ticks have passed (a regular repeating task starts execution at the next scheduler heartbeat).

    Closure Tasks
    A closure task is a handy alternative to using the traditional class-extending \pocketmine\scheduler\Task method and provides somewhat similar functionality to the old callback task. We can just specify the code to run, schedule the task and be on our way rather than having to define a new class. We can use a closure task for any one of the four scheduler methods described above (repeating, delayed, instant and delayed repeating). An example of each of the task scheduler methods are in the spoilers below:
    PHP:
    public function onEnable(){
       
    $this->getScheduler()->scheduleRepeatingTask(new ClosureTask(
          function(
    int $currentTick){
             
    //some code here to repeat every 20 ticks (1 second)
          
    }
       ), 
    20);
    }
    PHP:
    public function onEnable(){
       
    $this->getScheduler()->scheduleDelayedTask(new ClosureTask(
          function(
    int $currentTick){
             
    //some code here to run after 20 ticks (1 second)
          
    }
       ), 
    20);
    }
    PHP:
    public function onEnable(){
       
    $this->getScheduler()->scheduleTask(new ClosureTask(
          function(
    int $currentTick){
             
    //some code here to run on the next scheduler heartbeat (this tick or the next tick)
          
    }
       ));
    }
    An instant closure task is useful for kicking players during events, by kicking the player when the task is run at the next scheduler heartbeat we avoid breaking the player's connection state mid-tick.
    PHP:
    public function onChat(\pocketmine\event\player\PlayerChatEvent $event){
       
    $player $event->getPlayer(); //get the player into its own variable to avoid potentialy leaking the event object
       
    $this->getScheduler()->scheduleTask(new ClosureTask(
          function(
    int $currentTick) use($player){
             
    $player->kick();
          }
       ));
    }
    PHP:
    public function onEnable(){
       
    $this->getScheduler()->scheduleDelayedRepeatingTask(new ClosureTask(
          function(
    int $currentTick){
             
    //some code here to run after 20 ticks (1 second) have passed, every 20 ticks (1 second)
          
    }
       ), 
    2020);
    }
     
    Last edited: Feb 17, 2019
    Clik, DrakerZR, Minetron26 and 4 others like 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.