From 686072b87c828b5871b7596d478f89d8e8fd43d8 Mon Sep 17 00:00:00 2001 From: Brettflan Date: Sat, 30 Mar 2013 02:56:12 -0500 Subject: [PATCH] riding something across the border would double-trigger the border crossing handler since leaving a vehicle fires a teleport event (go figure); fixed Players going through a portal will now no longer be able to generate chunks outside the border; the portal teleport location is re-targeted inside the border to prevent that so that new portals aren't created outside the border added redstone comparator and activator rail to "safe open blocks" list for knockback safe location finder --- .../wimbli/WorldBorder/BorderCheckTask.java | 38 +++++++++++++------ src/com/wimbli/WorldBorder/BorderData.java | 10 ++++- src/com/wimbli/WorldBorder/WBListener.java | 19 ++++++++-- src/com/wimbli/WorldBorder/WorldFileData.java | 2 +- 4 files changed, 52 insertions(+), 17 deletions(-) diff --git a/src/com/wimbli/WorldBorder/BorderCheckTask.java b/src/com/wimbli/WorldBorder/BorderCheckTask.java index 2381b09..8212c44 100644 --- a/src/com/wimbli/WorldBorder/BorderCheckTask.java +++ b/src/com/wimbli/WorldBorder/BorderCheckTask.java @@ -2,12 +2,12 @@ package com.wimbli.WorldBorder; import org.bukkit.ChatColor; import org.bukkit.Effect; -import org.bukkit.entity.Entity; -import org.bukkit.entity.LivingEntity; +//import org.bukkit.entity.Entity; +//import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; import org.bukkit.Location; import org.bukkit.Server; -import org.bukkit.util.Vector; +//import org.bukkit.util.Vector; import org.bukkit.World; @@ -32,12 +32,12 @@ public class BorderCheckTask implements Runnable Player[] players = server.getOnlinePlayers(); for (int i = 0; i < players.length; i++){ - checkPlayer(players[i], null, false); + checkPlayer(players[i], null, false, true); } } // 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) + public static Location checkPlayer(Player player, Location targetLoc, boolean returnLocationOnly, boolean notify) { if (player == null || !player.isOnline()) return null; @@ -56,7 +56,16 @@ public class BorderCheckTask implements Runnable if (Config.isPlayerBypassing(player.getName())) return null; - Location newLoc = newLocation(player, loc, border); + // since we need to forcibly eject players who are inside vehicles, that fires a teleport event (go figure) and + // so would double trigger, so we need to handle it here to prevent sending two messages and two log entries etc. + // see further below for why players in vehicles now have to be ejected + if (player.isInsideVehicle()) + { + player.leaveVehicle(); + return null; + } + + Location newLoc = newLocation(player, loc, border, notify); if (Config.whooshEffect()) { // give some particle and sound effects where the player was beyond the border @@ -71,11 +80,12 @@ public class BorderCheckTask implements Runnable if (returnLocationOnly) return newLoc; + /* // Bukkit team have removed the ability to teleport any entity which has a passenger, causing this to fail horribly now, so... + * // unfortunately until they become sane again we must always eject player from whatever they're riding, which is done above if (!player.isInsideVehicle()) player.teleport(newLoc); else { - /* // Bukkit team have removed the ability to teleport any entity which has a passenger, causing this to fail horribly now, so... Entity ride = player.getVehicle(); if (ride != null) { // vehicles need to be offset vertically and have velocity stopped @@ -89,19 +99,24 @@ public class BorderCheckTask implements Runnable player.leaveVehicle(); player.teleport(newLoc); } - */ // so unfortunately until they become sane again we must always eject player from whatever they're riding player.leaveVehicle(); player.teleport(newLoc); } + */ // and in the meantime, since vehicle ejection is handled in new spot above, we can safely relocate the player at this point + player.teleport(newLoc); return null; } + public static Location checkPlayer(Player player, Location targetLoc, boolean returnLocationOnly) + { + return checkPlayer(player, targetLoc, returnLocationOnly, true); + } - private static Location newLocation(Player player, Location loc, BorderData border) + private static Location newLocation(Player player, Location loc, BorderData border, boolean notify) { if (Config.Debug()) { - Config.LogWarn("Border crossing in \"" + loc.getWorld().getName() + "\". Border " + border.toString()); + Config.LogWarn((notify ? "Border crossing" : "Check was run") + " in \"" + loc.getWorld().getName() + "\". Border " + border.toString()); Config.LogWarn("Player position X: " + Config.coord.format(loc.getX()) + " Y: " + Config.coord.format(loc.getY()) + " Z: " + Config.coord.format(loc.getZ())); } @@ -118,7 +133,8 @@ public class BorderCheckTask implements Runnable if (Config.Debug()) Config.LogWarn("New position in world \"" + newLoc.getWorld().getName() + "\" at X: " + Config.coord.format(newLoc.getX()) + " Y: " + Config.coord.format(newLoc.getY()) + " Z: " + Config.coord.format(newLoc.getZ())); - player.sendMessage(ChatColor.RED + Config.Message()); + if (notify) + player.sendMessage(ChatColor.RED + Config.Message()); return newLoc; } diff --git a/src/com/wimbli/WorldBorder/BorderData.java b/src/com/wimbli/WorldBorder/BorderData.java index bb1efe1..8b21b76 100644 --- a/src/com/wimbli/WorldBorder/BorderData.java +++ b/src/com/wimbli/WorldBorder/BorderData.java @@ -178,6 +178,14 @@ public class BorderData { return insideBorder(loc.getX(), loc.getZ(), Config.ShapeRound()); } + public boolean insideBorder(CoordXZ coord, boolean round) + { + return insideBorder(coord.x, coord.z, round); + } + public boolean insideBorder(CoordXZ coord) + { + return insideBorder(coord.x, coord.z, Config.ShapeRound()); + } public Location correctedPosition(Location loc, boolean round, boolean flying) { @@ -243,7 +251,7 @@ public class BorderData //these material IDs are acceptable for places to teleport player; breathable blocks and water public static final LinkedHashSet safeOpenBlocks = new LinkedHashSet(Arrays.asList( - new Integer[] {0, 6, 8, 9, 27, 28, 30, 31, 32, 37, 38, 39, 40, 50, 55, 59, 63, 64, 65, 66, 68, 69, 70, 71, 72, 75, 76, 77, 78, 83, 90, 93, 94, 96, 104, 105, 106, 115, 131, 132, 141, 142} + new Integer[] {0, 6, 8, 9, 27, 28, 30, 31, 32, 37, 38, 39, 40, 50, 55, 59, 63, 64, 65, 66, 68, 69, 70, 71, 72, 75, 76, 77, 78, 83, 90, 93, 94, 96, 104, 105, 106, 115, 131, 132, 141, 142, 149, 150, 157} )); //these material IDs are ones we don't want to drop the player onto, like cactus or lava or fire or activated Ender portal diff --git a/src/com/wimbli/WorldBorder/WBListener.java b/src/com/wimbli/WorldBorder/WBListener.java index 1f6d064..e785e69 100644 --- a/src/com/wimbli/WorldBorder/WBListener.java +++ b/src/com/wimbli/WorldBorder/WBListener.java @@ -4,22 +4,33 @@ import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; import org.bukkit.event.player.PlayerTeleportEvent; +import org.bukkit.event.player.PlayerPortalEvent; import org.bukkit.event.world.ChunkLoadEvent; import org.bukkit.Location; public class WBListener implements Listener { - @EventHandler(priority = EventPriority.LOWEST) + @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) public void onPlayerTeleport(PlayerTeleportEvent event) { - if (event.isCancelled()) return; - // if knockback is set to 0, simply return if (Config.KnockBack() == 0.0) return; - Location newLoc = BorderCheckTask.checkPlayer(event.getPlayer(), event.getTo(), true); + Location newLoc = BorderCheckTask.checkPlayer(event.getPlayer(), event.getTo(), true, true); + if (newLoc != null) + event.setTo(newLoc); + } + + @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) + public void onPlayerPortal(PlayerPortalEvent event) + { + // if knockback is set to 0, simply return + if (Config.KnockBack() == 0.0) + return; + + Location newLoc = BorderCheckTask.checkPlayer(event.getPlayer(), event.getTo(), true, false); if (newLoc != null) event.setTo(newLoc); } diff --git a/src/com/wimbli/WorldBorder/WorldFileData.java b/src/com/wimbli/WorldBorder/WorldFileData.java index b667f3e..4569b72 100644 --- a/src/com/wimbli/WorldBorder/WorldFileData.java +++ b/src/com/wimbli/WorldBorder/WorldFileData.java @@ -42,7 +42,7 @@ public class WorldFileData if (possible.exists() && possible.isDirectory()) { newData.regionFolder = possible; - continue; + break; } } if (!newData.regionFolder.exists() || !newData.regionFolder.isDirectory())