WorldFiles region format and magic check
This commit is contained in:
parent
e7e2c16ee6
commit
460b08a006
@ -5,14 +5,14 @@
|
||||
#include "typedefs.h"
|
||||
|
||||
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_H = 256;
|
||||
const int CHUNK_D = 16;
|
||||
|
||||
/* 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) */
|
||||
const blockid_t BLOCK_VOID = std::numeric_limits<blockid_t>::max();
|
||||
|
||||
@ -23,9 +23,27 @@
|
||||
#include <cstdint>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <cstring>
|
||||
|
||||
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() {
|
||||
chunksData = new ubyte*[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;
|
||||
}
|
||||
|
||||
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);
|
||||
if (found != openRegFiles.end()) {
|
||||
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)) {
|
||||
return nullptr;
|
||||
}
|
||||
openRegFiles[coord] = std::make_unique<files::rafile>(filename);
|
||||
openRegFiles[coord] = std::make_unique<regfile>(filename);
|
||||
return openRegFiles[coord].get();
|
||||
}
|
||||
|
||||
@ -285,26 +304,27 @@ ubyte* WorldFiles::readChunkData(int x,
|
||||
int chunkIndex = localZ * REGION_SIZE + localX;
|
||||
|
||||
glm::ivec3 coord(regionX, regionZ, layer);
|
||||
files::rafile* file = WorldFiles::getRegFile(coord, folder);
|
||||
if (file == nullptr) {
|
||||
regfile* rfile = WorldFiles::getRegFile(coord, folder);
|
||||
if (rfile == 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;
|
||||
|
||||
uint32_t offset;
|
||||
file->seekg(table_offset + chunkIndex * 4);
|
||||
file->read((char*)(&offset), 4);
|
||||
file.seekg(table_offset + chunkIndex * 4);
|
||||
file.read((char*)(&offset), 4);
|
||||
offset = dataio::read_int32_big((const ubyte*)(&offset), 0);
|
||||
if (offset == 0){
|
||||
return nullptr;
|
||||
}
|
||||
file->seekg(offset);
|
||||
file->read((char*)(&offset), 4);
|
||||
file.seekg(offset);
|
||||
file.read((char*)(&offset), 4);
|
||||
length = dataio::read_int32_big((const ubyte*)(&offset), 0);
|
||||
ubyte* data = new ubyte[length];
|
||||
file->read((char*)data, length);
|
||||
file.read((char*)data, length);
|
||||
if (data == nullptr) {
|
||||
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);
|
||||
}
|
||||
|
||||
char header[10] = REGION_FORMAT_MAGIC;
|
||||
char header[REGION_HEADER_SIZE] = REGION_FORMAT_MAGIC;
|
||||
header[8] = REGION_FORMAT_VERSION;
|
||||
header[9] = 0; // flags
|
||||
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]{};
|
||||
uint offsets[REGION_CHUNKS_COUNT]{};
|
||||
|
||||
|
||||
@ -15,12 +15,13 @@
|
||||
#include "../typedefs.h"
|
||||
#include "../settings.h"
|
||||
|
||||
const uint REGION_HEADER_SIZE = 10;
|
||||
const uint REGION_LAYER_VOXELS = 0;
|
||||
const uint REGION_LAYER_LIGHTS = 1;
|
||||
const uint REGION_SIZE_BIT = 5;
|
||||
const uint REGION_SIZE = (1 << (REGION_SIZE_BIT));
|
||||
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 MAX_OPEN_REGION_FILES = 16;
|
||||
|
||||
@ -52,9 +53,16 @@ public:
|
||||
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;
|
||||
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);
|
||||
std::filesystem::path getLightsFolder() const;
|
||||
@ -98,8 +106,8 @@ class WorldFiles {
|
||||
const std::filesystem::path& folder,
|
||||
int x, int z, int layer);
|
||||
|
||||
files::rafile* getRegFile(glm::ivec3 coord,
|
||||
const std::filesystem::path& folder);
|
||||
regfile* getRegFile(glm::ivec3 coord,
|
||||
const std::filesystem::path& folder);
|
||||
public:
|
||||
static bool parseRegionFilename(const std::string& name, int& x, int& y);
|
||||
std::filesystem::path getRegionsFolder() const;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user