fix: decoding varint for .schem files

This commit is contained in:
trafficlunar 2025-01-23 19:29:46 +00:00
parent 6ab167e7db
commit 6779713897
2 changed files with 37 additions and 8 deletions

View file

@ -37,7 +37,7 @@ interface LitematicNBT extends nbt.ListTagLike {
interface SpongeNBT extends nbt.ListTagLike {
Schematic: {
Blocks: {
Data: Int8Array;
Data: Uint8Array;
Palette: Record<string, number>;
};
DataVersion: number;
@ -153,14 +153,15 @@ function OpenSchematic({ close }: DialogProps) {
// Add every block to the canvas
const blocks: Block[] = [];
let index = 0;
let offset = 0;
for (let y = spongeData.Height; y > 0; y--) {
for (let x = 0; x < spongeData.Width; x++) {
const paletteValue = spongeData.Blocks.Data[index];
// Decode varint to get the pallete value
const { value: paletteValue, bytesRead } = decodeVarint(spongeData.Blocks.Data, offset);
const paletteBlock = Object.keys(spongeData.Blocks.Palette).find((key) => spongeData.Blocks.Palette[key] == paletteValue);
index++;
offset += bytesRead;
if (!paletteBlock) continue;
const blockIdWithProperties = paletteBlock.replace("minecraft:", "");

View file

@ -1,9 +1,37 @@
export function encodeVarint(number: number) {
export function encodeVarint(number: number): Uint8Array {
const result = [];
while (number >= 0x80) {
result.push((number & 0x7f) | 0x80); // Take 7 bits and set the MSB
number >>>= 7; // Right shift by 7 bits (logical shift)
// Take 7 bits and set the MSB
result.push((number & 0x7f) | 0x80);
// Right shift by 7 bits (logical shift)
number >>>= 7;
}
result.push(number); // Last byte without MSB set
// Last byte without MSB set
result.push(number);
return new Uint8Array(result);
}
export function decodeVarint(buffer: Uint8Array, offset: number): { value: number; bytesRead: number } {
let value = 0;
let position = 0;
let byte: number;
do {
if (position > 35) {
throw new Error("VarInt is too big");
}
// Read the current byte
byte = buffer[offset++];
// Extract the lower 7 bits of the byte and shift them to the correct position
value |= (byte & 0x7f) << (position * 7);
// Increment the position for the next byte
position++;
} while ((byte & 0x80) !== 0); // Continue if the most significant bit (MSB) is set
return { value, bytesRead: position };
}