mc-assets 0.2.34 → 0.2.35

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -18,6 +18,9 @@ export declare class AssetsParser {
18
18
  parseProperties(properties: string): Record<string, string | boolean>;
19
19
  getElements(queriedBlock: Omit<QueriedBlock, 'stateId'>, fallbackVariant?: boolean): 0 | 1 | BlockElement[];
20
20
  private resolvedModel;
21
+ issues: string[];
22
+ matchedModels: string[];
23
+ matchedConditions: string[];
21
24
  private getModelsByBlock;
22
25
  getResolvedModelsByModel(model: string, debugQueryName?: string, clearModel?: boolean): {
23
26
  resolvedModel: Pick<BlockModel, "textures" | "ao" | "elements"> & {
@@ -1,3 +1,11 @@
1
+ const getNamespace = (name) => {
2
+ const parts = name.split(':');
3
+ if (parts.length === 1)
4
+ return 'minecraft';
5
+ if (parts.length === 2)
6
+ return parts[0];
7
+ return parts.slice(0, -1).join(':');
8
+ };
1
9
  export class AssetsParser {
2
10
  version;
3
11
  blockStatesStore;
@@ -43,7 +51,12 @@ export class AssetsParser {
43
51
  }
44
52
  // looks like workaround
45
53
  resolvedModel = {};
54
+ issues = [];
55
+ matchedModels = [];
56
+ matchedConditions = [];
46
57
  getModelsByBlock(queriedBlock, fallbackVariant, multiOptim) {
58
+ this.matchedModels = [];
59
+ this.matchedConditions = [];
47
60
  const matchProperties = (block, /* to match against */ properties) => {
48
61
  if (!properties) {
49
62
  return true;
@@ -69,9 +82,12 @@ export class AssetsParser {
69
82
  };
70
83
  let applyModels = [];
71
84
  const blockStates = this.blockStatesStore.get(this.version, queriedBlock.name);
72
- if (!blockStates)
85
+ if (!blockStates) {
86
+ this.issues.push(`Block ${queriedBlock.name} not found in all registered blockstates. Place it into assets/${getNamespace(queriedBlock.name)}/blockstates/${queriedBlock.name}.json`);
73
87
  return;
88
+ }
74
89
  const states = blockStates.variants;
90
+ let stateMatched = false;
75
91
  if (states) {
76
92
  let state = states[''] || states['normal'];
77
93
  for (const key in states) {
@@ -82,9 +98,15 @@ export class AssetsParser {
82
98
  break;
83
99
  }
84
100
  }
101
+ if (state) {
102
+ const matchedStateName = Object.entries(states).find(([key]) => state === states[key])?.[0];
103
+ this.matchedConditions.push(`variant:${matchedStateName}`);
104
+ }
85
105
  if (!state) {
86
106
  if (fallbackVariant) {
87
- state = states[Object.keys(states)[0]];
107
+ const firstKey = Object.keys(states)[0];
108
+ state = states[firstKey];
109
+ this.matchedConditions.push(`fallback:${firstKey}`);
88
110
  }
89
111
  else {
90
112
  return;
@@ -92,12 +114,14 @@ export class AssetsParser {
92
114
  }
93
115
  if (state) {
94
116
  applyModels.push(state);
117
+ stateMatched = true;
95
118
  }
96
119
  }
97
120
  if (blockStates.multipart) {
98
121
  for (const { when, apply } of blockStates.multipart) {
99
122
  if (!when || matchProperties(queriedBlock, when)) {
100
123
  applyModels.push(apply);
124
+ this.matchedConditions.push(when ? `multipart:${JSON.stringify(when)}` : 'multipart:always');
101
125
  }
102
126
  }
103
127
  if (!applyModels.length && fallbackVariant) {
@@ -105,11 +129,22 @@ export class AssetsParser {
105
129
  const apply = multipartWithWhen[0]?.apply;
106
130
  if (apply) {
107
131
  applyModels.push(apply);
132
+ this.matchedConditions.push('multipart:fallback');
108
133
  }
109
134
  }
110
135
  }
111
- if (!applyModels.length)
136
+ if (!applyModels.length) {
137
+ if (!stateMatched) {
138
+ const blockstatesCount = Object.keys(states ?? {}).length;
139
+ if (blockstatesCount) {
140
+ this.issues.push(`Block did not match any possible state (${blockstatesCount} possible states)`);
141
+ }
142
+ else {
143
+ this.issues.push(`Blockstates for ${queriedBlock.name} are not defined`);
144
+ }
145
+ }
112
146
  return;
147
+ }
113
148
  const modelsResolved = [];
114
149
  let part = 0;
115
150
  for (const model of applyModels) {
@@ -141,8 +176,11 @@ export class AssetsParser {
141
176
  this.resolvedModel = {};
142
177
  }
143
178
  const modelData = this.blockModelsStore.get(this.version, model);
144
- if (!modelData)
179
+ if (!modelData) {
180
+ this.issues.push(`Model ${model} not found. Ensure it is present in assets/${getNamespace(model)}/models/${model}.json`);
145
181
  return;
182
+ }
183
+ this.matchedModels.push(model);
146
184
  return this.getResolvedModelsByModelData(modelData, debugQueryName, clearModel);
147
185
  }
148
186
  getResolvedModelsByModelData(modelData, debugQueryName, clearModel = true) {
@@ -154,8 +192,11 @@ export class AssetsParser {
154
192
  collectedParentModels.push(model);
155
193
  if (model.parent) {
156
194
  const parent = this.blockModelsStore.get(this.version, model.parent);
157
- if (!parent)
195
+ if (!parent) {
196
+ this.issues.push(`Parent model ${model.parent} not found for ${debugQueryName}`);
158
197
  return;
198
+ }
199
+ this.matchedModels.push(`parent:${model.parent}`);
159
200
  collectModels(parent);
160
201
  }
161
202
  };
@@ -192,14 +233,12 @@ export class AssetsParser {
192
233
  originalTexturePath = originalTexturePath.split('/').at(-1).replace('#', '');
193
234
  this.resolvedModel.textures ??= {};
194
235
  if (chain.includes(originalTexturePath)) {
195
- console.warn(`${debugQueryName}: Circular texture reference detected: ${chain.join(' -> ')}`);
236
+ this.issues.push(`${debugQueryName}: Circular texture reference detected: ${chain.join(' -> ')}`);
196
237
  return;
197
238
  }
198
239
  const existingKey = this.resolvedModel.textures[originalTexturePath];
199
240
  if (!existingKey) {
200
- // todo this also needs to be done at the validation stage
201
- // throw new Error(`Cannot resolve texture ${key} to ${value} because it is not defined`)
202
- console.warn(`${debugQueryName}: Cannot resolve texture ${originalTexturePath} for ${_originalKey} because it is not defined`);
241
+ this.issues.push(`${debugQueryName}: Cannot resolve texture ${originalTexturePath} for ${_originalKey} because it is not defined`);
203
242
  return;
204
243
  }
205
244
  else {
@@ -1,7 +1,7 @@
1
1
  import { QueriedBlock } from './assetsParser';
2
2
  import { BlockModel } from './types';
3
3
  export default function worldBlockProvider(blockstatesModels: any, blocksAtlas: any, version: string): {
4
- getAllResolvedModels0_1(block: Omit<QueriedBlock, "stateId">, fallbackVariant?: boolean): ({
4
+ getAllResolvedModels0_1(block: Omit<QueriedBlock, "stateId">, fallbackVariant?: boolean, possibleIssues?: string[], matchedModels?: string[], matchedConditions?: string[]): (({
5
5
  elements: {
6
6
  faces: {
7
7
  [k: string]: {
@@ -34,7 +34,7 @@ export default function worldBlockProvider(blockstatesModels: any, blocksAtlas:
34
34
  z?: number;
35
35
  uvlock?: boolean;
36
36
  weight?: number;
37
- }, "textures" | "elements">)[][];
37
+ }, "textures" | "elements">) | null)[][];
38
38
  transformModel: <T extends BlockModel | (Pick<BlockModel, "textures" | "ao" | "elements"> & {
39
39
  x?: number;
40
40
  y?: number;
@@ -57,15 +57,50 @@ export default function worldBlockProvider(blockstatesModels, blocksAtlas, versi
57
57
  };
58
58
  };
59
59
  return {
60
- getAllResolvedModels0_1(block, fallbackVariant = false) {
60
+ getAllResolvedModels0_1(block, fallbackVariant = false, possibleIssues = [], matchedModels = [], matchedConditions = []) {
61
+ assetsParser.issues = [];
62
+ assetsParser.matchedModels = [];
63
+ assetsParser.matchedConditions = [];
61
64
  const modelsParts = assetsParser.getAllResolvedModels(block, fallbackVariant) ?? [];
65
+ possibleIssues.push(...assetsParser.issues);
66
+ matchedModels.push(...assetsParser.matchedModels);
67
+ matchedConditions.push(...assetsParser.matchedConditions);
68
+ if (!modelsParts.length) {
69
+ possibleIssues.push(`No models found for block ${block.name}`);
70
+ return [];
71
+ }
62
72
  const interestedFaces = ['north', 'east', 'south', 'west', 'up', 'down'];
63
- return modelsParts.map(modelVariants => {
64
- return modelVariants.map(model => {
65
- return transformModel(model, block);
66
- }).filter(a => a.elements?.length);
67
- }).filter(a => a.length);
73
+ try {
74
+ const result = modelsParts.map(modelVariants => {
75
+ return modelVariants.map(model => {
76
+ try {
77
+ return transformModel(model, block);
78
+ }
79
+ catch (e) {
80
+ possibleIssues.push(`Error transforming model for ${block.name}: ${e.message}`);
81
+ return null;
82
+ }
83
+ }).filter(a => a?.elements?.length);
84
+ }).filter(a => a.length);
85
+ if (!result.length) {
86
+ possibleIssues.push(`No valid models after transformation for block ${block.name}`);
87
+ }
88
+ return result;
89
+ }
90
+ catch (e) {
91
+ possibleIssues.push(`Fatal error processing models for ${block.name}: ${e.message}`);
92
+ return [];
93
+ }
68
94
  },
95
+ // getResolvedModels0_1(block: Omit<QueriedBlock, 'stateId'>, fallbackVariant = false) {
96
+ // const modelsParts = assetsParser.getAllResolvedModels(block, fallbackVariant) ?? []
97
+ // const interestedFaces = ['north', 'east', 'south', 'west', 'up', 'down']
98
+ // return modelsParts.map(modelVariants => {
99
+ // return modelVariants.map(model => {
100
+ // return transformModel(model, block);
101
+ // }).filter(a => a.elements?.length)
102
+ // }).filter(a => a.length)
103
+ // },
69
104
  transformModel,
70
105
  getTextureInfo
71
106
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mc-assets",
3
- "version": "0.2.34",
3
+ "version": "0.2.35",
4
4
  "author": "Vitaly Turovsky <vital2580@icloud.com>",
5
5
  "license": "MIT",
6
6
  "files": [