mirror of
https://github.com/misode/misode.github.io.git
synced 2026-05-05 15:11:46 +00:00
Fix #626 update item displays to 1.21.4
This commit is contained in:
Generated
+7
-7
@@ -20,7 +20,7 @@
|
|||||||
"@zip.js/zip.js": "^2.4.5",
|
"@zip.js/zip.js": "^2.4.5",
|
||||||
"brace": "^0.11.1",
|
"brace": "^0.11.1",
|
||||||
"buffer": "^6.0.3",
|
"buffer": "^6.0.3",
|
||||||
"deepslate": "^0.22.3",
|
"deepslate": "^0.23.2",
|
||||||
"deepslate-1.18": "npm:deepslate@0.9.0-beta.9",
|
"deepslate-1.18": "npm:deepslate@0.9.0-beta.9",
|
||||||
"deepslate-1.18.2": "npm:deepslate@0.9.0",
|
"deepslate-1.18.2": "npm:deepslate@0.9.0",
|
||||||
"deepslate-1.20.4": "npm:deepslate@0.20.1",
|
"deepslate-1.20.4": "npm:deepslate@0.20.1",
|
||||||
@@ -1749,9 +1749,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/deepslate": {
|
"node_modules/deepslate": {
|
||||||
"version": "0.22.3",
|
"version": "0.23.2",
|
||||||
"resolved": "https://registry.npmjs.org/deepslate/-/deepslate-0.22.3.tgz",
|
"resolved": "https://registry.npmjs.org/deepslate/-/deepslate-0.23.2.tgz",
|
||||||
"integrity": "sha512-Oxd3ha7hfUaO5wv1ibMG3D6eeQkzEKTPaukJBWu8mK1ETT0xnoYroCgmzI3OmoUi8ZYbDUHzjwbP4txISNZ0ZQ==",
|
"integrity": "sha512-Adzy1W0rhJkT00rNp3PfnREC7JXc7BrWMo8h7xgmkfyk9GNLgEE/Zv0pUXvlIWc5yqeAnmqbPzgU5DXlNE5hBA==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"gl-matrix": "^3.3.0",
|
"gl-matrix": "^3.3.0",
|
||||||
"md5": "^2.3.0",
|
"md5": "^2.3.0",
|
||||||
@@ -6328,9 +6328,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"deepslate": {
|
"deepslate": {
|
||||||
"version": "0.22.3",
|
"version": "0.23.2",
|
||||||
"resolved": "https://registry.npmjs.org/deepslate/-/deepslate-0.22.3.tgz",
|
"resolved": "https://registry.npmjs.org/deepslate/-/deepslate-0.23.2.tgz",
|
||||||
"integrity": "sha512-Oxd3ha7hfUaO5wv1ibMG3D6eeQkzEKTPaukJBWu8mK1ETT0xnoYroCgmzI3OmoUi8ZYbDUHzjwbP4txISNZ0ZQ==",
|
"integrity": "sha512-Adzy1W0rhJkT00rNp3PfnREC7JXc7BrWMo8h7xgmkfyk9GNLgEE/Zv0pUXvlIWc5yqeAnmqbPzgU5DXlNE5hBA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"gl-matrix": "^3.3.0",
|
"gl-matrix": "^3.3.0",
|
||||||
"md5": "^2.3.0",
|
"md5": "^2.3.0",
|
||||||
|
|||||||
+1
-1
@@ -26,7 +26,7 @@
|
|||||||
"@zip.js/zip.js": "^2.4.5",
|
"@zip.js/zip.js": "^2.4.5",
|
||||||
"brace": "^0.11.1",
|
"brace": "^0.11.1",
|
||||||
"buffer": "^6.0.3",
|
"buffer": "^6.0.3",
|
||||||
"deepslate": "^0.22.3",
|
"deepslate": "^0.23.2",
|
||||||
"deepslate-1.18": "npm:deepslate@0.9.0-beta.9",
|
"deepslate-1.18": "npm:deepslate@0.9.0-beta.9",
|
||||||
"deepslate-1.18.2": "npm:deepslate@0.9.0",
|
"deepslate-1.18.2": "npm:deepslate@0.9.0",
|
||||||
"deepslate-1.20.4": "npm:deepslate@0.20.1",
|
"deepslate-1.20.4": "npm:deepslate@0.20.1",
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
import type { ItemStack } from 'deepslate/core'
|
import type { ItemStack } from 'deepslate/core'
|
||||||
import { Identifier } from 'deepslate/core'
|
|
||||||
import { useCallback, useEffect, useMemo, useRef, useState } from 'preact/hooks'
|
import { useCallback, useEffect, useMemo, useRef, useState } from 'preact/hooks'
|
||||||
import { useVersion } from '../contexts/Version.jsx'
|
import { useVersion } from '../contexts/Version.jsx'
|
||||||
import { useAsync } from '../hooks/useAsync.js'
|
import { useAsync } from '../hooks/useAsync.js'
|
||||||
import { fetchItemComponents, fetchRegistries } from '../services/index.js'
|
import { fetchItemComponents } from '../services/index.js'
|
||||||
import { ResolvedItem } from '../services/ResolvedItem.js'
|
import { ResolvedItem } from '../services/ResolvedItem.js'
|
||||||
import { renderItem } from '../services/Resources.js'
|
import { renderItem } from '../services/Resources.js'
|
||||||
import { jsonToNbt } from '../Utils.js'
|
import { jsonToNbt } from '../Utils.js'
|
||||||
@@ -42,13 +41,13 @@ export function ItemDisplay({ item, slotDecoration, tooltip, advancedTooltip }:
|
|||||||
}, [baseComponents])
|
}, [baseComponents])
|
||||||
const resolvedItem = useMemo(() => {
|
const resolvedItem = useMemo(() => {
|
||||||
return itemResolver(item)
|
return itemResolver(item)
|
||||||
}, [item, baseComponents])
|
}, [item, itemResolver])
|
||||||
|
|
||||||
const maxDamage = resolvedItem.getMaxDamage()
|
const maxDamage = resolvedItem.getMaxDamage()
|
||||||
const damage = resolvedItem.getDamage()
|
const damage = resolvedItem.getDamage()
|
||||||
|
|
||||||
return <div class="item-display" ref={el}>
|
return <div class="item-display" ref={el}>
|
||||||
<ItemItself item={resolvedItem} />
|
<RenderedItem item={resolvedItem} baseComponents={baseComponents} />
|
||||||
{item.count !== 1 && <>
|
{item.count !== 1 && <>
|
||||||
<svg class="item-count" width="100%" height="100%" viewBox="0 0 100 100" preserveAspectRatio="xMinYMid meet">
|
<svg class="item-count" width="100%" height="100%" viewBox="0 0 100 100" preserveAspectRatio="xMinYMid meet">
|
||||||
<text x="95" y="93" font-size="50" textAnchor="end" fontFamily="MinecraftSeven" fill="#373737">{item.count}</text>
|
<text x="95" y="93" font-size="50" textAnchor="end" fontFamily="MinecraftSeven" fill="#373737">{item.count}</text>
|
||||||
@@ -74,34 +73,16 @@ export function ItemDisplay({ item, slotDecoration, tooltip, advancedTooltip }:
|
|||||||
|
|
||||||
interface ResolvedProps extends Props {
|
interface ResolvedProps extends Props {
|
||||||
item: ResolvedItem
|
item: ResolvedItem
|
||||||
|
baseComponents: Map<string, Map<string, unknown>> | undefined
|
||||||
}
|
}
|
||||||
function ItemItself({ item }: ResolvedProps) {
|
function RenderedItem({ item, baseComponents }: ResolvedProps) {
|
||||||
const { version } = useVersion()
|
const { version } = useVersion()
|
||||||
|
const { value: src } = useAsync(async () => {
|
||||||
if (item.id.namespace !== Identifier.DEFAULT_NAMESPACE) {
|
if (!baseComponents) {
|
||||||
return Octicon.package
|
return undefined
|
||||||
}
|
}
|
||||||
|
return renderItem(version, item, baseComponents)
|
||||||
const { value: allModels, loading: loadingModels } = useAsync(async () => {
|
}, [version, item, baseComponents])
|
||||||
const registries = await fetchRegistries(version)
|
|
||||||
return registries.get('model')
|
|
||||||
}, [version])
|
|
||||||
|
|
||||||
if (loadingModels || allModels === undefined) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
const modelPath = `item/${item.id.path}`
|
|
||||||
if (allModels && allModels.includes('minecraft:' + modelPath)) {
|
|
||||||
return <RenderedItem item={item} />
|
|
||||||
}
|
|
||||||
|
|
||||||
return Octicon.package
|
|
||||||
}
|
|
||||||
|
|
||||||
function RenderedItem({ item }: ResolvedProps) {
|
|
||||||
const { version } = useVersion()
|
|
||||||
const { value: src } = useAsync(() => renderItem(version, item.flatten()), [version, item])
|
|
||||||
|
|
||||||
if (src) {
|
if (src) {
|
||||||
return <>
|
return <>
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ export const BlockStatePreview = ({ docAndNode, shown }: PreviewProps) => {
|
|||||||
|
|
||||||
const { value: resources } = useAsync(async () => {
|
const { value: resources } = useAsync(async () => {
|
||||||
if (!shown) return AsyncCancel
|
if (!shown) return AsyncCancel
|
||||||
const resources = await getResources(version)
|
const resources = await getResources(version, new Map())
|
||||||
const definition = BlockDefinition.fromJson(safeJsonParse(text) ?? {})
|
const definition = BlockDefinition.fromJson(safeJsonParse(text) ?? {})
|
||||||
const wrapper = new ResourceWrapper(resources, {
|
const wrapper = new ResourceWrapper(resources, {
|
||||||
getBlockDefinition(id) {
|
getBlockDefinition(id) {
|
||||||
|
|||||||
@@ -315,11 +315,12 @@ export class Deepslate {
|
|||||||
finalDensity: this.d.DensityFunction.fromJson(state),
|
finalDensity: this.d.DensityFunction.fromJson(state),
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
|
const levelHeight: deepslate19.LevelHeight = { minY: 0, height: 256 }
|
||||||
const unknownBiome = this.d.Identifier.create('unknown')
|
const unknownBiome = this.d.Identifier.create('unknown')
|
||||||
const randomState = new this.d.RandomState(settings, seed)
|
const randomState = new this.d.RandomState(settings, seed)
|
||||||
const biomeSource = new this.d.FixedBiomeSource(unknownBiome)
|
const biomeSource = new this.d.FixedBiomeSource(unknownBiome)
|
||||||
const chunkGenerator = new this.d.NoiseChunkGenerator(biomeSource, settings)
|
const chunkGenerator = new this.d.NoiseChunkGenerator(biomeSource, settings)
|
||||||
this.structureContextCache = { seed, settings, randomState, biomeSource, chunkGenerator }
|
this.structureContextCache = { seed, settings, randomState, biomeSource, chunkGenerator, levelHeight }
|
||||||
|
|
||||||
class SimpleStructure extends this.d.WorldgenStructure {
|
class SimpleStructure extends this.d.WorldgenStructure {
|
||||||
constructor(settings: deepslate19.WorldgenStructure.StructureSettings) {
|
constructor(settings: deepslate19.WorldgenStructure.StructureSettings) {
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import type { ItemComponentsProvider } from 'deepslate'
|
||||||
import { NbtByte, NbtDouble, NbtLong } from 'deepslate'
|
import { NbtByte, NbtDouble, NbtLong } from 'deepslate'
|
||||||
import type { Random } from 'deepslate/core'
|
import type { Random } from 'deepslate/core'
|
||||||
import { Identifier, ItemStack, LegacyRandom } from 'deepslate/core'
|
import { Identifier, ItemStack, LegacyRandom } from 'deepslate/core'
|
||||||
@@ -20,7 +21,7 @@ const StackMixers = {
|
|||||||
|
|
||||||
type StackMixer = keyof typeof StackMixers
|
type StackMixer = keyof typeof StackMixers
|
||||||
|
|
||||||
interface LootOptions {
|
interface LootOptions extends ItemComponentsProvider {
|
||||||
version: VersionId,
|
version: VersionId,
|
||||||
seed: bigint,
|
seed: bigint,
|
||||||
luck: number,
|
luck: number,
|
||||||
@@ -32,7 +33,6 @@ interface LootOptions {
|
|||||||
getPredicate(id: string): any,
|
getPredicate(id: string): any,
|
||||||
getEnchantments(): Map<string, any>,
|
getEnchantments(): Map<string, any>,
|
||||||
getEnchantmentTag(id: string): string[],
|
getEnchantmentTag(id: string): string[],
|
||||||
getBaseComponents(id: string): Map<string, NbtTag>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface LootContext extends LootOptions {
|
interface LootContext extends LootOptions {
|
||||||
@@ -235,12 +235,12 @@ function createItem(entry: any, consumer: ItemConsumer, ctx: LootContext) {
|
|||||||
switch (type) {
|
switch (type) {
|
||||||
case 'item':
|
case 'item':
|
||||||
const id = Identifier.parse(entry.name)
|
const id = Identifier.parse(entry.name)
|
||||||
entryConsumer(new ResolvedItem(new ItemStack(id, 1), ctx.getBaseComponents(id.toString())))
|
entryConsumer(new ResolvedItem(new ItemStack(id, 1), ctx.getItemComponents(id)))
|
||||||
break
|
break
|
||||||
case 'tag':
|
case 'tag':
|
||||||
ctx.getItemTag(entry.name).forEach(tagEntry => {
|
ctx.getItemTag(entry.name).forEach(tagEntry => {
|
||||||
const id = Identifier.parse(tagEntry)
|
const id = Identifier.parse(tagEntry)
|
||||||
entryConsumer(new ResolvedItem(new ItemStack(id, 1), ctx.getBaseComponents(id.toString())))
|
entryConsumer(new ResolvedItem(new ItemStack(id, 1), ctx.getItemComponents(id)))
|
||||||
})
|
})
|
||||||
break
|
break
|
||||||
case 'loot_table':
|
case 'loot_table':
|
||||||
@@ -303,7 +303,7 @@ const LootFunctions: Record<string, (params: any) => LootFunction> = {
|
|||||||
const level = ctx.random.nextInt(maxLevel - 1) + 1
|
const level = ctx.random.nextInt(maxLevel - 1) + 1
|
||||||
if (item.is('book')) {
|
if (item.is('book')) {
|
||||||
item.id = Identifier.create('enchanted_book')
|
item.id = Identifier.create('enchanted_book')
|
||||||
item.base = ctx.getBaseComponents(item.id.toString())
|
item.base = ctx.getItemComponents(item.id)
|
||||||
}
|
}
|
||||||
updateEnchantments(item, levels => {
|
updateEnchantments(item, levels => {
|
||||||
return levels.set(Identifier.parse(pick).toString(), level)
|
return levels.set(Identifier.parse(pick).toString(), level)
|
||||||
@@ -314,7 +314,7 @@ const LootFunctions: Record<string, (params: any) => LootFunction> = {
|
|||||||
const selected = selectEnchantments(item, computeInt(levels, ctx), allowed, ctx)
|
const selected = selectEnchantments(item, computeInt(levels, ctx), allowed, ctx)
|
||||||
if (item.is('book')) {
|
if (item.is('book')) {
|
||||||
item.id = Identifier.create('enchanted_book')
|
item.id = Identifier.create('enchanted_book')
|
||||||
item.base = ctx.getBaseComponents(item.id.toString())
|
item.base = ctx.getItemComponents(item.id)
|
||||||
}
|
}
|
||||||
updateEnchantments(item, levelsMap => {
|
updateEnchantments(item, levelsMap => {
|
||||||
for (const { id, lvl } of selected) {
|
for (const { id, lvl } of selected) {
|
||||||
@@ -437,7 +437,7 @@ const LootFunctions: Record<string, (params: any) => LootFunction> = {
|
|||||||
}
|
}
|
||||||
if (item.is('book')) {
|
if (item.is('book')) {
|
||||||
item.id = Identifier.create('enchanted_book')
|
item.id = Identifier.create('enchanted_book')
|
||||||
item.base = ctx.getBaseComponents(item.id.toString())
|
item.base = ctx.getItemComponents(item.id)
|
||||||
}
|
}
|
||||||
updateEnchantments(item, levels => {
|
updateEnchantments(item, levels => {
|
||||||
Object.entries(enchantments).forEach(([id, level]) => {
|
Object.entries(enchantments).forEach(([id, level]) => {
|
||||||
@@ -463,7 +463,7 @@ const LootFunctions: Record<string, (params: any) => LootFunction> = {
|
|||||||
set_item: ({ item: newId }) => (item, ctx) => {
|
set_item: ({ item: newId }) => (item, ctx) => {
|
||||||
if (typeof newId !== 'string') return
|
if (typeof newId !== 'string') return
|
||||||
item.id = Identifier.parse(newId)
|
item.id = Identifier.parse(newId)
|
||||||
item.base = ctx.getBaseComponents(item.id.toString())
|
item.base = ctx.getItemComponents(item.id)
|
||||||
},
|
},
|
||||||
set_loot_table: ({ name, seed }) => (item) => {
|
set_loot_table: ({ name, seed }) => (item) => {
|
||||||
item.set('container_loot', new NbtCompound()
|
item.set('container_loot', new NbtCompound()
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import { Identifier } from 'deepslate'
|
|
||||||
import { useMemo, useRef, useState } from 'preact/hooks'
|
import { useMemo, useRef, useState } from 'preact/hooks'
|
||||||
import { useLocale, useVersion } from '../../contexts/index.js'
|
import { useLocale, useVersion } from '../../contexts/index.js'
|
||||||
import { useAsync } from '../../hooks/useAsync.js'
|
import { useAsync } from '../../hooks/useAsync.js'
|
||||||
@@ -58,7 +57,7 @@ export const LootTablePreview = ({ docAndNode }: PreviewProps) => {
|
|||||||
getPredicate: () => undefined,
|
getPredicate: () => undefined,
|
||||||
getEnchantments: () => enchantments ?? new Map(),
|
getEnchantments: () => enchantments ?? new Map(),
|
||||||
getEnchantmentTag: (id) => (enchantmentTags?.get(id.replace(/^minecraft:/, '')) as any)?.values ?? [],
|
getEnchantmentTag: (id) => (enchantmentTags?.get(id.replace(/^minecraft:/, '')) as any)?.values ?? [],
|
||||||
getBaseComponents: (id) => new Map([...(itemComponents?.get(Identifier.parse(id).toString()) ?? new Map()).entries()].map(([k, v]) => [k, jsonToNbt(v)])),
|
getItemComponents: (id) => new Map([...(itemComponents?.get(id.toString()) ?? new Map()).entries()].map(([k, v]) => [k, jsonToNbt(v)])),
|
||||||
})
|
})
|
||||||
}, [version, seed, luck, daytime, weather, mixItems, text, dependencies, loading])
|
}, [version, seed, luck, daytime, weather, mixItems, text, dependencies, loading])
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ export const ModelPreview = ({ docAndNode, shown }: PreviewProps) => {
|
|||||||
|
|
||||||
const { value: resources } = useAsync(async () => {
|
const { value: resources } = useAsync(async () => {
|
||||||
if (!shown) return AsyncCancel
|
if (!shown) return AsyncCancel
|
||||||
const resources = await getResources(version)
|
const resources = await getResources(version, new Map())
|
||||||
const blockModel = BlockModel.fromJson(safeJsonParse(text) ?? {})
|
const blockModel = BlockModel.fromJson(safeJsonParse(text) ?? {})
|
||||||
blockModel.flatten(resources)
|
blockModel.flatten(resources)
|
||||||
const wrapper = new ResourceWrapper(resources, {
|
const wrapper = new ResourceWrapper(resources, {
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ export const StructureSetPreview = ({ docAndNode, shown }: PreviewProps) => {
|
|||||||
|
|
||||||
iterateWorld2D(imageData.current, transform, (x, y) => {
|
iterateWorld2D(imageData.current, transform, (x, y) => {
|
||||||
const pos = ChunkPos.create(x, y)
|
const pos = ChunkPos.create(x, y)
|
||||||
const structure = computeIfAbsent(chunkStructures, `${pos[0]} ${pos[1]}`, () => structureSet?.getStructureInChunk(pos[0], pos[1], context))
|
const structure = computeIfAbsent(chunkStructures, `${pos[0]} ${pos[1]}`, () => structureSet?.getStructureInChunk(pos[0], pos[1], context)?.id)
|
||||||
return { structure, pos }
|
return { structure, pos }
|
||||||
}, ({ structure, pos }) => {
|
}, ({ structure, pos }) => {
|
||||||
if (structure !== undefined) {
|
if (structure !== undefined) {
|
||||||
|
|||||||
@@ -209,15 +209,19 @@ export function getAssetUrl(versionId: VersionId, type: string, path: string): s
|
|||||||
|
|
||||||
export async function fetchResources(versionId: VersionId) {
|
export async function fetchResources(versionId: VersionId) {
|
||||||
const version = config.versions.find(v => v.id === versionId)!
|
const version = config.versions.find(v => v.id === versionId)!
|
||||||
|
const needsItemModels = checkVersion(versionId, '1.20.5')
|
||||||
|
const hasItemModels = checkVersion(versionId, '1.21.4')
|
||||||
await validateCache(version)
|
await validateCache(version)
|
||||||
try {
|
try {
|
||||||
const [blockDefinitions, models, uvMapping, atlas] = await Promise.all([
|
const [blockDefinitions, models, uvMapping, atlas, itemDefinitions] = await Promise.all([
|
||||||
fetchAllPresets(versionId, 'block_definition'),
|
fetchAllPresets(versionId, 'block_definition'),
|
||||||
fetchAllPresets(versionId, 'model'),
|
fetchAllPresets(versionId, 'model'),
|
||||||
fetch(`${mcmeta(version, 'atlas')}/all/data.min.json`).then(r => r.json()),
|
fetch(`${mcmeta(version, 'atlas')}/all/data.min.json`).then(r => r.json()),
|
||||||
loadImage(`${mcmeta(version, 'atlas')}/all/atlas.png`),
|
loadImage(`${mcmeta(version, 'atlas')}/all/atlas.png`),
|
||||||
|
// Always download the 1.21.4 item models for the version range 1.20.5 - 1.21.3
|
||||||
|
needsItemModels ? fetchAllPresets(hasItemModels ? versionId : '1.21.4', 'item_definition') : new Map<string, unknown>(),
|
||||||
])
|
])
|
||||||
return { blockDefinitions, models, uvMapping, atlas }
|
return { blockDefinitions, models, uvMapping, atlas, itemDefinitions }
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
throw new Error(`Error occured while fetching resources: ${message(e)}`)
|
throw new Error(`Error occured while fetching resources: ${message(e)}`)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,30 +11,10 @@ export class ResolvedItem extends ItemStack {
|
|||||||
super(item.id, item.count, item.components)
|
super(item.id, item.count, item.components)
|
||||||
}
|
}
|
||||||
|
|
||||||
public static create(id: string | Identifier, count: number, components: Map<string, NbtTag>, baseGetter: (id: string) => ReadonlyMap<string, NbtTag>) {
|
|
||||||
if (typeof id === 'string') {
|
|
||||||
id = Identifier.parse(id)
|
|
||||||
}
|
|
||||||
const item = new ItemStack(id, count, components)
|
|
||||||
return new ResolvedItem(item, baseGetter(id.toString()))
|
|
||||||
}
|
|
||||||
|
|
||||||
public clone(): ResolvedItem {
|
public clone(): ResolvedItem {
|
||||||
return new ResolvedItem(super.clone(), this.base)
|
return new ResolvedItem(super.clone(), this.base)
|
||||||
}
|
}
|
||||||
|
|
||||||
public flatten(): ItemStack {
|
|
||||||
const components = new Map(this.base)
|
|
||||||
for (const [key, value] of this.components) {
|
|
||||||
if (key.startsWith('!')) {
|
|
||||||
components.delete(key.slice(1))
|
|
||||||
} else {
|
|
||||||
components.set(key, value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return new ItemStack(this.id, this.count, components)
|
|
||||||
}
|
|
||||||
|
|
||||||
private getTag(key: string) {
|
private getTag(key: string) {
|
||||||
key = Identifier.parse(key).toString()
|
key = Identifier.parse(key).toString()
|
||||||
if (this.components.has(key)) {
|
if (this.components.has(key)) {
|
||||||
|
|||||||
@@ -1,18 +1,22 @@
|
|||||||
|
import { isObject } from '@spyglassmc/core'
|
||||||
|
import type { ItemComponentsProvider, ItemModelProvider } from 'deepslate'
|
||||||
|
import { ItemModel, NbtString } from 'deepslate'
|
||||||
import type { BlockDefinitionProvider, BlockFlagsProvider, BlockModelProvider, BlockPropertiesProvider, ItemStack, TextureAtlasProvider, UV } from 'deepslate/render'
|
import type { BlockDefinitionProvider, BlockFlagsProvider, BlockModelProvider, BlockPropertiesProvider, ItemStack, TextureAtlasProvider, UV } from 'deepslate/render'
|
||||||
import { BlockDefinition, BlockModel, Identifier, ItemRenderer, TextureAtlas, upperPowerOfTwo } from 'deepslate/render'
|
import { BlockDefinition, BlockModel, Identifier, ItemRenderer, TextureAtlas, upperPowerOfTwo } from 'deepslate/render'
|
||||||
import config from '../Config.js'
|
import config from '../Config.js'
|
||||||
import { message } from '../Utils.js'
|
import { jsonToNbt, message } from '../Utils.js'
|
||||||
import { fetchLanguage, fetchResources } from './DataFetcher.js'
|
import { fetchLanguage, fetchResources } from './DataFetcher.js'
|
||||||
import type { VersionId } from './Versions.js'
|
import type { VersionId } from './Versions.js'
|
||||||
|
import { checkVersion } from './Versions.js'
|
||||||
|
|
||||||
const Resources: Record<string, ResourceManager | Promise<ResourceManager>> = {}
|
const Resources: Record<string, ResourceManager | Promise<ResourceManager>> = {}
|
||||||
|
|
||||||
export async function getResources(version: VersionId) {
|
export async function getResources(version: VersionId, itemComponents: Map<string, Map<string, unknown>>) {
|
||||||
if (!Resources[version]) {
|
if (!Resources[version]) {
|
||||||
Resources[version] = (async () => {
|
Resources[version] = (async () => {
|
||||||
try {
|
try {
|
||||||
const { blockDefinitions, models, uvMapping, atlas} = await fetchResources(version)
|
const { blockDefinitions, models, uvMapping, atlas, itemDefinitions } = await fetchResources(version)
|
||||||
Resources[version] = new ResourceManager(blockDefinitions, models, uvMapping, atlas)
|
Resources[version] = new ResourceManager(version, blockDefinitions, models, uvMapping, atlas, itemDefinitions, itemComponents)
|
||||||
return Resources[version]
|
return Resources[version]
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error('Error: ', e)
|
console.error('Error: ', e)
|
||||||
@@ -27,7 +31,7 @@ export async function getResources(version: VersionId) {
|
|||||||
const RENDER_SIZE = 128
|
const RENDER_SIZE = 128
|
||||||
const ItemRenderCache = new Map<string, Promise<string>>()
|
const ItemRenderCache = new Map<string, Promise<string>>()
|
||||||
|
|
||||||
export async function renderItem(version: VersionId, item: ItemStack) {
|
export async function renderItem(version: VersionId, item: ItemStack, baseComponents: Map<string, Map<string, unknown>>) {
|
||||||
const cache_key = `${version} ${item.toString()}`
|
const cache_key = `${version} ${item.toString()}`
|
||||||
const cached = ItemRenderCache.get(cache_key)
|
const cached = ItemRenderCache.get(cache_key)
|
||||||
if (cached !== undefined) {
|
if (cached !== undefined) {
|
||||||
@@ -38,12 +42,12 @@ export async function renderItem(version: VersionId, item: ItemStack) {
|
|||||||
const canvas = document.createElement('canvas')
|
const canvas = document.createElement('canvas')
|
||||||
canvas.width = RENDER_SIZE
|
canvas.width = RENDER_SIZE
|
||||||
canvas.height = RENDER_SIZE
|
canvas.height = RENDER_SIZE
|
||||||
const resources = await getResources(version)
|
const resources = await getResources(version, baseComponents)
|
||||||
const gl = canvas.getContext('webgl2', { preserveDrawingBuffer: true })
|
const gl = canvas.getContext('webgl2', { preserveDrawingBuffer: true })
|
||||||
if (!gl) {
|
if (!gl) {
|
||||||
throw new Error('Cannot get WebGL2 context')
|
throw new Error('Cannot get WebGL2 context')
|
||||||
}
|
}
|
||||||
const renderer = new ItemRenderer(gl, item, resources)
|
const renderer = new ItemRenderer(gl, item, resources, { display_context: 'gui' })
|
||||||
renderer.drawItem()
|
renderer.drawItem()
|
||||||
return canvas.toDataURL()
|
return canvas.toDataURL()
|
||||||
})()
|
})()
|
||||||
@@ -51,20 +55,27 @@ export async function renderItem(version: VersionId, item: ItemStack) {
|
|||||||
return promise
|
return promise
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Resources extends BlockDefinitionProvider, BlockModelProvider, TextureAtlasProvider, BlockFlagsProvider, BlockPropertiesProvider {}
|
interface Resources extends BlockDefinitionProvider, BlockModelProvider, TextureAtlasProvider, BlockFlagsProvider, BlockPropertiesProvider, ItemModelProvider, ItemComponentsProvider {}
|
||||||
|
|
||||||
export class ResourceManager implements Resources {
|
export class ResourceManager implements Resources {
|
||||||
|
private readonly version: VersionId
|
||||||
private readonly blockDefinitions: { [id: string]: BlockDefinition }
|
private readonly blockDefinitions: { [id: string]: BlockDefinition }
|
||||||
private readonly blockModels: { [id: string]: BlockModel }
|
private readonly blockModels: { [id: string]: BlockModel }
|
||||||
|
private readonly itemModels: { [id: string]: ItemModel }
|
||||||
private textureAtlas: TextureAtlas
|
private textureAtlas: TextureAtlas
|
||||||
|
private readonly itemComponents: Map<string, Map<string, unknown>>
|
||||||
|
|
||||||
constructor(blockDefinitions: Map<string, unknown>, models: Map<string, unknown>, uvMapping: any, textureAtlas: HTMLImageElement) {
|
constructor(version: VersionId, blockDefinitions: Map<string, unknown>, models: Map<string, unknown>, uvMapping: any, textureAtlas: HTMLImageElement, itemDefinitions: Map<string, unknown>, itemComponents: Map<string, Map<string, unknown>>) {
|
||||||
|
this.version = version
|
||||||
this.blockDefinitions = {}
|
this.blockDefinitions = {}
|
||||||
this.blockModels = {}
|
this.blockModels = {}
|
||||||
|
this.itemModels = {}
|
||||||
this.textureAtlas = TextureAtlas.empty()
|
this.textureAtlas = TextureAtlas.empty()
|
||||||
this.loadBlockDefinitions(blockDefinitions)
|
this.loadBlockDefinitions(blockDefinitions)
|
||||||
this.loadBlockModels(models)
|
this.loadBlockModels(models)
|
||||||
this.loadBlockAtlas(textureAtlas, uvMapping)
|
this.loadBlockAtlas(textureAtlas, uvMapping)
|
||||||
|
this.loadItemModels(itemDefinitions)
|
||||||
|
this.itemComponents = itemComponents
|
||||||
}
|
}
|
||||||
|
|
||||||
public getBlockDefinition(id: Identifier) {
|
public getBlockDefinition(id: Identifier) {
|
||||||
@@ -95,6 +106,20 @@ export class ResourceManager implements Resources {
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public getItemModel(id: Identifier) {
|
||||||
|
return this.itemModels[id.toString()]
|
||||||
|
}
|
||||||
|
|
||||||
|
public getItemComponents(id: Identifier) {
|
||||||
|
const components = this.itemComponents.get(id.toString()) ?? new Map<string, unknown>()
|
||||||
|
const result = new Map([...components.entries()].map(([k, v]) => [k, jsonToNbt(v)]))
|
||||||
|
// Hack to make this version range work without needing another deepslate version
|
||||||
|
if (checkVersion(this.version, '1.20.5', '1.21.2')) {
|
||||||
|
result.set('minecraft:item_model', new NbtString(id.toString()))
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
private loadBlockModels(models: Map<string, unknown>) {
|
private loadBlockModels(models: Map<string, unknown>) {
|
||||||
[...models.entries()].forEach(([id, model]) => {
|
[...models.entries()].forEach(([id, model]) => {
|
||||||
this.blockModels[Identifier.create(id).toString()] = BlockModel.fromJson(model)
|
this.blockModels[Identifier.create(id).toString()] = BlockModel.fromJson(model)
|
||||||
@@ -108,6 +133,14 @@ export class ResourceManager implements Resources {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private loadItemModels(definitions: Map<string, unknown>) {
|
||||||
|
[...definitions.entries()].forEach(([id, definition]) => {
|
||||||
|
if (isObject(definition) && isObject((definition as any).model)) {
|
||||||
|
this.itemModels[Identifier.create(id).toString()] = ItemModel.fromJson((definition as any).model)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
private loadBlockAtlas(image: HTMLImageElement, textures: any) {
|
private loadBlockAtlas(image: HTMLImageElement, textures: any) {
|
||||||
const atlasCanvas = document.createElement('canvas')
|
const atlasCanvas = document.createElement('canvas')
|
||||||
const w = upperPowerOfTwo(image.width)
|
const w = upperPowerOfTwo(image.width)
|
||||||
@@ -161,6 +194,14 @@ export class ResourceWrapper implements Resources {
|
|||||||
public getDefaultBlockProperties(id: Identifier) {
|
public getDefaultBlockProperties(id: Identifier) {
|
||||||
return this.overrides.getDefaultBlockProperties?.(id) ?? this.wrapped.getDefaultBlockProperties(id)
|
return this.overrides.getDefaultBlockProperties?.(id) ?? this.wrapped.getDefaultBlockProperties(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public getItemModel(id: Identifier) {
|
||||||
|
return this.overrides.getItemModel?.(id) ?? this.wrapped.getItemModel(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
public getItemComponents(id: Identifier) {
|
||||||
|
return this.overrides.getItemComponents?.(id) ?? this.wrapped.getItemComponents(id)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export type Language = Record<string, string>
|
export type Language = Record<string, string>
|
||||||
|
|||||||
Reference in New Issue
Block a user