lib/region: Start working on region file parser
Something is fishy with dumpnbt or lib/nbt. Attempting to dump the extracted chunk fails, but external tools do manage to parse it.master
parent
6112da2e6f
commit
01e5f5eaac
Binary file not shown.
|
@ -0,0 +1,74 @@
|
||||||
|
if [ "$1" = "-v" ]; then
|
||||||
|
VERBOSE=true
|
||||||
|
shift
|
||||||
|
else
|
||||||
|
VERBOSE=false
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -f "$1" ]; then
|
||||||
|
echo "Usage: $0 [-v] FILE"
|
||||||
|
echo " -v display raw content and NBT dump"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# pointer data
|
||||||
|
OFFSET_HEX="0x$(dd bs=1 if="$1" count=3 2>/dev/null | hexdump -e '3/1 "%02x" "\n"')"
|
||||||
|
OFFSET="$(baseconvert -d $OFFSET_HEX)"
|
||||||
|
echo " offset: $OFFSET ($OFFSET_HEX)"
|
||||||
|
LENGTH_HEX="0x$(dd bs=1 if="$1" count=1 skip=3 2>/dev/null | hexdump -e '1/1 "%02x" "\n"')"
|
||||||
|
LENGTH="$(baseconvert -d $LENGTH_HEX)"
|
||||||
|
echo " length: $LENGTH ($LENGTH_HEX)"
|
||||||
|
|
||||||
|
#TODO: last modified
|
||||||
|
|
||||||
|
# chunk
|
||||||
|
DATA="$(dd if="$1" bs=4096 count=$LENGTH skip=$OFFSET 2>/dev/null | hexdump -v -e '16/1 "%02x" "\n"' | tr -d '
|
||||||
|
')"
|
||||||
|
|
||||||
|
# blob header
|
||||||
|
# bs=2 because each byte is two digits hex
|
||||||
|
COMPRESSED_LENGTH_HEX="0x$(dd bs=2 count=4 2> /dev/null <<< $DATA)"
|
||||||
|
COMPRESSED_LENGTH="$(baseconvert -d $COMPRESSED_LENGTH_HEX)"
|
||||||
|
echo " compressed length in bytes: $COMPRESSED_LENGTH ($COMPRESSED_LENGTH_HEX)"
|
||||||
|
FORMAT_HEX="0x$(dd bs=2 skip=4 count=1 2> /dev/null <<< $DATA)"
|
||||||
|
case $FORMAT_HEX in
|
||||||
|
"0x01")
|
||||||
|
FORMAT="gzip"
|
||||||
|
function UNCOMPRESS {
|
||||||
|
gzip -dc
|
||||||
|
}
|
||||||
|
;;
|
||||||
|
"0x02")
|
||||||
|
FORMAT="zlib"
|
||||||
|
function UNCOMPRESS {
|
||||||
|
cat > /tmp/chunk_zlib_decompress
|
||||||
|
python3 <<< "
|
||||||
|
import zlib,sys
|
||||||
|
a = open('/tmp/chunk_zlib_decompress', 'rb')
|
||||||
|
data = a.read()
|
||||||
|
a.close()
|
||||||
|
sys.stdout.buffer.write(zlib.decompress(data))
|
||||||
|
sys.stdout.buffer.flush()
|
||||||
|
"
|
||||||
|
rm /tmp/chunk_zlib_decompress
|
||||||
|
}
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
FORMAT="unknown"
|
||||||
|
function UNCOMPRESS {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
echo " format: $FORMAT ($FORMAT_HEX)"
|
||||||
|
|
||||||
|
if $VERBOSE; then
|
||||||
|
echo "Raw chunk data:"
|
||||||
|
echo "$DATA"
|
||||||
|
echo "NBT dump:"
|
||||||
|
|
||||||
|
#TODO: use pipes instead of a file
|
||||||
|
dd if="$1" bs=4096 count=$LENGTH skip=$OFFSET 2>/dev/null | dd bs=1 skip=5 count=$(($COMPRESSED_LENGTH-1)) 2>/dev/null | UNCOMPRESS > /tmp/chunk_uncompressed_nbt
|
||||||
|
dumpnbt /tmp/chunk_uncompressed_nbt
|
||||||
|
rm /tmp/chunk_uncompressed_nbt
|
||||||
|
fi
|
Binary file not shown.
|
@ -0,0 +1,17 @@
|
||||||
|
// Copyright 2023, FOSS-VG Developers and Contributers
|
||||||
|
//
|
||||||
|
// Author(s):
|
||||||
|
// BodgeMaster
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify it
|
||||||
|
// under the terms of the GNU Affero General Public License as published
|
||||||
|
// by the Free Software Foundation, version 3.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied
|
||||||
|
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
// See the GNU Affero General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Affero General Public License
|
||||||
|
// version 3 along with this program.
|
||||||
|
// If not, see https://www.gnu.org/licenses/agpl-3.0.en.html
|
|
@ -0,0 +1,57 @@
|
||||||
|
// Copyright 2023, FOSS-VG Developers and Contributers
|
||||||
|
//
|
||||||
|
// Author(s):
|
||||||
|
// BodgeMaster
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify it
|
||||||
|
// under the terms of the GNU Affero General Public License as published
|
||||||
|
// by the Free Software Foundation, version 3.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied
|
||||||
|
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
// See the GNU Affero General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Affero General Public License
|
||||||
|
// version 3 along with this program.
|
||||||
|
// If not, see https://www.gnu.org/licenses/agpl-3.0.en.html
|
||||||
|
|
||||||
|
|
||||||
|
// File structure:
|
||||||
|
// 4K table of uint32_t: pointing to chunks
|
||||||
|
// -> 24bit offset, 8 bit length
|
||||||
|
// -> both offset and length are multiplied by 4096 to get the real value
|
||||||
|
// -> lowest valid offset = 2
|
||||||
|
// -> chunk is not present if pointer=0
|
||||||
|
// -> chunk calculation: ((x % 32) + (z % 32) * 32) * 4
|
||||||
|
// -> what about negative chunks?
|
||||||
|
// 4k table of uint32_t: last modified timestamps
|
||||||
|
// individual chunks
|
||||||
|
// -> 5 byte header
|
||||||
|
// -> 4 byte length
|
||||||
|
// -> 1 byte compression type: 0?? 1->gzip 2->zlib
|
||||||
|
// -> extension idea: support for other compression algorithms
|
||||||
|
// - lzma
|
||||||
|
// - xz
|
||||||
|
// - lz4
|
||||||
|
// - zstd
|
||||||
|
// -> compressed NBT data
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
class Region {
|
||||||
|
uint32_t storagePointers[1024];
|
||||||
|
uint32_t lastModifiedTimestamps[1024];
|
||||||
|
|
||||||
|
// Chunk coordinates are uint8_t here bc they are 0<=x<32.
|
||||||
|
uint32_t* coordsToStoragePointer(uint8_t x, uint8_t z) {
|
||||||
|
return &storagePointers[z*32 + x];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Chunk coordinates are uint8_t here bc they are 0<=x<32.
|
||||||
|
uint32_t* coordsToLastModified(uint8_t x, uint8_t z) {
|
||||||
|
return &lastModifiedTimestamps[z*32 + x];
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue