diff --git a/src/consumer/assetsParser.ts b/src/consumer/assetsParser.ts index 0ea05dfec..2eacb83f7 100644 --- a/src/consumer/assetsParser.ts +++ b/src/consumer/assetsParser.ts @@ -145,7 +145,19 @@ export class AssetsParser { } const modelData = this.blockModelsStore.get(this.version, model) if (!modelData) return - const resolveModel = (model: BlockModel) => { + const collectedParentModels = [] as BlockModel[] + const collectModels = (model: BlockModel) => { + collectedParentModels.push(model) + + if (model.parent) { + const parent = this.blockModelsStore.get(this.version, model.parent) + if (!parent) return + collectModels(parent) + } + } + collectModels(modelData) + collectedParentModels.reverse() // from parent to child + for (const model of collectedParentModels) { if (model.ambientocclusion !== undefined) { this.resolvedModel.ao = model.ambientocclusion } @@ -156,8 +168,9 @@ export class AssetsParser { if (model.textures) { this.resolvedModel.textures ??= {} for (let [key, value] of Object.entries(model.textures)) { - if (value.includes('#')) { - const key = value.split('/').at(-1)!.slice(1) + if (value.includes('#')) value = value.split('/').at(-1)! + if (value.startsWith('#')) { + const key = value.slice(1) if (this.resolvedModel.textures[key]) { value = this.resolvedModel.textures[key]! } @@ -167,36 +180,34 @@ export class AssetsParser { } if (model.elements) { - this.resolvedModel.elements ??= [] - this.resolvedModel.elements.push(...structuredClone(model.elements)) + this.resolvedModel.elements = structuredClone(model.elements) } - - if (model.parent) { - const parent = this.blockModelsStore.get(this.version, model.parent) - if (!parent) return - resolveModel(parent) - } - return model } - resolveModel(modelData) - const resolveTexture = (originalTexturePath: string, _originalKey: string) => { + + const resolveTexture = (originalTexturePath: string, _originalKey: string, chain: string[]) => { + chain.push(_originalKey) if (originalTexturePath.includes('#')) { originalTexturePath = originalTexturePath.split('/').at(-1)!.replace('#', '') this.resolvedModel.textures ??= {} + if (chain.includes(originalTexturePath)) { + console.warn(`${debugQueryName}: Circular texture reference detected: ${chain.join(' -> ')}`) + return + } const existingKey = this.resolvedModel.textures[originalTexturePath] if (!existingKey) { // todo this also needs to be done at the validation stage // throw new Error(`Cannot resolve texture ${key} to ${value} because it is not defined`) console.warn(`${debugQueryName}: Cannot resolve texture ${originalTexturePath} for ${_originalKey} because it is not defined`) + return } else { - return existingKey + return resolveTexture(existingKey, originalTexturePath, chain) } } - return + return originalTexturePath } for (let [key, value] of Object.entries(this.resolvedModel.textures ?? {})) { if (!value.includes('#')) continue - const resolved = resolveTexture(value, key) + const resolved = resolveTexture(value, key, []) if (resolved) this.resolvedModel.textures![key] = resolved else delete this.resolvedModel.textures![key] } diff --git a/src/examples/parserDemo.ts b/src/examples/parserDemo.ts index ca0a7d11b..53ac17d59 100644 --- a/src/examples/parserDemo.ts +++ b/src/examples/parserDemo.ts @@ -10,7 +10,7 @@ const assetsParser = new AssetsParser('latest', getLoadedBlockstatesStore(blocks const modelsStore = getLoadedModelsStore(blockstatesModels) console.dir(assetsParser.getAllResolvedModels({ - name: 'stone', + name: 'piston', properties: {}, }, true), { depth: 6, diff --git a/src/examples/worldBlockProvidersDemo.ts b/src/examples/worldBlockProvidersDemo.ts index 59d451a9b..5f55023c8 100644 --- a/src/examples/worldBlockProvidersDemo.ts +++ b/src/examples/worldBlockProvidersDemo.ts @@ -10,9 +10,15 @@ const blocksProvider = worldBlockProvider(blockstatesModels, blocksAtlas, 'lates // console.log(blocksProvider.getTextureInfo("block/entity/decorated_pot/decorated_pot_base")) const result = blocksProvider.getAllResolvedModels0_1({ - name: 'oak_sign', + name: 'chiseled_bookshelf', properties: { - facing: 'east' + "slot_5_occupied": false, + "slot_4_occupied": false, + "slot_3_occupied": false, + "slot_2_occupied": false, + "slot_1_occupied": false, + "slot_0_occupied": false, + "facing": "south" }, }) diff --git a/src/missingBlockEntities.json b/src/missingBlockEntities.json index c22c24bc6..7a09073cb 100644 --- a/src/missingBlockEntities.json +++ b/src/missingBlockEntities.json @@ -1,34 +1,7 @@ { - "acacia_hanging_sign": true, - "bamboo_hanging_sign": true, - "birch_hanging_sign": true, - "black_glazed_terracotta": true, - "blue_glazed_terracotta": true, - "brown_glazed_terracotta": true, "bubble_column": true, - "cherry_hanging_sign": true, - "crimson_hanging_sign": true, - "cyan_glazed_terracotta": true, - "dark_oak_hanging_sign": true, "end_gateway": true, "end_portal": true, - "gray_glazed_terracotta": true, - "green_glazed_terracotta": true, - "jungle_hanging_sign": true, - "light_blue_glazed_terracotta": true, - "light_gray_glazed_terracotta": true, - "lime_glazed_terracotta": true, - "magenta_glazed_terracotta": true, - "mangrove_hanging_sign": true, - "oak_hanging_sign": true, - "orange_glazed_terracotta": true, - "pink_glazed_terracotta": true, - "purple_glazed_terracotta": true, - "red_glazed_terracotta": true, - "spruce_hanging_sign": true, "structure_void": true, - "trial_spawner": true, - "warped_hanging_sign": true, - "white_glazed_terracotta": true, - "yellow_glazed_terracotta": true + "trial_spawner": true }