diff --git a/src/main/java/net/minestom/server/item/ItemStack.java b/src/main/java/net/minestom/server/item/ItemStack.java index 9d42260dc..ea98bea59 100644 --- a/src/main/java/net/minestom/server/item/ItemStack.java +++ b/src/main/java/net/minestom/server/item/ItemStack.java @@ -7,6 +7,7 @@ import net.minestom.server.item.rule.VanillaStackingRule; import net.minestom.server.tag.Tag; import net.minestom.server.tag.TagReadable; import net.minestom.server.utils.NBTUtils; +import net.minestom.server.utils.validate.Check; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; @@ -79,6 +80,18 @@ public final class ItemStack implements TagReadable, HoverEventSource { + + private final List items; + + protected BundleMeta(ItemMetaBuilder metaBuilder, + @NotNull List items) { + super(metaBuilder); + this.items = List.copyOf(items); + } + + public @NotNull List getItems() { + return items; + } + + public static class Builder extends ItemMetaBuilder { + private List items = new ArrayList<>(); + + public Builder items(@NotNull List items) { + this.items = items; + updateItems(); + return this; + } + + public Builder addItem(@NotNull ItemStack item) { + items.add(item); + updateItems(); + return this; + } + + public Builder removeItem(@NotNull ItemStack item) { + items.remove(item); + updateItems(); + return this; + } + + @Override + public @NotNull BundleMeta build() { + return new BundleMeta(this, items); + } + + private void updateItems() { + mutateNbt(compound -> { + NBTList itemList = new NBTList<>(NBTTypes.TAG_Compound); + for (ItemStack item : items) { + itemList.add(item.toItemNBT()); + } + compound.set("Items", itemList); + }); + } + + @Override + public void read(@NotNull NBTCompound nbtCompound) { + if (nbtCompound.containsKey("Items")) { + final NBTList items = nbtCompound.getList("Items"); + for (NBTCompound item : items) { + this.items.add(ItemStack.fromItemNBT(item)); + } + } + } + + @Override + protected @NotNull Supplier<@NotNull ItemMetaBuilder> getSupplier() { + return Builder::new; + } + } +} diff --git a/src/test/java/demo/PlayerInit.java b/src/test/java/demo/PlayerInit.java index aa833918b..cd867eb8a 100644 --- a/src/test/java/demo/PlayerInit.java +++ b/src/test/java/demo/PlayerInit.java @@ -29,6 +29,7 @@ import net.minestom.server.inventory.Inventory; import net.minestom.server.inventory.InventoryType; import net.minestom.server.item.ItemStack; import net.minestom.server.item.Material; +import net.minestom.server.item.metadata.BundleMeta; import net.minestom.server.monitoring.BenchmarkManager; import net.minestom.server.monitoring.TickMonitor; import net.minestom.server.utils.MathUtils; @@ -104,6 +105,14 @@ public class PlayerInit { .canDestroy(Set.of(Block.DIAMOND_ORE))) .build(); player.getInventory().addItemStack(itemStack); + + ItemStack bundle = ItemStack.builder(Material.BUNDLE) + .meta(BundleMeta.class, bundleMetaBuilder -> { + bundleMetaBuilder.addItem(ItemStack.builder(Material.DIAMOND).amount(5).build()); + bundleMetaBuilder.addItem(ItemStack.builder(Material.RABBIT_FOOT).amount(5).build()); + }) + .build(); + player.getInventory().addItemStack(bundle); }); static {