minerender 2.1.0-alpha.145 → 2.1.0-alpha.147

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.
@@ -240,6 +240,10 @@ var Caching;
240
240
  var init_Caching = __esm({
241
241
  "src/cache/Caching.ts"() {
242
242
  Caching = class _Caching {
243
+ static {
244
+ /** Cached in place of a missing asset. The caches drop `undefined` results, which would request the asset again. */
245
+ this.MISSING = false;
246
+ }
243
247
  static {
244
248
  this._generation = 0;
245
249
  }
@@ -2405,15 +2409,21 @@ var init_ModelTextures = __esm({
2405
2409
  key.extension += ".mcmeta";
2406
2410
  }
2407
2411
  const keyStr = key.serialize();
2408
- return Caching.textureMetaCache.get(keyStr, (k) => {
2409
- return this.PERSISTENT_META_CACHE.getOrLoad(AssetLoader.persistentKey(keyStr), (k1) => {
2410
- return AssetLoader.get(key, "meta" /* META */).then((asset2) => {
2411
- if (asset2)
2412
- asset2.key = key;
2413
- return asset2;
2414
- });
2412
+ const meta = await Caching.textureMetaCache.get(keyStr, (k) => {
2413
+ return this.PERSISTENT_META_CACHE.getOrLoad(AssetLoader.persistentKey(keyStr), async (k1) => {
2414
+ if (AssetLoader.persistentScope === "") {
2415
+ const path = key.getFullPath();
2416
+ const slash = path.lastIndexOf("/");
2417
+ const listKey = new AssetKey(key.namespace, `${path.slice(0, slash + 1)}_list`, "textures", void 0, "assets", ".json", key.root);
2418
+ const list2 = await Caching.listAssetCache.get(listKey.serialize(), () => AssetLoader.get(listKey, "list" /* LIST */)).catch(() => void 0);
2419
+ if (list2 && !list2.files.includes(`${path.slice(slash + 1)}${key.extension}`)) return Caching.MISSING;
2420
+ }
2421
+ const asset2 = await AssetLoader.get(key, "meta" /* META */);
2422
+ if (asset2) asset2.key = key;
2423
+ return asset2 ?? Caching.MISSING;
2415
2424
  });
2416
2425
  });
2426
+ return meta === Caching.MISSING ? void 0 : meta;
2417
2427
  }
2418
2428
  /** Clears persisted texture metadata. Use {@link Caching.clear} to discard in-memory textures and metadata. */
2419
2429
  static async clearCache() {
@@ -4659,26 +4669,27 @@ var init_Entities = __esm({
4659
4669
  const path = isAssetKey(modelKey) ? modelKey.getFullPath() : modelKey.path;
4660
4670
  const root = isAssetKey(modelKey) ? modelKey.root : void 0;
4661
4671
  const key = new AssetKey(modelKey.namespace, path, void 0, void 0, "entity-models", ".json", root);
4662
- return Caching.entityTextureCache.get(key.serialize(), async () => {
4672
+ const texture = await Caching.entityTextureCache.get(key.serialize(), async () => {
4663
4673
  const name = path.split("/").pop();
4664
4674
  for (const candidate of [path, `${path}/${name}`]) {
4665
- const texture2 = new AssetKey(modelKey.namespace, candidate, "textures", "entity", "assets", ".png", root);
4666
- if (await ModelTextures.get(texture2)) return texture2;
4675
+ const texture3 = new AssetKey(modelKey.namespace, candidate, "textures", "entity", "assets", ".png", root);
4676
+ if (await ModelTextures.get(texture3)) return texture3;
4667
4677
  }
4668
4678
  const listKey = new AssetKey(modelKey.namespace, "_list", `${name}_variant`, void 0, "data", ".json", root);
4669
4679
  const list2 = await AssetLoader.get(listKey, "list" /* LIST */);
4670
4680
  const files = list2?.files.filter((file2) => file2.endsWith(".json") && file2 !== "_list.json");
4671
4681
  const file = files?.find((file2) => file2 === "temperate.json") ?? files?.[0];
4672
- if (!file) return void 0;
4682
+ if (!file) return Caching.MISSING;
4673
4683
  const variantKey = new AssetKey(modelKey.namespace, file.slice(0, -5), `${name}_variant`, void 0, "data", ".json", root);
4674
4684
  const variant = await AssetLoader.get(variantKey, "json" /* JSON */);
4675
4685
  const assets = variant?.assets;
4676
4686
  const textureId = variant?.asset_id ?? (typeof assets?.wild === "string" ? assets.wild : Object.values(assets ?? {}).find((value) => typeof value === "string"));
4677
- if (typeof textureId !== "string") return void 0;
4678
- const texture = AssetKey.parse("textures", textureId);
4679
- texture.root = root;
4680
- return texture;
4687
+ if (typeof textureId !== "string") return Caching.MISSING;
4688
+ const texture2 = AssetKey.parse("textures", textureId);
4689
+ texture2.root = root;
4690
+ return texture2;
4681
4691
  });
4692
+ return texture === Caching.MISSING ? void 0 : texture;
4682
4693
  }
4683
4694
  /** @deprecated Use getEntityList(); block entities share the entity dataset. */
4684
4695
  static getBlockList() {
@@ -9505,6 +9516,10 @@ var init_SkinTextures = __esm({
9505
9516
  });
9506
9517
 
9507
9518
  // src/skin/PlayerHeadTextures.ts
9519
+ var PlayerHeadTextures_exports = {};
9520
+ __export(PlayerHeadTextures_exports, {
9521
+ PlayerHeadTextures: () => PlayerHeadTextures
9522
+ });
9508
9523
  var PlayerHeadTextures;
9509
9524
  var init_PlayerHeadTextures = __esm({
9510
9525
  "src/skin/PlayerHeadTextures.ts"() {
@@ -11235,17 +11250,25 @@ var init_BlockObject = __esm({
11235
11250
  if (!key || this.options.displayPosition) return false;
11236
11251
  const generation = this._entityGeneration;
11237
11252
  const created = [];
11253
+ const placement = new Matrix410();
11238
11254
  let resolved;
11239
11255
  try {
11240
11256
  resolved = BlockEntities.resolve(await BlockEntities.getIndex(key.root), key.toNamespacedString(), this.state);
11241
11257
  if (!resolved) return false;
11258
+ BlockEntities.matrix(resolved, placement);
11242
11259
  for (const part of resolved.parts) {
11243
11260
  const [namespace, path] = part.model.includes(":") ? part.model.split(":") : [key.namespace, part.model];
11244
- const texture = part.textureLocation === void 0 ? void 0 : AssetKey.parse("textures", part.textureLocation.replace(/^([^:]+:)?textures\//, "$1"));
11261
+ let texture = part.textureLocation === void 0 ? void 0 : AssetKey.parse("textures", part.textureLocation.replace(/^([^:]+:)?textures\//, "$1"));
11262
+ if (part.textureLocation === void 0 && namespace === "minecraft" && path === "player_head") {
11263
+ const { PlayerHeadTextures: PlayerHeadTextures2 } = await Promise.resolve().then(() => (init_PlayerHeadTextures(), PlayerHeadTextures_exports));
11264
+ texture = (await PlayerHeadTextures2.get(void 0, key.root)).texture;
11265
+ }
11245
11266
  if (texture) texture.root = key.root;
11246
11267
  const entity = await Entities.getEntity(new BasicAssetKey(namespace, path), texture, { layer: part.layer });
11247
11268
  if (!entity) throw new MineRenderError(`Missing entity model ${part.model}`);
11248
- created.push(await this.scene.addEntity(entity, { wireframe: this.options.wireframe }));
11269
+ const object4 = await this.scene.addEntity(entity, { wireframe: this.options.wireframe });
11270
+ this.placeEntity(object4, placement);
11271
+ created.push(object4);
11249
11272
  }
11250
11273
  } catch (error) {
11251
11274
  log15.warn(`Could not draw block entity ${key.toNamespacedString()}, using its block model`, error);
@@ -11256,18 +11279,21 @@ var init_BlockObject = __esm({
11256
11279
  this.removeEntities(created);
11257
11280
  return true;
11258
11281
  }
11259
- BlockEntities.matrix(resolved, this._entityPlacement);
11282
+ this._entityPlacement.copy(placement);
11260
11283
  this._entities = created;
11261
11284
  this.placeEntities();
11262
11285
  this.setVisible(this.visible);
11263
11286
  return true;
11264
11287
  }
11265
11288
  placeEntities() {
11266
- const matrix = new Matrix410().makeTranslation(this.position.x - 8, this.position.y - 8, this.position.z - 8).multiply(this._entityPlacement);
11267
11289
  for (const entity of this._entities) {
11268
- matrix.decompose(entity.position, entity.quaternion, entity.scale);
11290
+ this.placeEntity(entity, this._entityPlacement);
11269
11291
  }
11270
11292
  }
11293
+ placeEntity(entity, placement) {
11294
+ const matrix = new Matrix410().makeTranslation(this.position.x - 8, this.position.y - 8, this.position.z - 8).multiply(placement);
11295
+ matrix.decompose(entity.position, entity.quaternion, entity.scale);
11296
+ }
11271
11297
  get isOccluding() {
11272
11298
  if (!this.visible) {
11273
11299
  return false;
@@ -11561,6 +11587,7 @@ init_PersistentCache();
11561
11587
  var NodeCache = class extends PersistentCache {
11562
11588
  constructor(backing) {
11563
11589
  super(backing);
11590
+ this.pendingWrites = /* @__PURE__ */ new Map();
11564
11591
  }
11565
11592
  ready() {
11566
11593
  return this.initialized ??= this.backing.init();
@@ -11571,7 +11598,14 @@ var NodeCache = class extends PersistentCache {
11571
11598
  }
11572
11599
  async put(key, value) {
11573
11600
  await this.ready();
11574
- return this.backing.setItem(key, value).then((res) => res.content);
11601
+ const previous = this.pendingWrites.get(key);
11602
+ const write = (previous ? previous.catch(() => void 0) : Promise.resolve()).then(() => this.backing.setItem(key, value)).then(() => value);
11603
+ this.pendingWrites.set(key, write);
11604
+ try {
11605
+ return await write;
11606
+ } finally {
11607
+ if (this.pendingWrites.get(key) === write) this.pendingWrites.delete(key);
11608
+ }
11575
11609
  }
11576
11610
  async delete(key) {
11577
11611
  await this.ready();
@@ -11617,7 +11651,10 @@ var NodeEnv = class {
11617
11651
  openCache(name, version2) {
11618
11652
  return new NodeCache(NodePersist.create({
11619
11653
  dir: name + version2,
11620
- encoding: "utf8"
11654
+ encoding: "utf8",
11655
+ // node-persist's unref'd one-second write queue delays loads and lets Node exit before writes finish.
11656
+ // NodeCache serializes writes to each key while allowing different files to write concurrently.
11657
+ writeQueue: false
11621
11658
  }));
11622
11659
  }
11623
11660
  };