Fix 1.21.5 text component handling in loot table preview

This commit is contained in:
Misode
2025-04-21 18:50:06 +02:00
parent df0c9639c5
commit 05d061de77
3 changed files with 40 additions and 22 deletions
+7 -5
View File
@@ -1,6 +1,7 @@
import type { MobEffectInstance, NbtTag } from 'deepslate'
import { ItemStack, NbtCompound, NbtList, PotionContents } from 'deepslate'
import { Identifier } from 'deepslate/core'
import { useVersion } from '../contexts/Version.jsx'
import type { ResolvedItem } from '../services/ResolvedItem.js'
import { intToDisplayHexRgb, makeDescriptionId, mergeTextComponentStyles } from '../Utils.js'
import { TextComponent } from './TextComponent.jsx'
@@ -11,8 +12,9 @@ interface Props {
resolver: (item: ItemStack) => ResolvedItem,
}
export function ItemTooltip({ item, advanced, resolver }: Props) {
const { version } = useVersion()
return <>
<TextComponent component={item.getStyledHoverName()} />
<TextComponent component={item.getStyledHoverName(version)} />
{!advanced && !item.has('custom_name') && item.is('filled_map') && item.has('map_id') && (
<TextComponent component={{ translate: 'filled_map.id', with: [item.get('map_id', tag => tag.getAsNumber())], color: 'gray' }} />
)}
@@ -25,7 +27,7 @@ export function ItemTooltip({ item, advanced, resolver }: Props) {
<TextComponent component={{ translate: `${layer.isCompound() ? (layer.hasCompound('pattern') ? layer.getString('translation_key') : `block.minecraft.banner.${layer.getString('pattern').replace(/^minecraft:/, '')}`) : ''}.${layer.isCompound() ? layer.getString('color') : ''}`, color: 'gray' }} />
)}
{item.is('crossbow') && item.getChargedProjectile() && (
<TextComponent component={{ translate: 'item.minecraft.crossbow.projectile', extra: [' ', resolver(item.getChargedProjectile()!).getDisplayName()] }}/>
<TextComponent component={{ translate: 'item.minecraft.crossbow.projectile', extra: [' ', resolver(item.getChargedProjectile()!).getDisplayName(version)] }}/>
)}
{item.is('disc_fragment_5') && (
<TextComponent component={{ translate: `${makeDescriptionId('item', item.id)}.desc`, color: 'gray' }} />
@@ -63,7 +65,7 @@ export function ItemTooltip({ item, advanced, resolver }: Props) {
{item.is('decorated_pot') && item.has('pot_decorations') && <>
<TextComponent component={''} />
{item.get('pot_decorations', tag => tag.isList() ? tag.map(e =>
<TextComponent component={mergeTextComponentStyles(resolver(new ItemStack(Identifier.parse(e.getAsString()), 1)).getHoverName(), { color: 'gray' })} />
<TextComponent component={mergeTextComponentStyles(resolver(new ItemStack(Identifier.parse(e.getAsString()), 1)).getHoverName(version), { color: 'gray' })} />
) : undefined)}
</>}
{item.id.path.endsWith('_shulker_box') && <>
@@ -72,7 +74,7 @@ export function ItemTooltip({ item, advanced, resolver }: Props) {
)}
{(item.get('container', tag => tag.isList() ? tag.getItems() : []) ?? []).slice(0, 5).map(e => {
const subItem = resolver(ItemStack.fromNbt(e.isCompound() ? e.getCompound('item') : new NbtCompound()))
return <TextComponent component={{ translate: 'container.shulkerBox.itemCount', with: [subItem.getHoverName(), subItem.count] }} />
return <TextComponent component={{ translate: 'container.shulkerBox.itemCount', with: [subItem.getHoverName(version), subItem.count] }} />
})}
{(item.get('container', tag => tag.isList() ? tag.length : 0) ?? 0) > 5 && (
<TextComponent component={{ translate: 'container.shulkerBox.more', with: [(item.get('container', tag => tag.isList() ? tag.length : 0) ?? 0) - 5], italic: true }} />
@@ -110,7 +112,7 @@ export function ItemTooltip({ item, advanced, resolver }: Props) {
? <TextComponent component={{ translate: 'item.color', with: [intToDisplayHexRgb(item.get('dyed_color', tag => tag.isCompound() ? tag.getNumber('rgb') : tag.getAsNumber()))], color: 'gray' }} />
: <TextComponent component={{ translate: 'item.dyed', color: 'gray' }} />
)}
{item.getLore().map((component) =>
{item.getLore(version).map((component) =>
<TextComponent component={component} base={{ color: 'dark_purple', italic: true }} />
)}
{item.showInTooltip('attribute_modifiers') && (
+13 -6
View File
@@ -5,6 +5,7 @@ import { Identifier, ItemStack, LegacyRandom } from 'deepslate/core'
import { NbtCompound, NbtInt, NbtList, NbtString, NbtTag } from 'deepslate/nbt'
import { ResolvedItem } from '../../services/ResolvedItem.js'
import type { VersionId } from '../../services/Versions.js'
import { checkVersion } from '../../services/Versions.js'
import { clamp, getWeightedRandom, isObject, jsonToNbt } from '../../Utils.js'
export interface SlottedItem {
@@ -470,16 +471,22 @@ const LootFunctions: Record<string, (params: any) => LootFunction> = {
.set('loot_table', new NbtString(Identifier.parse(typeof name === 'string' ? name : '').toString()))
.set('seed', new NbtLong(typeof seed === 'number' ? BigInt(seed) : BigInt(0))))
},
set_lore: ({ lore }) => (item) => {
set_lore: ({ lore }) => (item, ctx) => {
if (!Array.isArray(lore)) return
const lines: string[] = lore.flatMap((line: any) => line !== undefined ? [JSON.stringify(line)] : [])
const lines: NbtTag[] = lore.flatMap((line: any) => line !== undefined ? [
!checkVersion(ctx.version, '1.21.5')
? new NbtString(JSON.stringify(line))
: jsonToNbt(line),
] : [])
// TODO: account for mode
item.set('lore', new NbtList(lines.map(l => new NbtString(l))))
item.set('lore', new NbtList(lines))
},
set_name: ({ name, target }) => (item) => {
set_name: ({ name, target }) => (item, ctx) => {
if (name !== undefined) {
const newName = JSON.stringify(name)
item.set(target ?? 'custom_name', new NbtString(newName))
const newName = !checkVersion(ctx.version, '1.21.5')
? new NbtString(JSON.stringify(name))
: jsonToNbt(name)
item.set(target ?? 'custom_name', newName)
}
},
set_ominous_bottle_amplifier: ({ amplifier }) => (item, ctx) => {
+20 -11
View File
@@ -1,6 +1,8 @@
import type { NbtTag } from 'deepslate'
import { Identifier, ItemStack } from 'deepslate'
import { safeJsonParse } from '../Utils.js'
import type { VersionId } from './Versions.js'
import { checkVersion } from './Versions.js'
export class ResolvedItem extends ItemStack {
@@ -86,10 +88,10 @@ export class ResolvedItem extends ItemStack {
return this.has('enchantment_glint_override') || this.isEnchanted()
}
public getLore() {
public getLore(version: VersionId) {
return this.get('lore', tag => {
return tag.isList() ? tag.map(e => {
return safeJsonParse(e.getAsString()) ?? { text: '(invalid lore line)' }
return ResolvedItem.getTextComponent(e, version)
}) : []
}) ?? []
}
@@ -127,10 +129,10 @@ export class ResolvedItem extends ItemStack {
}
}
public getHoverName() {
const customName = this.get('custom_name', tag => tag.isString() ? tag.getAsString() : undefined)
public getHoverName(version: VersionId) {
const customName = this.get('custom_name', tag => ResolvedItem.getTextComponent(tag, version))
if (customName) {
return safeJsonParse(customName) ?? '(invalid custom name)'
return customName
}
const bookTitle = this.get('written_book_content', tag => tag.isCompound() ? (tag.hasCompound('title') ? tag.getCompound('title').getString('raw') : tag.getString('title')) : undefined)
@@ -138,9 +140,9 @@ export class ResolvedItem extends ItemStack {
return { text: bookTitle }
}
const itemName = this.get('item_name', tag => tag.isString() ? tag.getAsString() : undefined)
const itemName = this.get('item_name', tag => ResolvedItem.getTextComponent(tag, version))
if (itemName) {
return safeJsonParse(itemName) ?? { text: '(invalid item name)' }
return itemName
}
const guess = this.id.path
@@ -151,13 +153,13 @@ export class ResolvedItem extends ItemStack {
return { text: guess }
}
public getStyledHoverName() {
return { text: '', extra: [this.getHoverName()], color: this.getRarityColor(), italic: this.has('custom_name') }
public getStyledHoverName(version: VersionId) {
return { text: '', extra: [this.getHoverName(version)], color: this.getRarityColor(), italic: this.has('custom_name') }
}
public getDisplayName() {
public getDisplayName(version: VersionId) {
// Does not use translation key "chat.square_brackets" due to limitations of TextComponent
return { text: '[', extra: [this.getStyledHoverName(), ']'], color: this.getRarityColor() }
return { text: '[', extra: [this.getStyledHoverName(version), ']'], color: this.getRarityColor() }
}
public getChargedProjectile() {
@@ -168,4 +170,11 @@ export class ResolvedItem extends ItemStack {
return ItemStack.fromNbt(tag.getCompound(0))
})
}
private static getTextComponent(tag: NbtTag, version: VersionId) {
if (!checkVersion(version, '1.21.5')) {
return safeJsonParse(tag.getAsString()) ?? { text: '(invalid text component)' }
}
return tag.toSimplifiedJson()
}
}