diff --git a/src/de/diddiz/LogBlock/BlockChange.java b/src/de/diddiz/LogBlock/BlockChange.java index 4f5d399..a6c6641 100644 --- a/src/de/diddiz/LogBlock/BlockChange.java +++ b/src/de/diddiz/LogBlock/BlockChange.java @@ -1,9 +1,15 @@ package de.diddiz.LogBlock; +import static de.diddiz.util.BukkitUtils.materialName; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.text.SimpleDateFormat; import org.bukkit.Location; public class BlockChange { + private final static SimpleDateFormat formatter = new SimpleDateFormat("MM-dd HH:mm:ss"); + public final long date; public final Location loc; public final String playerName; public final int replaced, type; @@ -11,7 +17,8 @@ public class BlockChange public final String signtext; public final ChestAccess ca; - public BlockChange(Location loc, String playerName, int replaced, int type, byte data, String signtext, ChestAccess ca) { + public BlockChange(long date, Location loc, String playerName, int replaced, int type, byte data, String signtext, ChestAccess ca) { + this.date = date; this.loc = loc; this.playerName = playerName; this.replaced = replaced; @@ -20,4 +27,49 @@ public class BlockChange this.signtext = signtext; this.ca = ca; } + + public BlockChange(ResultSet rs, boolean coords) throws SQLException { + date = rs.getTimestamp("date").getTime(); + loc = coords ? new Location(null, rs.getInt("x"), rs.getInt("y"), rs.getInt("z")) : null; + playerName = rs.getString("playername"); + replaced = rs.getInt("replaced"); + type = rs.getInt("type"); + data = (byte)0; + signtext = type == 63 || type == 68 || replaced == 63 || replaced == 68 ? rs.getString("signtext") : null; + ca = type == replaced && (type == 23 || type == 54 || type == 61 || type == 62) ? new ChestAccess(rs.getShort("itemtype"), rs.getShort("itemamount"), (byte)0) : null; + } + + @Override + public String toString() { + final StringBuilder msg = new StringBuilder(formatter.format(date) + " " + playerName + " "); + if (signtext != null) { + final String action = type == 0 ? "destroyed " : "created "; + if (!signtext.contains("\0")) + msg.append(action + signtext); + else + msg.append(action + materialName(type != 0 ? type : replaced) + " [" + signtext.replace("\0", "] [") + "]"); + } else if (type == replaced) { + if (type == 0) + msg.append("did a unspecified action"); + else if (ca != null) { + if (ca.itemType == 0 || ca.itemAmount == 0) + msg.append("looked inside " + materialName(type)); + else if (ca.itemAmount < 0) + msg.append("took " + ca.itemAmount * -1 + "x " + materialName(ca.itemType)); + else + msg.append("put in " + ca.itemAmount + "x " + materialName(ca.itemType)); + } else if (type == 69) + msg.append("swiched " + materialName(type)); + else if (type == 77) + msg.append("pressed " + materialName(type)); + } else if (type == 0) + msg.append("destroyed " + materialName(replaced)); + else if (replaced == 0) + msg.append("created " + materialName(type)); + else + msg.append("replaced " + materialName(replaced) + " with " + materialName(type)); + if (loc != null) + msg.append(" at " + loc.getBlockX() + ":" + loc.getBlockY() + ":" + loc.getBlockZ()); + return msg.toString(); + } } diff --git a/src/de/diddiz/LogBlock/CommandsHandler.java b/src/de/diddiz/LogBlock/CommandsHandler.java index 9cbdbe0..8b81e2f 100644 --- a/src/de/diddiz/LogBlock/CommandsHandler.java +++ b/src/de/diddiz/LogBlock/CommandsHandler.java @@ -2,6 +2,8 @@ package de.diddiz.LogBlock; import static de.diddiz.util.BukkitUtils.giveTool; import static de.diddiz.util.BukkitUtils.saveSpawnHeight; +import static de.diddiz.util.BukkitUtils.senderName; +import static de.diddiz.util.Utils.isInt; import java.io.Closeable; import java.io.File; import java.io.FileWriter; @@ -204,7 +206,16 @@ public class CommandsHandler implements CommandExecutor sender.sendMessage(ChatColor.RED + "You aren't allowed to do this."); } else sender.sendMessage(ChatColor.RED + "You have to be a player."); - } else if (args[0].equalsIgnoreCase("savequeue")) { + } else if (command.equals("page")) { + if (args.length == 2 && isInt(args[1])) + showPage(sender, Integer.valueOf(args[1])); + else + sender.sendMessage(ChatColor.RED + "You have to specify a page"); + } else if (command.equals("next")) + showPage(sender, logblock.getSession(senderName(sender)).page + 1); + else if (command.equals("prev")) + showPage(sender, logblock.getSession(senderName(sender)).page - 1); + else if (args[0].equalsIgnoreCase("savequeue")) { if (logblock.hasPermission(sender, "logblock.rollback")) try { new CommandSaveQueue(sender, null, true); @@ -317,6 +328,22 @@ public class CommandsHandler implements CommandExecutor return true; } + private void showPage(CommandSender sender, int page) { + final Session session = logblock.getSession(senderName(sender)); + if (session.lookupCache != null && session.lookupCache.length > 0) { + final int startpos = (page - 1) * config.linesPerPage; + if (page > 0 && startpos < session.lookupCache.length - 1) { + final int stoppos = startpos + config.linesPerPage > session.lookupCache.length ? session.lookupCache.length : startpos + config.linesPerPage - 1; + sender.sendMessage(ChatColor.BLUE + "Page " + page + "/" + (int)Math.ceil(session.lookupCache.length / (double)config.linesPerPage)); + for (int i = startpos; i <= stoppos; i++) + sender.sendMessage(ChatColor.GOLD + session.lookupCache[i].toString()); + session.page = page; + } else + sender.sendMessage(ChatColor.RED + "There isn't a page '" + page + "'"); + } else + sender.sendMessage(ChatColor.RED + "No blocks in lookup cache"); + } + public abstract class LBCommand implements Runnable, Closeable { protected final CommandSender sender; @@ -361,20 +388,22 @@ public class CommandsHandler implements CommandExecutor @Override public void run() { try { + if (params.limit == 15) + params.limit = config.linesLimit; rs = state.executeQuery(params.getLookupQuery()); sender.sendMessage(ChatColor.DARK_AQUA + params.getTitle()); + final List blockchanges = new ArrayList(); if (rs.next()) { rs.beforeFirst(); - final SummarizationMode sum = params.sum; - final HistoryFormatter histformatter = new HistoryFormatter(sum, params.coords, (sender instanceof Player ? 2 / 3f : 1)); - if (sum == SummarizationMode.TYPES) - sender.sendMessage(ChatColor.GOLD + "Created - Destroyed - Block"); - else if (sum == SummarizationMode.PLAYERS) - sender.sendMessage(ChatColor.GOLD + "Created - Destroyed - Player"); while (rs.next()) - sender.sendMessage(ChatColor.GOLD + histformatter.format(rs)); - } else + blockchanges.add(new BlockChange(rs, params.coords)); + logblock.getSession(senderName(sender)).lookupCache = blockchanges.toArray(new BlockChange[blockchanges.size()]); + showPage(sender, 1); + } else { sender.sendMessage(ChatColor.DARK_AQUA + "No results found."); + logblock.getSession(senderName(sender)).lookupCache = null; + } + } catch (final Exception ex) { sender.sendMessage(ChatColor.RED + "Exception, check error log"); log.log(Level.SEVERE, "[LogBlock Lookup] Exception: ", ex); diff --git a/src/de/diddiz/LogBlock/Config.java b/src/de/diddiz/LogBlock/Config.java index 3b0d257..b32bae0 100644 --- a/src/de/diddiz/LogBlock/Config.java +++ b/src/de/diddiz/LogBlock/Config.java @@ -28,6 +28,7 @@ public class Config public final Set dontRollback, replaceAnyway; public final QueryParams toolQuery, toolBlockQuery; public final int defaultDist, defaultTime; + public final int linesPerPage, linesLimit; public final int toolID, toolblockID; public final boolean askRollbacks, askRedos, askClearLogs, askSavequeueBeforeRollback; public final Set hiddenPlayers, hiddenBlocks; @@ -131,6 +132,10 @@ public class Config config.setProperty("lookup.toolQuery", "area 0 all sum none limit 15 desc silent"); if (!subkeys.contains("toolBlockQuery")) config.setProperty("lookup.toolBlockQuery", "area 0 all sum none limit 15 desc silent"); + if (!subkeys.contains("linesPerPage")) + config.setProperty("lookup.linesPerPage", 15); + if (!subkeys.contains("linesLimit")) + config.setProperty("lookup.linesLimit", 1500); subkeys = config.getKeys("questioner"); if (subkeys == null) subkeys = new ArrayList(); @@ -206,6 +211,8 @@ public class Config toolblockID = config.getInt("lookup.toolblockID", 7); if (Material.getMaterial(toolblockID) == null || !Material.getMaterial(toolblockID).isBlock() || toolblockID == 0) throw new DataFormatException("lookup.toolblockID doesn't appear to be a valid block id"); + linesPerPage = config.getInt("lookup.linesPerPage", 15); + linesLimit = config.getInt("lookup.linesLimit", 1500); askRollbacks = config.getBoolean("questioner.askRollbacks", true); askRedos = config.getBoolean("questioner.askRedos", true); askClearLogs = config.getBoolean("questioner.askClearLogs", true); diff --git a/src/de/diddiz/LogBlock/Consumer.java b/src/de/diddiz/LogBlock/Consumer.java index dbf8426..ce0e340 100644 --- a/src/de/diddiz/LogBlock/Consumer.java +++ b/src/de/diddiz/LogBlock/Consumer.java @@ -262,7 +262,7 @@ public class Consumer extends TimerTask } final boolean needKeys = b.signtext != null || b.ca != null; table = config.tables.get(b.loc.getWorld().getName().hashCode()); - state.execute("INSERT INTO `" + table + "` (date, playerid, replaced, type, data, x, y, z) VALUES (now(), " + players.get(playerHash) + ", " + b.replaced + ", " + b.type + ", " + b.data + ", '" + b.loc.getBlockX() + "', " + b.loc.getBlockY() + ", '" + b.loc.getBlockZ() + "')", needKeys ? Statement.RETURN_GENERATED_KEYS : Statement.NO_GENERATED_KEYS); + state.execute("INSERT INTO `" + table + "` (date, playerid, replaced, type, data, x, y, z) VALUES (FROM_UNIXTIME(" + b.date + "), " + players.get(playerHash) + ", " + b.replaced + ", " + b.type + ", " + b.data + ", '" + b.loc.getBlockX() + "', " + b.loc.getBlockY() + ", '" + b.loc.getBlockZ() + "')", needKeys ? Statement.RETURN_GENERATED_KEYS : Statement.NO_GENERATED_KEYS); if (needKeys) { final ResultSet keys = state.getGeneratedKeys(); if (keys.next()) { @@ -341,7 +341,7 @@ public class Consumer extends TimerTask playerName = playerName.replaceAll("[^a-zA-Z0-9_]", ""); if (signtext != null) signtext = signtext.replace("\\", "\\\\").replace("'", "\\'"); - bqueue.add(new BlockChange(loc, playerName, typeBefore, typeAfter, data, signtext, ca)); + bqueue.add(new BlockChange(System.currentTimeMillis() / 1000, loc, playerName, typeBefore, typeAfter, data, signtext, ca)); } private static class KillRow diff --git a/src/de/diddiz/LogBlock/HistoryFormatter.java b/src/de/diddiz/LogBlock/HistoryFormatter.java index c8bf710..b74b041 100644 --- a/src/de/diddiz/LogBlock/HistoryFormatter.java +++ b/src/de/diddiz/LogBlock/HistoryFormatter.java @@ -4,12 +4,10 @@ import static de.diddiz.util.BukkitUtils.materialName; import static de.diddiz.util.Utils.spaces; import java.sql.ResultSet; import java.sql.SQLException; -import java.text.SimpleDateFormat; import de.diddiz.LogBlock.QueryParams.SummarizationMode; public class HistoryFormatter { - private final SimpleDateFormat formatter = new SimpleDateFormat("MM-dd HH:mm:ss"); private final SummarizationMode sum; private final boolean coords; private final float factor; @@ -21,43 +19,8 @@ public class HistoryFormatter } String format(ResultSet rs) throws SQLException { - if (sum == SummarizationMode.NONE) { - final StringBuilder msg = new StringBuilder(formatter.format(rs.getTimestamp("date")) + " " + rs.getString("playername") + " "); - final int type = rs.getInt("type"); - final int replaced = rs.getInt("replaced"); - final String signtext; - if ((type == 63 || type == 68 || replaced == 63 || replaced == 68) && (signtext = rs.getString("signtext")) != null) { - final String action = type == 0 ? "destroyed " : "created "; - if (!signtext.contains("\0")) - msg.append(action + signtext); - else - msg.append(action + "sign [" + signtext.replace("\0", "] [") + "]"); - } else if (type == replaced) { - if (type == 0) - msg.append("did a unspecified action"); - else if (type == 23 || type == 54 || type == 61 || type == 62) { - final int itemType = rs.getInt("itemtype"); - final int itemAmount = rs.getInt("itemamount"); - if (itemType == 0 || itemAmount == 0) - msg.append("looked inside " + materialName(type)); - else if (itemAmount < 0) - msg.append("took " + itemAmount * -1 + "x " + materialName(itemType)); - else - msg.append("put in " + itemAmount + "x " + materialName(itemType)); - } else if (type == 69) - msg.append("swiched " + materialName(type)); - else if (type == 77) - msg.append("pressed " + materialName(type)); - } else if (type == 0) - msg.append("destroyed " + materialName(replaced)); - else if (replaced == 0) - msg.append("created " + materialName(type)); - else - msg.append("replaced " + materialName(replaced) + " with " + materialName(type)); - if (coords) - msg.append(" at " + rs.getInt("x") + ":" + rs.getInt("y") + ":" + rs.getInt("z")); - return msg.toString(); - } + if (sum == SummarizationMode.NONE) + return new BlockChange(rs, coords).toString(); String c1 = String.valueOf(rs.getInt(2)), c2 = String.valueOf(rs.getInt(3)); c1 += spaces((int)((10 - c1.length()) / factor)); c2 += spaces((int)((10 - c2.length()) / factor)); diff --git a/src/de/diddiz/LogBlock/Session.java b/src/de/diddiz/LogBlock/Session.java index 27f9884..fdef4ab 100644 --- a/src/de/diddiz/LogBlock/Session.java +++ b/src/de/diddiz/LogBlock/Session.java @@ -9,6 +9,8 @@ public class Session public boolean toolBlockEnabled = true; public QueryParams toolBlockQuery; public ToolMode toolBlockMode; + public BlockChange[] lookupCache = null; + public int page = 1; Session(LogBlock logblock) { toolQuery = logblock.getConfig().toolQuery.clone(); diff --git a/src/de/diddiz/LogBlock/WorldEditor.java b/src/de/diddiz/LogBlock/WorldEditor.java index 2689cf9..923546e 100644 --- a/src/de/diddiz/LogBlock/WorldEditor.java +++ b/src/de/diddiz/LogBlock/WorldEditor.java @@ -50,7 +50,7 @@ public class WorldEditor implements Runnable } public void queueEdit(int x, int y, int z, int replaced, int type, byte data, String signtext, short itemType, short itemAmount, byte itemData) { - edits.add(new Edit(new Location(world, x, y, z), null, replaced, type, data, signtext, new ChestAccess(itemType, itemAmount, itemData))); + edits.add(new Edit(0, new Location(world, x, y, z), null, replaced, type, data, signtext, new ChestAccess(itemType, itemAmount, itemData))); } public long getElapsedTime() { @@ -99,8 +99,8 @@ public class WorldEditor implements Runnable private class Edit extends BlockChange { - public Edit(Location loc, String playerName, int replaced, int type, byte data, String signtext, ChestAccess ca) { - super(loc, playerName, replaced, type, data, signtext, ca); + public Edit(long time, Location loc, String playerName, int replaced, int type, byte data, String signtext, ChestAccess ca) { + super(time, loc, playerName, replaced, type, data, signtext, ca); } PerformResult perform() {