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.mjs
CHANGED
|
@@ -1504,24 +1504,20 @@ var AssetLoadError = class extends Error {
|
|
|
1504
1504
|
};
|
|
1505
1505
|
|
|
1506
1506
|
// src/util/BatchedExecutor.ts
|
|
1507
|
+
import { JobQueue as JobQueue2 } from "jobqu";
|
|
1507
1508
|
var BatchedExecutor = class {
|
|
1508
1509
|
constructor(interval = 1, batch = 30) {
|
|
1510
|
+
if (!Number.isFinite(interval) || interval < 0) throw new RangeError("Batch interval must be finite and nonnegative");
|
|
1511
|
+
if (!Number.isInteger(batch) || batch < 1) throw new RangeError("Batch size must be a positive integer");
|
|
1509
1512
|
this.interval = interval;
|
|
1510
1513
|
this.batch = batch;
|
|
1511
|
-
this.queue =
|
|
1512
|
-
this.task = setInterval(() => this.run());
|
|
1514
|
+
this.queue = new JobQueue2(async (task) => task(), { interval, maxPerRun: batch, maxActive: batch });
|
|
1513
1515
|
}
|
|
1514
1516
|
submit(task) {
|
|
1515
|
-
this.queue.
|
|
1517
|
+
return this.queue.add(() => task());
|
|
1516
1518
|
}
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
this.runNext();
|
|
1520
|
-
}
|
|
1521
|
-
}
|
|
1522
|
-
runNext() {
|
|
1523
|
-
let next = this.queue.shift();
|
|
1524
|
-
if (next) next();
|
|
1519
|
+
stop() {
|
|
1520
|
+
this.queue.end();
|
|
1525
1521
|
}
|
|
1526
1522
|
};
|
|
1527
1523
|
|
|
@@ -7243,15 +7239,12 @@ var Skins = class {
|
|
|
7243
7239
|
};
|
|
7244
7240
|
|
|
7245
7241
|
// src/world/Chunk.ts
|
|
7246
|
-
import {
|
|
7242
|
+
import { Vector3 as Vector311 } from "three";
|
|
7247
7243
|
|
|
7248
7244
|
// src/world/MineRenderWorld.ts
|
|
7249
7245
|
import { Vector3 as Vector310 } from "three";
|
|
7250
7246
|
var MineRenderWorld = class {
|
|
7251
7247
|
constructor(scene) {
|
|
7252
|
-
this._size = 4;
|
|
7253
|
-
//TODO: expandable
|
|
7254
|
-
this._blockSize = this._size * 16;
|
|
7255
7248
|
this._chunks = /* @__PURE__ */ new Map();
|
|
7256
7249
|
this.scene = scene;
|
|
7257
7250
|
}
|
|
@@ -7262,12 +7255,8 @@ var MineRenderWorld = class {
|
|
|
7262
7255
|
if (isTripleArray(posOrX)) {
|
|
7263
7256
|
return this.getBlockAt(new Vector310(posOrX[0], posOrX[1], posOrX[2]));
|
|
7264
7257
|
}
|
|
7265
|
-
const chunk = this.getChunkAt(posOrX);
|
|
7266
|
-
if (typeof chunk === "undefined") {
|
|
7267
|
-
return void 0;
|
|
7268
|
-
}
|
|
7269
7258
|
this.validatePosBounds(posOrX);
|
|
7270
|
-
return
|
|
7259
|
+
return this.getChunkAt(posOrX)?.getBlockAt(posOrX);
|
|
7271
7260
|
}
|
|
7272
7261
|
async setBlockAt(posOrX, yOrBlock, z, block) {
|
|
7273
7262
|
if (typeof posOrX == "number") {
|
|
@@ -7277,32 +7266,48 @@ var MineRenderWorld = class {
|
|
|
7277
7266
|
return this.setBlockAt(new Vector310(posOrX[0], posOrX[1], posOrX[2]), yOrBlock);
|
|
7278
7267
|
}
|
|
7279
7268
|
this.validatePosBounds(posOrX);
|
|
7280
|
-
const
|
|
7281
|
-
|
|
7282
|
-
|
|
7283
|
-
|
|
7284
|
-
|
|
7285
|
-
|
|
7286
|
-
const
|
|
7287
|
-
if (
|
|
7288
|
-
|
|
7289
|
-
|
|
7290
|
-
|
|
7291
|
-
|
|
7292
|
-
|
|
7293
|
-
|
|
7294
|
-
|
|
7269
|
+
const value = yOrBlock;
|
|
7270
|
+
const chunk = Chunk.isAir(value) ? this.getChunkAt(posOrX) : this.getOrCreateChunkAt(posOrX);
|
|
7271
|
+
return chunk?.setBlockAt(posOrX, value);
|
|
7272
|
+
}
|
|
7273
|
+
async placeMultiBlock(multiblock, useBatches = true, executor) {
|
|
7274
|
+
const keys = /* @__PURE__ */ new Map();
|
|
7275
|
+
for (const block of multiblock.blocks) {
|
|
7276
|
+
if (Chunk.isAir(block)) continue;
|
|
7277
|
+
const key = AssetKey.parse("blockstates", block.type);
|
|
7278
|
+
keys.set(key.serialize(), key);
|
|
7279
|
+
}
|
|
7280
|
+
await BlockStates.getAll(keys.values());
|
|
7281
|
+
if (!useBatches) {
|
|
7282
|
+
for (const block of multiblock.blocks) await this.setBlockAt(block.position, block);
|
|
7283
|
+
return;
|
|
7284
|
+
}
|
|
7285
|
+
const positions = /* @__PURE__ */ new Map();
|
|
7286
|
+
for (const block of multiblock.blocks) {
|
|
7287
|
+
const key = block.position.join(",");
|
|
7288
|
+
const group = positions.get(key);
|
|
7289
|
+
if (group) group.push(block);
|
|
7290
|
+
else positions.set(key, [block]);
|
|
7291
|
+
}
|
|
7292
|
+
const groups = [...positions.values()];
|
|
7293
|
+
const queue = executor ?? new BatchedExecutor();
|
|
7294
|
+
try {
|
|
7295
|
+
for (let i = 0; i < groups.length; i += queue.batch) {
|
|
7296
|
+
const results = await Promise.allSettled(groups.slice(i, i + queue.batch).map(
|
|
7297
|
+
(blocks) => queue.submit(async () => {
|
|
7298
|
+
for (const block of blocks) await this.setBlockAt(block.position, block);
|
|
7299
|
+
})
|
|
7300
|
+
));
|
|
7301
|
+
const failure = results.find((result) => result.status === "rejected");
|
|
7302
|
+
if (failure?.status === "rejected") throw failure.reason;
|
|
7295
7303
|
}
|
|
7296
|
-
}
|
|
7297
|
-
|
|
7298
|
-
await place(block);
|
|
7304
|
+
} finally {
|
|
7305
|
+
if (!executor) queue.stop();
|
|
7299
7306
|
}
|
|
7300
7307
|
}
|
|
7301
7308
|
async clear() {
|
|
7302
|
-
|
|
7303
|
-
|
|
7304
|
-
console.log("dispose chunk", chunk);
|
|
7305
|
-
await chunk?.dispose();
|
|
7309
|
+
for (const chunk of this._chunks.values()) {
|
|
7310
|
+
await chunk.dispose();
|
|
7306
7311
|
}
|
|
7307
7312
|
this._chunks.clear();
|
|
7308
7313
|
}
|
|
@@ -7316,8 +7321,7 @@ var MineRenderWorld = class {
|
|
|
7316
7321
|
return chunk;
|
|
7317
7322
|
}
|
|
7318
7323
|
getChunkAt(pos) {
|
|
7319
|
-
|
|
7320
|
-
return this._chunks[index];
|
|
7324
|
+
return this._chunks.get(this.worldPosToChunkKey(pos));
|
|
7321
7325
|
}
|
|
7322
7326
|
static worldToScenePosition(pos) {
|
|
7323
7327
|
return new Vector310(
|
|
@@ -7333,12 +7337,6 @@ var MineRenderWorld = class {
|
|
|
7333
7337
|
pos.z / 16
|
|
7334
7338
|
);
|
|
7335
7339
|
}
|
|
7336
|
-
worldPosToChunkIndex(pos) {
|
|
7337
|
-
const chunkX = Math.floor(pos.x / 16);
|
|
7338
|
-
const chunkY = Math.floor(pos.y / 16);
|
|
7339
|
-
const chunkZ = Math.floor(pos.z / 16);
|
|
7340
|
-
return chunkZ * this._size * this._size + chunkY * this._size + chunkX;
|
|
7341
|
-
}
|
|
7342
7340
|
worldPosToChunkKey(pos) {
|
|
7343
7341
|
const chunkX = Math.floor(pos.x / 16);
|
|
7344
7342
|
const chunkY = Math.floor(pos.y / 16);
|
|
@@ -7346,12 +7344,9 @@ var MineRenderWorld = class {
|
|
|
7346
7344
|
return `${chunkX}_${chunkY}_${chunkZ}`;
|
|
7347
7345
|
}
|
|
7348
7346
|
validatePosBounds(pos) {
|
|
7349
|
-
if (pos.x
|
|
7350
|
-
|
|
7351
|
-
|
|
7352
|
-
if (pos.x > this._blockSize) throw new Error("x>" + this._blockSize);
|
|
7353
|
-
if (pos.y > this._blockSize) throw new Error("y>" + this._blockSize);
|
|
7354
|
-
if (pos.z > this._blockSize) throw new Error("z>" + this._blockSize);
|
|
7347
|
+
if (![pos.x, pos.y, pos.z].every(Number.isInteger)) {
|
|
7348
|
+
throw new RangeError("Block coordinates must be integers");
|
|
7349
|
+
}
|
|
7355
7350
|
}
|
|
7356
7351
|
};
|
|
7357
7352
|
|
|
@@ -7364,16 +7359,6 @@ var Chunk = class _Chunk {
|
|
|
7364
7359
|
this.x = x;
|
|
7365
7360
|
this.y = y;
|
|
7366
7361
|
this.z = z;
|
|
7367
|
-
let anchor = new Object3D6();
|
|
7368
|
-
this._anchor = anchor;
|
|
7369
|
-
scene.add(anchor);
|
|
7370
|
-
anchor.position.set(this.x * 256 + 128 - 8, this.y * 256 + 128 - 8, this.z * 256 + 128 - 8);
|
|
7371
|
-
addBox3WireframeToObject(
|
|
7372
|
-
new Box32(new Vector311(0, 0, 0), new Vector311(256, 256, 256)),
|
|
7373
|
-
anchor,
|
|
7374
|
-
16776960,
|
|
7375
|
-
4
|
|
7376
|
-
);
|
|
7377
7362
|
}
|
|
7378
7363
|
getBlockAt(posOrX, y, z) {
|
|
7379
7364
|
if (typeof posOrX == "number") {
|
|
@@ -7399,7 +7384,7 @@ var Chunk = class _Chunk {
|
|
|
7399
7384
|
return this.setBlockInChunkAt(pos, block, worldPos);
|
|
7400
7385
|
}
|
|
7401
7386
|
/**
|
|
7402
|
-
* Set block at
|
|
7387
|
+
* Set a block at integer chunk-local coordinates from 0 to 15.
|
|
7403
7388
|
*/
|
|
7404
7389
|
async setBlockInChunkAt(pos, block, worldPos) {
|
|
7405
7390
|
if (typeof worldPos === "undefined") {
|
|
@@ -7412,15 +7397,13 @@ var Chunk = class _Chunk {
|
|
|
7412
7397
|
current.object.removeFromScene();
|
|
7413
7398
|
delete this._blocks[index];
|
|
7414
7399
|
}
|
|
7415
|
-
if (
|
|
7400
|
+
if (!block || _Chunk.isAir(block)) return void 0;
|
|
7416
7401
|
const blockState = await BlockStates.get(AssetKey.parse("blockstates", block.type));
|
|
7417
7402
|
if (blockState) {
|
|
7418
7403
|
const blockObject = await this.scene.addBlock(blockState, {
|
|
7419
7404
|
mergeMeshes: true,
|
|
7420
7405
|
instanceMeshes: true,
|
|
7421
|
-
wireframe: true,
|
|
7422
7406
|
maxInstanceCount: 2e3
|
|
7423
|
-
//TODO: setting this to high kills FPS; increase on demand somehow?
|
|
7424
7407
|
});
|
|
7425
7408
|
if (block.properties) {
|
|
7426
7409
|
await blockObject.setState(block.properties);
|
|
@@ -7436,23 +7419,21 @@ var Chunk = class _Chunk {
|
|
|
7436
7419
|
return void 0;
|
|
7437
7420
|
}
|
|
7438
7421
|
async clear() {
|
|
7439
|
-
|
|
7440
|
-
|
|
7441
|
-
for (let x = 0; x < 16; x++) {
|
|
7442
|
-
for (let z = 0; z < 16; z++) {
|
|
7443
|
-
for (let y = 0; y < 16; y++) {
|
|
7444
|
-
promises.push(this.setBlockInChunkAt(pos.set(x, y, z), void 0));
|
|
7445
|
-
}
|
|
7446
|
-
}
|
|
7447
|
-
}
|
|
7448
|
-
return Promise.all(promises).then((ignored) => {
|
|
7449
|
-
});
|
|
7422
|
+
this._blocks.forEach((block) => block.object.removeFromScene());
|
|
7423
|
+
this._blocks.length = 0;
|
|
7450
7424
|
}
|
|
7451
7425
|
async dispose() {
|
|
7452
7426
|
await this.clear();
|
|
7453
|
-
|
|
7427
|
+
}
|
|
7428
|
+
static isAir(block) {
|
|
7429
|
+
if (typeof block === "undefined" || typeof block.type === "undefined") return true;
|
|
7430
|
+
const key = AssetKey.parse("blockstates", block.type);
|
|
7431
|
+
return key.namespace === "minecraft" && !key.type && ["air", "cave_air", "void_air"].includes(key.path);
|
|
7454
7432
|
}
|
|
7455
7433
|
static chunkPosToBlockIndex(pos) {
|
|
7434
|
+
if ([pos.x, pos.y, pos.z].some((value) => !Number.isInteger(value) || value < 0 || value >= 16)) {
|
|
7435
|
+
throw new RangeError("Block coordinates must be integers from 0 to 15 within a chunk");
|
|
7436
|
+
}
|
|
7456
7437
|
return pos.y * 16 * 16 + pos.z * 16 + pos.x;
|
|
7457
7438
|
}
|
|
7458
7439
|
worldPosToChunkPos(pos) {
|