forked from LogBlock/LogBlock
Various minor improvements to querying and logging
- Allow use of "both" as a query parameter. This will search for created and destroyed blocks, but not chestaccess. This is useful for situations where the query defaults to "all" e.g. rollbacks. Fixes #210, #252 - Add block negation query parameter. Like with player names, you can now precede a block name with "!" to query for all except the specified blocks. Fixes #452, #216 - Allow use of area parameter with location parameter, as long as location is specified first. Fixes #458 - Better error when asking for kill log without world specified - Don't try to process events where the block is null. Fixes #463 - Replace problematic characters in world names with underscores when deciding on a default table name. Fixes #409 - Adjust for cocoa beans having reversed attachment direction in smart logging - Prevent out of bounds exception if a single-word timespec ends in a number. Fixes #354 - Prevent error when specifying a killer or victim in a teleport lookup. Fixes #333
This commit is contained in:
@@ -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() {
|
||||
|
||||
Executable → Regular
+40
-16
@@ -24,7 +24,7 @@ import static de.diddiz.util.Utils.*;
|
||||
|
||||
public final class QueryParams implements Cloneable
|
||||
{
|
||||
private static final Set<Integer> keywords = new HashSet<Integer>(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<Integer> keywords = new HashSet<Integer>(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<String> players = new ArrayList<String>();
|
||||
public List<String> killers = new ArrayList<String>();
|
||||
public List<String> victims = new ArrayList<String>();
|
||||
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<Block> types = new ArrayList<Block>();
|
||||
@@ -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<Integer> equivalent : getBlockEquivalents()) {
|
||||
boolean found = false;
|
||||
|
||||
@@ -14,7 +14,9 @@ public class WorldConfig extends LoggingEnabledMapping
|
||||
|
||||
public WorldConfig(File file) throws IOException {
|
||||
final Map<String, Object> def = new HashMap<String, Object>();
|
||||
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);
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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));
|
||||
|
||||
Reference in New Issue
Block a user