From 67797138974aff5d01be137985191efc0d84f6bd Mon Sep 17 00:00:00 2001 From: trafficlunar Date: Thu, 23 Jan 2025 19:29:46 +0000 Subject: [PATCH] fix: decoding varint for .schem files --- src/components/dialogs/OpenSchematic.tsx | 9 +++--- src/utils/varint.ts | 36 +++++++++++++++++++++--- 2 files changed, 37 insertions(+), 8 deletions(-) diff --git a/src/components/dialogs/OpenSchematic.tsx b/src/components/dialogs/OpenSchematic.tsx index 30ad75d..b4cc9ff 100644 --- a/src/components/dialogs/OpenSchematic.tsx +++ b/src/components/dialogs/OpenSchematic.tsx @@ -37,7 +37,7 @@ interface LitematicNBT extends nbt.ListTagLike { interface SpongeNBT extends nbt.ListTagLike { Schematic: { Blocks: { - Data: Int8Array; + Data: Uint8Array; Palette: Record; }; 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:", ""); diff --git a/src/utils/varint.ts b/src/utils/varint.ts index 27d5888..1491572 100644 --- a/src/utils/varint.ts +++ b/src/utils/varint.ts @@ -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 }; +}