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.
18.220.16.184