store amount in a seperate field for item updates + 1.21.4

This commit is contained in:
Brokkonaut
2024-12-06 04:42:13 +01:00
parent 8c024532b2
commit 0a685bca27
12 changed files with 205 additions and 57 deletions

View File

@@ -44,7 +44,7 @@
<dependency> <dependency>
<groupId>org.spigotmc</groupId> <groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId> <artifactId>spigot-api</artifactId>
<version>1.21-R0.1-SNAPSHOT</version> <version>1.21.4-R0.1-SNAPSHOT</version>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
<dependency> <dependency>

View File

@@ -12,6 +12,7 @@ import static de.diddiz.LogBlock.util.TypeColor.DEFAULT;
import de.diddiz.LogBlock.blockstate.BlockStateCodecs; import de.diddiz.LogBlock.blockstate.BlockStateCodecs;
import de.diddiz.LogBlock.util.BukkitUtils; import de.diddiz.LogBlock.util.BukkitUtils;
import de.diddiz.LogBlock.util.ItemStackAndAmount;
import de.diddiz.LogBlock.util.Utils; import de.diddiz.LogBlock.util.Utils;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
@@ -35,7 +36,6 @@ import org.bukkit.block.data.type.Repeater;
import org.bukkit.block.data.type.Sign; import org.bukkit.block.data.type.Sign;
import org.bukkit.block.data.type.Switch; import org.bukkit.block.data.type.Switch;
import org.bukkit.block.data.type.WallSign; import org.bukkit.block.data.type.WallSign;
import org.bukkit.inventory.ItemStack;
public class BlockChange implements LookupCacheElement { public class BlockChange implements LookupCacheElement {
public final long id, date; public final long id, date;
@@ -75,7 +75,7 @@ public class BlockChange implements LookupCacheElement {
typeState = p.needType ? rs.getBytes("typeState") : 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")); ItemStackAndAmount stack = Utils.loadItemStack(rs.getBytes("item"));
if (stack != null) { if (stack != null) {
catemp = new ChestAccess(stack, rs.getBoolean("itemremove"), rs.getInt("itemtype")); catemp = new ChestAccess(stack, rs.getBoolean("itemremove"), rs.getInt("itemtype"));
} }

View File

@@ -1,13 +1,13 @@
package de.diddiz.LogBlock; package de.diddiz.LogBlock;
import org.bukkit.inventory.ItemStack; import de.diddiz.LogBlock.util.ItemStackAndAmount;
public class ChestAccess { public class ChestAccess {
public final ItemStack itemStack; public final ItemStackAndAmount itemStack;
public final boolean remove; public final boolean remove;
public final int itemType; public final int itemType;
public ChestAccess(ItemStack itemStack, boolean remove, int itemType) { public ChestAccess(ItemStackAndAmount itemStack, boolean remove, int itemType) {
this.itemStack = itemStack; this.itemStack = itemStack;
this.remove = remove; this.remove = remove;
this.itemType = itemType; this.itemType = itemType;

View File

@@ -19,6 +19,7 @@ import java.sql.SQLException;
import java.sql.Statement; import java.sql.Statement;
import java.util.ArrayDeque; import java.util.ArrayDeque;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection;
import java.util.Deque; import java.util.Deque;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
@@ -52,6 +53,7 @@ import de.diddiz.LogBlock.config.Config;
import de.diddiz.LogBlock.events.BlockChangePreLogEvent; import de.diddiz.LogBlock.events.BlockChangePreLogEvent;
import de.diddiz.LogBlock.events.EntityChangePreLogEvent; import de.diddiz.LogBlock.events.EntityChangePreLogEvent;
import de.diddiz.LogBlock.util.BukkitUtils; import de.diddiz.LogBlock.util.BukkitUtils;
import de.diddiz.LogBlock.util.ItemStackAndAmount;
import de.diddiz.LogBlock.util.Utils; import de.diddiz.LogBlock.util.Utils;
public class Consumer extends Thread { public class Consumer extends Thread {
@@ -208,7 +210,7 @@ public class Consumer extends Thread {
* @param remove * @param remove
* true if the item was removed * true if the item was removed
*/ */
public void queueChestAccess(Actor actor, BlockState container, ItemStack itemStack, boolean remove) { public void queueChestAccess(Actor actor, BlockState container, ItemStackAndAmount itemStack, boolean remove) {
if (!(container instanceof InventoryHolder)) { if (!(container instanceof InventoryHolder)) {
throw new IllegalArgumentException("Container must be instanceof InventoryHolder"); throw new IllegalArgumentException("Container must be instanceof InventoryHolder");
} }
@@ -229,8 +231,8 @@ public class Consumer extends Thread {
* @param remove * @param remove
* true if the item was removed * true if the item was removed
*/ */
public void queueChestAccess(Actor actor, Location loc, BlockData type, ItemStack itemStack, boolean remove) { public void queueChestAccess(Actor actor, Location loc, BlockData type, ItemStackAndAmount itemStack, boolean remove) {
queueBlock(actor, loc, type, type, null, null, new ChestAccess(itemStack, remove, MaterialConverter.getOrAddMaterialId(itemStack.getType()))); queueBlock(actor, loc, type, type, null, null, new ChestAccess(itemStack, remove, MaterialConverter.getOrAddMaterialId(itemStack.stack().getType())));
} }
/** /**
@@ -261,8 +263,8 @@ public class Consumer extends Thread {
* The inventory of the container block * The inventory of the container block
*/ */
public void queueContainerBreak(Actor actor, Location loc, BlockData type, Inventory inv) { public void queueContainerBreak(Actor actor, Location loc, BlockData type, Inventory inv) {
final ItemStack[] items = compressInventory(inv.getContents()); final Collection<ItemStackAndAmount> items = compressInventory(inv.getContents());
for (final ItemStack item : items) { for (final ItemStackAndAmount item : items) {
queueChestAccess(actor, loc, type, item, true); queueChestAccess(actor, loc, type, item, true);
} }
queueBlockBreak(actor, loc, type); queueBlockBreak(actor, loc, type);

View File

@@ -4,6 +4,7 @@ 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.LogBlock.util.ComparableVersion; import de.diddiz.LogBlock.util.ComparableVersion;
import de.diddiz.LogBlock.util.ItemStackAndAmount;
import de.diddiz.LogBlock.util.UUIDFetcher; import de.diddiz.LogBlock.util.UUIDFetcher;
import de.diddiz.LogBlock.util.Utils; import de.diddiz.LogBlock.util.Utils;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
@@ -534,7 +535,7 @@ class Updater {
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
ItemStack stack = weaponMaterial.getMaxDurability() > 0 ? new ItemStack(weaponMaterial, Math.abs(amount), (short) itemdata) : new ItemStack(weaponMaterial, Math.abs(amount)); ItemStack stack = weaponMaterial.getMaxDurability() > 0 ? new ItemStack(weaponMaterial, Math.abs(amount), (short) itemdata) : new ItemStack(weaponMaterial, Math.abs(amount));
insertChestData.setLong(1, id); insertChestData.setLong(1, id);
insertChestData.setBytes(2, Utils.saveItemStack(stack)); insertChestData.setBytes(2, Utils.saveItemStack(ItemStackAndAmount.fromStack(stack)));
insertChestData.setInt(3, amount >= 0 ? 0 : 1); insertChestData.setInt(3, amount >= 0 ? 0 : 1);
insertChestData.setInt(4, MaterialConverter.getOrAddMaterialId(weaponMaterial)); insertChestData.setInt(4, MaterialConverter.getOrAddMaterialId(weaponMaterial));
insertChestData.addBatch(); insertChestData.addBatch();

View File

@@ -378,7 +378,7 @@ public class WorldEditor implements Runnable {
if (state instanceof InventoryHolder && state.getType() == replacedBlock.getMaterial()) { if (state instanceof InventoryHolder && state.getType() == replacedBlock.getMaterial()) {
int leftover; int leftover;
try { try {
leftover = modifyContainer(state, new ItemStack(ca.itemStack), !ca.remove); leftover = modifyContainer(state, ca.itemStack, !ca.remove);
} catch (final Exception ex) { } catch (final Exception ex) {
throw new WorldEditorException(ex.getMessage(), block.getLocation()); throw new WorldEditorException(ex.getMessage(), block.getLocation());
} }

View File

@@ -3,9 +3,8 @@ package de.diddiz.LogBlock;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import org.bukkit.inventory.ItemStack;
import de.diddiz.LogBlock.QueryParams.BlockChangeType; import de.diddiz.LogBlock.QueryParams.BlockChangeType;
import de.diddiz.LogBlock.util.ItemStackAndAmount;
import de.diddiz.LogBlock.util.Utils; import de.diddiz.LogBlock.util.Utils;
public class WorldEditorEditFactory { public class WorldEditorEditFactory {
@@ -25,7 +24,7 @@ public class WorldEditorEditFactory {
return; return;
} }
ChestAccess chestaccess = null; ChestAccess chestaccess = null;
ItemStack stack = Utils.loadItemStack(rs.getBytes("item")); ItemStackAndAmount stack = Utils.loadItemStack(rs.getBytes("item"));
if (stack != null) { if (stack != null) {
chestaccess = new ChestAccess(stack, rs.getBoolean("itemremove") == rollback, rs.getInt("itemtype")); chestaccess = new ChestAccess(stack, rs.getBoolean("itemremove") == rollback, rs.getInt("itemtype"));
} }

View File

@@ -3,6 +3,7 @@ package de.diddiz.LogBlock.listeners;
import de.diddiz.LogBlock.Actor; import de.diddiz.LogBlock.Actor;
import de.diddiz.LogBlock.LogBlock; import de.diddiz.LogBlock.LogBlock;
import de.diddiz.LogBlock.Logging; import de.diddiz.LogBlock.Logging;
import de.diddiz.LogBlock.util.ItemStackAndAmount;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.Tag; import org.bukkit.Tag;
@@ -78,9 +79,10 @@ public class ChestAccessLogging extends LoggingListener {
for (Entry<ItemStack, Integer> e : modifications.entrySet()) { for (Entry<ItemStack, Integer> e : modifications.entrySet()) {
ItemStack stack = e.getKey(); ItemStack stack = e.getKey();
int amount = e.getValue(); int amount = e.getValue();
stack.setAmount(Math.abs(amount)); if (amount != 0) {
// consumer.getLogblock().getLogger().info("Store container: " + stack + " take: " + (amount < 0)); // consumer.getLogblock().getLogger().info("Store container: " + stack + " take: " + (amount < 0));
consumer.queueChestAccess(Actor.actorFromEntity(actor), location, location.getWorld().getBlockAt(location).getBlockData(), stack, amount < 0); consumer.queueChestAccess(Actor.actorFromEntity(actor), location, location.getWorld().getBlockAt(location).getBlockData(), new ItemStackAndAmount(stack, Math.abs(amount)), amount < 0);
}
} }
modifications.clear(); modifications.clear();
} }
@@ -328,7 +330,7 @@ public class ChestAccessLogging extends LoggingListener {
if (currentInPot == null || currentInPot.getType() == Material.AIR || currentInPot.isSimilar(mainHand) && currentInPot.getAmount() < currentInPot.getMaxStackSize()) { if (currentInPot == null || currentInPot.getType() == Material.AIR || currentInPot.isSimilar(mainHand) && currentInPot.getAmount() < currentInPot.getMaxStackSize()) {
ItemStack stack = mainHand.clone(); ItemStack stack = mainHand.clone();
stack.setAmount(1); stack.setAmount(1);
consumer.queueChestAccess(Actor.actorFromEntity(player), clicked.getLocation(), clicked.getBlockData(), stack, false); consumer.queueChestAccess(Actor.actorFromEntity(player), clicked.getLocation(), clicked.getBlockData(), ItemStackAndAmount.fromStack(stack), false);
} }
} }
} else if (type == Material.CHISELED_BOOKSHELF) { } else if (type == Material.CHISELED_BOOKSHELF) {
@@ -353,7 +355,7 @@ public class ChestAccessLogging extends LoggingListener {
if (blockData.isSlotOccupied(slot)) { if (blockData.isSlotOccupied(slot)) {
// not empty: always take // not empty: always take
if (currentInSlot != null && currentInSlot.getType() != Material.AIR) { if (currentInSlot != null && currentInSlot.getType() != Material.AIR) {
consumer.queueChestAccess(Actor.actorFromEntity(player), clicked.getLocation(), clicked.getBlockData(), currentInSlot, true); consumer.queueChestAccess(Actor.actorFromEntity(player), clicked.getLocation(), clicked.getBlockData(), ItemStackAndAmount.fromStack(currentInSlot), true);
} }
} else { } else {
// empty: put if has tag BOOKSHELF_BOOKS // empty: put if has tag BOOKSHELF_BOOKS
@@ -361,7 +363,7 @@ public class ChestAccessLogging extends LoggingListener {
if (mainHand != null && mainHand.getType() != Material.AIR && Tag.ITEMS_BOOKSHELF_BOOKS.isTagged(mainHand.getType())) { if (mainHand != null && mainHand.getType() != Material.AIR && Tag.ITEMS_BOOKSHELF_BOOKS.isTagged(mainHand.getType())) {
ItemStack stack = mainHand.clone(); ItemStack stack = mainHand.clone();
stack.setAmount(1); stack.setAmount(1);
consumer.queueChestAccess(Actor.actorFromEntity(player), clicked.getLocation(), clicked.getBlockData(), stack, false); consumer.queueChestAccess(Actor.actorFromEntity(player), clicked.getLocation(), clicked.getBlockData(), ItemStackAndAmount.fromStack(stack), false);
} }
} }
} }

View File

@@ -5,11 +5,13 @@ import static de.diddiz.LogBlock.util.MessagingUtil.prettyMaterial;
import de.diddiz.LogBlock.LogBlock; import de.diddiz.LogBlock.LogBlock;
import java.io.File; import java.io.File;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.Set; import java.util.Set;
import java.util.UUID; import java.util.UUID;
@@ -146,8 +148,11 @@ public class BukkitUtils {
// https://minecraft.fandom.com/wiki/Tag#blocks_small_flowers // https://minecraft.fandom.com/wiki/Tag#blocks_small_flowers
Set<Material> smallFlowers = Tag.SMALL_FLOWERS.getValues(); Set<Material> smallFlowers = Tag.SMALL_FLOWERS.getValues();
// https://minecraft.fandom.com/wiki/Tag#blocks_tall_flowers Set<Material> tallFlowers = Set.of(Material.SUNFLOWER,
Set<Material> tallFlowers = Tag.TALL_FLOWERS.getValues(); Material.LILAC,
Material.PEONY,
Material.ROSE_BUSH,
Material.PITCHER_PLANT);
Set<Material> bannerStanding = Set.of(Material.WHITE_BANNER, Set<Material> bannerStanding = Set.of(Material.WHITE_BANNER,
Material.ORANGE_BANNER, Material.ORANGE_BANNER,
@@ -498,24 +503,22 @@ public class BukkitUtils {
return diff.toArray(new ItemStack[diff.size()]); return diff.toArray(new ItemStack[diff.size()]);
} }
public static ItemStack[] compressInventory(ItemStack[] items) { public static Collection<ItemStackAndAmount> compressInventory(ItemStack[] items) {
final ArrayList<ItemStack> compressed = new ArrayList<>(); final HashMap<ItemStack, Integer> compressed = new HashMap<>();
for (final ItemStack item : items) { for (final ItemStack item : items) {
if (item != null) { if (item != null && item.getType() != Material.AIR && item.getAmount() > 0) {
boolean found = false; int amount = item.getAmount();
for (final ItemStack item2 : compressed) { ItemStack stack = item.clone();
if (item2.isSimilar(item)) { stack.setAmount(1);
item2.setAmount(item2.getAmount() + item.getAmount()); Integer old = compressed.get(stack);
found = true; compressed.put(stack, (old == null ? 0 : old) + amount);
break;
} }
} }
if (!found) { ArrayList<ItemStackAndAmount> result = new ArrayList<>();
compressed.add(item.clone()); for (Entry<ItemStack, Integer> e : compressed.entrySet()) {
result.add(new ItemStackAndAmount(e.getKey(), e.getValue()));
} }
} return result;
}
return compressed.toArray(new ItemStack[compressed.size()]);
} }
public static String friendlyWorldname(String worldName) { public static String friendlyWorldname(String worldName) {
@@ -602,15 +605,13 @@ public class BukkitUtils {
return y; return y;
} }
public static int modifyContainer(BlockState b, ItemStack item, boolean remove) { public static int modifyContainer(BlockState b, ItemStackAndAmount item, boolean remove) {
if (b instanceof InventoryHolder c) { if (item.amount() > 0 && b instanceof InventoryHolder c) {
final Inventory inv = c.getInventory(); final Inventory inv = c.getInventory();
if (remove) { if (remove) {
final ItemStack tmp = inv.removeItem(item).get(0); return InventoryUtils.removeFromInventory(inv, item);
return tmp != null ? tmp.getAmount() : 0; } else {
} else if (item.getAmount() > 0) { return InventoryUtils.addToInventory(inv, item);
final ItemStack tmp = inv.addItem(item).get(0);
return tmp != null ? tmp.getAmount() : 0;
} }
} }
return 0; return 0;
@@ -656,16 +657,16 @@ public class BukkitUtils {
return m == Material.AIR || m == Material.CAVE_AIR || m == Material.VOID_AIR; return m == Material.AIR || m == Material.CAVE_AIR || m == Material.VOID_AIR;
} }
public static TextComponent toString(ItemStack stack) { public static TextComponent toString(ItemStackAndAmount stack) {
if (stack == null || stack.getAmount() == 0 || isEmpty(stack.getType())) { if (stack == null || stack.stack() == null || stack.amount() == 0 || isEmpty(stack.stack().getType())) {
return prettyMaterial("nothing"); return prettyMaterial("nothing");
} }
TextComponent msg = MessagingUtil.createTextComponentWithColor(stack.getAmount() + "x ", TypeColor.DEFAULT.getColor()); TextComponent msg = MessagingUtil.createTextComponentWithColor(stack.amount() + "x ", TypeColor.DEFAULT.getColor());
msg.addExtra(prettyMaterial(stack.getType())); msg.addExtra(prettyMaterial(stack.stack().getType()));
try { try {
String itemTag = stack.getItemMeta().getAsString(); String itemTag = stack.stack().getItemMeta().getAsString();
msg.setHoverEvent(new HoverEvent(Action.SHOW_ITEM, new Item(stack.getType().getKey().toString(), 1, itemTag != null ? ItemTag.ofNbt(itemTag) : null))); msg.setHoverEvent(new HoverEvent(Action.SHOW_ITEM, new Item(stack.stack().getType().getKey().toString(), 1, itemTag != null ? ItemTag.ofNbt(itemTag) : null)));
} catch (Exception e) { } catch (Exception e) {
LogBlock.getInstance().getLogger().log(Level.SEVERE, "Failed to convert Itemstack to JSON", e); LogBlock.getInstance().getLogger().log(Level.SEVERE, "Failed to convert Itemstack to JSON", e);
msg.setHoverEvent(new HoverEvent(Action.SHOW_TEXT, new Text(new BaseComponent[] { MessagingUtil.createTextComponentWithColor("Error", TypeColor.ERROR.getColor()) }))); msg.setHoverEvent(new HoverEvent(Action.SHOW_TEXT, new Text(new BaseComponent[] { MessagingUtil.createTextComponentWithColor("Error", TypeColor.ERROR.getColor()) })));

View File

@@ -0,0 +1,113 @@
package de.diddiz.LogBlock.util;
import org.bukkit.Material;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
public class InventoryUtils {
public static int addToInventory(Inventory inventory, ItemStackAndAmount item) {
if (item == null || item.stack() == null || item.stack().getType() == Material.AIR) {
return 0;
}
int maxStackSize = Math.max(Math.min(inventory.getMaxStackSize(), item.stack().getMaxStackSize()), 1);
ItemStack[] contents = inventory.getStorageContents();
int remaining = item.amount();
int initialRemaining = remaining;
// fill partial stacks
int firstPartial = -1;
while (remaining > 0) {
firstPartial = getFirstPartial(item.stack(), maxStackSize, contents, firstPartial + 1);
if (firstPartial < 0) {
break;
}
ItemStack content = contents[firstPartial];
int add = Math.min(maxStackSize - content.getAmount(), remaining);
content.setAmount(content.getAmount() + add);
remaining -= add;
}
// create new stacks
int firstFree = -1;
while (remaining > 0) {
firstFree = getFirstFree(contents, firstFree + 1);
if (firstFree < 0) {
break;
}
ItemStack content = item.stack().clone();
contents[firstFree] = content;
int add = Math.min(maxStackSize, remaining);
content.setAmount(add);
remaining -= add;
}
if (remaining < initialRemaining) {
inventory.setStorageContents(contents);
}
return remaining;
}
public static int removeFromInventory(Inventory inventory, ItemStackAndAmount item) {
if (item == null || item.stack() == null || item.stack().getType() == Material.AIR) {
return 0;
}
ItemStack[] contents = inventory.getStorageContents();
int remaining = item.amount();
int initialRemaining = remaining;
int firstSimilar = -1;
while (remaining > 0) {
firstSimilar = getFirstSimilar(item.stack(), contents, firstSimilar + 1);
if (firstSimilar < 0) {
break;
}
ItemStack content = contents[firstSimilar];
int here = content.getAmount();
if (here > remaining) {
content.setAmount(here - remaining);
remaining = 0;
} else {
contents[firstSimilar] = null;
remaining -= here;
}
}
if (remaining < initialRemaining) {
inventory.setStorageContents(contents);
}
return remaining;
}
private static int getFirstSimilar(ItemStack item, ItemStack[] contents, int start) {
for (int i = start; i < contents.length; i++) {
ItemStack content = contents[i];
if (content != null && content.isSimilar(item)) {
return i;
}
}
return -1;
}
private static int getFirstPartial(ItemStack item, int maxStackSize, ItemStack[] contents, int start) {
for (int i = start; i < contents.length; i++) {
ItemStack content = contents[i];
if (content != null && content.isSimilar(item) && content.getAmount() < maxStackSize) {
return i;
}
}
return -1;
}
private static int getFirstFree(ItemStack[] contents, int start) {
for (int i = start; i < contents.length; i++) {
ItemStack content = contents[i];
if (content == null || content.getAmount() == 0 || content.getType() == Material.AIR) {
return i;
}
}
return -1;
}
}

View File

@@ -0,0 +1,15 @@
package de.diddiz.LogBlock.util;
import org.bukkit.inventory.ItemStack;
public record ItemStackAndAmount(ItemStack stack, int amount) {
public static ItemStackAndAmount fromStack(ItemStack stack) {
int amount = stack.getAmount();
if (amount > 1) {
stack = stack.clone();
stack.setAmount(1);
}
return new ItemStackAndAmount(stack, amount);
}
}

View File

@@ -231,20 +231,35 @@ public class Utils {
return untrusted.replace("\\", "\\\\").replace("'", "\\'"); return untrusted.replace("\\", "\\\\").replace("'", "\\'");
} }
public static ItemStack loadItemStack(byte[] data) { public static ItemStackAndAmount loadItemStack(byte[] data) {
if (data == null || data.length == 0) { if (data == null || data.length == 0) {
return null; return null;
} }
YamlConfiguration conf = deserializeYamlConfiguration(data); YamlConfiguration conf = deserializeYamlConfiguration(data);
return conf == null ? null : conf.getItemStack("stack"); if (conf == null) {
return null;
}
ItemStack stack = conf.getItemStack("stack");
if (stack == null) {
return null;
}
int amount = conf.contains("amount") ? conf.getInt("amount") : stack.getAmount();
stack.setAmount(1);
return new ItemStackAndAmount(stack, amount);
} }
public static byte[] saveItemStack(ItemStack stack) { public static byte[] saveItemStack(ItemStackAndAmount stack) {
if (stack == null || BukkitUtils.isEmpty(stack.getType())) { if (stack == null || stack.stack() == null || BukkitUtils.isEmpty(stack.stack().getType())) {
return null; return null;
} }
YamlConfiguration conf = new YamlConfiguration(); YamlConfiguration conf = new YamlConfiguration();
conf.set("stack", stack); ItemStack itemStack = stack.stack();
if (itemStack.getAmount() > 1) {
itemStack = itemStack.clone();
itemStack.setAmount(1);
}
conf.set("stack", itemStack);
conf.set("amount", stack.amount());
return serializeYamlConfiguration(conf); return serializeYamlConfiguration(conf);
} }