diff --git a/CraftincBorderProtection.jar b/CraftincBorderProtection.jar new file mode 100644 index 0000000..0c9a0b5 Binary files /dev/null and b/CraftincBorderProtection.jar differ diff --git a/pom.xml b/pom.xml index db960a2..9d4854e 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ CraftincBorderProtection CraftincBorderProtection jar - 0.9.5 + 0.9.9 CraftincGates http://maven.apache.org diff --git a/src/main/java/de/craftinc/borderprotection/BorderManager.java b/src/main/java/de/craftinc/borderprotection/BorderManager.java index c7fc438..4c2c1ec 100644 --- a/src/main/java/de/craftinc/borderprotection/BorderManager.java +++ b/src/main/java/de/craftinc/borderprotection/BorderManager.java @@ -2,10 +2,12 @@ package de.craftinc.borderprotection; import org.bukkit.Location; import org.bukkit.World; +import org.bukkit.entity.Player; import java.io.File; import java.util.ArrayList; import java.util.Arrays; +import java.util.Calendar; import java.util.HashMap; public class BorderManager @@ -25,15 +27,21 @@ public class BorderManager private HashMap> borders = null; /** - * the buffer in blocks which applies when a player is teleported inside the border. 0 means the player + * For every player save the time when he got the last borderMessage + */ + public HashMap lastBorderMessage = new HashMap(); + + /** + * The buffer in blocks which applies when a player is teleported inside the border. 0 means the player * will be teleported directly to the border. */ private double buffer = 0.5; - public Serializer getSerializer() - { - return serializer; - } + /** + * A timeout for the border message. When a player tries to cross the border and sees the border message, + * the earliest possible time the message will show up again is after timeout milliseconds. + */ + private Long timeout = 10000L; /** * Serializer, which is used for loading and saving data to harddisk @@ -59,11 +67,21 @@ public class BorderManager * ********************************************************** */ + public Serializer getSerializer() + { + return serializer; + } + public double getBuffer() { return buffer; } + public Long getTimeout() + { + return timeout; + } + public HashMap> getBorders() { return borders; @@ -103,4 +121,89 @@ public class BorderManager borders.put(worldName, locations); } + + + /** + * Checks if the given location is inside the border rectangle. Returns null if yes, otherwise new coordinates. + * + * @param location location to check + * @param borderPoints points which define the border rectangle + * @param buffer if the player will be teleported back, then he will be buffer far away + * from the border he tried to cross + * @return null if the player is inside, otherwise a new player location + */ + public Double[] checkBorder( Location location, ArrayList borderPoints, double buffer ) + { + // New x and z: null by default + Double[] newXZ = { null, null }; + + // check if player is withing the X borders + newXZ[0] = _checkBorder(location.getX(), borderPoints.get(0).getX(), borderPoints.get(1).getX(), buffer); + // check if player is withing the Z borders + newXZ[1] = _checkBorder(location.getZ(), borderPoints.get(0).getZ(), borderPoints.get(1).getZ(), buffer); + + // Do nothing, if no new coordinates have been calculated. + if ( newXZ[0] == null && newXZ[1] == null ) + { + return null; + } + return newXZ; + } + + + /** + * Checks if the given location is between one specific border pair. + * + * @param location part of the location coordinates + * @param border1 one side of the rectangle + * @param border2 opposite side of the rectangle + * @return null if the location is inside, otherwise a new location + */ + public Double _checkBorder( double location, double border1, double border2, double buffer ) + { + double bigBorder = Math.max(border1, border2); + double smallBorder = Math.min(border1, border2); + + // if location is between borders do nothing + if ( location >= smallBorder && location <= bigBorder ) + { + return null; + } + else + { + if ( location > bigBorder ) + { + // if location is outside of the bigBorder, teleport to the bigBorder + return bigBorder - buffer; + } + else + { + // if location is outside of the smallBorder, teleport to the smallBorder + return smallBorder + buffer; + } + } + } + + + /** + * Show the border message to a player and respect the timeout. + * + * @param player Player who will see the border message. + */ + public void showMessageWithTimeout( Player player, String message ) + { + // get the current time + Long now = Calendar.getInstance().getTimeInMillis(); + + if ( ( lastBorderMessage.get(player.getName()) != null && + now - getTimeout() > lastBorderMessage.get(player.getName()) ) || + lastBorderMessage.get(player.getName()) == null ) + { + // show message + player.sendMessage(message); + + // set last sent message for this player to now + lastBorderMessage.put(player.getName(), now); + } + } } \ No newline at end of file diff --git a/src/main/java/de/craftinc/borderprotection/Commands.java b/src/main/java/de/craftinc/borderprotection/Commands.java index be62b66..c5c8218 100644 --- a/src/main/java/de/craftinc/borderprotection/Commands.java +++ b/src/main/java/de/craftinc/borderprotection/Commands.java @@ -74,7 +74,7 @@ public class Commands implements CommandExecutor } ArrayList borderPoints = borderManager.getBorders() - .get(worldName); + .get(worldName); String borderDef = borderPoints.get(0).getX() + "," + borderPoints.get(0).getZ() + " " + borderPoints.get(1).getX() + "," + borderPoints.get(1).getZ(); diff --git a/src/main/java/de/craftinc/borderprotection/Messages.java b/src/main/java/de/craftinc/borderprotection/Messages.java index 72cda7f..9d99f5e 100644 --- a/src/main/java/de/craftinc/borderprotection/Messages.java +++ b/src/main/java/de/craftinc/borderprotection/Messages.java @@ -37,15 +37,22 @@ public class Messages return sb.toString(); } + private static String borderExplanation = + "One day the holy mods and administrators will expand the border. It is then your mission to explore " + + "strange new worlds, to seek out new life and new civilizations, to boldly go where no one has gone before."; + public static String borderMessage = - "Sorry Dude! This is the border... the final frontier! One day the holy mods " + - "and administrators will expand the border. It is then your mission to explore " + - "strange new worlds, to seek out new life and new civilizations, to boldly go " + - "where no one has gone before."; + "Sorry Dude! This is the border... the final frontier! " + borderExplanation + NEWLINE + + makeCmd("/cibp get", "shows the borders of the current world"); + + public static String borderTeleportMessage = + "Sorry Dude! You cannot teleport outside the border. " + borderExplanation + NEWLINE + + makeCmd("/cibp get", "shows the borders of the current world"); public static String helpGeneral = ChatColor.GREEN + "CraftInc BorderProtection - Usage:" + NEWLINE + makeCmd("help", "shows this help") + + makeCmd("get | info", "shows the borders of the current world") + makeCmd("set", "Border rectangle edges will be this far away from point of origin.", "") + makeCmd("set", "Border rectangle is defined by the two points. A point is specified as: x,z", "", ""); @@ -56,7 +63,7 @@ public class Messages public static String borderInfo( String worldName, String borderDef ) { - return ChatColor.WHITE + "Border definition of world " + + return ChatColor.WHITE + "Borders of world " + ChatColor.YELLOW + worldName + ChatColor.WHITE + ": " + ChatColor.YELLOW + borderDef; diff --git a/src/main/java/de/craftinc/borderprotection/PlayerMoveListener.java b/src/main/java/de/craftinc/borderprotection/PlayerMoveListener.java index 4ce9ccb..d0a24bf 100644 --- a/src/main/java/de/craftinc/borderprotection/PlayerMoveListener.java +++ b/src/main/java/de/craftinc/borderprotection/PlayerMoveListener.java @@ -21,39 +21,6 @@ public class PlayerMoveListener implements Listener this.borderManager = borderManager; } - /** - * Checks if the player is outside of one specific border. - * - * @param player part of the player coordinates - * @param border1 one side of the rectangle - * @param border2 opposite side of the rectangle - * @return null if the player is inside, otherwise a new player location - */ - private Double checkBorder( double player, double border1, double border2 ) - { - double bigBorder = Math.max(border1, border2); - double smallBorder = Math.min(border1, border2); - - // if player is between borders do nothing - if ( player >= smallBorder && player <= bigBorder ) - { - return null; - } - else - { - if ( player > bigBorder ) - { - // if player is outside of the bigBorder, teleport him to the bigBorder - return bigBorder - borderManager.getBuffer(); - } - else - { - // if player is outside of the smallBorder, teleport him to the smallBorder - return smallBorder + borderManager.getBuffer(); - } - } - } - private Double goUpUntilFreeSpot( Player player ) { // go up in height until the player can stand in AIR @@ -82,14 +49,19 @@ public class PlayerMoveListener implements Listener return; } - // do nothing if there is no border defined + // do nothing if there are no border definitions at all if ( borderManager.getBorders() == null ) { return; } - Location pl = e.getPlayer().getLocation(); + // player location + Location playerLocation = e.getPlayer().getLocation(); + + // world where the player is in String worldName = e.getPlayer().getWorld().getName(); + + // borders of this world ArrayList borderPoints = borderManager.getBorders().get(worldName); // do nothing if there are no borders for this specific world @@ -97,29 +69,30 @@ public class PlayerMoveListener implements Listener return; // change x or z. default: do not change - Double newX, newY, newZ; + Double[] newXZ; - newX = checkBorder(pl.getX(), borderPoints.get(0).getX(), borderPoints.get(1).getX()); - newZ = checkBorder(pl.getZ(), borderPoints.get(0).getZ(), borderPoints.get(1).getZ()); + // check if player is inside the borders. null if yes, otherwise a tuple which defines the new player position + newXZ = borderManager.checkBorder(playerLocation, borderPoints, borderManager.getBuffer()); // Do nothing, if no new coordinates have been calculated. - if ( newX == null && newZ == null ) + if ( newXZ == null ) { return; } // if one of the coordinates is null, set it to the player's value - newX = newX == null ? pl.getX() : newX; - newZ = newZ == null ? pl.getZ() : newZ; + newXZ[0] = newXZ[0] == null ? playerLocation.getX() : newXZ[0]; + newXZ[1] = newXZ[1] == null ? playerLocation.getZ() : newXZ[1]; // change Y if necessary (when there is no free spot) - newY = goUpUntilFreeSpot(e.getPlayer()); + Double newY = goUpUntilFreeSpot(e.getPlayer()); // teleport the player to the new X and Z coordinates e.getPlayer().teleport( - new Location(e.getPlayer().getWorld(), newX, newY, newZ, pl.getYaw(), pl.getPitch())); + new Location(e.getPlayer().getWorld(), newXZ[0], newY, newXZ[1], playerLocation.getYaw(), + playerLocation.getPitch())); // send a message to the player - e.getPlayer().sendMessage(Messages.borderMessage); + borderManager.showMessageWithTimeout(e.getPlayer(), Messages.borderMessage); } } diff --git a/src/main/java/de/craftinc/borderprotection/PlayerTeleportListener.java b/src/main/java/de/craftinc/borderprotection/PlayerTeleportListener.java new file mode 100644 index 0000000..adda49a --- /dev/null +++ b/src/main/java/de/craftinc/borderprotection/PlayerTeleportListener.java @@ -0,0 +1,64 @@ +package de.craftinc.borderprotection; + +import org.bukkit.Location; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerTeleportEvent; + +import java.util.ArrayList; + +public class PlayerTeleportListener implements Listener +{ + private BorderManager borderManager; + + public PlayerTeleportListener( BorderManager borderManager ) + { + this.borderManager = borderManager; + } + + @EventHandler(priority = EventPriority.LOWEST) + public void onPlayerMove( PlayerTeleportEvent e ) + { + // do nothing if player has the ignoreborders permission + if ( e.getPlayer().hasPermission("craftinc.borderprotection.ignoreborders") ) + { + return; + } + + // do nothing if there are no border definitions at all + if ( borderManager.getBorders() == null ) + { + return; + } + + // target location + Location targetLocation = e.getTo(); + + // world where the player is in + String worldName = targetLocation.getWorld().getName(); + + // borders of this world + ArrayList borderPoints = borderManager.getBorders().get(worldName); + + // do nothing if there are no borders for this specific world + if ( borderPoints == null ) + { + return; + } + + // change x or z. default: do not change + Double[] newXZ; + + // check if target is inside the borders. null if yes, otherwise a tuple which defines the new position + newXZ = borderManager.checkBorder(targetLocation, borderPoints, borderManager.getBuffer()); + + + // Cancel event, if new coordinates have been calculated. + if ( newXZ != null ) + { + e.setCancelled(true); + borderManager.showMessageWithTimeout(e.getPlayer(), Messages.borderTeleportMessage); + } + } +} diff --git a/src/main/java/de/craftinc/borderprotection/Plugin.java b/src/main/java/de/craftinc/borderprotection/Plugin.java index f0d9888..734214e 100644 --- a/src/main/java/de/craftinc/borderprotection/Plugin.java +++ b/src/main/java/de/craftinc/borderprotection/Plugin.java @@ -23,11 +23,16 @@ public class Plugin extends JavaPlugin Plugin.cibpPlugin = this; BorderManager borderManager = new BorderManager(); - PlayerMoveListener eventListener = new PlayerMoveListener(borderManager); - Commands commandExecutor = new Commands(borderManager); + PlayerMoveListener playerMoveListener = new PlayerMoveListener(borderManager); + PlayerTeleportListener playerTeleportListener = new PlayerTeleportListener(borderManager); - PluginManager pm = this.getServer().getPluginManager(); + // commands + Commands commandExecutor = new Commands(borderManager); getCommand("cibp").setExecutor(commandExecutor); - pm.registerEvents(eventListener, this); + + // listeners + PluginManager pm = this.getServer().getPluginManager(); + pm.registerEvents(playerMoveListener, this); + pm.registerEvents(playerTeleportListener, this); } } diff --git a/src/main/java/de/craftinc/borderprotection/Util.java b/src/main/java/de/craftinc/borderprotection/Util.java index d898fee..8d16df9 100644 --- a/src/main/java/de/craftinc/borderprotection/Util.java +++ b/src/main/java/de/craftinc/borderprotection/Util.java @@ -17,6 +17,11 @@ public class Util for ( Object jsonEntry : json.toArray() ) { JSONObject j = (JSONObject) jsonEntry; +// // check if border for this world is enabled. continue if not +// String enabled = (String) j.get("enabled"); +// if (enabled != "1") { +// continue; +// } String worldname = (String) j.get("worldname"); ArrayList locations = new ArrayList(); JSONArray borderPoints = (JSONArray) j.get("borderPoints"); @@ -32,18 +37,20 @@ public class Util data.put(worldname, locations); } - if (data.size() > 0) { + if ( data.size() > 0 ) + { return data; } return null; } - public static JSONArray encodeJSON( HashMap> data ) + public static JSONArray encodeJSON( HashMap> data ) { JSONArray json = new JSONArray(); int i = 0; - for (ArrayList border: data.values()) { + for ( ArrayList border : data.values() ) + { // add point 1 as json array JSONArray point1 = new JSONArray(); @@ -62,15 +69,19 @@ public class Util // Add points and worldname to world json object JSONObject borderOfAWorld = new JSONObject(); - try { + try + { borderOfAWorld.put("worldname", border.get(0).getWorld().getName()); borderOfAWorld.put("borderPoints", points); json.add(i, borderOfAWorld); i++; } - catch (NullPointerException e) { - if (border.get(0).getWorld() == null) { - Plugin.getPlugin().getLogger().warning("A world is null. Ignoring this border (not saving this border)."); + catch ( NullPointerException e ) + { + if ( border.get(0).getWorld() == null ) + { + Plugin.getPlugin().getLogger() + .warning("A world is null. Ignoring this border (not saving this border)."); } } } diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index cb05d4a..628914c 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -1,6 +1,6 @@ name: CraftincBorderProtection main: de.craftinc.borderprotection.Plugin -version: 0.9.5 +version: 0.9.9 author: ddidderr website: http://www.craftinc.de/plugins/borderprotection