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/browser/index.mjs
CHANGED
|
@@ -29048,10 +29048,13 @@ var AnvilParser = class {
|
|
|
29048
29048
|
return this.locations(this.bytes(data)).map(({ x, z }) => ({ x, z }));
|
|
29049
29049
|
}
|
|
29050
29050
|
/** Decodes all stored chunks. Gzip, zlib, LZ4, and uncompressed payloads are supported. */
|
|
29051
|
-
static async parse(data) {
|
|
29051
|
+
static async parse(data, options = {}) {
|
|
29052
|
+
options.signal?.throwIfAborted();
|
|
29052
29053
|
const bytes = this.bytes(data);
|
|
29053
29054
|
const chunks = [];
|
|
29054
|
-
for (const location of this.locations(bytes))
|
|
29055
|
+
for (const location of this.locations(bytes)) {
|
|
29056
|
+
chunks.push(await this.abortable(this.readChunk(bytes, location, options), options.signal));
|
|
29057
|
+
}
|
|
29055
29058
|
return { chunks };
|
|
29056
29059
|
}
|
|
29057
29060
|
/**
|
|
@@ -29060,13 +29063,28 @@ var AnvilParser = class {
|
|
|
29060
29063
|
* @param localZ - Chunk z within the region, from 0 to 31.
|
|
29061
29064
|
* @returns The chunk with absolute coordinates, or `undefined` if the region has no chunk there.
|
|
29062
29065
|
*/
|
|
29063
|
-
static async parseChunk(data, localX, localZ) {
|
|
29066
|
+
static async parseChunk(data, localX, localZ, options = {}) {
|
|
29067
|
+
options.signal?.throwIfAborted();
|
|
29064
29068
|
if (![localX, localZ].every((value) => Number.isInteger(value) && value >= 0 && value < 32)) {
|
|
29065
29069
|
throw new RangeError("Region-local chunk coordinates must be integers from 0 to 31");
|
|
29066
29070
|
}
|
|
29067
29071
|
const bytes = this.bytes(data);
|
|
29068
29072
|
const location = this.locations(bytes).find(({ x, z }) => x === localX && z === localZ);
|
|
29069
|
-
return location ? this.readChunk(bytes, location) : void 0;
|
|
29073
|
+
return location ? this.abortable(this.readChunk(bytes, location, options), options.signal) : void 0;
|
|
29074
|
+
}
|
|
29075
|
+
static async abortable(promise, signal) {
|
|
29076
|
+
if (!signal) return promise;
|
|
29077
|
+
let abort;
|
|
29078
|
+
const cancelled = new Promise((_, reject) => {
|
|
29079
|
+
abort = () => reject(signal.reason);
|
|
29080
|
+
signal.addEventListener("abort", abort, { once: true });
|
|
29081
|
+
if (signal.aborted) abort();
|
|
29082
|
+
});
|
|
29083
|
+
try {
|
|
29084
|
+
return await Promise.race([promise, cancelled]);
|
|
29085
|
+
} finally {
|
|
29086
|
+
signal.removeEventListener("abort", abort);
|
|
29087
|
+
}
|
|
29070
29088
|
}
|
|
29071
29089
|
static bytes(data) {
|
|
29072
29090
|
return data instanceof Uint8Array ? data : new Uint8Array(data);
|
|
@@ -29092,20 +29110,41 @@ var AnvilParser = class {
|
|
|
29092
29110
|
}
|
|
29093
29111
|
return locations;
|
|
29094
29112
|
}
|
|
29095
|
-
static async readChunk(data, location) {
|
|
29096
|
-
|
|
29097
|
-
|
|
29113
|
+
static async readChunk(data, location, options) {
|
|
29114
|
+
options.signal?.throwIfAborted();
|
|
29115
|
+
const format2 = data[location.offset + 4];
|
|
29116
|
+
const external = (format2 & 128) !== 0;
|
|
29117
|
+
const compression = format2 & 127;
|
|
29098
29118
|
if (compression !== 1 && compression !== 2 && compression !== 3 && compression !== 4) {
|
|
29099
29119
|
throw new MineRenderError(`Unsupported Anvil compression ${compression}`);
|
|
29100
29120
|
}
|
|
29101
29121
|
let payload = data.subarray(location.offset + 5, location.offset + 4 + location.length);
|
|
29122
|
+
let expected;
|
|
29123
|
+
if (external) {
|
|
29124
|
+
if (!options.region || !options.readExternalChunk) {
|
|
29125
|
+
throw new MineRenderError("External Anvil .mcc chunks require region coordinates and readExternalChunk");
|
|
29126
|
+
}
|
|
29127
|
+
if (![options.region.x, options.region.z].every(Number.isSafeInteger)) {
|
|
29128
|
+
throw new RangeError("Anvil region coordinates must be safe integers");
|
|
29129
|
+
}
|
|
29130
|
+
expected = { x: options.region.x * 32 + location.x, z: options.region.z * 32 + location.z };
|
|
29131
|
+
if (![expected.x, expected.z].every(Number.isSafeInteger)) {
|
|
29132
|
+
throw new RangeError("External Anvil chunk coordinates must be safe integers");
|
|
29133
|
+
}
|
|
29134
|
+
const externalData = await options.readExternalChunk(expected.x, expected.z, options.signal);
|
|
29135
|
+
options.signal?.throwIfAborted();
|
|
29136
|
+
if (externalData === void 0) throw new MineRenderError(`External Anvil chunk c.${expected.x}.${expected.z}.mcc is missing`);
|
|
29137
|
+
payload = this.bytes(externalData);
|
|
29138
|
+
}
|
|
29102
29139
|
if (compression === 4) {
|
|
29103
29140
|
payload = decodeAnvilLz4(payload);
|
|
29104
29141
|
} else if (compression !== 3) {
|
|
29105
29142
|
const stream = new Blob([payload]).stream().pipeThrough(new DecompressionStream(compression === 1 ? "gzip" : "deflate"));
|
|
29106
29143
|
payload = new Uint8Array(await new Response(stream).arrayBuffer());
|
|
29107
29144
|
}
|
|
29145
|
+
options.signal?.throwIfAborted();
|
|
29108
29146
|
const nbt = await NBTHelper.fromBuffer(payload, "big");
|
|
29147
|
+
options.signal?.throwIfAborted();
|
|
29109
29148
|
const root = nbt.value;
|
|
29110
29149
|
const level = root.Level?.type === "compound" ? root.Level.value : root;
|
|
29111
29150
|
const dataVersion = root.DataVersion?.type === "int" ? root.DataVersion.value : void 0;
|
|
@@ -29118,6 +29157,9 @@ var AnvilParser = class {
|
|
|
29118
29157
|
if ((chunk.x % 32 + 32) % 32 !== location.x || (chunk.z % 32 + 32) % 32 !== location.z) {
|
|
29119
29158
|
throw new MineRenderError("Anvil chunk coordinates do not match its region location");
|
|
29120
29159
|
}
|
|
29160
|
+
if (expected && (chunk.x !== expected.x || chunk.z !== expected.z)) {
|
|
29161
|
+
throw new MineRenderError(`Anvil chunk coordinates do not match external file c.${expected.x}.${expected.z}.mcc`);
|
|
29162
|
+
}
|
|
29121
29163
|
for (const section of this.compounds(level.sections ?? level.Sections, "sections")) {
|
|
29122
29164
|
const y = this.integer(section.Y, "section Y");
|
|
29123
29165
|
if (section.Blocks || section.Data || section.Add) {
|
|
@@ -29249,6 +29291,7 @@ var AnvilWorldSource = class {
|
|
|
29249
29291
|
this.cachedBytes = 0;
|
|
29250
29292
|
this.maxCachedRegions = options.maxCachedRegions ?? 4;
|
|
29251
29293
|
this.maxCachedBytes = options.maxCachedBytes ?? 64 * 1024 * 1024;
|
|
29294
|
+
this.readExternalChunk = options.readExternalChunk;
|
|
29252
29295
|
for (const [name, value] of Object.entries({ maxCachedRegions: this.maxCachedRegions, maxCachedBytes: this.maxCachedBytes })) {
|
|
29253
29296
|
if (!Number.isSafeInteger(value) || value < 0) throw new RangeError(`${name} must be a nonnegative safe integer`);
|
|
29254
29297
|
}
|
|
@@ -29262,7 +29305,11 @@ var AnvilWorldSource = class {
|
|
|
29262
29305
|
const data = await this.getRegion(regionX, regionZ, signal);
|
|
29263
29306
|
signal?.throwIfAborted();
|
|
29264
29307
|
if (!data) return void 0;
|
|
29265
|
-
const chunk = await
|
|
29308
|
+
const chunk = await AnvilParser.parseChunk(data, x - regionX * 32, z - regionZ * 32, {
|
|
29309
|
+
region: { x: regionX, z: regionZ },
|
|
29310
|
+
readExternalChunk: this.readExternalChunk,
|
|
29311
|
+
signal
|
|
29312
|
+
});
|
|
29266
29313
|
signal?.throwIfAborted();
|
|
29267
29314
|
if (chunk && (chunk.x !== x || chunk.z !== z)) {
|
|
29268
29315
|
throw new MineRenderError(`Anvil chunk coordinates ${chunk.x},${chunk.z} do not match requested column ${x},${z}`);
|
|
@@ -29293,7 +29340,7 @@ var AnvilWorldSource = class {
|
|
|
29293
29340
|
settled: false,
|
|
29294
29341
|
promise: Promise.resolve().then(() => {
|
|
29295
29342
|
controller.signal.throwIfAborted();
|
|
29296
|
-
return this.readRegion(x, z, controller.signal);
|
|
29343
|
+
return abortable2(this.readRegion(x, z, controller.signal), controller.signal);
|
|
29297
29344
|
}).then((data) => {
|
|
29298
29345
|
controller.signal.throwIfAborted();
|
|
29299
29346
|
let bytes = data instanceof Uint8Array ? data : data === void 0 ? void 0 : new Uint8Array(data);
|