mirror of
https://github.com/Minestom/Minestom.git
synced 2025-03-13 07:09:51 +01:00
Use original NBT when possible
This commit is contained in:
parent
2b0c525ca2
commit
8d8a22f209
@ -47,8 +47,6 @@ public class ArgumentItemStack extends Argument<ItemStack> {
|
||||
final String materialName = input.substring(0, nbtIndex);
|
||||
final Material material = Registries.getMaterial(materialName);
|
||||
|
||||
ItemStack itemStack = ItemStack.of(material);
|
||||
|
||||
final String sNBT = input.substring(nbtIndex).replace("\\\"", "\"");
|
||||
|
||||
NBTCompound compound;
|
||||
@ -58,9 +56,7 @@ public class ArgumentItemStack extends Argument<ItemStack> {
|
||||
throw new ArgumentSyntaxException("Item NBT is invalid", input, INVALID_NBT);
|
||||
}
|
||||
|
||||
NBTUtils.loadDataIntoItem(itemStack, compound);
|
||||
|
||||
return itemStack;
|
||||
return NBTUtils.loadItem(material, 1, compound);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -8,6 +8,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.UnaryOperator;
|
||||
|
||||
public class ItemBuilder {
|
||||
|
||||
@ -38,8 +39,14 @@ public class ItemBuilder {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Contract(value = "_ -> this")
|
||||
public @NotNull ItemBuilder meta(@NotNull UnaryOperator<@NotNull ItemMetaBuilder> itemMetaConsumer) {
|
||||
itemMetaConsumer.apply(metaBuilder);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Contract(value = "_, _ -> this")
|
||||
public <T extends ItemMetaBuilder, U extends ItemMetaBuilder.Provider<T>> @NotNull ItemBuilder meta(Class<U> metaType, Consumer<T> itemMetaConsumer) {
|
||||
public <T extends ItemMetaBuilder, U extends ItemMetaBuilder.Provider<T>> @NotNull ItemBuilder meta(@NotNull Class<U> metaType, @NotNull Consumer<@NotNull T> itemMetaConsumer) {
|
||||
itemMetaConsumer.accept((T) metaBuilder);
|
||||
return this;
|
||||
}
|
||||
|
@ -30,6 +30,7 @@ public class ItemMeta implements Cloneable {
|
||||
|
||||
private final int customModelData;
|
||||
|
||||
private final @Nullable NBTCompound originalNbt;
|
||||
private SoftReference<NBTCompound> cache;
|
||||
|
||||
protected ItemMeta(@NotNull ItemMetaBuilder metaBuilder) {
|
||||
@ -42,6 +43,9 @@ public class ItemMeta implements Cloneable {
|
||||
this.enchantmentMap = Collections.unmodifiableMap(metaBuilder.enchantmentMap);
|
||||
this.attributes = new ArrayList<>();
|
||||
this.customModelData = 0;
|
||||
|
||||
// Can be null
|
||||
this.originalNbt = metaBuilder.originalNBT;
|
||||
}
|
||||
|
||||
@Contract(value = "_, -> new", pure = true)
|
||||
@ -69,28 +73,38 @@ public class ItemMeta implements Cloneable {
|
||||
}
|
||||
|
||||
@Contract(pure = true)
|
||||
public @Nullable List<@NotNull Component> getLore() {
|
||||
public @NotNull List<@NotNull Component> getLore() {
|
||||
return lore;
|
||||
}
|
||||
|
||||
public Map<Enchantment, Short> getEnchantmentMap() {
|
||||
@Contract(pure = true)
|
||||
public @NotNull Map<Enchantment, Short> getEnchantmentMap() {
|
||||
return enchantmentMap;
|
||||
}
|
||||
|
||||
public List<ItemAttribute> getAttributes() {
|
||||
@Contract(pure = true)
|
||||
public @NotNull List<ItemAttribute> getAttributes() {
|
||||
return attributes;
|
||||
}
|
||||
|
||||
@Contract(pure = true)
|
||||
public int getCustomModelData() {
|
||||
return customModelData;
|
||||
}
|
||||
|
||||
public @NotNull NBTCompound toNBT() {
|
||||
if (originalNbt != null) {
|
||||
// Return the nbt this meta has been created with
|
||||
return originalNbt;
|
||||
}
|
||||
|
||||
var nbt = cache != null ? cache.get() : null;
|
||||
if (nbt == null) {
|
||||
nbt = NBTUtils.metaToNBT(this);
|
||||
cache = new SoftReference<>(nbt);
|
||||
this.builder.write(nbt);
|
||||
this.cache = new SoftReference<>(nbt);
|
||||
}
|
||||
|
||||
return nbt;
|
||||
}
|
||||
|
||||
@ -108,6 +122,7 @@ public class ItemMeta implements Cloneable {
|
||||
return toNBT().hashCode();
|
||||
}
|
||||
|
||||
@Contract(value = "-> new", pure = true)
|
||||
protected @NotNull ItemMetaBuilder builder() {
|
||||
return builder.clone();
|
||||
}
|
||||
|
@ -1,20 +1,45 @@
|
||||
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.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jglrxavpok.hephaistos.nbt.NBTCompound;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public abstract class ItemMetaBuilder implements Cloneable {
|
||||
|
||||
protected int damage;
|
||||
protected boolean unbreakable;
|
||||
protected int hideFlag;
|
||||
protected Component displayName;
|
||||
protected List<Component> lore = new ArrayList<>();
|
||||
protected Map<Enchantment, Short> enchantmentMap = new HashMap<>();
|
||||
protected List<ItemAttribute> attributes = new ArrayList<>();
|
||||
protected int customModelData;
|
||||
|
||||
protected NBTCompound originalNBT;
|
||||
|
||||
protected ItemMetaBuilder() {
|
||||
}
|
||||
|
||||
public @NotNull ItemMetaBuilder damage(int damage) {
|
||||
this.damage = damage;
|
||||
return this;
|
||||
}
|
||||
|
||||
public @NotNull ItemMetaBuilder unbreakable(boolean unbreakable) {
|
||||
this.unbreakable = unbreakable;
|
||||
return this;
|
||||
}
|
||||
|
||||
public @NotNull ItemMetaBuilder hideFlag(int hideFlag) {
|
||||
this.hideFlag = hideFlag;
|
||||
return this;
|
||||
}
|
||||
|
||||
public @NotNull ItemMetaBuilder displayName(@Nullable Component displayName) {
|
||||
this.displayName = displayName;
|
||||
return this;
|
||||
@ -45,10 +70,30 @@ public abstract class ItemMetaBuilder implements Cloneable {
|
||||
return this;
|
||||
}
|
||||
|
||||
public @NotNull ItemMetaBuilder attributes(List<ItemAttribute> attributes) {
|
||||
this.attributes = attributes;
|
||||
return this;
|
||||
}
|
||||
|
||||
public @NotNull ItemMetaBuilder customModelData(int customModelData) {
|
||||
this.customModelData = customModelData;
|
||||
return this;
|
||||
}
|
||||
|
||||
public abstract @NotNull ItemMeta build();
|
||||
|
||||
public abstract void read(@NotNull NBTCompound nbtCompound);
|
||||
|
||||
public abstract void write(@NotNull NBTCompound nbtCompound);
|
||||
|
||||
protected abstract void deepClone(@NotNull ItemMetaBuilder metaBuilder);
|
||||
|
||||
public static @NotNull ItemMetaBuilder fromNBT(@NotNull ItemMetaBuilder metaBuilder, @NotNull NBTCompound nbtCompound) {
|
||||
NBTUtils.loadDataIntoMeta(metaBuilder, nbtCompound);
|
||||
metaBuilder.originalNBT = nbtCompound;
|
||||
return metaBuilder;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ItemMetaBuilder clone() {
|
||||
try {
|
||||
|
@ -81,6 +81,11 @@ public class ItemStack {
|
||||
return builder().meta(metaType, metaConsumer).build();
|
||||
}
|
||||
|
||||
@Contract(value = "_ -> new", pure = true)
|
||||
public @NotNull ItemStack withMeta(@NotNull UnaryOperator<@NotNull ItemMetaBuilder> metaOperator) {
|
||||
return builder().meta(metaOperator).build();
|
||||
}
|
||||
|
||||
@Contract(pure = true)
|
||||
public @Nullable Component getDisplayName() {
|
||||
return meta.getDisplayName();
|
||||
|
@ -7,6 +7,7 @@ import net.minestom.server.item.ItemMetaBuilder;
|
||||
import net.minestom.server.utils.Position;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jglrxavpok.hephaistos.nbt.NBTCompound;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@ -101,6 +102,40 @@ public class CompassMeta extends ItemMeta implements ItemMetaBuilder.Provider<Co
|
||||
return new CompassMeta(this, lodestoneTracked, lodestoneDimension, lodestonePosition);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(@NotNull NBTCompound nbtCompound) {
|
||||
if (nbtCompound.containsKey("LodestoneTracked")) {
|
||||
this.lodestoneTracked = nbtCompound.getByte("LodestoneTracked") == 1;
|
||||
}
|
||||
if (nbtCompound.containsKey("LodestoneDimension")) {
|
||||
this.lodestoneDimension = nbtCompound.getString("LodestoneDimension");
|
||||
}
|
||||
if (nbtCompound.containsKey("LodestonePos")) {
|
||||
final NBTCompound posCompound = nbtCompound.getCompound("LodestonePos");
|
||||
final int x = posCompound.getInt("X");
|
||||
final int y = posCompound.getInt("Y");
|
||||
final int z = posCompound.getInt("Z");
|
||||
|
||||
this.lodestonePosition = new Position(x, y, z);
|
||||
}
|
||||
}
|
||||
|
||||
@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 void deepClone(@NotNull ItemMetaBuilder metaBuilder) {
|
||||
var compassBuilder = (CompassMeta.Builder) metaBuilder;
|
||||
|
@ -136,8 +136,7 @@ public class CrossbowMeta extends ItemMeta {
|
||||
|
||||
final NBTCompound tagsCompound = projectileCompound.getCompound("tag");
|
||||
|
||||
ItemStack itemStack = ItemStack.of(material, count);
|
||||
NBTUtils.loadDataIntoItem(itemStack, tagsCompound);
|
||||
ItemStack itemStack = NBTUtils.loadItem(material, count, tagsCompound);
|
||||
|
||||
index++;
|
||||
|
||||
|
@ -6,11 +6,11 @@ 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.Enchantment;
|
||||
import net.minestom.server.item.ItemMeta;
|
||||
import net.minestom.server.item.ItemStack;
|
||||
import net.minestom.server.item.Material;
|
||||
import net.minestom.server.item.*;
|
||||
import net.minestom.server.item.attribute.AttributeSlot;
|
||||
import net.minestom.server.item.attribute.ItemAttribute;
|
||||
import net.minestom.server.registry.Registries;
|
||||
import net.minestom.server.utils.binary.BinaryReader;
|
||||
@ -24,6 +24,8 @@ import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.StringReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
@ -65,15 +67,17 @@ public final class NBTUtils {
|
||||
public static void loadAllItems(@NotNull NBTList<NBTCompound> items, @NotNull Inventory destination) {
|
||||
destination.clear();
|
||||
for (NBTCompound tag : items) {
|
||||
Material item = Registries.getMaterial(tag.getString("id"));
|
||||
if (item == Material.AIR) {
|
||||
item = Material.STONE;
|
||||
Material material = Registries.getMaterial(tag.getString("id"));
|
||||
if (material == Material.AIR) {
|
||||
material = Material.STONE;
|
||||
}
|
||||
ItemStack stack = ItemStack.of(item, tag.getByte("Count"));
|
||||
byte count = tag.getByte("Count");
|
||||
NBTCompound nbtCompound = null;
|
||||
if (tag.containsKey("tag")) {
|
||||
loadDataIntoItem(stack, tag.getCompound("tag"));
|
||||
nbtCompound = tag.getCompound("tag");
|
||||
}
|
||||
destination.setItemStack(tag.getByte("Slot"), stack);
|
||||
ItemStack itemStack = loadItem(material, count, nbtCompound);
|
||||
destination.setItemStack(tag.getByte("Slot"), itemStack);
|
||||
}
|
||||
}
|
||||
|
||||
@ -124,32 +128,44 @@ public final class NBTUtils {
|
||||
|
||||
final Material material = Material.fromId((short) id);
|
||||
final byte count = reader.readByte();
|
||||
ItemStack item = ItemStack.of(material, count);
|
||||
NBTCompound nbtCompound = null;
|
||||
|
||||
try {
|
||||
final NBT itemNBT = reader.readTag();
|
||||
if (itemNBT instanceof NBTCompound) { // can also be a TAG_End if no data
|
||||
NBTCompound nbt = (NBTCompound) itemNBT;
|
||||
loadDataIntoItem(item, nbt);
|
||||
nbtCompound = (NBTCompound) itemNBT;
|
||||
}
|
||||
} catch (IOException | NBTException e) {
|
||||
MinecraftServer.getExceptionManager().handleException(e);
|
||||
}
|
||||
|
||||
return item;
|
||||
return loadItem(material, count, nbtCompound);
|
||||
}
|
||||
|
||||
public static @NotNull ItemStack loadItem(@NotNull Material material, int count, NBTCompound nbtCompound) {
|
||||
return ItemStack.builder(material)
|
||||
.amount(count)
|
||||
.meta(metaBuilder -> {
|
||||
if (nbtCompound != null) {
|
||||
return ItemMetaBuilder.fromNBT(metaBuilder, nbtCompound);
|
||||
} else {
|
||||
return metaBuilder;
|
||||
}
|
||||
})
|
||||
.build();
|
||||
}
|
||||
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
public static void loadDataIntoItem(@NotNull ItemStack item, @NotNull NBTCompound nbt) {
|
||||
/*if (nbt.containsKey("Damage")) item.setDamage(nbt.getInt("Damage"));
|
||||
if (nbt.containsKey("Unbreakable")) item.setUnbreakable(nbt.getAsByte("Unbreakable") == 1);
|
||||
if (nbt.containsKey("HideFlags")) item.setHideFlag(nbt.getInt("HideFlags"));
|
||||
public static void loadDataIntoMeta(@NotNull ItemMetaBuilder metaBuilder, @NotNull NBTCompound nbt) {
|
||||
if (nbt.containsKey("Damage")) metaBuilder.damage(nbt.getInt("Damage"));
|
||||
if (nbt.containsKey("Unbreakable")) metaBuilder.unbreakable(nbt.getAsByte("Unbreakable") == 1);
|
||||
if (nbt.containsKey("HideFlags")) metaBuilder.hideFlag(nbt.getInt("HideFlags"));
|
||||
if (nbt.containsKey("display")) {
|
||||
final NBTCompound display = nbt.getCompound("display");
|
||||
if (display.containsKey("Name")) {
|
||||
final String rawName = display.getString("Name");
|
||||
final Component displayName = GsonComponentSerializer.gson().deserialize(rawName);
|
||||
item.setDisplayName(displayName);
|
||||
metaBuilder.displayName(displayName);
|
||||
}
|
||||
if (display.containsKey("Lore")) {
|
||||
NBTList<NBTString> loreList = display.getList("Lore");
|
||||
@ -157,19 +173,20 @@ public final class NBTUtils {
|
||||
for (NBTString s : loreList) {
|
||||
lore.add(GsonComponentSerializer.gson().deserialize(s.getValue()));
|
||||
}
|
||||
item.setLore(lore);
|
||||
metaBuilder.lore(lore);
|
||||
}
|
||||
}
|
||||
|
||||
// Enchantments
|
||||
if (nbt.containsKey("Enchantments")) {
|
||||
loadEnchantments(nbt.getList("Enchantments"), item::setEnchantment);
|
||||
loadEnchantments(nbt.getList("Enchantments"), metaBuilder::enchantment);
|
||||
}
|
||||
|
||||
// Attributes
|
||||
if (nbt.containsKey("AttributeModifiers")) {
|
||||
NBTList<NBTCompound> attributes = nbt.getList("AttributeModifiers");
|
||||
for (NBTCompound attributeNBT : attributes) {
|
||||
List<ItemAttribute> attributes = new ArrayList<>();
|
||||
NBTList<NBTCompound> nbtAttributes = nbt.getList("AttributeModifiers");
|
||||
for (NBTCompound attributeNBT : nbtAttributes) {
|
||||
final UUID uuid;
|
||||
{
|
||||
final int[] uuidArray = attributeNBT.getIntArray("UUID");
|
||||
@ -203,44 +220,37 @@ public final class NBTUtils {
|
||||
// Add attribute
|
||||
final ItemAttribute itemAttribute =
|
||||
new ItemAttribute(uuid, name, attribute, attributeOperation, value, attributeSlot);
|
||||
item.addAttribute(itemAttribute);
|
||||
}
|
||||
}
|
||||
|
||||
// Hide flags
|
||||
{
|
||||
if (nbt.containsKey("HideFlags")) {
|
||||
item.setHideFlag(nbt.getInt("HideFlags"));
|
||||
attributes.add(itemAttribute);
|
||||
}
|
||||
metaBuilder.attributes(attributes);
|
||||
}
|
||||
|
||||
// Custom model data
|
||||
{
|
||||
if (nbt.containsKey("CustomModelData")) {
|
||||
item.setCustomModelData(nbt.getInt("CustomModelData"));
|
||||
metaBuilder.customModelData(nbt.getInt("CustomModelData"));
|
||||
}
|
||||
}
|
||||
|
||||
// Meta specific field
|
||||
final ItemMeta itemMeta = item.getItemMeta();
|
||||
if (itemMeta != null) {
|
||||
itemMeta.read(nbt);
|
||||
}
|
||||
// Meta specific fields
|
||||
metaBuilder.read(nbt);
|
||||
|
||||
// Ownership
|
||||
{
|
||||
if (nbt.containsKey(ItemStack.OWNERSHIP_DATA_KEY)) {
|
||||
// FIXME: custom data
|
||||
/*if (nbt.containsKey(ItemStack.OWNERSHIP_DATA_KEY)) {
|
||||
final String identifierString = nbt.getString(ItemStack.OWNERSHIP_DATA_KEY);
|
||||
final UUID identifier = UUID.fromString(identifierString);
|
||||
final Data data = ItemStack.DATA_OWNERSHIP.getOwnObject(identifier);
|
||||
if (data != null) {
|
||||
item.setData(data);
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
//CanPlaceOn
|
||||
{
|
||||
// FIXME: PlaceOn/CanDestroy
|
||||
/*{
|
||||
if (nbt.containsKey("CanPlaceOn")) {
|
||||
NBTList<NBTString> canPlaceOn = nbt.getList("CanPlaceOn");
|
||||
canPlaceOn.forEach(x -> item.getCanPlaceOn().add(x.getValue()));
|
||||
@ -268,7 +278,7 @@ public final class NBTUtils {
|
||||
}
|
||||
}
|
||||
|
||||
public static void writeItemStack(BinaryWriter packet, @NotNull ItemStack itemStack) {
|
||||
public static void writeItemStack(@NotNull BinaryWriter packet, @NotNull ItemStack itemStack) {
|
||||
if (itemStack.isAir()) {
|
||||
packet.writeBoolean(false);
|
||||
} else {
|
||||
|
Loading…
Reference in New Issue
Block a user