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/browser/index.mjs
CHANGED
|
@@ -1497,24 +1497,20 @@ var AssetLoadError = class extends Error {
|
|
|
1497
1497
|
};
|
|
1498
1498
|
|
|
1499
1499
|
// src/util/BatchedExecutor.ts
|
|
1500
|
+
import { JobQueue as JobQueue2 } from "jobqu";
|
|
1500
1501
|
var BatchedExecutor = class {
|
|
1501
1502
|
constructor(interval = 1, batch = 30) {
|
|
1503
|
+
if (!Number.isFinite(interval) || interval < 0) throw new RangeError("Batch interval must be finite and nonnegative");
|
|
1504
|
+
if (!Number.isInteger(batch) || batch < 1) throw new RangeError("Batch size must be a positive integer");
|
|
1502
1505
|
this.interval = interval;
|
|
1503
1506
|
this.batch = batch;
|
|
1504
|
-
this.queue =
|
|
1505
|
-
this.task = setInterval(() => this.run());
|
|
1507
|
+
this.queue = new JobQueue2(async (task) => task(), { interval, maxPerRun: batch, maxActive: batch });
|
|
1506
1508
|
}
|
|
1507
1509
|
submit(task) {
|
|
1508
|
-
this.queue.
|
|
1510
|
+
return this.queue.add(() => task());
|
|
1509
1511
|
}
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
this.runNext();
|
|
1513
|
-
}
|
|
1514
|
-
}
|
|
1515
|
-
runNext() {
|
|
1516
|
-
let next = this.queue.shift();
|
|
1517
|
-
if (next) next();
|
|
1512
|
+
stop() {
|
|
1513
|
+
this.queue.end();
|
|
1518
1514
|
}
|
|
1519
1515
|
};
|
|
1520
1516
|
|
|
@@ -7193,15 +7189,12 @@ var Skins = class {
|
|
|
7193
7189
|
};
|
|
7194
7190
|
|
|
7195
7191
|
// src/world/Chunk.ts
|
|
7196
|
-
import {
|
|
7192
|
+
import { Vector3 as Vector311 } from "three";
|
|
7197
7193
|
|
|
7198
7194
|
// src/world/MineRenderWorld.ts
|
|
7199
7195
|
import { Vector3 as Vector310 } from "three";
|
|
7200
7196
|
var MineRenderWorld = class {
|
|
7201
7197
|
constructor(scene) {
|
|
7202
|
-
this._size = 4;
|
|
7203
|
-
//TODO: expandable
|
|
7204
|
-
this._blockSize = this._size * 16;
|
|
7205
7198
|
this._chunks = /* @__PURE__ */ new Map();
|
|
7206
7199
|
this.scene = scene;
|
|
7207
7200
|
}
|
|
@@ -7212,12 +7205,8 @@ var MineRenderWorld = class {
|
|
|
7212
7205
|
if (isTripleArray(posOrX)) {
|
|
7213
7206
|
return this.getBlockAt(new Vector310(posOrX[0], posOrX[1], posOrX[2]));
|
|
7214
7207
|
}
|
|
7215
|
-
const chunk = this.getChunkAt(posOrX);
|
|
7216
|
-
if (typeof chunk === "undefined") {
|
|
7217
|
-
return void 0;
|
|
7218
|
-
}
|
|
7219
7208
|
this.validatePosBounds(posOrX);
|
|
7220
|
-
return
|
|
7209
|
+
return this.getChunkAt(posOrX)?.getBlockAt(posOrX);
|
|
7221
7210
|
}
|
|
7222
7211
|
async setBlockAt(posOrX, yOrBlock, z, block) {
|
|
7223
7212
|
if (typeof posOrX == "number") {
|
|
@@ -7227,32 +7216,48 @@ var MineRenderWorld = class {
|
|
|
7227
7216
|
return this.setBlockAt(new Vector310(posOrX[0], posOrX[1], posOrX[2]), yOrBlock);
|
|
7228
7217
|
}
|
|
7229
7218
|
this.validatePosBounds(posOrX);
|
|
7230
|
-
const
|
|
7231
|
-
|
|
7232
|
-
|
|
7233
|
-
|
|
7234
|
-
|
|
7235
|
-
|
|
7236
|
-
const
|
|
7237
|
-
if (
|
|
7238
|
-
|
|
7239
|
-
|
|
7240
|
-
|
|
7241
|
-
|
|
7242
|
-
|
|
7243
|
-
|
|
7244
|
-
|
|
7219
|
+
const value = yOrBlock;
|
|
7220
|
+
const chunk = Chunk.isAir(value) ? this.getChunkAt(posOrX) : this.getOrCreateChunkAt(posOrX);
|
|
7221
|
+
return chunk?.setBlockAt(posOrX, value);
|
|
7222
|
+
}
|
|
7223
|
+
async placeMultiBlock(multiblock, useBatches = true, executor) {
|
|
7224
|
+
const keys = /* @__PURE__ */ new Map();
|
|
7225
|
+
for (const block of multiblock.blocks) {
|
|
7226
|
+
if (Chunk.isAir(block)) continue;
|
|
7227
|
+
const key = AssetKey.parse("blockstates", block.type);
|
|
7228
|
+
keys.set(key.serialize(), key);
|
|
7229
|
+
}
|
|
7230
|
+
await BlockStates.getAll(keys.values());
|
|
7231
|
+
if (!useBatches) {
|
|
7232
|
+
for (const block of multiblock.blocks) await this.setBlockAt(block.position, block);
|
|
7233
|
+
return;
|
|
7234
|
+
}
|
|
7235
|
+
const positions = /* @__PURE__ */ new Map();
|
|
7236
|
+
for (const block of multiblock.blocks) {
|
|
7237
|
+
const key = block.position.join(",");
|
|
7238
|
+
const group = positions.get(key);
|
|
7239
|
+
if (group) group.push(block);
|
|
7240
|
+
else positions.set(key, [block]);
|
|
7241
|
+
}
|
|
7242
|
+
const groups = [...positions.values()];
|
|
7243
|
+
const queue = executor ?? new BatchedExecutor();
|
|
7244
|
+
try {
|
|
7245
|
+
for (let i = 0; i < groups.length; i += queue.batch) {
|
|
7246
|
+
const results = await Promise.allSettled(groups.slice(i, i + queue.batch).map(
|
|
7247
|
+
(blocks) => queue.submit(async () => {
|
|
7248
|
+
for (const block of blocks) await this.setBlockAt(block.position, block);
|
|
7249
|
+
})
|
|
7250
|
+
));
|
|
7251
|
+
const failure = results.find((result) => result.status === "rejected");
|
|
7252
|
+
if (failure?.status === "rejected") throw failure.reason;
|
|
7245
7253
|
}
|
|
7246
|
-
}
|
|
7247
|
-
|
|
7248
|
-
await place(block);
|
|
7254
|
+
} finally {
|
|
7255
|
+
if (!executor) queue.stop();
|
|
7249
7256
|
}
|
|
7250
7257
|
}
|
|
7251
7258
|
async clear() {
|
|
7252
|
-
|
|
7253
|
-
|
|
7254
|
-
console.log("dispose chunk", chunk);
|
|
7255
|
-
await chunk?.dispose();
|
|
7259
|
+
for (const chunk of this._chunks.values()) {
|
|
7260
|
+
await chunk.dispose();
|
|
7256
7261
|
}
|
|
7257
7262
|
this._chunks.clear();
|
|
7258
7263
|
}
|
|
@@ -7266,8 +7271,7 @@ var MineRenderWorld = class {
|
|
|
7266
7271
|
return chunk;
|
|
7267
7272
|
}
|
|
7268
7273
|
getChunkAt(pos) {
|
|
7269
|
-
|
|
7270
|
-
return this._chunks[index];
|
|
7274
|
+
return this._chunks.get(this.worldPosToChunkKey(pos));
|
|
7271
7275
|
}
|
|
7272
7276
|
static worldToScenePosition(pos) {
|
|
7273
7277
|
return new Vector310(
|
|
@@ -7283,12 +7287,6 @@ var MineRenderWorld = class {
|
|
|
7283
7287
|
pos.z / 16
|
|
7284
7288
|
);
|
|
7285
7289
|
}
|
|
7286
|
-
worldPosToChunkIndex(pos) {
|
|
7287
|
-
const chunkX = Math.floor(pos.x / 16);
|
|
7288
|
-
const chunkY = Math.floor(pos.y / 16);
|
|
7289
|
-
const chunkZ = Math.floor(pos.z / 16);
|
|
7290
|
-
return chunkZ * this._size * this._size + chunkY * this._size + chunkX;
|
|
7291
|
-
}
|
|
7292
7290
|
worldPosToChunkKey(pos) {
|
|
7293
7291
|
const chunkX = Math.floor(pos.x / 16);
|
|
7294
7292
|
const chunkY = Math.floor(pos.y / 16);
|
|
@@ -7296,12 +7294,9 @@ var MineRenderWorld = class {
|
|
|
7296
7294
|
return `${chunkX}_${chunkY}_${chunkZ}`;
|
|
7297
7295
|
}
|
|
7298
7296
|
validatePosBounds(pos) {
|
|
7299
|
-
if (pos.x
|
|
7300
|
-
|
|
7301
|
-
|
|
7302
|
-
if (pos.x > this._blockSize) throw new Error("x>" + this._blockSize);
|
|
7303
|
-
if (pos.y > this._blockSize) throw new Error("y>" + this._blockSize);
|
|
7304
|
-
if (pos.z > this._blockSize) throw new Error("z>" + this._blockSize);
|
|
7297
|
+
if (![pos.x, pos.y, pos.z].every(Number.isInteger)) {
|
|
7298
|
+
throw new RangeError("Block coordinates must be integers");
|
|
7299
|
+
}
|
|
7305
7300
|
}
|
|
7306
7301
|
};
|
|
7307
7302
|
|
|
@@ -7314,16 +7309,6 @@ var Chunk = class _Chunk {
|
|
|
7314
7309
|
this.x = x;
|
|
7315
7310
|
this.y = y;
|
|
7316
7311
|
this.z = z;
|
|
7317
|
-
let anchor = new Object3D6();
|
|
7318
|
-
this._anchor = anchor;
|
|
7319
|
-
scene.add(anchor);
|
|
7320
|
-
anchor.position.set(this.x * 256 + 128 - 8, this.y * 256 + 128 - 8, this.z * 256 + 128 - 8);
|
|
7321
|
-
addBox3WireframeToObject(
|
|
7322
|
-
new Box32(new Vector311(0, 0, 0), new Vector311(256, 256, 256)),
|
|
7323
|
-
anchor,
|
|
7324
|
-
16776960,
|
|
7325
|
-
4
|
|
7326
|
-
);
|
|
7327
7312
|
}
|
|
7328
7313
|
getBlockAt(posOrX, y, z) {
|
|
7329
7314
|
if (typeof posOrX == "number") {
|
|
@@ -7349,7 +7334,7 @@ var Chunk = class _Chunk {
|
|
|
7349
7334
|
return this.setBlockInChunkAt(pos, block, worldPos);
|
|
7350
7335
|
}
|
|
7351
7336
|
/**
|
|
7352
|
-
* Set block at
|
|
7337
|
+
* Set a block at integer chunk-local coordinates from 0 to 15.
|
|
7353
7338
|
*/
|
|
7354
7339
|
async setBlockInChunkAt(pos, block, worldPos) {
|
|
7355
7340
|
if (typeof worldPos === "undefined") {
|
|
@@ -7362,15 +7347,13 @@ var Chunk = class _Chunk {
|
|
|
7362
7347
|
current.object.removeFromScene();
|
|
7363
7348
|
delete this._blocks[index];
|
|
7364
7349
|
}
|
|
7365
|
-
if (
|
|
7350
|
+
if (!block || _Chunk.isAir(block)) return void 0;
|
|
7366
7351
|
const blockState = await BlockStates.get(AssetKey.parse("blockstates", block.type));
|
|
7367
7352
|
if (blockState) {
|
|
7368
7353
|
const blockObject = await this.scene.addBlock(blockState, {
|
|
7369
7354
|
mergeMeshes: true,
|
|
7370
7355
|
instanceMeshes: true,
|
|
7371
|
-
wireframe: true,
|
|
7372
7356
|
maxInstanceCount: 2e3
|
|
7373
|
-
//TODO: setting this to high kills FPS; increase on demand somehow?
|
|
7374
7357
|
});
|
|
7375
7358
|
if (block.properties) {
|
|
7376
7359
|
await blockObject.setState(block.properties);
|
|
@@ -7386,23 +7369,21 @@ var Chunk = class _Chunk {
|
|
|
7386
7369
|
return void 0;
|
|
7387
7370
|
}
|
|
7388
7371
|
async clear() {
|
|
7389
|
-
|
|
7390
|
-
|
|
7391
|
-
for (let x = 0; x < 16; x++) {
|
|
7392
|
-
for (let z = 0; z < 16; z++) {
|
|
7393
|
-
for (let y = 0; y < 16; y++) {
|
|
7394
|
-
promises.push(this.setBlockInChunkAt(pos.set(x, y, z), void 0));
|
|
7395
|
-
}
|
|
7396
|
-
}
|
|
7397
|
-
}
|
|
7398
|
-
return Promise.all(promises).then((ignored) => {
|
|
7399
|
-
});
|
|
7372
|
+
this._blocks.forEach((block) => block.object.removeFromScene());
|
|
7373
|
+
this._blocks.length = 0;
|
|
7400
7374
|
}
|
|
7401
7375
|
async dispose() {
|
|
7402
7376
|
await this.clear();
|
|
7403
|
-
|
|
7377
|
+
}
|
|
7378
|
+
static isAir(block) {
|
|
7379
|
+
if (typeof block === "undefined" || typeof block.type === "undefined") return true;
|
|
7380
|
+
const key = AssetKey.parse("blockstates", block.type);
|
|
7381
|
+
return key.namespace === "minecraft" && !key.type && ["air", "cave_air", "void_air"].includes(key.path);
|
|
7404
7382
|
}
|
|
7405
7383
|
static chunkPosToBlockIndex(pos) {
|
|
7384
|
+
if ([pos.x, pos.y, pos.z].some((value) => !Number.isInteger(value) || value < 0 || value >= 16)) {
|
|
7385
|
+
throw new RangeError("Block coordinates must be integers from 0 to 15 within a chunk");
|
|
7386
|
+
}
|
|
7406
7387
|
return pos.y * 16 * 16 + pos.z * 16 + pos.x;
|
|
7407
7388
|
}
|
|
7408
7389
|
worldPosToChunkPos(pos) {
|