From 384fa3601b04fde6c8dbf4692806d7267b7afb90 Mon Sep 17 00:00:00 2001 From: graywolf336 Date: Fri, 5 Jun 2015 18:01:31 -0500 Subject: [PATCH] New command for signs, closes #79 A new command for signs. Refreshing them, cleaning them, and verifying them. Changed up some internal apis, if you were using them sorry for breaking it. Also, really update the signs when we jail someone who is offline via a new event. --- .../java/com/graywolf336/jail/JailIO.java | 60 ++++---- src/main/java/com/graywolf336/jail/Util.java | 123 +++++++++------ .../com/graywolf336/jail/beans/AnyCell.java | 26 ++++ .../java/com/graywolf336/jail/beans/Cell.java | 101 ++++++++++++- .../com/graywolf336/jail/beans/NoCell.java | 26 ++++ .../graywolf336/jail/command/JailHandler.java | 2 + .../command/subcommands/JailSignsCommand.java | 140 ++++++++++++++++++ .../java/com/graywolf336/jail/enums/Lang.java | 10 ++ .../graywolf336/jail/interfaces/ICell.java | 60 +++++--- .../jail/listeners/CellSignListener.java | 132 ++++------------- src/main/resources/en.yml | 5 + src/main/resources/plugin.yml | 3 + 12 files changed, 487 insertions(+), 201 deletions(-) create mode 100644 src/main/java/com/graywolf336/jail/command/subcommands/JailSignsCommand.java diff --git a/src/main/java/com/graywolf336/jail/JailIO.java b/src/main/java/com/graywolf336/jail/JailIO.java index 8824a5d..91b12ea 100644 --- a/src/main/java/com/graywolf336/jail/JailIO.java +++ b/src/main/java/com/graywolf336/jail/JailIO.java @@ -27,11 +27,11 @@ import com.graywolf336.jail.enums.Settings; /** * Handles all the saving and loading of the plugin's data. - * + * * @author graywolf336 * @since 2.x.x * @version 3.0.0 - * + * */ public class JailIO { private JailMain pl; @@ -86,7 +86,7 @@ public class JailIO { /** Prepares the storage engine to be used, returns true if everything went good. */ protected boolean prepareStorage(boolean doInitialCreations) { int inital = storage == -1 ? -1 : storage; - + String st = pl.getConfig().getString("storage.type", "flatfile"); if(st.equalsIgnoreCase("sqlite")) { storage = 1; @@ -97,7 +97,7 @@ public class JailIO { }else { storage = 0; } - + //Determine if we changed storage types midstream //this way we can know whether to save EVERYTHING //or not afterwards @@ -108,7 +108,7 @@ public class JailIO { pl.debug("The storage type " + st + " with the type being " + storage + "."); if(!pl.inDebug()) pl.getLogger().info("Storage type selected: " + st); - + switch(storage) { case 1: try { @@ -118,7 +118,7 @@ public class JailIO { sqliteConnection.setAutoCommit(true); this.con = sqliteConnection; pl.debug("Connection created for sqlite."); - + if(doInitialCreations) createTables(); } catch (ClassNotFoundException e) { e.printStackTrace(); @@ -163,7 +163,7 @@ public class JailIO { records = YamlConfiguration.loadConfiguration(new File(pl.getDataFolder(), "records.yml")); break; } - + if(changed) { changed = false; this.saveEverything(); @@ -174,7 +174,7 @@ public class JailIO { /** * Gets the connection for the sqlite and mysql, null if flatfile. - * + * * @return The connection for the sql database. */ private Connection getConnection() { @@ -461,7 +461,7 @@ public class JailIO { if(j != null) { if(j.getWorld() != null) { - Cell c = new Cell(set.getString("name")); + Cell c = new Cell(set.getInt("cellid"), set.getString("name")); c.setTeleport(new SimpleLocation(j.getWorldName(), set.getDouble("tp.x"), set.getDouble("tp.y"), set.getDouble("tp.z"), set.getFloat("tp.yaw"), set.getFloat("tp.pitch"))); @@ -475,7 +475,7 @@ public class JailIO { c.addSign(new SimpleLocation(co[0], co[1], co[2], co[3])); } } - + //Since we're loading the data, the cell hasn't officially changed c.setChanged(false); @@ -632,16 +632,16 @@ public class JailIO { String cNode = node + "cells."; pl.debug("Loading the jail " + name + "; " + node + "; " + cNode); Jail j = new Jail(pl, name); - + if(flat.getString(node + "world") == null || flat.getString(node + "world").isEmpty()) { - pl.getLogger().severe("Failed to load the jail, " + name + ", because the world is not set."); - return; + pl.getLogger().severe("Failed to load the jail, " + name + ", because the world is not set."); + return; } j.setWorld(flat.getString(node + "world")); j.setMaxPoint(new int[] {flat.getInt(node + "top.x"), flat.getInt(node + "top.y"), flat.getInt(node + "top.z")}); j.setMinPoint(new int[] {flat.getInt(node + "bottom.x"), flat.getInt(node + "bottom.y"), flat.getInt(node + "bottom.z")}); - + j.setTeleportIn(new Location( pl.getServer().getWorld(j.getWorldName()), flat.getDouble(node + "tps.in.x"), @@ -757,7 +757,7 @@ public class JailIO { /** * Saves the provided {@link Jail jail} to the storage system we are using. - * + * * @param j The jail to save. */ protected void saveJail(Jail j) { @@ -805,6 +805,9 @@ public class JailIO { try { for(Cell c : j.getCells()) { + if(c.getDatabaseID() != -1) + saveCell(j, c, false); + if(c.hasPrisoner() && c.getPrisoner().wasChanged()) { Prisoner p = c.getPrisoner(); PreparedStatement pPS = getConnection().prepareStatement("REPLACE INTO `" + prefix + "prisoners` (`uuid`, `name`, `jail`, `cell`, `muted`, `time`," @@ -943,7 +946,7 @@ public class JailIO { if(p.getPreviousGameMode() != null) flat.set(cNode + "prisoner.previousGameMode", p.getPreviousGameMode().toString()); } - + c.setChanged(false); } @@ -983,14 +986,19 @@ public class JailIO { //if the cell hasn't changed, no need to save it again //unless they're forcing the save if(!c.hasChanged() && !force) return; - + switch(storage) { case 1: case 2: try { pl.debug("Saving the cell " + c.getName()); - PreparedStatement cPS = getConnection().prepareStatement("INSERT INTO `" + prefix + "cells` (`name`, `jail`, `tp.x`, `tp.y`, `tp.z`, `tp.yaw`," - + "`tp.pitch`, `chest.x`, `chest.y`, `chest.z`, `signs`) VALUES (?,?,?,?,?,?,?,?,?,?,?)"); + boolean hasId = c.getDatabaseID() != -1; + + PreparedStatement cPS = getConnection().prepareStatement((hasId ? "REPLACE" : "INSERT") + + " INTO `" + prefix + "cells` (" + (hasId ? "`cellid`, " : "") + + "`name`, `jail`, `tp.x`, `tp.y`, `tp.z`, `tp.yaw`," + + "`tp.pitch`, `chest.x`, `chest.y`, `chest.z`, `signs`) VALUES (" + + (hasId ? c.getDatabaseID() + "," : "") + "?,?,?,?,?,?,?,?,?,?,?)"); cPS.setString(1, c.getName()); cPS.setString(2, j.getName()); @@ -1048,13 +1056,13 @@ public class JailIO { this.saveJail(j); break; } - + c.setChanged(false); } /** * Removes the prisoner from the storage system. - * + * * @param j the jail which the prisoner is in. * @param p the prisoner data */ @@ -1064,7 +1072,7 @@ public class JailIO { /** * Removes the prisoner from the storage system. - * + * * @param j the jail which the prisoner is in. * @param c the cell which the prisoner is in, null if none * @param p the prisoner data @@ -1104,7 +1112,7 @@ public class JailIO { /** * Removes the provided cell from the jail. - * + * * @param j instance of the jail the cell is in * @param c instance of the cell we are removing */ @@ -1152,7 +1160,7 @@ public class JailIO { /** * Removes a jail from the storage system. - * + * * @param j the jail instance to remove. */ protected void removeJail(Jail j) { @@ -1193,7 +1201,7 @@ public class JailIO { /** * Adds an entry to the database/file for the user, logging when they was jailed. - * + * * @param uuid of the player * @param username of the player * @param jailer who jailed them @@ -1244,7 +1252,7 @@ public class JailIO { /** * Gets all the record entries for the given player. - * + * * @param username the of the prisoner's records to get. * @return A List of strings containing the record entries. * @deprecated This calls getOfflinePlayer which is a blocking call from Bukkit diff --git a/src/main/java/com/graywolf336/jail/Util.java b/src/main/java/com/graywolf336/jail/Util.java index 3f651ef..ddd60cf 100644 --- a/src/main/java/com/graywolf336/jail/Util.java +++ b/src/main/java/com/graywolf336/jail/Util.java @@ -27,17 +27,18 @@ import com.graywolf336.jail.enums.Lang; /** * Provides a variety of methods, static, that are used throughout the plugin. - * + * * @author graywolf336 * @since 2.x.x - * @version 3.0.0 + * @version 3.1.0 */ public class Util { private final static Pattern DURATION_PATTERN = Pattern.compile("^(\\d+)\\s*(m(?:inute)?s?|h(?:ours?)?|d(?:ays?)?|s(?:econd)?s?)?$", Pattern.CASE_INSENSITIVE); + private static String[] signLines = new String[] { "", "", "", "" }; /** * Checks if the first {@link Vector} is inside this region. - * + * * @param point The point to check * @param first point of the region * @param second second point of the region @@ -53,9 +54,9 @@ public class Util { /** * Checks if two numbers are inside a point, or something. - * + * *

- * + * * @param loc The location. * @param first The first point * @param second The second point @@ -72,14 +73,14 @@ public class Util { point1 = second; } - return (point1 <= loc) && (loc <= point2); + return point1 <= loc && loc <= point2; } - + /** * Checks if the given string is inside the array, ignoring the casing. - * + * *

- * + * * @param value to check * @param array of strings to check * @return true if the array contains the provided value, false if it doesn't @@ -88,15 +89,15 @@ public class Util { for(String s : array) if(s.equalsIgnoreCase(value)) return true; - + return false; } /** * Checks if the given string is inside the list, ignoring the casing. - * + * *

- * + * * @param value to check * @param list of strings to check * @return true if the list contains the provided value, false if it doesn't @@ -108,40 +109,40 @@ public class Util { return false; } - + /** * Gets a single string from an array of strings, separated by the separator. - * + * * @param separator The item to separate the items * @param array The array of strings to combine * @return the resulting combined string */ public static String getStringFromArray(String separator, String... array) { StringBuilder result = new StringBuilder(); - + for(String s : array) { if(result.length() != 0) result.append(separator); result.append(s); } - + return result.toString(); } - + /** * Gets a single string from a list of strings, separated by the separator. - * + * * @param separator The item to separate the items * @param list The list of strings to combine * @return the resulting combined string */ public static String getStringFromList(String separator, List list) { StringBuilder result = new StringBuilder(); - + for(String s : list) { if(result.length() != 0) result.append(separator); result.append(s); } - + return result.toString(); } @@ -169,6 +170,16 @@ public class Util { return getColorfulMessage(msg); } + /** Replaces all the variables in the messages with their possible values. */ + public static String[] replaceAllVariables(Prisoner p, String... msgs) { + String[] results = new String[msgs.length]; + + for(int i = 0; i < msgs.length; i++) + results[i] = replaceAllVariables(p, msgs[i]); + + return results; + } + /** Returns the wand used throughout the different creation steps. */ public static ItemStack getWand() { ItemStack wand = new ItemStack(Material.WOOD_SWORD); @@ -184,9 +195,9 @@ public class Util { } /** - * + * * Converts a string like '20minutes' into the appropriate amount of the given unit. - * + * * @param time in a string to convert. * @param unit which to convert to. * @return The time in the unit given that is converted. @@ -198,7 +209,7 @@ public class Util { /** * Converts a string like '20minutes' into the appropriate amount of milliseconds. - * + * * @param time in a string to convert. * @return The time in milliseconds that is converted. * @throws Exception if there are no matches @@ -232,10 +243,10 @@ public class Util { return t; } - + /** * Convert a millisecond duration to a string format - * + * * @param millis A duration to convert to a string form * @return A string of the form "XdYhZAs". */ @@ -257,26 +268,42 @@ public class Util { sb.append(days); sb.append("d"); } - + if(days > 0 || hours > 0) { sb.append(hours); sb.append("h"); } - + if(days > 0 || hours > 0 || minutes > 0) { sb.append(minutes); sb.append("m"); } - + sb.append(seconds); sb.append("s"); - return(sb.toString()); + return sb.toString(); + } + + /** + * Updates the local cache of the lines which go on signs. + * + * @param lines array of string which go on signs, must contain exactly four. + * @throws Exception Throws an exception if there aren't exactly four lines. + */ + public static void updateSignLinesCache(String[] lines) throws Exception { + if(lines.length != 4) throw new Exception("Exactly four lines are required for the signs."); + signLines = lines; + } + + /** Gets all the lines which go on the cell signs. */ + public static String[] getSignLines() { + return signLines; } /** * Converts the player inventory to a String array of Base64 strings. First string is the content and second string is the armor. - * + * * @param playerInventory to turn into an array of strings. * @return Array of strings: [ main content, armor content ] * @throws IllegalStateException @@ -290,13 +317,13 @@ public class Util { } /** - * + * * A method to serialize an {@link ItemStack} array to Base64 String. - * + * *

- * + * * Based off of {@link #toBase64(Inventory)}. - * + * * @param items to turn into a Base64 String. * @return Base64 string of the items. * @throws IllegalStateException @@ -310,8 +337,8 @@ public class Util { dataOutput.writeInt(items.length); // Save every element in the list - for (int i = 0; i < items.length; i++) { - dataOutput.writeObject(items[i]); + for (ItemStack item : items) { + dataOutput.writeObject(item); } // Serialize that array @@ -324,14 +351,14 @@ public class Util { /** * A method to serialize an inventory to Base64 string. - * + * *

- * + * * Special thanks to Comphenix in the Bukkit forums or also known * as aadnk on GitHub. - * + * * Original Source - * + * * @param inventory to serialize * @return Base64 string of the provided inventory * @throws IllegalStateException @@ -358,16 +385,16 @@ public class Util { } /** - * + * * A method to get an {@link Inventory} from an encoded, Base64, string. - * + * *

- * + * * Special thanks to Comphenix in the Bukkit forums or also known * as aadnk on GitHub. - * + * * Original Source - * + * * @param data Base64 string of data containing an inventory. * @return Inventory created from the Base64 string. * @throws IOException @@ -394,11 +421,11 @@ public class Util { /** * Gets an array of ItemStacks from Base64 string. - * + * *

- * + * * Base off of {@link #fromBase64(String)}. - * + * * @param data Base64 string to convert to ItemStack array. * @return ItemStack array created from the Base64 string. * @throws IOException diff --git a/src/main/java/com/graywolf336/jail/beans/AnyCell.java b/src/main/java/com/graywolf336/jail/beans/AnyCell.java index 45edcdc..4d05643 100644 --- a/src/main/java/com/graywolf336/jail/beans/AnyCell.java +++ b/src/main/java/com/graywolf336/jail/beans/AnyCell.java @@ -1,13 +1,27 @@ package com.graywolf336.jail.beans; +import java.util.HashMap; import java.util.HashSet; +import java.util.List; import org.bukkit.Location; import org.bukkit.block.Chest; import com.graywolf336.jail.interfaces.ICell; +/** + * Pass this an instance of this class into the jailing of a player and they go to any open cell. + * + * @author graywolf336 + * @since 3.0.0 + * @version 1.0.0 + * + */ public class AnyCell implements ICell { + public int getDatabaseID() { + throw new UnsupportedOperationException(); + } + public String getName() { throw new UnsupportedOperationException(); } @@ -48,6 +62,18 @@ public class AnyCell implements ICell { throw new UnsupportedOperationException(); } + public List getInvalidSigns() { + throw new UnsupportedOperationException(); + } + + public List cleanSigns() { + throw new UnsupportedOperationException(); + } + + public HashMap> updateSigns() { + throw new UnsupportedOperationException(); + } + public void setTeleport(SimpleLocation location) { throw new UnsupportedOperationException(); } diff --git a/src/main/java/com/graywolf336/jail/beans/Cell.java b/src/main/java/com/graywolf336/jail/beans/Cell.java index 56954b9..e915b34 100644 --- a/src/main/java/com/graywolf336/jail/beans/Cell.java +++ b/src/main/java/com/graywolf336/jail/beans/Cell.java @@ -1,21 +1,29 @@ package com.graywolf336.jail.beans; +import java.util.ArrayList; +import java.util.HashMap; import java.util.HashSet; +import java.util.List; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.Material; +import org.bukkit.block.BlockState; import org.bukkit.block.Chest; +import org.bukkit.block.Sign; +import com.graywolf336.jail.Util; +import com.graywolf336.jail.enums.Lang; import com.graywolf336.jail.interfaces.ICell; /** Represents a Cell inside of a {@link Jail}. * * @author graywolf336 * @since 3.0.0 - * @version 1.1.4 + * @version 1.2.0 */ public class Cell implements ICell { + private int databaseid; private String name; private Prisoner p; private HashSet signs; @@ -27,10 +35,28 @@ public class Cell implements ICell { * @param name The name of the cell. */ public Cell(String name) { + this.databaseid = -1; this.name = name; this.signs = new HashSet(); this.changed = false; } + + /** + * Creates a new Cell with the id in the database and the name. + * + * @param id The id of the cell in the database. + * @param name The name of the cell. + */ + public Cell(int id, String name) { + this.databaseid = id; + this.name = name; + this.signs = new HashSet(); + this.changed = false; + } + + public int getDatabaseID() { + return this.databaseid; + } public String getName() { return this.name; @@ -85,6 +111,75 @@ public class Cell implements ICell { return r; } + + public List getInvalidSigns() { + List invalid = new ArrayList(); + + for(SimpleLocation s : new HashSet(signs)) + if (s.getLocation().getBlock().getState() instanceof Sign) + continue; + else + invalid.add(s.toString()); + + return invalid; + } + + public List cleanSigns() { + List cleaned = new ArrayList(); + + for(SimpleLocation s : new HashSet(signs)) { + if (s.getLocation().getBlock().getState() instanceof Sign) { + continue; + }else { + changed = true; + signs.remove(s); + cleaned.add(s.toString()); + } + } + + return cleaned; + } + + public HashMap> updateSigns() { + List removed = new ArrayList(); + List updated = new ArrayList(); + + for(SimpleLocation s : new HashSet(signs)) { + BlockState bs = s.getLocation().getBlock().getState(); + + if (bs instanceof Sign) { + Sign sign = (Sign) bs; + + if(hasPrisoner()) { + String[] lines = Util.replaceAllVariables(p, Util.getSignLines()); + + sign.setLine(0, lines[0]); + sign.setLine(1, lines[1]); + sign.setLine(2, lines[2]); + sign.setLine(3, lines[3]); + sign.update(true, false); + }else { + sign.setLine(0, ""); + sign.setLine(1, Lang.CELLEMPTYSIGN.get()); + sign.setLine(2, ""); + sign.setLine(3, ""); + sign.update(true, false); + } + + updated.add(s.toString()); + }else { + changed = true; + signs.remove(s); + removed.add(s.toString()); + } + } + + HashMap> results = new HashMap>(); + results.put("removed", removed); + results.put("updated", updated); + + return results; + } public void setTeleport(SimpleLocation location) { this.teleport = location; @@ -123,11 +218,11 @@ public class Cell implements ICell { }else return false; } - + public boolean setChanged(boolean changed) { return this.changed = changed; } - + public boolean hasChanged() { return this.changed; } diff --git a/src/main/java/com/graywolf336/jail/beans/NoCell.java b/src/main/java/com/graywolf336/jail/beans/NoCell.java index e41121b..3faccd7 100644 --- a/src/main/java/com/graywolf336/jail/beans/NoCell.java +++ b/src/main/java/com/graywolf336/jail/beans/NoCell.java @@ -1,13 +1,27 @@ package com.graywolf336.jail.beans; +import java.util.HashMap; import java.util.HashSet; +import java.util.List; import org.bukkit.Location; import org.bukkit.block.Chest; import com.graywolf336.jail.interfaces.ICell; +/** + * Pass this an instance of this class into the jailing of a player and they won't go into a cell. + * + * @author graywolf336 + * @since 3.0.0 + * @version 1.0.0 + * + */ public class NoCell implements ICell { + public int getDatabaseID() { + throw new UnsupportedOperationException(); + } + public String getName() { throw new UnsupportedOperationException(); } @@ -48,6 +62,18 @@ public class NoCell implements ICell { throw new UnsupportedOperationException(); } + public List getInvalidSigns() { + throw new UnsupportedOperationException(); + } + + public List cleanSigns() { + throw new UnsupportedOperationException(); + } + + public HashMap> updateSigns() { + throw new UnsupportedOperationException(); + } + public void setTeleport(SimpleLocation location) { throw new UnsupportedOperationException(); } diff --git a/src/main/java/com/graywolf336/jail/command/JailHandler.java b/src/main/java/com/graywolf336/jail/command/JailHandler.java index da4120d..a4a2752 100644 --- a/src/main/java/com/graywolf336/jail/command/JailHandler.java +++ b/src/main/java/com/graywolf336/jail/command/JailHandler.java @@ -28,6 +28,7 @@ import com.graywolf336.jail.command.subcommands.JailMuteCommand; import com.graywolf336.jail.command.subcommands.JailPayCommand; import com.graywolf336.jail.command.subcommands.JailRecordCommand; import com.graywolf336.jail.command.subcommands.JailReloadCommand; +import com.graywolf336.jail.command.subcommands.JailSignsCommand; import com.graywolf336.jail.command.subcommands.JailStatusCommand; import com.graywolf336.jail.command.subcommands.JailStickCommand; import com.graywolf336.jail.command.subcommands.JailStopCommand; @@ -261,6 +262,7 @@ public class JailHandler { load(JailPayCommand.class); load(JailRecordCommand.class); load(JailReloadCommand.class); + load(JailSignsCommand.class); load(JailStatusCommand.class); load(JailStickCommand.class); load(JailStopCommand.class); diff --git a/src/main/java/com/graywolf336/jail/command/subcommands/JailSignsCommand.java b/src/main/java/com/graywolf336/jail/command/subcommands/JailSignsCommand.java new file mode 100644 index 0000000..18f6e14 --- /dev/null +++ b/src/main/java/com/graywolf336/jail/command/subcommands/JailSignsCommand.java @@ -0,0 +1,140 @@ +package com.graywolf336.jail.command.subcommands; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map.Entry; + +import org.bukkit.command.CommandSender; +import org.bukkit.util.StringUtil; + +import com.graywolf336.jail.JailManager; +import com.graywolf336.jail.Util; +import com.graywolf336.jail.beans.Cell; +import com.graywolf336.jail.beans.Jail; +import com.graywolf336.jail.command.Command; +import com.graywolf336.jail.command.CommandInfo; +import com.graywolf336.jail.enums.Lang; + +@CommandInfo( + maxArgs = -1, + minimumArgs = 2, + needsPlayer = false, + pattern = "signs", + permission = "jail.command.jailsigns", + usage = "/jail signs [clean|refresh|verify] [jail] (cell)..." + ) +public class JailSignsCommand implements Command { + private static final String[] options = new String[] { "clean", "refresh", "verify" }; + + public boolean execute(JailManager jm, CommandSender sender, String... args) throws Exception { + if(!jm.isValidJail(args[2])) { + sender.sendMessage(" " + Lang.NOJAIL.get(args[1])); + return true; + } + + Jail j = jm.getJail(args[2]); + + HashMap> items = new HashMap>(); + + if(args[1].equalsIgnoreCase("clean")) { + //if they type clean, we can remove all signs which are no longer signs + //then provide them a list of signs which got cleaned up + + for(Cell c : j.getCells()) { + if(Util.isStringInsideArray(c.getName(), args) || args.length == 3) { + if(c.hasSigns()) { + List cleaned = c.cleanSigns(); + if(!cleaned.isEmpty()) { + items.put(c.getName(), cleaned); + } + } + } + } + + if(items.isEmpty()) { + sender.sendMessage(Lang.NOINVALIDSIGNS.get()); + }else { + sender.sendMessage(Lang.CLEANEDSIGNS.get()); + for(Entry> e : items.entrySet()) { + sender.sendMessage(" " + e.getKey()); + for(String s : e.getValue()) + sender.sendMessage(" Sign: " + s); + } + } + + return true; + }else if(args[1].equalsIgnoreCase("refresh")) { + //if they type refresh, we will go through all the signs and update them to + //display the correct message on the sign whether empty or time + + int cells = 0; + int updated = 0; + int removed = 0; + + for(Cell c : j.getCells()) { + if(Util.isStringInsideArray(c.getName(), args) || args.length == 3) { + HashMap> results = c.updateSigns(); + updated += results.get("updated").size(); + removed += results.get("removed").size(); + cells++; + } + } + + sender.sendMessage(Lang.SIGNSREFRESHED.get(new String[] { String.valueOf(updated), String.valueOf(removed), String.valueOf(cells) })); + return true; + }else if(args[1].equalsIgnoreCase("verify")) { + //if they type verify, we will go through all the signs and then provide them + //as a list of cells which have signs that aren't actually signs and provide + //the location where the signs are + + for(Cell c : j.getCells()) { + if(Util.isStringInsideArray(c.getName(), args) || args.length == 3) { + List invalids = c.getInvalidSigns(); + if(!invalids.isEmpty()) { + items.put(c.getName(), invalids); + } + } + } + + if(items.isEmpty()) { + sender.sendMessage(Lang.NOINVALIDSIGNS.get()); + }else { + sender.sendMessage(Lang.INVALIDSIGNS.get()); + for(Entry> e : items.entrySet()) { + sender.sendMessage(" " + e.getKey()); + for(String s : e.getValue()) + sender.sendMessage(" " + Lang.SIGN.get() + ": " + s); + } + } + return true; + }else + return false; + } + + public List provideTabCompletions(JailManager jm, CommandSender sender, String... args) throws Exception { + List results = new ArrayList(); + + switch(args.length) { + case 2: + for(String s : options) + if(args[1].isEmpty() || StringUtil.startsWithIgnoreCase(s, args[1])) + results.add(s); + break; + case 3: + results.addAll(jm.getJailsByPrefix(args[2])); + break; + default: + if(jm.isValidJail(args[2])) + for(Cell c : jm.getJail(args[2]).getCells()) + if(!Util.isStringInsideArray(c.getName(), args)) + results.add(c.getName()); + break; + } + + Collections.sort(results); + + return results; + } +} diff --git a/src/main/java/com/graywolf336/jail/enums/Lang.java b/src/main/java/com/graywolf336/jail/enums/Lang.java index c54089f..8ae16d3 100644 --- a/src/main/java/com/graywolf336/jail/enums/Lang.java +++ b/src/main/java/com/graywolf336/jail/enums/Lang.java @@ -133,6 +133,10 @@ public enum Lang { CELLREMOVALUNSUCCESSFUL("general"), /** The message sent whenever a cell is successfully removed. */ CELLREMOVED("general"), + /** The message sent when cleaning our cell signs. */ + CLEANEDSIGNS("general"), + /** The message sent when seeing what signs are invalid. */ + INVALIDSIGNS("general"), /** The line on a cell's sign when the prisoner is jailed forever. */ JAILEDFOREVERSIGN("general"), /** The simple word jailing to be put in other parts. */ @@ -151,6 +155,8 @@ public enum Lang { NOCELL("general"), /** Message sent when needing a cell or something and there are no cells. */ NOCELLS("general"), + /** Message sent when no invalid signs were found. */ + NOINVALIDSIGNS("general"), /** The message sent whenever the sender does something which the jail does not found. */ NOJAIL("general"), /** The message sent whenever the sender does something and there are no jails. */ @@ -173,6 +179,10 @@ public enum Lang { RECORDENTRY("general"), /** The message format sent saying how many times a user has been jailed. */ RECORDTIMESJAILED("general"), + /** The simple word: sign. */ + SIGN("general"), + /** The message sent when the signs are refreshed. */ + SIGNSREFRESHED("general"), /** The format of the time entry we should use for the record entries. */ TIMEFORMAT("general"), /** The simple word transferring to be put in other parts. */ diff --git a/src/main/java/com/graywolf336/jail/interfaces/ICell.java b/src/main/java/com/graywolf336/jail/interfaces/ICell.java index 0820378..2fc37b2 100644 --- a/src/main/java/com/graywolf336/jail/interfaces/ICell.java +++ b/src/main/java/com/graywolf336/jail/interfaces/ICell.java @@ -1,6 +1,8 @@ package com.graywolf336.jail.interfaces; +import java.util.HashMap; import java.util.HashSet; +import java.util.List; import org.bukkit.Location; import org.bukkit.block.Chest; @@ -9,74 +11,90 @@ import com.graywolf336.jail.beans.Prisoner; import com.graywolf336.jail.beans.SimpleLocation; public interface ICell { + /** Gets the id of the cell in the database, internal usage only */ + public int getDatabaseID(); + /** Gets the name of the cell. */ public String getName(); - + /** Sets the prisoner in this cell. */ public void setPrisoner(Prisoner prisoner); - + /** Gets the prisoner being held in this cell. */ public Prisoner getPrisoner(); - + /** Nullifies the prisoner data. */ public void removePrisoner(); - + /** Returns true if there is currently a prisoner in this cell. */ public boolean hasPrisoner(); - + /** Adds all the given signs to the cell. */ public void addAllSigns(HashSet signs); - + /** Adds a sign to the cell. */ public void addSign(SimpleLocation sign); - + /** Returns all the signs for this cell. */ public HashSet getSigns(); - + /** Checks if there are any signs for this cell. */ public boolean hasSigns(); - + /** Returns the entire list of signs in a string. */ public String getSignString(); - + + /** Gets a list of all the signs which are invalid (not signs anymore). */ + public List getInvalidSigns(); + + /** Removes all the signs which are no longer sign blocks. */ + public List cleanSigns(); + + /** + * Updates all the signs this cell has. + * + * @return collection of changes. The "removed" entry has all the signs which were removed. The "updated" entry has all the signs which got updated. + */ + public HashMap> updateSigns(); + /** Sets the location of where the prisoner will be teleported at when jailed here. */ public void setTeleport(SimpleLocation location); - + /** Gets the teleport location where the prisoner will be teleported at when jailed here. */ public Location getTeleport(); - + /** Sets the location of the chest. */ public void setChestLocation(SimpleLocation simpleLocation); - + /** * Gets the location of the chest, returns null if no chest is stored at this cell. - * + * * @return The location of the chest, null if none. */ public Location getChestLocation(); - + /** * Gets the chest for this cell, returns null if there is no chest or the location we have is not a chest. - * + * * @return The chest and its state. */ public Chest getChest(); - + /** * Checks if the chest location doesn't equal null and if it is a double chest. - * + * * @return true if there is a chest, false if there isn't. */ public boolean hasChest(); - + /** * Sets whether this cell has been changed or not. - * + * * @param changed true if we've changed it, mostly use if you want to force an update * @return the resulting change, whether it is changed or not */ public boolean setChanged(boolean changed); - + /** Gets whether the Cell has changed from the last save or not. */ public boolean hasChanged(); } diff --git a/src/main/java/com/graywolf336/jail/listeners/CellSignListener.java b/src/main/java/com/graywolf336/jail/listeners/CellSignListener.java index 3a98221..b07c11c 100644 --- a/src/main/java/com/graywolf336/jail/listeners/CellSignListener.java +++ b/src/main/java/com/graywolf336/jail/listeners/CellSignListener.java @@ -1,20 +1,17 @@ package com.graywolf336.jail.listeners; -import java.util.HashSet; import java.util.List; -import org.bukkit.block.Sign; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; import com.graywolf336.jail.JailMain; import com.graywolf336.jail.Util; -import com.graywolf336.jail.beans.SimpleLocation; -import com.graywolf336.jail.enums.Lang; import com.graywolf336.jail.enums.Settings; import com.graywolf336.jail.events.JailPluginReloadedEvent; -import com.graywolf336.jail.events.PrePrisonerJailedEvent; +import com.graywolf336.jail.events.OfflinePrisonerJailedEvent; +import com.graywolf336.jail.events.PrisonerJailedEvent; import com.graywolf336.jail.events.PrisonerReleasedEvent; import com.graywolf336.jail.events.PrisonerTimeChangeEvent; import com.graywolf336.jail.events.PrisonerTransferredEvent; @@ -26,11 +23,18 @@ public class CellSignListener implements Listener { public CellSignListener(JailMain plugin) { pl = plugin; List lines = pl.getConfig().getStringList(Settings.CELLSIGNLINES.getPath()); - + if(lines.size() >= 1) lineOne = lines.get(0); if(lines.size() >= 2) lineTwo = lines.get(1); if(lines.size() >= 3) lineThree = lines.get(2); if(lines.size() >= 4) lineFour = lines.get(3); + + try { + Util.updateSignLinesCache(new String[] { lineOne, lineTwo, lineThree, lineFour }); + }catch(Exception e) { + //this should never happen + pl.debug("Error on Cell Sign Listener constructor:" + e.getMessage()); + } } @EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR) @@ -38,137 +42,59 @@ public class CellSignListener implements Listener { pl.getServer().getScheduler().scheduleSyncDelayedTask(pl, new Runnable() { public void run() { if (event.hasCell() && event.getCell().hasSigns()) { - HashSet signs = event.getCell().getSigns(); - String s1 = Util.replaceAllVariables(event.getPrisoner(), lineOne); - String s2 = Util.replaceAllVariables(event.getPrisoner(), lineTwo); - String s3 = Util.replaceAllVariables(event.getPrisoner(), lineThree); - String s4 = Util.replaceAllVariables(event.getPrisoner(), lineFour); - - for (SimpleLocation s : signs) { - if (s.getLocation().getBlock().getState() instanceof Sign) { - Sign sign = (Sign) s.getLocation().getBlock().getState(); - sign.setLine(0, s1); - sign.setLine(1, s2); - sign.setLine(2, s3); - sign.setLine(3, s4); - sign.update(); - } else { - // Remove the sign from the cell since it isn't - // a valid sign - event.getCell().getSigns().remove(s); - } - } + event.getCell().updateSigns(); } } }); } - @EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR) - public void changeCellSignsOnJail(PrePrisonerJailedEvent event) { + @EventHandler(priority = EventPriority.MONITOR) + public void changeSignsOnOfflineJailing(OfflinePrisonerJailedEvent event) { if (event.hasCell() && event.getCell().hasSigns()) { - HashSet signs = event.getCell().getSigns(); - String s1 = Util.replaceAllVariables(event.getPrisoner(), lineOne); - String s2 = Util.replaceAllVariables(event.getPrisoner(), lineTwo); - String s3 = Util.replaceAllVariables(event.getPrisoner(), lineThree); - String s4 = Util.replaceAllVariables(event.getPrisoner(), lineFour); + event.getCell().updateSigns(); + } + } - for (SimpleLocation s : signs) { - if (s.getLocation().getBlock().getState() instanceof Sign) { - Sign sign = (Sign) s.getLocation().getBlock().getState(); - sign.setLine(0, s1); - sign.setLine(1, s2); - sign.setLine(2, s3); - sign.setLine(3, s4); - sign.update(); - } else { - // Remove the sign from the cell since it isn't - // a valid sign - event.getCell().getSigns().remove(s); - } - } + @EventHandler(priority = EventPriority.MONITOR) + public void changeCellSignsOnJail(PrisonerJailedEvent event) { + if (event.hasCell() && event.getCell().hasSigns()) { + event.getCell().updateSigns(); } } @EventHandler public void clearTheCellSigns(PrisonerReleasedEvent event) { if (event.hasCell() && event.getCell().hasSigns()) { - HashSet signs = event.getCell().getSigns(); - - for (SimpleLocation s : signs) { - if (s.getLocation().getBlock().getState() instanceof Sign) { - Sign sign = (Sign) s.getLocation().getBlock().getState(); - sign.setLine(0, ""); - sign.setLine(1, Lang.CELLEMPTYSIGN.get()); - sign.setLine(2, ""); - sign.setLine(3, ""); - sign.update(); - } else { - // Remove the sign from the cell since it isn't - // a valid sign - event.getCell().getSigns().remove(s); - } - } + event.getCell().updateSigns(); } } @EventHandler public void handleSignsOnTransfer(PrisonerTransferredEvent event) { if (event.hasOriginalCell() && event.getOriginalCell().hasSigns()) { - HashSet signs = event.getOriginalCell().getSigns(); - - for (SimpleLocation s : signs) { - if (s.getLocation().getBlock().getState() instanceof Sign) { - Sign sign = (Sign) s.getLocation().getBlock().getState(); - sign.setLine(0, ""); - sign.setLine(1, Lang.CELLEMPTYSIGN.get()); - sign.setLine(2, ""); - sign.setLine(3, ""); - sign.update(); - } else { - // Remove the sign from the cell since it isn't - // a valid sign - event.getOriginalCell().getSigns().remove(s); - } - } + event.getOriginalCell().updateSigns(); } if (event.hasTargetCell() && event.getTargetCell().hasSigns()) { - HashSet signs = event.getTargetCell().getSigns(); - String s1 = Util.replaceAllVariables(event.getPrisoner(), lineOne); - String s2 = Util.replaceAllVariables(event.getPrisoner(), lineTwo); - String s3 = Util.replaceAllVariables(event.getPrisoner(), lineThree); - String s4 = Util.replaceAllVariables(event.getPrisoner(), lineFour); - - for (SimpleLocation s : signs) { - if (s.getLocation().getBlock().getState() instanceof Sign) { - Sign sign = (Sign) s.getLocation().getBlock().getState(); - sign.setLine(0, s1); - sign.setLine(1, s2); - sign.setLine(2, s3); - sign.setLine(3, s4); - sign.update(); - } else { - // Remove the sign from the cell since it isn't - // a valid sign - event.getTargetCell().getSigns().remove(s); - } - } + event.getTargetCell().updateSigns(); } } - + @EventHandler(priority = EventPriority.MONITOR) - public void handleSignLineUpdates(JailPluginReloadedEvent event) { + public void handleSignLineUpdates(JailPluginReloadedEvent event) throws Exception { List lines = pl.getConfig().getStringList(Settings.CELLSIGNLINES.getPath()); - + //Reset the lines to nothing lineOne = ""; lineTwo = ""; lineThree = ""; lineFour = ""; - + if(lines.size() >= 1) lineOne = lines.get(0); if(lines.size() >= 2) lineTwo = lines.get(1); if(lines.size() >= 3) lineThree = lines.get(2); if(lines.size() >= 4) lineFour = lines.get(3); + + Util.updateSignLinesCache(new String[] { lineOne, lineTwo, lineThree, lineFour }); } } diff --git a/src/main/resources/en.yml b/src/main/resources/en.yml index 857af41..bc4e8fe 100644 --- a/src/main/resources/en.yml +++ b/src/main/resources/en.yml @@ -17,6 +17,8 @@ language: cellemptysign: 'Empty cell' cellremovalunsuccessful: '&cThe removal of cell %0% from jail %1% was unsuccessful because there is a prisoner in there still. Release or transfer before trying to remove the cell again.' cellremoved: '&9Cell %0% has been successfully removed from the jail %1%.' + cleanedsigns: '&aThe following signs were successfully cleaned:' + invalidsigns: '&cThe following signs are invalid:' jailedforeversign: '&cfor life' jailing: '&9jailing' jailremovalunsuccessful: '&cThe removal of the jail %0% was unsuccessful because there are prisoners in there, please release or transfer them first.' @@ -26,6 +28,7 @@ language: jailstickusagedisabled: '&cThe usage of Jail Sticks has been disabled by the Administrator.' nocell: '&cNo cell found by the name of %0% in the jail %1%.' nocells: '&cNo cells found in the jail %0%.' + noinvalidsigns: '&aNo invalid signs were found.' nojail: '&cNo jail found by the name of %0%.' nojails: '&cThere are currently no jails.' nopermission: '&cInsufficient permission.' @@ -37,6 +40,8 @@ language: prisonerscleared: '&cAll the prisoners from %0% have been cleared.' recordentry: '&7[%0%]: &9%1% &fjailed by &9%2% &ffor &9%3% &fminutes with a reason of &9%4%&f. [%5%]' recordtimesjailed: '&c%0% has been jailed &a%1% &ctimes.' + sign: 'Sign' + signsrefreshed: '&aWe have successfully refreshed %0% signs and removed %1% signs in %2% cells.' timeformat: "MM/dd/yyyy HH:mm:ss" transferring: '&9transferring' unknowncommand: '&cNo commands registered by the name of %0%.' diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 1b7eaee..514c818 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -50,6 +50,7 @@ permissions: jail.command.jailmute: true jail.command.jailrecord: true jail.command.jailreload: true + jail.command.jailsigns: true jail.command.jailstop: true jail.command.jailtelein: true jail.command.jailteleout: true @@ -106,6 +107,8 @@ permissions: default: op jail.command.jailmute: default: op + jail.command.jailsigns: + default: op jail.command.jailstop: default: op jail.command.jailset: