minerender 2.1.0-alpha.140 → 2.1.0-alpha.142
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/browser/esm/assets/BlockEntities.mjs +2 -0
- package/dist/browser/esm/assets/BlockEntities.mjs.map +1 -1
- package/dist/browser/esm/assets/Entities.mjs +29 -3
- package/dist/browser/esm/assets/Entities.mjs.map +1 -1
- package/dist/browser/esm/assets/MineRenderData.mjs +8 -17
- package/dist/browser/esm/assets/MineRenderData.mjs.map +1 -1
- package/dist/browser/esm/assets/_versions/DatasetVersions.mjs +22 -0
- package/dist/browser/esm/assets/_versions/DatasetVersions.mjs.map +1 -0
- package/dist/browser/esm/cache/Caching.mjs +2 -0
- package/dist/browser/esm/cache/Caching.mjs.map +1 -1
- package/dist/browser/esm/index.browser.d.mts +7 -0
- package/dist/browser/esm/world/SectionMesh.mjs +65 -9
- package/dist/browser/esm/world/SectionMesh.mjs.map +1 -1
- package/dist/browser/index.d.ts +7 -0
- package/dist/browser/index.js +240 -140
- package/dist/browser/index.js.map +1 -1
- package/dist/bundle.js +251 -147
- package/dist/bundle.js.map +1 -1
- package/dist/node/index.d.mts +7 -0
- package/dist/node/index.d.ts +7 -0
- package/dist/node/index.js +242 -140
- package/dist/node/index.js.map +1 -1
- package/dist/node/index.mjs +258 -156
- package/dist/node/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/browser/index.js
CHANGED
|
@@ -353,6 +353,7 @@ var init_Caching = __esm({
|
|
|
353
353
|
this.entityTextureCache,
|
|
354
354
|
this.entityAnimationCache,
|
|
355
355
|
this.blockEntityIndexCache,
|
|
356
|
+
this.entityDatasetVersionCache,
|
|
356
357
|
this.fontCache,
|
|
357
358
|
this.unihexCache,
|
|
358
359
|
this.bannerPatternCache,
|
|
@@ -408,6 +409,7 @@ var init_Caching = __esm({
|
|
|
408
409
|
_Caching.entityTextureCache = _Caching.createAssetCache();
|
|
409
410
|
_Caching.entityAnimationCache = _Caching.createAssetCache();
|
|
410
411
|
_Caching.blockEntityIndexCache = _Caching.createAssetCache();
|
|
412
|
+
_Caching.entityDatasetVersionCache = _Caching.createAssetCache();
|
|
411
413
|
_Caching.unihexCache = _Caching.createAssetCache();
|
|
412
414
|
_Caching.fontCache = _Caching.createAssetCache();
|
|
413
415
|
_Caching.bannerPatternCache = _Caching.createAssetCache();
|
|
@@ -3234,23 +3236,39 @@ var init_MinecraftCubeTexture = __esm({
|
|
|
3234
3236
|
}
|
|
3235
3237
|
});
|
|
3236
3238
|
|
|
3239
|
+
// src/assets/_versions/DatasetVersions.ts
|
|
3240
|
+
var parseRelease, compare2, nearestRelease;
|
|
3241
|
+
var init_DatasetVersions = __esm({
|
|
3242
|
+
"src/assets/_versions/DatasetVersions.ts"() {
|
|
3243
|
+
parseRelease = (value) => /^\d+\.\d+(?:\.\d+)?$/.test(value) ? value.split(".").map(Number) : void 0;
|
|
3244
|
+
compare2 = (left, right) => {
|
|
3245
|
+
for (let i = 0; i < 3; i++) {
|
|
3246
|
+
const difference = (left[i] ?? 0) - (right[i] ?? 0);
|
|
3247
|
+
if (difference) return difference;
|
|
3248
|
+
}
|
|
3249
|
+
return 0;
|
|
3250
|
+
};
|
|
3251
|
+
nearestRelease = (requestedVersion, published) => {
|
|
3252
|
+
const requested = parseRelease(requestedVersion);
|
|
3253
|
+
if (!requested) return void 0;
|
|
3254
|
+
const versions = published.map((name) => ({ name, number: parseRelease(name) })).filter((entry) => !!entry.number).sort((left, right) => compare2(left.number, right.number));
|
|
3255
|
+
const sameLine = versions.filter((entry) => entry.number[0] === requested[0] && entry.number[1] === requested[1]);
|
|
3256
|
+
const selected = sameLine.sort((left, right) => Math.abs((left.number[2] ?? 0) - (requested[2] ?? 0)) - Math.abs((right.number[2] ?? 0) - (requested[2] ?? 0)) || compare2(left.number, right.number))[0] ?? versions.filter((entry) => compare2(entry.number, requested) <= 0).pop() ?? versions[0];
|
|
3257
|
+
return selected?.name;
|
|
3258
|
+
};
|
|
3259
|
+
}
|
|
3260
|
+
});
|
|
3261
|
+
|
|
3237
3262
|
// src/assets/MineRenderData.ts
|
|
3238
|
-
var object2,
|
|
3263
|
+
var object2, MineRenderData;
|
|
3239
3264
|
var init_MineRenderData = __esm({
|
|
3240
3265
|
"src/assets/MineRenderData.ts"() {
|
|
3266
|
+
init_DatasetVersions();
|
|
3241
3267
|
init_AssetKey();
|
|
3242
3268
|
init_AssetLoader();
|
|
3243
3269
|
init_AssetParsers();
|
|
3244
3270
|
init_Caching();
|
|
3245
3271
|
object2 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
3246
|
-
release = (value) => /^\d+\.\d+(?:\.\d+)?$/.test(value) ? value.split(".").map(Number) : void 0;
|
|
3247
|
-
compare2 = (left, right) => {
|
|
3248
|
-
for (let i = 0; i < 3; i++) {
|
|
3249
|
-
const difference = (left[i] ?? 0) - (right[i] ?? 0);
|
|
3250
|
-
if (difference) return difference;
|
|
3251
|
-
}
|
|
3252
|
-
return 0;
|
|
3253
|
-
};
|
|
3254
3272
|
MineRenderData = class {
|
|
3255
3273
|
/** Loads one registry. Missing files and invalid data reject the request. */
|
|
3256
3274
|
static async get(dataset, root) {
|
|
@@ -3280,9 +3298,9 @@ var init_MineRenderData = __esm({
|
|
|
3280
3298
|
const scope = AssetLoader.persistentScope;
|
|
3281
3299
|
return this.cached(`resolve:${requestRoot === void 0 ? "sources" : "explicit"}:${root}`, scope, defaultRoot, async () => {
|
|
3282
3300
|
const requestedVersion = root.slice(root.lastIndexOf("/") + 1);
|
|
3283
|
-
let manifest = await this.manifest(root, requestRoot !== void 0 &&
|
|
3301
|
+
let manifest = await this.manifest(root, requestRoot !== void 0 && parseRelease(requestedVersion) ? requestedVersion : void 0, requestRoot);
|
|
3284
3302
|
if (manifest) return { requestedVersion, version: manifest.minecraftVersion, root, manifest };
|
|
3285
|
-
const requested =
|
|
3303
|
+
const requested = parseRelease(requestedVersion);
|
|
3286
3304
|
if (!requested) {
|
|
3287
3305
|
throw new Error(`No MineRender data is published for ${requestedVersion}; automatic fallback requires a release`);
|
|
3288
3306
|
}
|
|
@@ -3294,14 +3312,12 @@ var init_MineRenderData = __esm({
|
|
|
3294
3312
|
}
|
|
3295
3313
|
return value.versions;
|
|
3296
3314
|
});
|
|
3297
|
-
const
|
|
3298
|
-
const sameLine = versions.filter((entry) => entry.number[0] === requested[0] && entry.number[1] === requested[1]);
|
|
3299
|
-
const selected = sameLine.sort((left, right) => Math.abs((left.number[2] ?? 0) - (requested[2] ?? 0)) - Math.abs((right.number[2] ?? 0) - (requested[2] ?? 0)) || compare2(left.number, right.number))[0] ?? versions.filter((entry) => compare2(entry.number, requested) <= 0).pop() ?? versions[0];
|
|
3315
|
+
const selected = nearestRelease(requestedVersion, index.map((entry) => entry.name));
|
|
3300
3316
|
if (!selected) throw new Error(`No compatible MineRender data is published for ${requestedVersion}`);
|
|
3301
|
-
const resolvedRoot = `${base}/${selected
|
|
3302
|
-
manifest = await this.manifest(resolvedRoot, selected
|
|
3303
|
-
if (!manifest) throw new Error(`Missing MineRender manifest for published version ${selected
|
|
3304
|
-
return { requestedVersion, version: selected
|
|
3317
|
+
const resolvedRoot = `${base}/${selected}`;
|
|
3318
|
+
manifest = await this.manifest(resolvedRoot, selected, resolvedRoot);
|
|
3319
|
+
if (!manifest) throw new Error(`Missing MineRender manifest for published version ${selected}`);
|
|
3320
|
+
return { requestedVersion, version: selected, root: resolvedRoot, manifest };
|
|
3305
3321
|
});
|
|
3306
3322
|
}
|
|
3307
3323
|
static async manifest(root, expectedVersion, requestRoot) {
|
|
@@ -4421,118 +4437,12 @@ var init_Biomes = __esm({
|
|
|
4421
4437
|
}
|
|
4422
4438
|
});
|
|
4423
4439
|
|
|
4424
|
-
// src/assets/BlockEntities.ts
|
|
4425
|
-
var import_three9, log10, BlockEntities;
|
|
4426
|
-
var init_BlockEntities = __esm({
|
|
4427
|
-
"src/assets/BlockEntities.ts"() {
|
|
4428
|
-
import_three9 = require("three");
|
|
4429
|
-
init_AssetKey();
|
|
4430
|
-
init_AssetLoader();
|
|
4431
|
-
init_source();
|
|
4432
|
-
init_Caching();
|
|
4433
|
-
init_log();
|
|
4434
|
-
log10 = logger("BlockEntities");
|
|
4435
|
-
BlockEntities = class {
|
|
4436
|
-
/**
|
|
4437
|
-
* Loads the block index of a version. Versions and sources without one yield an empty index, and so does
|
|
4438
|
-
* a failed load: the index is optional, and blocks must not retry or fail with it one by one. The empty
|
|
4439
|
-
* result is cached like any other; `Caching.clear()` or `AssetLoader.setVersion()` forces a new attempt.
|
|
4440
|
-
*/
|
|
4441
|
-
static async getIndex(root) {
|
|
4442
|
-
const key = new AssetKey("entity-models", "blocks", void 0, void 0, void 0, ".json", root);
|
|
4443
|
-
key.rootType = void 0;
|
|
4444
|
-
const index = await Caching.blockEntityIndexCache.get(key.serialize(), async () => {
|
|
4445
|
-
try {
|
|
4446
|
-
return await AssetLoader.get(key, "json" /* JSON */) ?? {};
|
|
4447
|
-
} catch (error) {
|
|
4448
|
-
log10.warn("Could not load the block entity index; block entities are drawn as plain block models", error);
|
|
4449
|
-
return {};
|
|
4450
|
-
}
|
|
4451
|
-
});
|
|
4452
|
-
return index ?? {};
|
|
4453
|
-
}
|
|
4454
|
-
/** The index entry of a block ID such as `minecraft:chest`. */
|
|
4455
|
-
static entry(index, block) {
|
|
4456
|
-
const entry = Object.prototype.hasOwnProperty.call(index, block) ? index[block] : void 0;
|
|
4457
|
-
return Array.isArray(entry?.parts) ? entry : void 0;
|
|
4458
|
-
}
|
|
4459
|
-
/** Selects the parts and placement for a block ID such as `minecraft:chest`; undefined when nothing is drawn. */
|
|
4460
|
-
static resolve(index, block, state = {}) {
|
|
4461
|
-
const entry = this.entry(index, block);
|
|
4462
|
-
if (!entry) return void 0;
|
|
4463
|
-
const value = (property) => String(state[property]).toLowerCase();
|
|
4464
|
-
const parts = entry.parts.filter((part) => Object.entries(part.when ?? {}).every(([property, values]) => String(values).split("|").includes(value(property))));
|
|
4465
|
-
if (!parts.length) return void 0;
|
|
4466
|
-
let rotation = 0;
|
|
4467
|
-
if (entry.rotation) {
|
|
4468
|
-
const selected = value(entry.rotation.property);
|
|
4469
|
-
rotation = "degrees" in entry.rotation ? entry.rotation.degrees[selected] : Number(selected) * entry.rotation.step;
|
|
4470
|
-
if (!Number.isFinite(rotation)) rotation = 0;
|
|
4471
|
-
}
|
|
4472
|
-
return { parts, rotation, translation: entry.translation ?? [0, 0, 0] };
|
|
4473
|
-
}
|
|
4474
|
-
/** Placement in block space (0..16 per axis), applied on top of the model's own transform. */
|
|
4475
|
-
static matrix(resolved, matrix = new import_three9.Matrix4()) {
|
|
4476
|
-
return matrix.makeTranslation(8, 0, 8).multiply(new import_three9.Matrix4().makeRotationY(resolved.rotation * Math.PI / 180)).multiply(new import_three9.Matrix4().makeTranslation(resolved.translation[0] - 8, resolved.translation[1], resolved.translation[2] - 8));
|
|
4477
|
-
}
|
|
4478
|
-
};
|
|
4479
|
-
}
|
|
4480
|
-
});
|
|
4481
|
-
|
|
4482
|
-
// src/assets/DecoratedPots.ts
|
|
4483
|
-
var POTTERY_SHERDS, DecoratedPots;
|
|
4484
|
-
var init_DecoratedPots = __esm({
|
|
4485
|
-
"src/assets/DecoratedPots.ts"() {
|
|
4486
|
-
init_AssetKey();
|
|
4487
|
-
POTTERY_SHERDS = Object.freeze([
|
|
4488
|
-
"angler",
|
|
4489
|
-
"archer",
|
|
4490
|
-
"arms_up",
|
|
4491
|
-
"blade",
|
|
4492
|
-
"brewer",
|
|
4493
|
-
"burn",
|
|
4494
|
-
"danger",
|
|
4495
|
-
"explorer",
|
|
4496
|
-
"flow",
|
|
4497
|
-
"friend",
|
|
4498
|
-
"guster",
|
|
4499
|
-
"heart",
|
|
4500
|
-
"heartbreak",
|
|
4501
|
-
"howl",
|
|
4502
|
-
"miner",
|
|
4503
|
-
"mourner",
|
|
4504
|
-
"plenty",
|
|
4505
|
-
"prize",
|
|
4506
|
-
"scrape",
|
|
4507
|
-
"sheaf",
|
|
4508
|
-
"shelter",
|
|
4509
|
-
"skull",
|
|
4510
|
-
"snort"
|
|
4511
|
-
].map((pattern2) => `minecraft:${pattern2}_pottery_sherd`));
|
|
4512
|
-
DecoratedPots = class {
|
|
4513
|
-
/** Reads up to four item IDs in back, left, right, front order; missing and unmapped items use plain sides. */
|
|
4514
|
-
static getSideTextures(value, root) {
|
|
4515
|
-
const items = value === void 0 ? [] : value;
|
|
4516
|
-
if (!Array.isArray(items) || items.length > 4) throw new Error("pot_decorations must be an array of at most four item IDs");
|
|
4517
|
-
const textures = items.map((item) => {
|
|
4518
|
-
if (!isResourceLocation(item)) throw new Error("Pot decorations must be item identifiers");
|
|
4519
|
-
const id = item.includes(":") ? item : `minecraft:${item}`;
|
|
4520
|
-
return POTTERY_SHERDS.includes(id) ? id.slice("minecraft:".length).replace(/_sherd$/, "_pattern") : "decorated_pot_side";
|
|
4521
|
-
});
|
|
4522
|
-
return Object.fromEntries(["back", "left", "right", "front"].map((side, index) => [
|
|
4523
|
-
side,
|
|
4524
|
-
new AssetKey("minecraft", `decorated_pot/${textures[index] ?? "decorated_pot_side"}`, "textures", "entity", "assets", ".png", root)
|
|
4525
|
-
]));
|
|
4526
|
-
}
|
|
4527
|
-
};
|
|
4528
|
-
}
|
|
4529
|
-
});
|
|
4530
|
-
|
|
4531
4440
|
// src/assets/Entities.ts
|
|
4532
4441
|
var Entities;
|
|
4533
4442
|
var init_Entities = __esm({
|
|
4534
4443
|
"src/assets/Entities.ts"() {
|
|
4535
4444
|
init_AssetKey();
|
|
4445
|
+
init_DatasetVersions();
|
|
4536
4446
|
init_AssetLoader();
|
|
4537
4447
|
init_source();
|
|
4538
4448
|
init_Caching();
|
|
@@ -4540,11 +4450,36 @@ var init_Entities = __esm({
|
|
|
4540
4450
|
init_MineRenderError();
|
|
4541
4451
|
init_ModelTextures();
|
|
4542
4452
|
Entities = class {
|
|
4453
|
+
/**
|
|
4454
|
+
* Resolves `root` (default: the active version). Uses the exact dataset when published or when the
|
|
4455
|
+
* version is not a release; otherwise selects the nearest published release, like {@link MineRenderData.resolve}.
|
|
4456
|
+
* Textures keep the requested root.
|
|
4457
|
+
*/
|
|
4458
|
+
static async getDatasetRoot(root) {
|
|
4459
|
+
const requestRoot = (root ?? AssetLoader.ROOT).replace(/\/+$/, "");
|
|
4460
|
+
const requestedVersion = requestRoot.slice(requestRoot.lastIndexOf("/") + 1);
|
|
4461
|
+
const base = requestRoot.slice(0, requestRoot.lastIndexOf("/"));
|
|
4462
|
+
const selected = await Caching.entityDatasetVersionCache.get(root ?? `sources:${AssetLoader.ROOT}`, async () => {
|
|
4463
|
+
const key = new AssetKey("entity-models", "version", void 0, void 0, void 0, ".json", root);
|
|
4464
|
+
key.rootType = void 0;
|
|
4465
|
+
if (!parseRelease(requestedVersion) || await AssetLoader.get(key, "json" /* JSON */) !== void 0) return requestedVersion;
|
|
4466
|
+
const indexKey = new AssetKey("entity-models", "versions", void 0, void 0, void 0, ".json", base);
|
|
4467
|
+
indexKey.rootType = void 0;
|
|
4468
|
+
const index = await AssetLoader.get(indexKey, "json" /* JSON */);
|
|
4469
|
+
if (index === void 0) return requestedVersion;
|
|
4470
|
+
if (!index || typeof index !== "object" || Array.isArray(index) || !Array.isArray(index.versions) || !index.versions.every((entry) => entry && typeof entry === "object" && !Array.isArray(entry) && typeof entry.name === "string")) {
|
|
4471
|
+
throw new MineRenderError(`Invalid entity model version index at ${base}/entity-models/versions.json`);
|
|
4472
|
+
}
|
|
4473
|
+
return nearestRelease(requestedVersion, index.versions.map((entry) => entry.name)) ?? requestedVersion;
|
|
4474
|
+
});
|
|
4475
|
+
return selected === requestedVersion ? root : `${base}/${selected}`;
|
|
4476
|
+
}
|
|
4543
4477
|
/** Lists model paths in the `minecraft` namespace, including subdirectories and excluding `.json`. */
|
|
4544
4478
|
static async getEntityList() {
|
|
4479
|
+
const root = await this.getDatasetRoot();
|
|
4545
4480
|
const collect = async (path) => {
|
|
4546
4481
|
const prefix2 = path ? `${path}/` : "";
|
|
4547
|
-
const key = new AssetKey(DEFAULT_NAMESPACE, `${prefix2}_list`, void 0, void 0, "entity-models", ".json");
|
|
4482
|
+
const key = new AssetKey(DEFAULT_NAMESPACE, `${prefix2}_list`, void 0, void 0, "entity-models", ".json", root);
|
|
4548
4483
|
const list2 = await Caching.listAssetCache.get(key.serialize(), () => AssetLoader.get(key, "list" /* LIST */));
|
|
4549
4484
|
if (!list2) return [];
|
|
4550
4485
|
const files = list2.files.filter((file) => file.endsWith(".json") && file !== "_list.json").map((file) => `${prefix2}${file.slice(0, -5)}`);
|
|
@@ -4555,7 +4490,7 @@ var init_Entities = __esm({
|
|
|
4555
4490
|
}
|
|
4556
4491
|
static async getModelFile(modelKey) {
|
|
4557
4492
|
const path = isAssetKey(modelKey) ? modelKey.getFullPath() : modelKey.path;
|
|
4558
|
-
const key = new AssetKey(modelKey.namespace, path, void 0, void 0, "entity-models", ".json", isAssetKey(modelKey) ? modelKey.root : void 0);
|
|
4493
|
+
const key = new AssetKey(modelKey.namespace, path, void 0, void 0, "entity-models", ".json", await this.getDatasetRoot(isAssetKey(modelKey) ? modelKey.root : void 0));
|
|
4559
4494
|
return Caching.entityModelCache.get(key.serialize(), () => AssetLoader.get(key, "json" /* JSON */));
|
|
4560
4495
|
}
|
|
4561
4496
|
/** Returns selectable geometry-layer names, or an empty list when the model is missing. */
|
|
@@ -4616,7 +4551,7 @@ var init_Entities = __esm({
|
|
|
4616
4551
|
*/
|
|
4617
4552
|
static async getAnimations(modelKey) {
|
|
4618
4553
|
const path = isAssetKey(modelKey) ? modelKey.getFullPath() : modelKey.path;
|
|
4619
|
-
const key = new AssetKey(modelKey.namespace, path, void 0, void 0, "entity-models/animations", ".json", isAssetKey(modelKey) ? modelKey.root : void 0);
|
|
4554
|
+
const key = new AssetKey(modelKey.namespace, path, void 0, void 0, "entity-models/animations", ".json", await this.getDatasetRoot(isAssetKey(modelKey) ? modelKey.root : void 0));
|
|
4620
4555
|
const file = await Caching.entityAnimationCache.get(key.serialize(), () => AssetLoader.get(key, "json" /* JSON */));
|
|
4621
4556
|
return file?.animations;
|
|
4622
4557
|
}
|
|
@@ -4658,6 +4593,115 @@ var init_Entities = __esm({
|
|
|
4658
4593
|
}
|
|
4659
4594
|
});
|
|
4660
4595
|
|
|
4596
|
+
// src/assets/BlockEntities.ts
|
|
4597
|
+
var import_three9, log10, BlockEntities;
|
|
4598
|
+
var init_BlockEntities = __esm({
|
|
4599
|
+
"src/assets/BlockEntities.ts"() {
|
|
4600
|
+
import_three9 = require("three");
|
|
4601
|
+
init_AssetKey();
|
|
4602
|
+
init_Entities();
|
|
4603
|
+
init_AssetLoader();
|
|
4604
|
+
init_source();
|
|
4605
|
+
init_Caching();
|
|
4606
|
+
init_log();
|
|
4607
|
+
log10 = logger("BlockEntities");
|
|
4608
|
+
BlockEntities = class {
|
|
4609
|
+
/**
|
|
4610
|
+
* Loads the block index of a version. Versions and sources without one yield an empty index, and so does
|
|
4611
|
+
* a failed load: the index is optional, and blocks must not retry or fail with it one by one. The empty
|
|
4612
|
+
* result is cached like any other; `Caching.clear()` or `AssetLoader.setVersion()` forces a new attempt.
|
|
4613
|
+
*/
|
|
4614
|
+
static async getIndex(root) {
|
|
4615
|
+
const key = new AssetKey("entity-models", "blocks", void 0, void 0, void 0, ".json", root);
|
|
4616
|
+
key.rootType = void 0;
|
|
4617
|
+
const index = await Caching.blockEntityIndexCache.get(key.serialize(), async () => {
|
|
4618
|
+
try {
|
|
4619
|
+
key.root = await Entities.getDatasetRoot(root);
|
|
4620
|
+
return await AssetLoader.get(key, "json" /* JSON */) ?? {};
|
|
4621
|
+
} catch (error) {
|
|
4622
|
+
log10.warn("Could not load the block entity index; block entities are drawn as plain block models", error);
|
|
4623
|
+
return {};
|
|
4624
|
+
}
|
|
4625
|
+
});
|
|
4626
|
+
return index ?? {};
|
|
4627
|
+
}
|
|
4628
|
+
/** The index entry of a block ID such as `minecraft:chest`. */
|
|
4629
|
+
static entry(index, block) {
|
|
4630
|
+
const entry = Object.prototype.hasOwnProperty.call(index, block) ? index[block] : void 0;
|
|
4631
|
+
return Array.isArray(entry?.parts) ? entry : void 0;
|
|
4632
|
+
}
|
|
4633
|
+
/** Selects the parts and placement for a block ID such as `minecraft:chest`; undefined when nothing is drawn. */
|
|
4634
|
+
static resolve(index, block, state = {}) {
|
|
4635
|
+
const entry = this.entry(index, block);
|
|
4636
|
+
if (!entry) return void 0;
|
|
4637
|
+
const value = (property) => String(state[property]).toLowerCase();
|
|
4638
|
+
const parts = entry.parts.filter((part) => Object.entries(part.when ?? {}).every(([property, values]) => String(values).split("|").includes(value(property))));
|
|
4639
|
+
if (!parts.length) return void 0;
|
|
4640
|
+
let rotation = 0;
|
|
4641
|
+
if (entry.rotation) {
|
|
4642
|
+
const selected = value(entry.rotation.property);
|
|
4643
|
+
rotation = "degrees" in entry.rotation ? entry.rotation.degrees[selected] : Number(selected) * entry.rotation.step;
|
|
4644
|
+
if (!Number.isFinite(rotation)) rotation = 0;
|
|
4645
|
+
}
|
|
4646
|
+
return { parts, rotation, translation: entry.translation ?? [0, 0, 0] };
|
|
4647
|
+
}
|
|
4648
|
+
/** Placement in block space (0..16 per axis), applied on top of the model's own transform. */
|
|
4649
|
+
static matrix(resolved, matrix = new import_three9.Matrix4()) {
|
|
4650
|
+
return matrix.makeTranslation(8, 0, 8).multiply(new import_three9.Matrix4().makeRotationY(resolved.rotation * Math.PI / 180)).multiply(new import_three9.Matrix4().makeTranslation(resolved.translation[0] - 8, resolved.translation[1], resolved.translation[2] - 8));
|
|
4651
|
+
}
|
|
4652
|
+
};
|
|
4653
|
+
}
|
|
4654
|
+
});
|
|
4655
|
+
|
|
4656
|
+
// src/assets/DecoratedPots.ts
|
|
4657
|
+
var POTTERY_SHERDS, DecoratedPots;
|
|
4658
|
+
var init_DecoratedPots = __esm({
|
|
4659
|
+
"src/assets/DecoratedPots.ts"() {
|
|
4660
|
+
init_AssetKey();
|
|
4661
|
+
POTTERY_SHERDS = Object.freeze([
|
|
4662
|
+
"angler",
|
|
4663
|
+
"archer",
|
|
4664
|
+
"arms_up",
|
|
4665
|
+
"blade",
|
|
4666
|
+
"brewer",
|
|
4667
|
+
"burn",
|
|
4668
|
+
"danger",
|
|
4669
|
+
"explorer",
|
|
4670
|
+
"flow",
|
|
4671
|
+
"friend",
|
|
4672
|
+
"guster",
|
|
4673
|
+
"heart",
|
|
4674
|
+
"heartbreak",
|
|
4675
|
+
"howl",
|
|
4676
|
+
"miner",
|
|
4677
|
+
"mourner",
|
|
4678
|
+
"plenty",
|
|
4679
|
+
"prize",
|
|
4680
|
+
"scrape",
|
|
4681
|
+
"sheaf",
|
|
4682
|
+
"shelter",
|
|
4683
|
+
"skull",
|
|
4684
|
+
"snort"
|
|
4685
|
+
].map((pattern2) => `minecraft:${pattern2}_pottery_sherd`));
|
|
4686
|
+
DecoratedPots = class {
|
|
4687
|
+
/** Reads up to four item IDs in back, left, right, front order; missing and unmapped items use plain sides. */
|
|
4688
|
+
static getSideTextures(value, root) {
|
|
4689
|
+
const items = value === void 0 ? [] : value;
|
|
4690
|
+
if (!Array.isArray(items) || items.length > 4) throw new Error("pot_decorations must be an array of at most four item IDs");
|
|
4691
|
+
const textures = items.map((item) => {
|
|
4692
|
+
if (!isResourceLocation(item)) throw new Error("Pot decorations must be item identifiers");
|
|
4693
|
+
const id = item.includes(":") ? item : `minecraft:${item}`;
|
|
4694
|
+
return POTTERY_SHERDS.includes(id) ? id.slice("minecraft:".length).replace(/_sherd$/, "_pattern") : "decorated_pot_side";
|
|
4695
|
+
});
|
|
4696
|
+
return Object.fromEntries(["back", "left", "right", "front"].map((side, index) => [
|
|
4697
|
+
side,
|
|
4698
|
+
new AssetKey("minecraft", `decorated_pot/${textures[index] ?? "decorated_pot_side"}`, "textures", "entity", "assets", ".png", root)
|
|
4699
|
+
]));
|
|
4700
|
+
}
|
|
4701
|
+
};
|
|
4702
|
+
}
|
|
4703
|
+
});
|
|
4704
|
+
|
|
4661
4705
|
// src/assets/_fonts/Unihex.ts
|
|
4662
4706
|
var Unihex_exports = {};
|
|
4663
4707
|
__export(Unihex_exports, {
|
|
@@ -17978,7 +18022,7 @@ var AnvilWorldSource = class {
|
|
|
17978
18022
|
read.waiters++;
|
|
17979
18023
|
return new Promise((resolve, reject) => {
|
|
17980
18024
|
let finished = false;
|
|
17981
|
-
const
|
|
18025
|
+
const release = () => {
|
|
17982
18026
|
if (finished) return false;
|
|
17983
18027
|
finished = true;
|
|
17984
18028
|
signal?.removeEventListener("abort", abort);
|
|
@@ -17986,7 +18030,7 @@ var AnvilWorldSource = class {
|
|
|
17986
18030
|
return true;
|
|
17987
18031
|
};
|
|
17988
18032
|
const abort = () => {
|
|
17989
|
-
if (!
|
|
18033
|
+
if (!release()) return;
|
|
17990
18034
|
if (!read.waiters && !read.settled) {
|
|
17991
18035
|
if (this.pending.get(key) === read) this.pending.delete(key);
|
|
17992
18036
|
read.controller.abort(signal.reason);
|
|
@@ -17996,10 +18040,10 @@ var AnvilWorldSource = class {
|
|
|
17996
18040
|
signal?.addEventListener("abort", abort, { once: true });
|
|
17997
18041
|
read.promise.then(
|
|
17998
18042
|
(data) => {
|
|
17999
|
-
if (
|
|
18043
|
+
if (release()) resolve(data);
|
|
18000
18044
|
},
|
|
18001
18045
|
(error) => {
|
|
18002
|
-
if (
|
|
18046
|
+
if (release()) reject(error);
|
|
18003
18047
|
}
|
|
18004
18048
|
);
|
|
18005
18049
|
if (signal?.aborted) abort();
|
|
@@ -19607,6 +19651,9 @@ _SectionWorker.initialized = false;
|
|
|
19607
19651
|
var SectionWorker = _SectionWorker;
|
|
19608
19652
|
|
|
19609
19653
|
// src/world/SectionMesh.ts
|
|
19654
|
+
var BLOCK_SIZE = 16;
|
|
19655
|
+
var QUAD_VERTICES = 4;
|
|
19656
|
+
var QUAD_INDICES = 6;
|
|
19610
19657
|
var templateCache = /* @__PURE__ */ new WeakMap();
|
|
19611
19658
|
var WATER_TINT = new import_three46.Color(4159204).toArray();
|
|
19612
19659
|
function toInput(entries, maxAtlasSize, fluids, lighting) {
|
|
@@ -19643,8 +19690,8 @@ function toInput(entries, maxAtlasSize, fluids, lighting) {
|
|
|
19643
19690
|
if (!data) {
|
|
19644
19691
|
const indices = template.geometry.getIndex();
|
|
19645
19692
|
const position = template.geometry.getAttribute("position");
|
|
19646
|
-
const quads = indices.count /
|
|
19647
|
-
if (indices.count %
|
|
19693
|
+
const quads = indices.count / QUAD_INDICES;
|
|
19694
|
+
if (indices.count % QUAD_INDICES !== 0 || position.count !== quads * QUAD_VERTICES) {
|
|
19648
19695
|
throw new RangeError("Section template geometry must hold four vertices and six indices per quad");
|
|
19649
19696
|
}
|
|
19650
19697
|
data = {
|
|
@@ -19654,8 +19701,8 @@ function toInput(entries, maxAtlasSize, fluids, lighting) {
|
|
|
19654
19701
|
uvs: new Float32Array(quads * 8),
|
|
19655
19702
|
uvBounds: new Float32Array(quads * 16),
|
|
19656
19703
|
colors: new Float32Array(quads * 12),
|
|
19657
|
-
shade: new Float32Array(quads *
|
|
19658
|
-
indices: new Uint16Array(quads *
|
|
19704
|
+
shade: new Float32Array(quads * QUAD_VERTICES),
|
|
19705
|
+
indices: new Uint16Array(quads * QUAD_INDICES),
|
|
19659
19706
|
cullFaces: new Uint8Array(template.cullFaces),
|
|
19660
19707
|
biomeTint: template.biomeTint ? new Uint8Array(template.biomeTint) : void 0,
|
|
19661
19708
|
atlas: 0,
|
|
@@ -19667,7 +19714,7 @@ function toInput(entries, maxAtlasSize, fluids, lighting) {
|
|
|
19667
19714
|
const bounds = template.geometry.getAttribute("uvBounds");
|
|
19668
19715
|
const color2 = template.geometry.getAttribute("color");
|
|
19669
19716
|
const shade = template.geometry.getAttribute("shade");
|
|
19670
|
-
for (let vertex = 0; vertex < quads *
|
|
19717
|
+
for (let vertex = 0; vertex < quads * QUAD_VERTICES; vertex++) {
|
|
19671
19718
|
data.positions.set([position.getX(vertex), position.getY(vertex), position.getZ(vertex)], vertex * 3);
|
|
19672
19719
|
data.normals.set([normal.getX(vertex), normal.getY(vertex), normal.getZ(vertex)], vertex * 3);
|
|
19673
19720
|
data.uvs.set([uv.getX(vertex), uv.getY(vertex)], vertex * 2);
|
|
@@ -19680,7 +19727,7 @@ function toInput(entries, maxAtlasSize, fluids, lighting) {
|
|
|
19680
19727
|
data.colors.set([color2?.getX(vertex) ?? 1, color2?.getY(vertex) ?? 1, color2?.getZ(vertex) ?? 1], vertex * 3);
|
|
19681
19728
|
data.shade[vertex] = shade?.getX(vertex) ?? 1;
|
|
19682
19729
|
}
|
|
19683
|
-
for (let i2 = 0; i2 < data.indices.length; i2++) data.indices[i2] = indices.getX(i2) -
|
|
19730
|
+
for (let i2 = 0; i2 < data.indices.length; i2++) data.indices[i2] = indices.getX(i2) - QUAD_VERTICES * Math.floor(i2 / QUAD_INDICES);
|
|
19684
19731
|
templateCache.set(template, data);
|
|
19685
19732
|
}
|
|
19686
19733
|
id = input.templateData.length;
|
|
@@ -19713,6 +19760,54 @@ function toInput(entries, maxAtlasSize, fluids, lighting) {
|
|
|
19713
19760
|
}
|
|
19714
19761
|
return { input, atlases: atlases2 };
|
|
19715
19762
|
}
|
|
19763
|
+
function sortTransparentQuads(mesh) {
|
|
19764
|
+
const index = mesh.geometry.getIndex();
|
|
19765
|
+
if (index.count <= QUAD_INDICES) return;
|
|
19766
|
+
index.setUsage(import_three46.DynamicDrawUsage);
|
|
19767
|
+
const count = index.count / QUAD_INDICES;
|
|
19768
|
+
let source, centers, depths, order;
|
|
19769
|
+
const view = new import_three46.Matrix4(), localCamera = new import_three46.Vector3(), key = new import_three46.Vector3(), previous = new import_three46.Vector3();
|
|
19770
|
+
let previousOrthographic;
|
|
19771
|
+
mesh.onBeforeRender = (_renderer, _scene, camera) => {
|
|
19772
|
+
localCamera.setFromMatrixPosition(camera.matrixWorld).applyMatrix4(view.copy(mesh.matrixWorld).invert());
|
|
19773
|
+
const orthographic = !!camera.isOrthographicCamera;
|
|
19774
|
+
if (orthographic) {
|
|
19775
|
+
view.multiplyMatrices(camera.matrixWorldInverse, mesh.matrixWorld);
|
|
19776
|
+
key.set(view.elements[2], view.elements[6], view.elements[10]);
|
|
19777
|
+
} else {
|
|
19778
|
+
key.copy(localCamera).divideScalar(BLOCK_SIZE).floor();
|
|
19779
|
+
}
|
|
19780
|
+
if (orthographic === previousOrthographic && key.equals(previous)) return;
|
|
19781
|
+
previous.copy(key);
|
|
19782
|
+
previousOrthographic = orthographic;
|
|
19783
|
+
if (!centers) {
|
|
19784
|
+
source = new Uint32Array(index.array);
|
|
19785
|
+
centers = new Float32Array(count * 3);
|
|
19786
|
+
depths = new Float32Array(count);
|
|
19787
|
+
order = Uint32Array.from({ length: count }, (_, quad) => quad);
|
|
19788
|
+
const positions = mesh.geometry.getAttribute("position");
|
|
19789
|
+
for (let quad = 0; quad < count; quad++) {
|
|
19790
|
+
for (let axis = 0; axis < 3; axis++) {
|
|
19791
|
+
let center = 0;
|
|
19792
|
+
for (let corner = 0; corner < QUAD_VERTICES; corner++) center += positions.getComponent(quad * QUAD_VERTICES + corner, axis);
|
|
19793
|
+
centers[quad * 3 + axis] = center / QUAD_VERTICES;
|
|
19794
|
+
}
|
|
19795
|
+
}
|
|
19796
|
+
}
|
|
19797
|
+
for (let quad = 0; quad < count; quad++) {
|
|
19798
|
+
const x = centers[quad * 3], y = centers[quad * 3 + 1], z = centers[quad * 3 + 2];
|
|
19799
|
+
depths[quad] = orthographic ? key.x * x + key.y * y + key.z * z : -((x - localCamera.x) ** 2 + (y - localCamera.y) ** 2 + (z - localCamera.z) ** 2);
|
|
19800
|
+
}
|
|
19801
|
+
order.sort((a, b) => depths[a] - depths[b] || a - b);
|
|
19802
|
+
if (!order.some((quad, offset) => index.array[offset * QUAD_INDICES] !== source[quad * QUAD_INDICES])) return;
|
|
19803
|
+
for (let offset = 0; offset < count; offset++) {
|
|
19804
|
+
for (let indexOffset = 0; indexOffset < QUAD_INDICES; indexOffset++) {
|
|
19805
|
+
index.array[offset * QUAD_INDICES + indexOffset] = source[order[offset] * QUAD_INDICES + indexOffset];
|
|
19806
|
+
}
|
|
19807
|
+
}
|
|
19808
|
+
index.needsUpdate = true;
|
|
19809
|
+
};
|
|
19810
|
+
}
|
|
19716
19811
|
var SectionMesh = class _SectionMesh extends import_three46.Group {
|
|
19717
19812
|
constructor() {
|
|
19718
19813
|
super(...arguments);
|
|
@@ -19722,7 +19817,11 @@ var SectionMesh = class _SectionMesh extends import_three46.Group {
|
|
|
19722
19817
|
/** Returns the owning section cell for a triangle hit on this mesh's merged geometry. */
|
|
19723
19818
|
getBlockIndex(hit) {
|
|
19724
19819
|
if (hit.faceIndex === void 0 || hit.faceIndex === null) return void 0;
|
|
19725
|
-
|
|
19820
|
+
const mesh = hit.object;
|
|
19821
|
+
const owners = this.blockIndices.get(mesh);
|
|
19822
|
+
if (!owners) return void 0;
|
|
19823
|
+
const vertex = mesh.geometry.getIndex().getX(hit.faceIndex * 3);
|
|
19824
|
+
return owners[Math.floor(vertex / QUAD_VERTICES)];
|
|
19726
19825
|
}
|
|
19727
19826
|
/** Builds section-local meshes from visible quads. `maxAtlasSize` limits each atlas dimension in pixels. */
|
|
19728
19827
|
static build(entries, maxAtlasSize = 2048, fluids, lighting) {
|
|
@@ -19758,13 +19857,14 @@ var SectionMesh = class _SectionMesh extends import_three46.Group {
|
|
|
19758
19857
|
const material = Materials.createShadedCanvasMaterial(canvas, transparent, false, true);
|
|
19759
19858
|
material.side = import_three46.FrontSide;
|
|
19760
19859
|
if (page.layer === 2) {
|
|
19860
|
+
material.depthWrite = !material.transparent;
|
|
19761
19861
|
material.side = import_three46.DoubleSide;
|
|
19762
19862
|
material.forceSinglePass = true;
|
|
19763
|
-
material.depthWrite = !material.transparent;
|
|
19764
19863
|
}
|
|
19765
19864
|
material.vertexColors = true;
|
|
19766
19865
|
const texture = material.uniforms?.map?.value ?? material.map;
|
|
19767
19866
|
const mesh = new import_three46.Mesh(geometry, material);
|
|
19867
|
+
if (transparent) sortTransparentQuads(mesh);
|
|
19768
19868
|
section.add(mesh);
|
|
19769
19869
|
section.blockIndices.set(mesh, page.blockIndices);
|
|
19770
19870
|
const unsubscribe = [];
|