Add direct access to nbt for meta subclasses

This commit is contained in:
themode 2021-12-20 22:51:01 +01:00 committed by TheMode
parent c5141f4145
commit 9927665d91
11 changed files with 77 additions and 110 deletions

View File

@ -39,30 +39,28 @@ 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;
mutateNbt(compound -> compound.setInt("Damage", damage)); this.nbt.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;
mutateNbt(compound -> compound.set("Unbreakable", NBT.Boolean(unbreakable))); this.nbt.set("Unbreakable", NBT.Boolean(unbreakable));
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;
mutateNbt(compound -> compound.setInt("HideFlags", hideFlag)); this.nbt.setInt("HideFlags", hideFlag);
return this; return this;
} }
@Contract("_ -> this") @Contract("_ -> this")
public @NotNull ItemMetaBuilder hideFlag(@NotNull ItemHideFlag... hideFlags) { public @NotNull ItemMetaBuilder hideFlag(@NotNull ItemHideFlag... hideFlags) {
int result = 0; int result = 0;
for (ItemHideFlag hideFlag : hideFlags) { for (ItemHideFlag hideFlag : hideFlags) result |= hideFlag.getBitFieldPart();
result |= hideFlag.getBitFieldPart();
}
return hideFlag(result); return hideFlag(result);
} }
@ -71,8 +69,7 @@ public abstract class ItemMetaBuilder implements TagWritable {
this.displayName = displayName; this.displayName = displayName;
handleCompound("display", nbtCompound -> { handleCompound("display", nbtCompound -> {
if (displayName != null) { if (displayName != null) {
final String name = GsonComponentSerializer.gson().serialize(displayName); nbtCompound.setString("Name", GsonComponentSerializer.gson().serialize(displayName));
nbtCompound.setString("Name", name);
} else { } else {
nbtCompound.remove("Name"); nbtCompound.remove("Name");
} }
@ -118,16 +115,14 @@ public abstract class ItemMetaBuilder implements TagWritable {
@Contract("-> this") @Contract("-> this")
public @NotNull ItemMetaBuilder clearEnchantment() { public @NotNull ItemMetaBuilder clearEnchantment() {
this.enchantmentMap = new HashMap<>(); this.enchantmentMap = new HashMap<>();
enchantments(enchantmentMap); this.nbt.remove("Enchantments");
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 = new ArrayList<>(attributes); this.attributes = new ArrayList<>(attributes);
handleCollection(attributes, "AttributeModifiers", () -> NBT.List(NBTType.TAG_Compound,
handleCollection(attributes, "AttributeModifiers", () -> NBT.List(
NBTType.TAG_Compound,
attributes.stream() attributes.stream()
.map(itemAttribute -> NBT.Compound(Map.of( .map(itemAttribute -> NBT.Compound(Map.of(
"UUID", NBT.IntArray(Utils.uuidToIntArray(itemAttribute.getUuid())), "UUID", NBT.IntArray(Utils.uuidToIntArray(itemAttribute.getUuid())),
@ -138,14 +133,13 @@ public abstract class ItemMetaBuilder implements TagWritable {
"Name", NBT.String(itemAttribute.getInternalName())))) "Name", NBT.String(itemAttribute.getInternalName()))))
.toList() .toList()
)); ));
return this; return this;
} }
@Contract("_ -> this") @Contract("_ -> this")
public @NotNull ItemMetaBuilder customModelData(int customModelData) { public @NotNull ItemMetaBuilder customModelData(int customModelData) {
this.customModelData = customModelData; this.customModelData = customModelData;
mutateNbt(compound -> compound.setInt("CustomModelData", customModelData)); this.nbt.setInt("CustomModelData", customModelData);
return this; return this;
} }
@ -185,7 +179,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) {
mutateNbt(compound -> tag.write(compound, value)); tag.write(nbt, 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) {
@ -208,68 +202,59 @@ public abstract class ItemMetaBuilder implements TagWritable {
} }
} }
protected MutableNBTCompound mutableNbt() {
return nbt;
}
protected void mutateNbt(Consumer<MutableNBTCompound> consumer) { protected void mutateNbt(Consumer<MutableNBTCompound> consumer) {
consumer.accept(nbt); consumer.accept(nbt);
} }
protected @NotNull ItemMeta generate() {
return build();
}
protected void handleCompound(@NotNull String key, protected void handleCompound(@NotNull String key,
@NotNull Consumer<@NotNull MutableNBTCompound> consumer) { @NotNull Consumer<@NotNull MutableNBTCompound> consumer) {
mutateNbt(nbt -> { MutableNBTCompound compoundToModify = nbt.get(key) instanceof NBTCompound compound ?
MutableNBTCompound compoundToModify = nbt.get(key) instanceof NBTCompound compound ? compound.toMutableCompound() : new MutableNBTCompound();
compound.toMutableCompound() : new MutableNBTCompound(); consumer.accept(compoundToModify);
if (compoundToModify.isEmpty()) {
consumer.accept(compoundToModify); this.nbt.remove(key);
if (compoundToModify.isEmpty()) { } else {
nbt.remove(key); this.nbt.set(key, compoundToModify.toCompound());
} else { }
nbt.set(key, compoundToModify.toCompound());
}
});
} }
protected void handleNullable(@Nullable Object value, protected void handleNullable(@Nullable Object value,
@NotNull String key, @NotNull String key,
@NotNull Supplier<@NotNull NBT> supplier) { @NotNull Supplier<@NotNull NBT> supplier) {
mutateNbt(compound -> { if (value != null) {
if (value != null) { this.nbt.set(key, supplier.get());
compound.set(key, supplier.get()); } else {
} else { this.nbt.remove(key);
compound.remove(key); }
}
});
} }
protected void handleCollection(@NotNull Collection<?> objects, protected void handleCollection(@NotNull Collection<?> objects,
@NotNull String key, @NotNull String key,
@NotNull Supplier<@NotNull NBT> supplier) { @NotNull Supplier<@NotNull NBT> supplier) {
mutateNbt(compound -> { if (!objects.isEmpty()) {
if (!objects.isEmpty()) { this.nbt.set(key, supplier.get());
compound.set(key, supplier.get()); } else {
} else { this.nbt.remove(key);
compound.remove(key); }
}
});
} }
protected void handleMap(@NotNull Map<?, ?> objects, protected void handleMap(@NotNull Map<?, ?> objects,
@NotNull String key, @NotNull String key,
@NotNull Consumer<MutableNBTCompound> consumer) { @NotNull Consumer<MutableNBTCompound> consumer) {
mutateNbt(compound -> { if (!objects.isEmpty()) {
if (!objects.isEmpty()) { consumer.accept(nbt);
consumer.accept(compound); } else {
} else { nbt.remove(key);
compound.remove(key); }
}
});
} }
@ApiStatus.Internal @ApiStatus.Internal
public static void resetMeta(@NotNull ItemMetaBuilder src, @NotNull NBTCompound nbtCompound) { public static void resetMeta(@NotNull ItemMetaBuilder src, @NotNull NBTCompound nbtCompound) {
src.nbt = nbtCompound.toMutableCompound(); src.nbt.copyFrom(nbtCompound);
appendMeta(src, nbtCompound); appendMeta(src, nbtCompound);
} }
@ -339,8 +324,6 @@ public abstract class ItemMetaBuilder implements TagWritable {
if (nbt.get("CustomModelData") instanceof NBTInt customModelData) { if (nbt.get("CustomModelData") instanceof NBTInt customModelData) {
metaBuilder.customModelData = customModelData.getValue(); metaBuilder.customModelData = customModelData.getValue();
} }
// Meta specific fields
metaBuilder.read(nbt);
// CanPlaceOn // CanPlaceOn
if (nbt.get("CanPlaceOn") instanceof NBTList<?> canPlaceOn && if (nbt.get("CanPlaceOn") instanceof NBTList<?> canPlaceOn &&
canPlaceOn.getSubtagType() == NBTType.TAG_String) { canPlaceOn.getSubtagType() == NBTType.TAG_String) {
@ -357,6 +340,8 @@ public abstract class ItemMetaBuilder implements TagWritable {
metaBuilder.canDestroy.add(block); metaBuilder.canDestroy.add(block);
} }
} }
// Meta specific fields
metaBuilder.read(nbt);
} }
public interface Provider<T extends ItemMetaBuilder> { public interface Provider<T extends ItemMetaBuilder> {

View File

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

View File

@ -57,8 +57,7 @@ public class BundleMeta extends ItemMeta implements ItemMetaBuilder.Provider<Bun
} }
private void updateItems() { private void updateItems() {
mutateNbt(compound -> compound.set("Items", NBT.List(NBTType.TAG_Compound, mutableNbt().set("Items", NBT.List(NBTType.TAG_Compound, items.size(), i -> items.get(i).toItemNBT()));
items.size(), i -> items.get(i).toItemNBT())));
} }
@Override @Override

View File

@ -49,38 +49,30 @@ 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;
mutateNbt(compound -> compound.setByte("LodestoneTracked", (byte) (lodestoneTracked ? 1 : 0))); mutableNbt().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 -> { mutableNbt().setString("LodestoneDimension", lodestoneDimension);
if (lodestoneDimension != null) { } else {
compound.setString("LodestoneDimension", lodestoneDimension); mutableNbt().remove("LodestoneDimension");
} else { }
compound.remove("LodestoneDimension");
}
});
return this; return this;
} }
public Builder lodestonePosition(@Nullable Point lodestonePosition) { public Builder lodestonePosition(@Nullable Point lodestonePosition) {
this.lodestonePosition = lodestonePosition; this.lodestonePosition = lodestonePosition;
if (lodestonePosition != null) {
mutateNbt(compound -> { mutableNbt().set("LodestonePos", NBT.Compound(Map.of(
if (lodestonePosition != null) { "X", NBT.Int(lodestonePosition.blockX()),
compound.set("LodestonePos", NBT.Compound(Map.of( "Y", NBT.Int(lodestonePosition.blockY()),
"X", NBT.Int(lodestonePosition.blockX()), "Z", NBT.Int(lodestonePosition.blockZ()))));
"Y", NBT.Int(lodestonePosition.blockY()), } else {
"Z", NBT.Int(lodestonePosition.blockZ())))); mutableNbt().remove("LodestonePos");
} else { }
compound.remove("LodestonePos");
}
});
return this; return this;
} }

View File

@ -90,11 +90,8 @@ public class CrossbowMeta extends ItemMeta implements ItemMetaBuilder.Provider<S
public Builder projectile(@NotNull ItemStack projectile) { public Builder projectile(@NotNull ItemStack projectile) {
this.projectile1 = projectile; this.projectile1 = projectile;
this.triple = false; this.triple = false;
mutableNbt().set("ChargedProjectiles", NBT.List(NBTType.TAG_Compound,
List<NBTCompound> chargedProjectiles = projectile.isAir() ? List.of() : List.of(getItemCompound(projectile))));
projectile.isAir() ? List.of() : List.of(getItemCompound(projectile));
mutateNbt(compound -> compound.set("ChargedProjectiles", NBT.List(NBTType.TAG_Compound, chargedProjectiles)));
return this; return this;
} }
@ -109,16 +106,13 @@ public class CrossbowMeta extends ItemMeta implements ItemMetaBuilder.Provider<S
Check.argCondition(projectile1.isAir(), "the projectile1 of your crossbow isn't visible"); Check.argCondition(projectile1.isAir(), "the projectile1 of your crossbow isn't visible");
Check.argCondition(projectile2.isAir(), "the projectile2 of your crossbow isn't visible"); Check.argCondition(projectile2.isAir(), "the projectile2 of your crossbow isn't visible");
Check.argCondition(projectile3.isAir(), "the projectile3 of your crossbow isn't visible"); Check.argCondition(projectile3.isAir(), "the projectile3 of your crossbow isn't visible");
this.projectile1 = projectile1; this.projectile1 = projectile1;
this.projectile2 = projectile2; this.projectile2 = projectile2;
this.projectile3 = projectile3; this.projectile3 = projectile3;
this.triple = true; this.triple = true;
List<NBTCompound> chargedProjectiles = List<NBTCompound> chargedProjectiles =
List.of(getItemCompound(projectile1), getItemCompound(projectile2), getItemCompound(projectile3)); List.of(getItemCompound(projectile1), getItemCompound(projectile2), getItemCompound(projectile3));
mutateNbt(compound -> compound.set("ChargedProjectiles", NBT.List(NBTType.TAG_Compound, chargedProjectiles))); mutableNbt().set("ChargedProjectiles", NBT.List(NBTType.TAG_Compound, chargedProjectiles));
return this; return this;
} }
@ -129,7 +123,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;
mutateNbt(compound -> compound.setByte("Charged", (byte) (charged ? 1 : 0))); mutableNbt().set("Charged", NBT.Boolean(charged));
return this; return this;
} }

View File

@ -37,7 +37,7 @@ public class EnchantedBookMeta extends ItemMeta implements ItemMetaBuilder.Provi
public @NotNull Builder enchantments(@NotNull Map<Enchantment, Short> enchantments) { public @NotNull Builder enchantments(@NotNull Map<Enchantment, Short> enchantments) {
this.enchantments = enchantments; this.enchantments = enchantments;
mutateNbt(compound -> NBTUtils.writeEnchant(compound, "StoredEnchantments", enchantments)); NBTUtils.writeEnchant(mutableNbt(), "StoredEnchantments", enchantments);
return this; return this;
} }

View File

@ -7,6 +7,8 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jglrxavpok.hephaistos.nbt.NBTCompound; import org.jglrxavpok.hephaistos.nbt.NBTCompound;
import java.util.Objects;
public class FireworkEffectMeta extends ItemMeta implements ItemMetaBuilder.Provider<FireworkEffectMeta.Builder> { public class FireworkEffectMeta extends ItemMeta implements ItemMetaBuilder.Provider<FireworkEffectMeta.Builder> {
private final FireworkEffect fireworkEffect; private final FireworkEffect fireworkEffect;
@ -26,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;
mutateNbt(compound -> compound.set("Explosion", this.fireworkEffect.asCompound())); handleNullable(fireworkEffect, "Explosion", () -> Objects.requireNonNull(fireworkEffect).asCompound());
return this; return this;
} }

View File

@ -75,21 +75,19 @@ 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;
mutateNbt(compound -> compound.setInt("map", mapId)); mutableNbt().setInt("map", mapId);
return this; return this;
} }
public Builder mapScaleDirection(int value) { public Builder mapScaleDirection(int value) {
this.mapScaleDirection = value; this.mapScaleDirection = value;
mutateNbt(compound -> compound.setInt("map_scale_direction", value)); mutableNbt().setInt("map_scale_direction", value);
return this; return this;
} }
public Builder decorations(List<Decoration> value) { public Builder decorations(List<Decoration> value) {
this.decorations = new ArrayList<>(value); this.decorations = new ArrayList<>(value);
mutableNbt().set("Decorations", NBT.List(NBTType.TAG_Compound,
mutateNbt(compound -> compound.set("Decorations", NBT.List(
NBTType.TAG_Compound,
decorations.stream() decorations.stream()
.map(decoration -> NBT.Compound(Map.of( .map(decoration -> NBT.Compound(Map.of(
"id", NBT.String(decoration.id()), "id", NBT.String(decoration.id()),
@ -98,7 +96,7 @@ public class MapMeta extends ItemMeta implements ItemMetaBuilder.Provider<MapMet
"z", NBT.Byte(decoration.z()), "z", NBT.Byte(decoration.z()),
"rot", NBT.Double(decoration.rotation())))) "rot", NBT.Double(decoration.rotation()))))
.toList() .toList()
))); ));
return this; return this;
} }

View File

@ -49,15 +49,13 @@ 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;
mutateNbt(compound -> compound.setString("Potion", potionType.name())); mutableNbt().setString("Potion", potionType.name());
return this; return this;
} }
public Builder effects(@NotNull List<CustomPotionEffect> customPotionEffects) { public Builder effects(@NotNull List<CustomPotionEffect> customPotionEffects) {
this.customPotionEffects = customPotionEffects; this.customPotionEffects = customPotionEffects;
mutableNbt().set("CustomPotionEffects", NBT.List(NBTType.TAG_Compound,
NBTList<NBTCompound> potionList = NBT.List(
NBTType.TAG_Compound,
customPotionEffects.stream() customPotionEffects.stream()
.map(customPotionEffect -> NBT.Compound(Map.of( .map(customPotionEffect -> NBT.Compound(Map.of(
"Id", NBT.Byte(customPotionEffect.id()), "Id", NBT.Byte(customPotionEffect.id()),
@ -67,15 +65,13 @@ public class PotionMeta extends ItemMeta implements ItemMetaBuilder.Provider<Pot
"ShowParticles", NBT.Boolean(customPotionEffect.showParticles()), "ShowParticles", NBT.Boolean(customPotionEffect.showParticles()),
"ShowIcon", NBT.Boolean(customPotionEffect.showIcon())))) "ShowIcon", NBT.Boolean(customPotionEffect.showIcon()))))
.toList() .toList()
); ));
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;
mutateNbt(compound -> compound.setInt("CustomPotionColor", color.asRGB())); mutableNbt().setInt("CustomPotionColor", color.asRGB());
return this; return this;
} }

View File

@ -89,7 +89,7 @@ public class WrittenBookMeta extends ItemMeta implements ItemMetaBuilder.Provide
public Builder resolved(boolean resolved) { public Builder resolved(boolean resolved) {
this.resolved = resolved; this.resolved = resolved;
mutateNbt(compound -> compound.setByte("resolved", (byte) (resolved ? 1 : 0))); mutableNbt().set("resolved", NBT.Boolean(resolved));
return this; return this;
} }

View File

@ -2,10 +2,7 @@ package item;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor; import net.kyori.adventure.text.format.NamedTextColor;
import net.minestom.server.item.Enchantment; import net.minestom.server.item.*;
import net.minestom.server.item.ItemHideFlag;
import net.minestom.server.item.ItemStack;
import net.minestom.server.item.Material;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import java.util.Map; import java.util.Map;
@ -102,6 +99,10 @@ public class ItemTest {
item = item.withMeta(meta -> meta.enchantment(Enchantment.EFFICIENCY, (short) 10)); item = item.withMeta(meta -> meta.enchantment(Enchantment.EFFICIENCY, (short) 10));
enchantments = item.getMeta().getEnchantmentMap(); enchantments = item.getMeta().getEnchantmentMap();
assertEquals(enchantments.get(Enchantment.EFFICIENCY), (short) 10); assertEquals(enchantments.get(Enchantment.EFFICIENCY), (short) 10);
item = item.withMeta(ItemMetaBuilder::clearEnchantment);
enchantments = item.getMeta().getEnchantmentMap();
assertTrue(enchantments.isEmpty());
} }
@Test @Test