mc-assets 0.2.29 → 0.2.31

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.
@@ -19,7 +19,24 @@ export declare class AssetsParser {
19
19
  getElements(queriedBlock: Omit<QueriedBlock, 'stateId'>, fallbackVariant?: boolean): 0 | 1 | BlockElement[];
20
20
  private resolvedModel;
21
21
  private getModelsByBlock;
22
- private getResolvedModelsByModel;
22
+ getResolvedModelsByModel(model: string, debugQueryName?: string, clearModel?: boolean): {
23
+ resolvedModel: Pick<BlockModel, "textures" | "ao" | "elements"> & {
24
+ x?: number;
25
+ y?: number;
26
+ z?: number;
27
+ uvlock?: boolean;
28
+ weight?: number;
29
+ };
30
+ } | undefined;
31
+ getResolvedModelsByModelData(modelData: BlockModel, debugQueryName?: string, clearModel?: boolean): {
32
+ resolvedModel: Pick<BlockModel, "textures" | "ao" | "elements"> & {
33
+ x?: number;
34
+ y?: number;
35
+ z?: number;
36
+ uvlock?: boolean;
37
+ weight?: number;
38
+ };
39
+ };
23
40
  getResolvedModelFirst(queriedBlock: Omit<QueriedBlock, 'stateId'>, fallbackVariant?: boolean): (Pick<BlockModel, "textures" | "ao" | "elements"> & {
24
41
  x?: number;
25
42
  y?: number;
@@ -143,6 +143,12 @@ export class AssetsParser {
143
143
  const modelData = this.blockModelsStore.get(this.version, model);
144
144
  if (!modelData)
145
145
  return;
146
+ return this.getResolvedModelsByModelData(modelData, debugQueryName, clearModel);
147
+ }
148
+ getResolvedModelsByModelData(modelData, debugQueryName, clearModel = true) {
149
+ if (clearModel) {
150
+ this.resolvedModel = {};
151
+ }
146
152
  const collectedParentModels = [];
147
153
  const collectModels = (model) => {
148
154
  collectedParentModels.push(model);
@@ -1,6 +1,7 @@
1
1
  import { AtlasParser } from './atlasParser';
2
2
  import { AssetsParser } from './assetsParser';
3
3
  import { BlockModelsStore, BlockStatesStore } from './stores';
4
+ import { BlockModel } from './types';
4
5
  export declare class ItemsRenderer {
5
6
  version: string;
6
7
  itemsAtlasParser: AtlasParser;
@@ -15,7 +16,7 @@ export declare class ItemsRenderer {
15
16
  /** @deprecated */
16
17
  path: string;
17
18
  } | undefined;
18
- tryGetFullBlock(blockName: string, properties?: Record<string, string | boolean>): {
19
+ tryGetFullBlock(model: any, blockName: string): {
19
20
  top: {
20
21
  slice: [number, number, number, number];
21
22
  type: string;
@@ -34,8 +35,9 @@ export declare class ItemsRenderer {
34
35
  /** @deprecated */
35
36
  path: string;
36
37
  };
38
+ resolvedModel: BlockModel;
37
39
  } | undefined;
38
- getItemTexture(itemNameOrModel: string, properties?: Record<string, string | boolean>, exactItemResolve?: boolean): {
40
+ getItemTexture(itemNameOrModel: string, _properties?: Record<string, string | boolean>, exactItemResolve?: boolean): {
39
41
  slice: [number, number, number, number];
40
42
  type: string;
41
43
  /** @deprecated */
@@ -59,5 +61,6 @@ export declare class ItemsRenderer {
59
61
  /** @deprecated */
60
62
  path: string;
61
63
  };
64
+ resolvedModel: BlockModel;
62
65
  } | undefined;
63
66
  }
@@ -34,14 +34,10 @@ export class ItemsRenderer {
34
34
  path: type
35
35
  };
36
36
  }
37
- tryGetFullBlock(blockName, properties = {}) {
37
+ tryGetFullBlock(model, blockName) {
38
38
  if (!this.blocksAtlasParser)
39
39
  return;
40
- const resolvedModelParts = this.assetsParser.getResolvedModelFirst({
41
- name: blockName,
42
- properties,
43
- }, true);
44
- const resolvedModel = resolvedModelParts?.[0];
40
+ const { resolvedModel } = this.assetsParser.getResolvedModelsByModelData(model);
45
41
  if (!resolvedModel?.elements?.length)
46
42
  return;
47
43
  const isAllFullModels = resolvedModel.elements.every(elem => elem.from[0] === 0 && elem.from[1] === 0 && elem.from[2] === 0 && elem.to[0] === 16 && elem.to[1] === 16 && elem.to[2] === 16);
@@ -66,23 +62,35 @@ export class ItemsRenderer {
66
62
  top: topTextureResolved,
67
63
  left: leftTextureResolved,
68
64
  right: rightTextureResolved,
65
+ resolvedModel: resolvedModel
69
66
  };
70
67
  }
71
- getItemTexture(itemNameOrModel, properties = {}, exactItemResolve = false) {
72
- itemNameOrModel = itemNameOrModel.replace(/^minecraft:/, '');
68
+ getItemTexture(itemNameOrModel, _properties = {}, exactItemResolve = false) {
69
+ let [_namespace, _name] = itemNameOrModel.includes(':') ? itemNameOrModel.split(':') : ['minecraft', itemNameOrModel];
70
+ const namespace = _namespace === 'minecraft' ? '' : _namespace;
71
+ const name = _name;
72
+ const itemModelPath = namespace ? `${namespace}:item/${name}` : `item/${name}`;
73
+ const blockModelPath = namespace ? `${namespace}:block/${name}` : `block/${name}`;
74
+ const cleanFullModelPath = namespace ? `${namespace}:${name}` : name;
73
75
  let model;
74
- if (itemNameOrModel.includes('/') || exactItemResolve) {
75
- model = this.modelsStore.get(this.version, itemNameOrModel);
76
+ if (cleanFullModelPath.includes('/') || exactItemResolve) {
77
+ model = this.modelsStore.get(this.version, cleanFullModelPath);
76
78
  }
77
79
  else {
78
- model = this.modelsStore.get(this.version, `item/${itemNameOrModel}`);
79
- if (!model || model.parent?.includes('block/')) {
80
- return this.tryGetFullBlock(itemNameOrModel, properties);
80
+ model = this.modelsStore.get(this.version, itemModelPath);
81
+ let blockModel = model?.parent?.includes('block/');
82
+ if (!model) {
83
+ model = this.modelsStore.get(this.version, blockModelPath);
84
+ if (model)
85
+ blockModel = true;
86
+ }
87
+ if (blockModel) {
88
+ return this.tryGetFullBlock(model, cleanFullModelPath);
81
89
  }
82
90
  }
83
91
  if (!model)
84
92
  return;
85
- const texture = itemNameOrModel.includes('block/') ?
93
+ const texture = cleanFullModelPath.includes('block/') ?
86
94
  // first defined block texture
87
95
  Object.values(model.textures ?? {})[0] :
88
96
  model.textures?.layer0; // classic item texture
@@ -10,11 +10,19 @@ describe('ItemsRenderer', () => {
10
10
  const itemsAtlasParser = new AtlasParser(itemsAtlases, '');
11
11
  const blocksAtlasParser = new AtlasParser(blocksAtlases, '');
12
12
  const renderer = new ItemsRenderer('latest', blockstatesModels, itemsAtlasParser, blocksAtlasParser);
13
+ const getItemTexture = (item) => {
14
+ const result = renderer.getItemTexture(item);
15
+ if (!result)
16
+ return result;
17
+ result['resolvedModel'] = !!result['resolvedModel'];
18
+ return result;
19
+ };
13
20
  describe('getItemTexture', () => {
14
21
  it('items texture', () => {
15
- expect(renderer.getItemTexture('item_frame')).toMatchInlineSnapshot(`
22
+ expect(getItemTexture('item_frame')).toMatchInlineSnapshot(`
16
23
  {
17
24
  "path": "items",
25
+ "resolvedModel": false,
18
26
  "slice": [
19
27
  720,
20
28
  128,
@@ -26,7 +34,7 @@ describe('ItemsRenderer', () => {
26
34
  `);
27
35
  });
28
36
  it('full blocks texture', () => {
29
- expect(renderer.getItemTexture('stone')).toMatchInlineSnapshot(`
37
+ expect(getItemTexture('stone')).toMatchInlineSnapshot(`
30
38
  {
31
39
  "left": {
32
40
  "path": "blocks",
@@ -38,6 +46,7 @@ describe('ItemsRenderer', () => {
38
46
  ],
39
47
  "type": "blocks",
40
48
  },
49
+ "resolvedModel": true,
41
50
  "right": {
42
51
  "path": "blocks",
43
52
  "slice": [
@@ -62,9 +71,10 @@ describe('ItemsRenderer', () => {
62
71
  `);
63
72
  });
64
73
  it('invsprite textures', () => {
65
- expect(renderer.getItemTexture('chest')).toMatchInlineSnapshot(`
74
+ expect(getItemTexture('chest')).toMatchInlineSnapshot(`
66
75
  {
67
76
  "path": "items",
77
+ "resolvedModel": false,
68
78
  "slice": [
69
79
  400,
70
80
  0,
@@ -76,7 +86,8 @@ describe('ItemsRenderer', () => {
76
86
  `);
77
87
  });
78
88
  it('not implemented logic', () => {
79
- expect(renderer.getItemTexture('cut_copper_slab')).toMatchInlineSnapshot(`undefined`);
89
+ expect(getItemTexture('cut_copper_slab')).toMatchInlineSnapshot(`undefined`);
90
+ expect(getItemTexture('bla_bla')).toMatchInlineSnapshot(`undefined`);
80
91
  });
81
92
  });
82
93
  describe('resolveTexture', () => {
@@ -93,6 +104,7 @@ describe('ItemsRenderer', () => {
93
104
  "type": "items",
94
105
  }
95
106
  `);
107
+ expect(renderer.resolveTexture('bla')).toMatchInlineSnapshot(`undefined`);
96
108
  });
97
109
  });
98
110
  });
@@ -1,12 +1,47 @@
1
1
  import { QueriedBlock } from './assetsParser';
2
+ import { BlockModel } from './types';
2
3
  export default function worldBlockProvider(blockstatesModels: any, blocksAtlas: any, version: string): {
3
- getAllResolvedModels0_1(block: Omit<QueriedBlock, "stateId">, fallbackVariant?: boolean): {
4
- ao?: boolean;
4
+ getAllResolvedModels0_1(block: Omit<QueriedBlock, "stateId">, fallbackVariant?: boolean): ({
5
+ elements: {
6
+ faces: {
7
+ [k: string]: {
8
+ texture: {
9
+ u: number;
10
+ v: number;
11
+ su: number;
12
+ sv: number;
13
+ tileIndex: number;
14
+ debugName: string;
15
+ };
16
+ uv?: number[];
17
+ cullface?: string;
18
+ rotation?: number;
19
+ tintindex?: number;
20
+ };
21
+ };
22
+ from: import("./types").BlockElementPos;
23
+ to: import("./types").BlockElementPos;
24
+ rotation?: {
25
+ origin: [number, number, number];
26
+ axis: string;
27
+ angle: number;
28
+ rescale?: boolean;
29
+ };
30
+ }[];
31
+ } & Omit<Pick<BlockModel, "textures" | "ao" | "elements"> & {
32
+ x?: number;
33
+ y?: number;
34
+ z?: number;
35
+ uvlock?: boolean;
36
+ weight?: number;
37
+ }, "textures" | "elements">)[][];
38
+ transformModel: <T extends BlockModel | (Pick<BlockModel, "textures" | "ao" | "elements"> & {
5
39
  x?: number;
6
40
  y?: number;
7
41
  z?: number;
8
42
  uvlock?: boolean;
9
43
  weight?: number;
44
+ })>(model: T, block: Omit<QueriedBlock, "stateId">) => {
10
45
  elements: {
11
46
  faces: {
12
47
  [k: string]: {
@@ -33,8 +68,8 @@ export default function worldBlockProvider(blockstatesModels: any, blocksAtlas:
33
68
  rescale?: boolean;
34
69
  };
35
70
  }[];
36
- }[][];
37
- getTextureInfo(textureName: string): {
71
+ } & Omit<T, "textures" | "elements">;
72
+ getTextureInfo: (textureName: string) => {
38
73
  su: number;
39
74
  sv: number;
40
75
  getLoadedImage: () => Promise<HTMLImageElement>;
@@ -6,62 +6,67 @@ export default function worldBlockProvider(blockstatesModels, blocksAtlas, versi
6
6
  const blockModelsStore = getLoadedModelsStore(blockstatesModels);
7
7
  const assetsParser = new AssetsParser(version, blockStatesStore, blockModelsStore);
8
8
  const atlasParser = new AtlasParser(blocksAtlas, 'latest', 'legacy');
9
+ const getTextureInfo = (textureName) => {
10
+ return atlasParser.getTextureInfo(textureName.replace('block/', '').replace('blocks/', ''), version);
11
+ };
12
+ const transformModel = (model, block) => {
13
+ const { elements, textures, ...rest } = model;
14
+ return {
15
+ // todo validate elements
16
+ elements: elements?.map((elem) => {
17
+ return {
18
+ ...elem,
19
+ faces: Object.fromEntries(Object.entries(elem.faces).map(([faceName, face]) => {
20
+ const texture = face.texture;
21
+ if (!texture)
22
+ throw new Error(`Missing resolved texture ${texture} for face ${faceName} of ${block.name}`);
23
+ const finalTexture = getTextureInfo(texture);
24
+ if (!finalTexture)
25
+ throw new Error(`Missing texture data ${texture} for ${block.name}`);
26
+ const _from = elem.from;
27
+ const _to = elem.to;
28
+ // taken from https://github.com/DragonDev1906/Minecraft-Overviewer/
29
+ const COORDINATE_MAX = 16;
30
+ const uv = (face.uv || {
31
+ // default UVs
32
+ // format: [u1, v1, u2, v2] (u = x, v = y)
33
+ north: [_to[0], COORDINATE_MAX - _to[1], _from[0], COORDINATE_MAX - _from[1]],
34
+ east: [_from[2], COORDINATE_MAX - _to[1], _to[2], COORDINATE_MAX - _from[1]],
35
+ south: [_from[0], COORDINATE_MAX - _to[1], _to[0], COORDINATE_MAX - _from[1]],
36
+ west: [_from[2], COORDINATE_MAX - _to[1], _to[2], COORDINATE_MAX - _from[1]],
37
+ up: [_from[0], _from[2], _to[0], _to[2]],
38
+ down: [_to[0], _from[2], _from[0], _to[2]]
39
+ }[faceName]);
40
+ const su = (uv[2] - uv[0]) / COORDINATE_MAX * finalTexture.su;
41
+ const sv = (uv[3] - uv[1]) / COORDINATE_MAX * finalTexture.sv;
42
+ return [faceName, {
43
+ ...face,
44
+ texture: {
45
+ u: finalTexture.u + uv[0] / 16 * finalTexture.su,
46
+ v: finalTexture.v + uv[1] / 16 * finalTexture.sv,
47
+ su,
48
+ sv,
49
+ tileIndex: finalTexture.tileIndex,
50
+ debugName: texture,
51
+ },
52
+ }];
53
+ }))
54
+ };
55
+ }),
56
+ ...rest
57
+ };
58
+ };
9
59
  return {
10
60
  getAllResolvedModels0_1(block, fallbackVariant = false) {
11
61
  const modelsParts = assetsParser.getAllResolvedModels(block, fallbackVariant) ?? [];
12
62
  const interestedFaces = ['north', 'east', 'south', 'west', 'up', 'down'];
13
63
  return modelsParts.map(modelVariants => {
14
64
  return modelVariants.map(model => {
15
- const { elements, textures, ...rest } = model;
16
- return {
17
- // todo validate elements
18
- elements: elements?.map((elem) => {
19
- return {
20
- ...elem,
21
- faces: Object.fromEntries(Object.entries(elem.faces).map(([faceName, face]) => {
22
- const texture = face.texture;
23
- if (!texture)
24
- throw new Error(`Missing resolved texture ${texture} for face ${faceName} of ${block.name}`);
25
- const finalTexture = this.getTextureInfo(texture);
26
- if (!finalTexture)
27
- throw new Error(`Missing texture data ${texture} for ${block.name}`);
28
- const _from = elem.from;
29
- const _to = elem.to;
30
- // taken from https://github.com/DragonDev1906/Minecraft-Overviewer/
31
- const COORDINATE_MAX = 16;
32
- const uv = (face.uv || {
33
- // default UVs
34
- // format: [u1, v1, u2, v2] (u = x, v = y)
35
- north: [_to[0], COORDINATE_MAX - _to[1], _from[0], COORDINATE_MAX - _from[1]],
36
- east: [_from[2], COORDINATE_MAX - _to[1], _to[2], COORDINATE_MAX - _from[1]],
37
- south: [_from[0], COORDINATE_MAX - _to[1], _to[0], COORDINATE_MAX - _from[1]],
38
- west: [_from[2], COORDINATE_MAX - _to[1], _to[2], COORDINATE_MAX - _from[1]],
39
- up: [_from[0], _from[2], _to[0], _to[2]],
40
- down: [_to[0], _from[2], _from[0], _to[2]]
41
- }[faceName]);
42
- const su = (uv[2] - uv[0]) / COORDINATE_MAX * finalTexture.su;
43
- const sv = (uv[3] - uv[1]) / COORDINATE_MAX * finalTexture.sv;
44
- return [faceName, {
45
- ...face,
46
- texture: {
47
- u: finalTexture.u + uv[0] / 16 * finalTexture.su,
48
- v: finalTexture.v + uv[1] / 16 * finalTexture.sv,
49
- su,
50
- sv,
51
- tileIndex: finalTexture.tileIndex,
52
- debugName: texture,
53
- },
54
- }];
55
- }))
56
- };
57
- }),
58
- ...rest
59
- };
65
+ return transformModel(model, block);
60
66
  }).filter(a => a.elements?.length);
61
67
  }).filter(a => a.length);
62
68
  },
63
- getTextureInfo(textureName) {
64
- return atlasParser.getTextureInfo(textureName.replace('block/', '').replace('blocks/', ''), version);
65
- }
69
+ transformModel,
70
+ getTextureInfo
66
71
  };
67
72
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mc-assets",
3
- "version": "0.2.29",
3
+ "version": "0.2.31",
4
4
  "author": "Vitaly Turovsky <vital2580@icloud.com>",
5
5
  "license": "MIT",
6
6
  "files": [