diff --git a/src/main/java/net/minestom/server/item/ItemStack.java b/src/main/java/net/minestom/server/item/ItemStack.java index 844b4bd7a..d71e8abcc 100644 --- a/src/main/java/net/minestom/server/item/ItemStack.java +++ b/src/main/java/net/minestom/server/item/ItemStack.java @@ -32,15 +32,20 @@ public class ItemStack { private final int amount; private final ItemMeta meta; - protected ItemStack(@NotNull Material material, int amount, @NotNull ItemMeta meta) { + private final ItemStore store; + + protected ItemStack(@NotNull Material material, int amount, + @NotNull ItemMeta meta, + @NotNull ItemStore store) { this.material = material; this.amount = amount; this.meta = meta; + this.store = store; } @Contract(value = "_ -> new", pure = true) - public static @NotNull ItemBuilder builder(@NotNull Material material) { - return new ItemBuilder(material); + public static @NotNull ItemStackBuilder builder(@NotNull Material material) { + return new ItemStackBuilder(material); } @Contract(value = "_ ,_ -> new", pure = true) @@ -64,7 +69,7 @@ public class ItemStack { } @Contract(value = "_, -> new", pure = true) - public @NotNull ItemStack with(@NotNull Consumer<@NotNull ItemBuilder> builderConsumer) { + public @NotNull ItemStack with(@NotNull Consumer<@NotNull ItemStackBuilder> builderConsumer) { var builder = builder(); builderConsumer.accept(builder); return builder.build(); @@ -135,6 +140,11 @@ public class ItemStack { return meta; } + @Contract(pure = true) + public @NotNull ItemStore getStore() { + return store; + } + @Contract(pure = true) public boolean isAir() { return material.equals(Material.AIR); @@ -170,8 +180,8 @@ public class ItemStack { } @Contract(value = "-> new", pure = true) - protected @NotNull ItemBuilder builder() { - return new ItemBuilder(material, meta.builder()) + protected @NotNull ItemStackBuilder builder() { + return new ItemStackBuilder(material, meta.builder(), store.builder()) .amount(amount); } } diff --git a/src/main/java/net/minestom/server/item/ItemBuilder.java b/src/main/java/net/minestom/server/item/ItemStackBuilder.java similarity index 53% rename from src/main/java/net/minestom/server/item/ItemBuilder.java rename to src/main/java/net/minestom/server/item/ItemStackBuilder.java index 506107fdd..ed8ec655d 100644 --- a/src/main/java/net/minestom/server/item/ItemBuilder.java +++ b/src/main/java/net/minestom/server/item/ItemStackBuilder.java @@ -10,68 +10,82 @@ import java.util.List; import java.util.function.Consumer; import java.util.function.UnaryOperator; -public class ItemBuilder { +public class ItemStackBuilder { private final Material material; private int amount; protected ItemMetaBuilder metaBuilder; + protected ItemStoreBuilder storeBuilder; - protected ItemBuilder(@NotNull Material material, @NotNull ItemMetaBuilder metaBuilder) { + protected ItemStackBuilder(@NotNull Material material, @NotNull ItemMetaBuilder metaBuilder, @NotNull ItemStoreBuilder storeBuilder) { this.material = material; this.amount = 1; this.metaBuilder = metaBuilder; + this.storeBuilder = storeBuilder; } - protected ItemBuilder(@NotNull Material material) { + protected ItemStackBuilder(@NotNull Material material) { // TODO: meta depends on material - this(material, new CompassMeta.Builder()); + this(material, new CompassMeta.Builder(), new ItemStoreBuilder()); } @Contract(value = "_ -> this") - public @NotNull ItemBuilder amount(int amount) { + public @NotNull ItemStackBuilder amount(int amount) { this.amount = amount; return this; } @Contract(value = "_ -> this") - public @NotNull ItemBuilder meta(@NotNull ItemMeta itemMeta) { + public @NotNull ItemStackBuilder meta(@NotNull ItemMeta itemMeta) { this.metaBuilder = itemMeta.builder(); return this; } @Contract(value = "_ -> this") - public @NotNull ItemBuilder meta(@NotNull UnaryOperator<@NotNull ItemMetaBuilder> itemMetaConsumer) { + public @NotNull ItemStackBuilder meta(@NotNull UnaryOperator<@NotNull ItemMetaBuilder> itemMetaConsumer) { this.metaBuilder = itemMetaConsumer.apply(metaBuilder); return this; } @Contract(value = "_, _ -> this") - public > @NotNull ItemBuilder meta(@NotNull Class metaType, @NotNull Consumer<@NotNull T> itemMetaConsumer) { + public > @NotNull ItemStackBuilder meta(@NotNull Class metaType, @NotNull Consumer<@NotNull T> itemMetaConsumer) { itemMetaConsumer.accept((T) metaBuilder); return this; } @Contract(value = "_ -> this") - public @NotNull ItemBuilder displayName(@Nullable Component displayName) { + public @NotNull ItemStackBuilder displayName(@Nullable Component displayName) { this.metaBuilder.displayName(displayName); return this; } @Contract(value = "_ -> this") - public @NotNull ItemBuilder lore(List<@NotNull Component> lore) { + public @NotNull ItemStackBuilder lore(List<@NotNull Component> lore) { this.metaBuilder.lore(lore); return this; } @Contract(value = "_ -> this") - public @NotNull ItemBuilder lore(Component... lore) { + public @NotNull ItemStackBuilder lore(Component... lore) { this.metaBuilder.lore(lore); return this; } + @Contract(value = "_ -> this") + public @NotNull ItemStackBuilder store(@NotNull ItemStore store) { + this.storeBuilder = store.builder(); + return this; + } + + @Contract(value = "_ -> this") + public @NotNull ItemStackBuilder store(@NotNull Consumer<@NotNull ItemStoreBuilder> consumer) { + consumer.accept(storeBuilder); + return this; + } + @Contract(value = "-> new", pure = true) public @NotNull ItemStack build() { - return new ItemStack(material, amount, metaBuilder.build()); + return new ItemStack(material, amount, metaBuilder.build(), storeBuilder.build()); } } diff --git a/src/main/java/net/minestom/server/item/ItemStore.java b/src/main/java/net/minestom/server/item/ItemStore.java new file mode 100644 index 000000000..8dd82769a --- /dev/null +++ b/src/main/java/net/minestom/server/item/ItemStore.java @@ -0,0 +1,30 @@ +package net.minestom.server.item; + +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; + +import java.util.Collections; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +public class ItemStore { + + private final Map> entryMap; + + protected ItemStore(@NotNull Map> entryMap) { + this.entryMap = Collections.unmodifiableMap(entryMap); + } + + public T get(@NotNull String key) { + if (entryMap.containsKey(key)) { + return (T) entryMap.get(key).value; + } + return null; + } + + @Contract(value = "-> new", pure = true) + protected @NotNull ItemStoreBuilder builder() { + return new ItemStoreBuilder(new ConcurrentHashMap<>(entryMap)); + } + +} diff --git a/src/main/java/net/minestom/server/item/ItemStoreBuilder.java b/src/main/java/net/minestom/server/item/ItemStoreBuilder.java new file mode 100644 index 000000000..6f516be2b --- /dev/null +++ b/src/main/java/net/minestom/server/item/ItemStoreBuilder.java @@ -0,0 +1,46 @@ +package net.minestom.server.item; + +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +public class ItemStoreBuilder { + + private final Map> entryMap; + + protected ItemStoreBuilder(@NotNull Map> entryMap) { + this.entryMap = entryMap; + } + + protected ItemStoreBuilder() { + this(new ConcurrentHashMap<>()); + } + + public void set(@NotNull String key, T value, MergingRule mergingRule) { + this.entryMap.put(key, new Entry<>(value, mergingRule)); + } + + @Contract(value = "-> new", pure = true) + public @NotNull ItemStore build() { + return new ItemStore(new HashMap<>(entryMap)); + } + + public interface MergingRule { + @Nullable T apply(@NotNull T value1, @NotNull T value2); + } + + protected static class Entry { + protected final T value; + protected final MergingRule mergingRule; + + private Entry(@NotNull T value, @NotNull MergingRule mergingRule) { + this.value = value; + this.mergingRule = mergingRule; + } + } + +} diff --git a/src/test/java/demo/PlayerInit.java b/src/test/java/demo/PlayerInit.java index 022b5d45f..b82d1931b 100644 --- a/src/test/java/demo/PlayerInit.java +++ b/src/test/java/demo/PlayerInit.java @@ -27,6 +27,7 @@ import net.minestom.server.inventory.Inventory; import net.minestom.server.inventory.InventoryType; import net.minestom.server.inventory.PlayerInventory; import net.minestom.server.item.ItemStack; +import net.minestom.server.item.ItemStore; import net.minestom.server.item.ItemTag; import net.minestom.server.item.Material; import net.minestom.server.item.meta.CompassMeta; @@ -74,8 +75,14 @@ public class PlayerInit { builder.lodestonePosition(new Position(0, 0, 0)); builder.set(ItemTag.Integer("int"), 25); }) + .store(store -> { + store.set("key", 5, Integer::sum); + }) .build(); + ItemStore store = itemStack.getStore(); + System.out.println("value: " + store.get("key")); + itemStack = itemStack.with(itemBuilder -> itemBuilder .amount(10) .meta(CompassMeta.class, builder -> { @@ -225,7 +232,7 @@ public class PlayerInit { PlayerInventory inventory = player.getInventory(); ItemStack itemStack = ItemStack.of(Material.STONE, 64); inventory.addItemStack(itemStack.withMeta(metaBuilder -> metaBuilder.set(ItemTag.Integer("int"), 25))); - //inventory.replaceItemStack(0, i -> i.withAmount(32)); + inventory.replaceItemStack(0, i -> i.withAmount(32)); { ItemStack item = ItemStack.builder(Material.DIAMOND_CHESTPLATE)