Adding a delayed task to a plugin

We will now add a warp delay to the Warper plugin. This will require players to stand still after running the warp or home commands. If they move too much, the warp task will be canceled and they will not be teleported. This will prevent players from teleporting when someone is attacking them or they are falling to their death.

If you haven't already, add a variable of warpDelay in the main class. This is given in the following line of code:

static int warpDelay = 5; //in seconds

This time will be in seconds. We will multiply it by 20 later in the code to calculate the number of ticks by which we wish to delay the task.

We will also need to keep track of the player who is in the process of warping so that we can check whether they are moving. Add another variable of the current warpers. This will be a HashMap so that we can keep track of which players are warping and the tasks that will be run to teleport them. That way, if a specific player moves, we can get their task and cancel it. This is shown in the following code:

private static HashMap<String, BukkitTask>warpers = new HashMap<>();//Player UUID -> Warp Task

The code contains three new methods, which must be added to the main class in order to schedule the warp task, check whether a player has a warp task, and cancel a player's warp task. The code is as follows:

/**
 * Schedules a Player to be teleported after the delay time
 *
 * @param player The Player being teleported
 * @param loc The location of the destination
 */
public static void scheduleWarp(final Player player, final Location loc) {
  //Inform the player that they will be teleported
  player.sendMessage("You will be teleported in "+ warpDelay + " seconds");

  //Create a task to teleport the player
  BukkitRunnable bRunnable = new BukkitRunnable() {
    @Override
    public void run() {
      player.teleport(loc); 

      //Remove the player as a warper because they have already beenteleported
      warpers.remove(player.getName());
    }
  };

  //Schedule the task to run later
  BukkitTask task = bRunnable.runTaskLater(plugin, 20L * warpDelay);

  //Keep track of the player and their warp task
  warpers.put(player.getUniqueId().toString(), task);
}

/**
 * Returns true if the player is waiting to be teleported
 *
 * @param player The UUID of the Player in question
 * @return true if the player is waiting to be warped
 */
public static boolean isWarping(String player) {
  return warpers.containsKey(player);
}

/**
 * Cancels the warp task for the given player
 *
 * @param player The UUID of the Player whose warp task will be canceled
 */
public static void cancelWarp(String player) {
  //Check if the player is warping
  if (isWarping(player)) {
    //Remove the player as a warper
    //Cancel the task so that the player is not teleported
    warpers.remove(player).cancel();
  }
}

In the scheduleTeleportation method, note that both the player and loc variables are final. This is required to use the variables within the BukkitRunnable class. This must be done to ensure that the values will not change before the task is run. Also, note that the runTaskLater method call returns a BukkitTask, which is what we save inside the HashMap. You can see why it is saved by looking at the cancelWarp method, which removes the BukkitTask of the given player and then invokes the cancel method on it before it is executed.

In both the WarpCommand and HomeCommand classes, we teleport a player. We want to remove that line and replace it with a method call to scheduleTeleportation. The feature addition is nearing completion. All that is left to do is calling the cancelWarp method when a warper moves. For this, add an event listener to listen for the player move event. This can be seen in the following code:

package com.codisimus.warper;

import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerMoveEvent;

public class WarperPlayerListener implements Listener {
  @EventHandler (priority = EventPriority.MONITOR)
  public void onPlayerMove(PlayerMoveEvent event) {
    Player player = event.getPlayer();
    String playerUuid = player.getUniqueId().toString();

    //We only care about this event if the player is flagged aswarping
    if (Warper.isWarping(playerUuid)) {
      //Compare the block locations rather than the player locations
      //This allows a player to move their head without canceling thewarp
      Block blockFrom = event.getFrom().getBlock();
      Block blockTo = event.getTo().getBlock();

      //Cancel the warp if the player moves to a different block
      if (!blockFrom.equals(blockTo)) {
        Warper.cancelWarp(playerUuid);
        player.sendMessage("Warping canceled because you moved!");
      }
    }
  }
}

Do not forget to register the event within the onEnable method.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.220.16.184