minerender 2.1.0-alpha.35 → 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.
@@ -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.push(task);
1517
+ return this.queue.add(() => task());
1516
1518
  }
1517
- run() {
1518
- for (let i = 0; i < this.batch; i++) {
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
 
@@ -7274,22 +7270,39 @@ var MineRenderWorld = class {
7274
7270
  const chunk = Chunk.isAir(value) ? this.getChunkAt(posOrX) : this.getOrCreateChunkAt(posOrX);
7275
7271
  return chunk?.setBlockAt(posOrX, value);
7276
7272
  }
7277
- async placeMultiBlock(multiblock, useBatches = true, executor = new BatchedExecutor()) {
7278
- const keys = new Set(multiblock.blocks.map((block) => AssetKey.parse("blockstates", block.type)));
7279
- await BlockStates.getAll(keys);
7280
- const place = async (block) => {
7281
- if (useBatches && typeof executor !== "undefined") {
7282
- await new Promise((resolve, reject) => {
7283
- executor.submit(() => {
7284
- this.setBlockAt(block.position, block).then(resolve).catch(reject);
7285
- });
7286
- });
7287
- } else {
7288
- await this.setBlockAt(block.position, block);
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;
7289
7303
  }
7290
- };
7291
- for (let block of multiblock.blocks) {
7292
- await place(block);
7304
+ } finally {
7305
+ if (!executor) queue.stop();
7293
7306
  }
7294
7307
  }
7295
7308
  async clear() {