WorldFiles region format and magic check

This commit is contained in:
MihailRis
2024-01-03 23:25:58 +03:00
parent e7e2c16ee6
commit 460b08a006
3 changed files with 47 additions and 19 deletions
+2 -2
View File
@@ -5,14 +5,14 @@
#include "typedefs.h" #include "typedefs.h"
const int ENGINE_VERSION_MAJOR = 0; const int ENGINE_VERSION_MAJOR = 0;
const int ENGINE_VERSION_MINOR = 16; const int ENGINE_VERSION_MINOR = 17;
const int CHUNK_W = 16; const int CHUNK_W = 16;
const int CHUNK_H = 256; const int CHUNK_H = 256;
const int CHUNK_D = 16; const int CHUNK_D = 16;
/* Chunk volume (count of voxels per Chunk) */ /* Chunk volume (count of voxels per Chunk) */
const int CHUNK_VOL = (CHUNK_W * CHUNK_H * CHUNK_D); constexpr int CHUNK_VOL = (CHUNK_W * CHUNK_H * CHUNK_D);
/* BLOCK_VOID is block id used to mark non-existing voxel (voxel of missing chunk) */ /* BLOCK_VOID is block id used to mark non-existing voxel (voxel of missing chunk) */
const blockid_t BLOCK_VOID = std::numeric_limits<blockid_t>::max(); const blockid_t BLOCK_VOID = std::numeric_limits<blockid_t>::max();
+33 -13
View File
@@ -23,9 +23,27 @@
#include <cstdint> #include <cstdint>
#include <fstream> #include <fstream>
#include <sstream> #include <sstream>
#include <cstring>
namespace fs = std::filesystem; namespace fs = std::filesystem;
regfile::regfile(fs::path filename) : file(filename) {
if (file.length() < REGION_HEADER_SIZE)
throw std::runtime_error("incomplete region file header");
char header[REGION_HEADER_SIZE];
file.read(header, REGION_HEADER_SIZE);
// avoid of use strcmp_s
if (std::string(header, strlen(REGION_FORMAT_MAGIC)) != REGION_FORMAT_MAGIC) {
throw std::runtime_error("invalid region file magic number");
}
version = header[8];
if (version > 2) {
throw std::runtime_error(
"region format "+std::to_string(version)+" is not supported");
}
}
WorldRegion::WorldRegion() { WorldRegion::WorldRegion() {
chunksData = new ubyte*[REGION_CHUNKS_COUNT]{}; chunksData = new ubyte*[REGION_CHUNKS_COUNT]{};
sizes = new uint32_t[REGION_CHUNKS_COUNT]{}; sizes = new uint32_t[REGION_CHUNKS_COUNT]{};
@@ -252,7 +270,8 @@ ubyte* WorldFiles::getData(regionsmap& regions, const fs::path& folder,
return nullptr; return nullptr;
} }
files::rafile* WorldFiles::getRegFile(glm::ivec3 coord, const fs::path& folder) {
regfile* WorldFiles::getRegFile(glm::ivec3 coord, const fs::path& folder) {
const auto found = openRegFiles.find(coord); const auto found = openRegFiles.find(coord);
if (found != openRegFiles.end()) { if (found != openRegFiles.end()) {
return found->second.get(); return found->second.get();
@@ -266,7 +285,7 @@ files::rafile* WorldFiles::getRegFile(glm::ivec3 coord, const fs::path& folder)
if (!fs::is_regular_file(filename)) { if (!fs::is_regular_file(filename)) {
return nullptr; return nullptr;
} }
openRegFiles[coord] = std::make_unique<files::rafile>(filename); openRegFiles[coord] = std::make_unique<regfile>(filename);
return openRegFiles[coord].get(); return openRegFiles[coord].get();
} }
@@ -285,26 +304,27 @@ ubyte* WorldFiles::readChunkData(int x,
int chunkIndex = localZ * REGION_SIZE + localX; int chunkIndex = localZ * REGION_SIZE + localX;
glm::ivec3 coord(regionX, regionZ, layer); glm::ivec3 coord(regionX, regionZ, layer);
files::rafile* file = WorldFiles::getRegFile(coord, folder); regfile* rfile = WorldFiles::getRegFile(coord, folder);
if (file == nullptr) { if (rfile == nullptr) {
return nullptr; return nullptr;
} }
files::rafile& file = rfile->file;
size_t file_size = file->length(); size_t file_size = file.length();
size_t table_offset = file_size - REGION_CHUNKS_COUNT * 4; size_t table_offset = file_size - REGION_CHUNKS_COUNT * 4;
uint32_t offset; uint32_t offset;
file->seekg(table_offset + chunkIndex * 4); file.seekg(table_offset + chunkIndex * 4);
file->read((char*)(&offset), 4); file.read((char*)(&offset), 4);
offset = dataio::read_int32_big((const ubyte*)(&offset), 0); offset = dataio::read_int32_big((const ubyte*)(&offset), 0);
if (offset == 0){ if (offset == 0){
return nullptr; return nullptr;
} }
file->seekg(offset); file.seekg(offset);
file->read((char*)(&offset), 4); file.read((char*)(&offset), 4);
length = dataio::read_int32_big((const ubyte*)(&offset), 0); length = dataio::read_int32_big((const ubyte*)(&offset), 0);
ubyte* data = new ubyte[length]; ubyte* data = new ubyte[length];
file->read((char*)data, length); file.read((char*)data, length);
if (data == nullptr) { if (data == nullptr) {
std::cerr << "ERROR: failed to read data of chunk x("<< x <<"), z("<< z <<")" << std::endl; std::cerr << "ERROR: failed to read data of chunk x("<< x <<"), z("<< z <<")" << std::endl;
} }
@@ -343,13 +363,13 @@ void WorldFiles::writeRegion(int x, int z, WorldRegion* entry, fs::path folder,
openRegFiles.erase(regcoord); openRegFiles.erase(regcoord);
} }
char header[10] = REGION_FORMAT_MAGIC; char header[REGION_HEADER_SIZE] = REGION_FORMAT_MAGIC;
header[8] = REGION_FORMAT_VERSION; header[8] = REGION_FORMAT_VERSION;
header[9] = 0; // flags header[9] = 0; // flags
std::ofstream file(filename, std::ios::out | std::ios::binary); std::ofstream file(filename, std::ios::out | std::ios::binary);
file.write(header, 10); file.write(header, REGION_HEADER_SIZE);
size_t offset = 10; size_t offset = REGION_HEADER_SIZE;
char intbuf[4]{}; char intbuf[4]{};
uint offsets[REGION_CHUNKS_COUNT]{}; uint offsets[REGION_CHUNKS_COUNT]{};
+12 -4
View File
@@ -15,12 +15,13 @@
#include "../typedefs.h" #include "../typedefs.h"
#include "../settings.h" #include "../settings.h"
const uint REGION_HEADER_SIZE = 10;
const uint REGION_LAYER_VOXELS = 0; const uint REGION_LAYER_VOXELS = 0;
const uint REGION_LAYER_LIGHTS = 1; const uint REGION_LAYER_LIGHTS = 1;
const uint REGION_SIZE_BIT = 5; const uint REGION_SIZE_BIT = 5;
const uint REGION_SIZE = (1 << (REGION_SIZE_BIT)); const uint REGION_SIZE = (1 << (REGION_SIZE_BIT));
const uint REGION_CHUNKS_COUNT = ((REGION_SIZE) * (REGION_SIZE)); const uint REGION_CHUNKS_COUNT = ((REGION_SIZE) * (REGION_SIZE));
const uint REGION_FORMAT_VERSION = 1; const uint REGION_FORMAT_VERSION = 2;
const uint WORLD_FORMAT_VERSION = 1; const uint WORLD_FORMAT_VERSION = 1;
const uint MAX_OPEN_REGION_FILES = 16; const uint MAX_OPEN_REGION_FILES = 16;
@@ -52,9 +53,16 @@ public:
uint32_t* getSizes() const; uint32_t* getSizes() const;
}; };
struct regfile {
files::rafile file;
int version;
regfile(std::filesystem::path filename);
};
typedef std::unordered_map<glm::ivec2, std::unique_ptr<WorldRegion>> regionsmap; typedef std::unordered_map<glm::ivec2, std::unique_ptr<WorldRegion>> regionsmap;
class WorldFiles { class WorldFiles {
std::unordered_map<glm::ivec3, std::unique_ptr<files::rafile>> openRegFiles; std::unordered_map<glm::ivec3, std::unique_ptr<regfile>> openRegFiles;
void writeWorldInfo(const World* world); void writeWorldInfo(const World* world);
std::filesystem::path getLightsFolder() const; std::filesystem::path getLightsFolder() const;
@@ -98,8 +106,8 @@ class WorldFiles {
const std::filesystem::path& folder, const std::filesystem::path& folder,
int x, int z, int layer); int x, int z, int layer);
files::rafile* getRegFile(glm::ivec3 coord, regfile* getRegFile(glm::ivec3 coord,
const std::filesystem::path& folder); const std::filesystem::path& folder);
public: public:
static bool parseRegionFilename(const std::string& name, int& x, int& y); static bool parseRegionFilename(const std::string& name, int& x, int& y);
std::filesystem::path getRegionsFolder() const; std::filesystem::path getRegionsFolder() const;