package net.minestom.server.item; import net.kyori.adventure.text.Component; 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.TagReadable; import net.minestom.server.tag.Taggable; import net.minestom.server.utils.binary.Writeable; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.UnknownNullability; import org.jglrxavpok.hephaistos.nbt.NBTCompound; import java.util.*; import java.util.function.Consumer; public sealed interface ItemMeta extends TagReadable, Writeable permits ItemMetaImpl { @Override @UnknownNullability T getTag(@NotNull Tag tag); @Contract(value = "_, -> new", pure = true) @NotNull ItemMeta with(@NotNull Consumer<@NotNull Builder> builderConsumer); @NotNull NBTCompound toNBT(); @NotNull String toSNBT(); @Contract(pure = true) default int getDamage() { return getTag(ItemTags.DAMAGE); } @Contract(pure = true) default boolean isUnbreakable() { return getTag(ItemTags.UNBREAKABLE); } @Contract(pure = true) default int getHideFlag() { return getTag(ItemTags.HIDE_FLAGS); } @Contract(pure = true) default @Nullable Component getDisplayName() { return getTag(ItemTags.NAME); } @Contract(pure = true) default @NotNull List<@NotNull Component> getLore() { return getTag(ItemTags.LORE); } @Contract(pure = true) default @NotNull Map getEnchantmentMap() { return getTag(ItemTags.ENCHANTMENTS); } @Contract(pure = true) default @NotNull List<@NotNull ItemAttribute> getAttributes() { return getTag(ItemTags.ATTRIBUTES); } @Contract(pure = true) default int getCustomModelData() { return getTag(ItemTags.CUSTOM_MODEL_DATA); } @Contract(pure = true) default @NotNull Set<@NotNull Block> getCanDestroy() { return Set.copyOf(getTag(ItemTags.CAN_DESTROY)); } @Contract(pure = true) default @NotNull Set<@NotNull Block> getCanPlaceOn() { return Set.copyOf(getTag(ItemTags.CAN_PLACE_ON)); } sealed interface Builder extends Taggable permits ItemMetaImpl.Builder, ItemMetaView.Builder { @NotNull ItemMeta build(); default @NotNull Builder set(@NotNull Tag tag, @Nullable T value) { setTag(tag, value); return this; } @Contract("_ -> this") default @NotNull Builder damage(int damage) { return set(ItemTags.DAMAGE, damage); } @Contract("_ -> this") default @NotNull Builder unbreakable(boolean unbreakable) { return set(ItemTags.UNBREAKABLE, unbreakable); } @Contract("_ -> this") default @NotNull Builder hideFlag(int hideFlag) { return set(ItemTags.HIDE_FLAGS, hideFlag); } @Contract("_ -> this") default @NotNull Builder hideFlag(@NotNull ItemHideFlag... hideFlags) { int result = 0; for (ItemHideFlag hideFlag : hideFlags) result |= hideFlag.getBitFieldPart(); return hideFlag(result); } @Contract("_ -> this") default @NotNull Builder displayName(@Nullable Component displayName) { return set(ItemTags.NAME, displayName); } @Contract("_ -> this") default @NotNull Builder lore(@NotNull List lore) { return set(ItemTags.LORE, lore.isEmpty() ? null : List.class.cast(lore)); } @Contract("_ -> this") default @NotNull Builder lore(Component... lore) { return lore(Arrays.asList(lore)); } @Contract("_ -> this") default @NotNull Builder enchantments(@NotNull Map enchantments) { return set(ItemTags.ENCHANTMENTS, Map.copyOf(enchantments)); } @Contract("_, _ -> this") default @NotNull Builder enchantment(@NotNull Enchantment enchantment, short level) { var enchantments = new HashMap<>(getTag(ItemTags.ENCHANTMENTS)); enchantments.put(enchantment, level); return enchantments(enchantments); } @Contract("-> this") default @NotNull Builder clearEnchantment() { return enchantments(Map.of()); } @Contract("_ -> this") default @NotNull Builder attributes(@NotNull List<@NotNull ItemAttribute> attributes) { return set(ItemTags.ATTRIBUTES, attributes.isEmpty() ? null : attributes); } @Contract("_ -> this") default @NotNull Builder customModelData(int customModelData) { return set(ItemTags.CUSTOM_MODEL_DATA, customModelData); } @Contract("_ -> this") default @NotNull Builder canPlaceOn(@NotNull Set<@NotNull Block> blocks) { return set(ItemTags.CAN_PLACE_ON, blocks.stream().map(block -> Block.fromNamespaceId(block.name())).toList()); } @Contract("_ -> this") default @NotNull Builder canPlaceOn(@NotNull Block... blocks) { return canPlaceOn(Set.of(blocks)); } @Contract("_ -> this") default @NotNull Builder canDestroy(@NotNull Set<@NotNull Block> blocks) { return set(ItemTags.CAN_DESTROY, blocks.stream().map(block -> Block.fromNamespaceId(block.name())).toList()); } @Contract("_ -> this") default @NotNull Builder canDestroy(@NotNull Block... blocks) { return canDestroy(Set.of(blocks)); } } }