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