import type { ItemStack } from 'deepslate-1.20.4/core' import { AttributeModifierOperation, Enchantment, Identifier, MobEffectInstance, Potion } from 'deepslate-1.20.4/core' import { NbtList, NbtType } from 'deepslate-1.20.4/nbt' import { useLocale } from '../contexts/Locale.jsx' import { useVersion } from '../contexts/Version.jsx' import { useAsync } from '../hooks/useAsync.js' import { getLanguage, getTranslation } from '../services/Resources.js' import { message } from '../Utils.js' import { TextComponent } from './TextComponent.jsx' interface Props { item: ItemStack, advanced?: boolean, } export function ItemTooltip1204({ item, advanced }: Props) { const { version } = useVersion() const { lang } = useLocale() const { value: language } = useAsync(() => getLanguage(version, lang), [version, lang]) const isPotion = item.is('potion') || item.is('splash_potion') || item.is('lingering_potion') let displayName = item.tag.getCompound('display').getString('Name') let name: string | undefined if (displayName) { try { name = JSON.parse(displayName) } catch (e) { console.warn(`Error parsing display name '${displayName}': ${message(e)}`) displayName = '' } } if (name === undefined) { if (language) { let descriptionId = `${item.id.namespace}.${item.id.path}` if (isPotion) { descriptionId = `${descriptionId}.effect.${Potion.fromNbt(item).name}` } name = getTranslation(language, `item.${descriptionId}`) name ??= getTranslation(language, `block.${descriptionId}`) } name ??= item.id.path .replace(/[_\/]/g, ' ') .split(' ') .map(word => word.charAt(0).toUpperCase() + word.slice(1)) .join(' ') } const lore: any[] = [] item.tag.getCompound('display').getList('Lore', NbtType.String).forEach((line) => { try { lore.push(JSON.parse(line['value'])) } catch (e) { console.warn(`Error parsing lore line '${line}': ${message(e)}`) } }) const durability = item.getItem().durability const enchantments = (item.is('enchanted_book') ? item.tag.getList('StoredEnchantments', NbtType.Compound) : item.tag.getList('Enchantments', NbtType.Compound)) ?? NbtList.create() const effects = isPotion ? Potion.getAllEffects(item) : [] const attributeModifiers = isPotion ? Potion.getAllAttributeModifiers(item) : [] return <> 0 }} /> {shouldShow(item, 'additional') && <> {(!advanced && displayName.length === 0 && item.is('filled_map') && item.tag.hasNumber('map')) && <> } {(item.is('filled_map') && advanced) && <> } {isPotion && effects.length === 0 ? : effects.map(e => { const color = e.effect.category === 'harmful' ? 'red' : 'blue' let component: any = { translate: `effect.${e.effect.id.namespace}.${e.effect.id.path}` } if (e.amplifier > 0) { component = { translate: 'potion.withAmplifier', with: [component, { translate: `potion.potency.${e.amplifier}` }] } } if (e.duration > 20) { component = { translate: 'potion.withDuration', with: [component, MobEffectInstance.formatDuration(e)] } } return })} {attributeModifiers.length > 0 && <> {attributeModifiers.map(([attr, { amount, operation }]) => { const a = operation === AttributeModifierOperation.addition ? amount * 100 : amount if (amount > 0) { return } else if (amount < 0) { return } return null })} } } {shouldShow(item, 'enchantments') && enchantments.map(enchantment => { const id = enchantment.getString('id') const lvl = enchantment.getNumber('lvl') const ench = Enchantment.REGISTRY.get(Identifier.parse(id)) const component: any[] = [{ translate: `enchantment.${id.replace(':', '.')}`, color: ench?.isCurse ? 'red' : 'gray' }] if (lvl !== 1 || ench?.maxLevel !== 1) { component.push(' ', { translate: `enchantment.level.${lvl}`}) } return })} {item.tag.hasCompound('display') && <> {shouldShow(item, 'dye') && item.tag.getCompound('display').hasNumber('color') && (advanced ? : )} {lore.map((component) => )} } {shouldShow(item, 'unbreakable') && item.tag.getBoolean('Unbreakable') && } {(advanced && item.tag.getNumber('Damage') > 0 && durability) && } {advanced && <> {item.tag.size > 0 && } } } const TooltipMasks = { enchantments: 1, modifiers: 2, unbreakable: 4, can_destroy: 8, can_place: 16, additional: 32, dye: 64, upgrades: 128, } function shouldShow(item: ItemStack, mask: keyof typeof TooltipMasks) { const flags = item.tag.getNumber('HideFlags') return (flags & TooltipMasks[mask]) === 0 }