Initial reusable meta builder

This commit is contained in:
TheMode 2021-06-27 17:36:37 +02:00
parent edaec0cb6d
commit e772aace71
11 changed files with 127 additions and 87 deletions

View File

@ -51,7 +51,7 @@ public class ItemMeta implements TagReadable, Writeable {
this.canDestroy = new HashSet<>(metaBuilder.canDestroy); this.canDestroy = new HashSet<>(metaBuilder.canDestroy);
this.canPlaceOn = new HashSet<>(metaBuilder.canPlaceOn); this.canPlaceOn = new HashSet<>(metaBuilder.canPlaceOn);
this.nbt = metaBuilder.nbt; this.nbt = metaBuilder.nbt();
this.emptyBuilder = metaBuilder.getSupplier().get(); this.emptyBuilder = metaBuilder.getSupplier().get();
} }

View File

@ -2,7 +2,6 @@ package net.minestom.server.item;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer; import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
import net.minestom.server.adventure.AdventureSerializer;
import net.minestom.server.instance.block.Block; import net.minestom.server.instance.block.Block;
import net.minestom.server.item.attribute.ItemAttribute; import net.minestom.server.item.attribute.ItemAttribute;
import net.minestom.server.tag.Tag; import net.minestom.server.tag.Tag;
@ -15,12 +14,17 @@ import org.jetbrains.annotations.Nullable;
import org.jglrxavpok.hephaistos.nbt.*; import org.jglrxavpok.hephaistos.nbt.*;
import java.util.*; import java.util.*;
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.function.Supplier; import java.util.function.Supplier;
public abstract class ItemMetaBuilder implements TagWritable { public abstract class ItemMetaBuilder implements TagWritable {
protected NBTCompound nbt = new NBTCompound(); private static final AtomicReferenceFieldUpdater<ItemMetaBuilder, NBTCompound> NBT_UPDATER =
AtomicReferenceFieldUpdater.newUpdater(ItemMetaBuilder.class, NBTCompound.class, "nbt");
protected volatile boolean built = false;
private volatile NBTCompound nbt = new NBTCompound();
protected int damage; protected int damage;
protected boolean unbreakable; protected boolean unbreakable;
@ -36,21 +40,21 @@ public abstract class ItemMetaBuilder implements TagWritable {
@Contract("_ -> this") @Contract("_ -> this")
public @NotNull ItemMetaBuilder damage(int damage) { public @NotNull ItemMetaBuilder damage(int damage) {
this.damage = damage; this.damage = damage;
this.nbt.setInt("Damage", damage); mutateNbt(compound -> compound.setInt("Damage", damage));
return this; return this;
} }
@Contract("_ -> this") @Contract("_ -> this")
public @NotNull ItemMetaBuilder unbreakable(boolean unbreakable) { public @NotNull ItemMetaBuilder unbreakable(boolean unbreakable) {
this.unbreakable = unbreakable; this.unbreakable = unbreakable;
this.nbt.setByte("Unbreakable", (byte) (unbreakable ? 1 : 0)); mutateNbt(compound -> compound.setByte("Unbreakable", (byte) (unbreakable ? 1 : 0)));
return this; return this;
} }
@Contract("_ -> this") @Contract("_ -> this")
public @NotNull ItemMetaBuilder hideFlag(int hideFlag) { public @NotNull ItemMetaBuilder hideFlag(int hideFlag) {
this.hideFlag = hideFlag; this.hideFlag = hideFlag;
this.nbt.setInt("HideFlags", hideFlag); mutateNbt(compound -> compound.setInt("HideFlags", hideFlag));
return this; return this;
} }
@ -79,7 +83,7 @@ public abstract class ItemMetaBuilder implements TagWritable {
@Contract("_ -> this") @Contract("_ -> this")
public @NotNull ItemMetaBuilder lore(@NotNull List<@NotNull Component> lore) { public @NotNull ItemMetaBuilder lore(@NotNull List<@NotNull Component> lore) {
this.lore = lore; this.lore = new ArrayList<>(lore);
handleCompound("display", nbtCompound -> { handleCompound("display", nbtCompound -> {
final NBTList<NBTString> loreNBT = new NBTList<>(NBTTypes.TAG_String); final NBTList<NBTString> loreNBT = new NBTList<>(NBTTypes.TAG_String);
for (Component line : lore) { for (Component line : lore) {
@ -98,7 +102,7 @@ public abstract class ItemMetaBuilder implements TagWritable {
@Contract("_ -> this") @Contract("_ -> this")
public @NotNull ItemMetaBuilder enchantments(@NotNull Map<Enchantment, Short> enchantments) { public @NotNull ItemMetaBuilder enchantments(@NotNull Map<Enchantment, Short> enchantments) {
this.enchantmentMap = enchantments; this.enchantmentMap = new HashMap<>(enchantments);
handleMap(enchantmentMap, "Enchantments", nbt, () -> { handleMap(enchantmentMap, "Enchantments", nbt, () -> {
NBTUtils.writeEnchant(nbt, "Enchantments", enchantmentMap); NBTUtils.writeEnchant(nbt, "Enchantments", enchantmentMap);
return nbt.get("Enchantments"); return nbt.get("Enchantments");
@ -108,21 +112,21 @@ public abstract class ItemMetaBuilder implements TagWritable {
@Contract("_, _ -> this") @Contract("_, _ -> this")
public @NotNull ItemMetaBuilder enchantment(@NotNull Enchantment enchantment, short level) { public @NotNull ItemMetaBuilder enchantment(@NotNull Enchantment enchantment, short level) {
this.enchantmentMap.put(enchantment, level); this.enchantmentMap = Map.of(enchantment, level);
enchantments(enchantmentMap); enchantments(enchantmentMap);
return this; return this;
} }
@Contract("-> this") @Contract("-> this")
public @NotNull ItemMetaBuilder clearEnchantment() { public @NotNull ItemMetaBuilder clearEnchantment() {
this.enchantmentMap.clear(); this.enchantmentMap = Collections.emptyMap();
enchantments(enchantmentMap); enchantments(enchantmentMap);
return this; return this;
} }
@Contract("_ -> this") @Contract("_ -> this")
public @NotNull ItemMetaBuilder attributes(@NotNull List<@NotNull ItemAttribute> attributes) { public @NotNull ItemMetaBuilder attributes(@NotNull List<@NotNull ItemAttribute> attributes) {
this.attributes = attributes; this.attributes = new ArrayList<>(attributes);
handleCollection(attributes, "AttributeModifiers", nbt, () -> { handleCollection(attributes, "AttributeModifiers", nbt, () -> {
NBTList<NBTCompound> attributesNBT = new NBTList<>(NBTTypes.TAG_Compound); NBTList<NBTCompound> attributesNBT = new NBTList<>(NBTTypes.TAG_Compound);
@ -153,7 +157,7 @@ public abstract class ItemMetaBuilder implements TagWritable {
@Contract("_ -> this") @Contract("_ -> this")
public @NotNull ItemMetaBuilder canPlaceOn(@NotNull Set<@NotNull Block> blocks) { public @NotNull ItemMetaBuilder canPlaceOn(@NotNull Set<@NotNull Block> blocks) {
this.canPlaceOn = blocks; this.canPlaceOn = new HashSet<>(blocks);
handleCollection(canPlaceOn, "CanPlaceOn", nbt, () -> { handleCollection(canPlaceOn, "CanPlaceOn", nbt, () -> {
NBTList<NBTString> list = new NBTList<>(NBTTypes.TAG_String); NBTList<NBTString> list = new NBTList<>(NBTTypes.TAG_String);
canPlaceOn.forEach(block -> list.add(new NBTString(block.getName()))); canPlaceOn.forEach(block -> list.add(new NBTString(block.getName())));
@ -170,7 +174,7 @@ public abstract class ItemMetaBuilder implements TagWritable {
@Contract("_ -> this") @Contract("_ -> this")
public @NotNull ItemMetaBuilder canDestroy(@NotNull Set<@NotNull Block> blocks) { public @NotNull ItemMetaBuilder canDestroy(@NotNull Set<@NotNull Block> blocks) {
this.canDestroy = blocks; this.canDestroy = new HashSet<>(blocks);
handleCollection(canDestroy, "CanDestroy", nbt, () -> { handleCollection(canDestroy, "CanDestroy", nbt, () -> {
NBTList<NBTString> list = new NBTList<>(NBTTypes.TAG_String); NBTList<NBTString> list = new NBTList<>(NBTTypes.TAG_String);
canDestroy.forEach(block -> list.add(new NBTString(block.getName()))); canDestroy.forEach(block -> list.add(new NBTString(block.getName())));
@ -187,7 +191,7 @@ public abstract class ItemMetaBuilder implements TagWritable {
@Override @Override
public <T> void setTag(@NotNull Tag<T> tag, @Nullable T value) { public <T> void setTag(@NotNull Tag<T> tag, @Nullable T value) {
tag.write(nbt, value); mutateNbt(compound -> tag.write(compound, value));
} }
public <T> @NotNull ItemMetaBuilder set(@NotNull Tag<T> tag, @Nullable T value) { public <T> @NotNull ItemMetaBuilder set(@NotNull Tag<T> tag, @Nullable T value) {
@ -202,30 +206,51 @@ public abstract class ItemMetaBuilder implements TagWritable {
protected abstract @NotNull Supplier<@NotNull ItemMetaBuilder> getSupplier(); protected abstract @NotNull Supplier<@NotNull ItemMetaBuilder> getSupplier();
protected void mutateNbt(Consumer<NBTCompound> consumer) {
if (built) {
built = false;
final var currentNbt = nbt;
NBT_UPDATER.compareAndSet(this, currentNbt, currentNbt.deepClone());
}
synchronized (this) {
consumer.accept(nbt);
}
}
protected synchronized NBTCompound nbt() {
return nbt;
}
protected @NotNull ItemMeta generate() {
this.built = true;
return build();
}
protected void handleCompound(@NotNull String key, protected void handleCompound(@NotNull String key,
@NotNull Consumer<@NotNull NBTCompound> consumer) { @NotNull Consumer<@NotNull NBTCompound> consumer) {
NBTCompound compound = null; mutateNbt(nbt -> {
boolean newNbt = false; NBTCompound compound = null;
if (nbt.containsKey(key)) { boolean newNbt = false;
NBT dNbt = nbt.get(key); if (nbt.containsKey(key)) {
if (dNbt instanceof NBTCompound) { NBT dNbt = nbt.get(key);
compound = (NBTCompound) dNbt; if (dNbt instanceof NBTCompound) {
} compound = (NBTCompound) dNbt;
} else { }
compound = new NBTCompound(); } else {
newNbt = true; compound = new NBTCompound();
} newNbt = true;
if (compound != null) {
consumer.accept(compound);
if (newNbt && compound.getSize() > 0) {
this.nbt.set(key, compound);
} else if (!newNbt && compound.getSize() == 0) {
this.nbt.removeTag(key);
} }
} if (compound != null) {
consumer.accept(compound);
if (newNbt && compound.getSize() > 0) {
this.nbt.set(key, compound);
} else if (!newNbt && compound.getSize() == 0) {
this.nbt.removeTag(key);
}
}
});
} }
protected void handleNullable(@Nullable Object value, protected void handleNullable(@Nullable Object value,
@ -239,6 +264,12 @@ public abstract class ItemMetaBuilder implements TagWritable {
} }
} }
protected void handleNullable(@Nullable Object value,
@NotNull String key,
@NotNull Supplier<@NotNull NBT> supplier) {
mutateNbt(compound -> handleNullable(value, key, compound, supplier));
}
protected void handleCollection(@NotNull Collection<?> objects, protected void handleCollection(@NotNull Collection<?> objects,
@NotNull String key, @NotNull String key,
@NotNull NBTCompound nbtCompound, @NotNull NBTCompound nbtCompound,
@ -250,6 +281,12 @@ public abstract class ItemMetaBuilder implements TagWritable {
} }
} }
protected void handleCollection(@NotNull Collection<?> objects,
@NotNull String key,
@NotNull Supplier<@NotNull NBT> supplier) {
mutateNbt(compound -> handleCollection(objects, key, compound, supplier));
}
protected void handleMap(@NotNull Map<?, ?> objects, protected void handleMap(@NotNull Map<?, ?> objects,
@NotNull String key, @NotNull String key,
@NotNull NBTCompound nbtCompound, @NotNull NBTCompound nbtCompound,
@ -271,5 +308,4 @@ public abstract class ItemMetaBuilder implements TagWritable {
public interface Provider<T extends ItemMetaBuilder> { public interface Provider<T extends ItemMetaBuilder> {
} }
} }

View File

@ -109,9 +109,9 @@ public class ItemStackBuilder {
@Contract(value = "-> new", pure = true) @Contract(value = "-> new", pure = true)
public @NotNull ItemStack build() { public @NotNull ItemStack build() {
if (amount > 0) if (amount < 1)
return new ItemStack(material, amount, metaBuilder.build(), stackingRule); return ItemStack.AIR;
return ItemStack.AIR; return new ItemStack(material, amount, metaBuilder.generate(), stackingRule);
} }
private static final class DefaultMeta extends ItemMetaBuilder { private static final class DefaultMeta extends ItemMetaBuilder {
@ -130,5 +130,4 @@ public class ItemStackBuilder {
return DefaultMeta::new; return DefaultMeta::new;
} }
} }
} }

View File

@ -45,18 +45,20 @@ public class CompassMeta extends ItemMeta implements ItemMetaBuilder.Provider<Co
public Builder lodestoneTracked(boolean lodestoneTracked) { public Builder lodestoneTracked(boolean lodestoneTracked) {
this.lodestoneTracked = lodestoneTracked; this.lodestoneTracked = lodestoneTracked;
this.nbt.setByte("LodestoneTracked", (byte) (lodestoneTracked ? 1 : 0)); mutateNbt(compound -> compound.setByte("LodestoneTracked", (byte) (lodestoneTracked ? 1 : 0)));
return this; return this;
} }
public Builder lodestoneDimension(@Nullable String lodestoneDimension) { public Builder lodestoneDimension(@Nullable String lodestoneDimension) {
this.lodestoneDimension = lodestoneDimension; this.lodestoneDimension = lodestoneDimension;
if (lodestoneDimension != null) { mutateNbt(compound -> {
this.nbt.setString("LodestoneDimension", lodestoneDimension); if (lodestoneDimension != null) {
} else { compound.setString("LodestoneDimension", lodestoneDimension);
this.nbt.removeTag("LodestoneDimension"); } else {
} compound.removeTag("LodestoneDimension");
}
});
return this; return this;
} }
@ -64,15 +66,17 @@ public class CompassMeta extends ItemMeta implements ItemMetaBuilder.Provider<Co
public Builder lodestonePosition(@Nullable Position lodestonePosition) { public Builder lodestonePosition(@Nullable Position lodestonePosition) {
this.lodestonePosition = lodestonePosition; this.lodestonePosition = lodestonePosition;
if (lodestonePosition != null) { mutateNbt(compound -> {
NBTCompound posCompound = new NBTCompound(); if (lodestonePosition != null) {
posCompound.setInt("X", (int) lodestonePosition.getX()); NBTCompound posCompound = new NBTCompound();
posCompound.setInt("Y", (int) lodestonePosition.getY()); posCompound.setInt("X", (int) lodestonePosition.getX());
posCompound.setInt("Z", (int) lodestonePosition.getZ()); posCompound.setInt("Y", (int) lodestonePosition.getY());
this.nbt.set("LodestonePos", posCompound); posCompound.setInt("Z", (int) lodestonePosition.getZ());
} else { compound.set("LodestonePos", posCompound);
this.nbt.removeTag("LodestonePos"); } else {
} compound.removeTag("LodestonePos");
}
});
return this; return this;
} }

View File

@ -97,7 +97,7 @@ public class CrossbowMeta extends ItemMeta implements ItemMetaBuilder.Provider<S
if (!projectile.isAir()) { if (!projectile.isAir()) {
chargedProjectiles.add(getItemCompound(projectile)); chargedProjectiles.add(getItemCompound(projectile));
} }
this.nbt.set("ChargedProjectiles", chargedProjectiles); mutateNbt(compound -> compound.set("ChargedProjectiles", chargedProjectiles));
return this; return this;
} }
@ -123,7 +123,7 @@ public class CrossbowMeta extends ItemMeta implements ItemMetaBuilder.Provider<S
chargedProjectiles.add(getItemCompound(projectile1)); chargedProjectiles.add(getItemCompound(projectile1));
chargedProjectiles.add(getItemCompound(projectile2)); chargedProjectiles.add(getItemCompound(projectile2));
chargedProjectiles.add(getItemCompound(projectile3)); chargedProjectiles.add(getItemCompound(projectile3));
this.nbt.set("ChargedProjectiles", chargedProjectiles); mutateNbt(compound -> compound.set("ChargedProjectiles", chargedProjectiles));
return this; return this;
} }
@ -135,7 +135,7 @@ public class CrossbowMeta extends ItemMeta implements ItemMetaBuilder.Provider<S
*/ */
public Builder charged(boolean charged) { public Builder charged(boolean charged) {
this.charged = charged; this.charged = charged;
this.nbt.setByte("Charged", (byte) (charged ? 1 : 0)); mutateNbt(compound -> compound.setByte("Charged", (byte) (charged ? 1 : 0)));
return this; return this;
} }

View File

@ -35,13 +35,13 @@ public class EnchantedBookMeta extends ItemMeta implements ItemMetaBuilder.Provi
private Map<Enchantment, Short> enchantments = new HashMap<>(); private Map<Enchantment, Short> enchantments = new HashMap<>();
public @NotNull Builder enchantments(Map<Enchantment, Short> enchantments) { public @NotNull Builder enchantments(@NotNull Map<Enchantment, Short> enchantments) {
this.enchantments = enchantments; this.enchantments = enchantments;
NBTUtils.writeEnchant(nbt, "StoredEnchantments", enchantments); mutateNbt(compound -> NBTUtils.writeEnchant(compound, "StoredEnchantments", enchantments));
return this; return this;
} }
public @NotNull Builder enchantment(Enchantment enchantment, short level) { public @NotNull Builder enchantment(@NotNull Enchantment enchantment, short level) {
this.enchantments.put(enchantment, level); this.enchantments.put(enchantment, level);
enchantments(enchantments); enchantments(enchantments);
return this; return this;

View File

@ -28,7 +28,7 @@ public class FireworkEffectMeta extends ItemMeta implements ItemMetaBuilder.Prov
public Builder effect(@Nullable FireworkEffect fireworkEffect) { public Builder effect(@Nullable FireworkEffect fireworkEffect) {
this.fireworkEffect = fireworkEffect; this.fireworkEffect = fireworkEffect;
this.nbt.set("Explosion", this.fireworkEffect.asCompound()); mutateNbt(compound -> compound.set("Explosion", this.fireworkEffect.asCompound()));
return this; return this;
} }

View File

@ -91,18 +91,18 @@ public class MapMeta extends ItemMeta implements ItemMetaBuilder.Provider<MapMet
public Builder mapId(int value) { public Builder mapId(int value) {
this.mapId = value; this.mapId = value;
this.nbt.setInt("map", mapId); mutateNbt(compound -> compound.setInt("map", mapId));
return this; return this;
} }
public Builder mapScaleDirection(int value) { public Builder mapScaleDirection(int value) {
this.mapScaleDirection = value; this.mapScaleDirection = value;
this.nbt.setInt("map_scale_direction", value); mutateNbt(compound -> compound.setInt("map_scale_direction", value));
return this; return this;
} }
public Builder decorations(List<MapDecoration> value) { public Builder decorations(List<MapDecoration> value) {
this.decorations = value; this.decorations = new ArrayList<>(value);
NBTList<NBTCompound> decorationsList = new NBTList<>(NBTTypes.TAG_Compound); NBTList<NBTCompound> decorationsList = new NBTList<>(NBTTypes.TAG_Compound);
for (MapDecoration decoration : decorations) { for (MapDecoration decoration : decorations) {
@ -115,7 +115,7 @@ public class MapMeta extends ItemMeta implements ItemMetaBuilder.Provider<MapMet
decorationsList.add(decorationCompound); decorationsList.add(decorationCompound);
} }
this.nbt.set("Decorations", decorationsList); mutateNbt(compound -> compound.set("Decorations", decorationsList));
return this; return this;
} }
@ -123,14 +123,16 @@ public class MapMeta extends ItemMeta implements ItemMetaBuilder.Provider<MapMet
public Builder mapColor(Color value) { public Builder mapColor(Color value) {
this.mapColor = value; this.mapColor = value;
NBTCompound displayCompound; mutateNbt(nbt -> {
if (nbt.containsKey("display")) { NBTCompound displayCompound;
displayCompound = nbt.getCompound("display"); if (nbt.containsKey("display")) {
} else { displayCompound = nbt.getCompound("display");
displayCompound = new NBTCompound(); } else {
this.nbt.set("display", displayCompound); displayCompound = new NBTCompound();
} nbt.set("display", displayCompound);
displayCompound.setInt("MapColor", mapColor.asRGB()); }
displayCompound.setInt("MapColor", mapColor.asRGB());
});
return this; return this;
} }

View File

@ -52,7 +52,7 @@ public class PotionMeta extends ItemMeta implements ItemMetaBuilder.Provider<Pot
public Builder potionType(@NotNull PotionType potionType) { public Builder potionType(@NotNull PotionType potionType) {
this.potionType = potionType; this.potionType = potionType;
this.nbt.setString("Potion", potionType.getNamespaceID().asString()); mutateNbt(compound -> compound.setString("Potion", potionType.getNamespaceID().asString()));
return this; return this;
} }
@ -71,14 +71,14 @@ public class PotionMeta extends ItemMeta implements ItemMetaBuilder.Provider<Pot
potionList.add(potionCompound); potionList.add(potionCompound);
} }
this.nbt.set("CustomPotionEffects", potionList); mutateNbt(compound -> compound.set("CustomPotionEffects", potionList));
return this; return this;
} }
public Builder color(@NotNull Color color) { public Builder color(@NotNull Color color) {
this.color = color; this.color = color;
this.nbt.setInt("CustomPotionColor", color.asRGB()); mutateNbt(compound -> compound.setInt("CustomPotionColor", color.asRGB()));
return this; return this;
} }

View File

@ -2,7 +2,6 @@ package net.minestom.server.item.metadata;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer; import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
import net.minestom.server.adventure.AdventureSerializer;
import net.minestom.server.item.ItemMeta; import net.minestom.server.item.ItemMeta;
import net.minestom.server.item.ItemMetaBuilder; import net.minestom.server.item.ItemMetaBuilder;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@ -53,22 +52,22 @@ public class WritableBookMeta extends ItemMeta implements ItemMetaBuilder.Provid
public Builder author(@Nullable String author) { public Builder author(@Nullable String author) {
this.author = author; this.author = author;
handleNullable(author, "author", nbt, handleNullable(author, "author",
() -> new NBTString(Objects.requireNonNull(author))); () -> new NBTString(Objects.requireNonNull(author)));
return this; return this;
} }
public Builder title(@Nullable String title) { public Builder title(@Nullable String title) {
this.title = title; this.title = title;
handleNullable(title, "title", nbt, handleNullable(title, "title",
() -> new NBTString(Objects.requireNonNull(title))); () -> new NBTString(Objects.requireNonNull(title)));
return this; return this;
} }
public Builder pages(@NotNull List<@NotNull Component> pages) { public Builder pages(@NotNull List<@NotNull Component> pages) {
this.pages = pages; this.pages = new ArrayList<>(pages);
handleCollection(pages, "pages", nbt, () -> { handleCollection(pages, "pages", () -> {
NBTList<NBTString> list = new NBTList<>(NBTTypes.TAG_String); NBTList<NBTString> list = new NBTList<>(NBTTypes.TAG_String);
for (Component page : pages) { for (Component page : pages) {
list.add(new NBTString(GsonComponentSerializer.gson().serialize(page))); list.add(new NBTString(GsonComponentSerializer.gson().serialize(page)));

View File

@ -86,35 +86,35 @@ public class WrittenBookMeta extends ItemMeta implements ItemMetaBuilder.Provide
public Builder resolved(boolean resolved) { public Builder resolved(boolean resolved) {
this.resolved = resolved; this.resolved = resolved;
this.nbt.setByte("resolved", (byte) (resolved ? 1 : 0)); mutateNbt(compound -> compound.setByte("resolved", (byte) (resolved ? 1 : 0)));
return this; return this;
} }
public Builder generation(@Nullable WrittenBookGeneration generation) { public Builder generation(@Nullable WrittenBookGeneration generation) {
this.generation = generation; this.generation = generation;
handleNullable(generation, "generation", nbt, handleNullable(generation, "generation",
() -> new NBTInt(Objects.requireNonNull(generation).ordinal())); () -> new NBTInt(Objects.requireNonNull(generation).ordinal()));
return this; return this;
} }
public Builder author(@Nullable String author) { public Builder author(@Nullable String author) {
this.author = author; this.author = author;
handleNullable(author, "author", nbt, handleNullable(author, "author",
() -> new NBTString(Objects.requireNonNull(author))); () -> new NBTString(Objects.requireNonNull(author)));
return this; return this;
} }
public Builder title(@Nullable String title) { public Builder title(@Nullable String title) {
this.title = title; this.title = title;
handleNullable(title, "title", nbt, handleNullable(title, "title",
() -> new NBTString(Objects.requireNonNull(title))); () -> new NBTString(Objects.requireNonNull(title)));
return this; return this;
} }
public Builder pages(@NotNull List<@NotNull Component> pages) { public Builder pages(@NotNull List<@NotNull Component> pages) {
this.pages = pages; this.pages = new ArrayList<>(pages);
handleCollection(pages, "pages", nbt, () -> { handleCollection(pages, "pages", () -> {
NBTList<NBTString> list = new NBTList<>(NBTTypes.TAG_String); NBTList<NBTString> list = new NBTList<>(NBTTypes.TAG_String);
for (Component page : pages) { for (Component page : pages) {
list.add(new NBTString(GsonComponentSerializer.gson().serialize(page))); list.add(new NBTString(GsonComponentSerializer.gson().serialize(page)));