v1.00final

This commit is contained in:
Robin Kupper
2011-06-01 14:13:08 +02:00
parent d671188a0d
commit c52a1898dd
14 changed files with 270 additions and 242 deletions

View File

@@ -1,5 +1,6 @@
package de.diddiz.LogBlock; package de.diddiz.LogBlock;
import static de.diddiz.util.BukkitUtils.giveTool;
import java.io.Closeable; import java.io.Closeable;
import java.io.File; import java.io.File;
import java.io.FileWriter; import java.io.FileWriter;
@@ -27,7 +28,6 @@ import de.diddiz.LogBlock.QueryParams.SummarizationMode;
import de.diddiz.LogBlock.WorldEditor.WorldEditorException; import de.diddiz.LogBlock.WorldEditor.WorldEditorException;
import de.diddiz.LogBlockQuestioner.LogBlockQuestioner; import de.diddiz.LogBlockQuestioner.LogBlockQuestioner;
import de.diddiz.LogBlockQuestioner.QuestionerException; import de.diddiz.LogBlockQuestioner.QuestionerException;
import de.diddiz.util.BukkitUtils;
public class CommandsHandler implements CommandExecutor public class CommandsHandler implements CommandExecutor
{ {
@@ -109,7 +109,7 @@ public class CommandsHandler implements CommandExecutor
final Player player = (Player)sender; final Player player = (Player)sender;
if (args.length == 1) { if (args.length == 1) {
if (logblock.hasPermission(player, "logblock.tool")) if (logblock.hasPermission(player, "logblock.tool"))
BukkitUtils.giveTool(player, config.toolID); giveTool(player, config.toolID);
else else
sender.sendMessage(ChatColor.RED + "You aren't allowed to do this."); sender.sendMessage(ChatColor.RED + "You aren't allowed to do this.");
} else if (args[1].equalsIgnoreCase("enable") || args[1].equalsIgnoreCase("on")) { } else if (args[1].equalsIgnoreCase("enable") || args[1].equalsIgnoreCase("on")) {
@@ -135,7 +135,7 @@ public class CommandsHandler implements CommandExecutor
final Player player = (Player)sender; final Player player = (Player)sender;
if (args.length == 1) { if (args.length == 1) {
if (logblock.hasPermission(player, "logblock.toolblock")) if (logblock.hasPermission(player, "logblock.toolblock"))
BukkitUtils.giveTool(player, config.toolblockID); giveTool(player, config.toolblockID);
else else
player.sendMessage(ChatColor.RED + "You aren't allowed to do this."); player.sendMessage(ChatColor.RED + "You aren't allowed to do this.");
} else if (args[1].equalsIgnoreCase("enable") || args[1].equalsIgnoreCase("on")) { } else if (args[1].equalsIgnoreCase("enable") || args[1].equalsIgnoreCase("on")) {
@@ -430,12 +430,24 @@ public class CommandsHandler implements CommandExecutor
@Override @Override
public void run() { public void run() {
try { try {
rs = state.executeQuery(params.getQuery()); final int queue = logblock.getConsumer().getQueueSize();
if (queue > 50 && (!config.askSavequeueBeforeRollback || questioner != null && sender instanceof Player && questioner.askQuestion((Player)sender, "There are " + queue + " block in queue. Do yu want to process the queue before rollback?", "yes", "no").equals("yes")))
try {
new CommandSaveQueue(sender, null);
} catch (final Exception ex) {
sender.sendMessage(ChatColor.RED + ex.getMessage());
}
sender.sendMessage(ChatColor.DARK_AQUA + "Searching " + params.getTitle() + ":"); sender.sendMessage(ChatColor.DARK_AQUA + "Searching " + params.getTitle() + ":");
rs = state.executeQuery(params.getQuery());
final WorldEditor editor = new WorldEditor(logblock, params.world); final WorldEditor editor = new WorldEditor(logblock, params.world);
while (rs.next()) while (rs.next())
editor.queueBlockChange(rs.getInt("type"), rs.getInt("replaced"), rs.getByte("data"), rs.getInt("x"), rs.getInt("y"), rs.getInt("z"), rs.getString("signtext"), rs.getShort("itemtype"), rs.getShort("itemamount"), rs.getByte("itemdata")); editor.queueBlockChange(rs.getInt("type"), rs.getInt("replaced"), rs.getByte("data"), rs.getInt("x"), rs.getInt("y"), rs.getInt("z"), rs.getString("signtext"), rs.getShort("itemtype"), rs.getShort("itemamount"), rs.getByte("itemdata"));
final int changes = editor.getSize(); final int changes = editor.getSize();
if (changes == 0) {
sender.sendMessage(ChatColor.RED.toString() + changes + " blocks found.");
sender.sendMessage(ChatColor.RED + "Rollback aborted");
return;
}
sender.sendMessage(ChatColor.GREEN.toString() + changes + " blocks found."); sender.sendMessage(ChatColor.GREEN.toString() + changes + " blocks found.");
if (config.askRollbacks && questioner != null && sender instanceof Player && !questioner.askQuestion((Player)sender, "Are you sure you want to continue?", "yes", "no").equals("yes")) { if (config.askRollbacks && questioner != null && sender instanceof Player && !questioner.askQuestion((Player)sender, "Are you sure you want to continue?", "yes", "no").equals("yes")) {
sender.sendMessage(ChatColor.RED + "Rollback aborted"); sender.sendMessage(ChatColor.RED + "Rollback aborted");
@@ -445,6 +457,8 @@ public class CommandsHandler implements CommandExecutor
sender.sendMessage(ChatColor.GREEN + "Rollback finished successfully"); sender.sendMessage(ChatColor.GREEN + "Rollback finished successfully");
sender.sendMessage(ChatColor.GREEN + "Undid " + editor.getSuccesses() + " of " + changes + " changes (" + editor.getErrors() + " errors, " + editor.getBlacklistCollisions() + " blacklist collisions)"); sender.sendMessage(ChatColor.GREEN + "Undid " + editor.getSuccesses() + " of " + changes + " changes (" + editor.getErrors() + " errors, " + editor.getBlacklistCollisions() + " blacklist collisions)");
sender.sendMessage(ChatColor.GREEN + "Took: " + editor.getElapsedTime() + "ms"); sender.sendMessage(ChatColor.GREEN + "Took: " + editor.getElapsedTime() + "ms");
if (logblock.hasPermission(sender, "logblock.clearlog"))
sender.sendMessage(ChatColor.LIGHT_PURPLE + "Delete the log with '/lb clearlog last'");
} catch (final SQLException ex) { } catch (final SQLException ex) {
sender.sendMessage(ChatColor.RED + "SQL exception"); sender.sendMessage(ChatColor.RED + "SQL exception");
log.log(Level.SEVERE, "[LogBlock Rollback] SQL exception", ex); log.log(Level.SEVERE, "[LogBlock Rollback] SQL exception", ex);
@@ -475,6 +489,11 @@ public class CommandsHandler implements CommandExecutor
while (rs.next()) while (rs.next())
editor.queueBlockChange(rs.getInt("replaced"), rs.getInt("type"), rs.getByte("data"), rs.getInt("x"), rs.getInt("y"), rs.getInt("z"), rs.getString("signtext"), rs.getShort("itemtype"), (short)(rs.getShort("itemamount") * 1), rs.getByte("itemdata")); editor.queueBlockChange(rs.getInt("replaced"), rs.getInt("type"), rs.getByte("data"), rs.getInt("x"), rs.getInt("y"), rs.getInt("z"), rs.getString("signtext"), rs.getShort("itemtype"), (short)(rs.getShort("itemamount") * 1), rs.getByte("itemdata"));
final int changes = editor.getSize(); final int changes = editor.getSize();
if (changes == 0) {
sender.sendMessage(ChatColor.RED.toString() + changes + " blocks found.");
sender.sendMessage(ChatColor.RED + "Redo aborted");
return;
}
sender.sendMessage(ChatColor.GREEN.toString() + changes + " blocks found."); sender.sendMessage(ChatColor.GREEN.toString() + changes + " blocks found.");
if (config.askRedos && questioner != null && sender instanceof Player && !questioner.askQuestion((Player)sender, "Are you sure you want to continue?", "yes", "no").equals("yes")) { if (config.askRedos && questioner != null && sender instanceof Player && !questioner.askQuestion((Player)sender, "Are you sure you want to continue?", "yes", "no").equals("yes")) {
sender.sendMessage(ChatColor.RED + "Redo aborted"); sender.sendMessage(ChatColor.RED + "Redo aborted");
@@ -512,7 +531,12 @@ public class CommandsHandler implements CommandExecutor
final SimpleDateFormat formatter = new SimpleDateFormat("yyMMddHHmmss"); final SimpleDateFormat formatter = new SimpleDateFormat("yyMMddHHmmss");
int deleted; int deleted;
final String table = params.getTable(); final String table = params.getTable();
rs = state.executeQuery("SELECT count(*) FROM `" + table + "` " + params.getWhere()); final String join;
if (params.players.size() > 0)
join = "INNER JOIN `lb-players` USING (playerid) ";
else
join = "";
rs = state.executeQuery("SELECT count(*) FROM `" + table + "` " + join + params.getWhere());
rs.next(); rs.next();
if ((deleted = rs.getInt(1)) > 0) { if ((deleted = rs.getInt(1)) > 0) {
if (config.askClearLogs && sender instanceof Player && questioner != null) { if (config.askClearLogs && sender instanceof Player && questioner != null) {
@@ -525,13 +549,13 @@ public class CommandsHandler implements CommandExecutor
} }
if (config.dumpDeletedLog) if (config.dumpDeletedLog)
try { try {
state.execute("SELECT * FROM `" + table + "` " + params.getWhere() + "INTO OUTFILE '" + new File(dumpFolder, formatter.format(System.currentTimeMillis()) + " " + table + " " + params.getTitle() + ".csv").getAbsolutePath().replace("\\", "\\\\") + "' FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '\"' LINES TERMINATED BY '\n'"); state.execute("SELECT * FROM `" + table + "` " + join + params.getWhere() + "INTO OUTFILE '" + new File(dumpFolder, formatter.format(System.currentTimeMillis()) + " " + table + " " + params.getTitle() + ".csv").getAbsolutePath().replace("\\", "\\\\") + "' FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '\"' LINES TERMINATED BY '\n'");
} catch (final SQLException ex) { } catch (final SQLException ex) {
sender.sendMessage(ChatColor.RED + "Error while dumping log. Make sure your MySQL user has access to the LogBlock folder, or disable clearlog.dumpDeletedLog"); sender.sendMessage(ChatColor.RED + "Error while dumping log. Make sure your MySQL user has access to the LogBlock folder, or disable clearlog.dumpDeletedLog");
log.log(Level.SEVERE, "[LogBlock ClearLog] Exception while dumping", ex); log.log(Level.SEVERE, "[LogBlock ClearLog] Exception while dumping", ex);
return; return;
} }
state.execute("DELETE FROM `" + table + "` " + params.getWhere()); state.execute("DELETE `" + table + "` FROM `" + table + "` " + join + params.getWhere());
sender.sendMessage(ChatColor.GREEN + "Cleared out table " + table + ". Deleted " + deleted + " entries."); sender.sendMessage(ChatColor.GREEN + "Cleared out table " + table + ". Deleted " + deleted + " entries.");
} }
rs = state.executeQuery("SELECT COUNT(*) FROM `" + table + "-sign` LEFT JOIN `" + table + "` USING (id) WHERE `" + table + "`.id IS NULL"); rs = state.executeQuery("SELECT COUNT(*) FROM `" + table + "-sign` LEFT JOIN `" + table + "` USING (id) WHERE `" + table + "`.id IS NULL");
@@ -562,75 +586,10 @@ public class CommandsHandler implements CommandExecutor
} }
} }
private List<String> ArgsToList(String[] arr, int offset) { private static List<String> ArgsToList(String[] arr, int offset) {
final List<String> list = new ArrayList<String>(Arrays.asList(arr)); final List<String> list = new ArrayList<String>(Arrays.asList(arr));
for (int i = 0; i < offset; i++) for (int i = 0; i < offset; i++)
list.remove(0); list.remove(0);
return list; return list;
} }
private class HistoryFormatter
{
private final SimpleDateFormat formatter = new SimpleDateFormat("MM-dd HH:mm:ss");
private final SummarizationMode sum;
HistoryFormatter(SummarizationMode sum) {
this.sum = sum;
}
String format(ResultSet rs) {
try {
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;
if (type == 0)
action = "destroyed ";
else
action = "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) {
final int itemType = rs.getInt("itemtype");
final int itemAmount = rs.getInt("itemamount");
if (itemType == 0 || itemAmount == 0)
msg.append("looked inside " + BukkitUtils.getMaterialName(type));
else if (itemAmount < 0)
msg.append("took " + itemAmount * -1 + "x " + BukkitUtils.getMaterialName(itemType));
else
msg.append("put in " + itemAmount + "x " + BukkitUtils.getMaterialName(itemType));
}
} else if (type == 0)
msg.append("destroyed " + BukkitUtils.getMaterialName(replaced));
else if (replaced == 0)
msg.append("created " + BukkitUtils.getMaterialName(type));
else
msg.append("replaced " + BukkitUtils.getMaterialName(replaced) + " with " + BukkitUtils.getMaterialName(type));
return msg.toString();
} else if (sum == SummarizationMode.TYPES)
return fillWithSpaces(rs.getInt("created")) + fillWithSpaces(rs.getInt("destroyed")) + BukkitUtils.getMaterialName(rs.getInt("type"));
else
return fillWithSpaces(rs.getInt("created")) + fillWithSpaces(rs.getInt("destroyed")) + rs.getString("playername");
} catch (final SQLException ex) {
log.log(Level.SEVERE, "[LogBlock HistoryFormatter] Error", ex);
return null;
}
}
private String fillWithSpaces(Integer number) {
final StringBuilder filled = new StringBuilder(number.toString());
final int neededSpaces = (36 - filled.length() * 6) / 4;
for (int i = 0; i < neededSpaces; i++)
filled.append(' ');
return filled.toString();
}
}
} }

View File

@@ -1,57 +1,42 @@
package de.diddiz.LogBlock; package de.diddiz.LogBlock;
import static de.diddiz.util.Utils.parseTimeSpec;
import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.zip.DataFormatException;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.command.ConsoleCommandSender; import org.bukkit.command.ConsoleCommandSender;
import org.bukkit.util.config.Configuration; import org.bukkit.util.config.Configuration;
import de.diddiz.util.Utils;
public class Config public class Config
{ {
public final HashMap<Integer, String> tables; public final HashMap<Integer, String> tables;
public final String url; public final String url, user, password;
public final String user; public final int delayBetweenRuns, forceToProcessAtLeast, timePerRun;
public final String password;
public final int delayBetweenRuns;
public final int forceToProcessAtLeast;
public final int timePerRun;
public final boolean useBukkitScheduler; public final boolean useBukkitScheduler;
public final int keepLogDays; public final int keepLogDays;
public final boolean dumpDeletedLog; public final boolean dumpDeletedLog;
public final boolean logBlockCreations; public final boolean logBlockCreations, logBlockDestroyings, logSignTexts, logExplosions, logFire, logLeavesDecay, logLavaFlow, logChestAccess, logKills;
public final boolean logBlockDestroyings;
public final boolean logSignTexts;
public final boolean logExplosions;
public final boolean logCreeperExplosionsAsPlayerWhoTriggeredThese; public final boolean logCreeperExplosionsAsPlayerWhoTriggeredThese;
public final boolean logFire;
public final boolean logLeavesDecay;
public final boolean logLavaFlow;
public final boolean logChestAccess;
public final boolean logKills;
public final LogKillsLevel logKillsLevel; public final LogKillsLevel logKillsLevel;
public final Set<Integer> dontRollback; public final Set<Integer> dontRollback;
public final Set<Integer> replaceAnyway; public final Set<Integer> replaceAnyway;
public final QueryParams toolQuery; public final QueryParams toolQuery, toolBlockQuery;
public final QueryParams toolBlockQuery; public final int defaultDist, defaultTime;
public final int defaultDist; public final int toolID, toolblockID;
public final int defaultTime; public final boolean askRollbacks, askRedos, askClearLogs, askSavequeueBeforeRollback;
public final int toolID;
public final int toolblockID;
public final boolean askRollbacks;
public final boolean askRedos;
public final boolean askClearLogs;
public final Set<Integer> hiddenPlayers; public final Set<Integer> hiddenPlayers;
public static enum LogKillsLevel { public static enum LogKillsLevel {
PLAYERS, MONSTERS, ANIMALS PLAYERS, MONSTERS, ANIMALS
} }
Config(LogBlock logblock) throws Exception { Config(LogBlock logblock) throws DataFormatException, IOException {
final Configuration config = logblock.getConfiguration(); final Configuration config = logblock.getConfiguration();
config.load(); config.load();
final List<String> keys = config.getKeys(null); final List<String> keys = config.getKeys(null);
@@ -59,9 +44,9 @@ public class Config
if (!keys.contains("version")) if (!keys.contains("version"))
config.setProperty("version", logblock.getDescription().getVersion()); config.setProperty("version", logblock.getDescription().getVersion());
if (!keys.contains("loggedWorlds")) if (!keys.contains("loggedWorlds"))
config.setProperty("loggedWorlds", Arrays.asList(new String[]{"world", "nether"})); config.setProperty("loggedWorlds", Arrays.asList(new String[]{"world", "world_nether"}));
if (!keys.contains("tables")) if (!keys.contains("tables"))
config.setProperty("tables", Arrays.asList(new String[]{"lb-main", "lb-hell"})); config.setProperty("tables", Arrays.asList(new String[]{"lb-main", "lb-nether"}));
subkeys = config.getKeys("mysql"); subkeys = config.getKeys("mysql");
if (subkeys == null) if (subkeys == null)
subkeys = new ArrayList<String>(); subkeys = new ArrayList<String>();
@@ -90,7 +75,7 @@ public class Config
if (subkeys == null) if (subkeys == null)
subkeys = new ArrayList<String>(); subkeys = new ArrayList<String>();
if (!subkeys.contains("dumpDeletedLog")) if (!subkeys.contains("dumpDeletedLog"))
config.setProperty("clearlog.dumpDeletedLog", true); config.setProperty("clearlog.dumpDeletedLog", false);
if (!subkeys.contains("keepLogDays")) if (!subkeys.contains("keepLogDays"))
config.setProperty("clearlog.keepLogDays", -1); config.setProperty("clearlog.keepLogDays", -1);
subkeys = config.getKeys("logging"); subkeys = config.getKeys("logging");
@@ -119,7 +104,7 @@ public class Config
if (!subkeys.contains("logKillsLevel")) if (!subkeys.contains("logKillsLevel"))
config.setProperty("logging.logKillsLevel", "PLAYERS"); config.setProperty("logging.logKillsLevel", "PLAYERS");
if (!subkeys.contains("hiddenPlayers")) if (!subkeys.contains("hiddenPlayers"))
config.setProperty("logging.hiddenPlayers", Arrays.asList(new String[]{"Nessie", "Bigfoot", "Chewbacca"})); config.setProperty("logging.hiddenPlayers", new ArrayList<String>());
subkeys = config.getKeys("rollback"); subkeys = config.getKeys("rollback");
if (subkeys == null) if (subkeys == null)
subkeys = new ArrayList<String>(); subkeys = new ArrayList<String>();
@@ -151,8 +136,10 @@ public class Config
config.setProperty("questioner.askRedos", true); config.setProperty("questioner.askRedos", true);
if (!subkeys.contains("askClearLogs")) if (!subkeys.contains("askClearLogs"))
config.setProperty("questioner.askClearLogs", true); config.setProperty("questioner.askClearLogs", true);
if (!subkeys.contains("askSavequeueBeforeRollback"))
config.setProperty("questioner.askSavequeueBeforeRollback", true);
if (!config.save()) if (!config.save())
throw new Exception("Error while writing to config.yml"); throw new IOException("Error while writing to config.yml");
url = "jdbc:mysql://" + config.getString("mysql.host") + ":" + config.getString("mysql.port") + "/" + config.getString("mysql.database"); url = "jdbc:mysql://" + config.getString("mysql.host") + ":" + config.getString("mysql.port") + "/" + config.getString("mysql.database");
user = config.getString("mysql.user"); user = config.getString("mysql.user");
password = config.getString("mysql.password"); password = config.getString("mysql.password");
@@ -162,8 +149,8 @@ public class Config
useBukkitScheduler = config.getBoolean("consumer.useBukkitScheduler", true); useBukkitScheduler = config.getBoolean("consumer.useBukkitScheduler", true);
keepLogDays = config.getInt("clearlog.keepLogDays", -1); keepLogDays = config.getInt("clearlog.keepLogDays", -1);
if (keepLogDays * 86400000L > System.currentTimeMillis()) if (keepLogDays * 86400000L > System.currentTimeMillis())
throw new Exception("Too large timespan for keepLogDays. Must be shorter than " + (int)(System.currentTimeMillis() / 86400000L) + " days."); throw new DataFormatException("Too large timespan for keepLogDays. Must be shorter than " + (int)(System.currentTimeMillis() / 86400000L) + " days.");
dumpDeletedLog = config.getBoolean("clearlog.dumpDeletedLog", true); dumpDeletedLog = config.getBoolean("clearlog.dumpDeletedLog", false);
logBlockCreations = config.getBoolean("logging.logBlockCreations", true); logBlockCreations = config.getBoolean("logging.logBlockCreations", true);
logBlockDestroyings = config.getBoolean("logging.logBlockDestroyings", true); logBlockDestroyings = config.getBoolean("logging.logBlockDestroyings", true);
logSignTexts = config.getBoolean("logging.logSignTexts", false); logSignTexts = config.getBoolean("logging.logSignTexts", false);
@@ -177,7 +164,7 @@ public class Config
try { try {
logKillsLevel = LogKillsLevel.valueOf(config.getString("logging.logKillsLevel")); logKillsLevel = LogKillsLevel.valueOf(config.getString("logging.logKillsLevel"));
} catch (final IllegalArgumentException ex) { } catch (final IllegalArgumentException ex) {
throw new Exception("lookup.toolblockID doesn't appear to be a valid log level. Allowed are 'PLAYERS', 'MONSTERS' and 'ANIMALS'"); throw new DataFormatException("lookup.toolblockID doesn't appear to be a valid log level. Allowed are 'PLAYERS', 'MONSTERS' and 'ANIMALS'");
} }
hiddenPlayers = new HashSet<Integer>(); hiddenPlayers = new HashSet<Integer>();
for (final String playerName : config.getStringList("hiddenPlayers", new ArrayList<String>())) for (final String playerName : config.getStringList("hiddenPlayers", new ArrayList<String>()))
@@ -189,31 +176,32 @@ public class Config
toolQuery.prepareToolQuery = true; toolQuery.prepareToolQuery = true;
toolQuery.parseArgs(new ConsoleCommandSender(logblock.getServer()), Arrays.asList(config.getString("lookup.toolQuery").split(" "))); toolQuery.parseArgs(new ConsoleCommandSender(logblock.getServer()), Arrays.asList(config.getString("lookup.toolQuery").split(" ")));
} catch (final IllegalArgumentException ex) { } catch (final IllegalArgumentException ex) {
throw new Exception("Error at lookup.toolQuery: " + ex.getMessage()); throw new DataFormatException("Error at lookup.toolQuery: " + ex.getMessage());
} }
try { try {
toolBlockQuery = new QueryParams(logblock); toolBlockQuery = new QueryParams(logblock);
toolBlockQuery.prepareToolQuery = true; toolBlockQuery.prepareToolQuery = true;
toolBlockQuery.parseArgs(new ConsoleCommandSender(logblock.getServer()), Arrays.asList(config.getString("lookup.toolBlockQuery").split(" "))); toolBlockQuery.parseArgs(new ConsoleCommandSender(logblock.getServer()), Arrays.asList(config.getString("lookup.toolBlockQuery").split(" ")));
} catch (final IllegalArgumentException ex) { } catch (final IllegalArgumentException ex) {
throw new Exception("Error at lookup.toolBlockQuery: " + ex.getMessage()); throw new DataFormatException("Error at lookup.toolBlockQuery: " + ex.getMessage());
} }
defaultDist = config.getInt("lookup.defaultDist", 20); defaultDist = config.getInt("lookup.defaultDist", 20);
defaultTime = Utils.parseTimeSpec(config.getString("lookup.defaultTime").split(" ")); defaultTime = parseTimeSpec(config.getString("lookup.defaultTime").split(" "));
toolID = config.getInt("lookup.toolID", 270); toolID = config.getInt("lookup.toolID", 270);
if (Material.getMaterial(toolID) == null || Material.getMaterial(toolID).isBlock()) if (Material.getMaterial(toolID) == null || Material.getMaterial(toolID).isBlock())
throw new Exception("lookup.toolID doesn't appear to be a valid item id"); throw new DataFormatException("lookup.toolID doesn't appear to be a valid item id");
toolblockID = config.getInt("lookup.toolblockID", 7); toolblockID = config.getInt("lookup.toolblockID", 7);
if (Material.getMaterial(toolblockID) == null || !Material.getMaterial(toolblockID).isBlock() || toolblockID == 0) if (Material.getMaterial(toolblockID) == null || !Material.getMaterial(toolblockID).isBlock() || toolblockID == 0)
throw new Exception("lookup.toolblockID doesn't appear to be a valid block id"); throw new DataFormatException("lookup.toolblockID doesn't appear to be a valid block id");
askRollbacks = config.getBoolean("questioner.askRollbacks", true); askRollbacks = config.getBoolean("questioner.askRollbacks", true);
askRedos = config.getBoolean("questioner.askRedos", true); askRedos = config.getBoolean("questioner.askRedos", true);
askClearLogs = config.getBoolean("questioner.askClearLogs", true); askClearLogs = config.getBoolean("questioner.askClearLogs", true);
askSavequeueBeforeRollback = config.getBoolean("questioner.askSavequeueBeforeRollback", true);
final List<String> worldNames = config.getStringList("loggedWorlds", null); final List<String> worldNames = config.getStringList("loggedWorlds", null);
final List<String> worldTables = config.getStringList("tables", null); final List<String> worldTables = config.getStringList("tables", null);
tables = new HashMap<Integer, String>(); tables = new HashMap<Integer, String>();
if (worldNames == null || worldTables == null || worldNames.size() == 0 || worldNames.size() != worldTables.size()) if (worldNames == null || worldTables == null || worldNames.size() == 0 || worldNames.size() != worldTables.size())
throw new Exception("worldNames or worldTables not set properly"); throw new DataFormatException("worldNames or worldTables not set properly");
for (int i = 0; i < worldNames.size(); i++) for (int i = 0; i < worldNames.size(); i++)
tables.put(worldNames.get(i).hashCode(), worldTables.get(i)); tables.put(worldNames.get(i).hashCode(), worldTables.get(i));
} }

View File

@@ -1,5 +1,8 @@
package de.diddiz.LogBlock; package de.diddiz.LogBlock;
import static de.diddiz.util.BukkitUtils.compressInventory;
import static de.diddiz.util.BukkitUtils.getEntityName;
import static de.diddiz.util.BukkitUtils.rawData;
import java.sql.Connection; import java.sql.Connection;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
@@ -20,7 +23,6 @@ import org.bukkit.entity.Entity;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory; import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import de.diddiz.util.BukkitUtils;
public class Consumer extends TimerTask public class Consumer extends TimerTask
{ {
@@ -160,9 +162,9 @@ public class Consumer extends TimerTask
* Logs a container block break. The block type before is assumed to be o (air). All content is assumed to be taken. * Logs a container block break. The block type before is assumed to be o (air). All content is assumed to be taken.
*/ */
public void queueContainerBreak(String playerName, Location loc, int type, byte data, Inventory inv) { public void queueContainerBreak(String playerName, Location loc, int type, byte data, Inventory inv) {
final ItemStack[] items = BukkitUtils.compressInventory(inv.getContents()); final ItemStack[] items = compressInventory(inv.getContents());
for (final ItemStack item : items) for (final ItemStack item : items)
queueChestAccess(playerName, loc, type, (short)item.getTypeId(), (short)(item.getAmount() * -1), BukkitUtils.rawData(item)); queueChestAccess(playerName, loc, type, (short)item.getTypeId(), (short)(item.getAmount() * -1), rawData(item));
queueBlockBreak(playerName, loc, type, data); queueBlockBreak(playerName, loc, type, data);
} }
@@ -182,7 +184,7 @@ public class Consumer extends TimerTask
weapon = ((Player)killer).getItemInHand().getTypeId(); weapon = ((Player)killer).getItemInHand().getTypeId();
lastAttackedEntity.put(killer.getEntityId(), victim.getEntityId()); lastAttackedEntity.put(killer.getEntityId(), victim.getEntityId());
lastAttackTime.put(killer.getEntityId(), System.currentTimeMillis()); lastAttackTime.put(killer.getEntityId(), System.currentTimeMillis());
queueKill(victim.getWorld(), BukkitUtils.getEntityName(killer), BukkitUtils.getEntityName(victim), weapon); queueKill(victim.getWorld(), getEntityName(killer), getEntityName(victim), weapon);
} }
/** /**
@@ -421,6 +423,9 @@ public class Consumer extends TimerTask
ChestAccess(short itemType, short itemAmount, byte itemData) { ChestAccess(short itemType, short itemAmount, byte itemData) {
this.itemType = itemType; this.itemType = itemType;
this.itemAmount = itemAmount; this.itemAmount = itemAmount;
if (itemData < 0)
this.itemData = 0;
else
this.itemData = itemData; this.itemData = itemData;
} }
} }

View File

@@ -0,0 +1,67 @@
package de.diddiz.LogBlock;
import static de.diddiz.util.BukkitUtils.getMaterialName;
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;
HistoryFormatter(SummarizationMode sum) {
this.sum = sum;
}
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;
if (type == 0)
action = "destroyed ";
else
action = "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) {
final int itemType = rs.getInt("itemtype");
final int itemAmount = rs.getInt("itemamount");
if (itemType == 0 || itemAmount == 0)
msg.append("looked inside " + getMaterialName(type));
else if (itemAmount < 0)
msg.append("took " + itemAmount * -1 + "x " + getMaterialName(itemType));
else
msg.append("put in " + itemAmount + "x " + getMaterialName(itemType));
}
} else if (type == 0)
msg.append("destroyed " + getMaterialName(replaced));
else if (replaced == 0)
msg.append("created " + getMaterialName(type));
else
msg.append("replaced " + getMaterialName(replaced) + " with " + getMaterialName(type));
return msg.toString();
} else if (sum == SummarizationMode.TYPES)
return fillWithSpaces(rs.getInt("created")) + fillWithSpaces(rs.getInt("destroyed")) + getMaterialName(rs.getInt("type"));
else
return fillWithSpaces(rs.getInt("created")) + fillWithSpaces(rs.getInt("destroyed")) + rs.getString("playername");
}
private static String fillWithSpaces(Integer number) {
final StringBuilder filled = new StringBuilder(number.toString());
final int neededSpaces = (36 - filled.length() * 6) / 4;
for (int i = 0; i < neededSpaces; i++)
filled.append(' ');
return filled.toString();
}
}

View File

@@ -1,5 +1,8 @@
package de.diddiz.LogBlock; package de.diddiz.LogBlock;
import static de.diddiz.util.BukkitUtils.compareInventories;
import static de.diddiz.util.BukkitUtils.compressInventory;
import static de.diddiz.util.BukkitUtils.rawData;
import java.util.HashMap; import java.util.HashMap;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.block.BlockState; import org.bukkit.block.BlockState;
@@ -8,7 +11,6 @@ import org.bukkit.inventory.ItemStack;
import org.bukkitcontrib.event.inventory.InventoryCloseEvent; import org.bukkitcontrib.event.inventory.InventoryCloseEvent;
import org.bukkitcontrib.event.inventory.InventoryListener; import org.bukkitcontrib.event.inventory.InventoryListener;
import org.bukkitcontrib.event.inventory.InventoryOpenEvent; import org.bukkitcontrib.event.inventory.InventoryOpenEvent;
import de.diddiz.util.BukkitUtils;
class LBChestAccessListener extends InventoryListener class LBChestAccessListener extends InventoryListener
{ {
@@ -25,10 +27,10 @@ class LBChestAccessListener extends InventoryListener
final String playerName = event.getPlayer().getName(); final String playerName = event.getPlayer().getName();
final Location loc = event.getLocation(); final Location loc = event.getLocation();
final ItemStack[] before = containers.get(playerName.hashCode()); final ItemStack[] before = containers.get(playerName.hashCode());
final ItemStack[] after = BukkitUtils.compressInventory(event.getInventory().getContents()); final ItemStack[] after = compressInventory(event.getInventory().getContents());
final ItemStack[] diff = BukkitUtils.compareInventories(before, after); final ItemStack[] diff = compareInventories(before, after);
for (final ItemStack item : diff) for (final ItemStack item : diff)
consumer.queueChestAccess(playerName, loc, loc.getWorld().getBlockTypeIdAt(loc), (short)item.getTypeId(), (short)item.getAmount(), BukkitUtils.rawData(item)); consumer.queueChestAccess(playerName, loc, loc.getWorld().getBlockTypeIdAt(loc), (short)item.getTypeId(), (short)item.getAmount(), rawData(item));
containers.remove(playerName.hashCode()); containers.remove(playerName.hashCode());
} }
} }
@@ -38,7 +40,7 @@ class LBChestAccessListener extends InventoryListener
if (!event.isCancelled() && event.getLocation() != null) { if (!event.isCancelled() && event.getLocation() != null) {
final BlockState state = event.getLocation().getWorld().getBlockAt(event.getLocation()).getState(); final BlockState state = event.getLocation().getWorld().getBlockAt(event.getLocation()).getState();
if (state instanceof ContainerBlock) if (state instanceof ContainerBlock)
containers.put(event.getPlayer().getName().hashCode(), BukkitUtils.compressInventory(((ContainerBlock)state).getInventory().getContents())); containers.put(event.getPlayer().getName().hashCode(), compressInventory(((ContainerBlock)state).getInventory().getContents()));
} }
} }
} }

View File

@@ -44,7 +44,7 @@ class LBToolListener extends PlayerListener
if (tables.get(player.getWorld().getName().hashCode()) != null) { if (tables.get(player.getWorld().getName().hashCode()) != null) {
try { try {
final QueryParams params = logblock.getSession(player.getName()).toolQuery; final QueryParams params = logblock.getSession(player.getName()).toolQuery;
params.setLocation(event.getClickedBlock().getLocation()); params.setLocation(event.getClickedBlock().getFace(event.getBlockFace()).getLocation());
handler.new CommandLookup(player, params); handler.new CommandLookup(player, params);
} catch (final Exception ex) { } catch (final Exception ex) {
player.sendMessage(ChatColor.RED + ex.getMessage()); player.sendMessage(ChatColor.RED + ex.getMessage());

View File

@@ -1,13 +1,10 @@
package de.diddiz.LogBlock; package de.diddiz.LogBlock;
import static de.diddiz.util.Utils.downloadIfNotExists;
import java.io.File; import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URL; import java.net.URL;
import java.sql.Connection; import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.SQLException; import java.sql.SQLException;
import java.sql.Statement;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Timer; import java.util.Timer;
@@ -24,8 +21,7 @@ import org.bukkit.plugin.java.JavaPlugin;
import com.nijiko.permissions.PermissionHandler; import com.nijiko.permissions.PermissionHandler;
import com.nijikokun.bukkit.Permissions.Permissions; import com.nijikokun.bukkit.Permissions.Permissions;
import de.diddiz.LogBlock.QueryParams.BlockChangeType; import de.diddiz.LogBlock.QueryParams.BlockChangeType;
import de.diddiz.util.ConnectionPool; import de.diddiz.util.MySQLConnectionPool;
import de.diddiz.util.Utils;
// TODO Add painting logging // TODO Add painting logging
// TODO Add Button, lever etc logging // TODO Add Button, lever etc logging
@@ -34,7 +30,7 @@ public class LogBlock extends JavaPlugin
{ {
private Logger log; private Logger log;
private Config config; private Config config;
private ConnectionPool pool; private MySQLConnectionPool pool;
private Consumer consumer = null; private Consumer consumer = null;
private CommandsHandler commandsHandler; private CommandsHandler commandsHandler;
private Timer timer = null; private Timer timer = null;
@@ -59,35 +55,13 @@ public class LogBlock extends JavaPlugin
log = getServer().getLogger(); log = getServer().getLogger();
try { try {
config = new Config(this); config = new Config(this);
} catch (final Exception ex) { downloadIfNotExists(log, new File("lib/mysql-connector-java-bin.jar"), new URL("http://diddiz.insane-architects.net/download/mysql-connector-java-bin.jar"));
log.log(Level.SEVERE, "[LogBlock] Exception while reading config:", ex);
errorAtLoading = true;
return;
}
final File file = new File("lib/mysql-connector-java-bin.jar");
try {
if (!file.exists() || file.length() == 0) {
log.info("[LogBlock] Downloading " + file.getName() + "...");
Utils.download(new URL("http://diddiz.insane-architects.net/download/mysql-connector-java-bin.jar"), file);
}
if (!file.exists() || file.length() == 0)
throw new FileNotFoundException(file.getAbsolutePath() + file.getName());
} catch (final IOException e) {
log.log(Level.SEVERE, "[LogBlock] Error while downloading " + file.getName() + ".");
errorAtLoading = true;
return;
}
try {
log.info("[LogBlock] Connecting to " + config.user + "@" + config.url + "..."); log.info("[LogBlock] Connecting to " + config.user + "@" + config.url + "...");
pool = new ConnectionPool(config.url, config.user, config.password); pool = new MySQLConnectionPool(config.url, config.user, config.password);
getConnection().close(); getConnection().close();
new Updater(this).checkTables();
} catch (final Exception ex) { } catch (final Exception ex) {
log.log(Level.SEVERE, "[LogBlock] Exception while checking database connection", ex); log.log(Level.SEVERE, "[LogBlock] Error while loading: ", ex);
errorAtLoading = true;
return;
}
if (!checkTables()) {
log.log(Level.SEVERE, "[LogBlock] Errors while checking tables. They may not exist.");
errorAtLoading = true; errorAtLoading = true;
return; return;
} }
@@ -184,64 +158,6 @@ public class LogBlock extends JavaPlugin
log.info("LogBlock disabled."); log.info("LogBlock disabled.");
} }
private boolean checkTables() {
final Connection conn = getConnection();
Statement state = null;
if (conn == null)
return false;
try {
final DatabaseMetaData dbm = conn.getMetaData();
conn.setAutoCommit(true);
state = conn.createStatement();
if (!dbm.getTables(null, null, "lb-players", null).next()) {
log.log(Level.INFO, "[LogBlock] Crating table lb-players.");
state.execute("CREATE TABLE `lb-players` (playerid SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT, playername varchar(32) NOT NULL DEFAULT '-', PRIMARY KEY (playerid), UNIQUE (playername))");
if (!dbm.getTables(null, null, "lb-players", null).next())
return false;
}
for (final String table : config.tables.values()) {
if (!dbm.getTables(null, null, table, null).next()) {
log.log(Level.INFO, "[LogBlock] Crating table " + table + ".");
state.execute("CREATE TABLE `" + table + "` (id INT NOT NULL AUTO_INCREMENT, date DATETIME NOT NULL, playerid SMALLINT UNSIGNED NOT NULL, replaced TINYINT UNSIGNED NOT NULL, type TINYINT UNSIGNED NOT NULL, data TINYINT UNSIGNED NOT NULL, x SMALLINT NOT NULL, y TINYINT UNSIGNED NOT NULL, z SMALLINT NOT NULL, PRIMARY KEY (id), KEY coords (y, x, z), KEY date (date))");
if (!dbm.getTables(null, null, table, null).next())
return false;
}
if (!dbm.getTables(null, null, table + "-sign", null).next()) {
log.log(Level.INFO, "[LogBlock] Crating table " + table + "-sign.");
state.execute("CREATE TABLE `" + table + "-sign` (id INT NOT NULL, signtext TEXT, PRIMARY KEY (id));");
if (!dbm.getTables(null, null, table + "-sign", null).next())
return false;
}
if (dbm.getTables(null, null, table + "-chest", null).next() && state.executeQuery("SELECT * FROM `" + table + "-chest` LIMIT 1").getMetaData().getColumnCount() != 4) // Chest table update
state.execute("DROP TABLE `" + table + "-chest`");
if (!dbm.getTables(null, null, table + "-chest", null).next()) {
log.log(Level.INFO, "[LogBlock] Crating table " + table + "-chest.");
state.execute("CREATE TABLE `" + table + "-chest` (id INT NOT NULL, itemtype SMALLINT UNSIGNED NOT NULL, itemamount SMALLINT NOT NULL, itemdata TINYINT UNSIGNED NOT NULL, PRIMARY KEY (id))");
if (!dbm.getTables(null, null, table + "-chest", null).next())
return false;
}
if (config.logKills && !dbm.getTables(null, null, table + "-kills", null).next()) {
log.log(Level.INFO, "[LogBlock] Crating table " + table + "-kills.");
state.execute("CREATE TABLE `" + table + "-kills` (id INT UNSIGNED NOT NULL AUTO_INCREMENT, date DATETIME NOT NULL, killer SMALLINT UNSIGNED, victim SMALLINT UNSIGNED NOT NULL, weapon SMALLINT UNSIGNED NOT NULL, PRIMARY KEY (id));");
if (!dbm.getTables(null, null, table + "-kills", null).next())
return false;
}
}
return true;
} catch (final SQLException ex) {
log.log(Level.SEVERE, "[LogBlock] SQL exception while checking tables", ex);
} finally {
try {
if (state != null)
state.close();
conn.close();
} catch (final SQLException ex) {
log.log(Level.SEVERE, "[LogBlock] SQL exception on close", ex);
}
}
return false;
}
boolean hasPermission(CommandSender sender, String permission) { boolean hasPermission(CommandSender sender, String permission) {
if (permissions != null && sender instanceof Player) if (permissions != null && sender instanceof Player)
return permissions.permission((Player)sender, permission); return permissions.permission((Player)sender, permission);

View File

@@ -1,5 +1,11 @@
package de.diddiz.LogBlock; package de.diddiz.LogBlock;
import static de.diddiz.util.BukkitUtils.friendlyWorldname;
import static de.diddiz.util.BukkitUtils.getBlockEquivalents;
import static de.diddiz.util.BukkitUtils.getMaterialName;
import static de.diddiz.util.BukkitUtils.getSenderName;
import static de.diddiz.util.Utils.isInt;
import static de.diddiz.util.Utils.parseTimeSpec;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashSet; import java.util.HashSet;
@@ -14,8 +20,6 @@ import org.bukkit.plugin.Plugin;
import com.sk89q.worldedit.bukkit.WorldEditPlugin; import com.sk89q.worldedit.bukkit.WorldEditPlugin;
import com.sk89q.worldedit.bukkit.selections.CuboidSelection; import com.sk89q.worldedit.bukkit.selections.CuboidSelection;
import com.sk89q.worldedit.bukkit.selections.Selection; import com.sk89q.worldedit.bukkit.selections.Selection;
import de.diddiz.util.BukkitUtils;
import de.diddiz.util.Utils;
public class QueryParams implements Cloneable public class QueryParams implements Cloneable
{ {
@@ -90,7 +94,7 @@ public class QueryParams implements Cloneable
final StringBuilder title = new StringBuilder(); final StringBuilder title = new StringBuilder();
if (!types.isEmpty()) { if (!types.isEmpty()) {
for (int i = 0; i < types.size(); i++) for (int i = 0; i < types.size(); i++)
title.append(BukkitUtils.getMaterialName(types.get(i)) + ", "); title.append(getMaterialName(types.get(i)) + ", ");
title.deleteCharAt(title.length() - 2); title.deleteCharAt(title.length() - 2);
} else } else
title.append("Block "); title.append("Block ");
@@ -116,7 +120,7 @@ public class QueryParams implements Cloneable
title.append("at " + loc.getBlockX() + ":" + loc.getBlockY() + ":" + loc.getBlockZ() + " "); title.append("at " + loc.getBlockX() + ":" + loc.getBlockY() + ":" + loc.getBlockZ() + " ");
else if (sel != null) else if (sel != null)
title.append("inside selection "); title.append("inside selection ");
title.append("in " + BukkitUtils.friendlyWorldname(world.getName())); title.append("in " + friendlyWorldname(world.getName()));
title.setCharAt(0, String.valueOf(title.charAt(0)).toUpperCase().toCharArray()[0]); title.setCharAt(0, String.valueOf(title.charAt(0)).toUpperCase().toCharArray()[0]);
return title.toString(); return title.toString();
} }
@@ -204,10 +208,9 @@ public class QueryParams implements Cloneable
Player player = null; Player player = null;
if (sender instanceof Player) if (sender instanceof Player)
player = (Player)sender; player = (Player)sender;
final String name = BukkitUtils.getSenderName(sender);
final Session session; final Session session;
if (!prepareToolQuery) if (!prepareToolQuery)
session = logblock.getSession(name); session = logblock.getSession(getSenderName(sender));
else else
session = null; session = null;
if (player != null && world == null) if (player != null && world == null)
@@ -224,7 +227,7 @@ public class QueryParams implements Cloneable
throw new IllegalArgumentException("No or wrong count of arguments for '" + param + "'"); throw new IllegalArgumentException("No or wrong count of arguments for '" + param + "'");
for (final String playerName : values) for (final String playerName : values)
if (playerName.length() > 0) if (playerName.length() > 0)
players.add(playerName); players.add(playerName.replace("\\", "\\\\").replace("'", "\\'"));
} else if (param.equals("block") || param.equals("type")) { } else if (param.equals("block") || param.equals("type")) {
if (values == null || values.length < 1) if (values == null || values.length < 1)
throw new IllegalArgumentException("No or wrong count of arguments for '" + param + "'"); throw new IllegalArgumentException("No or wrong count of arguments for '" + param + "'");
@@ -242,7 +245,7 @@ public class QueryParams implements Cloneable
if (!prepareToolQuery) if (!prepareToolQuery)
loc = player.getLocation(); loc = player.getLocation();
} else { } else {
if (!Utils.isInt(values[0])) if (!isInt(values[0]))
throw new IllegalArgumentException("Not a number: '" + values[0] + "'"); throw new IllegalArgumentException("Not a number: '" + values[0] + "'");
radius = Integer.parseInt(values[0]); radius = Integer.parseInt(values[0]);
if (!prepareToolQuery) if (!prepareToolQuery)
@@ -264,14 +267,14 @@ public class QueryParams implements Cloneable
if (values == null) if (values == null)
minutes = logblock.getConfig().defaultTime; minutes = logblock.getConfig().defaultTime;
else else
minutes = Utils.parseTimeSpec(values); minutes = parseTimeSpec(values);
if (minutes == -1) if (minutes == -1)
throw new IllegalArgumentException("Faile to parse time spec for '" + param + "'"); throw new IllegalArgumentException("Faile to parse time spec for '" + param + "'");
} else if (param.equals("before")) { } else if (param.equals("before")) {
if (values == null) if (values == null)
minutes = logblock.getConfig().defaultTime * -1; minutes = logblock.getConfig().defaultTime * -1;
else else
minutes = Utils.parseTimeSpec(values) * -1; minutes = parseTimeSpec(values) * -1;
if (minutes == 1) if (minutes == 1)
throw new IllegalArgumentException("Faile to parse time spec for '" + param + "'"); throw new IllegalArgumentException("Faile to parse time spec for '" + param + "'");
} else if (param.equals("sum")) { } else if (param.equals("sum")) {
@@ -296,7 +299,7 @@ public class QueryParams implements Cloneable
else if (param.equals("limit")) { else if (param.equals("limit")) {
if (values.length != 1) if (values.length != 1)
throw new IllegalArgumentException("Wrong count of arguments for '" + param + "'"); throw new IllegalArgumentException("Wrong count of arguments for '" + param + "'");
if (!Utils.isInt(values[0])) if (!isInt(values[0]))
throw new IllegalArgumentException("Not a number: '" + values[0] + "'"); throw new IllegalArgumentException("Not a number: '" + values[0] + "'");
limit = Integer.parseInt(values[0]); limit = Integer.parseInt(values[0]);
} else if (param.equals("world")) { } else if (param.equals("world")) {
@@ -315,7 +318,7 @@ public class QueryParams implements Cloneable
i += values.length; i += values.length;
} }
if (types.size() > 0) if (types.size() > 0)
for (final Set<Integer> equivalent : BukkitUtils.getBlockEquivalents()) { for (final Set<Integer> equivalent : getBlockEquivalents()) {
boolean found = false; boolean found = false;
for (final Integer type : types) for (final Integer type : types)
if (equivalent.contains(type)) { if (equivalent.contains(type)) {

View File

@@ -0,0 +1,64 @@
package de.diddiz.LogBlock;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.logging.Level;
import java.util.logging.Logger;
class Updater
{
private final Logger log;
private final LogBlock logblock;
Updater(LogBlock logblock) {
this.logblock = logblock;
log = logblock.getServer().getLogger();
}
void checkTables() throws SQLException {
final Connection conn = logblock.getConnection();
if (conn == null)
throw new SQLException("No connection");
final Statement state = conn.createStatement();
final DatabaseMetaData dbm = conn.getMetaData();
conn.setAutoCommit(true);
if (!dbm.getTables(null, null, "lb-players", null).next()) {
log.log(Level.INFO, "[LogBlock] Crating table lb-players.");
state.execute("CREATE TABLE `lb-players` (playerid SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT, playername varchar(32) NOT NULL DEFAULT '-', PRIMARY KEY (playerid), UNIQUE (playername))");
if (!dbm.getTables(null, null, "lb-players", null).next())
throw new SQLException("Table lb-players not found");
}
for (final String table : logblock.getConfig().tables.values()) {
if (!dbm.getTables(null, null, table, null).next()) {
log.log(Level.INFO, "[LogBlock] Crating table " + table + ".");
state.execute("CREATE TABLE `" + table + "` (id INT NOT NULL AUTO_INCREMENT, date DATETIME NOT NULL, playerid SMALLINT UNSIGNED NOT NULL, replaced TINYINT UNSIGNED NOT NULL, type TINYINT UNSIGNED NOT NULL, data TINYINT UNSIGNED NOT NULL, x SMALLINT NOT NULL, y TINYINT UNSIGNED NOT NULL, z SMALLINT NOT NULL, PRIMARY KEY (id), KEY coords (x, z, y), KEY date (date))");
if (!dbm.getTables(null, null, table, null).next())
throw new SQLException("Table " + table + " not found");
}
if (!dbm.getTables(null, null, table + "-sign", null).next()) {
log.log(Level.INFO, "[LogBlock] Crating table " + table + "-sign.");
state.execute("CREATE TABLE `" + table + "-sign` (id INT NOT NULL, signtext TEXT, PRIMARY KEY (id));");
if (!dbm.getTables(null, null, table + "-sign", null).next())
throw new SQLException("Table " + table + "-sign not found");
}
if (dbm.getTables(null, null, table + "-chest", null).next() && state.executeQuery("SELECT * FROM `" + table + "-chest` LIMIT 1").getMetaData().getColumnCount() != 4) // Chest table update
state.execute("DROP TABLE `" + table + "-chest`");
if (!dbm.getTables(null, null, table + "-chest", null).next()) {
log.log(Level.INFO, "[LogBlock] Crating table " + table + "-chest.");
state.execute("CREATE TABLE `" + table + "-chest` (id INT NOT NULL, itemtype SMALLINT UNSIGNED NOT NULL, itemamount SMALLINT NOT NULL, itemdata TINYINT UNSIGNED NOT NULL, PRIMARY KEY (id))");
if (!dbm.getTables(null, null, table + "-chest", null).next())
throw new SQLException("Table " + table + "-chest not found");
}
if (logblock.getConfig().logKills && !dbm.getTables(null, null, table + "-kills", null).next()) {
log.log(Level.INFO, "[LogBlock] Crating table " + table + "-kills.");
state.execute("CREATE TABLE `" + table + "-kills` (id INT UNSIGNED NOT NULL AUTO_INCREMENT, date DATETIME NOT NULL, killer SMALLINT UNSIGNED, victim SMALLINT UNSIGNED NOT NULL, weapon SMALLINT UNSIGNED NOT NULL, PRIMARY KEY (id));");
if (!dbm.getTables(null, null, table + "-kills", null).next())
throw new SQLException("Table " + table + "-kills not found");
}
}
state.close();
conn.close();
}
}

View File

@@ -1,5 +1,6 @@
package de.diddiz.LogBlock; package de.diddiz.LogBlock;
import static de.diddiz.util.BukkitUtils.equalTypes;
import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.LinkedBlockingQueue;
import java.util.logging.Logger; import java.util.logging.Logger;
import org.bukkit.World; import org.bukkit.World;
@@ -11,7 +12,6 @@ import org.bukkit.block.Sign;
import org.bukkit.inventory.Inventory; import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.bukkit.material.Bed; import org.bukkit.material.Bed;
import de.diddiz.util.BukkitUtils;
public class WorldEditor implements Runnable public class WorldEditor implements Runnable
{ {
@@ -144,7 +144,7 @@ public class WorldEditor implements Runnable
return PerformResult.SUCCESS; return PerformResult.SUCCESS;
} else } else
return PerformResult.NO_ACTION; return PerformResult.NO_ACTION;
if (!(BukkitUtils.equalTypes(block.getTypeId(), type) || config.replaceAnyway.contains(block.getTypeId()))) if (!(equalTypes(block.getTypeId(), type) || config.replaceAnyway.contains(block.getTypeId())))
return PerformResult.NO_ACTION; return PerformResult.NO_ACTION;
if (state instanceof ContainerBlock) { if (state instanceof ContainerBlock) {
((ContainerBlock)state).getInventory().clear(); ((ContainerBlock)state).getInventory().clear();
@@ -156,8 +156,12 @@ public class WorldEditor implements Runnable
if (signtext != null && (curtype == 63 || curtype == 68)) { if (signtext != null && (curtype == 63 || curtype == 68)) {
final Sign sign = (Sign)block.getState(); final Sign sign = (Sign)block.getState();
final String[] lines = signtext.split("\0"); final String[] lines = signtext.split("\0");
try {
for (int i = 0; i < 4; i++) for (int i = 0; i < 4; i++)
sign.setLine(i, lines[i]); sign.setLine(i, lines[i]);
} catch (final IndexOutOfBoundsException ex) {
return PerformResult.ERROR;
}
if (!sign.update()) if (!sign.update())
return PerformResult.ERROR; return PerformResult.ERROR;
} else if (curtype == 26) { } else if (curtype == 26) {

View File

@@ -34,14 +34,15 @@ public class BukkitUtils
public static ItemStack[] compareInventories(ItemStack[] items1, ItemStack[] items2) { public static ItemStack[] compareInventories(ItemStack[] items1, ItemStack[] items2) {
final ItemStackComparator comperator = new ItemStackComparator(); final ItemStackComparator comperator = new ItemStackComparator();
final ArrayList<ItemStack> diff = new ArrayList<ItemStack>(); final ArrayList<ItemStack> diff = new ArrayList<ItemStack>();
final int l1 = items1.length, l2 = items2.length;
int c1 = 0, c2 = 0; int c1 = 0, c2 = 0;
while (c1 < items1.length || c2 < items2.length) { while (c1 < l1 || c2 < l2) {
if (c1 >= items1.length) { if (c1 >= l1) {
diff.add(items2[c2]); diff.add(items2[c2]);
c2++; c2++;
continue; continue;
} }
if (c2 >= items2.length) { if (c2 >= l2) {
items1[c1].setAmount(items1[c1].getAmount() * -1); items1[c1].setAmount(items1[c1].getAmount() * -1);
diff.add(items1[c1]); diff.add(items1[c1]);
c1++; c1++;
@@ -147,7 +148,7 @@ public class BukkitUtils
return item.getData().getData(); return item.getData().getData();
} }
private static class ItemStackComparator implements Comparator<ItemStack> public static class ItemStackComparator implements Comparator<ItemStack>
{ {
@Override @Override
public int compare(ItemStack a, ItemStack b) { public int compare(ItemStack a, ItemStack b) {

View File

@@ -22,7 +22,7 @@ import java.util.Map;
import java.util.Properties; import java.util.Properties;
import java.util.Vector; import java.util.Vector;
public class ConnectionPool implements Closeable public class MySQLConnectionPool implements Closeable
{ {
private final static int poolsize = 10; private final static int poolsize = 10;
private final static long timeToLive = 300000; private final static long timeToLive = 300000;
@@ -30,7 +30,7 @@ public class ConnectionPool implements Closeable
private final ConnectionReaper reaper; private final ConnectionReaper reaper;
private final String url, user, password; private final String url, user, password;
public ConnectionPool(String url, String user, String password) throws ClassNotFoundException { public MySQLConnectionPool(String url, String user, String password) throws ClassNotFoundException {
Class.forName("com.mysql.jdbc.Driver"); Class.forName("com.mysql.jdbc.Driver");
this.url = url; this.url = url;
this.user = user; this.user = user;

View File

@@ -2,6 +2,7 @@ package de.diddiz.util;
import java.io.BufferedOutputStream; import java.io.BufferedOutputStream;
import java.io.File; import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
@@ -9,23 +10,41 @@ import java.io.OutputStream;
import java.net.URL; import java.net.URL;
import java.text.ParseException; import java.text.ParseException;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.logging.Logger;
public class Utils public class Utils
{ {
public static void download(URL u, File file) throws IOException { public static void download(Logger log, URL url, File file) throws IOException {
if (!file.getParentFile().exists()) if (!file.getParentFile().exists())
file.getParentFile().mkdir(); file.getParentFile().mkdir();
if (file.exists()) if (file.exists())
file.delete(); file.delete();
file.createNewFile(); file.createNewFile();
final InputStream in = u.openStream(); final int size = url.openConnection().getContentLength();
log.info("Downloading " + file.getName() + " (" + size / 1024 + "kb) ...");
final InputStream in = url.openStream();
final OutputStream out = new BufferedOutputStream(new FileOutputStream(file)); final OutputStream out = new BufferedOutputStream(new FileOutputStream(file));
final byte[] buffer = new byte[1024]; final byte[] buffer = new byte[1024];
int len; int len, downloaded = 0, msgs = 0;
while ((len = in.read(buffer)) >= 0) final long start = System.currentTimeMillis();
while ((len = in.read(buffer)) >= 0) {
out.write(buffer, 0, len); out.write(buffer, 0, len);
downloaded += len;
if ((int)((System.currentTimeMillis() - start) / 500) > msgs) {
log.info((int)((double)downloaded / (double)size * 100d) + "%");
msgs++;
}
}
in.close(); in.close();
out.close(); out.close();
log.info("Download finished");
}
public static void downloadIfNotExists(Logger log, File file, URL url) throws IOException {
if (!file.exists() || file.length() == 0)
Utils.download(log, url, file);
if (!file.exists() || file.length() == 0)
throw new FileNotFoundException(file.getAbsolutePath() + file.getName());
} }
public static boolean isInt(String str) { public static boolean isInt(String str) {

View File

@@ -1,5 +1,5 @@
name: LogBlock name: LogBlock
version: '1.00rc3' version: '1.00final'
author: DiddiZ, bootswithdefer author: DiddiZ, bootswithdefer
website: http://www.diddiz.de/minecraft/ website: http://www.diddiz.de/minecraft/
main: de.diddiz.LogBlock.LogBlock main: de.diddiz.LogBlock.LogBlock