fix bugs with blocks models atlas usage

This commit is contained in:
Vitaly Turovsky 2025-02-07 14:16:01 +03:00
commit 2993bd2e45
8 changed files with 67 additions and 13 deletions

View file

@ -225,6 +225,7 @@ export class Entities extends EventEmitter {
size?: number;
} | {
resolvedModel: BlockModel
modelName: string
})
constructor (public viewer: Viewer) {
@ -426,7 +427,7 @@ export class Entities extends EventEmitter {
getItemMesh (item, isDropped = false) {
const textureUv = this.getItemUv?.(item)
if (textureUv && 'resolvedModel' in textureUv) {
const mesh = getBlockMeshFromModel(this.viewer.world.material, textureUv.resolvedModel, item.name ?? item.itemId)
const mesh = getBlockMeshFromModel(this.viewer.world.material, textureUv.resolvedModel, textureUv.modelName)
if (isDropped) {
const SCALE = 0.5
mesh.scale.set(SCALE, SCALE, SCALE)

View file

@ -249,7 +249,7 @@ export default class HoldingBlock {
this.objectOuterGroup.scale.set(scale, scale, scale)
}
async initHandObject (material: THREE.Material, blockstatesModels: any, blocksAtlases: any, handItem?: HandItemBlock) {
async initHandObject (handItem?: HandItemBlock) {
let animatingCurrent = false
if (!this.swingAnimation && !this.blockSwapAnimation && this.isDifferentItem(handItem)) {
animatingCurrent = true
@ -414,7 +414,7 @@ export default class HoldingBlock {
}
export const getBlockMeshFromModel = (material: THREE.Material, model: BlockModel, name: string) => {
const blockProvider = worldBlockProvider(viewer.world.blockstatesModels, viewer.world.blocksAtlases, 'latest')
const blockProvider = worldBlockProvider(viewer.world.blockstatesModels, viewer.world.blocksAtlasParser!.atlas, 'latest')
const worldRenderModel = blockProvider.transformModel(model, {
name,
properties: {}

View file

@ -117,8 +117,10 @@ export abstract class WorldRendererCommon<WorkerSend = any, WorkerReceive = any>
itemsAtlasParser: AtlasParser | undefined
blocksAtlasParser: AtlasParser | undefined
blocksAtlases = blocksAtlases
itemsAtlases = itemsAtlases
sourceData = {
blocksAtlases,
itemsAtlases
}
customTextures: {
items?: CustomTexturesData
blocks?: CustomTexturesData
@ -320,8 +322,8 @@ export abstract class WorldRendererCommon<WorkerSend = any, WorkerReceive = any>
}
async updateTexturesData (resourcePackUpdate = false, prioritizeBlockTextures?: string[]) {
const blocksAssetsParser = new AtlasParser(this.blocksAtlases, blocksAtlasLatest, blocksAtlasLegacy)
const itemsAssetsParser = new AtlasParser(this.itemsAtlases, itemsAtlasLatest, itemsAtlasLegacy)
const blocksAssetsParser = new AtlasParser(this.sourceData.blocksAtlases, blocksAtlasLatest, blocksAtlasLegacy)
const itemsAssetsParser = new AtlasParser(this.sourceData.itemsAtlases, itemsAtlasLatest, itemsAtlasLegacy)
const blockTexturesChanges = {} as Record<string, string>
const date = new Date()

View file

@ -67,7 +67,7 @@ export class WorldRendererThree extends WorldRendererCommon {
holdingBlock.toBeRenderedItem = item
return
}
void holdingBlock.initHandObject(this.material, this.blockstatesModels, this.blocksAtlases, item)
void holdingBlock.initHandObject(item)
}
changeHandSwingingState (isAnimationPlaying: boolean, isLeft = false) {

View file

@ -181,6 +181,7 @@ viewer.entities.getItemUv = (item) => {
if (renderInfo.blockData) {
return {
resolvedModel: renderInfo.blockData.resolvedModel,
modelName: renderInfo.modelName!
}
}
if (renderInfo.slice) {

View file

@ -179,6 +179,7 @@ export const renderSlot = (slot: GeneralInputItem, debugIsQuickbar = false): {
blockData?: Record<string, { slice, path }> & { resolvedModel: BlockModel },
scale?: number,
slice?: number[],
modelName?: string
} | undefined => {
let itemModelName = slot.name
const originalItemName = itemModelName
@ -212,7 +213,8 @@ export const renderSlot = (slot: GeneralInputItem, debugIsQuickbar = false): {
// is block
return {
texture: 'blocks',
blockData: itemTexture
blockData: itemTexture,
modelName: itemModelName
}
}
}

View file

@ -460,11 +460,11 @@ const updateAllReplacableTextures = async () => {
const repeatArr = (arr, i) => Array.from({ length: i }, () => arr)
const updateTextures = async () => {
const blocksFiles = Object.keys(viewer.world.blocksAtlases.latest.textures)
const itemsFiles = Object.keys(viewer.world.itemsAtlases.latest.textures)
const origBlocksFiles = Object.keys(viewer.world.sourceData.blocksAtlases.latest.textures)
const origItemsFiles = Object.keys(viewer.world.sourceData.itemsAtlases.latest.textures)
const { usedTextures: extraBlockTextures = new Set<string>() } = await prepareBlockstatesAndModels() ?? {}
const blocksData = await getResourcepackTiles('blocks', [...blocksFiles, ...extraBlockTextures])
const itemsData = await getResourcepackTiles('items', itemsFiles)
const blocksData = await getResourcepackTiles('blocks', [...origBlocksFiles, ...extraBlockTextures])
const itemsData = await getResourcepackTiles('items', origItemsFiles)
await updateAllReplacableTextures()
viewer.world.customTextures = {}
if (blocksData) {

View file

@ -0,0 +1,48 @@
import fs from 'fs'
export type ResourcePackItemDefinition = {
model: {
type: 'minecraft:model'
model: string
tints?: Array<{
type: 'minecraft:constant'
value: number // eg 12596533
}>
} | {
type: 'minecraft:empty'
}
}
export type ItemDefinitions = Record<string, ResourcePackItemDefinition>
export type ItemRenderDefinitionInput = {
item: string
}
const readFilesSafe = async (path: string) => {
try {
return await fs.promises.readdir(path)
} catch (error) {
return null
}
}
export const readResourcePackItemDefinitions = async (assetsPath: string) => {
const namespaces = fs.readdirSync(assetsPath)
const itemDefinitions: ItemDefinitions = {}
for (const namespace of namespaces) {
// eslint-disable-next-line no-await-in-loop
const items = await readFilesSafe(`${assetsPath}/${namespace}/items`)
if (!items) continue
for (const item of items) {
if (!item.endsWith('.json')) continue
const file = fs.readFileSync(`${assetsPath}/${namespace}/items/${item}`, 'utf8')
const json = JSON.parse(file)
itemDefinitions[`${namespace}:${item}`] = json
}
}
return itemDefinitions
}
export const itemsDefaultNamespace = 'minecraft'