minerender 2.1.0-alpha.34 → 2.1.0-alpha.36
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 +8 -13
- package/dist/browser/index.d.ts +8 -13
- package/dist/browser/index.js +62 -81
- package/dist/browser/index.js.map +1 -1
- package/dist/browser/index.mjs +63 -82
- package/dist/browser/index.mjs.map +1 -1
- package/dist/bundle.js +64 -83
- package/dist/bundle.js.map +1 -1
- package/dist/node/index.d.mts +8 -13
- package/dist/node/index.d.ts +8 -13
- package/dist/node/index.js +62 -81
- package/dist/node/index.js.map +1 -1
- package/dist/node/index.mjs +63 -82
- package/dist/node/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/node/index.d.mts
CHANGED
|
@@ -585,13 +585,11 @@ declare class BatchedExecutor {
|
|
|
585
585
|
readonly interval: number;
|
|
586
586
|
readonly batch: number;
|
|
587
587
|
private readonly queue;
|
|
588
|
-
private readonly task;
|
|
589
588
|
constructor(interval?: number, batch?: number);
|
|
590
|
-
submit(task: Task):
|
|
591
|
-
|
|
592
|
-
private runNext;
|
|
589
|
+
submit<T>(task: Task<T>): Promise<T>;
|
|
590
|
+
stop(): void;
|
|
593
591
|
}
|
|
594
|
-
type Task = () =>
|
|
592
|
+
type Task<T = unknown> = () => T | Promise<T>;
|
|
595
593
|
|
|
596
594
|
declare function prefix(prefix?: string): string;
|
|
597
595
|
|
|
@@ -1692,7 +1690,6 @@ declare class Chunk {
|
|
|
1692
1690
|
readonly y: number;
|
|
1693
1691
|
readonly z: number;
|
|
1694
1692
|
private readonly _blocks;
|
|
1695
|
-
private readonly _anchor;
|
|
1696
1693
|
constructor(scene: MineRenderScene, x: number, y: number, z: number);
|
|
1697
1694
|
getBlockAt(x: number, y: number, z: number): Maybe<BlockInfo>;
|
|
1698
1695
|
getBlockAt(pos: Vector3): Maybe<BlockInfo>;
|
|
@@ -1704,11 +1701,12 @@ declare class Chunk {
|
|
|
1704
1701
|
setBlockAt(pos: Vector3, block: Maybe<Block>): Promise<Maybe<BlockInfo>>;
|
|
1705
1702
|
setBlockAt(pos: TripleArray, block: Maybe<Block>): Promise<Maybe<BlockInfo>>;
|
|
1706
1703
|
/**
|
|
1707
|
-
* Set block at
|
|
1704
|
+
* Set a block at integer chunk-local coordinates from 0 to 15.
|
|
1708
1705
|
*/
|
|
1709
1706
|
setBlockInChunkAt(pos: Vector3, block?: Block, worldPos?: Vector3): Promise<Maybe<BlockInfo>>;
|
|
1710
1707
|
clear(): Promise<void>;
|
|
1711
1708
|
dispose(): Promise<void>;
|
|
1709
|
+
static isAir(block: Maybe<Block>): boolean;
|
|
1712
1710
|
static chunkPosToBlockIndex(pos: Vector3): number;
|
|
1713
1711
|
worldPosToChunkPos(pos: Vector3): Vector3;
|
|
1714
1712
|
chunkPosToWorldPos(pos: Vector3): Vector3;
|
|
@@ -1716,23 +1714,20 @@ declare class Chunk {
|
|
|
1716
1714
|
|
|
1717
1715
|
declare class MineRenderWorld {
|
|
1718
1716
|
readonly scene: MineRenderScene;
|
|
1719
|
-
private _size;
|
|
1720
|
-
private _blockSize;
|
|
1721
1717
|
private readonly _chunks;
|
|
1722
1718
|
constructor(scene: MineRenderScene);
|
|
1723
1719
|
getBlockAt(x: number, y: number, z: number): Maybe<BlockInfo>;
|
|
1724
1720
|
getBlockAt(pos: Vector3): Maybe<BlockInfo>;
|
|
1725
1721
|
getBlockAt(pos: TripleArray): Maybe<BlockInfo>;
|
|
1726
|
-
setBlockAt(x: number, y: number, z: number, block: Block): Promise<Maybe<BlockInfo>>;
|
|
1727
|
-
setBlockAt(pos: Vector3, block: Block): Promise<Maybe<BlockInfo>>;
|
|
1728
|
-
setBlockAt(pos: TripleArray, block: Block): Promise<Maybe<BlockInfo>>;
|
|
1722
|
+
setBlockAt(x: number, y: number, z: number, block: Maybe<Block>): Promise<Maybe<BlockInfo>>;
|
|
1723
|
+
setBlockAt(pos: Vector3, block: Maybe<Block>): Promise<Maybe<BlockInfo>>;
|
|
1724
|
+
setBlockAt(pos: TripleArray, block: Maybe<Block>): Promise<Maybe<BlockInfo>>;
|
|
1729
1725
|
placeMultiBlock(multiblock: MultiBlockStructure, useBatches?: boolean, executor?: BatchedExecutor): Promise<void>;
|
|
1730
1726
|
clear(): Promise<void>;
|
|
1731
1727
|
private getOrCreateChunkAt;
|
|
1732
1728
|
getChunkAt(pos: Vector3): Maybe<Chunk>;
|
|
1733
1729
|
static worldToScenePosition(pos: Vector3): Vector3;
|
|
1734
1730
|
static sceneToWorldPosition(pos: Vector3): Vector3;
|
|
1735
|
-
worldPosToChunkIndex(pos: Vector3): number;
|
|
1736
1731
|
worldPosToChunkKey(pos: Vector3): string;
|
|
1737
1732
|
validatePosBounds(pos: Vector3): void;
|
|
1738
1733
|
}
|
package/dist/node/index.d.ts
CHANGED
|
@@ -585,13 +585,11 @@ declare class BatchedExecutor {
|
|
|
585
585
|
readonly interval: number;
|
|
586
586
|
readonly batch: number;
|
|
587
587
|
private readonly queue;
|
|
588
|
-
private readonly task;
|
|
589
588
|
constructor(interval?: number, batch?: number);
|
|
590
|
-
submit(task: Task):
|
|
591
|
-
|
|
592
|
-
private runNext;
|
|
589
|
+
submit<T>(task: Task<T>): Promise<T>;
|
|
590
|
+
stop(): void;
|
|
593
591
|
}
|
|
594
|
-
type Task = () =>
|
|
592
|
+
type Task<T = unknown> = () => T | Promise<T>;
|
|
595
593
|
|
|
596
594
|
declare function prefix(prefix?: string): string;
|
|
597
595
|
|
|
@@ -1692,7 +1690,6 @@ declare class Chunk {
|
|
|
1692
1690
|
readonly y: number;
|
|
1693
1691
|
readonly z: number;
|
|
1694
1692
|
private readonly _blocks;
|
|
1695
|
-
private readonly _anchor;
|
|
1696
1693
|
constructor(scene: MineRenderScene, x: number, y: number, z: number);
|
|
1697
1694
|
getBlockAt(x: number, y: number, z: number): Maybe<BlockInfo>;
|
|
1698
1695
|
getBlockAt(pos: Vector3): Maybe<BlockInfo>;
|
|
@@ -1704,11 +1701,12 @@ declare class Chunk {
|
|
|
1704
1701
|
setBlockAt(pos: Vector3, block: Maybe<Block>): Promise<Maybe<BlockInfo>>;
|
|
1705
1702
|
setBlockAt(pos: TripleArray, block: Maybe<Block>): Promise<Maybe<BlockInfo>>;
|
|
1706
1703
|
/**
|
|
1707
|
-
* Set block at
|
|
1704
|
+
* Set a block at integer chunk-local coordinates from 0 to 15.
|
|
1708
1705
|
*/
|
|
1709
1706
|
setBlockInChunkAt(pos: Vector3, block?: Block, worldPos?: Vector3): Promise<Maybe<BlockInfo>>;
|
|
1710
1707
|
clear(): Promise<void>;
|
|
1711
1708
|
dispose(): Promise<void>;
|
|
1709
|
+
static isAir(block: Maybe<Block>): boolean;
|
|
1712
1710
|
static chunkPosToBlockIndex(pos: Vector3): number;
|
|
1713
1711
|
worldPosToChunkPos(pos: Vector3): Vector3;
|
|
1714
1712
|
chunkPosToWorldPos(pos: Vector3): Vector3;
|
|
@@ -1716,23 +1714,20 @@ declare class Chunk {
|
|
|
1716
1714
|
|
|
1717
1715
|
declare class MineRenderWorld {
|
|
1718
1716
|
readonly scene: MineRenderScene;
|
|
1719
|
-
private _size;
|
|
1720
|
-
private _blockSize;
|
|
1721
1717
|
private readonly _chunks;
|
|
1722
1718
|
constructor(scene: MineRenderScene);
|
|
1723
1719
|
getBlockAt(x: number, y: number, z: number): Maybe<BlockInfo>;
|
|
1724
1720
|
getBlockAt(pos: Vector3): Maybe<BlockInfo>;
|
|
1725
1721
|
getBlockAt(pos: TripleArray): Maybe<BlockInfo>;
|
|
1726
|
-
setBlockAt(x: number, y: number, z: number, block: Block): Promise<Maybe<BlockInfo>>;
|
|
1727
|
-
setBlockAt(pos: Vector3, block: Block): Promise<Maybe<BlockInfo>>;
|
|
1728
|
-
setBlockAt(pos: TripleArray, block: Block): Promise<Maybe<BlockInfo>>;
|
|
1722
|
+
setBlockAt(x: number, y: number, z: number, block: Maybe<Block>): Promise<Maybe<BlockInfo>>;
|
|
1723
|
+
setBlockAt(pos: Vector3, block: Maybe<Block>): Promise<Maybe<BlockInfo>>;
|
|
1724
|
+
setBlockAt(pos: TripleArray, block: Maybe<Block>): Promise<Maybe<BlockInfo>>;
|
|
1729
1725
|
placeMultiBlock(multiblock: MultiBlockStructure, useBatches?: boolean, executor?: BatchedExecutor): Promise<void>;
|
|
1730
1726
|
clear(): Promise<void>;
|
|
1731
1727
|
private getOrCreateChunkAt;
|
|
1732
1728
|
getChunkAt(pos: Vector3): Maybe<Chunk>;
|
|
1733
1729
|
static worldToScenePosition(pos: Vector3): Vector3;
|
|
1734
1730
|
static sceneToWorldPosition(pos: Vector3): Vector3;
|
|
1735
|
-
worldPosToChunkIndex(pos: Vector3): number;
|
|
1736
1731
|
worldPosToChunkKey(pos: Vector3): string;
|
|
1737
1732
|
validatePosBounds(pos: Vector3): void;
|
|
1738
1733
|
}
|
package/dist/node/index.js
CHANGED
|
@@ -1661,24 +1661,20 @@ var AssetLoadError = class extends Error {
|
|
|
1661
1661
|
};
|
|
1662
1662
|
|
|
1663
1663
|
// src/util/BatchedExecutor.ts
|
|
1664
|
+
var import_jobqu2 = require("jobqu");
|
|
1664
1665
|
var BatchedExecutor = class {
|
|
1665
1666
|
constructor(interval = 1, batch = 30) {
|
|
1667
|
+
if (!Number.isFinite(interval) || interval < 0) throw new RangeError("Batch interval must be finite and nonnegative");
|
|
1668
|
+
if (!Number.isInteger(batch) || batch < 1) throw new RangeError("Batch size must be a positive integer");
|
|
1666
1669
|
this.interval = interval;
|
|
1667
1670
|
this.batch = batch;
|
|
1668
|
-
this.queue =
|
|
1669
|
-
this.task = setInterval(() => this.run());
|
|
1671
|
+
this.queue = new import_jobqu2.JobQueue(async (task) => task(), { interval, maxPerRun: batch, maxActive: batch });
|
|
1670
1672
|
}
|
|
1671
1673
|
submit(task) {
|
|
1672
|
-
this.queue.
|
|
1674
|
+
return this.queue.add(() => task());
|
|
1673
1675
|
}
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
this.runNext();
|
|
1677
|
-
}
|
|
1678
|
-
}
|
|
1679
|
-
runNext() {
|
|
1680
|
-
let next = this.queue.shift();
|
|
1681
|
-
if (next) next();
|
|
1676
|
+
stop() {
|
|
1677
|
+
this.queue.end();
|
|
1682
1678
|
}
|
|
1683
1679
|
};
|
|
1684
1680
|
|
|
@@ -7388,9 +7384,6 @@ var import_three25 = require("three");
|
|
|
7388
7384
|
var import_three24 = require("three");
|
|
7389
7385
|
var MineRenderWorld = class {
|
|
7390
7386
|
constructor(scene) {
|
|
7391
|
-
this._size = 4;
|
|
7392
|
-
//TODO: expandable
|
|
7393
|
-
this._blockSize = this._size * 16;
|
|
7394
7387
|
this._chunks = /* @__PURE__ */ new Map();
|
|
7395
7388
|
this.scene = scene;
|
|
7396
7389
|
}
|
|
@@ -7401,12 +7394,8 @@ var MineRenderWorld = class {
|
|
|
7401
7394
|
if (isTripleArray(posOrX)) {
|
|
7402
7395
|
return this.getBlockAt(new import_three24.Vector3(posOrX[0], posOrX[1], posOrX[2]));
|
|
7403
7396
|
}
|
|
7404
|
-
const chunk = this.getChunkAt(posOrX);
|
|
7405
|
-
if (typeof chunk === "undefined") {
|
|
7406
|
-
return void 0;
|
|
7407
|
-
}
|
|
7408
7397
|
this.validatePosBounds(posOrX);
|
|
7409
|
-
return
|
|
7398
|
+
return this.getChunkAt(posOrX)?.getBlockAt(posOrX);
|
|
7410
7399
|
}
|
|
7411
7400
|
async setBlockAt(posOrX, yOrBlock, z, block) {
|
|
7412
7401
|
if (typeof posOrX == "number") {
|
|
@@ -7416,32 +7405,48 @@ var MineRenderWorld = class {
|
|
|
7416
7405
|
return this.setBlockAt(new import_three24.Vector3(posOrX[0], posOrX[1], posOrX[2]), yOrBlock);
|
|
7417
7406
|
}
|
|
7418
7407
|
this.validatePosBounds(posOrX);
|
|
7419
|
-
const
|
|
7420
|
-
|
|
7421
|
-
|
|
7422
|
-
|
|
7423
|
-
|
|
7424
|
-
|
|
7425
|
-
const
|
|
7426
|
-
if (
|
|
7427
|
-
|
|
7428
|
-
|
|
7429
|
-
|
|
7430
|
-
|
|
7431
|
-
|
|
7432
|
-
|
|
7433
|
-
|
|
7408
|
+
const value = yOrBlock;
|
|
7409
|
+
const chunk = Chunk.isAir(value) ? this.getChunkAt(posOrX) : this.getOrCreateChunkAt(posOrX);
|
|
7410
|
+
return chunk?.setBlockAt(posOrX, value);
|
|
7411
|
+
}
|
|
7412
|
+
async placeMultiBlock(multiblock, useBatches = true, executor) {
|
|
7413
|
+
const keys = /* @__PURE__ */ new Map();
|
|
7414
|
+
for (const block of multiblock.blocks) {
|
|
7415
|
+
if (Chunk.isAir(block)) continue;
|
|
7416
|
+
const key = AssetKey.parse("blockstates", block.type);
|
|
7417
|
+
keys.set(key.serialize(), key);
|
|
7418
|
+
}
|
|
7419
|
+
await BlockStates.getAll(keys.values());
|
|
7420
|
+
if (!useBatches) {
|
|
7421
|
+
for (const block of multiblock.blocks) await this.setBlockAt(block.position, block);
|
|
7422
|
+
return;
|
|
7423
|
+
}
|
|
7424
|
+
const positions = /* @__PURE__ */ new Map();
|
|
7425
|
+
for (const block of multiblock.blocks) {
|
|
7426
|
+
const key = block.position.join(",");
|
|
7427
|
+
const group = positions.get(key);
|
|
7428
|
+
if (group) group.push(block);
|
|
7429
|
+
else positions.set(key, [block]);
|
|
7430
|
+
}
|
|
7431
|
+
const groups = [...positions.values()];
|
|
7432
|
+
const queue = executor ?? new BatchedExecutor();
|
|
7433
|
+
try {
|
|
7434
|
+
for (let i = 0; i < groups.length; i += queue.batch) {
|
|
7435
|
+
const results = await Promise.allSettled(groups.slice(i, i + queue.batch).map(
|
|
7436
|
+
(blocks) => queue.submit(async () => {
|
|
7437
|
+
for (const block of blocks) await this.setBlockAt(block.position, block);
|
|
7438
|
+
})
|
|
7439
|
+
));
|
|
7440
|
+
const failure = results.find((result) => result.status === "rejected");
|
|
7441
|
+
if (failure?.status === "rejected") throw failure.reason;
|
|
7434
7442
|
}
|
|
7435
|
-
}
|
|
7436
|
-
|
|
7437
|
-
await place(block);
|
|
7443
|
+
} finally {
|
|
7444
|
+
if (!executor) queue.stop();
|
|
7438
7445
|
}
|
|
7439
7446
|
}
|
|
7440
7447
|
async clear() {
|
|
7441
|
-
|
|
7442
|
-
|
|
7443
|
-
console.log("dispose chunk", chunk);
|
|
7444
|
-
await chunk?.dispose();
|
|
7448
|
+
for (const chunk of this._chunks.values()) {
|
|
7449
|
+
await chunk.dispose();
|
|
7445
7450
|
}
|
|
7446
7451
|
this._chunks.clear();
|
|
7447
7452
|
}
|
|
@@ -7455,8 +7460,7 @@ var MineRenderWorld = class {
|
|
|
7455
7460
|
return chunk;
|
|
7456
7461
|
}
|
|
7457
7462
|
getChunkAt(pos) {
|
|
7458
|
-
|
|
7459
|
-
return this._chunks[index];
|
|
7463
|
+
return this._chunks.get(this.worldPosToChunkKey(pos));
|
|
7460
7464
|
}
|
|
7461
7465
|
static worldToScenePosition(pos) {
|
|
7462
7466
|
return new import_three24.Vector3(
|
|
@@ -7472,12 +7476,6 @@ var MineRenderWorld = class {
|
|
|
7472
7476
|
pos.z / 16
|
|
7473
7477
|
);
|
|
7474
7478
|
}
|
|
7475
|
-
worldPosToChunkIndex(pos) {
|
|
7476
|
-
const chunkX = Math.floor(pos.x / 16);
|
|
7477
|
-
const chunkY = Math.floor(pos.y / 16);
|
|
7478
|
-
const chunkZ = Math.floor(pos.z / 16);
|
|
7479
|
-
return chunkZ * this._size * this._size + chunkY * this._size + chunkX;
|
|
7480
|
-
}
|
|
7481
7479
|
worldPosToChunkKey(pos) {
|
|
7482
7480
|
const chunkX = Math.floor(pos.x / 16);
|
|
7483
7481
|
const chunkY = Math.floor(pos.y / 16);
|
|
@@ -7485,12 +7483,9 @@ var MineRenderWorld = class {
|
|
|
7485
7483
|
return `${chunkX}_${chunkY}_${chunkZ}`;
|
|
7486
7484
|
}
|
|
7487
7485
|
validatePosBounds(pos) {
|
|
7488
|
-
if (pos.x
|
|
7489
|
-
|
|
7490
|
-
|
|
7491
|
-
if (pos.x > this._blockSize) throw new Error("x>" + this._blockSize);
|
|
7492
|
-
if (pos.y > this._blockSize) throw new Error("y>" + this._blockSize);
|
|
7493
|
-
if (pos.z > this._blockSize) throw new Error("z>" + this._blockSize);
|
|
7486
|
+
if (![pos.x, pos.y, pos.z].every(Number.isInteger)) {
|
|
7487
|
+
throw new RangeError("Block coordinates must be integers");
|
|
7488
|
+
}
|
|
7494
7489
|
}
|
|
7495
7490
|
};
|
|
7496
7491
|
|
|
@@ -7503,16 +7498,6 @@ var Chunk = class _Chunk {
|
|
|
7503
7498
|
this.x = x;
|
|
7504
7499
|
this.y = y;
|
|
7505
7500
|
this.z = z;
|
|
7506
|
-
let anchor = new import_three25.Object3D();
|
|
7507
|
-
this._anchor = anchor;
|
|
7508
|
-
scene.add(anchor);
|
|
7509
|
-
anchor.position.set(this.x * 256 + 128 - 8, this.y * 256 + 128 - 8, this.z * 256 + 128 - 8);
|
|
7510
|
-
addBox3WireframeToObject(
|
|
7511
|
-
new import_three25.Box3(new import_three25.Vector3(0, 0, 0), new import_three25.Vector3(256, 256, 256)),
|
|
7512
|
-
anchor,
|
|
7513
|
-
16776960,
|
|
7514
|
-
4
|
|
7515
|
-
);
|
|
7516
7501
|
}
|
|
7517
7502
|
getBlockAt(posOrX, y, z) {
|
|
7518
7503
|
if (typeof posOrX == "number") {
|
|
@@ -7538,7 +7523,7 @@ var Chunk = class _Chunk {
|
|
|
7538
7523
|
return this.setBlockInChunkAt(pos, block, worldPos);
|
|
7539
7524
|
}
|
|
7540
7525
|
/**
|
|
7541
|
-
* Set block at
|
|
7526
|
+
* Set a block at integer chunk-local coordinates from 0 to 15.
|
|
7542
7527
|
*/
|
|
7543
7528
|
async setBlockInChunkAt(pos, block, worldPos) {
|
|
7544
7529
|
if (typeof worldPos === "undefined") {
|
|
@@ -7551,15 +7536,13 @@ var Chunk = class _Chunk {
|
|
|
7551
7536
|
current.object.removeFromScene();
|
|
7552
7537
|
delete this._blocks[index];
|
|
7553
7538
|
}
|
|
7554
|
-
if (
|
|
7539
|
+
if (!block || _Chunk.isAir(block)) return void 0;
|
|
7555
7540
|
const blockState = await BlockStates.get(AssetKey.parse("blockstates", block.type));
|
|
7556
7541
|
if (blockState) {
|
|
7557
7542
|
const blockObject = await this.scene.addBlock(blockState, {
|
|
7558
7543
|
mergeMeshes: true,
|
|
7559
7544
|
instanceMeshes: true,
|
|
7560
|
-
wireframe: true,
|
|
7561
7545
|
maxInstanceCount: 2e3
|
|
7562
|
-
//TODO: setting this to high kills FPS; increase on demand somehow?
|
|
7563
7546
|
});
|
|
7564
7547
|
if (block.properties) {
|
|
7565
7548
|
await blockObject.setState(block.properties);
|
|
@@ -7575,23 +7558,21 @@ var Chunk = class _Chunk {
|
|
|
7575
7558
|
return void 0;
|
|
7576
7559
|
}
|
|
7577
7560
|
async clear() {
|
|
7578
|
-
|
|
7579
|
-
|
|
7580
|
-
for (let x = 0; x < 16; x++) {
|
|
7581
|
-
for (let z = 0; z < 16; z++) {
|
|
7582
|
-
for (let y = 0; y < 16; y++) {
|
|
7583
|
-
promises.push(this.setBlockInChunkAt(pos.set(x, y, z), void 0));
|
|
7584
|
-
}
|
|
7585
|
-
}
|
|
7586
|
-
}
|
|
7587
|
-
return Promise.all(promises).then((ignored) => {
|
|
7588
|
-
});
|
|
7561
|
+
this._blocks.forEach((block) => block.object.removeFromScene());
|
|
7562
|
+
this._blocks.length = 0;
|
|
7589
7563
|
}
|
|
7590
7564
|
async dispose() {
|
|
7591
7565
|
await this.clear();
|
|
7592
|
-
|
|
7566
|
+
}
|
|
7567
|
+
static isAir(block) {
|
|
7568
|
+
if (typeof block === "undefined" || typeof block.type === "undefined") return true;
|
|
7569
|
+
const key = AssetKey.parse("blockstates", block.type);
|
|
7570
|
+
return key.namespace === "minecraft" && !key.type && ["air", "cave_air", "void_air"].includes(key.path);
|
|
7593
7571
|
}
|
|
7594
7572
|
static chunkPosToBlockIndex(pos) {
|
|
7573
|
+
if ([pos.x, pos.y, pos.z].some((value) => !Number.isInteger(value) || value < 0 || value >= 16)) {
|
|
7574
|
+
throw new RangeError("Block coordinates must be integers from 0 to 15 within a chunk");
|
|
7575
|
+
}
|
|
7595
7576
|
return pos.y * 16 * 16 + pos.z * 16 + pos.x;
|
|
7596
7577
|
}
|
|
7597
7578
|
worldPosToChunkPos(pos) {
|