Fixed item frame transactions not logging BlockFace data

This commit is contained in:
Intelli 2022-02-18 17:31:35 -07:00
parent c652ce852f
commit 527be90249
10 changed files with 72 additions and 30 deletions

View File

@ -123,7 +123,7 @@ public class Bukkit_v1_17 extends Bukkit_v1_16 implements BukkitInterface {
if (subMeta.hasItems()) { if (subMeta.hasItems()) {
list = new ArrayList<>(); list = new ArrayList<>();
for (ItemStack itemStack : subMeta.getItems()) { for (ItemStack itemStack : subMeta.getItems()) {
Map<String, Object> itemMap = Util.serializeItemStack(itemStack, slot); Map<String, Object> itemMap = Util.serializeItemStack(itemStack, null, slot);
if (itemMap.size() > 0) { if (itemMap.size() > 0) {
list.add(itemMap); list.add(itemMap);
} }

View File

@ -1,6 +1,7 @@
package net.coreprotect.database; package net.coreprotect.database;
import java.sql.Statement; import java.sql.Statement;
import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
@ -8,6 +9,7 @@ import org.bukkit.Bukkit;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.block.Block; import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.bukkit.entity.ArmorStand; import org.bukkit.entity.ArmorStand;
import org.bukkit.entity.Entity; import org.bukkit.entity.Entity;
@ -60,6 +62,7 @@ public class ContainerRollback extends Queue {
} }
Object container = null; Object container = null;
Material type = block.getType(); Material type = block.getType();
List<ItemFrame> matchingFrames = new ArrayList<>();
if (BlockGroup.CONTAINERS.contains(type)) { if (BlockGroup.CONTAINERS.contains(type)) {
container = Util.getContainerInventory(block.getState(), false); container = Util.getContainerInventory(block.getState(), false);
@ -74,6 +77,7 @@ public class ContainerRollback extends Queue {
else if (entity instanceof ItemFrame) { else if (entity instanceof ItemFrame) {
type = Material.ITEM_FRAME; type = Material.ITEM_FRAME;
container = entity; container = entity;
matchingFrames.add((ItemFrame) entity);
} }
} }
} }
@ -113,12 +117,27 @@ public class ContainerRollback extends Queue {
ItemStack itemstack = new ItemStack(rowType, rowAmount, (short) rowData); ItemStack itemstack = new ItemStack(rowType, rowAmount, (short) rowData);
Object[] populatedStack = Rollback.populateItemStack(itemstack, rowMetadata); Object[] populatedStack = Rollback.populateItemStack(itemstack, rowMetadata);
int slot = (Integer) populatedStack[0]; int slot = (Integer) populatedStack[0];
itemstack = (ItemStack) populatedStack[1]; String faceData = (String) populatedStack[1];
itemstack = (ItemStack) populatedStack[2];
if (type == Material.ITEM_FRAME && faceData.length() > 0) {
BlockFace blockFace = BlockFace.valueOf(faceData);
ItemFrame itemFrame = (ItemFrame) container;
if (blockFace != itemFrame.getFacing()) {
for (ItemFrame frame : matchingFrames) {
if (blockFace == frame.getFacing()) {
container = frame;
break;
}
}
}
}
Rollback.modifyContainerItems(type, container, slot, itemstack, action); Rollback.modifyContainerItems(type, container, slot, itemstack, action);
} }
} }
} }
matchingFrames.clear();
ConfigHandler.rollbackHash.put(finalUserString, new int[] { itemCount, modifyCount, entityCount, 1 }); ConfigHandler.rollbackHash.put(finalUserString, new int[] { itemCount, modifyCount, entityCount, 1 });
} }

View File

@ -1010,6 +1010,7 @@ public class Rollback extends Queue {
int lastY = 0; int lastY = 0;
int lastZ = 0; int lastZ = 0;
int lastWorldId = 0; int lastWorldId = 0;
String lastFace = "";
for (Object[] row : itemData) { for (Object[] row : itemData) {
int[] rollbackHashData1 = ConfigHandler.rollbackHash.get(finalUserString); int[] rollbackHashData1 = ConfigHandler.rollbackHash.get(finalUserString);
@ -1028,7 +1029,7 @@ public class Rollback extends Queue {
byte[] rowMetadata = (byte[]) row[12]; byte[] rowMetadata = (byte[]) row[12];
Material rowType = Util.getType(rowTypeRaw); Material rowType = Util.getType(rowTypeRaw);
if ((rollbackType == 0 && rowRolledBack == 0) || (rollbackType == 1 && rowRolledBack == 1)) { if (rowType != null && ((rollbackType == 0 && rowRolledBack == 0) || (rollbackType == 1 && rowRolledBack == 1))) {
if (inventoryRollback) { if (inventoryRollback) {
int rowUserId = (Integer) row[2]; int rowUserId = (Integer) row[2];
String rowUser = ConfigHandler.playerIdCacheReversed.get(rowUserId); String rowUser = ConfigHandler.playerIdCacheReversed.get(rowUserId);
@ -1061,9 +1062,9 @@ public class Rollback extends Queue {
ItemStack itemstack = new ItemStack(rowType, rowAmount, (short) rowData); ItemStack itemstack = new ItemStack(rowType, rowAmount, (short) rowData);
Object[] populatedStack = populateItemStack(itemstack, rowMetadata); Object[] populatedStack = populateItemStack(itemstack, rowMetadata);
if (rowAction == ItemLogger.ITEM_REMOVE_ENDER || rowAction == ItemLogger.ITEM_ADD_ENDER) { 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.getEnderChest(), (Integer) populatedStack[0], ((ItemStack) populatedStack[2]).clone(), action ^ 1);
} }
modifyContainerItems(containerType, player.getInventory(), (Integer) populatedStack[0], (ItemStack) populatedStack[1], action); modifyContainerItems(containerType, player.getInventory(), (Integer) populatedStack[0], (ItemStack) populatedStack[2], action);
itemCount1 = itemCount1 + rowAmount; itemCount1 = itemCount1 + rowAmount;
ConfigHandler.rollbackHash.put(finalUserString, new int[] { itemCount1, blockCount1, entityCount1, 0 }); ConfigHandler.rollbackHash.put(finalUserString, new int[] { itemCount1, blockCount1, entityCount1, 0 });
@ -1074,7 +1075,11 @@ public class Rollback extends Queue {
continue; // skip inventory & ender chest transactions continue; // skip inventory & ender chest transactions
} }
if (!containerInit || rowX != lastX || rowY != lastY || rowZ != lastZ || rowWorldId != lastWorldId) { ItemStack itemstack = new ItemStack(rowType, rowAmount, (short) rowData);
Object[] populatedStack = populateItemStack(itemstack, rowMetadata);
String faceData = (String) populatedStack[1];
if (!containerInit || rowX != lastX || rowY != lastY || rowZ != lastZ || rowWorldId != lastWorldId || !faceData.equals(lastFace)) {
container = null; // container patch 2.14.0 container = null; // container patch 2.14.0
String world = Util.getWorldName(rowWorldId); String world = Util.getWorldName(rowWorldId);
if (world.length() == 0) { if (world.length() == 0) {
@ -1095,6 +1100,7 @@ public class Rollback extends Queue {
containerType = block.getType(); containerType = block.getType();
} }
else if (BlockGroup.CONTAINERS.contains(Material.ARMOR_STAND) || BlockGroup.CONTAINERS.contains(Material.ITEM_FRAME)) { else if (BlockGroup.CONTAINERS.contains(Material.ARMOR_STAND) || BlockGroup.CONTAINERS.contains(Material.ITEM_FRAME)) {
BlockFace blockFace = BlockFace.valueOf(faceData);
for (Entity entity : block.getChunk().getEntities()) { for (Entity entity : block.getChunk().getEntities()) {
if (entity.getLocation().getBlockX() == rowX && entity.getLocation().getBlockY() == rowY && entity.getLocation().getBlockZ() == rowZ) { if (entity.getLocation().getBlockX() == rowX && entity.getLocation().getBlockY() == rowY && entity.getLocation().getBlockZ() == rowZ) {
if (entity instanceof ArmorStand) { if (entity instanceof ArmorStand) {
@ -1104,6 +1110,9 @@ public class Rollback extends Queue {
else if (entity instanceof ItemFrame) { else if (entity instanceof ItemFrame) {
container = entity; container = entity;
containerType = Material.ITEM_FRAME; containerType = Material.ITEM_FRAME;
if (blockFace == ((ItemFrame) entity).getFacing()) {
break;
}
} }
} }
} }
@ -1113,9 +1122,10 @@ public class Rollback extends Queue {
lastY = rowY; lastY = rowY;
lastZ = rowZ; lastZ = rowZ;
lastWorldId = rowWorldId; lastWorldId = rowWorldId;
lastFace = faceData;
} }
if (container != null && rowType != null) { if (container != null) {
int action = 0; int action = 0;
if (rollbackType == 0 && rowAction == 0) { if (rollbackType == 0 && rowAction == 0) {
action = 1; action = 1;
@ -1125,10 +1135,8 @@ public class Rollback extends Queue {
action = 1; action = 1;
} }
ItemStack itemstack = new ItemStack(rowType, rowAmount, (short) rowData);
Object[] populatedStack = populateItemStack(itemstack, rowMetadata);
int slot = (Integer) populatedStack[0]; int slot = (Integer) populatedStack[0];
itemstack = (ItemStack) populatedStack[1]; itemstack = (ItemStack) populatedStack[2];
modifyContainerItems(containerType, container, slot, itemstack, action); modifyContainerItems(containerType, container, slot, itemstack, action);
itemCount1 = itemCount1 + rowAmount; itemCount1 = itemCount1 + rowAmount;
@ -1652,6 +1660,7 @@ public class Rollback extends Queue {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public static Object[] populateItemStack(ItemStack itemstack, Object list) { public static Object[] populateItemStack(ItemStack itemstack, Object list) {
int slot = 0; int slot = 0;
String faceData = "";
try { try {
/* /*
@ -1682,6 +1691,9 @@ public class Rollback extends Queue {
if (mapData.get("slot") != null) { if (mapData.get("slot") != null) {
slot = (Integer) mapData.get("slot"); slot = (Integer) mapData.get("slot");
} }
else if (mapData.get("facing") != null) {
faceData = (String) mapData.get("facing");
}
else if (mapData.get("modifiers") != null) { else if (mapData.get("modifiers") != null) {
ItemMeta itemMeta = itemstack.getItemMeta(); ItemMeta itemMeta = itemstack.getItemMeta();
if (itemMeta.hasAttributeModifiers()) { if (itemMeta.hasAttributeModifiers()) {
@ -1798,7 +1810,7 @@ public class Rollback extends Queue {
catch (Exception e) { catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
} }
return new Object[] { slot, itemstack }; return new Object[] { slot, faceData, itemstack };
} }
public static Object[] populateItemStack(ItemStack itemstack, byte[] metadata) { public static Object[] populateItemStack(ItemStack itemstack, byte[] metadata) {
@ -1817,7 +1829,7 @@ public class Rollback extends Queue {
} }
} }
return new Object[] { 0, itemstack }; return new Object[] { 0, "", itemstack };
} }
} }

View File

@ -19,7 +19,7 @@ public class ContainerBreakLogger {
public static void log(PreparedStatement preparedStmt, int batchCount, String player, Location l, Material type, ItemStack[] oldInventory) { public static void log(PreparedStatement preparedStmt, int batchCount, String player, Location l, Material type, ItemStack[] oldInventory) {
try { try {
Util.mergeItems(type, oldInventory); Util.mergeItems(type, oldInventory);
ContainerLogger.logTransaction(preparedStmt, batchCount, player, type, oldInventory, 0, l); ContainerLogger.logTransaction(preparedStmt, batchCount, player, type, null, oldInventory, 0, l);
String loggingContainerId = player.toLowerCase(Locale.ROOT) + "." + l.getBlockX() + "." + l.getBlockY() + "." + l.getBlockZ(); String loggingContainerId = player.toLowerCase(Locale.ROOT) + "." + l.getBlockX() + "." + l.getBlockY() + "." + l.getBlockZ();
// If there was a pending chest transaction, it would have already been processed. // If there was a pending chest transaction, it would have already been processed.

View File

@ -32,6 +32,8 @@ public class ContainerLogger extends Queue {
public static void log(PreparedStatement preparedStmtContainer, PreparedStatement preparedStmtItems, int batchCount, String player, Material type, Object container, Location location) { public static void log(PreparedStatement preparedStmtContainer, PreparedStatement preparedStmtItems, int batchCount, String player, Material type, Object container, Location location) {
try { try {
ItemStack[] contents = null; ItemStack[] contents = null;
String faceData = null;
if (type == Material.ARMOR_STAND) { if (type == Material.ARMOR_STAND) {
EntityEquipment equipment = (EntityEquipment) container; EntityEquipment equipment = (EntityEquipment) container;
if (equipment != null) { if (equipment != null) {
@ -41,6 +43,7 @@ public class ContainerLogger extends Queue {
else if (type == Material.ITEM_FRAME) { else if (type == Material.ITEM_FRAME) {
ItemFrame itemFrame = (ItemFrame) container; ItemFrame itemFrame = (ItemFrame) container;
contents = Util.getItemFrameItem(itemFrame); contents = Util.getItemFrameItem(itemFrame);
faceData = itemFrame.getFacing().name();
} }
else { else {
Inventory inventory = (Inventory) container; Inventory inventory = (Inventory) container;
@ -138,8 +141,8 @@ public class ContainerLogger extends Queue {
Util.mergeItems(type, newInventory); Util.mergeItems(type, newInventory);
if (type != Material.ENDER_CHEST) { if (type != Material.ENDER_CHEST) {
logTransaction(preparedStmtContainer, batchCount, player, type, oldInventory, 0, location); logTransaction(preparedStmtContainer, batchCount, player, type, faceData, oldInventory, 0, location);
logTransaction(preparedStmtContainer, batchCount, player, type, newInventory, 1, location); logTransaction(preparedStmtContainer, batchCount, player, type, faceData, newInventory, 1, location);
} }
else { // pass ender chest transactions to item logger else { // pass ender chest transactions to item logger
ItemLogger.logTransaction(preparedStmtItems, batchCount, player, location, oldInventory, ItemLogger.ITEM_REMOVE_ENDER); ItemLogger.logTransaction(preparedStmtItems, batchCount, player, location, oldInventory, ItemLogger.ITEM_REMOVE_ENDER);
@ -154,7 +157,7 @@ public class ContainerLogger extends Queue {
} }
} }
protected static void logTransaction(PreparedStatement preparedStmt, int batchCount, String user, Material type, ItemStack[] items, int action, Location location) { protected static void logTransaction(PreparedStatement preparedStmt, int batchCount, String user, Material type, String faceData, ItemStack[] items, int action, Location location) {
try { try {
if (ConfigHandler.blacklist.get(user.toLowerCase(Locale.ROOT)) != null) { if (ConfigHandler.blacklist.get(user.toLowerCase(Locale.ROOT)) != null) {
return; return;
@ -164,7 +167,7 @@ public class ContainerLogger extends Queue {
if (item != null) { if (item != null) {
if (item.getAmount() > 0 && !Util.isAir(item.getType())) { if (item.getAmount() > 0 && !Util.isAir(item.getType())) {
// Object[] metadata = new Object[] { slot, item.getItemMeta() }; // Object[] metadata = new Object[] { slot, item.getItemMeta() };
List<List<Map<String, Object>>> metadata = ItemMetaHandler.seralize(item, type, slot); List<List<Map<String, Object>>> metadata = ItemMetaHandler.seralize(item, type, faceData, slot);
if (metadata.size() == 0) { if (metadata.size() == 0) {
metadata = null; metadata = null;
} }

View File

@ -63,7 +63,7 @@ public class ItemLogger {
for (ItemStack item : items) { for (ItemStack item : items) {
if (item != null && item.getAmount() > 0 && !Util.isAir(item.getType())) { if (item != null && item.getAmount() > 0 && !Util.isAir(item.getType())) {
// Object[] metadata = new Object[] { slot, item.getItemMeta() }; // Object[] metadata = new Object[] { slot, item.getItemMeta() };
List<List<Map<String, Object>>> data = ItemMetaHandler.seralize(item, null, 0); List<List<Map<String, Object>>> data = ItemMetaHandler.seralize(item, null, null, 0);
if (data.size() == 0) { if (data.size() == 0) {
data = null; data = null;
} }

View File

@ -317,7 +317,7 @@ public final class EntityDeathListener extends Queue implements Listener {
List<Object> ingredients = new ArrayList<>(); List<Object> ingredients = new ArrayList<>();
List<Object> itemMap = new ArrayList<>(); List<Object> itemMap = new ArrayList<>();
ItemStack item = merchantRecipe.getResult().clone(); ItemStack item = merchantRecipe.getResult().clone();
List<List<Map<String, Object>>> metadata = ItemMetaHandler.seralize(item, item.getType(), 0); List<List<Map<String, Object>>> metadata = ItemMetaHandler.seralize(item, item.getType(), null, 0);
item.setItemMeta(null); item.setItemMeta(null);
itemMap.add(item.serialize()); itemMap.add(item.serialize());
itemMap.add(metadata); itemMap.add(metadata);
@ -329,7 +329,7 @@ public final class EntityDeathListener extends Queue implements Listener {
for (ItemStack ingredient : merchantRecipe.getIngredients()) { for (ItemStack ingredient : merchantRecipe.getIngredients()) {
itemMap = new ArrayList<>(); itemMap = new ArrayList<>();
item = ingredient.clone(); item = ingredient.clone();
metadata = ItemMetaHandler.seralize(item, item.getType(), 0); metadata = ItemMetaHandler.seralize(item, item.getType(), null, 0);
item.setItemMeta(null); item.setItemMeta(null);
itemMap.add(item.serialize()); itemMap.add(item.serialize());
itemMap.add(metadata); itemMap.add(metadata);

View File

@ -1220,9 +1220,9 @@ public class Util extends Queue {
return newVersion(convertArray(oldVersionSplit), convertArray(currentVersionSplit)); return newVersion(convertArray(oldVersionSplit), convertArray(currentVersionSplit));
} }
public static Map<Integer, Object> serializeItemStackLegacy(ItemStack itemStack, int slot) { public static Map<Integer, Object> serializeItemStackLegacy(ItemStack itemStack, String faceData, int slot) {
Map<Integer, Object> result = new HashMap<>(); Map<Integer, Object> result = new HashMap<>();
Map<String, Object> itemMap = serializeItemStack(itemStack, slot); Map<String, Object> itemMap = serializeItemStack(itemStack, faceData, slot);
if (itemMap.size() > 1) { if (itemMap.size() > 1) {
result.put(0, itemMap.get("0")); result.put(0, itemMap.get("0"));
result.put(1, itemMap.get("1")); result.put(1, itemMap.get("1"));
@ -1245,11 +1245,11 @@ public class Util extends Queue {
return result; return result;
} }
public static Map<String, Object> serializeItemStack(ItemStack itemStack, int slot) { public static Map<String, Object> serializeItemStack(ItemStack itemStack, String faceData, int slot) {
Map<String, Object> itemMap = new HashMap<>(); Map<String, Object> itemMap = new HashMap<>();
if (itemStack != null && !itemStack.getType().equals(Material.AIR)) { if (itemStack != null && !itemStack.getType().equals(Material.AIR)) {
ItemStack item = itemStack.clone(); ItemStack item = itemStack.clone();
List<List<Map<String, Object>>> metadata = ItemMetaHandler.seralize(item, null, slot); List<List<Map<String, Object>>> metadata = ItemMetaHandler.seralize(item, null, faceData, slot);
item.setItemMeta(null); item.setItemMeta(null);
itemMap.put("0", item.serialize()); itemMap.put("0", item.serialize());
itemMap.put("1", metadata); itemMap.put("1", metadata);
@ -1269,7 +1269,7 @@ public class Util extends Queue {
List<List<Map<String, Object>>> metadata = (List<List<Map<String, Object>>>) itemMap.get("1"); List<List<Map<String, Object>>> metadata = (List<List<Map<String, Object>>>) itemMap.get("1");
Object[] populatedStack = Rollback.populateItemStack(item, metadata); Object[] populatedStack = Rollback.populateItemStack(item, metadata);
result = (ItemStack) populatedStack[1]; result = (ItemStack) populatedStack[2];
} }
return result; return result;
@ -1298,7 +1298,7 @@ public class Util extends Queue {
ItemStack[] inventory = shulkerBox.getSnapshotInventory().getStorageContents(); ItemStack[] inventory = shulkerBox.getSnapshotInventory().getStorageContents();
int slot = 0; int slot = 0;
for (ItemStack itemStack : inventory) { for (ItemStack itemStack : inventory) {
Map<Integer, Object> itemMap = serializeItemStackLegacy(itemStack, slot); Map<Integer, Object> itemMap = serializeItemStackLegacy(itemStack, null, slot);
if (itemMap.size() > 0) { if (itemMap.size() > 0) {
meta.add(itemMap); meta.add(itemMap);
} }

View File

@ -350,7 +350,7 @@ public class EntityUtil {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
List<List<Map<String, Object>>> metadata = (List<List<Map<String, Object>>>) itemMap.get(1); List<List<Map<String, Object>>> metadata = (List<List<Map<String, Object>>>) itemMap.get(1);
Object[] populatedStack = Rollback.populateItemStack(result, metadata); Object[] populatedStack = Rollback.populateItemStack(result, metadata);
result = (ItemStack) populatedStack[1]; result = (ItemStack) populatedStack[2];
int uses = (int) recipe.get(1); int uses = (int) recipe.get(1);
int maxUses = (int) recipe.get(2); int maxUses = (int) recipe.get(2);
boolean experienceReward = (boolean) recipe.get(3); boolean experienceReward = (boolean) recipe.get(3);
@ -365,7 +365,7 @@ public class EntityUtil {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
List<List<Map<String, Object>>> itemMetaData = (List<List<Map<String, Object>>>) ingredientMap.get(1); List<List<Map<String, Object>>> itemMetaData = (List<List<Map<String, Object>>>) ingredientMap.get(1);
populatedStack = Rollback.populateItemStack(item, itemMetaData); populatedStack = Rollback.populateItemStack(item, itemMetaData);
item = (ItemStack) populatedStack[1]; item = (ItemStack) populatedStack[2];
merchantIngredients.add(item); merchantIngredients.add(item);
} }
MerchantRecipe merchantRecipe = new MerchantRecipe(result, uses, maxUses, experienceReward); MerchantRecipe merchantRecipe = new MerchantRecipe(result, uses, maxUses, experienceReward);

View File

@ -109,7 +109,7 @@ public class ItemMetaHandler {
return result.toString(); return result.toString();
} }
public static List<List<Map<String, Object>>> seralize(ItemStack item, Material type, int slot) { public static List<List<Map<String, Object>>> seralize(ItemStack item, Material type, String faceData, int slot) {
List<List<Map<String, Object>>> metadata = new ArrayList<>(); List<List<Map<String, Object>>> metadata = new ArrayList<>();
List<Map<String, Object>> list = new ArrayList<>(); List<Map<String, Object>> list = new ArrayList<>();
List<Object> modifiers = new ArrayList<>(); List<Object> modifiers = new ArrayList<>();
@ -210,7 +210,7 @@ public class ItemMetaHandler {
list = new ArrayList<>(); list = new ArrayList<>();
for (ItemStack chargedProjectile : subMeta.getChargedProjectiles()) { for (ItemStack chargedProjectile : subMeta.getChargedProjectiles()) {
Map<String, Object> itemMap = Util.serializeItemStack(chargedProjectile, slot); Map<String, Object> itemMap = Util.serializeItemStack(chargedProjectile, null, slot);
if (itemMap.size() > 0) { if (itemMap.size() > 0) {
list.add(itemMap); list.add(itemMap);
} }
@ -246,6 +246,14 @@ public class ItemMetaHandler {
metadata.add(list); metadata.add(list);
} }
if (faceData != null && faceData.length() > 0) {
Map<String, Object> meta = new HashMap<>();
meta.put("facing", faceData);
list = new ArrayList<>();
list.add(meta);
metadata.add(list);
}
if (modifiers.size() > 0) { if (modifiers.size() > 0) {
Map<String, Object> meta = new HashMap<>(); Map<String, Object> meta = new HashMap<>();
meta.put("modifiers", modifiers); meta.put("modifiers", modifiers);