Allow for logging of item data greater than 256. Fixes #96, #235

This change involves refactoring many instances of "byte" to "short and altering a few ItemStack calls to use the int,int,short form instead of int,int,0,byte
Significantly it also involves altering the MaterialName system to allow shorts instead of bytes, and altering the rawdata() function to return the durability of an ItemStack rather than the data value of its Material.

One side effect of this is that tool durability is now logged, which will make for more accurate rollbacks.
This commit is contained in:
Philip Cass
2013-12-04 11:21:34 +00:00
parent d50c48f79d
commit c0b983e8e8
9 changed files with 51 additions and 23 deletions

View File

@@ -2,10 +2,9 @@ package de.diddiz.LogBlock;
public class ChestAccess public class ChestAccess
{ {
final short itemType, itemAmount; final short itemType, itemAmount, itemData;
final byte itemData;
public ChestAccess(short itemType, short itemAmount, byte itemData) { public ChestAccess(short itemType, short itemAmount, short itemData) {
this.itemType = itemType; this.itemType = itemType;
this.itemAmount = itemAmount; this.itemAmount = itemAmount;
this.itemData = itemData >= 0 ? itemData : 0; this.itemData = itemData >= 0 ? itemData : 0;

View File

@@ -607,7 +607,7 @@ public class CommandsHandler implements CommandExecutor
final WorldEditor editor = new WorldEditor(logblock, params.world); final WorldEditor editor = new WorldEditor(logblock, params.world);
while (rs.next()) while (rs.next())
editor.queueEdit(rs.getInt("x"), rs.getInt("y"), rs.getInt("z"), rs.getInt("replaced"), rs.getInt("type"), rs.getByte("data"), rs.getString("signtext"), rs.getShort("itemtype"), rs.getShort("itemamount"), rs.getByte("itemdata")); editor.queueEdit(rs.getInt("x"), rs.getInt("y"), rs.getInt("z"), rs.getInt("replaced"), rs.getInt("type"), rs.getByte("data"), rs.getString("signtext"), rs.getShort("itemtype"), rs.getShort("itemamount"), rs.getShort("itemdata"));
final int changes = editor.getSize(); final int changes = editor.getSize();
if (changes > 10000) { if (changes > 10000) {
editor.setSender(sender); editor.setSender(sender);

View File

@@ -122,7 +122,7 @@ public class Consumer extends TimerTask
* @param container * @param container
* The respective container. Must be an instance of an InventoryHolder. * The respective container. Must be an instance of an InventoryHolder.
*/ */
public void queueChestAccess(String playerName, BlockState container, short itemType, short itemAmount, byte itemData) { public void queueChestAccess(String playerName, BlockState container, short itemType, short itemAmount, short itemData) {
if (!(container instanceof InventoryHolder)) if (!(container instanceof InventoryHolder))
return; return;
queueChestAccess(playerName, new Location(container.getWorld(), container.getX(), container.getY(), container.getZ()), container.getTypeId(), itemType, itemAmount, itemData); queueChestAccess(playerName, new Location(container.getWorld(), container.getX(), container.getY(), container.getZ()), container.getTypeId(), itemType, itemAmount, itemData);
@@ -132,7 +132,7 @@ public class Consumer extends TimerTask
* @param type * @param type
* Type id of the container. * Type id of the container.
*/ */
public void queueChestAccess(String playerName, Location loc, int type, short itemType, short itemAmount, byte itemData) { 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)); queueBlock(playerName, loc, type, type, (byte)0, null, new ChestAccess(itemType, itemAmount, itemData));
} }

View File

@@ -235,6 +235,26 @@ class Updater
} }
config.set("version", "1.71"); config.set("version", "1.71");
} }
if (config.getString("version").compareTo("1.72") < 0) {
getLogger().info("Updating tables to 1.72 ...");
final Connection conn = logblock.getConnection();
try {
conn.setAutoCommit(true);
final Statement st = conn.createStatement();
for (final WorldConfig wcfg : getLoggedWorlds()) {
if (wcfg.isLogging(Logging.CHESTACCESS)) {
st.execute("ALTER TABLE `"+wcfg.table+"-chest` CHANGE itemdata itemdata SMALLINT UNSIGNED NOT NULL");
getLogger().info("Table "+wcfg.table+"-chest modified");
}
}
st.close();
conn.close();
} catch (final SQLException ex) {
Bukkit.getLogger().log(Level.SEVERE, "[Updater] Error: ", ex);
return false;
}
config.set("version", "1.72");
}
logblock.saveConfig(); logblock.saveConfig();
return true; return true;
@@ -257,7 +277,7 @@ class Updater
for (final WorldConfig wcfg : getLoggedWorlds()) { for (final WorldConfig wcfg : getLoggedWorlds()) {
createTable(dbm, state, wcfg.table, "(id INT UNSIGNED NOT NULL AUTO_INCREMENT, date DATETIME NOT NULL, playerid INT UNSIGNED NOT NULL, replaced TINYINT UNSIGNED NOT NULL, type TINYINT UNSIGNED NOT NULL, data TINYINT UNSIGNED NOT NULL, x MEDIUMINT NOT NULL, y SMALLINT UNSIGNED NOT NULL, z MEDIUMINT NOT NULL, PRIMARY KEY (id), KEY coords (x, z, y), KEY date (date), KEY playerid (playerid))"); createTable(dbm, state, wcfg.table, "(id INT UNSIGNED NOT NULL AUTO_INCREMENT, date DATETIME NOT NULL, playerid INT UNSIGNED NOT NULL, replaced TINYINT UNSIGNED NOT NULL, type TINYINT UNSIGNED NOT NULL, data TINYINT UNSIGNED NOT NULL, x MEDIUMINT NOT NULL, y SMALLINT UNSIGNED NOT NULL, z MEDIUMINT NOT NULL, PRIMARY KEY (id), KEY coords (x, z, y), KEY date (date), KEY playerid (playerid))");
createTable(dbm, state, wcfg.table + "-sign", "(id INT UNSIGNED NOT NULL, signtext VARCHAR(255) NOT NULL, PRIMARY KEY (id)) DEFAULT CHARSET utf8"); createTable(dbm, state, wcfg.table + "-sign", "(id INT UNSIGNED NOT NULL, signtext VARCHAR(255) NOT NULL, PRIMARY KEY (id)) DEFAULT CHARSET utf8");
createTable(dbm, state, wcfg.table + "-chest", "(id INT UNSIGNED NOT NULL, itemtype SMALLINT UNSIGNED NOT NULL, itemamount SMALLINT NOT NULL, itemdata TINYINT UNSIGNED NOT NULL, PRIMARY KEY (id))"); createTable(dbm, state, wcfg.table + "-chest", "(id INT UNSIGNED NOT NULL, itemtype SMALLINT UNSIGNED NOT NULL, itemamount SMALLINT NOT NULL, itemdata SMALLINT UNSIGNED NOT 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))");
} }

View File

@@ -71,7 +71,7 @@ public class WorldEditor implements Runnable
this.sender = sender; this.sender = sender;
} }
public void queueEdit(int x, int y, int z, int replaced, int type, byte data, String signtext, short itemType, short itemAmount, byte itemData) { public void queueEdit(int x, int y, int z, int replaced, int type, byte data, String signtext, short itemType, short itemAmount, short itemData) {
edits.add(new Edit(0, new Location(world, x, y, z), null, replaced, type, data, signtext, new ChestAccess(itemType, itemAmount, itemData))); edits.add(new Edit(0, new Location(world, x, y, z), null, replaced, type, data, signtext, new ChestAccess(itemType, itemAmount, itemData)));
} }
@@ -165,11 +165,11 @@ public class WorldEditor implements Runnable
} else if (ca != null && (type == 23 || type == 54 || type == 61 || type == 62)) { } else if (ca != null && (type == 23 || type == 54 || type == 61 || type == 62)) {
int leftover; int leftover;
try { try {
leftover = modifyContainer(state, new ItemStack(ca.itemType, -ca.itemAmount, (short)0, ca.itemData)); leftover = modifyContainer(state, new ItemStack(ca.itemType, -ca.itemAmount, ca.itemData));
if (leftover > 0) if (leftover > 0)
for (final BlockFace face : new BlockFace[]{BlockFace.NORTH, BlockFace.SOUTH, BlockFace.EAST, BlockFace.WEST}) for (final BlockFace face : new BlockFace[]{BlockFace.NORTH, BlockFace.SOUTH, BlockFace.EAST, BlockFace.WEST})
if (block.getRelative(face).getTypeId() == 54) if (block.getRelative(face).getTypeId() == 54)
leftover = modifyContainer(block.getRelative(face).getState(), new ItemStack(ca.itemType, ca.itemAmount < 0 ? leftover : -leftover, (short)0, ca.itemData)); leftover = modifyContainer(block.getRelative(face).getState(), new ItemStack(ca.itemType, ca.itemAmount < 0 ? leftover : -leftover, ca.itemData));
} catch (final Exception ex) { } catch (final Exception ex) {
throw new WorldEditorException(ex.getMessage(), block.getLocation()); throw new WorldEditorException(ex.getMessage(), block.getLocation());
} }

View File

@@ -242,7 +242,7 @@ public class BukkitUtils
for (final ItemStack item : items) for (final ItemStack item : items)
if (item != null) { if (item != null) {
final int type = item.getTypeId(); final int type = item.getTypeId();
final byte data = rawData(item); final short data = rawData(item);
boolean found = false; boolean found = false;
for (final ItemStack item2 : compressed) for (final ItemStack item2 : compressed)
if (type == item2.getTypeId() && data == rawData(item2)) { if (type == item2.getTypeId() && data == rawData(item2)) {
@@ -251,7 +251,7 @@ public class BukkitUtils
break; break;
} }
if (!found) if (!found)
compressed.add(new ItemStack(type, item.getAmount(), (short)0, data)); compressed.add(new ItemStack(type, item.getAmount(), data));
} }
Collections.sort(compressed, new ItemStackComparator()); Collections.sort(compressed, new ItemStackComparator());
return compressed.toArray(new ItemStack[compressed.size()]); return compressed.toArray(new ItemStack[compressed.size()]);
@@ -322,8 +322,8 @@ public class BukkitUtils
} }
} }
public static byte rawData(ItemStack item) { public static short rawData(ItemStack item) {
return item.getType() != null ? item.getData() != null ? item.getData().getData() : 0 : 0; return item.getType() != null ? item.getData() != null ? item.getDurability() : 0 : 0;
} }
public static int saveSpawnHeight(Location loc) { public static int saveSpawnHeight(Location loc) {
@@ -381,7 +381,7 @@ public class BukkitUtils
return -1; return -1;
if (aType > bType) if (aType > bType)
return 1; return 1;
final byte aData = rawData(a), bData = rawData(b); final short aData = rawData(a), bData = rawData(b);
if (aData < bData) if (aData < bData)
return -1; return -1;
if (aData > bData) if (aData > bData)

View File

@@ -1,7 +1,7 @@
package de.diddiz.util; package de.diddiz.util;
import static de.diddiz.util.Utils.isByte;
import static de.diddiz.util.Utils.isInt; import static de.diddiz.util.Utils.isInt;
import static de.diddiz.util.Utils.isShort;
import static org.bukkit.Bukkit.getLogger; import static org.bukkit.Bukkit.getLogger;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
@@ -16,7 +16,7 @@ import org.bukkit.material.MaterialData;
public class MaterialName public class MaterialName
{ {
private static final Map<Integer, String> materialNames = new HashMap<Integer, String>(); private static final Map<Integer, String> materialNames = new HashMap<Integer, String>();
private static final Map<Integer, Map<Byte, String>> materialDataNames = new HashMap<Integer, Map<Byte, String>>(); private static final Map<Integer, Map<Short, String>> materialDataNames = new HashMap<Integer, Map<Short, String>>();
static { static {
// Add all known materials // Add all known materials
@@ -57,13 +57,13 @@ public class MaterialName
if (cfg.isString(entry)) if (cfg.isString(entry))
materialNames.put(Integer.valueOf(entry), cfg.getString(entry)); materialNames.put(Integer.valueOf(entry), cfg.getString(entry));
else if (cfg.isConfigurationSection(entry)) { else if (cfg.isConfigurationSection(entry)) {
final Map<Byte, String> dataNames = new HashMap<Byte, String>(); final Map<Short, String> dataNames = new HashMap<Short, String>();
materialDataNames.put(Integer.valueOf(entry), dataNames); materialDataNames.put(Integer.valueOf(entry), dataNames);
final ConfigurationSection sec = cfg.getConfigurationSection(entry); final ConfigurationSection sec = cfg.getConfigurationSection(entry);
for (final String data : sec.getKeys(false)) for (final String data : sec.getKeys(false))
if (isByte(data)) { if (isShort(data)) {
if (sec.isString(data)) if (sec.isString(data))
dataNames.put(Byte.valueOf(data), sec.getString(data)); dataNames.put(Short.valueOf(data), sec.getString(data));
else else
getLogger().warning("Parsing materials.yml: '" + data + "' is not a string."); getLogger().warning("Parsing materials.yml: '" + data + "' is not a string.");
} else } else
@@ -84,8 +84,8 @@ public class MaterialName
/** /**
* @return Name of the material regarding it's data, or if it's unknown, the basic name. * @return Name of the material regarding it's data, or if it's unknown, the basic name.
*/ */
public static String materialName(int type, byte data) { public static String materialName(int type, short data) {
final Map<Byte, String> dataNames = materialDataNames.get(type); final Map<Short, String> dataNames = materialDataNames.get(type);
if (dataNames != null) if (dataNames != null)
if (dataNames.containsKey(data)) if (dataNames.containsKey(data))
return dataNames.get(data); return dataNames.get(data);

View File

@@ -19,6 +19,15 @@ public class Utils
return false; return false;
} }
public static boolean isShort(String str) {
try {
Short.parseShort(str);
return true;
} catch (final NumberFormatException ex) {
}
return false;
}
public static boolean isByte(String str) { public static boolean isByte(String str) {
try { try {
Byte.parseByte(str); Byte.parseByte(str);

View File

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