Added inventory rollback support for online players

This commit is contained in:
Intelli 2022-02-11 21:45:33 -07:00
parent 29d55e6ba9
commit a2353afd0a
13 changed files with 230 additions and 60 deletions

View file

@ -17,6 +17,7 @@ import org.bukkit.inventory.ItemStack;
import net.coreprotect.CoreProtect;
import net.coreprotect.config.ConfigHandler;
import net.coreprotect.consumer.Queue;
import net.coreprotect.consumer.process.Process;
import net.coreprotect.language.Phrase;
import net.coreprotect.model.BlockGroup;
import net.coreprotect.utility.Chat;
@ -38,7 +39,7 @@ public class ContainerRollback extends Queue {
userString = user.getName();
}
Queue.queueContainerRollbackUpdate(userString, location, lookupList, rollbackType); // Perform update transaction in consumer
Queue.queueRollbackUpdate(userString, location, lookupList, Process.CONTAINER_ROLLBACK_UPDATE, rollbackType); // Perform update transaction in consumer
final String finalUserString = userString;
ConfigHandler.rollbackHash.put(userString, new int[] { 0, 0, 0, 0 });

View file

@ -197,6 +197,12 @@ public class Database extends Queue {
if (table == 1) {
statement.executeUpdate("UPDATE " + ConfigHandler.prefix + "container SET rolled_back='" + rolledBack + "' WHERE rowid='" + id + "'");
}
else if (table == 2) {
statement.executeUpdate("UPDATE " + ConfigHandler.prefix + "item SET rolled_back='" + rolledBack + "' WHERE rowid='" + id + "'");
}
else if (table == 3) {
statement.executeUpdate("UPDATE " + ConfigHandler.prefix + "container SET rolled_back_inventory='" + rolledBack + "' WHERE rowid='" + id + "'");
}
else {
statement.executeUpdate("UPDATE " + ConfigHandler.prefix + "block SET rolled_back='" + rolledBack + "' WHERE rowid='" + id + "'");
}
@ -212,8 +218,8 @@ public class Database extends Queue {
String signInsert = "INSERT INTO " + ConfigHandler.prefix + "sign (time, user, wid, x, y, z, action, color, data, line_1, line_2, line_3, line_4) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
String blockInsert = "INSERT INTO " + ConfigHandler.prefix + "block (time, user, wid, x, y, z, type, data, meta, blockdata, action, rolled_back) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
String skullInsert = "INSERT INTO " + ConfigHandler.prefix + "skull (time, owner) VALUES (?, ?)";
String containerInsert = "INSERT INTO " + ConfigHandler.prefix + "container (time, user, wid, x, y, z, type, data, amount, metadata, action, rolled_back) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
String itemInsert = "INSERT INTO " + ConfigHandler.prefix + "item (time, user, wid, x, y, z, type, data, amount, action) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
String containerInsert = "INSERT INTO " + ConfigHandler.prefix + "container (time, user, wid, x, y, z, type, data, amount, metadata, action, rolled_back, rolled_back_inventory) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
String itemInsert = "INSERT INTO " + ConfigHandler.prefix + "item (time, user, wid, x, y, z, type, data, amount, action, rolled_back) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
String worldInsert = "INSERT INTO " + ConfigHandler.prefix + "world (id, world) VALUES (?, ?)";
String chatInsert = "INSERT INTO " + ConfigHandler.prefix + "chat (time, user, wid, x, y, z, message) VALUES (?, ?, ?, ?, ?, ?, ?)";
String commandInsert = "INSERT INTO " + ConfigHandler.prefix + "command (time, user, wid, x, y, z, message) VALUES (?, ?, ?, ?, ?, ?, ?)";
@ -333,9 +339,9 @@ public class Database extends Queue {
index = ", INDEX(time), INDEX(user,time), INDEX(wid,x,z,time)";
statement.executeUpdate("CREATE TABLE IF NOT EXISTS " + prefix + "command(rowid int(8) NOT NULL AUTO_INCREMENT,PRIMARY KEY(rowid),time int(10), user int(8), wid int(4), x int(8), y int (3), z int(8), message varchar(16000)" + index + ") ENGINE=InnoDB DEFAULT CHARACTER SET utf8mb4");
index = ", INDEX(wid,x,z,time), INDEX(user,time), INDEX(type,time)";
statement.executeUpdate("CREATE TABLE IF NOT EXISTS " + prefix + "container(rowid int(10) NOT NULL AUTO_INCREMENT,PRIMARY KEY(rowid), time int(10), user int(8), wid int(4), x int(8), y int(3), z int(8), type int(6), data int(6), amount int(4), metadata blob, action int(2), rolled_back tinyint(1)" + index + ") ENGINE=InnoDB DEFAULT CHARACTER SET utf8mb4");
statement.executeUpdate("CREATE TABLE IF NOT EXISTS " + prefix + "container(rowid int(10) NOT NULL AUTO_INCREMENT,PRIMARY KEY(rowid), time int(10), user int(8), wid int(4), x int(8), y int(3), z int(8), type int(6), data int(6), amount int(4), metadata blob, action int(2), rolled_back tinyint(1), rolled_back_inventory tinyint(1)" + index + ") ENGINE=InnoDB DEFAULT CHARACTER SET utf8mb4");
index = ", INDEX(wid,x,z,time), INDEX(user,time), INDEX(type,time)";
statement.executeUpdate("CREATE TABLE IF NOT EXISTS " + prefix + "item(rowid int(10) NOT NULL AUTO_INCREMENT,PRIMARY KEY(rowid), time int(10), user int(8), wid int(4), x int(8), y int(3), z int(8), type int(6), data blob, amount int(4), action tinyint(1)" + index + ") ENGINE=InnoDB DEFAULT CHARACTER SET utf8mb4");
statement.executeUpdate("CREATE TABLE IF NOT EXISTS " + prefix + "item(rowid int(10) NOT NULL AUTO_INCREMENT,PRIMARY KEY(rowid), time int(10), user int(8), wid int(4), x int(8), y int(3), z int(8), type int(6), data blob, amount int(4), action tinyint(1), rolled_back tinyint(1)" + index + ") ENGINE=InnoDB DEFAULT CHARACTER SET utf8mb4");
statement.executeUpdate("CREATE TABLE IF NOT EXISTS " + prefix + "database_lock(rowid int(8) NOT NULL AUTO_INCREMENT,PRIMARY KEY(rowid),status tinyint(1),time int(10)) ENGINE=InnoDB DEFAULT CHARACTER SET utf8mb4");
statement.executeUpdate("CREATE TABLE IF NOT EXISTS " + prefix + "entity(rowid int(8) NOT NULL AUTO_INCREMENT,PRIMARY KEY(rowid), time int(10), data blob) ENGINE=InnoDB DEFAULT CHARACTER SET utf8mb4");
index = ", INDEX(id)";
@ -411,10 +417,10 @@ public class Database extends Queue {
statement.executeUpdate("CREATE TABLE IF NOT EXISTS " + prefix + "command (time INTEGER, user INTEGER, wid INTEGER, x INTEGER, y INTEGER, z INTEGER, message TEXT);");
}
if (!tableData.contains(prefix + "container")) {
statement.executeUpdate("CREATE TABLE IF NOT EXISTS " + prefix + "container (time INTEGER, user INTEGER, wid INTEGER, x INTEGER, y INTEGER, z INTEGER, type INTEGER, data INTEGER, amount INTEGER, metadata BLOB, action INTEGER, rolled_back INTEGER);");
statement.executeUpdate("CREATE TABLE IF NOT EXISTS " + prefix + "container (time INTEGER, user INTEGER, wid INTEGER, x INTEGER, y INTEGER, z INTEGER, type INTEGER, data INTEGER, amount INTEGER, metadata BLOB, action INTEGER, rolled_back INTEGER, rolled_back_inventory INTEGER);");
}
if (!tableData.contains(prefix + "item")) {
statement.executeUpdate("CREATE TABLE IF NOT EXISTS " + prefix + "item (time INTEGER, user INTEGER, wid INTEGER, x INTEGER, y INTEGER, z INTEGER, type INTEGER, data BLOB, amount INTEGER, action INTEGER);");
statement.executeUpdate("CREATE TABLE IF NOT EXISTS " + prefix + "item (time INTEGER, user INTEGER, wid INTEGER, x INTEGER, y INTEGER, z INTEGER, type INTEGER, data BLOB, amount INTEGER, action INTEGER, rolled_back INTEGER);");
}
if (!tableData.contains(prefix + "database_lock")) {
statement.executeUpdate("CREATE TABLE IF NOT EXISTS " + prefix + "database_lock (status INTEGER, time INTEGER);");

View file

@ -56,7 +56,7 @@ public class Lookup extends Queue {
else if (i == 13 && map[i] instanceof Byte[]) {
results[newId] = Util.byteDataToString((byte[]) map[i], (int) map[6]);
}
else if (i > 0) {
else if (i > 0) { // skip rowid
if (map[i] instanceof Integer) {
results[newId] = map[i].toString();
}
@ -125,6 +125,10 @@ public class Lookup extends Queue {
invalidRollbackActions.add(3);
}
if (actionList.contains(4) && actionList.contains(11)) {
invalidRollbackActions.clear();
}
try {
while (Consumer.isPaused) {
Thread.sleep(1);
@ -211,6 +215,7 @@ public class Lookup extends Queue {
else {
int resultData = 0;
int resultAmount = -1;
int resultTable = 0;
byte[] resultMeta = null;
byte[] resultBlockData = null;
long resultId = results.getLong("id");
@ -224,10 +229,15 @@ public class Lookup extends Queue {
int resultZ = results.getInt("z");
int resultWorldId = results.getInt("wid");
boolean hasTbl = false;
if ((lookup && actionList.size() == 0) || actionList.contains(4) || actionList.contains(5) || actionList.contains(11)) {
resultData = results.getInt("data");
resultAmount = results.getInt("amount");
resultMeta = results.getBytes("metadata");
if (!lookup) {
resultTable = results.getInt("tbl");
hasTbl = true;
}
}
else {
resultData = results.getInt("data");
@ -236,7 +246,6 @@ public class Lookup extends Queue {
}
boolean valid = true;
if (!lookup) {
if (invalidRollbackActions.contains(resultAction)) {
valid = false;
@ -244,8 +253,14 @@ public class Lookup extends Queue {
}
if (valid) {
Object[] dataArray = new Object[] { resultId, resultTime, resultUserId, resultX, resultY, resultZ, resultType, resultData, resultAction, resultRolledBack, resultWorldId, resultAmount, resultMeta, resultBlockData };
list.add(dataArray);
if (hasTbl) {
Object[] dataArray = new Object[] { resultId, resultTime, resultUserId, resultX, resultY, resultZ, resultType, resultData, resultAction, resultRolledBack, resultWorldId, resultAmount, resultMeta, resultBlockData, resultTable };
list.add(dataArray);
}
else {
Object[] dataArray = new Object[] { resultId, resultTime, resultUserId, resultX, resultY, resultZ, resultType, resultData, resultAction, resultRolledBack, resultWorldId, resultAmount, resultMeta, resultBlockData };
list.add(dataArray);
}
}
}
}
@ -661,25 +676,25 @@ public class Lookup extends Queue {
baseQuery = baseQuery.replace("action NOT IN(-1)", "action NOT IN(3)"); // if block specified for include/exclude, filter out entity data
}
query = unionSelect + "SELECT " + (count ? "'0' as tbl," : "") + rows + " FROM " + ConfigHandler.prefix + queryTable + " " + index + "WHERE" + baseQuery + unionLimit + ") UNION ALL ";
query = unionSelect + "SELECT " + "'0' as tbl," + rows + " FROM " + ConfigHandler.prefix + queryTable + " " + index + "WHERE" + baseQuery + unionLimit + ") UNION ALL ";
itemLookup = true;
}
if (itemLookup) {
if (!count) {
rows = "rowid as id,time,user,wid,x,y,z,type,metadata,data,amount,action,rolled_back";
rows = "rowid as id,time,user,wid,x,y,z,type,metadata,data,amount,action,rolled_back_inventory as rolled_back";
}
query = query + unionSelect + "SELECT " + (count ? "'1' as tbl," : "") + rows + " FROM " + ConfigHandler.prefix + "container WHERE" + queryBlock + unionLimit + ") UNION ALL ";
query = query + unionSelect + "SELECT " + "'1' as tbl," + rows + " FROM " + ConfigHandler.prefix + "container WHERE" + queryBlock + unionLimit + ") UNION ALL ";
if (!count) {
rows = "rowid as id,time,user,wid,x,y,z,type,data as metadata,0 as data,amount,action,0 as rolled_back";
rows = "rowid as id,time,user,wid,x,y,z,type,data as metadata,0 as data,amount,action,rolled_back";
queryOrder = " ORDER BY time DESC, id DESC";
}
query = query + unionSelect + "SELECT " + (count ? "'2' as tbl," : "") + rows + " FROM " + ConfigHandler.prefix + "item WHERE" + queryBlock + unionLimit + ")";
query = query + unionSelect + "SELECT " + "'2' as tbl," + rows + " FROM " + ConfigHandler.prefix + "item WHERE" + queryBlock + unionLimit + ")";
}
if (query.length() == 0) {
query = "SELECT " + (count ? "'0' as tbl," : "") + rows + " FROM " + ConfigHandler.prefix + queryTable + " " + index + "WHERE" + baseQuery;
query = "SELECT " + "'0' as tbl," + rows + " FROM " + ConfigHandler.prefix + queryTable + " " + index + "WHERE" + baseQuery;
}
query = query + queryOrder + queryLimit + "";

View file

@ -15,6 +15,7 @@ import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TreeMap;
import java.util.UUID;
import org.bukkit.Bukkit;
import org.bukkit.DyeColor;
@ -75,6 +76,8 @@ import net.coreprotect.bukkit.BukkitAdapter;
import net.coreprotect.config.Config;
import net.coreprotect.config.ConfigHandler;
import net.coreprotect.consumer.Queue;
import net.coreprotect.consumer.process.Process;
import net.coreprotect.database.logger.ItemLogger;
import net.coreprotect.database.statement.UserStatement;
import net.coreprotect.language.Phrase;
import net.coreprotect.language.Selector;
@ -136,6 +139,7 @@ public class Rollback extends Queue {
TreeMap<Long, Integer> chunkList = new TreeMap<>();
HashMap<Long, ArrayList<Object[]>> dataList = new HashMap<>();
HashMap<Long, ArrayList<Object[]>> itemDataList = new HashMap<>();
boolean inventoryRollback = actionList.contains(11);
/*
int worldMin = BukkitAdapter.ADAPTER.getMinHeight(world);
@ -170,7 +174,7 @@ public class Rollback extends Queue {
int rowWorldId = (Integer) result[10];
int chunkX = rowX >> 4;
int chunkZ = rowZ >> 4;
long chunkKey = chunkX & 0xffffffffL | (chunkZ & 0xffffffffL) << 32;
long chunkKey = inventoryRollback ? 0 : (chunkX & 0xffffffffL | (chunkZ & 0xffffffffL) << 32);
// int rowAction = result[8];
// if (rowAction==10) result[8] = 0;
// if (rowAction==11) result[8] = 1;
@ -237,7 +241,7 @@ public class Rollback extends Queue {
String userString = "#server";
if (user != null) {
userString = user.getName();
if (verbose && preview == 0) {
if (verbose && preview == 0 && !actionList.contains(11)) {
Integer chunks = chunkList.size();
Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ROLLBACK_CHUNKS_FOUND, chunks.toString(), (chunks == 1 ? Selector.FIRST : Selector.SECOND)));
}
@ -245,8 +249,25 @@ public class Rollback extends Queue {
// Perform update transaction(s) in consumer
if (preview == 0) {
Queue.queueRollbackUpdate(userString, location, lookupList, rollbackType);
Queue.queueContainerRollbackUpdate(userString, location, itemList, rollbackType);
if (actionList.contains(11)) {
List<Object[]> inventoryList = new ArrayList<>();
List<Object[]> containerList = new ArrayList<>();
for (Object[] data : itemList) {
int table = (Integer) data[14];
if (table == 2) { // item
inventoryList.add(data);
}
else {
containerList.add(data);
}
}
Queue.queueRollbackUpdate(userString, location, inventoryList, Process.INVENTORY_ROLLBACK_UPDATE, rollbackType);
Queue.queueRollbackUpdate(userString, location, containerList, Process.INVENTORY_CONTAINER_ROLLBACK_UPDATE, rollbackType);
}
else {
Queue.queueRollbackUpdate(userString, location, lookupList, Process.ROLLBACK_UPDATE, rollbackType);
Queue.queueRollbackUpdate(userString, location, itemList, Process.CONTAINER_ROLLBACK_UPDATE, rollbackType);
}
}
ConfigHandler.rollbackHash.put(userString, new int[] { 0, 0, 0, 0 });
@ -272,7 +293,6 @@ public class Rollback extends Queue {
Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(CoreProtect.getInstance(), () -> {
try {
boolean clearInventories = false;
if (Config.getGlobal().ROLLBACK_ITEMS) {
clearInventories = true;
}
@ -1010,11 +1030,52 @@ public class Rollback extends Queue {
byte[] rowMetadata = (byte[]) row[12];
Material rowType = Util.getType(rowTypeRaw);
if (rowAction > 1) {
continue; // skip inventory & ender chest transactions
}
if ((rollbackType == 0 && rowRolledBack == 0) || (rollbackType == 1 && rowRolledBack == 1)) {
if (inventoryRollback) {
int rowUserId = (Integer) row[2];
String rowUser = ConfigHandler.playerIdCacheReversed.get(rowUserId);
if (rowUser == null) {
continue;
}
String uuid = ConfigHandler.uuidCache.get(rowUser.toLowerCase(Locale.ROOT));
if (uuid == null) {
continue;
}
Player player = Bukkit.getServer().getPlayer(UUID.fromString(uuid));
if (player == null) {
continue;
}
int inventoryAction = 0;
if (rowAction == ItemLogger.ITEM_DROP || rowAction == ItemLogger.ITEM_PICKUP) {
inventoryAction = (rowAction == ItemLogger.ITEM_PICKUP ? 1 : 0);
}
else if (rowAction == ItemLogger.ITEM_REMOVE_ENDER || rowAction == ItemLogger.ITEM_ADD_ENDER) {
inventoryAction = (rowAction == ItemLogger.ITEM_REMOVE_ENDER ? 1 : 0);
}
else {
inventoryAction = (rowAction == ItemLogger.ITEM_REMOVE ? 1 : 0);
}
int action = rollbackType == 0 ? (inventoryAction ^ 1) : inventoryAction;
ItemStack itemstack = new ItemStack(rowType, rowAmount, (short) rowData);
Object[] populatedStack = populateItemStack(itemstack, rowMetadata);
if (rowAction == ItemLogger.ITEM_REMOVE_ENDER || rowAction == ItemLogger.ITEM_ADD_ENDER) {
modifyContainerItems(containerType, player.getEnderChest(), (Integer) populatedStack[0], ((ItemStack) populatedStack[1]).clone(), action ^ 1);
}
modifyContainerItems(containerType, player.getInventory(), (Integer) populatedStack[0], (ItemStack) populatedStack[1], action);
itemCount1 = itemCount1 + rowAmount;
ConfigHandler.rollbackHash.put(finalUserString, new int[] { itemCount1, blockCount1, entityCount1, 0 });
continue; // remove this for merged rollbacks in future? (be sure to re-enable chunk sorting)
}
if (rowAction > 1) {
continue; // skip inventory & ender chest transactions
}
if (!containerInit || rowX != lastX || rowY != lastY || rowZ != lastZ || rowWorldId != lastWorldId) {
container = null; // container patch 2.14.0
String world = Util.getWorldName(rowWorldId);
@ -1143,7 +1204,7 @@ public class Rollback extends Queue {
entityCount = rollbackHashData[2];
ConfigHandler.rollbackHash.put(finalUserString, new int[] { itemCount, blockCount, entityCount, 0 });
if (verbose && user != null && preview == 0) {
if (verbose && user != null && preview == 0 && !actionList.contains(11)) {
Integer chunks = chunkList.size();
Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ROLLBACK_CHUNKS_MODIFIED, chunkCount.toString(), chunks.toString(), (chunks == 1 ? Selector.FIRST : Selector.SECOND)));
}
@ -1229,7 +1290,18 @@ public class Rollback extends Queue {
}
}
if (actionList.contains(4)) {
if (actionList.contains(4) && actionList.contains(11)) {
if (actionList.contains(0)) {
Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ROLLBACK_WORLD_ACTION, "+inventory", Selector.SECOND));
}
else if (actionList.contains(1)) {
Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ROLLBACK_WORLD_ACTION, "-inventory", Selector.SECOND));
}
else {
Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ROLLBACK_WORLD_ACTION, "inventory", Selector.SECOND));
}
}
else if (actionList.contains(4)) {
if (actionList.contains(0)) {
Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ROLLBACK_WORLD_ACTION, "-container", Selector.SECOND));
}
@ -1346,6 +1418,13 @@ public class Rollback extends Queue {
int excludeCount = 0;
for (String excludeUser : excludeUserList) {
// don't display that excluded #hopper in inventory rollbacks
if (actionList.contains(4) && actionList.contains(11)) {
if (excludeUser.equals("#hopper")) {
continue;
}
}
if (excludeCount == 0) {
excludeUsers = excludeUsers.append("" + excludeUser + "");
}
@ -1356,7 +1435,9 @@ public class Rollback extends Queue {
excludeCount++;
}
Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ROLLBACK_EXCLUDED_USERS, excludeUsers.toString(), (excludeCount == 1 ? Selector.FIRST : Selector.SECOND)));
if (excludeCount > 0) {
Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ROLLBACK_EXCLUDED_USERS, excludeUsers.toString(), (excludeCount == 1 ? Selector.FIRST : Selector.SECOND)));
}
}
StringBuilder modifiedData = new StringBuilder();
@ -1366,7 +1447,7 @@ public class Rollback extends Queue {
modifyCount++;
}
else if (preview == 0) {
if (itemCount > 0) {
if (itemCount > 0 || actionList.contains(4)) {
modifiedData = modifiedData.append(Phrase.build(Phrase.AMOUNT_ITEM, NumberFormat.getInstance().format(itemCount), (itemCount == 1 ? Selector.FIRST : Selector.SECOND)));
modifyCount++;
}
@ -1379,11 +1460,13 @@ public class Rollback extends Queue {
modifyCount++;
}
if (modifyCount > 0) {
modifiedData.append(", ");
if (blockCount > 0 || !actionList.contains(4)) {
if (modifyCount > 0) {
modifiedData.append(", ");
}
modifiedData.append(Phrase.build(Phrase.AMOUNT_BLOCK, NumberFormat.getInstance().format(blockCount), (blockCount == 1 ? Selector.FIRST : Selector.SECOND)));
modifyCount++;
}
modifiedData.append(Phrase.build(Phrase.AMOUNT_BLOCK, NumberFormat.getInstance().format(blockCount), (blockCount == 1 ? Selector.FIRST : Selector.SECOND)));
modifyCount++;
}
else if (preview > 0) {
modifiedData = modifiedData.append(Phrase.build(Phrase.AMOUNT_BLOCK, NumberFormat.getInstance().format(blockCount), (blockCount == 1 ? Selector.FIRST : Selector.SECOND)));
@ -1391,7 +1474,7 @@ public class Rollback extends Queue {
}
StringBuilder modifiedDataVerbose = new StringBuilder();
if (verbose && preview == 0) {
if (verbose && preview == 0 && !actionList.contains(11)) {
if (chunkCount > -1 && modifyCount < 3) {
if (modifyCount > 0) {
modifiedData.append(", ");
@ -1428,7 +1511,7 @@ public class Rollback extends Queue {
try {
ItemStack[] contents = null;
if (type.equals(Material.ARMOR_STAND)) {
if (type != null && type.equals(Material.ARMOR_STAND)) {
EntityEquipment equipment = (EntityEquipment) container;
if (equipment != null) {
if (action == 1) {

View file

@ -25,6 +25,7 @@ public class ContainerStatement {
preparedStmt.setObject(10, byteData);
preparedStmt.setInt(11, action);
preparedStmt.setInt(12, rolledBack);
preparedStmt.setInt(13, 0); // rolled_back_inventory
preparedStmt.addBatch();
if (batchCount > 0 && batchCount % 1000 == 0) {

View file

@ -23,6 +23,7 @@ public class ItemStatement {
preparedStmt.setObject(8, byteData);
preparedStmt.setInt(9, amount);
preparedStmt.setInt(10, action);
preparedStmt.setInt(11, 0); // rolled_back
preparedStmt.addBatch();
if (batchCount > 0 && batchCount % 1000 == 0) {