Add item modifier as convert format

This commit is contained in:
Misode
2024-11-29 06:37:39 +01:00
parent a948715523
commit 7501b392be
2 changed files with 73 additions and 16 deletions
+72 -16
View File
@@ -11,7 +11,7 @@ import type { VersionId } from '../services/Versions.js'
import { checkVersion } from '../services/Versions.js'
import { jsonToNbt } from '../Utils.js'
const FORMATS = ['give-command', 'loot-table'] as const
const FORMATS = ['give-command', 'loot-table', 'item-modifier'] as const
type Format = typeof FORMATS[number]
interface Props {
@@ -149,6 +149,11 @@ const CONVERSIONS: Record<Format, Partial<Record<Format, (input: string) => stri
const lootTable = createLootTable(itemStack)
return JSON.stringify(lootTable, null, 2)
},
'item-modifier': (input) => {
const itemStack = parseGiveCommand(new StringReader(input))
const itemModifier = createItemModifier(itemStack)
return JSON.stringify(itemModifier, null, 2)
},
},
'loot-table': {
'give-command': (input) => {
@@ -156,6 +161,27 @@ const CONVERSIONS: Record<Format, Partial<Record<Format, (input: string) => stri
const itemStack = getItemFromLootTable(lootTable)
return `give @s ${stringifyItemStack(itemStack)}`
},
'item-modifier': (input) => {
// TODO: preserve more of the loot functions
const lootTable = JSON.parse(input)
const itemStack = getItemFromLootTable(lootTable)
const itemModifier = createItemModifier(itemStack)
return JSON.stringify(itemModifier, null, 2)
},
},
'item-modifier': {
'give-command': (input) => {
const itemModifier = JSON.parse(input)
const itemStack = getItemFromItemModifier(itemModifier)
return `give @s ${stringifyItemStack(itemStack)}`
},
'loot-table': (input) => {
// TODO: preserve more of the loot functions
const itemModifier = JSON.parse(input)
const itemStack = getItemFromItemModifier(itemModifier)
const lootTable = createLootTable(itemStack)
return JSON.stringify(lootTable, null, 2)
},
},
}
@@ -238,6 +264,7 @@ function parseIdentifier(reader: StringReader) {
}
function createLootTable(item: ItemStack) {
const functions = createLootFunctions(item)
return {
pools: [
{
@@ -246,20 +273,7 @@ function createLootTable(item: ItemStack) {
{
type: 'minecraft:item',
name: item.id.toString(),
functions: (item.components.size > 0 || item.count > 1)
? [
...item.components.size > 0 ? [{
function: 'minecraft:set_components',
components: Object.fromEntries([...item.components.entries()].map(([key, value]) => {
return [key, value.toSimplifiedJson()]
})),
}] : [],
...item.count > 1 ? [{
function: 'minecraft:set_count',
count: item.count,
}]: [],
]
: undefined,
functions: functions.length > 0 ? functions : undefined,
},
],
},
@@ -267,6 +281,40 @@ function createLootTable(item: ItemStack) {
}
}
function createItemModifier(item: ItemStack) {
const functions = createLootFunctions(item)
if (!item.id.is('air')) {
functions.unshift({ function: 'minecraft:set_item', item: item.id.toString() })
}
return functions.length === 1 ? functions[0] : functions
}
function createLootFunctions(item: ItemStack): Record<string, unknown>[] {
const functions = []
if (item.components.size > 0) {
functions.push({
function: 'minecraft:set_components',
components: Object.fromEntries([...item.components.entries()].map(([key, value]) => {
return [key, value.toSimplifiedJson()]
})),
})
}
if (item.count > 1) {
functions.push({
function: 'minecraft:set_count',
count: item.count,
})
}
return functions
}
function getItemFromItemModifier(data: unknown): ItemStack {
const functions = Array.isArray(data)
? Json.readArray(data, e => Json.readObject(e) ?? {}) ?? []
: [Json.readObject(data) ?? {}]
return getItemFromLootFunctions(functions)
}
function getItemFromLootTable(data: unknown): ItemStack {
const root = Json.readObject(data) ?? {}
const pools = Json.readArray(root.pools, e => Json.readObject(e) ?? {}) ?? []
@@ -292,11 +340,19 @@ function getItemFromLootTable(data: unknown): ItemStack {
...Json.readArray(pool.functions, e => Json.readObject(e) ?? {}) ?? [],
...Json.readArray(root.functions, e => Json.readObject(e) ?? {}) ?? [],
]
return getItemFromLootFunctions(functions, name)
}
function getItemFromLootFunctions(functions: Record<string, unknown>[], initialItem?: string) {
let item = initialItem
let count = 1
const components = new Map<string, NbtTag>()
for (const fn of functions) {
const type = Json.readString(fn.function)?.replace(/^minecraft:/, '')
switch (type) {
case 'set_item':
item = Json.readString(fn.item) ?? item
break
case 'set_count':
const value = Json.readInt(fn.count)
if (value) {
@@ -310,7 +366,7 @@ function getItemFromLootTable(data: unknown): ItemStack {
}
}
}
return new ItemStack(Identifier.parse(name), count, components)
return new ItemStack(Identifier.parse(item ?? 'air'), count, components)
}
function stringifyItemStack(itemStack: ItemStack) {