diff --git a/src/de/diddiz/LogBlock/AreaBlockSearch.java b/src/de/diddiz/LogBlock/AreaBlockSearch.java index 8ff8011..a5212f1 100644 --- a/src/de/diddiz/LogBlock/AreaBlockSearch.java +++ b/src/de/diddiz/LogBlock/AreaBlockSearch.java @@ -8,7 +8,6 @@ import java.sql.Statement; import java.sql.Timestamp; import java.text.SimpleDateFormat; import java.util.logging.Level; -import java.util.logging.Logger; import org.bukkit.Location; import org.bukkit.Material; @@ -16,7 +15,6 @@ import org.bukkit.entity.Player; public class AreaBlockSearch implements Runnable { - static final Logger log = Logger.getLogger("Minecraft"); private Player player; private Location location; private int type; @@ -71,7 +69,7 @@ public class AreaBlockSearch implements Runnable hist = true; } } catch (SQLException ex) { - log.log(Level.SEVERE, this.getClass().getName() + " SQL exception", ex); + LogBlock.log.log(Level.SEVERE, this.getClass().getName() + " SQL exception", ex); } finally { try { if (rs != null) @@ -81,7 +79,7 @@ public class AreaBlockSearch implements Runnable if (conn != null) conn.close(); } catch (SQLException ex) { - log.log(Level.SEVERE, this.getClass().getName() + " SQL exception on close", ex); + LogBlock.log.log(Level.SEVERE, this.getClass().getName() + " SQL exception on close", ex); } } if (!hist) diff --git a/src/de/diddiz/LogBlock/AreaStats.java b/src/de/diddiz/LogBlock/AreaStats.java index 3bf538a..ffa16c8 100644 --- a/src/de/diddiz/LogBlock/AreaStats.java +++ b/src/de/diddiz/LogBlock/AreaStats.java @@ -8,13 +8,11 @@ import java.sql.Statement; import java.util.HashMap; import java.util.HashSet; import java.util.logging.Level; -import java.util.logging.Logger; import org.bukkit.entity.Player; public class AreaStats implements Runnable { - static final Logger log = Logger.getLogger("Minecraft"); private Player player; private int size; private Connection conn = null; @@ -69,7 +67,7 @@ public class AreaStats implements Runnable } } catch (SQLException ex) { - log.log(Level.SEVERE, this.getClass().getName() + " SQL exception", ex); + LogBlock.log.log(Level.SEVERE, this.getClass().getName() + " SQL exception", ex); } finally { try { if (rs != null) @@ -79,7 +77,7 @@ public class AreaStats implements Runnable if (conn != null) conn.close(); } catch (SQLException ex) { - log.log(Level.SEVERE, this.getClass().getName() + " SQL exception on close", ex); + LogBlock.log.log(Level.SEVERE, this.getClass().getName() + " SQL exception on close", ex); } } diff --git a/src/de/diddiz/LogBlock/LogBlock.java b/src/de/diddiz/LogBlock/LogBlock.java index 2e6fcb1..5cb374b 100644 --- a/src/de/diddiz/LogBlock/LogBlock.java +++ b/src/de/diddiz/LogBlock/LogBlock.java @@ -1,7 +1,6 @@ package de.diddiz.LogBlock; import java.io.File; -import java.io.FileWriter; import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.DriverManager; @@ -17,8 +16,8 @@ import java.util.concurrent.TimeUnit; import java.util.logging.Level; import java.util.logging.Logger; +import org.bukkit.ChatColor; import org.bukkit.Material; -import org.bukkit.Server; import org.bukkit.block.Block; import org.bukkit.entity.Player; import org.bukkit.event.Event; @@ -28,11 +27,11 @@ import org.bukkit.event.block.BlockListener; import org.bukkit.event.block.BlockPlaceEvent; import org.bukkit.event.block.BlockRightClickEvent; import org.bukkit.event.block.SignChangeEvent; +import org.bukkit.event.entity.EntityExplodeEvent; +import org.bukkit.event.entity.EntityListener; import org.bukkit.event.player.PlayerChatEvent; import org.bukkit.event.player.PlayerItemEvent; import org.bukkit.event.player.PlayerListener; -import org.bukkit.plugin.PluginDescriptionFile; -import org.bukkit.plugin.PluginLoader; import org.bukkit.plugin.PluginManager; import org.bukkit.plugin.java.JavaPlugin; @@ -42,10 +41,10 @@ import com.nijikokun.bukkit.Permissions.Permissions; public class LogBlock extends JavaPlugin { - private LBLPlayerListener lblPlayerListener = new LBLPlayerListener(); - private LBLBlockListener lblBlockListener = new LBLBlockListener(); - //private LBLEntityListener lblEntityListener = new LBLEntityListener(); - static final Logger log = Logger.getLogger("Minecraft"); + private LBLPlayerListener lblPlayerListener; + private LBLBlockListener lblBlockListener; + private LBLEntityListener lblEntityListener; + static Logger log; private List worldNames; private List worldTables; private boolean usePermissions = false; @@ -60,38 +59,19 @@ public class LogBlock extends JavaPlugin private int toolblockID = 7; private int keepLogDays = -1; private boolean toolblockRemove = true; + private boolean logExplosions = false; private Consumer consumer = null; private LinkedBlockingQueue bqueue = new LinkedBlockingQueue(); - public LogBlock(PluginLoader pluginLoader, Server instance, PluginDescriptionFile desc, File folder, File plugin, ClassLoader cLoader) - { - super(pluginLoader, instance, desc, folder, plugin, cLoader); - } - @Override public void onEnable() { + log = getServer().getLogger(); try { - File file = new File (getDataFolder(), "config.yml"); - if (!file.exists()) { - file.getParentFile().mkdirs(); - FileWriter writer = new FileWriter(file); - String crlf = System.getProperty("line.separator"); - writer.write("driver : com.mysql.jdbc.Driver" + crlf - + "url : jdbc:mysql://localhost:3306/db" + crlf - + "username : user" + crlf - + "password : pass" + crlf - + "delay : 6" + crlf - + "tool-id : 270" + crlf - + "tool-block-id : 7" + crlf - + "tool-block-remove : true" + crlf - + "default-distance : 20" + crlf - + "usePermissions : false" + crlf - + "keepLogDays : false" + crlf - + "worldNames : [world]" + crlf - + "worldTables : [lb-main]"); - writer.close(); - log.info(name + " Config created"); + if (!new File (getDataFolder(), "config.yml").exists()) { + log.log(Level.SEVERE, name + " Config not found"); + getServer().getPluginManager().disablePlugin(this); + return; } getConfiguration().load(); dbDriver = getConfiguration().getString("driver", "com.mysql.jdbc.Driver"); @@ -106,6 +86,7 @@ public class LogBlock extends JavaPlugin keepLogDays = getConfiguration().getInt("keepLogDays", -1); worldNames = getConfiguration().getStringList("worldNames", null); worldTables = getConfiguration().getStringList("worldTables", null); + logExplosions = getConfiguration().getBoolean("logExplosions", false); if (getConfiguration().getBoolean("usePermissions", false)) { if (getServer().getPluginManager().getPlugin("Permissions") != null) { usePermissions = true; @@ -121,12 +102,12 @@ public class LogBlock extends JavaPlugin try { new JDCConnectionDriver(dbDriver, dbUrl, dbUsername, dbPassword); } catch (Exception ex) { - log.log(Level.SEVERE, name + "Exception while creation database connection pool", ex); + log.log(Level.SEVERE, name + " Exception while creation database connection pool", ex); getServer().getPluginManager().disablePlugin(this); return; } if (worldNames == null || worldTables == null || worldNames.size() == 0 || worldNames.size() != worldTables.size()) { - log.log(Level.SEVERE, name + ": worldNames or worldTables not set porperly"); + log.log(Level.SEVERE, name + " worldNames or worldTables not set porperly"); getServer().getPluginManager().disablePlugin(this); return; } @@ -140,13 +121,21 @@ public class LogBlock extends JavaPlugin if (keepLogDays >= 0) dropOldLogs(); PluginManager pm = getServer().getPluginManager(); + + lblPlayerListener = new LBLPlayerListener(); pm.registerEvent(Type.PLAYER_COMMAND, lblPlayerListener, Event.Priority.Normal, this); - pm.registerEvent(Type.BLOCK_RIGHTCLICKED, lblBlockListener, Event.Priority.Monitor, this); pm.registerEvent(Type.PLAYER_ITEM, lblPlayerListener, Event.Priority.Monitor, this); + + lblBlockListener = new LBLBlockListener(); + pm.registerEvent(Type.BLOCK_RIGHTCLICKED, lblBlockListener, Event.Priority.Monitor, this); pm.registerEvent(Type.BLOCK_PLACED, lblBlockListener, Event.Priority.Monitor, this); pm.registerEvent(Type.BLOCK_BREAK, lblBlockListener, Event.Priority.Monitor, this); pm.registerEvent(Type.SIGN_CHANGE, lblBlockListener, Event.Priority.Monitor, this); - //pm.registerEvent(Type.ENTITY_EXPLODE, lblEntityListener, Event.Priority.Monitor, this); + + if (logExplosions) { + lblEntityListener = new LBLEntityListener(); + pm.registerEvent(Type.ENTITY_EXPLODE, lblEntityListener, Event.Priority.Monitor, this); + } consumer = new Consumer(); new Thread(consumer).start(); log.info("Logblock v" + getDescription().getVersion() + " enabled."); @@ -162,9 +151,14 @@ public class LogBlock extends JavaPlugin log.info("LogBlock disabled."); } - private Connection getConnection() throws SQLException + private Connection getConnection() { - return DriverManager.getConnection("jdbc:jdc:jdcpool"); + try { + return DriverManager.getConnection("jdbc:jdc:jdcpool"); + } catch (SQLException ex) { + log.log(Level.SEVERE, name + " SQL exception", ex); + return null; + } } private boolean checkTables(String table) @@ -225,6 +219,13 @@ public class LogBlock extends JavaPlugin } } + private String GetTable (String worldName) { + int idx = worldNames.indexOf(worldName); + if (idx == -1) + return null; + return worldTables.get(idx); + } + private void showBlockHistory(Player player, Block b) { @@ -288,10 +289,10 @@ public class LogBlock extends JavaPlugin { if (block == null || typeBefore < 0 || typeAfter < 0) return; - int idx = worldNames.indexOf(block.getWorld().getName()); - if (idx == -1) + String table = GetTable(block.getWorld().getName()); + if (table == null) return; - BlockRow row = new BlockRow(worldTables.get(idx), playerName, typeBefore, typeAfter, data, block.getX(), block.getY(), block.getZ()); + BlockRow row = new BlockRow(table, playerName, typeBefore, typeAfter, data, block.getX(), block.getY(), block.getZ()); if (!bqueue.offer(row)) log.info(name + " failed to queue block for " + playerName); } @@ -326,23 +327,18 @@ public class LogBlock extends JavaPlugin return false; } - private int parseTimeSpec(String ts) + private int parseTimeSpec(String time, String unit) { - String[] split = ts.split(" "); - - if (split.length < 2) - return 0; - int min; try { - min = Integer.parseInt(split[0]); + min = Integer.parseInt(time); } catch (NumberFormatException ex) { return 0; } - if (split[1].startsWith("hour")) + if (unit.startsWith("hour")) min *= 60; - else if (split[1].startsWith("day")) + else if (unit.startsWith("day")) min *= (60*24); return min; } @@ -356,22 +352,18 @@ public class LogBlock extends JavaPlugin Player player = event.getPlayer(); if (split[0].equalsIgnoreCase("/lb")) { event.setCancelled(true); - int idx = worldNames.indexOf(player.getWorld().getName()); - if (idx == -1) - return; - String table = worldTables.get(idx); - if (!CheckPermission(event.getPlayer(),"logblock.area")) - { + Connection conn = getConnection(); + String table = GetTable(event.getPlayer().getWorld().getName()); + if (!CheckPermission(event.getPlayer(),"logblock.rollback")) { event.getPlayer().sendMessage("§cInsufficient permissions"); return; } - Connection conn; - try { - conn = getConnection(); + if (conn == null) { + player.sendMessage(ChatColor.RED + "Can't create SQL connection."); + return; } - catch (SQLException ex) { - log.log(Level.SEVERE, name + " SQL exception", ex); - player.sendMessage("§cError, check server logs."); + if (table == null) { + player.sendMessage(ChatColor.RED + "This world isn't logged"); return; } if (split.length == 1) { @@ -417,36 +409,40 @@ public class LogBlock extends JavaPlugin } if (split[0].equalsIgnoreCase("/rollback")) { event.setCancelled(true); + if (split.length != 5) + { + player.sendMessage(ChatColor.RED + "Usage:"); + player.sendMessage(ChatColor.RED + "/rollback player [name] [time] [minutes|hours|days]"); + player.sendMessage(ChatColor.RED + "/rollback area [radius] [time] [minutes|hours|days]"); + return; + } + Connection conn = getConnection(); + String table = GetTable(event.getPlayer().getWorld().getName()); if (!CheckPermission(event.getPlayer(),"logblock.rollback")) { event.getPlayer().sendMessage("§cInsufficient permissions"); return; } - int idx = worldNames.indexOf(player.getWorld().getName()); - if (idx == -1) - return; - String table = worldTables.get(idx); - int minutes; - String name; - if (split.length < 3) - { - player.sendMessage("§cUsage: /rollback [player] [time spec]"); + if (conn == null) { + player.sendMessage(ChatColor.RED + "Can't create SQL connection."); return; } - name = split[1]; - minutes = parseTimeSpec(event.getMessage().substring(event.getMessage().indexOf(' ', 11) + 1)); - player.sendMessage("§cRolling back " + name + " by " + minutes + " minutes."); - Connection conn; - try { - conn = getConnection(); - } catch (SQLException ex) { - log.log(Level.SEVERE, name + " SQL exception", ex); - player.sendMessage("§cError, check server logs."); + if (table == null) { + player.sendMessage(ChatColor.RED + "This world isn't logged"); + return; + } + int minutes = parseTimeSpec(split[3], split[4]); + if (split[1].equalsIgnoreCase("player")) { + player.sendMessage(ChatColor.GREEN + "Rolling back " + split[2] + " by " + minutes + " minutes."); + Rollback rb = new Rollback(event.getPlayer(), conn, split[2], minutes, table); + new Thread(rb).start(); + return; + } + if (split[1].equalsIgnoreCase("area")) { + player.sendMessage(ChatColor.GREEN + "Rolling back area within " + split[2] + " blocks of you by " + minutes + " minutes."); + Rollback rb = new Rollback(event.getPlayer(), conn, Integer.parseInt(split[2]), minutes, table); + new Thread(rb).start(); return; } - Rollback rb = new Rollback(conn, name, minutes, player.getWorld(), table); - player.sendMessage("§cEdit count: " + rb.count()); - new Thread(rb).start(); - return; } if (split[0].equalsIgnoreCase("/getworldname")) { event.setCancelled(true); @@ -501,16 +497,15 @@ public class LogBlock extends JavaPlugin } } - //private class LBLEntityListener extends EntityListener - //{ - // public void onEntityExplode(EntityExplodeEvent event) { - // if (!event.isCancelled()) { - // if (event.getEntity() == null) { - // log.info("Exploding tnt at: " + event.getLocation().getBlockX() + ":" + event.getLocation().getBlockY() + ":" + event.getLocation().getBlockZ()); - // } - // } - // } - //} + private class LBLEntityListener extends EntityListener + { + public void onEntityExplode(EntityExplodeEvent event) { + if (!event.isCancelled()) { + for (Block block : event.blockList()) + queueBlock("environment", block, block.getTypeId(), 0, block.getData()); + } + } + } private class Consumer implements Runnable { diff --git a/src/de/diddiz/LogBlock/PlayerAreaStats.java b/src/de/diddiz/LogBlock/PlayerAreaStats.java index 8b11bfb..4a29b01 100644 --- a/src/de/diddiz/LogBlock/PlayerAreaStats.java +++ b/src/de/diddiz/LogBlock/PlayerAreaStats.java @@ -8,14 +8,12 @@ import java.sql.Statement; import java.util.HashMap; import java.util.HashSet; import java.util.logging.Level; -import java.util.logging.Logger; import org.bukkit.Material; import org.bukkit.entity.Player; public class PlayerAreaStats implements Runnable { - static final Logger log = Logger.getLogger("Minecraft"); private Player player; private String name; private int size; @@ -70,7 +68,7 @@ public class PlayerAreaStats implements Runnable } } catch (SQLException ex) { - log.log(Level.SEVERE, this.getClass().getName() + " SQL exception", ex); + LogBlock.log.log(Level.SEVERE, this.getClass().getName() + " SQL exception", ex); } finally { try { if (rs != null) @@ -80,7 +78,7 @@ public class PlayerAreaStats implements Runnable if (conn != null) conn.close(); } catch (SQLException ex) { - log.log(Level.SEVERE, this.getClass().getName() + " SQL exception on close", ex); + LogBlock.log.log(Level.SEVERE, this.getClass().getName() + " SQL exception on close", ex); } } diff --git a/src/de/diddiz/LogBlock/PlayerWorldStats.java b/src/de/diddiz/LogBlock/PlayerWorldStats.java index 9be3d12..e4d1dfe 100644 --- a/src/de/diddiz/LogBlock/PlayerWorldStats.java +++ b/src/de/diddiz/LogBlock/PlayerWorldStats.java @@ -8,13 +8,11 @@ import java.sql.Statement; import java.util.HashMap; import java.util.HashSet; import java.util.logging.Level; -import java.util.logging.Logger; import org.bukkit.entity.Player; public class PlayerWorldStats implements Runnable { - static final Logger log = Logger.getLogger("Minecraft"); private Player player; private Connection conn = null; private String table; @@ -55,7 +53,7 @@ public class PlayerWorldStats implements Runnable } } catch (SQLException ex) { - log.log(Level.SEVERE, this.getClass().getName() + " SQL exception", ex); + LogBlock.log.log(Level.SEVERE, this.getClass().getName() + " SQL exception", ex); } finally { try { if (rs != null) @@ -65,7 +63,7 @@ public class PlayerWorldStats implements Runnable if (conn != null) conn.close(); } catch (SQLException ex) { - log.log(Level.SEVERE, this.getClass().getName() + " SQL exception on close", ex); + LogBlock.log.log(Level.SEVERE, this.getClass().getName() + " SQL exception on close", ex); } } @@ -89,4 +87,3 @@ public class PlayerWorldStats implements Runnable } } } -// END threaded commands diff --git a/src/de/diddiz/LogBlock/Rollback.java b/src/de/diddiz/LogBlock/Rollback.java index cc31012..01d2204 100644 --- a/src/de/diddiz/LogBlock/Rollback.java +++ b/src/de/diddiz/LogBlock/Rollback.java @@ -7,34 +7,66 @@ import java.sql.SQLException; import java.sql.Statement; import java.util.concurrent.LinkedBlockingQueue; import java.util.logging.Level; -import java.util.logging.Logger; +import org.bukkit.ChatColor; import org.bukkit.World; import org.bukkit.block.Block; +import org.bukkit.entity.Player; public class Rollback implements Runnable { - static final Logger log = Logger.getLogger("Minecraft"); private LinkedBlockingQueue edits = new LinkedBlockingQueue(); - - Rollback(Connection conn, String name, int minutes, World world, String table) - { - PreparedStatement ps = null; - ResultSet rs = null; - edits.clear(); + PreparedStatement ps = null; + private Player player; + private Connection conn = null; + + Rollback(Player player, Connection conn, String name, int minutes, String table) { + this.player = player; + this.conn = conn; try { conn.setAutoCommit(false); ps = conn.prepareStatement("SELECT type, data, replaced, x, y, z FROM `" + table + "` WHERE player = ? AND date > date_sub(now(), INTERVAL ? MINUTE) ORDER BY date DESC", Statement.RETURN_GENERATED_KEYS); ps.setString(1, name); ps.setInt(2, minutes); + } catch (SQLException ex) { + LogBlock.log.log(Level.SEVERE, this.getClass().getName() + " SQL exception", ex); + player.sendMessage(ChatColor.RED + "Error, check server logs."); + return; + } + } + + Rollback(Player player, Connection conn, int radius, int minutes, String table) { + this.player = player; + this.conn = conn; + try { + conn.setAutoCommit(false); + ps = conn.prepareStatement("SELECT type, data, replaced, x, y, z FROM `" + table + "` WHERE y > 0 and x > ? and x < ? and z > ? and z < ? AND date > date_sub(now(), INTERVAL ? MINUTE) ORDER BY date DESC", Statement.RETURN_GENERATED_KEYS); + ps.setInt(1, player.getLocation().getBlockX()-radius); + ps.setInt(2, player.getLocation().getBlockX()+radius); + ps.setInt(3, player.getLocation().getBlockZ()-radius); + ps.setInt(4, player.getLocation().getBlockZ()+radius); + ps.setInt(5, minutes); + } catch (SQLException ex) { + LogBlock.log.log(Level.SEVERE, this.getClass().getName() + " SQL exception", ex); + player.sendMessage(ChatColor.RED + "Error, check server logs."); + return; + } + } + + public void run() + { + ResultSet rs = null; + edits.clear(); + try { rs = ps.executeQuery(); - while (rs.next()) { - Edit e = new Edit(rs.getInt("type"), rs.getInt("replaced"), rs.getByte("data"), rs.getInt("x"), rs.getInt("y"), rs.getInt("z"), world); + Edit e = new Edit(rs.getInt("type"), rs.getInt("replaced"), rs.getByte("data"), rs.getInt("x"), rs.getInt("y"), rs.getInt("z"), player.getWorld()); edits.offer(e); } } catch (SQLException ex) { - log.log(Level.SEVERE, this.getClass().getName() + " SQL exception", ex); + LogBlock.log.log(Level.SEVERE, this.getClass().getName() + " SQL exception", ex); + player.sendMessage("§cError, check server logs."); + return; } finally { try { if (rs != null) @@ -44,27 +76,23 @@ public class Rollback implements Runnable if (conn != null) conn.close(); } catch (SQLException ex) { - log.log(Level.SEVERE, this.getClass().getName() + " SQL exception on close", ex); + LogBlock.log.log(Level.SEVERE, this.getClass().getName() + " SQL exception on close", ex); + player.sendMessage("§cError, check server logs."); + return; } } - - } - - public int count() - { - return edits.size(); - } - - public void run() - { + int changes = edits.size(); + int rolledBack = 0; + player.sendMessage(ChatColor.GREEN + "" + changes + " Changes found."); Edit e = edits.poll(); - while (e != null) { - e.perform(); - e.log(); + if (e.perform()) + rolledBack++; e = edits.poll(); } + player.sendMessage(ChatColor.GREEN + "Rollback finished successfully"); + player.sendMessage(ChatColor.GREEN + "Undid " + rolledBack + " of " + changes + " changes"); } private class Edit @@ -85,27 +113,16 @@ public class Rollback implements Runnable this.world = world; } - public void perform() + public boolean perform() { Block block = world.getBlockAt(x, y, z); - if (block.getTypeId() == type || (block.getTypeId() >= 8 && block.getTypeId() <= 11)) - { + if (block.getTypeId() == type || (block.getTypeId() >= 8 && block.getTypeId() <= 11)) { if (block.setTypeId(replaced)) { block.setData(data); - log.info("R (" + x + ", " + y + ", " + z + ") " + replaced + " " + type); + return true; } - else - log.info("r (" + x + ", " + y + ", " + z + ") " + replaced + " " + type); } - } - - public void log() - { - int current = world.getBlockTypeIdAt(x, y, z); - if (current == type) - log.info("+ (" + x + ", " + y + ", " + z + ") " + replaced + " " + type); - else - log.info("- (" + x + ", " + y + ", " + z + ") " + replaced + " " + type); + return false; } } } \ No newline at end of file diff --git a/src/plugin.yml b/src/plugin.yml index 50aad4b..239094b 100644 --- a/src/plugin.yml +++ b/src/plugin.yml @@ -1,5 +1,5 @@ name: LogBlock -version: 0.4b +version: 0.5 author: DiddiZ, bootswithdefer website: http://www.diddiz.de/minecraft/ main: de.diddiz.LogBlock.LogBlock