mirror of https://github.com/Minestom/Minestom.git
276 lines
9.6 KiB
Java
276 lines
9.6 KiB
Java
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.instance.block.Block;
|
|
import net.minestom.server.item.attribute.ItemAttribute;
|
|
import net.minestom.server.tag.Tag;
|
|
import net.minestom.server.tag.TagWritable;
|
|
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.*;
|
|
|
|
import java.util.*;
|
|
import java.util.function.Consumer;
|
|
import java.util.function.Supplier;
|
|
|
|
public abstract class ItemMetaBuilder implements TagWritable {
|
|
|
|
protected NBTCompound nbt = new NBTCompound();
|
|
|
|
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 Set<Block> canDestroy = new HashSet<>();
|
|
protected Set<Block> canPlaceOn = new HashSet<>();
|
|
|
|
@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;
|
|
}
|
|
|
|
@Contract("_ -> this")
|
|
public @NotNull ItemMetaBuilder hideFlag(@NotNull ItemHideFlag... hideFlags) {
|
|
int result = 0;
|
|
for (ItemHideFlag hideFlag : hideFlags) {
|
|
result |= hideFlag.getBitFieldPart();
|
|
}
|
|
return hideFlag(result);
|
|
}
|
|
|
|
@Contract("_ -> this")
|
|
public @NotNull ItemMetaBuilder displayName(@Nullable Component displayName) {
|
|
this.displayName = displayName;
|
|
handleCompound("display", nbtCompound -> {
|
|
if (displayName != null) {
|
|
final String name = GsonComponentSerializer.gson().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;
|
|
}
|
|
|
|
@Contract("_ -> this")
|
|
public @NotNull ItemMetaBuilder lore(Component... lore) {
|
|
lore(Arrays.asList(lore));
|
|
return this;
|
|
}
|
|
|
|
@Contract("_ -> this")
|
|
public @NotNull ItemMetaBuilder enchantments(@NotNull Map<Enchantment, Short> enchantments) {
|
|
this.enchantmentMap = enchantments;
|
|
handleMap(enchantmentMap, "Enchantments", nbt, () -> {
|
|
NBTUtils.writeEnchant(nbt, "Enchantments", enchantmentMap);
|
|
return nbt.get("Enchantments");
|
|
});
|
|
return this;
|
|
}
|
|
|
|
@Contract("_, _ -> this")
|
|
public @NotNull ItemMetaBuilder enchantment(@NotNull Enchantment enchantment, short level) {
|
|
this.enchantmentMap.put(enchantment, level);
|
|
enchantments(enchantmentMap);
|
|
return this;
|
|
}
|
|
|
|
@Contract("-> this")
|
|
public @NotNull ItemMetaBuilder clearEnchantment() {
|
|
this.enchantmentMap.clear();
|
|
enchantments(enchantmentMap);
|
|
return this;
|
|
}
|
|
|
|
@Contract("_ -> this")
|
|
public @NotNull ItemMetaBuilder attributes(@NotNull List<@NotNull ItemAttribute> attributes) {
|
|
this.attributes = attributes;
|
|
|
|
handleCollection(attributes, "AttributeModifiers", nbt, () -> {
|
|
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())
|
|
);
|
|
}
|
|
return attributesNBT;
|
|
});
|
|
|
|
return this;
|
|
}
|
|
|
|
@Contract("_ -> this")
|
|
public @NotNull ItemMetaBuilder customModelData(int customModelData) {
|
|
this.customModelData = customModelData;
|
|
this.nbt.setInt("CustomModelData", customModelData);
|
|
return this;
|
|
}
|
|
|
|
@Contract("_ -> this")
|
|
public @NotNull ItemMetaBuilder canPlaceOn(@NotNull Set<@NotNull Block> blocks) {
|
|
this.canPlaceOn = blocks;
|
|
handleCollection(canPlaceOn, "CanPlaceOn", nbt, () -> {
|
|
NBTList<NBTString> list = new NBTList<>(NBTTypes.TAG_String);
|
|
canPlaceOn.forEach(block -> list.add(new NBTString(block.getName())));
|
|
nbt.set("CanPlaceOn", list);
|
|
return list;
|
|
});
|
|
return this;
|
|
}
|
|
|
|
@Contract("_ -> this")
|
|
public @NotNull ItemMetaBuilder canPlaceOn(@NotNull Block... blocks) {
|
|
return canPlaceOn(Set.of(blocks));
|
|
}
|
|
|
|
@Contract("_ -> this")
|
|
public @NotNull ItemMetaBuilder canDestroy(@NotNull Set<@NotNull Block> blocks) {
|
|
this.canDestroy = blocks;
|
|
handleCollection(canDestroy, "CanDestroy", nbt, () -> {
|
|
NBTList<NBTString> list = new NBTList<>(NBTTypes.TAG_String);
|
|
canDestroy.forEach(block -> list.add(new NBTString(block.getName())));
|
|
nbt.set("CanDestroy", list);
|
|
return list;
|
|
});
|
|
return this;
|
|
}
|
|
|
|
@Contract("_ -> this")
|
|
public @NotNull ItemMetaBuilder canDestroy(@NotNull Block... blocks) {
|
|
return canDestroy(Set.of(blocks));
|
|
}
|
|
|
|
@Override
|
|
public <T> void setTag(@NotNull Tag<T> tag, @Nullable T value) {
|
|
tag.write(nbt, value);
|
|
}
|
|
|
|
public <T> @NotNull ItemMetaBuilder set(@NotNull Tag<T> tag, @Nullable T value) {
|
|
setTag(tag, value);
|
|
return this;
|
|
}
|
|
|
|
@Contract("-> new")
|
|
public abstract @NotNull ItemMeta build();
|
|
|
|
public abstract void read(@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);
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
protected void handleNullable(@Nullable Object value,
|
|
@NotNull String key,
|
|
@NotNull NBTCompound nbtCompound,
|
|
@NotNull Supplier<@NotNull NBT> supplier) {
|
|
if (value != null) {
|
|
nbtCompound.set(key, supplier.get());
|
|
} else {
|
|
nbtCompound.removeTag(key);
|
|
}
|
|
}
|
|
|
|
protected void handleCollection(@NotNull Collection<?> objects,
|
|
@NotNull String key,
|
|
@NotNull NBTCompound nbtCompound,
|
|
@NotNull Supplier<@NotNull NBT> supplier) {
|
|
if (!objects.isEmpty()) {
|
|
nbtCompound.set(key, supplier.get());
|
|
} else {
|
|
nbtCompound.removeTag(key);
|
|
}
|
|
}
|
|
|
|
protected void handleMap(@NotNull Map<?, ?> objects,
|
|
@NotNull String key,
|
|
@NotNull NBTCompound nbtCompound,
|
|
@NotNull Supplier<@NotNull NBT> supplier) {
|
|
if (!objects.isEmpty()) {
|
|
nbtCompound.set(key, supplier.get());
|
|
} else {
|
|
nbtCompound.removeTag(key);
|
|
}
|
|
}
|
|
|
|
@Contract(value = "_, _ -> new", pure = true)
|
|
public static @NotNull ItemMetaBuilder fromNBT(@NotNull ItemMetaBuilder src, @NotNull NBTCompound nbtCompound) {
|
|
ItemMetaBuilder dest = src.getSupplier().get();
|
|
dest.nbt = nbtCompound.deepClone();
|
|
NBTUtils.loadDataIntoMeta(dest, dest.nbt);
|
|
return dest;
|
|
}
|
|
|
|
public interface Provider<T extends ItemMetaBuilder> {
|
|
}
|
|
|
|
}
|