minerender 2.1.0-alpha.7 → 2.1.0-alpha.8

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
@@ -68483,29 +68483,41 @@ return ${compiler2.callType("value", tagType)}
68483
68483
  static async loadAsync(src) {
68484
68484
  return new Promise((resolve, reject) => {
68485
68485
  const image = this._createImage();
68486
- image.src = src;
68487
68486
  image.onload = () => resolve(image);
68488
- image.onerror = (err) => reject(err);
68487
+ image.onerror = (err) => reject(err instanceof Error ? err : new Error("Failed to decode image"));
68488
+ image.src = src;
68489
68489
  });
68490
68490
  }
68491
68491
  static loadElement(src, onload, onerr) {
68492
68492
  const image = this._createImage();
68493
- image.src = src;
68494
68493
  if (onload)
68495
68494
  image.onload = onload;
68496
68495
  if (onerr)
68497
68496
  image.onerror = onerr;
68497
+ image.src = src;
68498
68498
  return image;
68499
68499
  }
68500
68500
  static async loadData(src) {
68501
68501
  console.debug(p2, "loadData", src);
68502
- return await this.infoToData(await this.getInfo(src));
68502
+ const image = await this.loadCanvasData(src);
68503
+ return image.data.getImageData(0, 0, image.width, image.height);
68503
68504
  }
68504
68505
  static async loadCanvasData(src) {
68505
- return await this.infoToCanvasData(await this.getInfo(src));
68506
+ const keyStr = serializeImageKey({ src });
68507
+ const info = this.getInfo(src);
68508
+ const cached = Caching.rawImageCache.getIfPresent(keyStr);
68509
+ try {
68510
+ return await this.infoToCanvasData(await info);
68511
+ } catch (err) {
68512
+ if (cached && Caching.rawImageCache.getIfPresent(keyStr) === cached) {
68513
+ Caching.rawImageCache.invalidate(keyStr);
68514
+ }
68515
+ throw err;
68516
+ }
68506
68517
  }
68507
68518
  static async infoToCanvasData(info) {
68508
- const image = await _ImageLoader.loadAsync(info.src);
68519
+ const type = info.type === "jpg" ? "jpeg" : info.type ?? "png";
68520
+ const image = await _ImageLoader.loadAsync(`data:image/${type};base64,${info.data.toString("base64")}`);
68509
68521
  const canvas = createCanvas(info.width, info.height);
68510
68522
  const context = canvas.getContext("2d");
68511
68523
  context.drawImage(image, 0, 0);
@@ -68516,11 +68528,8 @@ return ${compiler2.callType("value", tagType)}
68516
68528
  };
68517
68529
  }
68518
68530
  static async infoToData(info) {
68519
- const image = await _ImageLoader.loadAsync(info.src);
68520
- const canvas = createCanvas(info.width, info.height);
68521
- const context = canvas.getContext("2d");
68522
- context.drawImage(image, 0, 0);
68523
- return context.getImageData(0, 0, canvas.width, canvas.height);
68531
+ const image = await this.infoToCanvasData(info);
68532
+ return image.data.getImageData(0, 0, image.width, image.height);
68524
68533
  }
68525
68534
  static async getData(src) {
68526
68535
  const keyStr = serializeImageKey({ src });
@@ -68535,13 +68544,16 @@ return ${compiler2.callType("value", tagType)}
68535
68544
  });
68536
68545
  }
68537
68546
  static async processResponse(response) {
68538
- const src = response.config.url;
68547
+ const src = response.config?.url;
68539
68548
  const data = Buffer.from(response.data);
68540
68549
  const { width, height, type } = Env.provider.imageSize(data);
68550
+ if (!width || !height) {
68551
+ throw new Error("Invalid or unsupported image dimensions");
68552
+ }
68541
68553
  return {
68542
68554
  src,
68543
- width: width || 0,
68544
- height: height || 0,
68555
+ width,
68556
+ height,
68545
68557
  type,
68546
68558
  data
68547
68559
  };
@@ -68558,15 +68570,7 @@ return ${compiler2.callType("value", tagType)}
68558
68570
  return Requests.genericRequest({
68559
68571
  url: src,
68560
68572
  responseType: "arraybuffer"
68561
- }).then(this.processResponse).catch((err) => {
68562
- return {
68563
- src,
68564
- width: 0,
68565
- height: 0,
68566
- type: void 0,
68567
- data: Buffer.from([0])
68568
- };
68569
- });
68573
+ }).then(this.processResponse);
68570
68574
  }
68571
68575
  static async getInfo(src) {
68572
68576
  const keyStr = serializeImageKey({ src });
@@ -68588,16 +68592,22 @@ return ${compiler2.callType("value", tagType)}
68588
68592
 
68589
68593
  // src/texture/TextureLoader.ts
68590
68594
  var TextureLoader = class {
68595
+ /** Reports whether image loading failed, so cached textures can be retried. */
68596
+ static hasFailed(texture) {
68597
+ return this.failedTextures.has(texture);
68598
+ }
68591
68599
  static createTexture() {
68592
68600
  return new Texture();
68593
68601
  }
68594
68602
  static loadInBackground(src, format2 = RGBAFormat, rotation = 0) {
68595
68603
  const texture = this.createTexture();
68596
68604
  texture.colorSpace = SRGBColorSpace;
68597
- const image = ImageLoader.loadElement(src);
68598
- image.onload = function() {
68605
+ const image = ImageLoader.loadElement(src, () => {
68599
68606
  texture.needsUpdate = true;
68600
- };
68607
+ }, (error) => {
68608
+ this.failedTextures.add(texture);
68609
+ console.warn("Failed to load texture", src, error);
68610
+ });
68601
68611
  texture.image = image;
68602
68612
  texture.format = format2;
68603
68613
  texture.rotation = rotation;
@@ -68607,14 +68617,18 @@ return ${compiler2.callType("value", tagType)}
68607
68617
  const texture = new Texture();
68608
68618
  texture.colorSpace = SRGBColorSpace;
68609
68619
  ImageLoader.getData(src).then((image) => {
68610
- texture.needsUpdate = true;
68611
68620
  texture.image = image;
68621
+ texture.needsUpdate = true;
68622
+ }).catch((error) => {
68623
+ this.failedTextures.add(texture);
68624
+ console.warn("Failed to load texture", src, error);
68612
68625
  });
68613
68626
  texture.format = format2;
68614
68627
  texture.rotation = rotation;
68615
68628
  return Textures.initTextureProps(texture);
68616
68629
  }
68617
68630
  };
68631
+ TextureLoader.failedTextures = /* @__PURE__ */ new WeakSet();
68618
68632
 
68619
68633
  // src/texture/Textures.ts
68620
68634
  var Textures = class _Textures {
@@ -68637,6 +68651,10 @@ return ${compiler2.callType("value", tagType)}
68637
68651
  }
68638
68652
  static getImage(key) {
68639
68653
  const keyStr = serializeTextureKey(key);
68654
+ const cached = Caching.textureCache.peek(keyStr);
68655
+ if (cached && TextureLoader.hasFailed(cached)) {
68656
+ Caching.textureCache.invalidate(keyStr);
68657
+ }
68640
68658
  return Caching.textureCache.get(keyStr, (k4) => {
68641
68659
  return _Textures.createImage(key);
68642
68660
  });
@@ -68781,6 +68799,10 @@ return ${compiler2.callType("value", tagType)}
68781
68799
  }
68782
68800
  static getImage(key) {
68783
68801
  const keyStr = serializeMaterialKey(key);
68802
+ const map = Caching.materialCache.peek(keyStr)?.map;
68803
+ if (map && TextureLoader.hasFailed(map)) {
68804
+ Caching.materialCache.invalidate(keyStr);
68805
+ }
68784
68806
  return Caching.materialCache.get(keyStr, (k4) => {
68785
68807
  return _Materials.createImage(key);
68786
68808
  });
@@ -79068,11 +79090,21 @@ return ${compiler2.callType("value", tagType)}
79068
79090
  return this._persistentMetaCache ?? (this._persistentMetaCache = PersistentCache.open("minerender-texturemeta"));
79069
79091
  }
79070
79092
  static async get(key) {
79071
- const asset = await this.preload(key);
79072
- if (asset) {
79073
- return ImageLoader.infoToCanvasData(asset);
79093
+ const keyStr = key.serialize();
79094
+ const pending = this.preload(key);
79095
+ const cached = Caching.textureAssetCache.getIfPresent(keyStr);
79096
+ try {
79097
+ const asset = await pending;
79098
+ if (asset) {
79099
+ return await ImageLoader.infoToCanvasData(asset);
79100
+ }
79101
+ return void 0;
79102
+ } catch (err) {
79103
+ if (cached && Caching.textureAssetCache.getIfPresent(keyStr) === cached) {
79104
+ Caching.textureAssetCache.invalidate(keyStr);
79105
+ }
79106
+ throw err;
79074
79107
  }
79075
- return void 0;
79076
79108
  }
79077
79109
  static async preload(key) {
79078
79110
  const keyStr = key.serialize();
@@ -80367,8 +80399,8 @@ return ${compiler2.callType("value", tagType)}
80367
80399
  dispose() {
80368
80400
  super.dispose();
80369
80401
  }
80370
- async loadTextures() {
80371
- this.imageData = await ModelTextures.get(new AssetKey(
80402
+ get textureKey() {
80403
+ return new AssetKey(
80372
80404
  this.entity.key?.namespace ?? DEFAULT_NAMESPACE,
80373
80405
  this.entity.key.path,
80374
80406
  //TODO: texture may differ from entity name; most of them are in subdirectories for multiple variants etc.
@@ -80376,7 +80408,10 @@ return ${compiler2.callType("value", tagType)}
80376
80408
  "entity",
80377
80409
  "assets",
80378
80410
  ".png"
80379
- ));
80411
+ );
80412
+ }
80413
+ async loadTextures() {
80414
+ this.imageData = await ModelTextures.get(this.textureKey);
80380
80415
  }
80381
80416
  //TODO: abstract this, since extracted model data can be used for entities, blocks, players
80382
80417
  createMeshes(force = false) {
@@ -80409,20 +80444,23 @@ return ${compiler2.callType("value", tagType)}
80409
80444
  this.meshesCreated = true;
80410
80445
  }
80411
80446
  async applyTextures() {
80412
- const textureAsset = await ModelTextures.preload(new AssetKey(
80413
- this.entity.key?.namespace ?? DEFAULT_NAMESPACE,
80414
- this.entity.key.path,
80415
- "textures",
80416
- "entity",
80417
- "assets",
80418
- ".png"
80419
- ));
80420
- if (textureAsset) {
80421
- let mat = Materials.getImage({ texture: { src: textureAsset.src } });
80422
- this.iterateAllMeshes((mesh) => {
80423
- mesh.material = mat;
80424
- });
80425
- }
80447
+ const assetKeyStr = this.textureKey.serialize();
80448
+ const keyStr = `entity:${assetKeyStr}`;
80449
+ let mat = Caching.materialCache.getIfPresent(keyStr);
80450
+ if (!mat) {
80451
+ const pending = this.loadTextures();
80452
+ const cachedAsset = Caching.textureAssetCache.getIfPresent(assetKeyStr);
80453
+ await pending;
80454
+ if (!this.imageData) return;
80455
+ const canvas = this.imageData.data.canvas;
80456
+ const createMaterial = () => Materials.createBasicCanvasMaterial(canvas);
80457
+ mat = cachedAsset && Caching.textureAssetCache.getIfPresent(assetKeyStr) === cachedAsset ? Caching.materialCache.get(keyStr, createMaterial) : createMaterial();
80458
+ this.imageData = void 0;
80459
+ }
80460
+ this.iterateAllMeshes((mesh) => {
80461
+ mesh.material = mat;
80462
+ });
80463
+ this.notifyDirty();
80426
80464
  }
80427
80465
  };
80428
80466
  EntityObject.DEFAULT_OPTIONS = (0, import_ts_deepmerge4.default)({}, SceneObject.DEFAULT_OPTIONS, {});