minerender 2.1.0-alpha.91 → 2.1.0-alpha.92
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 +21 -4
- package/dist/browser/index.d.ts +21 -4
- package/dist/browser/index.js +56 -9
- package/dist/browser/index.js.map +1 -1
- package/dist/browser/index.mjs +56 -9
- package/dist/browser/index.mjs.map +1 -1
- package/dist/bundle.js +56 -9
- package/dist/bundle.js.map +1 -1
- package/dist/node/index.d.mts +21 -4
- package/dist/node/index.d.ts +21 -4
- package/dist/node/index.js +56 -9
- package/dist/node/index.js.map +1 -1
- package/dist/node/index.mjs +56 -9
- package/dist/node/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/node/index.mjs
CHANGED
|
@@ -29097,10 +29097,13 @@ var AnvilParser = class {
|
|
|
29097
29097
|
return this.locations(this.bytes(data)).map(({ x, z }) => ({ x, z }));
|
|
29098
29098
|
}
|
|
29099
29099
|
/** Decodes all stored chunks. Gzip, zlib, LZ4, and uncompressed payloads are supported. */
|
|
29100
|
-
static async parse(data) {
|
|
29100
|
+
static async parse(data, options = {}) {
|
|
29101
|
+
options.signal?.throwIfAborted();
|
|
29101
29102
|
const bytes = this.bytes(data);
|
|
29102
29103
|
const chunks = [];
|
|
29103
|
-
for (const location of this.locations(bytes))
|
|
29104
|
+
for (const location of this.locations(bytes)) {
|
|
29105
|
+
chunks.push(await this.abortable(this.readChunk(bytes, location, options), options.signal));
|
|
29106
|
+
}
|
|
29104
29107
|
return { chunks };
|
|
29105
29108
|
}
|
|
29106
29109
|
/**
|
|
@@ -29109,13 +29112,28 @@ var AnvilParser = class {
|
|
|
29109
29112
|
* @param localZ - Chunk z within the region, from 0 to 31.
|
|
29110
29113
|
* @returns The chunk with absolute coordinates, or `undefined` if the region has no chunk there.
|
|
29111
29114
|
*/
|
|
29112
|
-
static async parseChunk(data, localX, localZ) {
|
|
29115
|
+
static async parseChunk(data, localX, localZ, options = {}) {
|
|
29116
|
+
options.signal?.throwIfAborted();
|
|
29113
29117
|
if (![localX, localZ].every((value) => Number.isInteger(value) && value >= 0 && value < 32)) {
|
|
29114
29118
|
throw new RangeError("Region-local chunk coordinates must be integers from 0 to 31");
|
|
29115
29119
|
}
|
|
29116
29120
|
const bytes = this.bytes(data);
|
|
29117
29121
|
const location = this.locations(bytes).find(({ x, z }) => x === localX && z === localZ);
|
|
29118
|
-
return location ? this.readChunk(bytes, location) : void 0;
|
|
29122
|
+
return location ? this.abortable(this.readChunk(bytes, location, options), options.signal) : void 0;
|
|
29123
|
+
}
|
|
29124
|
+
static async abortable(promise, signal) {
|
|
29125
|
+
if (!signal) return promise;
|
|
29126
|
+
let abort;
|
|
29127
|
+
const cancelled = new Promise((_, reject) => {
|
|
29128
|
+
abort = () => reject(signal.reason);
|
|
29129
|
+
signal.addEventListener("abort", abort, { once: true });
|
|
29130
|
+
if (signal.aborted) abort();
|
|
29131
|
+
});
|
|
29132
|
+
try {
|
|
29133
|
+
return await Promise.race([promise, cancelled]);
|
|
29134
|
+
} finally {
|
|
29135
|
+
signal.removeEventListener("abort", abort);
|
|
29136
|
+
}
|
|
29119
29137
|
}
|
|
29120
29138
|
static bytes(data) {
|
|
29121
29139
|
return data instanceof Uint8Array ? data : new Uint8Array(data);
|
|
@@ -29141,20 +29159,41 @@ var AnvilParser = class {
|
|
|
29141
29159
|
}
|
|
29142
29160
|
return locations;
|
|
29143
29161
|
}
|
|
29144
|
-
static async readChunk(data, location) {
|
|
29145
|
-
|
|
29146
|
-
|
|
29162
|
+
static async readChunk(data, location, options) {
|
|
29163
|
+
options.signal?.throwIfAborted();
|
|
29164
|
+
const format2 = data[location.offset + 4];
|
|
29165
|
+
const external = (format2 & 128) !== 0;
|
|
29166
|
+
const compression = format2 & 127;
|
|
29147
29167
|
if (compression !== 1 && compression !== 2 && compression !== 3 && compression !== 4) {
|
|
29148
29168
|
throw new MineRenderError(`Unsupported Anvil compression ${compression}`);
|
|
29149
29169
|
}
|
|
29150
29170
|
let payload = data.subarray(location.offset + 5, location.offset + 4 + location.length);
|
|
29171
|
+
let expected;
|
|
29172
|
+
if (external) {
|
|
29173
|
+
if (!options.region || !options.readExternalChunk) {
|
|
29174
|
+
throw new MineRenderError("External Anvil .mcc chunks require region coordinates and readExternalChunk");
|
|
29175
|
+
}
|
|
29176
|
+
if (![options.region.x, options.region.z].every(Number.isSafeInteger)) {
|
|
29177
|
+
throw new RangeError("Anvil region coordinates must be safe integers");
|
|
29178
|
+
}
|
|
29179
|
+
expected = { x: options.region.x * 32 + location.x, z: options.region.z * 32 + location.z };
|
|
29180
|
+
if (![expected.x, expected.z].every(Number.isSafeInteger)) {
|
|
29181
|
+
throw new RangeError("External Anvil chunk coordinates must be safe integers");
|
|
29182
|
+
}
|
|
29183
|
+
const externalData = await options.readExternalChunk(expected.x, expected.z, options.signal);
|
|
29184
|
+
options.signal?.throwIfAborted();
|
|
29185
|
+
if (externalData === void 0) throw new MineRenderError(`External Anvil chunk c.${expected.x}.${expected.z}.mcc is missing`);
|
|
29186
|
+
payload = this.bytes(externalData);
|
|
29187
|
+
}
|
|
29151
29188
|
if (compression === 4) {
|
|
29152
29189
|
payload = decodeAnvilLz4(payload);
|
|
29153
29190
|
} else if (compression !== 3) {
|
|
29154
29191
|
const stream = new Blob([payload]).stream().pipeThrough(new DecompressionStream(compression === 1 ? "gzip" : "deflate"));
|
|
29155
29192
|
payload = new Uint8Array(await new Response(stream).arrayBuffer());
|
|
29156
29193
|
}
|
|
29194
|
+
options.signal?.throwIfAborted();
|
|
29157
29195
|
const nbt = await NBTHelper.fromBuffer(payload, "big");
|
|
29196
|
+
options.signal?.throwIfAborted();
|
|
29158
29197
|
const root = nbt.value;
|
|
29159
29198
|
const level = root.Level?.type === "compound" ? root.Level.value : root;
|
|
29160
29199
|
const dataVersion = root.DataVersion?.type === "int" ? root.DataVersion.value : void 0;
|
|
@@ -29167,6 +29206,9 @@ var AnvilParser = class {
|
|
|
29167
29206
|
if ((chunk.x % 32 + 32) % 32 !== location.x || (chunk.z % 32 + 32) % 32 !== location.z) {
|
|
29168
29207
|
throw new MineRenderError("Anvil chunk coordinates do not match its region location");
|
|
29169
29208
|
}
|
|
29209
|
+
if (expected && (chunk.x !== expected.x || chunk.z !== expected.z)) {
|
|
29210
|
+
throw new MineRenderError(`Anvil chunk coordinates do not match external file c.${expected.x}.${expected.z}.mcc`);
|
|
29211
|
+
}
|
|
29170
29212
|
for (const section of this.compounds(level.sections ?? level.Sections, "sections")) {
|
|
29171
29213
|
const y = this.integer(section.Y, "section Y");
|
|
29172
29214
|
if (section.Blocks || section.Data || section.Add) {
|
|
@@ -29298,6 +29340,7 @@ var AnvilWorldSource = class {
|
|
|
29298
29340
|
this.cachedBytes = 0;
|
|
29299
29341
|
this.maxCachedRegions = options.maxCachedRegions ?? 4;
|
|
29300
29342
|
this.maxCachedBytes = options.maxCachedBytes ?? 64 * 1024 * 1024;
|
|
29343
|
+
this.readExternalChunk = options.readExternalChunk;
|
|
29301
29344
|
for (const [name, value] of Object.entries({ maxCachedRegions: this.maxCachedRegions, maxCachedBytes: this.maxCachedBytes })) {
|
|
29302
29345
|
if (!Number.isSafeInteger(value) || value < 0) throw new RangeError(`${name} must be a nonnegative safe integer`);
|
|
29303
29346
|
}
|
|
@@ -29311,7 +29354,11 @@ var AnvilWorldSource = class {
|
|
|
29311
29354
|
const data = await this.getRegion(regionX, regionZ, signal);
|
|
29312
29355
|
signal?.throwIfAborted();
|
|
29313
29356
|
if (!data) return void 0;
|
|
29314
|
-
const chunk = await
|
|
29357
|
+
const chunk = await AnvilParser.parseChunk(data, x - regionX * 32, z - regionZ * 32, {
|
|
29358
|
+
region: { x: regionX, z: regionZ },
|
|
29359
|
+
readExternalChunk: this.readExternalChunk,
|
|
29360
|
+
signal
|
|
29361
|
+
});
|
|
29315
29362
|
signal?.throwIfAborted();
|
|
29316
29363
|
if (chunk && (chunk.x !== x || chunk.z !== z)) {
|
|
29317
29364
|
throw new MineRenderError(`Anvil chunk coordinates ${chunk.x},${chunk.z} do not match requested column ${x},${z}`);
|
|
@@ -29342,7 +29389,7 @@ var AnvilWorldSource = class {
|
|
|
29342
29389
|
settled: false,
|
|
29343
29390
|
promise: Promise.resolve().then(() => {
|
|
29344
29391
|
controller.signal.throwIfAborted();
|
|
29345
|
-
return this.readRegion(x, z, controller.signal);
|
|
29392
|
+
return abortable2(this.readRegion(x, z, controller.signal), controller.signal);
|
|
29346
29393
|
}).then((data) => {
|
|
29347
29394
|
controller.signal.throwIfAborted();
|
|
29348
29395
|
let bytes = data instanceof Uint8Array ? data : data === void 0 ? void 0 : new Uint8Array(data);
|