From 9f41fffbc3a3ade17ed250b995b8686816abc57c Mon Sep 17 00:00:00 2001 From: Ammar Askar Date: Sun, 22 Mar 2015 20:15:04 +0500 Subject: [PATCH] Reformat the entire project: Use of braces is now enforced EVERYWHERE Switched to 4spaces instead of tabs --- pom.xml | 320 +-- src/main/java/de/diddiz/LogBlock/Actor.java | 159 +- .../java/de/diddiz/LogBlock/AutoClearLog.java | 41 +- .../java/de/diddiz/LogBlock/BlockChange.java | 221 ++- .../java/de/diddiz/LogBlock/ChatMessage.java | 61 +- .../java/de/diddiz/LogBlock/ChestAccess.java | 15 +- .../de/diddiz/LogBlock/CommandsHandler.java | 1520 ++++++++------- .../java/de/diddiz/LogBlock/Consumer.java | 1715 +++++++++-------- .../de/diddiz/LogBlock/DumpedLogImporter.java | 120 +- src/main/java/de/diddiz/LogBlock/Kill.java | 105 +- .../java/de/diddiz/LogBlock/LogBlock.java | 559 +++--- src/main/java/de/diddiz/LogBlock/Logging.java | 41 +- .../diddiz/LogBlock/LookupCacheElement.java | 7 +- .../LogBlock/LookupCacheElementFactory.java | 48 +- src/main/java/de/diddiz/LogBlock/Metrics.java | 1417 +++++++------- .../java/de/diddiz/LogBlock/QueryParams.java | 1501 ++++++++------- src/main/java/de/diddiz/LogBlock/Session.java | 73 +- .../diddiz/LogBlock/SummedBlockChanges.java | 53 +- .../java/de/diddiz/LogBlock/SummedKills.java | 45 +- src/main/java/de/diddiz/LogBlock/Tool.java | 48 +- .../java/de/diddiz/LogBlock/ToolBehavior.java | 5 +- .../java/de/diddiz/LogBlock/ToolData.java | 19 +- .../java/de/diddiz/LogBlock/ToolMode.java | 19 +- src/main/java/de/diddiz/LogBlock/Updater.java | 858 +++++---- .../java/de/diddiz/LogBlock/WorldEditor.java | 391 ++-- .../de/diddiz/LogBlock/config/Config.java | 505 ++--- .../diddiz/LogBlock/config/WorldConfig.java | 46 +- .../events/BlockChangePreLogEvent.java | 153 +- .../diddiz/LogBlock/events/PreLogEvent.java | 77 +- .../LogBlock/listeners/BanListener.java | 76 +- .../LogBlock/listeners/BlockBreakLogging.java | 92 +- .../LogBlock/listeners/BlockBurnLogging.java | 63 +- .../LogBlock/listeners/BlockPlaceLogging.java | 142 +- .../listeners/BlockSpreadLogging.java | 76 +- .../LogBlock/listeners/ChatLogging.java | 42 +- .../listeners/ChestAccessLogging.java | 92 +- .../listeners/CreatureInteractLogging.java | 68 +- .../LogBlock/listeners/EndermenLogging.java | 23 +- .../LogBlock/listeners/ExplosionLogging.java | 182 +- .../LogBlock/listeners/FluidFlowLogging.java | 133 +- .../LogBlock/listeners/InteractLogging.java | 167 +- .../LogBlock/listeners/KillLogging.java | 62 +- .../listeners/LeavesDecayLogging.java | 30 +- .../listeners/LockedChestDecayLogging.java | 29 +- .../LogBlock/listeners/LoggingListener.java | 13 +- .../LogBlock/listeners/PlayerInfoLogging.java | 27 +- .../LogBlock/listeners/SignChangeLogging.java | 24 +- .../LogBlock/listeners/SnowFadeLogging.java | 29 +- .../LogBlock/listeners/SnowFormLogging.java | 30 +- .../listeners/StructureGrowLogging.java | 51 +- .../LogBlock/listeners/ToolListener.java | 201 +- .../LogBlock/listeners/WitherLogging.java | 20 +- src/main/java/de/diddiz/util/Block.java | 52 +- src/main/java/de/diddiz/util/BukkitUtils.java | 765 ++++---- src/main/java/de/diddiz/util/LoggingUtil.java | 364 ++-- .../java/de/diddiz/util/MaterialName.java | 502 ++--- .../de/diddiz/util/MySQLConnectionPool.java | 55 +- src/main/java/de/diddiz/util/UUIDFetcher.java | 102 +- src/main/java/de/diddiz/util/Utils.java | 316 +-- .../de/diddiz/worldedit/RegionContainer.java | 46 +- .../worldedit/WorldEditLoggingHook.java | 168 +- .../de/diddiz/LogBlock/QueryParsingTest.java | 14 +- 62 files changed, 7259 insertions(+), 6939 deletions(-) diff --git a/pom.xml b/pom.xml index 324213b..6892d30 100644 --- a/pom.xml +++ b/pom.xml @@ -1,170 +1,170 @@ - 4.0.0 + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + 4.0.0 - de.diddiz - logblock - 1.94-dev-SNAPSHOT - jar + de.diddiz + logblock + 1.94-dev-SNAPSHOT + jar - LogBlock - Logs blocks. - https://github.com/LogBlock/LogBlock + LogBlock + Logs blocks. + https://github.com/LogBlock/LogBlock - - UTF-8 - ${buildNumber} - + + UTF-8 + ${buildNumber} + - - scm:git:git://github.com/LogBlock/LogBlock.git - scm:git:ssh://git@github.com:LogBlock/LogBlock.git - https://github.com/LogBlock/LogBlock - + + scm:git:git://github.com/LogBlock/LogBlock.git + scm:git:ssh://git@github.com:LogBlock/LogBlock.git + https://github.com/LogBlock/LogBlock + - - jenkins - http://ci.kitteh.org/job/LogBlock - + + jenkins + http://ci.kitteh.org/job/LogBlock + - - - md_5-releases - http://repo.md-5.net/content/repositories/releases/ - - - md_5-snapshots - http://repo.md-5.net/content/repositories/snapshots/ - - + + + md_5-releases + http://repo.md-5.net/content/repositories/releases/ + + + md_5-snapshots + http://repo.md-5.net/content/repositories/snapshots/ + + - - - org.bukkit - bukkit - 1.7.2-R0.3 - provided - - - ${project.groupId} - questioner - ${project.version} - system - ${project.basedir}/LogBlockQuestioner.jar - - - com.sk89q - worldedit - 6.0.0-SNAPSHOT - provided - - - junit - junit - 4.11 - test - - - com.zaxxer - HikariCP-java6 - 2.3.4 - compile - - - - - repobo-snap - http://repo.bukkit.org/content/groups/public - - - sk89q-repo - http://maven.sk89q.com/repo/ - - - kitteh-repo - http://repo.kitteh.org/content/groups/public - - - - - static_build_number - - - !env.BUILD_NUMBER - - - - 0 - (manually compiled) - - - - dynamic_build_number - - - env.BUILD_NUMBER - - - - ${env.BUILD_NUMBER} - (build #${env.BUILD_NUMBER}) - - - + + + org.bukkit + bukkit + 1.7.2-R0.3 + provided + + + ${project.groupId} + questioner + ${project.version} + system + ${project.basedir}/LogBlockQuestioner.jar + + + com.sk89q + worldedit + 6.0.0-SNAPSHOT + provided + + + junit + junit + 4.11 + test + + + com.zaxxer + HikariCP-java6 + 2.3.4 + compile + + + + + repobo-snap + http://repo.bukkit.org/content/groups/public + + + sk89q-repo + http://maven.sk89q.com/repo/ + + + kitteh-repo + http://repo.kitteh.org/content/groups/public + + + + + static_build_number + + + !env.BUILD_NUMBER + + + + 0 + (manually compiled) + + + + dynamic_build_number + + + env.BUILD_NUMBER + + + + ${env.BUILD_NUMBER} + (build #${env.BUILD_NUMBER}) + + + - - ${project.name} - - - true - ${project.basedir}/src/main/resources - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.2 - - 1.6 - 1.6 - - - - org.codehaus.mojo - build-helper-maven-plugin - 1.9.1 - - - regex-property - - regex-property - - - minecraft.plugin.version - ${project.version} ${buildDescription} - [0-9\.]+ \(.+\) - ${project.version} - false - - - - - - org.apache.maven.plugins - maven-shade-plugin - 2.3 - - - - - package - - shade - - - - - - + + ${project.name} + + + true + ${project.basedir}/src/main/resources + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.2 + + 1.6 + 1.6 + + + + org.codehaus.mojo + build-helper-maven-plugin + 1.9.1 + + + regex-property + + regex-property + + + minecraft.plugin.version + ${project.version} ${buildDescription} + [0-9\.]+ \(.+\) + ${project.version} + false + + + + + + org.apache.maven.plugins + maven-shade-plugin + 2.3 + + + + + package + + shade + + + + + + diff --git a/src/main/java/de/diddiz/LogBlock/Actor.java b/src/main/java/de/diddiz/LogBlock/Actor.java index 69987c7..79cec30 100644 --- a/src/main/java/de/diddiz/LogBlock/Actor.java +++ b/src/main/java/de/diddiz/LogBlock/Actor.java @@ -1,99 +1,104 @@ package de.diddiz.LogBlock; -import static de.diddiz.util.BukkitUtils.entityName; - -import java.sql.ResultSet; -import java.sql.SQLException; - import org.bukkit.entity.Entity; import org.bukkit.entity.EntityType; import org.bukkit.entity.Player; import org.bukkit.projectiles.BlockProjectileSource; import org.bukkit.projectiles.ProjectileSource; +import java.sql.ResultSet; +import java.sql.SQLException; + +import static de.diddiz.util.BukkitUtils.entityName; + public class Actor { - @Override - public int hashCode() { - int hash = 5; - hash = 79 * hash + (this.UUID != null ? this.UUID.hashCode() : 0); - return hash; - } + @Override + public int hashCode() { + int hash = 5; + hash = 79 * hash + (this.UUID != null ? this.UUID.hashCode() : 0); + return hash; + } - @Override - public boolean equals(Object obj) { - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - final Actor other = (Actor) obj; - return ((this.UUID == null && other.UUID == null) || this.UUID.equals(other.UUID)); - } + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final Actor other = (Actor) obj; + return ((this.UUID == null && other.UUID == null) || this.UUID.equals(other.UUID)); + } - final String name; - final String UUID; + final String name; + final String UUID; - public Actor(String name, String UUID) { - this.name = name; - this.UUID = UUID; - - } - - public Actor(String name, java.util.UUID UUID) { - this.name = name; - this.UUID = UUID.toString(); - - } + public Actor(String name, String UUID) { + this.name = name; + this.UUID = UUID; - public Actor(String name) { - this(name, generateUUID(name)); - } - - public Actor(ResultSet rs) throws SQLException { - this(rs.getString("playername"),rs.getString("UUID")); - } - - public String getName() { - return name; - } + } - public String getUUID() { - return UUID; - } + public Actor(String name, java.util.UUID UUID) { + this.name = name; + this.UUID = UUID.toString(); - public static Actor actorFromEntity(Entity entity) { - if (entity instanceof Player) { - return new Actor(entityName(entity),entity.getUniqueId()); - } else { - return new Actor(entityName(entity)); - } - } - - public static Actor actorFromEntity(EntityType entity) { - return new Actor(entity.getName()); - } + } - public static Actor actorFromProjectileSource(ProjectileSource psource) { - if (psource instanceof Entity) return actorFromEntity((Entity) psource); - if (psource instanceof BlockProjectileSource) return new Actor(((BlockProjectileSource) psource).getBlock().getType().toString()); - else return new Actor(psource.toString()); + public Actor(String name) { + this(name, generateUUID(name)); + } - } - - public static boolean isValidUUID(String uuid) { - try { - java.util.UUID.fromString(uuid); - return true; - } catch (IllegalArgumentException e) { - return false; - } - } + public Actor(ResultSet rs) throws SQLException { + this(rs.getString("playername"), rs.getString("UUID")); + } - public static String generateUUID(String name) { - return "log_" + name; + public String getName() { + return name; + } - } + public String getUUID() { + return UUID; + } + + public static Actor actorFromEntity(Entity entity) { + if (entity instanceof Player) { + return new Actor(entityName(entity), entity.getUniqueId()); + } else { + return new Actor(entityName(entity)); + } + } + + public static Actor actorFromEntity(EntityType entity) { + return new Actor(entity.getName()); + } + + public static Actor actorFromProjectileSource(ProjectileSource psource) { + if (psource instanceof Entity) { + return actorFromEntity((Entity) psource); + } + if (psource instanceof BlockProjectileSource) { + return new Actor(((BlockProjectileSource) psource).getBlock().getType().toString()); + } else { + return new Actor(psource.toString()); + } + + } + + public static boolean isValidUUID(String uuid) { + try { + java.util.UUID.fromString(uuid); + return true; + } catch (IllegalArgumentException e) { + return false; + } + } + + public static String generateUUID(String name) { + return "log_" + name; + + } } diff --git a/src/main/java/de/diddiz/LogBlock/AutoClearLog.java b/src/main/java/de/diddiz/LogBlock/AutoClearLog.java index aa809f9..0173ec8 100644 --- a/src/main/java/de/diddiz/LogBlock/AutoClearLog.java +++ b/src/main/java/de/diddiz/LogBlock/AutoClearLog.java @@ -1,29 +1,28 @@ package de.diddiz.LogBlock; -import static de.diddiz.LogBlock.config.Config.autoClearLog; -import static org.bukkit.Bukkit.getConsoleSender; -import static org.bukkit.Bukkit.getLogger; -import static org.bukkit.Bukkit.getServer; import java.util.Arrays; import java.util.logging.Level; -public class AutoClearLog implements Runnable -{ - private final LogBlock logblock; +import static de.diddiz.LogBlock.config.Config.autoClearLog; +import static org.bukkit.Bukkit.*; - AutoClearLog(LogBlock logblock) { - this.logblock = logblock; - } +public class AutoClearLog implements Runnable { + private final LogBlock logblock; - @Override - public void run() { - final CommandsHandler handler = logblock.getCommandsHandler(); - for (final String paramStr : autoClearLog) - try { - final QueryParams params = new QueryParams(logblock, getConsoleSender(), Arrays.asList(paramStr.split(" "))); - handler.new CommandClearLog(getServer().getConsoleSender(), params, false); - } catch (final Exception ex) { - getLogger().log(Level.SEVERE, "Failed to schedule auto ClearLog: ", ex); - } - } + AutoClearLog(LogBlock logblock) { + this.logblock = logblock; + } + + @Override + public void run() { + final CommandsHandler handler = logblock.getCommandsHandler(); + for (final String paramStr : autoClearLog) { + try { + final QueryParams params = new QueryParams(logblock, getConsoleSender(), Arrays.asList(paramStr.split(" "))); + handler.new CommandClearLog(getServer().getConsoleSender(), params, false); + } catch (final Exception ex) { + getLogger().log(Level.SEVERE, "Failed to schedule auto ClearLog: ", ex); + } + } + } } diff --git a/src/main/java/de/diddiz/LogBlock/BlockChange.java b/src/main/java/de/diddiz/LogBlock/BlockChange.java index 493e52d..a5803df 100644 --- a/src/main/java/de/diddiz/LogBlock/BlockChange.java +++ b/src/main/java/de/diddiz/LogBlock/BlockChange.java @@ -1,119 +1,128 @@ package de.diddiz.LogBlock; -import static de.diddiz.util.MaterialName.materialName; +import de.diddiz.LogBlock.config.Config; +import de.diddiz.util.BukkitUtils; +import org.bukkit.Location; +import org.bukkit.Material; + import java.sql.ResultSet; import java.sql.SQLException; -import de.diddiz.util.BukkitUtils; -import org.bukkit.Location; - -import de.diddiz.LogBlock.config.Config; import static de.diddiz.util.LoggingUtil.checkText; -import org.bukkit.Material; +import static de.diddiz.util.MaterialName.materialName; -public class BlockChange implements LookupCacheElement -{ - public final long id, date; - public final Location loc; - public final Actor actor; - public final String playerName; - public final int replaced, type; - public final byte data; - public final String signtext; - public final ChestAccess ca; +public class BlockChange implements LookupCacheElement { + public final long id, date; + public final Location loc; + public final Actor actor; + public final String playerName; + public final int replaced, type; + public final byte data; + public final String signtext; + public final ChestAccess ca; - public BlockChange(long date, Location loc, Actor actor, int replaced, int type, byte data, String signtext, ChestAccess ca) { - id = 0; - this.date = date; - this.loc = loc; - this.actor = actor; - this.replaced = replaced; - this.type = type; - this.data = data; - this.signtext = checkText(signtext); - this.ca = ca; - this.playerName = actor == null ? null : actor.getName(); - } + public BlockChange(long date, Location loc, Actor actor, int replaced, int type, byte data, String signtext, ChestAccess ca) { + id = 0; + this.date = date; + this.loc = loc; + this.actor = actor; + this.replaced = replaced; + this.type = type; + this.data = data; + this.signtext = checkText(signtext); + this.ca = ca; + this.playerName = actor == null ? null : actor.getName(); + } - public BlockChange(ResultSet rs, QueryParams p) throws SQLException { - id = p.needId ? rs.getInt("id") : 0; - date = p.needDate ? rs.getTimestamp("date").getTime() : 0; - loc = p.needCoords ? new Location(p.world, rs.getInt("x"), rs.getInt("y"), rs.getInt("z")) : null; - actor = p.needPlayer ? new Actor(rs) : null; - playerName = p.needPlayer ? rs.getString("playername") : null; - replaced = p.needType ? rs.getInt("replaced") : 0; - type = p.needType ? rs.getInt("type") : 0; - data = p.needData ? rs.getByte("data") : (byte)0; - signtext = p.needSignText ? rs.getString("signtext") : null; - ca = p.needChestAccess && rs.getShort("itemtype") != 0 && rs.getShort("itemamount") != 0 ? new ChestAccess(rs.getShort("itemtype"), rs.getShort("itemamount"), rs.getShort("itemdata")) : null; - } + public BlockChange(ResultSet rs, QueryParams p) throws SQLException { + id = p.needId ? rs.getInt("id") : 0; + date = p.needDate ? rs.getTimestamp("date").getTime() : 0; + loc = p.needCoords ? new Location(p.world, rs.getInt("x"), rs.getInt("y"), rs.getInt("z")) : null; + actor = p.needPlayer ? new Actor(rs) : null; + playerName = p.needPlayer ? rs.getString("playername") : null; + replaced = p.needType ? rs.getInt("replaced") : 0; + type = p.needType ? rs.getInt("type") : 0; + data = p.needData ? rs.getByte("data") : (byte) 0; + signtext = p.needSignText ? rs.getString("signtext") : null; + ca = p.needChestAccess && rs.getShort("itemtype") != 0 && rs.getShort("itemamount") != 0 ? new ChestAccess(rs.getShort("itemtype"), rs.getShort("itemamount"), rs.getShort("itemdata")) : null; + } - @Override - public String toString() { - final StringBuilder msg = new StringBuilder(); - if (date > 0) - msg.append(Config.formatter.format(date)).append(" "); - if (actor != null) - msg.append(actor.getName()).append(" "); - if (signtext != null) { - final String action = type == 0 ? "destroyed " : "created "; - if (!signtext.contains("\0")) - msg.append(action).append(signtext); - else - msg.append(action).append(materialName(type != 0 ? type : replaced)).append(" [").append(signtext.replace("\0", "] [")).append("]"); - } else if (type == replaced) { - if (type == 0) - msg.append("did an unspecified action"); - else if (ca != null) { - if (ca.itemType == 0 || ca.itemAmount == 0) - msg.append("looked inside ").append(materialName(type)); - else if (ca.itemAmount < 0) - msg.append("took ").append(-ca.itemAmount).append("x ").append(materialName(ca.itemType, ca.itemData)).append(" from ").append(materialName(type)); - else - msg.append("put ").append(ca.itemAmount).append("x ").append(materialName(ca.itemType, ca.itemData)).append(" into ").append(materialName(type)); - } else if (BukkitUtils.getContainerBlocks().contains(Material.getMaterial(type))) - msg.append("opened ").append(materialName(type)); - else if (type == 64 || type == 71) - // This is a problem that will have to be addressed in LB 2, - // there is no way to tell from the top half of the block if - // the door is opened or closed. - msg.append("moved ").append(materialName(type)); - // Trapdoor - else if (type == 96) - msg.append((data < 8 || data > 11) ? "opened" : "closed").append(" ").append(materialName(type)); - // Fence gate - else if (type == 107) - msg.append(data > 3 ? "opened" : "closed").append(" ").append(materialName(type)); - else if (type == 69) - msg.append("switched ").append(materialName(type)); - else if (type == 77 || type == 143) - msg.append("pressed ").append(materialName(type)); - else if (type == 92) - msg.append("ate a piece of ").append(materialName(type)); - else if (type == 25 || type == 93 || type == 94 || type == 149 || type == 150) - msg.append("changed ").append(materialName(type)); - else if (type == 70 || type == 72 || type == 147 || type == 148) - msg.append("stepped on ").append(materialName(type)); - else if (type == 132) - msg.append("ran into ").append(materialName(type)); - } else if (type == 0) - msg.append("destroyed ").append(materialName(replaced, data)); - else if (replaced == 0) - msg.append("created ").append(materialName(type, data)); - else - msg.append("replaced ").append(materialName(replaced, (byte)0)).append(" with ").append(materialName(type, data)); - if (loc != null) - msg.append(" at ").append(loc.getBlockX()).append(":").append(loc.getBlockY()).append(":").append(loc.getBlockZ()); - return msg.toString(); - } + @Override + public String toString() { + final StringBuilder msg = new StringBuilder(); + if (date > 0) { + msg.append(Config.formatter.format(date)).append(" "); + } + if (actor != null) { + msg.append(actor.getName()).append(" "); + } + if (signtext != null) { + final String action = type == 0 ? "destroyed " : "created "; + if (!signtext.contains("\0")) { + msg.append(action).append(signtext); + } else { + msg.append(action).append(materialName(type != 0 ? type : replaced)).append(" [").append(signtext.replace("\0", "] [")).append("]"); + } + } else if (type == replaced) { + if (type == 0) { + msg.append("did an unspecified action"); + } else if (ca != null) { + if (ca.itemType == 0 || ca.itemAmount == 0) { + msg.append("looked inside ").append(materialName(type)); + } else if (ca.itemAmount < 0) { + msg.append("took ").append(-ca.itemAmount).append("x ").append(materialName(ca.itemType, ca.itemData)).append(" from ").append(materialName(type)); + } else { + msg.append("put ").append(ca.itemAmount).append("x ").append(materialName(ca.itemType, ca.itemData)).append(" into ").append(materialName(type)); + } + } else if (BukkitUtils.getContainerBlocks().contains(Material.getMaterial(type))) { + msg.append("opened ").append(materialName(type)); + } else if (type == 64 || type == 71) + // This is a problem that will have to be addressed in LB 2, + // there is no way to tell from the top half of the block if + // the door is opened or closed. + { + msg.append("moved ").append(materialName(type)); + } + // Trapdoor + else if (type == 96) { + msg.append((data < 8 || data > 11) ? "opened" : "closed").append(" ").append(materialName(type)); + } + // Fence gate + else if (type == 107) { + msg.append(data > 3 ? "opened" : "closed").append(" ").append(materialName(type)); + } else if (type == 69) { + msg.append("switched ").append(materialName(type)); + } else if (type == 77 || type == 143) { + msg.append("pressed ").append(materialName(type)); + } else if (type == 92) { + msg.append("ate a piece of ").append(materialName(type)); + } else if (type == 25 || type == 93 || type == 94 || type == 149 || type == 150) { + msg.append("changed ").append(materialName(type)); + } else if (type == 70 || type == 72 || type == 147 || type == 148) { + msg.append("stepped on ").append(materialName(type)); + } else if (type == 132) { + msg.append("ran into ").append(materialName(type)); + } + } else if (type == 0) { + msg.append("destroyed ").append(materialName(replaced, data)); + } else if (replaced == 0) { + msg.append("created ").append(materialName(type, data)); + } else { + msg.append("replaced ").append(materialName(replaced, (byte) 0)).append(" with ").append(materialName(type, data)); + } + if (loc != null) { + msg.append(" at ").append(loc.getBlockX()).append(":").append(loc.getBlockY()).append(":").append(loc.getBlockZ()); + } + return msg.toString(); + } - @Override - public Location getLocation() { - return loc; - } + @Override + public Location getLocation() { + return loc; + } - @Override - public String getMessage() { - return toString(); - } + @Override + public String getMessage() { + return toString(); + } } diff --git a/src/main/java/de/diddiz/LogBlock/ChatMessage.java b/src/main/java/de/diddiz/LogBlock/ChatMessage.java index ec5920e..097f56b 100644 --- a/src/main/java/de/diddiz/LogBlock/ChatMessage.java +++ b/src/main/java/de/diddiz/LogBlock/ChatMessage.java @@ -1,39 +1,40 @@ package de.diddiz.LogBlock; -import static de.diddiz.util.LoggingUtil.checkText; -import java.sql.ResultSet; -import java.sql.SQLException; import org.bukkit.Location; -public class ChatMessage implements LookupCacheElement -{ - final long id, date; - final String playerName, message; - final Actor player; +import java.sql.ResultSet; +import java.sql.SQLException; - public ChatMessage(Actor player, String message) { - id = 0; - date = System.currentTimeMillis() / 1000; - this.player = player; - this.message = checkText(message); - this.playerName = player == null ? null : player.getName(); - } +import static de.diddiz.util.LoggingUtil.checkText; - public ChatMessage(ResultSet rs, QueryParams p) throws SQLException { - id = p.needId ? rs.getInt("id") : 0; - date = p.needDate ? rs.getTimestamp("date").getTime() : 0; - player = p.needPlayer ? new Actor(rs) : null; - playerName = p.needPlayer ? rs.getString("playername") : null; - message = p.needMessage ? rs.getString("message") : null; - } +public class ChatMessage implements LookupCacheElement { + final long id, date; + final String playerName, message; + final Actor player; - @Override - public Location getLocation() { - return null; - } + public ChatMessage(Actor player, String message) { + id = 0; + date = System.currentTimeMillis() / 1000; + this.player = player; + this.message = checkText(message); + this.playerName = player == null ? null : player.getName(); + } - @Override - public String getMessage() { - return (player != null ? "<" + player.getName() + "> " : "") + (message != null ? message : ""); - } + public ChatMessage(ResultSet rs, QueryParams p) throws SQLException { + id = p.needId ? rs.getInt("id") : 0; + date = p.needDate ? rs.getTimestamp("date").getTime() : 0; + player = p.needPlayer ? new Actor(rs) : null; + playerName = p.needPlayer ? rs.getString("playername") : null; + message = p.needMessage ? rs.getString("message") : null; + } + + @Override + public Location getLocation() { + return null; + } + + @Override + public String getMessage() { + return (player != null ? "<" + player.getName() + "> " : "") + (message != null ? message : ""); + } } diff --git a/src/main/java/de/diddiz/LogBlock/ChestAccess.java b/src/main/java/de/diddiz/LogBlock/ChestAccess.java index f31b735..10260e5 100644 --- a/src/main/java/de/diddiz/LogBlock/ChestAccess.java +++ b/src/main/java/de/diddiz/LogBlock/ChestAccess.java @@ -1,12 +1,11 @@ package de.diddiz.LogBlock; -public class ChestAccess -{ - final short itemType, itemAmount, itemData; +public class ChestAccess { + final short itemType, itemAmount, itemData; - public ChestAccess(short itemType, short itemAmount, short itemData) { - this.itemType = itemType; - this.itemAmount = itemAmount; - this.itemData = itemData >= 0 ? itemData : 0; - } + public ChestAccess(short itemType, short itemAmount, short itemData) { + this.itemType = itemType; + this.itemAmount = itemAmount; + this.itemData = itemData >= 0 ? itemData : 0; + } } diff --git a/src/main/java/de/diddiz/LogBlock/CommandsHandler.java b/src/main/java/de/diddiz/LogBlock/CommandsHandler.java index 02446f4..78bbf2a 100755 --- a/src/main/java/de/diddiz/LogBlock/CommandsHandler.java +++ b/src/main/java/de/diddiz/LogBlock/CommandsHandler.java @@ -39,760 +39,826 @@ import static de.diddiz.util.Utils.listing; import static org.bukkit.Bukkit.getLogger; import static org.bukkit.Bukkit.getServer; -public class CommandsHandler implements CommandExecutor -{ - private final LogBlock logblock; - private final BukkitScheduler scheduler; - private final LogBlockQuestioner questioner; +public class CommandsHandler implements CommandExecutor { + private final LogBlock logblock; + private final BukkitScheduler scheduler; + private final LogBlockQuestioner questioner; - CommandsHandler(LogBlock logblock) { - this.logblock = logblock; - scheduler = logblock.getServer().getScheduler(); - questioner = (LogBlockQuestioner)logblock.getServer().getPluginManager().getPlugin("LogBlockQuestioner"); - } + CommandsHandler(LogBlock logblock) { + this.logblock = logblock; + scheduler = logblock.getServer().getScheduler(); + questioner = (LogBlockQuestioner) logblock.getServer().getPluginManager().getPlugin("LogBlockQuestioner"); + } - @Override - public boolean onCommand(CommandSender sender, Command cmd, String commandLabel, String[] args) { - try { - if (args.length == 0) { - sender.sendMessage(ChatColor.LIGHT_PURPLE + "LogBlock v" + logblock.getDescription().getVersion() + " by DiddiZ"); - sender.sendMessage(ChatColor.LIGHT_PURPLE + "Type /lb help for help"); - } else { - final String command = args[0].toLowerCase(); - if (command.equals("help")) { - sender.sendMessage(ChatColor.DARK_AQUA + "LogBlock Help:"); - sender.sendMessage(ChatColor.GOLD + "For the commands list type '/lb commands'"); - sender.sendMessage(ChatColor.GOLD + "For the parameters list type '/lb params'"); - sender.sendMessage(ChatColor.GOLD + "For the list of permissions you got type '/lb permissions'"); - } else if (command.equals("commands")) { - sender.sendMessage(ChatColor.DARK_AQUA + "LogBlock Commands:"); - sender.sendMessage(ChatColor.GOLD + "/lb tool -- Gives you the lb tool"); - sender.sendMessage(ChatColor.GOLD + "/lb tool [on|off] -- Enables/Disables tool"); - sender.sendMessage(ChatColor.GOLD + "/lb tool [params] -- Sets the tool lookup query"); - sender.sendMessage(ChatColor.GOLD + "/lb tool default -- Sets the tool lookup query to default"); - sender.sendMessage(ChatColor.GOLD + "/lb toolblock -- Analog to tool"); - sender.sendMessage(ChatColor.GOLD + "/lb hide -- Hides you from log"); - sender.sendMessage(ChatColor.GOLD + "/lb rollback [params] -- Rollback"); - sender.sendMessage(ChatColor.GOLD + "/lb redo [params] -- Redo"); - sender.sendMessage(ChatColor.GOLD + "/lb tp [params] -- Teleports you to the location of griefing"); - sender.sendMessage(ChatColor.GOLD + "/lb writelogfile [params] -- Writes a log file"); - sender.sendMessage(ChatColor.GOLD + "/lb lookup [params] -- Lookup"); - sender.sendMessage(ChatColor.GOLD + "/lb prev|next -- Browse lookup result pages"); - sender.sendMessage(ChatColor.GOLD + "/lb page -- Shows a specific lookup result page"); - sender.sendMessage(ChatColor.GOLD + "/lb me -- Displays your stats"); - sender.sendMessage(ChatColor.GOLD + "Look at github.com/LogBlock/LogBlock/wiki/Commands for the full commands reference"); - } else if (command.equals("params")) { - sender.sendMessage(ChatColor.DARK_AQUA + "LogBlock Query Parameters:"); - sender.sendMessage(ChatColor.GOLD + "Use doublequotes to escape a keyword: world \"world\""); - sender.sendMessage(ChatColor.GOLD + "player [name1] -- List of players"); - sender.sendMessage(ChatColor.GOLD + "block [type1] -- List of block types"); - sender.sendMessage(ChatColor.GOLD + "created, destroyed -- Show only created/destroyed blocks"); - sender.sendMessage(ChatColor.GOLD + "chestaccess -- Show only chest accesses"); - sender.sendMessage(ChatColor.GOLD + "area -- Area around you"); - sender.sendMessage(ChatColor.GOLD + "selection, sel -- Inside current WorldEdit selection"); - sender.sendMessage(ChatColor.GOLD + "world [worldname] -- Changes the world"); - sender.sendMessage(ChatColor.GOLD + "time [number] [minutes|hours|days] -- Limits time"); - sender.sendMessage(ChatColor.GOLD + "since -- Limits time to a fixed point"); - sender.sendMessage(ChatColor.GOLD + "before -- Affects only blocks before a fixed time"); - sender.sendMessage(ChatColor.GOLD + "limit -- Limits the result to count of rows"); - sender.sendMessage(ChatColor.GOLD + "sum [none|blocks|players] -- Sums the result"); - sender.sendMessage(ChatColor.GOLD + "asc, desc -- Changes the order of the displayed log"); - sender.sendMessage(ChatColor.GOLD + "coords -- Shows coordinates for each block"); - sender.sendMessage(ChatColor.GOLD + "silent -- Displays lesser messages"); - } else if (command.equals("permissions")) { - sender.sendMessage(ChatColor.DARK_AQUA + "You've got the following permissions:"); - for (final String permission : new String[]{"me", "lookup", "tp", "rollback", "clearlog", "hide", "ignoreRestrictions", "spawnTools"}) - if (logblock.hasPermission(sender, "logblock." + permission)) - sender.sendMessage(ChatColor.GOLD + "logblock." + permission); - for (final Tool tool : toolsByType.values()) - if (logblock.hasPermission(sender, "logblock.tools." + tool.name)) - sender.sendMessage(ChatColor.GOLD + "logblock.tools." + tool.name); - } else if (command.equals("logging")) { - if (logblock.hasPermission(sender, "logblock.lookup")) { - World world = null; - if (args.length > 1) - world = getServer().getWorld(args[1]); - else if (sender instanceof Player) - world = ((Player)sender).getWorld(); - if (world != null) { - final WorldConfig wcfg = getWorldConfig(world.getName()); - if (wcfg != null) { - sender.sendMessage(ChatColor.DARK_AQUA + "Currently logging in " + world.getName() + ":"); - final List logging = new ArrayList(); - for (final Logging l : Logging.values()) - if (wcfg.isLogging(l)) - logging.add(l.toString()); - sender.sendMessage(ChatColor.GOLD + listing(logging, ", ", " and ")); - } else { - sender.sendMessage(ChatColor.RED + "World not logged: '" + world.getName() + "'"); - sender.sendMessage(ChatColor.LIGHT_PURPLE + "Make the world name is listed at loggedWorlds in config. World names are case sensitive and must contains the path (if any), exactly like in the message above."); - } - } else - sender.sendMessage(ChatColor.RED + "No world specified"); - } else - sender.sendMessage(ChatColor.RED + "You aren't allowed to do this."); - } else if (toolsByName.get(command) != null) { - final Tool tool = toolsByName.get(command); - if (logblock.hasPermission(sender, "logblock.tools." + tool.name)) { - if (sender instanceof Player) { - final Player player = (Player)sender; - final Session session = Session.getSession(player.getName()); - final ToolData toolData = session.toolData.get(tool); - if (args.length == 1) { - if (logblock.hasPermission(player, "logblock.spawnTools")) { - giveTool(player, tool.item); - session.toolData.get(tool).enabled = true; - } else - sender.sendMessage(ChatColor.RED + "You aren't allowed to do this."); - } else if (args[1].equalsIgnoreCase("enable") || args[1].equalsIgnoreCase("on")) { - toolData.enabled = true; - player.sendMessage(ChatColor.GREEN + "Tool enabled."); - } else if (args[1].equalsIgnoreCase("disable") || args[1].equalsIgnoreCase("off")) { - toolData.enabled = false; - player.getInventory().removeItem(new ItemStack(tool.item, 1)); - player.sendMessage(ChatColor.GREEN + "Tool disabled."); - } else if (args[1].equalsIgnoreCase("mode")) { - if (args.length == 3) { - final ToolMode mode; - try { - mode = ToolMode.valueOf(args[2].toUpperCase()); - } catch (final IllegalArgumentException ex) { - sender.sendMessage(ChatColor.RED + "Can't find mode " + args[2]); - return true; - } - if (logblock.hasPermission(player, mode.getPermission())) { - toolData.mode = mode; - sender.sendMessage(ChatColor.GREEN + "Tool mode set to " + args[2]); - } else - sender.sendMessage(ChatColor.RED + "You aren't allowed to use mode " + args[2]); - } else - player.sendMessage(ChatColor.RED + "No mode specified"); - } else if (args[1].equalsIgnoreCase("default")) { - toolData.params = tool.params.clone(); - toolData.mode = tool.mode; - sender.sendMessage(ChatColor.GREEN + "Tool set to default."); - } else if (logblock.hasPermission(player, "logblock.lookup")) - try { - final QueryParams params = tool.params.clone(); - params.parseArgs(sender, argsToList(args, 1)); - toolData.params = params; - sender.sendMessage(ChatColor.GREEN + "Set tool query to: " + params.getTitle()); - } catch (final Exception ex) { - sender.sendMessage(ChatColor.RED + ex.getMessage()); - } - else - sender.sendMessage(ChatColor.RED + "You aren't allowed to do this."); - } else - sender.sendMessage(ChatColor.RED + "You have to be a player."); - } else - sender.sendMessage(ChatColor.RED + "You aren't allowed to do this."); - } else if (command.equals("hide")) { - if (sender instanceof Player) { - if (logblock.hasPermission(sender, "logblock.hide")) { - if (args.length == 2) { - if (args[1].equalsIgnoreCase("on")) { - Consumer.hide((Player) sender); - sender.sendMessage(ChatColor.GREEN + "You are now hidden and aren't logged. Type /lb hide to unhide."); - } else if (args[1].equalsIgnoreCase("off")) { - Consumer.unHide((Player) sender); - sender.sendMessage(ChatColor.GREEN + "You aren't hidden any longer."); - } - } else { - if (Consumer.toggleHide((Player) sender)) { - sender.sendMessage(ChatColor.GREEN + "You are now hidden and aren't logged. Type '/lb hide' again to unhide."); - } else { - sender.sendMessage(ChatColor.GREEN + "You aren't hidden any longer."); - } - } - } else - sender.sendMessage(ChatColor.RED + "You aren't allowed to do this."); - } else - sender.sendMessage(ChatColor.RED + "You have to be a player."); - } else if (command.equals("page")) { - if (args.length == 2 && isInt(args[1])) - showPage(sender, Integer.valueOf(args[1])); - else - sender.sendMessage(ChatColor.RED + "You have to specify a page"); - } else if (command.equals("next") || command.equals("+")) - showPage(sender, getSession(sender).page + 1); - else if (command.equals("prev") || command.equals("-")) - showPage(sender, getSession(sender).page - 1); - else if (args[0].equalsIgnoreCase("savequeue")) { - if (logblock.hasPermission(sender, "logblock.rollback")) - new CommandSaveQueue(sender, null, true); - else - sender.sendMessage(ChatColor.RED + "You aren't allowed to do this."); - } else if (args[0].equalsIgnoreCase("queuesize")) { - if (logblock.hasPermission(sender, "logblock.rollback")) - sender.sendMessage("Current queue size: " + logblock.getConsumer().getQueueSize()); - else - sender.sendMessage(ChatColor.RED + "You aren't allowed to do this."); - } else if (command.equals("rollback") || command.equals("undo") || command.equals("rb")) { - if (logblock.hasPermission(sender, "logblock.rollback")) { - final QueryParams params = new QueryParams(logblock); - params.since = defaultTime; - params.bct = BlockChangeType.ALL; - params.parseArgs(sender, argsToList(args, 1)); - new CommandRollback(sender, params, true); - } else - sender.sendMessage(ChatColor.RED + "You aren't allowed to do this."); - } else if (command.equals("redo")) { - if (logblock.hasPermission(sender, "logblock.rollback")) { - final QueryParams params = new QueryParams(logblock); - params.since = defaultTime; - params.bct = BlockChangeType.ALL; - params.parseArgs(sender, argsToList(args, 1)); - new CommandRedo(sender, params, true); - } else - sender.sendMessage(ChatColor.RED + "You aren't allowed to do this."); - } else if (command.equals("me")) { - if (sender instanceof Player) { - if (logblock.hasPermission(sender, "logblock.me")) { - final Player player = (Player)sender; - if (Config.isLogged(player.getWorld())) { - final QueryParams params = new QueryParams(logblock); - params.setPlayer(player.getName()); - params.world = player.getWorld(); - player.sendMessage("Total block changes: " + logblock.getCount(params)); - params.sum = SummarizationMode.TYPES; - new CommandLookup(sender, params, true); - } else - sender.sendMessage(ChatColor.RED + "This world isn't logged"); - } else - sender.sendMessage(ChatColor.RED + "You aren't allowed to do this."); - } else - sender.sendMessage(ChatColor.RED + "You have to be a player."); - } else if (command.equals("writelogfile")) { - if (logblock.hasPermission(sender, "logblock.rollback")) { - final QueryParams params = new QueryParams(logblock); - params.limit = -1; - params.bct = BlockChangeType.ALL; - params.parseArgs(sender, argsToList(args, 1)); - new CommandWriteLogFile(sender, params, true); - } else - sender.sendMessage(ChatColor.RED + "You aren't allowed to do this"); - } else if (command.equals("clearlog")) { - if (logblock.hasPermission(sender, "logblock.clearlog")) { - final QueryParams params = new QueryParams(logblock, sender, argsToList(args, 1)); - params.bct = BlockChangeType.ALL; - params.limit = -1; - new CommandClearLog(sender, params, true); - } else - sender.sendMessage(ChatColor.RED + "You aren't allowed to do this"); - } else if (command.equals("tp")) { - if (sender instanceof Player) { - if (logblock.hasPermission(sender, "logblock.tp")) - if (args.length == 2 || isInt(args[1])) { - final int pos = Integer.parseInt(args[1]) - 1; - final Player player = (Player)sender; - final Session session = getSession(player); - if (session.lookupCache != null) - if (pos >= 0 && pos < session.lookupCache.length) { - final Location loc = session.lookupCache[pos].getLocation(); - if (loc != null) { - player.teleport(new Location(loc.getWorld(), loc.getX() + 0.5, saveSpawnHeight(loc), loc.getZ() + 0.5, player.getLocation().getYaw(), 90)); - player.sendMessage(ChatColor.LIGHT_PURPLE + "Teleported to " + loc.getBlockX() + ":" + loc.getBlockY() + ":" + loc.getBlockZ()); - } else - sender.sendMessage(ChatColor.RED + "There is no location associated with that. Did you forget coords parameter?"); - } else - sender.sendMessage(ChatColor.RED + "'" + args[1] + " is out of range"); - else - sender.sendMessage(ChatColor.RED + "You havn't done a lookup yet"); - } else - new CommandTeleport(sender, new QueryParams(logblock, sender, argsToList(args, 1)), true); - else - sender.sendMessage(ChatColor.RED + "You aren't allowed to do this"); - } else - sender.sendMessage(ChatColor.RED + "You have to be a player."); - } else if (command.equals("lookup") || QueryParams.isKeyWord(args[0])) { - if (logblock.hasPermission(sender, "logblock.lookup")) { - final List argsList = new ArrayList(Arrays.asList(args)); - if (command.equals("lookup")) - argsList.remove(0); - new CommandLookup(sender, new QueryParams(logblock, sender, argsList), true); - } else - sender.sendMessage(ChatColor.RED + "You aren't allowed to do this"); - } else - sender.sendMessage(ChatColor.RED + "Unknown command '" + args[0] + "'"); - } - } catch (final IllegalArgumentException ex) { - sender.sendMessage(ChatColor.RED + ex.getMessage()); - } catch (final ArrayIndexOutOfBoundsException ex) { - sender.sendMessage(ChatColor.RED + "Not enough arguments given"); - } catch (final Exception ex) { - sender.sendMessage(ChatColor.RED + "Error, check server.log"); - getLogger().log(Level.WARNING, "Exception in commands handler: ", ex); - } - return true; - } + @Override + public boolean onCommand(CommandSender sender, Command cmd, String commandLabel, String[] args) { + try { + if (args.length == 0) { + sender.sendMessage(ChatColor.LIGHT_PURPLE + "LogBlock v" + logblock.getDescription().getVersion() + " by DiddiZ"); + sender.sendMessage(ChatColor.LIGHT_PURPLE + "Type /lb help for help"); + } else { + final String command = args[0].toLowerCase(); + if (command.equals("help")) { + sender.sendMessage(ChatColor.DARK_AQUA + "LogBlock Help:"); + sender.sendMessage(ChatColor.GOLD + "For the commands list type '/lb commands'"); + sender.sendMessage(ChatColor.GOLD + "For the parameters list type '/lb params'"); + sender.sendMessage(ChatColor.GOLD + "For the list of permissions you got type '/lb permissions'"); + } else if (command.equals("commands")) { + sender.sendMessage(ChatColor.DARK_AQUA + "LogBlock Commands:"); + sender.sendMessage(ChatColor.GOLD + "/lb tool -- Gives you the lb tool"); + sender.sendMessage(ChatColor.GOLD + "/lb tool [on|off] -- Enables/Disables tool"); + sender.sendMessage(ChatColor.GOLD + "/lb tool [params] -- Sets the tool lookup query"); + sender.sendMessage(ChatColor.GOLD + "/lb tool default -- Sets the tool lookup query to default"); + sender.sendMessage(ChatColor.GOLD + "/lb toolblock -- Analog to tool"); + sender.sendMessage(ChatColor.GOLD + "/lb hide -- Hides you from log"); + sender.sendMessage(ChatColor.GOLD + "/lb rollback [params] -- Rollback"); + sender.sendMessage(ChatColor.GOLD + "/lb redo [params] -- Redo"); + sender.sendMessage(ChatColor.GOLD + "/lb tp [params] -- Teleports you to the location of griefing"); + sender.sendMessage(ChatColor.GOLD + "/lb writelogfile [params] -- Writes a log file"); + sender.sendMessage(ChatColor.GOLD + "/lb lookup [params] -- Lookup"); + sender.sendMessage(ChatColor.GOLD + "/lb prev|next -- Browse lookup result pages"); + sender.sendMessage(ChatColor.GOLD + "/lb page -- Shows a specific lookup result page"); + sender.sendMessage(ChatColor.GOLD + "/lb me -- Displays your stats"); + sender.sendMessage(ChatColor.GOLD + "Look at github.com/LogBlock/LogBlock/wiki/Commands for the full commands reference"); + } else if (command.equals("params")) { + sender.sendMessage(ChatColor.DARK_AQUA + "LogBlock Query Parameters:"); + sender.sendMessage(ChatColor.GOLD + "Use doublequotes to escape a keyword: world \"world\""); + sender.sendMessage(ChatColor.GOLD + "player [name1] -- List of players"); + sender.sendMessage(ChatColor.GOLD + "block [type1] -- List of block types"); + sender.sendMessage(ChatColor.GOLD + "created, destroyed -- Show only created/destroyed blocks"); + sender.sendMessage(ChatColor.GOLD + "chestaccess -- Show only chest accesses"); + sender.sendMessage(ChatColor.GOLD + "area -- Area around you"); + sender.sendMessage(ChatColor.GOLD + "selection, sel -- Inside current WorldEdit selection"); + sender.sendMessage(ChatColor.GOLD + "world [worldname] -- Changes the world"); + sender.sendMessage(ChatColor.GOLD + "time [number] [minutes|hours|days] -- Limits time"); + sender.sendMessage(ChatColor.GOLD + "since -- Limits time to a fixed point"); + sender.sendMessage(ChatColor.GOLD + "before -- Affects only blocks before a fixed time"); + sender.sendMessage(ChatColor.GOLD + "limit -- Limits the result to count of rows"); + sender.sendMessage(ChatColor.GOLD + "sum [none|blocks|players] -- Sums the result"); + sender.sendMessage(ChatColor.GOLD + "asc, desc -- Changes the order of the displayed log"); + sender.sendMessage(ChatColor.GOLD + "coords -- Shows coordinates for each block"); + sender.sendMessage(ChatColor.GOLD + "silent -- Displays lesser messages"); + } else if (command.equals("permissions")) { + sender.sendMessage(ChatColor.DARK_AQUA + "You've got the following permissions:"); + for (final String permission : new String[]{"me", "lookup", "tp", "rollback", "clearlog", "hide", "ignoreRestrictions", "spawnTools"}) { + if (logblock.hasPermission(sender, "logblock." + permission)) { + sender.sendMessage(ChatColor.GOLD + "logblock." + permission); + } + } + for (final Tool tool : toolsByType.values()) { + if (logblock.hasPermission(sender, "logblock.tools." + tool.name)) { + sender.sendMessage(ChatColor.GOLD + "logblock.tools." + tool.name); + } + } + } else if (command.equals("logging")) { + if (logblock.hasPermission(sender, "logblock.lookup")) { + World world = null; + if (args.length > 1) { + world = getServer().getWorld(args[1]); + } else if (sender instanceof Player) { + world = ((Player) sender).getWorld(); + } + if (world != null) { + final WorldConfig wcfg = getWorldConfig(world.getName()); + if (wcfg != null) { + sender.sendMessage(ChatColor.DARK_AQUA + "Currently logging in " + world.getName() + ":"); + final List logging = new ArrayList(); + for (final Logging l : Logging.values()) { + if (wcfg.isLogging(l)) { + logging.add(l.toString()); + } + } + sender.sendMessage(ChatColor.GOLD + listing(logging, ", ", " and ")); + } else { + sender.sendMessage(ChatColor.RED + "World not logged: '" + world.getName() + "'"); + sender.sendMessage(ChatColor.LIGHT_PURPLE + "Make the world name is listed at loggedWorlds in config. World names are case sensitive and must contains the path (if any), exactly like in the message above."); + } + } else { + sender.sendMessage(ChatColor.RED + "No world specified"); + } + } else { + sender.sendMessage(ChatColor.RED + "You aren't allowed to do this."); + } + } else if (toolsByName.get(command) != null) { + final Tool tool = toolsByName.get(command); + if (logblock.hasPermission(sender, "logblock.tools." + tool.name)) { + if (sender instanceof Player) { + final Player player = (Player) sender; + final Session session = Session.getSession(player.getName()); + final ToolData toolData = session.toolData.get(tool); + if (args.length == 1) { + if (logblock.hasPermission(player, "logblock.spawnTools")) { + giveTool(player, tool.item); + session.toolData.get(tool).enabled = true; + } else { + sender.sendMessage(ChatColor.RED + "You aren't allowed to do this."); + } + } else if (args[1].equalsIgnoreCase("enable") || args[1].equalsIgnoreCase("on")) { + toolData.enabled = true; + player.sendMessage(ChatColor.GREEN + "Tool enabled."); + } else if (args[1].equalsIgnoreCase("disable") || args[1].equalsIgnoreCase("off")) { + toolData.enabled = false; + player.getInventory().removeItem(new ItemStack(tool.item, 1)); + player.sendMessage(ChatColor.GREEN + "Tool disabled."); + } else if (args[1].equalsIgnoreCase("mode")) { + if (args.length == 3) { + final ToolMode mode; + try { + mode = ToolMode.valueOf(args[2].toUpperCase()); + } catch (final IllegalArgumentException ex) { + sender.sendMessage(ChatColor.RED + "Can't find mode " + args[2]); + return true; + } + if (logblock.hasPermission(player, mode.getPermission())) { + toolData.mode = mode; + sender.sendMessage(ChatColor.GREEN + "Tool mode set to " + args[2]); + } else { + sender.sendMessage(ChatColor.RED + "You aren't allowed to use mode " + args[2]); + } + } else { + player.sendMessage(ChatColor.RED + "No mode specified"); + } + } else if (args[1].equalsIgnoreCase("default")) { + toolData.params = tool.params.clone(); + toolData.mode = tool.mode; + sender.sendMessage(ChatColor.GREEN + "Tool set to default."); + } else if (logblock.hasPermission(player, "logblock.lookup")) { + try { + final QueryParams params = tool.params.clone(); + params.parseArgs(sender, argsToList(args, 1)); + toolData.params = params; + sender.sendMessage(ChatColor.GREEN + "Set tool query to: " + params.getTitle()); + } catch (final Exception ex) { + sender.sendMessage(ChatColor.RED + ex.getMessage()); + } + } else { + sender.sendMessage(ChatColor.RED + "You aren't allowed to do this."); + } + } else { + sender.sendMessage(ChatColor.RED + "You have to be a player."); + } + } else { + sender.sendMessage(ChatColor.RED + "You aren't allowed to do this."); + } + } else if (command.equals("hide")) { + if (sender instanceof Player) { + if (logblock.hasPermission(sender, "logblock.hide")) { + if (args.length == 2) { + if (args[1].equalsIgnoreCase("on")) { + Consumer.hide((Player) sender); + sender.sendMessage(ChatColor.GREEN + "You are now hidden and aren't logged. Type /lb hide to unhide."); + } else if (args[1].equalsIgnoreCase("off")) { + Consumer.unHide((Player) sender); + sender.sendMessage(ChatColor.GREEN + "You aren't hidden any longer."); + } + } else { + if (Consumer.toggleHide((Player) sender)) { + sender.sendMessage(ChatColor.GREEN + "You are now hidden and aren't logged. Type '/lb hide' again to unhide."); + } else { + sender.sendMessage(ChatColor.GREEN + "You aren't hidden any longer."); + } + } + } else { + sender.sendMessage(ChatColor.RED + "You aren't allowed to do this."); + } + } else { + sender.sendMessage(ChatColor.RED + "You have to be a player."); + } + } else if (command.equals("page")) { + if (args.length == 2 && isInt(args[1])) { + showPage(sender, Integer.valueOf(args[1])); + } else { + sender.sendMessage(ChatColor.RED + "You have to specify a page"); + } + } else if (command.equals("next") || command.equals("+")) { + showPage(sender, getSession(sender).page + 1); + } else if (command.equals("prev") || command.equals("-")) { + showPage(sender, getSession(sender).page - 1); + } else if (args[0].equalsIgnoreCase("savequeue")) { + if (logblock.hasPermission(sender, "logblock.rollback")) { + new CommandSaveQueue(sender, null, true); + } else { + sender.sendMessage(ChatColor.RED + "You aren't allowed to do this."); + } + } else if (args[0].equalsIgnoreCase("queuesize")) { + if (logblock.hasPermission(sender, "logblock.rollback")) { + sender.sendMessage("Current queue size: " + logblock.getConsumer().getQueueSize()); + } else { + sender.sendMessage(ChatColor.RED + "You aren't allowed to do this."); + } + } else if (command.equals("rollback") || command.equals("undo") || command.equals("rb")) { + if (logblock.hasPermission(sender, "logblock.rollback")) { + final QueryParams params = new QueryParams(logblock); + params.since = defaultTime; + params.bct = BlockChangeType.ALL; + params.parseArgs(sender, argsToList(args, 1)); + new CommandRollback(sender, params, true); + } else { + sender.sendMessage(ChatColor.RED + "You aren't allowed to do this."); + } + } else if (command.equals("redo")) { + if (logblock.hasPermission(sender, "logblock.rollback")) { + final QueryParams params = new QueryParams(logblock); + params.since = defaultTime; + params.bct = BlockChangeType.ALL; + params.parseArgs(sender, argsToList(args, 1)); + new CommandRedo(sender, params, true); + } else { + sender.sendMessage(ChatColor.RED + "You aren't allowed to do this."); + } + } else if (command.equals("me")) { + if (sender instanceof Player) { + if (logblock.hasPermission(sender, "logblock.me")) { + final Player player = (Player) sender; + if (Config.isLogged(player.getWorld())) { + final QueryParams params = new QueryParams(logblock); + params.setPlayer(player.getName()); + params.world = player.getWorld(); + player.sendMessage("Total block changes: " + logblock.getCount(params)); + params.sum = SummarizationMode.TYPES; + new CommandLookup(sender, params, true); + } else { + sender.sendMessage(ChatColor.RED + "This world isn't logged"); + } + } else { + sender.sendMessage(ChatColor.RED + "You aren't allowed to do this."); + } + } else { + sender.sendMessage(ChatColor.RED + "You have to be a player."); + } + } else if (command.equals("writelogfile")) { + if (logblock.hasPermission(sender, "logblock.rollback")) { + final QueryParams params = new QueryParams(logblock); + params.limit = -1; + params.bct = BlockChangeType.ALL; + params.parseArgs(sender, argsToList(args, 1)); + new CommandWriteLogFile(sender, params, true); + } else { + sender.sendMessage(ChatColor.RED + "You aren't allowed to do this"); + } + } else if (command.equals("clearlog")) { + if (logblock.hasPermission(sender, "logblock.clearlog")) { + final QueryParams params = new QueryParams(logblock, sender, argsToList(args, 1)); + params.bct = BlockChangeType.ALL; + params.limit = -1; + new CommandClearLog(sender, params, true); + } else { + sender.sendMessage(ChatColor.RED + "You aren't allowed to do this"); + } + } else if (command.equals("tp")) { + if (sender instanceof Player) { + if (logblock.hasPermission(sender, "logblock.tp")) { + if (args.length == 2 || isInt(args[1])) { + final int pos = Integer.parseInt(args[1]) - 1; + final Player player = (Player) sender; + final Session session = getSession(player); + if (session.lookupCache != null) { + if (pos >= 0 && pos < session.lookupCache.length) { + final Location loc = session.lookupCache[pos].getLocation(); + if (loc != null) { + player.teleport(new Location(loc.getWorld(), loc.getX() + 0.5, saveSpawnHeight(loc), loc.getZ() + 0.5, player.getLocation().getYaw(), 90)); + player.sendMessage(ChatColor.LIGHT_PURPLE + "Teleported to " + loc.getBlockX() + ":" + loc.getBlockY() + ":" + loc.getBlockZ()); + } else { + sender.sendMessage(ChatColor.RED + "There is no location associated with that. Did you forget coords parameter?"); + } + } else { + sender.sendMessage(ChatColor.RED + "'" + args[1] + " is out of range"); + } + } else { + sender.sendMessage(ChatColor.RED + "You havn't done a lookup yet"); + } + } else { + new CommandTeleport(sender, new QueryParams(logblock, sender, argsToList(args, 1)), true); + } + } else { + sender.sendMessage(ChatColor.RED + "You aren't allowed to do this"); + } + } else { + sender.sendMessage(ChatColor.RED + "You have to be a player."); + } + } else if (command.equals("lookup") || QueryParams.isKeyWord(args[0])) { + if (logblock.hasPermission(sender, "logblock.lookup")) { + final List argsList = new ArrayList(Arrays.asList(args)); + if (command.equals("lookup")) { + argsList.remove(0); + } + new CommandLookup(sender, new QueryParams(logblock, sender, argsList), true); + } else { + sender.sendMessage(ChatColor.RED + "You aren't allowed to do this"); + } + } else { + sender.sendMessage(ChatColor.RED + "Unknown command '" + args[0] + "'"); + } + } + } catch (final IllegalArgumentException ex) { + sender.sendMessage(ChatColor.RED + ex.getMessage()); + } catch (final ArrayIndexOutOfBoundsException ex) { + sender.sendMessage(ChatColor.RED + "Not enough arguments given"); + } catch (final Exception ex) { + sender.sendMessage(ChatColor.RED + "Error, check server.log"); + getLogger().log(Level.WARNING, "Exception in commands handler: ", ex); + } + return true; + } - private static void showPage(CommandSender sender, int page) { - final Session session = getSession(sender); - if (session.lookupCache != null && session.lookupCache.length > 0) { - final int startpos = (page - 1) * linesPerPage; - if (page > 0 && startpos <= session.lookupCache.length - 1) { - final int stoppos = startpos + linesPerPage >= session.lookupCache.length ? session.lookupCache.length - 1 : startpos + linesPerPage - 1; - final int numberOfPages = (int)Math.ceil(session.lookupCache.length / (double)linesPerPage); - if (numberOfPages != 1) - sender.sendMessage(ChatColor.DARK_AQUA + "Page " + page + "/" + numberOfPages); - for (int i = startpos; i <= stoppos; i++) - sender.sendMessage(ChatColor.GOLD + (session.lookupCache[i].getLocation() != null ? "(" + (i + 1) + ") " : "") + session.lookupCache[i].getMessage()); - session.page = page; - } else - sender.sendMessage(ChatColor.RED + "There isn't a page '" + page + "'"); - } else - sender.sendMessage(ChatColor.RED + "No blocks in lookup cache"); - } + private static void showPage(CommandSender sender, int page) { + final Session session = getSession(sender); + if (session.lookupCache != null && session.lookupCache.length > 0) { + final int startpos = (page - 1) * linesPerPage; + if (page > 0 && startpos <= session.lookupCache.length - 1) { + final int stoppos = startpos + linesPerPage >= session.lookupCache.length ? session.lookupCache.length - 1 : startpos + linesPerPage - 1; + final int numberOfPages = (int) Math.ceil(session.lookupCache.length / (double) linesPerPage); + if (numberOfPages != 1) { + sender.sendMessage(ChatColor.DARK_AQUA + "Page " + page + "/" + numberOfPages); + } + for (int i = startpos; i <= stoppos; i++) { + sender.sendMessage(ChatColor.GOLD + (session.lookupCache[i].getLocation() != null ? "(" + (i + 1) + ") " : "") + session.lookupCache[i].getMessage()); + } + session.page = page; + } else { + sender.sendMessage(ChatColor.RED + "There isn't a page '" + page + "'"); + } + } else { + sender.sendMessage(ChatColor.RED + "No blocks in lookup cache"); + } + } - private boolean checkRestrictions(CommandSender sender, QueryParams params) { - if (sender.isOp() || logblock.hasPermission(sender, "logblock.ignoreRestrictions")) - return true; - if (rollbackMaxTime > 0 && (params.before > 0 || params.since > rollbackMaxTime)) { - sender.sendMessage(ChatColor.RED + "You are not allowed to rollback more than " + rollbackMaxTime + " minutes"); - return false; - } - if (rollbackMaxArea > 0 && (params.sel == null && params.loc == null || params.radius > rollbackMaxArea || params.sel != null && (params.sel.getSelection().getLength() > rollbackMaxArea || params.sel.getSelection().getWidth() > rollbackMaxArea))) { - sender.sendMessage(ChatColor.RED + "You are not allowed to rollback an area larger than " + rollbackMaxArea + " blocks"); - return false; - } - return true; - } + private boolean checkRestrictions(CommandSender sender, QueryParams params) { + if (sender.isOp() || logblock.hasPermission(sender, "logblock.ignoreRestrictions")) { + return true; + } + if (rollbackMaxTime > 0 && (params.before > 0 || params.since > rollbackMaxTime)) { + sender.sendMessage(ChatColor.RED + "You are not allowed to rollback more than " + rollbackMaxTime + " minutes"); + return false; + } + if (rollbackMaxArea > 0 && (params.sel == null && params.loc == null || params.radius > rollbackMaxArea || params.sel != null && (params.sel.getSelection().getLength() > rollbackMaxArea || params.sel.getSelection().getWidth() > rollbackMaxArea))) { + sender.sendMessage(ChatColor.RED + "You are not allowed to rollback an area larger than " + rollbackMaxArea + " blocks"); + return false; + } + return true; + } - public abstract class AbstractCommand implements Runnable, Closeable - { - protected CommandSender sender; - protected QueryParams params; - protected Connection conn = null; - protected Statement state = null; - protected ResultSet rs = null; + public abstract class AbstractCommand implements Runnable, Closeable { + protected CommandSender sender; + protected QueryParams params; + protected Connection conn = null; + protected Statement state = null; + protected ResultSet rs = null; - protected AbstractCommand(CommandSender sender, QueryParams params, boolean async) throws Exception { - this.sender = sender; - this.params = params; - if (async) { - if (scheduler.scheduleAsyncDelayedTask(logblock, this) == -1) - throw new Exception("Failed to schedule the command"); - } else - run(); - } + protected AbstractCommand(CommandSender sender, QueryParams params, boolean async) throws Exception { + this.sender = sender; + this.params = params; + if (async) { + if (scheduler.scheduleAsyncDelayedTask(logblock, this) == -1) { + throw new Exception("Failed to schedule the command"); + } + } else { + run(); + } + } - @Override - public final void close() { - try { - if (conn != null) - conn.close(); - if (state != null) - state.close(); - if (rs != null) - rs.close(); - } catch (final SQLException ex) { - getLogger().log(Level.SEVERE, "[CommandsHandler] SQL exception on close", ex); - } - } - } + @Override + public final void close() { + try { + if (conn != null) { + conn.close(); + } + if (state != null) { + state.close(); + } + if (rs != null) { + rs.close(); + } + } catch (final SQLException ex) { + getLogger().log(Level.SEVERE, "[CommandsHandler] SQL exception on close", ex); + } + } + } - public class CommandLookup extends AbstractCommand - { - public CommandLookup(CommandSender sender, QueryParams params, boolean async) throws Exception { - super(sender, params, async); - } + public class CommandLookup extends AbstractCommand { + public CommandLookup(CommandSender sender, QueryParams params, boolean async) throws Exception { + super(sender, params, async); + } - @Override - public void run() { - try { - if (params.bct == BlockChangeType.CHAT) { - params.needDate = true; - params.needPlayer = true; - params.needMessage = true; - } else if (params.bct == BlockChangeType.KILLS) { - params.needDate = true; - params.needPlayer = true; - params.needKiller = true; - params.needVictim = true; - params.needWeapon = true; - } else { - params.needDate = true; - params.needType = true; - params.needData = true; - params.needPlayer = true; - if (params.types.isEmpty() || Block.inList(params.types, 63) || Block.inList(params.types, 68)) - params.needSignText = true; - if (params.bct == BlockChangeType.CHESTACCESS || params.bct == BlockChangeType.ALL) - params.needChestAccess = true; - } - conn = logblock.getConnection(); - if (conn == null) { - sender.sendMessage(ChatColor.RED + "MySQL connection lost"); - return; - } - state = conn.createStatement(); - rs = executeQuery(state, params.getQuery()); - sender.sendMessage(ChatColor.DARK_AQUA + params.getTitle() + ":"); - if (rs.next()) { - rs.beforeFirst(); - final List blockchanges = new ArrayList(); - final LookupCacheElementFactory factory = new LookupCacheElementFactory(params, sender instanceof Player ? 2 / 3f : 1); - while (rs.next()) - blockchanges.add(factory.getLookupCacheElement(rs)); - getSession(sender).lookupCache = blockchanges.toArray(new LookupCacheElement[blockchanges.size()]); - if (blockchanges.size() > linesPerPage) - sender.sendMessage(ChatColor.DARK_AQUA.toString() + blockchanges.size() + " changes found." + (blockchanges.size() == linesLimit ? " Use 'limit -1' to see all changes." : "")); - if (params.sum != SummarizationMode.NONE) - if (params.bct == BlockChangeType.KILLS && params.sum == SummarizationMode.PLAYERS) - sender.sendMessage(ChatColor.GOLD + "Kills - Killed - Player"); - else - sender.sendMessage(ChatColor.GOLD + "Created - Destroyed - " + (params.sum == SummarizationMode.TYPES ? "Block" : "Player")); - showPage(sender, 1); - } else { - sender.sendMessage(ChatColor.DARK_AQUA + "No results found."); - getSession(sender).lookupCache = null; - } - } catch (final Exception ex) { - sender.sendMessage(ChatColor.RED + "Exception, check error log"); - getLogger().log(Level.SEVERE, "[Lookup] " + params.getQuery() + ": ", ex); - } finally { - close(); - } - } - } + @Override + public void run() { + try { + if (params.bct == BlockChangeType.CHAT) { + params.needDate = true; + params.needPlayer = true; + params.needMessage = true; + } else if (params.bct == BlockChangeType.KILLS) { + params.needDate = true; + params.needPlayer = true; + params.needKiller = true; + params.needVictim = true; + params.needWeapon = true; + } else { + params.needDate = true; + params.needType = true; + params.needData = true; + params.needPlayer = true; + if (params.types.isEmpty() || Block.inList(params.types, 63) || Block.inList(params.types, 68)) { + params.needSignText = true; + } + if (params.bct == BlockChangeType.CHESTACCESS || params.bct == BlockChangeType.ALL) { + params.needChestAccess = true; + } + } + conn = logblock.getConnection(); + if (conn == null) { + sender.sendMessage(ChatColor.RED + "MySQL connection lost"); + return; + } + state = conn.createStatement(); + rs = executeQuery(state, params.getQuery()); + sender.sendMessage(ChatColor.DARK_AQUA + params.getTitle() + ":"); + if (rs.next()) { + rs.beforeFirst(); + final List blockchanges = new ArrayList(); + final LookupCacheElementFactory factory = new LookupCacheElementFactory(params, sender instanceof Player ? 2 / 3f : 1); + while (rs.next()) { + blockchanges.add(factory.getLookupCacheElement(rs)); + } + getSession(sender).lookupCache = blockchanges.toArray(new LookupCacheElement[blockchanges.size()]); + if (blockchanges.size() > linesPerPage) { + sender.sendMessage(ChatColor.DARK_AQUA.toString() + blockchanges.size() + " changes found." + (blockchanges.size() == linesLimit ? " Use 'limit -1' to see all changes." : "")); + } + if (params.sum != SummarizationMode.NONE) { + if (params.bct == BlockChangeType.KILLS && params.sum == SummarizationMode.PLAYERS) { + sender.sendMessage(ChatColor.GOLD + "Kills - Killed - Player"); + } else { + sender.sendMessage(ChatColor.GOLD + "Created - Destroyed - " + (params.sum == SummarizationMode.TYPES ? "Block" : "Player")); + } + } + showPage(sender, 1); + } else { + sender.sendMessage(ChatColor.DARK_AQUA + "No results found."); + getSession(sender).lookupCache = null; + } + } catch (final Exception ex) { + sender.sendMessage(ChatColor.RED + "Exception, check error log"); + getLogger().log(Level.SEVERE, "[Lookup] " + params.getQuery() + ": ", ex); + } finally { + close(); + } + } + } - public class CommandWriteLogFile extends AbstractCommand - { - public CommandWriteLogFile(CommandSender sender, QueryParams params, boolean async) throws Exception { - super(sender, params, async); - } + public class CommandWriteLogFile extends AbstractCommand { + public CommandWriteLogFile(CommandSender sender, QueryParams params, boolean async) throws Exception { + super(sender, params, async); + } - @Override - public void run() { - File file = null; - try { - if (params.bct == BlockChangeType.CHAT) { - params.needDate = true; - params.needPlayer = true; - params.needMessage = true; - } else { - params.needDate = true; - params.needType = true; - params.needData = true; - params.needPlayer = true; - if (params.types.isEmpty() || Block.inList(params.types, 63) || Block.inList(params.types, 68)) - params.needSignText = true; - if (params.bct == BlockChangeType.CHESTACCESS || params.bct == BlockChangeType.ALL) - params.needChestAccess = true; - } - conn = logblock.getConnection(); - if (conn == null) { - sender.sendMessage(ChatColor.RED + "MySQL connection lost"); - return; - } - state = conn.createStatement(); - file = new File("plugins/LogBlock/log/" + params.getTitle().replace(":", ".") + ".log"); - sender.sendMessage(ChatColor.GREEN + "Creating " + file.getName()); - rs = executeQuery(state, params.getQuery()); - file.getParentFile().mkdirs(); - file.createNewFile(); - final FileWriter writer = new FileWriter(file); - final String newline = System.getProperty("line.separator"); - file.getParentFile().mkdirs(); - int counter = 0; - if (params.sum != SummarizationMode.NONE) - writer.write("Created - Destroyed - " + (params.sum == SummarizationMode.TYPES ? "Block" : "Player") + newline); - final LookupCacheElementFactory factory = new LookupCacheElementFactory(params, sender instanceof Player ? 2 / 3f : 1); - while (rs.next()) { - writer.write(factory.getLookupCacheElement(rs).getMessage() + newline); - counter++; - } - writer.close(); - sender.sendMessage(ChatColor.GREEN + "Wrote " + counter + " lines."); - } catch (final Exception ex) { - sender.sendMessage(ChatColor.RED + "Exception, check error log"); - getLogger().log(Level.SEVERE, "[WriteLogFile] " + params.getQuery() + " (file was " + file.getAbsolutePath() + "): ", ex); - } finally { - close(); - } - } - } + @Override + public void run() { + File file = null; + try { + if (params.bct == BlockChangeType.CHAT) { + params.needDate = true; + params.needPlayer = true; + params.needMessage = true; + } else { + params.needDate = true; + params.needType = true; + params.needData = true; + params.needPlayer = true; + if (params.types.isEmpty() || Block.inList(params.types, 63) || Block.inList(params.types, 68)) { + params.needSignText = true; + } + if (params.bct == BlockChangeType.CHESTACCESS || params.bct == BlockChangeType.ALL) { + params.needChestAccess = true; + } + } + conn = logblock.getConnection(); + if (conn == null) { + sender.sendMessage(ChatColor.RED + "MySQL connection lost"); + return; + } + state = conn.createStatement(); + file = new File("plugins/LogBlock/log/" + params.getTitle().replace(":", ".") + ".log"); + sender.sendMessage(ChatColor.GREEN + "Creating " + file.getName()); + rs = executeQuery(state, params.getQuery()); + file.getParentFile().mkdirs(); + file.createNewFile(); + final FileWriter writer = new FileWriter(file); + final String newline = System.getProperty("line.separator"); + file.getParentFile().mkdirs(); + int counter = 0; + if (params.sum != SummarizationMode.NONE) { + writer.write("Created - Destroyed - " + (params.sum == SummarizationMode.TYPES ? "Block" : "Player") + newline); + } + final LookupCacheElementFactory factory = new LookupCacheElementFactory(params, sender instanceof Player ? 2 / 3f : 1); + while (rs.next()) { + writer.write(factory.getLookupCacheElement(rs).getMessage() + newline); + counter++; + } + writer.close(); + sender.sendMessage(ChatColor.GREEN + "Wrote " + counter + " lines."); + } catch (final Exception ex) { + sender.sendMessage(ChatColor.RED + "Exception, check error log"); + getLogger().log(Level.SEVERE, "[WriteLogFile] " + params.getQuery() + " (file was " + file.getAbsolutePath() + "): ", ex); + } finally { + close(); + } + } + } - public class CommandSaveQueue extends AbstractCommand - { - public CommandSaveQueue(CommandSender sender, QueryParams params, boolean async) throws Exception { - super(sender, params, async); - } + public class CommandSaveQueue extends AbstractCommand { + public CommandSaveQueue(CommandSender sender, QueryParams params, boolean async) throws Exception { + super(sender, params, async); + } - @Override - public void run() { - final Consumer consumer = logblock.getConsumer(); - if (consumer.getQueueSize() > 0) { - sender.sendMessage(ChatColor.DARK_AQUA + "Current queue size: " + consumer.getQueueSize()); - int lastSize = -1, fails = 0; - while (consumer.getQueueSize() > 0) { - fails = lastSize == consumer.getQueueSize() ? fails + 1 : 0; - if (fails > 10) { - sender.sendMessage(ChatColor.RED + "Unable to save queue"); - return; - } - lastSize = consumer.getQueueSize(); - consumer.run(); - } - sender.sendMessage(ChatColor.GREEN + "Queue saved successfully"); - } - } - } + @Override + public void run() { + final Consumer consumer = logblock.getConsumer(); + if (consumer.getQueueSize() > 0) { + sender.sendMessage(ChatColor.DARK_AQUA + "Current queue size: " + consumer.getQueueSize()); + int lastSize = -1, fails = 0; + while (consumer.getQueueSize() > 0) { + fails = lastSize == consumer.getQueueSize() ? fails + 1 : 0; + if (fails > 10) { + sender.sendMessage(ChatColor.RED + "Unable to save queue"); + return; + } + lastSize = consumer.getQueueSize(); + consumer.run(); + } + sender.sendMessage(ChatColor.GREEN + "Queue saved successfully"); + } + } + } - public class CommandTeleport extends AbstractCommand - { - public CommandTeleport(CommandSender sender, QueryParams params, boolean async) throws Exception { - super(sender, params, async); - } + public class CommandTeleport extends AbstractCommand { + public CommandTeleport(CommandSender sender, QueryParams params, boolean async) throws Exception { + super(sender, params, async); + } - @Override - public void run() { - try { - params.needCoords = true; - if (params.bct == BlockChangeType.CHESTACCESS || params.bct == BlockChangeType.ALL) - params.needChestAccess = true; - params.limit = 1; - params.sum = SummarizationMode.NONE; - conn = logblock.getConnection(); - if (conn == null) { - sender.sendMessage(ChatColor.RED + "MySQL connection lost"); - return; - } - state = conn.createStatement(); - rs = executeQuery(state, params.getQuery()); - if (rs.next()) { - final Player player = (Player)sender; - final int y = rs.getInt("y"); - final Location loc = new Location(params.world, rs.getInt("x") + 0.5, y, rs.getInt("z") + 0.5, player.getLocation().getYaw(), 90); + @Override + public void run() { + try { + params.needCoords = true; + if (params.bct == BlockChangeType.CHESTACCESS || params.bct == BlockChangeType.ALL) { + params.needChestAccess = true; + } + params.limit = 1; + params.sum = SummarizationMode.NONE; + conn = logblock.getConnection(); + if (conn == null) { + sender.sendMessage(ChatColor.RED + "MySQL connection lost"); + return; + } + state = conn.createStatement(); + rs = executeQuery(state, params.getQuery()); + if (rs.next()) { + final Player player = (Player) sender; + final int y = rs.getInt("y"); + final Location loc = new Location(params.world, rs.getInt("x") + 0.5, y, rs.getInt("z") + 0.5, player.getLocation().getYaw(), 90); - // Teleport the player sync because omg thread safety - logblock.getServer().getScheduler().scheduleSyncDelayedTask(logblock, new Runnable() { - @Override - public void run() { - final int y2 = saveSpawnHeight(loc); - loc.setY(y2); - player.teleport(loc); - sender.sendMessage(ChatColor.GREEN + "You were teleported " + Math.abs(y2 - y) + " blocks " + (y2 - y > 0 ? "above" : "below")); - } - }); - } else - sender.sendMessage(ChatColor.RED + "No block change found to teleport to"); - } catch (final Exception ex) { - sender.sendMessage(ChatColor.RED + "Exception, check error log"); - getLogger().log(Level.SEVERE, "[Teleport] " + params.getQuery() + ": ", ex); - } finally { - close(); - } - } - } + // Teleport the player sync because omg thread safety + logblock.getServer().getScheduler().scheduleSyncDelayedTask(logblock, new Runnable() { + @Override + public void run() { + final int y2 = saveSpawnHeight(loc); + loc.setY(y2); + player.teleport(loc); + sender.sendMessage(ChatColor.GREEN + "You were teleported " + Math.abs(y2 - y) + " blocks " + (y2 - y > 0 ? "above" : "below")); + } + }); + } else { + sender.sendMessage(ChatColor.RED + "No block change found to teleport to"); + } + } catch (final Exception ex) { + sender.sendMessage(ChatColor.RED + "Exception, check error log"); + getLogger().log(Level.SEVERE, "[Teleport] " + params.getQuery() + ": ", ex); + } finally { + close(); + } + } + } - public class CommandRollback extends AbstractCommand - { - public CommandRollback(CommandSender sender, QueryParams params, boolean async) throws Exception { - super(sender, params, async); - } + public class CommandRollback extends AbstractCommand { + public CommandRollback(CommandSender sender, QueryParams params, boolean async) throws Exception { + super(sender, params, async); + } - @Override - public void run() { - try { - params.needCoords = true; - params.needType = true; - params.needData = true; - params.needSignText = true; - params.needChestAccess = true; - params.order = Order.DESC; - params.sum = SummarizationMode.NONE; - conn = logblock.getConnection(); - if (conn == null) { - sender.sendMessage(ChatColor.RED + "MySQL connection lost"); - return; - } - state = conn.createStatement(); - if (!checkRestrictions(sender, params)) - return; - if (logblock.getConsumer().getQueueSize() > 0) - new CommandSaveQueue(sender, null, false); - if (!params.silent) - sender.sendMessage(ChatColor.DARK_AQUA + "Searching " + params.getTitle() + ":"); - rs = executeQuery(state, params.getQuery()); + @Override + public void run() { + try { + params.needCoords = true; + params.needType = true; + params.needData = true; + params.needSignText = true; + params.needChestAccess = true; + params.order = Order.DESC; + params.sum = SummarizationMode.NONE; + conn = logblock.getConnection(); + if (conn == null) { + sender.sendMessage(ChatColor.RED + "MySQL connection lost"); + return; + } + state = conn.createStatement(); + if (!checkRestrictions(sender, params)) { + return; + } + if (logblock.getConsumer().getQueueSize() > 0) { + new CommandSaveQueue(sender, null, false); + } + if (!params.silent) { + sender.sendMessage(ChatColor.DARK_AQUA + "Searching " + params.getTitle() + ":"); + } + rs = executeQuery(state, params.getQuery()); final WorldEditor editor = new WorldEditor(logblock, params.world); - while (rs.next()) - editor.queueEdit(rs.getInt("x"), rs.getInt("y"), rs.getInt("z"), rs.getInt("replaced"), rs.getInt("type"), rs.getByte("data"), rs.getString("signtext"), rs.getShort("itemtype"), rs.getShort("itemamount"), rs.getShort("itemdata")); - final int changes = editor.getSize(); + while (rs.next()) { + editor.queueEdit(rs.getInt("x"), rs.getInt("y"), rs.getInt("z"), rs.getInt("replaced"), rs.getInt("type"), rs.getByte("data"), rs.getString("signtext"), rs.getShort("itemtype"), rs.getShort("itemamount"), rs.getShort("itemdata")); + } + final int changes = editor.getSize(); if (changes > 10000) { editor.setSender(sender); } - if (!params.silent) - sender.sendMessage(ChatColor.GREEN.toString() + changes + " blocks found."); - if (changes == 0) { - if (!params.silent) - sender.sendMessage(ChatColor.RED + "Rollback aborted"); - return; - } - if (!params.silent && askRollbacks && questioner != null && sender instanceof Player && !questioner.ask((Player)sender, "Are you sure you want to continue?", "yes", "no").equals("yes")) { - sender.sendMessage(ChatColor.RED + "Rollback aborted"); - return; - } - editor.start(); - getSession(sender).lookupCache = editor.errors; - sender.sendMessage(ChatColor.GREEN + "Rollback finished successfully (" + editor.getElapsedTime() + " ms, " + editor.getSuccesses() + "/" + changes + " blocks" + (editor.getErrors() > 0 ? ", " + ChatColor.RED + editor.getErrors() + " errors" + ChatColor.GREEN : "") + (editor.getBlacklistCollisions() > 0 ? ", " + editor.getBlacklistCollisions() + " blacklist collisions" : "") + ")"); - if (!params.silent && askClearLogAfterRollback && logblock.hasPermission(sender, "logblock.clearlog") && questioner != null && sender instanceof Player) { - Thread.sleep(1000); - if (questioner.ask((Player)sender, "Do you want to delete the rollbacked log?", "yes", "no").equals("yes")) { - params.silent = true; - new CommandClearLog(sender, params, false); - } else - sender.sendMessage(ChatColor.LIGHT_PURPLE + "Clearlog cancelled"); - } - } catch (final Exception ex) { - sender.sendMessage(ChatColor.RED + "Exception, check error log"); - getLogger().log(Level.SEVERE, "[Rollback] " + params.getQuery() + ": ", ex); - } finally { - close(); - } - } - } + if (!params.silent) { + sender.sendMessage(ChatColor.GREEN.toString() + changes + " blocks found."); + } + if (changes == 0) { + if (!params.silent) { + sender.sendMessage(ChatColor.RED + "Rollback aborted"); + } + return; + } + if (!params.silent && askRollbacks && questioner != null && sender instanceof Player && !questioner.ask((Player) sender, "Are you sure you want to continue?", "yes", "no").equals("yes")) { + sender.sendMessage(ChatColor.RED + "Rollback aborted"); + return; + } + editor.start(); + getSession(sender).lookupCache = editor.errors; + sender.sendMessage(ChatColor.GREEN + "Rollback finished successfully (" + editor.getElapsedTime() + " ms, " + editor.getSuccesses() + "/" + changes + " blocks" + (editor.getErrors() > 0 ? ", " + ChatColor.RED + editor.getErrors() + " errors" + ChatColor.GREEN : "") + (editor.getBlacklistCollisions() > 0 ? ", " + editor.getBlacklistCollisions() + " blacklist collisions" : "") + ")"); + if (!params.silent && askClearLogAfterRollback && logblock.hasPermission(sender, "logblock.clearlog") && questioner != null && sender instanceof Player) { + Thread.sleep(1000); + if (questioner.ask((Player) sender, "Do you want to delete the rollbacked log?", "yes", "no").equals("yes")) { + params.silent = true; + new CommandClearLog(sender, params, false); + } else { + sender.sendMessage(ChatColor.LIGHT_PURPLE + "Clearlog cancelled"); + } + } + } catch (final Exception ex) { + sender.sendMessage(ChatColor.RED + "Exception, check error log"); + getLogger().log(Level.SEVERE, "[Rollback] " + params.getQuery() + ": ", ex); + } finally { + close(); + } + } + } - public class CommandRedo extends AbstractCommand - { - public CommandRedo(CommandSender sender, QueryParams params, boolean async) throws Exception { - super(sender, params, async); - } + public class CommandRedo extends AbstractCommand { + public CommandRedo(CommandSender sender, QueryParams params, boolean async) throws Exception { + super(sender, params, async); + } - @Override - public void run() { - try { - params.needCoords = true; - params.needType = true; - params.needData = true; - params.needSignText = true; - params.needChestAccess = true; - params.order = Order.ASC; - params.sum = SummarizationMode.NONE; - conn = logblock.getConnection(); - if (conn == null) { - sender.sendMessage(ChatColor.RED + "MySQL connection lost"); - return; - } - state = conn.createStatement(); - if (!checkRestrictions(sender, params)) - return; - rs = executeQuery(state, params.getQuery()); - if (!params.silent) - sender.sendMessage(ChatColor.DARK_AQUA + "Searching " + params.getTitle() + ":"); - final WorldEditor editor = new WorldEditor(logblock, params.world); - while (rs.next()) - editor.queueEdit(rs.getInt("x"), rs.getInt("y"), rs.getInt("z"), rs.getInt("type"), rs.getInt("replaced"), rs.getByte("data"), rs.getString("signtext"), rs.getShort("itemtype"), (short)-rs.getShort("itemamount"), rs.getShort("itemdata")); - final int changes = editor.getSize(); - if (!params.silent) - sender.sendMessage(ChatColor.GREEN.toString() + changes + " blocks found."); - if (changes == 0) { - if (!params.silent) - sender.sendMessage(ChatColor.RED + "Redo aborted"); - return; - } - if (!params.silent && askRedos && questioner != null && sender instanceof Player && !questioner.ask((Player)sender, "Are you sure you want to continue?", "yes", "no").equals("yes")) { - sender.sendMessage(ChatColor.RED + "Redo aborted"); - return; - } - editor.start(); - sender.sendMessage(ChatColor.GREEN + "Redo finished successfully (" + editor.getElapsedTime() + " ms, " + editor.getSuccesses() + "/" + changes + " blocks" + (editor.getErrors() > 0 ? ", " + ChatColor.RED + editor.getErrors() + " errors" + ChatColor.GREEN : "") + (editor.getBlacklistCollisions() > 0 ? ", " + editor.getBlacklistCollisions() + " blacklist collisions" : "") + ")"); - } catch (final Exception ex) { - sender.sendMessage(ChatColor.RED + "Exception, check error log"); - getLogger().log(Level.SEVERE, "[Redo] " + params.getQuery() + ": ", ex); - } finally { - close(); - } - } - } + @Override + public void run() { + try { + params.needCoords = true; + params.needType = true; + params.needData = true; + params.needSignText = true; + params.needChestAccess = true; + params.order = Order.ASC; + params.sum = SummarizationMode.NONE; + conn = logblock.getConnection(); + if (conn == null) { + sender.sendMessage(ChatColor.RED + "MySQL connection lost"); + return; + } + state = conn.createStatement(); + if (!checkRestrictions(sender, params)) { + return; + } + rs = executeQuery(state, params.getQuery()); + if (!params.silent) { + sender.sendMessage(ChatColor.DARK_AQUA + "Searching " + params.getTitle() + ":"); + } + final WorldEditor editor = new WorldEditor(logblock, params.world); + while (rs.next()) { + editor.queueEdit(rs.getInt("x"), rs.getInt("y"), rs.getInt("z"), rs.getInt("type"), rs.getInt("replaced"), rs.getByte("data"), rs.getString("signtext"), rs.getShort("itemtype"), (short) -rs.getShort("itemamount"), rs.getShort("itemdata")); + } + final int changes = editor.getSize(); + if (!params.silent) { + sender.sendMessage(ChatColor.GREEN.toString() + changes + " blocks found."); + } + if (changes == 0) { + if (!params.silent) { + sender.sendMessage(ChatColor.RED + "Redo aborted"); + } + return; + } + if (!params.silent && askRedos && questioner != null && sender instanceof Player && !questioner.ask((Player) sender, "Are you sure you want to continue?", "yes", "no").equals("yes")) { + sender.sendMessage(ChatColor.RED + "Redo aborted"); + return; + } + editor.start(); + sender.sendMessage(ChatColor.GREEN + "Redo finished successfully (" + editor.getElapsedTime() + " ms, " + editor.getSuccesses() + "/" + changes + " blocks" + (editor.getErrors() > 0 ? ", " + ChatColor.RED + editor.getErrors() + " errors" + ChatColor.GREEN : "") + (editor.getBlacklistCollisions() > 0 ? ", " + editor.getBlacklistCollisions() + " blacklist collisions" : "") + ")"); + } catch (final Exception ex) { + sender.sendMessage(ChatColor.RED + "Exception, check error log"); + getLogger().log(Level.SEVERE, "[Redo] " + params.getQuery() + ": ", ex); + } finally { + close(); + } + } + } - public class CommandClearLog extends AbstractCommand - { - public CommandClearLog(CommandSender sender, QueryParams params, boolean async) throws Exception { - super(sender, params, async); - } + public class CommandClearLog extends AbstractCommand { + public CommandClearLog(CommandSender sender, QueryParams params, boolean async) throws Exception { + super(sender, params, async); + } - @Override - public void run() { - try { - conn = logblock.getConnection(); - state = conn.createStatement(); - if (conn == null) { - sender.sendMessage(ChatColor.RED + "MySQL connection lost"); - return; - } - if (!checkRestrictions(sender, params)) - return; - final File dumpFolder = new File(logblock.getDataFolder(), "dump"); - if (!dumpFolder.exists()) - dumpFolder.mkdirs(); - final String time = new SimpleDateFormat("yyMMddHHmmss").format(System.currentTimeMillis()); - int deleted; - final String table = params.getTable(); - final String join = params.players.size() > 0 ? "INNER JOIN `lb-players` USING (playerid) " : ""; - rs = state.executeQuery("SELECT count(*) FROM `" + table + "` " + join + params.getWhere()); - rs.next(); - if ((deleted = rs.getInt(1)) > 0) { - if (!params.silent && askClearLogs && sender instanceof Player && questioner != null) { - sender.sendMessage(ChatColor.DARK_AQUA + "Searching " + params.getTitle() + ":"); - sender.sendMessage(ChatColor.GREEN.toString() + deleted + " blocks found."); - if (!questioner.ask((Player)sender, "Are you sure you want to continue?", "yes", "no").equals("yes")) { - sender.sendMessage(ChatColor.RED + "ClearLog aborted"); - return; - } - } - if (dumpDeletedLog) - try { - state.execute("SELECT * FROM `" + table + "` " + join + params.getWhere() + "INTO OUTFILE '" + new File(dumpFolder, time + " " + table + " " + params.getTitle().replace(":", ".") + ".csv").getAbsolutePath().replace("\\", "\\\\") + "' FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '\"' LINES TERMINATED BY '\n'"); - } 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"); - getLogger().log(Level.SEVERE, "[ClearLog] Exception while dumping log: ", ex); - return; - } - state.execute("DELETE `" + table + "` FROM `" + table + "` " + join + params.getWhere()); - 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.next(); - if ((deleted = rs.getInt(1)) > 0) { - if (dumpDeletedLog) - state.execute("SELECT id, signtext FROM `" + table + "-sign` LEFT JOIN `" + table + "` USING (id) WHERE `" + table + "`.id IS NULL INTO OUTFILE '" + new File(dumpFolder, time + " " + table + "-sign " + params.getTitle() + ".csv").getAbsolutePath().replace("\\", "\\\\") + "' FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '\"' LINES TERMINATED BY '\n'"); - state.execute("DELETE `" + table + "-sign` FROM `" + table + "-sign` LEFT JOIN `" + table + "` USING (id) WHERE `" + table + "`.id IS NULL;"); - sender.sendMessage(ChatColor.GREEN + "Cleared out table " + table + "-sign. Deleted " + deleted + " entries."); - } - rs = state.executeQuery("SELECT COUNT(*) FROM `" + table + "-chest` LEFT JOIN `" + table + "` USING (id) WHERE `" + table + "`.id IS NULL"); - rs.next(); - if ((deleted = rs.getInt(1)) > 0) { - if (dumpDeletedLog) - state.execute("SELECT id, itemtype, itemamount, itemdata FROM `" + table + "-chest` LEFT JOIN `" + table + "` USING (id) WHERE `" + table + "`.id IS NULL INTO OUTFILE '" + new File(dumpFolder, time + " " + table + "-chest " + params.getTitle() + ".csv").getAbsolutePath().replace("\\", "\\\\") + "' FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '\"' LINES TERMINATED BY '\n'"); - state.execute("DELETE `" + table + "-chest` FROM `" + table + "-chest` LEFT JOIN `" + table + "` USING (id) WHERE `" + table + "`.id IS NULL;"); - sender.sendMessage(ChatColor.GREEN + "Cleared out table " + table + "-chest. Deleted " + deleted + " entries."); - } - } catch (final Exception ex) { - sender.sendMessage(ChatColor.RED + "Exception, check error log"); - getLogger().log(Level.SEVERE, "[ClearLog] Exception: ", ex); - } finally { - close(); - } - } - } + @Override + public void run() { + try { + conn = logblock.getConnection(); + state = conn.createStatement(); + if (conn == null) { + sender.sendMessage(ChatColor.RED + "MySQL connection lost"); + return; + } + if (!checkRestrictions(sender, params)) { + return; + } + final File dumpFolder = new File(logblock.getDataFolder(), "dump"); + if (!dumpFolder.exists()) { + dumpFolder.mkdirs(); + } + final String time = new SimpleDateFormat("yyMMddHHmmss").format(System.currentTimeMillis()); + int deleted; + final String table = params.getTable(); + final String join = params.players.size() > 0 ? "INNER JOIN `lb-players` USING (playerid) " : ""; + rs = state.executeQuery("SELECT count(*) FROM `" + table + "` " + join + params.getWhere()); + rs.next(); + if ((deleted = rs.getInt(1)) > 0) { + if (!params.silent && askClearLogs && sender instanceof Player && questioner != null) { + sender.sendMessage(ChatColor.DARK_AQUA + "Searching " + params.getTitle() + ":"); + sender.sendMessage(ChatColor.GREEN.toString() + deleted + " blocks found."); + if (!questioner.ask((Player) sender, "Are you sure you want to continue?", "yes", "no").equals("yes")) { + sender.sendMessage(ChatColor.RED + "ClearLog aborted"); + return; + } + } + if (dumpDeletedLog) { + try { + state.execute("SELECT * FROM `" + table + "` " + join + params.getWhere() + "INTO OUTFILE '" + new File(dumpFolder, time + " " + table + " " + params.getTitle().replace(":", ".") + ".csv").getAbsolutePath().replace("\\", "\\\\") + "' FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '\"' LINES TERMINATED BY '\n'"); + } 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"); + getLogger().log(Level.SEVERE, "[ClearLog] Exception while dumping log: ", ex); + return; + } + } + state.execute("DELETE `" + table + "` FROM `" + table + "` " + join + params.getWhere()); + 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.next(); + if ((deleted = rs.getInt(1)) > 0) { + if (dumpDeletedLog) { + state.execute("SELECT id, signtext FROM `" + table + "-sign` LEFT JOIN `" + table + "` USING (id) WHERE `" + table + "`.id IS NULL INTO OUTFILE '" + new File(dumpFolder, time + " " + table + "-sign " + params.getTitle() + ".csv").getAbsolutePath().replace("\\", "\\\\") + "' FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '\"' LINES TERMINATED BY '\n'"); + } + state.execute("DELETE `" + table + "-sign` FROM `" + table + "-sign` LEFT JOIN `" + table + "` USING (id) WHERE `" + table + "`.id IS NULL;"); + sender.sendMessage(ChatColor.GREEN + "Cleared out table " + table + "-sign. Deleted " + deleted + " entries."); + } + rs = state.executeQuery("SELECT COUNT(*) FROM `" + table + "-chest` LEFT JOIN `" + table + "` USING (id) WHERE `" + table + "`.id IS NULL"); + rs.next(); + if ((deleted = rs.getInt(1)) > 0) { + if (dumpDeletedLog) { + state.execute("SELECT id, itemtype, itemamount, itemdata FROM `" + table + "-chest` LEFT JOIN `" + table + "` USING (id) WHERE `" + table + "`.id IS NULL INTO OUTFILE '" + new File(dumpFolder, time + " " + table + "-chest " + params.getTitle() + ".csv").getAbsolutePath().replace("\\", "\\\\") + "' FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '\"' LINES TERMINATED BY '\n'"); + } + state.execute("DELETE `" + table + "-chest` FROM `" + table + "-chest` LEFT JOIN `" + table + "` USING (id) WHERE `" + table + "`.id IS NULL;"); + sender.sendMessage(ChatColor.GREEN + "Cleared out table " + table + "-chest. Deleted " + deleted + " entries."); + } + } catch (final Exception ex) { + sender.sendMessage(ChatColor.RED + "Exception, check error log"); + getLogger().log(Level.SEVERE, "[ClearLog] Exception: ", ex); + } finally { + close(); + } + } + } - private static ResultSet executeQuery(Statement state, String query) throws SQLException { - if (Config.debug) { - long startTime = System.currentTimeMillis(); - ResultSet rs = state.executeQuery(query); - getLogger().log(Level.INFO, "[LogBlock Debug] Time Taken: " + (System.currentTimeMillis() - startTime) + " milliseconds. Query: " + query ); - return rs; - } else { - return state.executeQuery(query); - } - } + private static ResultSet executeQuery(Statement state, String query) throws SQLException { + if (Config.debug) { + long startTime = System.currentTimeMillis(); + ResultSet rs = state.executeQuery(query); + getLogger().log(Level.INFO, "[LogBlock Debug] Time Taken: " + (System.currentTimeMillis() - startTime) + " milliseconds. Query: " + query); + return rs; + } else { + return state.executeQuery(query); + } + } - private static List argsToList(String[] arr, int offset) { - final List list = new ArrayList(Arrays.asList(arr)); - for (int i = 0; i < offset; i++) - list.remove(0); - return list; - } + private static List argsToList(String[] arr, int offset) { + final List list = new ArrayList(Arrays.asList(arr)); + for (int i = 0; i < offset; i++) { + list.remove(0); + } + return list; + } } diff --git a/src/main/java/de/diddiz/LogBlock/Consumer.java b/src/main/java/de/diddiz/LogBlock/Consumer.java index 579f1d5..729b1b8 100644 --- a/src/main/java/de/diddiz/LogBlock/Consumer.java +++ b/src/main/java/de/diddiz/LogBlock/Consumer.java @@ -12,6 +12,7 @@ import org.bukkit.entity.Projectile; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.InventoryHolder; import org.bukkit.inventory.ItemStack; +import org.bukkit.projectiles.ProjectileSource; import java.io.File; import java.io.FileNotFoundException; @@ -26,859 +27,863 @@ import java.util.logging.Level; import static de.diddiz.LogBlock.config.Config.*; import static de.diddiz.util.BukkitUtils.*; import static org.bukkit.Bukkit.getLogger; -import org.bukkit.projectiles.ProjectileSource; - -public class Consumer extends TimerTask -{ - private final Queue queue = new LinkedBlockingQueue(); - private final Set failedPlayers = new HashSet(); - private final LogBlock logblock; - private final Map playerIds = new HashMap(); - private final Lock lock = new ReentrantLock(); - - Consumer(LogBlock logblock) { - this.logblock = logblock; - try { - Class.forName("PlayerLeaveRow"); - } catch (final ClassNotFoundException ex) { - } - } - - /** - * Logs any block change. Don't try to combine broken and placed blocks. Queue two block changes or use the queueBLockReplace methods. - */ - public void queueBlock(Actor actor, Location loc, int typeBefore, int typeAfter, byte data) { - queueBlock(actor, loc, typeBefore, typeAfter, data, null, null); - } - - /** - * Logs a block break. The type afterwards is assumed to be o (air). - * - * @param before - * Blockstate of the block before actually being destroyed. - */ - public void queueBlockBreak(Actor actor, BlockState before) { - queueBlockBreak(actor, new Location(before.getWorld(), before.getX(), before.getY(), before.getZ()), before.getTypeId(), before.getRawData()); - } - - /** - * Logs a block break. The block type afterwards is assumed to be o (air). - */ - public void queueBlockBreak(Actor actor, Location loc, int typeBefore, byte dataBefore) { - queueBlock(actor, loc, typeBefore, 0, dataBefore); - } - - /** - * Logs a block place. The block type before is assumed to be o (air). - * - * @param after - * Blockstate of the block after actually being placed. - */ - public void queueBlockPlace(Actor actor, BlockState after) { - queueBlockPlace(actor, new Location(after.getWorld(), after.getX(), after.getY(), after.getZ()), after.getBlock().getTypeId(), after.getBlock().getData()); - } - - /** - * Logs a block place. The block type before is assumed to be o (air). - */ - public void queueBlockPlace(Actor actor, Location loc, int type, byte data) { - queueBlock(actor, loc, 0, type, data); - } - - /** - * @param before - * Blockstate of the block before actually being destroyed. - * @param after - * Blockstate of the block after actually being placed. - */ - public void queueBlockReplace(Actor actor, BlockState before, BlockState after) { - queueBlockReplace(actor, new Location(before.getWorld(), before.getX(), before.getY(), before.getZ()), before.getTypeId(), before.getRawData(), after.getTypeId(), after.getRawData()); - } - - /** - * @param before - * Blockstate of the block before actually being destroyed. - */ - public void queueBlockReplace(Actor actor, BlockState before, int typeAfter, byte dataAfter) { - queueBlockReplace(actor, new Location(before.getWorld(), before.getX(), before.getY(), before.getZ()), before.getTypeId(), before.getRawData(), typeAfter, dataAfter); - } - - /** - * @param after - * Blockstate of the block after actually being placed. - */ - public void queueBlockReplace(Actor actor, int typeBefore, byte dataBefore, BlockState after) { - queueBlockReplace(actor, new Location(after.getWorld(), after.getX(), after.getY(), after.getZ()), typeBefore, dataBefore, after.getTypeId(), after.getRawData()); - } - - public void queueBlockReplace(Actor actor, Location loc, int typeBefore, byte dataBefore, int typeAfter, byte dataAfter) { - if (dataBefore == 0 && (typeBefore != typeAfter)) - queueBlock(actor, loc, typeBefore, typeAfter, dataAfter); - else { - queueBlockBreak(actor, loc, typeBefore, dataBefore); - queueBlockPlace(actor, loc, typeAfter, dataAfter); - } - } - - /** - * @param container - * The respective container. Must be an instance of an InventoryHolder. - */ - public void queueChestAccess(Actor actor, BlockState container, short itemType, short itemAmount, short itemData) { - if (!(container instanceof InventoryHolder)) - return; - queueChestAccess(actor, new Location(container.getWorld(), container.getX(), container.getY(), container.getZ()), container.getTypeId(), itemType, itemAmount, itemData); - } - - /** - * @param type - * Type id of the container. - */ - public void queueChestAccess(Actor actor, Location loc, int type, short itemType, short itemAmount, short itemData) { - queueBlock(actor, loc, type, type, (byte)0, null, new ChestAccess(itemType, itemAmount, itemData)); - } - - /** - * 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 an instance of InventoryHolder - */ - public void queueContainerBreak(Actor actor, BlockState container) { - if (!(container instanceof InventoryHolder)) - return; - queueContainerBreak(actor, new Location(container.getWorld(), container.getX(), container.getY(), container.getZ()), container.getTypeId(), container.getRawData(), ((InventoryHolder)container).getInventory()); - } - - /** - * 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(Actor actor, Location loc, int type, byte data, Inventory inv) { - final ItemStack[] items = compressInventory(inv.getContents()); - for (final ItemStack item : items) - queueChestAccess(actor, loc, type, (short)item.getTypeId(), (short)(item.getAmount() * -1), rawData(item)); - queueBlockBreak(actor, loc, type, data); - } - - /** - * @param killer - * Can't be null - * @param victim - * Can't be null - */ - public void queueKill(Entity killer, Entity victim) { - if (killer == null || victim == null) - return; - int weapon = 0; - Actor killerActor = Actor.actorFromEntity(killer); - // If it's a projectile kill we want to manually assign the weapon, so check for player before converting a projectile to its source - if (killer instanceof Player && ((Player)killer).getItemInHand() != null) - weapon = ((Player)killer).getItemInHand().getTypeId(); - if(killer instanceof Projectile) { - ProjectileSource ps = ((Projectile)killer).getShooter(); - killerActor = Actor.actorFromProjectileSource(ps); - weapon = itemIDfromProjectileEntity(killer); - } - - queueKill(victim.getLocation(), killerActor, Actor.actorFromEntity(victim), weapon); - } - - /** - * This form should only be used when the killer is not an entity e.g. for fall or suffocation damage - * @param killer - * Can't be null - * @param victim - * Can't be null - */ - public void queueKill(Actor killer, Entity victim) { - if (killer == null || victim == null) - return; - queueKill(victim.getLocation(), killer, Actor.actorFromEntity(victim), 0); - } - - /** - * @param world - * World the victim was inside. - * @param killerName - * Name of the killer. Can be null. - * @param victimName - * Name of the victim. Can't be null. - * @param weapon - * Item id of the weapon. 0 for no weapon. - * @deprecated Use {@link #queueKill(Location,String,String,int)} instead - */ - @Deprecated - public void queueKill(World world, Actor killer, Actor victim, int weapon) { - queueKill(new Location(world, 0, 0, 0), killer, victim, weapon); - } - - /** - * @param location - * Location of the victim. - * @param killer - * Killer Actor. Can be null. - * @param victim - * Victim Actor. Can't be null. - * @param weapon - * Item id of the weapon. 0 for no weapon. - */ - public void queueKill(Location location, Actor killer, Actor victim, int weapon) { - if (victim == null || !isLogged(location.getWorld())) - return; - queue.add(new KillRow(location, killer == null ? null : killer, victim, weapon)); - } - - /** - * @param type - * Type of the sign. Must be 63 or 68. - * @param lines - * The four lines on the sign. - */ - public void queueSignBreak(Actor actor, Location loc, int type, byte data, String[] lines) { - if (type != 63 && type != 68 || lines == null || lines.length != 4) - return; - queueBlock(actor, loc, type, 0, data, lines[0] + "\0" + lines[1] + "\0" + lines[2] + "\0" + lines[3], null); - } - - public void queueSignBreak(Actor actor, Sign sign) { - queueSignBreak(actor, new Location(sign.getWorld(), sign.getX(), sign.getY(), sign.getZ()), sign.getTypeId(), sign.getRawData(), sign.getLines()); - } - - /** - * @param type - * Type of the sign. Must be 63 or 68. - * @param lines - * The four lines on the sign. - */ - public void queueSignPlace(Actor actor, Location loc, int type, byte data, String[] lines) { - if (type != 63 && type != 68 || lines == null || lines.length != 4) - return; - queueBlock(actor, loc, 0, type, data, lines[0] + "\0" + lines[1] + "\0" + lines[2] + "\0" + lines[3], null); - } - - public void queueSignPlace(Actor actor, Sign sign) { - queueSignPlace(actor, new Location(sign.getWorld(), sign.getX(), sign.getY(), sign.getZ()), sign.getTypeId(), sign.getRawData(), sign.getLines()); - } - - public void queueChat(Actor player, String message) { - for (String ignored : Config.ignoredChat) { - if (message.startsWith(ignored)) { - return; - } - } - if (hiddenPlayers.contains(player.getName().toLowerCase())) { - return; - } - queue.add(new ChatRow(player, message)); - } - - public void queueJoin(Player player) { - queue.add(new PlayerJoinRow(player)); - } - - public void queueLeave(Player player) { - queue.add(new PlayerLeaveRow(player)); - } - - @Override - public synchronized void run() { - if (queue.isEmpty() || !lock.tryLock()) - return; - long startTime = System.currentTimeMillis(); - int startSize = queue.size(); - - final Connection conn = logblock.getConnection(); - Statement state = null; - if (Config.queueWarningSize > 0 && queue.size() >= Config.queueWarningSize) { - getLogger().info("[Consumer] Queue overloaded. Size: " + getQueueSize()); - } - - int count = 0; - - try { - if (conn == null) - return; - conn.setAutoCommit(false); - state = conn.createStatement(); - final long start = System.currentTimeMillis(); - process: - while (!queue.isEmpty() && (System.currentTimeMillis() - start < timePerRun || count < forceToProcessAtLeast)) { - final Row r = queue.poll(); - if (r == null) - continue; - for (final Actor actor : r.getActors()) { - if (!playerIds.containsKey(actor)) { - if (!addPlayer(state, actor)) { - if (!failedPlayers.contains(actor)) { - failedPlayers.add(actor); - getLogger().warning("[Consumer] Failed to add player " + actor.getName()); - } - continue process; - } - } - } - if (r instanceof PreparedStatementRow) { - PreparedStatementRow PSRow = (PreparedStatementRow) r; - if (r instanceof MergeableRow) { - int batchCount=count; - // if we've reached our row target but not exceeded our time target, allow merging of up to 50% of our row limit more rows - if (count > forceToProcessAtLeast) batchCount = forceToProcessAtLeast / 2; - while(!queue.isEmpty()) { - MergeableRow mRow = (MergeableRow) PSRow; - Row s = queue.peek(); - if (s == null) break; - if (!(s instanceof MergeableRow)) break; - MergeableRow mRow2 = (MergeableRow) s; - if (mRow.canMerge(mRow2)) { - PSRow = mRow.merge((MergeableRow) queue.poll()); - count++; - batchCount++; - if (batchCount > forceToProcessAtLeast) break; - } else break; - } - } - 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++; - } - conn.commit(); - } catch (final SQLException ex) { - getLogger().log(Level.SEVERE, "[Consumer] SQL exception", ex); - } finally { - try { - if (state != null) - state.close(); - if (conn != null) - conn.close(); - } catch (final SQLException ex) { - getLogger().log(Level.SEVERE, "[Consumer] SQL exception on close", ex); - } - lock.unlock(); - - if (debug) { - long timeElapsed = System.currentTimeMillis() - startTime; - float rowPerTime = count / timeElapsed; - getLogger().log(Level.INFO, "[Consumer] Finished consumer cycle in " + timeElapsed + " milliseconds."); - getLogger().log(Level.INFO, "[Consumer] Total rows processed: " + count + ". row/time: " + String.format("%.4f", rowPerTime)); - } - } - } - - public void writeToFile() throws FileNotFoundException { - final long time = System.currentTimeMillis(); - final Set insertedPlayers = new HashSet(); - int counter = 0; - new File("plugins/LogBlock/import/").mkdirs(); - PrintWriter writer = new PrintWriter(new File("plugins/LogBlock/import/queue-" + time + "-0.sql")); - while (!queue.isEmpty()) { - final Row r = queue.poll(); - if (r == null) - continue; - for (final Actor actor : r.getActors()) - if (!playerIds.containsKey(actor) && !insertedPlayers.contains(actor)) { - // Odd query contruction is to work around innodb auto increment behaviour - bug #492 - writer.println("INSERT IGNORE INTO `lb-players` (playername,UUID) SELECT '" + actor.getName() + "','" + actor.getUUID() + "' FROM `lb-players` WHERE NOT EXISTS (SELECT NULL FROM `lb-players` WHERE UUID = '" + actor.getUUID() + "') LIMIT 1;"); - insertedPlayers.add(actor); - } - for (final String insert : r.getInserts()) - writer.println(insert); - counter++; - if (counter % 1000 == 0) { - writer.close(); - writer = new PrintWriter(new File("plugins/LogBlock/import/queue-" + time + "-" + counter / 1000 + ".sql")); - } - } - writer.close(); - } - - int getQueueSize() { - return queue.size(); - } - - static void hide(Player player) { - hiddenPlayers.add(player.getName().toLowerCase()); - } - - static void unHide(Player player) { - hiddenPlayers.remove(player.getName().toLowerCase()); - } - - static boolean toggleHide(Player player) { - final String playerName = player.getName().toLowerCase(); - if (hiddenPlayers.contains(playerName)) { - hiddenPlayers.remove(playerName); - return false; - } - hiddenPlayers.add(playerName); - return true; - } - - private boolean addPlayer(Statement state, Actor actor) throws SQLException { - // Odd query contruction is to work around innodb auto increment behaviour - bug #492 - String name = actor.getName(); - String uuid = actor.getUUID(); - state.execute("INSERT IGNORE INTO `lb-players` (playername,UUID) SELECT '" + name + "','" + uuid + "' FROM `lb-players` WHERE NOT EXISTS (SELECT NULL FROM `lb-players` WHERE UUID = '" + uuid + "') LIMIT 1;"); - final ResultSet rs = state.executeQuery("SELECT playerid FROM `lb-players` WHERE UUID = '" + uuid + "'"); - if (rs.next()) - playerIds.put(actor, rs.getInt(1)); - rs.close(); - return playerIds.containsKey(actor); - } - - private void queueBlock(Actor actor, Location loc, int typeBefore, int typeAfter, byte data, String signtext, ChestAccess ca) { - - if (Config.fireCustomEvents) { - // Create and call the event - BlockChangePreLogEvent event = new BlockChangePreLogEvent(actor, loc, typeBefore, typeAfter, data, signtext, ca); - logblock.getServer().getPluginManager().callEvent(event); - if (event.isCancelled()) return; - - // Update variables - actor = event.getOwnerActor(); - 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 (actor == null || loc == null || typeBefore < 0 || typeAfter < 0 || (Config.safetyIdCheck && (typeBefore > 255 || typeAfter > 255)) || hiddenPlayers.contains(actor.getName().toLowerCase()) || !isLogged(loc.getWorld()) || typeBefore != typeAfter && hiddenBlocks.contains(typeBefore) && hiddenBlocks.contains(typeAfter)) return; - queue.add(new BlockRow(loc, actor, typeBefore, typeAfter, data, signtext, ca)); - } - - private String playerID(Actor actor) { - if (actor == null) - return "NULL"; - final Integer id = playerIds.get(actor); - if (id != null) - return id.toString(); - return "(SELECT playerid FROM `lb-players` WHERE UUID = '" + actor.getUUID() + "')"; - } - - private Integer playerIDAsInt(Actor actor) { - if (actor == null) { - return null; - } - return playerIds.get(actor); - } - - private static interface Row - { - String[] getInserts(); - - /** - * - * @deprecated - Names are not guaranteed to be unique. Use {@link #getActors() } - */ - String[] getPlayers(); - - Actor[] getActors(); - } - - private interface PreparedStatementRow extends Row - { - - abstract void setConnection(Connection connection); - abstract void executeStatements() throws SQLException; - } - - private interface MergeableRow extends PreparedStatementRow - { - abstract boolean isUnique(); - abstract boolean canMerge(MergeableRow row); - abstract MergeableRow merge(MergeableRow second); - } - - private class BlockRow extends BlockChange implements MergeableRow - { - private Connection connection; - - public BlockRow(Location loc, Actor actor, int replaced, int type, byte data, String signtext, ChestAccess ca) { - super(System.currentTimeMillis() / 1000, loc, actor, replaced, type, data, signtext, ca); - } - - @Override - public String[] getInserts() { - final String table = getWorldConfig(loc.getWorld()).table; - final String[] inserts = new String[ca != null || signtext != null ? 2 : 1]; - inserts[0] = "INSERT INTO `" + table + "` (date, playerid, replaced, type, data, x, y, z) VALUES (FROM_UNIXTIME(" + date + "), " + playerID(actor) + ", " + replaced + ", " + type + ", " + data + ", '" + loc.getBlockX() + "', " + loc.getBlockY() + ", '" + loc.getBlockZ() + "');"; - if (signtext != null) { - inserts[1] = "INSERT INTO `" + table + "-sign` (id, signtext) values (LAST_INSERT_ID(), '" + signtext.replace("\\", "\\\\").replace("'", "\\'") + "');"; - } - else if (ca != null) - inserts[1] = "INSERT INTO `" + table + "-chest` (id, itemtype, itemamount, itemdata) values (LAST_INSERT_ID(), " + ca.itemType + ", " + ca.itemAmount + ", " + ca.itemData + ");"; - return inserts; - } - - @Override - public String[] getPlayers() { - return new String[]{actor.getName()}; - } - - @Override - public Actor[] getActors() { - return new Actor[]{actor}; - } - - @Override - public void setConnection(Connection connection) { - this.connection = connection; - } - - @Override - public void executeStatements() throws SQLException { - final String table = getWorldConfig(loc.getWorld()).table; - - PreparedStatement ps1 = null; - PreparedStatement ps = null; - try { - ps1 = connection.prepareStatement("INSERT INTO `" + table + "` (date, playerid, replaced, type, data, x, y, z) VALUES(FROM_UNIXTIME(?), " + playerID(actor) + ", ?, ?, ?, ?, ?, ?)", Statement.RETURN_GENERATED_KEYS); - ps1.setLong(1, date ); - 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); - - if (signtext != null) { - ps = connection.prepareStatement("INSERT INTO `" + table + "-sign` (signtext, id) VALUES(?, ?)"); - ps.setString(1, signtext); - ps.setInt(2, id); - ps.executeUpdate(); - } else if (ca != null) { - 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(); - } - } - catch (final SQLException ex) { - if (ps1 != null) { - getLogger().log(Level.SEVERE, "[Consumer] Troublesome query: " + ps1.toString()); - } - if (ps != null) { - getLogger().log(Level.SEVERE, "[Consumer] Troublesome query: " + ps.toString()); - } - throw ex; - } - finally { - // individual try/catch here, though ugly, prevents resource leaks - if( ps1 != null ) { - try { - ps1.close(); - } - catch(SQLException e) { - // ideally should log to logger, none is available in this class - // at the time of this writing, so I'll leave that to the plugin - // maintainers to integrate if they wish - e.printStackTrace(); - } - } - - if( ps != null ) { - try { - ps.close(); - } - catch(SQLException e) { - e.printStackTrace(); - } - } - } - } - - @Override - public boolean isUnique() { - return !(signtext == null && ca == null && playerIds.containsKey(actor)); - } - - @Override - public boolean canMerge(MergeableRow row) { - return !this.isUnique() && !row.isUnique() && row instanceof BlockRow && getWorldConfig(loc.getWorld()).table.equals(getWorldConfig(((BlockRow) row).loc.getWorld()).table); - } - - @Override - public MergeableRow merge(MergeableRow singleRow) { - return new MultiBlockChangeRow(this,(BlockRow) singleRow); - } - } - - private class MultiBlockChangeRow implements MergeableRow{ - private List rows = new ArrayList(); - private Connection connection; - private Set players = new HashSet(); - private Set actors = new HashSet(); - private String table; - - MultiBlockChangeRow (BlockRow first, BlockRow second) { - if (first.isUnique() || second.isUnique()) throw new IllegalArgumentException("Can't merge a unique row"); - rows.add(first); - rows.add(second); - actors.addAll(Arrays.asList(first.getActors())); - actors.addAll(Arrays.asList(second.getActors())); - players.addAll(Arrays.asList(first.getPlayers())); - players.addAll(Arrays.asList(second.getPlayers())); - table = getWorldConfig(first.loc.getWorld()).table; - } - - @Override - public void setConnection(Connection connection) { - this.connection = connection; - } - - @Override - public void executeStatements() throws SQLException { - PreparedStatement ps = null; - try { - ps = connection.prepareStatement("INSERT INTO `" + table + "` (date, playerid, replaced, type, data, x, y, z) VALUES(FROM_UNIXTIME(?), ?, ?, ?, ?, ?, ?, ?)"); - for (BlockRow row : rows) { - ps.setLong(1, row.date ); - ps.setInt(2, playerIds.get(row.actor)); - ps.setInt(3, row.replaced); - ps.setInt(4, row.type); - ps.setInt(5, row.data); - ps.setInt(6, row.loc.getBlockX()); - ps.setInt(7, row.loc.getBlockY()); - ps.setInt(8, row.loc.getBlockZ()); - ps.addBatch(); - } - ps.executeBatch(); - } catch (final SQLException ex) { - if (ps != null) { - getLogger().log(Level.SEVERE, "[Consumer] Troublesome query: " + ps.toString()); - } - throw ex; - } finally { - // individual try/catch here, though ugly, prevents resource leaks - if( ps != null ) { - try { - ps.close(); - } - catch(SQLException e) { - e.printStackTrace(); - } - } - } - } - - @Override - public boolean isUnique() { - return true; - } - - @Override - public boolean canMerge(MergeableRow row) { - return !row.isUnique() && row instanceof BlockRow && table.equals(getWorldConfig(((BlockRow) row).loc.getWorld()).table); - } - - @Override - public MergeableRow merge(MergeableRow second) { - if (second.isUnique()) throw new IllegalArgumentException("Can't merge a unique row"); - rows.add((BlockRow) second); - actors.addAll(Arrays.asList(second.getActors())); - players.addAll(Arrays.asList(second.getPlayers())); - return this; - } - - @Override - public String[] getInserts() { - List l = new ArrayList(); - for (BlockRow row : rows) { - l.addAll(Arrays.asList(row.getInserts())); - } - return (String[]) l.toArray(); - } - - @Override - public String[] getPlayers() { - return (String[]) players.toArray(); - } - - @Override - public Actor[] getActors() { - return (Actor[]) actors.toArray(); - } - } - - private class KillRow implements Row - { - final long date; - final Actor killer, victim; - final int weapon; - final Location loc; - - KillRow(Location loc, Actor attacker, Actor defender, int weapon) { - date = System.currentTimeMillis() / 1000; - this.loc = loc; - killer = attacker; - victim = defender; - this.weapon = weapon; - } - - @Override - public String[] getInserts() { - return new String[]{"INSERT INTO `" + getWorldConfig(loc.getWorld()).table + "-kills` (date, killer, victim, weapon, x, y, z) VALUES (FROM_UNIXTIME(" + date + "), " + playerID(killer) + ", " + playerID(victim) + ", " + weapon + ", " + loc.getBlockX() + ", " + (loc.getBlockY() < 0 ? 0 : loc.getBlockY()) + ", " + loc.getBlockZ() + ");"}; - } - - @Override - public String[] getPlayers() { - return new String[]{killer.getName(), victim.getName()}; - } - - @Override - public Actor[] getActors() { - return new Actor[]{killer,victim}; - } - } - - private class ChatRow extends ChatMessage implements PreparedStatementRow - { - private Connection connection; - - ChatRow(Actor player, String message) { - super(player, message); - } - - @Override - public String[] getInserts() { - return new String[]{"INSERT INTO `lb-chat` (date, playerid, message) VALUES (FROM_UNIXTIME(" + date + "), " + playerID(player) + ", '" + message.replace("\\", "\\\\").replace("'", "\\'") + "');"}; - } - - @Override - public String[] getPlayers() { - return new String[]{player.getName()}; - } - - @Override - public Actor[] getActors() { - return new Actor[]{player}; - } - - @Override - public void setConnection(Connection connection) { - this.connection = connection; - } - - @Override - public void executeStatements() throws SQLException { - boolean noID = false; - Integer id; - - String sql = "INSERT INTO `lb-chat` (date, playerid, message) VALUES (FROM_UNIXTIME(?), "; - if ((id = playerIDAsInt(player)) == null) { - noID = true; - sql += playerID(player) + ", "; - } else { - sql += "?, "; - } - sql += "?)"; - - PreparedStatement ps = null; - try { - ps = connection.prepareStatement(sql); - ps.setLong(1, date); - if (!noID) { - ps.setInt(2, id); - ps.setString(3, message); - } else { - ps.setString(2, message); - } - ps.execute(); - } - // we intentionally do not catch SQLException, it is thrown to the caller - finally { - if( ps != null ) { - try { - ps.close(); - } - catch(SQLException e) { - // should print to a Logger instead if one is ever added to this class - e.printStackTrace(); - } - } - } - } - } - - private class PlayerJoinRow implements Row - { - private final Actor player; - private final long lastLogin; - private final String ip; - - PlayerJoinRow(Player player) { - this.player = Actor.actorFromEntity(player); - lastLogin = System.currentTimeMillis() / 1000; - ip = player.getAddress().toString().replace("'", "\\'"); - } - - @Override - public String[] getInserts() { - if (logPlayerInfo) - return new String[]{"UPDATE `lb-players` SET lastlogin = FROM_UNIXTIME(" + lastLogin + "), firstlogin = IF(firstlogin = 0, FROM_UNIXTIME(" + lastLogin + "), firstlogin), ip = '" + ip + "', playername = '" + player.getName() + "' WHERE UUID = '" + player.getUUID() + "';"}; - return new String[]{"UPDATE `lb-players` SET playername = '" + player.getName() + "' WHERE UUID = '" + player.getUUID() + "';"}; - } - - @Override - public String[] getPlayers() { - return new String[]{player.getName()}; - } - - @Override - public Actor[] getActors() { - return new Actor[]{player}; - } - } - - private class PlayerLeaveRow implements Row - {; - private final long leaveTime; - private final Actor actor; - - PlayerLeaveRow(Player player) { - leaveTime = System.currentTimeMillis() / 1000; - actor = Actor.actorFromEntity(player); - } - - @Override - public String[] getInserts() { - if (logPlayerInfo) - return new String[]{"UPDATE `lb-players` SET onlinetime = onlinetime + TIMESTAMPDIFF(SECOND, lastlogin, FROM_UNIXTIME('" + leaveTime + "')), playername = '" + actor.getName() + "' WHERE lastlogin > 0 && UUID = '" + actor.getUUID() + "';"}; - return new String[]{"UPDATE `lb-players` SET playername = '" + actor.getName() + "' WHERE UUID = '" + actor.getUUID() + "';"}; - } - - @Override - public String[] getPlayers() { - return new String[]{actor.getName()}; - } - - @Override - public Actor[] getActors() { - return new Actor[]{actor}; - } - } + +public class Consumer extends TimerTask { + private final Queue queue = new LinkedBlockingQueue(); + private final Set failedPlayers = new HashSet(); + private final LogBlock logblock; + private final Map playerIds = new HashMap(); + private final Lock lock = new ReentrantLock(); + + Consumer(LogBlock logblock) { + this.logblock = logblock; + try { + Class.forName("PlayerLeaveRow"); + } catch (final ClassNotFoundException ex) { + } + } + + /** + * Logs any block change. Don't try to combine broken and placed blocks. Queue two block changes or use the queueBLockReplace methods. + */ + public void queueBlock(Actor actor, Location loc, int typeBefore, int typeAfter, byte data) { + queueBlock(actor, loc, typeBefore, typeAfter, data, null, null); + } + + /** + * Logs a block break. The type afterwards is assumed to be o (air). + * + * @param before Blockstate of the block before actually being destroyed. + */ + public void queueBlockBreak(Actor actor, BlockState before) { + queueBlockBreak(actor, new Location(before.getWorld(), before.getX(), before.getY(), before.getZ()), before.getTypeId(), before.getRawData()); + } + + /** + * Logs a block break. The block type afterwards is assumed to be o (air). + */ + public void queueBlockBreak(Actor actor, Location loc, int typeBefore, byte dataBefore) { + queueBlock(actor, loc, typeBefore, 0, dataBefore); + } + + /** + * Logs a block place. The block type before is assumed to be o (air). + * + * @param after Blockstate of the block after actually being placed. + */ + public void queueBlockPlace(Actor actor, BlockState after) { + queueBlockPlace(actor, new Location(after.getWorld(), after.getX(), after.getY(), after.getZ()), after.getBlock().getTypeId(), after.getBlock().getData()); + } + + /** + * Logs a block place. The block type before is assumed to be o (air). + */ + public void queueBlockPlace(Actor actor, Location loc, int type, byte data) { + queueBlock(actor, loc, 0, type, data); + } + + /** + * @param before Blockstate of the block before actually being destroyed. + * @param after Blockstate of the block after actually being placed. + */ + public void queueBlockReplace(Actor actor, BlockState before, BlockState after) { + queueBlockReplace(actor, new Location(before.getWorld(), before.getX(), before.getY(), before.getZ()), before.getTypeId(), before.getRawData(), after.getTypeId(), after.getRawData()); + } + + /** + * @param before Blockstate of the block before actually being destroyed. + */ + public void queueBlockReplace(Actor actor, BlockState before, int typeAfter, byte dataAfter) { + queueBlockReplace(actor, new Location(before.getWorld(), before.getX(), before.getY(), before.getZ()), before.getTypeId(), before.getRawData(), typeAfter, dataAfter); + } + + /** + * @param after Blockstate of the block after actually being placed. + */ + public void queueBlockReplace(Actor actor, int typeBefore, byte dataBefore, BlockState after) { + queueBlockReplace(actor, new Location(after.getWorld(), after.getX(), after.getY(), after.getZ()), typeBefore, dataBefore, after.getTypeId(), after.getRawData()); + } + + public void queueBlockReplace(Actor actor, Location loc, int typeBefore, byte dataBefore, int typeAfter, byte dataAfter) { + if (dataBefore == 0 && (typeBefore != typeAfter)) { + queueBlock(actor, loc, typeBefore, typeAfter, dataAfter); + } else { + queueBlockBreak(actor, loc, typeBefore, dataBefore); + queueBlockPlace(actor, loc, typeAfter, dataAfter); + } + } + + /** + * @param container The respective container. Must be an instance of an InventoryHolder. + */ + public void queueChestAccess(Actor actor, BlockState container, short itemType, short itemAmount, short itemData) { + if (!(container instanceof InventoryHolder)) { + return; + } + queueChestAccess(actor, new Location(container.getWorld(), container.getX(), container.getY(), container.getZ()), container.getTypeId(), itemType, itemAmount, itemData); + } + + /** + * @param type Type id of the container. + */ + public void queueChestAccess(Actor actor, Location loc, int type, short itemType, short itemAmount, short itemData) { + queueBlock(actor, loc, type, type, (byte) 0, null, new ChestAccess(itemType, itemAmount, itemData)); + } + + /** + * 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 an instance of InventoryHolder + */ + public void queueContainerBreak(Actor actor, BlockState container) { + if (!(container instanceof InventoryHolder)) { + return; + } + queueContainerBreak(actor, new Location(container.getWorld(), container.getX(), container.getY(), container.getZ()), container.getTypeId(), container.getRawData(), ((InventoryHolder) container).getInventory()); + } + + /** + * 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(Actor actor, Location loc, int type, byte data, Inventory inv) { + final ItemStack[] items = compressInventory(inv.getContents()); + for (final ItemStack item : items) { + queueChestAccess(actor, loc, type, (short) item.getTypeId(), (short) (item.getAmount() * -1), rawData(item)); + } + queueBlockBreak(actor, loc, type, data); + } + + /** + * @param killer Can't be null + * @param victim Can't be null + */ + public void queueKill(Entity killer, Entity victim) { + if (killer == null || victim == null) { + return; + } + int weapon = 0; + Actor killerActor = Actor.actorFromEntity(killer); + // If it's a projectile kill we want to manually assign the weapon, so check for player before converting a projectile to its source + if (killer instanceof Player && ((Player) killer).getItemInHand() != null) { + weapon = ((Player) killer).getItemInHand().getTypeId(); + } + if (killer instanceof Projectile) { + ProjectileSource ps = ((Projectile) killer).getShooter(); + killerActor = Actor.actorFromProjectileSource(ps); + weapon = itemIDfromProjectileEntity(killer); + } + + queueKill(victim.getLocation(), killerActor, Actor.actorFromEntity(victim), weapon); + } + + /** + * This form should only be used when the killer is not an entity e.g. for fall or suffocation damage + * + * @param killer Can't be null + * @param victim Can't be null + */ + public void queueKill(Actor killer, Entity victim) { + if (killer == null || victim == null) { + return; + } + queueKill(victim.getLocation(), killer, Actor.actorFromEntity(victim), 0); + } + + /** + * @param world World the victim was inside. + * @param killerName Name of the killer. Can be null. + * @param victimName Name of the victim. Can't be null. + * @param weapon Item id of the weapon. 0 for no weapon. + * @deprecated Use {@link #queueKill(Location, String, String, int)} instead + */ + @Deprecated + public void queueKill(World world, Actor killer, Actor victim, int weapon) { + queueKill(new Location(world, 0, 0, 0), killer, victim, weapon); + } + + /** + * @param location Location of the victim. + * @param killer Killer Actor. Can be null. + * @param victim Victim Actor. Can't be null. + * @param weapon Item id of the weapon. 0 for no weapon. + */ + public void queueKill(Location location, Actor killer, Actor victim, int weapon) { + if (victim == null || !isLogged(location.getWorld())) { + return; + } + queue.add(new KillRow(location, killer == null ? null : killer, victim, weapon)); + } + + /** + * @param type Type of the sign. Must be 63 or 68. + * @param lines The four lines on the sign. + */ + public void queueSignBreak(Actor actor, Location loc, int type, byte data, String[] lines) { + if (type != 63 && type != 68 || lines == null || lines.length != 4) { + return; + } + queueBlock(actor, loc, type, 0, data, lines[0] + "\0" + lines[1] + "\0" + lines[2] + "\0" + lines[3], null); + } + + public void queueSignBreak(Actor actor, Sign sign) { + queueSignBreak(actor, new Location(sign.getWorld(), sign.getX(), sign.getY(), sign.getZ()), sign.getTypeId(), sign.getRawData(), sign.getLines()); + } + + /** + * @param type Type of the sign. Must be 63 or 68. + * @param lines The four lines on the sign. + */ + public void queueSignPlace(Actor actor, Location loc, int type, byte data, String[] lines) { + if (type != 63 && type != 68 || lines == null || lines.length != 4) { + return; + } + queueBlock(actor, loc, 0, type, data, lines[0] + "\0" + lines[1] + "\0" + lines[2] + "\0" + lines[3], null); + } + + public void queueSignPlace(Actor actor, Sign sign) { + queueSignPlace(actor, new Location(sign.getWorld(), sign.getX(), sign.getY(), sign.getZ()), sign.getTypeId(), sign.getRawData(), sign.getLines()); + } + + public void queueChat(Actor player, String message) { + for (String ignored : Config.ignoredChat) { + if (message.startsWith(ignored)) { + return; + } + } + if (hiddenPlayers.contains(player.getName().toLowerCase())) { + return; + } + queue.add(new ChatRow(player, message)); + } + + public void queueJoin(Player player) { + queue.add(new PlayerJoinRow(player)); + } + + public void queueLeave(Player player) { + queue.add(new PlayerLeaveRow(player)); + } + + @Override + public synchronized void run() { + if (queue.isEmpty() || !lock.tryLock()) { + return; + } + long startTime = System.currentTimeMillis(); + int startSize = queue.size(); + + final Connection conn = logblock.getConnection(); + Statement state = null; + if (Config.queueWarningSize > 0 && queue.size() >= Config.queueWarningSize) { + getLogger().info("[Consumer] Queue overloaded. Size: " + getQueueSize()); + } + + int count = 0; + + try { + if (conn == null) { + return; + } + conn.setAutoCommit(false); + state = conn.createStatement(); + final long start = System.currentTimeMillis(); + process: + while (!queue.isEmpty() && (System.currentTimeMillis() - start < timePerRun || count < forceToProcessAtLeast)) { + final Row r = queue.poll(); + if (r == null) { + continue; + } + for (final Actor actor : r.getActors()) { + if (!playerIds.containsKey(actor)) { + if (!addPlayer(state, actor)) { + if (!failedPlayers.contains(actor)) { + failedPlayers.add(actor); + getLogger().warning("[Consumer] Failed to add player " + actor.getName()); + } + continue process; + } + } + } + if (r instanceof PreparedStatementRow) { + PreparedStatementRow PSRow = (PreparedStatementRow) r; + if (r instanceof MergeableRow) { + int batchCount = count; + // if we've reached our row target but not exceeded our time target, allow merging of up to 50% of our row limit more rows + if (count > forceToProcessAtLeast) { + batchCount = forceToProcessAtLeast / 2; + } + while (!queue.isEmpty()) { + MergeableRow mRow = (MergeableRow) PSRow; + Row s = queue.peek(); + if (s == null) { + break; + } + if (!(s instanceof MergeableRow)) { + break; + } + MergeableRow mRow2 = (MergeableRow) s; + if (mRow.canMerge(mRow2)) { + PSRow = mRow.merge((MergeableRow) queue.poll()); + count++; + batchCount++; + if (batchCount > forceToProcessAtLeast) { + break; + } + } else { + break; + } + } + } + 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++; + } + conn.commit(); + } catch (final SQLException ex) { + getLogger().log(Level.SEVERE, "[Consumer] SQL exception", ex); + } finally { + try { + if (state != null) { + state.close(); + } + if (conn != null) { + conn.close(); + } + } catch (final SQLException ex) { + getLogger().log(Level.SEVERE, "[Consumer] SQL exception on close", ex); + } + lock.unlock(); + + if (debug) { + long timeElapsed = System.currentTimeMillis() - startTime; + float rowPerTime = count / timeElapsed; + getLogger().log(Level.INFO, "[Consumer] Finished consumer cycle in " + timeElapsed + " milliseconds."); + getLogger().log(Level.INFO, "[Consumer] Total rows processed: " + count + ". row/time: " + String.format("%.4f", rowPerTime)); + } + } + } + + public void writeToFile() throws FileNotFoundException { + final long time = System.currentTimeMillis(); + final Set insertedPlayers = new HashSet(); + int counter = 0; + new File("plugins/LogBlock/import/").mkdirs(); + PrintWriter writer = new PrintWriter(new File("plugins/LogBlock/import/queue-" + time + "-0.sql")); + while (!queue.isEmpty()) { + final Row r = queue.poll(); + if (r == null) { + continue; + } + for (final Actor actor : r.getActors()) { + if (!playerIds.containsKey(actor) && !insertedPlayers.contains(actor)) { + // Odd query contruction is to work around innodb auto increment behaviour - bug #492 + writer.println("INSERT IGNORE INTO `lb-players` (playername,UUID) SELECT '" + actor.getName() + "','" + actor.getUUID() + "' FROM `lb-players` WHERE NOT EXISTS (SELECT NULL FROM `lb-players` WHERE UUID = '" + actor.getUUID() + "') LIMIT 1;"); + insertedPlayers.add(actor); + } + } + for (final String insert : r.getInserts()) { + writer.println(insert); + } + counter++; + if (counter % 1000 == 0) { + writer.close(); + writer = new PrintWriter(new File("plugins/LogBlock/import/queue-" + time + "-" + counter / 1000 + ".sql")); + } + } + writer.close(); + } + + int getQueueSize() { + return queue.size(); + } + + static void hide(Player player) { + hiddenPlayers.add(player.getName().toLowerCase()); + } + + static void unHide(Player player) { + hiddenPlayers.remove(player.getName().toLowerCase()); + } + + static boolean toggleHide(Player player) { + final String playerName = player.getName().toLowerCase(); + if (hiddenPlayers.contains(playerName)) { + hiddenPlayers.remove(playerName); + return false; + } + hiddenPlayers.add(playerName); + return true; + } + + private boolean addPlayer(Statement state, Actor actor) throws SQLException { + // Odd query contruction is to work around innodb auto increment behaviour - bug #492 + String name = actor.getName(); + String uuid = actor.getUUID(); + state.execute("INSERT IGNORE INTO `lb-players` (playername,UUID) SELECT '" + name + "','" + uuid + "' FROM `lb-players` WHERE NOT EXISTS (SELECT NULL FROM `lb-players` WHERE UUID = '" + uuid + "') LIMIT 1;"); + final ResultSet rs = state.executeQuery("SELECT playerid FROM `lb-players` WHERE UUID = '" + uuid + "'"); + if (rs.next()) { + playerIds.put(actor, rs.getInt(1)); + } + rs.close(); + return playerIds.containsKey(actor); + } + + private void queueBlock(Actor actor, Location loc, int typeBefore, int typeAfter, byte data, String signtext, ChestAccess ca) { + + if (Config.fireCustomEvents) { + // Create and call the event + BlockChangePreLogEvent event = new BlockChangePreLogEvent(actor, loc, typeBefore, typeAfter, data, signtext, ca); + logblock.getServer().getPluginManager().callEvent(event); + if (event.isCancelled()) { + return; + } + + // Update variables + actor = event.getOwnerActor(); + 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 (actor == null || loc == null || typeBefore < 0 || typeAfter < 0 || (Config.safetyIdCheck && (typeBefore > 255 || typeAfter > 255)) || hiddenPlayers.contains(actor.getName().toLowerCase()) || !isLogged(loc.getWorld()) || typeBefore != typeAfter && hiddenBlocks.contains(typeBefore) && hiddenBlocks.contains(typeAfter)) { + return; + } + queue.add(new BlockRow(loc, actor, typeBefore, typeAfter, data, signtext, ca)); + } + + private String playerID(Actor actor) { + if (actor == null) { + return "NULL"; + } + final Integer id = playerIds.get(actor); + if (id != null) { + return id.toString(); + } + return "(SELECT playerid FROM `lb-players` WHERE UUID = '" + actor.getUUID() + "')"; + } + + private Integer playerIDAsInt(Actor actor) { + if (actor == null) { + return null; + } + return playerIds.get(actor); + } + + private static interface Row { + String[] getInserts(); + + /** + * @deprecated - Names are not guaranteed to be unique. Use {@link #getActors() } + */ + String[] getPlayers(); + + Actor[] getActors(); + } + + private interface PreparedStatementRow extends Row { + + abstract void setConnection(Connection connection); + + abstract void executeStatements() throws SQLException; + } + + private interface MergeableRow extends PreparedStatementRow { + abstract boolean isUnique(); + + abstract boolean canMerge(MergeableRow row); + + abstract MergeableRow merge(MergeableRow second); + } + + private class BlockRow extends BlockChange implements MergeableRow { + private Connection connection; + + public BlockRow(Location loc, Actor actor, int replaced, int type, byte data, String signtext, ChestAccess ca) { + super(System.currentTimeMillis() / 1000, loc, actor, replaced, type, data, signtext, ca); + } + + @Override + public String[] getInserts() { + final String table = getWorldConfig(loc.getWorld()).table; + final String[] inserts = new String[ca != null || signtext != null ? 2 : 1]; + inserts[0] = "INSERT INTO `" + table + "` (date, playerid, replaced, type, data, x, y, z) VALUES (FROM_UNIXTIME(" + date + "), " + playerID(actor) + ", " + replaced + ", " + type + ", " + data + ", '" + loc.getBlockX() + "', " + loc.getBlockY() + ", '" + loc.getBlockZ() + "');"; + if (signtext != null) { + inserts[1] = "INSERT INTO `" + table + "-sign` (id, signtext) values (LAST_INSERT_ID(), '" + signtext.replace("\\", "\\\\").replace("'", "\\'") + "');"; + } else if (ca != null) { + inserts[1] = "INSERT INTO `" + table + "-chest` (id, itemtype, itemamount, itemdata) values (LAST_INSERT_ID(), " + ca.itemType + ", " + ca.itemAmount + ", " + ca.itemData + ");"; + } + return inserts; + } + + @Override + public String[] getPlayers() { + return new String[]{actor.getName()}; + } + + @Override + public Actor[] getActors() { + return new Actor[]{actor}; + } + + @Override + public void setConnection(Connection connection) { + this.connection = connection; + } + + @Override + public void executeStatements() throws SQLException { + final String table = getWorldConfig(loc.getWorld()).table; + + PreparedStatement ps1 = null; + PreparedStatement ps = null; + try { + ps1 = connection.prepareStatement("INSERT INTO `" + table + "` (date, playerid, replaced, type, data, x, y, z) VALUES(FROM_UNIXTIME(?), " + playerID(actor) + ", ?, ?, ?, ?, ?, ?)", Statement.RETURN_GENERATED_KEYS); + ps1.setLong(1, date); + 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); + + if (signtext != null) { + ps = connection.prepareStatement("INSERT INTO `" + table + "-sign` (signtext, id) VALUES(?, ?)"); + ps.setString(1, signtext); + ps.setInt(2, id); + ps.executeUpdate(); + } else if (ca != null) { + 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(); + } + } catch (final SQLException ex) { + if (ps1 != null) { + getLogger().log(Level.SEVERE, "[Consumer] Troublesome query: " + ps1.toString()); + } + if (ps != null) { + getLogger().log(Level.SEVERE, "[Consumer] Troublesome query: " + ps.toString()); + } + throw ex; + } finally { + // individual try/catch here, though ugly, prevents resource leaks + if (ps1 != null) { + try { + ps1.close(); + } catch (SQLException e) { + // ideally should log to logger, none is available in this class + // at the time of this writing, so I'll leave that to the plugin + // maintainers to integrate if they wish + e.printStackTrace(); + } + } + + if (ps != null) { + try { + ps.close(); + } catch (SQLException e) { + e.printStackTrace(); + } + } + } + } + + @Override + public boolean isUnique() { + return !(signtext == null && ca == null && playerIds.containsKey(actor)); + } + + @Override + public boolean canMerge(MergeableRow row) { + return !this.isUnique() && !row.isUnique() && row instanceof BlockRow && getWorldConfig(loc.getWorld()).table.equals(getWorldConfig(((BlockRow) row).loc.getWorld()).table); + } + + @Override + public MergeableRow merge(MergeableRow singleRow) { + return new MultiBlockChangeRow(this, (BlockRow) singleRow); + } + } + + private class MultiBlockChangeRow implements MergeableRow { + private List rows = new ArrayList(); + private Connection connection; + private Set players = new HashSet(); + private Set actors = new HashSet(); + private String table; + + MultiBlockChangeRow(BlockRow first, BlockRow second) { + if (first.isUnique() || second.isUnique()) { + throw new IllegalArgumentException("Can't merge a unique row"); + } + rows.add(first); + rows.add(second); + actors.addAll(Arrays.asList(first.getActors())); + actors.addAll(Arrays.asList(second.getActors())); + players.addAll(Arrays.asList(first.getPlayers())); + players.addAll(Arrays.asList(second.getPlayers())); + table = getWorldConfig(first.loc.getWorld()).table; + } + + @Override + public void setConnection(Connection connection) { + this.connection = connection; + } + + @Override + public void executeStatements() throws SQLException { + PreparedStatement ps = null; + try { + ps = connection.prepareStatement("INSERT INTO `" + table + "` (date, playerid, replaced, type, data, x, y, z) VALUES(FROM_UNIXTIME(?), ?, ?, ?, ?, ?, ?, ?)"); + for (BlockRow row : rows) { + ps.setLong(1, row.date); + ps.setInt(2, playerIds.get(row.actor)); + ps.setInt(3, row.replaced); + ps.setInt(4, row.type); + ps.setInt(5, row.data); + ps.setInt(6, row.loc.getBlockX()); + ps.setInt(7, row.loc.getBlockY()); + ps.setInt(8, row.loc.getBlockZ()); + ps.addBatch(); + } + ps.executeBatch(); + } catch (final SQLException ex) { + if (ps != null) { + getLogger().log(Level.SEVERE, "[Consumer] Troublesome query: " + ps.toString()); + } + throw ex; + } finally { + // individual try/catch here, though ugly, prevents resource leaks + if (ps != null) { + try { + ps.close(); + } catch (SQLException e) { + e.printStackTrace(); + } + } + } + } + + @Override + public boolean isUnique() { + return true; + } + + @Override + public boolean canMerge(MergeableRow row) { + return !row.isUnique() && row instanceof BlockRow && table.equals(getWorldConfig(((BlockRow) row).loc.getWorld()).table); + } + + @Override + public MergeableRow merge(MergeableRow second) { + if (second.isUnique()) { + throw new IllegalArgumentException("Can't merge a unique row"); + } + rows.add((BlockRow) second); + actors.addAll(Arrays.asList(second.getActors())); + players.addAll(Arrays.asList(second.getPlayers())); + return this; + } + + @Override + public String[] getInserts() { + List l = new ArrayList(); + for (BlockRow row : rows) { + l.addAll(Arrays.asList(row.getInserts())); + } + return (String[]) l.toArray(); + } + + @Override + public String[] getPlayers() { + return (String[]) players.toArray(); + } + + @Override + public Actor[] getActors() { + return (Actor[]) actors.toArray(); + } + } + + private class KillRow implements Row { + final long date; + final Actor killer, victim; + final int weapon; + final Location loc; + + KillRow(Location loc, Actor attacker, Actor defender, int weapon) { + date = System.currentTimeMillis() / 1000; + this.loc = loc; + killer = attacker; + victim = defender; + this.weapon = weapon; + } + + @Override + public String[] getInserts() { + return new String[]{"INSERT INTO `" + getWorldConfig(loc.getWorld()).table + "-kills` (date, killer, victim, weapon, x, y, z) VALUES (FROM_UNIXTIME(" + date + "), " + playerID(killer) + ", " + playerID(victim) + ", " + weapon + ", " + loc.getBlockX() + ", " + (loc.getBlockY() < 0 ? 0 : loc.getBlockY()) + ", " + loc.getBlockZ() + ");"}; + } + + @Override + public String[] getPlayers() { + return new String[]{killer.getName(), victim.getName()}; + } + + @Override + public Actor[] getActors() { + return new Actor[]{killer, victim}; + } + } + + private class ChatRow extends ChatMessage implements PreparedStatementRow { + private Connection connection; + + ChatRow(Actor player, String message) { + super(player, message); + } + + @Override + public String[] getInserts() { + return new String[]{"INSERT INTO `lb-chat` (date, playerid, message) VALUES (FROM_UNIXTIME(" + date + "), " + playerID(player) + ", '" + message.replace("\\", "\\\\").replace("'", "\\'") + "');"}; + } + + @Override + public String[] getPlayers() { + return new String[]{player.getName()}; + } + + @Override + public Actor[] getActors() { + return new Actor[]{player}; + } + + @Override + public void setConnection(Connection connection) { + this.connection = connection; + } + + @Override + public void executeStatements() throws SQLException { + boolean noID = false; + Integer id; + + String sql = "INSERT INTO `lb-chat` (date, playerid, message) VALUES (FROM_UNIXTIME(?), "; + if ((id = playerIDAsInt(player)) == null) { + noID = true; + sql += playerID(player) + ", "; + } else { + sql += "?, "; + } + sql += "?)"; + + PreparedStatement ps = null; + try { + ps = connection.prepareStatement(sql); + ps.setLong(1, date); + if (!noID) { + ps.setInt(2, id); + ps.setString(3, message); + } else { + ps.setString(2, message); + } + ps.execute(); + } + // we intentionally do not catch SQLException, it is thrown to the caller + finally { + if (ps != null) { + try { + ps.close(); + } catch (SQLException e) { + // should print to a Logger instead if one is ever added to this class + e.printStackTrace(); + } + } + } + } + } + + private class PlayerJoinRow implements Row { + private final Actor player; + private final long lastLogin; + private final String ip; + + PlayerJoinRow(Player player) { + this.player = Actor.actorFromEntity(player); + lastLogin = System.currentTimeMillis() / 1000; + ip = player.getAddress().toString().replace("'", "\\'"); + } + + @Override + public String[] getInserts() { + if (logPlayerInfo) { + return new String[]{"UPDATE `lb-players` SET lastlogin = FROM_UNIXTIME(" + lastLogin + "), firstlogin = IF(firstlogin = 0, FROM_UNIXTIME(" + lastLogin + "), firstlogin), ip = '" + ip + "', playername = '" + player.getName() + "' WHERE UUID = '" + player.getUUID() + "';"}; + } + return new String[]{"UPDATE `lb-players` SET playername = '" + player.getName() + "' WHERE UUID = '" + player.getUUID() + "';"}; + } + + @Override + public String[] getPlayers() { + return new String[]{player.getName()}; + } + + @Override + public Actor[] getActors() { + return new Actor[]{player}; + } + } + + private class PlayerLeaveRow implements Row { + ; + private final long leaveTime; + private final Actor actor; + + PlayerLeaveRow(Player player) { + leaveTime = System.currentTimeMillis() / 1000; + actor = Actor.actorFromEntity(player); + } + + @Override + public String[] getInserts() { + if (logPlayerInfo) { + return new String[]{"UPDATE `lb-players` SET onlinetime = onlinetime + TIMESTAMPDIFF(SECOND, lastlogin, FROM_UNIXTIME('" + leaveTime + "')), playername = '" + actor.getName() + "' WHERE lastlogin > 0 && UUID = '" + actor.getUUID() + "';"}; + } + return new String[]{"UPDATE `lb-players` SET playername = '" + actor.getName() + "' WHERE UUID = '" + actor.getUUID() + "';"}; + } + + @Override + public String[] getPlayers() { + return new String[]{actor.getName()}; + } + + @Override + public Actor[] getActors() { + return new Actor[]{actor}; + } + } } diff --git a/src/main/java/de/diddiz/LogBlock/DumpedLogImporter.java b/src/main/java/de/diddiz/LogBlock/DumpedLogImporter.java index d40d0b5..85bc6a7 100644 --- a/src/main/java/de/diddiz/LogBlock/DumpedLogImporter.java +++ b/src/main/java/de/diddiz/LogBlock/DumpedLogImporter.java @@ -1,70 +1,70 @@ package de.diddiz.LogBlock; -import static de.diddiz.util.Utils.newline; -import static org.bukkit.Bukkit.getLogger; -import java.io.BufferedReader; -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileReader; -import java.io.FileWriter; +import de.diddiz.util.Utils.ExtensionFilenameFilter; + +import java.io.*; import java.sql.Connection; import java.sql.SQLException; import java.sql.Statement; import java.util.logging.Level; -import de.diddiz.util.Utils.ExtensionFilenameFilter; -public class DumpedLogImporter implements Runnable -{ - private final LogBlock logblock; +import static de.diddiz.util.Utils.newline; +import static org.bukkit.Bukkit.getLogger; - DumpedLogImporter(LogBlock logblock) { - this.logblock = logblock; - } +public class DumpedLogImporter implements Runnable { + private final LogBlock logblock; - @Override - public void run() { - final File[] imports = new File("plugins/LogBlock/import/").listFiles(new ExtensionFilenameFilter("sql")); - if (imports != null && imports.length > 0) { - getLogger().info("Found " + imports.length + " imports."); - Connection conn = null; - try { - conn = logblock.getConnection(); - if (conn == null) - return; - conn.setAutoCommit(false); - final Statement st = conn.createStatement(); - final BufferedWriter writer = new BufferedWriter(new FileWriter(new File(logblock.getDataFolder(), "import/failed.txt"))); - int successes = 0, errors = 0; - for (final File sqlFile : imports) { - getLogger().info("Trying to import " + sqlFile.getName() + " ..."); - final BufferedReader reader = new BufferedReader(new FileReader(sqlFile)); - String line; - while ((line = reader.readLine()) != null) - try { - st.execute(line); - successes++; - } catch (final Exception ex) { - getLogger().warning("Error while importing: '" + line + "': " + ex.getMessage()); - writer.write(line + newline); - errors++; - } - conn.commit(); - reader.close(); - sqlFile.delete(); - getLogger().info("Successfully imported " + sqlFile.getName() + "."); - } - writer.close(); - st.close(); - getLogger().info("Successfully imported stored queue. (" + successes + " rows imported, " + errors + " errors)"); - } catch (final Exception ex) { - getLogger().log(Level.WARNING, "Error while importing: ", ex); - } finally { - if (conn != null) - try { - conn.close(); - } catch (final SQLException ex) { - } - } - } - } + DumpedLogImporter(LogBlock logblock) { + this.logblock = logblock; + } + + @Override + public void run() { + final File[] imports = new File("plugins/LogBlock/import/").listFiles(new ExtensionFilenameFilter("sql")); + if (imports != null && imports.length > 0) { + getLogger().info("Found " + imports.length + " imports."); + Connection conn = null; + try { + conn = logblock.getConnection(); + if (conn == null) { + return; + } + conn.setAutoCommit(false); + final Statement st = conn.createStatement(); + final BufferedWriter writer = new BufferedWriter(new FileWriter(new File(logblock.getDataFolder(), "import/failed.txt"))); + int successes = 0, errors = 0; + for (final File sqlFile : imports) { + getLogger().info("Trying to import " + sqlFile.getName() + " ..."); + final BufferedReader reader = new BufferedReader(new FileReader(sqlFile)); + String line; + while ((line = reader.readLine()) != null) { + try { + st.execute(line); + successes++; + } catch (final Exception ex) { + getLogger().warning("Error while importing: '" + line + "': " + ex.getMessage()); + writer.write(line + newline); + errors++; + } + } + conn.commit(); + reader.close(); + sqlFile.delete(); + getLogger().info("Successfully imported " + sqlFile.getName() + "."); + } + writer.close(); + st.close(); + getLogger().info("Successfully imported stored queue. (" + successes + " rows imported, " + errors + " errors)"); + } catch (final Exception ex) { + getLogger().log(Level.WARNING, "Error while importing: ", ex); + } finally { + if (conn != null) { + try { + conn.close(); + } catch (final SQLException ex) { + } + } + } + } + } } diff --git a/src/main/java/de/diddiz/LogBlock/Kill.java b/src/main/java/de/diddiz/LogBlock/Kill.java index 058265d..3e58631 100755 --- a/src/main/java/de/diddiz/LogBlock/Kill.java +++ b/src/main/java/de/diddiz/LogBlock/Kill.java @@ -1,65 +1,66 @@ package de.diddiz.LogBlock; -import java.sql.ResultSet; -import java.sql.SQLException; +import de.diddiz.LogBlock.config.Config; import org.bukkit.Location; import org.bukkit.inventory.ItemStack; -import de.diddiz.LogBlock.config.Config; +import java.sql.ResultSet; +import java.sql.SQLException; -public class Kill implements LookupCacheElement -{ - final long id, date; - public final Location loc; - final String killerName, victimName; - final int weapon; +public class Kill implements LookupCacheElement { + final long id, date; + public final Location loc; + final String killerName, victimName; + final int weapon; - public Kill(String killerName, String victimName, int weapon, Location loc) { - id = 0; - date = System.currentTimeMillis() / 1000; - this.loc = loc; - this.killerName = killerName; - this.victimName = victimName; - this.weapon = weapon; - } + public Kill(String killerName, String victimName, int weapon, Location loc) { + id = 0; + date = System.currentTimeMillis() / 1000; + this.loc = loc; + this.killerName = killerName; + this.victimName = victimName; + this.weapon = weapon; + } - public Kill(ResultSet rs, QueryParams p) throws SQLException { - id = p.needId ? rs.getInt("id") : 0; - date = p.needDate ? rs.getTimestamp("date").getTime() : 0; - loc = p.needCoords ? new Location(p.world, rs.getInt("x"), rs.getInt("y"), rs.getInt("z")) : null; - killerName = p.needKiller ? rs.getString("killer") : null; - victimName = p.needVictim ? rs.getString("victim") : null; - weapon = p.needWeapon ? rs.getInt("weapon") : 0; - } + public Kill(ResultSet rs, QueryParams p) throws SQLException { + id = p.needId ? rs.getInt("id") : 0; + date = p.needDate ? rs.getTimestamp("date").getTime() : 0; + loc = p.needCoords ? new Location(p.world, rs.getInt("x"), rs.getInt("y"), rs.getInt("z")) : null; + killerName = p.needKiller ? rs.getString("killer") : null; + victimName = p.needVictim ? rs.getString("victim") : null; + weapon = p.needWeapon ? rs.getInt("weapon") : 0; + } - @Override - public String toString() { - final StringBuilder msg = new StringBuilder(); - if (date > 0) - msg.append(Config.formatter.format(date)).append(" "); - msg.append(killerName).append(" killed ").append(victimName); - if (loc != null) - msg.append(" at ").append(loc.getBlockX()).append(":").append(loc.getBlockY()).append(":").append(loc.getBlockZ()); - String weaponName = prettyItemName(new ItemStack(weapon)); - msg.append(" with " + weaponName); // + ("aeiou".contains(weaponName.substring(0, 1)) ? "an " : "a " ) - return msg.toString(); - } + @Override + public String toString() { + final StringBuilder msg = new StringBuilder(); + if (date > 0) { + msg.append(Config.formatter.format(date)).append(" "); + } + msg.append(killerName).append(" killed ").append(victimName); + if (loc != null) { + msg.append(" at ").append(loc.getBlockX()).append(":").append(loc.getBlockY()).append(":").append(loc.getBlockZ()); + } + String weaponName = prettyItemName(new ItemStack(weapon)); + msg.append(" with " + weaponName); // + ("aeiou".contains(weaponName.substring(0, 1)) ? "an " : "a " ) + return msg.toString(); + } - @Override - public Location getLocation() { - return loc; - } + @Override + public Location getLocation() { + return loc; + } - @Override - public String getMessage() { - return toString(); - } + @Override + public String getMessage() { + return toString(); + } - public String prettyItemName(ItemStack i) { - String item = i.getType().toString().replace('_', ' ' ).toLowerCase(); - if(item.equals("air")) { - item = "fist"; - } - return item; - } + public String prettyItemName(ItemStack i) { + String item = i.getType().toString().replace('_', ' ').toLowerCase(); + if (item.equals("air")) { + item = "fist"; + } + return item; + } } diff --git a/src/main/java/de/diddiz/LogBlock/LogBlock.java b/src/main/java/de/diddiz/LogBlock/LogBlock.java index 860701e..47078cb 100644 --- a/src/main/java/de/diddiz/LogBlock/LogBlock.java +++ b/src/main/java/de/diddiz/LogBlock/LogBlock.java @@ -1,28 +1,7 @@ package de.diddiz.LogBlock; import de.diddiz.LogBlock.config.Config; -import de.diddiz.LogBlock.listeners.BanListener; -import de.diddiz.LogBlock.listeners.BlockBreakLogging; -import de.diddiz.LogBlock.listeners.BlockBurnLogging; -import de.diddiz.LogBlock.listeners.BlockPlaceLogging; -import de.diddiz.LogBlock.listeners.BlockSpreadLogging; -import de.diddiz.LogBlock.listeners.ChatLogging; -import de.diddiz.LogBlock.listeners.ChestAccessLogging; -import de.diddiz.LogBlock.listeners.CreatureInteractLogging; -import de.diddiz.LogBlock.listeners.EndermenLogging; -import de.diddiz.LogBlock.listeners.ExplosionLogging; -import de.diddiz.LogBlock.listeners.FluidFlowLogging; -import de.diddiz.LogBlock.listeners.InteractLogging; -import de.diddiz.LogBlock.listeners.KillLogging; -import de.diddiz.LogBlock.listeners.LeavesDecayLogging; -import de.diddiz.LogBlock.listeners.LockedChestDecayLogging; -import de.diddiz.LogBlock.listeners.PlayerInfoLogging; -import de.diddiz.LogBlock.listeners.SignChangeLogging; -import de.diddiz.LogBlock.listeners.SnowFadeLogging; -import de.diddiz.LogBlock.listeners.SnowFormLogging; -import de.diddiz.LogBlock.listeners.StructureGrowLogging; -import de.diddiz.LogBlock.listeners.ToolListener; -import de.diddiz.LogBlock.listeners.WitherLogging; +import de.diddiz.LogBlock.listeners.*; import de.diddiz.util.MySQLConnectionPool; import de.diddiz.worldedit.WorldEditLoggingHook; import org.bukkit.ChatColor; @@ -48,269 +27,301 @@ import static de.diddiz.LogBlock.config.Config.*; import static de.diddiz.util.MaterialName.materialName; import static org.bukkit.Bukkit.getPluginManager; -public class LogBlock extends JavaPlugin -{ - private static LogBlock logblock = null; - private MySQLConnectionPool pool; - private Consumer consumer = null; - private CommandsHandler commandsHandler; - private Updater updater = null; - private Timer timer = null; - private boolean errorAtLoading = false, noDb = false, connected = true; +public class LogBlock extends JavaPlugin { + private static LogBlock logblock = null; + private MySQLConnectionPool pool; + private Consumer consumer = null; + private CommandsHandler commandsHandler; + private Updater updater = null; + private Timer timer = null; + private boolean errorAtLoading = false, noDb = false, connected = true; - public static LogBlock getInstance() { - return logblock; - } + public static LogBlock getInstance() { + return logblock; + } - public Consumer getConsumer() { - return consumer; - } + public Consumer getConsumer() { + return consumer; + } - public CommandsHandler getCommandsHandler() { - return commandsHandler; - } + public CommandsHandler getCommandsHandler() { + return commandsHandler; + } - Updater getUpdater() { - return updater; - } + Updater getUpdater() { + return updater; + } - @Override - public void onLoad() { - logblock = this; - try { - updater = new Updater(this); - Config.load(this); - getLogger().info("Connecting to " + user + "@" + url + "..."); - pool = new MySQLConnectionPool(url, user, password); - final Connection conn = getConnection(); - if (conn == null) { - noDb = true; - return; - } - final Statement st = conn.createStatement(); - final ResultSet rs = st.executeQuery("SHOW CHARACTER SET where charset='utf8mb4';"); - if (rs.next()) { - Config.mb4=true; - // Allegedly JDBC driver since 2010 hasn't needed this. I did. - st.executeQuery("SET NAMES utf8mb4;"); - } - conn.close(); - if (updater.update()) - load(this); - updater.checkTables(); - } catch (final NullPointerException ex) { - getLogger().log(Level.SEVERE, "Error while loading: ", ex); - } catch (final Exception ex) { - getLogger().severe("Error while loading: " + ex.getMessage()); - errorAtLoading = true; - return; - } - consumer = new Consumer(this); - } + @Override + public void onLoad() { + logblock = this; + try { + updater = new Updater(this); + Config.load(this); + getLogger().info("Connecting to " + user + "@" + url + "..."); + pool = new MySQLConnectionPool(url, user, password); + final Connection conn = getConnection(); + if (conn == null) { + noDb = true; + return; + } + final Statement st = conn.createStatement(); + final ResultSet rs = st.executeQuery("SHOW CHARACTER SET where charset='utf8mb4';"); + if (rs.next()) { + Config.mb4 = true; + // Allegedly JDBC driver since 2010 hasn't needed this. I did. + st.executeQuery("SET NAMES utf8mb4;"); + } + conn.close(); + if (updater.update()) { + load(this); + } + updater.checkTables(); + } catch (final NullPointerException ex) { + getLogger().log(Level.SEVERE, "Error while loading: ", ex); + } catch (final Exception ex) { + getLogger().severe("Error while loading: " + ex.getMessage()); + errorAtLoading = true; + return; + } + consumer = new Consumer(this); + } - @Override - public void onEnable() { - materialName(0); // Force static code to run - final PluginManager pm = getPluginManager(); - if (errorAtLoading) { - pm.disablePlugin(this); - return; - } - if (noDb) - return; - if (pm.getPlugin("WorldEdit") != null) { - if(Integer.parseInt(pm.getPlugin("WorldEdit").getDescription().getVersion().substring(0, 1)) > 5) { - new WorldEditLoggingHook(this).hook(); - } else { - getLogger().warning("Failed to hook into WorldEdit. Your WorldEdit version seems to be outdated, please make sure WorldEdit is at least version 6."); - } - } - commandsHandler = new CommandsHandler(this); - getCommand("lb").setExecutor(commandsHandler); - if (enableAutoClearLog && autoClearLogDelay > 0) - getServer().getScheduler().runTaskTimerAsynchronously(this, new AutoClearLog(this), 6000, autoClearLogDelay * 60 * 20); - getServer().getScheduler().runTaskAsynchronously(this, new DumpedLogImporter(this)); - registerEvents(); - if (useBukkitScheduler) { - if (getServer().getScheduler().runTaskTimerAsynchronously(this, consumer, delayBetweenRuns < 20 ? 20 : delayBetweenRuns, delayBetweenRuns).getTaskId() > 0) - getLogger().info("Scheduled consumer with bukkit scheduler."); - else { - getLogger().warning("Failed to schedule consumer with bukkit scheduler. Now trying schedule with timer."); - timer = new Timer(); - timer.schedule(consumer, delayBetweenRuns < 20 ? 1000 : delayBetweenRuns * 50, delayBetweenRuns * 50); - } - } else { - timer = new Timer(); - timer.schedule(consumer, delayBetweenRuns < 20 ? 1000 : delayBetweenRuns * 50, delayBetweenRuns * 50); - getLogger().info("Scheduled consumer with timer."); - } - getServer().getScheduler().runTaskAsynchronously(this, new Updater.PlayerCountChecker(this)); - for (final Tool tool : toolsByType.values()) - if (pm.getPermission("logblock.tools." + tool.name) == null) { - final Permission perm = new Permission("logblock.tools." + tool.name, tool.permissionDefault); - pm.addPermission(perm); - } - try { - Metrics metrics = new Metrics(this); - metrics.start(); - } catch (IOException ex) { - getLogger().info("Could not start metrics: " + ex.getMessage()); - } - } + @Override + public void onEnable() { + materialName(0); // Force static code to run + final PluginManager pm = getPluginManager(); + if (errorAtLoading) { + pm.disablePlugin(this); + return; + } + if (noDb) { + return; + } + if (pm.getPlugin("WorldEdit") != null) { + if (Integer.parseInt(pm.getPlugin("WorldEdit").getDescription().getVersion().substring(0, 1)) > 5) { + new WorldEditLoggingHook(this).hook(); + } else { + getLogger().warning("Failed to hook into WorldEdit. Your WorldEdit version seems to be outdated, please make sure WorldEdit is at least version 6."); + } + } + commandsHandler = new CommandsHandler(this); + getCommand("lb").setExecutor(commandsHandler); + if (enableAutoClearLog && autoClearLogDelay > 0) { + getServer().getScheduler().runTaskTimerAsynchronously(this, new AutoClearLog(this), 6000, autoClearLogDelay * 60 * 20); + } + getServer().getScheduler().runTaskAsynchronously(this, new DumpedLogImporter(this)); + registerEvents(); + if (useBukkitScheduler) { + if (getServer().getScheduler().runTaskTimerAsynchronously(this, consumer, delayBetweenRuns < 20 ? 20 : delayBetweenRuns, delayBetweenRuns).getTaskId() > 0) { + getLogger().info("Scheduled consumer with bukkit scheduler."); + } else { + getLogger().warning("Failed to schedule consumer with bukkit scheduler. Now trying schedule with timer."); + timer = new Timer(); + timer.schedule(consumer, delayBetweenRuns < 20 ? 1000 : delayBetweenRuns * 50, delayBetweenRuns * 50); + } + } else { + timer = new Timer(); + timer.schedule(consumer, delayBetweenRuns < 20 ? 1000 : delayBetweenRuns * 50, delayBetweenRuns * 50); + getLogger().info("Scheduled consumer with timer."); + } + getServer().getScheduler().runTaskAsynchronously(this, new Updater.PlayerCountChecker(this)); + for (final Tool tool : toolsByType.values()) { + if (pm.getPermission("logblock.tools." + tool.name) == null) { + final Permission perm = new Permission("logblock.tools." + tool.name, tool.permissionDefault); + pm.addPermission(perm); + } + } + try { + Metrics metrics = new Metrics(this); + metrics.start(); + } catch (IOException ex) { + getLogger().info("Could not start metrics: " + ex.getMessage()); + } + } - private void registerEvents() { - final PluginManager pm = getPluginManager(); - pm.registerEvents(new ToolListener(this), this); - pm.registerEvents(new PlayerInfoLogging(this), this); - if (askRollbackAfterBan) - pm.registerEvents(new BanListener(this), this); - if (isLogging(Logging.BLOCKPLACE)) - pm.registerEvents(new BlockPlaceLogging(this), this); - if (isLogging(Logging.BLOCKPLACE) || isLogging(Logging.LAVAFLOW) || isLogging(Logging.WATERFLOW)) - pm.registerEvents(new FluidFlowLogging(this), this); - if (isLogging(Logging.BLOCKBREAK)) - pm.registerEvents(new BlockBreakLogging(this), this); - if (isLogging(Logging.SIGNTEXT)) - pm.registerEvents(new SignChangeLogging(this), this); - if (isLogging(Logging.FIRE)) - pm.registerEvents(new BlockBurnLogging(this), this); - if (isLogging(Logging.SNOWFORM)) - pm.registerEvents(new SnowFormLogging(this), this); - if (isLogging(Logging.SNOWFADE)) - pm.registerEvents(new SnowFadeLogging(this), this); - if (isLogging(Logging.CREEPEREXPLOSION) || isLogging(Logging.TNTEXPLOSION) || isLogging(Logging.GHASTFIREBALLEXPLOSION) || isLogging(Logging.ENDERDRAGON) || isLogging(Logging.MISCEXPLOSION)) - pm.registerEvents(new ExplosionLogging(this), this); - if (isLogging(Logging.LEAVESDECAY)) - pm.registerEvents(new LeavesDecayLogging(this), this); - if (isLogging(Logging.CHESTACCESS)) { - pm.registerEvents(new ChestAccessLogging(this), this); - } - if (isLogging(Logging.SWITCHINTERACT) || isLogging(Logging.DOORINTERACT) || isLogging(Logging.CAKEEAT) || isLogging(Logging.DIODEINTERACT) || isLogging(Logging.COMPARATORINTERACT) || isLogging(Logging.NOTEBLOCKINTERACT) || isLogging(Logging.PRESUREPLATEINTERACT) || isLogging(Logging.TRIPWIREINTERACT) || isLogging(Logging.CROPTRAMPLE)) - pm.registerEvents(new InteractLogging(this), this); - if (isLogging(Logging.CREATURECROPTRAMPLE)) { - pm.registerEvents(new CreatureInteractLogging(this), this); - } - if (isLogging(Logging.KILL)) - pm.registerEvents(new KillLogging(this), this); - if (isLogging(Logging.CHAT)) - pm.registerEvents(new ChatLogging(this), this); - if (isLogging(Logging.ENDERMEN)) - pm.registerEvents(new EndermenLogging(this), this); - if (isLogging(Logging.WITHER)) - pm.registerEvents(new WitherLogging(this), this); - if (isLogging(Logging.NATURALSTRUCTUREGROW) || isLogging(Logging.BONEMEALSTRUCTUREGROW)) - pm.registerEvents(new StructureGrowLogging(this), this); - if (isLogging(Logging.GRASSGROWTH) || isLogging(Logging.MYCELIUMSPREAD) || isLogging(Logging.VINEGROWTH) || isLogging(Logging.MUSHROOMSPREAD)) - pm.registerEvents(new BlockSpreadLogging(this), this); - if (isLogging(Logging.LOCKEDCHESTDECAY)) - pm.registerEvents(new LockedChestDecayLogging(this), this); - } + private void registerEvents() { + final PluginManager pm = getPluginManager(); + pm.registerEvents(new ToolListener(this), this); + pm.registerEvents(new PlayerInfoLogging(this), this); + if (askRollbackAfterBan) { + pm.registerEvents(new BanListener(this), this); + } + if (isLogging(Logging.BLOCKPLACE)) { + pm.registerEvents(new BlockPlaceLogging(this), this); + } + if (isLogging(Logging.BLOCKPLACE) || isLogging(Logging.LAVAFLOW) || isLogging(Logging.WATERFLOW)) { + pm.registerEvents(new FluidFlowLogging(this), this); + } + if (isLogging(Logging.BLOCKBREAK)) { + pm.registerEvents(new BlockBreakLogging(this), this); + } + if (isLogging(Logging.SIGNTEXT)) { + pm.registerEvents(new SignChangeLogging(this), this); + } + if (isLogging(Logging.FIRE)) { + pm.registerEvents(new BlockBurnLogging(this), this); + } + if (isLogging(Logging.SNOWFORM)) { + pm.registerEvents(new SnowFormLogging(this), this); + } + if (isLogging(Logging.SNOWFADE)) { + pm.registerEvents(new SnowFadeLogging(this), this); + } + if (isLogging(Logging.CREEPEREXPLOSION) || isLogging(Logging.TNTEXPLOSION) || isLogging(Logging.GHASTFIREBALLEXPLOSION) || isLogging(Logging.ENDERDRAGON) || isLogging(Logging.MISCEXPLOSION)) { + pm.registerEvents(new ExplosionLogging(this), this); + } + if (isLogging(Logging.LEAVESDECAY)) { + pm.registerEvents(new LeavesDecayLogging(this), this); + } + if (isLogging(Logging.CHESTACCESS)) { + pm.registerEvents(new ChestAccessLogging(this), this); + } + if (isLogging(Logging.SWITCHINTERACT) || isLogging(Logging.DOORINTERACT) || isLogging(Logging.CAKEEAT) || isLogging(Logging.DIODEINTERACT) || isLogging(Logging.COMPARATORINTERACT) || isLogging(Logging.NOTEBLOCKINTERACT) || isLogging(Logging.PRESUREPLATEINTERACT) || isLogging(Logging.TRIPWIREINTERACT) || isLogging(Logging.CROPTRAMPLE)) { + pm.registerEvents(new InteractLogging(this), this); + } + if (isLogging(Logging.CREATURECROPTRAMPLE)) { + pm.registerEvents(new CreatureInteractLogging(this), this); + } + if (isLogging(Logging.KILL)) { + pm.registerEvents(new KillLogging(this), this); + } + if (isLogging(Logging.CHAT)) { + pm.registerEvents(new ChatLogging(this), this); + } + if (isLogging(Logging.ENDERMEN)) { + pm.registerEvents(new EndermenLogging(this), this); + } + if (isLogging(Logging.WITHER)) { + pm.registerEvents(new WitherLogging(this), this); + } + if (isLogging(Logging.NATURALSTRUCTUREGROW) || isLogging(Logging.BONEMEALSTRUCTUREGROW)) { + pm.registerEvents(new StructureGrowLogging(this), this); + } + if (isLogging(Logging.GRASSGROWTH) || isLogging(Logging.MYCELIUMSPREAD) || isLogging(Logging.VINEGROWTH) || isLogging(Logging.MUSHROOMSPREAD)) { + pm.registerEvents(new BlockSpreadLogging(this), this); + } + if (isLogging(Logging.LOCKEDCHESTDECAY)) { + pm.registerEvents(new LockedChestDecayLogging(this), this); + } + } - @Override - public void onDisable() { - if (timer != null) - timer.cancel(); - getServer().getScheduler().cancelTasks(this); - if (consumer != null) { - if (logPlayerInfo && getServer().getOnlinePlayers() != null) - for (final Player player : getServer().getOnlinePlayers()) - consumer.queueLeave(player); - getLogger().info("Waiting for consumer ..."); - consumer.run(); - if (consumer.getQueueSize() > 0) { - int tries = 9; - while (consumer.getQueueSize() > 0) { - getLogger().info("Remaining queue size: " + consumer.getQueueSize()); - if (tries > 0) - getLogger().info("Remaining tries: " + tries); - else { - getLogger().info("Unable to save queue to database. Trying to write to a local file."); - try { - consumer.writeToFile(); - getLogger().info("Successfully dumped queue."); - } catch (final FileNotFoundException ex) { - getLogger().info("Failed to write. Given up."); - break; - } - } - consumer.run(); - tries--; - } - } - } - if (pool != null) - pool.close(); - } + @Override + public void onDisable() { + if (timer != null) { + timer.cancel(); + } + getServer().getScheduler().cancelTasks(this); + if (consumer != null) { + if (logPlayerInfo && getServer().getOnlinePlayers() != null) { + for (final Player player : getServer().getOnlinePlayers()) { + consumer.queueLeave(player); + } + } + getLogger().info("Waiting for consumer ..."); + consumer.run(); + if (consumer.getQueueSize() > 0) { + int tries = 9; + while (consumer.getQueueSize() > 0) { + getLogger().info("Remaining queue size: " + consumer.getQueueSize()); + if (tries > 0) { + getLogger().info("Remaining tries: " + tries); + } else { + getLogger().info("Unable to save queue to database. Trying to write to a local file."); + try { + consumer.writeToFile(); + getLogger().info("Successfully dumped queue."); + } catch (final FileNotFoundException ex) { + getLogger().info("Failed to write. Given up."); + break; + } + } + consumer.run(); + tries--; + } + } + } + if (pool != null) { + pool.close(); + } + } - @Override - public boolean onCommand(CommandSender sender, Command cmd, String commandLabel, String[] args) { - if (noDb) - sender.sendMessage(ChatColor.RED + "No database connected. Check your MySQL user/pw and database for typos. Start/restart your MySQL server."); - return true; - } + @Override + public boolean onCommand(CommandSender sender, Command cmd, String commandLabel, String[] args) { + if (noDb) { + sender.sendMessage(ChatColor.RED + "No database connected. Check your MySQL user/pw and database for typos. Start/restart your MySQL server."); + } + return true; + } - public boolean hasPermission(CommandSender sender, String permission) { - return sender.hasPermission(permission); - } + public boolean hasPermission(CommandSender sender, String permission) { + return sender.hasPermission(permission); + } - public Connection getConnection() { - try { - final Connection conn = pool.getConnection(); - if (!connected) { - getLogger().info("MySQL connection rebuild"); - connected = true; - } - return conn; - } catch (final Exception ex) { - if (connected) { - getLogger().log(Level.SEVERE, "Error while fetching connection: ", ex); - connected = false; - } else - getLogger().severe("MySQL connection lost"); - return null; - } - } + public Connection getConnection() { + try { + final Connection conn = pool.getConnection(); + if (!connected) { + getLogger().info("MySQL connection rebuild"); + connected = true; + } + return conn; + } catch (final Exception ex) { + if (connected) { + getLogger().log(Level.SEVERE, "Error while fetching connection: ", ex); + connected = false; + } else { + getLogger().severe("MySQL connection lost"); + } + return null; + } + } - /** - * @param params - * QueryParams that contains the needed columns (all other will be filled with default values) and the params. World is required. - */ - public List getBlockChanges(QueryParams params) throws SQLException { - final Connection conn = getConnection(); - Statement state = null; - if (conn == null) - throw new SQLException("No connection"); - try { - state = conn.createStatement(); - final ResultSet rs = state.executeQuery(params.getQuery()); - final List blockchanges = new ArrayList(); - while (rs.next()) - blockchanges.add(new BlockChange(rs, params)); - return blockchanges; - } finally { - if (state != null) - state.close(); - conn.close(); - } - } + /** + * @param params QueryParams that contains the needed columns (all other will be filled with default values) and the params. World is required. + */ + public List getBlockChanges(QueryParams params) throws SQLException { + final Connection conn = getConnection(); + Statement state = null; + if (conn == null) { + throw new SQLException("No connection"); + } + try { + state = conn.createStatement(); + final ResultSet rs = state.executeQuery(params.getQuery()); + final List blockchanges = new ArrayList(); + while (rs.next()) { + blockchanges.add(new BlockChange(rs, params)); + } + return blockchanges; + } finally { + if (state != null) { + state.close(); + } + conn.close(); + } + } - public int getCount(QueryParams params) throws SQLException { - final Connection conn = getConnection(); - Statement state = null; - if (conn == null) - throw new SQLException("No connection"); - try { - state = conn.createStatement(); - final QueryParams p = params.clone(); - p.needCount = true; - final ResultSet rs = state.executeQuery(p.getQuery()); - if (!rs.next()) - return 0; - return rs.getInt(1); - } finally { - if (state != null) - state.close(); - conn.close(); - } - } + public int getCount(QueryParams params) throws SQLException { + final Connection conn = getConnection(); + Statement state = null; + if (conn == null) { + throw new SQLException("No connection"); + } + try { + state = conn.createStatement(); + final QueryParams p = params.clone(); + p.needCount = true; + final ResultSet rs = state.executeQuery(p.getQuery()); + if (!rs.next()) { + return 0; + } + return rs.getInt(1); + } finally { + if (state != null) { + state.close(); + } + conn.close(); + } + } } diff --git a/src/main/java/de/diddiz/LogBlock/Logging.java b/src/main/java/de/diddiz/LogBlock/Logging.java index 80e2f6d..7776518 100644 --- a/src/main/java/de/diddiz/LogBlock/Logging.java +++ b/src/main/java/de/diddiz/LogBlock/Logging.java @@ -1,28 +1,27 @@ package de.diddiz.LogBlock; -public enum Logging -{ - BLOCKPLACE(true), BLOCKBREAK(true), SIGNTEXT, TNTEXPLOSION(true), CREEPEREXPLOSION(true), - GHASTFIREBALLEXPLOSION(true), ENDERDRAGON(true), MISCEXPLOSION, FIRE(true), LEAVESDECAY, - LAVAFLOW, WATERFLOW, CHESTACCESS, KILL, CHAT, SNOWFORM, SNOWFADE, DOORINTERACT, - SWITCHINTERACT, CAKEEAT, ENDERMEN, NOTEBLOCKINTERACT, DIODEINTERACT, COMPARATORINTERACT, - PRESUREPLATEINTERACT, TRIPWIREINTERACT, CREATURECROPTRAMPLE, CROPTRAMPLE, - NATURALSTRUCTUREGROW, GRASSGROWTH, MYCELIUMSPREAD, VINEGROWTH, MUSHROOMSPREAD, - WITHER(true), WITHER_SKULL(true), BONEMEALSTRUCTUREGROW, - WORLDEDIT, TNTMINECARTEXPLOSION(true), LOCKEDCHESTDECAY; +public enum Logging { + BLOCKPLACE(true), BLOCKBREAK(true), SIGNTEXT, TNTEXPLOSION(true), CREEPEREXPLOSION(true), + GHASTFIREBALLEXPLOSION(true), ENDERDRAGON(true), MISCEXPLOSION, FIRE(true), LEAVESDECAY, + LAVAFLOW, WATERFLOW, CHESTACCESS, KILL, CHAT, SNOWFORM, SNOWFADE, DOORINTERACT, + SWITCHINTERACT, CAKEEAT, ENDERMEN, NOTEBLOCKINTERACT, DIODEINTERACT, COMPARATORINTERACT, + PRESUREPLATEINTERACT, TRIPWIREINTERACT, CREATURECROPTRAMPLE, CROPTRAMPLE, + NATURALSTRUCTUREGROW, GRASSGROWTH, MYCELIUMSPREAD, VINEGROWTH, MUSHROOMSPREAD, + WITHER(true), WITHER_SKULL(true), BONEMEALSTRUCTUREGROW, + WORLDEDIT, TNTMINECARTEXPLOSION(true), LOCKEDCHESTDECAY; - public static final int length = Logging.values().length; - private final boolean defaultEnabled; + public static final int length = Logging.values().length; + private final boolean defaultEnabled; - private Logging() { - this(false); - } + private Logging() { + this(false); + } - private Logging(boolean defaultEnabled) { - this.defaultEnabled = defaultEnabled; - } + private Logging(boolean defaultEnabled) { + this.defaultEnabled = defaultEnabled; + } - public boolean isDefaultEnabled() { - return defaultEnabled; - } + public boolean isDefaultEnabled() { + return defaultEnabled; + } } diff --git a/src/main/java/de/diddiz/LogBlock/LookupCacheElement.java b/src/main/java/de/diddiz/LogBlock/LookupCacheElement.java index bf2cdc9..595a2e3 100644 --- a/src/main/java/de/diddiz/LogBlock/LookupCacheElement.java +++ b/src/main/java/de/diddiz/LogBlock/LookupCacheElement.java @@ -2,9 +2,8 @@ package de.diddiz.LogBlock; import org.bukkit.Location; -public interface LookupCacheElement -{ - public Location getLocation(); +public interface LookupCacheElement { + public Location getLocation(); - public String getMessage(); + public String getMessage(); } diff --git a/src/main/java/de/diddiz/LogBlock/LookupCacheElementFactory.java b/src/main/java/de/diddiz/LogBlock/LookupCacheElementFactory.java index 2822878..6a1af34 100755 --- a/src/main/java/de/diddiz/LogBlock/LookupCacheElementFactory.java +++ b/src/main/java/de/diddiz/LogBlock/LookupCacheElementFactory.java @@ -1,30 +1,34 @@ package de.diddiz.LogBlock; -import java.sql.ResultSet; -import java.sql.SQLException; import de.diddiz.LogBlock.QueryParams.BlockChangeType; import de.diddiz.LogBlock.QueryParams.SummarizationMode; -public class LookupCacheElementFactory -{ - private final QueryParams params; - private final float spaceFactor; +import java.sql.ResultSet; +import java.sql.SQLException; - public LookupCacheElementFactory(QueryParams params, float spaceFactor) { - this.params = params; - this.spaceFactor = spaceFactor; - } +public class LookupCacheElementFactory { + private final QueryParams params; + private final float spaceFactor; - public LookupCacheElement getLookupCacheElement(ResultSet rs) throws SQLException { - if (params.bct == BlockChangeType.CHAT) - return new ChatMessage(rs, params); - if (params.bct == BlockChangeType.KILLS) - if (params.sum == SummarizationMode.NONE) - return new Kill(rs, params); - else if (params.sum == SummarizationMode.PLAYERS) - return new SummedKills(rs, params, spaceFactor); - if (params.sum == SummarizationMode.NONE) - return new BlockChange(rs, params); - return new SummedBlockChanges(rs, params, spaceFactor); - } + public LookupCacheElementFactory(QueryParams params, float spaceFactor) { + this.params = params; + this.spaceFactor = spaceFactor; + } + + public LookupCacheElement getLookupCacheElement(ResultSet rs) throws SQLException { + if (params.bct == BlockChangeType.CHAT) { + return new ChatMessage(rs, params); + } + if (params.bct == BlockChangeType.KILLS) { + if (params.sum == SummarizationMode.NONE) { + return new Kill(rs, params); + } else if (params.sum == SummarizationMode.PLAYERS) { + return new SummedKills(rs, params, spaceFactor); + } + } + if (params.sum == SummarizationMode.NONE) { + return new BlockChange(rs, params); + } + return new SummedBlockChanges(rs, params, spaceFactor); + } } diff --git a/src/main/java/de/diddiz/LogBlock/Metrics.java b/src/main/java/de/diddiz/LogBlock/Metrics.java index 29f64de..6a542b4 100644 --- a/src/main/java/de/diddiz/LogBlock/Metrics.java +++ b/src/main/java/de/diddiz/LogBlock/Metrics.java @@ -34,726 +34,717 @@ import org.bukkit.plugin.Plugin; import org.bukkit.plugin.PluginDescriptionFile; import org.bukkit.scheduler.BukkitTask; -import java.io.BufferedReader; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.OutputStream; -import java.io.UnsupportedEncodingException; +import java.io.*; import java.net.Proxy; import java.net.URL; import java.net.URLConnection; import java.net.URLEncoder; -import java.util.Collections; -import java.util.HashSet; -import java.util.Iterator; -import java.util.LinkedHashSet; -import java.util.Set; -import java.util.UUID; +import java.util.*; import java.util.logging.Level; import java.util.zip.GZIPOutputStream; public class Metrics { - /** - * The current revision number - */ - private final static int REVISION = 7; - - /** - * The base url of the metrics domain - */ - private static final String BASE_URL = "http://report.mcstats.org"; - - /** - * The url used to report a server's status - */ - private static final String REPORT_URL = "/plugin/%s"; - - /** - * Interval of time to ping (in minutes) - */ - private static final int PING_INTERVAL = 15; - - /** - * The plugin this metrics submits for - */ - private final Plugin plugin; - - /** - * All of the custom graphs to submit to metrics - */ - private final Set graphs = Collections.synchronizedSet(new HashSet()); - - /** - * The plugin configuration file - */ - private final YamlConfiguration configuration; - - /** - * The plugin configuration file - */ - private final File configurationFile; - - /** - * Unique server id - */ - private final String guid; - - /** - * Debug mode - */ - private final boolean debug; - - /** - * Lock for synchronization - */ - private final Object optOutLock = new Object(); - - /** - * The scheduled task - */ - private volatile BukkitTask task = null; - - public Metrics(final Plugin plugin) throws IOException { - if (plugin == null) { - throw new IllegalArgumentException("Plugin cannot be null"); - } - - this.plugin = plugin; - - // load the config - configurationFile = getConfigFile(); - configuration = YamlConfiguration.loadConfiguration(configurationFile); - - // add some defaults - configuration.addDefault("opt-out", false); - configuration.addDefault("guid", UUID.randomUUID().toString()); - configuration.addDefault("debug", false); - - // Do we need to create the file? - if (configuration.get("guid", null) == null) { - configuration.options().header("http://mcstats.org").copyDefaults(true); - configuration.save(configurationFile); - } - - // Load the guid then - guid = configuration.getString("guid"); - debug = configuration.getBoolean("debug", false); - } - - /** - * Construct and create a Graph that can be used to separate specific plotters to their own graphs on the metrics - * website. Plotters can be added to the graph object returned. - * - * @param name The name of the graph - * @return Graph object created. Will never return NULL under normal circumstances unless bad parameters are given - */ - public Graph createGraph(final String name) { - if (name == null) { - throw new IllegalArgumentException("Graph name cannot be null"); - } - - // Construct the graph object - final Graph graph = new Graph(name); - - // Now we can add our graph - graphs.add(graph); - - // and return back - return graph; - } - - /** - * Add a Graph object to BukkitMetrics that represents data for the plugin that should be sent to the backend - * - * @param graph The name of the graph - */ - public void addGraph(final Graph graph) { - if (graph == null) { - throw new IllegalArgumentException("Graph cannot be null"); - } - - graphs.add(graph); - } - - /** - * Start measuring statistics. This will immediately create an async repeating task as the plugin and send the - * initial data to the metrics backend, and then after that it will post in increments of PING_INTERVAL * 1200 - * ticks. - * - * @return True if statistics measuring is running, otherwise false. - */ - public boolean start() { - synchronized (optOutLock) { - // Did we opt out? - if (isOptOut()) { - return false; - } - - // Is metrics already running? - if (task != null) { - return true; - } - - // Begin hitting the server with glorious data - task = plugin.getServer().getScheduler().runTaskTimerAsynchronously(plugin, new Runnable() { - - private boolean firstPost = true; - - public void run() { - try { - // This has to be synchronized or it can collide with the disable method. - synchronized (optOutLock) { - // Disable Task, if it is running and the server owner decided to opt-out - if (isOptOut() && task != null) { - task.cancel(); - task = null; - // Tell all plotters to stop gathering information. - for (Graph graph : graphs) { - graph.onOptOut(); - } - } - } - - // We use the inverse of firstPost because if it is the first time we are posting, - // it is not a interval ping, so it evaluates to FALSE - // Each time thereafter it will evaluate to TRUE, i.e PING! - postPlugin(!firstPost); - - // After the first post we set firstPost to false - // Each post thereafter will be a ping - firstPost = false; - } catch (IOException e) { - if (debug) { - Bukkit.getLogger().log(Level.INFO, "[Metrics] " + e.getMessage()); - } - } - } - }, 0, PING_INTERVAL * 1200); - - return true; - } - } - - /** - * Has the server owner denied plugin metrics? - * - * @return true if metrics should be opted out of it - */ - public boolean isOptOut() { - synchronized (optOutLock) { - try { - // Reload the metrics file - configuration.load(getConfigFile()); - } catch (IOException ex) { - if (debug) { - Bukkit.getLogger().log(Level.INFO, "[Metrics] " + ex.getMessage()); - } - return true; - } catch (InvalidConfigurationException ex) { - if (debug) { - Bukkit.getLogger().log(Level.INFO, "[Metrics] " + ex.getMessage()); - } - return true; - } - return configuration.getBoolean("opt-out", false); - } - } - - /** - * Enables metrics for the server by setting "opt-out" to false in the config file and starting the metrics task. - * - * @throws java.io.IOException - */ - public void enable() throws IOException { - // This has to be synchronized or it can collide with the check in the task. - synchronized (optOutLock) { - // Check if the server owner has already set opt-out, if not, set it. - if (isOptOut()) { - configuration.set("opt-out", false); - configuration.save(configurationFile); - } - - // Enable Task, if it is not running - if (task == null) { - start(); - } - } - } - - /** - * Disables metrics for the server by setting "opt-out" to true in the config file and canceling the metrics task. - * - * @throws java.io.IOException - */ - public void disable() throws IOException { - // This has to be synchronized or it can collide with the check in the task. - synchronized (optOutLock) { - // Check if the server owner has already set opt-out, if not, set it. - if (!isOptOut()) { - configuration.set("opt-out", true); - configuration.save(configurationFile); - } - - // Disable Task, if it is running - if (task != null) { - task.cancel(); - task = null; - } - } - } - - /** - * Gets the File object of the config file that should be used to store data such as the GUID and opt-out status - * - * @return the File object for the config file - */ - public File getConfigFile() { - // I believe the easiest way to get the base folder (e.g craftbukkit set via -P) for plugins to use - // is to abuse the plugin object we already have - // plugin.getDataFolder() => base/plugins/PluginA/ - // pluginsFolder => base/plugins/ - // The base is not necessarily relative to the startup directory. - File pluginsFolder = plugin.getDataFolder().getParentFile(); - - // return => base/plugins/PluginMetrics/config.yml - return new File(new File(pluginsFolder, "PluginMetrics"), "config.yml"); - } - - /** - * Generic method that posts a plugin to the metrics website - */ - private void postPlugin(final boolean isPing) throws IOException { - // Server software specific section - PluginDescriptionFile description = plugin.getDescription(); - String pluginName = description.getName(); - boolean onlineMode = Bukkit.getServer().getOnlineMode(); // TRUE if online mode is enabled - String pluginVersion = description.getVersion(); - String serverVersion = Bukkit.getVersion(); - int playersOnline = Bukkit.getServer().getOnlinePlayers().length; - - // END server software specific section -- all code below does not use any code outside of this class / Java - - // Construct the post data - StringBuilder json = new StringBuilder(1024); - json.append('{'); - - // The plugin's description file containg all of the plugin data such as name, version, author, etc - appendJSONPair(json, "guid", guid); - appendJSONPair(json, "plugin_version", pluginVersion); - appendJSONPair(json, "server_version", serverVersion); - appendJSONPair(json, "players_online", Integer.toString(playersOnline)); - - // New data as of R6 - String osname = System.getProperty("os.name"); - String osarch = System.getProperty("os.arch"); - String osversion = System.getProperty("os.version"); - String java_version = System.getProperty("java.version"); - int coreCount = Runtime.getRuntime().availableProcessors(); - - // normalize os arch .. amd64 -> x86_64 - if (osarch.equals("amd64")) { - osarch = "x86_64"; - } - - appendJSONPair(json, "osname", osname); - appendJSONPair(json, "osarch", osarch); - appendJSONPair(json, "osversion", osversion); - appendJSONPair(json, "cores", Integer.toString(coreCount)); - appendJSONPair(json, "auth_mode", onlineMode ? "1" : "0"); - appendJSONPair(json, "java_version", java_version); - - // If we're pinging, append it - if (isPing) { - appendJSONPair(json, "ping", "1"); - } - - if (graphs.size() > 0) { - synchronized (graphs) { - json.append(','); - json.append('"'); - json.append("graphs"); - json.append('"'); - json.append(':'); - json.append('{'); - - boolean firstGraph = true; - - final Iterator iter = graphs.iterator(); - - while (iter.hasNext()) { - Graph graph = iter.next(); - - StringBuilder graphJson = new StringBuilder(); - graphJson.append('{'); - - for (Plotter plotter : graph.getPlotters()) { - appendJSONPair(graphJson, plotter.getColumnName(), Integer.toString(plotter.getValue())); - } - - graphJson.append('}'); - - if (!firstGraph) { - json.append(','); - } - - json.append(escapeJSON(graph.getName())); - json.append(':'); - json.append(graphJson); - - firstGraph = false; - } - - json.append('}'); - } - } - - // close json - json.append('}'); - - // Create the url - URL url = new URL(BASE_URL + String.format(REPORT_URL, urlEncode(pluginName))); - - // Connect to the website - URLConnection connection; - - // Mineshafter creates a socks proxy, so we can safely bypass it - // It does not reroute POST requests so we need to go around it - if (isMineshafterPresent()) { - connection = url.openConnection(Proxy.NO_PROXY); - } else { - connection = url.openConnection(); - } - - - byte[] uncompressed = json.toString().getBytes(); - byte[] compressed = gzip(json.toString()); - - // Headers - connection.addRequestProperty("User-Agent", "MCStats/" + REVISION); - connection.addRequestProperty("Content-Type", "application/json"); - connection.addRequestProperty("Content-Encoding", "gzip"); - connection.addRequestProperty("Content-Length", Integer.toString(compressed.length)); - connection.addRequestProperty("Accept", "application/json"); - connection.addRequestProperty("Connection", "close"); - - connection.setDoOutput(true); - - if (debug) { - System.out.println("[Metrics] Prepared request for " + pluginName + " uncompressed=" + uncompressed.length + " compressed=" + compressed.length); - } - - // Write the data - OutputStream os = connection.getOutputStream(); - os.write(compressed); - os.flush(); - - // Now read the response - final BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream())); - String response = reader.readLine(); - - // close resources - os.close(); - reader.close(); - - if (response == null || response.startsWith("ERR") || response.startsWith("7")) { - if (response == null) { - response = "null"; - } else if (response.startsWith("7")) { - response = response.substring(response.startsWith("7,") ? 2 : 1); - } - - throw new IOException(response); - } else { - // Is this the first update this hour? - if (response.equals("1") || response.contains("This is your first update this hour")) { - synchronized (graphs) { - final Iterator iter = graphs.iterator(); - - while (iter.hasNext()) { - final Graph graph = iter.next(); - - for (Plotter plotter : graph.getPlotters()) { - plotter.reset(); - } - } - } - } - } - } - - /** - * GZip compress a string of bytes - * - * @param input - * @return - */ - public static byte[] gzip(String input) { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - GZIPOutputStream gzos = null; - - try { - gzos = new GZIPOutputStream(baos); - gzos.write(input.getBytes("UTF-8")); - } catch (IOException e) { - e.printStackTrace(); - } finally { - if (gzos != null) try { - gzos.close(); - } catch (IOException ignore) { - } - } - - return baos.toByteArray(); - } - - /** - * Check if mineshafter is present. If it is, we need to bypass it to send POST requests - * - * @return true if mineshafter is installed on the server - */ - private boolean isMineshafterPresent() { - try { - Class.forName("mineshafter.MineServer"); - return true; - } catch (Exception e) { - return false; - } - } - - /** - * Appends a json encoded key/value pair to the given string builder. - * - * @param json - * @param key - * @param value - * @throws UnsupportedEncodingException - */ - private static void appendJSONPair(StringBuilder json, String key, String value) throws UnsupportedEncodingException { - boolean isValueNumeric = false; - - try { - if (value.equals("0") || !value.endsWith("0")) { - Double.parseDouble(value); - isValueNumeric = true; - } - } catch (NumberFormatException e) { - isValueNumeric = false; - } - - if (json.charAt(json.length() - 1) != '{') { - json.append(','); - } - - json.append(escapeJSON(key)); - json.append(':'); - - if (isValueNumeric) { - json.append(value); - } else { - json.append(escapeJSON(value)); - } - } - - /** - * Escape a string to create a valid JSON string - * - * @param text - * @return - */ - private static String escapeJSON(String text) { - StringBuilder builder = new StringBuilder(); - - builder.append('"'); - for (int index = 0; index < text.length(); index++) { - char chr = text.charAt(index); - - switch (chr) { - case '"': - case '\\': - builder.append('\\'); - builder.append(chr); - break; - case '\b': - builder.append("\\b"); - break; - case '\t': - builder.append("\\t"); - break; - case '\n': - builder.append("\\n"); - break; - case '\r': - builder.append("\\r"); - break; - default: - if (chr < ' ') { - String t = "000" + Integer.toHexString(chr); - builder.append("\\u" + t.substring(t.length() - 4)); - } else { - builder.append(chr); - } - break; - } - } - builder.append('"'); - - return builder.toString(); - } - - /** - * Encode text as UTF-8 - * - * @param text the text to encode - * @return the encoded text, as UTF-8 - */ - private static String urlEncode(final String text) throws UnsupportedEncodingException { - return URLEncoder.encode(text, "UTF-8"); - } - - /** - * Represents a custom graph on the website - */ - public static class Graph { - - /** - * The graph's name, alphanumeric and spaces only :) If it does not comply to the above when submitted, it is - * rejected - */ - private final String name; - - /** - * The set of plotters that are contained within this graph - */ - private final Set plotters = new LinkedHashSet(); - - private Graph(final String name) { - this.name = name; - } - - /** - * Gets the graph's name - * - * @return the Graph's name - */ - public String getName() { - return name; - } - - /** - * Add a plotter to the graph, which will be used to plot entries - * - * @param plotter the plotter to add to the graph - */ - public void addPlotter(final Plotter plotter) { - plotters.add(plotter); - } - - /** - * Remove a plotter from the graph - * - * @param plotter the plotter to remove from the graph - */ - public void removePlotter(final Plotter plotter) { - plotters.remove(plotter); - } - - /** - * Gets an unmodifiable set of the plotter objects in the graph - * - * @return an unmodifiable {@link java.util.Set} of the plotter objects - */ - public Set getPlotters() { - return Collections.unmodifiableSet(plotters); - } - - @Override - public int hashCode() { - return name.hashCode(); - } - - @Override - public boolean equals(final Object object) { - if (!(object instanceof Graph)) { - return false; - } - - final Graph graph = (Graph) object; - return graph.name.equals(name); - } - - /** - * Called when the server owner decides to opt-out of BukkitMetrics while the server is running. - */ - protected void onOptOut() { - } - } - - /** - * Interface used to collect custom data for a plugin - */ - public static abstract class Plotter { - - /** - * The plot's name - */ - private final String name; - - /** - * Construct a plotter with the default plot name - */ - public Plotter() { - this("Default"); - } - - /** - * Construct a plotter with a specific plot name - * - * @param name the name of the plotter to use, which will show up on the website - */ - public Plotter(final String name) { - this.name = name; - } - - /** - * Get the current value for the plotted point. Since this function defers to an external function it may or may - * not return immediately thus cannot be guaranteed to be thread friendly or safe. This function can be called - * from any thread so care should be taken when accessing resources that need to be synchronized. - * - * @return the current value for the point to be plotted. - */ - public abstract int getValue(); - - /** - * Get the column name for the plotted point - * - * @return the plotted point's column name - */ - public String getColumnName() { - return name; - } - - /** - * Called after the website graphs have been updated - */ - public void reset() { - } - - @Override - public int hashCode() { - return getColumnName().hashCode(); - } - - @Override - public boolean equals(final Object object) { - if (!(object instanceof Plotter)) { - return false; - } - - final Plotter plotter = (Plotter) object; - return plotter.name.equals(name) && plotter.getValue() == getValue(); - } - } + /** + * The current revision number + */ + private final static int REVISION = 7; + + /** + * The base url of the metrics domain + */ + private static final String BASE_URL = "http://report.mcstats.org"; + + /** + * The url used to report a server's status + */ + private static final String REPORT_URL = "/plugin/%s"; + + /** + * Interval of time to ping (in minutes) + */ + private static final int PING_INTERVAL = 15; + + /** + * The plugin this metrics submits for + */ + private final Plugin plugin; + + /** + * All of the custom graphs to submit to metrics + */ + private final Set graphs = Collections.synchronizedSet(new HashSet()); + + /** + * The plugin configuration file + */ + private final YamlConfiguration configuration; + + /** + * The plugin configuration file + */ + private final File configurationFile; + + /** + * Unique server id + */ + private final String guid; + + /** + * Debug mode + */ + private final boolean debug; + + /** + * Lock for synchronization + */ + private final Object optOutLock = new Object(); + + /** + * The scheduled task + */ + private volatile BukkitTask task = null; + + public Metrics(final Plugin plugin) throws IOException { + if (plugin == null) { + throw new IllegalArgumentException("Plugin cannot be null"); + } + + this.plugin = plugin; + + // load the config + configurationFile = getConfigFile(); + configuration = YamlConfiguration.loadConfiguration(configurationFile); + + // add some defaults + configuration.addDefault("opt-out", false); + configuration.addDefault("guid", UUID.randomUUID().toString()); + configuration.addDefault("debug", false); + + // Do we need to create the file? + if (configuration.get("guid", null) == null) { + configuration.options().header("http://mcstats.org").copyDefaults(true); + configuration.save(configurationFile); + } + + // Load the guid then + guid = configuration.getString("guid"); + debug = configuration.getBoolean("debug", false); + } + + /** + * Construct and create a Graph that can be used to separate specific plotters to their own graphs on the metrics + * website. Plotters can be added to the graph object returned. + * + * @param name The name of the graph + * @return Graph object created. Will never return NULL under normal circumstances unless bad parameters are given + */ + public Graph createGraph(final String name) { + if (name == null) { + throw new IllegalArgumentException("Graph name cannot be null"); + } + + // Construct the graph object + final Graph graph = new Graph(name); + + // Now we can add our graph + graphs.add(graph); + + // and return back + return graph; + } + + /** + * Add a Graph object to BukkitMetrics that represents data for the plugin that should be sent to the backend + * + * @param graph The name of the graph + */ + public void addGraph(final Graph graph) { + if (graph == null) { + throw new IllegalArgumentException("Graph cannot be null"); + } + + graphs.add(graph); + } + + /** + * Start measuring statistics. This will immediately create an async repeating task as the plugin and send the + * initial data to the metrics backend, and then after that it will post in increments of PING_INTERVAL * 1200 + * ticks. + * + * @return True if statistics measuring is running, otherwise false. + */ + public boolean start() { + synchronized (optOutLock) { + // Did we opt out? + if (isOptOut()) { + return false; + } + + // Is metrics already running? + if (task != null) { + return true; + } + + // Begin hitting the server with glorious data + task = plugin.getServer().getScheduler().runTaskTimerAsynchronously(plugin, new Runnable() { + + private boolean firstPost = true; + + public void run() { + try { + // This has to be synchronized or it can collide with the disable method. + synchronized (optOutLock) { + // Disable Task, if it is running and the server owner decided to opt-out + if (isOptOut() && task != null) { + task.cancel(); + task = null; + // Tell all plotters to stop gathering information. + for (Graph graph : graphs) { + graph.onOptOut(); + } + } + } + + // We use the inverse of firstPost because if it is the first time we are posting, + // it is not a interval ping, so it evaluates to FALSE + // Each time thereafter it will evaluate to TRUE, i.e PING! + postPlugin(!firstPost); + + // After the first post we set firstPost to false + // Each post thereafter will be a ping + firstPost = false; + } catch (IOException e) { + if (debug) { + Bukkit.getLogger().log(Level.INFO, "[Metrics] " + e.getMessage()); + } + } + } + }, 0, PING_INTERVAL * 1200); + + return true; + } + } + + /** + * Has the server owner denied plugin metrics? + * + * @return true if metrics should be opted out of it + */ + public boolean isOptOut() { + synchronized (optOutLock) { + try { + // Reload the metrics file + configuration.load(getConfigFile()); + } catch (IOException ex) { + if (debug) { + Bukkit.getLogger().log(Level.INFO, "[Metrics] " + ex.getMessage()); + } + return true; + } catch (InvalidConfigurationException ex) { + if (debug) { + Bukkit.getLogger().log(Level.INFO, "[Metrics] " + ex.getMessage()); + } + return true; + } + return configuration.getBoolean("opt-out", false); + } + } + + /** + * Enables metrics for the server by setting "opt-out" to false in the config file and starting the metrics task. + * + * @throws java.io.IOException + */ + public void enable() throws IOException { + // This has to be synchronized or it can collide with the check in the task. + synchronized (optOutLock) { + // Check if the server owner has already set opt-out, if not, set it. + if (isOptOut()) { + configuration.set("opt-out", false); + configuration.save(configurationFile); + } + + // Enable Task, if it is not running + if (task == null) { + start(); + } + } + } + + /** + * Disables metrics for the server by setting "opt-out" to true in the config file and canceling the metrics task. + * + * @throws java.io.IOException + */ + public void disable() throws IOException { + // This has to be synchronized or it can collide with the check in the task. + synchronized (optOutLock) { + // Check if the server owner has already set opt-out, if not, set it. + if (!isOptOut()) { + configuration.set("opt-out", true); + configuration.save(configurationFile); + } + + // Disable Task, if it is running + if (task != null) { + task.cancel(); + task = null; + } + } + } + + /** + * Gets the File object of the config file that should be used to store data such as the GUID and opt-out status + * + * @return the File object for the config file + */ + public File getConfigFile() { + // I believe the easiest way to get the base folder (e.g craftbukkit set via -P) for plugins to use + // is to abuse the plugin object we already have + // plugin.getDataFolder() => base/plugins/PluginA/ + // pluginsFolder => base/plugins/ + // The base is not necessarily relative to the startup directory. + File pluginsFolder = plugin.getDataFolder().getParentFile(); + + // return => base/plugins/PluginMetrics/config.yml + return new File(new File(pluginsFolder, "PluginMetrics"), "config.yml"); + } + + /** + * Generic method that posts a plugin to the metrics website + */ + private void postPlugin(final boolean isPing) throws IOException { + // Server software specific section + PluginDescriptionFile description = plugin.getDescription(); + String pluginName = description.getName(); + boolean onlineMode = Bukkit.getServer().getOnlineMode(); // TRUE if online mode is enabled + String pluginVersion = description.getVersion(); + String serverVersion = Bukkit.getVersion(); + int playersOnline = Bukkit.getServer().getOnlinePlayers().length; + + // END server software specific section -- all code below does not use any code outside of this class / Java + + // Construct the post data + StringBuilder json = new StringBuilder(1024); + json.append('{'); + + // The plugin's description file containg all of the plugin data such as name, version, author, etc + appendJSONPair(json, "guid", guid); + appendJSONPair(json, "plugin_version", pluginVersion); + appendJSONPair(json, "server_version", serverVersion); + appendJSONPair(json, "players_online", Integer.toString(playersOnline)); + + // New data as of R6 + String osname = System.getProperty("os.name"); + String osarch = System.getProperty("os.arch"); + String osversion = System.getProperty("os.version"); + String java_version = System.getProperty("java.version"); + int coreCount = Runtime.getRuntime().availableProcessors(); + + // normalize os arch .. amd64 -> x86_64 + if (osarch.equals("amd64")) { + osarch = "x86_64"; + } + + appendJSONPair(json, "osname", osname); + appendJSONPair(json, "osarch", osarch); + appendJSONPair(json, "osversion", osversion); + appendJSONPair(json, "cores", Integer.toString(coreCount)); + appendJSONPair(json, "auth_mode", onlineMode ? "1" : "0"); + appendJSONPair(json, "java_version", java_version); + + // If we're pinging, append it + if (isPing) { + appendJSONPair(json, "ping", "1"); + } + + if (graphs.size() > 0) { + synchronized (graphs) { + json.append(','); + json.append('"'); + json.append("graphs"); + json.append('"'); + json.append(':'); + json.append('{'); + + boolean firstGraph = true; + + final Iterator iter = graphs.iterator(); + + while (iter.hasNext()) { + Graph graph = iter.next(); + + StringBuilder graphJson = new StringBuilder(); + graphJson.append('{'); + + for (Plotter plotter : graph.getPlotters()) { + appendJSONPair(graphJson, plotter.getColumnName(), Integer.toString(plotter.getValue())); + } + + graphJson.append('}'); + + if (!firstGraph) { + json.append(','); + } + + json.append(escapeJSON(graph.getName())); + json.append(':'); + json.append(graphJson); + + firstGraph = false; + } + + json.append('}'); + } + } + + // close json + json.append('}'); + + // Create the url + URL url = new URL(BASE_URL + String.format(REPORT_URL, urlEncode(pluginName))); + + // Connect to the website + URLConnection connection; + + // Mineshafter creates a socks proxy, so we can safely bypass it + // It does not reroute POST requests so we need to go around it + if (isMineshafterPresent()) { + connection = url.openConnection(Proxy.NO_PROXY); + } else { + connection = url.openConnection(); + } + + + byte[] uncompressed = json.toString().getBytes(); + byte[] compressed = gzip(json.toString()); + + // Headers + connection.addRequestProperty("User-Agent", "MCStats/" + REVISION); + connection.addRequestProperty("Content-Type", "application/json"); + connection.addRequestProperty("Content-Encoding", "gzip"); + connection.addRequestProperty("Content-Length", Integer.toString(compressed.length)); + connection.addRequestProperty("Accept", "application/json"); + connection.addRequestProperty("Connection", "close"); + + connection.setDoOutput(true); + + if (debug) { + System.out.println("[Metrics] Prepared request for " + pluginName + " uncompressed=" + uncompressed.length + " compressed=" + compressed.length); + } + + // Write the data + OutputStream os = connection.getOutputStream(); + os.write(compressed); + os.flush(); + + // Now read the response + final BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream())); + String response = reader.readLine(); + + // close resources + os.close(); + reader.close(); + + if (response == null || response.startsWith("ERR") || response.startsWith("7")) { + if (response == null) { + response = "null"; + } else if (response.startsWith("7")) { + response = response.substring(response.startsWith("7,") ? 2 : 1); + } + + throw new IOException(response); + } else { + // Is this the first update this hour? + if (response.equals("1") || response.contains("This is your first update this hour")) { + synchronized (graphs) { + final Iterator iter = graphs.iterator(); + + while (iter.hasNext()) { + final Graph graph = iter.next(); + + for (Plotter plotter : graph.getPlotters()) { + plotter.reset(); + } + } + } + } + } + } + + /** + * GZip compress a string of bytes + * + * @param input + * @return + */ + public static byte[] gzip(String input) { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + GZIPOutputStream gzos = null; + + try { + gzos = new GZIPOutputStream(baos); + gzos.write(input.getBytes("UTF-8")); + } catch (IOException e) { + e.printStackTrace(); + } finally { + if (gzos != null) { + try { + gzos.close(); + } catch (IOException ignore) { + } + } + } + + return baos.toByteArray(); + } + + /** + * Check if mineshafter is present. If it is, we need to bypass it to send POST requests + * + * @return true if mineshafter is installed on the server + */ + private boolean isMineshafterPresent() { + try { + Class.forName("mineshafter.MineServer"); + return true; + } catch (Exception e) { + return false; + } + } + + /** + * Appends a json encoded key/value pair to the given string builder. + * + * @param json + * @param key + * @param value + * @throws UnsupportedEncodingException + */ + private static void appendJSONPair(StringBuilder json, String key, String value) throws UnsupportedEncodingException { + boolean isValueNumeric = false; + + try { + if (value.equals("0") || !value.endsWith("0")) { + Double.parseDouble(value); + isValueNumeric = true; + } + } catch (NumberFormatException e) { + isValueNumeric = false; + } + + if (json.charAt(json.length() - 1) != '{') { + json.append(','); + } + + json.append(escapeJSON(key)); + json.append(':'); + + if (isValueNumeric) { + json.append(value); + } else { + json.append(escapeJSON(value)); + } + } + + /** + * Escape a string to create a valid JSON string + * + * @param text + * @return + */ + private static String escapeJSON(String text) { + StringBuilder builder = new StringBuilder(); + + builder.append('"'); + for (int index = 0; index < text.length(); index++) { + char chr = text.charAt(index); + + switch (chr) { + case '"': + case '\\': + builder.append('\\'); + builder.append(chr); + break; + case '\b': + builder.append("\\b"); + break; + case '\t': + builder.append("\\t"); + break; + case '\n': + builder.append("\\n"); + break; + case '\r': + builder.append("\\r"); + break; + default: + if (chr < ' ') { + String t = "000" + Integer.toHexString(chr); + builder.append("\\u" + t.substring(t.length() - 4)); + } else { + builder.append(chr); + } + break; + } + } + builder.append('"'); + + return builder.toString(); + } + + /** + * Encode text as UTF-8 + * + * @param text the text to encode + * @return the encoded text, as UTF-8 + */ + private static String urlEncode(final String text) throws UnsupportedEncodingException { + return URLEncoder.encode(text, "UTF-8"); + } + + /** + * Represents a custom graph on the website + */ + public static class Graph { + + /** + * The graph's name, alphanumeric and spaces only :) If it does not comply to the above when submitted, it is + * rejected + */ + private final String name; + + /** + * The set of plotters that are contained within this graph + */ + private final Set plotters = new LinkedHashSet(); + + private Graph(final String name) { + this.name = name; + } + + /** + * Gets the graph's name + * + * @return the Graph's name + */ + public String getName() { + return name; + } + + /** + * Add a plotter to the graph, which will be used to plot entries + * + * @param plotter the plotter to add to the graph + */ + public void addPlotter(final Plotter plotter) { + plotters.add(plotter); + } + + /** + * Remove a plotter from the graph + * + * @param plotter the plotter to remove from the graph + */ + public void removePlotter(final Plotter plotter) { + plotters.remove(plotter); + } + + /** + * Gets an unmodifiable set of the plotter objects in the graph + * + * @return an unmodifiable {@link java.util.Set} of the plotter objects + */ + public Set getPlotters() { + return Collections.unmodifiableSet(plotters); + } + + @Override + public int hashCode() { + return name.hashCode(); + } + + @Override + public boolean equals(final Object object) { + if (!(object instanceof Graph)) { + return false; + } + + final Graph graph = (Graph) object; + return graph.name.equals(name); + } + + /** + * Called when the server owner decides to opt-out of BukkitMetrics while the server is running. + */ + protected void onOptOut() { + } + } + + /** + * Interface used to collect custom data for a plugin + */ + public static abstract class Plotter { + + /** + * The plot's name + */ + private final String name; + + /** + * Construct a plotter with the default plot name + */ + public Plotter() { + this("Default"); + } + + /** + * Construct a plotter with a specific plot name + * + * @param name the name of the plotter to use, which will show up on the website + */ + public Plotter(final String name) { + this.name = name; + } + + /** + * Get the current value for the plotted point. Since this function defers to an external function it may or may + * not return immediately thus cannot be guaranteed to be thread friendly or safe. This function can be called + * from any thread so care should be taken when accessing resources that need to be synchronized. + * + * @return the current value for the point to be plotted. + */ + public abstract int getValue(); + + /** + * Get the column name for the plotted point + * + * @return the plotted point's column name + */ + public String getColumnName() { + return name; + } + + /** + * Called after the website graphs have been updated + */ + public void reset() { + } + + @Override + public int hashCode() { + return getColumnName().hashCode(); + } + + @Override + public boolean equals(final Object object) { + if (!(object instanceof Plotter)) { + return false; + } + + final Plotter plotter = (Plotter) object; + return plotter.name.equals(name) && plotter.getValue() == getValue(); + } + } } \ No newline at end of file diff --git a/src/main/java/de/diddiz/LogBlock/QueryParams.java b/src/main/java/de/diddiz/LogBlock/QueryParams.java index 47f22bd..519ee33 100644 --- a/src/main/java/de/diddiz/LogBlock/QueryParams.java +++ b/src/main/java/de/diddiz/LogBlock/QueryParams.java @@ -10,11 +10,7 @@ import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.bukkit.plugin.Plugin; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashSet; -import java.util.List; -import java.util.Set; +import java.util.*; import static de.diddiz.LogBlock.Session.getSession; import static de.diddiz.LogBlock.config.Config.*; @@ -24,432 +20,500 @@ import static de.diddiz.util.MaterialName.materialName; import static de.diddiz.util.MaterialName.typeFromName; import static de.diddiz.util.Utils.*; -public final class QueryParams implements Cloneable -{ - private static final Set keywords = new HashSet(Arrays.asList("player".hashCode(), "area".hashCode(), "selection".hashCode(), "sel".hashCode(), "block".hashCode(), "type".hashCode(), "sum".hashCode(), "destroyed".hashCode(), "created".hashCode(), "chestaccess".hashCode(), "all".hashCode(), "time".hashCode(), "since".hashCode(), "before".hashCode(), "limit".hashCode(), "world".hashCode(), "asc".hashCode(), "desc".hashCode(), "last".hashCode(), "coords".hashCode(), "silent".hashCode(), "chat".hashCode(), "search".hashCode(), "match".hashCode(), "loc".hashCode(), "location".hashCode(), "kills".hashCode(), "killer".hashCode(), "victim".hashCode(), "both".hashCode())); - public BlockChangeType bct = BlockChangeType.BOTH; - public int limit = -1, before = 0, since = 0, radius = -1; - public Location loc = null; - public Order order = Order.DESC; - public List players = new ArrayList(); - public List killers = new ArrayList(); - public List victims = new ArrayList(); - public boolean excludePlayersMode = false, excludeKillersMode = false, excludeVictimsMode = false, excludeBlocksMode = false, prepareToolQuery = false, silent = false; - public RegionContainer sel = null; - public SummarizationMode sum = SummarizationMode.NONE; - public List types = new ArrayList(); - public World world = null; - public String match = null; - public boolean needCount = false, needId = false, needDate = false, needType = false, needData = false, needPlayer = false, needCoords = false, needSignText = false, needChestAccess = false, needMessage = false, needKiller = false, needVictim = false, needWeapon = false; - private final LogBlock logblock; +public final class QueryParams implements Cloneable { + private static final Set keywords = new HashSet(Arrays.asList("player".hashCode(), "area".hashCode(), "selection".hashCode(), "sel".hashCode(), "block".hashCode(), "type".hashCode(), "sum".hashCode(), "destroyed".hashCode(), "created".hashCode(), "chestaccess".hashCode(), "all".hashCode(), "time".hashCode(), "since".hashCode(), "before".hashCode(), "limit".hashCode(), "world".hashCode(), "asc".hashCode(), "desc".hashCode(), "last".hashCode(), "coords".hashCode(), "silent".hashCode(), "chat".hashCode(), "search".hashCode(), "match".hashCode(), "loc".hashCode(), "location".hashCode(), "kills".hashCode(), "killer".hashCode(), "victim".hashCode(), "both".hashCode())); + public BlockChangeType bct = BlockChangeType.BOTH; + public int limit = -1, before = 0, since = 0, radius = -1; + public Location loc = null; + public Order order = Order.DESC; + public List players = new ArrayList(); + public List killers = new ArrayList(); + public List victims = new ArrayList(); + public boolean excludePlayersMode = false, excludeKillersMode = false, excludeVictimsMode = false, excludeBlocksMode = false, prepareToolQuery = false, silent = false; + public RegionContainer sel = null; + public SummarizationMode sum = SummarizationMode.NONE; + public List types = new ArrayList(); + public World world = null; + public String match = null; + public boolean needCount = false, needId = false, needDate = false, needType = false, needData = false, needPlayer = false, needCoords = false, needSignText = false, needChestAccess = false, needMessage = false, needKiller = false, needVictim = false, needWeapon = false; + private final LogBlock logblock; - public QueryParams(LogBlock logblock) { - this.logblock = logblock; - } + public QueryParams(LogBlock logblock) { + this.logblock = logblock; + } - public QueryParams(LogBlock logblock, CommandSender sender, List args) throws IllegalArgumentException { - this.logblock = logblock; - parseArgs(sender, args); - } + public QueryParams(LogBlock logblock, CommandSender sender, List args) throws IllegalArgumentException { + this.logblock = logblock; + parseArgs(sender, args); + } - public static boolean isKeyWord(String param) { - return keywords.contains(param.toLowerCase().hashCode()); - } + public static boolean isKeyWord(String param) { + return keywords.contains(param.toLowerCase().hashCode()); + } - public String getLimit() { - return limit > 0 ? "LIMIT " + limit : ""; - } + public String getLimit() { + return limit > 0 ? "LIMIT " + limit : ""; + } - public String getQuery() { - if (bct == BlockChangeType.CHAT) { - String select = "SELECT "; - if (needCount) - select += "COUNT(*) AS count"; - else { - if (needId) - select += "id, "; - if (needDate) - select += "date, "; - if (needPlayer) - select += "playername, UUID,"; - if (needMessage) - select += "message, "; - select = select.substring(0, select.length() - 2); - } - String from = "FROM `lb-chat` "; + public String getQuery() { + if (bct == BlockChangeType.CHAT) { + String select = "SELECT "; + if (needCount) { + select += "COUNT(*) AS count"; + } else { + if (needId) { + select += "id, "; + } + if (needDate) { + select += "date, "; + } + if (needPlayer) { + select += "playername, UUID,"; + } + if (needMessage) { + select += "message, "; + } + select = select.substring(0, select.length() - 2); + } + String from = "FROM `lb-chat` "; - if (needPlayer || players.size() > 0) - from += "INNER JOIN `lb-players` USING (playerid) "; - return select + " " + from + getWhere() + "ORDER BY date " + order + ", id " + order + " " + getLimit(); - } - if (bct == BlockChangeType.KILLS) { - if (sum == SummarizationMode.NONE) { - String select = "SELECT "; - if (needCount) - select += "COUNT(*) AS count"; - else { - if (needId) - select += "id, "; - if (needDate) - select += "date, "; - if (needPlayer || needKiller) - select += "killers.playername as killer, "; - if (needPlayer || needVictim) - select += "victims.playername as victim, "; - if (needWeapon) - select += "weapon, "; - if (needCoords) - select += "x, y, z, "; - select = select.substring(0, select.length() - 2); - } - String from = "FROM `" + getTable() + "-kills` "; + if (needPlayer || players.size() > 0) { + from += "INNER JOIN `lb-players` USING (playerid) "; + } + return select + " " + from + getWhere() + "ORDER BY date " + order + ", id " + order + " " + getLimit(); + } + if (bct == BlockChangeType.KILLS) { + if (sum == SummarizationMode.NONE) { + String select = "SELECT "; + if (needCount) { + select += "COUNT(*) AS count"; + } else { + if (needId) { + select += "id, "; + } + if (needDate) { + select += "date, "; + } + if (needPlayer || needKiller) { + select += "killers.playername as killer, "; + } + if (needPlayer || needVictim) { + select += "victims.playername as victim, "; + } + if (needWeapon) { + select += "weapon, "; + } + if (needCoords) { + select += "x, y, z, "; + } + select = select.substring(0, select.length() - 2); + } + String from = "FROM `" + getTable() + "-kills` "; - if (needPlayer || needKiller || killers.size() > 0) - from += "INNER JOIN `lb-players` as killers ON (killer=killers.playerid) "; + if (needPlayer || needKiller || killers.size() > 0) { + from += "INNER JOIN `lb-players` as killers ON (killer=killers.playerid) "; + } - if (needPlayer || needVictim || victims.size() > 0) - from += "INNER JOIN `lb-players` as victims ON (victim=victims.playerid) "; + if (needPlayer || needVictim || victims.size() > 0) { + from += "INNER JOIN `lb-players` as victims ON (victim=victims.playerid) "; + } - return select + " " + from + getWhere() + "ORDER BY date " + order + ", id " + order + " " + getLimit(); - } else if (sum == SummarizationMode.PLAYERS) - return "SELECT playername, UUID, SUM(kills) AS kills, SUM(killed) AS killed FROM ((SELECT killer AS playerid, count(*) AS kills, 0 as killed FROM `" + getTable() + "-kills` INNER JOIN `lb-players` as killers ON (killer=killers.playerid) INNER JOIN `lb-players` as victims ON (victim=victims.playerid) " + getWhere(BlockChangeType.KILLS) + "GROUP BY killer) UNION (SELECT victim AS playerid, 0 as kills, count(*) AS killed FROM `" + getTable() + "-kills` INNER JOIN `lb-players` as killers ON (killer=killers.playerid) INNER JOIN `lb-players` as victims ON (victim=victims.playerid) " + getWhere(BlockChangeType.KILLS) + "GROUP BY victim)) AS t INNER JOIN `lb-players` USING (playerid) GROUP BY playerid ORDER BY SUM(kills) + SUM(killed) " + order + " " + getLimit(); - } - if (sum == SummarizationMode.NONE) { - String select = "SELECT "; - if (needCount) - select += "COUNT(*) AS count"; - else { - if (needId) - select += "`" + getTable() + "`.id, "; - if (needDate) - select += "date, "; - if (needType) - select += "replaced, type, "; - if (needData) - select += "data, "; - if (needPlayer) - select += "playername, UUID, "; - if (needCoords) - select += "x, y, z, "; - if (needSignText) - select += "signtext, "; - if (needChestAccess) - select += "itemtype, itemamount, itemdata, "; - select = select.substring(0, select.length() - 2); - } - String from = "FROM `" + getTable() + "` "; - if (needPlayer || players.size() > 0) - from += "INNER JOIN `lb-players` USING (playerid) "; - if (needSignText) - from += "LEFT JOIN `" + getTable() + "-sign` USING (id) "; - if (needChestAccess) - // If BlockChangeType is CHESTACCESS, we can use more efficient query - if (bct == BlockChangeType.CHESTACCESS) { - from += "RIGHT JOIN `" + getTable() + "-chest` USING (id) "; - } else { - from += "LEFT JOIN `" + getTable() + "-chest` USING (id) "; - } - return select + " " + from + getWhere() + "ORDER BY date " + order + ", id " + order + " " + getLimit(); - } else if (sum == SummarizationMode.TYPES) - return "SELECT type, SUM(created) AS created, SUM(destroyed) AS destroyed FROM ((SELECT type, count(*) AS created, 0 AS destroyed FROM `" + getTable() + "` INNER JOIN `lb-players` USING (playerid) " + getWhere(BlockChangeType.CREATED) + "GROUP BY type) UNION (SELECT replaced AS type, 0 AS created, count(*) AS destroyed FROM `" + getTable() + "` INNER JOIN `lb-players` USING (playerid) " + getWhere(BlockChangeType.DESTROYED) + "GROUP BY replaced)) AS t GROUP BY type ORDER BY SUM(created) + SUM(destroyed) " + order + " " + getLimit(); - else - return "SELECT playername, UUID, SUM(created) AS created, SUM(destroyed) AS destroyed FROM ((SELECT playerid, count(*) AS created, 0 AS destroyed FROM `" + getTable() + "` " + getWhere(BlockChangeType.CREATED) + "GROUP BY playerid) UNION (SELECT playerid, 0 AS created, count(*) AS destroyed FROM `" + getTable() + "` " + getWhere(BlockChangeType.DESTROYED) + "GROUP BY playerid)) AS t INNER JOIN `lb-players` USING (playerid) GROUP BY playerid ORDER BY SUM(created) + SUM(destroyed) " + order + " " + getLimit(); - } + return select + " " + from + getWhere() + "ORDER BY date " + order + ", id " + order + " " + getLimit(); + } else if (sum == SummarizationMode.PLAYERS) { + return "SELECT playername, UUID, SUM(kills) AS kills, SUM(killed) AS killed FROM ((SELECT killer AS playerid, count(*) AS kills, 0 as killed FROM `" + getTable() + "-kills` INNER JOIN `lb-players` as killers ON (killer=killers.playerid) INNER JOIN `lb-players` as victims ON (victim=victims.playerid) " + getWhere(BlockChangeType.KILLS) + "GROUP BY killer) UNION (SELECT victim AS playerid, 0 as kills, count(*) AS killed FROM `" + getTable() + "-kills` INNER JOIN `lb-players` as killers ON (killer=killers.playerid) INNER JOIN `lb-players` as victims ON (victim=victims.playerid) " + getWhere(BlockChangeType.KILLS) + "GROUP BY victim)) AS t INNER JOIN `lb-players` USING (playerid) GROUP BY playerid ORDER BY SUM(kills) + SUM(killed) " + order + " " + getLimit(); + } + } + if (sum == SummarizationMode.NONE) { + String select = "SELECT "; + if (needCount) { + select += "COUNT(*) AS count"; + } else { + if (needId) { + select += "`" + getTable() + "`.id, "; + } + if (needDate) { + select += "date, "; + } + if (needType) { + select += "replaced, type, "; + } + if (needData) { + select += "data, "; + } + if (needPlayer) { + select += "playername, UUID, "; + } + if (needCoords) { + select += "x, y, z, "; + } + if (needSignText) { + select += "signtext, "; + } + if (needChestAccess) { + select += "itemtype, itemamount, itemdata, "; + } + select = select.substring(0, select.length() - 2); + } + String from = "FROM `" + getTable() + "` "; + if (needPlayer || players.size() > 0) { + from += "INNER JOIN `lb-players` USING (playerid) "; + } + if (needSignText) { + from += "LEFT JOIN `" + getTable() + "-sign` USING (id) "; + } + if (needChestAccess) + // If BlockChangeType is CHESTACCESS, we can use more efficient query + { + if (bct == BlockChangeType.CHESTACCESS) { + from += "RIGHT JOIN `" + getTable() + "-chest` USING (id) "; + } else { + from += "LEFT JOIN `" + getTable() + "-chest` USING (id) "; + } + } + return select + " " + from + getWhere() + "ORDER BY date " + order + ", id " + order + " " + getLimit(); + } else if (sum == SummarizationMode.TYPES) { + return "SELECT type, SUM(created) AS created, SUM(destroyed) AS destroyed FROM ((SELECT type, count(*) AS created, 0 AS destroyed FROM `" + getTable() + "` INNER JOIN `lb-players` USING (playerid) " + getWhere(BlockChangeType.CREATED) + "GROUP BY type) UNION (SELECT replaced AS type, 0 AS created, count(*) AS destroyed FROM `" + getTable() + "` INNER JOIN `lb-players` USING (playerid) " + getWhere(BlockChangeType.DESTROYED) + "GROUP BY replaced)) AS t GROUP BY type ORDER BY SUM(created) + SUM(destroyed) " + order + " " + getLimit(); + } else { + return "SELECT playername, UUID, SUM(created) AS created, SUM(destroyed) AS destroyed FROM ((SELECT playerid, count(*) AS created, 0 AS destroyed FROM `" + getTable() + "` " + getWhere(BlockChangeType.CREATED) + "GROUP BY playerid) UNION (SELECT playerid, 0 AS created, count(*) AS destroyed FROM `" + getTable() + "` " + getWhere(BlockChangeType.DESTROYED) + "GROUP BY playerid)) AS t INNER JOIN `lb-players` USING (playerid) GROUP BY playerid ORDER BY SUM(created) + SUM(destroyed) " + order + " " + getLimit(); + } + } - public String getTable() { - return getWorldConfig(world).table; - } + public String getTable() { + return getWorldConfig(world).table; + } - public String getTitle() { - final StringBuilder title = new StringBuilder(); - if (bct == BlockChangeType.CHESTACCESS) - title.append("chest accesses "); - else if (bct == BlockChangeType.CHAT) - title.append("chat messages "); - else if (bct == BlockChangeType.KILLS) - title.append("kills "); - else { - if (!types.isEmpty()) { - if (excludeBlocksMode) - title.append("all blocks except "); - final String[] blocknames = new String[types.size()]; - for (int i = 0; i < types.size(); i++) - blocknames[i] = materialName(types.get(i).getBlock()); - title.append(listing(blocknames, ", ", " and ")).append(" "); - } else - title.append("block "); - if (bct == BlockChangeType.CREATED) - title.append("creations "); - else if (bct == BlockChangeType.DESTROYED) - title.append("destructions "); - else - title.append("changes "); - } - if (killers.size() > 10) - title.append(excludeKillersMode ? "without" : "from").append(" many killers "); - else if (!killers.isEmpty()) - title.append(excludeKillersMode ? "without" : "from").append(" ").append(listing(killers.toArray(new String[killers.size()]), ", ", " and ")).append(" "); - if (victims.size() > 10) - title.append(excludeVictimsMode ? "without" : "of").append(" many victims "); - else if (!victims.isEmpty()) - title.append(excludeVictimsMode ? "without" : "of").append(" victim").append(victims.size() != 1 ? "s" : "").append(" ").append(listing(victims.toArray(new String[victims.size()]), ", ", " and ")).append(" "); - if (players.size() > 10) - title.append(excludePlayersMode ? "without" : "from").append(" many players "); - else if (!players.isEmpty()) - title.append(excludePlayersMode ? "without" : "from").append(" player").append(players.size() != 1 ? "s" : "").append(" ").append(listing(players.toArray(new String[players.size()]), ", ", " and ")).append(" "); - if (match != null && match.length() > 0) - title.append("matching '").append(match).append("' "); - if (before > 0 && since > 0) - title.append("between ").append(since).append(" and ").append(before).append(" minutes ago "); - else if (since > 0) - title.append("in the last ").append(since).append(" minutes "); - else if (before > 0) - title.append("more than ").append(before * -1).append(" minutes ago "); - if (loc != null) { - if (radius > 0) - title.append("within ").append(radius).append(" blocks of ").append(prepareToolQuery ? "clicked block" : "location").append(" "); - else if (radius == 0) - title.append("at ").append(loc.getBlockX()).append(":").append(loc.getBlockY()).append(":").append(loc.getBlockZ()).append(" "); - } else if (sel != null) - title.append(prepareToolQuery ? "at double chest " : "inside selection "); - else if (prepareToolQuery) - if (radius > 0) - title.append("within ").append(radius).append(" blocks of clicked block "); - else if (radius == 0) - title.append("at clicked block "); - if (world != null && !(sel != null && prepareToolQuery)) - title.append("in ").append(friendlyWorldname(world.getName())).append(" "); - if (sum != SummarizationMode.NONE) - title.append("summed up by ").append(sum == SummarizationMode.TYPES ? "blocks" : "players").append(" "); - title.deleteCharAt(title.length() - 1); - title.setCharAt(0, String.valueOf(title.charAt(0)).toUpperCase().toCharArray()[0]); - return title.toString(); - } + public String getTitle() { + final StringBuilder title = new StringBuilder(); + if (bct == BlockChangeType.CHESTACCESS) { + title.append("chest accesses "); + } else if (bct == BlockChangeType.CHAT) { + title.append("chat messages "); + } else if (bct == BlockChangeType.KILLS) { + title.append("kills "); + } else { + if (!types.isEmpty()) { + if (excludeBlocksMode) { + title.append("all blocks except "); + } + final String[] blocknames = new String[types.size()]; + for (int i = 0; i < types.size(); i++) { + blocknames[i] = materialName(types.get(i).getBlock()); + } + title.append(listing(blocknames, ", ", " and ")).append(" "); + } else { + title.append("block "); + } + if (bct == BlockChangeType.CREATED) { + title.append("creations "); + } else if (bct == BlockChangeType.DESTROYED) { + title.append("destructions "); + } else { + title.append("changes "); + } + } + if (killers.size() > 10) { + title.append(excludeKillersMode ? "without" : "from").append(" many killers "); + } else if (!killers.isEmpty()) { + title.append(excludeKillersMode ? "without" : "from").append(" ").append(listing(killers.toArray(new String[killers.size()]), ", ", " and ")).append(" "); + } + if (victims.size() > 10) { + title.append(excludeVictimsMode ? "without" : "of").append(" many victims "); + } else if (!victims.isEmpty()) { + title.append(excludeVictimsMode ? "without" : "of").append(" victim").append(victims.size() != 1 ? "s" : "").append(" ").append(listing(victims.toArray(new String[victims.size()]), ", ", " and ")).append(" "); + } + if (players.size() > 10) { + title.append(excludePlayersMode ? "without" : "from").append(" many players "); + } else if (!players.isEmpty()) { + title.append(excludePlayersMode ? "without" : "from").append(" player").append(players.size() != 1 ? "s" : "").append(" ").append(listing(players.toArray(new String[players.size()]), ", ", " and ")).append(" "); + } + if (match != null && match.length() > 0) { + title.append("matching '").append(match).append("' "); + } + if (before > 0 && since > 0) { + title.append("between ").append(since).append(" and ").append(before).append(" minutes ago "); + } else if (since > 0) { + title.append("in the last ").append(since).append(" minutes "); + } else if (before > 0) { + title.append("more than ").append(before * -1).append(" minutes ago "); + } + if (loc != null) { + if (radius > 0) { + title.append("within ").append(radius).append(" blocks of ").append(prepareToolQuery ? "clicked block" : "location").append(" "); + } else if (radius == 0) { + title.append("at ").append(loc.getBlockX()).append(":").append(loc.getBlockY()).append(":").append(loc.getBlockZ()).append(" "); + } + } else if (sel != null) { + title.append(prepareToolQuery ? "at double chest " : "inside selection "); + } else if (prepareToolQuery) { + if (radius > 0) { + title.append("within ").append(radius).append(" blocks of clicked block "); + } else if (radius == 0) { + title.append("at clicked block "); + } + } + if (world != null && !(sel != null && prepareToolQuery)) { + title.append("in ").append(friendlyWorldname(world.getName())).append(" "); + } + if (sum != SummarizationMode.NONE) { + title.append("summed up by ").append(sum == SummarizationMode.TYPES ? "blocks" : "players").append(" "); + } + title.deleteCharAt(title.length() - 1); + title.setCharAt(0, String.valueOf(title.charAt(0)).toUpperCase().toCharArray()[0]); + return title.toString(); + } - public String getWhere() { - return getWhere(bct); - } + public String getWhere() { + return getWhere(bct); + } - public String getWhere(BlockChangeType blockChangeType) { - final StringBuilder where = new StringBuilder("WHERE "); - if (blockChangeType == BlockChangeType.CHAT) { - if (match != null && match.length() > 0) { - final boolean unlike = match.startsWith("-"); - if (match.length() > 3 && !unlike || match.length() > 4) - where.append("MATCH (message) AGAINST ('").append(match).append("' IN BOOLEAN MODE) AND "); - else - where.append("message ").append(unlike ? "NOT " : "").append("LIKE '%").append(unlike ? match.substring(1) : match).append("%' AND "); - } - } else if (blockChangeType == BlockChangeType.KILLS) { - if (!players.isEmpty()) - if (!excludePlayersMode) { - where.append('('); - for (final String killerName : players) - where.append("killers.playername = '").append(killerName).append("' OR "); - for (final String victimName : players) - where.append("victims.playername = '").append(victimName).append("' OR "); - where.delete(where.length() - 4, where.length()); - where.append(") AND "); - } else { - for (final String killerName : players) - where.append("killers.playername != '").append(killerName).append("' AND "); - for (final String victimName : players) - where.append("victims.playername != '").append(victimName).append("' AND "); - } + public String getWhere(BlockChangeType blockChangeType) { + final StringBuilder where = new StringBuilder("WHERE "); + if (blockChangeType == BlockChangeType.CHAT) { + if (match != null && match.length() > 0) { + final boolean unlike = match.startsWith("-"); + if (match.length() > 3 && !unlike || match.length() > 4) { + where.append("MATCH (message) AGAINST ('").append(match).append("' IN BOOLEAN MODE) AND "); + } else { + where.append("message ").append(unlike ? "NOT " : "").append("LIKE '%").append(unlike ? match.substring(1) : match).append("%' AND "); + } + } + } else if (blockChangeType == BlockChangeType.KILLS) { + if (!players.isEmpty()) { + if (!excludePlayersMode) { + where.append('('); + for (final String killerName : players) { + where.append("killers.playername = '").append(killerName).append("' OR "); + } + for (final String victimName : players) { + where.append("victims.playername = '").append(victimName).append("' OR "); + } + where.delete(where.length() - 4, where.length()); + where.append(") AND "); + } else { + for (final String killerName : players) { + where.append("killers.playername != '").append(killerName).append("' AND "); + } + for (final String victimName : players) { + where.append("victims.playername != '").append(victimName).append("' AND "); + } + } + } - if (!killers.isEmpty()) - if (!excludeKillersMode) { - where.append('('); - for (final String killerName : killers) - where.append("killers.playername = '").append(killerName).append("' OR "); - where.delete(where.length() - 4, where.length()); - where.append(") AND "); - } else - for (final String killerName : killers) - where.append("killers.playername != '").append(killerName).append("' AND "); + if (!killers.isEmpty()) { + if (!excludeKillersMode) { + where.append('('); + for (final String killerName : killers) { + where.append("killers.playername = '").append(killerName).append("' OR "); + } + where.delete(where.length() - 4, where.length()); + where.append(") AND "); + } else { + for (final String killerName : killers) { + where.append("killers.playername != '").append(killerName).append("' AND "); + } + } + } - if (!victims.isEmpty()) - if (!excludeVictimsMode) { - where.append('('); - for (final String victimName : victims) - where.append("victims.playername = '").append(victimName).append("' OR "); - where.delete(where.length() - 4, where.length()); - where.append(") AND "); - } else - for (final String victimName : victims) - where.append("victims.playername != '").append(victimName).append("' AND "); + if (!victims.isEmpty()) { + if (!excludeVictimsMode) { + where.append('('); + for (final String victimName : victims) { + where.append("victims.playername = '").append(victimName).append("' OR "); + } + where.delete(where.length() - 4, where.length()); + where.append(") AND "); + } else { + for (final String victimName : victims) { + where.append("victims.playername != '").append(victimName).append("' AND "); + } + } + } if (loc != null) { - if (radius == 0) + if (radius == 0) { compileLocationQuery( where, loc.getBlockX(), loc.getBlockX(), loc.getBlockY(), loc.getBlockY(), loc.getBlockZ(), loc.getBlockZ() - ); - - else if (radius > 0) + ); + } else if (radius > 0) { compileLocationQuery( where, loc.getBlockX() - radius + 1, loc.getBlockX() + radius - 1, loc.getBlockY() - radius + 1, loc.getBlockY() + radius - 1, loc.getBlockZ() - radius + 1, loc.getBlockZ() + radius - 1 - ); + ); + } - } else if (sel != null) + } else if (sel != null) { compileLocationQuery( where, sel.getSelection().getMinimumPoint().getBlockX(), sel.getSelection().getMaximumPoint().getBlockX(), sel.getSelection().getMinimumPoint().getBlockY(), sel.getSelection().getMaximumPoint().getBlockY(), sel.getSelection().getMinimumPoint().getBlockZ(), sel.getSelection().getMaximumPoint().getBlockZ() - ); + ); + } - } else { - switch (blockChangeType) { - case ALL: - if (!types.isEmpty()) { - if (excludeBlocksMode) - where.append("NOT "); - where.append('('); - for (final Block block : types) { - where.append("((type = ").append(block.getBlock()).append(" OR replaced = ").append(block.getBlock()); - if (block.getData() != -1) { - where.append(") AND data = ").append(block.getData()); - } else { - where.append(")"); - } - where.append(") OR "); - } - where.delete(where.length() - 4, where.length() - 1); - where.append(") AND "); - } - break; - case BOTH: - if (!types.isEmpty()) { - if (excludeBlocksMode) - where.append("NOT "); - where.append('('); - for (final Block block : types) { - where.append("((type = ").append(block.getBlock()).append(" OR replaced = ").append(block.getBlock()); - if (block.getData() != -1) { - where.append(") AND data = ").append(block.getData()); - } else { - where.append(")"); - } - where.append(") OR "); - } - where.delete(where.length() - 4, where.length()); - where.append(") AND "); - } - where.append("type != replaced AND "); - break; - case CREATED: - if (!types.isEmpty()) { - if (excludeBlocksMode) - where.append("NOT "); - where.append('('); - for (final Block block : types) { - where.append("((type = ").append(block.getBlock()); - if (block.getData() != -1) { - where.append(") AND data = ").append(block.getData()); - } else { - where.append(")"); - } - where.append(") OR "); - } - where.delete(where.length() - 4, where.length()); - where.append(") AND "); - } - where.append("type != 0 AND type != replaced AND "); - break; - case DESTROYED: - if (!types.isEmpty()) { - if (excludeBlocksMode) - where.append("NOT "); - where.append('('); - for (final Block block : types) { - where.append("((replaced = ").append(block.getBlock()); - if (block.getData() != -1) { - where.append(") AND data = ").append(block.getData()); - } else { - where.append(")"); - } - where.append(") OR "); - } - where.delete(where.length() - 4, where.length()); - where.append(") AND "); - } - where.append("replaced != 0 AND type != replaced AND "); - break; - case CHESTACCESS: - if (!types.isEmpty()) { - if (excludeBlocksMode) - where.append("NOT "); - where.append('('); - for (final Block block : types) { - where.append("((itemtype = ").append(block.getBlock()); - if (block.getData() != -1) { - where.append(") AND itemdata = ").append(block.getData()); - } else { - where.append(")"); - } - where.append(") OR "); - } - where.delete(where.length() - 4, where.length()); - where.append(") AND "); - } - break; - } + } else { + switch (blockChangeType) { + case ALL: + if (!types.isEmpty()) { + if (excludeBlocksMode) { + where.append("NOT "); + } + where.append('('); + for (final Block block : types) { + where.append("((type = ").append(block.getBlock()).append(" OR replaced = ").append(block.getBlock()); + if (block.getData() != -1) { + where.append(") AND data = ").append(block.getData()); + } else { + where.append(")"); + } + where.append(") OR "); + } + where.delete(where.length() - 4, where.length() - 1); + where.append(") AND "); + } + break; + case BOTH: + if (!types.isEmpty()) { + if (excludeBlocksMode) { + where.append("NOT "); + } + where.append('('); + for (final Block block : types) { + where.append("((type = ").append(block.getBlock()).append(" OR replaced = ").append(block.getBlock()); + if (block.getData() != -1) { + where.append(") AND data = ").append(block.getData()); + } else { + where.append(")"); + } + where.append(") OR "); + } + where.delete(where.length() - 4, where.length()); + where.append(") AND "); + } + where.append("type != replaced AND "); + break; + case CREATED: + if (!types.isEmpty()) { + if (excludeBlocksMode) { + where.append("NOT "); + } + where.append('('); + for (final Block block : types) { + where.append("((type = ").append(block.getBlock()); + if (block.getData() != -1) { + where.append(") AND data = ").append(block.getData()); + } else { + where.append(")"); + } + where.append(") OR "); + } + where.delete(where.length() - 4, where.length()); + where.append(") AND "); + } + where.append("type != 0 AND type != replaced AND "); + break; + case DESTROYED: + if (!types.isEmpty()) { + if (excludeBlocksMode) { + where.append("NOT "); + } + where.append('('); + for (final Block block : types) { + where.append("((replaced = ").append(block.getBlock()); + if (block.getData() != -1) { + where.append(") AND data = ").append(block.getData()); + } else { + where.append(")"); + } + where.append(") OR "); + } + where.delete(where.length() - 4, where.length()); + where.append(") AND "); + } + where.append("replaced != 0 AND type != replaced AND "); + break; + case CHESTACCESS: + if (!types.isEmpty()) { + if (excludeBlocksMode) { + where.append("NOT "); + } + where.append('('); + for (final Block block : types) { + where.append("((itemtype = ").append(block.getBlock()); + if (block.getData() != -1) { + where.append(") AND itemdata = ").append(block.getData()); + } else { + where.append(")"); + } + where.append(") OR "); + } + where.delete(where.length() - 4, where.length()); + where.append(") AND "); + } + break; + } if (loc != null) { - if (radius == 0) + if (radius == 0) { compileLocationQuery( where, loc.getBlockX(), loc.getBlockX(), loc.getBlockY(), loc.getBlockY(), loc.getBlockZ(), loc.getBlockZ() - ); - - else if (radius > 0) + ); + } else if (radius > 0) { compileLocationQuery( where, loc.getBlockX() - radius + 1, loc.getBlockX() + radius - 1, loc.getBlockY() - radius + 1, loc.getBlockY() + radius - 1, loc.getBlockZ() - radius + 1, loc.getBlockZ() + radius - 1 - ); + ); + } - } else if (sel != null) + } else if (sel != null) { compileLocationQuery( where, sel.getSelection().getMinimumPoint().getBlockX(), sel.getSelection().getMaximumPoint().getBlockX(), sel.getSelection().getMinimumPoint().getBlockY(), sel.getSelection().getMaximumPoint().getBlockY(), sel.getSelection().getMinimumPoint().getBlockZ(), sel.getSelection().getMaximumPoint().getBlockZ() - ); + ); + } - } - if (!players.isEmpty() && sum != SummarizationMode.PLAYERS && blockChangeType != BlockChangeType.KILLS) - if (!excludePlayersMode) { - where.append('('); - for (final String playerName : players) - where.append("playername = '").append(playerName).append("' OR "); - where.delete(where.length() - 4, where.length()); - where.append(") AND "); - } else - for (final String playerName : players) - where.append("playername != '").append(playerName).append("' AND "); - if (since > 0) - where.append("date > date_sub(now(), INTERVAL ").append(since).append(" MINUTE) AND "); - if (before > 0) - where.append("date < date_sub(now(), INTERVAL ").append(before).append(" MINUTE) AND "); - if (where.length() > 6) - where.delete(where.length() - 4, where.length()); - else - where.delete(0, where.length()); - return where.toString(); - } - - private void compileLocationQuery(StringBuilder where, int blockX, int blockX2, int blockY, int blockY2, int blockZ, int blockZ2) { - compileLocationQueryPart(where, "x", blockX, blockX2); - where.append(" AND "); + } + if (!players.isEmpty() && sum != SummarizationMode.PLAYERS && blockChangeType != BlockChangeType.KILLS) { + if (!excludePlayersMode) { + where.append('('); + for (final String playerName : players) { + where.append("playername = '").append(playerName).append("' OR "); + } + where.delete(where.length() - 4, where.length()); + where.append(") AND "); + } else { + for (final String playerName : players) { + where.append("playername != '").append(playerName).append("' AND "); + } + } + } + if (since > 0) { + where.append("date > date_sub(now(), INTERVAL ").append(since).append(" MINUTE) AND "); + } + if (before > 0) { + where.append("date < date_sub(now(), INTERVAL ").append(before).append(" MINUTE) AND "); + } + if (where.length() > 6) { + where.delete(where.length() - 4, where.length()); + } else { + where.delete(0, where.length()); + } + return where.toString(); + } + + private void compileLocationQuery(StringBuilder where, int blockX, int blockX2, int blockY, int blockY2, int blockZ, int blockZ2) { + compileLocationQueryPart(where, "x", blockX, blockX2); + where.append(" AND "); compileLocationQueryPart(where, "y", blockY, blockY2); where.append(" AND "); compileLocationQueryPart(where, "z", blockZ, blockZ2); @@ -459,12 +523,12 @@ public final class QueryParams implements Cloneable private void compileLocationQueryPart(StringBuilder where, String locValue, int loc, int loc2) { int min = Math.min(loc, loc2); int max = Math.max(loc2, loc); - - if (min == max) + + if (min == max) { where.append(locValue).append(" = ").append(min); - else if (max - min > 50) + } else if (max - min > 50) { where.append(locValue).append(" >= ").append(min).append(" AND ").append(locValue).append(" <= ").append(max); - else { + } else { where.append(locValue).append(" in ("); for (int c = min; c < max; c++) { where.append(c).append(","); @@ -474,327 +538,374 @@ public final class QueryParams implements Cloneable } } - public void parseArgs(CommandSender sender, List args) throws IllegalArgumentException { - if (args == null || args.isEmpty()) - throw new IllegalArgumentException("No parameters specified."); - args = Utils.parseQuotes(args); - final Player player = sender instanceof Player ? (Player)sender : null; - final Session session = prepareToolQuery ? null : getSession(sender); - if (player != null && world == null) - world = player.getWorld(); - for (int i = 0; i < args.size(); i++) { - final String param = args.get(i).toLowerCase(); - final String[] values = getValues(args, i + 1); - if (param.equals("last")) { - if (session.lastQuery == null) - throw new IllegalArgumentException("This is your first command, you can't use last."); - merge(session.lastQuery); - } else if (param.equals("player")) { - if (values.length < 1) - throw new IllegalArgumentException("No or wrong count of arguments for '" + param + "'"); - for (final String playerName : values) - if (playerName.length() > 0) { - if (playerName.contains("!")) - excludePlayersMode = true; - if (playerName.contains("\"")) - players.add(playerName.replaceAll("[^a-zA-Z0-9_]", "")); - else { - final List matches = logblock.getServer().matchPlayer(playerName); - if (matches.size() > 1) - throw new IllegalArgumentException("Ambiguous playername '" + param + "'"); - players.add(matches.size() == 1 ? matches.get(0).getName() : playerName.replaceAll("[^a-zA-Z0-9_]", "")); - } - } - needPlayer = true; - } else if (param.equals("killer")) { - if (values.length < 1) - throw new IllegalArgumentException("No or wrong count of arguments for '" + param + "'"); - for (final String killerName : values) - if (killerName.length() > 0) { - if (killerName.contains("!")) - excludeVictimsMode = true; - if (killerName.contains("\"")) - killers.add(killerName.replaceAll("[^a-zA-Z0-9_]", "")); - else { - final List matches = logblock.getServer().matchPlayer(killerName); - if (matches.size() > 1) - throw new IllegalArgumentException("Ambiguous victimname '" + param + "'"); - killers.add(matches.size() == 1 ? matches.get(0).getName() : killerName.replaceAll("[^a-zA-Z0-9_]", "")); - } - } - needKiller = true; - } else if (param.equals("victim")) { - if (values.length < 1) - throw new IllegalArgumentException("No or wrong count of arguments for '" + param + "'"); - for (final String victimName : values) - if (victimName.length() > 0) { - if (victimName.contains("!")) - excludeVictimsMode = true; - if (victimName.contains("\"")) - victims.add(victimName.replaceAll("[^a-zA-Z0-9_]", "")); - else { - final List matches = logblock.getServer().matchPlayer(victimName); - if (matches.size() > 1) - throw new IllegalArgumentException("Ambiguous victimname '" + param + "'"); - victims.add(matches.size() == 1 ? matches.get(0).getName() : victimName.replaceAll("[^a-zA-Z0-9_]", "")); - } - } - needVictim = true; - } else if (param.equals("weapon")) { - if (values.length < 1) - throw new IllegalArgumentException("No or wrong count of arguments for '" + param + "'"); - for (final String weaponName : values) { - Material mat = Material.matchMaterial(weaponName); - if (mat == null) - try { - mat = Material.getMaterial(Integer.parseInt(weaponName)); - } catch (NumberFormatException e) { - throw new IllegalArgumentException("Data type not a valid number: '" + weaponName + "'"); - } - if (mat == null) - throw new IllegalArgumentException("No material matching: '" + weaponName + "'"); - types.add(new Block(mat.getId(), -1)); - } - needWeapon = true; - } else if (param.equals("block") || param.equals("type")) { - if (values.length < 1) - throw new IllegalArgumentException("No or wrong count of arguments for '" + param + "'"); - for (String blockName : values) { - if (blockName.startsWith("!")) { - excludeBlocksMode = true; - blockName = blockName.substring(1); - } - if (blockName.contains(":")) { - String[] blockNameSplit = blockName.split(":"); - if (blockNameSplit.length > 2) - throw new IllegalArgumentException("No material matching: '" + blockName + "'"); - final int data; - try { - data = Integer.parseInt(blockNameSplit[1]); - } catch (NumberFormatException e) { - throw new IllegalArgumentException("Data type not a valid number: '" + blockNameSplit[1] + "'"); - } - if (data > 255 || data < 0) - throw new IllegalArgumentException("Data type out of range (0-255): '" + data + "'"); - final Material mat = Material.matchMaterial(blockNameSplit[0]); - if (mat == null) - throw new IllegalArgumentException("No material matching: '" + blockName + "'"); - types.add(new Block(mat.getId(), data)); - } else { - final Material mat = Material.matchMaterial(blockName); - types.add(new Block(typeFromName(blockName), -1)); - } - } - } else if (param.equals("area")) { - if (player == null && !prepareToolQuery && loc == null) - throw new IllegalArgumentException("You have to be a player to use area, or specify a location first"); - if (values.length == 0) { - radius = defaultDist; - if (!prepareToolQuery && loc == null) - loc = player.getLocation(); - } else { - if (!isInt(values[0])) - throw new IllegalArgumentException("Not a number: '" + values[0] + "'"); - radius = Integer.parseInt(values[0]); - if (!prepareToolQuery && loc == null) - loc = player.getLocation(); - } - } else if (param.equals("selection") || param.equals("sel")) { - if (player == null) - throw new IllegalArgumentException("You have to ba a player to use selection"); - final Plugin we = player.getServer().getPluginManager().getPlugin("WorldEdit"); - if (we != null) { - setSelection(RegionContainer.fromPlayerSelection(player, we)); - } else { - throw new IllegalArgumentException("WorldEdit not found!"); - } - } else if (param.equals("time") || param.equals("since")) { - since = values.length > 0 ? parseTimeSpec(values) : defaultTime; - if (since == -1) - throw new IllegalArgumentException("Failed to parse time spec for '" + param + "'"); - } else if (param.equals("before")) { - before = values.length > 0 ? parseTimeSpec(values) : defaultTime; - if (before == -1) - throw new IllegalArgumentException("Faile to parse time spec for '" + param + "'"); - } else if (param.equals("sum")) { - if (values.length != 1) - throw new IllegalArgumentException("No or wrong count of arguments for '" + param + "'"); - if (values[0].startsWith("p")) - sum = SummarizationMode.PLAYERS; - else if (values[0].startsWith("b")) - sum = SummarizationMode.TYPES; - else if (values[0].startsWith("n")) - sum = SummarizationMode.NONE; - else - throw new IllegalArgumentException("Wrong summarization mode"); - } else if (param.equals("created")) - bct = BlockChangeType.CREATED; - else if (param.equals("destroyed")) - bct = BlockChangeType.DESTROYED; - else if (param.equals("both")) - bct = BlockChangeType.BOTH; - else if (param.equals("chestaccess")) - bct = BlockChangeType.CHESTACCESS; - else if (param.equals("chat")) - bct = BlockChangeType.CHAT; - else if (param.equals("kills")) { - bct = BlockChangeType.KILLS; - } - else if (param.equals("all")) - bct = BlockChangeType.ALL; - else if (param.equals("limit")) { - if (values.length != 1) - throw new IllegalArgumentException("Wrong count of arguments for '" + param + "'"); - if (!isInt(values[0])) - throw new IllegalArgumentException("Not a number: '" + values[0] + "'"); - limit = Integer.parseInt(values[0]); - } else if (param.equals("world")) { - if (values.length != 1) - throw new IllegalArgumentException("Wrong count of arguments for '" + param + "'"); - final World w = sender.getServer().getWorld(values[0].replace("\"", "")); - if (w == null) - throw new IllegalArgumentException("There is no world called '" + values[0] + "'"); - world = w; - } else if (param.equals("asc")) - order = Order.ASC; - else if (param.equals("desc")) - order = Order.DESC; - else if (param.equals("coords")) - needCoords = true; - else if (param.equals("silent")) - silent = true; - else if (param.equals("search") || param.equals("match")) { - if (values.length == 0) - throw new IllegalArgumentException("No arguments for '" + param + "'"); - match = join(values, " ").replace("\\", "\\\\").replace("'", "\\'"); - } else if (param.equals("loc") || param.equals("location")) { - final String[] vectors = values.length == 1 ? values[0].split(":") : values; - if (vectors.length != 3) - throw new IllegalArgumentException("Wrong count arguments for '" + param + "'"); - for (final String vec : vectors) - if (!isInt(vec)) - throw new IllegalArgumentException("Not a number: '" + vec + "'"); - loc = new Location(null, Integer.valueOf(vectors[0]), Integer.valueOf(vectors[1]), Integer.valueOf(vectors[2])); - radius = 0; - } else - throw new IllegalArgumentException("Not a valid argument: '" + param + "'"); - i += values.length; - } - if (bct == BlockChangeType.KILLS) { - if (world == null) - throw new IllegalArgumentException("No world specified"); - if (!getWorldConfig(world).isLogging(Logging.KILL)) - throw new IllegalArgumentException("Kill logging not enabled for world '" + world.getName() + "'"); - } - if (types.size() > 0) - for (final Set equivalent : getBlockEquivalents()) { - boolean found = false; - for (final Block block : types) - if (equivalent.contains(block.getBlock())) { - found = true; - break; - } - if (found) - for (final Integer type : equivalent) - if (!Block.inList(types, type)) - types.add(new Block(type, -1)); - } - if (!prepareToolQuery && bct != BlockChangeType.CHAT) { - if (world == null) - throw new IllegalArgumentException("No world specified"); - if (!isLogged(world)) - throw new IllegalArgumentException("This world ('" + world.getName() + "') isn't logged"); - } - if (session != null) - session.lastQuery = clone(); - } + public void parseArgs(CommandSender sender, List args) throws IllegalArgumentException { + if (args == null || args.isEmpty()) { + throw new IllegalArgumentException("No parameters specified."); + } + args = Utils.parseQuotes(args); + final Player player = sender instanceof Player ? (Player) sender : null; + final Session session = prepareToolQuery ? null : getSession(sender); + if (player != null && world == null) { + world = player.getWorld(); + } + for (int i = 0; i < args.size(); i++) { + final String param = args.get(i).toLowerCase(); + final String[] values = getValues(args, i + 1); + if (param.equals("last")) { + if (session.lastQuery == null) { + throw new IllegalArgumentException("This is your first command, you can't use last."); + } + merge(session.lastQuery); + } else if (param.equals("player")) { + if (values.length < 1) { + throw new IllegalArgumentException("No or wrong count of arguments for '" + param + "'"); + } + for (final String playerName : values) { + if (playerName.length() > 0) { + if (playerName.contains("!")) { + excludePlayersMode = true; + } + if (playerName.contains("\"")) { + players.add(playerName.replaceAll("[^a-zA-Z0-9_]", "")); + } else { + final List matches = logblock.getServer().matchPlayer(playerName); + if (matches.size() > 1) { + throw new IllegalArgumentException("Ambiguous playername '" + param + "'"); + } + players.add(matches.size() == 1 ? matches.get(0).getName() : playerName.replaceAll("[^a-zA-Z0-9_]", "")); + } + } + } + needPlayer = true; + } else if (param.equals("killer")) { + if (values.length < 1) { + throw new IllegalArgumentException("No or wrong count of arguments for '" + param + "'"); + } + for (final String killerName : values) { + if (killerName.length() > 0) { + if (killerName.contains("!")) { + excludeVictimsMode = true; + } + if (killerName.contains("\"")) { + killers.add(killerName.replaceAll("[^a-zA-Z0-9_]", "")); + } else { + final List matches = logblock.getServer().matchPlayer(killerName); + if (matches.size() > 1) { + throw new IllegalArgumentException("Ambiguous victimname '" + param + "'"); + } + killers.add(matches.size() == 1 ? matches.get(0).getName() : killerName.replaceAll("[^a-zA-Z0-9_]", "")); + } + } + } + needKiller = true; + } else if (param.equals("victim")) { + if (values.length < 1) { + throw new IllegalArgumentException("No or wrong count of arguments for '" + param + "'"); + } + for (final String victimName : values) { + if (victimName.length() > 0) { + if (victimName.contains("!")) { + excludeVictimsMode = true; + } + if (victimName.contains("\"")) { + victims.add(victimName.replaceAll("[^a-zA-Z0-9_]", "")); + } else { + final List matches = logblock.getServer().matchPlayer(victimName); + if (matches.size() > 1) { + throw new IllegalArgumentException("Ambiguous victimname '" + param + "'"); + } + victims.add(matches.size() == 1 ? matches.get(0).getName() : victimName.replaceAll("[^a-zA-Z0-9_]", "")); + } + } + } + needVictim = true; + } else if (param.equals("weapon")) { + if (values.length < 1) { + throw new IllegalArgumentException("No or wrong count of arguments for '" + param + "'"); + } + for (final String weaponName : values) { + Material mat = Material.matchMaterial(weaponName); + if (mat == null) { + try { + mat = Material.getMaterial(Integer.parseInt(weaponName)); + } catch (NumberFormatException e) { + throw new IllegalArgumentException("Data type not a valid number: '" + weaponName + "'"); + } + } + if (mat == null) { + throw new IllegalArgumentException("No material matching: '" + weaponName + "'"); + } + types.add(new Block(mat.getId(), -1)); + } + needWeapon = true; + } else if (param.equals("block") || param.equals("type")) { + if (values.length < 1) { + throw new IllegalArgumentException("No or wrong count of arguments for '" + param + "'"); + } + for (String blockName : values) { + if (blockName.startsWith("!")) { + excludeBlocksMode = true; + blockName = blockName.substring(1); + } + if (blockName.contains(":")) { + String[] blockNameSplit = blockName.split(":"); + if (blockNameSplit.length > 2) { + throw new IllegalArgumentException("No material matching: '" + blockName + "'"); + } + final int data; + try { + data = Integer.parseInt(blockNameSplit[1]); + } catch (NumberFormatException e) { + throw new IllegalArgumentException("Data type not a valid number: '" + blockNameSplit[1] + "'"); + } + if (data > 255 || data < 0) { + throw new IllegalArgumentException("Data type out of range (0-255): '" + data + "'"); + } + final Material mat = Material.matchMaterial(blockNameSplit[0]); + if (mat == null) { + throw new IllegalArgumentException("No material matching: '" + blockName + "'"); + } + types.add(new Block(mat.getId(), data)); + } else { + final Material mat = Material.matchMaterial(blockName); + types.add(new Block(typeFromName(blockName), -1)); + } + } + } else if (param.equals("area")) { + if (player == null && !prepareToolQuery && loc == null) { + throw new IllegalArgumentException("You have to be a player to use area, or specify a location first"); + } + if (values.length == 0) { + radius = defaultDist; + if (!prepareToolQuery && loc == null) { + loc = player.getLocation(); + } + } else { + if (!isInt(values[0])) { + throw new IllegalArgumentException("Not a number: '" + values[0] + "'"); + } + radius = Integer.parseInt(values[0]); + if (!prepareToolQuery && loc == null) { + loc = player.getLocation(); + } + } + } else if (param.equals("selection") || param.equals("sel")) { + if (player == null) { + throw new IllegalArgumentException("You have to ba a player to use selection"); + } + final Plugin we = player.getServer().getPluginManager().getPlugin("WorldEdit"); + if (we != null) { + setSelection(RegionContainer.fromPlayerSelection(player, we)); + } else { + throw new IllegalArgumentException("WorldEdit not found!"); + } + } else if (param.equals("time") || param.equals("since")) { + since = values.length > 0 ? parseTimeSpec(values) : defaultTime; + if (since == -1) { + throw new IllegalArgumentException("Failed to parse time spec for '" + param + "'"); + } + } else if (param.equals("before")) { + before = values.length > 0 ? parseTimeSpec(values) : defaultTime; + if (before == -1) { + throw new IllegalArgumentException("Faile to parse time spec for '" + param + "'"); + } + } else if (param.equals("sum")) { + if (values.length != 1) { + throw new IllegalArgumentException("No or wrong count of arguments for '" + param + "'"); + } + if (values[0].startsWith("p")) { + sum = SummarizationMode.PLAYERS; + } else if (values[0].startsWith("b")) { + sum = SummarizationMode.TYPES; + } else if (values[0].startsWith("n")) { + sum = SummarizationMode.NONE; + } else { + throw new IllegalArgumentException("Wrong summarization mode"); + } + } else if (param.equals("created")) { + bct = BlockChangeType.CREATED; + } else if (param.equals("destroyed")) { + bct = BlockChangeType.DESTROYED; + } else if (param.equals("both")) { + bct = BlockChangeType.BOTH; + } else if (param.equals("chestaccess")) { + bct = BlockChangeType.CHESTACCESS; + } else if (param.equals("chat")) { + bct = BlockChangeType.CHAT; + } else if (param.equals("kills")) { + bct = BlockChangeType.KILLS; + } else if (param.equals("all")) { + bct = BlockChangeType.ALL; + } else if (param.equals("limit")) { + if (values.length != 1) { + throw new IllegalArgumentException("Wrong count of arguments for '" + param + "'"); + } + if (!isInt(values[0])) { + throw new IllegalArgumentException("Not a number: '" + values[0] + "'"); + } + limit = Integer.parseInt(values[0]); + } else if (param.equals("world")) { + if (values.length != 1) { + throw new IllegalArgumentException("Wrong count of arguments for '" + param + "'"); + } + final World w = sender.getServer().getWorld(values[0].replace("\"", "")); + if (w == null) { + throw new IllegalArgumentException("There is no world called '" + values[0] + "'"); + } + world = w; + } else if (param.equals("asc")) { + order = Order.ASC; + } else if (param.equals("desc")) { + order = Order.DESC; + } else if (param.equals("coords")) { + needCoords = true; + } else if (param.equals("silent")) { + silent = true; + } else if (param.equals("search") || param.equals("match")) { + if (values.length == 0) { + throw new IllegalArgumentException("No arguments for '" + param + "'"); + } + match = join(values, " ").replace("\\", "\\\\").replace("'", "\\'"); + } else if (param.equals("loc") || param.equals("location")) { + final String[] vectors = values.length == 1 ? values[0].split(":") : values; + if (vectors.length != 3) { + throw new IllegalArgumentException("Wrong count arguments for '" + param + "'"); + } + for (final String vec : vectors) { + if (!isInt(vec)) { + throw new IllegalArgumentException("Not a number: '" + vec + "'"); + } + } + loc = new Location(null, Integer.valueOf(vectors[0]), Integer.valueOf(vectors[1]), Integer.valueOf(vectors[2])); + radius = 0; + } else { + throw new IllegalArgumentException("Not a valid argument: '" + param + "'"); + } + i += values.length; + } + if (bct == BlockChangeType.KILLS) { + if (world == null) { + throw new IllegalArgumentException("No world specified"); + } + if (!getWorldConfig(world).isLogging(Logging.KILL)) { + throw new IllegalArgumentException("Kill logging not enabled for world '" + world.getName() + "'"); + } + } + if (types.size() > 0) { + for (final Set equivalent : getBlockEquivalents()) { + boolean found = false; + for (final Block block : types) { + if (equivalent.contains(block.getBlock())) { + found = true; + break; + } + } + if (found) { + for (final Integer type : equivalent) { + if (!Block.inList(types, type)) { + types.add(new Block(type, -1)); + } + } + } + } + } + if (!prepareToolQuery && bct != BlockChangeType.CHAT) { + if (world == null) { + throw new IllegalArgumentException("No world specified"); + } + if (!isLogged(world)) { + throw new IllegalArgumentException("This world ('" + world.getName() + "') isn't logged"); + } + } + if (session != null) { + session.lastQuery = clone(); + } + } - public void setLocation(Location loc) { - this.loc = loc; - world = loc.getWorld(); - } + public void setLocation(Location loc) { + this.loc = loc; + world = loc.getWorld(); + } - public void setSelection(RegionContainer container) { - this.sel = container; - world = sel.getSelection().getWorld(); - } + public void setSelection(RegionContainer container) { + this.sel = container; + world = sel.getSelection().getWorld(); + } - public void setPlayer(String playerName) { - players.clear(); - players.add(playerName); - } + public void setPlayer(String playerName) { + players.clear(); + players.add(playerName); + } - @Override - protected QueryParams clone() { - try { - final QueryParams params = (QueryParams)super.clone(); - params.players = new ArrayList(players); - params.types = new ArrayList(types); - return params; - } catch (final CloneNotSupportedException ex) { - } - return null; - } + @Override + protected QueryParams clone() { + try { + final QueryParams params = (QueryParams) super.clone(); + params.players = new ArrayList(players); + params.types = new ArrayList(types); + return params; + } catch (final CloneNotSupportedException ex) { + } + return null; + } - private static String[] getValues(List args, int offset) { - // The variable i will store the last value's index - int i; - // Iterate over the all the values from the offset up till the end - for (i = offset; i < args.size(); i++) { - // We found a keyword, break here since anything after this isn't a value. - if (isKeyWord(args.get(i))) { - break; - } - } - // If there are no values, i.e there is a keyword immediately after the offset - // return an empty string array - if (i == offset) { - return new String[0]; - } + private static String[] getValues(List args, int offset) { + // The variable i will store the last value's index + int i; + // Iterate over the all the values from the offset up till the end + for (i = offset; i < args.size(); i++) { + // We found a keyword, break here since anything after this isn't a value. + if (isKeyWord(args.get(i))) { + break; + } + } + // If there are no values, i.e there is a keyword immediately after the offset + // return an empty string array + if (i == offset) { + return new String[0]; + } - final String[] values = new String[i - offset]; - for (int j = offset; j < i; j++) { - String value = args.get(j); + final String[] values = new String[i - offset]; + for (int j = offset; j < i; j++) { + String value = args.get(j); - // If the value is encapsulated in quotes, strip them - if (value.startsWith("\"") && value.endsWith("\"")) { - value = value.substring(1, value.length() - 1); - } - values[j - offset] = value; - } - return values; - } + // If the value is encapsulated in quotes, strip them + if (value.startsWith("\"") && value.endsWith("\"")) { + value = value.substring(1, value.length() - 1); + } + values[j - offset] = value; + } + return values; + } - public void merge(QueryParams p) { - players = p.players; - excludePlayersMode = p.excludePlayersMode; - types = p.types; - loc = p.loc; - radius = p.radius; - sel = p.sel; - if (p.since != 0 || since != defaultTime) - since = p.since; - before = p.before; - sum = p.sum; - bct = p.bct; - limit = p.limit; - world = p.world; - order = p.order; - match = p.match; - } + public void merge(QueryParams p) { + players = p.players; + excludePlayersMode = p.excludePlayersMode; + types = p.types; + loc = p.loc; + radius = p.radius; + sel = p.sel; + if (p.since != 0 || since != defaultTime) { + since = p.since; + } + before = p.before; + sum = p.sum; + bct = p.bct; + limit = p.limit; + world = p.world; + order = p.order; + match = p.match; + } - public static enum BlockChangeType - { - ALL, BOTH, CHESTACCESS, CREATED, DESTROYED, CHAT, KILLS - } + public static enum BlockChangeType { + ALL, BOTH, CHESTACCESS, CREATED, DESTROYED, CHAT, KILLS + } - public static enum Order - { - ASC, DESC - } + public static enum Order { + ASC, DESC + } - public static enum SummarizationMode - { - NONE, PLAYERS, TYPES - } + public static enum SummarizationMode { + NONE, PLAYERS, TYPES + } } diff --git a/src/main/java/de/diddiz/LogBlock/Session.java b/src/main/java/de/diddiz/LogBlock/Session.java index 7cc1d72..3e53355 100644 --- a/src/main/java/de/diddiz/LogBlock/Session.java +++ b/src/main/java/de/diddiz/LogBlock/Session.java @@ -1,46 +1,49 @@ package de.diddiz.LogBlock; -import static de.diddiz.LogBlock.config.Config.toolsByType; -import static org.bukkit.Bukkit.getServer; -import java.util.HashMap; -import java.util.Map; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; -public class Session -{ - private static final Map sessions = new HashMap(); - public QueryParams lastQuery = null; - public LookupCacheElement[] lookupCache = null; - public int page = 1; - public Map toolData; +import java.util.HashMap; +import java.util.Map; - private Session(Player player) { - toolData = new HashMap(); - final LogBlock logblock = LogBlock.getInstance(); - if (player != null) - for (final Tool tool : toolsByType.values()) - toolData.put(tool, new ToolData(tool, logblock, player)); - } +import static de.diddiz.LogBlock.config.Config.toolsByType; +import static org.bukkit.Bukkit.getServer; - public static boolean hasSession(CommandSender sender) { - return sessions.containsKey(sender.getName().toLowerCase()); - } +public class Session { + private static final Map sessions = new HashMap(); + public QueryParams lastQuery = null; + public LookupCacheElement[] lookupCache = null; + public int page = 1; + public Map toolData; - public static boolean hasSession(String playerName) { - return sessions.containsKey(playerName.toLowerCase()); - } + private Session(Player player) { + toolData = new HashMap(); + final LogBlock logblock = LogBlock.getInstance(); + if (player != null) { + for (final Tool tool : toolsByType.values()) { + toolData.put(tool, new ToolData(tool, logblock, player)); + } + } + } - public static Session getSession(CommandSender sender) { - return getSession(sender.getName()); - } + public static boolean hasSession(CommandSender sender) { + return sessions.containsKey(sender.getName().toLowerCase()); + } - public static Session getSession(String playerName) { - Session session = sessions.get(playerName.toLowerCase()); - if (session == null) { - session = new Session(getServer().getPlayer(playerName)); - sessions.put(playerName.toLowerCase(), session); - } - return session; - } + public static boolean hasSession(String playerName) { + return sessions.containsKey(playerName.toLowerCase()); + } + + public static Session getSession(CommandSender sender) { + return getSession(sender.getName()); + } + + public static Session getSession(String playerName) { + Session session = sessions.get(playerName.toLowerCase()); + if (session == null) { + session = new Session(getServer().getPlayer(playerName)); + sessions.put(playerName.toLowerCase(), session); + } + return session; + } } diff --git a/src/main/java/de/diddiz/LogBlock/SummedBlockChanges.java b/src/main/java/de/diddiz/LogBlock/SummedBlockChanges.java index 5e7cd61..f6dfa0d 100644 --- a/src/main/java/de/diddiz/LogBlock/SummedBlockChanges.java +++ b/src/main/java/de/diddiz/LogBlock/SummedBlockChanges.java @@ -1,35 +1,36 @@ package de.diddiz.LogBlock; +import de.diddiz.LogBlock.QueryParams.SummarizationMode; +import org.bukkit.Location; + +import java.sql.ResultSet; +import java.sql.SQLException; + import static de.diddiz.util.MaterialName.materialName; import static de.diddiz.util.Utils.spaces; -import java.sql.ResultSet; -import java.sql.SQLException; -import org.bukkit.Location; -import de.diddiz.LogBlock.QueryParams.SummarizationMode; -public class SummedBlockChanges implements LookupCacheElement -{ - private final String group; - private final int created, destroyed; - private final float spaceFactor; - private final Actor actor; +public class SummedBlockChanges implements LookupCacheElement { + private final String group; + private final int created, destroyed; + private final float spaceFactor; + private final Actor actor; - public SummedBlockChanges(ResultSet rs, QueryParams p, float spaceFactor) throws SQLException { - // Actor currently useless here as we don't yet output UUID in results anywhere - actor = p.sum == SummarizationMode.PLAYERS ? new Actor(rs) : null; - group = actor == null ? materialName(rs.getInt("type")) : actor.getName(); - created = rs.getInt("created"); - destroyed = rs.getInt("destroyed"); - this.spaceFactor = spaceFactor; - } + public SummedBlockChanges(ResultSet rs, QueryParams p, float spaceFactor) throws SQLException { + // Actor currently useless here as we don't yet output UUID in results anywhere + actor = p.sum == SummarizationMode.PLAYERS ? new Actor(rs) : null; + group = actor == null ? materialName(rs.getInt("type")) : actor.getName(); + created = rs.getInt("created"); + destroyed = rs.getInt("destroyed"); + this.spaceFactor = spaceFactor; + } - @Override - public Location getLocation() { - return null; - } + @Override + public Location getLocation() { + return null; + } - @Override - public String getMessage() { - return created + spaces((int)((10 - String.valueOf(created).length()) / spaceFactor)) + destroyed + spaces((int)((10 - String.valueOf(destroyed).length()) / spaceFactor)) + group; - } + @Override + public String getMessage() { + return created + spaces((int) ((10 - String.valueOf(created).length()) / spaceFactor)) + destroyed + spaces((int) ((10 - String.valueOf(destroyed).length()) / spaceFactor)) + group; + } } diff --git a/src/main/java/de/diddiz/LogBlock/SummedKills.java b/src/main/java/de/diddiz/LogBlock/SummedKills.java index 5e3d702..3db7781 100644 --- a/src/main/java/de/diddiz/LogBlock/SummedKills.java +++ b/src/main/java/de/diddiz/LogBlock/SummedKills.java @@ -1,30 +1,31 @@ package de.diddiz.LogBlock; -import static de.diddiz.util.Utils.spaces; -import java.sql.ResultSet; -import java.sql.SQLException; import org.bukkit.Location; -public class SummedKills implements LookupCacheElement -{ - private final Actor player; - private final int kills, killed; - private final float spaceFactor; +import java.sql.ResultSet; +import java.sql.SQLException; - public SummedKills(ResultSet rs, QueryParams p, float spaceFactor) throws SQLException { - player = new Actor(rs); - kills = rs.getInt("kills"); - killed = rs.getInt("killed"); - this.spaceFactor = spaceFactor; - } +import static de.diddiz.util.Utils.spaces; - @Override - public Location getLocation() { - return null; - } +public class SummedKills implements LookupCacheElement { + private final Actor player; + private final int kills, killed; + private final float spaceFactor; - @Override - public String getMessage() { - return kills + spaces((int)((6 - String.valueOf(kills).length()) / spaceFactor)) + killed + spaces((int)((7 - String.valueOf(killed).length()) / spaceFactor)) + player.getName(); - } + public SummedKills(ResultSet rs, QueryParams p, float spaceFactor) throws SQLException { + player = new Actor(rs); + kills = rs.getInt("kills"); + killed = rs.getInt("killed"); + this.spaceFactor = spaceFactor; + } + + @Override + public Location getLocation() { + return null; + } + + @Override + public String getMessage() { + return kills + spaces((int) ((6 - String.valueOf(kills).length()) / spaceFactor)) + killed + spaces((int) ((7 - String.valueOf(killed).length()) / spaceFactor)) + player.getName(); + } } diff --git a/src/main/java/de/diddiz/LogBlock/Tool.java b/src/main/java/de/diddiz/LogBlock/Tool.java index 8f1a6e8..e84c982 100644 --- a/src/main/java/de/diddiz/LogBlock/Tool.java +++ b/src/main/java/de/diddiz/LogBlock/Tool.java @@ -1,30 +1,30 @@ package de.diddiz.LogBlock; -import java.util.List; import org.bukkit.permissions.PermissionDefault; -public class Tool -{ - public final String name; - public final List aliases; - public final ToolBehavior leftClickBehavior, rightClickBehavior; - public final boolean defaultEnabled; - public final int item; - public final boolean canDrop; - public final QueryParams params; - public final ToolMode mode; - public final PermissionDefault permissionDefault; +import java.util.List; - public Tool(String name, List aliases, ToolBehavior leftClickBehavior, ToolBehavior rightClickBehavior, boolean defaultEnabled, int item, boolean canDrop, QueryParams params, ToolMode mode, PermissionDefault permissionDefault) { - this.name = name; - this.aliases = aliases; - this.leftClickBehavior = leftClickBehavior; - this.rightClickBehavior = rightClickBehavior; - this.defaultEnabled = defaultEnabled; - this.item = item; - this.canDrop = canDrop; - this.params = params; - this.mode = mode; - this.permissionDefault = permissionDefault; - } +public class Tool { + public final String name; + public final List aliases; + public final ToolBehavior leftClickBehavior, rightClickBehavior; + public final boolean defaultEnabled; + public final int item; + public final boolean canDrop; + public final QueryParams params; + public final ToolMode mode; + public final PermissionDefault permissionDefault; + + public Tool(String name, List aliases, ToolBehavior leftClickBehavior, ToolBehavior rightClickBehavior, boolean defaultEnabled, int item, boolean canDrop, QueryParams params, ToolMode mode, PermissionDefault permissionDefault) { + this.name = name; + this.aliases = aliases; + this.leftClickBehavior = leftClickBehavior; + this.rightClickBehavior = rightClickBehavior; + this.defaultEnabled = defaultEnabled; + this.item = item; + this.canDrop = canDrop; + this.params = params; + this.mode = mode; + this.permissionDefault = permissionDefault; + } } diff --git a/src/main/java/de/diddiz/LogBlock/ToolBehavior.java b/src/main/java/de/diddiz/LogBlock/ToolBehavior.java index 4f78f20..e51e7b5 100644 --- a/src/main/java/de/diddiz/LogBlock/ToolBehavior.java +++ b/src/main/java/de/diddiz/LogBlock/ToolBehavior.java @@ -1,6 +1,5 @@ package de.diddiz.LogBlock; -public enum ToolBehavior -{ - TOOL, BLOCK, NONE +public enum ToolBehavior { + TOOL, BLOCK, NONE } diff --git a/src/main/java/de/diddiz/LogBlock/ToolData.java b/src/main/java/de/diddiz/LogBlock/ToolData.java index 1b8d1a2..f524393 100644 --- a/src/main/java/de/diddiz/LogBlock/ToolData.java +++ b/src/main/java/de/diddiz/LogBlock/ToolData.java @@ -2,15 +2,14 @@ package de.diddiz.LogBlock; import org.bukkit.entity.Player; -public class ToolData -{ - public boolean enabled; - public QueryParams params; - public ToolMode mode; +public class ToolData { + public boolean enabled; + public QueryParams params; + public ToolMode mode; - public ToolData(Tool tool, LogBlock logblock, Player player) { - enabled = tool.defaultEnabled && logblock.hasPermission(player, "logblock.tools." + tool.name); - params = tool.params.clone(); - mode = tool.mode; - } + public ToolData(Tool tool, LogBlock logblock, Player player) { + enabled = tool.defaultEnabled && logblock.hasPermission(player, "logblock.tools." + tool.name); + params = tool.params.clone(); + mode = tool.mode; + } } diff --git a/src/main/java/de/diddiz/LogBlock/ToolMode.java b/src/main/java/de/diddiz/LogBlock/ToolMode.java index a69e1ee..bea69c0 100644 --- a/src/main/java/de/diddiz/LogBlock/ToolMode.java +++ b/src/main/java/de/diddiz/LogBlock/ToolMode.java @@ -1,15 +1,14 @@ package de.diddiz.LogBlock; -public enum ToolMode -{ - CLEARLOG("logblock.clearlog"), LOOKUP("logblock.lookup"), REDO("logblock.rollback"), ROLLBACK("logblock.rollback"), WRITELOGFILE("logblock.rollback"); - private final String permission; +public enum ToolMode { + CLEARLOG("logblock.clearlog"), LOOKUP("logblock.lookup"), REDO("logblock.rollback"), ROLLBACK("logblock.rollback"), WRITELOGFILE("logblock.rollback"); + private final String permission; - private ToolMode(String permission) { - this.permission = permission; - } + private ToolMode(String permission) { + this.permission = permission; + } - public String getPermission() { - return permission; - } + public String getPermission() { + return permission; + } } diff --git a/src/main/java/de/diddiz/LogBlock/Updater.java b/src/main/java/de/diddiz/LogBlock/Updater.java index 15946c6..6151a3e 100644 --- a/src/main/java/de/diddiz/LogBlock/Updater.java +++ b/src/main/java/de/diddiz/LogBlock/Updater.java @@ -2,446 +2,464 @@ package de.diddiz.LogBlock; import de.diddiz.LogBlock.config.Config; import de.diddiz.LogBlock.config.WorldConfig; +import de.diddiz.util.UUIDFetcher; import org.bukkit.Bukkit; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.configuration.file.YamlConfiguration; import java.io.File; import java.io.IOException; -import java.sql.Connection; -import java.sql.DatabaseMetaData; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; +import java.sql.*; +import java.util.*; import java.util.logging.Level; -import java.util.ArrayList; -import java.util.List; -import java.util.Map.Entry; import static de.diddiz.LogBlock.config.Config.getLoggedWorlds; import static de.diddiz.LogBlock.config.Config.isLogging; import static de.diddiz.util.BukkitUtils.friendlyWorldname; -import de.diddiz.util.UUIDFetcher; -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; -import java.util.logging.Logger; import static org.bukkit.Bukkit.getLogger; -class Updater -{ - private final LogBlock logblock; - final int UUID_CONVERT_BATCH_SIZE = 100; +class Updater { + private final LogBlock logblock; + final int UUID_CONVERT_BATCH_SIZE = 100; - Updater(LogBlock logblock) { - this.logblock = logblock; - } + Updater(LogBlock logblock) { + this.logblock = logblock; + } - boolean update() { - final ConfigurationSection config = logblock.getConfig(); - if (config.getString("version").compareTo(logblock.getDescription().getVersion()) >= 0) - return false; - if (config.getString("version").compareTo("1.27") < 0) { - getLogger().info("Updating tables to 1.27 ..."); - if (isLogging(Logging.CHAT)) { - final Connection conn = logblock.getConnection(); - try { - conn.setAutoCommit(true); - final Statement st = conn.createStatement(); - st.execute("ALTER TABLE `lb-chat` ENGINE = MyISAM, ADD FULLTEXT message (message)"); - st.close(); - conn.close(); - } catch (final SQLException ex) { - Bukkit.getLogger().log(Level.SEVERE, "[Updater] Error: ", ex); - return false; - } - } - config.set("version", "1.27"); - } - if (config.getString("version").compareTo("1.30") < 0) { - getLogger().info("Updating config to 1.30 ..."); - for (final String tool : config.getConfigurationSection("tools").getKeys(false)) - if (config.get("tools." + tool + ".permissionDefault") == null) - config.set("tools." + tool + ".permissionDefault", "OP"); - config.set("version", "1.30"); - } - if (config.getString("version").compareTo("1.31") < 0) { - getLogger().info("Updating tables to 1.31 ..."); - final Connection conn = logblock.getConnection(); - try { - conn.setAutoCommit(true); - final Statement st = conn.createStatement(); - st.execute("ALTER TABLE `lb-players` ADD COLUMN lastlogin DATETIME NOT NULL, ADD COLUMN onlinetime TIME NOT NULL, ADD COLUMN ip VARCHAR(255) NOT NULL"); - st.close(); - conn.close(); - } catch (final SQLException ex) { - Bukkit.getLogger().log(Level.SEVERE, "[Updater] Error: ", ex); - return false; - } - config.set("version", "1.31"); - } - if (config.getString("version").compareTo("1.32") < 0) { - getLogger().info("Updating tables to 1.32 ..."); - final Connection conn = logblock.getConnection(); - try { - conn.setAutoCommit(true); - final Statement st = conn.createStatement(); - st.execute("ALTER TABLE `lb-players` ADD COLUMN firstlogin DATETIME NOT NULL AFTER playername"); - st.close(); - conn.close(); - } catch (final SQLException ex) { - Bukkit.getLogger().log(Level.SEVERE, "[Updater] Error: ", ex); - return false; - } - config.set("version", "1.32"); - } - if (config.getString("version").compareTo("1.40") < 0) { - getLogger().info("Updating config to 1.40 ..."); - config.set("clearlog.keepLogDays", null); - config.set("version", "1.40"); - } - if (config.getString("version").compareTo("1.42") < 0) { - getLogger().info("Updating config to 1.42 ..."); - for (final String world : config.getStringList("loggedWorlds")) { - final File file = new File(logblock.getDataFolder(), friendlyWorldname(world) + ".yml"); - final YamlConfiguration wcfg = YamlConfiguration.loadConfiguration(file); - if (wcfg.contains("logBlockCreations")) - wcfg.set("logging.BLOCKPLACE", wcfg.getBoolean("logBlockCreations")); - if (wcfg.contains("logBlockDestroyings")) - wcfg.set("logging.BLOCKBREAK", wcfg.getBoolean("logBlockDestroyings")); - if (wcfg.contains("logSignTexts")) - wcfg.set("logging.SIGNTEXT", wcfg.getBoolean("logSignTexts")); - if (wcfg.contains("logFire")) - wcfg.set("logging.FIRE", wcfg.getBoolean("logFire")); - if (wcfg.contains("logLeavesDecay")) - wcfg.set("logging.LEAVESDECAY", wcfg.getBoolean("logLeavesDecay")); - if (wcfg.contains("logLavaFlow")) - wcfg.set("logging.LAVAFLOW", wcfg.getBoolean("logLavaFlow")); - if (wcfg.contains("logWaterFlow")) - wcfg.set("logging.WATERFLOW", wcfg.getBoolean("logWaterFlow")); - if (wcfg.contains("logChestAccess")) - wcfg.set("logging.CHESTACCESS", wcfg.getBoolean("logChestAccess")); - if (wcfg.contains("logButtonsAndLevers")) - wcfg.set("logging.SWITCHINTERACT", wcfg.getBoolean("logButtonsAndLevers")); - if (wcfg.contains("logKills")) - wcfg.set("logging.KILL", wcfg.getBoolean("logKills")); - if (wcfg.contains("logChat")) - wcfg.set("logging.CHAT", wcfg.getBoolean("logChat")); - if (wcfg.contains("logSnowForm")) - wcfg.set("logging.SNOWFORM", wcfg.getBoolean("logSnowForm")); - if (wcfg.contains("logSnowFade")) - wcfg.set("logging.SNOWFADE", wcfg.getBoolean("logSnowFade")); - if (wcfg.contains("logDoors")) - wcfg.set("logging.DOORINTERACT", wcfg.getBoolean("logDoors")); - if (wcfg.contains("logCakes")) - wcfg.set("logging.CAKEEAT", wcfg.getBoolean("logCakes")); - if (wcfg.contains("logEndermen")) - wcfg.set("logging.ENDERMEN", wcfg.getBoolean("logEndermen")); - if (wcfg.contains("logExplosions")) { - final boolean logExplosions = wcfg.getBoolean("logExplosions"); - wcfg.set("logging.TNTEXPLOSION", logExplosions); - wcfg.set("logging.MISCEXPLOSION", logExplosions); - wcfg.set("logging.CREEPEREXPLOSION", logExplosions); - wcfg.set("logging.GHASTFIREBALLEXPLOSION", logExplosions); - } - wcfg.set("logBlockCreations", null); - wcfg.set("logBlockDestroyings", null); - wcfg.set("logSignTexts", null); - wcfg.set("logExplosions", null); - wcfg.set("logFire", null); - wcfg.set("logLeavesDecay", null); - wcfg.set("logLavaFlow", null); - wcfg.set("logWaterFlow", null); - wcfg.set("logChestAccess", null); - wcfg.set("logButtonsAndLevers", null); - wcfg.set("logKills", null); - wcfg.set("logChat", null); - wcfg.set("logSnowForm", null); - wcfg.set("logSnowFade", null); - wcfg.set("logDoors", null); - wcfg.set("logCakes", null); - wcfg.set("logEndermen", null); - try { - wcfg.save(file); - } catch (final IOException ex) { - Bukkit.getLogger().log(Level.SEVERE, "[Updater] Error: ", ex); - } - } - config.set("clearlog.keepLogDays", null); - config.set("version", "1.42"); - } - if (config.getString("version").compareTo("1.51") < 0) { - getLogger().info("Updating tables to 1.51 ..."); - final Connection conn = logblock.getConnection(); - try { - conn.setAutoCommit(true); - final Statement st = conn.createStatement(); - for (final WorldConfig wcfg : getLoggedWorlds()) - if (wcfg.isLogging(Logging.KILL)) - st.execute("ALTER TABLE `" + wcfg.table + "-kills` ADD (x MEDIUMINT NOT NULL DEFAULT 0, y SMALLINT NOT NULL DEFAULT 0, z MEDIUMINT NOT NULL DEFAULT 0)"); - st.close(); - conn.close(); - } catch (final SQLException ex) { - Bukkit.getLogger().log(Level.SEVERE, "[Updater] Error: ", ex); - return false; - } - config.set("version", "1.51"); - } - if (config.getString("version").compareTo("1.52") < 0) { - getLogger().info("Updating tables to 1.52 ..."); - final Connection conn = logblock.getConnection(); - try { - conn.setAutoCommit(true); - final Statement st = conn.createStatement(); - final ResultSet rs = st.executeQuery("SHOW COLUMNS FROM `lb-players` WHERE field = 'onlinetime'"); - if (rs.next() && rs.getString("Type").equalsIgnoreCase("time")) { - st.execute("ALTER TABLE `lb-players` ADD onlinetime2 INT UNSIGNED NOT NULL"); - st.execute("UPDATE `lb-players` SET onlinetime2 = HOUR(onlinetime) * 3600 + MINUTE(onlinetime) * 60 + SECOND(onlinetime)"); - st.execute("ALTER TABLE `lb-players` DROP onlinetime"); - st.execute("ALTER TABLE `lb-players` CHANGE onlinetime2 onlinetime INT UNSIGNED NOT NULL"); - } else - getLogger().info("Column lb-players was already modified, skipping it."); - st.close(); - conn.close(); - } catch (final SQLException ex) { - Bukkit.getLogger().log(Level.SEVERE, "[Updater] Error: ", ex); - return false; - } - config.set("version", "1.52"); - } - if (config.getString("version").compareTo("1.81") < 0) { - getLogger().info("Updating tables to 1.81 ..."); - final Connection conn = logblock.getConnection(); - try { - conn.setAutoCommit(true); - final Statement st = conn.createStatement(); - for (final WorldConfig wcfg : getLoggedWorlds()) { - if (wcfg.isLogging(Logging.CHESTACCESS)) { - st.execute("ALTER TABLE `"+wcfg.table+"-chest` CHANGE itemdata itemdata SMALLINT NOT NULL"); - getLogger().info("Table "+wcfg.table+"-chest modified"); - } - } - st.close(); - conn.close(); - } catch (final SQLException ex) { - Bukkit.getLogger().log(Level.SEVERE, "[Updater] Error: ", ex); - return false; - } - config.set("version", "1.81"); - } - - if (config.getString("version").compareTo("1.90") < 0) { - getLogger().info("Updating tables to 1.9 ..."); - getLogger().info("Importing UUIDs for large databases may take some time"); - final Connection conn = logblock.getConnection(); - try { - conn.setAutoCommit(true); - final Statement st = conn.createStatement(); - st.execute("ALTER TABLE `lb-players` ADD `UUID` VARCHAR(36) NOT NULL"); - } catch (final SQLException ex) { - // Error 1060 is MySQL error "column already exists". We want to continue with import if we get that error - if (ex.getErrorCode() != 1060) { - Bukkit.getLogger().log(Level.SEVERE, "[Updater] Error: ", ex); - return false; - } - } - try { - String unimportedPrefix="noimport_"; - ResultSet rs; - conn.setAutoCommit(true); - final Statement st = conn.createStatement(); - if (config.getBoolean("logging.logPlayerInfo")) { - // Start by assuming anything with no onlinetime is not a player - st.execute("UPDATE `lb-players` SET UUID = CONCAT ('log_',playername) WHERE onlinetime=0 AND LENGTH(UUID) = 0"); - } else { - // If we can't assume that, we must assume anything we can't look up is not a player - unimportedPrefix = "log_"; - } - // Tell people how many are needing converted - rs = st.executeQuery("SELECT COUNT(playername) FROM `lb-players` WHERE LENGTH(UUID)=0"); - rs.next(); - String total = Integer.toString(rs.getInt(1)); - getLogger().info(total + " players to convert"); - int done = 0; - - conn.setAutoCommit(false); - Map players = new HashMap(); - List names = new ArrayList(UUID_CONVERT_BATCH_SIZE); - Map response; - rs = st.executeQuery("SELECT playerid,playername FROM `lb-players` WHERE LENGTH(UUID)=0 LIMIT " + Integer.toString(UUID_CONVERT_BATCH_SIZE)); - while (rs.next()) { - do { - players.put(rs.getString(2),rs.getInt(1)); - names.add(rs.getString(2)); - } while (rs.next()); - if (names.size()>0) { - String theUUID; - response = UUIDFetcher.getUUIDs(names); - for (Map.Entry entry : players.entrySet()) { - if (response.get(entry.getKey()) == null) { - theUUID = unimportedPrefix + entry.getKey(); - getLogger().warning(entry.getKey() + " not found - giving UUID of " + theUUID); - } else { - theUUID = response.get(entry.getKey()).toString(); - } - String thePID = entry.getValue().toString(); - st.execute("UPDATE `lb-players` SET UUID = '" + theUUID + "' WHERE playerid = " + thePID); - done++; - } - conn.commit(); - players.clear(); - names.clear(); - getLogger().info("Processed " + Integer.toString(done) + " out of " + total); - rs = st.executeQuery("SELECT playerid,playername FROM `lb-players` WHERE LENGTH(UUID)=0 LIMIT " + Integer.toString(UUID_CONVERT_BATCH_SIZE)); - } - } - st.close(); - conn.close(); - - } catch (final SQLException ex) { - Bukkit.getLogger().log(Level.SEVERE, "[Updater] Error: ", ex); - return false; - } catch (Exception ex) { - Bukkit.getLogger().log(Level.SEVERE, "[UUID importer]", ex); - return false; - } - config.set("version", "1.90"); - } - // Ensure charset for free-text fields is UTF-8, or UTF8-mb4 if possible - // As this may be an expensive operation and the database default may already be this, check on a table-by-table basis before converting - if (config.getString("version").compareTo("1.92") < 0) { - getLogger().info("Updating tables to 1.92 ..."); - String charset = "utf8"; - if ( Config.mb4) charset="utf8mb4"; - final Connection conn = logblock.getConnection(); - try { - conn.setAutoCommit(true); - final Statement st = conn.createStatement(); - if (isLogging(Logging.CHAT)) { - final ResultSet rs = st.executeQuery("SHOW FULL COLUMNS FROM `lb-chat` WHERE field = 'message'"); - if (rs.next() && !rs.getString("Collation").substring(0,4).equalsIgnoreCase(charset)) { - st.execute("ALTER TABLE `lb-chat` CONVERT TO CHARSET " + charset); - getLogger().info("Table lb-chat modified"); - } else { - getLogger().info("Table lb-chat already fine, skipping it"); - } - } - for (final WorldConfig wcfg : getLoggedWorlds()) { - if (wcfg.isLogging(Logging.SIGNTEXT)) { - final ResultSet rs = st.executeQuery("SHOW FULL COLUMNS FROM `"+wcfg.table+"-sign` WHERE field = 'signtext'"); - if (rs.next() && !rs.getString("Collation").substring(0,4).equalsIgnoreCase(charset)) { - st.execute("ALTER TABLE `"+wcfg.table+"-sign` CONVERT TO CHARSET " + charset); - getLogger().info("Table "+wcfg.table+"-sign modified"); - } else { - getLogger().info("Table "+wcfg.table+"-sign already fine, skipping it"); - } - } - } - st.close(); - conn.close(); - } catch (final SQLException ex) { - Bukkit.getLogger().log(Level.SEVERE, "[Updater] Error: ", ex); - return false; - } - config.set("version", "1.92"); - } - if (config.getString("version").compareTo("1.94") < 0) { - getLogger().info("Updating tables to 1.94 ..."); - final Connection conn = logblock.getConnection(); - try { - conn.setAutoCommit(true); - final Statement st = conn.createStatement(); - // Need to wrap both these next two inside individual try/catch statements in case index does not exist - try { - st.execute("DROP INDEX UUID ON `lb-players`"); - } catch (final SQLException ex) { - if (ex.getErrorCode() != 1091) { - Bukkit.getLogger().log(Level.SEVERE, "[Updater] Error: ", ex); - return false; - } - } - try { - st.execute("DROP INDEX playername ON `lb-players`"); - } catch (final SQLException ex) { - if (ex.getErrorCode() != 1091) { - Bukkit.getLogger().log(Level.SEVERE, "[Updater] Error: ", ex); - return false; - } - } - st.execute("CREATE INDEX UUID ON `lb-players` (UUID);"); - st.execute("CREATE INDEX playername ON `lb-players` (playername);"); - st.close(); - conn.close(); - } catch (final SQLException ex) { - Bukkit.getLogger().log(Level.SEVERE, "[Updater] Error: ", ex); - return false; - } - config.set("version", "1.94"); - } + boolean update() { + final ConfigurationSection config = logblock.getConfig(); + if (config.getString("version").compareTo(logblock.getDescription().getVersion()) >= 0) { + return false; + } + if (config.getString("version").compareTo("1.27") < 0) { + getLogger().info("Updating tables to 1.27 ..."); + if (isLogging(Logging.CHAT)) { + final Connection conn = logblock.getConnection(); + try { + conn.setAutoCommit(true); + final Statement st = conn.createStatement(); + st.execute("ALTER TABLE `lb-chat` ENGINE = MyISAM, ADD FULLTEXT message (message)"); + st.close(); + conn.close(); + } catch (final SQLException ex) { + Bukkit.getLogger().log(Level.SEVERE, "[Updater] Error: ", ex); + return false; + } + } + config.set("version", "1.27"); + } + if (config.getString("version").compareTo("1.30") < 0) { + getLogger().info("Updating config to 1.30 ..."); + for (final String tool : config.getConfigurationSection("tools").getKeys(false)) { + if (config.get("tools." + tool + ".permissionDefault") == null) { + config.set("tools." + tool + ".permissionDefault", "OP"); + } + } + config.set("version", "1.30"); + } + if (config.getString("version").compareTo("1.31") < 0) { + getLogger().info("Updating tables to 1.31 ..."); + final Connection conn = logblock.getConnection(); + try { + conn.setAutoCommit(true); + final Statement st = conn.createStatement(); + st.execute("ALTER TABLE `lb-players` ADD COLUMN lastlogin DATETIME NOT NULL, ADD COLUMN onlinetime TIME NOT NULL, ADD COLUMN ip VARCHAR(255) NOT NULL"); + st.close(); + conn.close(); + } catch (final SQLException ex) { + Bukkit.getLogger().log(Level.SEVERE, "[Updater] Error: ", ex); + return false; + } + config.set("version", "1.31"); + } + if (config.getString("version").compareTo("1.32") < 0) { + getLogger().info("Updating tables to 1.32 ..."); + final Connection conn = logblock.getConnection(); + try { + conn.setAutoCommit(true); + final Statement st = conn.createStatement(); + st.execute("ALTER TABLE `lb-players` ADD COLUMN firstlogin DATETIME NOT NULL AFTER playername"); + st.close(); + conn.close(); + } catch (final SQLException ex) { + Bukkit.getLogger().log(Level.SEVERE, "[Updater] Error: ", ex); + return false; + } + config.set("version", "1.32"); + } + if (config.getString("version").compareTo("1.40") < 0) { + getLogger().info("Updating config to 1.40 ..."); + config.set("clearlog.keepLogDays", null); + config.set("version", "1.40"); + } + if (config.getString("version").compareTo("1.42") < 0) { + getLogger().info("Updating config to 1.42 ..."); + for (final String world : config.getStringList("loggedWorlds")) { + final File file = new File(logblock.getDataFolder(), friendlyWorldname(world) + ".yml"); + final YamlConfiguration wcfg = YamlConfiguration.loadConfiguration(file); + if (wcfg.contains("logBlockCreations")) { + wcfg.set("logging.BLOCKPLACE", wcfg.getBoolean("logBlockCreations")); + } + if (wcfg.contains("logBlockDestroyings")) { + wcfg.set("logging.BLOCKBREAK", wcfg.getBoolean("logBlockDestroyings")); + } + if (wcfg.contains("logSignTexts")) { + wcfg.set("logging.SIGNTEXT", wcfg.getBoolean("logSignTexts")); + } + if (wcfg.contains("logFire")) { + wcfg.set("logging.FIRE", wcfg.getBoolean("logFire")); + } + if (wcfg.contains("logLeavesDecay")) { + wcfg.set("logging.LEAVESDECAY", wcfg.getBoolean("logLeavesDecay")); + } + if (wcfg.contains("logLavaFlow")) { + wcfg.set("logging.LAVAFLOW", wcfg.getBoolean("logLavaFlow")); + } + if (wcfg.contains("logWaterFlow")) { + wcfg.set("logging.WATERFLOW", wcfg.getBoolean("logWaterFlow")); + } + if (wcfg.contains("logChestAccess")) { + wcfg.set("logging.CHESTACCESS", wcfg.getBoolean("logChestAccess")); + } + if (wcfg.contains("logButtonsAndLevers")) { + wcfg.set("logging.SWITCHINTERACT", wcfg.getBoolean("logButtonsAndLevers")); + } + if (wcfg.contains("logKills")) { + wcfg.set("logging.KILL", wcfg.getBoolean("logKills")); + } + if (wcfg.contains("logChat")) { + wcfg.set("logging.CHAT", wcfg.getBoolean("logChat")); + } + if (wcfg.contains("logSnowForm")) { + wcfg.set("logging.SNOWFORM", wcfg.getBoolean("logSnowForm")); + } + if (wcfg.contains("logSnowFade")) { + wcfg.set("logging.SNOWFADE", wcfg.getBoolean("logSnowFade")); + } + if (wcfg.contains("logDoors")) { + wcfg.set("logging.DOORINTERACT", wcfg.getBoolean("logDoors")); + } + if (wcfg.contains("logCakes")) { + wcfg.set("logging.CAKEEAT", wcfg.getBoolean("logCakes")); + } + if (wcfg.contains("logEndermen")) { + wcfg.set("logging.ENDERMEN", wcfg.getBoolean("logEndermen")); + } + if (wcfg.contains("logExplosions")) { + final boolean logExplosions = wcfg.getBoolean("logExplosions"); + wcfg.set("logging.TNTEXPLOSION", logExplosions); + wcfg.set("logging.MISCEXPLOSION", logExplosions); + wcfg.set("logging.CREEPEREXPLOSION", logExplosions); + wcfg.set("logging.GHASTFIREBALLEXPLOSION", logExplosions); + } + wcfg.set("logBlockCreations", null); + wcfg.set("logBlockDestroyings", null); + wcfg.set("logSignTexts", null); + wcfg.set("logExplosions", null); + wcfg.set("logFire", null); + wcfg.set("logLeavesDecay", null); + wcfg.set("logLavaFlow", null); + wcfg.set("logWaterFlow", null); + wcfg.set("logChestAccess", null); + wcfg.set("logButtonsAndLevers", null); + wcfg.set("logKills", null); + wcfg.set("logChat", null); + wcfg.set("logSnowForm", null); + wcfg.set("logSnowFade", null); + wcfg.set("logDoors", null); + wcfg.set("logCakes", null); + wcfg.set("logEndermen", null); + try { + wcfg.save(file); + } catch (final IOException ex) { + Bukkit.getLogger().log(Level.SEVERE, "[Updater] Error: ", ex); + } + } + config.set("clearlog.keepLogDays", null); + config.set("version", "1.42"); + } + if (config.getString("version").compareTo("1.51") < 0) { + getLogger().info("Updating tables to 1.51 ..."); + final Connection conn = logblock.getConnection(); + try { + conn.setAutoCommit(true); + final Statement st = conn.createStatement(); + for (final WorldConfig wcfg : getLoggedWorlds()) { + if (wcfg.isLogging(Logging.KILL)) { + st.execute("ALTER TABLE `" + wcfg.table + "-kills` ADD (x MEDIUMINT NOT NULL DEFAULT 0, y SMALLINT NOT NULL DEFAULT 0, z MEDIUMINT NOT NULL DEFAULT 0)"); + } + } + st.close(); + conn.close(); + } catch (final SQLException ex) { + Bukkit.getLogger().log(Level.SEVERE, "[Updater] Error: ", ex); + return false; + } + config.set("version", "1.51"); + } + if (config.getString("version").compareTo("1.52") < 0) { + getLogger().info("Updating tables to 1.52 ..."); + final Connection conn = logblock.getConnection(); + try { + conn.setAutoCommit(true); + final Statement st = conn.createStatement(); + final ResultSet rs = st.executeQuery("SHOW COLUMNS FROM `lb-players` WHERE field = 'onlinetime'"); + if (rs.next() && rs.getString("Type").equalsIgnoreCase("time")) { + st.execute("ALTER TABLE `lb-players` ADD onlinetime2 INT UNSIGNED NOT NULL"); + st.execute("UPDATE `lb-players` SET onlinetime2 = HOUR(onlinetime) * 3600 + MINUTE(onlinetime) * 60 + SECOND(onlinetime)"); + st.execute("ALTER TABLE `lb-players` DROP onlinetime"); + st.execute("ALTER TABLE `lb-players` CHANGE onlinetime2 onlinetime INT UNSIGNED NOT NULL"); + } else { + getLogger().info("Column lb-players was already modified, skipping it."); + } + st.close(); + conn.close(); + } catch (final SQLException ex) { + Bukkit.getLogger().log(Level.SEVERE, "[Updater] Error: ", ex); + return false; + } + config.set("version", "1.52"); + } + if (config.getString("version").compareTo("1.81") < 0) { + getLogger().info("Updating tables to 1.81 ..."); + final Connection conn = logblock.getConnection(); + try { + conn.setAutoCommit(true); + final Statement st = conn.createStatement(); + for (final WorldConfig wcfg : getLoggedWorlds()) { + if (wcfg.isLogging(Logging.CHESTACCESS)) { + st.execute("ALTER TABLE `" + wcfg.table + "-chest` CHANGE itemdata itemdata SMALLINT NOT NULL"); + getLogger().info("Table " + wcfg.table + "-chest modified"); + } + } + st.close(); + conn.close(); + } catch (final SQLException ex) { + Bukkit.getLogger().log(Level.SEVERE, "[Updater] Error: ", ex); + return false; + } + config.set("version", "1.81"); + } - logblock.saveConfig(); - return true; - } + if (config.getString("version").compareTo("1.90") < 0) { + getLogger().info("Updating tables to 1.9 ..."); + getLogger().info("Importing UUIDs for large databases may take some time"); + final Connection conn = logblock.getConnection(); + try { + conn.setAutoCommit(true); + final Statement st = conn.createStatement(); + st.execute("ALTER TABLE `lb-players` ADD `UUID` VARCHAR(36) NOT NULL"); + } catch (final SQLException ex) { + // Error 1060 is MySQL error "column already exists". We want to continue with import if we get that error + if (ex.getErrorCode() != 1060) { + Bukkit.getLogger().log(Level.SEVERE, "[Updater] Error: ", ex); + return false; + } + } + try { + String unimportedPrefix = "noimport_"; + ResultSet rs; + conn.setAutoCommit(true); + final Statement st = conn.createStatement(); + if (config.getBoolean("logging.logPlayerInfo")) { + // Start by assuming anything with no onlinetime is not a player + st.execute("UPDATE `lb-players` SET UUID = CONCAT ('log_',playername) WHERE onlinetime=0 AND LENGTH(UUID) = 0"); + } else { + // If we can't assume that, we must assume anything we can't look up is not a player + unimportedPrefix = "log_"; + } + // Tell people how many are needing converted + rs = st.executeQuery("SELECT COUNT(playername) FROM `lb-players` WHERE LENGTH(UUID)=0"); + rs.next(); + String total = Integer.toString(rs.getInt(1)); + getLogger().info(total + " players to convert"); + int done = 0; - 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); - createTable(dbm, state, "lb-players", "(playerid INT UNSIGNED NOT NULL AUTO_INCREMENT, UUID varchar(36) NOT NULL, playername varchar(32) NOT NULL, firstlogin DATETIME NOT NULL, lastlogin DATETIME NOT NULL, onlinetime INT UNSIGNED NOT NULL, ip varchar(255) NOT NULL, PRIMARY KEY (playerid), INDEX (UUID), INDEX (playername))"); - // Players table must not be empty or inserts won't work - bug #492 - final ResultSet rs = state.executeQuery("SELECT NULL FROM `lb-players` LIMIT 1;"); - if (!rs.next()) - state.execute("INSERT IGNORE INTO `lb-players` (UUID,playername) VALUES ('log_dummy_record','dummy_record')"); - if (isLogging(Logging.CHAT)) - createTable(dbm, state, "lb-chat", "(id INT UNSIGNED NOT NULL AUTO_INCREMENT, date DATETIME NOT NULL, playerid INT UNSIGNED NOT NULL, message VARCHAR(255) NOT NULL, PRIMARY KEY (id), KEY playerid (playerid), FULLTEXT message (message)) ENGINE=MyISAM DEFAULT CHARSET utf8"); - for (final WorldConfig wcfg : getLoggedWorlds()) { - createTable(dbm, state, wcfg.table, "(id INT UNSIGNED NOT NULL AUTO_INCREMENT, date DATETIME NOT NULL, playerid INT UNSIGNED NOT NULL, replaced TINYINT UNSIGNED NOT NULL, type TINYINT UNSIGNED NOT NULL, data TINYINT UNSIGNED NOT NULL, x MEDIUMINT NOT NULL, y SMALLINT UNSIGNED NOT NULL, z MEDIUMINT NOT NULL, PRIMARY KEY (id), KEY coords (x, z, y), KEY date (date), KEY playerid (playerid))"); - createTable(dbm, state, wcfg.table + "-sign", "(id INT UNSIGNED NOT NULL, signtext VARCHAR(255) NOT NULL, PRIMARY KEY (id)) DEFAULT CHARSET utf8"); - createTable(dbm, state, wcfg.table + "-chest", "(id INT UNSIGNED NOT NULL, itemtype SMALLINT UNSIGNED NOT NULL, itemamount SMALLINT NOT NULL, itemdata SMALLINT NOT NULL, PRIMARY KEY (id))"); - if (wcfg.isLogging(Logging.KILL)) - createTable(dbm, state, wcfg.table + "-kills", "(id INT UNSIGNED NOT NULL AUTO_INCREMENT, date DATETIME NOT NULL, killer INT UNSIGNED, victim INT UNSIGNED NOT NULL, weapon SMALLINT UNSIGNED NOT NULL, x MEDIUMINT NOT NULL, y SMALLINT NOT NULL, z MEDIUMINT NOT NULL, PRIMARY KEY (id))"); - } - state.close(); - conn.close(); - } + conn.setAutoCommit(false); + Map players = new HashMap(); + List names = new ArrayList(UUID_CONVERT_BATCH_SIZE); + Map response; + rs = st.executeQuery("SELECT playerid,playername FROM `lb-players` WHERE LENGTH(UUID)=0 LIMIT " + Integer.toString(UUID_CONVERT_BATCH_SIZE)); + while (rs.next()) { + do { + players.put(rs.getString(2), rs.getInt(1)); + names.add(rs.getString(2)); + } while (rs.next()); + if (names.size() > 0) { + String theUUID; + response = UUIDFetcher.getUUIDs(names); + for (Map.Entry entry : players.entrySet()) { + if (response.get(entry.getKey()) == null) { + theUUID = unimportedPrefix + entry.getKey(); + getLogger().warning(entry.getKey() + " not found - giving UUID of " + theUUID); + } else { + theUUID = response.get(entry.getKey()).toString(); + } + String thePID = entry.getValue().toString(); + st.execute("UPDATE `lb-players` SET UUID = '" + theUUID + "' WHERE playerid = " + thePID); + done++; + } + conn.commit(); + players.clear(); + names.clear(); + getLogger().info("Processed " + Integer.toString(done) + " out of " + total); + rs = st.executeQuery("SELECT playerid,playername FROM `lb-players` WHERE LENGTH(UUID)=0 LIMIT " + Integer.toString(UUID_CONVERT_BATCH_SIZE)); + } + } + st.close(); + conn.close(); - private static void createTable(DatabaseMetaData dbm, Statement state, String table, String query) throws SQLException { - if (!dbm.getTables(null, null, table, null).next()) { - getLogger().log(Level.INFO, "Creating table " + table + "."); - state.execute("CREATE TABLE `" + table + "` " + query); - if (!dbm.getTables(null, null, table, null).next()) - throw new SQLException("Table " + table + " not found and failed to create"); - } - } + } catch (final SQLException ex) { + Bukkit.getLogger().log(Level.SEVERE, "[Updater] Error: ", ex); + return false; + } catch (Exception ex) { + Bukkit.getLogger().log(Level.SEVERE, "[UUID importer]", ex); + return false; + } + config.set("version", "1.90"); + } + // Ensure charset for free-text fields is UTF-8, or UTF8-mb4 if possible + // As this may be an expensive operation and the database default may already be this, check on a table-by-table basis before converting + if (config.getString("version").compareTo("1.92") < 0) { + getLogger().info("Updating tables to 1.92 ..."); + String charset = "utf8"; + if (Config.mb4) { + charset = "utf8mb4"; + } + final Connection conn = logblock.getConnection(); + try { + conn.setAutoCommit(true); + final Statement st = conn.createStatement(); + if (isLogging(Logging.CHAT)) { + final ResultSet rs = st.executeQuery("SHOW FULL COLUMNS FROM `lb-chat` WHERE field = 'message'"); + if (rs.next() && !rs.getString("Collation").substring(0, 4).equalsIgnoreCase(charset)) { + st.execute("ALTER TABLE `lb-chat` CONVERT TO CHARSET " + charset); + getLogger().info("Table lb-chat modified"); + } else { + getLogger().info("Table lb-chat already fine, skipping it"); + } + } + for (final WorldConfig wcfg : getLoggedWorlds()) { + if (wcfg.isLogging(Logging.SIGNTEXT)) { + final ResultSet rs = st.executeQuery("SHOW FULL COLUMNS FROM `" + wcfg.table + "-sign` WHERE field = 'signtext'"); + if (rs.next() && !rs.getString("Collation").substring(0, 4).equalsIgnoreCase(charset)) { + st.execute("ALTER TABLE `" + wcfg.table + "-sign` CONVERT TO CHARSET " + charset); + getLogger().info("Table " + wcfg.table + "-sign modified"); + } else { + getLogger().info("Table " + wcfg.table + "-sign already fine, skipping it"); + } + } + } + st.close(); + conn.close(); + } catch (final SQLException ex) { + Bukkit.getLogger().log(Level.SEVERE, "[Updater] Error: ", ex); + return false; + } + config.set("version", "1.92"); + } + if (config.getString("version").compareTo("1.94") < 0) { + getLogger().info("Updating tables to 1.94 ..."); + final Connection conn = logblock.getConnection(); + try { + conn.setAutoCommit(true); + final Statement st = conn.createStatement(); + // Need to wrap both these next two inside individual try/catch statements in case index does not exist + try { + st.execute("DROP INDEX UUID ON `lb-players`"); + } catch (final SQLException ex) { + if (ex.getErrorCode() != 1091) { + Bukkit.getLogger().log(Level.SEVERE, "[Updater] Error: ", ex); + return false; + } + } + try { + st.execute("DROP INDEX playername ON `lb-players`"); + } catch (final SQLException ex) { + if (ex.getErrorCode() != 1091) { + Bukkit.getLogger().log(Level.SEVERE, "[Updater] Error: ", ex); + return false; + } + } + st.execute("CREATE INDEX UUID ON `lb-players` (UUID);"); + st.execute("CREATE INDEX playername ON `lb-players` (playername);"); + st.close(); + conn.close(); + } catch (final SQLException ex) { + Bukkit.getLogger().log(Level.SEVERE, "[Updater] Error: ", ex); + return false; + } + config.set("version", "1.94"); + } - public static class PlayerCountChecker implements Runnable { + logblock.saveConfig(); + return true; + } - private LogBlock logblock; + 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); + createTable(dbm, state, "lb-players", "(playerid INT UNSIGNED NOT NULL AUTO_INCREMENT, UUID varchar(36) NOT NULL, playername varchar(32) NOT NULL, firstlogin DATETIME NOT NULL, lastlogin DATETIME NOT NULL, onlinetime INT UNSIGNED NOT NULL, ip varchar(255) NOT NULL, PRIMARY KEY (playerid), INDEX (UUID), INDEX (playername))"); + // Players table must not be empty or inserts won't work - bug #492 + final ResultSet rs = state.executeQuery("SELECT NULL FROM `lb-players` LIMIT 1;"); + if (!rs.next()) { + state.execute("INSERT IGNORE INTO `lb-players` (UUID,playername) VALUES ('log_dummy_record','dummy_record')"); + } + if (isLogging(Logging.CHAT)) { + createTable(dbm, state, "lb-chat", "(id INT UNSIGNED NOT NULL AUTO_INCREMENT, date DATETIME NOT NULL, playerid INT UNSIGNED NOT NULL, message VARCHAR(255) NOT NULL, PRIMARY KEY (id), KEY playerid (playerid), FULLTEXT message (message)) ENGINE=MyISAM DEFAULT CHARSET utf8"); + } + for (final WorldConfig wcfg : getLoggedWorlds()) { + createTable(dbm, state, wcfg.table, "(id INT UNSIGNED NOT NULL AUTO_INCREMENT, date DATETIME NOT NULL, playerid INT UNSIGNED NOT NULL, replaced TINYINT UNSIGNED NOT NULL, type TINYINT UNSIGNED NOT NULL, data TINYINT UNSIGNED NOT NULL, x MEDIUMINT NOT NULL, y SMALLINT UNSIGNED NOT NULL, z MEDIUMINT NOT NULL, PRIMARY KEY (id), KEY coords (x, z, y), KEY date (date), KEY playerid (playerid))"); + createTable(dbm, state, wcfg.table + "-sign", "(id INT UNSIGNED NOT NULL, signtext VARCHAR(255) NOT NULL, PRIMARY KEY (id)) DEFAULT CHARSET utf8"); + createTable(dbm, state, wcfg.table + "-chest", "(id INT UNSIGNED NOT NULL, itemtype SMALLINT UNSIGNED NOT NULL, itemamount SMALLINT NOT NULL, itemdata SMALLINT NOT NULL, PRIMARY KEY (id))"); + if (wcfg.isLogging(Logging.KILL)) { + createTable(dbm, state, wcfg.table + "-kills", "(id INT UNSIGNED NOT NULL AUTO_INCREMENT, date DATETIME NOT NULL, killer INT UNSIGNED, victim INT UNSIGNED NOT NULL, weapon SMALLINT UNSIGNED NOT NULL, x MEDIUMINT NOT NULL, y SMALLINT NOT NULL, z MEDIUMINT NOT NULL, PRIMARY KEY (id))"); + } + } + state.close(); + conn.close(); + } - public PlayerCountChecker(LogBlock logblock) { - this.logblock = logblock; - } + private static void createTable(DatabaseMetaData dbm, Statement state, String table, String query) throws SQLException { + if (!dbm.getTables(null, null, table, null).next()) { + getLogger().log(Level.INFO, "Creating table " + table + "."); + state.execute("CREATE TABLE `" + table + "` " + query); + if (!dbm.getTables(null, null, table, null).next()) { + throw new SQLException("Table " + table + " not found and failed to create"); + } + } + } - @Override - public void run() { - final Connection conn = logblock.getConnection(); - try { - conn.setAutoCommit(true); - final Statement st = conn.createStatement(); - ResultSet rs = st.executeQuery("SELECT auto_increment FROM information_schema.columns AS col join information_schema.tables AS tab ON (col.table_schema=tab.table_schema AND col.table_name=tab.table_name) WHERE col.table_name = 'lb-players' AND col.column_name = 'playerid' AND col.data_type = 'smallint' AND col.table_schema = DATABASE() AND auto_increment > 65000;"); - if (rs.next()) { - for (int i = 0; i < 6; i++) { - logblock.getLogger().warning("Your server reached 65000 players. You should soon update your database table schema - see FAQ: https://github.com/LogBlock/LogBlock/wiki/FAQ#logblock-your-server-reached-65000-players-"); - } - } - st.close(); - conn.close(); - } catch (final SQLException ex) { - logblock.getLogger().log(Level.SEVERE, "[Updater] Error: ", ex); - } - } - } + public static class PlayerCountChecker implements Runnable { + + private LogBlock logblock; + + public PlayerCountChecker(LogBlock logblock) { + this.logblock = logblock; + } + + @Override + public void run() { + final Connection conn = logblock.getConnection(); + try { + conn.setAutoCommit(true); + final Statement st = conn.createStatement(); + ResultSet rs = st.executeQuery("SELECT auto_increment FROM information_schema.columns AS col join information_schema.tables AS tab ON (col.table_schema=tab.table_schema AND col.table_name=tab.table_name) WHERE col.table_name = 'lb-players' AND col.column_name = 'playerid' AND col.data_type = 'smallint' AND col.table_schema = DATABASE() AND auto_increment > 65000;"); + if (rs.next()) { + for (int i = 0; i < 6; i++) { + logblock.getLogger().warning("Your server reached 65000 players. You should soon update your database table schema - see FAQ: https://github.com/LogBlock/LogBlock/wiki/FAQ#logblock-your-server-reached-65000-players-"); + } + } + st.close(); + conn.close(); + } catch (final SQLException ex) { + logblock.getLogger().log(Level.SEVERE, "[Updater] Error: ", ex); + } + } + } } diff --git a/src/main/java/de/diddiz/LogBlock/WorldEditor.java b/src/main/java/de/diddiz/LogBlock/WorldEditor.java index fb5553f..1c54adc 100644 --- a/src/main/java/de/diddiz/LogBlock/WorldEditor.java +++ b/src/main/java/de/diddiz/LogBlock/WorldEditor.java @@ -2,6 +2,7 @@ package de.diddiz.LogBlock; import org.bukkit.ChatColor; import org.bukkit.Location; +import org.bukkit.Material; import org.bukkit.World; import org.bukkit.block.Block; import org.bukkit.block.BlockFace; @@ -10,7 +11,6 @@ import org.bukkit.block.Sign; import org.bukkit.command.CommandSender; import org.bukkit.inventory.InventoryHolder; import org.bukkit.inventory.ItemStack; -import org.bukkit.Material; import org.bukkit.material.Bed; import org.bukkit.material.PistonBaseMaterial; import org.bukkit.material.PistonExtensionMaterial; @@ -26,95 +26,93 @@ import java.util.logging.Level; import static de.diddiz.LogBlock.config.Config.dontRollback; import static de.diddiz.LogBlock.config.Config.replaceAnyway; -import static de.diddiz.util.BukkitUtils.equalTypes; -import static de.diddiz.util.BukkitUtils.getContainerBlocks; -import static de.diddiz.util.BukkitUtils.modifyContainer; +import static de.diddiz.util.BukkitUtils.*; import static de.diddiz.util.MaterialName.materialName; import static org.bukkit.Bukkit.getLogger; -public class WorldEditor implements Runnable -{ - private final LogBlock logblock; - private final Queue edits = new LinkedBlockingQueue(); - private final World world; +public class WorldEditor implements Runnable { + private final LogBlock logblock; + private final Queue edits = new LinkedBlockingQueue(); + private final World world; /** * The player responsible for editing the world, used to report progress */ private CommandSender sender; - private int taskID; - private int successes = 0, blacklistCollisions = 0; - private long elapsedTime = 0; - public LookupCacheElement[] errors; + private int taskID; + private int successes = 0, blacklistCollisions = 0; + private long elapsedTime = 0; + public LookupCacheElement[] errors; - public WorldEditor(LogBlock logblock, World world) { - this.logblock = logblock; - this.world = world; - } + public WorldEditor(LogBlock logblock, World world) { + this.logblock = logblock; + this.world = world; + } - public int getSize() { - return edits.size(); - } + public int getSize() { + return edits.size(); + } - public int getSuccesses() { - return successes; - } + public int getSuccesses() { + return successes; + } - public int getErrors() { - return errors.length; - } + public int getErrors() { + return errors.length; + } - public int getBlacklistCollisions() { - return blacklistCollisions; - } + public int getBlacklistCollisions() { + return blacklistCollisions; + } public void setSender(CommandSender sender) { this.sender = sender; } - public void queueEdit(int x, int y, int z, int replaced, int type, byte data, String signtext, short itemType, short itemAmount, short itemData) { - edits.add(new Edit(0, new Location(world, x, y, z), null, replaced, type, data, signtext, new ChestAccess(itemType, itemAmount, itemData))); - } + public void queueEdit(int x, int y, int z, int replaced, int type, byte data, String signtext, short itemType, short itemAmount, short itemData) { + edits.add(new Edit(0, new Location(world, x, y, z), null, replaced, type, data, signtext, new ChestAccess(itemType, itemAmount, itemData))); + } - public long getElapsedTime() { - return elapsedTime; - } + public long getElapsedTime() { + return elapsedTime; + } - synchronized public void start() throws Exception { - final long start = System.currentTimeMillis(); - taskID = logblock.getServer().getScheduler().scheduleSyncRepeatingTask(logblock, this, 0, 1); - if (taskID == -1) - throw new Exception("Failed to schedule task"); - try { - this.wait(); - } catch (final InterruptedException ex) { - throw new Exception("Interrupted"); - } - elapsedTime = System.currentTimeMillis() - start; - } + synchronized public void start() throws Exception { + final long start = System.currentTimeMillis(); + taskID = logblock.getServer().getScheduler().scheduleSyncRepeatingTask(logblock, this, 0, 1); + if (taskID == -1) { + throw new Exception("Failed to schedule task"); + } + try { + this.wait(); + } catch (final InterruptedException ex) { + throw new Exception("Interrupted"); + } + elapsedTime = System.currentTimeMillis() - start; + } - @Override - public synchronized void run() { - final List errorList = new ArrayList(); - int counter = 0; + @Override + public synchronized void run() { + final List errorList = new ArrayList(); + int counter = 0; float size = edits.size(); - while (!edits.isEmpty() && counter < 100) { - try { - switch (edits.poll().perform()) { - case SUCCESS: - successes++; - break; - case BLACKLISTED: - blacklistCollisions++; - break; - } - } catch (final WorldEditorException ex) { - errorList.add(ex); - } catch (final Exception ex) { - getLogger().log(Level.WARNING, "[WorldEditor] Exeption: ", ex); - } - counter++; + while (!edits.isEmpty() && counter < 100) { + try { + switch (edits.poll().perform()) { + case SUCCESS: + successes++; + break; + case BLACKLISTED: + blacklistCollisions++; + break; + } + } catch (final WorldEditorException ex) { + errorList.add(ex); + } catch (final Exception ex) { + getLogger().log(Level.WARNING, "[WorldEditor] Exeption: ", ex); + } + counter++; if (sender != null) { float percentage = ((size - edits.size()) / size) * 100.0F; if (percentage % 20 == 0) { @@ -122,131 +120,150 @@ public class WorldEditor implements Runnable " Blocks edited: " + counter); } } - } - if (edits.isEmpty()) { - logblock.getServer().getScheduler().cancelTask(taskID); - if (errorList.size() > 0) - try { - final File file = new File("plugins/LogBlock/error/WorldEditor-" + new SimpleDateFormat("yy-MM-dd-HH-mm-ss").format(System.currentTimeMillis()) + ".log"); - file.getParentFile().mkdirs(); - final PrintWriter writer = new PrintWriter(file); - for (final LookupCacheElement err : errorList) - writer.println(err.getMessage()); - writer.close(); - } catch (final Exception ex) { - } - errors = errorList.toArray(new WorldEditorException[errorList.size()]); - notify(); - } - } + } + if (edits.isEmpty()) { + logblock.getServer().getScheduler().cancelTask(taskID); + if (errorList.size() > 0) { + try { + final File file = new File("plugins/LogBlock/error/WorldEditor-" + new SimpleDateFormat("yy-MM-dd-HH-mm-ss").format(System.currentTimeMillis()) + ".log"); + file.getParentFile().mkdirs(); + final PrintWriter writer = new PrintWriter(file); + for (final LookupCacheElement err : errorList) { + writer.println(err.getMessage()); + } + writer.close(); + } catch (final Exception ex) { + } + } + errors = errorList.toArray(new WorldEditorException[errorList.size()]); + notify(); + } + } - private static enum PerformResult - { - SUCCESS, BLACKLISTED, NO_ACTION - } + private static enum PerformResult { + SUCCESS, BLACKLISTED, NO_ACTION + } - private class Edit extends BlockChange - { - public Edit(long time, Location loc, Actor actor, int replaced, int type, byte data, String signtext, ChestAccess ca) { - super(time, loc, actor, replaced, type, data, signtext, ca); - } + private class Edit extends BlockChange { + public Edit(long time, Location loc, Actor actor, int replaced, int type, byte data, String signtext, ChestAccess ca) { + super(time, loc, actor, replaced, type, data, signtext, ca); + } - PerformResult perform() throws WorldEditorException { - if (dontRollback.contains(replaced)) - return PerformResult.BLACKLISTED; - final Block block = loc.getBlock(); - if (replaced == 0 && block.getTypeId() == 0) - return PerformResult.NO_ACTION; - final BlockState state = block.getState(); - if (!world.isChunkLoaded(block.getChunk())) - world.loadChunk(block.getChunk()); - if (type == replaced) { - if (type == 0) { - if (!block.setTypeId(0)) - throw new WorldEditorException(block.getTypeId(), 0, block.getLocation()); - } else if (ca != null) { - if (getContainerBlocks().contains(Material.getMaterial(type))) { - int leftover; - try { - leftover = modifyContainer(state, new ItemStack(ca.itemType, -ca.itemAmount, ca.itemData)); - // Special-case blocks which might be double chests - if (leftover > 0 && (type == 54 || type == 146)) - for (final BlockFace face : new BlockFace[]{BlockFace.NORTH, BlockFace.SOUTH, BlockFace.EAST, BlockFace.WEST}) - if (block.getRelative(face).getTypeId() == type) - leftover = modifyContainer(block.getRelative(face).getState(), new ItemStack(ca.itemType, ca.itemAmount < 0 ? leftover : -leftover, ca.itemData)); - } catch (final Exception ex) { - throw new WorldEditorException(ex.getMessage(), block.getLocation()); - } - if (!state.update()) - throw new WorldEditorException("Failed to update inventory of " + materialName(block.getTypeId()), block.getLocation()); - if (leftover > 0 && ca.itemAmount < 0) - throw new WorldEditorException("Not enough space left in " + materialName(block.getTypeId()), block.getLocation()); - } - } else - return PerformResult.NO_ACTION; - return PerformResult.SUCCESS; - } - if (!(equalTypes(block.getTypeId(), type) || replaceAnyway.contains(block.getTypeId()))) - return PerformResult.NO_ACTION; - if (state instanceof InventoryHolder) { - ((InventoryHolder)state).getInventory().clear(); - state.update(); - } - if (block.getTypeId() == replaced) { - if (block.getData() != (type == 0 ? data : (byte)0)) - block.setData(type == 0 ? data : (byte)0, true); - else - return PerformResult.NO_ACTION; - } else if (!block.setTypeIdAndData(replaced, type == 0 ? data : (byte)0, true)) - throw new WorldEditorException(block.getTypeId(), replaced, block.getLocation()); - final int curtype = block.getTypeId(); - if (signtext != null && (curtype == 63 || curtype == 68)) { - final Sign sign = (Sign)block.getState(); - final String[] lines = signtext.split("\0", 4); - if (lines.length < 4) - return PerformResult.NO_ACTION; - for (int i = 0; i < 4; i++) - sign.setLine(i, lines[i]); - if (!sign.update()) - throw new WorldEditorException("Failed to update signtext of " + materialName(block.getTypeId()), block.getLocation()); - } else if (curtype == 26) { - final Bed bed = (Bed)block.getState().getData(); - final Block secBlock = bed.isHeadOfBed() ? block.getRelative(bed.getFacing().getOppositeFace()) : block.getRelative(bed.getFacing()); - if (secBlock.getTypeId() == 0 && !secBlock.setTypeIdAndData(26, (byte)(bed.getData() | 8), true)) - throw new WorldEditorException(secBlock.getTypeId(), 26, secBlock.getLocation()); - } else if ((curtype == 29 || curtype == 33) && (block.getData() & 8) > 0) { - final PistonBaseMaterial piston = (PistonBaseMaterial)block.getState().getData(); - final Block secBlock = block.getRelative(piston.getFacing()); - if (secBlock.getTypeId() == 0 && !secBlock.setTypeIdAndData(34, curtype == 29 ? (byte)(block.getData() | 8) : (byte)(block.getData() & ~8), true)) - throw new WorldEditorException(secBlock.getTypeId(), 34, secBlock.getLocation()); - } else if (curtype == 34) { - final PistonExtensionMaterial piston = (PistonExtensionMaterial)block.getState().getData(); - final Block secBlock = block.getRelative(piston.getFacing().getOppositeFace()); - if (secBlock.getTypeId() == 0 && !secBlock.setTypeIdAndData(piston.isSticky() ? 29 : 33, (byte)(block.getData() | 8), true)) - throw new WorldEditorException(secBlock.getTypeId(), piston.isSticky() ? 29 : 33, secBlock.getLocation()); - } else if (curtype == 18 && (block.getData() & 8) > 0) - block.setData((byte)(block.getData() & 0xF7)); - return PerformResult.SUCCESS; - } - } + PerformResult perform() throws WorldEditorException { + if (dontRollback.contains(replaced)) { + return PerformResult.BLACKLISTED; + } + final Block block = loc.getBlock(); + if (replaced == 0 && block.getTypeId() == 0) { + return PerformResult.NO_ACTION; + } + final BlockState state = block.getState(); + if (!world.isChunkLoaded(block.getChunk())) { + world.loadChunk(block.getChunk()); + } + if (type == replaced) { + if (type == 0) { + if (!block.setTypeId(0)) { + throw new WorldEditorException(block.getTypeId(), 0, block.getLocation()); + } + } else if (ca != null) { + if (getContainerBlocks().contains(Material.getMaterial(type))) { + int leftover; + try { + leftover = modifyContainer(state, new ItemStack(ca.itemType, -ca.itemAmount, ca.itemData)); + // Special-case blocks which might be double chests + if (leftover > 0 && (type == 54 || type == 146)) { + for (final BlockFace face : new BlockFace[]{BlockFace.NORTH, BlockFace.SOUTH, BlockFace.EAST, BlockFace.WEST}) { + if (block.getRelative(face).getTypeId() == type) { + leftover = modifyContainer(block.getRelative(face).getState(), new ItemStack(ca.itemType, ca.itemAmount < 0 ? leftover : -leftover, ca.itemData)); + } + } + } + } catch (final Exception ex) { + throw new WorldEditorException(ex.getMessage(), block.getLocation()); + } + if (!state.update()) { + throw new WorldEditorException("Failed to update inventory of " + materialName(block.getTypeId()), block.getLocation()); + } + if (leftover > 0 && ca.itemAmount < 0) { + throw new WorldEditorException("Not enough space left in " + materialName(block.getTypeId()), block.getLocation()); + } + } + } else { + return PerformResult.NO_ACTION; + } + return PerformResult.SUCCESS; + } + if (!(equalTypes(block.getTypeId(), type) || replaceAnyway.contains(block.getTypeId()))) { + return PerformResult.NO_ACTION; + } + if (state instanceof InventoryHolder) { + ((InventoryHolder) state).getInventory().clear(); + state.update(); + } + if (block.getTypeId() == replaced) { + if (block.getData() != (type == 0 ? data : (byte) 0)) { + block.setData(type == 0 ? data : (byte) 0, true); + } else { + return PerformResult.NO_ACTION; + } + } else if (!block.setTypeIdAndData(replaced, type == 0 ? data : (byte) 0, true)) { + throw new WorldEditorException(block.getTypeId(), replaced, block.getLocation()); + } + final int curtype = block.getTypeId(); + if (signtext != null && (curtype == 63 || curtype == 68)) { + final Sign sign = (Sign) block.getState(); + final String[] lines = signtext.split("\0", 4); + if (lines.length < 4) { + return PerformResult.NO_ACTION; + } + for (int i = 0; i < 4; i++) { + sign.setLine(i, lines[i]); + } + if (!sign.update()) { + throw new WorldEditorException("Failed to update signtext of " + materialName(block.getTypeId()), block.getLocation()); + } + } else if (curtype == 26) { + final Bed bed = (Bed) block.getState().getData(); + final Block secBlock = bed.isHeadOfBed() ? block.getRelative(bed.getFacing().getOppositeFace()) : block.getRelative(bed.getFacing()); + if (secBlock.getTypeId() == 0 && !secBlock.setTypeIdAndData(26, (byte) (bed.getData() | 8), true)) { + throw new WorldEditorException(secBlock.getTypeId(), 26, secBlock.getLocation()); + } + } else if ((curtype == 29 || curtype == 33) && (block.getData() & 8) > 0) { + final PistonBaseMaterial piston = (PistonBaseMaterial) block.getState().getData(); + final Block secBlock = block.getRelative(piston.getFacing()); + if (secBlock.getTypeId() == 0 && !secBlock.setTypeIdAndData(34, curtype == 29 ? (byte) (block.getData() | 8) : (byte) (block.getData() & ~8), true)) { + throw new WorldEditorException(secBlock.getTypeId(), 34, secBlock.getLocation()); + } + } else if (curtype == 34) { + final PistonExtensionMaterial piston = (PistonExtensionMaterial) block.getState().getData(); + final Block secBlock = block.getRelative(piston.getFacing().getOppositeFace()); + if (secBlock.getTypeId() == 0 && !secBlock.setTypeIdAndData(piston.isSticky() ? 29 : 33, (byte) (block.getData() | 8), true)) { + throw new WorldEditorException(secBlock.getTypeId(), piston.isSticky() ? 29 : 33, secBlock.getLocation()); + } + } else if (curtype == 18 && (block.getData() & 8) > 0) { + block.setData((byte) (block.getData() & 0xF7)); + } + return PerformResult.SUCCESS; + } + } - @SuppressWarnings("serial") - public static class WorldEditorException extends Exception implements LookupCacheElement - { - private final Location loc; + @SuppressWarnings("serial") + public static class WorldEditorException extends Exception implements LookupCacheElement { + private final Location loc; - public WorldEditorException(int typeBefore, int typeAfter, Location loc) { - this("Failed to replace " + materialName(typeBefore) + " with " + materialName(typeAfter), loc); - } + public WorldEditorException(int typeBefore, int typeAfter, Location loc) { + this("Failed to replace " + materialName(typeBefore) + " with " + materialName(typeAfter), loc); + } - public WorldEditorException(String msg, Location loc) { - super(msg + " at " + loc.getWorld().getName() + ":" + loc.getBlockX() + ":" + loc.getBlockY() + ":" + loc.getBlockZ()); - this.loc = loc; - } + public WorldEditorException(String msg, Location loc) { + super(msg + " at " + loc.getWorld().getName() + ":" + loc.getBlockX() + ":" + loc.getBlockY() + ":" + loc.getBlockZ()); + this.loc = loc; + } - @Override - public Location getLocation() { - return loc; - } - } + @Override + public Location getLocation() { + return loc; + } + } } diff --git a/src/main/java/de/diddiz/LogBlock/config/Config.java b/src/main/java/de/diddiz/LogBlock/config/Config.java index e02217f..ed6cbae 100644 --- a/src/main/java/de/diddiz/LogBlock/config/Config.java +++ b/src/main/java/de/diddiz/LogBlock/config/Config.java @@ -18,265 +18,276 @@ import static de.diddiz.util.BukkitUtils.friendlyWorldname; import static de.diddiz.util.Utils.parseTimeSpec; import static org.bukkit.Bukkit.*; -public class Config -{ - private static LoggingEnabledMapping superWorldConfig; - 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 int queueWarningSize; - public static boolean enableAutoClearLog; - public static List autoClearLog; - public static int autoClearLogDelay; - public static boolean dumpDeletedLog; - public static boolean logCreeperExplosionsAsPlayerWhoTriggeredThese, logPlayerInfo; - public static LogKillsLevel logKillsLevel; - public static Set dontRollback, replaceAnyway; - public static int rollbackMaxTime, rollbackMaxArea; - public static Map toolsByName; - public static Map toolsByType; - public static int defaultDist, defaultTime; - public static int linesPerPage, linesLimit; - public static boolean askRollbacks, askRedos, askClearLogs, askClearLogAfterRollback, askRollbackAfterBan; - public static String banPermission; - public static Set hiddenBlocks; - public static Set hiddenPlayers; - public static Set ignoredChat; - public static SimpleDateFormat formatter; - public static boolean safetyIdCheck; - public static boolean debug; - public static boolean logEnvironmentalKills; - // Not loaded from config - checked at runtime - public static boolean mb4 = false; +public class Config { + private static LoggingEnabledMapping superWorldConfig; + 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 int queueWarningSize; + public static boolean enableAutoClearLog; + public static List autoClearLog; + public static int autoClearLogDelay; + public static boolean dumpDeletedLog; + public static boolean logCreeperExplosionsAsPlayerWhoTriggeredThese, logPlayerInfo; + public static LogKillsLevel logKillsLevel; + public static Set dontRollback, replaceAnyway; + public static int rollbackMaxTime, rollbackMaxArea; + public static Map toolsByName; + public static Map toolsByType; + public static int defaultDist, defaultTime; + public static int linesPerPage, linesLimit; + public static boolean askRollbacks, askRedos, askClearLogs, askClearLogAfterRollback, askRollbackAfterBan; + public static String banPermission; + public static Set hiddenBlocks; + public static Set hiddenPlayers; + public static Set ignoredChat; + public static SimpleDateFormat formatter; + public static boolean safetyIdCheck; + public static boolean debug; + public static boolean logEnvironmentalKills; + // Not loaded from config - checked at runtime + public static boolean mb4 = false; - public static enum LogKillsLevel - { - PLAYERS, MONSTERS, ANIMALS; - } + public static enum LogKillsLevel { + PLAYERS, MONSTERS, ANIMALS; + } - public static void load(LogBlock logblock) throws DataFormatException, IOException { - final ConfigurationSection config = logblock.getConfig(); - final Map def = new HashMap(); - def.put("version", logblock.getDescription().getVersion()); - final List worldNames = new ArrayList(); - for (final World world : getWorlds()) - worldNames.add(world.getName()); - if (worldNames.isEmpty()) { - worldNames.add("world"); - worldNames.add("world_nether"); - worldNames.add("world_the_end"); - } - def.put("loggedWorlds", worldNames); - def.put("mysql.host", "localhost"); - def.put("mysql.port", 3306); - def.put("mysql.database", "minecraft"); - def.put("mysql.user", "username"); - def.put("mysql.password", "pass"); - def.put("consumer.delayBetweenRuns", 2); - def.put("consumer.forceToProcessAtLeast", 200); - def.put("consumer.timePerRun", 1000); - def.put("consumer.fireCustomEvents", false); - def.put("consumer.useBukkitScheduler", true); - def.put("consumer.queueWarningSize", 1000); - def.put("clearlog.dumpDeletedLog", false); - def.put("clearlog.enableAutoClearLog", false); - def.put("clearlog.auto", Arrays.asList("world \"world\" before 365 days all", "world \"world\" player lavaflow waterflow leavesdecay before 7 days all", "world world_nether before 365 days all", "world world_nether player lavaflow before 7 days all")); - def.put("clearlog.autoClearLogDelay", "6h"); - def.put("logging.logCreeperExplosionsAsPlayerWhoTriggeredThese", false); - def.put("logging.logKillsLevel", "PLAYERS"); - def.put("logging.logEnvironmentalKills", false); - def.put("logging.logPlayerInfo", false); - def.put("logging.hiddenPlayers", new ArrayList()); - def.put("logging.hiddenBlocks", Arrays.asList(0)); - def.put("logging.ignoredChat", Arrays.asList("/register", "/login")); - def.put("rollback.dontRollback", Arrays.asList(10, 11, 46, 51)); - def.put("rollback.replaceAnyway", Arrays.asList(8, 9, 10, 11, 51)); - def.put("rollback.maxTime", "2 days"); - def.put("rollback.maxArea", 50); - def.put("lookup.defaultDist", 20); - def.put("lookup.defaultTime", "30 minutes"); - def.put("lookup.linesPerPage", 15); - def.put("lookup.linesLimit", 1500); - try { - formatter = new SimpleDateFormat(config.getString("lookup.dateFormat", "MM-dd HH:mm:ss")); - } catch (IllegalArgumentException e) { - throw new DataFormatException("Invalid specification for date format, please see http://docs.oracle.com/javase/1.4.2/docs/api/java/text/SimpleDateFormat.html : " + e.getMessage()); - } - def.put("lookup.dateFormat", "MM-dd HH:mm:ss"); - def.put("questioner.askRollbacks", true); - def.put("questioner.askRedos", true); - def.put("questioner.askClearLogs", true); - def.put("questioner.askClearLogAfterRollback", true); - def.put("questioner.askRollbackAfterBan", false); - def.put("questioner.banPermission", "mcbans.ban.local"); - def.put("tools.tool.aliases", Arrays.asList("t")); - def.put("tools.tool.leftClickBehavior", "NONE"); - def.put("tools.tool.rightClickBehavior", "TOOL"); - def.put("tools.tool.defaultEnabled", true); - def.put("tools.tool.item", 270); - def.put("tools.tool.canDrop", true); - def.put("tools.tool.params", "area 0 all sum none limit 15 desc silent"); - def.put("tools.tool.mode", "LOOKUP"); - def.put("tools.tool.permissionDefault", "OP"); - def.put("tools.toolblock.aliases", Arrays.asList("tb")); - def.put("tools.toolblock.leftClickBehavior", "TOOL"); - def.put("tools.toolblock.rightClickBehavior", "BLOCK"); - def.put("tools.toolblock.defaultEnabled", true); - def.put("tools.toolblock.item", 7); - def.put("tools.toolblock.canDrop", false); - def.put("tools.toolblock.params", "area 0 all sum none limit 15 desc silent"); - def.put("tools.toolblock.mode", "LOOKUP"); - def.put("tools.toolblock.permissionDefault", "OP"); - def.put("safety.id.check", true); - def.put("debug", false); - for (final Entry e : def.entrySet()) - if (!config.contains(e.getKey())) - config.set(e.getKey(), e.getValue()); - logblock.saveConfig(); - url = "jdbc:mysql://" + config.getString("mysql.host") + ":" + config.getInt("mysql.port") + "/" + getStringIncludingInts(config, "mysql.database"); - user = getStringIncludingInts(config, "mysql.user"); - password = getStringIncludingInts(config, "mysql.password"); - delayBetweenRuns = config.getInt("consumer.delayBetweenRuns", 2); - forceToProcessAtLeast = config.getInt("consumer.forceToProcessAtLeast", 0); - timePerRun = config.getInt("consumer.timePerRun", 1000); - fireCustomEvents = config.getBoolean("consumer.fireCustomEvents", false); - useBukkitScheduler = config.getBoolean("consumer.useBukkitScheduler", true); - queueWarningSize = config.getInt("consumer.queueWarningSize", 1000); - enableAutoClearLog = config.getBoolean("clearlog.enableAutoClearLog"); - autoClearLog = config.getStringList("clearlog.auto"); - dumpDeletedLog = config.getBoolean("clearlog.dumpDeletedLog", false); - autoClearLogDelay = parseTimeSpec(config.getString("clearlog.autoClearLogDelay").split(" ")); - logCreeperExplosionsAsPlayerWhoTriggeredThese = config.getBoolean("logging.logCreeperExplosionsAsPlayerWhoTriggeredThese", false); - logPlayerInfo = config.getBoolean("logging.logPlayerInfo", true); - try { - logKillsLevel = LogKillsLevel.valueOf(config.getString("logging.logKillsLevel").toUpperCase()); - } catch (final IllegalArgumentException ex) { - throw new DataFormatException("logging.logKillsLevel doesn't appear to be a valid log level. Allowed are 'PLAYERS', 'MONSTERS' and 'ANIMALS'"); - } - logEnvironmentalKills = config.getBoolean("logging.logEnvironmentalKills", false); - hiddenPlayers = new HashSet(); - for (final String playerName : config.getStringList("logging.hiddenPlayers")) - hiddenPlayers.add(playerName.toLowerCase().trim()); - hiddenBlocks = new HashSet(); - for (final Object blocktype : config.getList("logging.hiddenBlocks")) { - final Material mat = Material.matchMaterial(String.valueOf(blocktype)); - if (mat != null) - hiddenBlocks.add(mat.getId()); - else - throw new DataFormatException("Not a valid material: '" + blocktype + "'"); - } - ignoredChat = new HashSet(); - for (String chatCommand : config.getStringList("logging.ignoredChat")) { - ignoredChat.add(chatCommand); - } - dontRollback = new HashSet(config.getIntegerList("rollback.dontRollback")); - replaceAnyway = new HashSet(config.getIntegerList("rollback.replaceAnyway")); - rollbackMaxTime = parseTimeSpec(config.getString("rollback.maxTime").split(" ")); - rollbackMaxArea = config.getInt("rollback.maxArea", 50); - defaultDist = config.getInt("lookup.defaultDist", 20); - defaultTime = parseTimeSpec(config.getString("lookup.defaultTime").split(" ")); - linesPerPage = config.getInt("lookup.linesPerPage", 15); - linesLimit = config.getInt("lookup.linesLimit", 1500); - askRollbacks = config.getBoolean("questioner.askRollbacks", true); - askRedos = config.getBoolean("questioner.askRedos", true); - askClearLogs = config.getBoolean("questioner.askClearLogs", true); - askClearLogAfterRollback = config.getBoolean("questioner.askClearLogAfterRollback", true); - askRollbackAfterBan = config.getBoolean("questioner.askRollbackAfterBan", false); - safetyIdCheck = config.getBoolean("safety.id.check", true); - debug = config.getBoolean("debug", false); - banPermission = config.getString("questioner.banPermission"); - final List tools = new ArrayList(); - final ConfigurationSection toolsSec = config.getConfigurationSection("tools"); - for (final String toolName : toolsSec.getKeys(false)) - try { - final ConfigurationSection tSec = toolsSec.getConfigurationSection(toolName); - final List aliases = tSec.getStringList("aliases"); - final ToolBehavior leftClickBehavior = ToolBehavior.valueOf(tSec.getString("leftClickBehavior").toUpperCase()); - final ToolBehavior rightClickBehavior = ToolBehavior.valueOf(tSec.getString("rightClickBehavior").toUpperCase()); - final boolean defaultEnabled = tSec.getBoolean("defaultEnabled", false); - final int item = tSec.getInt("item", 0); - final boolean canDrop = tSec.getBoolean("canDrop", false); - final QueryParams params = new QueryParams(logblock); - params.prepareToolQuery = true; - params.parseArgs(getConsoleSender(), Arrays.asList(tSec.getString("params").split(" "))); - final ToolMode mode = ToolMode.valueOf(tSec.getString("mode").toUpperCase()); - final PermissionDefault pdef = PermissionDefault.valueOf(tSec.getString("permissionDefault").toUpperCase()); - tools.add(new Tool(toolName, aliases, leftClickBehavior, rightClickBehavior, defaultEnabled, item, canDrop, params, mode, pdef)); - } catch (final Exception ex) { - getLogger().log(Level.WARNING, "Error at parsing tool '" + toolName + "': ", ex); - } - toolsByName = new HashMap(); - toolsByType = new HashMap(); - for (final Tool tool : tools) { - toolsByType.put(tool.item, tool); - toolsByName.put(tool.name.toLowerCase(), tool); - for (final String alias : tool.aliases) - toolsByName.put(alias, tool); - } - final List loggedWorlds = config.getStringList("loggedWorlds"); - worldConfigs = new HashMap(); - if (loggedWorlds.isEmpty()) - throw new DataFormatException("No worlds configured"); - for (final String world : loggedWorlds) - worldConfigs.put(world, new WorldConfig(new File(logblock.getDataFolder(), friendlyWorldname(world) + ".yml"))); - superWorldConfig = new LoggingEnabledMapping(); - for (final WorldConfig wcfg : worldConfigs.values()) - for (final Logging l : Logging.values()) - if (wcfg.isLogging(l)) - superWorldConfig.setLogging(l, true); - } + public static void load(LogBlock logblock) throws DataFormatException, IOException { + final ConfigurationSection config = logblock.getConfig(); + final Map def = new HashMap(); + def.put("version", logblock.getDescription().getVersion()); + final List worldNames = new ArrayList(); + for (final World world : getWorlds()) { + worldNames.add(world.getName()); + } + if (worldNames.isEmpty()) { + worldNames.add("world"); + worldNames.add("world_nether"); + worldNames.add("world_the_end"); + } + def.put("loggedWorlds", worldNames); + def.put("mysql.host", "localhost"); + def.put("mysql.port", 3306); + def.put("mysql.database", "minecraft"); + def.put("mysql.user", "username"); + def.put("mysql.password", "pass"); + def.put("consumer.delayBetweenRuns", 2); + def.put("consumer.forceToProcessAtLeast", 200); + def.put("consumer.timePerRun", 1000); + def.put("consumer.fireCustomEvents", false); + def.put("consumer.useBukkitScheduler", true); + def.put("consumer.queueWarningSize", 1000); + def.put("clearlog.dumpDeletedLog", false); + def.put("clearlog.enableAutoClearLog", false); + def.put("clearlog.auto", Arrays.asList("world \"world\" before 365 days all", "world \"world\" player lavaflow waterflow leavesdecay before 7 days all", "world world_nether before 365 days all", "world world_nether player lavaflow before 7 days all")); + def.put("clearlog.autoClearLogDelay", "6h"); + def.put("logging.logCreeperExplosionsAsPlayerWhoTriggeredThese", false); + def.put("logging.logKillsLevel", "PLAYERS"); + def.put("logging.logEnvironmentalKills", false); + def.put("logging.logPlayerInfo", false); + def.put("logging.hiddenPlayers", new ArrayList()); + def.put("logging.hiddenBlocks", Arrays.asList(0)); + def.put("logging.ignoredChat", Arrays.asList("/register", "/login")); + def.put("rollback.dontRollback", Arrays.asList(10, 11, 46, 51)); + def.put("rollback.replaceAnyway", Arrays.asList(8, 9, 10, 11, 51)); + def.put("rollback.maxTime", "2 days"); + def.put("rollback.maxArea", 50); + def.put("lookup.defaultDist", 20); + def.put("lookup.defaultTime", "30 minutes"); + def.put("lookup.linesPerPage", 15); + def.put("lookup.linesLimit", 1500); + try { + formatter = new SimpleDateFormat(config.getString("lookup.dateFormat", "MM-dd HH:mm:ss")); + } catch (IllegalArgumentException e) { + throw new DataFormatException("Invalid specification for date format, please see http://docs.oracle.com/javase/1.4.2/docs/api/java/text/SimpleDateFormat.html : " + e.getMessage()); + } + def.put("lookup.dateFormat", "MM-dd HH:mm:ss"); + def.put("questioner.askRollbacks", true); + def.put("questioner.askRedos", true); + def.put("questioner.askClearLogs", true); + def.put("questioner.askClearLogAfterRollback", true); + def.put("questioner.askRollbackAfterBan", false); + def.put("questioner.banPermission", "mcbans.ban.local"); + def.put("tools.tool.aliases", Arrays.asList("t")); + def.put("tools.tool.leftClickBehavior", "NONE"); + def.put("tools.tool.rightClickBehavior", "TOOL"); + def.put("tools.tool.defaultEnabled", true); + def.put("tools.tool.item", 270); + def.put("tools.tool.canDrop", true); + def.put("tools.tool.params", "area 0 all sum none limit 15 desc silent"); + def.put("tools.tool.mode", "LOOKUP"); + def.put("tools.tool.permissionDefault", "OP"); + def.put("tools.toolblock.aliases", Arrays.asList("tb")); + def.put("tools.toolblock.leftClickBehavior", "TOOL"); + def.put("tools.toolblock.rightClickBehavior", "BLOCK"); + def.put("tools.toolblock.defaultEnabled", true); + def.put("tools.toolblock.item", 7); + def.put("tools.toolblock.canDrop", false); + def.put("tools.toolblock.params", "area 0 all sum none limit 15 desc silent"); + def.put("tools.toolblock.mode", "LOOKUP"); + def.put("tools.toolblock.permissionDefault", "OP"); + def.put("safety.id.check", true); + def.put("debug", false); + for (final Entry e : def.entrySet()) { + if (!config.contains(e.getKey())) { + config.set(e.getKey(), e.getValue()); + } + } + logblock.saveConfig(); + url = "jdbc:mysql://" + config.getString("mysql.host") + ":" + config.getInt("mysql.port") + "/" + getStringIncludingInts(config, "mysql.database"); + user = getStringIncludingInts(config, "mysql.user"); + password = getStringIncludingInts(config, "mysql.password"); + delayBetweenRuns = config.getInt("consumer.delayBetweenRuns", 2); + forceToProcessAtLeast = config.getInt("consumer.forceToProcessAtLeast", 0); + timePerRun = config.getInt("consumer.timePerRun", 1000); + fireCustomEvents = config.getBoolean("consumer.fireCustomEvents", false); + useBukkitScheduler = config.getBoolean("consumer.useBukkitScheduler", true); + queueWarningSize = config.getInt("consumer.queueWarningSize", 1000); + enableAutoClearLog = config.getBoolean("clearlog.enableAutoClearLog"); + autoClearLog = config.getStringList("clearlog.auto"); + dumpDeletedLog = config.getBoolean("clearlog.dumpDeletedLog", false); + autoClearLogDelay = parseTimeSpec(config.getString("clearlog.autoClearLogDelay").split(" ")); + logCreeperExplosionsAsPlayerWhoTriggeredThese = config.getBoolean("logging.logCreeperExplosionsAsPlayerWhoTriggeredThese", false); + logPlayerInfo = config.getBoolean("logging.logPlayerInfo", true); + try { + logKillsLevel = LogKillsLevel.valueOf(config.getString("logging.logKillsLevel").toUpperCase()); + } catch (final IllegalArgumentException ex) { + throw new DataFormatException("logging.logKillsLevel doesn't appear to be a valid log level. Allowed are 'PLAYERS', 'MONSTERS' and 'ANIMALS'"); + } + logEnvironmentalKills = config.getBoolean("logging.logEnvironmentalKills", false); + hiddenPlayers = new HashSet(); + for (final String playerName : config.getStringList("logging.hiddenPlayers")) { + hiddenPlayers.add(playerName.toLowerCase().trim()); + } + hiddenBlocks = new HashSet(); + for (final Object blocktype : config.getList("logging.hiddenBlocks")) { + final Material mat = Material.matchMaterial(String.valueOf(blocktype)); + if (mat != null) { + hiddenBlocks.add(mat.getId()); + } else { + throw new DataFormatException("Not a valid material: '" + blocktype + "'"); + } + } + ignoredChat = new HashSet(); + for (String chatCommand : config.getStringList("logging.ignoredChat")) { + ignoredChat.add(chatCommand); + } + dontRollback = new HashSet(config.getIntegerList("rollback.dontRollback")); + replaceAnyway = new HashSet(config.getIntegerList("rollback.replaceAnyway")); + rollbackMaxTime = parseTimeSpec(config.getString("rollback.maxTime").split(" ")); + rollbackMaxArea = config.getInt("rollback.maxArea", 50); + defaultDist = config.getInt("lookup.defaultDist", 20); + defaultTime = parseTimeSpec(config.getString("lookup.defaultTime").split(" ")); + linesPerPage = config.getInt("lookup.linesPerPage", 15); + linesLimit = config.getInt("lookup.linesLimit", 1500); + askRollbacks = config.getBoolean("questioner.askRollbacks", true); + askRedos = config.getBoolean("questioner.askRedos", true); + askClearLogs = config.getBoolean("questioner.askClearLogs", true); + askClearLogAfterRollback = config.getBoolean("questioner.askClearLogAfterRollback", true); + askRollbackAfterBan = config.getBoolean("questioner.askRollbackAfterBan", false); + safetyIdCheck = config.getBoolean("safety.id.check", true); + debug = config.getBoolean("debug", false); + banPermission = config.getString("questioner.banPermission"); + final List tools = new ArrayList(); + final ConfigurationSection toolsSec = config.getConfigurationSection("tools"); + for (final String toolName : toolsSec.getKeys(false)) { + try { + final ConfigurationSection tSec = toolsSec.getConfigurationSection(toolName); + final List aliases = tSec.getStringList("aliases"); + final ToolBehavior leftClickBehavior = ToolBehavior.valueOf(tSec.getString("leftClickBehavior").toUpperCase()); + final ToolBehavior rightClickBehavior = ToolBehavior.valueOf(tSec.getString("rightClickBehavior").toUpperCase()); + final boolean defaultEnabled = tSec.getBoolean("defaultEnabled", false); + final int item = tSec.getInt("item", 0); + final boolean canDrop = tSec.getBoolean("canDrop", false); + final QueryParams params = new QueryParams(logblock); + params.prepareToolQuery = true; + params.parseArgs(getConsoleSender(), Arrays.asList(tSec.getString("params").split(" "))); + final ToolMode mode = ToolMode.valueOf(tSec.getString("mode").toUpperCase()); + final PermissionDefault pdef = PermissionDefault.valueOf(tSec.getString("permissionDefault").toUpperCase()); + tools.add(new Tool(toolName, aliases, leftClickBehavior, rightClickBehavior, defaultEnabled, item, canDrop, params, mode, pdef)); + } catch (final Exception ex) { + getLogger().log(Level.WARNING, "Error at parsing tool '" + toolName + "': ", ex); + } + } + toolsByName = new HashMap(); + toolsByType = new HashMap(); + for (final Tool tool : tools) { + toolsByType.put(tool.item, tool); + toolsByName.put(tool.name.toLowerCase(), tool); + for (final String alias : tool.aliases) { + toolsByName.put(alias, tool); + } + } + final List loggedWorlds = config.getStringList("loggedWorlds"); + worldConfigs = new HashMap(); + if (loggedWorlds.isEmpty()) { + throw new DataFormatException("No worlds configured"); + } + for (final String world : loggedWorlds) { + worldConfigs.put(world, new WorldConfig(new File(logblock.getDataFolder(), friendlyWorldname(world) + ".yml"))); + } + superWorldConfig = new LoggingEnabledMapping(); + for (final WorldConfig wcfg : worldConfigs.values()) { + for (final Logging l : Logging.values()) { + if (wcfg.isLogging(l)) { + superWorldConfig.setLogging(l, true); + } + } + } + } - private static String getStringIncludingInts(ConfigurationSection cfg, String key) { - String str = cfg.getString(key); - if (str == null) - str = String.valueOf(cfg.getInt(key)); - if (str == null) - str = "No value set for '" + key + "'"; - return str; - } + private static String getStringIncludingInts(ConfigurationSection cfg, String key) { + String str = cfg.getString(key); + if (str == null) { + str = String.valueOf(cfg.getInt(key)); + } + if (str == null) { + str = "No value set for '" + key + "'"; + } + return str; + } - public static boolean isLogging(World world, Logging l) { - final WorldConfig wcfg = worldConfigs.get(world.getName()); - return wcfg != null && wcfg.isLogging(l); - } + public static boolean isLogging(World world, Logging l) { + final WorldConfig wcfg = worldConfigs.get(world.getName()); + return wcfg != null && wcfg.isLogging(l); + } - public static boolean isLogging(String worldName, Logging l) { - final WorldConfig wcfg = worldConfigs.get(worldName); - return wcfg != null && wcfg.isLogging(l); - } + public static boolean isLogging(String worldName, Logging l) { + final WorldConfig wcfg = worldConfigs.get(worldName); + return wcfg != null && wcfg.isLogging(l); + } - public static boolean isLogged(World world) { - return worldConfigs.containsKey(world.getName()); - } + public static boolean isLogged(World world) { + return worldConfigs.containsKey(world.getName()); + } - public static WorldConfig getWorldConfig(World world) { - return worldConfigs.get(world.getName()); - } + public static WorldConfig getWorldConfig(World world) { + return worldConfigs.get(world.getName()); + } - public static WorldConfig getWorldConfig(String world) { - return worldConfigs.get(world); - } + public static WorldConfig getWorldConfig(String world) { + return worldConfigs.get(world); + } - public static boolean isLogging(Logging l) { - return superWorldConfig.isLogging(l); - } + public static boolean isLogging(Logging l) { + return superWorldConfig.isLogging(l); + } - public static Collection getLoggedWorlds() { - return worldConfigs.values(); - } + public static Collection getLoggedWorlds() { + return worldConfigs.values(); + } } -class LoggingEnabledMapping -{ - private final boolean[] logging = new boolean[Logging.length]; +class LoggingEnabledMapping { + private final boolean[] logging = new boolean[Logging.length]; - public void setLogging(Logging l, boolean enabled) { - logging[l.ordinal()] = enabled; - } + public void setLogging(Logging l, boolean enabled) { + logging[l.ordinal()] = enabled; + } - public boolean isLogging(Logging l) { - return logging[l.ordinal()]; - } + public boolean isLogging(Logging l) { + return logging[l.ordinal()]; + } } diff --git a/src/main/java/de/diddiz/LogBlock/config/WorldConfig.java b/src/main/java/de/diddiz/LogBlock/config/WorldConfig.java index 1fef2d0..4a1878b 100644 --- a/src/main/java/de/diddiz/LogBlock/config/WorldConfig.java +++ b/src/main/java/de/diddiz/LogBlock/config/WorldConfig.java @@ -1,31 +1,35 @@ package de.diddiz.LogBlock.config; +import de.diddiz.LogBlock.Logging; +import org.bukkit.configuration.file.YamlConfiguration; + import java.io.File; import java.io.IOException; import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; -import org.bukkit.configuration.file.YamlConfiguration; -import de.diddiz.LogBlock.Logging; -public class WorldConfig extends LoggingEnabledMapping -{ - public final String table; +public class WorldConfig extends LoggingEnabledMapping { + public final String table; - public WorldConfig(File file) throws IOException { - final Map def = new HashMap(); - // "Before MySQL 5.1.6, database and table names cannot contain "/", "\", ".", or characters that are not permitted in file names" - MySQL manual - // They _can_ contain spaces, but replace them as well - def.put("table", "lb-" + file.getName().substring(0, file.getName().length() - 4).replaceAll("[ ./\\\\]", "_")); - for (final Logging l : Logging.values()) - def.put("logging." + l.toString(), l.isDefaultEnabled()); - final YamlConfiguration config = YamlConfiguration.loadConfiguration(file); - for (final Entry e : def.entrySet()) - if (config.get(e.getKey()) == null) - config.set(e.getKey(), e.getValue()); - config.save(file); - table = config.getString("table"); - for (final Logging l : Logging.values()) - setLogging(l, config.getBoolean("logging." + l.toString())); - } + public WorldConfig(File file) throws IOException { + final Map def = new HashMap(); + // "Before MySQL 5.1.6, database and table names cannot contain "/", "\", ".", or characters that are not permitted in file names" - MySQL manual + // They _can_ contain spaces, but replace them as well + def.put("table", "lb-" + file.getName().substring(0, file.getName().length() - 4).replaceAll("[ ./\\\\]", "_")); + for (final Logging l : Logging.values()) { + def.put("logging." + l.toString(), l.isDefaultEnabled()); + } + final YamlConfiguration config = YamlConfiguration.loadConfiguration(file); + for (final Entry e : def.entrySet()) { + if (config.get(e.getKey()) == null) { + config.set(e.getKey(), e.getValue()); + } + } + config.save(file); + table = config.getString("table"); + for (final Logging l : Logging.values()) { + setLogging(l, config.getBoolean("logging." + l.toString())); + } + } } diff --git a/src/main/java/de/diddiz/LogBlock/events/BlockChangePreLogEvent.java b/src/main/java/de/diddiz/LogBlock/events/BlockChangePreLogEvent.java index e2b8f6c..5decd89 100644 --- a/src/main/java/de/diddiz/LogBlock/events/BlockChangePreLogEvent.java +++ b/src/main/java/de/diddiz/LogBlock/events/BlockChangePreLogEvent.java @@ -1,4 +1,5 @@ package de.diddiz.LogBlock.events; + import de.diddiz.LogBlock.Actor; import de.diddiz.LogBlock.ChestAccess; import org.apache.commons.lang.Validate; @@ -7,111 +8,117 @@ 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; + 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(Actor owner, Location location, int typeBefore, int typeAfter, byte data, - String signText, ChestAccess chestAccess) { + public BlockChangePreLogEvent(Actor 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; - } + super(owner); + this.location = location; + this.typeBefore = typeBefore; + this.typeAfter = typeAfter; + this.data = data; + this.signText = signText; + this.chestAccess = chestAccess; + } - public Location getLocation() { + public Location getLocation() { - return location; - } + return location; + } - public void setLocation(Location location) { + public void setLocation(Location location) { - this.location = location; - } + this.location = location; + } - public int getTypeBefore() { + public int getTypeBefore() { - return typeBefore; - } + return typeBefore; + } - public void setTypeBefore(int typeBefore) { + public void setTypeBefore(int typeBefore) { - this.typeBefore = typeBefore; - } + this.typeBefore = typeBefore; + } - public int getTypeAfter() { + public int getTypeAfter() { - return typeAfter; - } + return typeAfter; + } - public void setTypeAfter(int typeAfter) { + public void setTypeAfter(int typeAfter) { - this.typeAfter = typeAfter; - } + this.typeAfter = typeAfter; + } - public byte getData() { + public byte getData() { - return data; - } + return data; + } - public void setData(byte data) { + public void setData(byte data) { - this.data = data; - } + this.data = data; + } - public String getSignText() { + public String getSignText() { - return signText; - } + return signText; + } - public void setSignText(String[] signText) { + public void setSignText(String[] signText) { - if (signText != null) { - // Check for block - Validate.isTrue(isValidSign(), "Must be valid sign block"); + 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"); + // 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; - } - } + this.signText = signText[0] + "\0" + signText[1] + "\0" + signText[2] + "\0" + signText[3]; + } else { + this.signText = null; + } + } - private boolean isValidSign() { + 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; - } + 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() { + public ChestAccess getChestAccess() { - return chestAccess; - } + return chestAccess; + } - public void setChestAccess(ChestAccess chestAccess) { + public void setChestAccess(ChestAccess chestAccess) { - this.chestAccess = chestAccess; - } + this.chestAccess = chestAccess; + } - public HandlerList getHandlers() { + public HandlerList getHandlers() { - return handlers; - } + return handlers; + } - public static HandlerList getHandlerList() { + public static HandlerList getHandlerList() { - return handlers; - } + return handlers; + } } diff --git a/src/main/java/de/diddiz/LogBlock/events/PreLogEvent.java b/src/main/java/de/diddiz/LogBlock/events/PreLogEvent.java index 49c8598..51a7a22 100644 --- a/src/main/java/de/diddiz/LogBlock/events/PreLogEvent.java +++ b/src/main/java/de/diddiz/LogBlock/events/PreLogEvent.java @@ -1,56 +1,57 @@ package de.diddiz.LogBlock.events; + import de.diddiz.LogBlock.Actor; import org.bukkit.event.Cancellable; import org.bukkit.event.Event; public abstract class PreLogEvent extends Event implements Cancellable { - protected boolean cancelled = false; - protected Actor owner; + protected boolean cancelled = false; + protected Actor owner; - public PreLogEvent(Actor owner) { + public PreLogEvent(Actor owner) { - this.owner = owner; - } + this.owner = owner; + } - /** - * Returns the player/monster/cause involved in this event - * - * @return Player/monster/cause who is involved in this event - * @deprecated {@link #getOwnerActor() } returns an object encapsulating - * name and uuid. Names are not guaranteed to be unique. - */ - public String getOwner() { + /** + * Returns the player/monster/cause involved in this event + * + * @return Player/monster/cause who is involved in this event + * @deprecated {@link #getOwnerActor() } returns an object encapsulating + * name and uuid. Names are not guaranteed to be unique. + */ + public String getOwner() { - return owner.getName(); - } - - /** - * Returns the player/monster/cause involved in this event - * - * @return Player/monster/cause who is involved in this event - */ - public Actor getOwnerActor() { - return owner; - } + return owner.getName(); + } - /** - * Sets the player/monster/cause involved in this event - * - * @param owner The player/monster/cause who is involved in this event - */ - public void setOwner(Actor owner) { + /** + * Returns the player/monster/cause involved in this event + * + * @return Player/monster/cause who is involved in this event + */ + public Actor getOwnerActor() { + return owner; + } - this.owner = 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(Actor owner) { - public boolean isCancelled() { + this.owner = owner; + } - return cancelled; - } + public boolean isCancelled() { - public void setCancelled(boolean cancelled) { + return cancelled; + } - this.cancelled = cancelled; - } + public void setCancelled(boolean cancelled) { + + this.cancelled = cancelled; + } } diff --git a/src/main/java/de/diddiz/LogBlock/listeners/BanListener.java b/src/main/java/de/diddiz/LogBlock/listeners/BanListener.java index 8fd3801..f7c2969 100644 --- a/src/main/java/de/diddiz/LogBlock/listeners/BanListener.java +++ b/src/main/java/de/diddiz/LogBlock/listeners/BanListener.java @@ -1,48 +1,48 @@ package de.diddiz.LogBlock.listeners; -import static de.diddiz.LogBlock.config.Config.banPermission; -import static de.diddiz.LogBlock.config.Config.isLogged; -import static org.bukkit.Bukkit.getScheduler; +import de.diddiz.LogBlock.CommandsHandler; +import de.diddiz.LogBlock.LogBlock; +import de.diddiz.LogBlock.QueryParams; import org.bukkit.World; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.player.PlayerCommandPreprocessEvent; -import de.diddiz.LogBlock.CommandsHandler; -import de.diddiz.LogBlock.LogBlock; -import de.diddiz.LogBlock.QueryParams; -public class BanListener implements Listener -{ - private final CommandsHandler handler; - private final LogBlock logblock; +import static de.diddiz.LogBlock.config.Config.banPermission; +import static de.diddiz.LogBlock.config.Config.isLogged; +import static org.bukkit.Bukkit.getScheduler; - public BanListener(LogBlock logblock) { - this.logblock = logblock; - handler = logblock.getCommandsHandler(); - } +public class BanListener implements Listener { + private final CommandsHandler handler; + private final LogBlock logblock; - @EventHandler - public void onPlayerCommandPreprocess(final PlayerCommandPreprocessEvent event) { - final String[] split = event.getMessage().split(" "); - if (split.length > 1 && split[0].equalsIgnoreCase("/ban") && logblock.hasPermission(event.getPlayer(), banPermission)) { - final QueryParams p = new QueryParams(logblock); - p.setPlayer(split[1].equalsIgnoreCase("g") ? split[2] : split[1]); - p.since = 0; - p.silent = false; - getScheduler().scheduleAsyncDelayedTask(logblock, new Runnable() - { - @Override - public void run() { - for (final World world : logblock.getServer().getWorlds()) - if (isLogged(world)) { - p.world = world; - try { - handler.new CommandRollback(event.getPlayer(), p, false); - } catch (final Exception ex) { - } - } - } - }); - } - } + public BanListener(LogBlock logblock) { + this.logblock = logblock; + handler = logblock.getCommandsHandler(); + } + + @EventHandler + public void onPlayerCommandPreprocess(final PlayerCommandPreprocessEvent event) { + final String[] split = event.getMessage().split(" "); + if (split.length > 1 && split[0].equalsIgnoreCase("/ban") && logblock.hasPermission(event.getPlayer(), banPermission)) { + final QueryParams p = new QueryParams(logblock); + p.setPlayer(split[1].equalsIgnoreCase("g") ? split[2] : split[1]); + p.since = 0; + p.silent = false; + getScheduler().scheduleAsyncDelayedTask(logblock, new Runnable() { + @Override + public void run() { + for (final World world : logblock.getServer().getWorlds()) { + if (isLogged(world)) { + p.world = world; + try { + handler.new CommandRollback(event.getPlayer(), p, false); + } catch (final Exception ex) { + } + } + } + } + }); + } + } } diff --git a/src/main/java/de/diddiz/LogBlock/listeners/BlockBreakLogging.java b/src/main/java/de/diddiz/LogBlock/listeners/BlockBreakLogging.java index 22dad56..b27db53 100644 --- a/src/main/java/de/diddiz/LogBlock/listeners/BlockBreakLogging.java +++ b/src/main/java/de/diddiz/LogBlock/listeners/BlockBreakLogging.java @@ -1,10 +1,10 @@ package de.diddiz.LogBlock.listeners; import de.diddiz.LogBlock.Actor; -import static de.diddiz.LogBlock.config.Config.getWorldConfig; -import static de.diddiz.LogBlock.config.Config.isLogging; -import static de.diddiz.util.LoggingUtil.smartLogBlockBreak; -import static de.diddiz.util.LoggingUtil.smartLogFallables; +import de.diddiz.LogBlock.LogBlock; +import de.diddiz.LogBlock.Logging; +import de.diddiz.LogBlock.config.WorldConfig; +import de.diddiz.util.BukkitUtils; import org.bukkit.GameMode; import org.bukkit.Material; import org.bukkit.block.Block; @@ -13,50 +13,52 @@ import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.block.BlockBreakEvent; import org.bukkit.event.player.PlayerBucketFillEvent; -import de.diddiz.LogBlock.LogBlock; -import de.diddiz.LogBlock.Logging; -import de.diddiz.LogBlock.config.WorldConfig; -import de.diddiz.util.BukkitUtils; -public class BlockBreakLogging extends LoggingListener -{ - public BlockBreakLogging(LogBlock lb) { - super(lb); - } +import static de.diddiz.LogBlock.config.Config.getWorldConfig; +import static de.diddiz.LogBlock.config.Config.isLogging; +import static de.diddiz.util.LoggingUtil.smartLogBlockBreak; +import static de.diddiz.util.LoggingUtil.smartLogFallables; - @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) - public void onBlockBreak(BlockBreakEvent event) { - if (isLogging(event.getBlock().getWorld(), Logging.BLOCKBREAK)) { - WorldConfig wcfg = getWorldConfig(event.getBlock().getWorld()); - if (wcfg == null) return; +public class BlockBreakLogging extends LoggingListener { + public BlockBreakLogging(LogBlock lb) { + super(lb); + } - final Actor actor = Actor.actorFromEntity(event.getPlayer()); - final Block origin = event.getBlock(); - final int typeId = origin.getTypeId(); - final Material type = origin.getType(); + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onBlockBreak(BlockBreakEvent event) { + if (isLogging(event.getBlock().getWorld(), Logging.BLOCKBREAK)) { + WorldConfig wcfg = getWorldConfig(event.getBlock().getWorld()); + if (wcfg == null) { + return; + } - if (wcfg.isLogging(Logging.SIGNTEXT) && (typeId == 63 || typeId == 68)) { - consumer.queueSignBreak(actor, (Sign) origin.getState()); - } else if (wcfg.isLogging(Logging.CHESTACCESS) && BukkitUtils.getContainerBlocks().contains(type)) { - consumer.queueContainerBreak(actor, origin.getState()); - } else if (type == Material.ICE) { - // When in creative mode ice doesn't form water - if (event.getPlayer().getGameMode().equals(GameMode.CREATIVE)) { - consumer.queueBlockBreak(actor, origin.getState()); - } else { - consumer.queueBlockReplace(actor, origin.getState(), 9, (byte) 0); - } - } else { - smartLogBlockBreak(consumer, actor, origin); - } - smartLogFallables(consumer, actor, origin); - } - } + final Actor actor = Actor.actorFromEntity(event.getPlayer()); + final Block origin = event.getBlock(); + final int typeId = origin.getTypeId(); + final Material type = origin.getType(); - @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) - public void onPlayerBucketFill(PlayerBucketFillEvent event) { - if (isLogging(event.getBlockClicked().getWorld(), Logging.BLOCKBREAK)) { - consumer.queueBlockBreak(Actor.actorFromEntity(event.getPlayer()), event.getBlockClicked().getState()); - } - } + if (wcfg.isLogging(Logging.SIGNTEXT) && (typeId == 63 || typeId == 68)) { + consumer.queueSignBreak(actor, (Sign) origin.getState()); + } else if (wcfg.isLogging(Logging.CHESTACCESS) && BukkitUtils.getContainerBlocks().contains(type)) { + consumer.queueContainerBreak(actor, origin.getState()); + } else if (type == Material.ICE) { + // When in creative mode ice doesn't form water + if (event.getPlayer().getGameMode().equals(GameMode.CREATIVE)) { + consumer.queueBlockBreak(actor, origin.getState()); + } else { + consumer.queueBlockReplace(actor, origin.getState(), 9, (byte) 0); + } + } else { + smartLogBlockBreak(consumer, actor, origin); + } + smartLogFallables(consumer, actor, origin); + } + } + + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onPlayerBucketFill(PlayerBucketFillEvent event) { + if (isLogging(event.getBlockClicked().getWorld(), Logging.BLOCKBREAK)) { + consumer.queueBlockBreak(Actor.actorFromEntity(event.getPlayer()), event.getBlockClicked().getState()); + } + } } diff --git a/src/main/java/de/diddiz/LogBlock/listeners/BlockBurnLogging.java b/src/main/java/de/diddiz/LogBlock/listeners/BlockBurnLogging.java index e819b63..b0571cd 100644 --- a/src/main/java/de/diddiz/LogBlock/listeners/BlockBurnLogging.java +++ b/src/main/java/de/diddiz/LogBlock/listeners/BlockBurnLogging.java @@ -1,12 +1,10 @@ package de.diddiz.LogBlock.listeners; -import static de.diddiz.LogBlock.config.Config.isLogging; -import static de.diddiz.util.LoggingUtil.smartLogBlockBreak; -import static de.diddiz.util.LoggingUtil.smartLogFallables; - +import de.diddiz.LogBlock.Actor; +import de.diddiz.LogBlock.LogBlock; +import de.diddiz.LogBlock.Logging; import org.bukkit.Material; import org.bukkit.block.Block; -import org.bukkit.block.BlockFace; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; @@ -14,34 +12,33 @@ import org.bukkit.event.block.Action; import org.bukkit.event.block.BlockBurnEvent; import org.bukkit.event.player.PlayerInteractEvent; -import de.diddiz.LogBlock.Actor; -import de.diddiz.LogBlock.LogBlock; -import de.diddiz.LogBlock.Logging; +import static de.diddiz.LogBlock.config.Config.isLogging; +import static de.diddiz.util.LoggingUtil.smartLogBlockBreak; +import static de.diddiz.util.LoggingUtil.smartLogFallables; -public class BlockBurnLogging extends LoggingListener -{ - public BlockBurnLogging(LogBlock lb) { - super(lb); - } +public class BlockBurnLogging extends LoggingListener { + public BlockBurnLogging(LogBlock lb) { + super(lb); + } - @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) - public void onBlockBurn(BlockBurnEvent event) { - if (isLogging(event.getBlock().getWorld(), Logging.FIRE)) { - smartLogBlockBreak(consumer, new Actor("Fire"), event.getBlock()); - smartLogFallables(consumer, new Actor("Fire"), event.getBlock()); - } - } - - @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) - public void onExtinguish(PlayerInteractEvent event) { - if(event.getAction().equals(Action.LEFT_CLICK_BLOCK)){ - Player player = event.getPlayer(); - Block block = event.getClickedBlock().getRelative(event.getBlockFace()); - if (block.getType().equals(Material.FIRE) && isLogging(player.getWorld(), Logging.FIRE)) { - Actor actor = Actor.actorFromEntity(player); - smartLogBlockBreak(consumer, actor, block); - smartLogFallables(consumer, actor, block); - } - } - } + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onBlockBurn(BlockBurnEvent event) { + if (isLogging(event.getBlock().getWorld(), Logging.FIRE)) { + smartLogBlockBreak(consumer, new Actor("Fire"), event.getBlock()); + smartLogFallables(consumer, new Actor("Fire"), event.getBlock()); + } + } + + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onExtinguish(PlayerInteractEvent event) { + if (event.getAction().equals(Action.LEFT_CLICK_BLOCK)) { + Player player = event.getPlayer(); + Block block = event.getClickedBlock().getRelative(event.getBlockFace()); + if (block.getType().equals(Material.FIRE) && isLogging(player.getWorld(), Logging.FIRE)) { + Actor actor = Actor.actorFromEntity(player); + smartLogBlockBreak(consumer, actor, block); + smartLogFallables(consumer, actor, block); + } + } + } } diff --git a/src/main/java/de/diddiz/LogBlock/listeners/BlockPlaceLogging.java b/src/main/java/de/diddiz/LogBlock/listeners/BlockPlaceLogging.java index 58ae7fb..c532537 100644 --- a/src/main/java/de/diddiz/LogBlock/listeners/BlockPlaceLogging.java +++ b/src/main/java/de/diddiz/LogBlock/listeners/BlockPlaceLogging.java @@ -1,9 +1,10 @@ package de.diddiz.LogBlock.listeners; import de.diddiz.LogBlock.Actor; -import static de.diddiz.LogBlock.config.Config.getWorldConfig; -import static de.diddiz.LogBlock.config.Config.isLogging; - +import de.diddiz.LogBlock.LogBlock; +import de.diddiz.LogBlock.Logging; +import de.diddiz.LogBlock.config.WorldConfig; +import de.diddiz.util.BukkitUtils; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.block.BlockFace; @@ -12,79 +13,80 @@ import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.block.BlockPlaceEvent; import org.bukkit.event.player.PlayerBucketEmptyEvent; -import de.diddiz.LogBlock.LogBlock; -import de.diddiz.LogBlock.Logging; -import de.diddiz.LogBlock.config.WorldConfig; -import de.diddiz.util.BukkitUtils; -public class BlockPlaceLogging extends LoggingListener -{ - public BlockPlaceLogging(LogBlock lb) { - super(lb); - } +import static de.diddiz.LogBlock.config.Config.getWorldConfig; +import static de.diddiz.LogBlock.config.Config.isLogging; - @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) - public void onBlockPlace(BlockPlaceEvent event) { - final WorldConfig wcfg = getWorldConfig(event.getBlock().getWorld()); - if (wcfg != null && wcfg.isLogging(Logging.BLOCKPLACE)) { - final Material type = event.getBlock().getType(); - final BlockState before = event.getBlockReplacedState(); - final BlockState after = event.getBlockPlaced().getState(); - final Actor actor = Actor.actorFromEntity(event.getPlayer()); +public class BlockPlaceLogging extends LoggingListener { + public BlockPlaceLogging(LogBlock lb) { + super(lb); + } - //Handle falling blocks - if (BukkitUtils.getRelativeTopFallables().contains(type)) { + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onBlockPlace(BlockPlaceEvent event) { + final WorldConfig wcfg = getWorldConfig(event.getBlock().getWorld()); + if (wcfg != null && wcfg.isLogging(Logging.BLOCKPLACE)) { + final Material type = event.getBlock().getType(); + final BlockState before = event.getBlockReplacedState(); + final BlockState after = event.getBlockPlaced().getState(); + final Actor actor = Actor.actorFromEntity(event.getPlayer()); - // Catch placed blocks overwriting something - if (before.getType() != Material.AIR) { - consumer.queueBlockBreak(actor, before); - } + //Handle falling blocks + if (BukkitUtils.getRelativeTopFallables().contains(type)) { - Location loc = event.getBlock().getLocation(); - int x = loc.getBlockX(); - int y = loc.getBlockY(); - int z = loc.getBlockZ(); - // Blocks only fall if they have a chance to start a velocity - if (event.getBlock().getRelative(BlockFace.DOWN).getType() == Material.AIR) { - while (y > 0 && BukkitUtils.canFall(loc.getWorld(), x, (y - 1), z)) { - y--; - } - } - // If y is 0 then the sand block fell out of the world :( - if (y != 0) { - Location finalLoc = new Location(loc.getWorld(), x, y, z); - // Run this check to avoid false positives - if (!BukkitUtils.getFallingEntityKillers().contains(finalLoc.getBlock().getType())) { - if (finalLoc.getBlock().getType() == Material.AIR || finalLoc.equals(event.getBlock().getLocation())) { - consumer.queueBlockPlace(actor, finalLoc, type.getId(), event.getBlock().getData()); - } else { - consumer.queueBlockReplace(actor, finalLoc, finalLoc.getBlock().getTypeId(), finalLoc.getBlock().getData(), type.getId(), event.getBlock().getData()); - } - } - } - return; - } + // Catch placed blocks overwriting something + if (before.getType() != Material.AIR) { + consumer.queueBlockBreak(actor, before); + } - //Sign logging is handled elsewhere - if (wcfg.isLogging(Logging.SIGNTEXT) && (type.getId() == 63 || type.getId() == 68)) return; + Location loc = event.getBlock().getLocation(); + int x = loc.getBlockX(); + int y = loc.getBlockY(); + int z = loc.getBlockZ(); + // Blocks only fall if they have a chance to start a velocity + if (event.getBlock().getRelative(BlockFace.DOWN).getType() == Material.AIR) { + while (y > 0 && BukkitUtils.canFall(loc.getWorld(), x, (y - 1), z)) { + y--; + } + } + // If y is 0 then the sand block fell out of the world :( + if (y != 0) { + Location finalLoc = new Location(loc.getWorld(), x, y, z); + // Run this check to avoid false positives + if (!BukkitUtils.getFallingEntityKillers().contains(finalLoc.getBlock().getType())) { + if (finalLoc.getBlock().getType() == Material.AIR || finalLoc.equals(event.getBlock().getLocation())) { + consumer.queueBlockPlace(actor, finalLoc, type.getId(), event.getBlock().getData()); + } else { + consumer.queueBlockReplace(actor, finalLoc, finalLoc.getBlock().getTypeId(), finalLoc.getBlock().getData(), type.getId(), event.getBlock().getData()); + } + } + } + return; + } - //Delay queuing by one tick to allow data to be updated - LogBlock.getInstance().getServer().getScheduler().scheduleSyncDelayedTask(LogBlock.getInstance(), new Runnable() - { - @Override - public void run() { - if (before.getTypeId() == 0) - consumer.queueBlockPlace(actor, after); - else - consumer.queueBlockReplace(actor, before, after); - } - }, 1L); - } - } + //Sign logging is handled elsewhere + if (wcfg.isLogging(Logging.SIGNTEXT) && (type.getId() == 63 || type.getId() == 68)) { + return; + } - @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) - public void onPlayerBucketEmpty(PlayerBucketEmptyEvent event) { - if (isLogging(event.getPlayer().getWorld(), Logging.BLOCKPLACE)) - consumer.queueBlockPlace(Actor.actorFromEntity(event.getPlayer()), event.getBlockClicked().getRelative(event.getBlockFace()).getLocation(), event.getBucket() == Material.WATER_BUCKET ? 9 : 11, (byte)0); - } + //Delay queuing by one tick to allow data to be updated + LogBlock.getInstance().getServer().getScheduler().scheduleSyncDelayedTask(LogBlock.getInstance(), new Runnable() { + @Override + public void run() { + if (before.getTypeId() == 0) { + consumer.queueBlockPlace(actor, after); + } else { + consumer.queueBlockReplace(actor, before, after); + } + } + }, 1L); + } + } + + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onPlayerBucketEmpty(PlayerBucketEmptyEvent event) { + if (isLogging(event.getPlayer().getWorld(), Logging.BLOCKPLACE)) { + consumer.queueBlockPlace(Actor.actorFromEntity(event.getPlayer()), event.getBlockClicked().getRelative(event.getBlockFace()).getLocation(), event.getBucket() == Material.WATER_BUCKET ? 9 : 11, (byte) 0); + } + } } diff --git a/src/main/java/de/diddiz/LogBlock/listeners/BlockSpreadLogging.java b/src/main/java/de/diddiz/LogBlock/listeners/BlockSpreadLogging.java index 1cac2d0..ca3d923 100644 --- a/src/main/java/de/diddiz/LogBlock/listeners/BlockSpreadLogging.java +++ b/src/main/java/de/diddiz/LogBlock/listeners/BlockSpreadLogging.java @@ -3,50 +3,58 @@ package de.diddiz.LogBlock.listeners; import de.diddiz.LogBlock.Actor; import de.diddiz.LogBlock.LogBlock; import de.diddiz.LogBlock.Logging; -import static de.diddiz.LogBlock.config.Config.isLogging; import org.bukkit.Material; import org.bukkit.World; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.block.BlockSpreadEvent; -public class BlockSpreadLogging extends LoggingListener -{ +import static de.diddiz.LogBlock.config.Config.isLogging; - public BlockSpreadLogging(LogBlock lb) { - super(lb); - } +public class BlockSpreadLogging extends LoggingListener { - @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) - public void onBlockSpread(BlockSpreadEvent event) { + public BlockSpreadLogging(LogBlock lb) { + super(lb); + } - String name; + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onBlockSpread(BlockSpreadEvent event) { - World world = event.getBlock().getWorld(); - Material type = event.getSource().getType(); + String name; - switch (type) { - case GRASS: - if (!isLogging(world, Logging.GRASSGROWTH)) return; - name = "GrassGrowth"; - break; - case MYCEL: - if (!isLogging(world, Logging.MYCELIUMSPREAD)) return; - name = "MyceliumSpread"; - break; - case VINE: - if (!isLogging(world, Logging.VINEGROWTH)) return; - name = "VineGrowth"; - break; - case RED_MUSHROOM: - case BROWN_MUSHROOM: - if (!isLogging(world, Logging.MUSHROOMSPREAD)) return; - name = "MushroomSpread"; - break; - default: - return; - } + World world = event.getBlock().getWorld(); + Material type = event.getSource().getType(); - consumer.queueBlockReplace(new Actor(name), event.getBlock().getState(), event.getNewState()); - } + switch (type) { + case GRASS: + if (!isLogging(world, Logging.GRASSGROWTH)) { + return; + } + name = "GrassGrowth"; + break; + case MYCEL: + if (!isLogging(world, Logging.MYCELIUMSPREAD)) { + return; + } + name = "MyceliumSpread"; + break; + case VINE: + if (!isLogging(world, Logging.VINEGROWTH)) { + return; + } + name = "VineGrowth"; + break; + case RED_MUSHROOM: + case BROWN_MUSHROOM: + if (!isLogging(world, Logging.MUSHROOMSPREAD)) { + return; + } + name = "MushroomSpread"; + break; + default: + return; + } + + consumer.queueBlockReplace(new Actor(name), event.getBlock().getState(), event.getNewState()); + } } diff --git a/src/main/java/de/diddiz/LogBlock/listeners/ChatLogging.java b/src/main/java/de/diddiz/LogBlock/listeners/ChatLogging.java index 80078c5..e8985f2 100644 --- a/src/main/java/de/diddiz/LogBlock/listeners/ChatLogging.java +++ b/src/main/java/de/diddiz/LogBlock/listeners/ChatLogging.java @@ -3,33 +3,35 @@ package de.diddiz.LogBlock.listeners; import de.diddiz.LogBlock.Actor; import de.diddiz.LogBlock.LogBlock; import de.diddiz.LogBlock.Logging; -import static de.diddiz.LogBlock.config.Config.isLogging; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.player.AsyncPlayerChatEvent; import org.bukkit.event.player.PlayerCommandPreprocessEvent; import org.bukkit.event.server.ServerCommandEvent; -public class ChatLogging extends LoggingListener -{ - public ChatLogging(LogBlock lb) { - super(lb); - } +import static de.diddiz.LogBlock.config.Config.isLogging; - @EventHandler(priority = EventPriority.MONITOR) - public void onPlayerCommandPreprocess(PlayerCommandPreprocessEvent event) { - if (isLogging(event.getPlayer().getWorld(), Logging.CHAT)) - consumer.queueChat(Actor.actorFromEntity(event.getPlayer()), event.getMessage()); - } +public class ChatLogging extends LoggingListener { + public ChatLogging(LogBlock lb) { + super(lb); + } - @EventHandler(priority = EventPriority.MONITOR) - public void onPlayerChat(AsyncPlayerChatEvent event) { - if (isLogging(event.getPlayer().getWorld(), Logging.CHAT)) - consumer.queueChat(Actor.actorFromEntity(event.getPlayer()), event.getMessage()); - } + @EventHandler(priority = EventPriority.MONITOR) + public void onPlayerCommandPreprocess(PlayerCommandPreprocessEvent event) { + if (isLogging(event.getPlayer().getWorld(), Logging.CHAT)) { + consumer.queueChat(Actor.actorFromEntity(event.getPlayer()), event.getMessage()); + } + } - @EventHandler(priority = EventPriority.MONITOR) - public void onServerCommand(ServerCommandEvent event) { - consumer.queueChat(new Actor("Console"), "/" + event.getCommand()); - } + @EventHandler(priority = EventPriority.MONITOR) + public void onPlayerChat(AsyncPlayerChatEvent event) { + if (isLogging(event.getPlayer().getWorld(), Logging.CHAT)) { + consumer.queueChat(Actor.actorFromEntity(event.getPlayer()), event.getMessage()); + } + } + + @EventHandler(priority = EventPriority.MONITOR) + public void onServerCommand(ServerCommandEvent event) { + consumer.queueChat(new Actor("Console"), "/" + event.getCommand()); + } } diff --git a/src/main/java/de/diddiz/LogBlock/listeners/ChestAccessLogging.java b/src/main/java/de/diddiz/LogBlock/listeners/ChestAccessLogging.java index 9354556..3ada3b9 100644 --- a/src/main/java/de/diddiz/LogBlock/listeners/ChestAccessLogging.java +++ b/src/main/java/de/diddiz/LogBlock/listeners/ChestAccessLogging.java @@ -1,15 +1,7 @@ package de.diddiz.LogBlock.listeners; import de.diddiz.LogBlock.Actor; -import static de.diddiz.LogBlock.config.Config.isLogging; -import static de.diddiz.util.BukkitUtils.compareInventories; -import static de.diddiz.util.BukkitUtils.compressInventory; -import static de.diddiz.util.BukkitUtils.getInventoryHolderLocation; -import static de.diddiz.util.BukkitUtils.getInventoryHolderType; -import static de.diddiz.util.BukkitUtils.rawData; -import java.util.HashMap; -import java.util.Map; - +import de.diddiz.LogBlock.LogBlock; import de.diddiz.LogBlock.Logging; import org.bukkit.Location; import org.bukkit.block.BlockState; @@ -21,47 +13,55 @@ import org.bukkit.event.inventory.InventoryCloseEvent; import org.bukkit.event.inventory.InventoryOpenEvent; import org.bukkit.inventory.InventoryHolder; import org.bukkit.inventory.ItemStack; -import de.diddiz.LogBlock.LogBlock; -public class ChestAccessLogging extends LoggingListener -{ - private final Map containers = new HashMap(); +import java.util.HashMap; +import java.util.Map; - public ChestAccessLogging(LogBlock lb) { - super(lb); - } +import static de.diddiz.LogBlock.config.Config.isLogging; +import static de.diddiz.util.BukkitUtils.*; - @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) - public void onInventoryClose(InventoryCloseEvent event) { +public class ChestAccessLogging extends LoggingListener { + private final Map containers = new HashMap(); - if (!isLogging(event.getPlayer().getWorld(), Logging.CHESTACCESS)) return; - InventoryHolder holder = event.getInventory().getHolder(); - if (holder instanceof BlockState || holder instanceof DoubleChest) { - final HumanEntity player = event.getPlayer(); - final ItemStack[] before = containers.get(player); - if (before != null) { - final ItemStack[] after = compressInventory(event.getInventory().getContents()); - final ItemStack[] diff = compareInventories(before, after); - final Location loc = getInventoryHolderLocation(holder); - for (final ItemStack item : diff) { - consumer.queueChestAccess(Actor.actorFromEntity(player), loc, loc.getWorld().getBlockTypeIdAt(loc), (short)item.getTypeId(), (short)item.getAmount(), rawData(item)); - } - containers.remove(player); - } - } - } + public ChestAccessLogging(LogBlock lb) { + super(lb); + } - @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) - public void onInventoryOpen(InventoryOpenEvent event) { + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onInventoryClose(InventoryCloseEvent event) { - if (!isLogging(event.getPlayer().getWorld(), Logging.CHESTACCESS)) return; - if (event.getInventory() != null) { - InventoryHolder holder = event.getInventory().getHolder(); - if (holder instanceof BlockState || holder instanceof DoubleChest) { - if (getInventoryHolderType(holder) != 58) { - containers.put(event.getPlayer(), compressInventory(event.getInventory().getContents())); - } - } - } - } + if (!isLogging(event.getPlayer().getWorld(), Logging.CHESTACCESS)) { + return; + } + InventoryHolder holder = event.getInventory().getHolder(); + if (holder instanceof BlockState || holder instanceof DoubleChest) { + final HumanEntity player = event.getPlayer(); + final ItemStack[] before = containers.get(player); + if (before != null) { + final ItemStack[] after = compressInventory(event.getInventory().getContents()); + final ItemStack[] diff = compareInventories(before, after); + final Location loc = getInventoryHolderLocation(holder); + for (final ItemStack item : diff) { + consumer.queueChestAccess(Actor.actorFromEntity(player), loc, loc.getWorld().getBlockTypeIdAt(loc), (short) item.getTypeId(), (short) item.getAmount(), rawData(item)); + } + containers.remove(player); + } + } + } + + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onInventoryOpen(InventoryOpenEvent event) { + + if (!isLogging(event.getPlayer().getWorld(), Logging.CHESTACCESS)) { + return; + } + if (event.getInventory() != null) { + InventoryHolder holder = event.getInventory().getHolder(); + if (holder instanceof BlockState || holder instanceof DoubleChest) { + if (getInventoryHolderType(holder) != 58) { + containers.put(event.getPlayer(), compressInventory(event.getInventory().getContents())); + } + } + } + } } diff --git a/src/main/java/de/diddiz/LogBlock/listeners/CreatureInteractLogging.java b/src/main/java/de/diddiz/LogBlock/listeners/CreatureInteractLogging.java index 940359e..ea0cab0 100644 --- a/src/main/java/de/diddiz/LogBlock/listeners/CreatureInteractLogging.java +++ b/src/main/java/de/diddiz/LogBlock/listeners/CreatureInteractLogging.java @@ -3,7 +3,6 @@ package de.diddiz.LogBlock.listeners; import de.diddiz.LogBlock.Actor; import de.diddiz.LogBlock.LogBlock; import de.diddiz.LogBlock.Logging; -import static de.diddiz.LogBlock.config.Config.getWorldConfig; import de.diddiz.LogBlock.config.WorldConfig; import de.diddiz.util.BukkitUtils; import org.bukkit.Location; @@ -16,42 +15,45 @@ import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.entity.EntityInteractEvent; -public class CreatureInteractLogging extends LoggingListener -{ - public CreatureInteractLogging(LogBlock lb) { - super(lb); - } +import static de.diddiz.LogBlock.config.Config.getWorldConfig; - @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) - public void onEntityInteract(EntityInteractEvent event) { - final WorldConfig wcfg = getWorldConfig(event.getEntity().getWorld()); +public class CreatureInteractLogging extends LoggingListener { + public CreatureInteractLogging(LogBlock lb) { + super(lb); + } - final EntityType entityType = event.getEntityType(); + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onEntityInteract(EntityInteractEvent event) { + final WorldConfig wcfg = getWorldConfig(event.getEntity().getWorld()); - // Mobs only - if (event.getEntity() instanceof Player || entityType == null) return; + final EntityType entityType = event.getEntityType(); - if (wcfg != null) { - final Block clicked = event.getBlock(); - final Material type = clicked.getType(); - final int typeId = type.getId(); - final byte blockData = clicked.getData(); - final Location loc = clicked.getLocation(); + // Mobs only + if (event.getEntity() instanceof Player || entityType == null) { + return; + } - switch (type) { - case SOIL: - if (wcfg.isLogging(Logging.CREATURECROPTRAMPLE)) { - // 3 = Dirt ID - consumer.queueBlock(Actor.actorFromEntity(entityType), loc, typeId, 3, blockData); - // Log the crop on top as being broken - Block trampledCrop = clicked.getRelative(BlockFace.UP); - if (BukkitUtils.getCropBlocks().contains(trampledCrop.getType())) { - consumer.queueBlockBreak(new Actor("CreatureTrample"), trampledCrop.getState()); - } - } - break; - } - } - } + if (wcfg != null) { + final Block clicked = event.getBlock(); + final Material type = clicked.getType(); + final int typeId = type.getId(); + final byte blockData = clicked.getData(); + final Location loc = clicked.getLocation(); + + switch (type) { + case SOIL: + if (wcfg.isLogging(Logging.CREATURECROPTRAMPLE)) { + // 3 = Dirt ID + consumer.queueBlock(Actor.actorFromEntity(entityType), loc, typeId, 3, blockData); + // Log the crop on top as being broken + Block trampledCrop = clicked.getRelative(BlockFace.UP); + if (BukkitUtils.getCropBlocks().contains(trampledCrop.getType())) { + consumer.queueBlockBreak(new Actor("CreatureTrample"), trampledCrop.getState()); + } + } + break; + } + } + } } diff --git a/src/main/java/de/diddiz/LogBlock/listeners/EndermenLogging.java b/src/main/java/de/diddiz/LogBlock/listeners/EndermenLogging.java index 1f4bc21..9fc14ba 100644 --- a/src/main/java/de/diddiz/LogBlock/listeners/EndermenLogging.java +++ b/src/main/java/de/diddiz/LogBlock/listeners/EndermenLogging.java @@ -3,21 +3,22 @@ package de.diddiz.LogBlock.listeners; import de.diddiz.LogBlock.Actor; import de.diddiz.LogBlock.LogBlock; import de.diddiz.LogBlock.Logging; -import static de.diddiz.LogBlock.config.Config.isLogging; import org.bukkit.entity.Enderman; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.entity.EntityChangeBlockEvent; -public class EndermenLogging extends LoggingListener -{ - public EndermenLogging(LogBlock lb) { - super(lb); - } +import static de.diddiz.LogBlock.config.Config.isLogging; - @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) - public void onEntityChangeBlock(EntityChangeBlockEvent event) { - if (event.getEntity() instanceof Enderman && isLogging(event.getBlock().getWorld(), Logging.ENDERMEN)) - consumer.queueBlockReplace(new Actor("Enderman"), event.getBlock().getState(), event.getTo().getId(), (byte)0); // Figure out how to get the data of the placed block; - } +public class EndermenLogging extends LoggingListener { + public EndermenLogging(LogBlock lb) { + super(lb); + } + + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onEntityChangeBlock(EntityChangeBlockEvent event) { + if (event.getEntity() instanceof Enderman && isLogging(event.getBlock().getWorld(), Logging.ENDERMEN)) { + consumer.queueBlockReplace(new Actor("Enderman"), event.getBlock().getState(), event.getTo().getId(), (byte) 0); // Figure out how to get the data of the placed block; + } + } } diff --git a/src/main/java/de/diddiz/LogBlock/listeners/ExplosionLogging.java b/src/main/java/de/diddiz/LogBlock/listeners/ExplosionLogging.java index 4d9bb66..070b717 100644 --- a/src/main/java/de/diddiz/LogBlock/listeners/ExplosionLogging.java +++ b/src/main/java/de/diddiz/LogBlock/listeners/ExplosionLogging.java @@ -1,105 +1,105 @@ package de.diddiz.LogBlock.listeners; -import static de.diddiz.LogBlock.config.Config.getWorldConfig; -import static de.diddiz.LogBlock.config.Config.logCreeperExplosionsAsPlayerWhoTriggeredThese; -import static de.diddiz.util.BukkitUtils.getContainerBlocks; - +import de.diddiz.LogBlock.Actor; +import de.diddiz.LogBlock.LogBlock; +import de.diddiz.LogBlock.Logging; +import de.diddiz.LogBlock.config.WorldConfig; import org.bukkit.Material; import org.bukkit.block.Block; import org.bukkit.block.Sign; -import org.bukkit.entity.Creeper; -import org.bukkit.entity.EnderDragon; -import org.bukkit.entity.Entity; -import org.bukkit.entity.Fireball; -import org.bukkit.entity.Ghast; -import org.bukkit.entity.Player; -import org.bukkit.entity.TNTPrimed; -import org.bukkit.entity.Wither; -import org.bukkit.entity.WitherSkull; +import org.bukkit.entity.*; import org.bukkit.entity.minecart.ExplosiveMinecart; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.entity.EntityExplodeEvent; import org.bukkit.projectiles.ProjectileSource; -import de.diddiz.LogBlock.Actor; -import de.diddiz.LogBlock.LogBlock; -import de.diddiz.LogBlock.Logging; -import de.diddiz.LogBlock.config.WorldConfig; +import static de.diddiz.LogBlock.config.Config.getWorldConfig; +import static de.diddiz.LogBlock.config.Config.logCreeperExplosionsAsPlayerWhoTriggeredThese; +import static de.diddiz.util.BukkitUtils.getContainerBlocks; -public class ExplosionLogging extends LoggingListener -{ - public ExplosionLogging(LogBlock lb) { - super(lb); - } +public class ExplosionLogging extends LoggingListener { + public ExplosionLogging(LogBlock lb) { + super(lb); + } - @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) - public void onEntityExplode(EntityExplodeEvent event) { - final WorldConfig wcfg = getWorldConfig(event.getLocation().getWorld()); - if (wcfg != null) { - Actor actor = new Actor("Explosion"); - Entity source = event.getEntity(); - if (source == null) { - if (!wcfg.isLogging(Logging.MISCEXPLOSION)) - return; - } else if (source instanceof TNTPrimed) { - if (!wcfg.isLogging(Logging.TNTEXPLOSION)) - return; - actor = new Actor("TNT"); - } else if (source instanceof ExplosiveMinecart) { - if (!wcfg.isLogging(Logging.TNTMINECARTEXPLOSION)) - return; - actor = new Actor("TNTMinecart"); - } else if (source instanceof Creeper) { - if (!wcfg.isLogging(Logging.CREEPEREXPLOSION)) - return; - if (logCreeperExplosionsAsPlayerWhoTriggeredThese) { - final Entity target = ((Creeper) source).getTarget(); - actor = target instanceof Player ? Actor.actorFromEntity(target) : new Actor("Creeper"); - } else - new Actor("Creeper"); - } else if (source instanceof Fireball) { - Fireball fireball = (Fireball) source; - ProjectileSource shooter = fireball.getShooter(); - if (shooter == null) { - return; - } - if (shooter instanceof Ghast) { - if (!wcfg.isLogging(Logging.GHASTFIREBALLEXPLOSION)) { - return; - } - actor = Actor.actorFromProjectileSource(shooter); - } else if (shooter instanceof Wither) { - if (!wcfg.isLogging(Logging.WITHER)) { - return; - } - actor = Actor.actorFromProjectileSource(shooter); - } - } else if (source instanceof EnderDragon) { - if (!wcfg.isLogging(Logging.ENDERDRAGON)) - return; - actor = Actor.actorFromEntity(source); - } else if (source instanceof Wither) { - if(!wcfg.isLogging(Logging.WITHER)) - return; - actor = Actor.actorFromEntity(source); - } else if (source instanceof WitherSkull) { - if(!wcfg.isLogging(Logging.WITHER_SKULL)) - return; - actor = Actor.actorFromEntity(source); - } else { - if (!wcfg.isLogging(Logging.MISCEXPLOSION)) - return; - } - for (final Block block : event.blockList()) { - final int type = block.getTypeId(); - if (wcfg.isLogging(Logging.SIGNTEXT) & (type == 63 || type == 68)) - consumer.queueSignBreak(actor, (Sign)block.getState()); - else if (wcfg.isLogging(Logging.CHESTACCESS) && (getContainerBlocks().contains(Material.getMaterial(type)))) - consumer.queueContainerBreak(actor, block.getState()); - else - consumer.queueBlockBreak(actor, block.getState()); - } - } - } + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onEntityExplode(EntityExplodeEvent event) { + final WorldConfig wcfg = getWorldConfig(event.getLocation().getWorld()); + if (wcfg != null) { + Actor actor = new Actor("Explosion"); + Entity source = event.getEntity(); + if (source == null) { + if (!wcfg.isLogging(Logging.MISCEXPLOSION)) { + return; + } + } else if (source instanceof TNTPrimed) { + if (!wcfg.isLogging(Logging.TNTEXPLOSION)) { + return; + } + actor = new Actor("TNT"); + } else if (source instanceof ExplosiveMinecart) { + if (!wcfg.isLogging(Logging.TNTMINECARTEXPLOSION)) { + return; + } + actor = new Actor("TNTMinecart"); + } else if (source instanceof Creeper) { + if (!wcfg.isLogging(Logging.CREEPEREXPLOSION)) { + return; + } + if (logCreeperExplosionsAsPlayerWhoTriggeredThese) { + final Entity target = ((Creeper) source).getTarget(); + actor = target instanceof Player ? Actor.actorFromEntity(target) : new Actor("Creeper"); + } else { + new Actor("Creeper"); + } + } else if (source instanceof Fireball) { + Fireball fireball = (Fireball) source; + ProjectileSource shooter = fireball.getShooter(); + if (shooter == null) { + return; + } + if (shooter instanceof Ghast) { + if (!wcfg.isLogging(Logging.GHASTFIREBALLEXPLOSION)) { + return; + } + actor = Actor.actorFromProjectileSource(shooter); + } else if (shooter instanceof Wither) { + if (!wcfg.isLogging(Logging.WITHER)) { + return; + } + actor = Actor.actorFromProjectileSource(shooter); + } + } else if (source instanceof EnderDragon) { + if (!wcfg.isLogging(Logging.ENDERDRAGON)) { + return; + } + actor = Actor.actorFromEntity(source); + } else if (source instanceof Wither) { + if (!wcfg.isLogging(Logging.WITHER)) { + return; + } + actor = Actor.actorFromEntity(source); + } else if (source instanceof WitherSkull) { + if (!wcfg.isLogging(Logging.WITHER_SKULL)) { + return; + } + actor = Actor.actorFromEntity(source); + } else { + if (!wcfg.isLogging(Logging.MISCEXPLOSION)) { + return; + } + } + for (final Block block : event.blockList()) { + final int type = block.getTypeId(); + if (wcfg.isLogging(Logging.SIGNTEXT) & (type == 63 || type == 68)) { + consumer.queueSignBreak(actor, (Sign) block.getState()); + } else if (wcfg.isLogging(Logging.CHESTACCESS) && (getContainerBlocks().contains(Material.getMaterial(type)))) { + consumer.queueContainerBreak(actor, block.getState()); + } else { + consumer.queueBlockBreak(actor, block.getState()); + } + } + } + } } diff --git a/src/main/java/de/diddiz/LogBlock/listeners/FluidFlowLogging.java b/src/main/java/de/diddiz/LogBlock/listeners/FluidFlowLogging.java index d64bfb6..ec1efc5 100644 --- a/src/main/java/de/diddiz/LogBlock/listeners/FluidFlowLogging.java +++ b/src/main/java/de/diddiz/LogBlock/listeners/FluidFlowLogging.java @@ -3,80 +3,81 @@ package de.diddiz.LogBlock.listeners; import de.diddiz.LogBlock.Actor; import de.diddiz.LogBlock.LogBlock; import de.diddiz.LogBlock.Logging; -import static de.diddiz.LogBlock.config.Config.getWorldConfig; import de.diddiz.LogBlock.config.WorldConfig; -import java.util.Arrays; -import java.util.HashSet; -import java.util.Set; import org.bukkit.block.Block; import org.bukkit.block.BlockFace; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.block.BlockFromToEvent; -public class FluidFlowLogging extends LoggingListener -{ - private static final Set nonFluidProofBlocks = new HashSet(Arrays.asList(27, 28, 31, 32, 37, 38, 39, 40, 50, 51, 55, 59, 66, 69, 70, 75, 76, 78, 93, 94, 104, 105, 106)); +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; - public FluidFlowLogging(LogBlock lb) { - super(lb); - } +import static de.diddiz.LogBlock.config.Config.getWorldConfig; - @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) - public void onBlockFromTo(BlockFromToEvent event) { - final WorldConfig wcfg = getWorldConfig(event.getBlock().getWorld()); - if (wcfg != null) { - final Block to = event.getToBlock(); - final int typeFrom = event.getBlock().getTypeId(); - final int typeTo = to.getTypeId(); - final boolean canFlow = typeTo == 0 || nonFluidProofBlocks.contains(typeTo); - if (typeFrom == 10 || typeFrom == 11) { - if (canFlow && wcfg.isLogging(Logging.LAVAFLOW)) { - if (isSurroundedByWater(to) && event.getBlock().getData() <= 2) - consumer.queueBlockReplace(new Actor("LavaFlow"), to.getState(), 4, (byte)0); - else if (typeTo == 0) { - consumer.queueBlockPlace(new Actor("LavaFlow"), to.getLocation(), 10, (byte)(event.getBlock().getData() + 1)); - } else { - consumer.queueBlockReplace(new Actor("LavaFlow"), to.getState(), 10, (byte)(event.getBlock().getData() + 1)); - } - } else if (typeTo == 8 || typeTo == 9) { - if (event.getFace() == BlockFace.DOWN) { - consumer.queueBlockReplace(new Actor("LavaFlow"), to.getState(), 1, (byte)0); - } else { - consumer.queueBlockReplace(new Actor("LavaFlow"), to.getState(), 4, (byte)0); - } - } - } else if ((typeFrom == 8 || typeFrom == 9) && wcfg.isLogging(Logging.WATERFLOW)) { - if (typeTo == 0) { - consumer.queueBlockPlace(new Actor("WaterFlow"), to.getLocation(), 8, (byte)(event.getBlock().getData() + 1)); - } else if (nonFluidProofBlocks.contains(typeTo)) { - consumer.queueBlockReplace(new Actor("WaterFlow"), to.getState(), 8, (byte)(event.getBlock().getData() + 1)); - } - else if (typeTo == 10 || typeTo == 11) { - if (to.getData() == 0) { - consumer.queueBlockReplace(new Actor("WaterFlow"), to.getState(), 49, (byte)0); - } else if (event.getFace() == BlockFace.DOWN) { - consumer.queueBlockReplace(new Actor("LavaFlow"), to.getState(), 1, (byte)0); - } - } - if (typeTo == 0 || nonFluidProofBlocks.contains(typeTo)) { - for (final BlockFace face : new BlockFace[]{BlockFace.DOWN, BlockFace.NORTH, BlockFace.WEST, BlockFace.EAST, BlockFace.SOUTH}) { - final Block lower = to.getRelative(face); - if (lower.getTypeId() == 10 || lower.getTypeId() == 11) { - consumer.queueBlockReplace(new Actor("WaterFlow"), lower.getState(), lower.getData() == 0 ? 49 : 4, (byte)0); - } - } - } - } - } - } +public class FluidFlowLogging extends LoggingListener { + private static final Set nonFluidProofBlocks = new HashSet(Arrays.asList(27, 28, 31, 32, 37, 38, 39, 40, 50, 51, 55, 59, 66, 69, 70, 75, 76, 78, 93, 94, 104, 105, 106)); - private static boolean isSurroundedByWater(Block block) { - for (final BlockFace face : new BlockFace[]{BlockFace.NORTH, BlockFace.WEST, BlockFace.EAST, BlockFace.SOUTH}) { - final int type = block.getRelative(face).getTypeId(); - if (type == 8 || type == 9) - return true; - } - return false; - } + public FluidFlowLogging(LogBlock lb) { + super(lb); + } + + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onBlockFromTo(BlockFromToEvent event) { + final WorldConfig wcfg = getWorldConfig(event.getBlock().getWorld()); + if (wcfg != null) { + final Block to = event.getToBlock(); + final int typeFrom = event.getBlock().getTypeId(); + final int typeTo = to.getTypeId(); + final boolean canFlow = typeTo == 0 || nonFluidProofBlocks.contains(typeTo); + if (typeFrom == 10 || typeFrom == 11) { + if (canFlow && wcfg.isLogging(Logging.LAVAFLOW)) { + if (isSurroundedByWater(to) && event.getBlock().getData() <= 2) { + consumer.queueBlockReplace(new Actor("LavaFlow"), to.getState(), 4, (byte) 0); + } else if (typeTo == 0) { + consumer.queueBlockPlace(new Actor("LavaFlow"), to.getLocation(), 10, (byte) (event.getBlock().getData() + 1)); + } else { + consumer.queueBlockReplace(new Actor("LavaFlow"), to.getState(), 10, (byte) (event.getBlock().getData() + 1)); + } + } else if (typeTo == 8 || typeTo == 9) { + if (event.getFace() == BlockFace.DOWN) { + consumer.queueBlockReplace(new Actor("LavaFlow"), to.getState(), 1, (byte) 0); + } else { + consumer.queueBlockReplace(new Actor("LavaFlow"), to.getState(), 4, (byte) 0); + } + } + } else if ((typeFrom == 8 || typeFrom == 9) && wcfg.isLogging(Logging.WATERFLOW)) { + if (typeTo == 0) { + consumer.queueBlockPlace(new Actor("WaterFlow"), to.getLocation(), 8, (byte) (event.getBlock().getData() + 1)); + } else if (nonFluidProofBlocks.contains(typeTo)) { + consumer.queueBlockReplace(new Actor("WaterFlow"), to.getState(), 8, (byte) (event.getBlock().getData() + 1)); + } else if (typeTo == 10 || typeTo == 11) { + if (to.getData() == 0) { + consumer.queueBlockReplace(new Actor("WaterFlow"), to.getState(), 49, (byte) 0); + } else if (event.getFace() == BlockFace.DOWN) { + consumer.queueBlockReplace(new Actor("LavaFlow"), to.getState(), 1, (byte) 0); + } + } + if (typeTo == 0 || nonFluidProofBlocks.contains(typeTo)) { + for (final BlockFace face : new BlockFace[]{BlockFace.DOWN, BlockFace.NORTH, BlockFace.WEST, BlockFace.EAST, BlockFace.SOUTH}) { + final Block lower = to.getRelative(face); + if (lower.getTypeId() == 10 || lower.getTypeId() == 11) { + consumer.queueBlockReplace(new Actor("WaterFlow"), lower.getState(), lower.getData() == 0 ? 49 : 4, (byte) 0); + } + } + } + } + } + } + + private static boolean isSurroundedByWater(Block block) { + for (final BlockFace face : new BlockFace[]{BlockFace.NORTH, BlockFace.WEST, BlockFace.EAST, BlockFace.SOUTH}) { + final int type = block.getRelative(face).getTypeId(); + if (type == 8 || type == 9) { + return true; + } + } + return false; + } } diff --git a/src/main/java/de/diddiz/LogBlock/listeners/InteractLogging.java b/src/main/java/de/diddiz/LogBlock/listeners/InteractLogging.java index 086cb33..dd3e350 100644 --- a/src/main/java/de/diddiz/LogBlock/listeners/InteractLogging.java +++ b/src/main/java/de/diddiz/LogBlock/listeners/InteractLogging.java @@ -1,8 +1,9 @@ package de.diddiz.LogBlock.listeners; import de.diddiz.LogBlock.Actor; -import static de.diddiz.LogBlock.config.Config.getWorldConfig; - +import de.diddiz.LogBlock.LogBlock; +import de.diddiz.LogBlock.Logging; +import de.diddiz.LogBlock.config.WorldConfig; import de.diddiz.util.BukkitUtils; import org.bukkit.Location; import org.bukkit.Material; @@ -13,86 +14,90 @@ import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.block.Action; import org.bukkit.event.player.PlayerInteractEvent; -import de.diddiz.LogBlock.LogBlock; -import de.diddiz.LogBlock.Logging; -import de.diddiz.LogBlock.config.WorldConfig; -import org.bukkit.entity.EntityType; -public class InteractLogging extends LoggingListener -{ - public InteractLogging(LogBlock lb) { - super(lb); - } +import static de.diddiz.LogBlock.config.Config.getWorldConfig; - @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) - public void onPlayerInteract(PlayerInteractEvent event) { - final WorldConfig wcfg = getWorldConfig(event.getPlayer().getWorld()); - if (wcfg != null) { - final Block clicked = event.getClickedBlock(); - if (clicked == null) return; - final Material type = clicked.getType(); - final int typeId = type.getId(); - final byte blockData = clicked.getData(); - final Player player = event.getPlayer(); - final Location loc = clicked.getLocation(); +public class InteractLogging extends LoggingListener { + public InteractLogging(LogBlock lb) { + super(lb); + } - switch (type) { - case LEVER: - case WOOD_BUTTON: - case STONE_BUTTON: - if (wcfg.isLogging(Logging.SWITCHINTERACT) && event.getAction() == Action.RIGHT_CLICK_BLOCK) - consumer.queueBlock(Actor.actorFromEntity(player), loc, typeId, typeId, blockData); - break; - case FENCE_GATE: - case WOODEN_DOOR: - case TRAP_DOOR: - if (wcfg.isLogging(Logging.DOORINTERACT) && event.getAction() == Action.RIGHT_CLICK_BLOCK) - consumer.queueBlock(Actor.actorFromEntity(player), loc, typeId, typeId, blockData); - break; - case CAKE_BLOCK: - if (wcfg.isLogging(Logging.CAKEEAT) && event.getAction() == Action.RIGHT_CLICK_BLOCK && player.getFoodLevel() < 20) - consumer.queueBlock(Actor.actorFromEntity(player), loc, typeId, typeId, blockData); - break; - case NOTE_BLOCK: - if (wcfg.isLogging(Logging.NOTEBLOCKINTERACT) && event.getAction() == Action.RIGHT_CLICK_BLOCK) - consumer.queueBlock(Actor.actorFromEntity(player), loc, typeId, typeId, blockData); - break; - case DIODE_BLOCK_OFF: - case DIODE_BLOCK_ON: - if (wcfg.isLogging(Logging.DIODEINTERACT) && event.getAction() == Action.RIGHT_CLICK_BLOCK) - consumer.queueBlock(Actor.actorFromEntity(player), loc, typeId, typeId, blockData); - break; - case REDSTONE_COMPARATOR_OFF: - case REDSTONE_COMPARATOR_ON: - if (wcfg.isLogging(Logging.COMPARATORINTERACT) && event.getAction() == Action.RIGHT_CLICK_BLOCK) { - consumer.queueBlock(Actor.actorFromEntity(player), loc, typeId, typeId, blockData); - } - break; - case WOOD_PLATE: - case STONE_PLATE: - case IRON_PLATE: - case GOLD_PLATE: - if (wcfg.isLogging(Logging.PRESUREPLATEINTERACT) && event.getAction() == Action.PHYSICAL) { - consumer.queueBlock(Actor.actorFromEntity(player), loc, typeId, typeId, blockData); - } - break; - case TRIPWIRE: - if (wcfg.isLogging(Logging.TRIPWIREINTERACT) && event.getAction() == Action.PHYSICAL) { - consumer.queueBlock(Actor.actorFromEntity(player), loc, typeId, typeId, blockData); - } - break; - case SOIL: - if (wcfg.isLogging(Logging.CROPTRAMPLE) && event.getAction() == Action.PHYSICAL) { - // 3 = Dirt ID - consumer.queueBlock(Actor.actorFromEntity(player), loc, typeId, 3, blockData); - // Log the crop on top as being broken - Block trampledCrop = clicked.getRelative(BlockFace.UP); - if (BukkitUtils.getCropBlocks().contains(trampledCrop.getType())) { - consumer.queueBlockBreak(Actor.actorFromEntity(player), trampledCrop.getState()); - } - } - break; - } - } - } + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onPlayerInteract(PlayerInteractEvent event) { + final WorldConfig wcfg = getWorldConfig(event.getPlayer().getWorld()); + if (wcfg != null) { + final Block clicked = event.getClickedBlock(); + if (clicked == null) { + return; + } + final Material type = clicked.getType(); + final int typeId = type.getId(); + final byte blockData = clicked.getData(); + final Player player = event.getPlayer(); + final Location loc = clicked.getLocation(); + + switch (type) { + case LEVER: + case WOOD_BUTTON: + case STONE_BUTTON: + if (wcfg.isLogging(Logging.SWITCHINTERACT) && event.getAction() == Action.RIGHT_CLICK_BLOCK) { + consumer.queueBlock(Actor.actorFromEntity(player), loc, typeId, typeId, blockData); + } + break; + case FENCE_GATE: + case WOODEN_DOOR: + case TRAP_DOOR: + if (wcfg.isLogging(Logging.DOORINTERACT) && event.getAction() == Action.RIGHT_CLICK_BLOCK) { + consumer.queueBlock(Actor.actorFromEntity(player), loc, typeId, typeId, blockData); + } + break; + case CAKE_BLOCK: + if (wcfg.isLogging(Logging.CAKEEAT) && event.getAction() == Action.RIGHT_CLICK_BLOCK && player.getFoodLevel() < 20) { + consumer.queueBlock(Actor.actorFromEntity(player), loc, typeId, typeId, blockData); + } + break; + case NOTE_BLOCK: + if (wcfg.isLogging(Logging.NOTEBLOCKINTERACT) && event.getAction() == Action.RIGHT_CLICK_BLOCK) { + consumer.queueBlock(Actor.actorFromEntity(player), loc, typeId, typeId, blockData); + } + break; + case DIODE_BLOCK_OFF: + case DIODE_BLOCK_ON: + if (wcfg.isLogging(Logging.DIODEINTERACT) && event.getAction() == Action.RIGHT_CLICK_BLOCK) { + consumer.queueBlock(Actor.actorFromEntity(player), loc, typeId, typeId, blockData); + } + break; + case REDSTONE_COMPARATOR_OFF: + case REDSTONE_COMPARATOR_ON: + if (wcfg.isLogging(Logging.COMPARATORINTERACT) && event.getAction() == Action.RIGHT_CLICK_BLOCK) { + consumer.queueBlock(Actor.actorFromEntity(player), loc, typeId, typeId, blockData); + } + break; + case WOOD_PLATE: + case STONE_PLATE: + case IRON_PLATE: + case GOLD_PLATE: + if (wcfg.isLogging(Logging.PRESUREPLATEINTERACT) && event.getAction() == Action.PHYSICAL) { + consumer.queueBlock(Actor.actorFromEntity(player), loc, typeId, typeId, blockData); + } + break; + case TRIPWIRE: + if (wcfg.isLogging(Logging.TRIPWIREINTERACT) && event.getAction() == Action.PHYSICAL) { + consumer.queueBlock(Actor.actorFromEntity(player), loc, typeId, typeId, blockData); + } + break; + case SOIL: + if (wcfg.isLogging(Logging.CROPTRAMPLE) && event.getAction() == Action.PHYSICAL) { + // 3 = Dirt ID + consumer.queueBlock(Actor.actorFromEntity(player), loc, typeId, 3, blockData); + // Log the crop on top as being broken + Block trampledCrop = clicked.getRelative(BlockFace.UP); + if (BukkitUtils.getCropBlocks().contains(trampledCrop.getType())) { + consumer.queueBlockBreak(Actor.actorFromEntity(player), trampledCrop.getState()); + } + } + break; + } + } + } } diff --git a/src/main/java/de/diddiz/LogBlock/listeners/KillLogging.java b/src/main/java/de/diddiz/LogBlock/listeners/KillLogging.java index 0a8a7b7..49c8c76 100644 --- a/src/main/java/de/diddiz/LogBlock/listeners/KillLogging.java +++ b/src/main/java/de/diddiz/LogBlock/listeners/KillLogging.java @@ -3,10 +3,7 @@ package de.diddiz.LogBlock.listeners; import de.diddiz.LogBlock.Actor; import de.diddiz.LogBlock.LogBlock; import de.diddiz.LogBlock.Logging; -import de.diddiz.LogBlock.config.Config.LogKillsLevel; -import static de.diddiz.LogBlock.config.Config.isLogging; -import static de.diddiz.LogBlock.config.Config.logEnvironmentalKills; -import static de.diddiz.LogBlock.config.Config.logKillsLevel; +import de.diddiz.LogBlock.config.Config.*; import org.bukkit.entity.Entity; import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Monster; @@ -17,34 +14,37 @@ import org.bukkit.event.entity.EntityDamageByEntityEvent; import org.bukkit.event.entity.EntityDamageEvent; import org.bukkit.event.entity.EntityDeathEvent; +import static de.diddiz.LogBlock.config.Config.*; -public class KillLogging extends LoggingListener -{ - public KillLogging(LogBlock lb) { - super(lb); - } +public class KillLogging extends LoggingListener { - @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) - public void onEntityDeath(EntityDeathEvent deathEvent) { - EntityDamageEvent event = deathEvent.getEntity().getLastDamageCause(); - // For a death event, there should always be a damage event and it should not be cancelled. Check anyway. - if (event!= null && event.isCancelled() == false && isLogging(event.getEntity().getWorld(), Logging.KILL) && event.getEntity() instanceof LivingEntity) { - final LivingEntity victim = (LivingEntity)event.getEntity(); - if (event instanceof EntityDamageByEntityEvent) { - final Entity killer = ((EntityDamageByEntityEvent)event).getDamager(); - if (logKillsLevel == LogKillsLevel.PLAYERS && !(victim instanceof Player && killer instanceof Player)) - return; - else if (logKillsLevel == LogKillsLevel.MONSTERS && !((victim instanceof Player || victim instanceof Monster) && killer instanceof Player || killer instanceof Monster)) - return; - consumer.queueKill(killer, victim); - } else if (logEnvironmentalKills) { - if (logKillsLevel == LogKillsLevel.PLAYERS && !(victim instanceof Player)) - return; - else if (logKillsLevel == LogKillsLevel.MONSTERS && !((victim instanceof Player || victim instanceof Monster))) - return; - consumer.queueKill(new Actor(event.getCause().toString()),victim); - } - } - } + public KillLogging(LogBlock lb) { + super(lb); + } + + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onEntityDeath(EntityDeathEvent deathEvent) { + EntityDamageEvent event = deathEvent.getEntity().getLastDamageCause(); + // For a death event, there should always be a damage event and it should not be cancelled. Check anyway. + if (event != null && event.isCancelled() == false && isLogging(event.getEntity().getWorld(), Logging.KILL) && event.getEntity() instanceof LivingEntity) { + final LivingEntity victim = (LivingEntity) event.getEntity(); + if (event instanceof EntityDamageByEntityEvent) { + final Entity killer = ((EntityDamageByEntityEvent) event).getDamager(); + if (logKillsLevel == LogKillsLevel.PLAYERS && !(victim instanceof Player && killer instanceof Player)) { + return; + } else if (logKillsLevel == LogKillsLevel.MONSTERS && !((victim instanceof Player || victim instanceof Monster) && killer instanceof Player || killer instanceof Monster)) { + return; + } + consumer.queueKill(killer, victim); + } else if (logEnvironmentalKills) { + if (logKillsLevel == LogKillsLevel.PLAYERS && !(victim instanceof Player)) { + return; + } else if (logKillsLevel == LogKillsLevel.MONSTERS && !((victim instanceof Player || victim instanceof Monster))) { + return; + } + consumer.queueKill(new Actor(event.getCause().toString()), victim); + } + } + } } diff --git a/src/main/java/de/diddiz/LogBlock/listeners/LeavesDecayLogging.java b/src/main/java/de/diddiz/LogBlock/listeners/LeavesDecayLogging.java index 253eaa5..055974e 100644 --- a/src/main/java/de/diddiz/LogBlock/listeners/LeavesDecayLogging.java +++ b/src/main/java/de/diddiz/LogBlock/listeners/LeavesDecayLogging.java @@ -3,24 +3,24 @@ package de.diddiz.LogBlock.listeners; import de.diddiz.LogBlock.Actor; import de.diddiz.LogBlock.LogBlock; import de.diddiz.LogBlock.Logging; -import static de.diddiz.LogBlock.config.Config.isLogging; -import static de.diddiz.util.LoggingUtil.smartLogBlockBreak; -import static de.diddiz.util.LoggingUtil.smartLogFallables; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.block.LeavesDecayEvent; -public class LeavesDecayLogging extends LoggingListener -{ - public LeavesDecayLogging(LogBlock lb) { - super(lb); - } +import static de.diddiz.LogBlock.config.Config.isLogging; +import static de.diddiz.util.LoggingUtil.smartLogBlockBreak; +import static de.diddiz.util.LoggingUtil.smartLogFallables; - @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) - public void onLeavesDecay(LeavesDecayEvent event) { - if (isLogging(event.getBlock().getWorld(), Logging.LEAVESDECAY)) { - smartLogBlockBreak(consumer, new Actor("LeavesDecay"), event.getBlock()); - smartLogFallables(consumer, new Actor("LeavesDecay"), event.getBlock()); - } - } +public class LeavesDecayLogging extends LoggingListener { + public LeavesDecayLogging(LogBlock lb) { + super(lb); + } + + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onLeavesDecay(LeavesDecayEvent event) { + if (isLogging(event.getBlock().getWorld(), Logging.LEAVESDECAY)) { + smartLogBlockBreak(consumer, new Actor("LeavesDecay"), event.getBlock()); + smartLogFallables(consumer, new Actor("LeavesDecay"), event.getBlock()); + } + } } diff --git a/src/main/java/de/diddiz/LogBlock/listeners/LockedChestDecayLogging.java b/src/main/java/de/diddiz/LogBlock/listeners/LockedChestDecayLogging.java index 5f1c766..159d12b 100644 --- a/src/main/java/de/diddiz/LogBlock/listeners/LockedChestDecayLogging.java +++ b/src/main/java/de/diddiz/LogBlock/listeners/LockedChestDecayLogging.java @@ -3,23 +3,24 @@ package de.diddiz.LogBlock.listeners; import de.diddiz.LogBlock.Actor; import de.diddiz.LogBlock.LogBlock; import de.diddiz.LogBlock.Logging; -import static de.diddiz.LogBlock.config.Config.isLogging; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.block.BlockFadeEvent; -public class LockedChestDecayLogging extends LoggingListener -{ - public LockedChestDecayLogging(LogBlock lb) { - super(lb); - } +import static de.diddiz.LogBlock.config.Config.isLogging; - @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) - public void onBlockFade(BlockFadeEvent event) { - if (isLogging(event.getBlock().getWorld(), Logging.LOCKEDCHESTDECAY)) { - final int type = event.getBlock().getTypeId(); - if (type == 95) - consumer.queueBlockReplace(new Actor("LockedChestDecay"), event.getBlock().getState(), event.getNewState()); - } - } +public class LockedChestDecayLogging extends LoggingListener { + public LockedChestDecayLogging(LogBlock lb) { + super(lb); + } + + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onBlockFade(BlockFadeEvent event) { + if (isLogging(event.getBlock().getWorld(), Logging.LOCKEDCHESTDECAY)) { + final int type = event.getBlock().getTypeId(); + if (type == 95) { + consumer.queueBlockReplace(new Actor("LockedChestDecay"), event.getBlock().getState(), event.getNewState()); + } + } + } } diff --git a/src/main/java/de/diddiz/LogBlock/listeners/LoggingListener.java b/src/main/java/de/diddiz/LogBlock/listeners/LoggingListener.java index 6258104..4f91089 100644 --- a/src/main/java/de/diddiz/LogBlock/listeners/LoggingListener.java +++ b/src/main/java/de/diddiz/LogBlock/listeners/LoggingListener.java @@ -1,14 +1,13 @@ package de.diddiz.LogBlock.listeners; -import org.bukkit.event.Listener; import de.diddiz.LogBlock.Consumer; import de.diddiz.LogBlock.LogBlock; +import org.bukkit.event.Listener; -public class LoggingListener implements Listener -{ - protected final Consumer consumer; +public class LoggingListener implements Listener { + protected final Consumer consumer; - public LoggingListener(LogBlock lb) { - consumer = lb.getConsumer(); - } + public LoggingListener(LogBlock lb) { + consumer = lb.getConsumer(); + } } diff --git a/src/main/java/de/diddiz/LogBlock/listeners/PlayerInfoLogging.java b/src/main/java/de/diddiz/LogBlock/listeners/PlayerInfoLogging.java index 4fe8951..dad3503 100644 --- a/src/main/java/de/diddiz/LogBlock/listeners/PlayerInfoLogging.java +++ b/src/main/java/de/diddiz/LogBlock/listeners/PlayerInfoLogging.java @@ -1,24 +1,23 @@ package de.diddiz.LogBlock.listeners; +import de.diddiz.LogBlock.LogBlock; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.event.player.PlayerQuitEvent; -import de.diddiz.LogBlock.LogBlock; -public class PlayerInfoLogging extends LoggingListener -{ - public PlayerInfoLogging(LogBlock lb) { - super(lb); - } +public class PlayerInfoLogging extends LoggingListener { + public PlayerInfoLogging(LogBlock lb) { + super(lb); + } - @EventHandler(priority = EventPriority.MONITOR) - public void onPlayerJoin(PlayerJoinEvent event) { - consumer.queueJoin(event.getPlayer()); - } + @EventHandler(priority = EventPriority.MONITOR) + public void onPlayerJoin(PlayerJoinEvent event) { + consumer.queueJoin(event.getPlayer()); + } - @EventHandler(priority = EventPriority.MONITOR) - public void onPlayerQuit(PlayerQuitEvent event) { - consumer.queueLeave(event.getPlayer()); - } + @EventHandler(priority = EventPriority.MONITOR) + public void onPlayerQuit(PlayerQuitEvent event) { + consumer.queueLeave(event.getPlayer()); + } } diff --git a/src/main/java/de/diddiz/LogBlock/listeners/SignChangeLogging.java b/src/main/java/de/diddiz/LogBlock/listeners/SignChangeLogging.java index 0b2e823..4d808dd 100644 --- a/src/main/java/de/diddiz/LogBlock/listeners/SignChangeLogging.java +++ b/src/main/java/de/diddiz/LogBlock/listeners/SignChangeLogging.java @@ -3,21 +3,21 @@ package de.diddiz.LogBlock.listeners; import de.diddiz.LogBlock.Actor; import de.diddiz.LogBlock.LogBlock; import de.diddiz.LogBlock.Logging; -import static de.diddiz.LogBlock.config.Config.isLogging; -import org.bukkit.entity.Entity; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.block.SignChangeEvent; -public class SignChangeLogging extends LoggingListener -{ - public SignChangeLogging(LogBlock lb) { - super(lb); - } +import static de.diddiz.LogBlock.config.Config.isLogging; - @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) - public void onSignChange(SignChangeEvent event) { - if (isLogging(event.getBlock().getWorld(), Logging.SIGNTEXT)) - consumer.queueSignPlace(Actor.actorFromEntity(event.getPlayer()), event.getBlock().getLocation(), event.getBlock().getTypeId(), event.getBlock().getData(), event.getLines()); - } +public class SignChangeLogging extends LoggingListener { + public SignChangeLogging(LogBlock lb) { + super(lb); + } + + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onSignChange(SignChangeEvent event) { + if (isLogging(event.getBlock().getWorld(), Logging.SIGNTEXT)) { + consumer.queueSignPlace(Actor.actorFromEntity(event.getPlayer()), event.getBlock().getLocation(), event.getBlock().getTypeId(), event.getBlock().getData(), event.getLines()); + } + } } diff --git a/src/main/java/de/diddiz/LogBlock/listeners/SnowFadeLogging.java b/src/main/java/de/diddiz/LogBlock/listeners/SnowFadeLogging.java index e15c638..8acc3eb 100644 --- a/src/main/java/de/diddiz/LogBlock/listeners/SnowFadeLogging.java +++ b/src/main/java/de/diddiz/LogBlock/listeners/SnowFadeLogging.java @@ -3,23 +3,24 @@ package de.diddiz.LogBlock.listeners; import de.diddiz.LogBlock.Actor; import de.diddiz.LogBlock.LogBlock; import de.diddiz.LogBlock.Logging; -import static de.diddiz.LogBlock.config.Config.isLogging; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.block.BlockFadeEvent; -public class SnowFadeLogging extends LoggingListener -{ - public SnowFadeLogging(LogBlock lb) { - super(lb); - } +import static de.diddiz.LogBlock.config.Config.isLogging; - @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) - public void onBlockFade(BlockFadeEvent event) { - if (isLogging(event.getBlock().getWorld(), Logging.SNOWFADE)) { - final int type = event.getBlock().getTypeId(); - if (type == 78 || type == 79) - consumer.queueBlockReplace(new Actor("SnowFade"), event.getBlock().getState(), event.getNewState()); - } - } +public class SnowFadeLogging extends LoggingListener { + public SnowFadeLogging(LogBlock lb) { + super(lb); + } + + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onBlockFade(BlockFadeEvent event) { + if (isLogging(event.getBlock().getWorld(), Logging.SNOWFADE)) { + final int type = event.getBlock().getTypeId(); + if (type == 78 || type == 79) { + consumer.queueBlockReplace(new Actor("SnowFade"), event.getBlock().getState(), event.getNewState()); + } + } + } } diff --git a/src/main/java/de/diddiz/LogBlock/listeners/SnowFormLogging.java b/src/main/java/de/diddiz/LogBlock/listeners/SnowFormLogging.java index f911a56..d3c4146 100644 --- a/src/main/java/de/diddiz/LogBlock/listeners/SnowFormLogging.java +++ b/src/main/java/de/diddiz/LogBlock/listeners/SnowFormLogging.java @@ -3,17 +3,16 @@ package de.diddiz.LogBlock.listeners; import de.diddiz.LogBlock.Actor; import de.diddiz.LogBlock.LogBlock; import de.diddiz.LogBlock.Logging; -import static de.diddiz.LogBlock.config.Config.isLogging; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.block.BlockFormEvent; -import org.bukkit.event.block.LeavesDecayEvent; -public class SnowFormLogging extends LoggingListener -{ - public SnowFormLogging(LogBlock lb) { - super(lb); - } +import static de.diddiz.LogBlock.config.Config.isLogging; + +public class SnowFormLogging extends LoggingListener { + public SnowFormLogging(LogBlock lb) { + super(lb); + } // @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) // public void onLeavesDecay(LeavesDecayEvent event) { @@ -21,12 +20,13 @@ public class SnowFormLogging extends LoggingListener // consumer.queueBlockBreak("LeavesDecay", event.getBlock().getState()); // } - @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) - public void onBlockForm(BlockFormEvent event) { - if (isLogging(event.getBlock().getWorld(), Logging.SNOWFORM)) { - final int type = event.getNewState().getTypeId(); - if (type == 78 || type == 79) - consumer.queueBlockReplace(new Actor("SnowForm"), event.getBlock().getState(), event.getNewState()); - } - } + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onBlockForm(BlockFormEvent event) { + if (isLogging(event.getBlock().getWorld(), Logging.SNOWFORM)) { + final int type = event.getNewState().getTypeId(); + if (type == 78 || type == 79) { + consumer.queueBlockReplace(new Actor("SnowForm"), event.getBlock().getState(), event.getNewState()); + } + } + } } diff --git a/src/main/java/de/diddiz/LogBlock/listeners/StructureGrowLogging.java b/src/main/java/de/diddiz/LogBlock/listeners/StructureGrowLogging.java index 786acfe..c5730d2 100644 --- a/src/main/java/de/diddiz/LogBlock/listeners/StructureGrowLogging.java +++ b/src/main/java/de/diddiz/LogBlock/listeners/StructureGrowLogging.java @@ -3,35 +3,38 @@ package de.diddiz.LogBlock.listeners; import de.diddiz.LogBlock.Actor; import de.diddiz.LogBlock.LogBlock; import de.diddiz.LogBlock.Logging; -import static de.diddiz.LogBlock.config.Config.getWorldConfig; import de.diddiz.LogBlock.config.WorldConfig; import org.bukkit.block.BlockState; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.world.StructureGrowEvent; -public class StructureGrowLogging extends LoggingListener -{ - public StructureGrowLogging(LogBlock lb) { - super(lb); - } +import static de.diddiz.LogBlock.config.Config.getWorldConfig; - @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) - public void onStructureGrow(StructureGrowEvent event) { - final WorldConfig wcfg = getWorldConfig(event.getWorld()); - if (wcfg != null) { - final Actor actor; - if (event.getPlayer() != null) { - if (!wcfg.isLogging(Logging.BONEMEALSTRUCTUREGROW)) - return; - actor = Actor.actorFromEntity(event.getPlayer()); - } else { - if (!wcfg.isLogging(Logging.NATURALSTRUCTUREGROW)) - return; - actor = new Actor("NaturalGrow"); - } - for (final BlockState state : event.getBlocks()) - consumer.queueBlockReplace(actor, state.getBlock().getState(), state); - } - } +public class StructureGrowLogging extends LoggingListener { + public StructureGrowLogging(LogBlock lb) { + super(lb); + } + + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onStructureGrow(StructureGrowEvent event) { + final WorldConfig wcfg = getWorldConfig(event.getWorld()); + if (wcfg != null) { + final Actor actor; + if (event.getPlayer() != null) { + if (!wcfg.isLogging(Logging.BONEMEALSTRUCTUREGROW)) { + return; + } + actor = Actor.actorFromEntity(event.getPlayer()); + } else { + if (!wcfg.isLogging(Logging.NATURALSTRUCTUREGROW)) { + return; + } + actor = new Actor("NaturalGrow"); + } + for (final BlockState state : event.getBlocks()) { + consumer.queueBlockReplace(actor, state.getBlock().getState(), state); + } + } + } } diff --git a/src/main/java/de/diddiz/LogBlock/listeners/ToolListener.java b/src/main/java/de/diddiz/LogBlock/listeners/ToolListener.java index 1a7a622..06dcab8 100644 --- a/src/main/java/de/diddiz/LogBlock/listeners/ToolListener.java +++ b/src/main/java/de/diddiz/LogBlock/listeners/ToolListener.java @@ -1,13 +1,6 @@ package de.diddiz.LogBlock.listeners; -import de.diddiz.LogBlock.CommandsHandler; -import de.diddiz.LogBlock.LogBlock; -import de.diddiz.LogBlock.QueryParams; -import de.diddiz.LogBlock.Session; -import de.diddiz.LogBlock.Tool; -import de.diddiz.LogBlock.ToolBehavior; -import de.diddiz.LogBlock.ToolData; -import de.diddiz.LogBlock.ToolMode; +import de.diddiz.LogBlock.*; import de.diddiz.worldedit.RegionContainer; import org.bukkit.ChatColor; import org.bukkit.block.Block; @@ -28,104 +21,104 @@ import static de.diddiz.LogBlock.Session.hasSession; import static de.diddiz.LogBlock.config.Config.isLogged; import static de.diddiz.LogBlock.config.Config.toolsByType; -public class ToolListener implements Listener -{ - private final CommandsHandler handler; - private final LogBlock logblock; +public class ToolListener implements Listener { + private final CommandsHandler handler; + private final LogBlock logblock; - public ToolListener(LogBlock logblock) { - this.logblock = logblock; - handler = logblock.getCommandsHandler(); - } + public ToolListener(LogBlock logblock) { + this.logblock = logblock; + handler = logblock.getCommandsHandler(); + } - @EventHandler(ignoreCancelled = true) - public void onPlayerInteract(PlayerInteractEvent event) { - if (event.getMaterial() != null) { - final Action action = event.getAction(); - final int type = event.getMaterial().getId(); - final Tool tool = toolsByType.get(type); - final Player player = event.getPlayer(); - if (tool != null && (action == Action.RIGHT_CLICK_BLOCK || action == Action.LEFT_CLICK_BLOCK) && logblock.hasPermission(player, "logblock.tools." + tool.name)) { - final ToolBehavior behavior = action == Action.RIGHT_CLICK_BLOCK ? tool.rightClickBehavior : tool.leftClickBehavior; - final ToolData toolData = getSession(player).toolData.get(tool); - if (behavior != ToolBehavior.NONE && toolData.enabled) { - if (!isLogged(player.getWorld())) { - player.sendMessage(ChatColor.RED + "This world is not currently logged."); - event.setCancelled(true); - return; - } - final Block block = event.getClickedBlock(); - final QueryParams params = toolData.params; - params.loc = null; - params.sel = null; - if (behavior == ToolBehavior.BLOCK) - params.setLocation(block.getRelative(event.getBlockFace()).getLocation()); - else if ((block.getTypeId() != 54 && block.getTypeId() != 146) || tool.params.radius != 0) - params.setLocation(block.getLocation()); - else { - if (logblock.getServer().getPluginManager().isPluginEnabled("WorldEdit")) { - for (final BlockFace face : new BlockFace[]{BlockFace.NORTH, BlockFace.SOUTH, BlockFace.EAST, BlockFace.WEST}) { - if (block.getRelative(face).getTypeId() == block.getTypeId()) { - params.setSelection(RegionContainer.fromCorners(event.getPlayer().getWorld(), - block.getLocation(), block.getRelative(face).getLocation())); - } - } - } - if (params.sel == null) { - params.setLocation(block.getLocation()); - } - } - try { - if (toolData.mode == ToolMode.ROLLBACK) - handler.new CommandRollback(player, params, true); - else if (toolData.mode == ToolMode.REDO) - handler.new CommandRedo(player, params, true); - else if (toolData.mode == ToolMode.CLEARLOG) - handler.new CommandClearLog(player, params, true); - else if (toolData.mode == ToolMode.WRITELOGFILE) - handler.new CommandWriteLogFile(player, params, true); - else - handler.new CommandLookup(player, params, true); - } catch (final Exception ex) { - player.sendMessage(ChatColor.RED + ex.getMessage()); - } - event.setCancelled(true); - } - } - } - } + @EventHandler(ignoreCancelled = true) + public void onPlayerInteract(PlayerInteractEvent event) { + if (event.getMaterial() != null) { + final Action action = event.getAction(); + final int type = event.getMaterial().getId(); + final Tool tool = toolsByType.get(type); + final Player player = event.getPlayer(); + if (tool != null && (action == Action.RIGHT_CLICK_BLOCK || action == Action.LEFT_CLICK_BLOCK) && logblock.hasPermission(player, "logblock.tools." + tool.name)) { + final ToolBehavior behavior = action == Action.RIGHT_CLICK_BLOCK ? tool.rightClickBehavior : tool.leftClickBehavior; + final ToolData toolData = getSession(player).toolData.get(tool); + if (behavior != ToolBehavior.NONE && toolData.enabled) { + if (!isLogged(player.getWorld())) { + player.sendMessage(ChatColor.RED + "This world is not currently logged."); + event.setCancelled(true); + return; + } + final Block block = event.getClickedBlock(); + final QueryParams params = toolData.params; + params.loc = null; + params.sel = null; + if (behavior == ToolBehavior.BLOCK) { + params.setLocation(block.getRelative(event.getBlockFace()).getLocation()); + } else if ((block.getTypeId() != 54 && block.getTypeId() != 146) || tool.params.radius != 0) { + params.setLocation(block.getLocation()); + } else { + if (logblock.getServer().getPluginManager().isPluginEnabled("WorldEdit")) { + for (final BlockFace face : new BlockFace[]{BlockFace.NORTH, BlockFace.SOUTH, BlockFace.EAST, BlockFace.WEST}) { + if (block.getRelative(face).getTypeId() == block.getTypeId()) { + params.setSelection(RegionContainer.fromCorners(event.getPlayer().getWorld(), + block.getLocation(), block.getRelative(face).getLocation())); + } + } + } + if (params.sel == null) { + params.setLocation(block.getLocation()); + } + } + try { + if (toolData.mode == ToolMode.ROLLBACK) { + handler.new CommandRollback(player, params, true); + } else if (toolData.mode == ToolMode.REDO) { + handler.new CommandRedo(player, params, true); + } else if (toolData.mode == ToolMode.CLEARLOG) { + handler.new CommandClearLog(player, params, true); + } else if (toolData.mode == ToolMode.WRITELOGFILE) { + handler.new CommandWriteLogFile(player, params, true); + } else { + handler.new CommandLookup(player, params, true); + } + } catch (final Exception ex) { + player.sendMessage(ChatColor.RED + ex.getMessage()); + } + event.setCancelled(true); + } + } + } + } - @EventHandler - public void onPlayerChangedWorld(PlayerChangedWorldEvent event) { - final Player player = event.getPlayer(); - if (hasSession(player)) { - final Session session = getSession(player); - for (final Entry entry : session.toolData.entrySet()) { - final Tool tool = entry.getKey(); - final ToolData toolData = entry.getValue(); - if (toolData.enabled && !logblock.hasPermission(player, "logblock.tools." + tool.name)) { - toolData.enabled = false; - player.getInventory().removeItem(new ItemStack(tool.item, 1)); - player.sendMessage(ChatColor.GREEN + "Tool disabled."); - } - } - } - } + @EventHandler + public void onPlayerChangedWorld(PlayerChangedWorldEvent event) { + final Player player = event.getPlayer(); + if (hasSession(player)) { + final Session session = getSession(player); + for (final Entry entry : session.toolData.entrySet()) { + final Tool tool = entry.getKey(); + final ToolData toolData = entry.getValue(); + if (toolData.enabled && !logblock.hasPermission(player, "logblock.tools." + tool.name)) { + toolData.enabled = false; + player.getInventory().removeItem(new ItemStack(tool.item, 1)); + player.sendMessage(ChatColor.GREEN + "Tool disabled."); + } + } + } + } - @EventHandler - public void onPlayerDropItem(PlayerDropItemEvent event) { - final Player player = event.getPlayer(); - if (hasSession(player)) { - final Session session = getSession(player); - for (final Entry entry : session.toolData.entrySet()) { - final Tool tool = entry.getKey(); - final ToolData toolData = entry.getValue(); - final int item = event.getItemDrop().getItemStack().getTypeId(); - if (item == tool.item && toolData.enabled && !tool.canDrop) { - player.sendMessage(ChatColor.RED + "You cannot drop this tool."); - event.setCancelled(true); - } - } - } - } + @EventHandler + public void onPlayerDropItem(PlayerDropItemEvent event) { + final Player player = event.getPlayer(); + if (hasSession(player)) { + final Session session = getSession(player); + for (final Entry entry : session.toolData.entrySet()) { + final Tool tool = entry.getKey(); + final ToolData toolData = entry.getValue(); + final int item = event.getItemDrop().getItemStack().getTypeId(); + if (item == tool.item && toolData.enabled && !tool.canDrop) { + player.sendMessage(ChatColor.RED + "You cannot drop this tool."); + event.setCancelled(true); + } + } + } + } } diff --git a/src/main/java/de/diddiz/LogBlock/listeners/WitherLogging.java b/src/main/java/de/diddiz/LogBlock/listeners/WitherLogging.java index ec5dad2..fa74c93 100644 --- a/src/main/java/de/diddiz/LogBlock/listeners/WitherLogging.java +++ b/src/main/java/de/diddiz/LogBlock/listeners/WitherLogging.java @@ -10,15 +10,15 @@ import org.bukkit.event.entity.EntityChangeBlockEvent; import static de.diddiz.LogBlock.config.Config.isLogging; -public class WitherLogging extends LoggingListener -{ - public WitherLogging(LogBlock lb) { - super(lb); - } +public class WitherLogging extends LoggingListener { + public WitherLogging(LogBlock lb) { + super(lb); + } - @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) - public void onEntityChangeBlock(EntityChangeBlockEvent event) { - if (event.getEntity() instanceof Wither && isLogging(event.getBlock().getWorld(), Logging.WITHER)) - consumer.queueBlockReplace(Actor.actorFromEntity(event.getEntity()), event.getBlock().getState(), event.getTo().getId(), event.getData()); // Wither walked through a block. - } + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onEntityChangeBlock(EntityChangeBlockEvent event) { + if (event.getEntity() instanceof Wither && isLogging(event.getBlock().getWorld(), Logging.WITHER)) { + consumer.queueBlockReplace(Actor.actorFromEntity(event.getEntity()), event.getBlock().getState(), event.getTo().getId(), event.getData()); // Wither walked through a block. + } + } } diff --git a/src/main/java/de/diddiz/util/Block.java b/src/main/java/de/diddiz/util/Block.java index e411c52..e59fce7 100644 --- a/src/main/java/de/diddiz/util/Block.java +++ b/src/main/java/de/diddiz/util/Block.java @@ -2,35 +2,33 @@ package de.diddiz.util; import java.util.List; -public class Block -{ - private int block; - private int data; +public class Block { + private int block; + private int data; - /** - * @param block The id of the block - * @param data The data for the block, -1 for any data - * - */ - public Block(int block, int data) { - this.block = block; - this.data = data; - } + /** + * @param block The id of the block + * @param data The data for the block, -1 for any data + */ + public Block(int block, int data) { + this.block = block; + this.data = data; + } - public int getBlock() { - return this.block; - } + public int getBlock() { + return this.block; + } - public int getData() { - return this.data; - } + public int getData() { + return this.data; + } - public static boolean inList(List types, int blockID) { - for (Block block : types) { - if (block.getBlock() == blockID) { - return true; - } - } - return false; - } + public static boolean inList(List types, int blockID) { + for (Block block : types) { + if (block.getBlock() == blockID) { + return true; + } + } + return false; + } } diff --git a/src/main/java/de/diddiz/util/BukkitUtils.java b/src/main/java/de/diddiz/util/BukkitUtils.java index 308641e..11f05d9 100644 --- a/src/main/java/de/diddiz/util/BukkitUtils.java +++ b/src/main/java/de/diddiz/util/BukkitUtils.java @@ -1,22 +1,6 @@ package de.diddiz.util; -import static de.diddiz.util.MaterialName.materialName; -import java.io.File; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.Comparator; -import java.util.EnumMap; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import org.bukkit.ChatColor; -import org.bukkit.Chunk; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.World; +import org.bukkit.*; import org.bukkit.block.BlockFace; import org.bukkit.block.BlockState; import org.bukkit.block.DoubleChest; @@ -28,405 +12,424 @@ import org.bukkit.inventory.Inventory; import org.bukkit.inventory.InventoryHolder; import org.bukkit.inventory.ItemStack; -public class BukkitUtils -{ - private static final Set> blockEquivalents; - private static final Set relativeBreakable; - private static final Set relativeTopBreakable; - private static final Set relativeTopFallables; - private static final Set fallingEntityKillers; +import java.io.File; +import java.util.*; - private static final Set cropBlocks; - private static final Set containerBlocks; +import static de.diddiz.util.MaterialName.materialName; - private static final Map projectileItems; +public class BukkitUtils { + private static final Set> blockEquivalents; + private static final Set relativeBreakable; + private static final Set relativeTopBreakable; + private static final Set relativeTopFallables; + private static final Set fallingEntityKillers; - static { - blockEquivalents = new HashSet>(7); - blockEquivalents.add(new HashSet(Arrays.asList(2, 3, 60))); - blockEquivalents.add(new HashSet(Arrays.asList(8, 9, 79))); - blockEquivalents.add(new HashSet(Arrays.asList(10, 11))); - blockEquivalents.add(new HashSet(Arrays.asList(61, 62))); - blockEquivalents.add(new HashSet(Arrays.asList(73, 74))); - blockEquivalents.add(new HashSet(Arrays.asList(75, 76))); - blockEquivalents.add(new HashSet(Arrays.asList(93, 94))); + private static final Set cropBlocks; + private static final Set containerBlocks; - // Blocks that break when they are attached to a block - relativeBreakable = new HashSet(11); - relativeBreakable.add(Material.WALL_SIGN); - relativeBreakable.add(Material.LADDER); - relativeBreakable.add(Material.STONE_BUTTON); - relativeBreakable.add(Material.WOOD_BUTTON); - relativeBreakable.add(Material.REDSTONE_TORCH_ON); - relativeBreakable.add(Material.REDSTONE_TORCH_OFF); - relativeBreakable.add(Material.LEVER); - relativeBreakable.add(Material.TORCH); - relativeBreakable.add(Material.TRAP_DOOR); - relativeBreakable.add(Material.TRIPWIRE_HOOK); - relativeBreakable.add(Material.COCOA); + private static final Map projectileItems; - // Blocks that break when they are on top of a block - relativeTopBreakable = new HashSet(33); - relativeTopBreakable.add(Material.SAPLING); - relativeTopBreakable.add(Material.LONG_GRASS); - relativeTopBreakable.add(Material.DEAD_BUSH); - relativeTopBreakable.add(Material.YELLOW_FLOWER); - relativeTopBreakable.add(Material.RED_ROSE); - relativeTopBreakable.add(Material.BROWN_MUSHROOM); - relativeTopBreakable.add(Material.RED_MUSHROOM); - relativeTopBreakable.add(Material.CROPS); - relativeTopBreakable.add(Material.POTATO); - relativeTopBreakable.add(Material.CARROT); - relativeTopBreakable.add(Material.WATER_LILY); - relativeTopBreakable.add(Material.CACTUS); - relativeTopBreakable.add(Material.SUGAR_CANE_BLOCK); - relativeTopBreakable.add(Material.FLOWER_POT); - relativeTopBreakable.add(Material.POWERED_RAIL); - relativeTopBreakable.add(Material.DETECTOR_RAIL); - relativeTopBreakable.add(Material.ACTIVATOR_RAIL); - relativeTopBreakable.add(Material.RAILS); - relativeTopBreakable.add(Material.REDSTONE_WIRE); - relativeTopBreakable.add(Material.SIGN_POST); - relativeTopBreakable.add(Material.STONE_PLATE); - relativeTopBreakable.add(Material.WOOD_PLATE); - relativeTopBreakable.add(Material.IRON_PLATE); - relativeTopBreakable.add(Material.GOLD_PLATE); - relativeTopBreakable.add(Material.SNOW); - relativeTopBreakable.add(Material.DIODE_BLOCK_ON); - relativeTopBreakable.add(Material.DIODE_BLOCK_OFF); - relativeTopBreakable.add(Material.REDSTONE_COMPARATOR_ON); - relativeTopBreakable.add(Material.REDSTONE_COMPARATOR_OFF); - relativeTopBreakable.add(Material.WOODEN_DOOR); - relativeTopBreakable.add(Material.IRON_DOOR_BLOCK); - relativeTopBreakable.add(Material.CARPET); - relativeTopBreakable.add(Material.DOUBLE_PLANT); + static { + blockEquivalents = new HashSet>(7); + blockEquivalents.add(new HashSet(Arrays.asList(2, 3, 60))); + blockEquivalents.add(new HashSet(Arrays.asList(8, 9, 79))); + blockEquivalents.add(new HashSet(Arrays.asList(10, 11))); + blockEquivalents.add(new HashSet(Arrays.asList(61, 62))); + blockEquivalents.add(new HashSet(Arrays.asList(73, 74))); + blockEquivalents.add(new HashSet(Arrays.asList(75, 76))); + blockEquivalents.add(new HashSet(Arrays.asList(93, 94))); - // Blocks that fall - relativeTopFallables = new HashSet(4); - relativeTopFallables.add(Material.SAND); - relativeTopFallables.add(Material.GRAVEL); - relativeTopFallables.add(Material.DRAGON_EGG); - relativeTopFallables.add(Material.ANVIL); + // Blocks that break when they are attached to a block + relativeBreakable = new HashSet(11); + relativeBreakable.add(Material.WALL_SIGN); + relativeBreakable.add(Material.LADDER); + relativeBreakable.add(Material.STONE_BUTTON); + relativeBreakable.add(Material.WOOD_BUTTON); + relativeBreakable.add(Material.REDSTONE_TORCH_ON); + relativeBreakable.add(Material.REDSTONE_TORCH_OFF); + relativeBreakable.add(Material.LEVER); + relativeBreakable.add(Material.TORCH); + relativeBreakable.add(Material.TRAP_DOOR); + relativeBreakable.add(Material.TRIPWIRE_HOOK); + relativeBreakable.add(Material.COCOA); - // Blocks that break falling entities - fallingEntityKillers = new HashSet(32); - fallingEntityKillers.add(Material.SIGN_POST); - fallingEntityKillers.add(Material.WALL_SIGN); - fallingEntityKillers.add(Material.STONE_PLATE); - fallingEntityKillers.add(Material.WOOD_PLATE); - fallingEntityKillers.add(Material.IRON_PLATE); - fallingEntityKillers.add(Material.GOLD_PLATE); - fallingEntityKillers.add(Material.SAPLING); - fallingEntityKillers.add(Material.YELLOW_FLOWER); - fallingEntityKillers.add(Material.RED_ROSE); - fallingEntityKillers.add(Material.CROPS); - fallingEntityKillers.add(Material.CARROT); - fallingEntityKillers.add(Material.POTATO); - fallingEntityKillers.add(Material.RED_MUSHROOM); - fallingEntityKillers.add(Material.BROWN_MUSHROOM); - fallingEntityKillers.add(Material.STEP); - fallingEntityKillers.add(Material.WOOD_STEP); - fallingEntityKillers.add(Material.TORCH); - fallingEntityKillers.add(Material.FLOWER_POT); - fallingEntityKillers.add(Material.POWERED_RAIL); - fallingEntityKillers.add(Material.DETECTOR_RAIL); - fallingEntityKillers.add(Material.ACTIVATOR_RAIL); - fallingEntityKillers.add(Material.RAILS); - fallingEntityKillers.add(Material.LEVER); - fallingEntityKillers.add(Material.REDSTONE_WIRE); - fallingEntityKillers.add(Material.REDSTONE_TORCH_ON); - fallingEntityKillers.add(Material.REDSTONE_TORCH_OFF); - fallingEntityKillers.add(Material.DIODE_BLOCK_ON); - fallingEntityKillers.add(Material.DIODE_BLOCK_OFF); - fallingEntityKillers.add(Material.REDSTONE_COMPARATOR_ON); - fallingEntityKillers.add(Material.REDSTONE_COMPARATOR_OFF); - fallingEntityKillers.add(Material.DAYLIGHT_DETECTOR); - fallingEntityKillers.add(Material.CARPET); + // Blocks that break when they are on top of a block + relativeTopBreakable = new HashSet(33); + relativeTopBreakable.add(Material.SAPLING); + relativeTopBreakable.add(Material.LONG_GRASS); + relativeTopBreakable.add(Material.DEAD_BUSH); + relativeTopBreakable.add(Material.YELLOW_FLOWER); + relativeTopBreakable.add(Material.RED_ROSE); + relativeTopBreakable.add(Material.BROWN_MUSHROOM); + relativeTopBreakable.add(Material.RED_MUSHROOM); + relativeTopBreakable.add(Material.CROPS); + relativeTopBreakable.add(Material.POTATO); + relativeTopBreakable.add(Material.CARROT); + relativeTopBreakable.add(Material.WATER_LILY); + relativeTopBreakable.add(Material.CACTUS); + relativeTopBreakable.add(Material.SUGAR_CANE_BLOCK); + relativeTopBreakable.add(Material.FLOWER_POT); + relativeTopBreakable.add(Material.POWERED_RAIL); + relativeTopBreakable.add(Material.DETECTOR_RAIL); + relativeTopBreakable.add(Material.ACTIVATOR_RAIL); + relativeTopBreakable.add(Material.RAILS); + relativeTopBreakable.add(Material.REDSTONE_WIRE); + relativeTopBreakable.add(Material.SIGN_POST); + relativeTopBreakable.add(Material.STONE_PLATE); + relativeTopBreakable.add(Material.WOOD_PLATE); + relativeTopBreakable.add(Material.IRON_PLATE); + relativeTopBreakable.add(Material.GOLD_PLATE); + relativeTopBreakable.add(Material.SNOW); + relativeTopBreakable.add(Material.DIODE_BLOCK_ON); + relativeTopBreakable.add(Material.DIODE_BLOCK_OFF); + relativeTopBreakable.add(Material.REDSTONE_COMPARATOR_ON); + relativeTopBreakable.add(Material.REDSTONE_COMPARATOR_OFF); + relativeTopBreakable.add(Material.WOODEN_DOOR); + relativeTopBreakable.add(Material.IRON_DOOR_BLOCK); + relativeTopBreakable.add(Material.CARPET); + relativeTopBreakable.add(Material.DOUBLE_PLANT); - // Crop Blocks - cropBlocks = new HashSet(5); - cropBlocks.add(Material.CROPS); - cropBlocks.add(Material.MELON_STEM); - cropBlocks.add(Material.PUMPKIN_STEM); - cropBlocks.add(Material.CARROT); - cropBlocks.add(Material.POTATO); + // Blocks that fall + relativeTopFallables = new HashSet(4); + relativeTopFallables.add(Material.SAND); + relativeTopFallables.add(Material.GRAVEL); + relativeTopFallables.add(Material.DRAGON_EGG); + relativeTopFallables.add(Material.ANVIL); - // Container Blocks - containerBlocks = new HashSet(6); - containerBlocks.add(Material.CHEST); - containerBlocks.add(Material.TRAPPED_CHEST); - containerBlocks.add(Material.DISPENSER); - containerBlocks.add(Material.DROPPER); - containerBlocks.add(Material.HOPPER); - containerBlocks.add(Material.BREWING_STAND); - containerBlocks.add(Material.FURNACE); - containerBlocks.add(Material.BURNING_FURNACE); - containerBlocks.add(Material.BEACON); - // Doesn't actually have a block inventory - // containerBlocks.add(Material.ENDER_CHEST); + // Blocks that break falling entities + fallingEntityKillers = new HashSet(32); + fallingEntityKillers.add(Material.SIGN_POST); + fallingEntityKillers.add(Material.WALL_SIGN); + fallingEntityKillers.add(Material.STONE_PLATE); + fallingEntityKillers.add(Material.WOOD_PLATE); + fallingEntityKillers.add(Material.IRON_PLATE); + fallingEntityKillers.add(Material.GOLD_PLATE); + fallingEntityKillers.add(Material.SAPLING); + fallingEntityKillers.add(Material.YELLOW_FLOWER); + fallingEntityKillers.add(Material.RED_ROSE); + fallingEntityKillers.add(Material.CROPS); + fallingEntityKillers.add(Material.CARROT); + fallingEntityKillers.add(Material.POTATO); + fallingEntityKillers.add(Material.RED_MUSHROOM); + fallingEntityKillers.add(Material.BROWN_MUSHROOM); + fallingEntityKillers.add(Material.STEP); + fallingEntityKillers.add(Material.WOOD_STEP); + fallingEntityKillers.add(Material.TORCH); + fallingEntityKillers.add(Material.FLOWER_POT); + fallingEntityKillers.add(Material.POWERED_RAIL); + fallingEntityKillers.add(Material.DETECTOR_RAIL); + fallingEntityKillers.add(Material.ACTIVATOR_RAIL); + fallingEntityKillers.add(Material.RAILS); + fallingEntityKillers.add(Material.LEVER); + fallingEntityKillers.add(Material.REDSTONE_WIRE); + fallingEntityKillers.add(Material.REDSTONE_TORCH_ON); + fallingEntityKillers.add(Material.REDSTONE_TORCH_OFF); + fallingEntityKillers.add(Material.DIODE_BLOCK_ON); + fallingEntityKillers.add(Material.DIODE_BLOCK_OFF); + fallingEntityKillers.add(Material.REDSTONE_COMPARATOR_ON); + fallingEntityKillers.add(Material.REDSTONE_COMPARATOR_OFF); + fallingEntityKillers.add(Material.DAYLIGHT_DETECTOR); + fallingEntityKillers.add(Material.CARPET); - // It doesn't seem like you could injure people with some of these, but they exist, so.... - projectileItems = new EnumMap(EntityType.class); - projectileItems.put(EntityType.ARROW,262); - projectileItems.put(EntityType.EGG,344); - projectileItems.put(EntityType.ENDER_PEARL,368); - projectileItems.put(EntityType.SMALL_FIREBALL,385); // Fire charge - projectileItems.put(EntityType.FIREBALL,385); // Fire charge - projectileItems.put(EntityType.FISHING_HOOK,346); - projectileItems.put(EntityType.SNOWBALL,332); - projectileItems.put(EntityType.SPLASH_POTION,373); - projectileItems.put(EntityType.THROWN_EXP_BOTTLE,384); - projectileItems.put(EntityType.WITHER_SKULL,397); + // Crop Blocks + cropBlocks = new HashSet(5); + cropBlocks.add(Material.CROPS); + cropBlocks.add(Material.MELON_STEM); + cropBlocks.add(Material.PUMPKIN_STEM); + cropBlocks.add(Material.CARROT); + cropBlocks.add(Material.POTATO); - } + // Container Blocks + containerBlocks = new HashSet(6); + containerBlocks.add(Material.CHEST); + containerBlocks.add(Material.TRAPPED_CHEST); + containerBlocks.add(Material.DISPENSER); + containerBlocks.add(Material.DROPPER); + containerBlocks.add(Material.HOPPER); + containerBlocks.add(Material.BREWING_STAND); + containerBlocks.add(Material.FURNACE); + containerBlocks.add(Material.BURNING_FURNACE); + containerBlocks.add(Material.BEACON); + // Doesn't actually have a block inventory + // containerBlocks.add(Material.ENDER_CHEST); - private static final BlockFace[] relativeBlockFaces = new BlockFace[] { - BlockFace.EAST, BlockFace.WEST, BlockFace.NORTH, BlockFace.SOUTH, BlockFace.UP, BlockFace.DOWN - }; + // It doesn't seem like you could injure people with some of these, but they exist, so.... + projectileItems = new EnumMap(EntityType.class); + projectileItems.put(EntityType.ARROW, 262); + projectileItems.put(EntityType.EGG, 344); + projectileItems.put(EntityType.ENDER_PEARL, 368); + projectileItems.put(EntityType.SMALL_FIREBALL, 385); // Fire charge + projectileItems.put(EntityType.FIREBALL, 385); // Fire charge + projectileItems.put(EntityType.FISHING_HOOK, 346); + projectileItems.put(EntityType.SNOWBALL, 332); + projectileItems.put(EntityType.SPLASH_POTION, 373); + projectileItems.put(EntityType.THROWN_EXP_BOTTLE, 384); + projectileItems.put(EntityType.WITHER_SKULL, 397); - /** - * Returns a list of block locations around the block that are of the type specified by the integer list parameter - * - * @param block - * @param type - * @return List of block locations around the block that are of the type specified by the integer list parameter - */ - public static List getBlocksNearby(org.bukkit.block.Block block, Set type) { - ArrayList blocks = new ArrayList(); - for (BlockFace blockFace : relativeBlockFaces) { - if (type.contains(block.getRelative(blockFace).getType())) { - blocks.add(block.getRelative(blockFace).getLocation()); - } - } - return blocks; - } + } - public static boolean isTop(Material mat, byte data) { + private static final BlockFace[] relativeBlockFaces = new BlockFace[]{ + BlockFace.EAST, BlockFace.WEST, BlockFace.NORTH, BlockFace.SOUTH, BlockFace.UP, BlockFace.DOWN + }; - switch (mat) { - case DOUBLE_PLANT: - return data > 5; - case IRON_DOOR_BLOCK: - case WOODEN_DOOR: - return data == 8 || data == 9; - default: - return false; - } - } + /** + * Returns a list of block locations around the block that are of the type specified by the integer list parameter + * + * @param block + * @param type + * @return List of block locations around the block that are of the type specified by the integer list parameter + */ + public static List getBlocksNearby(org.bukkit.block.Block block, Set type) { + ArrayList blocks = new ArrayList(); + for (BlockFace blockFace : relativeBlockFaces) { + if (type.contains(block.getRelative(blockFace).getType())) { + blocks.add(block.getRelative(blockFace).getLocation()); + } + } + return blocks; + } - public static int getInventoryHolderType(InventoryHolder holder) { - if (holder instanceof DoubleChest) { - return ((DoubleChest)holder).getLocation().getBlock().getTypeId(); - } else if (holder instanceof BlockState) { - return ((BlockState)holder).getTypeId(); - } else { - return -1; - } - } + public static boolean isTop(Material mat, byte data) { - public static Location getInventoryHolderLocation(InventoryHolder holder) { - if (holder instanceof DoubleChest) { - return ((DoubleChest)holder).getLocation(); - } else if (holder instanceof BlockState) { - return ((BlockState)holder).getLocation(); - } else { - return null; - } - } + switch (mat) { + case DOUBLE_PLANT: + return data > 5; + case IRON_DOOR_BLOCK: + case WOODEN_DOOR: + return data == 8 || data == 9; + default: + return false; + } + } - public static ItemStack[] compareInventories(ItemStack[] items1, ItemStack[] items2) { - final ItemStackComparator comperator = new ItemStackComparator(); - final ArrayList diff = new ArrayList(); - final int l1 = items1.length, l2 = items2.length; - int c1 = 0, c2 = 0; - while (c1 < l1 || c2 < l2) { - if (c1 >= l1) { - diff.add(items2[c2]); - c2++; - continue; - } - if (c2 >= l2) { - items1[c1].setAmount(items1[c1].getAmount() * -1); - diff.add(items1[c1]); - c1++; - continue; - } - final int comp = comperator.compare(items1[c1], items2[c2]); - if (comp < 0) { - items1[c1].setAmount(items1[c1].getAmount() * -1); - diff.add(items1[c1]); - c1++; - } else if (comp > 0) { - diff.add(items2[c2]); - c2++; - } else { - final int amount = items2[c2].getAmount() - items1[c1].getAmount(); - if (amount != 0) { - items1[c1].setAmount(amount); - diff.add(items1[c1]); - } - c1++; - c2++; - } - } - return diff.toArray(new ItemStack[diff.size()]); - } + public static int getInventoryHolderType(InventoryHolder holder) { + if (holder instanceof DoubleChest) { + return ((DoubleChest) holder).getLocation().getBlock().getTypeId(); + } else if (holder instanceof BlockState) { + return ((BlockState) holder).getTypeId(); + } else { + return -1; + } + } - public static ItemStack[] compressInventory(ItemStack[] items) { - final ArrayList compressed = new ArrayList(); - for (final ItemStack item : items) - if (item != null) { - final int type = item.getTypeId(); - final short data = rawData(item); - boolean found = false; - for (final ItemStack item2 : compressed) - if (type == item2.getTypeId() && data == rawData(item2)) { - item2.setAmount(item2.getAmount() + item.getAmount()); - found = true; - break; - } - if (!found) - compressed.add(new ItemStack(type, item.getAmount(), data)); - } - Collections.sort(compressed, new ItemStackComparator()); - return compressed.toArray(new ItemStack[compressed.size()]); - } + public static Location getInventoryHolderLocation(InventoryHolder holder) { + if (holder instanceof DoubleChest) { + return ((DoubleChest) holder).getLocation(); + } else if (holder instanceof BlockState) { + return ((BlockState) holder).getLocation(); + } else { + return null; + } + } - public static boolean equalTypes(int type1, int type2) { - if (type1 == type2) - return true; - for (final Set equivalent : blockEquivalents) - if (equivalent.contains(type1) && equivalent.contains(type2)) - return true; - return false; - } + public static ItemStack[] compareInventories(ItemStack[] items1, ItemStack[] items2) { + final ItemStackComparator comperator = new ItemStackComparator(); + final ArrayList diff = new ArrayList(); + final int l1 = items1.length, l2 = items2.length; + int c1 = 0, c2 = 0; + while (c1 < l1 || c2 < l2) { + if (c1 >= l1) { + diff.add(items2[c2]); + c2++; + continue; + } + if (c2 >= l2) { + items1[c1].setAmount(items1[c1].getAmount() * -1); + diff.add(items1[c1]); + c1++; + continue; + } + final int comp = comperator.compare(items1[c1], items2[c2]); + if (comp < 0) { + items1[c1].setAmount(items1[c1].getAmount() * -1); + diff.add(items1[c1]); + c1++; + } else if (comp > 0) { + diff.add(items2[c2]); + c2++; + } else { + final int amount = items2[c2].getAmount() - items1[c1].getAmount(); + if (amount != 0) { + items1[c1].setAmount(amount); + diff.add(items1[c1]); + } + c1++; + c2++; + } + } + return diff.toArray(new ItemStack[diff.size()]); + } - public static String friendlyWorldname(String worldName) { - return new File(worldName).getName(); - } + public static ItemStack[] compressInventory(ItemStack[] items) { + final ArrayList compressed = new ArrayList(); + for (final ItemStack item : items) { + if (item != null) { + final int type = item.getTypeId(); + final short data = rawData(item); + boolean found = false; + for (final ItemStack item2 : compressed) { + if (type == item2.getTypeId() && data == rawData(item2)) { + item2.setAmount(item2.getAmount() + item.getAmount()); + found = true; + break; + } + } + if (!found) { + compressed.add(new ItemStack(type, item.getAmount(), data)); + } + } + } + Collections.sort(compressed, new ItemStackComparator()); + return compressed.toArray(new ItemStack[compressed.size()]); + } - public static Set> getBlockEquivalents() { - return blockEquivalents; - } + public static boolean equalTypes(int type1, int type2) { + if (type1 == type2) { + return true; + } + for (final Set equivalent : blockEquivalents) { + if (equivalent.contains(type1) && equivalent.contains(type2)) { + return true; + } + } + return false; + } - public static Set getRelativeBreakables() { - return relativeBreakable; - } + public static String friendlyWorldname(String worldName) { + return new File(worldName).getName(); + } - public static Set getRelativeTopBreakabls() { - return relativeTopBreakable; - } + public static Set> getBlockEquivalents() { + return blockEquivalents; + } - public static Set getRelativeTopFallables() { - return relativeTopFallables; - } + public static Set getRelativeBreakables() { + return relativeBreakable; + } - public static Set getFallingEntityKillers() { - return fallingEntityKillers; - } + public static Set getRelativeTopBreakabls() { + return relativeTopBreakable; + } - public static Set getCropBlocks() { - return cropBlocks; - } + public static Set getRelativeTopFallables() { + return relativeTopFallables; + } - public static Set getContainerBlocks() { - return containerBlocks; - } + public static Set getFallingEntityKillers() { + return fallingEntityKillers; + } - public static String entityName(Entity entity) { - if (entity instanceof Player) - return ((Player)entity).getName(); - if (entity instanceof TNTPrimed) - return "TNT"; - return entity.getClass().getSimpleName().substring(5); - } + public static Set getCropBlocks() { + return cropBlocks; + } - public static void giveTool(Player player, int type) { - final Inventory inv = player.getInventory(); - if (inv.contains(type)) - player.sendMessage(ChatColor.RED + "You have already a " + materialName(type)); - else { - final int free = inv.firstEmpty(); - if (free >= 0) { - if (player.getItemInHand() != null && player.getItemInHand().getTypeId() != 0) - inv.setItem(free, player.getItemInHand()); - player.setItemInHand(new ItemStack(type, 1)); - player.sendMessage(ChatColor.GREEN + "Here's your " + materialName(type)); - } else - player.sendMessage(ChatColor.RED + "You have no empty slot in your inventory"); - } - } + public static Set getContainerBlocks() { + return containerBlocks; + } - public static short rawData(ItemStack item) { - return item.getType() != null ? item.getData() != null ? item.getDurability() : 0 : 0; - } + public static String entityName(Entity entity) { + if (entity instanceof Player) { + return ((Player) entity).getName(); + } + if (entity instanceof TNTPrimed) { + return "TNT"; + } + return entity.getClass().getSimpleName().substring(5); + } - public static int saveSpawnHeight(Location loc) { - final World world = loc.getWorld(); - final Chunk chunk = world.getChunkAt(loc); - if (!world.isChunkLoaded(chunk)) - world.loadChunk(chunk); - final int x = loc.getBlockX(), z = loc.getBlockZ(); - int y = loc.getBlockY(); - boolean lower = world.getBlockTypeIdAt(x, y, z) == 0, upper = world.getBlockTypeIdAt(x, y + 1, z) == 0; - while ((!lower || !upper) && y != 127) { - lower = upper; - upper = world.getBlockTypeIdAt(x, ++y, z) == 0; - } - while (world.getBlockTypeIdAt(x, y - 1, z) == 0 && y != 0) - y--; - return y; - } + public static void giveTool(Player player, int type) { + final Inventory inv = player.getInventory(); + if (inv.contains(type)) { + player.sendMessage(ChatColor.RED + "You have already a " + materialName(type)); + } else { + final int free = inv.firstEmpty(); + if (free >= 0) { + if (player.getItemInHand() != null && player.getItemInHand().getTypeId() != 0) { + inv.setItem(free, player.getItemInHand()); + } + player.setItemInHand(new ItemStack(type, 1)); + player.sendMessage(ChatColor.GREEN + "Here's your " + materialName(type)); + } else { + player.sendMessage(ChatColor.RED + "You have no empty slot in your inventory"); + } + } + } - public static int modifyContainer(BlockState b, ItemStack item) { - if (b instanceof InventoryHolder) { - final Inventory inv = ((InventoryHolder)b).getInventory(); - if (item.getAmount() < 0) { - item.setAmount(-item.getAmount()); - final ItemStack tmp = inv.removeItem(item).get(0); - return tmp != null ? tmp.getAmount() : 0; - } else if (item.getAmount() > 0) { - final ItemStack tmp = inv.addItem(item).get(0); - return tmp != null ? tmp.getAmount() : 0; - } - } - return 0; - } + public static short rawData(ItemStack item) { + return item.getType() != null ? item.getData() != null ? item.getDurability() : 0 : 0; + } - public static boolean canFall(World world, int x, int y, int z) { - Material mat = world.getBlockAt(x, y, z).getType(); + public static int saveSpawnHeight(Location loc) { + final World world = loc.getWorld(); + final Chunk chunk = world.getChunkAt(loc); + if (!world.isChunkLoaded(chunk)) { + world.loadChunk(chunk); + } + final int x = loc.getBlockX(), z = loc.getBlockZ(); + int y = loc.getBlockY(); + boolean lower = world.getBlockTypeIdAt(x, y, z) == 0, upper = world.getBlockTypeIdAt(x, y + 1, z) == 0; + while ((!lower || !upper) && y != 127) { + lower = upper; + upper = world.getBlockTypeIdAt(x, ++y, z) == 0; + } + while (world.getBlockTypeIdAt(x, y - 1, z) == 0 && y != 0) { + y--; + } + return y; + } - // Air - if (mat == Material.AIR) { - return true; - } else if (mat == Material.WATER || mat == Material.STATIONARY_WATER || mat == Material.LAVA || mat == Material.STATIONARY_LAVA) { // Fluids - return true; - } else if (getFallingEntityKillers().contains(mat) || mat == Material.FIRE || mat == Material.VINE || mat == Material.LONG_GRASS || mat == Material.DEAD_BUSH) { // Misc. - return true; - } - return false; - } + public static int modifyContainer(BlockState b, ItemStack item) { + if (b instanceof InventoryHolder) { + final Inventory inv = ((InventoryHolder) b).getInventory(); + if (item.getAmount() < 0) { + item.setAmount(-item.getAmount()); + final ItemStack tmp = inv.removeItem(item).get(0); + return tmp != null ? tmp.getAmount() : 0; + } else if (item.getAmount() > 0) { + final ItemStack tmp = inv.addItem(item).get(0); + return tmp != null ? tmp.getAmount() : 0; + } + } + return 0; + } - public static class ItemStackComparator implements Comparator - { - @Override - public int compare(ItemStack a, ItemStack b) { - final int aType = a.getTypeId(), bType = b.getTypeId(); - if (aType < bType) - return -1; - if (aType > bType) - return 1; - final short aData = rawData(a), bData = rawData(b); - if (aData < bData) - return -1; - if (aData > bData) - return 1; - return 0; - } - } + public static boolean canFall(World world, int x, int y, int z) { + Material mat = world.getBlockAt(x, y, z).getType(); - public static int itemIDfromProjectileEntity(Entity e) { - Integer i = projectileItems.get(e.getType()); - return (i == null) ? 0 : i; - } + // Air + if (mat == Material.AIR) { + return true; + } else if (mat == Material.WATER || mat == Material.STATIONARY_WATER || mat == Material.LAVA || mat == Material.STATIONARY_LAVA) { // Fluids + return true; + } else if (getFallingEntityKillers().contains(mat) || mat == Material.FIRE || mat == Material.VINE || mat == Material.LONG_GRASS || mat == Material.DEAD_BUSH) { // Misc. + return true; + } + return false; + } + + public static class ItemStackComparator implements Comparator { + @Override + public int compare(ItemStack a, ItemStack b) { + final int aType = a.getTypeId(), bType = b.getTypeId(); + if (aType < bType) { + return -1; + } + if (aType > bType) { + return 1; + } + final short aData = rawData(a), bData = rawData(b); + if (aData < bData) { + return -1; + } + if (aData > bData) { + return 1; + } + return 0; + } + } + + public static int itemIDfromProjectileEntity(Entity e) { + Integer i = projectileItems.get(e.getType()); + return (i == null) ? 0 : i; + } } diff --git a/src/main/java/de/diddiz/util/LoggingUtil.java b/src/main/java/de/diddiz/util/LoggingUtil.java index 0b4d67a..51a0e44 100644 --- a/src/main/java/de/diddiz/util/LoggingUtil.java +++ b/src/main/java/de/diddiz/util/LoggingUtil.java @@ -3,208 +3,212 @@ package de.diddiz.util; import de.diddiz.LogBlock.Actor; import de.diddiz.LogBlock.Consumer; import de.diddiz.LogBlock.Logging; -import static de.diddiz.LogBlock.config.Config.getWorldConfig; -import static de.diddiz.LogBlock.config.Config.mb4; import de.diddiz.LogBlock.config.WorldConfig; -import java.util.List; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.block.Block; import org.bukkit.block.BlockFace; import org.bukkit.block.BlockState; import org.bukkit.block.Sign; -import org.bukkit.material.Button; -import org.bukkit.material.CocoaPlant; -import org.bukkit.material.Ladder; -import org.bukkit.material.Lever; -import org.bukkit.material.MaterialData; -import org.bukkit.material.RedstoneTorch; -import org.bukkit.material.Torch; -import org.bukkit.material.TrapDoor; -import org.bukkit.material.TripwireHook; +import org.bukkit.material.*; + +import java.util.List; + +import static de.diddiz.LogBlock.config.Config.getWorldConfig; +import static de.diddiz.LogBlock.config.Config.mb4; public class LoggingUtil { - public static void smartLogFallables(Consumer consumer, Actor actor, Block origin) { + public static void smartLogFallables(Consumer consumer, Actor actor, Block origin) { - WorldConfig wcfg = getWorldConfig(origin.getWorld()); - if (wcfg == null) return; + WorldConfig wcfg = getWorldConfig(origin.getWorld()); + if (wcfg == null) { + return; + } - //Handle falling blocks - Block checkBlock = origin.getRelative(BlockFace.UP); - int up = 0; - final int highestBlock = checkBlock.getWorld().getHighestBlockYAt(checkBlock.getLocation()); - while (BukkitUtils.getRelativeTopFallables().contains(checkBlock.getType())) { + //Handle falling blocks + Block checkBlock = origin.getRelative(BlockFace.UP); + int up = 0; + final int highestBlock = checkBlock.getWorld().getHighestBlockYAt(checkBlock.getLocation()); + while (BukkitUtils.getRelativeTopFallables().contains(checkBlock.getType())) { - // Record this block as falling - consumer.queueBlockBreak(actor, checkBlock.getState()); + // Record this block as falling + consumer.queueBlockBreak(actor, checkBlock.getState()); - // Guess where the block is going (This could be thrown of by explosions, but it is better than nothing) - Location loc = origin.getLocation(); - int x = loc.getBlockX(); - int y = loc.getBlockY(); - int z = loc.getBlockZ(); - while (y > 0 && BukkitUtils.canFall(loc.getWorld(), x, (y - 1), z)) { - y--; - } - // If y is 0 then the sand block fell out of the world :( - if (y != 0) { - Location finalLoc = new Location(loc.getWorld(), x, y, z); - // Run this check to avoid false positives - if (!BukkitUtils.getFallingEntityKillers().contains(finalLoc.getBlock().getType())) { - finalLoc.add(0, up, 0); // Add this here after checking for block breakers - if (finalLoc.getBlock().getType() == Material.AIR || BukkitUtils.getRelativeTopFallables().contains(finalLoc.getBlock().getType())) { - consumer.queueBlockPlace(actor, finalLoc, checkBlock.getTypeId(), checkBlock.getData()); - } else { - consumer.queueBlockReplace(actor, finalLoc, finalLoc.getBlock().getTypeId(), finalLoc.getBlock().getData(), checkBlock.getTypeId(), checkBlock.getData()); - } - up++; - } - } - if (checkBlock.getY() >= highestBlock) break; - checkBlock = checkBlock.getRelative(BlockFace.UP); - } - } + // Guess where the block is going (This could be thrown of by explosions, but it is better than nothing) + Location loc = origin.getLocation(); + int x = loc.getBlockX(); + int y = loc.getBlockY(); + int z = loc.getBlockZ(); + while (y > 0 && BukkitUtils.canFall(loc.getWorld(), x, (y - 1), z)) { + y--; + } + // If y is 0 then the sand block fell out of the world :( + if (y != 0) { + Location finalLoc = new Location(loc.getWorld(), x, y, z); + // Run this check to avoid false positives + if (!BukkitUtils.getFallingEntityKillers().contains(finalLoc.getBlock().getType())) { + finalLoc.add(0, up, 0); // Add this here after checking for block breakers + if (finalLoc.getBlock().getType() == Material.AIR || BukkitUtils.getRelativeTopFallables().contains(finalLoc.getBlock().getType())) { + consumer.queueBlockPlace(actor, finalLoc, checkBlock.getTypeId(), checkBlock.getData()); + } else { + consumer.queueBlockReplace(actor, finalLoc, finalLoc.getBlock().getTypeId(), finalLoc.getBlock().getData(), checkBlock.getTypeId(), checkBlock.getData()); + } + up++; + } + } + if (checkBlock.getY() >= highestBlock) { + break; + } + checkBlock = checkBlock.getRelative(BlockFace.UP); + } + } - public static void smartLogBlockBreak(Consumer consumer, Actor actor, Block origin) { + public static void smartLogBlockBreak(Consumer consumer, Actor actor, Block origin) { - WorldConfig wcfg = getWorldConfig(origin.getWorld()); - if (wcfg == null) return; + WorldConfig wcfg = getWorldConfig(origin.getWorld()); + if (wcfg == null) { + return; + } - Block checkBlock = origin.getRelative(BlockFace.UP); - if (BukkitUtils.getRelativeTopBreakabls().contains(checkBlock.getType())) { - if (wcfg.isLogging(Logging.SIGNTEXT) && checkBlock.getType() == Material.SIGN_POST) { - consumer.queueSignBreak(actor, (Sign) checkBlock.getState()); - } else if (checkBlock.getType() == Material.IRON_DOOR_BLOCK || checkBlock.getType() == Material.WOODEN_DOOR) { - Block doorBlock = checkBlock; - // If the doorBlock is the top half a door the player simply punched a door - // this will be handled later. - if (!BukkitUtils.isTop(doorBlock.getType(), doorBlock.getData())) { - doorBlock = doorBlock.getRelative(BlockFace.UP); - // Fall back check just in case the top half wasn't a door - if (doorBlock.getType() == Material.IRON_DOOR_BLOCK || doorBlock.getType() == Material.WOODEN_DOOR) { - consumer.queueBlockBreak(actor, doorBlock.getState()); - } - consumer.queueBlockBreak(actor, checkBlock.getState()); - } - } else if (checkBlock.getType() == Material.DOUBLE_PLANT) { - Block plantBlock = checkBlock; - // If the plantBlock is the top half of a double plant the player simply - // punched the plant this will be handled later. - if (!BukkitUtils.isTop(plantBlock.getType(), plantBlock.getData())) { - plantBlock = plantBlock.getRelative(BlockFace.UP); - // Fall back check just in case the top half wasn't a plant - if (plantBlock.getType() == Material.DOUBLE_PLANT) { - consumer.queueBlockBreak(actor, plantBlock.getState()); - } - consumer.queueBlockBreak(actor, checkBlock.getState()); - } - } else { - consumer.queueBlockBreak(actor, checkBlock.getState()); - } - } + Block checkBlock = origin.getRelative(BlockFace.UP); + if (BukkitUtils.getRelativeTopBreakabls().contains(checkBlock.getType())) { + if (wcfg.isLogging(Logging.SIGNTEXT) && checkBlock.getType() == Material.SIGN_POST) { + consumer.queueSignBreak(actor, (Sign) checkBlock.getState()); + } else if (checkBlock.getType() == Material.IRON_DOOR_BLOCK || checkBlock.getType() == Material.WOODEN_DOOR) { + Block doorBlock = checkBlock; + // If the doorBlock is the top half a door the player simply punched a door + // this will be handled later. + if (!BukkitUtils.isTop(doorBlock.getType(), doorBlock.getData())) { + doorBlock = doorBlock.getRelative(BlockFace.UP); + // Fall back check just in case the top half wasn't a door + if (doorBlock.getType() == Material.IRON_DOOR_BLOCK || doorBlock.getType() == Material.WOODEN_DOOR) { + consumer.queueBlockBreak(actor, doorBlock.getState()); + } + consumer.queueBlockBreak(actor, checkBlock.getState()); + } + } else if (checkBlock.getType() == Material.DOUBLE_PLANT) { + Block plantBlock = checkBlock; + // If the plantBlock is the top half of a double plant the player simply + // punched the plant this will be handled later. + if (!BukkitUtils.isTop(plantBlock.getType(), plantBlock.getData())) { + plantBlock = plantBlock.getRelative(BlockFace.UP); + // Fall back check just in case the top half wasn't a plant + if (plantBlock.getType() == Material.DOUBLE_PLANT) { + consumer.queueBlockBreak(actor, plantBlock.getState()); + } + consumer.queueBlockBreak(actor, checkBlock.getState()); + } + } else { + consumer.queueBlockBreak(actor, checkBlock.getState()); + } + } - List relativeBreakables = BukkitUtils.getBlocksNearby(origin, BukkitUtils.getRelativeBreakables()); - if (relativeBreakables.size() != 0) { - for (Location location : relativeBreakables) { - final Material blockType = location.getBlock().getType(); - final BlockState blockState = location.getBlock().getState(); - final MaterialData data = blockState.getData(); - switch (blockType) { - case REDSTONE_TORCH_ON: - case REDSTONE_TORCH_OFF: - if (blockState.getBlock().getRelative(((RedstoneTorch) data).getAttachedFace()).equals(origin)) { - consumer.queueBlockBreak(actor, blockState); - } - break; - case TORCH: - if (blockState.getBlock().getRelative(((Torch) data).getAttachedFace()).equals(origin)) { - consumer.queueBlockBreak(actor, blockState); - } - break; - case COCOA: - if (blockState.getBlock().getRelative(((CocoaPlant) data).getAttachedFace().getOppositeFace()).equals(origin)) { - consumer.queueBlockBreak(actor, blockState); - } - break; - case LADDER: - if (blockState.getBlock().getRelative(((Ladder) data).getAttachedFace()).equals(origin)) { - consumer.queueBlockBreak(actor, blockState); - } - break; - case LEVER: - if (blockState.getBlock().getRelative(((Lever) data).getAttachedFace()).equals(origin)) { - consumer.queueBlockBreak(actor, blockState); - } - break; - case TRIPWIRE_HOOK: - if (blockState.getBlock().getRelative(((TripwireHook) data).getAttachedFace()).equals(origin)) { - consumer.queueBlockBreak(actor, blockState); - } - break; - case WOOD_BUTTON: - case STONE_BUTTON: - if (blockState.getBlock().getRelative(((Button) data).getAttachedFace()).equals(origin)) { - consumer.queueBlockBreak(actor, blockState); - } - break; - case WALL_SIGN: - if (blockState.getBlock().getRelative(((org.bukkit.material.Sign) data).getAttachedFace()).equals(origin)) { - if (wcfg.isLogging(Logging.SIGNTEXT)) { - consumer.queueSignBreak(actor, (Sign) blockState); - } else { - consumer.queueBlockBreak(actor, blockState); - } - } - break; - case TRAP_DOOR: - if (blockState.getBlock().getRelative(((TrapDoor) data).getAttachedFace()).equals(origin)) { - consumer.queueBlockBreak(actor, blockState); - } - break; - default: - consumer.queueBlockBreak(actor, blockState); - break; - } - } - } + List relativeBreakables = BukkitUtils.getBlocksNearby(origin, BukkitUtils.getRelativeBreakables()); + if (relativeBreakables.size() != 0) { + for (Location location : relativeBreakables) { + final Material blockType = location.getBlock().getType(); + final BlockState blockState = location.getBlock().getState(); + final MaterialData data = blockState.getData(); + switch (blockType) { + case REDSTONE_TORCH_ON: + case REDSTONE_TORCH_OFF: + if (blockState.getBlock().getRelative(((RedstoneTorch) data).getAttachedFace()).equals(origin)) { + consumer.queueBlockBreak(actor, blockState); + } + break; + case TORCH: + if (blockState.getBlock().getRelative(((Torch) data).getAttachedFace()).equals(origin)) { + consumer.queueBlockBreak(actor, blockState); + } + break; + case COCOA: + if (blockState.getBlock().getRelative(((CocoaPlant) data).getAttachedFace().getOppositeFace()).equals(origin)) { + consumer.queueBlockBreak(actor, blockState); + } + break; + case LADDER: + if (blockState.getBlock().getRelative(((Ladder) data).getAttachedFace()).equals(origin)) { + consumer.queueBlockBreak(actor, blockState); + } + break; + case LEVER: + if (blockState.getBlock().getRelative(((Lever) data).getAttachedFace()).equals(origin)) { + consumer.queueBlockBreak(actor, blockState); + } + break; + case TRIPWIRE_HOOK: + if (blockState.getBlock().getRelative(((TripwireHook) data).getAttachedFace()).equals(origin)) { + consumer.queueBlockBreak(actor, blockState); + } + break; + case WOOD_BUTTON: + case STONE_BUTTON: + if (blockState.getBlock().getRelative(((Button) data).getAttachedFace()).equals(origin)) { + consumer.queueBlockBreak(actor, blockState); + } + break; + case WALL_SIGN: + if (blockState.getBlock().getRelative(((org.bukkit.material.Sign) data).getAttachedFace()).equals(origin)) { + if (wcfg.isLogging(Logging.SIGNTEXT)) { + consumer.queueSignBreak(actor, (Sign) blockState); + } else { + consumer.queueBlockBreak(actor, blockState); + } + } + break; + case TRAP_DOOR: + if (blockState.getBlock().getRelative(((TrapDoor) data).getAttachedFace()).equals(origin)) { + consumer.queueBlockBreak(actor, blockState); + } + break; + default: + consumer.queueBlockBreak(actor, blockState); + break; + } + } + } - // Special door check - if (origin.getType() == Material.IRON_DOOR_BLOCK || origin.getType() == Material.WOODEN_DOOR) { - Block doorBlock = origin; + // Special door check + if (origin.getType() == Material.IRON_DOOR_BLOCK || origin.getType() == Material.WOODEN_DOOR) { + Block doorBlock = origin; - // Up or down? - if (!BukkitUtils.isTop(doorBlock.getType(), doorBlock.getData())) { - doorBlock = doorBlock.getRelative(BlockFace.UP); - } else { - doorBlock = doorBlock.getRelative(BlockFace.DOWN); - } + // Up or down? + if (!BukkitUtils.isTop(doorBlock.getType(), doorBlock.getData())) { + doorBlock = doorBlock.getRelative(BlockFace.UP); + } else { + doorBlock = doorBlock.getRelative(BlockFace.DOWN); + } - if (doorBlock.getType() == Material.IRON_DOOR_BLOCK || doorBlock.getType() == Material.WOODEN_DOOR) { - consumer.queueBlockBreak(actor, doorBlock.getState()); - } - } else if (origin.getType() == Material.DOUBLE_PLANT) { // Special double plant check - Block plantBlock = origin; + if (doorBlock.getType() == Material.IRON_DOOR_BLOCK || doorBlock.getType() == Material.WOODEN_DOOR) { + consumer.queueBlockBreak(actor, doorBlock.getState()); + } + } else if (origin.getType() == Material.DOUBLE_PLANT) { // Special double plant check + Block plantBlock = origin; - // Up or down? - if (!BukkitUtils.isTop(origin.getType(), origin.getData())) { - plantBlock = plantBlock.getRelative(BlockFace.UP); - } else { - plantBlock = plantBlock.getRelative(BlockFace.DOWN); - } + // Up or down? + if (!BukkitUtils.isTop(origin.getType(), origin.getData())) { + plantBlock = plantBlock.getRelative(BlockFace.UP); + } else { + plantBlock = plantBlock.getRelative(BlockFace.DOWN); + } - if (plantBlock.getType() == Material.DOUBLE_PLANT) { - consumer.queueBlockBreak(actor, plantBlock.getState()); - } - } + if (plantBlock.getType() == Material.DOUBLE_PLANT) { + consumer.queueBlockBreak(actor, plantBlock.getState()); + } + } - // Do this down here so that the block is added after blocks sitting on it - consumer.queueBlockBreak(actor, origin.getState()); - } - - public static String checkText(String text) { - if (text==null) return text; - if (mb4) return text; - return text.replaceAll("[^\\u0000-\\uFFFF]", "?"); - } + // Do this down here so that the block is added after blocks sitting on it + consumer.queueBlockBreak(actor, origin.getState()); + } + + public static String checkText(String text) { + if (text == null) { + return text; + } + if (mb4) { + return text; + } + return text.replaceAll("[^\\u0000-\\uFFFF]", "?"); + } } diff --git a/src/main/java/de/diddiz/util/MaterialName.java b/src/main/java/de/diddiz/util/MaterialName.java index 2be9310..5ef543f 100644 --- a/src/main/java/de/diddiz/util/MaterialName.java +++ b/src/main/java/de/diddiz/util/MaterialName.java @@ -1,258 +1,270 @@ package de.diddiz.util; -import static de.diddiz.util.Utils.isInt; -import static de.diddiz.util.Utils.isShort; -import static org.bukkit.Bukkit.getLogger; -import java.io.File; -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; -import java.util.logging.Level; import org.bukkit.Material; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.material.MaterialData; -public class MaterialName -{ - private static final String[] COLORS = {"white","orange","magenta","light blue","yellow","lime","pink","gray","silver","cyan","purple","blue","brown","green","red","black"}; - private static final Map materialNames = new HashMap(); - private static final Map> materialDataNames = new HashMap>(); - private static final Map nameTypes = new HashMap(); +import java.io.File; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.logging.Level; - static { - // Add all known materials - for (final Material mat : Material.values()) - materialNames.put(mat.getId(), mat.toString().replace('_', ' ').toLowerCase()); - // Load config - final File file = new File("plugins/LogBlock/materials.yml"); - final YamlConfiguration cfg = YamlConfiguration.loadConfiguration(file); - if (cfg.getKeys(false).isEmpty()) { - // Generate defaults - cfg.options().header("Add block or item names you want to be overridden or also names for custom blocks"); - cfg.set("1.1", "granite"); - cfg.set("1.2", "polished granite"); - cfg.set("1.3", "diorite"); - cfg.set("1.4", "polished diorite"); - cfg.set("1.5", "andesite"); - cfg.set("1.6", "polished andesite"); - cfg.set("5.0", "oak wood"); - cfg.set("5.1", "spruce wood"); - cfg.set("5.2", "birch wood"); - cfg.set("5.3", "jungle wood"); - cfg.set("5.4", "acacia wood"); - cfg.set("5.5", "dark oak wood"); - cfg.set("3.1", "coarse dirt"); - cfg.set("3.2", "podzol"); - cfg.set("6.1", "redwood sapling"); - cfg.set("6.2", "birch sapling"); - cfg.set("6.3", "jungle sapling"); - cfg.set("6.4", "acacia sapling"); - cfg.set("6.5", "dark oak sapling"); - cfg.set("9", "water"); - cfg.set("11", "lava"); - cfg.set("12.1", "red sand"); - cfg.set("17.0", "oak log"); - cfg.set("17.1", "spruce log"); - cfg.set("17.2", "birch log"); - cfg.set("17.3", "jungle log"); - cfg.set("17.4", "oak log"); - cfg.set("17.5", "spruce log"); - cfg.set("17.6", "birch log"); - cfg.set("17.7", "jungle log"); - cfg.set("17.8", "oak log"); - cfg.set("17.9", "spruce log"); - cfg.set("17.10", "birch log"); - cfg.set("17.11", "jungle log"); - cfg.set("17.12", "oak log"); - cfg.set("17.13", "spruce log"); - cfg.set("17.14", "birch log"); - cfg.set("17.15", "jungle log"); - cfg.set("18.1", "spruce leaves"); - cfg.set("18.2", "birch leaves"); - cfg.set("18.3", "jungle leaves"); - cfg.set("18.4", "oak leaves"); - cfg.set("18.5", "spruce leaves"); - cfg.set("18.6", "birch leaves"); - cfg.set("18.7", "jungle leaves"); - cfg.set("18.8", "oak leaves"); - cfg.set("18.9", "spruce leaves"); - cfg.set("18.10", "birch leaves"); - cfg.set("18.11", "jungle leaves"); - cfg.set("18.12", "oak leaves"); - cfg.set("18.13", "spruce leaves"); - cfg.set("18.14", "birch leaves"); - cfg.set("18.15", "jungle leaves"); - cfg.set("19.1", "wet sponge"); - cfg.set("37.0", "dandelion"); - cfg.set("38.0", "poppy"); - cfg.set("38.1", "blue orchid"); - cfg.set("38.2", "allium"); - cfg.set("38.3", "azure bluet"); - cfg.set("38.4", "red tulip"); - cfg.set("38.5", "orange tulip"); - cfg.set("38.6", "white tulip"); - cfg.set("38.7", "pink tulip"); - cfg.set("38.8", "oxeye daisy"); - cfg.set("24.1", "chiseled sandstone"); - cfg.set("24.2", "smooth sandstone"); - cfg.set("31.0", "dead bush"); - cfg.set("31.1", "tall grass"); - cfg.set("31.2", "fern"); - cfg.set("98.0", "stone brick"); - cfg.set("98.1", "mossy stone brick"); - cfg.set("98.2", "cracked stone brick"); - cfg.set("98.3", "chiseled stone brick"); - cfg.set("125.0","oak double step"); - cfg.set("125.1","spruce double step"); - cfg.set("125.2","birch double step"); - cfg.set("125.3","jungle double step"); - cfg.set("125.4","acacia double step"); - cfg.set("125.5","dark oak double step"); - cfg.set("126.0", "oak step"); - cfg.set("126.1", "spruce step"); - cfg.set("126.2", "birch step"); - cfg.set("126.3", "jungle step"); - cfg.set("126.4", "acacia step"); - cfg.set("126.5", "dark oak step"); - cfg.set("126.8", "oak step"); - cfg.set("126.9", "spruce step"); - cfg.set("126.10", "birch step"); - cfg.set("126.11", "jungle step"); - cfg.set("126.12", "acacia step"); - cfg.set("126.13", "dark oak step"); - cfg.set("139.1", "mossy cobble wall"); - cfg.set("155.1", "chiseled quartz block"); - cfg.set("155.2", "pillar quartz block"); - cfg.set("155.3", "pillar quartz block"); - cfg.set("155.4", "pillar quartz block"); - cfg.set("161.0", "acacia leaves"); - cfg.set("161.1", "dark oak leaves"); - cfg.set("161.4", "acacia leaves"); - cfg.set("161.5", "dark oak leaves"); - cfg.set("161.8", "acacia leaves"); - cfg.set("161.9", "dark oak leaves"); - cfg.set("161.12", "acacia leaves"); - cfg.set("161.13", "dark oak leaves"); - cfg.set("162.0", "acacia log"); - cfg.set("162.1", "dark oak log"); - cfg.set("162.4", "acacia log"); - cfg.set("162.5", "dark oak log"); - cfg.set("162.8", "acacia log"); - cfg.set("162.9", "dark oak log"); - cfg.set("162.12", "acacia log"); - cfg.set("162.13", "dark oak log"); - cfg.set("168.1", "prismarine brick"); - cfg.set("168.2", "dark prismarine"); - cfg.set("181.0", "red sandstone double step"); - cfg.set("181.8", "smooth red sandstone double step"); - cfg.set("162.13", "dark oak log"); - cfg.set("175.0", "sunflower"); - cfg.set("175.1", "lilac"); - cfg.set("175.2", "double tall grass"); - cfg.set("175.3", "large fern"); - cfg.set("175.4", "rose bush"); - cfg.set("175.5", "peony"); - cfg.set("175.8", "sunflower"); - cfg.set("175.9", "lilac"); - cfg.set("175.10", "double tall grass"); - cfg.set("175.11", "large fern"); - cfg.set("175.12", "rose bush"); - cfg.set("175.13", "peony"); - cfg.set("179.1", "chiseled sandstone"); - cfg.set("179.2", "smooth sandstone"); - cfg.set("263.1", "charcoal"); - for (byte i = 0; i < 10; i++) { - cfg.set("43." + i, toReadable(Material.DOUBLE_STEP.getNewData(i))); - } - cfg.set("43.8", "stone double step"); - cfg.set("43.9", "sandstone double step"); - cfg.set("43.15", "quartz double step"); - for (byte i = 0; i < 8; i++) { - cfg.set("44." + i, toReadable(Material.STEP.getNewData(i))); - // The second half of this data list should read the same as the first half - cfg.set("44." + (i+7), toReadable(Material.STEP.getNewData(i))); - } - for (byte i = 0; i < 16; i++) { - cfg.set("351." + i, toReadable(Material.INK_SACK.getNewData(i))); - cfg.set("35." + i, COLORS[i] + " wool"); - cfg.set("159." + i, COLORS[i] + " stained clay"); - cfg.set("95." + i, COLORS[i] + " stained glass"); - cfg.set("160." + i, COLORS[i] + " stained glass pane"); - cfg.set("171." + i, COLORS[i] + " carpet"); - } - for (byte i = 0; i < 6; i++) { - cfg.set("125." + i, toReadable(Material.WOOD_DOUBLE_STEP.getNewData(i))); - cfg.set("126." + i, toReadable(Material.WOOD_STEP.getNewData(i))); - cfg.set("126." + i+8, toReadable(Material.WOOD_STEP.getNewData(i))); - } - try { - cfg.save(file); - } catch (final IOException ex) { - getLogger().log(Level.WARNING, "Unable to save material.yml: ", ex); - } - } - if (cfg.getString("263.1") == null) { - getLogger().info("[Logblock-names] Logblock's default materials.yml file has been updated with more names"); - getLogger().info("[Logblock-names] Consider deleting your current materials.yml file to allow it to be recreated"); - } - for (final String entry : cfg.getKeys(false)) - if (isInt(entry)) { - if (cfg.isString(entry)) { - materialNames.put(Integer.valueOf(entry), cfg.getString(entry)); - nameTypes.put(cfg.getString(entry), Integer.valueOf(entry)); - } - else if (cfg.isConfigurationSection(entry)) { - final Map dataNames = new HashMap(); - materialDataNames.put(Integer.valueOf(entry), dataNames); - final ConfigurationSection sec = cfg.getConfigurationSection(entry); - for (final String data : sec.getKeys(false)) - if (isShort(data)) { - if (sec.isString(data)) { - dataNames.put(Short.valueOf(data), sec.getString(data)); - nameTypes.put(sec.getString(data), Integer.valueOf(entry)); - } - else - getLogger().warning("Parsing materials.yml: '" + data + "' is not a string."); - } else - getLogger().warning("Parsing materials.yml: '" + data + "' is no valid material data"); - } else - getLogger().warning("Parsing materials.yml: '" + entry + "' is neither a string nor a section."); - } else - getLogger().warning("Parsing materials.yml: '" + entry + "' is no valid material id"); - } +import static de.diddiz.util.Utils.isInt; +import static de.diddiz.util.Utils.isShort; +import static org.bukkit.Bukkit.getLogger; - /** - * @return Name of the material, or if it's unknown, the id. - */ - public static String materialName(int type) { - return materialNames.containsKey(type) ? materialNames.get(type) : String.valueOf(type); - } +public class MaterialName { + private static final String[] COLORS = {"white", "orange", "magenta", "light blue", "yellow", "lime", "pink", "gray", "silver", "cyan", "purple", "blue", "brown", "green", "red", "black"}; + private static final Map materialNames = new HashMap(); + private static final Map> materialDataNames = new HashMap>(); + private static final Map nameTypes = new HashMap(); - /** - * @return Name of the material regarding it's data, or if it's unknown, the basic name. - */ - public static String materialName(int type, short data) { - final Map dataNames = materialDataNames.get(type); - if (dataNames != null) - if (dataNames.containsKey(data)) - return dataNames.get(data); - return materialName(type); - } - - public static Integer typeFromName(String name) { - Integer answer = nameTypes.get(toReadable(name)); - if (answer != null) return answer; - final Material mat = Material.matchMaterial(name); - if (mat == null) throw new IllegalArgumentException("No material matching: '" + name + "'"); - return mat.getId(); - } + static { + // Add all known materials + for (final Material mat : Material.values()) { + materialNames.put(mat.getId(), mat.toString().replace('_', ' ').toLowerCase()); + } + // Load config + final File file = new File("plugins/LogBlock/materials.yml"); + final YamlConfiguration cfg = YamlConfiguration.loadConfiguration(file); + if (cfg.getKeys(false).isEmpty()) { + // Generate defaults + cfg.options().header("Add block or item names you want to be overridden or also names for custom blocks"); + cfg.set("1.1", "granite"); + cfg.set("1.2", "polished granite"); + cfg.set("1.3", "diorite"); + cfg.set("1.4", "polished diorite"); + cfg.set("1.5", "andesite"); + cfg.set("1.6", "polished andesite"); + cfg.set("5.0", "oak wood"); + cfg.set("5.1", "spruce wood"); + cfg.set("5.2", "birch wood"); + cfg.set("5.3", "jungle wood"); + cfg.set("5.4", "acacia wood"); + cfg.set("5.5", "dark oak wood"); + cfg.set("3.1", "coarse dirt"); + cfg.set("3.2", "podzol"); + cfg.set("6.1", "redwood sapling"); + cfg.set("6.2", "birch sapling"); + cfg.set("6.3", "jungle sapling"); + cfg.set("6.4", "acacia sapling"); + cfg.set("6.5", "dark oak sapling"); + cfg.set("9", "water"); + cfg.set("11", "lava"); + cfg.set("12.1", "red sand"); + cfg.set("17.0", "oak log"); + cfg.set("17.1", "spruce log"); + cfg.set("17.2", "birch log"); + cfg.set("17.3", "jungle log"); + cfg.set("17.4", "oak log"); + cfg.set("17.5", "spruce log"); + cfg.set("17.6", "birch log"); + cfg.set("17.7", "jungle log"); + cfg.set("17.8", "oak log"); + cfg.set("17.9", "spruce log"); + cfg.set("17.10", "birch log"); + cfg.set("17.11", "jungle log"); + cfg.set("17.12", "oak log"); + cfg.set("17.13", "spruce log"); + cfg.set("17.14", "birch log"); + cfg.set("17.15", "jungle log"); + cfg.set("18.1", "spruce leaves"); + cfg.set("18.2", "birch leaves"); + cfg.set("18.3", "jungle leaves"); + cfg.set("18.4", "oak leaves"); + cfg.set("18.5", "spruce leaves"); + cfg.set("18.6", "birch leaves"); + cfg.set("18.7", "jungle leaves"); + cfg.set("18.8", "oak leaves"); + cfg.set("18.9", "spruce leaves"); + cfg.set("18.10", "birch leaves"); + cfg.set("18.11", "jungle leaves"); + cfg.set("18.12", "oak leaves"); + cfg.set("18.13", "spruce leaves"); + cfg.set("18.14", "birch leaves"); + cfg.set("18.15", "jungle leaves"); + cfg.set("19.1", "wet sponge"); + cfg.set("37.0", "dandelion"); + cfg.set("38.0", "poppy"); + cfg.set("38.1", "blue orchid"); + cfg.set("38.2", "allium"); + cfg.set("38.3", "azure bluet"); + cfg.set("38.4", "red tulip"); + cfg.set("38.5", "orange tulip"); + cfg.set("38.6", "white tulip"); + cfg.set("38.7", "pink tulip"); + cfg.set("38.8", "oxeye daisy"); + cfg.set("24.1", "chiseled sandstone"); + cfg.set("24.2", "smooth sandstone"); + cfg.set("31.0", "dead bush"); + cfg.set("31.1", "tall grass"); + cfg.set("31.2", "fern"); + cfg.set("98.0", "stone brick"); + cfg.set("98.1", "mossy stone brick"); + cfg.set("98.2", "cracked stone brick"); + cfg.set("98.3", "chiseled stone brick"); + cfg.set("125.0", "oak double step"); + cfg.set("125.1", "spruce double step"); + cfg.set("125.2", "birch double step"); + cfg.set("125.3", "jungle double step"); + cfg.set("125.4", "acacia double step"); + cfg.set("125.5", "dark oak double step"); + cfg.set("126.0", "oak step"); + cfg.set("126.1", "spruce step"); + cfg.set("126.2", "birch step"); + cfg.set("126.3", "jungle step"); + cfg.set("126.4", "acacia step"); + cfg.set("126.5", "dark oak step"); + cfg.set("126.8", "oak step"); + cfg.set("126.9", "spruce step"); + cfg.set("126.10", "birch step"); + cfg.set("126.11", "jungle step"); + cfg.set("126.12", "acacia step"); + cfg.set("126.13", "dark oak step"); + cfg.set("139.1", "mossy cobble wall"); + cfg.set("155.1", "chiseled quartz block"); + cfg.set("155.2", "pillar quartz block"); + cfg.set("155.3", "pillar quartz block"); + cfg.set("155.4", "pillar quartz block"); + cfg.set("161.0", "acacia leaves"); + cfg.set("161.1", "dark oak leaves"); + cfg.set("161.4", "acacia leaves"); + cfg.set("161.5", "dark oak leaves"); + cfg.set("161.8", "acacia leaves"); + cfg.set("161.9", "dark oak leaves"); + cfg.set("161.12", "acacia leaves"); + cfg.set("161.13", "dark oak leaves"); + cfg.set("162.0", "acacia log"); + cfg.set("162.1", "dark oak log"); + cfg.set("162.4", "acacia log"); + cfg.set("162.5", "dark oak log"); + cfg.set("162.8", "acacia log"); + cfg.set("162.9", "dark oak log"); + cfg.set("162.12", "acacia log"); + cfg.set("162.13", "dark oak log"); + cfg.set("168.1", "prismarine brick"); + cfg.set("168.2", "dark prismarine"); + cfg.set("181.0", "red sandstone double step"); + cfg.set("181.8", "smooth red sandstone double step"); + cfg.set("162.13", "dark oak log"); + cfg.set("175.0", "sunflower"); + cfg.set("175.1", "lilac"); + cfg.set("175.2", "double tall grass"); + cfg.set("175.3", "large fern"); + cfg.set("175.4", "rose bush"); + cfg.set("175.5", "peony"); + cfg.set("175.8", "sunflower"); + cfg.set("175.9", "lilac"); + cfg.set("175.10", "double tall grass"); + cfg.set("175.11", "large fern"); + cfg.set("175.12", "rose bush"); + cfg.set("175.13", "peony"); + cfg.set("179.1", "chiseled sandstone"); + cfg.set("179.2", "smooth sandstone"); + cfg.set("263.1", "charcoal"); + for (byte i = 0; i < 10; i++) { + cfg.set("43." + i, toReadable(Material.DOUBLE_STEP.getNewData(i))); + } + cfg.set("43.8", "stone double step"); + cfg.set("43.9", "sandstone double step"); + cfg.set("43.15", "quartz double step"); + for (byte i = 0; i < 8; i++) { + cfg.set("44." + i, toReadable(Material.STEP.getNewData(i))); + // The second half of this data list should read the same as the first half + cfg.set("44." + (i + 7), toReadable(Material.STEP.getNewData(i))); + } + for (byte i = 0; i < 16; i++) { + cfg.set("351." + i, toReadable(Material.INK_SACK.getNewData(i))); + cfg.set("35." + i, COLORS[i] + " wool"); + cfg.set("159." + i, COLORS[i] + " stained clay"); + cfg.set("95." + i, COLORS[i] + " stained glass"); + cfg.set("160." + i, COLORS[i] + " stained glass pane"); + cfg.set("171." + i, COLORS[i] + " carpet"); + } + for (byte i = 0; i < 6; i++) { + cfg.set("125." + i, toReadable(Material.WOOD_DOUBLE_STEP.getNewData(i))); + cfg.set("126." + i, toReadable(Material.WOOD_STEP.getNewData(i))); + cfg.set("126." + i + 8, toReadable(Material.WOOD_STEP.getNewData(i))); + } + try { + cfg.save(file); + } catch (final IOException ex) { + getLogger().log(Level.WARNING, "Unable to save material.yml: ", ex); + } + } + if (cfg.getString("263.1") == null) { + getLogger().info("[Logblock-names] Logblock's default materials.yml file has been updated with more names"); + getLogger().info("[Logblock-names] Consider deleting your current materials.yml file to allow it to be recreated"); + } + for (final String entry : cfg.getKeys(false)) { + if (isInt(entry)) { + if (cfg.isString(entry)) { + materialNames.put(Integer.valueOf(entry), cfg.getString(entry)); + nameTypes.put(cfg.getString(entry), Integer.valueOf(entry)); + } else if (cfg.isConfigurationSection(entry)) { + final Map dataNames = new HashMap(); + materialDataNames.put(Integer.valueOf(entry), dataNames); + final ConfigurationSection sec = cfg.getConfigurationSection(entry); + for (final String data : sec.getKeys(false)) { + if (isShort(data)) { + if (sec.isString(data)) { + dataNames.put(Short.valueOf(data), sec.getString(data)); + nameTypes.put(sec.getString(data), Integer.valueOf(entry)); + } else { + getLogger().warning("Parsing materials.yml: '" + data + "' is not a string."); + } + } else { + getLogger().warning("Parsing materials.yml: '" + data + "' is no valid material data"); + } + } + } else { + getLogger().warning("Parsing materials.yml: '" + entry + "' is neither a string nor a section."); + } + } else { + getLogger().warning("Parsing materials.yml: '" + entry + "' is no valid material id"); + } + } + } - private static String toReadable(MaterialData matData) { - return matData.toString().toLowerCase().replace('_', ' ').replaceAll("[^a-z ]", ""); - } + /** + * @return Name of the material, or if it's unknown, the id. + */ + public static String materialName(int type) { + return materialNames.containsKey(type) ? materialNames.get(type) : String.valueOf(type); + } - private static String toReadable(String matData) { - return matData.toLowerCase().replace('_', ' ').replaceAll("[^a-z ]", ""); - } + /** + * @return Name of the material regarding it's data, or if it's unknown, the basic name. + */ + public static String materialName(int type, short data) { + final Map dataNames = materialDataNames.get(type); + if (dataNames != null) { + if (dataNames.containsKey(data)) { + return dataNames.get(data); + } + } + return materialName(type); + } + + public static Integer typeFromName(String name) { + Integer answer = nameTypes.get(toReadable(name)); + if (answer != null) { + return answer; + } + final Material mat = Material.matchMaterial(name); + if (mat == null) { + throw new IllegalArgumentException("No material matching: '" + name + "'"); + } + return mat.getId(); + } + + private static String toReadable(MaterialData matData) { + return matData.toString().toLowerCase().replace('_', ' ').replaceAll("[^a-z ]", ""); + } + + private static String toReadable(String matData) { + return matData.toLowerCase().replace('_', ' ').replaceAll("[^a-z ]", ""); + } } diff --git a/src/main/java/de/diddiz/util/MySQLConnectionPool.java b/src/main/java/de/diddiz/util/MySQLConnectionPool.java index 6227cb8..0f7c976 100644 --- a/src/main/java/de/diddiz/util/MySQLConnectionPool.java +++ b/src/main/java/de/diddiz/util/MySQLConnectionPool.java @@ -7,40 +7,39 @@ import java.io.Closeable; import java.sql.Connection; import java.sql.SQLException; -public class MySQLConnectionPool implements Closeable -{ +public class MySQLConnectionPool implements Closeable { - private final HikariDataSource ds; + private final HikariDataSource ds; - public MySQLConnectionPool(String url, String user, String password) throws ClassNotFoundException { - this.ds = new HikariDataSource(); - ds.setJdbcUrl(url); - ds.setUsername(user); - ds.setPassword(password); + public MySQLConnectionPool(String url, String user, String password) throws ClassNotFoundException { + this.ds = new HikariDataSource(); + ds.setJdbcUrl(url); + ds.setUsername(user); + ds.setPassword(password); - ds.setMinimumIdle(2); - ds.setPoolName("LogBlock-Connection-Pool"); + ds.setMinimumIdle(2); + ds.setPoolName("LogBlock-Connection-Pool"); - ds.addDataSourceProperty("useUnicode", "true"); - ds.addDataSourceProperty("characterEncoding", "utf-8"); - ds.addDataSourceProperty("rewriteBatchedStatements", "true"); + ds.addDataSourceProperty("useUnicode", "true"); + ds.addDataSourceProperty("characterEncoding", "utf-8"); + ds.addDataSourceProperty("rewriteBatchedStatements", "true"); - ds.addDataSourceProperty("cachePrepStmts", "true"); - ds.addDataSourceProperty("prepStmtCacheSize", "250"); - ds.addDataSourceProperty("prepStmtCacheSqlLimit", "2048"); - } + ds.addDataSourceProperty("cachePrepStmts", "true"); + ds.addDataSourceProperty("prepStmtCacheSize", "250"); + ds.addDataSourceProperty("prepStmtCacheSqlLimit", "2048"); + } - @Override - public void close() { - ds.close(); - } + @Override + public void close() { + ds.close(); + } - public Connection getConnection() throws SQLException { - Connection connection = ds.getConnection(); - if (Config.mb4) { - connection.createStatement().executeQuery("SET NAMES utf8mb4"); - } - return connection; - } + public Connection getConnection() throws SQLException { + Connection connection = ds.getConnection(); + if (Config.mb4) { + connection.createStatement().executeQuery("SET NAMES utf8mb4"); + } + return connection; + } } diff --git a/src/main/java/de/diddiz/util/UUIDFetcher.java b/src/main/java/de/diddiz/util/UUIDFetcher.java index a699c95..2b4d66a 100644 --- a/src/main/java/de/diddiz/util/UUIDFetcher.java +++ b/src/main/java/de/diddiz/util/UUIDFetcher.java @@ -18,62 +18,62 @@ import java.util.UUID; public class UUIDFetcher { - private static final String PROFILE_URL = "https://api.mojang.com/profiles/minecraft"; - private static final JSONParser jsonParser = new JSONParser(); + private static final String PROFILE_URL = "https://api.mojang.com/profiles/minecraft"; + private static final JSONParser jsonParser = new JSONParser(); - public static Map getUUIDs(List names) throws Exception { - Map uuidMap = new HashMap(); - HttpURLConnection connection = createConnection(); - String body = JSONArray.toJSONString(names); - writeBody(connection, body); - JSONArray array = (JSONArray) jsonParser.parse(new InputStreamReader(connection.getInputStream())); - for (Object profile : array) { - JSONObject jsonProfile = (JSONObject) profile; - String id = (String) jsonProfile.get("id"); - String name = (String) jsonProfile.get("name"); - UUID uuid = UUIDFetcher.getUUID(id); - uuidMap.put(name, uuid); - } - return uuidMap; - } + public static Map getUUIDs(List names) throws Exception { + Map uuidMap = new HashMap(); + HttpURLConnection connection = createConnection(); + String body = JSONArray.toJSONString(names); + writeBody(connection, body); + JSONArray array = (JSONArray) jsonParser.parse(new InputStreamReader(connection.getInputStream())); + for (Object profile : array) { + JSONObject jsonProfile = (JSONObject) profile; + String id = (String) jsonProfile.get("id"); + String name = (String) jsonProfile.get("name"); + UUID uuid = UUIDFetcher.getUUID(id); + uuidMap.put(name, uuid); + } + return uuidMap; + } - private static void writeBody(HttpURLConnection connection, String body) throws Exception { - OutputStream stream = connection.getOutputStream(); - stream.write(body.getBytes()); - stream.flush(); - stream.close(); - } + private static void writeBody(HttpURLConnection connection, String body) throws Exception { + OutputStream stream = connection.getOutputStream(); + stream.write(body.getBytes()); + stream.flush(); + stream.close(); + } - private static HttpURLConnection createConnection() throws Exception { - URL url = new URL(PROFILE_URL); - HttpURLConnection connection = (HttpURLConnection) url.openConnection(); - connection.setRequestMethod("POST"); - connection.setRequestProperty("Content-Type", "application/json"); - connection.setUseCaches(false); - connection.setDoInput(true); - connection.setDoOutput(true); - return connection; - } + private static HttpURLConnection createConnection() throws Exception { + URL url = new URL(PROFILE_URL); + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + connection.setRequestMethod("POST"); + connection.setRequestProperty("Content-Type", "application/json"); + connection.setUseCaches(false); + connection.setDoInput(true); + connection.setDoOutput(true); + return connection; + } - private static UUID getUUID(String id) { - return UUID.fromString(id.substring(0, 8) + "-" + id.substring(8, 12) + "-" + id.substring(12, 16) + "-" + id.substring(16, 20) + "-" + id.substring(20, 32)); - } + private static UUID getUUID(String id) { + return UUID.fromString(id.substring(0, 8) + "-" + id.substring(8, 12) + "-" + id.substring(12, 16) + "-" + id.substring(16, 20) + "-" + id.substring(20, 32)); + } - public static byte[] toBytes(UUID uuid) { - ByteBuffer byteBuffer = ByteBuffer.wrap(new byte[16]); - byteBuffer.putLong(uuid.getMostSignificantBits()); - byteBuffer.putLong(uuid.getLeastSignificantBits()); - return byteBuffer.array(); - } + public static byte[] toBytes(UUID uuid) { + ByteBuffer byteBuffer = ByteBuffer.wrap(new byte[16]); + byteBuffer.putLong(uuid.getMostSignificantBits()); + byteBuffer.putLong(uuid.getLeastSignificantBits()); + return byteBuffer.array(); + } - public static UUID fromBytes(byte[] array) { - if (array.length != 16) { - throw new IllegalArgumentException("Illegal byte array length: " + array.length); - } - ByteBuffer byteBuffer = ByteBuffer.wrap(array); - long mostSignificant = byteBuffer.getLong(); - long leastSignificant = byteBuffer.getLong(); - return new UUID(mostSignificant, leastSignificant); - } + public static UUID fromBytes(byte[] array) { + if (array.length != 16) { + throw new IllegalArgumentException("Illegal byte array length: " + array.length); + } + ByteBuffer byteBuffer = ByteBuffer.wrap(array); + long mostSignificant = byteBuffer.getLong(); + long leastSignificant = byteBuffer.getLong(); + return new UUID(mostSignificant, leastSignificant); + } } diff --git a/src/main/java/de/diddiz/util/Utils.java b/src/main/java/de/diddiz/util/Utils.java index 2cd7edc..9c531cc 100644 --- a/src/main/java/de/diddiz/util/Utils.java +++ b/src/main/java/de/diddiz/util/Utils.java @@ -9,166 +9,186 @@ import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; -public class Utils -{ - public static String newline = System.getProperty("line.separator"); +public class Utils { + public static String newline = System.getProperty("line.separator"); - public static boolean isInt(String str) { - try { - Integer.parseInt(str); - return true; - } catch (final NumberFormatException ex) { - } - return false; - } + public static boolean isInt(String str) { + try { + Integer.parseInt(str); + return true; + } catch (final NumberFormatException ex) { + } + return false; + } - public static boolean isShort(String str) { - try { - Short.parseShort(str); - return true; - } catch (final NumberFormatException ex) { - } - return false; - } + public static boolean isShort(String str) { + try { + Short.parseShort(str); + return true; + } catch (final NumberFormatException ex) { + } + return false; + } - public static boolean isByte(String str) { - try { - Byte.parseByte(str); - return true; - } catch (final NumberFormatException ex) { - } - return false; - } + public static boolean isByte(String str) { + try { + Byte.parseByte(str); + return true; + } catch (final NumberFormatException ex) { + } + return false; + } - public static String listing(String[] entries, String delimiter, String finalDelimiter) { - final int len = entries.length; - if (len == 0) - return ""; - if (len == 1) - return entries[0]; - final StringBuilder builder = new StringBuilder(entries[0]); - for (int i = 1; i < len - 1; i++) - builder.append(delimiter).append(entries[i]); - builder.append(finalDelimiter).append(entries[len - 1]); - return builder.toString(); - } + public static String listing(String[] entries, String delimiter, String finalDelimiter) { + final int len = entries.length; + if (len == 0) { + return ""; + } + if (len == 1) { + return entries[0]; + } + final StringBuilder builder = new StringBuilder(entries[0]); + for (int i = 1; i < len - 1; i++) { + builder.append(delimiter).append(entries[i]); + } + builder.append(finalDelimiter).append(entries[len - 1]); + return builder.toString(); + } - public static String listing(List entries, String delimiter, String finalDelimiter) { - final int len = entries.size(); - if (len == 0) - return ""; - if (len == 1) - return entries.get(0).toString(); - final StringBuilder builder = new StringBuilder(entries.get(0).toString()); - for (int i = 1; i < len - 1; i++) - builder.append(delimiter).append(entries.get(i).toString()); - builder.append(finalDelimiter).append(entries.get(len - 1).toString()); - return builder.toString(); - } + public static String listing(List entries, String delimiter, String finalDelimiter) { + final int len = entries.size(); + if (len == 0) { + return ""; + } + if (len == 1) { + return entries.get(0).toString(); + } + final StringBuilder builder = new StringBuilder(entries.get(0).toString()); + for (int i = 1; i < len - 1; i++) { + builder.append(delimiter).append(entries.get(i).toString()); + } + builder.append(finalDelimiter).append(entries.get(len - 1).toString()); + return builder.toString(); + } - public static int parseTimeSpec(String[] spec) { - if (spec == null || spec.length < 1 || spec.length > 2) - return -1; - if (spec.length == 1 && isInt(spec[0])) - return Integer.valueOf(spec[0]); - if (!spec[0].contains(":") && !spec[0].contains(".")) - if (spec.length == 2) { - if (!isInt(spec[0])) - return -1; - int min = Integer.parseInt(spec[0]); - if (spec[1].startsWith("h")) - min *= 60; - else if (spec[1].startsWith("d")) - min *= 1440; - return min; - } else if (spec.length == 1) { - int days = 0, hours = 0, minutes = 0; - int lastIndex = 0, currIndex = 1; - while (currIndex <= spec[0].length()) { - while (currIndex <= spec[0].length() && isInt(spec[0].substring(lastIndex, currIndex))) - currIndex++; - if (currIndex - 1 != lastIndex) { - if (currIndex > spec[0].length()) - return -1; - final String param = spec[0].substring(currIndex - 1, currIndex).toLowerCase(); - if (param.equals("d")) - days = Integer.parseInt(spec[0].substring(lastIndex, currIndex - 1)); - else if (param.equals("h")) - hours = Integer.parseInt(spec[0].substring(lastIndex, currIndex - 1)); - else if (param.equals("m")) - minutes = Integer.parseInt(spec[0].substring(lastIndex, currIndex - 1)); - } - lastIndex = currIndex; - currIndex++; - } - if (days == 0 && hours == 0 && minutes == 0) - return -1; - return minutes + hours * 60 + days * 1440; - } else - return -1; - final String timestamp; - if (spec.length == 1) { - if (spec[0].contains(":")) - timestamp = new SimpleDateFormat("dd.MM.yyyy").format(System.currentTimeMillis()) + " " + spec[0]; - else - timestamp = spec[0] + " 00:00:00"; - } else - timestamp = spec[0] + " " + spec[1]; - try { - return (int)((System.currentTimeMillis() - new SimpleDateFormat("dd.MM.yyyy HH:mm:ss").parse(timestamp).getTime()) / 60000); - } catch (final ParseException ex) { - return -1; - } - } + public static int parseTimeSpec(String[] spec) { + if (spec == null || spec.length < 1 || spec.length > 2) { + return -1; + } + if (spec.length == 1 && isInt(spec[0])) { + return Integer.valueOf(spec[0]); + } + if (!spec[0].contains(":") && !spec[0].contains(".")) { + if (spec.length == 2) { + if (!isInt(spec[0])) { + return -1; + } + int min = Integer.parseInt(spec[0]); + if (spec[1].startsWith("h")) { + min *= 60; + } else if (spec[1].startsWith("d")) { + min *= 1440; + } + return min; + } else if (spec.length == 1) { + int days = 0, hours = 0, minutes = 0; + int lastIndex = 0, currIndex = 1; + while (currIndex <= spec[0].length()) { + while (currIndex <= spec[0].length() && isInt(spec[0].substring(lastIndex, currIndex))) { + currIndex++; + } + if (currIndex - 1 != lastIndex) { + if (currIndex > spec[0].length()) { + return -1; + } + final String param = spec[0].substring(currIndex - 1, currIndex).toLowerCase(); + if (param.equals("d")) { + days = Integer.parseInt(spec[0].substring(lastIndex, currIndex - 1)); + } else if (param.equals("h")) { + hours = Integer.parseInt(spec[0].substring(lastIndex, currIndex - 1)); + } else if (param.equals("m")) { + minutes = Integer.parseInt(spec[0].substring(lastIndex, currIndex - 1)); + } + } + lastIndex = currIndex; + currIndex++; + } + if (days == 0 && hours == 0 && minutes == 0) { + return -1; + } + return minutes + hours * 60 + days * 1440; + } else { + return -1; + } + } + final String timestamp; + if (spec.length == 1) { + if (spec[0].contains(":")) { + timestamp = new SimpleDateFormat("dd.MM.yyyy").format(System.currentTimeMillis()) + " " + spec[0]; + } else { + timestamp = spec[0] + " 00:00:00"; + } + } else { + timestamp = spec[0] + " " + spec[1]; + } + try { + return (int) ((System.currentTimeMillis() - new SimpleDateFormat("dd.MM.yyyy HH:mm:ss").parse(timestamp).getTime()) / 60000); + } catch (final ParseException ex) { + return -1; + } + } - public static String spaces(int count) { - final StringBuilder filled = new StringBuilder(count); - for (int i = 0; i < count; i++) - filled.append(' '); - return filled.toString(); - } + public static String spaces(int count) { + final StringBuilder filled = new StringBuilder(count); + for (int i = 0; i < count; i++) { + filled.append(' '); + } + return filled.toString(); + } - public static String join(String[] s, String delimiter) { - if (s == null || s.length == 0) - return ""; - final int len = s.length; - final StringBuilder builder = new StringBuilder(s[0]); - for (int i = 1; i < len; i++) - builder.append(delimiter).append(s[i]); - return builder.toString(); - } + public static String join(String[] s, String delimiter) { + if (s == null || s.length == 0) { + return ""; + } + final int len = s.length; + final StringBuilder builder = new StringBuilder(s[0]); + for (int i = 1; i < len; i++) { + builder.append(delimiter).append(s[i]); + } + return builder.toString(); + } - /*** - * Converts a list of arguments e.g ['lb', 'clearlog', 'world', '"my', 'world', 'of', 'swag"'] - * into a list of arguments with any text encapsulated by quotes treated as one word - * For this particular example: ['lb', 'clearlog', 'world', '"my world of swag"'] - * @param args The list of arguments - * @return A new list with the quoted arguments parsed to single values - */ - public static List parseQuotes(List args) { - List newArguments = new ArrayList(); - String subjectString = join(args.toArray(new String[args.size()]), " "); + /** + * Converts a list of arguments e.g ['lb', 'clearlog', 'world', '"my', 'world', 'of', 'swag"'] + * into a list of arguments with any text encapsulated by quotes treated as one word + * For this particular example: ['lb', 'clearlog', 'world', '"my world of swag"'] + * + * @param args The list of arguments + * @return A new list with the quoted arguments parsed to single values + */ + public static List parseQuotes(List args) { + List newArguments = new ArrayList(); + String subjectString = join(args.toArray(new String[args.size()]), " "); - Pattern regex = Pattern.compile("[^\\s\"']+|\"[^\"]*\"|'[^']*'"); - Matcher regexMatcher = regex.matcher(subjectString); - while (regexMatcher.find()) { - newArguments.add(regexMatcher.group()); - } + Pattern regex = Pattern.compile("[^\\s\"']+|\"[^\"]*\"|'[^']*'"); + Matcher regexMatcher = regex.matcher(subjectString); + while (regexMatcher.find()) { + newArguments.add(regexMatcher.group()); + } - return newArguments; - } + return newArguments; + } - public static class ExtensionFilenameFilter implements FilenameFilter - { - private final String ext; + public static class ExtensionFilenameFilter implements FilenameFilter { + private final String ext; - public ExtensionFilenameFilter(String ext) { - this.ext = ext; - } + public ExtensionFilenameFilter(String ext) { + this.ext = ext; + } - @Override - public boolean accept(File dir, String name) { - return name.toLowerCase().endsWith(ext); - } - } + @Override + public boolean accept(File dir, String name) { + return name.toLowerCase().endsWith(ext); + } + } } diff --git a/src/main/java/de/diddiz/worldedit/RegionContainer.java b/src/main/java/de/diddiz/worldedit/RegionContainer.java index e94b9a5..3258434 100644 --- a/src/main/java/de/diddiz/worldedit/RegionContainer.java +++ b/src/main/java/de/diddiz/worldedit/RegionContainer.java @@ -10,32 +10,32 @@ import org.bukkit.plugin.Plugin; public class RegionContainer { - private Selection selection; + private Selection selection; - public RegionContainer(Selection sel) { - this.selection = sel; - } + public RegionContainer(Selection sel) { + this.selection = sel; + } - public static RegionContainer fromPlayerSelection(Player player, Plugin plugin) { - final Selection selection = ((WorldEditPlugin) plugin).getSelection(player); - if (selection == null) { - throw new IllegalArgumentException("No selection defined"); - } - if (!(selection instanceof CuboidSelection)) { - throw new IllegalArgumentException("You have to define a cuboid selection"); - } - return new RegionContainer(selection); - } + public static RegionContainer fromPlayerSelection(Player player, Plugin plugin) { + final Selection selection = ((WorldEditPlugin) plugin).getSelection(player); + if (selection == null) { + throw new IllegalArgumentException("No selection defined"); + } + if (!(selection instanceof CuboidSelection)) { + throw new IllegalArgumentException("You have to define a cuboid selection"); + } + return new RegionContainer(selection); + } - public static RegionContainer fromCorners(World world, Location first, Location second) { - return new RegionContainer(new CuboidSelection(world, first, second)); - } + public static RegionContainer fromCorners(World world, Location first, Location second) { + return new RegionContainer(new CuboidSelection(world, first, second)); + } - public Selection getSelection() { - return selection; - } + public Selection getSelection() { + return selection; + } - public void setSelection(Selection selection) { - this.selection = selection; - } + public void setSelection(Selection selection) { + this.selection = selection; + } } diff --git a/src/main/java/de/diddiz/worldedit/WorldEditLoggingHook.java b/src/main/java/de/diddiz/worldedit/WorldEditLoggingHook.java index 7acc140..0bdef23 100644 --- a/src/main/java/de/diddiz/worldedit/WorldEditLoggingHook.java +++ b/src/main/java/de/diddiz/worldedit/WorldEditLoggingHook.java @@ -6,14 +6,12 @@ import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.blocks.BaseBlock; import com.sk89q.worldedit.bukkit.BukkitWorld; import com.sk89q.worldedit.event.extent.EditSessionEvent; -//...so they ALSO have a class called Actor... need to fully-qualify when we use ours import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.extent.logging.AbstractLoggingExtent; import com.sk89q.worldedit.util.eventbus.Subscribe; import de.diddiz.LogBlock.LogBlock; import de.diddiz.LogBlock.Logging; import de.diddiz.LogBlock.config.Config; -import java.util.logging.Level; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.Material; @@ -22,93 +20,103 @@ import org.bukkit.block.Block; import org.bukkit.block.BlockState; import org.bukkit.block.Sign; +import java.util.logging.Level; + +//...so they ALSO have a class called Actor... need to fully-qualify when we use ours + public class WorldEditLoggingHook { - private LogBlock plugin; + private LogBlock plugin; - public WorldEditLoggingHook(LogBlock plugin) { - this.plugin = plugin; - } + public WorldEditLoggingHook(LogBlock plugin) { + this.plugin = plugin; + } - // Convert WE Actor to LB Actor - private de.diddiz.LogBlock.Actor AtoA(Actor weActor) { - if (weActor.isPlayer()) { - return new de.diddiz.LogBlock.Actor(weActor.getName(),weActor.getUniqueId()); - } - return new de.diddiz.LogBlock.Actor(weActor.getName()); - } + // Convert WE Actor to LB Actor + private de.diddiz.LogBlock.Actor AtoA(Actor weActor) { + if (weActor.isPlayer()) { + return new de.diddiz.LogBlock.Actor(weActor.getName(), weActor.getUniqueId()); + } + return new de.diddiz.LogBlock.Actor(weActor.getName()); + } - private World adapt(com.sk89q.worldedit.world.World weWorld) { - if (weWorld == null) { - throw new NullPointerException("[Logblock-Worldedit] The provided world was null."); - } - if (weWorld instanceof BukkitWorld) return ((BukkitWorld) weWorld).getWorld(); - World world = Bukkit.getServer().getWorld(weWorld.getName()); - if (world == null) throw new IllegalArgumentException("Can't find a Bukkit world for " + weWorld); - return world; - } + private World adapt(com.sk89q.worldedit.world.World weWorld) { + if (weWorld == null) { + throw new NullPointerException("[Logblock-Worldedit] The provided world was null."); + } + if (weWorld instanceof BukkitWorld) { + return ((BukkitWorld) weWorld).getWorld(); + } + World world = Bukkit.getServer().getWorld(weWorld.getName()); + if (world == null) { + throw new IllegalArgumentException("Can't find a Bukkit world for " + weWorld); + } + return world; + } - public void hook() { - WorldEdit.getInstance().getEventBus().register(new Object() { - @Subscribe - public void wrapForLogging(final EditSessionEvent event) { - final Actor actor = event.getActor(); - if (actor == null ) return; - final de.diddiz.LogBlock.Actor lbActor = AtoA(actor); + public void hook() { + WorldEdit.getInstance().getEventBus().register(new Object() { + @Subscribe + public void wrapForLogging(final EditSessionEvent event) { + final Actor actor = event.getActor(); + if (actor == null) { + return; + } + final de.diddiz.LogBlock.Actor lbActor = AtoA(actor); - // Check to ensure the world should be logged - final World world; - final com.sk89q.worldedit.world.World k = event.getWorld(); - try { - world = adapt(k); - } catch (RuntimeException ex) { - plugin.getLogger().warning("Failed to register logging for WorldEdit!"); - plugin.getLogger().log(Level.WARNING, ex.getMessage(),ex); - return; - } + // Check to ensure the world should be logged + final World world; + final com.sk89q.worldedit.world.World k = event.getWorld(); + try { + world = adapt(k); + } catch (RuntimeException ex) { + plugin.getLogger().warning("Failed to register logging for WorldEdit!"); + plugin.getLogger().log(Level.WARNING, ex.getMessage(), ex); + return; + } - // If config becomes reloadable, this check should be moved - if (!(Config.isLogging(world, Logging.WORLDEDIT))) { - return; - } - - event.setExtent(new AbstractLoggingExtent(event.getExtent()) { - @Override - protected void onBlockChange(Vector pt, BaseBlock block) { + // If config becomes reloadable, this check should be moved + if (!(Config.isLogging(world, Logging.WORLDEDIT))) { + return; + } - if (event.getStage() != EditSession.Stage.BEFORE_CHANGE) { - return; - } + event.setExtent(new AbstractLoggingExtent(event.getExtent()) { + @Override + protected void onBlockChange(Vector pt, BaseBlock block) { - Location location = new Location(world, pt.getBlockX(), pt.getBlockY(), pt.getBlockZ()); - Block origin = location.getBlock(); - int typeBefore = origin.getTypeId(); - byte dataBefore = origin.getData(); - // If we're dealing with a sign, store the block state to read the text off - BlockState stateBefore = null; - if (typeBefore == Material.SIGN_POST.getId() || typeBefore == Material.SIGN.getId()) { - stateBefore = origin.getState(); - } + if (event.getStage() != EditSession.Stage.BEFORE_CHANGE) { + return; + } - // Check to see if we've broken a sign - if (Config.isLogging(location.getWorld().getName(), Logging.SIGNTEXT) && (typeBefore == Material.SIGN_POST.getId() || typeBefore == Material.SIGN.getId())) { - plugin.getConsumer().queueSignBreak(lbActor, (Sign) stateBefore); - if (block.getType() != Material.AIR.getId()) { - plugin.getConsumer().queueBlockPlace(lbActor, location, block.getType(), (byte) block.getData()); - } - } else { - if (dataBefore != 0) { - plugin.getConsumer().queueBlockBreak(lbActor, location, typeBefore, dataBefore); - if (block.getType() != Material.AIR.getId()) { - plugin.getConsumer().queueBlockPlace(lbActor, location, block.getType(), (byte) block.getData()); - } - } else { - plugin.getConsumer().queueBlock(lbActor, location, typeBefore, block.getType(), (byte) block.getData()); - } - } - } - }); - } - }); - } + Location location = new Location(world, pt.getBlockX(), pt.getBlockY(), pt.getBlockZ()); + Block origin = location.getBlock(); + int typeBefore = origin.getTypeId(); + byte dataBefore = origin.getData(); + // If we're dealing with a sign, store the block state to read the text off + BlockState stateBefore = null; + if (typeBefore == Material.SIGN_POST.getId() || typeBefore == Material.SIGN.getId()) { + stateBefore = origin.getState(); + } + + // Check to see if we've broken a sign + if (Config.isLogging(location.getWorld().getName(), Logging.SIGNTEXT) && (typeBefore == Material.SIGN_POST.getId() || typeBefore == Material.SIGN.getId())) { + plugin.getConsumer().queueSignBreak(lbActor, (Sign) stateBefore); + if (block.getType() != Material.AIR.getId()) { + plugin.getConsumer().queueBlockPlace(lbActor, location, block.getType(), (byte) block.getData()); + } + } else { + if (dataBefore != 0) { + plugin.getConsumer().queueBlockBreak(lbActor, location, typeBefore, dataBefore); + if (block.getType() != Material.AIR.getId()) { + plugin.getConsumer().queueBlockPlace(lbActor, location, block.getType(), (byte) block.getData()); + } + } else { + plugin.getConsumer().queueBlock(lbActor, location, typeBefore, block.getType(), (byte) block.getData()); + } + } + } + }); + } + }); + } } diff --git a/src/test/java/de/diddiz/LogBlock/QueryParsingTest.java b/src/test/java/de/diddiz/LogBlock/QueryParsingTest.java index ebb729c..30e8ee6 100644 --- a/src/test/java/de/diddiz/LogBlock/QueryParsingTest.java +++ b/src/test/java/de/diddiz/LogBlock/QueryParsingTest.java @@ -10,12 +10,12 @@ import java.util.List; public class QueryParsingTest { - @Test - public void testParseQuotes() { - // input = /lb clearlog world "my world of swag" player "player" - List input = Arrays.asList("lb", "clearlog", "world", "\"my", "world", "of", "swag\"", "player", "\"player\""); - List expectedOut = Arrays.asList("lb", "clearlog", "world", "\"my world of swag\"", "player", "\"player\""); - Assert.assertEquals(Utils.parseQuotes(input), expectedOut); - } + @Test + public void testParseQuotes() { + // input = /lb clearlog world "my world of swag" player "player" + List input = Arrays.asList("lb", "clearlog", "world", "\"my", "world", "of", "swag\"", "player", "\"player\""); + List expectedOut = Arrays.asList("lb", "clearlog", "world", "\"my world of swag\"", "player", "\"player\""); + Assert.assertEquals(Utils.parseQuotes(input), expectedOut); + } }