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.d.mts
CHANGED
|
@@ -3178,7 +3178,7 @@ declare class AnvilParser {
|
|
|
3178
3178
|
x: number;
|
|
3179
3179
|
z: number;
|
|
3180
3180
|
}[];
|
|
3181
|
-
/** Decodes all stored chunks. Gzip, zlib, and uncompressed payloads are supported. */
|
|
3181
|
+
/** Decodes all stored chunks. Gzip, zlib, LZ4, and uncompressed payloads are supported. */
|
|
3182
3182
|
static parse(data: RegionInput): Promise<AnvilRegion>;
|
|
3183
3183
|
/**
|
|
3184
3184
|
* Decodes one chunk for {@link MineRenderWorld.placeChunk}.
|
package/dist/node/index.d.ts
CHANGED
|
@@ -3178,7 +3178,7 @@ declare class AnvilParser {
|
|
|
3178
3178
|
x: number;
|
|
3179
3179
|
z: number;
|
|
3180
3180
|
}[];
|
|
3181
|
-
/** Decodes all stored chunks. Gzip, zlib, and uncompressed payloads are supported. */
|
|
3181
|
+
/** Decodes all stored chunks. Gzip, zlib, LZ4, and uncompressed payloads are supported. */
|
|
3182
3182
|
static parse(data: RegionInput): Promise<AnvilRegion>;
|
|
3183
3183
|
/**
|
|
3184
3184
|
* Decodes one chunk for {@link MineRenderWorld.placeChunk}.
|
package/dist/node/index.js
CHANGED
|
@@ -29113,13 +29113,131 @@ var ChunkData = class _ChunkData {
|
|
|
29113
29113
|
}
|
|
29114
29114
|
};
|
|
29115
29115
|
|
|
29116
|
+
// src/world/_compression/Lz4.ts
|
|
29117
|
+
init_MineRenderError();
|
|
29118
|
+
function decodeAnvilLz4(data) {
|
|
29119
|
+
const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
|
|
29120
|
+
const blocks = [];
|
|
29121
|
+
let cursor = 0, totalSize = 0;
|
|
29122
|
+
while (true) {
|
|
29123
|
+
if (cursor + 21 > data.length) throw invalid("truncated block header or missing terminator");
|
|
29124
|
+
if (view.getUint32(cursor) !== 1280980034 || view.getUint32(cursor + 4) !== 1819239275) {
|
|
29125
|
+
throw invalid("invalid block signature");
|
|
29126
|
+
}
|
|
29127
|
+
const token = data[cursor + 8];
|
|
29128
|
+
const method = token & 240;
|
|
29129
|
+
const size = view.getInt32(cursor + 9, true);
|
|
29130
|
+
const decodedSize = view.getInt32(cursor + 13, true);
|
|
29131
|
+
const checksum = view.getUint32(cursor + 17, true);
|
|
29132
|
+
cursor += 21;
|
|
29133
|
+
if (method !== 16 && method !== 32) throw invalid("unsupported block method");
|
|
29134
|
+
if (size < 0 || decodedSize < 0 || decodedSize > 2 ** (10 + (token & 15)) || size === 0 !== (decodedSize === 0) || method === 16 && size !== decodedSize) {
|
|
29135
|
+
throw invalid("invalid block lengths");
|
|
29136
|
+
}
|
|
29137
|
+
if (size === 0) {
|
|
29138
|
+
if (checksum !== 0 || cursor !== data.length) throw invalid("invalid terminator or trailing bytes");
|
|
29139
|
+
break;
|
|
29140
|
+
}
|
|
29141
|
+
if (cursor + size > data.length || decodedSize > size * 255) throw invalid("invalid block lengths");
|
|
29142
|
+
blocks.push({ start: cursor, size, decodedSize, raw: method === 16, checksum });
|
|
29143
|
+
totalSize += decodedSize;
|
|
29144
|
+
cursor += size;
|
|
29145
|
+
}
|
|
29146
|
+
const output = new Uint8Array(totalSize);
|
|
29147
|
+
let offset = 0;
|
|
29148
|
+
for (const block of blocks) {
|
|
29149
|
+
const source = data.subarray(block.start, block.start + block.size);
|
|
29150
|
+
const target = output.subarray(offset, offset + block.decodedSize);
|
|
29151
|
+
if (block.raw) target.set(source);
|
|
29152
|
+
else decodeBlock(source, target);
|
|
29153
|
+
if (checksum32(target) !== block.checksum) throw invalid("block checksum mismatch");
|
|
29154
|
+
offset += block.decodedSize;
|
|
29155
|
+
}
|
|
29156
|
+
return output;
|
|
29157
|
+
}
|
|
29158
|
+
function decodeBlock(source, target) {
|
|
29159
|
+
let input = 0, output = 0, matched = false;
|
|
29160
|
+
const length = (nibble) => {
|
|
29161
|
+
let value = nibble;
|
|
29162
|
+
if (value === 15) {
|
|
29163
|
+
let extension;
|
|
29164
|
+
do {
|
|
29165
|
+
if (input === source.length) throw invalid("truncated sequence length");
|
|
29166
|
+
extension = source[input++];
|
|
29167
|
+
value += extension;
|
|
29168
|
+
} while (extension === 255);
|
|
29169
|
+
}
|
|
29170
|
+
return value;
|
|
29171
|
+
};
|
|
29172
|
+
while (input < source.length) {
|
|
29173
|
+
const token = source[input++];
|
|
29174
|
+
const literals = length(token >>> 4);
|
|
29175
|
+
if (input + literals > source.length || output + literals > target.length) {
|
|
29176
|
+
throw invalid("literal sequence exceeds block bounds");
|
|
29177
|
+
}
|
|
29178
|
+
target.set(source.subarray(input, input + literals), output);
|
|
29179
|
+
input += literals;
|
|
29180
|
+
output += literals;
|
|
29181
|
+
if (input === source.length) {
|
|
29182
|
+
if (output !== target.length || matched && literals < 5) throw invalid("invalid final literal sequence");
|
|
29183
|
+
return;
|
|
29184
|
+
}
|
|
29185
|
+
if (input + 2 > source.length) throw invalid("truncated match offset");
|
|
29186
|
+
const distance = source[input] | source[input + 1] << 8;
|
|
29187
|
+
input += 2;
|
|
29188
|
+
if (distance === 0 || distance > output) throw invalid("match offset exceeds block history");
|
|
29189
|
+
const count = length(token & 15) + 4;
|
|
29190
|
+
if (output > target.length - 12 || output + count > target.length - 5) {
|
|
29191
|
+
throw invalid("match exceeds block bounds");
|
|
29192
|
+
}
|
|
29193
|
+
for (let end = output + count; output < end; output++) target[output] = target[output - distance];
|
|
29194
|
+
matched = true;
|
|
29195
|
+
}
|
|
29196
|
+
throw invalid("missing final literal sequence");
|
|
29197
|
+
}
|
|
29198
|
+
function checksum32(data) {
|
|
29199
|
+
const prime1 = 2654435761, prime2 = 2246822519, prime3 = 3266489917, prime4 = 668265263, prime5 = 374761393;
|
|
29200
|
+
const seed = 2538058380;
|
|
29201
|
+
const rotate = (value, bits) => value << bits | value >>> 32 - bits;
|
|
29202
|
+
const round = (value, word) => Math.imul(rotate(value + Math.imul(word, prime2), 13), prime1);
|
|
29203
|
+
const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
|
|
29204
|
+
let cursor = 0, hash;
|
|
29205
|
+
if (data.length >= 16) {
|
|
29206
|
+
let a = seed + prime1 + prime2, b = seed + prime2, c = seed, d = seed - prime1;
|
|
29207
|
+
while (cursor + 16 <= data.length) {
|
|
29208
|
+
a = round(a, view.getUint32(cursor, true));
|
|
29209
|
+
b = round(b, view.getUint32(cursor + 4, true));
|
|
29210
|
+
c = round(c, view.getUint32(cursor + 8, true));
|
|
29211
|
+
d = round(d, view.getUint32(cursor + 12, true));
|
|
29212
|
+
cursor += 16;
|
|
29213
|
+
}
|
|
29214
|
+
hash = rotate(a, 1) + rotate(b, 7) + rotate(c, 12) + rotate(d, 18);
|
|
29215
|
+
} else {
|
|
29216
|
+
hash = seed + prime5;
|
|
29217
|
+
}
|
|
29218
|
+
hash += data.length;
|
|
29219
|
+
while (cursor + 4 <= data.length) {
|
|
29220
|
+
hash = Math.imul(rotate(hash + Math.imul(view.getUint32(cursor, true), prime3), 17), prime4);
|
|
29221
|
+
cursor += 4;
|
|
29222
|
+
}
|
|
29223
|
+
while (cursor < data.length) {
|
|
29224
|
+
hash = Math.imul(rotate(hash + Math.imul(data[cursor++], prime5), 11), prime1);
|
|
29225
|
+
}
|
|
29226
|
+
hash = Math.imul(hash ^ hash >>> 15, prime2);
|
|
29227
|
+
hash = Math.imul(hash ^ hash >>> 13, prime3);
|
|
29228
|
+
return (hash ^ hash >>> 16) & 268435455;
|
|
29229
|
+
}
|
|
29230
|
+
function invalid(detail) {
|
|
29231
|
+
return new MineRenderError(`Invalid Anvil LZ4 stream: ${detail}`);
|
|
29232
|
+
}
|
|
29233
|
+
|
|
29116
29234
|
// src/world/AnvilParser.ts
|
|
29117
29235
|
var AnvilParser = class {
|
|
29118
29236
|
/** Lists occupied chunk positions within the region, using local coordinates from 0 to 31. */
|
|
29119
29237
|
static getChunkList(data) {
|
|
29120
29238
|
return this.locations(this.bytes(data)).map(({ x, z }) => ({ x, z }));
|
|
29121
29239
|
}
|
|
29122
|
-
/** Decodes all stored chunks. Gzip, zlib, and uncompressed payloads are supported. */
|
|
29240
|
+
/** Decodes all stored chunks. Gzip, zlib, LZ4, and uncompressed payloads are supported. */
|
|
29123
29241
|
static async parse(data) {
|
|
29124
29242
|
const bytes = this.bytes(data);
|
|
29125
29243
|
const chunks = [];
|
|
@@ -29167,11 +29285,13 @@ var AnvilParser = class {
|
|
|
29167
29285
|
static async readChunk(data, location) {
|
|
29168
29286
|
const compression = data[location.offset + 4];
|
|
29169
29287
|
if (compression & 128) throw new MineRenderError("External Anvil .mcc chunks are not supported");
|
|
29170
|
-
if (compression !== 1 && compression !== 2 && compression !== 3) {
|
|
29171
|
-
throw new MineRenderError(`Unsupported Anvil compression ${compression}
|
|
29288
|
+
if (compression !== 1 && compression !== 2 && compression !== 3 && compression !== 4) {
|
|
29289
|
+
throw new MineRenderError(`Unsupported Anvil compression ${compression}`);
|
|
29172
29290
|
}
|
|
29173
29291
|
let payload = data.subarray(location.offset + 5, location.offset + 4 + location.length);
|
|
29174
|
-
if (compression
|
|
29292
|
+
if (compression === 4) {
|
|
29293
|
+
payload = decodeAnvilLz4(payload);
|
|
29294
|
+
} else if (compression !== 3) {
|
|
29175
29295
|
const stream = new Blob([payload]).stream().pipeThrough(new DecompressionStream(compression === 1 ? "gzip" : "deflate"));
|
|
29176
29296
|
payload = new Uint8Array(await new Response(stream).arrayBuffer());
|
|
29177
29297
|
}
|