mirror of
https://github.com/Minestom/Minestom.git
synced 2025-01-06 00:17:58 +01:00
Handle nbt directly inside builders instead of lazily
This commit is contained in:
parent
4f5fd125c4
commit
d6e7c9a635
@ -2,7 +2,6 @@ package net.minestom.server.item;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.minestom.server.item.attribute.ItemAttribute;
|
||||
import net.minestom.server.utils.NBTUtils;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@ -11,7 +10,6 @@ import org.jglrxavpok.hephaistos.nbt.NBTCompound;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class ItemMeta {
|
||||
@ -40,13 +38,8 @@ public class ItemMeta {
|
||||
this.attributes = Collections.unmodifiableList(metaBuilder.attributes);
|
||||
this.customModelData = metaBuilder.customModelData;
|
||||
|
||||
// nbt
|
||||
{
|
||||
this.nbt = Objects.requireNonNullElseGet(metaBuilder.originalNBT, NBTCompound::new);
|
||||
NBTUtils.writeMetaNBT(this, nbt);
|
||||
|
||||
this.emptyBuilder = metaBuilder.getSupplier().get();
|
||||
}
|
||||
this.nbt = metaBuilder.nbt;
|
||||
this.emptyBuilder = metaBuilder.getSupplier().get();
|
||||
}
|
||||
|
||||
@Contract(value = "_, -> new", pure = true)
|
||||
|
@ -1,18 +1,24 @@
|
||||
package net.minestom.server.item;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
|
||||
import net.minestom.server.adventure.AdventureSerializer;
|
||||
import net.minestom.server.item.attribute.ItemAttribute;
|
||||
import net.minestom.server.utils.NBTUtils;
|
||||
import net.minestom.server.utils.Utils;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jglrxavpok.hephaistos.nbt.NBTCompound;
|
||||
import org.jglrxavpok.hephaistos.nbt.*;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public abstract class ItemMetaBuilder {
|
||||
|
||||
protected NBTCompound nbt = new NBTCompound();
|
||||
|
||||
protected int damage;
|
||||
protected boolean unbreakable;
|
||||
protected int hideFlag;
|
||||
@ -22,23 +28,24 @@ public abstract class ItemMetaBuilder {
|
||||
protected List<ItemAttribute> attributes = new ArrayList<>();
|
||||
protected int customModelData;
|
||||
|
||||
protected NBTCompound originalNBT;
|
||||
|
||||
@Contract("_ -> this")
|
||||
public @NotNull ItemMetaBuilder damage(int damage) {
|
||||
this.damage = damage;
|
||||
this.nbt.setInt("Damage", damage);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Contract("_ -> this")
|
||||
public @NotNull ItemMetaBuilder unbreakable(boolean unbreakable) {
|
||||
this.unbreakable = unbreakable;
|
||||
this.nbt.setByte("Unbreakable", (byte) (unbreakable ? 1 : 0));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Contract("_ -> this")
|
||||
public @NotNull ItemMetaBuilder hideFlag(int hideFlag) {
|
||||
this.hideFlag = hideFlag;
|
||||
this.nbt.setInt("HideFlags", hideFlag);
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -54,12 +61,31 @@ public abstract class ItemMetaBuilder {
|
||||
@Contract("_ -> this")
|
||||
public @NotNull ItemMetaBuilder displayName(@Nullable Component displayName) {
|
||||
this.displayName = displayName;
|
||||
|
||||
handleCompound("display", nbtCompound -> {
|
||||
if (displayName != null) {
|
||||
final String name = AdventureSerializer.serialize(displayName);
|
||||
nbtCompound.setString("Name", name);
|
||||
} else {
|
||||
nbtCompound.removeTag("Name");
|
||||
}
|
||||
});
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
@Contract("_ -> this")
|
||||
public @NotNull ItemMetaBuilder lore(@NotNull List<@NotNull Component> lore) {
|
||||
this.lore = lore;
|
||||
|
||||
handleCompound("display", nbtCompound -> {
|
||||
final NBTList<NBTString> loreNBT = new NBTList<>(NBTTypes.TAG_String);
|
||||
for (Component line : lore) {
|
||||
loreNBT.add(new NBTString(GsonComponentSerializer.gson().serialize(line)));
|
||||
}
|
||||
nbtCompound.set("Lore", loreNBT);
|
||||
});
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -71,13 +97,21 @@ public abstract class ItemMetaBuilder {
|
||||
|
||||
@Contract("_ -> this")
|
||||
public @NotNull ItemMetaBuilder enchantments(@NotNull Map<Enchantment, Short> enchantments) {
|
||||
this.enchantmentMap.putAll(enchantments);
|
||||
this.enchantmentMap = enchantments;
|
||||
|
||||
if (!enchantmentMap.isEmpty()) {
|
||||
NBTUtils.writeEnchant(nbt, "Enchantments", enchantmentMap);
|
||||
} else {
|
||||
this.nbt.removeTag("Enchantments");
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
@Contract("_, _ -> this")
|
||||
public @NotNull ItemMetaBuilder enchantment(@NotNull Enchantment enchantment, short level) {
|
||||
this.enchantmentMap.put(enchantment, level);
|
||||
enchantments(enchantmentMap);
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -90,29 +124,45 @@ public abstract class ItemMetaBuilder {
|
||||
@Contract("_ -> this")
|
||||
public @NotNull ItemMetaBuilder attributes(@NotNull List<@NotNull ItemAttribute> attributes) {
|
||||
this.attributes = attributes;
|
||||
|
||||
|
||||
if (!attributes.isEmpty()) {
|
||||
NBTList<NBTCompound> attributesNBT = new NBTList<>(NBTTypes.TAG_Compound);
|
||||
|
||||
for (ItemAttribute itemAttribute : attributes) {
|
||||
final UUID uuid = itemAttribute.getUuid();
|
||||
attributesNBT.add(
|
||||
new NBTCompound()
|
||||
.setIntArray("UUID", Utils.uuidToIntArray(uuid))
|
||||
.setDouble("Amount", itemAttribute.getValue())
|
||||
.setString("Slot", itemAttribute.getSlot().name().toLowerCase())
|
||||
.setString("AttributeName", itemAttribute.getAttribute().getKey())
|
||||
.setInt("Operation", itemAttribute.getOperation().getId())
|
||||
.setString("Name", itemAttribute.getInternalName())
|
||||
);
|
||||
}
|
||||
this.nbt.set("AttributeModifiers", attributesNBT);
|
||||
} else {
|
||||
this.nbt.removeTag("AttributeModifiers");
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
@Contract("_ -> this")
|
||||
public @NotNull ItemMetaBuilder customModelData(int customModelData) {
|
||||
this.customModelData = customModelData;
|
||||
this.nbt.setInt("CustomModelData", customModelData);
|
||||
return this;
|
||||
}
|
||||
|
||||
public <T> @NotNull ItemMetaBuilder set(@NotNull ItemTag<T> tag, @Nullable T value) {
|
||||
if (originalNBT != null) {
|
||||
// Item is from nbt
|
||||
if (value != null) {
|
||||
tag.write(originalNBT, value);
|
||||
} else {
|
||||
this.originalNBT.removeTag(tag.getKey());
|
||||
}
|
||||
return this;
|
||||
if (value != null) {
|
||||
tag.write(nbt, value);
|
||||
} else {
|
||||
// Create item meta based on nbt
|
||||
var currentNbt = build().nbt();
|
||||
return fromNBT(this, currentNbt).set(tag, value);
|
||||
this.nbt.removeTag(tag.getKey());
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Contract("-> new")
|
||||
@ -120,15 +170,38 @@ public abstract class ItemMetaBuilder {
|
||||
|
||||
public abstract void read(@NotNull NBTCompound nbtCompound);
|
||||
|
||||
public abstract void write(@NotNull NBTCompound nbtCompound);
|
||||
|
||||
protected abstract @NotNull Supplier<@NotNull ItemMetaBuilder> getSupplier();
|
||||
|
||||
protected void handleCompound(@NotNull String key,
|
||||
@NotNull Consumer<@NotNull NBTCompound> consumer) {
|
||||
NBTCompound compound = null;
|
||||
boolean newNbt = false;
|
||||
if (nbt.containsKey(key)) {
|
||||
NBT dNbt = nbt.get(key);
|
||||
if (dNbt instanceof NBTCompound) {
|
||||
compound = (NBTCompound) dNbt;
|
||||
}
|
||||
} else {
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Contract(value = "_, _ -> new", pure = true)
|
||||
public static @NotNull ItemMetaBuilder fromNBT(@NotNull ItemMetaBuilder src, @NotNull NBTCompound nbtCompound) {
|
||||
ItemMetaBuilder dest = src.getSupplier().get();
|
||||
NBTUtils.loadDataIntoMeta(dest, nbtCompound);
|
||||
dest.originalNBT = nbtCompound;
|
||||
return dest;
|
||||
}
|
||||
|
||||
|
@ -45,16 +45,35 @@ public class CompassMeta extends ItemMeta implements ItemMetaBuilder.Provider<Co
|
||||
|
||||
public Builder lodestoneTracked(boolean lodestoneTracked) {
|
||||
this.lodestoneTracked = lodestoneTracked;
|
||||
this.nbt.setByte("LodestoneTracked", (byte) (lodestoneTracked ? 1 : 0));
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder lodestoneDimension(@Nullable String lodestoneDimension) {
|
||||
this.lodestoneDimension = lodestoneDimension;
|
||||
|
||||
if (lodestoneDimension != null) {
|
||||
this.nbt.setString("LodestoneDimension", lodestoneDimension);
|
||||
} else {
|
||||
this.nbt.removeTag("LodestoneDimension");
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder lodestonePosition(@Nullable Position lodestonePosition) {
|
||||
this.lodestonePosition = lodestonePosition;
|
||||
|
||||
if (lodestonePosition != null) {
|
||||
NBTCompound posCompound = new NBTCompound();
|
||||
posCompound.setInt("X", (int) lodestonePosition.getX());
|
||||
posCompound.setInt("Y", (int) lodestonePosition.getY());
|
||||
posCompound.setInt("Z", (int) lodestonePosition.getZ());
|
||||
this.nbt.set("LodestonePos", posCompound);
|
||||
} else {
|
||||
this.nbt.removeTag("LodestonePos");
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -81,22 +100,6 @@ public class CompassMeta extends ItemMeta implements ItemMetaBuilder.Provider<Co
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(@NotNull NBTCompound nbtCompound) {
|
||||
nbtCompound.setByte("LodestoneTracked", (byte) (lodestoneTracked ? 1 : 0));
|
||||
if (lodestoneDimension != null) {
|
||||
nbtCompound.setString("LodestoneDimension", lodestoneDimension);
|
||||
}
|
||||
|
||||
if (lodestonePosition != null) {
|
||||
NBTCompound posCompound = new NBTCompound();
|
||||
posCompound.setInt("X", (int) lodestonePosition.getX());
|
||||
posCompound.setInt("Y", (int) lodestonePosition.getY());
|
||||
posCompound.setInt("Z", (int) lodestonePosition.getZ());
|
||||
nbtCompound.set("LodestonePos", posCompound);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NotNull Supplier<ItemMetaBuilder> getSupplier() {
|
||||
return Builder::new;
|
||||
|
@ -90,21 +90,47 @@ public class MapMeta extends ItemMeta {
|
||||
|
||||
public Builder mapId(int value) {
|
||||
this.mapId = value;
|
||||
this.nbt.setInt("map", mapId);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder mapScaleDirection(int value) {
|
||||
this.mapScaleDirection = value;
|
||||
this.nbt.setInt("map_scale_direction", value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder decorations(List<MapDecoration> value) {
|
||||
this.decorations = value;
|
||||
|
||||
NBTList<NBTCompound> decorationsList = new NBTList<>(NBTTypes.TAG_Compound);
|
||||
for (MapDecoration decoration : decorations) {
|
||||
NBTCompound decorationCompound = new NBTCompound();
|
||||
decorationCompound.setString("id", decoration.getId());
|
||||
decorationCompound.setByte("type", decoration.getType());
|
||||
decorationCompound.setByte("x", decoration.getX());
|
||||
decorationCompound.setByte("z", decoration.getZ());
|
||||
decorationCompound.setDouble("rot", decoration.getRotation());
|
||||
|
||||
decorationsList.add(decorationCompound);
|
||||
}
|
||||
this.nbt.set("Decorations", decorationsList);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder mapColor(Color value) {
|
||||
this.mapColor = value;
|
||||
|
||||
NBTCompound displayCompound;
|
||||
if (nbt.containsKey("display")) {
|
||||
displayCompound = nbt.getCompound("display");
|
||||
} else {
|
||||
displayCompound = new NBTCompound();
|
||||
this.nbt.set("display", displayCompound);
|
||||
}
|
||||
displayCompound.setInt("MapColor", mapColor.asRGB());
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -116,11 +142,11 @@ public class MapMeta extends ItemMeta {
|
||||
@Override
|
||||
public void read(@NotNull NBTCompound compound) {
|
||||
if (compound.containsKey("map")) {
|
||||
this.mapId = compound.getAsInt("map");
|
||||
mapId(compound.getAsInt("map"));
|
||||
}
|
||||
|
||||
if (compound.containsKey("map_scale_direction")) {
|
||||
this.mapScaleDirection = compound.getAsInt("map_scale_direction");
|
||||
mapScaleDirection(compound.getAsInt("map_scale_direction"));
|
||||
}
|
||||
|
||||
if (compound.containsKey("Decorations")) {
|
||||
@ -156,38 +182,6 @@ public class MapMeta extends ItemMeta {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(@NotNull NBTCompound compound) {
|
||||
compound.setInt("map", mapId);
|
||||
|
||||
compound.setInt("map_scale_direction", mapScaleDirection);
|
||||
|
||||
if (!decorations.isEmpty()) {
|
||||
NBTList<NBTCompound> decorationsList = new NBTList<>(NBTTypes.TAG_Compound);
|
||||
for (MapDecoration decoration : decorations) {
|
||||
NBTCompound decorationCompound = new NBTCompound();
|
||||
decorationCompound.setString("id", decoration.getId());
|
||||
decorationCompound.setByte("type", decoration.getType());
|
||||
decorationCompound.setByte("x", decoration.getX());
|
||||
decorationCompound.setByte("z", decoration.getZ());
|
||||
decorationCompound.setDouble("rot", decoration.getRotation());
|
||||
|
||||
decorationsList.add(decorationCompound);
|
||||
}
|
||||
compound.set("Decorations", decorationsList);
|
||||
}
|
||||
|
||||
{
|
||||
NBTCompound displayCompound;
|
||||
if (compound.containsKey("display")) {
|
||||
displayCompound = compound.getCompound("display");
|
||||
} else {
|
||||
displayCompound = new NBTCompound();
|
||||
}
|
||||
displayCompound.setInt("MapColor", mapColor.asRGB());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NotNull Supplier<@NotNull ItemMetaBuilder> getSupplier() {
|
||||
return Builder::new;
|
||||
|
@ -193,7 +193,7 @@ public class CrossbowMeta extends ItemMeta {
|
||||
|
||||
@NotNull
|
||||
private NBTCompound getItemCompound(@NotNull ItemStack itemStack) {
|
||||
NBTCompound compound = NBTUtils.getMetaNBT(itemStack.getMeta());
|
||||
NBTCompound compound = itemStack.getMeta().nbt();
|
||||
compound.setByte("Count", (byte) itemStack.getAmount());
|
||||
compound.setString("id", itemStack.getMaterial().getName());
|
||||
return compound;
|
||||
|
@ -5,11 +5,13 @@ import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
|
||||
import net.kyori.adventure.util.Codec;
|
||||
import net.minestom.server.MinecraftServer;
|
||||
import net.minestom.server.adventure.AdventureSerializer;
|
||||
import net.minestom.server.attribute.Attribute;
|
||||
import net.minestom.server.attribute.AttributeOperation;
|
||||
import net.minestom.server.inventory.Inventory;
|
||||
import net.minestom.server.item.*;
|
||||
import net.minestom.server.item.Enchantment;
|
||||
import net.minestom.server.item.ItemMetaBuilder;
|
||||
import net.minestom.server.item.ItemStack;
|
||||
import net.minestom.server.item.Material;
|
||||
import net.minestom.server.item.attribute.AttributeSlot;
|
||||
import net.minestom.server.item.attribute.ItemAttribute;
|
||||
import net.minestom.server.registry.Registries;
|
||||
@ -86,7 +88,7 @@ public final class NBTUtils {
|
||||
final ItemStack stack = inventory.getItemStack(i);
|
||||
NBTCompound nbt = new NBTCompound();
|
||||
|
||||
NBTCompound tag = getMetaNBT(stack.getMeta());
|
||||
NBTCompound tag = stack.getMeta().nbt();
|
||||
|
||||
nbt.set("tag", tag);
|
||||
nbt.setByte("Slot", (byte) i);
|
||||
@ -290,103 +292,6 @@ public final class NBTUtils {
|
||||
}
|
||||
}
|
||||
|
||||
public static void writeMetaNBT(@NotNull ItemMeta itemMeta, @NotNull NBTCompound itemNBT) {
|
||||
// Unbreakable
|
||||
if (itemMeta.isUnbreakable()) {
|
||||
itemNBT.setInt("Unbreakable", 1);
|
||||
}
|
||||
|
||||
// Damage
|
||||
{
|
||||
final int damage = itemMeta.getDamage();
|
||||
if (damage > 0) {
|
||||
itemNBT.setInt("Damage", damage);
|
||||
}
|
||||
}
|
||||
|
||||
// Start display
|
||||
{
|
||||
final var displayName = itemMeta.getDisplayName();
|
||||
final var lore = itemMeta.getLore();
|
||||
final boolean hasDisplayName = displayName != null;
|
||||
final boolean hasLore = !lore.isEmpty();
|
||||
if (hasDisplayName || hasLore) {
|
||||
NBTCompound displayNBT = new NBTCompound();
|
||||
if (hasDisplayName) {
|
||||
final String name = AdventureSerializer.serialize(displayName);
|
||||
displayNBT.setString("Name", name);
|
||||
}
|
||||
|
||||
if (hasLore) {
|
||||
final NBTList<NBTString> loreNBT = new NBTList<>(NBTTypes.TAG_String);
|
||||
for (Component line : lore) {
|
||||
loreNBT.add(new NBTString(GsonComponentSerializer.gson().serialize(line)));
|
||||
}
|
||||
displayNBT.set("Lore", loreNBT);
|
||||
}
|
||||
|
||||
itemNBT.set("display", displayNBT);
|
||||
}
|
||||
}
|
||||
// End display
|
||||
|
||||
// Start enchantment
|
||||
{
|
||||
final var enchantmentMap = itemMeta.getEnchantmentMap();
|
||||
if (!enchantmentMap.isEmpty()) {
|
||||
NBTUtils.writeEnchant(itemNBT, "Enchantments", enchantmentMap);
|
||||
}
|
||||
}
|
||||
// End enchantment
|
||||
|
||||
// Start attribute
|
||||
{
|
||||
final var attributes = itemMeta.getAttributes();
|
||||
if (!attributes.isEmpty()) {
|
||||
NBTList<NBTCompound> attributesNBT = new NBTList<>(NBTTypes.TAG_Compound);
|
||||
|
||||
for (ItemAttribute itemAttribute : attributes) {
|
||||
final UUID uuid = itemAttribute.getUuid();
|
||||
attributesNBT.add(
|
||||
new NBTCompound()
|
||||
.setIntArray("UUID", Utils.uuidToIntArray(uuid))
|
||||
.setDouble("Amount", itemAttribute.getValue())
|
||||
.setString("Slot", itemAttribute.getSlot().name().toLowerCase())
|
||||
.setString("AttributeName", itemAttribute.getAttribute().getKey())
|
||||
.setInt("Operation", itemAttribute.getOperation().getId())
|
||||
.setString("Name", itemAttribute.getInternalName())
|
||||
);
|
||||
}
|
||||
itemNBT.set("AttributeModifiers", attributesNBT);
|
||||
}
|
||||
}
|
||||
// End attribute
|
||||
|
||||
// Start hide flag
|
||||
{
|
||||
final int hideFlag = itemMeta.getHideFlag();
|
||||
if (hideFlag != 0) {
|
||||
itemNBT.setInt("HideFlags", hideFlag);
|
||||
}
|
||||
}
|
||||
// End hide flag
|
||||
|
||||
// Start custom model data
|
||||
{
|
||||
final int customModelData = itemMeta.getCustomModelData();
|
||||
if (customModelData != 0) {
|
||||
itemNBT.setInt("CustomModelData", customModelData);
|
||||
}
|
||||
}
|
||||
// End custom model data
|
||||
}
|
||||
|
||||
public static @NotNull NBTCompound getMetaNBT(@NotNull ItemMeta itemMeta) {
|
||||
var nbt = new NBTCompound();
|
||||
writeMetaNBT(itemMeta, nbt);
|
||||
return nbt;
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface EnchantmentSetter {
|
||||
void applyEnchantment(Enchantment name, short level);
|
||||
|
@ -243,9 +243,11 @@ public class PlayerInit {
|
||||
.displayName(Component.text("test"))
|
||||
.lore(Component.text("lore"))
|
||||
.build();
|
||||
|
||||
//inventory.setChestplate(item);
|
||||
|
||||
inventory.setChestplate(item.with(itemStackBuilder -> {
|
||||
itemStackBuilder.lore(Collections.emptyList())
|
||||
.displayName(null);
|
||||
itemStackBuilder.lore(Collections.emptyList());
|
||||
}));
|
||||
}
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user