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

View file

@ -1,9 +1,37 @@
export function encodeVarint(number: number) { export function encodeVarint(number: number): Uint8Array {
const result = []; const result = [];
while (number >= 0x80) { while (number >= 0x80) {
result.push((number & 0x7f) | 0x80); // Take 7 bits and set the MSB // Take 7 bits and set the MSB
number >>>= 7; // Right shift by 7 bits (logical shift) 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); 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 };
}