minerender 2.1.0-alpha.75 → 2.1.0-alpha.76
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/index.d.mts +473 -12
- package/dist/browser/index.d.ts +473 -12
- package/dist/browser/index.js +245 -9
- package/dist/browser/index.js.map +1 -1
- package/dist/browser/index.mjs +245 -9
- package/dist/browser/index.mjs.map +1 -1
- package/dist/bundle.js +245 -9
- package/dist/bundle.js.map +1 -1
- package/dist/node/index.d.mts +473 -12
- package/dist/node/index.d.ts +473 -12
- package/dist/node/index.js +245 -9
- package/dist/node/index.js.map +1 -1
- package/dist/node/index.mjs +245 -9
- package/dist/node/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/node/index.mjs
CHANGED
|
@@ -68,6 +68,7 @@ var init_PersistentCache = __esm({
|
|
|
68
68
|
/** Bump to invalidate every persisted entry. */
|
|
69
69
|
this.VERSION = 2;
|
|
70
70
|
}
|
|
71
|
+
/** Opens a named store in the active environment using the current cache schema version. */
|
|
71
72
|
static open(name) {
|
|
72
73
|
return Env.provider.openCache(name, _PersistentCache.VERSION);
|
|
73
74
|
}
|
|
@@ -329,6 +330,7 @@ var init_Caching = __esm({
|
|
|
329
330
|
this.fontCache
|
|
330
331
|
];
|
|
331
332
|
}
|
|
333
|
+
/** Invalidates in-memory entries so later lookups reload them. Persisted entries are retained. */
|
|
332
334
|
static clear() {
|
|
333
335
|
for (const cache of this.all) {
|
|
334
336
|
cache.invalidateAll();
|
|
@@ -371,6 +373,7 @@ var init_Geometries = __esm({
|
|
|
371
373
|
}
|
|
372
374
|
return geometry;
|
|
373
375
|
}
|
|
376
|
+
/** Returns shared geometry. Use {@link createBox} when the caller needs to modify or dispose it independently. */
|
|
374
377
|
static getBox(key) {
|
|
375
378
|
const keyStr = serializeBoxGeometryKey(key);
|
|
376
379
|
return Caching.boxGeometryCache.get(keyStr, (k) => {
|
|
@@ -554,12 +557,15 @@ var init_Requests = __esm({
|
|
|
554
557
|
static {
|
|
555
558
|
this.mcAssetRequestQueue = new RequestQueue();
|
|
556
559
|
}
|
|
560
|
+
/** Queues a general request. Set `request.signal` to cancel it and `request.timeout` to limit each attempt. */
|
|
557
561
|
static genericRequest(request) {
|
|
558
562
|
return this.genericQueue.request(request);
|
|
559
563
|
}
|
|
564
|
+
/** Queues a request separately from general traffic, using the configured asset base URL for relative paths. */
|
|
560
565
|
static mcAssetRequest(request) {
|
|
561
566
|
return this.mcAssetRequestQueue.request(request);
|
|
562
567
|
}
|
|
568
|
+
/** Sets the base URL for relative asset requests. Use {@link AssetLoader.setVersion} to change Minecraft versions. */
|
|
563
569
|
static setMcAssetRoot(root) {
|
|
564
570
|
this.mcAssetRequestQueue.baseURL = root;
|
|
565
571
|
}
|
|
@@ -612,6 +618,7 @@ var init_WrappedImage = __esm({
|
|
|
612
618
|
}
|
|
613
619
|
return false;
|
|
614
620
|
}
|
|
621
|
+
/** Whether the dimensions form a vertical strip of square frames, without consulting `.mcmeta`. */
|
|
615
622
|
get animated() {
|
|
616
623
|
return this.height > this.width && this.height % this.width === 0;
|
|
617
624
|
}
|
|
@@ -658,6 +665,7 @@ var init_ImageLoader = __esm({
|
|
|
658
665
|
static _createImage() {
|
|
659
666
|
return createImage();
|
|
660
667
|
}
|
|
668
|
+
/** Resolves when an image URL has decoded, or rejects if decoding fails. */
|
|
661
669
|
static async loadAsync(src) {
|
|
662
670
|
return new Promise((resolve, reject) => {
|
|
663
671
|
const image = this._createImage();
|
|
@@ -666,6 +674,7 @@ var init_ImageLoader = __esm({
|
|
|
666
674
|
image.src = src;
|
|
667
675
|
});
|
|
668
676
|
}
|
|
677
|
+
/** Returns an image immediately. Use the callbacks to observe loading, or await {@link loadAsync}. */
|
|
669
678
|
static loadElement(src, onload, onerr) {
|
|
670
679
|
const image = this._createImage();
|
|
671
680
|
if (onload)
|
|
@@ -693,6 +702,7 @@ var init_ImageLoader = __esm({
|
|
|
693
702
|
throw err;
|
|
694
703
|
}
|
|
695
704
|
}
|
|
705
|
+
/** Decodes the supplied bytes into a canvas without fetching the source URL again. */
|
|
696
706
|
static async infoToCanvasData(info) {
|
|
697
707
|
const type = info.type === "jpg" ? "jpeg" : info.type ?? "png";
|
|
698
708
|
const image = await _ImageLoader.loadAsync(`data:image/${type};base64,${info.data.toString("base64")}`);
|
|
@@ -709,12 +719,14 @@ var init_ImageLoader = __esm({
|
|
|
709
719
|
const image = await this.infoToCanvasData(info);
|
|
710
720
|
return image.data.getImageData(0, 0, image.width, image.height);
|
|
711
721
|
}
|
|
722
|
+
/** Returns cached RGBA pixels for an image URL or data URL. Failed loads can be retried. */
|
|
712
723
|
static async getData(src) {
|
|
713
724
|
const keyStr = serializeImageKey({ src });
|
|
714
725
|
return await Caching.imageDataCache.get(keyStr, (k) => {
|
|
715
726
|
return _ImageLoader.loadData(src);
|
|
716
727
|
});
|
|
717
728
|
}
|
|
729
|
+
/** Returns a cached canvas context and dimensions for an image URL or data URL. */
|
|
718
730
|
static async getCanvasData(src) {
|
|
719
731
|
const keyStr = serializeImageKey({ src });
|
|
720
732
|
return await Caching.canvasImageDataCache.get(keyStr, (k) => {
|
|
@@ -814,6 +826,7 @@ var init_TextureLoader = __esm({
|
|
|
814
826
|
texture.rotation = rotation;
|
|
815
827
|
return Textures.initTextureProps(texture);
|
|
816
828
|
}
|
|
829
|
+
/** Loads image pixels in the background. `rotation` is in radians. Check {@link hasFailed} for load failures. */
|
|
817
830
|
static load(src, format2 = RGBAFormat, rotation = 0) {
|
|
818
831
|
const texture = new Texture();
|
|
819
832
|
texture.colorSpace = THREE.SRGBColorSpace;
|
|
@@ -862,6 +875,7 @@ var init_Textures = __esm({
|
|
|
862
875
|
return this.initTextureProps(texture);
|
|
863
876
|
});
|
|
864
877
|
}
|
|
878
|
+
/** Sets nearest-neighbor filters without changing the texture's color space. Returns the same texture. */
|
|
865
879
|
static initTextureProps(texture) {
|
|
866
880
|
texture.magFilter = THREE2.NearestFilter;
|
|
867
881
|
texture.minFilter = THREE2.NearestFilter;
|
|
@@ -874,11 +888,13 @@ var init_Textures = __esm({
|
|
|
874
888
|
static createAsset(key) {
|
|
875
889
|
return new Texture2();
|
|
876
890
|
}
|
|
891
|
+
/** Creates an sRGB color texture from a canvas. */
|
|
877
892
|
static createCanvasTexture(canvas) {
|
|
878
893
|
const texture = new CanvasTexture(canvas);
|
|
879
894
|
texture.colorSpace = THREE2.SRGBColorSpace;
|
|
880
895
|
return this.initTextureProps(texture);
|
|
881
896
|
}
|
|
897
|
+
/** Returns a shared texture immediately and loads its image asynchronously. Failed cached loads are retried. */
|
|
882
898
|
static getImage(key) {
|
|
883
899
|
const keyStr = serializeTextureKey(key);
|
|
884
900
|
const cached2 = Caching.textureCache.peek(keyStr);
|
|
@@ -903,6 +919,7 @@ var init_Materials = __esm({
|
|
|
903
919
|
init_TextureLoader();
|
|
904
920
|
init_Caching();
|
|
905
921
|
Materials = class _Materials {
|
|
922
|
+
/** Shared checkerboard material, created on first access. */
|
|
906
923
|
static get MISSING_TEXTURE() {
|
|
907
924
|
return Caching.materialCache.get("builtin:missing-texture", () => new MeshBasicMaterial({
|
|
908
925
|
map: Textures.getMissing(),
|
|
@@ -1006,6 +1023,7 @@ var init_Materials = __esm({
|
|
|
1006
1023
|
if (tint !== void 0) material.color.multiply(new Color(tint));
|
|
1007
1024
|
return material;
|
|
1008
1025
|
}
|
|
1026
|
+
/** Creates an unlit, transparent GUI material without depth writes or tone mapping. */
|
|
1009
1027
|
static createGuiCanvasMaterial(canvas) {
|
|
1010
1028
|
const material = new MeshBasicMaterial({
|
|
1011
1029
|
map: Textures.createCanvasTexture(canvas),
|
|
@@ -1172,6 +1190,7 @@ var init_Materials = __esm({
|
|
|
1172
1190
|
}
|
|
1173
1191
|
return this.createBasicCanvasMaterial(canvas, transparent, shade);
|
|
1174
1192
|
}
|
|
1193
|
+
/** Returns a shared image material. Use {@link createImage} for a separate material instance. */
|
|
1175
1194
|
static getImage(key) {
|
|
1176
1195
|
const keyStr = serializeMaterialKey(key);
|
|
1177
1196
|
const map = Caching.materialCache.peek(keyStr)?.map;
|
|
@@ -1346,6 +1365,14 @@ var init_AssetKey = __esm({
|
|
|
1346
1365
|
}
|
|
1347
1366
|
};
|
|
1348
1367
|
AssetKey = class _AssetKey extends BasicAssetKey {
|
|
1368
|
+
/**
|
|
1369
|
+
* Creates a key from separate path components. Use {@link parse} for a combined reference.
|
|
1370
|
+
*
|
|
1371
|
+
* @param assetType - Asset directory, such as `models`, `textures`, or `blockstates`.
|
|
1372
|
+
* @param type - Subdirectory, such as `block` or `item`.
|
|
1373
|
+
* @param rootType - Top-level directory, usually `assets` or `data`.
|
|
1374
|
+
* @param root - Base URL override for hosted asset sources.
|
|
1375
|
+
*/
|
|
1349
1376
|
constructor(namespace, path, assetType, type, rootType = "assets", extension = ".json", root) {
|
|
1350
1377
|
super(namespace, path);
|
|
1351
1378
|
this.namespace = namespace;
|
|
@@ -1357,6 +1384,16 @@ var init_AssetKey = __esm({
|
|
|
1357
1384
|
this.root = root;
|
|
1358
1385
|
this.isAssetKey = true;
|
|
1359
1386
|
}
|
|
1387
|
+
/**
|
|
1388
|
+
* Parses an asset reference such as `minecraft:block/stone`.
|
|
1389
|
+
* A missing namespace defaults to the origin's namespace or `minecraft`.
|
|
1390
|
+
*
|
|
1391
|
+
* @param assetType - Asset category, such as `models` or `textures`.
|
|
1392
|
+
* @param str - Path with an optional namespace and file extension.
|
|
1393
|
+
* @param origin - Supplies the asset root, default namespace, and non-texture extension.
|
|
1394
|
+
* @returns A key with the matching extension removed from its path. Textures use `.png`;
|
|
1395
|
+
* other assets use the origin's extension or `.json`.
|
|
1396
|
+
*/
|
|
1360
1397
|
static parse(assetType, str, origin) {
|
|
1361
1398
|
let namespace = origin?.namespace || DEFAULT_NAMESPACE;
|
|
1362
1399
|
if (str.includes(":")) {
|
|
@@ -1388,6 +1425,7 @@ var init_AssetKey = __esm({
|
|
|
1388
1425
|
];
|
|
1389
1426
|
return a.join("/");
|
|
1390
1427
|
}
|
|
1428
|
+
/** Joins the type subdirectory and path without adding a namespace or file extension. */
|
|
1391
1429
|
getFullPath() {
|
|
1392
1430
|
let p10 = [];
|
|
1393
1431
|
if (this.type) {
|
|
@@ -1399,6 +1437,7 @@ var init_AssetKey = __esm({
|
|
|
1399
1437
|
toNamespacedString() {
|
|
1400
1438
|
return this.namespace + ":" + this.getFullPath();
|
|
1401
1439
|
}
|
|
1440
|
+
/** Returns a cache identifier that includes the explicit root or {@link AssetLoader.ROOT}. */
|
|
1402
1441
|
serialize() {
|
|
1403
1442
|
return this.toString();
|
|
1404
1443
|
}
|
|
@@ -1458,6 +1497,7 @@ var init_DisplayTransforms = __esm({
|
|
|
1458
1497
|
const scale = new Vector32(...transform.scale ?? [1, 1, 1]).clampScalar(-4, 4);
|
|
1459
1498
|
return new Matrix4().compose(translation, rotation, scale);
|
|
1460
1499
|
}
|
|
1500
|
+
/** Transforms geometry in place and reverses triangle winding when the matrix reflects it. */
|
|
1461
1501
|
static apply(geometry, matrix) {
|
|
1462
1502
|
geometry.applyMatrix4(matrix);
|
|
1463
1503
|
if (matrix.determinant() < 0) {
|
|
@@ -1485,6 +1525,7 @@ var init_ModelMerger = __esm({
|
|
|
1485
1525
|
init_AssetKey();
|
|
1486
1526
|
init_DisplayTransforms();
|
|
1487
1527
|
ModelMerger = class {
|
|
1528
|
+
/** Loads the parent chain and returns a merged model without modifying the supplied definition. */
|
|
1488
1529
|
static async mergeWithParents(model) {
|
|
1489
1530
|
const models = await this.collectAllParents(model);
|
|
1490
1531
|
let merged = {};
|
|
@@ -1552,6 +1593,7 @@ var init_Models = __esm({
|
|
|
1552
1593
|
static get PERSISTENT_CACHE() {
|
|
1553
1594
|
return this._persistentCache ??= PersistentCache.open("minerender-models");
|
|
1554
1595
|
}
|
|
1596
|
+
/** Lists item filenames from the asset source's `_list.json`, with a legacy model-directory fallback. */
|
|
1555
1597
|
static async getItemList() {
|
|
1556
1598
|
const key = new AssetKey(DEFAULT_NAMESPACE, "_list", "items");
|
|
1557
1599
|
const legacyKey = new AssetKey(DEFAULT_NAMESPACE, "_list", "models", "item");
|
|
@@ -1622,6 +1664,7 @@ var init_Models = __esm({
|
|
|
1622
1664
|
}
|
|
1623
1665
|
throw new Error(`Unsupported item model ${node?.type ?? "definition"} for ${key.toNamespacedString()}`);
|
|
1624
1666
|
}
|
|
1667
|
+
/** Loads one model file without resolving its parents. Returns `undefined` when the file is missing. */
|
|
1625
1668
|
static async getRaw(key) {
|
|
1626
1669
|
if (!key.assetType) {
|
|
1627
1670
|
key.assetType = "models";
|
|
@@ -1641,6 +1684,12 @@ var init_Models = __esm({
|
|
|
1641
1684
|
return asset;
|
|
1642
1685
|
});
|
|
1643
1686
|
}
|
|
1687
|
+
/**
|
|
1688
|
+
* Loads a model and resolves its parent chain. Returns `undefined` when the model is missing.
|
|
1689
|
+
* Item keys use GUI context, false conditions, and zero numeric properties.
|
|
1690
|
+
*
|
|
1691
|
+
* @param key - Model key, for example `AssetKey.parse("models", "minecraft:item/diamond_sword")`.
|
|
1692
|
+
*/
|
|
1644
1693
|
static async getMerged(key) {
|
|
1645
1694
|
if (!key.assetType) {
|
|
1646
1695
|
key.assetType = "models";
|
|
@@ -1653,9 +1702,11 @@ var init_Models = __esm({
|
|
|
1653
1702
|
return _Models.loadAndMerge(key);
|
|
1654
1703
|
});
|
|
1655
1704
|
}
|
|
1705
|
+
/** Alias for {@link getMerged}. */
|
|
1656
1706
|
static async get(key) {
|
|
1657
1707
|
return this.getMerged(key);
|
|
1658
1708
|
}
|
|
1709
|
+
/** Clears persisted models. Use {@link Caching.clear} to also discard in-memory assets. */
|
|
1659
1710
|
static async clearCache() {
|
|
1660
1711
|
return this.PERSISTENT_CACHE.clear();
|
|
1661
1712
|
}
|
|
@@ -1678,6 +1729,7 @@ var init_BlockStates = __esm({
|
|
|
1678
1729
|
return this._persistentCache ??= PersistentCache.open("minerender-blockstates");
|
|
1679
1730
|
}
|
|
1680
1731
|
// BlockState names are hardcoded
|
|
1732
|
+
/** Returns blockstate filenames from the selected version's `_list.json`, or an empty list. */
|
|
1681
1733
|
static async getList() {
|
|
1682
1734
|
const key = new AssetKey(
|
|
1683
1735
|
DEFAULT_NAMESPACE,
|
|
@@ -1698,6 +1750,7 @@ var init_BlockStates = __esm({
|
|
|
1698
1750
|
return AssetLoader.get(key, "json" /* JSON */);
|
|
1699
1751
|
});
|
|
1700
1752
|
}
|
|
1753
|
+
/** Looks up vanilla property definitions for the key's block path, or returns `undefined`. */
|
|
1701
1754
|
static async getDefaultState(key) {
|
|
1702
1755
|
const defaultStates = await this.getDefaultStates();
|
|
1703
1756
|
if (!defaultStates) {
|
|
@@ -1705,6 +1758,7 @@ var init_BlockStates = __esm({
|
|
|
1705
1758
|
}
|
|
1706
1759
|
return defaultStates["minecraft:" + key.path];
|
|
1707
1760
|
}
|
|
1761
|
+
/** Loads a cached blockstate definition for {@link MineRenderScene.addBlock}, or returns `undefined`. */
|
|
1708
1762
|
static async get(key) {
|
|
1709
1763
|
if (!key.assetType) {
|
|
1710
1764
|
key.assetType = "blockstates";
|
|
@@ -1731,6 +1785,7 @@ var init_BlockStates = __esm({
|
|
|
1731
1785
|
}
|
|
1732
1786
|
return Promise.all(promises);
|
|
1733
1787
|
}
|
|
1788
|
+
/** Clears persisted blockstates. Use {@link Caching.clear} to also discard in-memory assets. */
|
|
1734
1789
|
static async clearCache() {
|
|
1735
1790
|
await this.PERSISTENT_CACHE.clear();
|
|
1736
1791
|
}
|
|
@@ -1756,9 +1811,11 @@ var init_Assets = __esm({
|
|
|
1756
1811
|
static parseAssetKey(assetType, str, origin) {
|
|
1757
1812
|
return AssetKey.parse(assetType, str, origin);
|
|
1758
1813
|
}
|
|
1814
|
+
/** Loads a model with its parent chain resolved. See {@link Models.getMerged}. */
|
|
1759
1815
|
static async getModel(key) {
|
|
1760
1816
|
return Models.getMerged(key);
|
|
1761
1817
|
}
|
|
1818
|
+
/** Loads a blockstate definition. See {@link BlockStates.get}. */
|
|
1762
1819
|
static async getBlockState(key) {
|
|
1763
1820
|
return BlockStates.get(key);
|
|
1764
1821
|
}
|
|
@@ -1805,6 +1862,10 @@ var BatchedExecutor;
|
|
|
1805
1862
|
var init_BatchedExecutor = __esm({
|
|
1806
1863
|
"src/util/BatchedExecutor.ts"() {
|
|
1807
1864
|
BatchedExecutor = class {
|
|
1865
|
+
/**
|
|
1866
|
+
* @param interval - Delay between queue runs, in milliseconds.
|
|
1867
|
+
* @param batch - Maximum tasks started per run and maximum tasks active at once.
|
|
1868
|
+
*/
|
|
1808
1869
|
constructor(interval = 1, batch = 30) {
|
|
1809
1870
|
if (!Number.isFinite(interval) || interval < 0) throw new RangeError("Batch interval must be finite and nonnegative");
|
|
1810
1871
|
if (!Number.isInteger(batch) || batch < 1) throw new RangeError("Batch size must be a positive integer");
|
|
@@ -1812,9 +1873,11 @@ var init_BatchedExecutor = __esm({
|
|
|
1812
1873
|
this.batch = batch;
|
|
1813
1874
|
this.queue = new JobQueue2(async (task) => task(), { interval, maxPerRun: batch, maxActive: batch });
|
|
1814
1875
|
}
|
|
1876
|
+
/** Queues a task and resolves with its result, or rejects with its error. */
|
|
1815
1877
|
submit(task) {
|
|
1816
1878
|
return this.queue.add(() => task());
|
|
1817
1879
|
}
|
|
1880
|
+
/** Rejects queued and future tasks. Tasks already running are allowed to finish. */
|
|
1818
1881
|
stop() {
|
|
1819
1882
|
this.queue.end();
|
|
1820
1883
|
}
|
|
@@ -1956,6 +2019,7 @@ var NBTHelper;
|
|
|
1956
2019
|
var init_NBTHelper = __esm({
|
|
1957
2020
|
"src/nbt/NBTHelper.ts"() {
|
|
1958
2021
|
NBTHelper = class {
|
|
2022
|
+
/** Parses NBT bytes and preserves format and compression metadata. Omit `format` for automatic detection. */
|
|
1959
2023
|
static async fromBuffer(data, format2) {
|
|
1960
2024
|
const buffer = Buffer3.from(data instanceof Uint8Array ? data : new Uint8Array(data));
|
|
1961
2025
|
const prismarineNbt = await import("prismarine-nbt");
|
|
@@ -2100,6 +2164,7 @@ var init_HostedAssetSource = __esm({
|
|
|
2100
2164
|
["json" /* JSON */, _HostedAssetSource.JSON]
|
|
2101
2165
|
]);
|
|
2102
2166
|
}
|
|
2167
|
+
/** Retries missing assets with the `minecraft` namespace and default root. Other failures reject. */
|
|
2103
2168
|
async loadOrRetryWithDefaults(key, parser) {
|
|
2104
2169
|
const direct = await this.load(key, parser);
|
|
2105
2170
|
if (typeof direct !== "undefined") {
|
|
@@ -2157,6 +2222,10 @@ var init_HostedAssetSource = __esm({
|
|
|
2157
2222
|
assetBasePath(key) {
|
|
2158
2223
|
return `${key.root ?? this.root ?? AssetLoader.ROOT}/${key.rootType !== void 0 ? key.rootType + "/" : ""}${key.namespace !== void 0 ? key.namespace + "/" : ""}${key.assetType !== void 0 ? key.assetType + "/" : ""}`;
|
|
2159
2224
|
}
|
|
2225
|
+
/**
|
|
2226
|
+
* Creates a hosted source for {@link AssetLoader.addSource}.
|
|
2227
|
+
* Set `options.retryDefaults` to `false` to restrict lookups to the requested namespace and root.
|
|
2228
|
+
*/
|
|
2160
2229
|
constructor(root, options) {
|
|
2161
2230
|
super();
|
|
2162
2231
|
this._root = root;
|
|
@@ -2188,6 +2257,11 @@ var BrowserArchiveProxy;
|
|
|
2188
2257
|
var init_BrowserArchiveProxy = __esm({
|
|
2189
2258
|
"src/assets/source/archive/BrowserArchiveProxy.ts"() {
|
|
2190
2259
|
BrowserArchiveProxy = class {
|
|
2260
|
+
/**
|
|
2261
|
+
* Opens a ZIP for asset lookup.
|
|
2262
|
+
* @param id - Cache identity for this content. Change it when the pack changes.
|
|
2263
|
+
* A File supplies an identity from its name, size, and modification time when omitted.
|
|
2264
|
+
*/
|
|
2191
2265
|
constructor(blob, id) {
|
|
2192
2266
|
this._blob = blob;
|
|
2193
2267
|
this._reader = new ZipReader(new BlobReader(this._blob));
|
|
@@ -2387,6 +2461,7 @@ var init_ArchiveAssetSource = __esm({
|
|
|
2387
2461
|
dataPackFormat: copyFormat(options.dataPackFormat)
|
|
2388
2462
|
};
|
|
2389
2463
|
}
|
|
2464
|
+
/** Creates a browser ZIP source from a Blob or File. */
|
|
2390
2465
|
static blob(blob, options) {
|
|
2391
2466
|
return new _ArchiveAssetSource(new BrowserArchiveProxy(blob), options);
|
|
2392
2467
|
}
|
|
@@ -2519,6 +2594,7 @@ var init_AssetLoader = __esm({
|
|
|
2519
2594
|
FALLBACK_ROOT = "https://raw.githubusercontent.com/InventivetalentDev/minerender-fallback-assets/master";
|
|
2520
2595
|
AssetLoader = class {
|
|
2521
2596
|
static {
|
|
2597
|
+
/** Default asset base URL. Use {@link setVersion} to select a Minecraft version. */
|
|
2522
2598
|
this.ROOT = DEFAULT_ROOT;
|
|
2523
2599
|
}
|
|
2524
2600
|
static {
|
|
@@ -2531,6 +2607,7 @@ var init_AssetLoader = __esm({
|
|
|
2531
2607
|
static get version() {
|
|
2532
2608
|
return this.ROOT.substring(this.ROOT.lastIndexOf("/") + 1);
|
|
2533
2609
|
}
|
|
2610
|
+
/** Selects an mcasset.cloud version, updates the vanilla source, and clears in-memory caches. */
|
|
2534
2611
|
static setVersion(version) {
|
|
2535
2612
|
this.ROOT = `https://assets.mcasset.cloud/${version}`;
|
|
2536
2613
|
const source = new HostedAssetSource(this.ROOT, { retryDefaults: false });
|
|
@@ -2564,6 +2641,13 @@ var init_AssetLoader = __esm({
|
|
|
2564
2641
|
return scope ? `${scope}
|
|
2565
2642
|
${key}` : key;
|
|
2566
2643
|
}
|
|
2644
|
+
/**
|
|
2645
|
+
* Registers a source at the highest priority.
|
|
2646
|
+
* Call {@link Caching.clear} after changing sources to discard previously loaded assets.
|
|
2647
|
+
*
|
|
2648
|
+
* @param key - Name used to replace or remove this source.
|
|
2649
|
+
* @param override - Removes the first source with this name before adding the new one.
|
|
2650
|
+
*/
|
|
2567
2651
|
static addSource(key, source, override = true) {
|
|
2568
2652
|
if (override) {
|
|
2569
2653
|
const existing = this.removeSource(key);
|
|
@@ -2574,6 +2658,7 @@ ${key}` : key;
|
|
|
2574
2658
|
this._SOURCES.unshift({ key, source });
|
|
2575
2659
|
console.log(p4, "Added AssetSource", key);
|
|
2576
2660
|
}
|
|
2661
|
+
/** Removes and returns the first source with this name. Call {@link Caching.clear} to reload assets. */
|
|
2577
2662
|
static removeSource(key) {
|
|
2578
2663
|
const index = this._SOURCES.findIndex((s) => s.key === key);
|
|
2579
2664
|
if (index != -1) {
|
|
@@ -2588,6 +2673,7 @@ ${key}` : key;
|
|
|
2588
2673
|
this.addSource("mcassets-fallback", new HostedAssetSource(FALLBACK_ROOT, { retryDefaults: false }));
|
|
2589
2674
|
this.addSource("mcassets", new HostedAssetSource(this.ROOT, { retryDefaults: false }));
|
|
2590
2675
|
}
|
|
2676
|
+
/** Loads from all sources and returns defined results in priority order. Any source failure rejects the call. */
|
|
2591
2677
|
static async getAll(key, parser) {
|
|
2592
2678
|
const sources = [...this._SOURCES];
|
|
2593
2679
|
const results = [];
|
|
@@ -2649,6 +2735,7 @@ var init_ModelTextures = __esm({
|
|
|
2649
2735
|
static get PERSISTENT_META_CACHE() {
|
|
2650
2736
|
return this._persistentMetaCache ??= PersistentCache.open("minerender-texturemeta");
|
|
2651
2737
|
}
|
|
2738
|
+
/** Loads and decodes a texture into a readable canvas, or returns `undefined` when missing. */
|
|
2652
2739
|
static async get(key) {
|
|
2653
2740
|
const keyStr = key.serialize();
|
|
2654
2741
|
const pending = this.preload(key);
|
|
@@ -2666,6 +2753,7 @@ var init_ModelTextures = __esm({
|
|
|
2666
2753
|
throw err;
|
|
2667
2754
|
}
|
|
2668
2755
|
}
|
|
2756
|
+
/** Fetches and caches encoded texture bytes without decoding the pixels. */
|
|
2669
2757
|
static async preload(key) {
|
|
2670
2758
|
const keyStr = key.serialize();
|
|
2671
2759
|
return Caching.textureAssetCache.get(keyStr, (k) => {
|
|
@@ -2676,6 +2764,7 @@ var init_ModelTextures = __esm({
|
|
|
2676
2764
|
});
|
|
2677
2765
|
});
|
|
2678
2766
|
}
|
|
2767
|
+
/** Loads a texture's `.mcmeta` file, or returns `undefined` when no metadata file exists. */
|
|
2679
2768
|
static async getMeta(key) {
|
|
2680
2769
|
if (!key.extension || !key.extension.endsWith(".mcmeta")) {
|
|
2681
2770
|
key = Object.assign(new AssetKey("", ""), key);
|
|
@@ -2692,6 +2781,7 @@ var init_ModelTextures = __esm({
|
|
|
2692
2781
|
});
|
|
2693
2782
|
});
|
|
2694
2783
|
}
|
|
2784
|
+
/** Clears persisted texture metadata. Use {@link Caching.clear} to discard in-memory textures and metadata. */
|
|
2695
2785
|
static async clearCache() {
|
|
2696
2786
|
await this.PERSISTENT_META_CACHE.clear();
|
|
2697
2787
|
}
|
|
@@ -2779,6 +2869,7 @@ var init_Ticker = __esm({
|
|
|
2779
2869
|
}
|
|
2780
2870
|
return handle;
|
|
2781
2871
|
}
|
|
2872
|
+
/** Starts or resumes the shared tick loop. Repeated calls have no effect. */
|
|
2782
2873
|
static start() {
|
|
2783
2874
|
if (this.interval) return;
|
|
2784
2875
|
this.interval = this.schedule(() => {
|
|
@@ -2801,6 +2892,7 @@ var init_Ticker = __esm({
|
|
|
2801
2892
|
_Ticker.fiveSecondTicks = 0;
|
|
2802
2893
|
}, 1e3 * 5);
|
|
2803
2894
|
}
|
|
2895
|
+
/** Pauses the loop while retaining callbacks for a later {@link start}. */
|
|
2804
2896
|
static stop() {
|
|
2805
2897
|
if (this.interval) clearInterval(this.interval);
|
|
2806
2898
|
if (this.oneSecondTicksTracker) clearInterval(this.oneSecondTicksTracker);
|
|
@@ -2809,12 +2901,14 @@ var init_Ticker = __esm({
|
|
|
2809
2901
|
this.oneSecondTicksTracker = void 0;
|
|
2810
2902
|
this.fiveSecondTicksTracker = void 0;
|
|
2811
2903
|
}
|
|
2904
|
+
/** Registers a callback, starts the loop if needed, and returns an ID for {@link remove}. */
|
|
2812
2905
|
static add(tick) {
|
|
2813
2906
|
this.start();
|
|
2814
2907
|
const c = this.counter++;
|
|
2815
2908
|
this._tickers.set(c, tick);
|
|
2816
2909
|
return c;
|
|
2817
2910
|
}
|
|
2911
|
+
/** Removes a callback by ID and stops the timers when no callbacks remain. */
|
|
2818
2912
|
static remove(c) {
|
|
2819
2913
|
if (typeof c === "number") this._tickers.delete(c);
|
|
2820
2914
|
if (!this._tickers.size) this.stop();
|
|
@@ -2828,6 +2922,7 @@ var init_Ticker = __esm({
|
|
|
2828
2922
|
static get tpsFiveSeconds() {
|
|
2829
2923
|
return this.fiveSecondTps;
|
|
2830
2924
|
}
|
|
2925
|
+
/** Stops the loop and removes all registered callbacks. */
|
|
2831
2926
|
static dispose() {
|
|
2832
2927
|
this.stop();
|
|
2833
2928
|
this._tickers.clear();
|
|
@@ -2874,6 +2969,7 @@ var init_TextureAtlas = __esm({
|
|
|
2874
2969
|
}
|
|
2875
2970
|
};
|
|
2876
2971
|
}
|
|
2972
|
+
/** Copies pixels for a texture variable from its current atlas rectangle. */
|
|
2877
2973
|
getData(texture) {
|
|
2878
2974
|
const pos = this.positions[texture];
|
|
2879
2975
|
const size = this.sizes[texture];
|
|
@@ -3153,6 +3249,7 @@ var init_UVMapper = __esm({
|
|
|
3153
3249
|
}
|
|
3154
3250
|
uv.needsUpdate = true;
|
|
3155
3251
|
}
|
|
3252
|
+
/** Returns the shared atlas for a keyed, merged model, creating it on first use. */
|
|
3156
3253
|
static async getAtlas(model) {
|
|
3157
3254
|
const keyStr = model.key.serialize();
|
|
3158
3255
|
return Caching.modelTextureAtlasCache.get(keyStr, (k) => {
|
|
@@ -3223,6 +3320,11 @@ var init_UVMapper = __esm({
|
|
|
3223
3320
|
}
|
|
3224
3321
|
return [tl, tr, bl, br];
|
|
3225
3322
|
}
|
|
3323
|
+
/**
|
|
3324
|
+
* Combines model textures and animation metadata into an atlas.
|
|
3325
|
+
* Mapped UVs are stored on copies of the model's elements, available through the returned atlas.
|
|
3326
|
+
* Returns `undefined` for models without a texture map.
|
|
3327
|
+
*/
|
|
3226
3328
|
static async createAtlas(originalModel) {
|
|
3227
3329
|
const textureMap = {};
|
|
3228
3330
|
const metaMap = {};
|
|
@@ -3587,6 +3689,7 @@ var init_Entities = __esm({
|
|
|
3587
3689
|
init_MineRenderError();
|
|
3588
3690
|
init_ModelTextures();
|
|
3589
3691
|
Entities = class {
|
|
3692
|
+
/** Lists model paths in the `minecraft` namespace, including subdirectories and excluding `.json`. */
|
|
3590
3693
|
static async getEntityList() {
|
|
3591
3694
|
const collect = async (path) => {
|
|
3592
3695
|
const prefix2 = path ? `${path}/` : "";
|
|
@@ -3604,6 +3707,7 @@ var init_Entities = __esm({
|
|
|
3604
3707
|
const key = new AssetKey(modelKey.namespace, path, void 0, void 0, "entity-models", ".json", isAssetKey(modelKey) ? modelKey.root : void 0);
|
|
3605
3708
|
return Caching.entityModelCache.get(key.serialize(), () => AssetLoader.get(key, "json" /* JSON */));
|
|
3606
3709
|
}
|
|
3710
|
+
/** Returns selectable geometry-layer names, or an empty list when the model is missing. */
|
|
3607
3711
|
static async getLayerList(modelKey) {
|
|
3608
3712
|
return Object.keys((await this.getModelFile(modelKey))?.layers ?? {});
|
|
3609
3713
|
}
|
|
@@ -3611,6 +3715,15 @@ var init_Entities = __esm({
|
|
|
3611
3715
|
static async getPassList(modelKey) {
|
|
3612
3716
|
return (await this.getModelFile(modelKey))?.passes ?? [];
|
|
3613
3717
|
}
|
|
3718
|
+
/**
|
|
3719
|
+
* Loads the layers and textures to pass to {@link MineRenderScene.addEntity}.
|
|
3720
|
+
* By default, selects `main`, unconditional passes, and passes enabled by `options.when`.
|
|
3721
|
+
*
|
|
3722
|
+
* @param modelKey - Dataset model, such as `new BasicAssetKey("minecraft", "zombie")`.
|
|
3723
|
+
* @param textureKey - Texture override for the first selected layer.
|
|
3724
|
+
* @param options - Layer selection, conditional passes, and per-layer texture overrides.
|
|
3725
|
+
* @returns The selected model, or `undefined` when its dataset file is missing.
|
|
3726
|
+
*/
|
|
3614
3727
|
static async getEntity(modelKey, textureKey, options) {
|
|
3615
3728
|
const model = await this.getModelFile(modelKey);
|
|
3616
3729
|
if (!model) return void 0;
|
|
@@ -3656,6 +3769,7 @@ var init_Entities = __esm({
|
|
|
3656
3769
|
const file = await Caching.entityAnimationCache.get(key.serialize(), () => AssetLoader.get(key, "json" /* JSON */));
|
|
3657
3770
|
return file?.animations;
|
|
3658
3771
|
}
|
|
3772
|
+
/** Finds a fallback texture using the model path, its directory, and vanilla variant data. */
|
|
3659
3773
|
static async resolveTexture(modelKey) {
|
|
3660
3774
|
const path = isAssetKey(modelKey) ? modelKey.getFullPath() : modelKey.path;
|
|
3661
3775
|
const root = isAssetKey(modelKey) ? modelKey.root : void 0;
|
|
@@ -3816,12 +3930,14 @@ var init_EntityAnimationPlayer = __esm({
|
|
|
3816
3930
|
this._animation = void 0;
|
|
3817
3931
|
this._time = 0;
|
|
3818
3932
|
}
|
|
3933
|
+
/** Applies the pose at an absolute playback time. Returns `false` when no clip is active. */
|
|
3819
3934
|
setTime(seconds) {
|
|
3820
3935
|
if (!this._animation) return false;
|
|
3821
3936
|
this._time = seconds;
|
|
3822
3937
|
this.apply();
|
|
3823
3938
|
return true;
|
|
3824
3939
|
}
|
|
3940
|
+
/** Advances playback by elapsed seconds multiplied by the speed passed to {@link play}. */
|
|
3825
3941
|
advance(deltaSeconds) {
|
|
3826
3942
|
return this.setTime(this._time + deltaSeconds * this.speed);
|
|
3827
3943
|
}
|
|
@@ -3859,6 +3975,7 @@ var init_InstanceReference = __esm({
|
|
|
3859
3975
|
if (!this.instanceable.isInstanceActive(this.index, this)) throw new MineRenderError("Instance has been removed");
|
|
3860
3976
|
return this.instanceable;
|
|
3861
3977
|
}
|
|
3978
|
+
/** Releases this placement's slot for reuse. Repeated calls have no effect. */
|
|
3862
3979
|
removeFromScene() {
|
|
3863
3980
|
if (this.instanceable.isInstanceActive(this.index, this)) this.instanceable.removeInstanceAt(this.index);
|
|
3864
3981
|
}
|
|
@@ -3871,9 +3988,11 @@ var init_InstanceReference = __esm({
|
|
|
3871
3988
|
setMatrix(matrix) {
|
|
3872
3989
|
this.activeInstanceable.setMatrixAt(this.index, matrix);
|
|
3873
3990
|
}
|
|
3991
|
+
/** Hides or restores this placement while preserving its transform and allocated slot. */
|
|
3874
3992
|
setVisible(visible) {
|
|
3875
3993
|
this.activeInstanceable.setInstanceVisibleAt(this.index, visible);
|
|
3876
3994
|
}
|
|
3995
|
+
/** Updates the supplied transform components. Positions use scene units and rotations use radians. */
|
|
3877
3996
|
setPositionRotationScale(position, rotation, scale) {
|
|
3878
3997
|
this.activeInstanceable.setPositionRotationScaleAt(this.index, position, rotation, scale);
|
|
3879
3998
|
}
|
|
@@ -3950,6 +4069,7 @@ var init_SceneObject = __esm({
|
|
|
3950
4069
|
}
|
|
3951
4070
|
async init() {
|
|
3952
4071
|
}
|
|
4072
|
+
/** Marks ancestor scenes for redraw and emits a `change` event. */
|
|
3953
4073
|
notifyDirty() {
|
|
3954
4074
|
this.traverseAncestors((parent) => {
|
|
3955
4075
|
const scene = parent;
|
|
@@ -3985,15 +4105,17 @@ var init_SceneObject = __esm({
|
|
|
3985
4105
|
return obj;
|
|
3986
4106
|
}
|
|
3987
4107
|
/**
|
|
3988
|
-
*
|
|
4108
|
+
* Finds a named part, such as `head`, without the internal `group:` prefix.
|
|
4109
|
+
* Returns `undefined` when the group does not exist.
|
|
3989
4110
|
*/
|
|
3990
4111
|
getGroupByName(name) {
|
|
3991
4112
|
return this.getObjectByName(`group:${name}`);
|
|
3992
4113
|
}
|
|
3993
4114
|
/**
|
|
3994
|
-
*
|
|
3995
|
-
* @param name name
|
|
3996
|
-
* @param visible
|
|
4115
|
+
* Changes a named group's visibility and requests a redraw.
|
|
4116
|
+
* @param name - Part name without the `group:` prefix.
|
|
4117
|
+
* @param visible - Visibility to assign. Omit it to toggle the current value.
|
|
4118
|
+
* @returns The resulting visibility, or `false` if the group does not exist.
|
|
3997
4119
|
*/
|
|
3998
4120
|
toggleGroupVisibility(name, visible) {
|
|
3999
4121
|
return this.toggleObjectVisibility(this.getGroupByName(name), visible);
|
|
@@ -4044,15 +4166,16 @@ var init_SceneObject = __esm({
|
|
|
4044
4166
|
return mesh;
|
|
4045
4167
|
}
|
|
4046
4168
|
/**
|
|
4047
|
-
*
|
|
4169
|
+
* Finds a named mesh without the internal `mesh:` prefix, or returns `undefined`.
|
|
4048
4170
|
*/
|
|
4049
4171
|
getMeshByName(name) {
|
|
4050
4172
|
return this.getObjectByName(`mesh:${name}`);
|
|
4051
4173
|
}
|
|
4052
4174
|
/**
|
|
4053
|
-
*
|
|
4054
|
-
* @param name name
|
|
4055
|
-
* @param visible
|
|
4175
|
+
* Changes a named mesh's visibility and requests a redraw.
|
|
4176
|
+
* @param name - Mesh name without the `mesh:` prefix.
|
|
4177
|
+
* @param visible - Visibility to assign. Omit it to toggle the current value.
|
|
4178
|
+
* @returns The resulting visibility, or `false` if the mesh does not exist.
|
|
4056
4179
|
*/
|
|
4057
4180
|
toggleMeshVisibility(name, visible) {
|
|
4058
4181
|
return this.toggleObjectVisibility(this.getMeshByName(name), visible);
|
|
@@ -4098,12 +4221,14 @@ var init_SceneObject = __esm({
|
|
|
4098
4221
|
get isInstanced() {
|
|
4099
4222
|
return this._isInstanced;
|
|
4100
4223
|
}
|
|
4224
|
+
/** Number of live placements, excluding released instance slots. */
|
|
4101
4225
|
get instanceCounter() {
|
|
4102
4226
|
return this._instanceCounter;
|
|
4103
4227
|
}
|
|
4104
4228
|
constructInstanceReference(i) {
|
|
4105
4229
|
return new InstanceReference(this, i);
|
|
4106
4230
|
}
|
|
4231
|
+
/** Allocates a placement of this instanced object, reusing a released slot when available. */
|
|
4107
4232
|
nextInstance() {
|
|
4108
4233
|
const mesh = this.instanceMesh;
|
|
4109
4234
|
if (!mesh) throw new MineRenderError("Object is not instanced");
|
|
@@ -4250,6 +4375,7 @@ var init_SceneObject = __esm({
|
|
|
4250
4375
|
vector.setFromMatrixScale(matrix);
|
|
4251
4376
|
return vector;
|
|
4252
4377
|
}
|
|
4378
|
+
/** Updates supplied transform components. For a shared model, affects every live instance. */
|
|
4253
4379
|
setPositionRotationScale(position, rotation, scale) {
|
|
4254
4380
|
if (this.isInstanced) {
|
|
4255
4381
|
for (const i of this.activeInstanceIndices()) {
|
|
@@ -4268,6 +4394,7 @@ var init_SceneObject = __esm({
|
|
|
4268
4394
|
}
|
|
4269
4395
|
this.notifyDirty();
|
|
4270
4396
|
}
|
|
4397
|
+
/** Sets position in scene units. For a shared model, updates every live instance. */
|
|
4271
4398
|
setPosition(position) {
|
|
4272
4399
|
if (this.isInstanced) {
|
|
4273
4400
|
for (const i of this.activeInstanceIndices()) {
|
|
@@ -4285,6 +4412,7 @@ var init_SceneObject = __esm({
|
|
|
4285
4412
|
return this.position;
|
|
4286
4413
|
}
|
|
4287
4414
|
}
|
|
4415
|
+
/** Sets rotation in radians. For a shared model, updates every live instance. */
|
|
4288
4416
|
setRotation(rotation) {
|
|
4289
4417
|
if (this.isInstanced) {
|
|
4290
4418
|
for (const i of this.activeInstanceIndices()) {
|
|
@@ -4302,6 +4430,7 @@ var init_SceneObject = __esm({
|
|
|
4302
4430
|
return this.rotation;
|
|
4303
4431
|
}
|
|
4304
4432
|
}
|
|
4433
|
+
/** Sets scale factors. For a shared model, updates every live instance. */
|
|
4305
4434
|
setScale(scale) {
|
|
4306
4435
|
if (this.isInstanced) {
|
|
4307
4436
|
for (const i of this.activeInstanceIndices()) {
|
|
@@ -4339,6 +4468,7 @@ var init_SceneObject = __esm({
|
|
|
4339
4468
|
this.notifyDirty();
|
|
4340
4469
|
super.dispose();
|
|
4341
4470
|
}
|
|
4471
|
+
/** Releases instance slots and removes children, disposing children that implement Disposable. */
|
|
4342
4472
|
disposeAndRemoveAllChildren() {
|
|
4343
4473
|
if (this.instanceMesh) {
|
|
4344
4474
|
if (this._scene) this._scene.stats.instanceCount -= this.instanceReferences.size;
|
|
@@ -4361,6 +4491,7 @@ var init_SceneObject = __esm({
|
|
|
4361
4491
|
}
|
|
4362
4492
|
this.notifyDirty();
|
|
4363
4493
|
}
|
|
4494
|
+
/** Detaches the object from its parent and requests a redraw. */
|
|
4364
4495
|
removeFromScene() {
|
|
4365
4496
|
this.notifyDirty();
|
|
4366
4497
|
this.removeFromParent();
|
|
@@ -4512,12 +4643,15 @@ var init_EntityObject = __esm({
|
|
|
4512
4643
|
if (this.animationPlayers.length) this.notifyDirty();
|
|
4513
4644
|
}
|
|
4514
4645
|
//</editor-fold>
|
|
4646
|
+
/** Finds a selected draw by its layer key, such as `main` or `main#2`, or returns `undefined`. */
|
|
4515
4647
|
getLayerGroup(name) {
|
|
4516
4648
|
return super.getGroupByName(`layer:${name}`);
|
|
4517
4649
|
}
|
|
4650
|
+
/** Finds a part name without `group:`. Supply `layerName` to restrict the search to one draw. */
|
|
4518
4651
|
getGroupByName(name, layerName) {
|
|
4519
4652
|
return layerName === void 0 ? super.getGroupByName(name) : this.getLayerGroup(layerName)?.getObjectByName(`group:${name}`);
|
|
4520
4653
|
}
|
|
4654
|
+
/** Finds a mesh name without `mesh:`. Supply `layerName` to restrict the search to one draw. */
|
|
4521
4655
|
getMeshByName(name, layerName) {
|
|
4522
4656
|
return layerName === void 0 ? super.getMeshByName(name) : this.getLayerGroup(layerName)?.getObjectByName(`mesh:${name}`);
|
|
4523
4657
|
}
|
|
@@ -5188,6 +5322,7 @@ var init_ModelCulling = __esm({
|
|
|
5188
5322
|
"src/model/ModelCulling.ts"() {
|
|
5189
5323
|
init_CubeFace();
|
|
5190
5324
|
ModelCulling = class {
|
|
5325
|
+
/** Rotates a world-direction bit mask into model space. Bits follow {@link CUBE_FACES}. */
|
|
5191
5326
|
static toLocalMask(worldMask, rotation) {
|
|
5192
5327
|
let localMask = 0;
|
|
5193
5328
|
for (const [localFace, offset] of CUBE_FACE_OFFSETS.entries()) {
|
|
@@ -5198,6 +5333,7 @@ var init_ModelCulling = __esm({
|
|
|
5198
5333
|
}
|
|
5199
5334
|
return localMask;
|
|
5200
5335
|
}
|
|
5336
|
+
/** Whether a model fills one block with opaque faces and can hide adjacent block faces. */
|
|
5201
5337
|
static isOpaqueFullCube(atlas) {
|
|
5202
5338
|
if (!atlas || atlas.hasTransparency !== false || atlas.model.elements?.length !== 1) return false;
|
|
5203
5339
|
const element = atlas.model.elements[0];
|
|
@@ -5982,6 +6118,7 @@ var Meshes = class _Meshes {
|
|
|
5982
6118
|
static createBox(key) {
|
|
5983
6119
|
return new Mesh(Geometries.getBox(key.geometry), Materials.getImage(key.material));
|
|
5984
6120
|
}
|
|
6121
|
+
/** Returns a shared Mesh object. Use {@link createBox} for a mesh with its own transform and parent. */
|
|
5985
6122
|
static getBox(key) {
|
|
5986
6123
|
const keyStr = serializeMeshKey(key);
|
|
5987
6124
|
return Caching.boxMeshCache.get(keyStr, (k) => {
|
|
@@ -6094,6 +6231,7 @@ init_AssetParsers();
|
|
|
6094
6231
|
init_ModelTextures();
|
|
6095
6232
|
init_Caching();
|
|
6096
6233
|
var Fonts = class {
|
|
6234
|
+
/** Combines font definitions in source-priority order. Unsupported Unihex and TrueType providers are skipped. */
|
|
6097
6235
|
static async get(key = "minecraft:default") {
|
|
6098
6236
|
const fontKey = typeof key === "string" ? AssetKey.parse("font", key) : key;
|
|
6099
6237
|
return await Caching.fontCache.get(fontKey.serialize(), () => this.load(fontKey, []));
|
|
@@ -9310,6 +9448,13 @@ var GuiHelper = class {
|
|
|
9310
9448
|
});
|
|
9311
9449
|
return layers;
|
|
9312
9450
|
}
|
|
9451
|
+
/**
|
|
9452
|
+
* Calculates a slot's top-left position in GUI pixels.
|
|
9453
|
+
* @param slot - Zero-based slot index, or `[column, row]`.
|
|
9454
|
+
* @param origin - Position of the first slot.
|
|
9455
|
+
* @param offset - Horizontal and vertical spacing between slot origins, in pixels.
|
|
9456
|
+
* @param rowSize - Slots per row when `slot` is an index.
|
|
9457
|
+
*/
|
|
9313
9458
|
static inventorySlot(slot, origin = [0, 0], offset = [18, 18], rowSize = 9) {
|
|
9314
9459
|
const [column, row] = typeof slot === "number" ? [slot % rowSize, Math.floor(slot / rowSize)] : slot;
|
|
9315
9460
|
return [origin[0] + column * offset[0], origin[1] + row * offset[1]];
|
|
@@ -9967,6 +10112,7 @@ var SceneStatsDisplay = class {
|
|
|
9967
10112
|
appendTo(el) {
|
|
9968
10113
|
el.append(this.statsContainer);
|
|
9969
10114
|
}
|
|
10115
|
+
/** Stops the refresh timer and removes the panel from the page. */
|
|
9970
10116
|
dispose() {
|
|
9971
10117
|
clearInterval(this.interval);
|
|
9972
10118
|
this.interval = void 0;
|
|
@@ -9991,6 +10137,7 @@ var InstanceManager = class {
|
|
|
9991
10137
|
this.isInstanceManager = true;
|
|
9992
10138
|
this.instanceCache = {};
|
|
9993
10139
|
}
|
|
10140
|
+
/** Allocates a new placement of a cached model, or returns `undefined` if the key is unknown. */
|
|
9994
10141
|
async get(key) {
|
|
9995
10142
|
if (key in this.instanceCache) {
|
|
9996
10143
|
console.debug(p9, "key in cache", key);
|
|
@@ -9998,6 +10145,7 @@ var InstanceManager = class {
|
|
|
9998
10145
|
}
|
|
9999
10146
|
return void 0;
|
|
10000
10147
|
}
|
|
10148
|
+
/** Allocates a placement, calling the supplier once when the shared model is first needed. */
|
|
10001
10149
|
async getOrCreate(key, supplier) {
|
|
10002
10150
|
if (key in this.instanceCache) {
|
|
10003
10151
|
return await this.get(key);
|
|
@@ -10014,6 +10162,7 @@ var InstanceManager = class {
|
|
|
10014
10162
|
throw error;
|
|
10015
10163
|
}
|
|
10016
10164
|
}
|
|
10165
|
+
/** Forgets cached models without disposing them or releasing their existing placements. */
|
|
10017
10166
|
reset() {
|
|
10018
10167
|
for (let instanceCacheKey in this.instanceCache) {
|
|
10019
10168
|
delete this.instanceCache[instanceCacheKey];
|
|
@@ -10059,6 +10208,7 @@ function matchesCondition(condition, state) {
|
|
|
10059
10208
|
});
|
|
10060
10209
|
}
|
|
10061
10210
|
var BlockStateResolver = class {
|
|
10211
|
+
/** Loads vanilla property defaults, falling back to preview values inferred from the blockstate file. */
|
|
10062
10212
|
static async defaults(blockState) {
|
|
10063
10213
|
const defaults = blockState.key ? await BlockStates.getDefaultState(blockState.key) : void 0;
|
|
10064
10214
|
const state = {};
|
|
@@ -10078,9 +10228,11 @@ var BlockStateResolver = class {
|
|
|
10078
10228
|
}
|
|
10079
10229
|
return state;
|
|
10080
10230
|
}
|
|
10231
|
+
/** Selects matching models. Supply `choose` to control selection within each alternatives array. */
|
|
10081
10232
|
static select(blockState, state, choose = this.choose) {
|
|
10082
10233
|
return this.matching(blockState, state).map(choose);
|
|
10083
10234
|
}
|
|
10235
|
+
/** Returns matching model groups before choosing weighted alternatives. */
|
|
10084
10236
|
static matching(blockState, state) {
|
|
10085
10237
|
const out = [];
|
|
10086
10238
|
if (blockState.variants) {
|
|
@@ -10104,6 +10256,7 @@ var BlockStateResolver = class {
|
|
|
10104
10256
|
}
|
|
10105
10257
|
return out;
|
|
10106
10258
|
}
|
|
10259
|
+
/** Selects a random alternative using positive integer weights, each defaulting to 1. */
|
|
10107
10260
|
static choose(variants) {
|
|
10108
10261
|
if (!Array.isArray(variants)) return variants;
|
|
10109
10262
|
if (!variants.length) throw new MineRenderError("Blockstate variant arrays must not be empty");
|
|
@@ -10121,6 +10274,7 @@ var BlockStateResolver = class {
|
|
|
10121
10274
|
}
|
|
10122
10275
|
return variants[variants.length - 1];
|
|
10123
10276
|
}
|
|
10277
|
+
/** Converts blockstate rotations in degrees into the Euler rotation used by model rendering. */
|
|
10124
10278
|
static rotation(variant) {
|
|
10125
10279
|
const rotation = new Euler8();
|
|
10126
10280
|
if (typeof variant.x !== "undefined") {
|
|
@@ -10407,6 +10561,7 @@ var BlockObject = class _BlockObject extends SceneObject {
|
|
|
10407
10561
|
}
|
|
10408
10562
|
this.notifyDirty();
|
|
10409
10563
|
}
|
|
10564
|
+
/** Selected property values. Use {@link setState} to change properties and rebuild the rendered models. */
|
|
10410
10565
|
get state() {
|
|
10411
10566
|
return this._state;
|
|
10412
10567
|
}
|
|
@@ -10506,6 +10661,7 @@ var BlockObject = class _BlockObject extends SceneObject {
|
|
|
10506
10661
|
obj.setPosition(this.position);
|
|
10507
10662
|
return obj;
|
|
10508
10663
|
}
|
|
10664
|
+
/** Clears selected properties and rebuilds models without reapplying property defaults. */
|
|
10509
10665
|
async resetState() {
|
|
10510
10666
|
this._previousState = this._state;
|
|
10511
10667
|
this._state = {};
|
|
@@ -12405,6 +12561,11 @@ function compoundList(tags, name) {
|
|
|
12405
12561
|
// src/model/multiblock/StructureParser.ts
|
|
12406
12562
|
init_MineRenderError();
|
|
12407
12563
|
var StructureParser = class {
|
|
12564
|
+
/**
|
|
12565
|
+
* Parses decoded NBT, omitting air blocks.
|
|
12566
|
+
* @param _nbt - Structure data decoded by {@link NBTHelper.fromBuffer}.
|
|
12567
|
+
* @param paletteIndex - Palette to select when the structure has several. Defaults to 0.
|
|
12568
|
+
*/
|
|
12408
12569
|
static async parse(_nbt, paletteIndex) {
|
|
12409
12570
|
const nbt = _nbt.value;
|
|
12410
12571
|
let palette;
|
|
@@ -13239,6 +13400,7 @@ var SkinImage = class {
|
|
|
13239
13400
|
// src/skin/SkinTextures.ts
|
|
13240
13401
|
init_Textures();
|
|
13241
13402
|
var SkinTextures = class {
|
|
13403
|
+
/** Loads a skin URL. Pass `legacy` to override layout detection from the image dimensions. */
|
|
13242
13404
|
static async get(src, legacy) {
|
|
13243
13405
|
const image = await SkinImage.getData(src);
|
|
13244
13406
|
const scale = image.width / 64;
|
|
@@ -13412,6 +13574,14 @@ var SkinObject = class extends SceneObject {
|
|
|
13412
13574
|
}
|
|
13413
13575
|
}
|
|
13414
13576
|
}
|
|
13577
|
+
/**
|
|
13578
|
+
* Loads a skin texture, detecting slim arms and legacy layouts by default.
|
|
13579
|
+
* To override detection, set `slim` or `legacy` in the options passed to
|
|
13580
|
+
* `new SkinObject(options)` or `scene.addSkin(src, options)`.
|
|
13581
|
+
* Use {@link setSlim} or {@link setLegacy} to change these settings later.
|
|
13582
|
+
*
|
|
13583
|
+
* @param src - URL of the skin texture.
|
|
13584
|
+
*/
|
|
13415
13585
|
async setSkinTexture(src) {
|
|
13416
13586
|
if (typeof src === "undefined") return;
|
|
13417
13587
|
this.skinTextureSrc = src;
|
|
@@ -13563,6 +13733,7 @@ var MineRenderScene = class _MineRenderScene extends Scene4 {
|
|
|
13563
13733
|
this.stats.sceneObjectCount += change;
|
|
13564
13734
|
}
|
|
13565
13735
|
}
|
|
13736
|
+
/** Initializes each object before attaching it to the scene. */
|
|
13566
13737
|
async initAndAdd(...object2) {
|
|
13567
13738
|
this.dirty = true;
|
|
13568
13739
|
for (let obj of object2) {
|
|
@@ -13598,13 +13769,33 @@ var MineRenderScene = class _MineRenderScene extends Scene4 {
|
|
|
13598
13769
|
return obj;
|
|
13599
13770
|
}
|
|
13600
13771
|
}
|
|
13772
|
+
/**
|
|
13773
|
+
* Adds a model loaded with {@link Models.getMerged}.
|
|
13774
|
+
* Set `options.instanceMeshes` to `false` to create a separate ModelObject.
|
|
13775
|
+
*
|
|
13776
|
+
* @param parent - Object to attach the model to. Defaults to this scene.
|
|
13777
|
+
* @returns The model, or a reference to one placement of a shared model.
|
|
13778
|
+
*/
|
|
13601
13779
|
async addModel(model, options, parent = this) {
|
|
13602
13780
|
options = { ...options, tints: await ItemTints.get(model, options?.tints) };
|
|
13603
13781
|
return this.addSceneObject(model, () => new ModelObject(model, options), options, parent);
|
|
13604
13782
|
}
|
|
13783
|
+
/**
|
|
13784
|
+
* Adds the models selected by a blockstate loaded with {@link BlockStates.get}.
|
|
13785
|
+
* Set `options.initialState` to choose block properties such as `facing` or `axis`.
|
|
13786
|
+
* Use the returned object's `setPosition` method to move all of its model parts.
|
|
13787
|
+
*/
|
|
13605
13788
|
async addBlock(blockState, options, parent = this) {
|
|
13606
13789
|
return this.addSceneObject(blockState, () => new BlockObject(blockState, options), options, parent);
|
|
13607
13790
|
}
|
|
13791
|
+
/**
|
|
13792
|
+
* Loads a skin and adds an initialized player model.
|
|
13793
|
+
*
|
|
13794
|
+
* @param skin - Texture URL, such as one returned by {@link Skins.fromUuidOrUsername}.
|
|
13795
|
+
* Omit it to assign a texture later with {@link SkinObject.setSkinTexture}.
|
|
13796
|
+
* @param options - Player settings, including `slim` and `legacy` detection overrides.
|
|
13797
|
+
* @param parent - Object to attach the player to. Defaults to this scene.
|
|
13798
|
+
*/
|
|
13608
13799
|
async addSkin(skin, options, parent = this) {
|
|
13609
13800
|
this.dirty = true;
|
|
13610
13801
|
const obj = new SkinObject(options);
|
|
@@ -13616,9 +13807,14 @@ var MineRenderScene = class _MineRenderScene extends Scene4 {
|
|
|
13616
13807
|
parent.add(obj);
|
|
13617
13808
|
return obj;
|
|
13618
13809
|
}
|
|
13810
|
+
/** Adds an entity loaded with {@link Entities.getEntity}, using its selected layers and textures. */
|
|
13619
13811
|
async addEntity(entity, options, parent = this) {
|
|
13620
13812
|
return this.addSceneObject(entity, () => new EntityObject(entity, options), options, parent);
|
|
13621
13813
|
}
|
|
13814
|
+
/**
|
|
13815
|
+
* Adds GUI layers in draw order. One GUI pixel equals one scene unit.
|
|
13816
|
+
* Layer positions start at the top left, with positive GUI y pointing down.
|
|
13817
|
+
*/
|
|
13622
13818
|
async addGui(layers, options, parent = this) {
|
|
13623
13819
|
const obj = new GuiObject(layers, options);
|
|
13624
13820
|
obj.scene = this;
|
|
@@ -14481,6 +14677,7 @@ var Renderer = class _Renderer {
|
|
|
14481
14677
|
get element() {
|
|
14482
14678
|
return this._element;
|
|
14483
14679
|
}
|
|
14680
|
+
/** Attaches the canvas to an element and sizes it to that element's dimensions. */
|
|
14484
14681
|
appendTo(element) {
|
|
14485
14682
|
if (this._disposed) return;
|
|
14486
14683
|
this._element = element;
|
|
@@ -14508,6 +14705,7 @@ var Renderer = class _Renderer {
|
|
|
14508
14705
|
events.add(changeEvent2);
|
|
14509
14706
|
dispatcher.addEventListener(changeEvent2, this._changeListener);
|
|
14510
14707
|
}
|
|
14708
|
+
/** Updates the camera and canvas size. Width and height are in CSS pixels. */
|
|
14511
14709
|
resize(width, height) {
|
|
14512
14710
|
if (this._disposed) return;
|
|
14513
14711
|
if (isPerspectiveCamera(this.camera)) {
|
|
@@ -14546,12 +14744,14 @@ var Renderer = class _Renderer {
|
|
|
14546
14744
|
if (this._frameCallbacks.get(callback) === subscription) this._frameCallbacks.delete(callback);
|
|
14547
14745
|
};
|
|
14548
14746
|
}
|
|
14747
|
+
/** Starts or resumes the animation loop and registered frame callbacks. */
|
|
14549
14748
|
start() {
|
|
14550
14749
|
if (this._disposed) return;
|
|
14551
14750
|
this.stop();
|
|
14552
14751
|
this._running = true;
|
|
14553
14752
|
if (!this._inAnimationLoop) this.renderer.setAnimationLoop(this._animationLoop);
|
|
14554
14753
|
}
|
|
14754
|
+
/** Pauses rendering and frame callbacks. Call {@link start} to resume. */
|
|
14555
14755
|
stop() {
|
|
14556
14756
|
if (this._disposed) return;
|
|
14557
14757
|
this._running = false;
|
|
@@ -14660,12 +14860,15 @@ var Renderer = class _Renderer {
|
|
|
14660
14860
|
const canvas = trim ? trimCanvas(this.renderer.domElement) : this.renderer.domElement;
|
|
14661
14861
|
return canvas.toDataURL(mime, quality);
|
|
14662
14862
|
}
|
|
14863
|
+
/** Exports visible scene meshes as OBJ text, without texture images. */
|
|
14663
14864
|
toObj() {
|
|
14664
14865
|
return SceneExporter.toObj(this.scene);
|
|
14665
14866
|
}
|
|
14867
|
+
/** Exports visible scene meshes as PLY. Set `options.binary` for an ArrayBuffer. */
|
|
14666
14868
|
toPLY(options) {
|
|
14667
14869
|
return SceneExporter.toPLY(this.scene, options);
|
|
14668
14870
|
}
|
|
14871
|
+
/** Exports a static textured scene in the browser. Set `options.binary` for GLB output. */
|
|
14669
14872
|
toGLTF(options) {
|
|
14670
14873
|
return SceneExporter.toGLTF(this.scene, options);
|
|
14671
14874
|
}
|
|
@@ -14708,12 +14911,14 @@ init_request();
|
|
|
14708
14911
|
init_Requests();
|
|
14709
14912
|
var Skins = class {
|
|
14710
14913
|
//<editor-fold desc="Skins">
|
|
14914
|
+
/** Returns a skin URL for {@link MineRenderScene.addSkin}, or `undefined` if name lookup fails. */
|
|
14711
14915
|
static async fromUuidOrUsername(uuidOrUsername) {
|
|
14712
14916
|
if (uuidOrUsername.length === 32 || uuidOrUsername.length === 36) {
|
|
14713
14917
|
return this.fromUuid(uuidOrUsername);
|
|
14714
14918
|
}
|
|
14715
14919
|
return this.fromUsername(uuidOrUsername);
|
|
14716
14920
|
}
|
|
14921
|
+
/** Builds a proxy URL for a UUID without downloading or checking the skin. */
|
|
14717
14922
|
static async fromUuid(uuid) {
|
|
14718
14923
|
return this.getMcProxySkinUrl(uuid);
|
|
14719
14924
|
}
|
|
@@ -14725,6 +14930,7 @@ var Skins = class {
|
|
|
14725
14930
|
return void 0;
|
|
14726
14931
|
});
|
|
14727
14932
|
}
|
|
14933
|
+
/** Looks up a saved MineSkin skin and returns its texture URL, or `undefined` on lookup failure. */
|
|
14728
14934
|
static async fromMineSkin(mineskinId) {
|
|
14729
14935
|
return this.getMineSkin(mineskinId).then((mineskin) => {
|
|
14730
14936
|
if (mineskin) {
|
|
@@ -14735,12 +14941,14 @@ var Skins = class {
|
|
|
14735
14941
|
}
|
|
14736
14942
|
//</editor-fold>
|
|
14737
14943
|
//<editor-fold desc="Capes">
|
|
14944
|
+
/** Resolves a player's Minecraft cape URL for {@link SkinObject.setCapeTexture}. */
|
|
14738
14945
|
static async capeFromUuidOrUsername(uuidOrUsername) {
|
|
14739
14946
|
if (uuidOrUsername.length === 32 || uuidOrUsername.length === 36) {
|
|
14740
14947
|
return this.capeFromUuid(uuidOrUsername);
|
|
14741
14948
|
}
|
|
14742
14949
|
return this.capeFromUsername(uuidOrUsername);
|
|
14743
14950
|
}
|
|
14951
|
+
/** Builds a proxy URL without checking whether the player has a cape. */
|
|
14744
14952
|
static async capeFromUuid(uuid) {
|
|
14745
14953
|
return this.getMcProxyCapeUrl(uuid);
|
|
14746
14954
|
}
|
|
@@ -14895,16 +15103,19 @@ var ChunkData = class _ChunkData {
|
|
|
14895
15103
|
this.freeIds = [];
|
|
14896
15104
|
this.nbt = /* @__PURE__ */ new Map();
|
|
14897
15105
|
}
|
|
15106
|
+
/** Returns a detached copy of a cell, or `undefined` for air. Indices range from 0 to 4095. */
|
|
14898
15107
|
get(index) {
|
|
14899
15108
|
_ChunkData.validateIndex(index);
|
|
14900
15109
|
const entry = this.palette[this.indices[index]];
|
|
14901
15110
|
return entry ? _ChunkData.copyBlock(entry.state, this.nbt.get(index)) : void 0;
|
|
14902
15111
|
}
|
|
15112
|
+
/** Captures a cell's data and returns a copy-producing reader that survives later cell changes. */
|
|
14903
15113
|
snapshot(index) {
|
|
14904
15114
|
_ChunkData.validateIndex(index);
|
|
14905
15115
|
const entry = this.palette[this.indices[index]];
|
|
14906
15116
|
return entry ? _ChunkData.copyBlock.bind(void 0, entry.state, this.nbt.get(index)) : void 0;
|
|
14907
15117
|
}
|
|
15118
|
+
/** Copies block data into a cell. An omitted block or an air block clears the cell. */
|
|
14908
15119
|
set(index, block) {
|
|
14909
15120
|
_ChunkData.validateIndex(index);
|
|
14910
15121
|
let state;
|
|
@@ -14969,15 +15180,23 @@ var ChunkData = class _ChunkData {
|
|
|
14969
15180
|
|
|
14970
15181
|
// src/world/AnvilParser.ts
|
|
14971
15182
|
var AnvilParser = class {
|
|
15183
|
+
/** Lists occupied chunk positions within the region, using local coordinates from 0 to 31. */
|
|
14972
15184
|
static getChunkList(data) {
|
|
14973
15185
|
return this.locations(this.bytes(data)).map(({ x, z }) => ({ x, z }));
|
|
14974
15186
|
}
|
|
15187
|
+
/** Decodes all stored chunks. Gzip, zlib, and uncompressed payloads are supported. */
|
|
14975
15188
|
static async parse(data) {
|
|
14976
15189
|
const bytes = this.bytes(data);
|
|
14977
15190
|
const chunks = [];
|
|
14978
15191
|
for (const location of this.locations(bytes)) chunks.push(await this.readChunk(bytes, location));
|
|
14979
15192
|
return { chunks };
|
|
14980
15193
|
}
|
|
15194
|
+
/**
|
|
15195
|
+
* Decodes one chunk for {@link MineRenderWorld.placeChunk}.
|
|
15196
|
+
* @param localX - Chunk x within the region, from 0 to 31.
|
|
15197
|
+
* @param localZ - Chunk z within the region, from 0 to 31.
|
|
15198
|
+
* @returns The chunk with absolute coordinates, or `undefined` if the region has no chunk there.
|
|
15199
|
+
*/
|
|
14981
15200
|
static async parseChunk(data, localX, localZ) {
|
|
14982
15201
|
if (![localX, localZ].every((value) => Number.isInteger(value) && value >= 0 && value < 32)) {
|
|
14983
15202
|
throw new RangeError("Region-local chunk coordinates must be integers from 0 to 31");
|
|
@@ -15182,6 +15401,7 @@ var SectionModels = class {
|
|
|
15182
15401
|
this.templates = /* @__PURE__ */ new Set();
|
|
15183
15402
|
if (!Number.isInteger(maxAtlasSize) || maxAtlasSize < 1) throw new RangeError("maxAtlasSize must be a positive integer");
|
|
15184
15403
|
}
|
|
15404
|
+
/** Returns a cube template, or `undefined` when the block requires an individual render object. */
|
|
15185
15405
|
async get(blockState, properties = {}) {
|
|
15186
15406
|
if (!blockState.variants || blockState.multipart) return void 0;
|
|
15187
15407
|
let states = this.states.get(blockState);
|
|
@@ -15235,6 +15455,7 @@ var SectionModels = class {
|
|
|
15235
15455
|
}
|
|
15236
15456
|
return { variants, templates };
|
|
15237
15457
|
}
|
|
15458
|
+
/** Disposes prepared geometry and clears this world's template caches. */
|
|
15238
15459
|
clear() {
|
|
15239
15460
|
for (const template of this.templates) template.geometry.dispose();
|
|
15240
15461
|
this.templates.clear();
|
|
@@ -15285,6 +15506,13 @@ var MineRenderWorld = class {
|
|
|
15285
15506
|
this.validatePosBounds(posOrX);
|
|
15286
15507
|
await this.getChunkAt(posOrX)?.setBlockVisibleAt(posOrX, yOrVisible);
|
|
15287
15508
|
}
|
|
15509
|
+
/**
|
|
15510
|
+
* Places a structure's blocks at their stored positions, then refreshes neighboring faces.
|
|
15511
|
+
* Entity NBT is retained by the structure but is not rendered.
|
|
15512
|
+
*
|
|
15513
|
+
* @param useBatches - Uses bounded batches by default. Set to `false` for sequential placement.
|
|
15514
|
+
* @param executor - Optional queue for batched placement. The caller remains responsible for stopping it.
|
|
15515
|
+
*/
|
|
15288
15516
|
async placeMultiBlock(multiblock, useBatches = true, executor) {
|
|
15289
15517
|
const changes = /* @__PURE__ */ new Map();
|
|
15290
15518
|
try {
|
|
@@ -15381,6 +15609,7 @@ var MineRenderWorld = class {
|
|
|
15381
15609
|
});
|
|
15382
15610
|
}
|
|
15383
15611
|
}
|
|
15612
|
+
/** Removes all chunks and releases their block placements and section meshes. */
|
|
15384
15613
|
async clear() {
|
|
15385
15614
|
await this.culling;
|
|
15386
15615
|
const chunks = [...this._chunks.values()];
|
|
@@ -15466,9 +15695,11 @@ var MineRenderWorld = class {
|
|
|
15466
15695
|
}
|
|
15467
15696
|
return chunk;
|
|
15468
15697
|
}
|
|
15698
|
+
/** Returns the loaded chunk containing a world block position, without creating a chunk. */
|
|
15469
15699
|
getChunkAt(pos) {
|
|
15470
15700
|
return this._chunks.get(this.worldPosToChunkKey(pos));
|
|
15471
15701
|
}
|
|
15702
|
+
/** Converts block coordinates to scene units by multiplying each component by 16. */
|
|
15472
15703
|
static worldToScenePosition(pos) {
|
|
15473
15704
|
return new Vector316(
|
|
15474
15705
|
pos.x * 16,
|
|
@@ -15476,6 +15707,7 @@ var MineRenderWorld = class {
|
|
|
15476
15707
|
pos.z * 16
|
|
15477
15708
|
);
|
|
15478
15709
|
}
|
|
15710
|
+
/** Converts scene units to block coordinates without rounding to an integer block. */
|
|
15479
15711
|
static sceneToWorldPosition(pos) {
|
|
15480
15712
|
return new Vector316(
|
|
15481
15713
|
pos.x / 16,
|
|
@@ -15508,6 +15740,7 @@ var SectionMesh = class _SectionMesh extends Group2 {
|
|
|
15508
15740
|
super(...arguments);
|
|
15509
15741
|
this.ownedMeshes = [];
|
|
15510
15742
|
}
|
|
15743
|
+
/** Builds section-local meshes from visible cube faces. `maxAtlasSize` limits each atlas dimension in pixels. */
|
|
15511
15744
|
static build(entries, maxAtlasSize = 2048) {
|
|
15512
15745
|
if (!Number.isInteger(maxAtlasSize) || maxAtlasSize < 1) throw new RangeError("Section atlas size must be a positive integer");
|
|
15513
15746
|
const visible = entries.filter((entry) => entry.template.cullFaces.some((direction) => !(entry.cullMask & direction)));
|
|
@@ -15652,7 +15885,7 @@ var Chunk = class _Chunk {
|
|
|
15652
15885
|
return this.setBlockInChunkAt(pos, block, worldPos);
|
|
15653
15886
|
}
|
|
15654
15887
|
/**
|
|
15655
|
-
*
|
|
15888
|
+
* Places a block at integer chunk-local coordinates from 0 to 15.
|
|
15656
15889
|
*/
|
|
15657
15890
|
async setBlockInChunkAt(pos, block, worldPos, onBlocksChanged = this.onBlocksChanged) {
|
|
15658
15891
|
if (typeof worldPos === "undefined") {
|
|
@@ -15701,6 +15934,7 @@ var Chunk = class _Chunk {
|
|
|
15701
15934
|
await onBlocksChanged?.([worldPos]);
|
|
15702
15935
|
}
|
|
15703
15936
|
}
|
|
15937
|
+
/** Changes visibility at world block coordinates while preserving the block's data. */
|
|
15704
15938
|
async setBlockVisibleAt(pos, visible) {
|
|
15705
15939
|
const index = _Chunk.chunkPosToBlockIndex(this.worldPosToChunkPos(pos));
|
|
15706
15940
|
const block = this.renderedBlocks.get(index);
|
|
@@ -15754,6 +15988,7 @@ var Chunk = class _Chunk {
|
|
|
15754
15988
|
this.scene.dirty = true;
|
|
15755
15989
|
this.meshDirty = false;
|
|
15756
15990
|
}
|
|
15991
|
+
/** Removes stored blocks and their render objects, then notifies the owning world of changed positions. */
|
|
15757
15992
|
async clear(onBlocksChanged = this.onBlocksChanged) {
|
|
15758
15993
|
const positions = [...this.renderedBlocks.keys()].map((index) => this.chunkPosToWorldPos(
|
|
15759
15994
|
new Vector317(index % 16, Math.floor(index / 256), Math.floor(index / 16) % 16)
|
|
@@ -15774,6 +16009,7 @@ var Chunk = class _Chunk {
|
|
|
15774
16009
|
static isAir(block) {
|
|
15775
16010
|
return ChunkData.isAir(block);
|
|
15776
16011
|
}
|
|
16012
|
+
/** Maps chunk-local coordinates from 0 to 15 to a storage index, with x varying fastest, then z, then y. */
|
|
15777
16013
|
static chunkPosToBlockIndex(pos) {
|
|
15778
16014
|
if ([pos.x, pos.y, pos.z].some((value) => !Number.isInteger(value) || value < 0 || value >= 16)) {
|
|
15779
16015
|
throw new RangeError("Block coordinates must be integers from 0 to 15 within a chunk");
|