From 329508ab41c1fc34100ffa8b462d82a2a3f0d82b Mon Sep 17 00:00:00 2001 From: Paul Schulze Date: Sat, 22 Sep 2012 16:41:45 +0200 Subject: [PATCH] craftinc-borderprotection initial commit --- .gitignore | 4 + pom.xml | 47 +++++++ .../borderprotection/BorderManager.java | 106 +++++++++++++++ .../craftinc/borderprotection/Commands.java | 87 ++++++++++++ .../craftinc/borderprotection/Messages.java | 70 ++++++++++ .../borderprotection/PlayerMoveListener.java | 125 ++++++++++++++++++ .../de/craftinc/borderprotection/Plugin.java | 33 +++++ .../craftinc/borderprotection/Serializer.java | 97 ++++++++++++++ .../de/craftinc/borderprotection/Util.java | 79 +++++++++++ src/main/resources/plugin.yml | 18 +++ 10 files changed, 666 insertions(+) create mode 100644 .gitignore create mode 100644 pom.xml create mode 100644 src/main/java/de/craftinc/borderprotection/BorderManager.java create mode 100644 src/main/java/de/craftinc/borderprotection/Commands.java create mode 100644 src/main/java/de/craftinc/borderprotection/Messages.java create mode 100644 src/main/java/de/craftinc/borderprotection/PlayerMoveListener.java create mode 100644 src/main/java/de/craftinc/borderprotection/Plugin.java create mode 100644 src/main/java/de/craftinc/borderprotection/Serializer.java create mode 100644 src/main/java/de/craftinc/borderprotection/Util.java create mode 100644 src/main/resources/plugin.yml diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b728ec1 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +lib/ +target/ +*.iml +.idea/ diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..db960a2 --- /dev/null +++ b/pom.xml @@ -0,0 +1,47 @@ + + + 4.0.0 + CraftincBorderProtection + CraftincBorderProtection + jar + 0.9.5 + CraftincGates + http://maven.apache.org + + UTF-8 + + + + org.bukkit + bukkit + RELEASE + jar + compile + + + junit + junit + 4.10 + test + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 2.3.2 + + 1.6 + 1.6 + + + + + + + bukkit-repo + http://repo.bukkit.org/content/groups/public + + + diff --git a/src/main/java/de/craftinc/borderprotection/BorderManager.java b/src/main/java/de/craftinc/borderprotection/BorderManager.java new file mode 100644 index 0000000..c7fc438 --- /dev/null +++ b/src/main/java/de/craftinc/borderprotection/BorderManager.java @@ -0,0 +1,106 @@ +package de.craftinc.borderprotection; + +import org.bukkit.Location; +import org.bukkit.World; + +import java.io.File; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; + +public class BorderManager +{ + /** + * ********************************************************* + * GLOBAL VARIABLES + * ********************************************************** + */ + + private final String dataFileName = "data.json"; + + /** + * Borders of all Worlds. String is World.getName(). Location is one point of the border. A border + * consists of two points which create a rectangle. + */ + private HashMap> borders = null; + + /** + * 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; + } + + /** + * Serializer, which is used for loading and saving data to harddisk + */ + private Serializer serializer; + + /** + * ********************************************************* + * CONSTRUCTOR + * ********************************************************** + */ + public BorderManager() + { + // initialize Serializer and load data file + serializer = new Serializer(new File(Plugin.getPlugin().getDataFolder(), dataFileName)); + borders = serializer.loadDataFile(); + } + + + /** + * ********************************************************* + * GETTERS AND SETTERS + * ********************************************************** + */ + + public double getBuffer() + { + return buffer; + } + + public HashMap> getBorders() + { + return borders; + } + + public void setBorder( String worldName, double border ) + { + if ( borders == null ) + { + borders = new HashMap>(); + } + + World world = Plugin.getPlugin().getServer().getWorld(worldName); + + // set two points which define a square + borders.put(worldName, new ArrayList(Arrays.asList( + new Location(world, border, 0, border), + new Location(world, -border, 0, -border) + ))); + } + + public void setBorder( String worldName, String[] borderPoints ) + { + if ( borders == null ) + { + borders = new HashMap>(); + } + + ArrayList locations = new ArrayList(); + World world = Plugin.getPlugin().getServer().getWorld(worldName); + + for ( String borderPoint : borderPoints ) + { + String[] point = borderPoint.split(","); + locations.add(new Location(world, Double.parseDouble(point[0]), 0, Double.parseDouble(point[1]))); + } + + borders.put(worldName, locations); + } +} \ 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 new file mode 100644 index 0000000..be62b66 --- /dev/null +++ b/src/main/java/de/craftinc/borderprotection/Commands.java @@ -0,0 +1,87 @@ +package de.craftinc.borderprotection; + +import org.bukkit.Location; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import java.util.ArrayList; + +public class Commands implements CommandExecutor +{ + private BorderManager borderManager; + + public Commands( BorderManager borderManager ) + { + this.borderManager = borderManager; + } + + @Override + public boolean onCommand( CommandSender sender, Command command, String label, String[] args ) + { + // Check if command comes from a player. + if ( !( sender instanceof Player ) ) + { + sender.sendMessage(Messages.commandIssuedByNonPlayer); + return true; + } + + // command for all actions + if ( command.getName().equalsIgnoreCase("cibp") ) + { + // help + if ( args.length == 0 || ( args.length > 0 && args[0].equalsIgnoreCase("help") ) ) + { + sender.sendMessage(Messages.helpGeneral); + return true; + } + + // set + if ( ( args.length == 2 || args.length == 3 ) && args[0].equalsIgnoreCase("set") ) + { + if ( !sender.hasPermission("craftinc.borderprotection.set") ) + { + sender.sendMessage(Messages.noPermissionSet); + return false; + } + if ( args.length == 2 ) + { + borderManager.setBorder(( (Player) sender ).getWorld().getName(), Double.parseDouble(args[1])); + } + else if ( args.length == 3 ) + { + String[] borderDefinition = { args[1], args[2] }; + borderManager.setBorder(( (Player) sender ).getWorld().getName(), borderDefinition); + } + + // save the new border + borderManager.getSerializer().saveDataFile(borderManager.getBorders()); + return true; + } + + // get + if ( args.length == 1 && ( args[0].equalsIgnoreCase("get") || args[0].equalsIgnoreCase("info") ) ) + { + String worldName = ( (Player) sender ).getWorld().getName(); + + // exit and send the player a message if no border is set + if ( borderManager.getBorders() == null || + borderManager.getBorders().get(worldName) == null ) + { + sender.sendMessage(Messages.borderInfoNoBorderSet); + return true; + } + + ArrayList borderPoints = borderManager.getBorders() + .get(worldName); + String borderDef = borderPoints.get(0).getX() + "," + borderPoints.get(0).getZ() + " " + + borderPoints.get(1).getX() + "," + borderPoints.get(1).getZ(); + + sender.sendMessage(Messages.borderInfo(worldName, borderDef)); + return true; + } + } + return false; + } +} diff --git a/src/main/java/de/craftinc/borderprotection/Messages.java b/src/main/java/de/craftinc/borderprotection/Messages.java new file mode 100644 index 0000000..72cda7f --- /dev/null +++ b/src/main/java/de/craftinc/borderprotection/Messages.java @@ -0,0 +1,70 @@ +package de.craftinc.borderprotection; + +import org.bukkit.ChatColor; + +public class Messages +{ + private static final String NEWLINE = "\n"; + + private static String makeCmd( String command, String explanation, String... args ) + { + StringBuilder sb = new StringBuilder(); + + // command + sb.append(ChatColor.YELLOW); + sb.append(command); + if ( args.length > 0 ) + { + sb.append(" "); + sb.append(ChatColor.BLUE); + for ( int i = 0; i < args.length; i++ ) + { + String s = args[i]; + sb.append(s); + if ( i != args.length - 1 ) + { + sb.append(" "); + } + } + } + + sb.append(ChatColor.YELLOW); + sb.append(": "); + sb.append(ChatColor.WHITE); + sb.append(explanation); + sb.append(NEWLINE); + + return sb.toString(); + } + + 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."; + + public static String helpGeneral = + ChatColor.GREEN + "CraftInc BorderProtection - Usage:" + NEWLINE + + makeCmd("help", "shows this help") + + 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", + "", ""); + + public static String commandIssuedByNonPlayer + = ChatColor.RED + "Only a player can use CraftInc BorderProtection commands!"; + + public static String borderInfo( String worldName, String borderDef ) + { + + return ChatColor.WHITE + "Border definition of world " + + ChatColor.YELLOW + worldName + + ChatColor.WHITE + ": " + + ChatColor.YELLOW + borderDef; + } + + public static String borderInfoNoBorderSet = + ChatColor.YELLOW + "No border here."; + + public static String noPermissionSet = + ChatColor.RED + "Sorry, you don't have permission to set the border."; +} \ No newline at end of file diff --git a/src/main/java/de/craftinc/borderprotection/PlayerMoveListener.java b/src/main/java/de/craftinc/borderprotection/PlayerMoveListener.java new file mode 100644 index 0000000..4ce9ccb --- /dev/null +++ b/src/main/java/de/craftinc/borderprotection/PlayerMoveListener.java @@ -0,0 +1,125 @@ +package de.craftinc.borderprotection; + +import org.bukkit.Location; +import org.bukkit.Material; +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; + +import java.util.ArrayList; + +public class PlayerMoveListener implements Listener +{ + + private BorderManager borderManager; + + public PlayerMoveListener( BorderManager borderManager ) + { + 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 + Block footBlock = player.getLocation().getBlock(); + Block headBlock = player.getEyeLocation().getBlock(); + while ( footBlock.getType() != Material.AIR || headBlock.getType() != Material.AIR ) + { + byte offset = 1; + if ( headBlock.getType() != Material.AIR ) + { + offset = 2; + } + footBlock = footBlock.getRelative(0, offset, 0); + headBlock = headBlock.getRelative(0, offset, 0); + } + // set the y value to a spot where the player can stand free + return (double) footBlock.getY(); + } + + @EventHandler(priority = EventPriority.NORMAL) + public void onPlayerMove( PlayerMoveEvent e ) + { + // do nothing if player has the ignoreborders permission + if ( e.getPlayer().hasPermission("craftinc.borderprotection.ignoreborders") ) + { + return; + } + + // do nothing if there is no border defined + if ( borderManager.getBorders() == null ) + { + return; + } + + Location pl = e.getPlayer().getLocation(); + String worldName = e.getPlayer().getWorld().getName(); + 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 newX, newY, newZ; + + newX = checkBorder(pl.getX(), borderPoints.get(0).getX(), borderPoints.get(1).getX()); + newZ = checkBorder(pl.getZ(), borderPoints.get(0).getZ(), borderPoints.get(1).getZ()); + + // Do nothing, if no new coordinates have been calculated. + if ( newX == null && newZ == 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; + + // change Y if necessary (when there is no free spot) + 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())); + + // send a message to the player + e.getPlayer().sendMessage(Messages.borderMessage); + } +} diff --git a/src/main/java/de/craftinc/borderprotection/Plugin.java b/src/main/java/de/craftinc/borderprotection/Plugin.java new file mode 100644 index 0000000..f0d9888 --- /dev/null +++ b/src/main/java/de/craftinc/borderprotection/Plugin.java @@ -0,0 +1,33 @@ +package de.craftinc.borderprotection; + +import org.bukkit.plugin.PluginManager; +import org.bukkit.plugin.java.JavaPlugin; + +public class Plugin extends JavaPlugin +{ + private static JavaPlugin cibpPlugin; + + public static JavaPlugin getPlugin() + { + return cibpPlugin; + } + + @Override + public void onDisable() + { + } + + @Override + public void onEnable() + { + Plugin.cibpPlugin = this; + + BorderManager borderManager = new BorderManager(); + PlayerMoveListener eventListener = new PlayerMoveListener(borderManager); + Commands commandExecutor = new Commands(borderManager); + + PluginManager pm = this.getServer().getPluginManager(); + getCommand("cibp").setExecutor(commandExecutor); + pm.registerEvents(eventListener, this); + } +} diff --git a/src/main/java/de/craftinc/borderprotection/Serializer.java b/src/main/java/de/craftinc/borderprotection/Serializer.java new file mode 100644 index 0000000..cc08059 --- /dev/null +++ b/src/main/java/de/craftinc/borderprotection/Serializer.java @@ -0,0 +1,97 @@ +package de.craftinc.borderprotection; + +import org.bukkit.Location; +import org.json.simple.JSONArray; +import org.json.simple.parser.JSONParser; +import org.json.simple.parser.ParseException; + +import java.io.*; +import java.util.ArrayList; +import java.util.HashMap; + +public class Serializer +{ + private File dataFile; + + public Serializer( File dataFile ) + { + this.dataFile = dataFile; + } + + public HashMap> loadDataFile() + { + try + { + FileReader fr = new FileReader(dataFile); + BufferedReader br = new BufferedReader(fr); + StringBuilder fileContents = new StringBuilder(); + + String line; + while ( ( line = br.readLine() ) != null ) + { + fileContents.append(line); + } + + JSONParser jsonParser = new JSONParser(); + JSONArray json = (JSONArray) jsonParser.parse(fileContents.toString()); + + return Util.decodeJSON(json); + } + catch ( IOException e ) + { + if ( e instanceof FileNotFoundException ) + { + Plugin.getPlugin().getLogger().info("Data file not found."); + } + else + { + e.printStackTrace(); + } + } + catch ( ParseException e ) + { + Plugin.getPlugin().getLogger() + .severe("Could not parse json data file. When you set up a new border, the corrupt data file will be overwritten!"); + e.printStackTrace(); + } + return null; + } + + public void saveDataFile( HashMap> data ) + { + // if there is not data, do nothing and log it to console + if ( data == null ) + { + Plugin.getPlugin().getLogger().severe("Could not save data, because it is null"); + return; + } + + // create plugin directory if it doesn't exists + if ( !Plugin.getPlugin().getDataFolder().exists() ) + { + Plugin.getPlugin().getLogger().info("Creating plugin directory..."); + if ( !Plugin.getPlugin().getDataFolder().mkdir() ) + { + Plugin.getPlugin().getLogger().severe("Could not create plugin directory"); + } + else + { + Plugin.getPlugin().getLogger().info("Plugin directory created successfully"); + } + } + + JSONArray json = Util.encodeJSON(data); + + // Write to file + try + { + FileWriter fw = new FileWriter(dataFile); + fw.write(json.toJSONString()); + fw.close(); + } + catch ( IOException e ) + { + e.printStackTrace(); + } + } +} \ No newline at end of file diff --git a/src/main/java/de/craftinc/borderprotection/Util.java b/src/main/java/de/craftinc/borderprotection/Util.java new file mode 100644 index 0000000..d898fee --- /dev/null +++ b/src/main/java/de/craftinc/borderprotection/Util.java @@ -0,0 +1,79 @@ +package de.craftinc.borderprotection; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; + +import java.util.ArrayList; +import java.util.HashMap; + +public class Util +{ + public static HashMap> decodeJSON( JSONArray json ) + { + HashMap> data = new HashMap>(); + + for ( Object jsonEntry : json.toArray() ) + { + JSONObject j = (JSONObject) jsonEntry; + String worldname = (String) j.get("worldname"); + ArrayList locations = new ArrayList(); + JSONArray borderPoints = (JSONArray) j.get("borderPoints"); + + for ( Object pointObj : borderPoints ) + { + JSONArray point = (JSONArray) pointObj; + + locations + .add(new Location(Bukkit.getWorld(worldname), (Double) point.get(0), 0, (Double) point.get(1))); + } + + data.put(worldname, locations); + } + + if (data.size() > 0) { + return data; + } + + return null; + } + + public static JSONArray encodeJSON( HashMap> data ) + { + JSONArray json = new JSONArray(); + int i = 0; + for (ArrayList border: data.values()) { + + // add point 1 as json array + JSONArray point1 = new JSONArray(); + point1.add(0, border.get(0).getX()); + point1.add(1, border.get(0).getZ()); + + // add point 2 as json array + JSONArray point2 = new JSONArray(); + point2.add(0, border.get(1).getX()); + point2.add(1, border.get(1).getZ()); + + // add both points to points json array + JSONArray points = new JSONArray(); + points.add(point1); + points.add(point2); + + // Add points and worldname to world json object + JSONObject borderOfAWorld = new JSONObject(); + 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)."); + } + } + } + return json; + } +} diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml new file mode 100644 index 0000000..cb05d4a --- /dev/null +++ b/src/main/resources/plugin.yml @@ -0,0 +1,18 @@ +name: CraftincBorderProtection +main: de.craftinc.borderprotection.Plugin +version: 0.9.5 +author: ddidderr +website: http://www.craftinc.de/plugins/borderprotection + + +commands: + cibp: + description: Shows help for CraftInc BorderProtection + +permissions: + craftinc.borderprotection.set: + default: false + description: Allows to set the border for a world. + craftinc.borderprotection.ignoreborders: + default: false + description: Allows to be everywhere on the map (ignoring the borders).