diff --git a/src/main/java/net/minestom/server/item/ItemMeta.java b/src/main/java/net/minestom/server/item/ItemMeta.java index 6c3c959f5..a7392b723 100644 --- a/src/main/java/net/minestom/server/item/ItemMeta.java +++ b/src/main/java/net/minestom/server/item/ItemMeta.java @@ -53,7 +53,7 @@ public class ItemMeta implements TagReadable, Writeable { this.canPlaceOn = Set.copyOf(metaBuilder.canPlaceOn); this.metaBuilder = metaBuilder; - this.nbt = metaBuilder.nbt(); + this.nbt = metaBuilder.nbt.toCompound(); } @Contract(value = "_, -> new", pure = true) diff --git a/src/main/java/net/minestom/server/item/ItemMetaBuilder.java b/src/main/java/net/minestom/server/item/ItemMetaBuilder.java index e800d471d..81a6a0997 100644 --- a/src/main/java/net/minestom/server/item/ItemMetaBuilder.java +++ b/src/main/java/net/minestom/server/item/ItemMetaBuilder.java @@ -15,17 +15,11 @@ import org.jglrxavpok.hephaistos.nbt.*; import org.jglrxavpok.hephaistos.nbt.mutable.MutableNBTCompound; import java.util.*; -import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; import java.util.function.Consumer; import java.util.function.Supplier; public abstract class ItemMetaBuilder implements TagWritable { - - private static final AtomicReferenceFieldUpdater NBT_UPDATER = - AtomicReferenceFieldUpdater.newUpdater(ItemMetaBuilder.class, NBTCompound.class, "nbt"); - - protected volatile boolean built = false; - private volatile NBTCompound nbt = new NBTCompound(); + MutableNBTCompound nbt = new MutableNBTCompound(); protected int damage; protected boolean unbreakable; @@ -106,7 +100,7 @@ public abstract class ItemMetaBuilder implements TagWritable { public @NotNull ItemMetaBuilder enchantments(@NotNull Map enchantments) { this.enchantmentMap = new HashMap<>(enchantments); handleMap(enchantmentMap, "Enchantments", () -> { - MutableNBTCompound mutableCopy = new MutableNBTCompound(nbt); + MutableNBTCompound mutableCopy = nbt.toMutableCompound(); NBTUtils.writeEnchant(mutableCopy, "Enchantments", enchantmentMap); return mutableCopy.get("Enchantments"); }); @@ -205,24 +199,11 @@ public abstract class ItemMetaBuilder implements TagWritable { protected abstract @NotNull Supplier<@NotNull ItemMetaBuilder> getSupplier(); - protected synchronized void mutateNbt(Consumer consumer) { - MutableNBTCompound copy = new MutableNBTCompound(nbt); - consumer.accept(copy); - if (built) { - built = false; - final var currentNbt = nbt; - NBT_UPDATER.compareAndSet(this, currentNbt, copy.toCompound()); - } else { - nbt = copy.toCompound(); - } - } - - protected synchronized NBTCompound nbt() { - return nbt; + protected void mutateNbt(Consumer consumer) { + consumer.accept(nbt); } protected @NotNull ItemMeta generate() { - this.built = true; return build(); } @@ -280,8 +261,8 @@ public abstract class ItemMetaBuilder implements TagWritable { @Contract(value = "_, _ -> new", pure = true) public static @NotNull ItemMetaBuilder fromNBT(@NotNull ItemMetaBuilder src, @NotNull NBTCompound nbtCompound) { ItemMetaBuilder dest = src.getSupplier().get(); - dest.nbt = nbtCompound; - NBTUtils.loadDataIntoMeta(dest, dest.nbt); + dest.nbt = nbtCompound.toMutableCompound(); + NBTUtils.loadDataIntoMeta(dest, nbtCompound); return dest; } diff --git a/src/main/java/net/minestom/server/item/ItemStackBuilder.java b/src/main/java/net/minestom/server/item/ItemStackBuilder.java index e39d67d1d..b663e4343 100644 --- a/src/main/java/net/minestom/server/item/ItemStackBuilder.java +++ b/src/main/java/net/minestom/server/item/ItemStackBuilder.java @@ -112,8 +112,7 @@ public class ItemStackBuilder { @Contract(value = "-> new", pure = true) public @NotNull ItemStack build() { - if (amount < 1) - return ItemStack.AIR; + if (amount < 1) return ItemStack.AIR; return new ItemStack(material, amount, metaBuilder.generate(), stackingRule); } diff --git a/src/main/java/net/minestom/server/item/metadata/FireworkMeta.java b/src/main/java/net/minestom/server/item/metadata/FireworkMeta.java index 0c144255f..5dc6df1b4 100644 --- a/src/main/java/net/minestom/server/item/metadata/FireworkMeta.java +++ b/src/main/java/net/minestom/server/item/metadata/FireworkMeta.java @@ -14,7 +14,6 @@ import java.util.Collections; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; import java.util.function.Supplier; -import java.util.stream.Collectors; public class FireworkMeta extends ItemMeta implements ItemMetaBuilder.Provider { diff --git a/src/main/java/net/minestom/server/item/metadata/PotionMeta.java b/src/main/java/net/minestom/server/item/metadata/PotionMeta.java index e21b8a5f6..42620e83c 100644 --- a/src/main/java/net/minestom/server/item/metadata/PotionMeta.java +++ b/src/main/java/net/minestom/server/item/metadata/PotionMeta.java @@ -16,7 +16,6 @@ import java.time.Duration; import java.util.ArrayList; import java.util.List; import java.util.function.Supplier; -import java.util.stream.Collectors; public class PotionMeta extends ItemMeta implements ItemMetaBuilder.Provider { diff --git a/src/main/java/net/minestom/server/item/metadata/WritableBookMeta.java b/src/main/java/net/minestom/server/item/metadata/WritableBookMeta.java index d28620e58..c661ec5bb 100644 --- a/src/main/java/net/minestom/server/item/metadata/WritableBookMeta.java +++ b/src/main/java/net/minestom/server/item/metadata/WritableBookMeta.java @@ -13,7 +13,6 @@ import java.util.Collections; import java.util.List; import java.util.Objects; import java.util.function.Supplier; -import java.util.stream.Collectors; public class WritableBookMeta extends ItemMeta implements ItemMetaBuilder.Provider { diff --git a/src/main/java/net/minestom/server/item/metadata/WrittenBookMeta.java b/src/main/java/net/minestom/server/item/metadata/WrittenBookMeta.java index 1bb871575..37b66c3ef 100644 --- a/src/main/java/net/minestom/server/item/metadata/WrittenBookMeta.java +++ b/src/main/java/net/minestom/server/item/metadata/WrittenBookMeta.java @@ -14,7 +14,6 @@ import org.jglrxavpok.hephaistos.nbt.*; import java.util.*; import java.util.function.Supplier; -import java.util.stream.Collectors; public class WrittenBookMeta extends ItemMeta implements ItemMetaBuilder.Provider { diff --git a/src/main/java/net/minestom/server/item/rule/VanillaStackingRule.java b/src/main/java/net/minestom/server/item/rule/VanillaStackingRule.java index a9bc105ba..fa6d7f9db 100644 --- a/src/main/java/net/minestom/server/item/rule/VanillaStackingRule.java +++ b/src/main/java/net/minestom/server/item/rule/VanillaStackingRule.java @@ -19,8 +19,7 @@ public final class VanillaStackingRule implements StackingRule { @Override public @NotNull ItemStack apply(@NotNull ItemStack item, int amount) { - if (amount > 0) return item.withAmount(amount); - return ItemStack.AIR; + return amount > 0 ? item.withAmount(amount) : ItemStack.AIR; } @Override diff --git a/src/test/java/item/ItemTest.java b/src/test/java/item/ItemTest.java index 4f381482c..41c2bc1af 100644 --- a/src/test/java/item/ItemTest.java +++ b/src/test/java/item/ItemTest.java @@ -103,4 +103,14 @@ public class ItemTest { enchantments = item.getMeta().getEnchantmentMap(); assertEquals(enchantments.get(Enchantment.EFFICIENCY), (short) 10); } + + @Test + public void testBuilderReuse() { + var builder = ItemStack.builder(Material.DIAMOND); + var item1 = builder.build(); + var item2 = builder.displayName(Component.text("Name")).build(); + assertNull(item1.getDisplayName()); + assertNotNull(item2.getDisplayName()); + assertNotEquals(item1, item2, "Item builder should be reusable"); + } } diff --git a/src/test/java/regressions/ItemMetaBuilderRegressions.java b/src/test/java/regressions/ItemMetaBuilderRegressions.java index 562a07ea5..33932dd20 100644 --- a/src/test/java/regressions/ItemMetaBuilderRegressions.java +++ b/src/test/java/regressions/ItemMetaBuilderRegressions.java @@ -4,7 +4,6 @@ import net.minestom.server.item.ItemMeta; import net.minestom.server.item.ItemMetaBuilder; import org.jetbrains.annotations.NotNull; import org.jglrxavpok.hephaistos.nbt.NBTCompound; -import org.jglrxavpok.hephaistos.nbt.NBTShort; import org.jglrxavpok.hephaistos.nbt.NBTString; import org.jglrxavpok.hephaistos.nbt.mutable.MutableNBTCompound; import org.junit.jupiter.api.Test;