diff --git a/src/app/components/previews/LootTable.ts b/src/app/components/previews/LootTable.ts index 0dc4da1e..4f5846ea 100644 --- a/src/app/components/previews/LootTable.ts +++ b/src/app/components/previews/LootTable.ts @@ -27,6 +27,9 @@ interface LootOptions { daytime: number, weather: string, stackMixer: StackMixer, + getItemTag(id: string): string[], + getLootTable(id: string): any, + getPredicate(id: string): any, getBaseComponents(id: string): Map, } @@ -35,9 +38,6 @@ interface LootContext extends LootOptions { luck: number weather: string, dayTime: number, - getItemTag(id: string): string[], - getLootTable(id: string): any, - getPredicate(id: string): any, } export function generateLootTable(lootTable: any, options: LootOptions) { @@ -133,10 +133,6 @@ function createLootContext(options: LootOptions): LootContext { luck: options.luck, weather: options.weather, dayTime: options.daytime, - // TODO - getItemTag: () => [], - getLootTable: () => ({ pools: [] }), - getPredicate: () => [], } } @@ -207,7 +203,7 @@ function expandEntry(entry: any, ctx: LootContext, consumer: (entry: any) => voi return true case 'tag': if (entry.expand) { - ctx.getItemTag(entry.tag ?? '').forEach(tagEntry => { + ctx.getItemTag(entry.name ?? '').forEach(tagEntry => { consumer({ type: 'item', name: tagEntry }) }) } else { @@ -243,7 +239,10 @@ function createItem(entry: any, consumer: ItemConsumer, ctx: LootContext) { }) break case 'loot_table': - generateTable(ctx.getLootTable(entry.name), entryConsumer, ctx) + const lootTable = typeof entry.value === 'string' ? ctx.getLootTable(entry.value) : entry.value + if (lootTable !== undefined) { + generateTable(lootTable, entryConsumer, ctx) + } break case 'dynamic': // not relevant for this simulation @@ -365,7 +364,7 @@ const LootFunctions: Record LootFunction> = { }, set_count: ({ count, add }) => (item, ctx) => { const oldCount = add ? (item.count) : 0 - item.count = clamp(oldCount + computeInt(count, ctx), 0, 64) + item.count = oldCount + computeInt(count, ctx) }, set_custom_data: ({ tag }) => (item) => { try { @@ -638,7 +637,6 @@ function testItemPredicate(predicate: any, item: ResolvedItem, ctx: LootContext) } if (predicate.count !== undefined) { const { min, max } = prepareIntRange(predicate.count, ctx) - console.log(min, max, item.count) if (min > item.count || item.count > max) { return false } diff --git a/src/app/components/previews/LootTable1204.ts b/src/app/components/previews/LootTable1204.ts index 8dd70324..27aa7501 100644 --- a/src/app/components/previews/LootTable1204.ts +++ b/src/app/components/previews/LootTable1204.ts @@ -25,6 +25,9 @@ interface LootOptions { daytime: number, weather: string, stackMixer: StackMixer, + getItemTag(id: string): string[], + getLootTable(id: string): any, + getPredicate(id: string): any, } interface LootContext extends LootOptions { @@ -32,9 +35,6 @@ interface LootContext extends LootOptions { luck: number weather: string, dayTime: number, - getItemTag(id: string): string[], - getLootTable(id: string): any, - getPredicate(id: string): any, } export function generateLootTable(lootTable: any, options: LootOptions) { @@ -130,9 +130,6 @@ function createLootContext(options: LootOptions): LootContext { luck: options.luck, weather: options.weather, dayTime: options.daytime, - getItemTag: () => [], - getLootTable: () => ({ pools: [] }), - getPredicate: () => [], } } @@ -203,7 +200,7 @@ function expandEntry(entry: any, ctx: LootContext, consumer: (entry: any) => voi return true case 'tag': if (entry.expand) { - ctx.getItemTag(entry.tag ?? '').forEach(tagEntry => { + ctx.getItemTag(entry.name ?? '').forEach(tagEntry => { consumer({ type: 'item', name: tagEntry }) }) } else { @@ -241,7 +238,10 @@ function createItem(entry: any, consumer: ItemConsumer, ctx: LootContext) { }) break case 'loot_table': - generateTable(ctx.getLootTable(entry.name), entryConsumer, ctx) + const lootTable = ctx.getLootTable(entry.name) + if (lootTable !== undefined) { + generateTable(lootTable, entryConsumer, ctx) + } break case 'dynamic': // not relevant for this simulation @@ -659,7 +659,6 @@ const AlwaysHasGlint = new Set([ ]) export function itemHasGlint(item: ItemStack) { - console.log(item) if (AlwaysHasGlint.has(item.id.toString())) { return true } diff --git a/src/app/components/previews/LootTablePreview.tsx b/src/app/components/previews/LootTablePreview.tsx index b8ab580b..ae23a42c 100644 --- a/src/app/components/previews/LootTablePreview.tsx +++ b/src/app/components/previews/LootTablePreview.tsx @@ -2,7 +2,7 @@ import { DataModel } from '@mcschema/core' import { useMemo, useRef, useState } from 'preact/hooks' import { useLocale, useVersion } from '../../contexts/index.js' import { useAsync } from '../../hooks/useAsync.js' -import { checkVersion, fetchItemComponents } from '../../services/index.js' +import { checkVersion, fetchAllPresets, fetchItemComponents } from '../../services/index.js' import { clamp, jsonToNbt, randomSeed } from '../../Utils.js' import { Btn, BtnMenu, NumberInput } from '../index.js' import { ItemDisplay } from '../ItemDisplay.jsx' @@ -14,7 +14,7 @@ import { generateLootTable as generateLootTable1204 } from './LootTable1204.js' export const LootTablePreview = ({ data }: PreviewProps) => { const { locale } = useLocale() const { version } = useVersion() - const use1204 = checkVersion(version, undefined, '1.20.4') + const use1204 = !checkVersion(version, '1.20.5') const [seed, setSeed] = useState(randomSeed()) const [luck, setLuck] = useState(0) @@ -24,22 +24,39 @@ export const LootTablePreview = ({ data }: PreviewProps) => { const [advancedTooltips, setAdvancedTooltips] = useState(true) const overlay = useRef(null) - const { value: itemComponents } = useAsync(() => { - return use1204 ? Promise.resolve(undefined) : fetchItemComponents(version) - }, [use1204, version]) + const { value: dependencies, loading } = useAsync(() => { + return Promise.all([ + fetchAllPresets(version, 'tag/item'), + fetchAllPresets(version, 'loot_table'), + use1204 ? Promise.resolve(undefined) : fetchItemComponents(version), + ]) + }, [version]) const table = DataModel.unwrapLists(data) const state = JSON.stringify(table) const items = useMemo(() => { - if (use1204) { - return generateLootTable1204(table, { version, seed, luck, daytime, weather, stackMixer: mixItems ? 'container' : 'default' }) - } else { - if (itemComponents === undefined) { - return [] - } - return generateLootTable(table, { version, seed, luck, daytime, weather, stackMixer: mixItems ? 'container' : 'default', getBaseComponents: (id) => new Map([...(itemComponents.get(id) ?? new Map()).entries()].map(([k, v]) => [k, jsonToNbt(v)])) }) + if (dependencies === undefined || loading) { + return [] } - }, [version, seed, luck, daytime, weather, mixItems, state, itemComponents]) + const [itemTags, lootTables, itemComponents] = dependencies + if (use1204) { + return generateLootTable1204(table, { + version, seed, luck, daytime, weather, + stackMixer: mixItems ? 'container' : 'default', + getItemTag: (id) => (itemTags.get(id.replace(/^minecraft:/, '')) as any)?.values ?? [], + getLootTable: (id) => lootTables.get(id.replace(/^minecraft:/, '')), + getPredicate: () => undefined, + }) + } + return generateLootTable(table, { + version, seed, luck, daytime, weather, + stackMixer: mixItems ? 'container' : 'default', + getItemTag: (id) => (itemTags.get(id.replace(/^minecraft:/, '')) as any)?.values ?? [], + getLootTable: (id) => lootTables.get(id.replace(/^minecraft:/, '')), + getPredicate: () => undefined, + getBaseComponents: (id) => new Map([...(itemComponents?.get(id) ?? new Map()).entries()].map(([k, v]) => [k, jsonToNbt(v)])), + }) + }, [version, seed, luck, daytime, weather, mixItems, state, dependencies, loading]) return <>