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.
@@ -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.push(task);
1510
+ return this.queue.add(() => task());
1509
1511
  }
1510
- run() {
1511
- for (let i = 0; i < this.batch; i++) {
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
 
@@ -7224,22 +7220,39 @@ var MineRenderWorld = class {
7224
7220
  const chunk = Chunk.isAir(value) ? this.getChunkAt(posOrX) : this.getOrCreateChunkAt(posOrX);
7225
7221
  return chunk?.setBlockAt(posOrX, value);
7226
7222
  }
7227
- async placeMultiBlock(multiblock, useBatches = true, executor = new BatchedExecutor()) {
7228
- const keys = new Set(multiblock.blocks.map((block) => AssetKey.parse("blockstates", block.type)));
7229
- await BlockStates.getAll(keys);
7230
- const place = async (block) => {
7231
- if (useBatches && typeof executor !== "undefined") {
7232
- await new Promise((resolve, reject) => {
7233
- executor.submit(() => {
7234
- this.setBlockAt(block.position, block).then(resolve).catch(reject);
7235
- });
7236
- });
7237
- } else {
7238
- await this.setBlockAt(block.position, block);
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;
7239
7253
  }
7240
- };
7241
- for (let block of multiblock.blocks) {
7242
- await place(block);
7254
+ } finally {
7255
+ if (!executor) queue.stop();
7243
7256
  }
7244
7257
  }
7245
7258
  async clear() {