diff --git a/src/main/java/de/diddiz/LogBlock/CommandsHandler.java b/src/main/java/de/diddiz/LogBlock/CommandsHandler.java index 8b087c6..6aa200a 100644 --- a/src/main/java/de/diddiz/LogBlock/CommandsHandler.java +++ b/src/main/java/de/diddiz/LogBlock/CommandsHandler.java @@ -228,11 +228,19 @@ public class CommandsHandler implements CommandExecutor sender.sendMessage(ChatColor.RED + "You aren't allowed to do this."); } else if (command.equals("rollback") || command.equals("undo") || command.equals("rb")) { if (logblock.hasPermission(sender, "logblock.rollback")) { - final QueryParams params = new QueryParams(logblock); - params.since = defaultTime; - params.bct = BlockChangeType.ALL; - params.parseArgs(sender, argsToList(args, 1)); - new CommandRollback(sender, params, true); + if(logblock.worldEditEnabled) { + final WorldEditQueryParams params = new WorldEditQueryParams(logblock); + params.since = defaultTime; + params.bct = BlockChangeType.ALL; + params.parseArgs(sender, argsToList(args, 1)); + new CommandRollback(sender, params, true); + } else { + final QueryParams params = new QueryParams(logblock); + params.since = defaultTime; + params.bct = BlockChangeType.ALL; + params.parseArgs(sender, argsToList(args, 1)); + new CommandRollback(sender, params, true); + } } else sender.sendMessage(ChatColor.RED + "You aren't allowed to do this."); } else if (command.equals("redo")) { @@ -308,7 +316,11 @@ public class CommandsHandler implements CommandExecutor final List argsList = new ArrayList(Arrays.asList(args)); if (command.equals("lookup")) argsList.remove(0); - new CommandLookup(sender, new QueryParams(logblock, sender, argsList), true); + if(logblock.worldEditEnabled) { + new CommandLookup(sender, new WorldEditQueryParams(logblock, sender, argsList), true); + } else { + new CommandLookup(sender, new QueryParams(logblock, sender, argsList), true); + } } else sender.sendMessage(ChatColor.RED + "You aren't allowed to do this"); } else @@ -348,7 +360,15 @@ public class CommandsHandler implements CommandExecutor sender.sendMessage(ChatColor.RED + "You are not allowed to rollback more than " + rollbackMaxTime + " minutes"); return false; } - if (rollbackMaxArea > 0 && (params.sel == null && params.loc == null || params.radius > rollbackMaxArea || params.sel != null && (params.sel.getLength() > rollbackMaxArea || params.sel.getWidth() > rollbackMaxArea))) { + boolean worldEditEnabled = this.logblock.getServer().getPluginManager().getPlugin("WorldEdit") != null; + if (worldEditEnabled) { + WorldEditQueryParams WEparams = (WorldEditQueryParams) params; + if (rollbackMaxArea > 0 && (WEparams.sel == null && WEparams.loc == null || WEparams.radius > rollbackMaxArea || WEparams.sel != null && (WEparams.sel.getLength() > rollbackMaxArea || WEparams.sel.getWidth() > rollbackMaxArea))) { + sender.sendMessage(ChatColor.RED + "You are not allowed to rollback an area larger than " + rollbackMaxArea + " blocks"); + return false; + } + } + if (rollbackMaxArea > 0 && (params.loc == null || params.radius > rollbackMaxArea)) { sender.sendMessage(ChatColor.RED + "You are not allowed to rollback an area larger than " + rollbackMaxArea + " blocks"); return false; } diff --git a/src/main/java/de/diddiz/LogBlock/LogBlock.java b/src/main/java/de/diddiz/LogBlock/LogBlock.java index 09700cf..0896bcb 100644 --- a/src/main/java/de/diddiz/LogBlock/LogBlock.java +++ b/src/main/java/de/diddiz/LogBlock/LogBlock.java @@ -13,7 +13,6 @@ import static de.diddiz.LogBlock.config.Config.url; import static de.diddiz.LogBlock.config.Config.useBukkitScheduler; import static de.diddiz.LogBlock.config.Config.user; import static org.bukkit.Bukkit.getPluginManager; -import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.sql.Connection; @@ -61,6 +60,7 @@ public class LogBlock extends JavaPlugin private Updater updater = null; private Timer timer = null; private boolean errorAtLoading = false, noDb = false, connected = true; + public boolean worldEditEnabled = false; public static LogBlock getInstance() { return logblock; @@ -115,9 +115,9 @@ public class LogBlock extends JavaPlugin if (noDb) return; if (pm.getPlugin("WorldEdit") == null) { - new Exception("WorldEdit is not installed please download and install").printStackTrace(); - pm.disablePlugin(this); - return; + this.worldEditEnabled = false; + } else { + this.worldEditEnabled = true; } commandsHandler = new CommandsHandler(this); getCommand("lb").setExecutor(commandsHandler); diff --git a/src/main/java/de/diddiz/LogBlock/QueryParams.java b/src/main/java/de/diddiz/LogBlock/QueryParams.java index 9f5387f..b1cbcc7 100644 --- a/src/main/java/de/diddiz/LogBlock/QueryParams.java +++ b/src/main/java/de/diddiz/LogBlock/QueryParams.java @@ -12,9 +12,6 @@ import static de.diddiz.util.Utils.isInt; import static de.diddiz.util.Utils.join; import static de.diddiz.util.Utils.listing; import static de.diddiz.util.Utils.parseTimeSpec; -import com.sk89q.worldedit.bukkit.WorldEditPlugin; -import com.sk89q.worldedit.bukkit.selections.CuboidSelection; -import com.sk89q.worldedit.bukkit.selections.Selection; import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; @@ -25,10 +22,9 @@ import org.bukkit.Material; import org.bukkit.World; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; -import org.bukkit.plugin.Plugin; import de.diddiz.util.Block; -public final class QueryParams implements Cloneable +public class QueryParams implements Cloneable { private static final Set keywords = new HashSet(Arrays.asList("player".hashCode(), "area".hashCode(), "selection".hashCode(), "sel".hashCode(), "block".hashCode(), "type".hashCode(), "sum".hashCode(), "destroyed".hashCode(), "created".hashCode(), "chestaccess".hashCode(), "all".hashCode(), "time".hashCode(), "since".hashCode(), "before".hashCode(), "limit".hashCode(), "world".hashCode(), "asc".hashCode(), "desc".hashCode(), "last".hashCode(), "coords".hashCode(), "silent".hashCode(), "chat".hashCode(), "search".hashCode(), "match".hashCode(), "loc".hashCode(), "location".hashCode())); public BlockChangeType bct = BlockChangeType.BOTH; @@ -37,13 +33,12 @@ public final class QueryParams implements Cloneable public Order order = Order.DESC; public List players = new ArrayList(); public boolean excludePlayersMode = false, prepareToolQuery = false, silent = false; - public Selection sel = null; public SummarizationMode sum = SummarizationMode.NONE; public List types = new ArrayList(); public World world = null; public String match = null; public boolean needCount = false, needId = false, needDate = false, needType = false, needData = false, needPlayer = false, needCoords = false, needSignText = false, needChestAccess = false, needMessage = false; - private final LogBlock logblock; + protected final LogBlock logblock; public QueryParams(LogBlock logblock) { this.logblock = logblock; @@ -163,14 +158,13 @@ public final class QueryParams implements Cloneable title.append("within ").append(radius).append(" blocks of ").append(prepareToolQuery ? "clicked block" : "you").append(" "); else if (radius == 0) title.append("at ").append(loc.getBlockX()).append(":").append(loc.getBlockY()).append(":").append(loc.getBlockZ()).append(" "); - } else if (sel != null) - title.append(prepareToolQuery ? "at double chest " : "inside selection "); + } else if (prepareToolQuery) if (radius > 0) title.append("within ").append(radius).append(" blocks of clicked block "); else if (radius == 0) title.append("at clicked block "); - if (world != null && !(sel != null && prepareToolQuery)) + if (world != null && !(prepareToolQuery)) title.append("in ").append(friendlyWorldname(world.getName())).append(" "); if (sum != SummarizationMode.NONE) title.append("summed up by ").append(sum == SummarizationMode.TYPES ? "blocks" : "players").append(" "); @@ -287,8 +281,7 @@ public final class QueryParams implements Cloneable where.append("x = '").append(loc.getBlockX()).append("' AND y = '").append(loc.getBlockY()).append("' AND z = '").append(loc.getBlockZ()).append("' AND "); else if (radius > 0) where.append("x > '").append(loc.getBlockX() - radius).append("' AND x < '").append(loc.getBlockX() + radius).append("' AND z > '").append(loc.getBlockZ() - radius).append("' AND z < '").append(loc.getBlockZ() + radius).append("' AND "); - } else if (sel != null) - where.append("x >= '").append(sel.getMinimumPoint().getBlockX()).append("' AND x <= '").append(sel.getMaximumPoint().getBlockX()).append("' AND y >= '").append(sel.getMinimumPoint().getBlockY()).append("' AND y <= '").append(sel.getMaximumPoint().getBlockY()).append("' AND z >= '").append(sel.getMinimumPoint().getBlockZ()).append("' AND z <= '").append(sel.getMaximumPoint().getBlockZ()).append("' AND "); + } } if (!players.isEmpty() && sum != SummarizationMode.PLAYERS) if (!excludePlayersMode) { @@ -382,18 +375,6 @@ public final class QueryParams implements Cloneable if (!prepareToolQuery) loc = player.getLocation(); } - } else if (param.equals("selection") || param.equals("sel")) { - if (player == null) - throw new IllegalArgumentException("You have to ba a player to use selection"); - final Plugin we = player.getServer().getPluginManager().getPlugin("WorldEdit"); - if (we == null) - throw new IllegalArgumentException("WorldEdit plugin not found"); - final Selection selection = ((WorldEditPlugin)we).getSelection(player); - if (selection == null) - throw new IllegalArgumentException("No selection defined"); - if (!(selection instanceof CuboidSelection)) - throw new IllegalArgumentException("You have to define a cuboid selection"); - setSelection(selection); } else if (param.equals("time") || param.equals("since")) { since = values.length > 0 ? parseTimeSpec(values) : defaultTime; if (since == -1) @@ -489,11 +470,6 @@ public final class QueryParams implements Cloneable world = loc.getWorld(); } - public void setSelection(Selection sel) { - this.sel = sel; - world = sel.getWorld(); - } - public void setPlayer(String playerName) { players.clear(); players.add(playerName); @@ -511,7 +487,7 @@ public final class QueryParams implements Cloneable return null; } - private static String[] getValues(List args, int offset) { + protected static String[] getValues(List args, int offset) { int i; for (i = offset; i < args.size(); i++) if (isKeyWord(args.get(i))) @@ -530,7 +506,6 @@ public final class QueryParams implements Cloneable types = p.types; loc = p.loc; radius = p.radius; - sel = p.sel; if (p.since != 0 || since != defaultTime) since = p.since; before = p.before; diff --git a/src/main/java/de/diddiz/LogBlock/WorldEditQueryParams.java b/src/main/java/de/diddiz/LogBlock/WorldEditQueryParams.java new file mode 100644 index 0000000..722709a --- /dev/null +++ b/src/main/java/de/diddiz/LogBlock/WorldEditQueryParams.java @@ -0,0 +1,497 @@ +package de.diddiz.LogBlock; + +import static de.diddiz.LogBlock.Session.getSession; +import static de.diddiz.LogBlock.config.Config.defaultDist; +import static de.diddiz.LogBlock.config.Config.defaultTime; +import static de.diddiz.LogBlock.config.Config.isLogged; +import static de.diddiz.util.BukkitUtils.friendlyWorldname; +import static de.diddiz.util.BukkitUtils.getBlockEquivalents; +import static de.diddiz.util.MaterialName.materialName; +import static de.diddiz.util.Utils.isInt; +import static de.diddiz.util.Utils.join; +import static de.diddiz.util.Utils.listing; +import static de.diddiz.util.Utils.parseTimeSpec; + +import java.util.List; +import java.util.Set; + +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.World; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.bukkit.plugin.Plugin; + +import com.sk89q.worldedit.bukkit.WorldEditPlugin; +import com.sk89q.worldedit.bukkit.selections.CuboidSelection; +import com.sk89q.worldedit.bukkit.selections.Selection; + +import de.diddiz.util.Block; + +public class WorldEditQueryParams extends QueryParams { + + public Selection sel = null; + + public WorldEditQueryParams(LogBlock logblock) { + super(logblock); + } + + public WorldEditQueryParams(LogBlock logblock, CommandSender sender, List args) throws IllegalArgumentException { + super(logblock); + parseArgs(sender, args); + } + + @Override + public String getQuery() { + if (bct == BlockChangeType.CHAT) { + String select = "SELECT "; + if (needCount) + select += "COUNT(*) AS count"; + else { + if (needId) + select += "id, "; + if (needDate) + select += "date, "; + if (needPlayer) + select += "playername, "; + if (needMessage) + select += "message, "; + select = select.substring(0, select.length() - 2); + } + String from = "FROM `lb-chat` "; + + if (needPlayer || players.size() > 0) + from += "INNER JOIN `lb-players` USING (playerid) "; + return select + " " + from + getWhere() + "ORDER BY date " + order + ", id " + order + " " + getLimit(); + } + if (sum == SummarizationMode.NONE) { + String select = "SELECT "; + if (needCount) + select += "COUNT(*) AS count"; + else { + if (needId) + select += "`" + getTable() + "`.id, "; + if (needDate) + select += "date, "; + if (needType) + select += "replaced, type, "; + if (needData) + select += "data, "; + if (needPlayer) + select += "playername, "; + if (needCoords) + select += "x, y, z, "; + if (needSignText) + select += "signtext, "; + if (needChestAccess) + select += "itemtype, itemamount, itemdata, "; + select = select.substring(0, select.length() - 2); + } + String from = "FROM `" + getTable() + "` "; + if (needPlayer || players.size() > 0) + from += "INNER JOIN `lb-players` USING (playerid) "; + if (needSignText) + from += "LEFT JOIN `" + getTable() + "-sign` USING (id) "; + if (needChestAccess) + from += "LEFT JOIN `" + getTable() + "-chest` USING (id) "; + return select + " " + from + getWhere() + "ORDER BY date " + order + ", id " + order + " " + getLimit(); + } else if (sum == SummarizationMode.TYPES) + return "SELECT type, SUM(created) AS created, SUM(destroyed) AS destroyed FROM ((SELECT type, count(*) AS created, 0 AS destroyed FROM `" + getTable() + "` INNER JOIN `lb-players` USING (playerid) " + getWhere(BlockChangeType.CREATED) + "GROUP BY type) UNION (SELECT replaced AS type, 0 AS created, count(*) AS destroyed FROM `" + getTable() + "` INNER JOIN `lb-players` USING (playerid) " + getWhere(BlockChangeType.DESTROYED) + "GROUP BY replaced)) AS t GROUP BY type ORDER BY SUM(created) + SUM(destroyed) " + order + " " + getLimit(); + else + return "SELECT playername, SUM(created) AS created, SUM(destroyed) AS destroyed FROM ((SELECT playerid, count(*) AS created, 0 AS destroyed FROM `" + getTable() + "` " + getWhere(BlockChangeType.CREATED) + "GROUP BY playerid) UNION (SELECT playerid, 0 AS created, count(*) AS destroyed FROM `" + getTable() + "` " + getWhere(BlockChangeType.DESTROYED) + "GROUP BY playerid)) AS t INNER JOIN `lb-players` USING (playerid) GROUP BY playerid ORDER BY SUM(created) + SUM(destroyed) " + order + " " + getLimit(); + } + + @Override + public String getTitle() { + final StringBuilder title = new StringBuilder(); + if (bct == BlockChangeType.CHESTACCESS) + title.append("chest accesses "); + else if (bct == BlockChangeType.CHAT) + title.append("chat messages "); + else { + if (!types.isEmpty()) { + final String[] blocknames = new String[types.size()]; + for (int i = 0; i < types.size(); i++) + blocknames[i] = materialName(types.get(i).getBlock()); + title.append(listing(blocknames, ", ", " and ")).append(" "); + } else + title.append("block "); + if (bct == BlockChangeType.CREATED) + title.append("creations "); + else if (bct == BlockChangeType.DESTROYED) + title.append("destructions "); + else + title.append("changes "); + } + if (players.size() > 10) + title.append(excludePlayersMode ? "without" : "from").append(" many players "); + else if (!players.isEmpty()) + title.append(excludePlayersMode ? "without" : "from").append(" player").append(players.size() != 1 ? "s" : "").append(" ").append(listing(players.toArray(new String[players.size()]), ", ", " and ")).append(" "); + if (match != null && match.length() > 0) + title.append("matching '").append(match).append("' "); + if (before > 0 && since > 0) + title.append("between ").append(since).append(" and ").append(before).append(" minutes ago "); + else if (since > 0) + title.append("in the last ").append(since).append(" minutes "); + else if (before > 0) + title.append("more than ").append(before * -1).append(" minutes ago "); + if (loc != null) { + if (radius > 0) + title.append("within ").append(radius).append(" blocks of ").append(prepareToolQuery ? "clicked block" : "you").append(" "); + else if (radius == 0) + title.append("at ").append(loc.getBlockX()).append(":").append(loc.getBlockY()).append(":").append(loc.getBlockZ()).append(" "); + } else if (sel != null) + title.append(prepareToolQuery ? "at double chest " : "inside selection "); + else if (prepareToolQuery) + if (radius > 0) + title.append("within ").append(radius).append(" blocks of clicked block "); + else if (radius == 0) + title.append("at clicked block "); + if (world != null && !(sel != null && prepareToolQuery)) + title.append("in ").append(friendlyWorldname(world.getName())).append(" "); + if (sum != SummarizationMode.NONE) + title.append("summed up by ").append(sum == SummarizationMode.TYPES ? "blocks" : "players").append(" "); + title.deleteCharAt(title.length() - 1); + title.setCharAt(0, String.valueOf(title.charAt(0)).toUpperCase().toCharArray()[0]); + return title.toString(); + } + + @Override + public void merge(QueryParams p) { + players = p.players; + excludePlayersMode = p.excludePlayersMode; + types = p.types; + loc = p.loc; + radius = p.radius; + if (p instanceof WorldEditQueryParams) { + sel = ((WorldEditQueryParams) p).sel; + } + if (p.since != 0 || since != defaultTime) + since = p.since; + before = p.before; + sum = p.sum; + bct = p.bct; + limit = p.limit; + world = p.world; + order = p.order; + match = p.match; + } + + @Override + public void parseArgs(CommandSender sender, List args) throws IllegalArgumentException { + if (args == null || args.isEmpty()) + throw new IllegalArgumentException("No parameters specified."); + final Player player = sender instanceof Player ? (Player)sender : null; + final Session session = prepareToolQuery ? null : getSession(sender); + if (player != null && world == null) + world = player.getWorld(); + for (int i = 0; i < args.size(); i++) { + final String param = args.get(i).toLowerCase(); + final String[] values = getValues(args, i + 1); + if (param.equals("last")) { + if (session.lastQuery == null) + throw new IllegalArgumentException("This is your first command, you can't use last."); + merge(session.lastQuery); + } else if (param.equals("player")) { + if (values.length < 1) + throw new IllegalArgumentException("No or wrong count of arguments for '" + param + "'"); + for (final String playerName : values) + if (playerName.length() > 0) { + if (playerName.contains("!")) + excludePlayersMode = true; + if (playerName.contains("\"")) + players.add(playerName.replaceAll("[^a-zA-Z0-9_]", "")); + else { + final List matches = logblock.getServer().matchPlayer(playerName); + if (matches.size() > 1) + throw new IllegalArgumentException("Ambiguous playername '" + param + "'"); + players.add(matches.size() == 1 ? matches.get(0).getName() : playerName.replaceAll("[^a-zA-Z0-9_]", "")); + } + } + } else if (param.equals("block") || param.equals("type")) { + if (values.length < 1) + throw new IllegalArgumentException("No or wrong count of arguments for '" + param + "'"); + for (final String blockName : values) { + if (blockName.contains(":")) { + String[] blockNameSplit = blockName.split(":"); + if (blockNameSplit.length > 2) + throw new IllegalArgumentException("No material matching: '" + blockName + "'"); + final int data; + try { + data = Integer.parseInt(blockNameSplit[1]); + } catch (NumberFormatException e) { + throw new IllegalArgumentException("Data type not a valid number: '" + blockNameSplit[1] + "'"); + } + if (data > 255 || data < 0) + throw new IllegalArgumentException("Data type out of range (0-255): '" + data + "'"); + final Material mat = Material.matchMaterial(blockNameSplit[0]); + if (mat == null) + throw new IllegalArgumentException("No material matching: '" + blockName + "'"); + types.add(new Block(mat.getId(), data)); + } else { + final Material mat = Material.matchMaterial(blockName); + if (mat == null) + throw new IllegalArgumentException("No material matching: '" + blockName + "'"); + types.add(new Block(mat.getId(), -1)); + } + } + } else if (param.equals("area")) { + if (player == null && !prepareToolQuery) + throw new IllegalArgumentException("You have to be a player to use area"); + if (values.length == 0) { + radius = defaultDist; + if (!prepareToolQuery) + loc = player.getLocation(); + } else { + if (!isInt(values[0])) + throw new IllegalArgumentException("Not a number: '" + values[0] + "'"); + radius = Integer.parseInt(values[0]); + if (!prepareToolQuery) + loc = player.getLocation(); + } + } else if (param.equals("selection") || param.equals("sel")) { + if (player == null) + throw new IllegalArgumentException("You have to be a player to use selection"); + final Plugin we = player.getServer().getPluginManager().getPlugin("WorldEdit"); + if (we == null) + throw new IllegalArgumentException("WorldEdit plugin not found"); + final Selection selection = ((WorldEditPlugin)we).getSelection(player); + if (selection == null) + throw new IllegalArgumentException("No selection defined"); + if (!(selection instanceof CuboidSelection)) + throw new IllegalArgumentException("You have to define a cuboid selection"); + this.setSelection(selection); + } else if (param.equals("time") || param.equals("since")) { + since = values.length > 0 ? parseTimeSpec(values) : defaultTime; + if (since == -1) + throw new IllegalArgumentException("Failed to parse time spec for '" + param + "'"); + } else if (param.equals("before")) { + before = values.length > 0 ? parseTimeSpec(values) : defaultTime; + if (before == -1) + throw new IllegalArgumentException("Faile to parse time spec for '" + param + "'"); + } else if (param.equals("sum")) { + if (values.length != 1) + throw new IllegalArgumentException("No or wrong count of arguments for '" + param + "'"); + if (values[0].startsWith("p")) + sum = SummarizationMode.PLAYERS; + else if (values[0].startsWith("b")) + sum = SummarizationMode.TYPES; + else if (values[0].startsWith("n")) + sum = SummarizationMode.NONE; + else + throw new IllegalArgumentException("Wrong summarization mode"); + } else if (param.equals("created")) + bct = BlockChangeType.CREATED; + else if (param.equals("destroyed")) + bct = BlockChangeType.DESTROYED; + else if (param.equals("chestaccess")) + bct = BlockChangeType.CHESTACCESS; + else if (param.equals("chat")) + bct = BlockChangeType.CHAT; + else if (param.equals("all")) + bct = BlockChangeType.ALL; + else if (param.equals("limit")) { + if (values.length != 1) + throw new IllegalArgumentException("Wrong count of arguments for '" + param + "'"); + if (!isInt(values[0])) + throw new IllegalArgumentException("Not a number: '" + values[0] + "'"); + limit = Integer.parseInt(values[0]); + } else if (param.equals("world")) { + if (values.length != 1) + throw new IllegalArgumentException("Wrong count of arguments for '" + param + "'"); + final World w = sender.getServer().getWorld(values[0].replace("\"", "")); + if (w == null) + throw new IllegalArgumentException("There is no world called '" + values[0] + "'"); + world = w; + } else if (param.equals("asc")) + order = Order.ASC; + else if (param.equals("desc")) + order = Order.DESC; + else if (param.equals("coords")) + needCoords = true; + else if (param.equals("silent")) + silent = true; + else if (param.equals("search") || param.equals("match")) { + if (values.length == 0) + throw new IllegalArgumentException("No arguments for '" + param + "'"); + match = join(values, " ").replace("\\", "\\\\").replace("'", "\\'"); + } else if (param.equals("loc") || param.equals("location")) { + final String[] vectors = values.length == 1 ? values[0].split(":") : values; + if (vectors.length != 3) + throw new IllegalArgumentException("Wrong count arguments for '" + param + "'"); + for (final String vec : vectors) + if (!isInt(vec)) + throw new IllegalArgumentException("Not a number: '" + vec + "'"); + loc = new Location(null, Integer.valueOf(vectors[0]), Integer.valueOf(vectors[1]), Integer.valueOf(vectors[2])); + radius = 0; + } else + throw new IllegalArgumentException("Not a valid argument: '" + param + "'"); + i += values.length; + } + if (types.size() > 0) + for (final Set equivalent : getBlockEquivalents()) { + boolean found = false; + for (final Block block : types) + if (equivalent.contains(block.getBlock())) { + found = true; + break; + } + if (found) + for (final Integer type : equivalent) + if (!Block.inList(types, type)) + types.add(new Block(type, -1)); + } + if (!prepareToolQuery && bct != BlockChangeType.CHAT) { + if (world == null) + throw new IllegalArgumentException("No world specified"); + if (!isLogged(world)) + throw new IllegalArgumentException("This world ('" + world.getName() + "') isn't logged"); + } + if (session != null) + session.lastQuery = clone(); + } + + @Override + public String getWhere() { + return getWhere(bct); + } + + @Override + public String getWhere(BlockChangeType blockChangeType) { + final StringBuilder where = new StringBuilder("WHERE "); + if (blockChangeType == BlockChangeType.CHAT) { + if (match != null && match.length() > 0) { + final boolean unlike = match.startsWith("-"); + if (match.length() > 3 && !unlike || match.length() > 4) + where.append("MATCH (message) AGAINST ('").append(match).append("' IN BOOLEAN MODE) AND "); + else + where.append("message ").append(unlike ? "NOT " : "").append("LIKE '%").append(unlike ? match.substring(1) : match).append("%' AND "); + } + } else { + switch (blockChangeType) { + case ALL: + if (!types.isEmpty()) { + where.append('('); + for (final Block block : types) { + where.append("((type = ").append(block.getBlock()).append(" OR replaced = ").append(block.getBlock()); + if (block.getData() != -1) { + where.append(") AND data = ").append(block.getData()); + } else { + where.append(")"); + } + where.append(") OR "); + } + where.delete(where.length() - 4, where.length() - 1); + where.append(") AND "); + } + break; + case BOTH: + if (!types.isEmpty()) { + where.append('('); + for (final Block block : types) { + where.append("((type = ").append(block.getBlock()).append(" OR replaced = ").append(block.getBlock()); + if (block.getData() != -1) { + where.append(") AND data = ").append(block.getData()); + } else { + where.append(")"); + } + where.append(") OR "); + } + where.delete(where.length() - 4, where.length()); + where.append(") AND "); + } + where.append("type != replaced AND "); + break; + case CREATED: + if (!types.isEmpty()) { + where.append('('); + for (final Block block : types) { + where.append("((type = ").append(block.getBlock()); + if (block.getData() != -1) { + where.append(") AND data = ").append(block.getData()); + } else { + where.append(")"); + } + where.append(") OR "); + } + where.delete(where.length() - 4, where.length()); + where.append(") AND "); + } else + where.append("type != 0 AND "); + where.append("type != replaced AND "); + break; + case DESTROYED: + if (!types.isEmpty()) { + where.append('('); + for (final Block block : types) { + where.append("((replaced = ").append(block.getBlock()); + if (block.getData() != -1) { + where.append(") AND data = ").append(block.getData()); + } else { + where.append(")"); + } + where.append(") OR "); + } + where.delete(where.length() - 4, where.length()); + where.append(") AND "); + } else + where.append("replaced != 0 AND "); + where.append("type != replaced AND "); + break; + case CHESTACCESS: + where.append("(type = 23 OR type = 54 OR type = 61 OR type = 62) AND type = replaced AND "); + if (!types.isEmpty()) { + where.append('('); + for (final Block block : types) { + where.append("((itemtype = ").append(block.getBlock()); + if (block.getData() != -1) { + where.append(") AND itemdata = ").append(block.getData()); + } else { + where.append(")"); + } + where.append(") OR "); + } + where.delete(where.length() - 4, where.length()); + where.append(") AND "); + } + break; + } + if (loc != null) { + if (radius == 0) + where.append("x = '").append(loc.getBlockX()).append("' AND y = '").append(loc.getBlockY()).append("' AND z = '").append(loc.getBlockZ()).append("' AND "); + else if (radius > 0) + where.append("x > '").append(loc.getBlockX() - radius).append("' AND x < '").append(loc.getBlockX() + radius).append("' AND z > '").append(loc.getBlockZ() - radius).append("' AND z < '").append(loc.getBlockZ() + radius).append("' AND "); + } else if (sel != null) + where.append("x >= '").append(sel.getMinimumPoint().getBlockX()).append("' AND x <= '").append(sel.getMaximumPoint().getBlockX()).append("' AND y >= '").append(sel.getMinimumPoint().getBlockY()).append("' AND y <= '").append(sel.getMaximumPoint().getBlockY()).append("' AND z >= '").append(sel.getMinimumPoint().getBlockZ()).append("' AND z <= '").append(sel.getMaximumPoint().getBlockZ()).append("' AND "); + } + if (!players.isEmpty() && sum != SummarizationMode.PLAYERS) + if (!excludePlayersMode) { + where.append('('); + for (final String playerName : players) + where.append("playername = '").append(playerName).append("' OR "); + where.delete(where.length() - 4, where.length()); + where.append(") AND "); + } else + for (final String playerName : players) + where.append("playername != '").append(playerName).append("' AND "); + if (since > 0) + where.append("date > date_sub(now(), INTERVAL ").append(since).append(" MINUTE) AND "); + if (before > 0) + where.append("date < date_sub(now(), INTERVAL ").append(before).append(" MINUTE) AND "); + if (where.length() > 6) + where.delete(where.length() - 4, where.length()); + else + where.delete(0, where.length()); + return where.toString(); + } + + public void setSelection(Selection sel) { + this.sel = sel; + world = sel.getWorld(); + } + + public void setSelection(World world, Location location, Location location2) { + this.setSelection(new CuboidSelection(world, location, location2)); + } + +} diff --git a/src/main/java/de/diddiz/LogBlock/config/Config.java b/src/main/java/de/diddiz/LogBlock/config/Config.java index 51a98f4..cf96e03 100644 --- a/src/main/java/de/diddiz/LogBlock/config/Config.java +++ b/src/main/java/de/diddiz/LogBlock/config/Config.java @@ -28,6 +28,7 @@ import de.diddiz.LogBlock.QueryParams; import de.diddiz.LogBlock.Tool; import de.diddiz.LogBlock.ToolBehavior; import de.diddiz.LogBlock.ToolMode; +import de.diddiz.LogBlock.WorldEditQueryParams; public class Config { @@ -185,7 +186,12 @@ public class Config final boolean defaultEnabled = tSec.getBoolean("defaultEnabled", false); final int item = tSec.getInt("item", 0); final boolean canDrop = tSec.getBoolean("canDrop", false); - final QueryParams params = new QueryParams(logblock); + final QueryParams params; + if (logblock.worldEditEnabled) { + params = new WorldEditQueryParams(logblock); + } else { + params = new QueryParams(logblock); + } params.prepareToolQuery = true; params.parseArgs(getConsoleSender(), Arrays.asList(tSec.getString("params").split(" "))); final ToolMode mode = ToolMode.valueOf(tSec.getString("mode").toUpperCase()); diff --git a/src/main/java/de/diddiz/LogBlock/listeners/ToolListener.java b/src/main/java/de/diddiz/LogBlock/listeners/ToolListener.java index 97a2ff3..ab6c858 100644 --- a/src/main/java/de/diddiz/LogBlock/listeners/ToolListener.java +++ b/src/main/java/de/diddiz/LogBlock/listeners/ToolListener.java @@ -4,7 +4,6 @@ import static de.diddiz.LogBlock.Session.getSession; import static de.diddiz.LogBlock.Session.hasSession; import static de.diddiz.LogBlock.config.Config.isLogged; import static de.diddiz.LogBlock.config.Config.toolsByType; -import com.sk89q.worldedit.bukkit.selections.CuboidSelection; import java.util.Map.Entry; import org.bukkit.ChatColor; import org.bukkit.block.Block; @@ -25,6 +24,7 @@ import de.diddiz.LogBlock.Tool; import de.diddiz.LogBlock.ToolBehavior; import de.diddiz.LogBlock.ToolData; import de.diddiz.LogBlock.ToolMode; +import de.diddiz.LogBlock.WorldEditQueryParams; public class ToolListener implements Listener { @@ -49,18 +49,22 @@ public class ToolListener implements Listener if (behavior != ToolBehavior.NONE && toolData.enabled) { final Block block = event.getClickedBlock(); final QueryParams params = toolData.params; + boolean paramsWorldEdit = logblock.worldEditEnabled && (params instanceof WorldEditQueryParams); params.loc = null; - params.sel = null; + if (paramsWorldEdit) + ((WorldEditQueryParams) params).sel = null; if (behavior == ToolBehavior.BLOCK) params.setLocation(block.getRelative(event.getBlockFace()).getLocation()); else if (block.getTypeId() != 54 || tool.params.radius != 0) params.setLocation(block.getLocation()); else { - for (final BlockFace face : new BlockFace[]{BlockFace.NORTH, BlockFace.SOUTH, BlockFace.EAST, BlockFace.WEST}) - if (block.getRelative(face).getTypeId() == 54) - params.setSelection(new CuboidSelection(event.getPlayer().getWorld(), block.getLocation(), block.getRelative(face).getLocation())); - if (params.sel == null) - params.setLocation(block.getLocation()); + if (paramsWorldEdit) { + for (final BlockFace face : new BlockFace[]{BlockFace.NORTH, BlockFace.SOUTH, BlockFace.EAST, BlockFace.WEST}) + if (block.getRelative(face).getTypeId() == 54) + ((WorldEditQueryParams) params).setSelection(event.getPlayer().getWorld(), block.getLocation(), block.getRelative(face).getLocation()); + if (((WorldEditQueryParams) params).sel == null) + params.setLocation(block.getLocation()); + } } try { if (toolData.mode == ToolMode.ROLLBACK)