diff --git a/src/main/java/de/diddiz/LogBlock/CommandsHandler.java b/src/main/java/de/diddiz/LogBlock/CommandsHandler.java index b3c8039..16cbf56 100755 --- a/src/main/java/de/diddiz/LogBlock/CommandsHandler.java +++ b/src/main/java/de/diddiz/LogBlock/CommandsHandler.java @@ -551,8 +551,8 @@ public class CommandsHandler implements CommandExecutor rs = state.executeQuery(params.getQuery()); if (rs.next()) { final Player player = (Player)sender; - final int y = rs.getInt(2); - final Location loc = new Location(params.world, rs.getInt(1) + 0.5, y, rs.getInt(3) + 0.5, player.getLocation().getYaw(), 90); + final int y = rs.getInt("y"); + final Location loc = new Location(params.world, rs.getInt("x") + 0.5, y, rs.getInt("z") + 0.5, player.getLocation().getYaw(), 90); // Teleport the player sync because omg thread safety logblock.getServer().getScheduler().scheduleSyncDelayedTask(logblock, new Runnable() { diff --git a/src/main/java/de/diddiz/LogBlock/QueryParams.java b/src/main/java/de/diddiz/LogBlock/QueryParams.java old mode 100755 new mode 100644 index 01f0b56..4de1977 --- a/src/main/java/de/diddiz/LogBlock/QueryParams.java +++ b/src/main/java/de/diddiz/LogBlock/QueryParams.java @@ -24,7 +24,7 @@ import static de.diddiz.util.Utils.*; public final 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(), "kills".hashCode(), "killer".hashCode(), "victim".hashCode())); + 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(), "kills".hashCode(), "killer".hashCode(), "victim".hashCode(), "both".hashCode())); public BlockChangeType bct = BlockChangeType.BOTH; public int limit = -1, before = 0, since = 0, radius = -1; public Location loc = null; @@ -32,7 +32,7 @@ public final class QueryParams implements Cloneable public List players = new ArrayList(); public List killers = new ArrayList(); public List victims = new ArrayList(); - public boolean excludePlayersMode = false, excludeKillersMode = false, excludeVictimsMode = false, prepareToolQuery = false, silent = false; + public boolean excludePlayersMode = false, excludeKillersMode = false, excludeVictimsMode = false, excludeBlocksMode = false, prepareToolQuery = false, silent = false; public RegionContainer sel = null; public SummarizationMode sum = SummarizationMode.NONE; public List types = new ArrayList(); @@ -168,6 +168,8 @@ public final class QueryParams implements Cloneable title.append("kills "); else { if (!types.isEmpty()) { + if (excludeBlocksMode) + title.append("all blocks except "); final String[] blocknames = new String[types.size()]; for (int i = 0; i < types.size(); i++) blocknames[i] = materialName(types.get(i).getBlock()); @@ -203,7 +205,7 @@ public final class QueryParams implements Cloneable 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(" "); + title.append("within ").append(radius).append(" blocks of ").append(prepareToolQuery ? "clicked block" : "location").append(" "); else if (radius == 0) title.append("at ").append(loc.getBlockX()).append(":").append(loc.getBlockY()).append(":").append(loc.getBlockZ()).append(" "); } else if (sel != null) @@ -304,6 +306,8 @@ public final class QueryParams implements Cloneable switch (blockChangeType) { case ALL: if (!types.isEmpty()) { + if (excludeBlocksMode) + where.append("NOT "); where.append('('); for (final Block block : types) { where.append("((type = ").append(block.getBlock()).append(" OR replaced = ").append(block.getBlock()); @@ -320,6 +324,8 @@ public final class QueryParams implements Cloneable break; case BOTH: if (!types.isEmpty()) { + if (excludeBlocksMode) + where.append("NOT "); where.append('('); for (final Block block : types) { where.append("((type = ").append(block.getBlock()).append(" OR replaced = ").append(block.getBlock()); @@ -337,6 +343,8 @@ public final class QueryParams implements Cloneable break; case CREATED: if (!types.isEmpty()) { + if (excludeBlocksMode) + where.append("NOT "); where.append('('); for (final Block block : types) { where.append("((type = ").append(block.getBlock()); @@ -349,12 +357,13 @@ public final class QueryParams implements Cloneable } where.delete(where.length() - 4, where.length()); where.append(") AND "); - } else - where.append("type != 0 AND "); - where.append("type != replaced AND "); + } + where.append("type != 0 AND type != replaced AND "); break; case DESTROYED: if (!types.isEmpty()) { + if (excludeBlocksMode) + where.append("NOT "); where.append('('); for (final Block block : types) { where.append("((replaced = ").append(block.getBlock()); @@ -367,12 +376,13 @@ public final class QueryParams implements Cloneable } where.delete(where.length() - 4, where.length()); where.append(") AND "); - } else - where.append("replaced != 0 AND "); - where.append("type != replaced AND "); + } + where.append("replaced != 0 AND type != replaced AND "); break; case CHESTACCESS: if (!types.isEmpty()) { + if (excludeBlocksMode) + where.append("NOT "); where.append('('); for (final Block block : types) { where.append("((itemtype = ").append(block.getBlock()); @@ -492,6 +502,7 @@ public final class QueryParams implements Cloneable players.add(matches.size() == 1 ? matches.get(0).getName() : playerName.replaceAll("[^a-zA-Z0-9_]", "")); } } + needPlayer = true; } else if (param.equals("killer")) { if (values.length < 1) throw new IllegalArgumentException("No or wrong count of arguments for '" + param + "'"); @@ -508,6 +519,7 @@ public final class QueryParams implements Cloneable killers.add(matches.size() == 1 ? matches.get(0).getName() : killerName.replaceAll("[^a-zA-Z0-9_]", "")); } } + needKiller = true; } else if (param.equals("victim")) { if (values.length < 1) throw new IllegalArgumentException("No or wrong count of arguments for '" + param + "'"); @@ -524,6 +536,7 @@ public final class QueryParams implements Cloneable victims.add(matches.size() == 1 ? matches.get(0).getName() : victimName.replaceAll("[^a-zA-Z0-9_]", "")); } } + needVictim = true; } else if (param.equals("weapon")) { if (values.length < 1) throw new IllegalArgumentException("No or wrong count of arguments for '" + param + "'"); @@ -539,10 +552,15 @@ public final class QueryParams implements Cloneable throw new IllegalArgumentException("No material matching: '" + weaponName + "'"); types.add(new Block(mat.getId(), -1)); } + needWeapon = true; } 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) { + for (String blockName : values) { + if (blockName.startsWith("!")) { + excludeBlocksMode = true; + blockName = blockName.substring(1); + } if (blockName.contains(":")) { String[] blockNameSplit = blockName.split(":"); if (blockNameSplit.length > 2) @@ -567,17 +585,17 @@ public final class QueryParams implements Cloneable } } } else if (param.equals("area")) { - if (player == null && !prepareToolQuery) - throw new IllegalArgumentException("You have to ba a player to use area"); + if (player == null && !prepareToolQuery && loc == null) + throw new IllegalArgumentException("You have to be a player to use area, or specify a location first"); if (values.length == 0) { radius = defaultDist; - if (!prepareToolQuery) + if (!prepareToolQuery && loc == null) loc = player.getLocation(); } else { if (!isInt(values[0])) throw new IllegalArgumentException("Not a number: '" + values[0] + "'"); radius = Integer.parseInt(values[0]); - if (!prepareToolQuery) + if (!prepareToolQuery && loc == null) loc = player.getLocation(); } } else if (param.equals("selection") || param.equals("sel")) { @@ -612,6 +630,8 @@ public final class QueryParams implements Cloneable bct = BlockChangeType.CREATED; else if (param.equals("destroyed")) bct = BlockChangeType.DESTROYED; + else if (param.equals("both")) + bct = BlockChangeType.BOTH; else if (param.equals("chestaccess")) bct = BlockChangeType.CHESTACCESS; else if (param.equals("chat")) @@ -659,8 +679,12 @@ public final class QueryParams implements Cloneable throw new IllegalArgumentException("Not a valid argument: '" + param + "'"); i += values.length; } - if (bct == BlockChangeType.KILLS && !getWorldConfig(world).isLogging(Logging.KILL)) - throw new IllegalArgumentException("Kill logging not enabled for world '" + world.getName() + "'"); + if (bct == BlockChangeType.KILLS) { + if (world == null) + throw new IllegalArgumentException("No world specified"); + if (!getWorldConfig(world).isLogging(Logging.KILL)) + throw new IllegalArgumentException("Kill logging not enabled for world '" + world.getName() + "'"); + } if (types.size() > 0) for (final Set equivalent : getBlockEquivalents()) { boolean found = false; diff --git a/src/main/java/de/diddiz/LogBlock/config/WorldConfig.java b/src/main/java/de/diddiz/LogBlock/config/WorldConfig.java index ee81eda..1fef2d0 100644 --- a/src/main/java/de/diddiz/LogBlock/config/WorldConfig.java +++ b/src/main/java/de/diddiz/LogBlock/config/WorldConfig.java @@ -14,7 +14,9 @@ public class WorldConfig extends LoggingEnabledMapping public WorldConfig(File file) throws IOException { final Map def = new HashMap(); - def.put("table", "lb-" + file.getName().substring(0, file.getName().length() - 4).replace(' ', '_')); + // "Before MySQL 5.1.6, database and table names cannot contain "/", "\", ".", or characters that are not permitted in file names" - MySQL manual + // They _can_ contain spaces, but replace them as well + def.put("table", "lb-" + file.getName().substring(0, file.getName().length() - 4).replaceAll("[ ./\\\\]", "_")); for (final Logging l : Logging.values()) def.put("logging." + l.toString(), l.isDefaultEnabled()); final YamlConfiguration config = YamlConfiguration.loadConfiguration(file); diff --git a/src/main/java/de/diddiz/LogBlock/listeners/InteractLogging.java b/src/main/java/de/diddiz/LogBlock/listeners/InteractLogging.java index 6caddb1..4c96dc2 100644 --- a/src/main/java/de/diddiz/LogBlock/listeners/InteractLogging.java +++ b/src/main/java/de/diddiz/LogBlock/listeners/InteractLogging.java @@ -27,6 +27,7 @@ public class InteractLogging extends LoggingListener final WorldConfig wcfg = getWorldConfig(event.getPlayer().getWorld()); if (wcfg != null) { final Block clicked = event.getClickedBlock(); + if (clicked == null) return; final Material type = clicked.getType(); final int typeId = type.getId(); final byte blockData = clicked.getData(); diff --git a/src/main/java/de/diddiz/util/LoggingUtil.java b/src/main/java/de/diddiz/util/LoggingUtil.java index b53c6a8..5b905bb 100644 --- a/src/main/java/de/diddiz/util/LoggingUtil.java +++ b/src/main/java/de/diddiz/util/LoggingUtil.java @@ -109,7 +109,7 @@ public class LoggingUtil { } break; case COCOA: - if (blockState.getBlock().getRelative(((CocoaPlant) data).getAttachedFace()).equals(origin)) { + if (blockState.getBlock().getRelative(((CocoaPlant) data).getAttachedFace().getOppositeFace()).equals(origin)) { consumer.queueBlockBreak(playerName, blockState); } break; diff --git a/src/main/java/de/diddiz/util/Utils.java b/src/main/java/de/diddiz/util/Utils.java index 2929ce5..167dec7 100644 --- a/src/main/java/de/diddiz/util/Utils.java +++ b/src/main/java/de/diddiz/util/Utils.java @@ -76,6 +76,8 @@ public class Utils while (currIndex <= spec[0].length() && isInt(spec[0].substring(lastIndex, currIndex))) currIndex++; if (currIndex - 1 != lastIndex) { + if (currIndex > spec[0].length()) + return -1; final String param = spec[0].substring(currIndex - 1, currIndex).toLowerCase(); if (param.equals("d")) days = Integer.parseInt(spec[0].substring(lastIndex, currIndex - 1));