minerender 2.1.0-alpha.28 → 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.
package/dist/bundle.js CHANGED
@@ -67364,7 +67364,7 @@ return ${compiler2.callType("value", tagType)}
67364
67364
  }
67365
67365
  static async getItemModel(key) {
67366
67366
  const itemKey = new AssetKey(key.namespace, key.path, "items", void 0, key.rootType, ".json", key.root);
67367
- const model = await this.PERSISTENT_CACHE.getOrLoad(itemKey.serialize(), async () => {
67367
+ const model = await this.PERSISTENT_CACHE.getOrLoad(AssetLoader.persistentKey(itemKey.serialize()), async () => {
67368
67368
  const result = await AssetLoader.getFirst([itemKey, key], "json" /* JSON */);
67369
67369
  if (!result) return void 0;
67370
67370
  if (result.key.assetType !== "items") return { ...result.asset, key };
@@ -67410,7 +67410,7 @@ return ${compiler2.callType("value", tagType)}
67410
67410
  }
67411
67411
  const keyStr = key.serialize();
67412
67412
  return Caching.rawModelCache.get(keyStr, (k4) => {
67413
- return this.PERSISTENT_CACHE.getOrLoad(keyStr, (k1) => {
67413
+ return this.PERSISTENT_CACHE.getOrLoad(AssetLoader.persistentKey(keyStr), (k1) => {
67414
67414
  return AssetLoader.get(key, "model" /* MODEL */);
67415
67415
  });
67416
67416
  }).then((asset) => {
@@ -67485,7 +67485,7 @@ return ${compiler2.callType("value", tagType)}
67485
67485
  }
67486
67486
  const keyStr = key.serialize();
67487
67487
  return Caching.blockStateCache.get(keyStr, (k4) => {
67488
- return this.PERSISTENT_CACHE.getOrLoad(keyStr, (k1) => {
67488
+ return this.PERSISTENT_CACHE.getOrLoad(AssetLoader.persistentKey(keyStr), (k1) => {
67489
67489
  return AssetLoader.get(key, "blockstate" /* BLOCKSTATE */);
67490
67490
  });
67491
67491
  }).then((asset) => {
@@ -67539,6 +67539,14 @@ return ${compiler2.callType("value", tagType)}
67539
67539
  var AssetSource = class {
67540
67540
  constructor() {
67541
67541
  }
67542
+ /**
67543
+ * Identifies this source's content across sessions for persistent caching. Sources that
67544
+ * cannot tell whether their content changed (an unnamed archive, for example) return
67545
+ * undefined, which keeps their results out of long-lived caches.
67546
+ */
67547
+ get cacheId() {
67548
+ return void 0;
67549
+ }
67542
67550
  };
67543
67551
  var AssetLoadError = class extends Error {
67544
67552
  constructor(source, key, path, cause) {
@@ -67800,6 +67808,9 @@ return ${compiler2.callType("value", tagType)}
67800
67808
  get root() {
67801
67809
  return this._root;
67802
67810
  }
67811
+ get cacheId() {
67812
+ return `hosted:${this._root}`;
67813
+ }
67803
67814
  get options() {
67804
67815
  return this._options;
67805
67816
  }
@@ -77324,9 +77335,10 @@ return ${compiler2.callType("value", tagType)}
77324
77335
 
77325
77336
  // src/assets/source/archive/BrowserArchiveProxy.ts
77326
77337
  var BrowserArchiveProxy = class {
77327
- constructor(blob) {
77338
+ constructor(blob, id) {
77328
77339
  this._blob = blob;
77329
77340
  this._reader = new ZipReader(new BlobReader(this._blob));
77341
+ this.id = id ?? (typeof File !== "undefined" && blob instanceof File ? `${blob.name}:${blob.size}:${blob.lastModified}` : void 0);
77330
77342
  }
77331
77343
  async getEntries() {
77332
77344
  return (await this._reader.getEntries()).map((e6) => {
@@ -77351,6 +77363,10 @@ return ${compiler2.callType("value", tagType)}
77351
77363
  static blob(blob) {
77352
77364
  return new _ArchiveAssetSource(new BrowserArchiveProxy(blob));
77353
77365
  }
77366
+ get cacheId() {
77367
+ const id = this._archiveProxy.id;
77368
+ return id === void 0 ? void 0 : `archive:${id}`;
77369
+ }
77354
77370
  async getEntries() {
77355
77371
  return this._archiveProxy.getEntries();
77356
77372
  }
@@ -77403,6 +77419,7 @@ return ${compiler2.callType("value", tagType)}
77403
77419
 
77404
77420
  // src/assets/AssetLoader.ts
77405
77421
  var p7 = prefix("AssetLoader");
77422
+ var FALLBACK_ROOT = "https://raw.githubusercontent.com/InventivetalentDev/minerender-fallback-assets/master";
77406
77423
  var _AssetLoader = class _AssetLoader {
77407
77424
  static get version() {
77408
77425
  return this.ROOT.substring(this.ROOT.lastIndexOf("/") + 1);
@@ -77418,6 +77435,28 @@ return ${compiler2.callType("value", tagType)}
77418
77435
  }
77419
77436
  Caching.clear();
77420
77437
  }
77438
+ /**
77439
+ * Scope for persistent cache keys. Empty with only the default vanilla sources, so their
77440
+ * entries stay valid across sessions; otherwise it names every added source (resource packs,
77441
+ * mirrors) so their results never masquerade as vanilla assets after a reload.
77442
+ */
77443
+ static get persistentScope() {
77444
+ const parts = [];
77445
+ for (const { key, source } of this._SOURCES) {
77446
+ const id = source.cacheId;
77447
+ if (key === "mcassets" && id === `hosted:${this.ROOT}`) continue;
77448
+ if (key === "mcassets-fallback" && id === `hosted:${FALLBACK_ROOT}`) continue;
77449
+ if (id === void 0) return this.SESSION_SCOPE;
77450
+ parts.push(`${key}=${id}`);
77451
+ }
77452
+ return parts.join("|");
77453
+ }
77454
+ /** Prefixes a persistent cache key with the current source scope. */
77455
+ static persistentKey(key) {
77456
+ const scope = this.persistentScope;
77457
+ return scope ? `${scope}
77458
+ ${key}` : key;
77459
+ }
77421
77460
  static addSource(key, source, override = true) {
77422
77461
  if (override) {
77423
77462
  const existing = this.removeSource(key);
@@ -77479,7 +77518,9 @@ return ${compiler2.callType("value", tagType)}
77479
77518
  };
77480
77519
  _AssetLoader.ROOT = DEFAULT_ROOT;
77481
77520
  _AssetLoader._SOURCES = [];
77482
- _AssetLoader.addSource("mcassets-fallback", new HostedAssetSource("https://raw.githubusercontent.com/InventivetalentDev/minerender-fallback-assets/master", { retryDefaults: false }));
77521
+ /** Used when a registered source cannot identify its content, so nothing persists past this session. */
77522
+ _AssetLoader.SESSION_SCOPE = `session:${Date.now().toString(36)}:${Math.random().toString(36).slice(2)}`;
77523
+ _AssetLoader.addSource("mcassets-fallback", new HostedAssetSource(FALLBACK_ROOT, { retryDefaults: false }));
77483
77524
  _AssetLoader.addSource("mcassets", new HostedAssetSource(_AssetLoader.ROOT, { retryDefaults: false }));
77484
77525
  var AssetLoader = _AssetLoader;
77485
77526
 
@@ -77522,7 +77563,7 @@ return ${compiler2.callType("value", tagType)}
77522
77563
  }
77523
77564
  const keyStr = key.serialize();
77524
77565
  return Caching.textureMetaCache.get(keyStr, (k4) => {
77525
- return this.PERSISTENT_META_CACHE.getOrLoad(keyStr, (k1) => {
77566
+ return this.PERSISTENT_META_CACHE.getOrLoad(AssetLoader.persistentKey(keyStr), (k1) => {
77526
77567
  return AssetLoader.get(key, "meta" /* META */).then((asset) => {
77527
77568
  if (asset)
77528
77569
  asset.key = key;
@@ -80375,7 +80416,9 @@ return ${compiler2.callType("value", tagType)}
80375
80416
  if (typeof variant.y !== "undefined") {
80376
80417
  rotation.y = toRadians(clampRotationDegrees(typeof variant.x !== "undefined" ? variant.y : 360 - variant.y));
80377
80418
  }
80378
- const model = await Models.getMerged(AssetKey.parse("models", variant.model));
80419
+ const modelKey = AssetKey.parse("models", variant.model);
80420
+ modelKey.root = this.blockState.key?.root;
80421
+ const model = await Models.getMerged(modelKey);
80379
80422
  const options = {
80380
80423
  ...this.options,
80381
80424
  tints: model ? await BlockTints.get(this.blockState.key, this.state, model, this.options.tints) : this.options.tints,
@@ -81210,56 +81253,12 @@ return ${compiler2.callType("value", tagType)}
81210
81253
  }
81211
81254
  },
81212
81255
  cape: {
81213
- //TODO
81214
- east: {
81215
- uv: [
81216
- 0,
81217
- 36,
81218
- 4,
81219
- 48
81220
- ]
81221
- },
81222
- west: {
81223
- uv: [
81224
- 8,
81225
- 36,
81226
- 12,
81227
- 48
81228
- ]
81229
- },
81230
- north: {
81231
- uv: [
81232
- 4,
81233
- 36,
81234
- 8,
81235
- 48
81236
- ]
81237
- },
81238
- south: {
81239
- uv: [
81240
- 12,
81241
- 36,
81242
- 16,
81243
- 48
81244
- ]
81245
- },
81246
- up: {
81247
- uv: [
81248
- 4,
81249
- 32,
81250
- 8,
81251
- 36
81252
- ]
81253
- },
81254
- down: {
81255
- uv: [
81256
- 8,
81257
- 32,
81258
- 12,
81259
- 36
81260
- ],
81261
- rotation: 180
81262
- }
81256
+ east: { uv: [0, 1, 1, 17] },
81257
+ west: { uv: [11, 1, 12, 17] },
81258
+ north: { uv: [1, 1, 11, 17] },
81259
+ south: { uv: [12, 1, 22, 17] },
81260
+ up: { uv: [11, 1, 1, 0] },
81261
+ down: { uv: [21, 0, 11, 1] }
81263
81262
  }
81264
81263
  };
81265
81264
  var classicSkinTextureCoordinates = {
@@ -81363,14 +81362,27 @@ return ${compiler2.callType("value", tagType)}
81363
81362
  const key = `skin:${serializeImageKey({ src })}:${isLegacy}`;
81364
81363
  const material = Caching.materialCache.get(key, () => {
81365
81364
  const pixels = isLegacy ? this.normalizeLegacy(image, scale) : new Uint8Array(image.data);
81366
- const texture = Textures.initTextureProps(new DataTexture(pixels, image.width, image.width));
81367
- texture.colorSpace = SRGBColorSpace;
81368
- texture.flipY = true;
81369
- texture.needsUpdate = true;
81370
- return new MeshBasicMaterial({ map: texture, transparent: true, side: DoubleSide, alphaTest: 0.5 });
81365
+ return this.createMaterial(pixels, image.width, image.width);
81371
81366
  });
81372
81367
  return { material, slim, legacy: isLegacy };
81373
81368
  }
81369
+ static async getCape(src) {
81370
+ const image = await ImageLoader.getData(src);
81371
+ const scale = image.width / 64;
81372
+ if (!Number.isInteger(scale) || scale < 1 || image.height !== image.width / 2) {
81373
+ throw new MineRenderError(`Invalid cape dimensions ${image.width}x${image.height}; expected 64x32 or an integer-scaled equivalent`);
81374
+ }
81375
+ return Caching.materialCache.get(`cape:${serializeImageKey({ src })}`, () => {
81376
+ return this.createMaterial(new Uint8Array(image.data), image.width, image.height, false);
81377
+ });
81378
+ }
81379
+ static createMaterial(pixels, width, height, transparent = true) {
81380
+ const texture = Textures.initTextureProps(new DataTexture(pixels, width, height));
81381
+ texture.colorSpace = SRGBColorSpace;
81382
+ texture.flipY = true;
81383
+ texture.needsUpdate = true;
81384
+ return new MeshBasicMaterial({ map: texture, transparent, side: transparent ? DoubleSide : FrontSide, alphaTest: transparent ? 0.5 : 0 });
81385
+ }
81374
81386
  static isSlim(image, scale) {
81375
81387
  for (const [x4, y5] of [[46, 52], [54, 20]]) {
81376
81388
  for (let row = y5 * scale; row < (y5 + 12) * scale; row++) {
@@ -81433,6 +81445,7 @@ return ${compiler2.callType("value", tagType)}
81433
81445
  this.slim = false;
81434
81446
  this.detectedSlim = false;
81435
81447
  this.skinLoad = 0;
81448
+ this.capeLoad = 0;
81436
81449
  this.options = (0, import_ts_deepmerge7.default)({}, SceneObject.DEFAULT_OPTIONS, options ?? {});
81437
81450
  this.slim = this.options.slim ?? false;
81438
81451
  }
@@ -81502,6 +81515,7 @@ return ${compiler2.callType("value", tagType)}
81502
81515
  this.detectedSlim = texture.slim;
81503
81516
  this.updateSlim(this.options.slim ?? this.detectedSlim);
81504
81517
  for (const part of SKIN_PARTS) {
81518
+ if (part === "cape" /* CAPE */) continue;
81505
81519
  const mesh = this.getMeshByName(part);
81506
81520
  if (mesh) {
81507
81521
  mesh.material = texture.material;
@@ -81509,7 +81523,34 @@ return ${compiler2.callType("value", tagType)}
81509
81523
  }
81510
81524
  this.notifyDirty();
81511
81525
  }
81512
- //TODO: cape
81526
+ /** Load a vanilla cape texture, or pass undefined to remove the cape. */
81527
+ async setCapeTexture(src) {
81528
+ const load = ++this.capeLoad;
81529
+ if (src === void 0) {
81530
+ const group = this.getGroupByName("cape" /* CAPE */);
81531
+ if (group) this.remove(group);
81532
+ this.notifyDirty();
81533
+ return;
81534
+ }
81535
+ const material = await SkinTextures.getCape(src);
81536
+ if (load !== this.capeLoad) return;
81537
+ const mesh = this.getMeshByName("cape" /* CAPE */);
81538
+ if (mesh) {
81539
+ mesh.material = material;
81540
+ } else {
81541
+ const group = this.createAndAddGroup("cape" /* CAPE */, 0, 24, 2);
81542
+ group.rotation.set(toRadians(-6), Math.PI, 0);
81543
+ const geometry = this._getBoxGeometryFromDimensions(
81544
+ classicSkinGeometries.cape,
81545
+ classicSkinTextureCoordinates.cape,
81546
+ [64, 32],
81547
+ [64, 32]
81548
+ );
81549
+ const cape = this.createAndAddMesh("cape" /* CAPE */, group, geometry, material);
81550
+ cape.position.set(0, -8, -0.5);
81551
+ }
81552
+ this.notifyDirty();
81553
+ }
81513
81554
  /** Select the arm model, or pass undefined to use texture detection. */
81514
81555
  setSlim(slim) {
81515
81556
  this.options.slim = slim;
@@ -81537,6 +81578,7 @@ return ${compiler2.callType("value", tagType)}
81537
81578
  }
81538
81579
  dispose() {
81539
81580
  this.skinLoad++;
81581
+ this.capeLoad++;
81540
81582
  super.dispose();
81541
81583
  }
81542
81584
  //TODO: layer toggles