Identify players by UUID and migrate existing databases to include this. Fixes #538, fixes #568

This creates a new column in the lb-players table called UUID. If this is in the form of a UUID,
it's assumed to be a player. If not, it's assumed to be a server entity (zombie, sheep, or
WaterFlow, LavaFlow etc.). LogBlock will set the UUID of entities to "log_" plus their name
(i.e. log_zombie or log_sheep)

To assist this is a new class Actor, which wraps a name/UUID pair, with constructors that will
generate one from server entities, or SQL results. Every listener and every class in Consumer
needed to be updated to deal with this

As of yet, only the playername is displayed in results (although the queries do return UUID data).
Similarly, you can only query by name (the database stores the last name they have logged in as).
In addition, the WorldEdit hook has been disabled (is not compiled) since LB needs to be updated
to use their new API, and the LB code hook has to extract UUID information for insertion.

The UUID importer assumes any player with an onlinetime of 0 is a server-generated source, and set
the UUID as above (log_sheep etc.).  For everything else, it sends 100 names at a time to Mojang's
name->UUID service, and records them if available.  If no result is found, it records their UUID as
noimport_theirname.  As this is more likely than other updates to be interrupted mid-way, the
importer is tolerant of e.g. the column already being added, and will resume where it left off.
This commit is contained in:
Philip Cass
2015-02-14 13:52:06 +00:00
parent d7f2ac5a65
commit e3dc430931
36 changed files with 596 additions and 277 deletions

View File

@ -89,6 +89,9 @@
<configuration>
<source>1.6</source>
<target>1.6</target>
<excludes>
<exclude>**/de/diddiz/worldedit/*.java</exclude>
</excludes>
</configuration>
</plugin>
</plugins>

View File

@ -0,0 +1,85 @@
package de.diddiz.LogBlock;
import static de.diddiz.util.BukkitUtils.entityName;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import java.sql.ResultSet;
import java.sql.SQLException;
public class Actor {
@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;
if ((this.UUID == null) ? (other.UUID != null) : !this.UUID.equals(other.UUID)) {
return false;
}
return true;
}
final String name;
final String UUID;
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 static Actor actorFromEntity(Entity entity) {
if (entity instanceof Player) {
return new Actor(entityName(entity),entity.getUniqueId().toString());
} else {
return new Actor(entityName(entity));
}
}
public static Actor actorFromEntity(EntityType entity) {
return new Actor(entity.getName());
}
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;
}
}

View File

@ -14,28 +14,31 @@ 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, String playerName, int replaced, int type, byte data, String signtext, 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.playerName = playerName;
this.actor = actor;
this.replaced = replaced;
this.type = type;
this.data = data;
this.signtext = 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;
@ -49,8 +52,8 @@ public class BlockChange implements LookupCacheElement
final StringBuilder msg = new StringBuilder();
if (date > 0)
msg.append(Config.formatter.format(date)).append(" ");
if (playerName != null)
msg.append(playerName).append(" ");
if (actor != null)
msg.append(actor.getName()).append(" ");
if (signtext != null) {
final String action = type == 0 ? "destroyed " : "created ";
if (!signtext.contains("\0"))

View File

@ -8,17 +8,20 @@ public class ChatMessage implements LookupCacheElement
{
final long id, date;
final String playerName, message;
final Actor player;
public ChatMessage(String playerName, String message) {
public ChatMessage(Actor player, String message) {
id = 0;
date = System.currentTimeMillis() / 1000;
this.playerName = playerName;
this.player = player;
this.message = message;
this.playerName = player == null ? null : player.getName();
}
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;
}
@ -30,6 +33,6 @@ public class ChatMessage implements LookupCacheElement
@Override
public String getMessage() {
return (playerName != null ? "<" + playerName + "> " : "") + (message != null ? message : "");
return (player != null ? "<" + player.getName() + "> " : "") + (message != null ? message : "");
}
}

View File

@ -29,9 +29,9 @@ import static org.bukkit.Bukkit.getLogger;
public class Consumer extends TimerTask
{
private final Queue<Row> queue = new LinkedBlockingQueue<Row>();
private final Set<String> failedPlayers = new HashSet<String>();
private final Set<Actor> failedPlayers = new HashSet<Actor>();
private final LogBlock logblock;
private final Map<String, Integer> playerIds = new HashMap<String, Integer>();
private final Map<Actor, Integer> playerIds = new HashMap<Actor, Integer>();
private final Lock lock = new ReentrantLock();
Consumer(LogBlock logblock) {
@ -45,8 +45,8 @@ public class Consumer extends TimerTask
/**
* 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(String playerName, Location loc, int typeBefore, int typeAfter, byte data) {
queueBlock(playerName, loc, typeBefore, typeAfter, data, null, null);
public void queueBlock(Actor actor, Location loc, int typeBefore, int typeAfter, byte data) {
queueBlock(actor, loc, typeBefore, typeAfter, data, null, null);
}
/**
@ -55,15 +55,15 @@ public class Consumer extends TimerTask
* @param before
* Blockstate of the block before actually being destroyed.
*/
public void queueBlockBreak(String playerName, BlockState before) {
queueBlockBreak(playerName, new Location(before.getWorld(), before.getX(), before.getY(), before.getZ()), before.getTypeId(), before.getRawData());
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(String playerName, Location loc, int typeBefore, byte dataBefore) {
queueBlock(playerName, loc, typeBefore, 0, dataBefore);
public void queueBlockBreak(Actor actor, Location loc, int typeBefore, byte dataBefore) {
queueBlock(actor, loc, typeBefore, 0, dataBefore);
}
/**
@ -72,15 +72,15 @@ public class Consumer extends TimerTask
* @param after
* Blockstate of the block after actually being placed.
*/
public void queueBlockPlace(String playerName, BlockState after) {
queueBlockPlace(playerName, new Location(after.getWorld(), after.getX(), after.getY(), after.getZ()), after.getBlock().getTypeId(), after.getBlock().getData());
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(String playerName, Location loc, int type, byte data) {
queueBlock(playerName, loc, 0, type, data);
public void queueBlockPlace(Actor actor, Location loc, int type, byte data) {
queueBlock(actor, loc, 0, type, data);
}
/**
@ -89,32 +89,32 @@ public class Consumer extends TimerTask
* @param after
* Blockstate of the block after actually being placed.
*/
public void queueBlockReplace(String playerName, BlockState before, BlockState after) {
queueBlockReplace(playerName, new Location(before.getWorld(), before.getX(), before.getY(), before.getZ()), before.getTypeId(), before.getRawData(), after.getTypeId(), after.getRawData());
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(String playerName, BlockState before, int typeAfter, byte dataAfter) {
queueBlockReplace(playerName, new Location(before.getWorld(), before.getX(), before.getY(), before.getZ()), before.getTypeId(), before.getRawData(), typeAfter, dataAfter);
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(String playerName, int typeBefore, byte dataBefore, BlockState after) {
queueBlockReplace(playerName, new Location(after.getWorld(), after.getX(), after.getY(), after.getZ()), typeBefore, dataBefore, after.getTypeId(), after.getRawData());
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(String playerName, Location loc, int typeBefore, byte dataBefore, int typeAfter, byte dataAfter) {
public void queueBlockReplace(Actor actor, Location loc, int typeBefore, byte dataBefore, int typeAfter, byte dataAfter) {
if (dataBefore == 0 && (typeBefore != typeAfter))
queueBlock(playerName, loc, typeBefore, typeAfter, dataAfter);
queueBlock(actor, loc, typeBefore, typeAfter, dataAfter);
else {
queueBlockBreak(playerName, loc, typeBefore, dataBefore);
queueBlockPlace(playerName, loc, typeAfter, dataAfter);
queueBlockBreak(actor, loc, typeBefore, dataBefore);
queueBlockPlace(actor, loc, typeAfter, dataAfter);
}
}
@ -122,18 +122,18 @@ public class Consumer extends TimerTask
* @param container
* The respective container. Must be an instance of an InventoryHolder.
*/
public void queueChestAccess(String playerName, BlockState container, short itemType, short itemAmount, short itemData) {
public void queueChestAccess(Actor actor, BlockState container, short itemType, short itemAmount, short itemData) {
if (!(container instanceof InventoryHolder))
return;
queueChestAccess(playerName, new Location(container.getWorld(), container.getX(), container.getY(), container.getZ()), container.getTypeId(), itemType, itemAmount, itemData);
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(String playerName, Location loc, int type, short itemType, short itemAmount, short itemData) {
queueBlock(playerName, loc, type, type, (byte)0, null, new ChestAccess(itemType, itemAmount, itemData));
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));
}
/**
@ -142,20 +142,20 @@ public class Consumer extends TimerTask
* @param container
* Must be an instance of InventoryHolder
*/
public void queueContainerBreak(String playerName, BlockState container) {
public void queueContainerBreak(Actor actor, BlockState container) {
if (!(container instanceof InventoryHolder))
return;
queueContainerBreak(playerName, new Location(container.getWorld(), container.getX(), container.getY(), container.getZ()), container.getTypeId(), container.getRawData(), ((InventoryHolder)container).getInventory());
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(String playerName, Location loc, int type, byte data, Inventory inv) {
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(playerName, loc, type, (short)item.getTypeId(), (short)(item.getAmount() * -1), rawData(item));
queueBlockBreak(playerName, loc, type, data);
queueChestAccess(actor, loc, type, (short)item.getTypeId(), (short)(item.getAmount() * -1), rawData(item));
queueBlockBreak(actor, loc, type, data);
}
/**
@ -170,7 +170,7 @@ public class Consumer extends TimerTask
int weapon = 0;
if (killer instanceof Player && ((Player)killer).getItemInHand() != null)
weapon = ((Player)killer).getItemInHand().getTypeId();
queueKill(victim.getLocation(), entityName(killer), entityName(victim), weapon);
queueKill(victim.getLocation(), Actor.actorFromEntity(killer), Actor.actorFromEntity(victim), weapon);
}
/**
@ -180,10 +180,10 @@ public class Consumer extends TimerTask
* @param victim
* Can't be null
*/
public void queueKill(String killer, Entity victim) {
public void queueKill(Actor killer, Entity victim) {
if (killer == null || victim == null)
return;
queueKill(victim.getLocation(), killer, entityName(victim), 0);
queueKill(victim.getLocation(), killer, Actor.actorFromEntity(victim), 0);
}
/**
@ -198,24 +198,24 @@ public class Consumer extends TimerTask
* @deprecated Use {@link #queueKill(Location,String,String,int)} instead
*/
@Deprecated
public void queueKill(World world, String killerName, String victimName, int weapon) {
queueKill(new Location(world, 0, 0, 0), killerName, victimName, weapon);
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 killerName
* Name of the killer. Can be null.
* @param victimName
* Name of the victim. Can't be null.
* @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, String killerName, String victimName, int weapon) {
if (victimName == null || !isLogged(location.getWorld()))
public void queueKill(Location location, Actor killer, Actor victim, int weapon) {
if (victim == null || !isLogged(location.getWorld()))
return;
queue.add(new KillRow(location, killerName == null ? null : killerName.replaceAll("[^a-zA-Z0-9_]", ""), victimName.replaceAll("[^a-zA-Z0-9_]", ""), weapon));
queue.add(new KillRow(location, killer == null ? null : killer, victim, weapon));
}
/**
@ -224,14 +224,14 @@ public class Consumer extends TimerTask
* @param lines
* The four lines on the sign.
*/
public void queueSignBreak(String playerName, Location loc, int type, byte data, String[] lines) {
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(playerName, loc, type, 0, data, lines[0] + "\0" + lines[1] + "\0" + lines[2] + "\0" + lines[3], null);
queueBlock(actor, loc, type, 0, data, lines[0] + "\0" + lines[1] + "\0" + lines[2] + "\0" + lines[3], null);
}
public void queueSignBreak(String playerName, Sign sign) {
queueSignBreak(playerName, new Location(sign.getWorld(), sign.getX(), sign.getY(), sign.getZ()), sign.getTypeId(), sign.getRawData(), sign.getLines());
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());
}
/**
@ -240,17 +240,17 @@ public class Consumer extends TimerTask
* @param lines
* The four lines on the sign.
*/
public void queueSignPlace(String playerName, Location loc, int type, byte data, String[] lines) {
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(playerName, loc, 0, type, data, lines[0] + "\0" + lines[1] + "\0" + lines[2] + "\0" + lines[3], null);
queueBlock(actor, loc, 0, type, data, lines[0] + "\0" + lines[1] + "\0" + lines[2] + "\0" + lines[3], null);
}
public void queueSignPlace(String playerName, Sign sign) {
queueSignPlace(playerName, new Location(sign.getWorld(), sign.getX(), sign.getY(), sign.getZ()), sign.getTypeId(), sign.getRawData(), sign.getLines());
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(String player, String message) {
public void queueChat(Actor player, String message) {
for (String ignored : Config.ignoredChat) {
if (message.startsWith(ignored)) {
return;
@ -289,12 +289,12 @@ public class Consumer extends TimerTask
final Row r = queue.poll();
if (r == null)
continue;
for (final String player : r.getPlayers()) {
if (!playerIds.containsKey(player)) {
if (!addPlayer(state, player)) {
if (!failedPlayers.contains(player)) {
failedPlayers.add(player);
getLogger().warning("[Consumer] Failed to add player " + player);
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;
}
@ -339,7 +339,7 @@ public class Consumer extends TimerTask
public void writeToFile() throws FileNotFoundException {
final long time = System.currentTimeMillis();
final Set<String> insertedPlayers = new HashSet<String>();
final Set<Actor> insertedPlayers = new HashSet<Actor>();
int counter = 0;
new File("plugins/LogBlock/import/").mkdirs();
PrintWriter writer = new PrintWriter(new File("plugins/LogBlock/import/queue-" + time + "-0.sql"));
@ -347,11 +347,11 @@ public class Consumer extends TimerTask
final Row r = queue.poll();
if (r == null)
continue;
for (final String player : r.getPlayers())
if (!playerIds.containsKey(player) && !insertedPlayers.contains(player)) {
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) SELECT '" + player + "' FROM `lb-players` WHERE NOT EXISTS (SELECT NULL FROM `lb-players` WHERE playername = '" + player + "') LIMIT 1;");
insertedPlayers.add(player);
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);
@ -378,26 +378,28 @@ public class Consumer extends TimerTask
return true;
}
private boolean addPlayer(Statement state, String playerName) throws SQLException {
private boolean addPlayer(Statement state, Actor actor) throws SQLException {
// Odd query contruction is to work around innodb auto increment behaviour - bug #492
state.execute("INSERT IGNORE INTO `lb-players` (playername) SELECT '" + playerName + "' FROM `lb-players` WHERE NOT EXISTS (SELECT NULL FROM `lb-players` WHERE playername = '" + playerName + "') LIMIT 1;");
final ResultSet rs = state.executeQuery("SELECT playerid FROM `lb-players` WHERE playername = '" + playerName + "'");
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(playerName, rs.getInt(1));
playerIds.put(actor, rs.getInt(1));
rs.close();
return playerIds.containsKey(playerName);
return playerIds.containsKey(actor);
}
private void queueBlock(String playerName, Location loc, int typeBefore, int typeAfter, byte data, String signtext, ChestAccess ca) {
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(playerName, loc, typeBefore, typeAfter, data, signtext, ca);
BlockChangePreLogEvent event = new BlockChangePreLogEvent(actor, loc, typeBefore, typeAfter, data, signtext, ca);
logblock.getServer().getPluginManager().callEvent(event);
if (event.isCancelled()) return;
// Update variables
playerName = event.getOwner();
actor = event.getOwnerActor();
loc = event.getLocation();
typeBefore = event.getTypeBefore();
typeAfter = event.getTypeAfter();
@ -406,31 +408,37 @@ public class Consumer extends TimerTask
ca = event.getChestAccess();
}
// Do this last so LogBlock still has final say in what is being added
if (playerName == null || loc == null || typeBefore < 0 || typeAfter < 0 || (Config.safetyIdCheck && (typeBefore > 255 || typeAfter > 255)) || hiddenPlayers.contains(playerName.toLowerCase()) || !isLogged(loc.getWorld()) || typeBefore != typeAfter && hiddenBlocks.contains(typeBefore) && hiddenBlocks.contains(typeAfter)) return;
queue.add(new BlockRow(loc, playerName.replaceAll("[^a-zA-Z0-9_]", ""), typeBefore, typeAfter, data, signtext, ca));
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(String playerName) {
if (playerName == null)
private String playerID(Actor actor) {
if (actor == null)
return "NULL";
final Integer id = playerIds.get(playerName);
final Integer id = playerIds.get(actor);
if (id != null)
return id.toString();
return "(SELECT playerid FROM `lb-players` WHERE playername = '" + playerName + "')";
return "(SELECT playerid FROM `lb-players` WHERE UUID = '" + actor.getUUID() + "')";
}
private Integer playerIDAsInt(String playerName) {
if (playerName == null) {
private Integer playerIDAsInt(Actor actor) {
if (actor == null) {
return null;
}
return playerIds.get(playerName);
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
@ -445,15 +453,15 @@ public class Consumer extends TimerTask
{
private Connection connection;
public BlockRow(Location loc, String playerName, int replaced, int type, byte data, String signtext, ChestAccess ca) {
super(System.currentTimeMillis() / 1000, loc, playerName, replaced, type, data, signtext, ca);
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(playerName) + ", " + replaced + ", " + type + ", " + data + ", '" + loc.getBlockX() + "', " + loc.getBlockY() + ", '" + loc.getBlockZ() + "');";
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("'", "\\'") + "');";
}
@ -464,7 +472,12 @@ public class Consumer extends TimerTask
@Override
public String[] getPlayers() {
return new String[]{playerName};
return new String[]{actor.getName()};
}
@Override
public Actor[] getActors() {
return new Actor[]{actor};
}
@Override
@ -479,7 +492,7 @@ public class Consumer extends TimerTask
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(playerName) + ", ?, ?, ?, ?, ?, ?)", Statement.RETURN_GENERATED_KEYS);
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);
@ -538,11 +551,11 @@ public class Consumer extends TimerTask
private class KillRow implements Row
{
final long date;
final String killer, victim;
final Actor killer, victim;
final int weapon;
final Location loc;
KillRow(Location loc, String attacker, String defender, int weapon) {
KillRow(Location loc, Actor attacker, Actor defender, int weapon) {
date = System.currentTimeMillis() / 1000;
this.loc = loc;
killer = attacker;
@ -557,7 +570,12 @@ public class Consumer extends TimerTask
@Override
public String[] getPlayers() {
return new String[]{killer, victim};
return new String[]{killer.getName(), victim.getName()};
}
@Override
public Actor[] getActors() {
return new Actor[]{killer,victim};
}
}
@ -565,18 +583,23 @@ public class Consumer extends TimerTask
{
private Connection connection;
ChatRow(String player, String message) {
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(playerName) + ", '" + message.replace("\\", "\\\\").replace("'", "\\'") + "');"};
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[]{playerName};
return new String[]{player.getName()};
}
@Override
public Actor[] getActors() {
return new Actor[]{player};
}
@Override
@ -590,9 +613,9 @@ public class Consumer extends TimerTask
Integer id;
String sql = "INSERT INTO `lb-chat` (date, playerid, message) VALUES (FROM_UNIXTIME(?), ";
if ((id = playerIDAsInt(playerName)) == null) {
if ((id = playerIDAsInt(player)) == null) {
noID = true;
sql += playerID(playerName) + ", ";
sql += playerID(player) + ", ";
} else {
sql += "?, ";
}
@ -627,45 +650,55 @@ public class Consumer extends TimerTask
private class PlayerJoinRow implements Row
{
private final String playerName;
private final Actor player;
private final long lastLogin;
private final String ip;
PlayerJoinRow(Player player) {
playerName = player.getName();
this.player = Actor.actorFromEntity(player);
lastLogin = System.currentTimeMillis() / 1000;
ip = player.getAddress().toString().replace("'", "\\'");
}
@Override
public String[] getInserts() {
return new String[]{"UPDATE `lb-players` SET lastlogin = FROM_UNIXTIME(" + lastLogin + "), firstlogin = IF(firstlogin = 0, FROM_UNIXTIME(" + lastLogin + "), firstlogin), ip = '" + ip + "' WHERE " + (playerIds.containsKey(playerName) ? "playerid = " + playerIds.get(playerName) : "playerName = '" + playerName + "'") + ";"};
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() + "';"};
}
@Override
public String[] getPlayers() {
return new String[]{playerName};
return new String[]{player.getName()};
}
@Override
public Actor[] getActors() {
return new Actor[]{player};
}
}
private class PlayerLeaveRow implements Row
{
private final String playerName;
{;
private final long leaveTime;
private final Actor actor;
PlayerLeaveRow(Player player) {
playerName = player.getName();
leaveTime = System.currentTimeMillis() / 1000;
actor = Actor.actorFromEntity(player);
}
@Override
public String[] getInserts() {
return new String[]{"UPDATE `lb-players` SET onlinetime = onlinetime + TIMESTAMPDIFF(SECOND, lastlogin, FROM_UNIXTIME('" + leaveTime + "')) WHERE lastlogin > 0 && " + (playerIds.containsKey(playerName) ? "playerid = " + playerIds.get(playerName) : "playerName = '" + playerName + "'") + ";"};
return new String[]{"UPDATE `lb-players` SET onlinetime = onlinetime + TIMESTAMPDIFF(SECOND, lastlogin, FROM_UNIXTIME('" + leaveTime + "')), playername = '" + actor.getName() + "' WHERE lastlogin > 0 && UUID = '" + actor.getUUID() + "';"};
}
@Override
public String[] getPlayers() {
return new String[]{playerName};
return new String[]{actor.getName()};
}
@Override
public Actor[] getActors() {
return new Actor[]{actor};
}
}
}

View File

@ -24,7 +24,7 @@ import de.diddiz.LogBlock.listeners.StructureGrowLogging;
import de.diddiz.LogBlock.listeners.ToolListener;
import de.diddiz.LogBlock.listeners.WitherLogging;
import de.diddiz.util.MySQLConnectionPool;
import de.diddiz.worldedit.LogBlockEditSessionFactory;
//import de.diddiz.worldedit.LogBlockEditSessionFactory;
import org.bukkit.ChatColor;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
@ -109,9 +109,9 @@ public class LogBlock extends JavaPlugin
}
if (noDb)
return;
if (pm.getPlugin("WorldEdit") != null) {
LogBlockEditSessionFactory.initialize(this);
}
// if (pm.getPlugin("WorldEdit") != null) {
// LogBlockEditSessionFactory.initialize(this);
// }
commandsHandler = new CommandsHandler(this);
getCommand("lb").setExecutor(commandsHandler);
if (enableAutoClearLog && autoClearLogDelay > 0)

View File

@ -69,7 +69,7 @@ public final class QueryParams implements Cloneable
if (needDate)
select += "date, ";
if (needPlayer)
select += "playername, ";
select += "playername, UUID,";
if (needMessage)
select += "message, ";
select = select.substring(0, select.length() - 2);
@ -110,7 +110,7 @@ public final class QueryParams implements Cloneable
return select + " " + from + getWhere() + "ORDER BY date " + order + ", id " + order + " " + getLimit();
} else if (sum == SummarizationMode.PLAYERS)
return "SELECT playername, 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();
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 ";
@ -126,7 +126,7 @@ public final class QueryParams implements Cloneable
if (needData)
select += "data, ";
if (needPlayer)
select += "playername, ";
select += "playername, UUID, ";
if (needCoords)
select += "x, y, z, ";
if (needSignText)

View File

@ -12,11 +12,14 @@ 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 {
group = p.sum == SummarizationMode.PLAYERS ? rs.getString(1) : materialName(rs.getInt(1));
created = rs.getInt(2);
destroyed = rs.getInt(3);
// 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;
}

12
src/main/java/de/diddiz/LogBlock/SummedKills.java Executable file → Normal file
View File

@ -1,22 +1,20 @@
package de.diddiz.LogBlock;
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 SummedKills implements LookupCacheElement
{
private final String playerName;
private final Actor player;
private final int kills, killed;
private final float spaceFactor;
public SummedKills(ResultSet rs, QueryParams p, float spaceFactor) throws SQLException {
playerName = rs.getString(1);
kills = rs.getInt(2);
killed = rs.getInt(3);
player = new Actor(rs);
kills = rs.getInt("kills");
killed = rs.getInt("killed");
this.spaceFactor = spaceFactor;
}
@ -27,6 +25,6 @@ public class SummedKills implements LookupCacheElement
@Override
public String getMessage() {
return kills + spaces((int)((6 - String.valueOf(kills).length()) / spaceFactor)) + killed + spaces((int)((7 - String.valueOf(killed).length()) / spaceFactor)) + playerName;
return kills + spaces((int)((6 - String.valueOf(kills).length()) / spaceFactor)) + killed + spaces((int)((7 - String.valueOf(killed).length()) / spaceFactor)) + player.getName();
}
}

View File

@ -13,15 +13,24 @@ import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
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;
Updater(LogBlock logblock) {
this.logblock = logblock;
@ -256,6 +265,77 @@ class Updater
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 {
ResultSet rs;
conn.setAutoCommit(true);
final Statement st = conn.createStatement();
// 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");
// 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 <String,Integer> players = new HashMap<String,Integer>();
List <String> names = new ArrayList<String>(UUID_CONVERT_BATCH_SIZE);
Map <String,UUID> 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<String,Integer> entry : players.entrySet()) {
if (response.get(entry.getKey()) == null) {
theUUID = "noimport_" + 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");
}
logblock.saveConfig();
return true;
}
@ -267,11 +347,11 @@ class Updater
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, 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), UNIQUE (playername))");
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), UNIQUE (UUID))");
// 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` (playername) VALUES ('dummy_record')");
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()) {

View File

@ -147,8 +147,8 @@ public class WorldEditor implements Runnable
private class Edit extends BlockChange
{
public Edit(long time, Location loc, String playerName, int replaced, int type, byte data, String signtext, ChestAccess ca) {
super(time, loc, playerName, replaced, type, data, signtext, ca);
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 {

View File

@ -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;
import org.bukkit.Location;
@ -13,7 +14,7 @@ public class BlockChangePreLogEvent extends PreLogEvent {
private String signText;
private ChestAccess chestAccess;
public BlockChangePreLogEvent(String owner, Location location, int typeBefore, int typeAfter, byte data,
public BlockChangePreLogEvent(Actor owner, Location location, int typeBefore, int typeAfter, byte data,
String signText, ChestAccess chestAccess) {
super(owner);

View File

@ -1,24 +1,36 @@
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 String owner;
protected Actor owner;
public PreLogEvent(String owner) {
public PreLogEvent(Actor owner) {
this.owner = owner.replaceAll("[^a-zA-Z0-9_]", "");
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() {
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;
}
@ -27,9 +39,9 @@ public abstract class PreLogEvent extends Event implements Cancellable {
*
* @param owner The player/monster/cause who is involved in this event
*/
public void setOwner(String owner) {
public void setOwner(Actor owner) {
this.owner = owner.replaceAll("[^a-zA-Z0-9_]", "");
this.owner = owner;
}
public boolean isCancelled() {

View File

@ -1,5 +1,6 @@
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;
@ -29,33 +30,33 @@ public class BlockBreakLogging extends LoggingListener
WorldConfig wcfg = getWorldConfig(event.getBlock().getWorld());
if (wcfg == null) return;
final String playerName = event.getPlayer().getName();
final Actor actor = Actor.actorFromEntity(event.getPlayer());
final Block origin = event.getBlock();
final int typeId = origin.getTypeId();
final Material type = origin.getType();
if (wcfg.isLogging(Logging.SIGNTEXT) && (typeId == 63 || typeId == 68)) {
consumer.queueSignBreak(playerName, (Sign) origin.getState());
consumer.queueSignBreak(actor, (Sign) origin.getState());
} else if (wcfg.isLogging(Logging.CHESTACCESS) && BukkitUtils.getContainerBlocks().contains(type)) {
consumer.queueContainerBreak(playerName, origin.getState());
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(playerName, origin.getState());
consumer.queueBlockBreak(actor, origin.getState());
} else {
consumer.queueBlockReplace(playerName, origin.getState(), 9, (byte) 0);
consumer.queueBlockReplace(actor, origin.getState(), 9, (byte) 0);
}
} else {
smartLogBlockBreak(consumer, playerName, origin);
smartLogBlockBreak(consumer, actor, origin);
}
smartLogFallables(consumer, playerName, 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(event.getPlayer().getName(), event.getBlockClicked().getState());
consumer.queueBlockBreak(Actor.actorFromEntity(event.getPlayer()), event.getBlockClicked().getState());
}
}
}

View File

@ -1,13 +1,14 @@
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.BlockBurnEvent;
import de.diddiz.LogBlock.LogBlock;
import de.diddiz.LogBlock.Logging;
public class BlockBurnLogging extends LoggingListener
{
@ -18,8 +19,8 @@ public class BlockBurnLogging extends LoggingListener
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onBlockBurn(BlockBurnEvent event) {
if (isLogging(event.getBlock().getWorld(), Logging.FIRE)) {
smartLogBlockBreak(consumer, "Fire", event.getBlock());
smartLogFallables(consumer, "Fire", event.getBlock());
smartLogBlockBreak(consumer, new Actor("Fire"), event.getBlock());
smartLogFallables(consumer, new Actor("Fire"), event.getBlock());
}
}
}

View File

@ -1,5 +1,6 @@
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;
@ -29,14 +30,14 @@ public class BlockPlaceLogging extends LoggingListener
final Material type = event.getBlock().getType();
final BlockState before = event.getBlockReplacedState();
final BlockState after = event.getBlockPlaced().getState();
final String playerName = event.getPlayer().getName();
final Actor actor = Actor.actorFromEntity(event.getPlayer());
//Handle falling blocks
if (BukkitUtils.getRelativeTopFallables().contains(type)) {
// Catch placed blocks overwriting something
if (before.getType() != Material.AIR) {
consumer.queueBlockBreak(playerName, before);
consumer.queueBlockBreak(actor, before);
}
Location loc = event.getBlock().getLocation();
@ -55,9 +56,9 @@ public class BlockPlaceLogging extends LoggingListener
// 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(playerName, finalLoc, type.getId(), event.getBlock().getData());
consumer.queueBlockPlace(actor, finalLoc, type.getId(), event.getBlock().getData());
} else {
consumer.queueBlockReplace(playerName, finalLoc, finalLoc.getBlock().getTypeId(), finalLoc.getBlock().getData(), type.getId(), event.getBlock().getData());
consumer.queueBlockReplace(actor, finalLoc, finalLoc.getBlock().getTypeId(), finalLoc.getBlock().getData(), type.getId(), event.getBlock().getData());
}
}
}
@ -73,9 +74,9 @@ public class BlockPlaceLogging extends LoggingListener
@Override
public void run() {
if (before.getTypeId() == 0)
consumer.queueBlockPlace(playerName, after);
consumer.queueBlockPlace(actor, after);
else
consumer.queueBlockReplace(playerName, before, after);
consumer.queueBlockReplace(actor, before, after);
}
}, 1L);
}
@ -84,6 +85,6 @@ public class BlockPlaceLogging extends LoggingListener
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onPlayerBucketEmpty(PlayerBucketEmptyEvent event) {
if (isLogging(event.getPlayer().getWorld(), Logging.BLOCKPLACE))
consumer.queueBlockPlace(event.getPlayer().getName(), event.getBlockClicked().getRelative(event.getBlockFace()).getLocation(), event.getBucket() == Material.WATER_BUCKET ? 9 : 11, (byte)0);
consumer.queueBlockPlace(Actor.actorFromEntity(event.getPlayer()), event.getBlockClicked().getRelative(event.getBlockFace()).getLocation(), event.getBucket() == Material.WATER_BUCKET ? 9 : 11, (byte)0);
}
}

View File

@ -1,15 +1,15 @@
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;
import static de.diddiz.LogBlock.config.Config.isLogging;
public class BlockSpreadLogging extends LoggingListener
{
@ -47,6 +47,6 @@ public class BlockSpreadLogging extends LoggingListener
return;
}
consumer.queueBlockReplace(name, event.getBlock().getState(), event.getNewState());
consumer.queueBlockReplace(new Actor(name), event.getBlock().getState(), event.getNewState());
}
}

View File

@ -1,13 +1,14 @@
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;
import de.diddiz.LogBlock.LogBlock;
import de.diddiz.LogBlock.Logging;
public class ChatLogging extends LoggingListener
{
@ -18,17 +19,17 @@ public class ChatLogging extends LoggingListener
@EventHandler(priority = EventPriority.MONITOR)
public void onPlayerCommandPreprocess(PlayerCommandPreprocessEvent event) {
if (isLogging(event.getPlayer().getWorld(), Logging.CHAT))
consumer.queueChat(event.getPlayer().getName(), event.getMessage());
consumer.queueChat(Actor.actorFromEntity(event.getPlayer()), event.getMessage());
}
@EventHandler(priority = EventPriority.MONITOR)
public void onPlayerChat(AsyncPlayerChatEvent event) {
if (isLogging(event.getPlayer().getWorld(), Logging.CHAT))
consumer.queueChat(event.getPlayer().getName(), event.getMessage());
consumer.queueChat(Actor.actorFromEntity(event.getPlayer()), event.getMessage());
}
@EventHandler(priority = EventPriority.MONITOR)
public void onServerCommand(ServerCommandEvent event) {
consumer.queueChat("Console", "/" + event.getCommand());
consumer.queueChat(new Actor("Console"), "/" + event.getCommand());
}
}

View File

@ -1,5 +1,6 @@
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;
@ -43,7 +44,7 @@ public class ChestAccessLogging extends LoggingListener
final ItemStack[] diff = compareInventories(before, after);
final Location loc = getInventoryHolderLocation(holder);
for (final ItemStack item : diff) {
consumer.queueChestAccess(player.getName(), loc, loc.getWorld().getBlockTypeIdAt(loc), (short)item.getTypeId(), (short)item.getAmount(), rawData(item));
consumer.queueChestAccess(Actor.actorFromEntity(player), loc, loc.getWorld().getBlockTypeIdAt(loc), (short)item.getTypeId(), (short)item.getAmount(), rawData(item));
}
containers.remove(player);
}

View File

@ -1,7 +1,9 @@
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;
@ -14,8 +16,6 @@ import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.entity.EntityInteractEvent;
import static de.diddiz.LogBlock.config.Config.getWorldConfig;
public class CreatureInteractLogging extends LoggingListener
{
public CreatureInteractLogging(LogBlock lb) {
@ -42,11 +42,11 @@ public class CreatureInteractLogging extends LoggingListener
case SOIL:
if (wcfg.isLogging(Logging.CREATURECROPTRAMPLE)) {
// 3 = Dirt ID
consumer.queueBlock(entityType.getName(), loc, typeId, 3, blockData);
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("CreatureTrample", trampledCrop.getState());
consumer.queueBlockBreak(new Actor("CreatureTrample"), trampledCrop.getState());
}
}
break;

View File

@ -1,12 +1,13 @@
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;
import de.diddiz.LogBlock.LogBlock;
import de.diddiz.LogBlock.Logging;
public class EndermenLogging extends LoggingListener
{
@ -17,6 +18,6 @@ public class EndermenLogging extends LoggingListener
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onEntityChangeBlock(EntityChangeBlockEvent event) {
if (event.getEntity() instanceof Enderman && isLogging(event.getBlock().getWorld(), Logging.ENDERMEN))
consumer.queueBlockReplace("Enderman", event.getBlock().getState(), event.getTo().getId(), (byte)0); // Figure out how to get the data of the placed block;
consumer.queueBlockReplace(new Actor("Enderman"), event.getBlock().getState(), event.getTo().getId(), (byte)0); // Figure out how to get the data of the placed block;
}
}

View File

@ -1,8 +1,13 @@
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 static de.diddiz.LogBlock.config.Config.logCreeperExplosionsAsPlayerWhoTriggeredThese;
import de.diddiz.LogBlock.config.WorldConfig;
import static de.diddiz.util.BukkitUtils.getContainerBlocks;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.Sign;
import org.bukkit.entity.Creeper;
@ -10,19 +15,14 @@ import org.bukkit.entity.EnderDragon;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Fireball;
import org.bukkit.entity.Ghast;
import org.bukkit.entity.minecart.ExplosiveMinecart;
import org.bukkit.entity.Player;
import org.bukkit.entity.TNTPrimed;
import org.bukkit.entity.Wither;
import org.bukkit.entity.WitherSkull;
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.Material;
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
{
@ -34,7 +34,7 @@ public class ExplosionLogging extends LoggingListener
public void onEntityExplode(EntityExplodeEvent event) {
final WorldConfig wcfg = getWorldConfig(event.getLocation().getWorld());
if (wcfg != null) {
String name = "Explosion";
Actor actor = new Actor("Explosion");
Entity source = event.getEntity();
if (source == null) {
if (!wcfg.isLogging(Logging.MISCEXPLOSION))
@ -42,19 +42,19 @@ public class ExplosionLogging extends LoggingListener
} else if (source instanceof TNTPrimed) {
if (!wcfg.isLogging(Logging.TNTEXPLOSION))
return;
name = "TNT";
actor = new Actor("TNT");
} else if (source instanceof ExplosiveMinecart) {
if (!wcfg.isLogging(Logging.TNTMINECARTEXPLOSION))
return;
name = "TNTMinecart";
actor = new Actor("TNTMinecart");
} else if (source instanceof Creeper) {
if (!wcfg.isLogging(Logging.CREEPEREXPLOSION))
return;
if (logCreeperExplosionsAsPlayerWhoTriggeredThese) {
final Entity target = ((Creeper) source).getTarget();
name = target instanceof Player ? ((Player)target).getName() : "Creeper";
actor = target instanceof Player ? Actor.actorFromEntity(target) : new Actor("Creeper");
} else
name = "Creeper";
new Actor("Creeper");
} else if (source instanceof Fireball) {
Fireball fireball = (Fireball) source;
Entity shooter = fireball.getShooter();
@ -65,25 +65,25 @@ public class ExplosionLogging extends LoggingListener
if (!wcfg.isLogging(Logging.GHASTFIREBALLEXPLOSION)) {
return;
}
name = "Ghast";
actor = Actor.actorFromEntity(shooter);
} else if (shooter instanceof Wither) {
if (!wcfg.isLogging(Logging.WITHER)) {
return;
}
name = "Wither";
actor = Actor.actorFromEntity(shooter);
}
} else if (source instanceof EnderDragon) {
if (!wcfg.isLogging(Logging.ENDERDRAGON))
return;
name = "EnderDragon";
actor = Actor.actorFromEntity(source);
} else if (source instanceof Wither) {
if(!wcfg.isLogging(Logging.WITHER))
return;
name = "Wither";
actor = Actor.actorFromEntity(source);
} else if (source instanceof WitherSkull) {
if(!wcfg.isLogging(Logging.WITHER_SKULL))
return;
name = "WitherSkull";
actor = Actor.actorFromEntity(source);
} else {
if (!wcfg.isLogging(Logging.MISCEXPLOSION))
return;
@ -91,11 +91,11 @@ public class ExplosionLogging extends LoggingListener
for (final Block block : event.blockList()) {
final int type = block.getTypeId();
if (wcfg.isLogging(Logging.SIGNTEXT) & (type == 63 || type == 68))
consumer.queueSignBreak(name, (Sign)block.getState());
consumer.queueSignBreak(actor, (Sign)block.getState());
else if (wcfg.isLogging(Logging.CHESTACCESS) && (getContainerBlocks().contains(Material.getMaterial(type))))
consumer.queueContainerBreak(name, block.getState());
consumer.queueContainerBreak(actor, block.getState());
else
consumer.queueBlockBreak(name, block.getState());
consumer.queueBlockBreak(actor, block.getState());
}
}
}

View File

@ -1,6 +1,10 @@
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;
@ -9,9 +13,6 @@ import org.bukkit.block.BlockFace;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.block.BlockFromToEvent;
import de.diddiz.LogBlock.LogBlock;
import de.diddiz.LogBlock.Logging;
import de.diddiz.LogBlock.config.WorldConfig;
public class FluidFlowLogging extends LoggingListener
{
@ -32,37 +33,37 @@ public class FluidFlowLogging extends LoggingListener
if (typeFrom == 10 || typeFrom == 11) {
if (canFlow && wcfg.isLogging(Logging.LAVAFLOW)) {
if (isSurroundedByWater(to) && event.getBlock().getData() <= 2)
consumer.queueBlockReplace("LavaFlow", to.getState(), 4, (byte)0);
consumer.queueBlockReplace(new Actor("LavaFlow"), to.getState(), 4, (byte)0);
else if (typeTo == 0) {
consumer.queueBlockPlace("LavaFlow", to.getLocation(), 10, (byte)(event.getBlock().getData() + 1));
consumer.queueBlockPlace(new Actor("LavaFlow"), to.getLocation(), 10, (byte)(event.getBlock().getData() + 1));
} else {
consumer.queueBlockReplace("LavaFlow", to.getState(), 10, (byte)(event.getBlock().getData() + 1));
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("LavaFlow", to.getState(), 1, (byte)0);
consumer.queueBlockReplace(new Actor("LavaFlow"), to.getState(), 1, (byte)0);
} else {
consumer.queueBlockReplace("LavaFlow", to.getState(), 4, (byte)0);
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("WaterFlow", to.getLocation(), 8, (byte)(event.getBlock().getData() + 1));
consumer.queueBlockPlace(new Actor("WaterFlow"), to.getLocation(), 8, (byte)(event.getBlock().getData() + 1));
} else if (nonFluidProofBlocks.contains(typeTo)) {
consumer.queueBlockReplace("WaterFlow", to.getState(), 8, (byte)(event.getBlock().getData() + 1));
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("WaterFlow", to.getState(), 49, (byte)0);
consumer.queueBlockReplace(new Actor("WaterFlow"), to.getState(), 49, (byte)0);
} else if (event.getFace() == BlockFace.DOWN) {
consumer.queueBlockReplace("LavaFlow", to.getState(), 1, (byte)0);
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("WaterFlow", lower.getState(), lower.getData() == 0 ? 49 : 4, (byte)0);
consumer.queueBlockReplace(new Actor("WaterFlow"), lower.getState(), lower.getData() == 0 ? 49 : 4, (byte)0);
}
}
}

View File

@ -1,5 +1,6 @@
package de.diddiz.LogBlock.listeners;
import de.diddiz.LogBlock.Actor;
import static de.diddiz.LogBlock.config.Config.getWorldConfig;
import de.diddiz.util.BukkitUtils;
@ -15,6 +16,7 @@ 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
{
@ -39,31 +41,31 @@ public class InteractLogging extends LoggingListener
case WOOD_BUTTON:
case STONE_BUTTON:
if (wcfg.isLogging(Logging.SWITCHINTERACT) && event.getAction() == Action.RIGHT_CLICK_BLOCK)
consumer.queueBlock(player.getName(), loc, typeId, typeId, blockData);
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(player.getName(), loc, typeId, typeId, blockData);
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(player.getName(), loc, typeId, typeId, blockData);
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(player.getName(), loc, typeId, typeId, blockData);
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(player.getName(), loc, typeId, typeId, blockData);
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(player.getName(), loc, typeId, typeId, blockData);
consumer.queueBlock(Actor.actorFromEntity(player), loc, typeId, typeId, blockData);
}
break;
case WOOD_PLATE:
@ -71,22 +73,22 @@ public class InteractLogging extends LoggingListener
case IRON_PLATE:
case GOLD_PLATE:
if (wcfg.isLogging(Logging.PRESUREPLATEINTERACT) && event.getAction() == Action.PHYSICAL) {
consumer.queueBlock(player.getName(), loc, typeId, typeId, blockData);
consumer.queueBlock(Actor.actorFromEntity(player), loc, typeId, typeId, blockData);
}
break;
case TRIPWIRE:
if (wcfg.isLogging(Logging.TRIPWIREINTERACT) && event.getAction() == Action.PHYSICAL) {
consumer.queueBlock(player.getName(), loc, typeId, typeId, blockData);
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(player.getName(), loc, typeId, 3, blockData);
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(player.getName(), trampledCrop.getState());
consumer.queueBlockBreak(Actor.actorFromEntity(player), trampledCrop.getState());
}
}
break;

View File

@ -1,8 +1,12 @@
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.logKillsLevel;
import static de.diddiz.LogBlock.config.Config.logEnvironmentalKills;
import static de.diddiz.LogBlock.config.Config.logKillsLevel;
import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Monster;
@ -12,9 +16,6 @@ import org.bukkit.event.EventPriority;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.event.entity.EntityDamageEvent;
import org.bukkit.event.entity.EntityDeathEvent;
import de.diddiz.LogBlock.LogBlock;
import de.diddiz.LogBlock.Logging;
import de.diddiz.LogBlock.config.Config.LogKillsLevel;
public class KillLogging extends LoggingListener
@ -42,7 +43,7 @@ public class KillLogging extends LoggingListener
return;
else if (logKillsLevel == LogKillsLevel.MONSTERS && !((victim instanceof Player || victim instanceof Monster)))
return;
consumer.queueKill(event.getCause().toString(),victim);
consumer.queueKill(new Actor(event.getCause().toString()),victim);
}
}
}

View File

@ -1,13 +1,14 @@
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;
import de.diddiz.LogBlock.LogBlock;
import de.diddiz.LogBlock.Logging;
public class LeavesDecayLogging extends LoggingListener
{
@ -18,8 +19,8 @@ public class LeavesDecayLogging extends LoggingListener
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onLeavesDecay(LeavesDecayEvent event) {
if (isLogging(event.getBlock().getWorld(), Logging.LEAVESDECAY)) {
smartLogBlockBreak(consumer, "LeavesDecay", event.getBlock());
smartLogFallables(consumer, "LeavesDecay", event.getBlock());
smartLogBlockBreak(consumer, new Actor("LeavesDecay"), event.getBlock());
smartLogFallables(consumer, new Actor("LeavesDecay"), event.getBlock());
}
}
}

View File

@ -1,11 +1,12 @@
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;
import de.diddiz.LogBlock.LogBlock;
import de.diddiz.LogBlock.Logging;
public class LockedChestDecayLogging extends LoggingListener
{
@ -18,7 +19,7 @@ public class LockedChestDecayLogging extends LoggingListener
if (isLogging(event.getBlock().getWorld(), Logging.LOCKEDCHESTDECAY)) {
final int type = event.getBlock().getTypeId();
if (type == 95)
consumer.queueBlockReplace("LockedChestDecay", event.getBlock().getState(), event.getNewState());
consumer.queueBlockReplace(new Actor("LockedChestDecay"), event.getBlock().getState(), event.getNewState());
}
}
}

View File

@ -1,11 +1,13 @@
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;
import de.diddiz.LogBlock.LogBlock;
import de.diddiz.LogBlock.Logging;
public class SignChangeLogging extends LoggingListener
{
@ -16,6 +18,6 @@ public class SignChangeLogging extends LoggingListener
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onSignChange(SignChangeEvent event) {
if (isLogging(event.getBlock().getWorld(), Logging.SIGNTEXT))
consumer.queueSignPlace(event.getPlayer().getName(), event.getBlock().getLocation(), event.getBlock().getTypeId(), event.getBlock().getData(), event.getLines());
consumer.queueSignPlace(Actor.actorFromEntity(event.getPlayer()), event.getBlock().getLocation(), event.getBlock().getTypeId(), event.getBlock().getData(), event.getLines());
}
}

View File

@ -1,11 +1,12 @@
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;
import de.diddiz.LogBlock.LogBlock;
import de.diddiz.LogBlock.Logging;
public class SnowFadeLogging extends LoggingListener
{
@ -18,7 +19,7 @@ public class SnowFadeLogging extends LoggingListener
if (isLogging(event.getBlock().getWorld(), Logging.SNOWFADE)) {
final int type = event.getBlock().getTypeId();
if (type == 78 || type == 79)
consumer.queueBlockReplace("SnowFade", event.getBlock().getState(), event.getNewState());
consumer.queueBlockReplace(new Actor("SnowFade"), event.getBlock().getState(), event.getNewState());
}
}
}

View File

@ -1,12 +1,13 @@
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;
import de.diddiz.LogBlock.LogBlock;
import de.diddiz.LogBlock.Logging;
public class SnowFormLogging extends LoggingListener
{
@ -14,18 +15,18 @@ public class SnowFormLogging extends LoggingListener
super(lb);
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onLeavesDecay(LeavesDecayEvent event) {
if (isLogging(event.getBlock().getWorld(), Logging.SNOWFORM))
consumer.queueBlockBreak("LeavesDecay", event.getBlock().getState());
}
// @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
// public void onLeavesDecay(LeavesDecayEvent event) {
// if (isLogging(event.getBlock().getWorld(), Logging.SNOWFORM))
// 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("SnowForm", event.getBlock().getState(), event.getNewState());
consumer.queueBlockReplace(new Actor("SnowForm"), event.getBlock().getState(), event.getNewState());
}
}
}

View File

@ -1,13 +1,14 @@
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;
import de.diddiz.LogBlock.LogBlock;
import de.diddiz.LogBlock.Logging;
import de.diddiz.LogBlock.config.WorldConfig;
public class StructureGrowLogging extends LoggingListener
{
@ -19,18 +20,18 @@ public class StructureGrowLogging extends LoggingListener
public void onStructureGrow(StructureGrowEvent event) {
final WorldConfig wcfg = getWorldConfig(event.getWorld());
if (wcfg != null) {
final String playerName;
final Actor actor;
if (event.getPlayer() != null) {
if (!wcfg.isLogging(Logging.BONEMEALSTRUCTUREGROW))
return;
playerName = event.getPlayer().getName();
actor = Actor.actorFromEntity(event.getPlayer());
} else {
if (!wcfg.isLogging(Logging.NATURALSTRUCTUREGROW))
return;
playerName = "NaturalGrow";
actor = new Actor("NaturalGrow");
}
for (final BlockState state : event.getBlocks())
consumer.queueBlockReplace(playerName, state.getBlock().getState(), state);
consumer.queueBlockReplace(actor, state.getBlock().getState(), state);
}
}
}

View File

@ -1,5 +1,6 @@
package de.diddiz.LogBlock.listeners;
import de.diddiz.LogBlock.Actor;
import de.diddiz.LogBlock.LogBlock;
import de.diddiz.LogBlock.Logging;
import org.bukkit.entity.Wither;
@ -18,6 +19,6 @@ public class WitherLogging extends LoggingListener
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onEntityChangeBlock(EntityChangeBlockEvent event) {
if (event.getEntity() instanceof Wither && isLogging(event.getBlock().getWorld(), Logging.WITHER))
consumer.queueBlockReplace("Wither", event.getBlock().getState(), event.getTo().getId(), event.getData()); // Wither walked through a block.
consumer.queueBlockReplace(Actor.actorFromEntity(event.getEntity()), event.getBlock().getState(), event.getTo().getId(), event.getData()); // Wither walked through a block.
}
}

View File

@ -1,6 +1,10 @@
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 de.diddiz.LogBlock.config.WorldConfig;
import java.util.List;
import org.bukkit.Location;
import org.bukkit.Material;
@ -17,13 +21,10 @@ import org.bukkit.material.RedstoneTorch;
import org.bukkit.material.Torch;
import org.bukkit.material.TrapDoor;
import org.bukkit.material.TripwireHook;
import de.diddiz.LogBlock.Consumer;
import de.diddiz.LogBlock.Logging;
import de.diddiz.LogBlock.config.WorldConfig;
public class LoggingUtil {
public static void smartLogFallables(Consumer consumer, String playerName, Block origin) {
public static void smartLogFallables(Consumer consumer, Actor actor, Block origin) {
WorldConfig wcfg = getWorldConfig(origin.getWorld());
if (wcfg == null) return;
@ -35,7 +36,7 @@ public class LoggingUtil {
while (BukkitUtils.getRelativeTopFallables().contains(checkBlock.getType())) {
// Record this block as falling
consumer.queueBlockBreak(playerName, checkBlock.getState());
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();
@ -52,9 +53,9 @@ public class LoggingUtil {
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(playerName, finalLoc, checkBlock.getTypeId(), checkBlock.getData());
consumer.queueBlockPlace(actor, finalLoc, checkBlock.getTypeId(), checkBlock.getData());
} else {
consumer.queueBlockReplace(playerName, finalLoc, finalLoc.getBlock().getTypeId(), finalLoc.getBlock().getData(), checkBlock.getTypeId(), checkBlock.getData());
consumer.queueBlockReplace(actor, finalLoc, finalLoc.getBlock().getTypeId(), finalLoc.getBlock().getData(), checkBlock.getTypeId(), checkBlock.getData());
}
up++;
}
@ -64,7 +65,7 @@ public class LoggingUtil {
}
}
public static void smartLogBlockBreak(Consumer consumer, String playerName, Block origin) {
public static void smartLogBlockBreak(Consumer consumer, Actor actor, Block origin) {
WorldConfig wcfg = getWorldConfig(origin.getWorld());
if (wcfg == null) return;
@ -72,7 +73,7 @@ public class LoggingUtil {
Block checkBlock = origin.getRelative(BlockFace.UP);
if (BukkitUtils.getRelativeTopBreakabls().contains(checkBlock.getType())) {
if (wcfg.isLogging(Logging.SIGNTEXT) && checkBlock.getType() == Material.SIGN_POST) {
consumer.queueSignBreak(playerName, (Sign) checkBlock.getState());
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
@ -81,9 +82,9 @@ public class LoggingUtil {
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(playerName, doorBlock.getState());
consumer.queueBlockBreak(actor, doorBlock.getState());
}
consumer.queueBlockBreak(playerName, checkBlock.getState());
consumer.queueBlockBreak(actor, checkBlock.getState());
}
} else if (checkBlock.getType() == Material.DOUBLE_PLANT) {
Block plantBlock = checkBlock;
@ -93,12 +94,12 @@ public class LoggingUtil {
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(playerName, plantBlock.getState());
consumer.queueBlockBreak(actor, plantBlock.getState());
}
consumer.queueBlockBreak(playerName, checkBlock.getState());
consumer.queueBlockBreak(actor, checkBlock.getState());
}
} else {
consumer.queueBlockBreak(playerName, checkBlock.getState());
consumer.queueBlockBreak(actor, checkBlock.getState());
}
}
@ -112,56 +113,56 @@ public class LoggingUtil {
case REDSTONE_TORCH_ON:
case REDSTONE_TORCH_OFF:
if (blockState.getBlock().getRelative(((RedstoneTorch) data).getAttachedFace()).equals(origin)) {
consumer.queueBlockBreak(playerName, blockState);
consumer.queueBlockBreak(actor, blockState);
}
break;
case TORCH:
if (blockState.getBlock().getRelative(((Torch) data).getAttachedFace()).equals(origin)) {
consumer.queueBlockBreak(playerName, blockState);
consumer.queueBlockBreak(actor, blockState);
}
break;
case COCOA:
if (blockState.getBlock().getRelative(((CocoaPlant) data).getAttachedFace().getOppositeFace()).equals(origin)) {
consumer.queueBlockBreak(playerName, blockState);
consumer.queueBlockBreak(actor, blockState);
}
break;
case LADDER:
if (blockState.getBlock().getRelative(((Ladder) data).getAttachedFace()).equals(origin)) {
consumer.queueBlockBreak(playerName, blockState);
consumer.queueBlockBreak(actor, blockState);
}
break;
case LEVER:
if (blockState.getBlock().getRelative(((Lever) data).getAttachedFace()).equals(origin)) {
consumer.queueBlockBreak(playerName, blockState);
consumer.queueBlockBreak(actor, blockState);
}
break;
case TRIPWIRE_HOOK:
if (blockState.getBlock().getRelative(((TripwireHook) data).getAttachedFace()).equals(origin)) {
consumer.queueBlockBreak(playerName, blockState);
consumer.queueBlockBreak(actor, blockState);
}
break;
case WOOD_BUTTON:
case STONE_BUTTON:
if (blockState.getBlock().getRelative(((Button) data).getAttachedFace()).equals(origin)) {
consumer.queueBlockBreak(playerName, blockState);
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(playerName, (Sign) blockState);
consumer.queueSignBreak(actor, (Sign) blockState);
} else {
consumer.queueBlockBreak(playerName, blockState);
consumer.queueBlockBreak(actor, blockState);
}
}
break;
case TRAP_DOOR:
if (blockState.getBlock().getRelative(((TrapDoor) data).getAttachedFace()).equals(origin)) {
consumer.queueBlockBreak(playerName, blockState);
consumer.queueBlockBreak(actor, blockState);
}
break;
default:
consumer.queueBlockBreak(playerName, blockState);
consumer.queueBlockBreak(actor, blockState);
break;
}
}
@ -179,7 +180,7 @@ public class LoggingUtil {
}
if (doorBlock.getType() == Material.IRON_DOOR_BLOCK || doorBlock.getType() == Material.WOODEN_DOOR) {
consumer.queueBlockBreak(playerName, doorBlock.getState());
consumer.queueBlockBreak(actor, doorBlock.getState());
}
} else if (origin.getType() == Material.DOUBLE_PLANT) { // Special double plant check
Block plantBlock = origin;
@ -192,11 +193,11 @@ public class LoggingUtil {
}
if (plantBlock.getType() == Material.DOUBLE_PLANT) {
consumer.queueBlockBreak(playerName, plantBlock.getState());
consumer.queueBlockBreak(actor, plantBlock.getState());
}
}
// Do this down here so that the block is added after blocks sitting on it
consumer.queueBlockBreak(playerName, origin.getState());
consumer.queueBlockBreak(actor, origin.getState());
}
}

View File

@ -0,0 +1,79 @@
package de.diddiz.util;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
// Adapted from https://gist.github.com/evilmidget38/26d70114b834f71fb3b4
public class UUIDFetcher {
private static final String PROFILE_URL = "https://api.mojang.com/profiles/minecraft";
private static final JSONParser jsonParser = new JSONParser();
public static Map<String, UUID> getUUIDs(List<String> names) throws Exception {
Map<String, UUID> uuidMap = new HashMap<String, UUID>();
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 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));
}
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);
}
}

View File

@ -57,7 +57,7 @@ public class LogBlockEditSession extends EditSession {
// 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(player.getName(), (Sign) stateBefore);
plugin.getConsumer().queueSignBreak(player, (Sign) stateBefore);
if (block.getType() != Material.AIR.getId()) {
plugin.getConsumer().queueBlockPlace(player.getName(), location, block.getType(), (byte) block.getData());
}

View File

@ -1,5 +1,5 @@
name: ${project.name}
version: '1.81'
version: '1.9'
author: DiddiZ
authors: [md_5, ammar2, frymaster]
website: http://dev.bukkit.org/server-mods/logblock/