forked from LogBlock/LogBlock
Serialize BlockStates
Banner, spawner and player heads can now be rolled back
This commit is contained in:
2
pom.xml
2
pom.xml
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
<groupId>de.diddiz</groupId>
|
<groupId>de.diddiz</groupId>
|
||||||
<artifactId>logblock</artifactId>
|
<artifactId>logblock</artifactId>
|
||||||
<version>1.13-SNAPSHOT</version>
|
<version>1.13.1-SNAPSHOT</version>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
<name>LogBlock</name>
|
<name>LogBlock</name>
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
package de.diddiz.LogBlock;
|
package de.diddiz.LogBlock;
|
||||||
|
|
||||||
|
import de.diddiz.LogBlock.blockstate.BlockStateCodecs;
|
||||||
import de.diddiz.LogBlock.config.Config;
|
import de.diddiz.LogBlock.config.Config;
|
||||||
import de.diddiz.util.BukkitUtils;
|
import de.diddiz.util.BukkitUtils;
|
||||||
import de.diddiz.util.Utils;
|
import de.diddiz.util.Utils;
|
||||||
@@ -14,29 +15,28 @@ import org.bukkit.inventory.ItemStack;
|
|||||||
|
|
||||||
import java.sql.ResultSet;
|
import java.sql.ResultSet;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
|
import java.util.logging.Level;
|
||||||
import static de.diddiz.util.LoggingUtil.checkText;
|
|
||||||
|
|
||||||
public class BlockChange implements LookupCacheElement {
|
public class BlockChange implements LookupCacheElement {
|
||||||
public final long id, date;
|
public final long id, date;
|
||||||
public final Location loc;
|
public final Location loc;
|
||||||
public final Actor actor;
|
public final Actor actor;
|
||||||
public final String playerName;
|
public final String playerName;
|
||||||
// public final BlockData replaced, type;
|
|
||||||
public final int replacedMaterial, replacedData, typeMaterial, typeData;
|
public final int replacedMaterial, replacedData, typeMaterial, typeData;
|
||||||
public final String signtext;
|
public final byte[] replacedState, typeState;
|
||||||
public final ChestAccess ca;
|
public final ChestAccess ca;
|
||||||
|
|
||||||
public BlockChange(long date, Location loc, Actor actor, int replaced, int replacedData, int type, int typeData, String signtext, ChestAccess ca) {
|
public BlockChange(long date, Location loc, Actor actor, int replaced, int replacedData, byte[] replacedState, int type, int typeData, byte[] typeState, ChestAccess ca) {
|
||||||
id = 0;
|
id = 0;
|
||||||
this.date = date;
|
this.date = date;
|
||||||
this.loc = loc;
|
this.loc = loc;
|
||||||
this.actor = actor;
|
this.actor = actor;
|
||||||
this.replacedMaterial = replaced;
|
this.replacedMaterial = replaced;
|
||||||
this.replacedData = replacedData;
|
this.replacedData = replacedData;
|
||||||
|
this.replacedState = replacedState;
|
||||||
this.typeMaterial = type;
|
this.typeMaterial = type;
|
||||||
this.typeData = typeData;
|
this.typeData = typeData;
|
||||||
this.signtext = checkText(signtext);
|
this.typeState = typeState;
|
||||||
this.ca = ca;
|
this.ca = ca;
|
||||||
this.playerName = actor == null ? null : actor.getName();
|
this.playerName = actor == null ? null : actor.getName();
|
||||||
}
|
}
|
||||||
@@ -51,7 +51,8 @@ public class BlockChange implements LookupCacheElement {
|
|||||||
replacedData = p.needType ? rs.getInt("replacedData") : -1;
|
replacedData = p.needType ? rs.getInt("replacedData") : -1;
|
||||||
typeMaterial = p.needType ? rs.getInt("type") : 0;
|
typeMaterial = p.needType ? rs.getInt("type") : 0;
|
||||||
typeData = p.needType ? rs.getInt("typeData") : -1;
|
typeData = p.needType ? rs.getInt("typeData") : -1;
|
||||||
signtext = p.needSignText ? rs.getString("signtext") : null;
|
replacedState = p.needType ? rs.getBytes("replacedState") : null;
|
||||||
|
typeState = p.needType ? rs.getBytes("typeState") : null;
|
||||||
ChestAccess catemp = null;
|
ChestAccess catemp = null;
|
||||||
if (p.needChestAccess) {
|
if (p.needChestAccess) {
|
||||||
ItemStack stack = Utils.loadItemStack(rs.getBytes("item"));
|
ItemStack stack = Utils.loadItemStack(rs.getBytes("item"));
|
||||||
@@ -66,6 +67,32 @@ public class BlockChange implements LookupCacheElement {
|
|||||||
public String toString() {
|
public String toString() {
|
||||||
BlockData type = MaterialConverter.getBlockData(typeMaterial, typeData);
|
BlockData type = MaterialConverter.getBlockData(typeMaterial, typeData);
|
||||||
BlockData replaced = MaterialConverter.getBlockData(replacedMaterial, replacedData);
|
BlockData replaced = MaterialConverter.getBlockData(replacedMaterial, replacedData);
|
||||||
|
String typeDetails = null;
|
||||||
|
if (BlockStateCodecs.hasCodec(type.getMaterial())) {
|
||||||
|
try {
|
||||||
|
typeDetails = BlockStateCodecs.toString(type.getMaterial(), typeState);
|
||||||
|
} catch (Exception e) {
|
||||||
|
LogBlock.getInstance().getLogger().log(Level.SEVERE, "Could not parse BlockState for " + type.getMaterial(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (typeDetails == null) {
|
||||||
|
typeDetails = "";
|
||||||
|
} else {
|
||||||
|
typeDetails = " " + typeDetails;
|
||||||
|
}
|
||||||
|
String replacedDetails = null;
|
||||||
|
if (BlockStateCodecs.hasCodec(replaced.getMaterial())) {
|
||||||
|
try {
|
||||||
|
replacedDetails = BlockStateCodecs.toString(replaced.getMaterial(), replacedState);
|
||||||
|
} catch (Exception e) {
|
||||||
|
LogBlock.getInstance().getLogger().log(Level.SEVERE, "Could not parse BlockState for " + replaced.getMaterial(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (replacedDetails == null) {
|
||||||
|
replacedDetails = "";
|
||||||
|
} else {
|
||||||
|
replacedDetails = " " + replacedDetails;
|
||||||
|
}
|
||||||
final StringBuilder msg = new StringBuilder();
|
final StringBuilder msg = new StringBuilder();
|
||||||
if (date > 0) {
|
if (date > 0) {
|
||||||
msg.append(Config.formatter.format(date)).append(" ");
|
msg.append(Config.formatter.format(date)).append(" ");
|
||||||
@@ -73,14 +100,7 @@ public class BlockChange implements LookupCacheElement {
|
|||||||
if (actor != null) {
|
if (actor != null) {
|
||||||
msg.append(actor.getName()).append(" ");
|
msg.append(actor.getName()).append(" ");
|
||||||
}
|
}
|
||||||
if (signtext != null) {
|
if (type.equals(replaced)) {
|
||||||
final String action = BukkitUtils.isEmpty(type.getMaterial()) ? "destroyed " : "created ";
|
|
||||||
if (!signtext.contains("\0")) {
|
|
||||||
msg.append(action).append(signtext);
|
|
||||||
} else {
|
|
||||||
msg.append(action).append((!BukkitUtils.isEmpty(type.getMaterial()) ? type : replaced).getMaterial().name()).append(" [").append(signtext.replace("\0", "] [")).append("]");
|
|
||||||
}
|
|
||||||
} else if (type.equals(replaced)) {
|
|
||||||
if (BukkitUtils.isEmpty(type.getMaterial())) {
|
if (BukkitUtils.isEmpty(type.getMaterial())) {
|
||||||
msg.append("did an unspecified action");
|
msg.append("did an unspecified action");
|
||||||
} else if (ca != null) {
|
} else if (ca != null) {
|
||||||
@@ -110,11 +130,11 @@ public class BlockChange implements LookupCacheElement {
|
|||||||
msg.append("ran into ").append(type.getMaterial().name());
|
msg.append("ran into ").append(type.getMaterial().name());
|
||||||
}
|
}
|
||||||
} else if (BukkitUtils.isEmpty(type.getMaterial())) {
|
} else if (BukkitUtils.isEmpty(type.getMaterial())) {
|
||||||
msg.append("destroyed ").append(replaced.getMaterial().name());
|
msg.append("destroyed ").append(replaced.getMaterial().name()).append(replacedDetails);
|
||||||
} else if (BukkitUtils.isEmpty(replaced.getMaterial())) {
|
} else if (BukkitUtils.isEmpty(replaced.getMaterial())) {
|
||||||
msg.append("created ").append(type.getMaterial().name());
|
msg.append("created ").append(type.getMaterial().name()).append(typeDetails);
|
||||||
} else {
|
} else {
|
||||||
msg.append("replaced ").append(replaced.getMaterial().name()).append(" with ").append(type.getMaterial().name());
|
msg.append("replaced ").append(replaced.getMaterial().name()).append(replacedDetails).append(" with ").append(type.getMaterial().name()).append(typeDetails);
|
||||||
}
|
}
|
||||||
if (loc != null) {
|
if (loc != null) {
|
||||||
msg.append(" at ").append(loc.getBlockX()).append(":").append(loc.getBlockY()).append(":").append(loc.getBlockZ());
|
msg.append(" at ").append(loc.getBlockX()).append(":").append(loc.getBlockY()).append(":").append(loc.getBlockZ());
|
||||||
|
@@ -10,7 +10,6 @@ import de.diddiz.util.Utils;
|
|||||||
|
|
||||||
import org.bukkit.ChatColor;
|
import org.bukkit.ChatColor;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.Material;
|
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
import org.bukkit.command.Command;
|
import org.bukkit.command.Command;
|
||||||
import org.bukkit.command.CommandExecutor;
|
import org.bukkit.command.CommandExecutor;
|
||||||
@@ -456,9 +455,6 @@ public class CommandsHandler implements CommandExecutor {
|
|||||||
params.needType = true;
|
params.needType = true;
|
||||||
params.needData = true;
|
params.needData = true;
|
||||||
params.needPlayer = true;
|
params.needPlayer = true;
|
||||||
if (params.types.isEmpty() || params.types.contains(Material.SIGN) || params.types.contains(Material.WALL_SIGN)) {
|
|
||||||
params.needSignText = true;
|
|
||||||
}
|
|
||||||
if (params.bct == BlockChangeType.CHESTACCESS || params.bct == BlockChangeType.ALL) {
|
if (params.bct == BlockChangeType.CHESTACCESS || params.bct == BlockChangeType.ALL) {
|
||||||
params.needChestAccess = true;
|
params.needChestAccess = true;
|
||||||
}
|
}
|
||||||
@@ -521,9 +517,6 @@ public class CommandsHandler implements CommandExecutor {
|
|||||||
params.needType = true;
|
params.needType = true;
|
||||||
params.needData = true;
|
params.needData = true;
|
||||||
params.needPlayer = true;
|
params.needPlayer = true;
|
||||||
if (params.types.isEmpty() || params.types.contains(Material.SIGN) || params.types.contains(Material.WALL_SIGN)) {
|
|
||||||
params.needSignText = true;
|
|
||||||
}
|
|
||||||
if (params.bct == BlockChangeType.CHESTACCESS || params.bct == BlockChangeType.ALL) {
|
if (params.bct == BlockChangeType.CHESTACCESS || params.bct == BlockChangeType.ALL) {
|
||||||
params.needChestAccess = true;
|
params.needChestAccess = true;
|
||||||
}
|
}
|
||||||
@@ -646,7 +639,6 @@ public class CommandsHandler implements CommandExecutor {
|
|||||||
params.needCoords = true;
|
params.needCoords = true;
|
||||||
params.needType = true;
|
params.needType = true;
|
||||||
params.needData = true;
|
params.needData = true;
|
||||||
params.needSignText = true;
|
|
||||||
params.needChestAccess = true;
|
params.needChestAccess = true;
|
||||||
params.order = Order.DESC;
|
params.order = Order.DESC;
|
||||||
params.sum = SummarizationMode.NONE;
|
params.sum = SummarizationMode.NONE;
|
||||||
@@ -674,7 +666,7 @@ public class CommandsHandler implements CommandExecutor {
|
|||||||
if (stack != null) {
|
if (stack != null) {
|
||||||
chestaccess = new ChestAccess(stack, rs.getBoolean("itemremove"));
|
chestaccess = new ChestAccess(stack, rs.getBoolean("itemremove"));
|
||||||
}
|
}
|
||||||
editor.queueEdit(rs.getInt("x"), rs.getInt("y"), rs.getInt("z"), rs.getInt("replaced"), rs.getInt("replacedData"), rs.getInt("type"), rs.getInt("typeData"), rs.getString("signtext"), chestaccess);
|
editor.queueEdit(rs.getInt("x"), rs.getInt("y"), rs.getInt("z"), rs.getInt("replaced"), rs.getInt("replacedData"), rs.getBytes("replacedState"), rs.getInt("type"), rs.getInt("typeData"), rs.getBytes("typeState"), chestaccess);
|
||||||
}
|
}
|
||||||
final int changes = editor.getSize();
|
final int changes = editor.getSize();
|
||||||
if (changes > 10000) {
|
if (changes > 10000) {
|
||||||
@@ -725,7 +717,6 @@ public class CommandsHandler implements CommandExecutor {
|
|||||||
params.needCoords = true;
|
params.needCoords = true;
|
||||||
params.needType = true;
|
params.needType = true;
|
||||||
params.needData = true;
|
params.needData = true;
|
||||||
params.needSignText = true;
|
|
||||||
params.needChestAccess = true;
|
params.needChestAccess = true;
|
||||||
params.order = Order.ASC;
|
params.order = Order.ASC;
|
||||||
params.sum = SummarizationMode.NONE;
|
params.sum = SummarizationMode.NONE;
|
||||||
@@ -749,7 +740,7 @@ public class CommandsHandler implements CommandExecutor {
|
|||||||
if (stack != null) {
|
if (stack != null) {
|
||||||
chestaccess = new ChestAccess(stack, !rs.getBoolean("itemremove"));
|
chestaccess = new ChestAccess(stack, !rs.getBoolean("itemremove"));
|
||||||
}
|
}
|
||||||
editor.queueEdit(rs.getInt("x"), rs.getInt("y"), rs.getInt("z"), rs.getInt("type"), rs.getInt("typeData"), rs.getInt("replaced"), rs.getInt("replacedData"), rs.getString("signtext"), chestaccess);
|
editor.queueEdit(rs.getInt("x"), rs.getInt("y"), rs.getInt("z"), rs.getInt("type"), rs.getInt("typeData"), rs.getBytes("typeState"), rs.getInt("replaced"), rs.getInt("replacedData"), rs.getBytes("replacedState"), chestaccess);
|
||||||
}
|
}
|
||||||
final int changes = editor.getSize();
|
final int changes = editor.getSize();
|
||||||
if (!params.silent) {
|
if (!params.silent) {
|
||||||
@@ -824,23 +815,23 @@ public class CommandsHandler implements CommandExecutor {
|
|||||||
state.execute("DELETE `" + table + "` FROM `" + table + "-blocks` " + join + params.getWhere());
|
state.execute("DELETE `" + table + "` FROM `" + table + "-blocks` " + join + params.getWhere());
|
||||||
sender.sendMessage(ChatColor.GREEN + "Cleared out table " + table + ". Deleted " + deleted + " entries.");
|
sender.sendMessage(ChatColor.GREEN + "Cleared out table " + table + ". Deleted " + deleted + " entries.");
|
||||||
}
|
}
|
||||||
rs = state.executeQuery("SELECT COUNT(*) FROM `" + table + "-sign` LEFT JOIN `" + table + "-blocks` USING (id) WHERE `" + table + "-blocks`.id IS NULL");
|
rs = state.executeQuery("SELECT COUNT(*) FROM `" + table + "-state` LEFT JOIN `" + table + "-blocks` USING (id) WHERE `" + table + "-blocks`.id IS NULL");
|
||||||
rs.next();
|
rs.next();
|
||||||
if ((deleted = rs.getInt(1)) > 0) {
|
if ((deleted = rs.getInt(1)) > 0) {
|
||||||
if (dumpDeletedLog) {
|
if (dumpDeletedLog) {
|
||||||
state.execute("SELECT id, signtext FROM `" + table + "-sign` LEFT JOIN `" + table + "-blocks` USING (id) WHERE `" + table + "-blocks`.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("SELECT id, replacedState, typeState FROM `" + table + "-state` LEFT JOIN `" + table + "-blocks` USING (id) WHERE `" + table + "-blocks`.id IS NULL INTO OUTFILE '" + new File(dumpFolder, time + " " + table + "-state " + 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 + "-blocks` USING (id) WHERE `" + table + "-blocks`.id IS NULL;");
|
state.execute("DELETE `" + table + "-state` FROM `" + table + "-state` LEFT JOIN `" + table + "-blocks` USING (id) WHERE `" + table + "-blocks`.id IS NULL;");
|
||||||
sender.sendMessage(ChatColor.GREEN + "Cleared out table " + table + "-sign. Deleted " + deleted + " entries.");
|
sender.sendMessage(ChatColor.GREEN + "Cleared out table " + table + "-state. Deleted " + deleted + " entries.");
|
||||||
}
|
}
|
||||||
rs = state.executeQuery("SELECT COUNT(*) FROM `" + table + "-chestdata` LEFT JOIN `" + table + "-blocks` USING (id) WHERE `" + table + "-blocks`.id IS NULL");
|
rs = state.executeQuery("SELECT COUNT(*) FROM `" + table + "-chestdata` LEFT JOIN `" + table + "-blocks` USING (id) WHERE `" + table + "-blocks`.id IS NULL");
|
||||||
rs.next();
|
rs.next();
|
||||||
if ((deleted = rs.getInt(1)) > 0) {
|
if ((deleted = rs.getInt(1)) > 0) {
|
||||||
if (dumpDeletedLog) {
|
if (dumpDeletedLog) {
|
||||||
state.execute("SELECT id, item, itemremove FROM `" + table + "-chest` LEFT JOIN `" + table + "-blocks` USING (id) WHERE `" + table + "-blocks`.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("SELECT id, item, itemremove FROM `" + table + "-chestdata` LEFT JOIN `" + table + "-blocks` USING (id) WHERE `" + table + "-blocks`.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 + "-blocks` USING (id) WHERE `" + table + "-blocks`.id IS NULL;");
|
state.execute("DELETE `" + table + "-chestdata` FROM `" + table + "-chestdata` LEFT JOIN `" + table + "-blocks` USING (id) WHERE `" + table + "-blocks`.id IS NULL;");
|
||||||
sender.sendMessage(ChatColor.GREEN + "Cleared out table " + table + "-chest. Deleted " + deleted + " entries.");
|
sender.sendMessage(ChatColor.GREEN + "Cleared out table " + table + "-chestdata. Deleted " + deleted + " entries.");
|
||||||
}
|
}
|
||||||
} catch (final Exception ex) {
|
} catch (final Exception ex) {
|
||||||
sender.sendMessage(ChatColor.RED + "Exception, check error log");
|
sender.sendMessage(ChatColor.RED + "Exception, check error log");
|
||||||
|
@@ -1,5 +1,7 @@
|
|||||||
package de.diddiz.LogBlock;
|
package de.diddiz.LogBlock;
|
||||||
|
|
||||||
|
import de.diddiz.LogBlock.blockstate.BlockStateCodecSign;
|
||||||
|
import de.diddiz.LogBlock.blockstate.BlockStateCodecs;
|
||||||
import de.diddiz.LogBlock.config.Config;
|
import de.diddiz.LogBlock.config.Config;
|
||||||
import de.diddiz.LogBlock.events.BlockChangePreLogEvent;
|
import de.diddiz.LogBlock.events.BlockChangePreLogEvent;
|
||||||
import de.diddiz.util.Utils;
|
import de.diddiz.util.Utils;
|
||||||
@@ -63,7 +65,7 @@ public class Consumer extends TimerTask {
|
|||||||
* Data of the block after the change
|
* Data of the block after the change
|
||||||
*/
|
*/
|
||||||
public void queueBlock(Actor actor, Location loc, BlockData typeBefore, BlockData typeAfter) {
|
public void queueBlock(Actor actor, Location loc, BlockData typeBefore, BlockData typeAfter) {
|
||||||
queueBlock(actor, loc, typeBefore, typeAfter, null, null);
|
queueBlock(actor, loc, typeBefore, typeAfter, null, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -75,7 +77,7 @@ public class Consumer extends TimerTask {
|
|||||||
* Blockstate of the block before actually being destroyed.
|
* Blockstate of the block before actually being destroyed.
|
||||||
*/
|
*/
|
||||||
public void queueBlockBreak(Actor actor, BlockState before) {
|
public void queueBlockBreak(Actor actor, BlockState before) {
|
||||||
queueBlockBreak(actor, new Location(before.getWorld(), before.getX(), before.getY(), before.getZ()), before.getBlockData());
|
queueBlock(actor, new Location(before.getWorld(), before.getX(), before.getY(), before.getZ()), before.getBlockData(), null, BlockStateCodecs.serialize(before), null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -103,7 +105,7 @@ public class Consumer extends TimerTask {
|
|||||||
* Blockstate of the block after actually being placed.
|
* Blockstate of the block after actually being placed.
|
||||||
*/
|
*/
|
||||||
public void queueBlockPlace(Actor actor, BlockState after) {
|
public void queueBlockPlace(Actor actor, BlockState after) {
|
||||||
queueBlockPlace(actor, new Location(after.getWorld(), after.getX(), after.getY(), after.getZ()), after.getBlockData());
|
queueBlock(actor, new Location(after.getWorld(), after.getX(), after.getY(), after.getZ()), null, after.getBlockData(), null, BlockStateCodecs.serialize(after), null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -133,7 +135,7 @@ public class Consumer extends TimerTask {
|
|||||||
* Blockstate of the block after actually being placed.
|
* Blockstate of the block after actually being placed.
|
||||||
*/
|
*/
|
||||||
public void queueBlockReplace(Actor actor, BlockState before, BlockState after) {
|
public void queueBlockReplace(Actor actor, BlockState before, BlockState after) {
|
||||||
queueBlockReplace(actor, new Location(before.getWorld(), before.getX(), before.getY(), before.getZ()), before.getBlockData(), after.getBlockData());
|
queueBlock(actor, new Location(before.getWorld(), before.getX(), before.getY(), before.getZ()), before.getBlockData(), after.getBlockData(), BlockStateCodecs.serialize(before), BlockStateCodecs.serialize(after), null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -149,7 +151,7 @@ public class Consumer extends TimerTask {
|
|||||||
* Data of the block after being replaced
|
* Data of the block after being replaced
|
||||||
*/
|
*/
|
||||||
public void queueBlockReplace(Actor actor, BlockState before, BlockData typeAfter) {
|
public void queueBlockReplace(Actor actor, BlockState before, BlockData typeAfter) {
|
||||||
queueBlockReplace(actor, new Location(before.getWorld(), before.getX(), before.getY(), before.getZ()), before.getBlockData(), typeAfter);
|
queueBlock(actor, new Location(before.getWorld(), before.getX(), before.getY(), before.getZ()), before.getBlockData(), typeAfter, BlockStateCodecs.serialize(before), null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -165,12 +167,11 @@ public class Consumer extends TimerTask {
|
|||||||
* Blockstate of the block after actually being placed.
|
* Blockstate of the block after actually being placed.
|
||||||
*/
|
*/
|
||||||
public void queueBlockReplace(Actor actor, BlockData typeBefore, BlockState after) {
|
public void queueBlockReplace(Actor actor, BlockData typeBefore, BlockState after) {
|
||||||
queueBlockReplace(actor, new Location(after.getWorld(), after.getX(), after.getY(), after.getZ()), typeBefore, after.getBlockData());
|
queueBlock(actor, new Location(after.getWorld(), after.getX(), after.getY(), after.getZ()), typeBefore, after.getBlockData(), null, BlockStateCodecs.serialize(after), null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void queueBlockReplace(Actor actor, Location loc, BlockData typeBefore, BlockData typeAfter) {
|
public void queueBlockReplace(Actor actor, Location loc, BlockData typeBefore, BlockData typeAfter) {
|
||||||
queueBlockBreak(actor, loc, typeBefore);
|
queueBlock(actor, loc, typeBefore, typeAfter, null, null, null);
|
||||||
queueBlockPlace(actor, loc, typeAfter);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -211,7 +212,7 @@ public class Consumer extends TimerTask {
|
|||||||
* Data of the item taken/stored
|
* Data of the item taken/stored
|
||||||
*/
|
*/
|
||||||
public void queueChestAccess(Actor actor, Location loc, BlockData type, ItemStack itemStack, boolean remove) {
|
public void queueChestAccess(Actor actor, Location loc, BlockData type, ItemStack itemStack, boolean remove) {
|
||||||
queueBlock(actor, loc, type, type, null, new ChestAccess(itemStack, remove));
|
queueBlock(actor, loc, type, type, null, null, new ChestAccess(itemStack, remove));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -326,11 +327,8 @@ public class Consumer extends TimerTask {
|
|||||||
* @param lines
|
* @param lines
|
||||||
* The four lines on the sign.
|
* The four lines on the sign.
|
||||||
*/
|
*/
|
||||||
public void queueSignBreak(Actor actor, Location loc, BlockData type, String[] lines) {
|
public void queueSignBreak(Actor actor, Location loc, BlockData type, byte[] typeState) {
|
||||||
if ((type.getMaterial() != Material.SIGN && type.getMaterial() != Material.WALL_SIGN) || lines == null || lines.length != 4) {
|
queueBlock(actor, loc, type, null, typeState, null, null);
|
||||||
return;
|
|
||||||
}
|
|
||||||
queueBlock(actor, loc, type, null, lines[0] + "\0" + lines[1] + "\0" + lines[2] + "\0" + lines[3], null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -342,7 +340,7 @@ public class Consumer extends TimerTask {
|
|||||||
* The sign being broken
|
* The sign being broken
|
||||||
*/
|
*/
|
||||||
public void queueSignBreak(Actor actor, Sign sign) {
|
public void queueSignBreak(Actor actor, Sign sign) {
|
||||||
queueSignBreak(actor, new Location(sign.getWorld(), sign.getX(), sign.getY(), sign.getZ()), sign.getBlockData(), sign.getLines());
|
queueSignBreak(actor, new Location(sign.getWorld(), sign.getX(), sign.getY(), sign.getZ()), sign.getBlockData(), BlockStateCodecs.serialize(sign));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -363,7 +361,7 @@ public class Consumer extends TimerTask {
|
|||||||
if ((type.getMaterial() != Material.SIGN && type.getMaterial() != Material.WALL_SIGN) || lines == null || lines.length != 4) {
|
if ((type.getMaterial() != Material.SIGN && type.getMaterial() != Material.WALL_SIGN) || lines == null || lines.length != 4) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
queueBlock(actor, loc, null, type, lines[0] + "\0" + lines[1] + "\0" + lines[2] + "\0" + lines[3], null);
|
queueBlock(actor, loc, null, type, null, Utils.serializeYamlConfiguration(BlockStateCodecSign.serialize(lines)), null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -585,7 +583,7 @@ public class Consumer extends TimerTask {
|
|||||||
return playerIds.containsKey(actor);
|
return playerIds.containsKey(actor);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void queueBlock(Actor actor, Location loc, BlockData typeBefore, BlockData typeAfter, String signtext, ChestAccess ca) {
|
private void queueBlock(Actor actor, Location loc, BlockData typeBefore, BlockData typeAfter, byte[] stateBefore, byte[] stateAfter, ChestAccess ca) {
|
||||||
if (typeBefore == null) {
|
if (typeBefore == null) {
|
||||||
typeBefore = Bukkit.createBlockData(Material.AIR);
|
typeBefore = Bukkit.createBlockData(Material.AIR);
|
||||||
}
|
}
|
||||||
@@ -594,7 +592,7 @@ public class Consumer extends TimerTask {
|
|||||||
}
|
}
|
||||||
if (Config.fireCustomEvents) {
|
if (Config.fireCustomEvents) {
|
||||||
// Create and call the event
|
// Create and call the event
|
||||||
BlockChangePreLogEvent event = new BlockChangePreLogEvent(actor, loc, typeBefore, typeAfter, signtext, ca);
|
BlockChangePreLogEvent event = new BlockChangePreLogEvent(actor, loc, typeBefore, typeAfter, null, ca);
|
||||||
logblock.getServer().getPluginManager().callEvent(event);
|
logblock.getServer().getPluginManager().callEvent(event);
|
||||||
if (event.isCancelled()) {
|
if (event.isCancelled()) {
|
||||||
return;
|
return;
|
||||||
@@ -605,7 +603,7 @@ public class Consumer extends TimerTask {
|
|||||||
loc = event.getLocation();
|
loc = event.getLocation();
|
||||||
typeBefore = event.getTypeBefore();
|
typeBefore = event.getTypeBefore();
|
||||||
typeAfter = event.getTypeAfter();
|
typeAfter = event.getTypeAfter();
|
||||||
signtext = event.getSignText();
|
// signtext = event.getSignText();
|
||||||
ca = event.getChestAccess();
|
ca = event.getChestAccess();
|
||||||
}
|
}
|
||||||
// Do this last so LogBlock still has final say in what is being added
|
// Do this last so LogBlock still has final say in what is being added
|
||||||
@@ -620,7 +618,7 @@ public class Consumer extends TimerTask {
|
|||||||
int typeMaterialId = MaterialConverter.getOrAddMaterialId(typeString);
|
int typeMaterialId = MaterialConverter.getOrAddMaterialId(typeString);
|
||||||
int typeStateId = MaterialConverter.getOrAddBlockStateId(typeString);
|
int typeStateId = MaterialConverter.getOrAddBlockStateId(typeString);
|
||||||
|
|
||||||
queue.add(new BlockRow(loc, actor, replacedMaterialId, replacedStateId, typeMaterialId, typeStateId, signtext, ca));
|
queue.add(new BlockRow(loc, actor, replacedMaterialId, replacedStateId, stateBefore, typeMaterialId, typeStateId, stateAfter, ca));
|
||||||
}
|
}
|
||||||
|
|
||||||
private String playerID(Actor actor) {
|
private String playerID(Actor actor) {
|
||||||
@@ -670,19 +668,19 @@ public class Consumer extends TimerTask {
|
|||||||
private class BlockRow extends BlockChange implements MergeableRow {
|
private class BlockRow extends BlockChange implements MergeableRow {
|
||||||
private Connection connection;
|
private Connection connection;
|
||||||
|
|
||||||
public BlockRow(Location loc, Actor actor, int replaced, int replacedData, int type, int typeData, String signtext, ChestAccess ca) {
|
public BlockRow(Location loc, Actor actor, int replaced, int replacedData, byte[] replacedState, int type, int typeData, byte[] typeState, ChestAccess ca) {
|
||||||
super(System.currentTimeMillis() / 1000, loc, actor, replaced, replacedData, type, typeData, signtext, ca);
|
super(System.currentTimeMillis() / 1000, loc, actor, replaced, replacedData, replacedState, type, typeData, typeState, ca);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String[] getInserts() {
|
public String[] getInserts() {
|
||||||
final String table = getWorldConfig(loc.getWorld()).table;
|
final String table = getWorldConfig(loc.getWorld()).table;
|
||||||
final String[] inserts = new String[ca != null || signtext != null ? 2 : 1];
|
final String[] inserts = new String[ca != null || replacedState != null || typeState != null ? 2 : 1];
|
||||||
|
|
||||||
inserts[0] = "INSERT INTO `" + table + "-blocks` (date, playerid, replaced, replaceddata, type, typedata, x, y, z) VALUES (FROM_UNIXTIME(" + date + "), " + playerID(actor) + ", " + replacedMaterial + ", " + replacedData + ", " + typeMaterial + ", " + typeData + ", '" + loc.getBlockX()
|
inserts[0] = "INSERT INTO `" + table + "-blocks` (date, playerid, replaced, replaceddata, type, typedata, x, y, z) VALUES (FROM_UNIXTIME(" + date + "), " + playerID(actor) + ", " + replacedMaterial + ", " + replacedData + ", " + typeMaterial + ", " + typeData + ", '" + loc.getBlockX()
|
||||||
+ "', " + safeY(loc) + ", '" + loc.getBlockZ() + "');";
|
+ "', " + safeY(loc) + ", '" + loc.getBlockZ() + "');";
|
||||||
if (signtext != null) {
|
if (replacedState != null || typeState != null) {
|
||||||
inserts[1] = "INSERT INTO `" + table + "-sign` (id, signtext) values (LAST_INSERT_ID(), '" + mysqlTextEscape(signtext) + "');";
|
inserts[1] = "INSERT INTO `" + table + "-state` (replacedState, typeState, id) VALUES('" + Utils.mysqlEscapeBytes(replacedState) + "', '" + Utils.mysqlEscapeBytes(typeState) + "', LAST_INSERT_ID());";
|
||||||
} else if (ca != null) {
|
} else if (ca != null) {
|
||||||
inserts[1] = "INSERT INTO `" + table + "-chestdata` (id, item, itemremoved) values (LAST_INSERT_ID(), '" + Utils.mysqlEscapeBytes(Utils.saveItemStack(ca.itemStack)) + "', " + (ca.remove ? 1 : 0) + ");";
|
inserts[1] = "INSERT INTO `" + table + "-chestdata` (id, item, itemremoved) values (LAST_INSERT_ID(), '" + Utils.mysqlEscapeBytes(Utils.saveItemStack(ca.itemStack)) + "', " + (ca.remove ? 1 : 0) + ");";
|
||||||
}
|
}
|
||||||
@@ -727,10 +725,11 @@ public class Consumer extends TimerTask {
|
|||||||
rs.next();
|
rs.next();
|
||||||
id = rs.getInt(1);
|
id = rs.getInt(1);
|
||||||
|
|
||||||
if (signtext != null) {
|
if (typeState != null || replacedState != null) {
|
||||||
ps = connection.prepareStatement("INSERT INTO `" + table + "-sign` (signtext, id) VALUES(?, ?)");
|
ps = connection.prepareStatement("INSERT INTO `" + table + "-state` (replacedState, typeState, id) VALUES(?, ?, ?)");
|
||||||
ps.setString(1, signtext);
|
ps.setBytes(1, replacedState);
|
||||||
ps.setInt(2, id);
|
ps.setBytes(2, typeState);
|
||||||
|
ps.setInt(3, id);
|
||||||
ps.executeUpdate();
|
ps.executeUpdate();
|
||||||
} else if (ca != null) {
|
} else if (ca != null) {
|
||||||
ps = connection.prepareStatement("INSERT INTO `" + table + "-chestdata` (item, itemremove, id) values (?, ?, ?)");
|
ps = connection.prepareStatement("INSERT INTO `" + table + "-chestdata` (item, itemremove, id) values (?, ?, ?)");
|
||||||
@@ -772,7 +771,7 @@ public class Consumer extends TimerTask {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isUnique() {
|
public boolean isUnique() {
|
||||||
return !(signtext == null && ca == null && playerIds.containsKey(actor));
|
return !(typeState == null && replacedState == null && ca == null && playerIds.containsKey(actor));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@@ -34,7 +34,7 @@ public final class QueryParams implements Cloneable {
|
|||||||
public List<Integer> typeIds = new ArrayList<Integer>();
|
public List<Integer> typeIds = new ArrayList<Integer>();
|
||||||
public World world = null;
|
public World world = null;
|
||||||
public String match = 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;
|
public boolean needCount = false, needId = false, needDate = false, needType = false, needData = false, needPlayer = false, needCoords = false, needChestAccess = false, needMessage = false, needKiller = false, needVictim = false, needWeapon = false;
|
||||||
private final LogBlock logblock;
|
private final LogBlock logblock;
|
||||||
|
|
||||||
public QueryParams(LogBlock logblock) {
|
public QueryParams(LogBlock logblock) {
|
||||||
@@ -145,8 +145,8 @@ public final class QueryParams implements Cloneable {
|
|||||||
if (needCoords) {
|
if (needCoords) {
|
||||||
select += "x, y, z, ";
|
select += "x, y, z, ";
|
||||||
}
|
}
|
||||||
if (needSignText) {
|
if (needData) {
|
||||||
select += "signtext, ";
|
select += "replacedState, typeState, ";
|
||||||
}
|
}
|
||||||
if (needChestAccess) {
|
if (needChestAccess) {
|
||||||
select += "item, itemremove, ";
|
select += "item, itemremove, ";
|
||||||
@@ -157,8 +157,8 @@ public final class QueryParams implements Cloneable {
|
|||||||
if (needPlayer || players.size() > 0) {
|
if (needPlayer || players.size() > 0) {
|
||||||
from += "INNER JOIN `lb-players` USING (playerid) ";
|
from += "INNER JOIN `lb-players` USING (playerid) ";
|
||||||
}
|
}
|
||||||
if (needSignText) {
|
if (!needCount && needData) {
|
||||||
from += "LEFT JOIN `" + getTable() + "-sign` USING (id) ";
|
from += "LEFT JOIN `" + getTable() + "-state` USING (id) ";
|
||||||
}
|
}
|
||||||
if (needChestAccess)
|
if (needChestAccess)
|
||||||
// If BlockChangeType is CHESTACCESS, we can use more efficient query
|
// If BlockChangeType is CHESTACCESS, we can use more efficient query
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
package de.diddiz.LogBlock;
|
package de.diddiz.LogBlock;
|
||||||
|
|
||||||
|
import de.diddiz.LogBlock.blockstate.BlockStateCodecSign;
|
||||||
import de.diddiz.LogBlock.config.Config;
|
import de.diddiz.LogBlock.config.Config;
|
||||||
import de.diddiz.LogBlock.config.WorldConfig;
|
import de.diddiz.LogBlock.config.WorldConfig;
|
||||||
import de.diddiz.util.UUIDFetcher;
|
import de.diddiz.util.UUIDFetcher;
|
||||||
@@ -386,7 +387,7 @@ class Updater {
|
|||||||
}
|
}
|
||||||
for (final WorldConfig wcfg : getLoggedWorlds()) {
|
for (final WorldConfig wcfg : getLoggedWorlds()) {
|
||||||
if (wcfg.isLogging(Logging.SIGNTEXT)) {
|
if (wcfg.isLogging(Logging.SIGNTEXT)) {
|
||||||
checkCharset(wcfg.table + "-sign","signtext",st);
|
// checkCharset(wcfg.table + "-sign","signtext",st);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
st.close();
|
st.close();
|
||||||
@@ -565,7 +566,7 @@ class Updater {
|
|||||||
}
|
}
|
||||||
rs.close();
|
rs.close();
|
||||||
|
|
||||||
PreparedStatement updateWeaponStatement = conn.prepareStatement("UPDATE `" + wcfg.table + "`-kills SET weapon = ? WHERE id = ?");
|
PreparedStatement updateWeaponStatement = conn.prepareStatement("UPDATE `" + wcfg.table + "-kills` SET weapon = ? WHERE id = ?");
|
||||||
for (int start = 0;; start += 10000) {
|
for (int start = 0;; start += 10000) {
|
||||||
rs = st.executeQuery("SELECT id, weapon FROM `" + wcfg.table + "-kills` ORDER BY id ASC LIMIT " + start + ",10000");
|
rs = st.executeQuery("SELECT id, weapon FROM `" + wcfg.table + "-kills` ORDER BY id ASC LIMIT " + start + ",10000");
|
||||||
boolean anyUpdate = false;
|
boolean anyUpdate = false;
|
||||||
@@ -622,7 +623,85 @@ class Updater {
|
|||||||
}
|
}
|
||||||
config.set("version", "1.13.0");
|
config.set("version", "1.13.0");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (configVersion.compareTo(new ComparableVersion("1.13.1")) < 0) {
|
||||||
|
getLogger().info("Updating tables to 1.13.1 ...");
|
||||||
|
try {
|
||||||
|
final Connection conn = logblock.getConnection();
|
||||||
|
conn.setAutoCommit(false);
|
||||||
|
final Statement st = conn.createStatement();
|
||||||
|
for (final WorldConfig wcfg : getLoggedWorlds()) {
|
||||||
|
getLogger().info("Processing world " + wcfg.world + "...");
|
||||||
|
if (wcfg.isLogging(Logging.SIGNTEXT)) {
|
||||||
|
int rowsToConvert = 0;
|
||||||
|
int done = 0;
|
||||||
|
try {
|
||||||
|
ResultSet rs = st.executeQuery("SELECT count(*) as rowcount FROM `" + wcfg.table + "-sign`");
|
||||||
|
if (rs.next()) {
|
||||||
|
rowsToConvert = rs.getInt(1);
|
||||||
|
getLogger().info("Converting " + rowsToConvert + " entries in " + wcfg.table + "-sign");
|
||||||
|
}
|
||||||
|
rs.close();
|
||||||
|
|
||||||
|
PreparedStatement insertSignState = conn.prepareStatement("INSERT INTO `" + wcfg.table + "-state` (id, replacedState, typeState) VALUES (?, ?, ?)");
|
||||||
|
PreparedStatement deleteSign = conn.prepareStatement("DELETE FROM `" + wcfg.table + "-sign` WHERE id = ?");
|
||||||
|
while (true) {
|
||||||
|
rs = st.executeQuery("SELECT id, signtext, replaced, type FROM `" + wcfg.table + "-sign` LEFT JOIN `" + wcfg.table + "-blocks` USING (id) ORDER BY id ASC LIMIT 10000");
|
||||||
|
boolean anyRow = false;
|
||||||
|
while (rs.next()) {
|
||||||
|
anyRow = true;
|
||||||
|
int id = rs.getInt("id");
|
||||||
|
String signText = rs.getString("signtext");
|
||||||
|
int replaced = rs.getInt("replaced");
|
||||||
|
boolean nullBlock = rs.wasNull();
|
||||||
|
int type = rs.getInt("type");
|
||||||
|
|
||||||
|
if (!nullBlock && signText != null) {
|
||||||
|
String[] lines = signText.split("\0", 4);
|
||||||
|
byte[] bytes = Utils.serializeYamlConfiguration(BlockStateCodecSign.serialize(lines));
|
||||||
|
|
||||||
|
Material replacedMaterial = MaterialConverter.getBlockData(replaced, -1).getMaterial();
|
||||||
|
Material typeMaterial = MaterialConverter.getBlockData(type, -1).getMaterial();
|
||||||
|
boolean wasSign = replacedMaterial == Material.SIGN || replacedMaterial == Material.WALL_SIGN;
|
||||||
|
boolean isSign = typeMaterial == Material.SIGN || typeMaterial == Material.WALL_SIGN;
|
||||||
|
|
||||||
|
insertSignState.setInt(1, id);
|
||||||
|
insertSignState.setBytes(2, wasSign ? bytes : null);
|
||||||
|
insertSignState.setBytes(3, isSign ? bytes : null);
|
||||||
|
insertSignState.addBatch();
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteSign.setInt(1, id);
|
||||||
|
deleteSign.addBatch();
|
||||||
|
done++;
|
||||||
|
}
|
||||||
|
rs.close();
|
||||||
|
if (!anyRow) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
insertSignState.executeBatch();
|
||||||
|
deleteSign.executeBatch();
|
||||||
|
conn.commit();
|
||||||
|
getLogger().info("Done: " + done + "/" + rowsToConvert + " (" + (rowsToConvert > 0 ? (done * 100 / rowsToConvert) : 100) + "%)");
|
||||||
|
}
|
||||||
|
insertSignState.close();
|
||||||
|
deleteSign.close();
|
||||||
|
} catch (SQLException e) {
|
||||||
|
getLogger().info("Could not convert " + wcfg.table + "-sign: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
st.close();
|
||||||
|
conn.close();
|
||||||
|
} catch (final SQLException ex) {
|
||||||
|
Bukkit.getLogger().log(Level.SEVERE, "[Updater] Error: ", ex);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
config.set("version", "1.13.1");
|
||||||
|
}
|
||||||
|
|
||||||
logblock.saveConfig();
|
logblock.saveConfig();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -667,8 +746,9 @@ class Updater {
|
|||||||
|
|
||||||
for (final WorldConfig wcfg : getLoggedWorlds()) {
|
for (final WorldConfig wcfg : getLoggedWorlds()) {
|
||||||
createTable(dbm, state, wcfg.table + "-blocks", "(id INT UNSIGNED NOT NULL AUTO_INCREMENT, date DATETIME NOT NULL, playerid INT UNSIGNED NOT NULL, replaced SMALLINT UNSIGNED NOT NULL, replacedData SMALLINT NOT NULL, type SMALLINT UNSIGNED NOT NULL, typeData SMALLINT 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 + "-blocks", "(id INT UNSIGNED NOT NULL AUTO_INCREMENT, date DATETIME NOT NULL, playerid INT UNSIGNED NOT NULL, replaced SMALLINT UNSIGNED NOT NULL, replacedData SMALLINT NOT NULL, type SMALLINT UNSIGNED NOT NULL, typeData SMALLINT 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 " + charset);
|
// createTable(dbm, state, wcfg.table + "-sign", "(id INT UNSIGNED NOT NULL, signtext VARCHAR(255) NOT NULL, PRIMARY KEY (id)) DEFAULT CHARSET " + charset);
|
||||||
createTable(dbm, state, wcfg.table + "-chestdata", "(id INT UNSIGNED NOT NULL, item MEDIUMBLOB, itemremove TINYINT, PRIMARY KEY (id))");
|
createTable(dbm, state, wcfg.table + "-chestdata", "(id INT UNSIGNED NOT NULL, item MEDIUMBLOB, itemremove TINYINT, PRIMARY KEY (id))");
|
||||||
|
createTable(dbm, state, wcfg.table + "-state", "(id INT UNSIGNED NOT NULL, replacedState MEDIUMBLOB NULL, typeState MEDIUMBLOB NULL, PRIMARY KEY (id))");
|
||||||
if (wcfg.isLogging(Logging.KILL)) {
|
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))");
|
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))");
|
||||||
}
|
}
|
||||||
|
@@ -7,7 +7,6 @@ import org.bukkit.World;
|
|||||||
import org.bukkit.block.Block;
|
import org.bukkit.block.Block;
|
||||||
import org.bukkit.block.BlockFace;
|
import org.bukkit.block.BlockFace;
|
||||||
import org.bukkit.block.BlockState;
|
import org.bukkit.block.BlockState;
|
||||||
import org.bukkit.block.Sign;
|
|
||||||
import org.bukkit.block.data.Bisected.Half;
|
import org.bukkit.block.data.Bisected.Half;
|
||||||
import org.bukkit.block.data.BlockData;
|
import org.bukkit.block.data.BlockData;
|
||||||
import org.bukkit.block.data.type.Bed;
|
import org.bukkit.block.data.type.Bed;
|
||||||
@@ -20,6 +19,7 @@ import org.bukkit.command.CommandSender;
|
|||||||
import org.bukkit.inventory.InventoryHolder;
|
import org.bukkit.inventory.InventoryHolder;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
|
||||||
|
import de.diddiz.LogBlock.blockstate.BlockStateCodecs;
|
||||||
import de.diddiz.util.BukkitUtils;
|
import de.diddiz.util.BukkitUtils;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@@ -76,8 +76,8 @@ public class WorldEditor implements Runnable {
|
|||||||
this.sender = sender;
|
this.sender = sender;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void queueEdit(int x, int y, int z, int replaced, int replaceData, int type, int typeData, String signtext, ChestAccess item) {
|
public void queueEdit(int x, int y, int z, int replaced, int replaceData, byte[] replacedState, int type, int typeData, byte[] typeState, ChestAccess item) {
|
||||||
edits.add(new Edit(0, new Location(world, x, y, z), null, replaced, replaceData, type, typeData, signtext, item));
|
edits.add(new Edit(0, new Location(world, x, y, z), null, replaced, replaceData, replacedState, type, typeData, typeState, item));
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getElapsedTime() {
|
public long getElapsedTime() {
|
||||||
@@ -153,8 +153,8 @@ public class WorldEditor implements Runnable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private class Edit extends BlockChange {
|
private class Edit extends BlockChange {
|
||||||
public Edit(long time, Location loc, Actor actor, int replaced, int replaceData, int type, int typeData, String signtext, ChestAccess ca) {
|
public Edit(long time, Location loc, Actor actor, int replaced, int replaceData, byte[] replacedState, int type, int typeData, byte[] typeState, ChestAccess ca) {
|
||||||
super(time, loc, actor, replaced, replaceData, type, typeData, signtext, ca);
|
super(time, loc, actor, replaced, replaceData,replacedState , type, typeData, typeState, ca);
|
||||||
}
|
}
|
||||||
|
|
||||||
PerformResult perform() throws WorldEditorException {
|
PerformResult perform() throws WorldEditorException {
|
||||||
@@ -172,7 +172,7 @@ public class WorldEditor implements Runnable {
|
|||||||
if (BukkitUtils.isEmpty(replacedBlock.getMaterial()) && BukkitUtils.isEmpty(block.getType())) {
|
if (BukkitUtils.isEmpty(replacedBlock.getMaterial()) && BukkitUtils.isEmpty(block.getType())) {
|
||||||
return PerformResult.NO_ACTION;
|
return PerformResult.NO_ACTION;
|
||||||
}
|
}
|
||||||
final BlockState state = block.getState();
|
BlockState state = block.getState();
|
||||||
if (!world.isChunkLoaded(block.getChunk())) {
|
if (!world.isChunkLoaded(block.getChunk())) {
|
||||||
world.loadChunk(block.getChunk());
|
world.loadChunk(block.getChunk());
|
||||||
}
|
}
|
||||||
@@ -217,21 +217,18 @@ public class WorldEditor implements Runnable {
|
|||||||
}
|
}
|
||||||
block.setBlockData(replacedBlock);
|
block.setBlockData(replacedBlock);
|
||||||
BlockData newData = block.getBlockData();
|
BlockData newData = block.getBlockData();
|
||||||
|
if (BlockStateCodecs.hasCodec(replacedBlock.getMaterial())) {
|
||||||
|
state = block.getState();
|
||||||
|
try {
|
||||||
|
BlockStateCodecs.deserialize(state, replacedState);
|
||||||
|
state.update();
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new WorldEditorException("Failed to restore blockstate of " + block.getType() + ": " + e, block.getLocation());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
final Material curtype = block.getType();
|
final Material curtype = block.getType();
|
||||||
if (signtext != null && (curtype == Material.SIGN || curtype == Material.WALL_SIGN)) {
|
if (newData instanceof Bed) {
|
||||||
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 " + block.getType(), block.getLocation());
|
|
||||||
}
|
|
||||||
} else if (newData instanceof Bed) {
|
|
||||||
final Bed bed = (Bed) newData;
|
final Bed bed = (Bed) newData;
|
||||||
final Block secBlock = bed.getPart() == Part.HEAD ? block.getRelative(bed.getFacing().getOppositeFace()) : block.getRelative(bed.getFacing());
|
final Block secBlock = bed.getPart() == Part.HEAD ? block.getRelative(bed.getFacing().getOppositeFace()) : block.getRelative(bed.getFacing());
|
||||||
if (secBlock.isEmpty()) {
|
if (secBlock.isEmpty()) {
|
||||||
|
@@ -0,0 +1,15 @@
|
|||||||
|
package de.diddiz.LogBlock.blockstate;
|
||||||
|
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.block.BlockState;
|
||||||
|
import org.bukkit.configuration.file.YamlConfiguration;
|
||||||
|
|
||||||
|
public interface BlockStateCodec {
|
||||||
|
Material[] getApplicableMaterials();
|
||||||
|
|
||||||
|
YamlConfiguration serialize(BlockState state);
|
||||||
|
|
||||||
|
void deserialize(BlockState state, YamlConfiguration conf);
|
||||||
|
|
||||||
|
String toString(YamlConfiguration conf);
|
||||||
|
}
|
@@ -0,0 +1,70 @@
|
|||||||
|
package de.diddiz.LogBlock.blockstate;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.bukkit.DyeColor;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.block.Banner;
|
||||||
|
import org.bukkit.block.BlockState;
|
||||||
|
import org.bukkit.block.banner.Pattern;
|
||||||
|
import org.bukkit.block.banner.PatternType;
|
||||||
|
import org.bukkit.configuration.ConfigurationSection;
|
||||||
|
import org.bukkit.configuration.file.YamlConfiguration;
|
||||||
|
|
||||||
|
public class BlockStateCodecBanner implements BlockStateCodec {
|
||||||
|
@Override
|
||||||
|
public Material[] getApplicableMaterials() {
|
||||||
|
return new Material[] { Material.WHITE_BANNER, Material.ORANGE_BANNER, Material.MAGENTA_BANNER, Material.LIGHT_BLUE_BANNER, Material.YELLOW_BANNER, Material.LIME_BANNER, Material.PINK_BANNER, Material.GRAY_BANNER, Material.LIGHT_GRAY_BANNER, Material.CYAN_BANNER, Material.PURPLE_BANNER,
|
||||||
|
Material.BLUE_BANNER, Material.BROWN_BANNER, Material.GREEN_BANNER, Material.RED_BANNER, Material.BLACK_BANNER, Material.WHITE_WALL_BANNER, Material.ORANGE_WALL_BANNER, Material.MAGENTA_WALL_BANNER, Material.LIGHT_BLUE_WALL_BANNER, Material.YELLOW_WALL_BANNER,
|
||||||
|
Material.LIME_WALL_BANNER, Material.PINK_WALL_BANNER, Material.GRAY_WALL_BANNER, Material.LIGHT_GRAY_WALL_BANNER, Material.CYAN_WALL_BANNER, Material.PURPLE_WALL_BANNER, Material.BLUE_WALL_BANNER, Material.BROWN_WALL_BANNER, Material.GREEN_WALL_BANNER, Material.RED_WALL_BANNER,
|
||||||
|
Material.BLACK_WALL_BANNER };
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public YamlConfiguration serialize(BlockState state) {
|
||||||
|
if (state instanceof Banner) {
|
||||||
|
Banner banner = (Banner) state;
|
||||||
|
int nr = 0;
|
||||||
|
List<Pattern> patterns = banner.getPatterns();
|
||||||
|
if (!patterns.isEmpty()) {
|
||||||
|
YamlConfiguration conf = new YamlConfiguration();
|
||||||
|
ConfigurationSection patternsSection = conf.createSection("patterns");
|
||||||
|
for (Pattern pattern : patterns) {
|
||||||
|
ConfigurationSection section = patternsSection.createSection(Integer.toString(nr));
|
||||||
|
section.set("color", pattern.getColor().name());
|
||||||
|
section.set("pattern", pattern.getPattern().name());
|
||||||
|
nr++;
|
||||||
|
}
|
||||||
|
return conf;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void deserialize(BlockState state, YamlConfiguration conf) {
|
||||||
|
if (state instanceof Banner) {
|
||||||
|
Banner banner = (Banner) state;
|
||||||
|
int oldPatterns = banner.getPatterns().size();
|
||||||
|
for (int i = 0; i < oldPatterns; i++) {
|
||||||
|
banner.removePattern(0);
|
||||||
|
}
|
||||||
|
ConfigurationSection patternsSection = conf == null ? null : conf.getConfigurationSection("patterns");
|
||||||
|
if (patternsSection != null) {
|
||||||
|
for (String key : patternsSection.getKeys(false)) {
|
||||||
|
ConfigurationSection section = patternsSection.getConfigurationSection(key);
|
||||||
|
if (section != null) {
|
||||||
|
DyeColor color = DyeColor.valueOf(section.getString("color"));
|
||||||
|
PatternType type = PatternType.valueOf(section.getString("pattern"));
|
||||||
|
banner.addPattern(new Pattern(color, type));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString(YamlConfiguration conf) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,76 @@
|
|||||||
|
package de.diddiz.LogBlock.blockstate;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.block.BlockState;
|
||||||
|
import org.bukkit.block.Sign;
|
||||||
|
import org.bukkit.configuration.file.YamlConfiguration;
|
||||||
|
|
||||||
|
public class BlockStateCodecSign implements BlockStateCodec {
|
||||||
|
@Override
|
||||||
|
public Material[] getApplicableMaterials() {
|
||||||
|
return new Material[] { Material.WALL_SIGN, Material.SIGN };
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public YamlConfiguration serialize(BlockState state) {
|
||||||
|
if (state instanceof Sign) {
|
||||||
|
Sign sign = (Sign) state;
|
||||||
|
String[] lines = sign.getLines();
|
||||||
|
boolean hasText = false;
|
||||||
|
for (int i = 0; i < lines.length; i++) {
|
||||||
|
if (lines[i] != null && lines[i].length() > 0) {
|
||||||
|
hasText = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (hasText) {
|
||||||
|
YamlConfiguration conf = new YamlConfiguration();
|
||||||
|
conf.set("lines", Arrays.asList(lines));
|
||||||
|
return conf;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is required for the SignChangeEvent, because we have no BlockState there.
|
||||||
|
*/
|
||||||
|
public static YamlConfiguration serialize(String[] lines) {
|
||||||
|
YamlConfiguration conf = new YamlConfiguration();
|
||||||
|
conf.set("lines", Arrays.asList(lines));
|
||||||
|
return conf;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void deserialize(BlockState state, YamlConfiguration conf) {
|
||||||
|
if (state instanceof Sign) {
|
||||||
|
Sign sign = (Sign) state;
|
||||||
|
List<String> lines = Collections.emptyList();
|
||||||
|
if (conf != null) {
|
||||||
|
lines = conf.getStringList("lines");
|
||||||
|
}
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
String line = lines.size() > i && lines.get(i) != null ? lines.get(i) : "";
|
||||||
|
sign.setLine(i, line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString(YamlConfiguration conf) {
|
||||||
|
if (conf != null) {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
for (String line : conf.getStringList("lines")) {
|
||||||
|
if (sb.length() > 0)
|
||||||
|
sb.append(" ");
|
||||||
|
sb.append("[").append(line).append("]");
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,54 @@
|
|||||||
|
package de.diddiz.LogBlock.blockstate;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.OfflinePlayer;
|
||||||
|
import org.bukkit.block.BlockState;
|
||||||
|
import org.bukkit.block.Skull;
|
||||||
|
import org.bukkit.configuration.file.YamlConfiguration;
|
||||||
|
|
||||||
|
public class BlockStateCodecSkull implements BlockStateCodec {
|
||||||
|
@Override
|
||||||
|
public Material[] getApplicableMaterials() {
|
||||||
|
return new Material[] { Material.PLAYER_WALL_HEAD, Material.PLAYER_HEAD };
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public YamlConfiguration serialize(BlockState state) {
|
||||||
|
if (state instanceof Skull) {
|
||||||
|
Skull skull = (Skull) state;
|
||||||
|
OfflinePlayer owner = skull.hasOwner() ? skull.getOwningPlayer() : null;
|
||||||
|
if (owner != null) {
|
||||||
|
YamlConfiguration conf = new YamlConfiguration();
|
||||||
|
conf.set("owner", owner.getUniqueId().toString());
|
||||||
|
return conf;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void deserialize(BlockState state, YamlConfiguration conf) {
|
||||||
|
if (state instanceof Skull) {
|
||||||
|
Skull skull = (Skull) state;
|
||||||
|
UUID ownerId = conf == null ? null : UUID.fromString(conf.getString("owner"));
|
||||||
|
if (ownerId == null) {
|
||||||
|
skull.setOwningPlayer(null);
|
||||||
|
} else {
|
||||||
|
skull.setOwningPlayer(Bukkit.getOfflinePlayer(ownerId));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString(YamlConfiguration conf) {
|
||||||
|
UUID ownerId = conf == null ? null : UUID.fromString(conf.getString("owner"));
|
||||||
|
if (ownerId != null) {
|
||||||
|
OfflinePlayer owner = Bukkit.getOfflinePlayer(ownerId);
|
||||||
|
return "[" + (owner.getName() != null ? owner.getName() : owner.getUniqueId().toString()) + "]";
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,60 @@
|
|||||||
|
package de.diddiz.LogBlock.blockstate;
|
||||||
|
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.block.BlockState;
|
||||||
|
import org.bukkit.block.CreatureSpawner;
|
||||||
|
import org.bukkit.configuration.file.YamlConfiguration;
|
||||||
|
import org.bukkit.entity.EntityType;
|
||||||
|
|
||||||
|
public class BlockStateCodecSpawner implements BlockStateCodec {
|
||||||
|
@Override
|
||||||
|
public Material[] getApplicableMaterials() {
|
||||||
|
return new Material[] { Material.SPAWNER };
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public YamlConfiguration serialize(BlockState state) {
|
||||||
|
if (state instanceof CreatureSpawner) {
|
||||||
|
CreatureSpawner spawner = (CreatureSpawner) state;
|
||||||
|
YamlConfiguration conf = new YamlConfiguration();
|
||||||
|
conf.set("delay", spawner.getDelay());
|
||||||
|
conf.set("maxNearbyEntities", spawner.getMaxNearbyEntities());
|
||||||
|
conf.set("maxSpawnDelay", spawner.getMaxSpawnDelay());
|
||||||
|
conf.set("minSpawnDelay", spawner.getMinSpawnDelay());
|
||||||
|
conf.set("requiredPlayerRange", spawner.getRequiredPlayerRange());
|
||||||
|
conf.set("spawnCount", spawner.getSpawnCount());
|
||||||
|
conf.set("spawnedType", spawner.getSpawnedType().name());
|
||||||
|
conf.set("spawnRange", spawner.getSpawnRange());
|
||||||
|
return conf;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void deserialize(BlockState state, YamlConfiguration conf) {
|
||||||
|
if (state instanceof CreatureSpawner) {
|
||||||
|
CreatureSpawner spawner = (CreatureSpawner) state;
|
||||||
|
if (conf != null) {
|
||||||
|
spawner.setDelay(conf.getInt("delay"));
|
||||||
|
spawner.setMaxNearbyEntities(conf.getInt("maxNearbyEntities"));
|
||||||
|
spawner.setMaxSpawnDelay(conf.getInt("maxSpawnDelay"));
|
||||||
|
spawner.setMinSpawnDelay(conf.getInt("minSpawnDelay"));
|
||||||
|
spawner.setRequiredPlayerRange(conf.getInt("requiredPlayerRange"));
|
||||||
|
spawner.setSpawnCount(conf.getInt("spawnCount"));
|
||||||
|
spawner.setSpawnedType(EntityType.valueOf(conf.getString("spawnedType")));
|
||||||
|
spawner.setSpawnRange(conf.getInt("spawnRange"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString(YamlConfiguration conf) {
|
||||||
|
if (conf != null) {
|
||||||
|
EntityType entity = EntityType.valueOf(conf.getString("spawnedType"));
|
||||||
|
if (entity != null) {
|
||||||
|
return "[" + entity + "]";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,80 @@
|
|||||||
|
package de.diddiz.LogBlock.blockstate;
|
||||||
|
|
||||||
|
import java.util.EnumMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.block.BlockState;
|
||||||
|
import org.bukkit.configuration.InvalidConfigurationException;
|
||||||
|
import org.bukkit.configuration.file.YamlConfiguration;
|
||||||
|
|
||||||
|
import de.diddiz.LogBlock.LogBlock;
|
||||||
|
import de.diddiz.util.Utils;
|
||||||
|
|
||||||
|
public class BlockStateCodecs {
|
||||||
|
private static Map<Material, BlockStateCodec> codecs = new EnumMap<>(Material.class);
|
||||||
|
|
||||||
|
public static void registerCodec(BlockStateCodec codec) {
|
||||||
|
Material[] materials = codec.getApplicableMaterials();
|
||||||
|
for (Material material : materials) {
|
||||||
|
if (codecs.containsKey(material)) {
|
||||||
|
throw new IllegalArgumentException("BlockStateCodec for " + material + " already registered!");
|
||||||
|
}
|
||||||
|
codecs.put(material, codec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static {
|
||||||
|
registerCodec(new BlockStateCodecSign());
|
||||||
|
registerCodec(new BlockStateCodecSkull());
|
||||||
|
registerCodec(new BlockStateCodecBanner());
|
||||||
|
registerCodec(new BlockStateCodecSpawner());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean hasCodec(Material material) {
|
||||||
|
return codecs.containsKey(material);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte[] serialize(BlockState state) {
|
||||||
|
BlockStateCodec codec = codecs.get(state.getType());
|
||||||
|
if (codec != null) {
|
||||||
|
YamlConfiguration serialized = codec.serialize(state);
|
||||||
|
if (serialized != null && !serialized.getKeys(false).isEmpty()) {
|
||||||
|
return Utils.serializeYamlConfiguration(serialized);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void deserialize(BlockState block, byte[] state) {
|
||||||
|
BlockStateCodec codec = codecs.get(block.getType());
|
||||||
|
if (codec != null) {
|
||||||
|
YamlConfiguration conf = null;
|
||||||
|
try {
|
||||||
|
if (state != null) {
|
||||||
|
conf = Utils.deserializeYamlConfiguration(state);
|
||||||
|
}
|
||||||
|
} catch (InvalidConfigurationException e) {
|
||||||
|
LogBlock.getInstance().getLogger().log(Level.SEVERE, "Exception while deserializing BlockState", e);
|
||||||
|
}
|
||||||
|
codec.deserialize(block, conf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String toString(Material material, byte[] state) {
|
||||||
|
BlockStateCodec codec = codecs.get(material);
|
||||||
|
if (codec != null) {
|
||||||
|
YamlConfiguration conf = null;
|
||||||
|
try {
|
||||||
|
if (state != null) {
|
||||||
|
conf = Utils.deserializeYamlConfiguration(state);
|
||||||
|
}
|
||||||
|
} catch (InvalidConfigurationException e) {
|
||||||
|
LogBlock.getInstance().getLogger().log(Level.SEVERE, "Exception while deserializing BlockState", e);
|
||||||
|
}
|
||||||
|
return codec.toString(conf);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
@@ -14,6 +14,7 @@ import com.sk89q.worldedit.world.block.BlockStateHolder;
|
|||||||
|
|
||||||
import de.diddiz.LogBlock.LogBlock;
|
import de.diddiz.LogBlock.LogBlock;
|
||||||
import de.diddiz.LogBlock.Logging;
|
import de.diddiz.LogBlock.Logging;
|
||||||
|
import de.diddiz.LogBlock.blockstate.BlockStateCodecs;
|
||||||
import de.diddiz.LogBlock.config.Config;
|
import de.diddiz.LogBlock.config.Config;
|
||||||
import de.diddiz.util.BukkitUtils;
|
import de.diddiz.util.BukkitUtils;
|
||||||
|
|
||||||
@@ -22,8 +23,6 @@ import org.bukkit.Location;
|
|||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
import org.bukkit.block.Block;
|
import org.bukkit.block.Block;
|
||||||
import org.bukkit.block.BlockState;
|
|
||||||
import org.bukkit.block.Sign;
|
|
||||||
import org.bukkit.block.data.BlockData;
|
import org.bukkit.block.data.BlockData;
|
||||||
|
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
@@ -104,9 +103,8 @@ public class WorldEditLoggingHook {
|
|||||||
Material typeBefore = origin.getType();
|
Material typeBefore = origin.getType();
|
||||||
|
|
||||||
// Check to see if we've broken a sign
|
// Check to see if we've broken a sign
|
||||||
if (Config.isLogging(location.getWorld().getName(), Logging.SIGNTEXT) && (typeBefore == Material.SIGN || typeBefore == Material.WALL_SIGN)) {
|
if (BlockStateCodecs.hasCodec(typeBefore)) {
|
||||||
BlockState stateBefore = origin.getState();
|
plugin.getConsumer().queueBlockBreak(lbActor, origin.getState());
|
||||||
plugin.getConsumer().queueSignBreak(lbActor, (Sign) stateBefore);
|
|
||||||
} else if (!origin.isEmpty()) {
|
} else if (!origin.isEmpty()) {
|
||||||
plugin.getConsumer().queueBlockBreak(lbActor, location, origin.getBlockData());
|
plugin.getConsumer().queueBlockBreak(lbActor, location, origin.getBlockData());
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user