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/bundle.js CHANGED
@@ -11384,7 +11384,7 @@ var MineRender = (() => {
11384
11384
  Object.defineProperty(exports13, "__esModule", { value: true });
11385
11385
  exports13.JobQueue = void 0;
11386
11386
  var Base_1 = require_Base();
11387
- var JobQueue2 = class extends Base_1.RunnerBase {
11387
+ var JobQueue3 = class extends Base_1.RunnerBase {
11388
11388
  /**
11389
11389
  * Create a new queue
11390
11390
  * @param runner function(key):Promise to execute the job
@@ -11418,7 +11418,7 @@ var MineRender = (() => {
11418
11418
  }
11419
11419
  }
11420
11420
  };
11421
- exports13.JobQueue = JobQueue2;
11421
+ exports13.JobQueue = JobQueue3;
11422
11422
  }
11423
11423
  });
11424
11424
 
@@ -70311,24 +70311,20 @@ return ${compiler2.callType("value", tagType)}
70311
70311
  init_dirname();
70312
70312
  init_buffer2();
70313
70313
  init_process2();
70314
+ var import_jobqu2 = __toESM(require_src());
70314
70315
  var BatchedExecutor = class {
70315
70316
  constructor(interval = 1, batch = 30) {
70317
+ if (!Number.isFinite(interval) || interval < 0) throw new RangeError("Batch interval must be finite and nonnegative");
70318
+ if (!Number.isInteger(batch) || batch < 1) throw new RangeError("Batch size must be a positive integer");
70316
70319
  this.interval = interval;
70317
70320
  this.batch = batch;
70318
- this.queue = [];
70319
- this.task = setInterval(() => this.run());
70321
+ this.queue = new import_jobqu2.JobQueue(async (task) => task(), { interval, maxPerRun: batch, maxActive: batch });
70320
70322
  }
70321
70323
  submit(task) {
70322
- this.queue.push(task);
70324
+ return this.queue.add(() => task());
70323
70325
  }
70324
- run() {
70325
- for (let i4 = 0; i4 < this.batch; i4++) {
70326
- this.runNext();
70327
- }
70328
- }
70329
- runNext() {
70330
- let next = this.queue.shift();
70331
- if (next) next();
70326
+ stop() {
70327
+ this.queue.end();
70332
70328
  }
70333
70329
  };
70334
70330
 
@@ -87553,9 +87549,6 @@ uniform float opacity;varying vec2 vUv;void main(){vec4 texel=texture2D(inputBuf
87553
87549
  init_process2();
87554
87550
  var MineRenderWorld = class {
87555
87551
  constructor(scene) {
87556
- this._size = 4;
87557
- //TODO: expandable
87558
- this._blockSize = this._size * 16;
87559
87552
  this._chunks = /* @__PURE__ */ new Map();
87560
87553
  this.scene = scene;
87561
87554
  }
@@ -87566,12 +87559,8 @@ uniform float opacity;varying vec2 vUv;void main(){vec4 texel=texture2D(inputBuf
87566
87559
  if (isTripleArray(posOrX)) {
87567
87560
  return this.getBlockAt(new Vector3(posOrX[0], posOrX[1], posOrX[2]));
87568
87561
  }
87569
- const chunk = this.getChunkAt(posOrX);
87570
- if (typeof chunk === "undefined") {
87571
- return void 0;
87572
- }
87573
87562
  this.validatePosBounds(posOrX);
87574
- return chunk.getBlockAt(posOrX);
87563
+ return this.getChunkAt(posOrX)?.getBlockAt(posOrX);
87575
87564
  }
87576
87565
  async setBlockAt(posOrX, yOrBlock, z4, block) {
87577
87566
  if (typeof posOrX == "number") {
@@ -87581,32 +87570,48 @@ uniform float opacity;varying vec2 vUv;void main(){vec4 texel=texture2D(inputBuf
87581
87570
  return this.setBlockAt(new Vector3(posOrX[0], posOrX[1], posOrX[2]), yOrBlock);
87582
87571
  }
87583
87572
  this.validatePosBounds(posOrX);
87584
- const chunk = this.getOrCreateChunkAt(posOrX);
87585
- return chunk.setBlockAt(posOrX, yOrBlock);
87586
- }
87587
- async placeMultiBlock(multiblock, useBatches = true, executor = new BatchedExecutor()) {
87588
- const keys = new Set(multiblock.blocks.map((block) => AssetKey.parse("blockstates", block.type)));
87589
- await BlockStates.getAll(keys);
87590
- const place = async (block) => {
87591
- if (useBatches && typeof executor !== "undefined") {
87592
- await new Promise((resolve, reject) => {
87593
- executor.submit(() => {
87594
- this.setBlockAt(block.position, block).then(resolve).catch(reject);
87595
- });
87596
- });
87597
- } else {
87598
- await this.setBlockAt(block.position, block);
87573
+ const value = yOrBlock;
87574
+ const chunk = Chunk.isAir(value) ? this.getChunkAt(posOrX) : this.getOrCreateChunkAt(posOrX);
87575
+ return chunk?.setBlockAt(posOrX, value);
87576
+ }
87577
+ async placeMultiBlock(multiblock, useBatches = true, executor) {
87578
+ const keys = /* @__PURE__ */ new Map();
87579
+ for (const block of multiblock.blocks) {
87580
+ if (Chunk.isAir(block)) continue;
87581
+ const key = AssetKey.parse("blockstates", block.type);
87582
+ keys.set(key.serialize(), key);
87583
+ }
87584
+ await BlockStates.getAll(keys.values());
87585
+ if (!useBatches) {
87586
+ for (const block of multiblock.blocks) await this.setBlockAt(block.position, block);
87587
+ return;
87588
+ }
87589
+ const positions = /* @__PURE__ */ new Map();
87590
+ for (const block of multiblock.blocks) {
87591
+ const key = block.position.join(",");
87592
+ const group = positions.get(key);
87593
+ if (group) group.push(block);
87594
+ else positions.set(key, [block]);
87595
+ }
87596
+ const groups = [...positions.values()];
87597
+ const queue2 = executor ?? new BatchedExecutor();
87598
+ try {
87599
+ for (let i4 = 0; i4 < groups.length; i4 += queue2.batch) {
87600
+ const results = await Promise.allSettled(groups.slice(i4, i4 + queue2.batch).map(
87601
+ (blocks) => queue2.submit(async () => {
87602
+ for (const block of blocks) await this.setBlockAt(block.position, block);
87603
+ })
87604
+ ));
87605
+ const failure = results.find((result) => result.status === "rejected");
87606
+ if (failure?.status === "rejected") throw failure.reason;
87599
87607
  }
87600
- };
87601
- for (let block of multiblock.blocks) {
87602
- await place(block);
87608
+ } finally {
87609
+ if (!executor) queue2.stop();
87603
87610
  }
87604
87611
  }
87605
87612
  async clear() {
87606
- console.log("CHUNKS", this._chunks);
87607
- for (let chunk of this._chunks.values()) {
87608
- console.log("dispose chunk", chunk);
87609
- await chunk?.dispose();
87613
+ for (const chunk of this._chunks.values()) {
87614
+ await chunk.dispose();
87610
87615
  }
87611
87616
  this._chunks.clear();
87612
87617
  }
@@ -87620,8 +87625,7 @@ uniform float opacity;varying vec2 vUv;void main(){vec4 texel=texture2D(inputBuf
87620
87625
  return chunk;
87621
87626
  }
87622
87627
  getChunkAt(pos) {
87623
- const index = this.worldPosToChunkIndex(pos);
87624
- return this._chunks[index];
87628
+ return this._chunks.get(this.worldPosToChunkKey(pos));
87625
87629
  }
87626
87630
  static worldToScenePosition(pos) {
87627
87631
  return new Vector3(
@@ -87637,12 +87641,6 @@ uniform float opacity;varying vec2 vUv;void main(){vec4 texel=texture2D(inputBuf
87637
87641
  pos.z / 16
87638
87642
  );
87639
87643
  }
87640
- worldPosToChunkIndex(pos) {
87641
- const chunkX = Math.floor(pos.x / 16);
87642
- const chunkY = Math.floor(pos.y / 16);
87643
- const chunkZ = Math.floor(pos.z / 16);
87644
- return chunkZ * this._size * this._size + chunkY * this._size + chunkX;
87645
- }
87646
87644
  worldPosToChunkKey(pos) {
87647
87645
  const chunkX = Math.floor(pos.x / 16);
87648
87646
  const chunkY = Math.floor(pos.y / 16);
@@ -87650,12 +87648,9 @@ uniform float opacity;varying vec2 vUv;void main(){vec4 texel=texture2D(inputBuf
87650
87648
  return `${chunkX}_${chunkY}_${chunkZ}`;
87651
87649
  }
87652
87650
  validatePosBounds(pos) {
87653
- if (pos.x < 0) throw new Error("x<0");
87654
- if (pos.y < 0) throw new Error("y<0");
87655
- if (pos.z < 0) throw new Error("z<0");
87656
- if (pos.x > this._blockSize) throw new Error("x>" + this._blockSize);
87657
- if (pos.y > this._blockSize) throw new Error("y>" + this._blockSize);
87658
- if (pos.z > this._blockSize) throw new Error("z>" + this._blockSize);
87651
+ if (![pos.x, pos.y, pos.z].every(Number.isInteger)) {
87652
+ throw new RangeError("Block coordinates must be integers");
87653
+ }
87659
87654
  }
87660
87655
  };
87661
87656
 
@@ -87668,16 +87663,6 @@ uniform float opacity;varying vec2 vUv;void main(){vec4 texel=texture2D(inputBuf
87668
87663
  this.x = x4;
87669
87664
  this.y = y5;
87670
87665
  this.z = z4;
87671
- let anchor = new Object3D();
87672
- this._anchor = anchor;
87673
- scene.add(anchor);
87674
- anchor.position.set(this.x * 256 + 128 - 8, this.y * 256 + 128 - 8, this.z * 256 + 128 - 8);
87675
- addBox3WireframeToObject(
87676
- new Box3(new Vector3(0, 0, 0), new Vector3(256, 256, 256)),
87677
- anchor,
87678
- 16776960,
87679
- 4
87680
- );
87681
87666
  }
87682
87667
  getBlockAt(posOrX, y5, z4) {
87683
87668
  if (typeof posOrX == "number") {
@@ -87703,7 +87688,7 @@ uniform float opacity;varying vec2 vUv;void main(){vec4 texel=texture2D(inputBuf
87703
87688
  return this.setBlockInChunkAt(pos, block, worldPos);
87704
87689
  }
87705
87690
  /**
87706
- * Set block at a _chunk_ position (0-16)
87691
+ * Set a block at integer chunk-local coordinates from 0 to 15.
87707
87692
  */
87708
87693
  async setBlockInChunkAt(pos, block, worldPos) {
87709
87694
  if (typeof worldPos === "undefined") {
@@ -87716,15 +87701,13 @@ uniform float opacity;varying vec2 vUv;void main(){vec4 texel=texture2D(inputBuf
87716
87701
  current.object.removeFromScene();
87717
87702
  delete this._blocks[index];
87718
87703
  }
87719
- if (typeof block === "undefined" || typeof block.type === "undefined" || block.type === "air") return void 0;
87704
+ if (!block || _Chunk.isAir(block)) return void 0;
87720
87705
  const blockState = await BlockStates.get(AssetKey.parse("blockstates", block.type));
87721
87706
  if (blockState) {
87722
87707
  const blockObject = await this.scene.addBlock(blockState, {
87723
87708
  mergeMeshes: true,
87724
87709
  instanceMeshes: true,
87725
- wireframe: true,
87726
87710
  maxInstanceCount: 2e3
87727
- //TODO: setting this to high kills FPS; increase on demand somehow?
87728
87711
  });
87729
87712
  if (block.properties) {
87730
87713
  await blockObject.setState(block.properties);
@@ -87740,23 +87723,21 @@ uniform float opacity;varying vec2 vUv;void main(){vec4 texel=texture2D(inputBuf
87740
87723
  return void 0;
87741
87724
  }
87742
87725
  async clear() {
87743
- let promises = [];
87744
- let pos = new Vector3();
87745
- for (let x4 = 0; x4 < 16; x4++) {
87746
- for (let z4 = 0; z4 < 16; z4++) {
87747
- for (let y5 = 0; y5 < 16; y5++) {
87748
- promises.push(this.setBlockInChunkAt(pos.set(x4, y5, z4), void 0));
87749
- }
87750
- }
87751
- }
87752
- return Promise.all(promises).then((ignored) => {
87753
- });
87726
+ this._blocks.forEach((block) => block.object.removeFromScene());
87727
+ this._blocks.length = 0;
87754
87728
  }
87755
87729
  async dispose() {
87756
87730
  await this.clear();
87757
- this.scene.remove(this._anchor);
87731
+ }
87732
+ static isAir(block) {
87733
+ if (typeof block === "undefined" || typeof block.type === "undefined") return true;
87734
+ const key = AssetKey.parse("blockstates", block.type);
87735
+ return key.namespace === "minecraft" && !key.type && ["air", "cave_air", "void_air"].includes(key.path);
87758
87736
  }
87759
87737
  static chunkPosToBlockIndex(pos) {
87738
+ if ([pos.x, pos.y, pos.z].some((value) => !Number.isInteger(value) || value < 0 || value >= 16)) {
87739
+ throw new RangeError("Block coordinates must be integers from 0 to 15 within a chunk");
87740
+ }
87760
87741
  return pos.y * 16 * 16 + pos.z * 16 + pos.x;
87761
87742
  }
87762
87743
  worldPosToChunkPos(pos) {