minerender 2.1.0-alpha.90 → 2.1.0-alpha.91
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 +1 -1
- package/dist/browser/index.d.ts +1 -1
- package/dist/browser/index.js +124 -4
- package/dist/browser/index.js.map +1 -1
- package/dist/browser/index.mjs +124 -4
- package/dist/browser/index.mjs.map +1 -1
- package/dist/bundle.js +127 -4
- package/dist/bundle.js.map +1 -1
- package/dist/node/index.d.mts +1 -1
- package/dist/node/index.d.ts +1 -1
- package/dist/node/index.js +124 -4
- package/dist/node/index.js.map +1 -1
- package/dist/node/index.mjs +124 -4
- package/dist/node/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/node/index.mjs
CHANGED
|
@@ -28972,13 +28972,131 @@ var ChunkData = class _ChunkData {
|
|
|
28972
28972
|
}
|
|
28973
28973
|
};
|
|
28974
28974
|
|
|
28975
|
+
// src/world/_compression/Lz4.ts
|
|
28976
|
+
init_MineRenderError();
|
|
28977
|
+
function decodeAnvilLz4(data) {
|
|
28978
|
+
const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
|
|
28979
|
+
const blocks = [];
|
|
28980
|
+
let cursor = 0, totalSize = 0;
|
|
28981
|
+
while (true) {
|
|
28982
|
+
if (cursor + 21 > data.length) throw invalid("truncated block header or missing terminator");
|
|
28983
|
+
if (view.getUint32(cursor) !== 1280980034 || view.getUint32(cursor + 4) !== 1819239275) {
|
|
28984
|
+
throw invalid("invalid block signature");
|
|
28985
|
+
}
|
|
28986
|
+
const token = data[cursor + 8];
|
|
28987
|
+
const method = token & 240;
|
|
28988
|
+
const size = view.getInt32(cursor + 9, true);
|
|
28989
|
+
const decodedSize = view.getInt32(cursor + 13, true);
|
|
28990
|
+
const checksum = view.getUint32(cursor + 17, true);
|
|
28991
|
+
cursor += 21;
|
|
28992
|
+
if (method !== 16 && method !== 32) throw invalid("unsupported block method");
|
|
28993
|
+
if (size < 0 || decodedSize < 0 || decodedSize > 2 ** (10 + (token & 15)) || size === 0 !== (decodedSize === 0) || method === 16 && size !== decodedSize) {
|
|
28994
|
+
throw invalid("invalid block lengths");
|
|
28995
|
+
}
|
|
28996
|
+
if (size === 0) {
|
|
28997
|
+
if (checksum !== 0 || cursor !== data.length) throw invalid("invalid terminator or trailing bytes");
|
|
28998
|
+
break;
|
|
28999
|
+
}
|
|
29000
|
+
if (cursor + size > data.length || decodedSize > size * 255) throw invalid("invalid block lengths");
|
|
29001
|
+
blocks.push({ start: cursor, size, decodedSize, raw: method === 16, checksum });
|
|
29002
|
+
totalSize += decodedSize;
|
|
29003
|
+
cursor += size;
|
|
29004
|
+
}
|
|
29005
|
+
const output = new Uint8Array(totalSize);
|
|
29006
|
+
let offset = 0;
|
|
29007
|
+
for (const block of blocks) {
|
|
29008
|
+
const source = data.subarray(block.start, block.start + block.size);
|
|
29009
|
+
const target = output.subarray(offset, offset + block.decodedSize);
|
|
29010
|
+
if (block.raw) target.set(source);
|
|
29011
|
+
else decodeBlock(source, target);
|
|
29012
|
+
if (checksum32(target) !== block.checksum) throw invalid("block checksum mismatch");
|
|
29013
|
+
offset += block.decodedSize;
|
|
29014
|
+
}
|
|
29015
|
+
return output;
|
|
29016
|
+
}
|
|
29017
|
+
function decodeBlock(source, target) {
|
|
29018
|
+
let input = 0, output = 0, matched = false;
|
|
29019
|
+
const length = (nibble) => {
|
|
29020
|
+
let value = nibble;
|
|
29021
|
+
if (value === 15) {
|
|
29022
|
+
let extension;
|
|
29023
|
+
do {
|
|
29024
|
+
if (input === source.length) throw invalid("truncated sequence length");
|
|
29025
|
+
extension = source[input++];
|
|
29026
|
+
value += extension;
|
|
29027
|
+
} while (extension === 255);
|
|
29028
|
+
}
|
|
29029
|
+
return value;
|
|
29030
|
+
};
|
|
29031
|
+
while (input < source.length) {
|
|
29032
|
+
const token = source[input++];
|
|
29033
|
+
const literals = length(token >>> 4);
|
|
29034
|
+
if (input + literals > source.length || output + literals > target.length) {
|
|
29035
|
+
throw invalid("literal sequence exceeds block bounds");
|
|
29036
|
+
}
|
|
29037
|
+
target.set(source.subarray(input, input + literals), output);
|
|
29038
|
+
input += literals;
|
|
29039
|
+
output += literals;
|
|
29040
|
+
if (input === source.length) {
|
|
29041
|
+
if (output !== target.length || matched && literals < 5) throw invalid("invalid final literal sequence");
|
|
29042
|
+
return;
|
|
29043
|
+
}
|
|
29044
|
+
if (input + 2 > source.length) throw invalid("truncated match offset");
|
|
29045
|
+
const distance = source[input] | source[input + 1] << 8;
|
|
29046
|
+
input += 2;
|
|
29047
|
+
if (distance === 0 || distance > output) throw invalid("match offset exceeds block history");
|
|
29048
|
+
const count = length(token & 15) + 4;
|
|
29049
|
+
if (output > target.length - 12 || output + count > target.length - 5) {
|
|
29050
|
+
throw invalid("match exceeds block bounds");
|
|
29051
|
+
}
|
|
29052
|
+
for (let end = output + count; output < end; output++) target[output] = target[output - distance];
|
|
29053
|
+
matched = true;
|
|
29054
|
+
}
|
|
29055
|
+
throw invalid("missing final literal sequence");
|
|
29056
|
+
}
|
|
29057
|
+
function checksum32(data) {
|
|
29058
|
+
const prime1 = 2654435761, prime2 = 2246822519, prime3 = 3266489917, prime4 = 668265263, prime5 = 374761393;
|
|
29059
|
+
const seed = 2538058380;
|
|
29060
|
+
const rotate = (value, bits) => value << bits | value >>> 32 - bits;
|
|
29061
|
+
const round = (value, word) => Math.imul(rotate(value + Math.imul(word, prime2), 13), prime1);
|
|
29062
|
+
const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
|
|
29063
|
+
let cursor = 0, hash;
|
|
29064
|
+
if (data.length >= 16) {
|
|
29065
|
+
let a = seed + prime1 + prime2, b = seed + prime2, c = seed, d = seed - prime1;
|
|
29066
|
+
while (cursor + 16 <= data.length) {
|
|
29067
|
+
a = round(a, view.getUint32(cursor, true));
|
|
29068
|
+
b = round(b, view.getUint32(cursor + 4, true));
|
|
29069
|
+
c = round(c, view.getUint32(cursor + 8, true));
|
|
29070
|
+
d = round(d, view.getUint32(cursor + 12, true));
|
|
29071
|
+
cursor += 16;
|
|
29072
|
+
}
|
|
29073
|
+
hash = rotate(a, 1) + rotate(b, 7) + rotate(c, 12) + rotate(d, 18);
|
|
29074
|
+
} else {
|
|
29075
|
+
hash = seed + prime5;
|
|
29076
|
+
}
|
|
29077
|
+
hash += data.length;
|
|
29078
|
+
while (cursor + 4 <= data.length) {
|
|
29079
|
+
hash = Math.imul(rotate(hash + Math.imul(view.getUint32(cursor, true), prime3), 17), prime4);
|
|
29080
|
+
cursor += 4;
|
|
29081
|
+
}
|
|
29082
|
+
while (cursor < data.length) {
|
|
29083
|
+
hash = Math.imul(rotate(hash + Math.imul(data[cursor++], prime5), 11), prime1);
|
|
29084
|
+
}
|
|
29085
|
+
hash = Math.imul(hash ^ hash >>> 15, prime2);
|
|
29086
|
+
hash = Math.imul(hash ^ hash >>> 13, prime3);
|
|
29087
|
+
return (hash ^ hash >>> 16) & 268435455;
|
|
29088
|
+
}
|
|
29089
|
+
function invalid(detail) {
|
|
29090
|
+
return new MineRenderError(`Invalid Anvil LZ4 stream: ${detail}`);
|
|
29091
|
+
}
|
|
29092
|
+
|
|
28975
29093
|
// src/world/AnvilParser.ts
|
|
28976
29094
|
var AnvilParser = class {
|
|
28977
29095
|
/** Lists occupied chunk positions within the region, using local coordinates from 0 to 31. */
|
|
28978
29096
|
static getChunkList(data) {
|
|
28979
29097
|
return this.locations(this.bytes(data)).map(({ x, z }) => ({ x, z }));
|
|
28980
29098
|
}
|
|
28981
|
-
/** Decodes all stored chunks. Gzip, zlib, and uncompressed payloads are supported. */
|
|
29099
|
+
/** Decodes all stored chunks. Gzip, zlib, LZ4, and uncompressed payloads are supported. */
|
|
28982
29100
|
static async parse(data) {
|
|
28983
29101
|
const bytes = this.bytes(data);
|
|
28984
29102
|
const chunks = [];
|
|
@@ -29026,11 +29144,13 @@ var AnvilParser = class {
|
|
|
29026
29144
|
static async readChunk(data, location) {
|
|
29027
29145
|
const compression = data[location.offset + 4];
|
|
29028
29146
|
if (compression & 128) throw new MineRenderError("External Anvil .mcc chunks are not supported");
|
|
29029
|
-
if (compression !== 1 && compression !== 2 && compression !== 3) {
|
|
29030
|
-
throw new MineRenderError(`Unsupported Anvil compression ${compression}
|
|
29147
|
+
if (compression !== 1 && compression !== 2 && compression !== 3 && compression !== 4) {
|
|
29148
|
+
throw new MineRenderError(`Unsupported Anvil compression ${compression}`);
|
|
29031
29149
|
}
|
|
29032
29150
|
let payload = data.subarray(location.offset + 5, location.offset + 4 + location.length);
|
|
29033
|
-
if (compression
|
|
29151
|
+
if (compression === 4) {
|
|
29152
|
+
payload = decodeAnvilLz4(payload);
|
|
29153
|
+
} else if (compression !== 3) {
|
|
29034
29154
|
const stream = new Blob([payload]).stream().pipeThrough(new DecompressionStream(compression === 1 ? "gzip" : "deflate"));
|
|
29035
29155
|
payload = new Uint8Array(await new Response(stream).arrayBuffer());
|
|
29036
29156
|
}
|