From beb224fa1e95ab2f9a36c323d40b314cc1ef0277 Mon Sep 17 00:00:00 2001 From: Brettflan Date: Wed, 14 Dec 2011 07:18:18 -0600 Subject: [PATCH] Player teleports are now monitored and (if necessary) redirected inside the border; sadly this doesn't prevent the original target chunk from being loaded/generated (which would be nice if it's outside your border), but at least the player never ends up there now for even a fraction of a second --- .../wimbli/WorldBorder/BorderCheckTask.java | 82 ++++++++++--------- .../wimbli/WorldBorder/WBPlayerListener.java | 19 +++++ src/com/wimbli/WorldBorder/WorldBorder.java | 16 ++-- 3 files changed, 69 insertions(+), 48 deletions(-) create mode 100644 src/com/wimbli/WorldBorder/WBPlayerListener.java diff --git a/src/com/wimbli/WorldBorder/BorderCheckTask.java b/src/com/wimbli/WorldBorder/BorderCheckTask.java index 1bf5721..2d5985b 100644 --- a/src/com/wimbli/WorldBorder/BorderCheckTask.java +++ b/src/com/wimbli/WorldBorder/BorderCheckTask.java @@ -20,58 +20,64 @@ public class BorderCheckTask implements Runnable public void run() { -// long startTime = Config.Now(); // for monitoring plugin efficiency if (server == null) - { -// Config.timeUsed += Config.Now() - startTime; // for monitoring plugin efficiency return; - } Player[] players = server.getOnlinePlayers(); for (int i = 0; i < players.length; i++){ - if (players[i] == null || !players[i].isOnline()) continue; + checkPlayer(players[i], null, false); + } + } - Location loc = players[i].getLocation(); - if (loc == null) continue; + // set targetLoc only if not current player location; set returnLocationOnly to true to have new Location returned if they need to be moved to one, instead of directly handling it + public static Location checkPlayer(Player player, Location targetLoc, boolean returnLocationOnly) + { + if (player == null || !player.isOnline()) return null; - World world = loc.getWorld(); - if (world == null) continue; - BorderData border = Config.Border(world.getName()); - if (border == null) continue; + Location loc = (targetLoc == null) ? player.getLocation() : targetLoc; + if (loc == null) return null; - if (border.insideBorder(loc.getX(), loc.getZ(), Config.ShapeRound())) - continue; + World world = loc.getWorld(); + if (world == null) return null; + BorderData border = Config.Border(world.getName()); + if (border == null) return null; - Location newLoc = newLocation(players[i], loc, border); + if (border.insideBorder(loc.getX(), loc.getZ(), Config.ShapeRound())) + return null; - if (!players[i].isInsideVehicle()) - players[i].teleport(newLoc); - else - { - Vehicle ride = players[i].getVehicle(); - if (ride != null) - { // vehicles need to be offset vertically and have velocity stopped - double vertOffset = ride.getLocation().getY() - loc.getY(); - newLoc.setY(newLoc.getY() + vertOffset); - ride.setVelocity(new Vector(0, 0, 0)); - ride.teleport(newLoc); - } - else - { // if player.getVehicle() returns null (when riding a pig on older Bukkit releases, for instance), player has to be ejected - players[i].leaveVehicle(); - players[i].teleport(newLoc); - } + Location newLoc = newLocation(player, loc, border); + + if (Config.whooshEffect()) + { // show some smoke and play the extinguish sound effect where the player was beyond the border + world.playEffect(loc, Effect.SMOKE, 4); + world.playEffect(loc, Effect.SMOKE, 4); + world.playEffect(loc, Effect.EXTINGUISH, 0); + } + + if (returnLocationOnly) + return newLoc; + + if (!player.isInsideVehicle()) + player.teleport(newLoc); + else + { + Vehicle ride = player.getVehicle(); + if (ride != null) + { // vehicles need to be offset vertically and have velocity stopped + double vertOffset = ride.getLocation().getY() - loc.getY(); + newLoc.setY(newLoc.getY() + vertOffset); + ride.setVelocity(new Vector(0, 0, 0)); + ride.teleport(newLoc); } - - if (Config.whooshEffect()) - { // show some smoke and play the extinguish sound effect where the player was beyond the border - world.playEffect(loc, Effect.SMOKE, 4); - world.playEffect(loc, Effect.SMOKE, 4); - world.playEffect(loc, Effect.EXTINGUISH, 0); + else + { // if player.getVehicle() returns null (when riding a pig on older Bukkit releases, for instance), player has to be ejected + player.leaveVehicle(); + player.teleport(newLoc); } } -// Config.timeUsed += Config.Now() - startTime; // for monitoring plugin efficiency + + return null; } private static Location newLocation(Player player, Location loc, BorderData border) diff --git a/src/com/wimbli/WorldBorder/WBPlayerListener.java b/src/com/wimbli/WorldBorder/WBPlayerListener.java new file mode 100644 index 0000000..2e6d207 --- /dev/null +++ b/src/com/wimbli/WorldBorder/WBPlayerListener.java @@ -0,0 +1,19 @@ +package com.wimbli.WorldBorder; + +import org.bukkit.event.player.PlayerListener; +import org.bukkit.event.player.PlayerTeleportEvent; +import org.bukkit.Location; + + +public class WBPlayerListener extends PlayerListener +{ + @Override + public void onPlayerTeleport(PlayerTeleportEvent event) + { + if (event.isCancelled()) return; + + Location newLoc = BorderCheckTask.checkPlayer(event.getPlayer(), event.getTo(), true); + if (newLoc != null) + event.setTo(newLoc); + } +} diff --git a/src/com/wimbli/WorldBorder/WorldBorder.java b/src/com/wimbli/WorldBorder/WorldBorder.java index 8c2f63f..fe4d0eb 100644 --- a/src/com/wimbli/WorldBorder/WorldBorder.java +++ b/src/com/wimbli/WorldBorder/WorldBorder.java @@ -1,5 +1,7 @@ package com.wimbli.WorldBorder; +import org.bukkit.event.Event; +import org.bukkit.event.Event.Priority; import org.bukkit.Location; import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.plugin.PluginDescriptionFile; @@ -7,6 +9,8 @@ import org.bukkit.plugin.PluginDescriptionFile; public class WorldBorder extends JavaPlugin { + private final WBPlayerListener pl = new WBPlayerListener(); + public void onEnable() { PluginDescriptionFile desc = this.getDescription(); @@ -23,16 +27,8 @@ public class WorldBorder extends JavaPlugin // our one real command, though it does also have aliases "wb" and "worldborder" getCommand("wborder").setExecutor(new WBCommand(this)); -/* // for monitoring plugin efficiency - getServer().getScheduler().scheduleSyncRepeatingTask(this, new Runnable() - { - public long startTime = Config.Now(); - public void run() - { - Config.Log("Running for " + (int)((Config.Now() - startTime) / (60000)) + " minutes, has used total border checking time of " + Config.timeUsed + "ms."); - } - }, 1200, 1200); -*/ + // keep an eye on teleports, to redirect them to a spot inside the border if necessary + getServer().getPluginManager().registerEvent(Event.Type.PLAYER_TELEPORT, pl, Priority.Lowest, this); } public void onDisable()