minerender 2.1.0-alpha.27 → 2.1.0-alpha.29

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.
@@ -1319,7 +1319,7 @@ var Models = class _Models {
1319
1319
  }
1320
1320
  static async getItemModel(key) {
1321
1321
  const itemKey = new AssetKey(key.namespace, key.path, "items", void 0, key.rootType, ".json", key.root);
1322
- const model = await this.PERSISTENT_CACHE.getOrLoad(itemKey.serialize(), async () => {
1322
+ const model = await this.PERSISTENT_CACHE.getOrLoad(AssetLoader.persistentKey(itemKey.serialize()), async () => {
1323
1323
  const result = await AssetLoader.getFirst([itemKey, key], "json" /* JSON */);
1324
1324
  if (!result) return void 0;
1325
1325
  if (result.key.assetType !== "items") return { ...result.asset, key };
@@ -1365,7 +1365,7 @@ var Models = class _Models {
1365
1365
  }
1366
1366
  const keyStr = key.serialize();
1367
1367
  return Caching.rawModelCache.get(keyStr, (k) => {
1368
- return this.PERSISTENT_CACHE.getOrLoad(keyStr, (k1) => {
1368
+ return this.PERSISTENT_CACHE.getOrLoad(AssetLoader.persistentKey(keyStr), (k1) => {
1369
1369
  return AssetLoader.get(key, "model" /* MODEL */);
1370
1370
  });
1371
1371
  }).then((asset) => {
@@ -1437,7 +1437,7 @@ var BlockStates = class {
1437
1437
  }
1438
1438
  const keyStr = key.serialize();
1439
1439
  return Caching.blockStateCache.get(keyStr, (k) => {
1440
- return this.PERSISTENT_CACHE.getOrLoad(keyStr, (k1) => {
1440
+ return this.PERSISTENT_CACHE.getOrLoad(AssetLoader.persistentKey(keyStr), (k1) => {
1441
1441
  return AssetLoader.get(key, "blockstate" /* BLOCKSTATE */);
1442
1442
  });
1443
1443
  }).then((asset) => {
@@ -1483,6 +1483,14 @@ var Assets = class {
1483
1483
  var AssetSource = class {
1484
1484
  constructor() {
1485
1485
  }
1486
+ /**
1487
+ * Identifies this source's content across sessions for persistent caching. Sources that
1488
+ * cannot tell whether their content changed (an unnamed archive, for example) return
1489
+ * undefined, which keeps their results out of long-lived caches.
1490
+ */
1491
+ get cacheId() {
1492
+ return void 0;
1493
+ }
1486
1494
  };
1487
1495
  var AssetLoadError = class extends Error {
1488
1496
  constructor(source, key, path, cause) {
@@ -1771,6 +1779,9 @@ var HostedAssetSource = class _HostedAssetSource extends AssetSource {
1771
1779
  get root() {
1772
1780
  return this._root;
1773
1781
  }
1782
+ get cacheId() {
1783
+ return `hosted:${this._root}`;
1784
+ }
1774
1785
  get options() {
1775
1786
  return this._options;
1776
1787
  }
@@ -1786,9 +1797,10 @@ var HostedAssetSource = class _HostedAssetSource extends AssetSource {
1786
1797
  // src/assets/source/archive/BrowserArchiveProxy.ts
1787
1798
  import { BlobReader, BlobWriter, ZipReader } from "@zip.js/zip.js";
1788
1799
  var BrowserArchiveProxy = class {
1789
- constructor(blob) {
1800
+ constructor(blob, id) {
1790
1801
  this._blob = blob;
1791
1802
  this._reader = new ZipReader(new BlobReader(this._blob));
1803
+ this.id = id ?? (typeof File !== "undefined" && blob instanceof File ? `${blob.name}:${blob.size}:${blob.lastModified}` : void 0);
1792
1804
  }
1793
1805
  async getEntries() {
1794
1806
  return (await this._reader.getEntries()).map((e) => {
@@ -1813,6 +1825,10 @@ var ArchiveAssetSource = class _ArchiveAssetSource extends AssetSource {
1813
1825
  static blob(blob) {
1814
1826
  return new _ArchiveAssetSource(new BrowserArchiveProxy(blob));
1815
1827
  }
1828
+ get cacheId() {
1829
+ const id = this._archiveProxy.id;
1830
+ return id === void 0 ? void 0 : `archive:${id}`;
1831
+ }
1816
1832
  async getEntries() {
1817
1833
  return this._archiveProxy.getEntries();
1818
1834
  }
@@ -1855,6 +1871,7 @@ var ArchiveAssetSource = class _ArchiveAssetSource extends AssetSource {
1855
1871
 
1856
1872
  // src/assets/AssetLoader.ts
1857
1873
  var p4 = prefix("AssetLoader");
1874
+ var FALLBACK_ROOT = "https://raw.githubusercontent.com/InventivetalentDev/minerender-fallback-assets/master";
1858
1875
  var AssetLoader = class {
1859
1876
  static {
1860
1877
  this.ROOT = DEFAULT_ROOT;
@@ -1862,6 +1879,10 @@ var AssetLoader = class {
1862
1879
  static {
1863
1880
  this._SOURCES = [];
1864
1881
  }
1882
+ static {
1883
+ /** Used when a registered source cannot identify its content, so nothing persists past this session. */
1884
+ this.SESSION_SCOPE = `session:${Date.now().toString(36)}:${Math.random().toString(36).slice(2)}`;
1885
+ }
1865
1886
  static get version() {
1866
1887
  return this.ROOT.substring(this.ROOT.lastIndexOf("/") + 1);
1867
1888
  }
@@ -1876,6 +1897,28 @@ var AssetLoader = class {
1876
1897
  }
1877
1898
  Caching.clear();
1878
1899
  }
1900
+ /**
1901
+ * Scope for persistent cache keys. Empty with only the default vanilla sources, so their
1902
+ * entries stay valid across sessions; otherwise it names every added source (resource packs,
1903
+ * mirrors) so their results never masquerade as vanilla assets after a reload.
1904
+ */
1905
+ static get persistentScope() {
1906
+ const parts = [];
1907
+ for (const { key, source } of this._SOURCES) {
1908
+ const id = source.cacheId;
1909
+ if (key === "mcassets" && id === `hosted:${this.ROOT}`) continue;
1910
+ if (key === "mcassets-fallback" && id === `hosted:${FALLBACK_ROOT}`) continue;
1911
+ if (id === void 0) return this.SESSION_SCOPE;
1912
+ parts.push(`${key}=${id}`);
1913
+ }
1914
+ return parts.join("|");
1915
+ }
1916
+ /** Prefixes a persistent cache key with the current source scope. */
1917
+ static persistentKey(key) {
1918
+ const scope = this.persistentScope;
1919
+ return scope ? `${scope}
1920
+ ${key}` : key;
1921
+ }
1879
1922
  static addSource(key, source, override = true) {
1880
1923
  if (override) {
1881
1924
  const existing = this.removeSource(key);
@@ -1897,7 +1940,7 @@ var AssetLoader = class {
1897
1940
  return void 0;
1898
1941
  }
1899
1942
  static {
1900
- this.addSource("mcassets-fallback", new HostedAssetSource("https://raw.githubusercontent.com/InventivetalentDev/minerender-fallback-assets/master", { retryDefaults: false }));
1943
+ this.addSource("mcassets-fallback", new HostedAssetSource(FALLBACK_ROOT, { retryDefaults: false }));
1901
1944
  this.addSource("mcassets", new HostedAssetSource(this.ROOT, { retryDefaults: false }));
1902
1945
  }
1903
1946
  static async getAll(key, parser) {
@@ -1979,7 +2022,7 @@ var ModelTextures = class {
1979
2022
  }
1980
2023
  const keyStr = key.serialize();
1981
2024
  return Caching.textureMetaCache.get(keyStr, (k) => {
1982
- return this.PERSISTENT_META_CACHE.getOrLoad(keyStr, (k1) => {
2025
+ return this.PERSISTENT_META_CACHE.getOrLoad(AssetLoader.persistentKey(keyStr), (k1) => {
1983
2026
  return AssetLoader.get(key, "meta" /* META */).then((asset) => {
1984
2027
  if (asset)
1985
2028
  asset.key = key;
@@ -4659,7 +4702,9 @@ var BlockObject = class _BlockObject extends SceneObject {
4659
4702
  if (typeof variant.y !== "undefined") {
4660
4703
  rotation.y = toRadians(clampRotationDegrees(typeof variant.x !== "undefined" ? variant.y : 360 - variant.y));
4661
4704
  }
4662
- const model = await Models.getMerged(AssetKey.parse("models", variant.model));
4705
+ const modelKey = AssetKey.parse("models", variant.model);
4706
+ modelKey.root = this.blockState.key?.root;
4707
+ const model = await Models.getMerged(modelKey);
4663
4708
  const options = {
4664
4709
  ...this.options,
4665
4710
  tints: model ? await BlockTints.get(this.blockState.key, this.state, model, this.options.tints) : this.options.tints,
@@ -5451,56 +5496,12 @@ var baseSkinCoordinates = {
5451
5496
  }
5452
5497
  },
5453
5498
  cape: {
5454
- //TODO
5455
- east: {
5456
- uv: [
5457
- 0,
5458
- 36,
5459
- 4,
5460
- 48
5461
- ]
5462
- },
5463
- west: {
5464
- uv: [
5465
- 8,
5466
- 36,
5467
- 12,
5468
- 48
5469
- ]
5470
- },
5471
- north: {
5472
- uv: [
5473
- 4,
5474
- 36,
5475
- 8,
5476
- 48
5477
- ]
5478
- },
5479
- south: {
5480
- uv: [
5481
- 12,
5482
- 36,
5483
- 16,
5484
- 48
5485
- ]
5486
- },
5487
- up: {
5488
- uv: [
5489
- 4,
5490
- 32,
5491
- 8,
5492
- 36
5493
- ]
5494
- },
5495
- down: {
5496
- uv: [
5497
- 8,
5498
- 32,
5499
- 12,
5500
- 36
5501
- ],
5502
- rotation: 180
5503
- }
5499
+ east: { uv: [0, 1, 1, 17] },
5500
+ west: { uv: [11, 1, 12, 17] },
5501
+ north: { uv: [1, 1, 11, 17] },
5502
+ south: { uv: [12, 1, 22, 17] },
5503
+ up: { uv: [11, 1, 1, 0] },
5504
+ down: { uv: [21, 0, 11, 1] }
5504
5505
  }
5505
5506
  };
5506
5507
  var classicSkinTextureCoordinates = {
@@ -5581,14 +5582,110 @@ var slimSkinGeometries = {
5581
5582
 
5582
5583
  // src/skin/scene/SkinObject.ts
5583
5584
  var import_ts_deepmerge7 = __toESM(require_dist());
5585
+
5586
+ // src/skin/SkinTextures.ts
5587
+ import { DataTexture, DoubleSide as DoubleSide2, FrontSide as FrontSide2, MeshBasicMaterial as MeshBasicMaterial3, SRGBColorSpace as SRGBColorSpace3 } from "three";
5588
+ var SkinTextures = class {
5589
+ static async get(src, legacy) {
5590
+ const image = await ImageLoader.getData(src);
5591
+ const scale = image.width / 64;
5592
+ if (!Number.isInteger(scale) || scale < 1 || image.height !== image.width && image.height !== image.width / 2) {
5593
+ throw new MineRenderError(`Invalid skin dimensions ${image.width}x${image.height}; expected 64x64 or 64x32, or an integer-scaled equivalent`);
5594
+ }
5595
+ const isLegacy = legacy ?? image.height === image.width / 2;
5596
+ if (!isLegacy && image.height !== image.width) {
5597
+ throw new MineRenderError(`Invalid skin dimensions ${image.width}x${image.height}; non-legacy skins must be square`);
5598
+ }
5599
+ const slim = !isLegacy && this.isSlim(image, scale);
5600
+ const key = `skin:${serializeImageKey({ src })}:${isLegacy}`;
5601
+ const material = Caching.materialCache.get(key, () => {
5602
+ const pixels = isLegacy ? this.normalizeLegacy(image, scale) : new Uint8Array(image.data);
5603
+ return this.createMaterial(pixels, image.width, image.width);
5604
+ });
5605
+ return { material, slim, legacy: isLegacy };
5606
+ }
5607
+ static async getCape(src) {
5608
+ const image = await ImageLoader.getData(src);
5609
+ const scale = image.width / 64;
5610
+ if (!Number.isInteger(scale) || scale < 1 || image.height !== image.width / 2) {
5611
+ throw new MineRenderError(`Invalid cape dimensions ${image.width}x${image.height}; expected 64x32 or an integer-scaled equivalent`);
5612
+ }
5613
+ return Caching.materialCache.get(`cape:${serializeImageKey({ src })}`, () => {
5614
+ return this.createMaterial(new Uint8Array(image.data), image.width, image.height, false);
5615
+ });
5616
+ }
5617
+ static createMaterial(pixels, width, height, transparent = true) {
5618
+ const texture = Textures.initTextureProps(new DataTexture(pixels, width, height));
5619
+ texture.colorSpace = SRGBColorSpace3;
5620
+ texture.flipY = true;
5621
+ texture.needsUpdate = true;
5622
+ return new MeshBasicMaterial3({ map: texture, transparent, side: transparent ? DoubleSide2 : FrontSide2, alphaTest: transparent ? 0.5 : 0 });
5623
+ }
5624
+ static isSlim(image, scale) {
5625
+ for (const [x, y] of [[46, 52], [54, 20]]) {
5626
+ for (let row = y * scale; row < (y + 12) * scale; row++) {
5627
+ for (let column = x * scale; column < (x + 1) * scale; column++) {
5628
+ if (image.data[(row * image.width + column) * 4 + 3] !== 0) return false;
5629
+ }
5630
+ }
5631
+ }
5632
+ return true;
5633
+ }
5634
+ static normalizeLegacy(image, scale) {
5635
+ const pixels = new Uint8Array(image.width * image.width * 4);
5636
+ pixels.set(image.data.subarray(0, image.width * image.width / 2 * 4));
5637
+ for (const [sx, sy, dx, dy, width, height] of [
5638
+ [4, 16, 20, 48, 4, 4],
5639
+ [8, 16, 24, 48, 4, 4],
5640
+ [0, 20, 24, 52, 4, 12],
5641
+ [4, 20, 20, 52, 4, 12],
5642
+ [8, 20, 16, 52, 4, 12],
5643
+ [12, 20, 28, 52, 4, 12],
5644
+ [44, 16, 36, 48, 4, 4],
5645
+ [48, 16, 40, 48, 4, 4],
5646
+ [40, 20, 40, 52, 4, 12],
5647
+ [44, 20, 36, 52, 4, 12],
5648
+ [48, 20, 32, 52, 4, 12],
5649
+ [52, 20, 44, 52, 4, 12]
5650
+ ]) {
5651
+ for (let y = 0; y < height * scale; y++) {
5652
+ for (let x = 0; x < width * scale; x++) {
5653
+ const source = ((sy * scale + y) * image.width + sx * scale + x) * 4;
5654
+ const target = ((dy * scale + y) * image.width + (dx + width) * scale - 1 - x) * 4;
5655
+ pixels.set(image.data.subarray(source, source + 4), target);
5656
+ }
5657
+ }
5658
+ }
5659
+ let clearHat = true;
5660
+ for (let y = 0; y < 32 * scale; y++) {
5661
+ for (let x = 32 * scale; x < image.width; x++) {
5662
+ if (pixels[(y * image.width + x) * 4 + 3] < 128) clearHat = false;
5663
+ }
5664
+ }
5665
+ for (let y = 0; y < image.width; y++) {
5666
+ for (let x = 0; x < image.width; x++) {
5667
+ const alpha = (y * image.width + x) * 4 + 3;
5668
+ if (x < 32 * scale && y < 16 * scale || y >= 16 * scale && y < 32 * scale || x >= 16 * scale && x < 48 * scale && y >= 48 * scale) {
5669
+ pixels[alpha] = 255;
5670
+ } else if (clearHat && x >= 32 * scale && y < 32 * scale) {
5671
+ pixels[alpha] = 0;
5672
+ }
5673
+ }
5674
+ }
5675
+ return pixels;
5676
+ }
5677
+ };
5678
+
5679
+ // src/skin/scene/SkinObject.ts
5584
5680
  var SkinObject = class extends SceneObject {
5585
5681
  constructor(options) {
5586
5682
  super();
5587
5683
  this.slim = false;
5588
- this.legacy = false;
5589
- this.skinTextureWidth = 64;
5590
- this.skinTextureHeight = 64;
5684
+ this.detectedSlim = false;
5685
+ this.skinLoad = 0;
5686
+ this.capeLoad = 0;
5591
5687
  this.options = (0, import_ts_deepmerge7.default)({}, SceneObject.DEFAULT_OPTIONS, options ?? {});
5688
+ this.slim = this.options.slim ?? false;
5592
5689
  }
5593
5690
  async init() {
5594
5691
  this.createMeshes();
@@ -5597,15 +5694,13 @@ var SkinObject = class extends SceneObject {
5597
5694
  }
5598
5695
  createMeshes() {
5599
5696
  console.log("#createMeshes");
5600
- const mat = Materials.MISSING_TEXTURE;
5697
+ const mat = this.skinMaterial ?? Materials.MISSING_TEXTURE;
5601
5698
  {
5602
5699
  const headGroup = this.createAndAddGroup("head", 0, 28, 0, "y" /* Y */, -4);
5603
5700
  const headGeo = this.getBoxGeometry("head" /* HEAD */);
5604
5701
  const head = this.createAndAddMesh("head", headGroup, headGeo, mat, "y" /* Y */, 4);
5605
- if (!this.legacy) {
5606
- const hatGeo = this.getBoxGeometry("hat" /* HAT */);
5607
- const hat = this.createAndAddMesh("hat", headGroup, hatGeo, mat, "y" /* Y */, 4);
5608
- }
5702
+ const hatGeo = this.getBoxGeometry("hat" /* HAT */);
5703
+ const hat = this.createAndAddMesh("hat", headGroup, hatGeo, mat, "y" /* Y */, 4);
5609
5704
  }
5610
5705
  {
5611
5706
  const bodyGroup = this.createAndAddGroup("body", 0, 18, 0);
@@ -5648,21 +5743,58 @@ var SkinObject = class extends SceneObject {
5648
5743
  }
5649
5744
  console.log("#createMeshes done");
5650
5745
  }
5651
- setSkinTexture(src) {
5746
+ async setSkinTexture(src) {
5652
5747
  if (typeof src === "undefined") return;
5653
- const mat = Materials.getImage({
5654
- texture: { src },
5655
- transparent: true
5656
- });
5657
- for (let part of SKIN_PARTS) {
5658
- let mesh = this.getMeshByName(part);
5748
+ this.skinTextureSrc = src;
5749
+ const load = ++this.skinLoad;
5750
+ const texture = await SkinTextures.get(src, this.options.legacy);
5751
+ if (load !== this.skinLoad) return;
5752
+ this.skinMaterial = texture.material;
5753
+ this.detectedSlim = texture.slim;
5754
+ this.updateSlim(this.options.slim ?? this.detectedSlim);
5755
+ for (const part of SKIN_PARTS) {
5756
+ if (part === "cape" /* CAPE */) continue;
5757
+ const mesh = this.getMeshByName(part);
5659
5758
  if (mesh) {
5660
- mesh.material = mat;
5759
+ mesh.material = texture.material;
5661
5760
  }
5662
5761
  }
5762
+ this.notifyDirty();
5663
5763
  }
5664
- //TODO: cape
5764
+ /** Load a vanilla cape texture, or pass undefined to remove the cape. */
5765
+ async setCapeTexture(src) {
5766
+ const load = ++this.capeLoad;
5767
+ if (src === void 0) {
5768
+ const group = this.getGroupByName("cape" /* CAPE */);
5769
+ if (group) this.remove(group);
5770
+ this.notifyDirty();
5771
+ return;
5772
+ }
5773
+ const material = await SkinTextures.getCape(src);
5774
+ if (load !== this.capeLoad) return;
5775
+ const mesh = this.getMeshByName("cape" /* CAPE */);
5776
+ if (mesh) {
5777
+ mesh.material = material;
5778
+ } else {
5779
+ const group = this.createAndAddGroup("cape" /* CAPE */, 0, 24, 2);
5780
+ group.rotation.set(toRadians(-6), Math.PI, 0);
5781
+ const geometry = this._getBoxGeometryFromDimensions(
5782
+ classicSkinGeometries.cape,
5783
+ classicSkinTextureCoordinates.cape,
5784
+ [64, 32],
5785
+ [64, 32]
5786
+ );
5787
+ const cape = this.createAndAddMesh("cape" /* CAPE */, group, geometry, material);
5788
+ cape.position.set(0, -8, -0.5);
5789
+ }
5790
+ this.notifyDirty();
5791
+ }
5792
+ /** Select the arm model, or pass undefined to use texture detection. */
5665
5793
  setSlim(slim) {
5794
+ this.options.slim = slim;
5795
+ this.updateSlim(slim ?? this.detectedSlim);
5796
+ }
5797
+ updateSlim(slim) {
5666
5798
  if (slim === this.slim) return;
5667
5799
  this.slim = slim;
5668
5800
  for (const part of ["leftArm" /* LEFT_ARM */, "leftSleeve" /* LEFT_SLEEVE */, "rightArm" /* RIGHT_ARM */, "rightSleeve" /* RIGHT_SLEEVE */]) {
@@ -5676,17 +5808,23 @@ var SkinObject = class extends SceneObject {
5676
5808
  if (rightArm) rightArm.position.x -= offset;
5677
5809
  this.notifyDirty();
5678
5810
  }
5679
- setLegacy(legacy) {
5680
- if (legacy !== this.legacy) {
5681
- }
5682
- this.legacy = legacy;
5811
+ /** Select the texture layout, or pass undefined to detect it from image dimensions. */
5812
+ async setLegacy(legacy) {
5813
+ if (legacy === this.options.legacy) return;
5814
+ this.options.legacy = legacy;
5815
+ if (this.skinTextureSrc) await this.setSkinTexture(this.skinTextureSrc);
5816
+ }
5817
+ dispose() {
5818
+ this.skinLoad++;
5819
+ this.capeLoad++;
5820
+ super.dispose();
5683
5821
  }
5684
5822
  //TODO: layer toggles
5685
5823
  getBoxGeometry(part) {
5686
5824
  console.log("slim", this.slim);
5687
5825
  const coordinates = this.slim ? slimSkinTextureCoordinates : classicSkinTextureCoordinates;
5688
5826
  const geometries = this.slim ? slimSkinGeometries : classicSkinGeometries;
5689
- return this._getBoxGeometryFromDimensions(geometries[part], coordinates[part], [64, 64], [this.skinTextureWidth, this.skinTextureHeight]);
5827
+ return this._getBoxGeometryFromDimensions(geometries[part], coordinates[part], [64, 64], [64, 64]);
5690
5828
  }
5691
5829
  };
5692
5830
 
@@ -5799,10 +5937,10 @@ var MineRenderScene = class _MineRenderScene extends Scene2 {
5799
5937
  this.dirty = true;
5800
5938
  const obj = new SkinObject(options);
5801
5939
  obj.scene = this;
5802
- await obj.init();
5803
5940
  if (skin) {
5804
- obj.setSkinTexture(skin);
5941
+ await obj.setSkinTexture(skin);
5805
5942
  }
5943
+ await obj.init();
5806
5944
  parent.add(obj);
5807
5945
  return obj;
5808
5946
  }
@@ -5815,7 +5953,7 @@ function isMineRenderScene(obj) {
5815
5953
  }
5816
5954
 
5817
5955
  // src/renderer/Renderer.ts
5818
- import { AxesHelper as AxesHelper2, GridHelper, OrthographicCamera, PCFSoftShadowMap, PerspectiveCamera, SRGBColorSpace as SRGBColorSpace3, Vector3 as Vector39, WebGLRenderer } from "three";
5956
+ import { AxesHelper as AxesHelper2, GridHelper, OrthographicCamera, PCFSoftShadowMap, PerspectiveCamera, SRGBColorSpace as SRGBColorSpace4, Vector3 as Vector39, WebGLRenderer } from "three";
5819
5957
  var import_ts_deepmerge9 = __toESM(require_dist());
5820
5958
  import Stats from "stats.js";
5821
5959
  import { EffectComposer, RenderPass } from "postprocessing";
@@ -6569,7 +6707,7 @@ var Renderer = class _Renderer {
6569
6707
  renderer.setClearColor(0, 0);
6570
6708
  renderer.shadowMap.enabled = true;
6571
6709
  renderer.shadowMap.type = PCFSoftShadowMap;
6572
- renderer.outputColorSpace = SRGBColorSpace3;
6710
+ renderer.outputColorSpace = SRGBColorSpace4;
6573
6711
  renderer.setSize(this.viewWidth, this.viewHeight);
6574
6712
  return renderer;
6575
6713
  }
@@ -7276,6 +7414,7 @@ export {
7276
7414
  SchematicParser,
7277
7415
  SkinObject,
7278
7416
  SkinPart,
7417
+ SkinTextures,
7279
7418
  Skins,
7280
7419
  StructureParser,
7281
7420
  TextureAtlas,