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
This commit is contained in:
Brettflan 2013-03-30 02:56:12 -05:00
parent 1c950228d7
commit 686072b87c
4 changed files with 52 additions and 17 deletions

View File

@ -2,12 +2,12 @@ package com.wimbli.WorldBorder;
import org.bukkit.ChatColor; import org.bukkit.ChatColor;
import org.bukkit.Effect; import org.bukkit.Effect;
import org.bukkit.entity.Entity; //import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity; //import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.Server; import org.bukkit.Server;
import org.bukkit.util.Vector; //import org.bukkit.util.Vector;
import org.bukkit.World; import org.bukkit.World;
@ -32,12 +32,12 @@ public class BorderCheckTask implements Runnable
Player[] players = server.getOnlinePlayers(); Player[] players = server.getOnlinePlayers();
for (int i = 0; i < players.length; i++){ 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 // 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; if (player == null || !player.isOnline()) return null;
@ -56,7 +56,16 @@ public class BorderCheckTask implements Runnable
if (Config.isPlayerBypassing(player.getName())) if (Config.isPlayerBypassing(player.getName()))
return null; 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()) if (Config.whooshEffect())
{ // give some particle and sound effects where the player was beyond the border { // give some particle and sound effects where the player was beyond the border
@ -71,11 +80,12 @@ public class BorderCheckTask implements Runnable
if (returnLocationOnly) if (returnLocationOnly)
return newLoc; 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()) if (!player.isInsideVehicle())
player.teleport(newLoc); player.teleport(newLoc);
else 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(); Entity ride = player.getVehicle();
if (ride != null) if (ride != null)
{ // vehicles need to be offset vertically and have velocity stopped { // vehicles need to be offset vertically and have velocity stopped
@ -89,19 +99,24 @@ public class BorderCheckTask implements Runnable
player.leaveVehicle(); player.leaveVehicle();
player.teleport(newLoc); player.teleport(newLoc);
} }
*/ // so unfortunately until they become sane again we must always eject player from whatever they're riding
player.leaveVehicle(); player.leaveVehicle();
player.teleport(newLoc); 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; 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()) 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())); 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()) 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())); 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; return newLoc;
} }

View File

@ -178,6 +178,14 @@ public class BorderData
{ {
return insideBorder(loc.getX(), loc.getZ(), Config.ShapeRound()); 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) 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 //these material IDs are acceptable for places to teleport player; breathable blocks and water
public static final LinkedHashSet<Integer> safeOpenBlocks = new LinkedHashSet<Integer>(Arrays.asList( public static final LinkedHashSet<Integer> safeOpenBlocks = new LinkedHashSet<Integer>(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 //these material IDs are ones we don't want to drop the player onto, like cactus or lava or fire or activated Ender portal

View File

@ -4,22 +4,33 @@ import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority; import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener; import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerTeleportEvent; import org.bukkit.event.player.PlayerTeleportEvent;
import org.bukkit.event.player.PlayerPortalEvent;
import org.bukkit.event.world.ChunkLoadEvent; import org.bukkit.event.world.ChunkLoadEvent;
import org.bukkit.Location; import org.bukkit.Location;
public class WBListener implements Listener public class WBListener implements Listener
{ {
@EventHandler(priority = EventPriority.LOWEST) @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true)
public void onPlayerTeleport(PlayerTeleportEvent event) public void onPlayerTeleport(PlayerTeleportEvent event)
{ {
if (event.isCancelled()) return;
// if knockback is set to 0, simply return // if knockback is set to 0, simply return
if (Config.KnockBack() == 0.0) if (Config.KnockBack() == 0.0)
return; 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) if (newLoc != null)
event.setTo(newLoc); event.setTo(newLoc);
} }

View File

@ -42,7 +42,7 @@ public class WorldFileData
if (possible.exists() && possible.isDirectory()) if (possible.exists() && possible.isDirectory())
{ {
newData.regionFolder = possible; newData.regionFolder = possible;
continue; break;
} }
} }
if (!newData.regionFolder.exists() || !newData.regionFolder.isDirectory()) if (!newData.regionFolder.exists() || !newData.regionFolder.isDirectory())