mirror of
https://github.com/minetest/minetestmapper.git
synced 2024-12-04 13:23:47 +01:00
Add support for map block version 29
This commit is contained in:
parent
5c435f6459
commit
b0ca3d7066
@ -1,4 +1,3 @@
|
|||||||
#include <stdint.h>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
@ -39,7 +38,7 @@ void BlockDecoder::reset()
|
|||||||
|
|
||||||
m_version = 0;
|
m_version = 0;
|
||||||
m_contentWidth = 0;
|
m_contentWidth = 0;
|
||||||
m_mapData = ustring();
|
m_mapData.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void BlockDecoder::decode(const ustring &datastr)
|
void BlockDecoder::decode(const ustring &datastr)
|
||||||
@ -49,7 +48,6 @@ void BlockDecoder::decode(const ustring &datastr)
|
|||||||
// TODO: bounds checks
|
// TODO: bounds checks
|
||||||
|
|
||||||
uint8_t version = data[0];
|
uint8_t version = data[0];
|
||||||
//uint8_t flags = data[1];
|
|
||||||
if (version < 22) {
|
if (version < 22) {
|
||||||
std::ostringstream oss;
|
std::ostringstream oss;
|
||||||
oss << "Unsupported map version " << (int)version;
|
oss << "Unsupported map version " << (int)version;
|
||||||
@ -57,12 +55,46 @@ void BlockDecoder::decode(const ustring &datastr)
|
|||||||
}
|
}
|
||||||
m_version = version;
|
m_version = version;
|
||||||
|
|
||||||
|
ustring datastr2;
|
||||||
|
if (version >= 29) {
|
||||||
|
// decompress whole block at once
|
||||||
|
m_zstd_decompressor.setData(data, length, 1);
|
||||||
|
datastr2 = m_zstd_decompressor.decompress();
|
||||||
|
data = datastr2.c_str();
|
||||||
|
length = datastr2.size();
|
||||||
|
}
|
||||||
|
|
||||||
size_t dataOffset = 0;
|
size_t dataOffset = 0;
|
||||||
if (version >= 27)
|
if (version >= 29)
|
||||||
|
dataOffset = 7;
|
||||||
|
else if (version >= 27)
|
||||||
dataOffset = 4;
|
dataOffset = 4;
|
||||||
else
|
else
|
||||||
dataOffset = 2;
|
dataOffset = 2;
|
||||||
|
|
||||||
|
auto decode_mapping = [&] () {
|
||||||
|
dataOffset++; // mapping version
|
||||||
|
uint16_t numMappings = readU16(data + dataOffset);
|
||||||
|
dataOffset += 2;
|
||||||
|
for (int i = 0; i < numMappings; ++i) {
|
||||||
|
uint16_t nodeId = readU16(data + dataOffset);
|
||||||
|
dataOffset += 2;
|
||||||
|
uint16_t nameLen = readU16(data + dataOffset);
|
||||||
|
dataOffset += 2;
|
||||||
|
std::string name(reinterpret_cast<const char *>(data) + dataOffset, nameLen);
|
||||||
|
if (name == "air")
|
||||||
|
m_blockAirId = nodeId;
|
||||||
|
else if (name == "ignore")
|
||||||
|
m_blockIgnoreId = nodeId;
|
||||||
|
else
|
||||||
|
m_nameMap[nodeId] = name;
|
||||||
|
dataOffset += nameLen;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (version >= 29)
|
||||||
|
decode_mapping();
|
||||||
|
|
||||||
uint8_t contentWidth = data[dataOffset];
|
uint8_t contentWidth = data[dataOffset];
|
||||||
dataOffset++;
|
dataOffset++;
|
||||||
uint8_t paramsWidth = data[dataOffset];
|
uint8_t paramsWidth = data[dataOffset];
|
||||||
@ -73,14 +105,20 @@ void BlockDecoder::decode(const ustring &datastr)
|
|||||||
throw std::runtime_error("unsupported map version (paramsWidth)");
|
throw std::runtime_error("unsupported map version (paramsWidth)");
|
||||||
m_contentWidth = contentWidth;
|
m_contentWidth = contentWidth;
|
||||||
|
|
||||||
|
if (version >= 29) {
|
||||||
|
m_mapData.resize((contentWidth + paramsWidth) * 4096);
|
||||||
|
m_mapData.assign(data + dataOffset, m_mapData.size());
|
||||||
|
return; // we have read everything we need and can return early
|
||||||
|
}
|
||||||
|
|
||||||
|
// version < 29
|
||||||
ZlibDecompressor decompressor(data, length);
|
ZlibDecompressor decompressor(data, length);
|
||||||
decompressor.setSeekPos(dataOffset);
|
decompressor.setSeekPos(dataOffset);
|
||||||
m_mapData = decompressor.decompress();
|
m_mapData = decompressor.decompress();
|
||||||
decompressor.decompress(); // unused metadata
|
decompressor.decompress(); // unused metadata
|
||||||
dataOffset = decompressor.seekPos();
|
dataOffset = decompressor.seekPos();
|
||||||
|
|
||||||
// Skip unused data
|
// Skip unused node timers
|
||||||
if (version == 23)
|
if (version == 23)
|
||||||
dataOffset += 1;
|
dataOffset += 1;
|
||||||
if (version == 24) {
|
if (version == 24) {
|
||||||
@ -104,33 +142,7 @@ void BlockDecoder::decode(const ustring &datastr)
|
|||||||
dataOffset += 4; // Skip timestamp
|
dataOffset += 4; // Skip timestamp
|
||||||
|
|
||||||
// Read mapping
|
// Read mapping
|
||||||
{
|
decode_mapping();
|
||||||
dataOffset++; // mapping version
|
|
||||||
uint16_t numMappings = readU16(data + dataOffset);
|
|
||||||
dataOffset += 2;
|
|
||||||
for (int i = 0; i < numMappings; ++i) {
|
|
||||||
uint16_t nodeId = readU16(data + dataOffset);
|
|
||||||
dataOffset += 2;
|
|
||||||
uint16_t nameLen = readU16(data + dataOffset);
|
|
||||||
dataOffset += 2;
|
|
||||||
std::string name(reinterpret_cast<const char *>(data) + dataOffset, nameLen);
|
|
||||||
if (name == "air")
|
|
||||||
m_blockAirId = nodeId;
|
|
||||||
else if (name == "ignore")
|
|
||||||
m_blockIgnoreId = nodeId;
|
|
||||||
else
|
|
||||||
m_nameMap[nodeId] = name;
|
|
||||||
dataOffset += nameLen;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Node timers
|
|
||||||
if (version >= 25) {
|
|
||||||
uint8_t timerLength = data[dataOffset++];
|
|
||||||
uint16_t numTimers = readU16(data + dataOffset);
|
|
||||||
dataOffset += 2;
|
|
||||||
dataOffset += numTimers * timerLength;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BlockDecoder::isEmpty() const
|
bool BlockDecoder::isEmpty() const
|
||||||
|
@ -43,7 +43,7 @@ if(NOT CUSTOM_DOCDIR STREQUAL "")
|
|||||||
message(STATUS "Using DOCDIR=${DOCDIR}")
|
message(STATUS "Using DOCDIR=${DOCDIR}")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
#set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
|
set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
|
||||||
|
|
||||||
# Libraries: gd
|
# Libraries: gd
|
||||||
|
|
||||||
@ -59,6 +59,10 @@ endif(NOT LIBGD_LIBRARY OR NOT LIBGD_INCLUDE_DIR)
|
|||||||
|
|
||||||
find_package(ZLIB REQUIRED)
|
find_package(ZLIB REQUIRED)
|
||||||
|
|
||||||
|
# Libraries: zstd
|
||||||
|
|
||||||
|
find_package(Zstd REQUIRED)
|
||||||
|
|
||||||
# Libraries: sqlite3
|
# Libraries: sqlite3
|
||||||
|
|
||||||
find_library(SQLITE3_LIBRARY sqlite3)
|
find_library(SQLITE3_LIBRARY sqlite3)
|
||||||
@ -148,6 +152,7 @@ include_directories(
|
|||||||
${SQLITE3_INCLUDE_DIR}
|
${SQLITE3_INCLUDE_DIR}
|
||||||
${LIBGD_INCLUDE_DIR}
|
${LIBGD_INCLUDE_DIR}
|
||||||
${ZLIB_INCLUDE_DIR}
|
${ZLIB_INCLUDE_DIR}
|
||||||
|
${ZSTD_INCLUDE_DIR}
|
||||||
)
|
)
|
||||||
|
|
||||||
configure_file(
|
configure_file(
|
||||||
@ -171,6 +176,7 @@ add_executable(minetestmapper
|
|||||||
PlayerAttributes.cpp
|
PlayerAttributes.cpp
|
||||||
TileGenerator.cpp
|
TileGenerator.cpp
|
||||||
ZlibDecompressor.cpp
|
ZlibDecompressor.cpp
|
||||||
|
ZstdDecompressor.cpp
|
||||||
Image.cpp
|
Image.cpp
|
||||||
mapper.cpp
|
mapper.cpp
|
||||||
util.cpp
|
util.cpp
|
||||||
@ -188,6 +194,7 @@ target_link_libraries(
|
|||||||
${REDIS_LIBRARY}
|
${REDIS_LIBRARY}
|
||||||
${LIBGD_LIBRARY}
|
${LIBGD_LIBRARY}
|
||||||
${ZLIB_LIBRARY}
|
${ZLIB_LIBRARY}
|
||||||
|
${ZSTD_LIBRARY}
|
||||||
)
|
)
|
||||||
|
|
||||||
# Installing & Packaging
|
# Installing & Packaging
|
||||||
|
58
ZstdDecompressor.cpp
Normal file
58
ZstdDecompressor.cpp
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
#include <zstd.h>
|
||||||
|
#include "ZstdDecompressor.h"
|
||||||
|
|
||||||
|
ZstdDecompressor::ZstdDecompressor():
|
||||||
|
m_data(nullptr),
|
||||||
|
m_seekPos(0),
|
||||||
|
m_size(0)
|
||||||
|
{
|
||||||
|
m_stream = ZSTD_createDStream();
|
||||||
|
}
|
||||||
|
|
||||||
|
ZstdDecompressor::~ZstdDecompressor()
|
||||||
|
{
|
||||||
|
ZSTD_freeDStream(reinterpret_cast<ZSTD_DStream*>(m_stream));
|
||||||
|
}
|
||||||
|
|
||||||
|
void ZstdDecompressor::setData(const u8 *data, size_t size, size_t seekPos)
|
||||||
|
{
|
||||||
|
m_data = data;
|
||||||
|
m_seekPos = seekPos;
|
||||||
|
m_size = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t ZstdDecompressor::seekPos() const
|
||||||
|
{
|
||||||
|
return m_seekPos;
|
||||||
|
}
|
||||||
|
|
||||||
|
ustring ZstdDecompressor::decompress()
|
||||||
|
{
|
||||||
|
ZSTD_DStream *stream = reinterpret_cast<ZSTD_DStream*>(m_stream);
|
||||||
|
ZSTD_inBuffer inbuf = { m_data, m_size, m_seekPos };
|
||||||
|
|
||||||
|
ustring buffer;
|
||||||
|
constexpr size_t BUFSIZE = 32 * 1024;
|
||||||
|
|
||||||
|
buffer.resize(BUFSIZE);
|
||||||
|
ZSTD_outBuffer outbuf = { &buffer[0], buffer.size(), 0 };
|
||||||
|
|
||||||
|
ZSTD_initDStream(stream);
|
||||||
|
|
||||||
|
size_t ret;
|
||||||
|
do {
|
||||||
|
ret = ZSTD_decompressStream(stream, &outbuf, &inbuf);
|
||||||
|
if (outbuf.size == outbuf.pos) {
|
||||||
|
outbuf.size += BUFSIZE;
|
||||||
|
buffer.resize(outbuf.size);
|
||||||
|
outbuf.dst = &buffer[0];
|
||||||
|
}
|
||||||
|
} while (ret != 0);
|
||||||
|
if (ZSTD_isError(ret))
|
||||||
|
throw DecompressError();
|
||||||
|
|
||||||
|
m_seekPos = inbuf.pos;
|
||||||
|
buffer.resize(outbuf.pos);
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
24
cmake/FindZstd.cmake
Normal file
24
cmake/FindZstd.cmake
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
mark_as_advanced(ZSTD_LIBRARY ZSTD_INCLUDE_DIR)
|
||||||
|
|
||||||
|
find_path(ZSTD_INCLUDE_DIR NAMES zstd.h)
|
||||||
|
|
||||||
|
find_library(ZSTD_LIBRARY NAMES zstd)
|
||||||
|
|
||||||
|
if(ZSTD_INCLUDE_DIR AND ZSTD_LIBRARY)
|
||||||
|
# Check that the API we use exists
|
||||||
|
include(CheckSymbolExists)
|
||||||
|
unset(HAVE_ZSTD_INITDSTREAM CACHE)
|
||||||
|
set(CMAKE_REQUIRED_INCLUDES ${ZSTD_INCLUDE_DIR})
|
||||||
|
set(CMAKE_REQUIRED_LIBRARIES ${ZSTD_LIBRARY})
|
||||||
|
check_symbol_exists(ZSTD_initDStream zstd.h HAVE_ZSTD_INITDSTREAM)
|
||||||
|
unset(CMAKE_REQUIRED_INCLUDES)
|
||||||
|
unset(CMAKE_REQUIRED_LIBRARIES)
|
||||||
|
|
||||||
|
if(NOT HAVE_ZSTD_INITDSTREAM)
|
||||||
|
unset(ZSTD_INCLUDE_DIR CACHE)
|
||||||
|
unset(ZSTD_LIBRARY CACHE)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
include(FindPackageHandleStandardArgs)
|
||||||
|
find_package_handle_standard_args(Zstd DEFAULT_MSG ZSTD_LIBRARY ZSTD_INCLUDE_DIR)
|
@ -1,8 +1,9 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
#include <ZstdDecompressor.h>
|
||||||
|
|
||||||
class BlockDecoder {
|
class BlockDecoder {
|
||||||
public:
|
public:
|
||||||
@ -17,9 +18,11 @@ public:
|
|||||||
private:
|
private:
|
||||||
typedef std::unordered_map<uint16_t, std::string> NameMap;
|
typedef std::unordered_map<uint16_t, std::string> NameMap;
|
||||||
NameMap m_nameMap;
|
NameMap m_nameMap;
|
||||||
int m_blockAirId;
|
uint16_t m_blockAirId, m_blockIgnoreId;
|
||||||
int m_blockIgnoreId;
|
|
||||||
|
|
||||||
u8 m_version, m_contentWidth;
|
u8 m_version, m_contentWidth;
|
||||||
ustring m_mapData;
|
ustring m_mapData;
|
||||||
|
|
||||||
|
// one instance for performance
|
||||||
|
ZstdDecompressor m_zstd_decompressor;
|
||||||
};
|
};
|
||||||
|
22
include/ZstdDecompressor.h
Normal file
22
include/ZstdDecompressor.h
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <string>
|
||||||
|
#include "types.h"
|
||||||
|
|
||||||
|
class ZstdDecompressor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
class DecompressError {};
|
||||||
|
|
||||||
|
ZstdDecompressor();
|
||||||
|
~ZstdDecompressor();
|
||||||
|
void setData(const u8 *data, size_t size, size_t seekPos);
|
||||||
|
size_t seekPos() const;
|
||||||
|
ustring decompress();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void *m_stream; // ZSTD_DStream
|
||||||
|
const u8 *m_data;
|
||||||
|
size_t m_seekPos, m_size;
|
||||||
|
};
|
@ -1,7 +1,7 @@
|
|||||||
#!/bin/bash -e
|
#!/bin/bash -e
|
||||||
|
|
||||||
install_linux_deps() {
|
install_linux_deps() {
|
||||||
local pkgs=(cmake libgd-dev libsqlite3-dev libleveldb-dev libpq-dev libhiredis-dev)
|
local pkgs=(cmake libgd-dev libsqlite3-dev libleveldb-dev libpq-dev libhiredis-dev libzstd-dev)
|
||||||
|
|
||||||
sudo apt-get update
|
sudo apt-get update
|
||||||
sudo apt-get install -y --no-install-recommends ${pkgs[@]} "$@"
|
sudo apt-get install -y --no-install-recommends ${pkgs[@]} "$@"
|
||||||
|
Loading…
Reference in New Issue
Block a user