diff --git a/src/main/java/de/diddiz/LogBlock/Consumer.java b/src/main/java/de/diddiz/LogBlock/Consumer.java index a24ef03..2cc0b2b 100644 --- a/src/main/java/de/diddiz/LogBlock/Consumer.java +++ b/src/main/java/de/diddiz/LogBlock/Consumer.java @@ -1,6 +1,7 @@ package de.diddiz.LogBlock; import de.diddiz.LogBlock.config.Config; +import de.diddiz.LogBlock.events.BlockChangePreLogEvent; import org.bukkit.Location; import org.bukkit.World; import org.bukkit.block.BlockState; @@ -50,7 +51,7 @@ public class Consumer extends TimerTask /** * Logs a block break. The type afterwards is assumed to be o (air). - * + * * @param before * Blockstate of the block before actually being destroyed. */ @@ -67,7 +68,7 @@ public class Consumer extends TimerTask /** * Logs a block place. The block type before is assumed to be o (air). - * + * * @param after * Blockstate of the block after actually being placed. */ @@ -137,7 +138,7 @@ 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. - * + * * @param container * Must be instanceof InventoryHolder */ @@ -282,26 +283,26 @@ public class Consumer extends TimerTask } continue process; } - } - } - if (r instanceof PreparedStatementRow) { - PreparedStatementRow PSRow = (PreparedStatementRow) r; - PSRow.setConnection(conn); - try { - PSRow.executeStatements(); - } catch (final SQLException ex) { - getLogger().log(Level.SEVERE, "[Consumer] SQL exception on insertion: ", ex); - break; - } - } else { - for (final String insert : r.getInserts()) - try { - state.execute(insert); - } catch (final SQLException ex) { - getLogger().log(Level.SEVERE, "[Consumer] SQL exception on " + insert + ": ", ex); - break process; - } - } + } + } + if (r instanceof PreparedStatementRow) { + PreparedStatementRow PSRow = (PreparedStatementRow) r; + PSRow.setConnection(conn); + try { + PSRow.executeStatements(); + } catch (final SQLException ex) { + getLogger().log(Level.SEVERE, "[Consumer] SQL exception on insertion: ", ex); + break; + } + } else { + for (final String insert : r.getInserts()) + try { + state.execute(insert); + } catch (final SQLException ex) { + getLogger().log(Level.SEVERE, "[Consumer] SQL exception on " + insert + ": ", ex); + break process; + } + } count++; } @@ -371,8 +372,24 @@ public class Consumer extends TimerTask } private void queueBlock(String playerName, Location loc, int typeBefore, int typeAfter, byte data, String signtext, ChestAccess ca) { - if (playerName == null || loc == null || typeBefore < 0 || typeAfter < 0 || typeBefore > 255 || typeAfter > 255 || hiddenPlayers.contains(playerName) || !isLogged(loc.getWorld()) || typeBefore != typeAfter && hiddenBlocks.contains(typeBefore) && hiddenBlocks.contains(typeAfter)) - return; + + if (Config.fireCustomEvents) { + // Create and call the event + BlockChangePreLogEvent event = new BlockChangePreLogEvent(playerName, loc, typeBefore, typeAfter, data, signtext, ca); + logblock.getServer().getPluginManager().callEvent(event); + if (event.isCancelled()) return; + + // Update variables + playerName = event.getOwner(); + loc = event.getLocation(); + typeBefore = event.getTypeBefore(); + typeAfter = event.getTypeAfter(); + data = event.getData(); + signtext = event.getSignText(); + ca = event.getChestAccess(); + } + // Do this last so LogBlock still has final say in what is being added + if (playerName == null || loc == null || typeBefore < 0 || typeAfter < 0 || typeBefore > 255 || typeAfter > 255 || hiddenPlayers.contains(playerName) || !isLogged(loc.getWorld()) || typeBefore != typeAfter && hiddenBlocks.contains(typeBefore) && hiddenBlocks.contains(typeAfter)) return; queue.add(new BlockRow(loc, playerName.replaceAll("[^a-zA-Z0-9_]", ""), typeBefore, typeAfter, data, signtext, ca)); } @@ -385,12 +402,12 @@ public class Consumer extends TimerTask return "(SELECT playerid FROM `lb-players` WHERE playername = '" + playerName + "')"; } - private Integer playerIDAsInt(String playerName) { - if (playerName == null) { - return null; - } - return playerIds.get(playerName); - } + private Integer playerIDAsInt(String playerName) { + if (playerName == null) { + return null; + } + return playerIds.get(playerName); + } private static interface Row { @@ -399,21 +416,21 @@ public class Consumer extends TimerTask String[] getPlayers(); } - private interface PreparedStatementRow extends Row - { + private interface PreparedStatementRow extends Row + { - abstract void setConnection(Connection connection); - abstract void executeStatements() throws SQLException; + abstract void setConnection(Connection connection); + abstract void executeStatements() throws SQLException; - } + } private class BlockRow extends BlockChange implements PreparedStatementRow { - private Connection connection; + private Connection connection; public BlockRow(Location loc, String playerName, int replaced, int type, byte data, String signtext, ChestAccess ca) { - super(System.currentTimeMillis() / 1000, loc, playerName, replaced, type, data, signtext, ca); - } + super(System.currentTimeMillis() / 1000, loc, playerName, replaced, type, data, signtext, ca); + } @Override public String[] getInserts() { @@ -432,44 +449,44 @@ public class Consumer extends TimerTask return new String[]{playerName}; } - @Override - public void setConnection(Connection connection) { - this.connection = connection; - } + @Override + public void setConnection(Connection connection) { + this.connection = connection; + } - @Override - public void executeStatements() throws SQLException { - final String table = getWorldConfig(loc.getWorld()).table; + @Override + public void executeStatements() throws SQLException { + final String table = getWorldConfig(loc.getWorld()).table; - PreparedStatement ps1 = connection.prepareStatement("INSERT INTO `" + table + "` (date, playerid, replaced, type, data, x, y, z) VALUES(?, " + playerID(playerName) + ", ?, ?, ?, ?, ?, ?)", Statement.RETURN_GENERATED_KEYS); - ps1.setTimestamp(1, new Timestamp(date * 1000)); - ps1.setInt(2, replaced); - ps1.setInt(3, type); - ps1.setInt(4, data); - ps1.setInt(5, loc.getBlockX()); - ps1.setInt(6, loc.getBlockY()); - ps1.setInt(7, loc.getBlockZ()); - ps1.executeUpdate(); + PreparedStatement ps1 = connection.prepareStatement("INSERT INTO `" + table + "` (date, playerid, replaced, type, data, x, y, z) VALUES(?, " + playerID(playerName) + ", ?, ?, ?, ?, ?, ?)", Statement.RETURN_GENERATED_KEYS); + ps1.setTimestamp(1, new Timestamp(date * 1000)); + ps1.setInt(2, replaced); + ps1.setInt(3, type); + ps1.setInt(4, data); + ps1.setInt(5, loc.getBlockX()); + ps1.setInt(6, loc.getBlockY()); + ps1.setInt(7, loc.getBlockZ()); + ps1.executeUpdate(); - int id; - ResultSet rs = ps1.getGeneratedKeys(); - rs.next(); - id = rs.getInt(1); + int id; + ResultSet rs = ps1.getGeneratedKeys(); + rs.next(); + id = rs.getInt(1); - if (signtext != null) { - PreparedStatement ps = connection.prepareStatement("INSERT INTO `" + table + "-sign` (signtext, id) VALUES(?, ?)"); - ps.setString(1, signtext); - ps.setInt(2, id); - ps.executeUpdate(); - } else if (ca != null) { - PreparedStatement ps = connection.prepareStatement("INSERT INTO `" + table + "-chest` (itemtype, itemamount, itemdata, id) values (?, ?, ?, ?)"); - ps.setInt(1, ca.itemType); - ps.setInt(2, ca.itemAmount); - ps.setInt(3, ca.itemData); - ps.setInt(4, id); - ps.executeUpdate(); - } - } + if (signtext != null) { + PreparedStatement ps = connection.prepareStatement("INSERT INTO `" + table + "-sign` (signtext, id) VALUES(?, ?)"); + ps.setString(1, signtext); + ps.setInt(2, id); + ps.executeUpdate(); + } else if (ca != null) { + PreparedStatement ps = connection.prepareStatement("INSERT INTO `" + table + "-chest` (itemtype, itemamount, itemdata, id) values (?, ?, ?, ?)"); + ps.setInt(1, ca.itemType); + ps.setInt(2, ca.itemAmount); + ps.setInt(3, ca.itemData); + ps.setInt(4, id); + ps.executeUpdate(); + } + } } private class KillRow implements Row @@ -500,7 +517,7 @@ public class Consumer extends TimerTask private class ChatRow extends ChatMessage implements PreparedStatementRow { - private Connection connection; + private Connection connection; ChatRow(String player, String message) { super(player, message); @@ -516,34 +533,34 @@ public class Consumer extends TimerTask return new String[]{playerName}; } - @Override - public void setConnection(Connection connection) { - this.connection = connection; - } + @Override + public void setConnection(Connection connection) { + this.connection = connection; + } - @Override - public void executeStatements() throws SQLException { - boolean noID = false; - Integer id; + @Override + public void executeStatements() throws SQLException { + boolean noID = false; + Integer id; - String sql = "INSERT INTO `lb-chat` (date, playerid, message) VALUES (?, "; - if ((id = playerIDAsInt(playerName)) == null) { - noID = true; - sql += playerID(playerName) + ", "; - } else { - sql += "?, "; - } - sql += "?)"; - PreparedStatement ps = connection.prepareStatement(sql); - ps.setTimestamp(1, new Timestamp(date * 1000)); - if (!noID) { - ps.setInt(2, id); - ps.setString(3, message); - } else { - ps.setString(2, message); - } - ps.execute(); - } + String sql = "INSERT INTO `lb-chat` (date, playerid, message) VALUES (?, "; + if ((id = playerIDAsInt(playerName)) == null) { + noID = true; + sql += playerID(playerName) + ", "; + } else { + sql += "?, "; + } + sql += "?)"; + PreparedStatement ps = connection.prepareStatement(sql); + ps.setTimestamp(1, new Timestamp(date * 1000)); + if (!noID) { + ps.setInt(2, id); + ps.setString(3, message); + } else { + ps.setString(2, message); + } + ps.execute(); + } } private class PlayerJoinRow implements Row diff --git a/src/main/java/de/diddiz/LogBlock/config/Config.java b/src/main/java/de/diddiz/LogBlock/config/Config.java index 80da7eb..4523139 100644 --- a/src/main/java/de/diddiz/LogBlock/config/Config.java +++ b/src/main/java/de/diddiz/LogBlock/config/Config.java @@ -1,34 +1,22 @@ package de.diddiz.LogBlock.config; -import static de.diddiz.util.BukkitUtils.friendlyWorldname; -import static de.diddiz.util.Utils.parseTimeSpec; -import static org.bukkit.Bukkit.getConsoleSender; -import static org.bukkit.Bukkit.getLogger; -import static org.bukkit.Bukkit.getWorlds; -import java.io.File; -import java.io.IOException; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; -import java.util.logging.Level; -import java.util.zip.DataFormatException; +import de.diddiz.LogBlock.*; import org.bukkit.Material; import org.bukkit.World; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.permissions.PermissionDefault; -import de.diddiz.LogBlock.LogBlock; -import de.diddiz.LogBlock.Logging; -import de.diddiz.LogBlock.QueryParams; -import de.diddiz.LogBlock.Tool; -import de.diddiz.LogBlock.ToolBehavior; -import de.diddiz.LogBlock.ToolMode; + +import java.io.File; +import java.io.IOException; +import java.text.SimpleDateFormat; +import java.util.*; +import java.util.Map.Entry; +import java.util.logging.Level; +import java.util.zip.DataFormatException; + +import static de.diddiz.util.BukkitUtils.friendlyWorldname; +import static de.diddiz.util.Utils.parseTimeSpec; +import static org.bukkit.Bukkit.*; public class Config { @@ -36,6 +24,7 @@ public class Config private static Map worldConfigs; public static String url, user, password; public static int delayBetweenRuns, forceToProcessAtLeast, timePerRun; + public static boolean fireCustomEvents; public static boolean useBukkitScheduler; public static boolean enableAutoClearLog; public static List autoClearLog; @@ -82,6 +71,7 @@ public class Config def.put("consumer.delayBetweenRuns", 6); def.put("consumer.forceToProcessAtLeast", 20); def.put("consumer.timePerRun", 200); + def.put("consumer.fireCustomEvents", false); def.put("consumer.useBukkitScheduler", true); def.put("clearlog.dumpDeletedLog", false); def.put("clearlog.enableAutoClearLog", false); @@ -141,6 +131,7 @@ public class Config delayBetweenRuns = config.getInt("consumer.delayBetweenRuns", 6); forceToProcessAtLeast = config.getInt("consumer.forceToProcessAtLeast", 0); timePerRun = config.getInt("consumer.timePerRun", 100); + fireCustomEvents = config.getBoolean("consumer.fireCustomEvents", false); useBukkitScheduler = config.getBoolean("consumer.useBukkitScheduler", true); enableAutoClearLog = config.getBoolean("clearlog.enableAutoClearLog"); autoClearLog = config.getStringList("clearlog.auto"); diff --git a/src/main/java/de/diddiz/LogBlock/events/BlockChangePreLogEvent.java b/src/main/java/de/diddiz/LogBlock/events/BlockChangePreLogEvent.java new file mode 100644 index 0000000..fa7c668 --- /dev/null +++ b/src/main/java/de/diddiz/LogBlock/events/BlockChangePreLogEvent.java @@ -0,0 +1,116 @@ +package de.diddiz.LogBlock.events; +import de.diddiz.LogBlock.ChestAccess; +import org.apache.commons.lang.Validate; +import org.bukkit.Location; +import org.bukkit.event.HandlerList; + +public class BlockChangePreLogEvent extends PreLogEvent { + + private static final HandlerList handlers = new HandlerList(); + private Location location; + private int typeBefore, typeAfter; + private byte data; + private String signText; + private ChestAccess chestAccess; + + public BlockChangePreLogEvent(String owner, Location location, int typeBefore, int typeAfter, byte data, + String signText, ChestAccess chestAccess) { + + super(owner); + this.location = location; + this.typeBefore = typeBefore; + this.typeAfter = typeAfter; + this.data = data; + this.signText = signText; + this.chestAccess = chestAccess; + } + + public Location getLocation() { + + return location; + } + + public void setLocation(Location location) { + + this.location = location; + } + + public int getTypeBefore() { + + return typeBefore; + } + + public void setTypeBefore(int typeBefore) { + + this.typeBefore = typeBefore; + } + + public int getTypeAfter() { + + return typeAfter; + } + + public void setTypeAfter(int typeAfter) { + + this.typeAfter = typeAfter; + } + + public byte getData() { + + return data; + } + + public void setData(byte data) { + + this.data = data; + } + + public String getSignText() { + + return signText; + } + + public void setSignText(String[] signText) { + + if (signText != null) { + // Check for block + Validate.isTrue(isValidSign(), "Must be valid sign block"); + + // Check for problems + Validate.noNullElements(signText, "No null lines"); + Validate.isTrue(signText.length == 4, "Sign text must be 4 strings"); + + this.signText = signText[0] + "\0" + signText[1] + "\0" + signText[2] + "\0" + signText[3]; + } else { + this.signText = null; + } + } + + private boolean isValidSign() { + + if ((typeAfter == 63 || typeAfter == 68) && typeBefore == 0) return true; + if ((typeBefore == 63 || typeBefore == 68) && typeAfter == 0) return true; + if ((typeAfter == 63 || typeAfter == 68) && typeBefore == typeAfter) return true; + return false; + } + + public ChestAccess getChestAccess() { + + return chestAccess; + } + + public void setChestAccess(ChestAccess chestAccess) { + + this.chestAccess = chestAccess; + } + + public HandlerList getHandlers() { + + return handlers; + } + + public static HandlerList getHandlerList() { + + return handlers; + } +} diff --git a/src/main/java/de/diddiz/LogBlock/events/PreLogEvent.java b/src/main/java/de/diddiz/LogBlock/events/PreLogEvent.java new file mode 100644 index 0000000..3c12e6b --- /dev/null +++ b/src/main/java/de/diddiz/LogBlock/events/PreLogEvent.java @@ -0,0 +1,44 @@ +package de.diddiz.LogBlock.events; +import org.bukkit.event.Cancellable; +import org.bukkit.event.Event; + +public abstract class PreLogEvent extends Event implements Cancellable { + + protected boolean cancelled = false; + protected String owner; + + public PreLogEvent(String owner) { + + this.owner = owner.replaceAll("[^a-zA-Z0-9_]", ""); + } + + /** + * Returns the player/monster/cause involved in this event + * + * @return Player/monster/cause who is involved in this event + */ + public String getOwner() { + + return owner; + } + + /** + * Sets the player/monster/cause involved in this event + * + * @param owner The player/monster/cause who is involved in this event + */ + public void setOwner(String owner) { + + this.owner = owner.replaceAll("[^a-zA-Z0-9_]", ""); + } + + public boolean isCancelled() { + + return cancelled; + } + + public void setCancelled(boolean cancelled) { + + this.cancelled = cancelled; + } +}