Worlds indexing
This commit is contained in:
@@ -0,0 +1,71 @@
|
||||
#include "WorldConverter.h"
|
||||
|
||||
#include <memory>
|
||||
#include <iostream>
|
||||
#include <stdexcept>
|
||||
#include "WorldFiles.h"
|
||||
#include "../voxels/Chunk.h"
|
||||
#include "../content/ContentLUT.h"
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
using std::string;
|
||||
using std::unique_ptr;
|
||||
using fs::path;
|
||||
|
||||
WorldConverter::WorldConverter(path folder,
|
||||
const Content* content,
|
||||
const ContentLUT* lut)
|
||||
: lut(lut), content(content) {
|
||||
DebugSettings settings;
|
||||
wfile = new WorldFiles(folder, settings);
|
||||
|
||||
path regionsFolder = wfile->getRegionsFolder();
|
||||
if (!fs::is_directory(regionsFolder)) {
|
||||
std::cerr << "nothing to convert" << std::endl;
|
||||
return;
|
||||
}
|
||||
for (auto file : fs::directory_iterator(regionsFolder)) {
|
||||
regions.push(file.path());
|
||||
}
|
||||
}
|
||||
|
||||
WorldConverter::~WorldConverter() {
|
||||
delete wfile;
|
||||
}
|
||||
|
||||
bool WorldConverter::hasNext() const {
|
||||
return !regions.empty();
|
||||
}
|
||||
|
||||
void WorldConverter::convertNext() {
|
||||
if (!hasNext()) {
|
||||
throw std::runtime_error("no more regions to convert");
|
||||
}
|
||||
path regfile = regions.front();
|
||||
regions.pop();
|
||||
if (!fs::is_regular_file(regfile))
|
||||
return;
|
||||
int x, y;
|
||||
string name = regfile.stem().string();
|
||||
if (!WorldFiles::parseRegionFilename(name, x, y)) {
|
||||
std::cerr << "could not parse name " << name << std::endl;
|
||||
return;
|
||||
}
|
||||
std::cout << "converting region " << name << std::endl;
|
||||
for (uint cz = 0; cz < REGION_SIZE; cz++) {
|
||||
for (uint cx = 0; cx < REGION_SIZE; cx++) {
|
||||
int gx = cx + x * REGION_SIZE;
|
||||
int gz = cz + y * REGION_SIZE;
|
||||
unique_ptr<ubyte[]> data (wfile->getChunk(gx, gz));
|
||||
if (data == nullptr)
|
||||
continue;
|
||||
Chunk::convert(data.get(), lut);
|
||||
wfile->put(gx, gz, data.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WorldConverter::write() {
|
||||
std::cout << "writing world" << std::endl;
|
||||
wfile->write(nullptr, content);
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
#ifndef FILES_WORLD_CONVERTER_H_
|
||||
#define FILES_WORLD_CONVERTER_H_
|
||||
|
||||
#include <queue>
|
||||
#include <filesystem>
|
||||
|
||||
class Content;
|
||||
class ContentLUT;
|
||||
class WorldFiles;
|
||||
|
||||
class WorldConverter {
|
||||
WorldFiles* wfile;
|
||||
const ContentLUT* const lut;
|
||||
const Content* const content;
|
||||
std::queue<std::filesystem::path> regions;
|
||||
public:
|
||||
WorldConverter(std::filesystem::path folder, const Content* content, const ContentLUT* lut);
|
||||
~WorldConverter();
|
||||
|
||||
bool hasNext() const;
|
||||
void convertNext();
|
||||
|
||||
void write();
|
||||
};
|
||||
|
||||
#endif // FILES_WORLD_CONVERTER_H_
|
||||
@@ -122,7 +122,7 @@ WorldRegion* WorldFiles::getOrCreateRegion(
|
||||
return region;
|
||||
}
|
||||
|
||||
ubyte* WorldFiles::compress(ubyte* src, size_t srclen, size_t& len) {
|
||||
ubyte* WorldFiles::compress(const ubyte* src, size_t srclen, size_t& len) {
|
||||
len = extrle::encode(src, srclen, compressionBuffer);
|
||||
ubyte* data = new ubyte[len];
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
@@ -131,12 +131,27 @@ ubyte* WorldFiles::compress(ubyte* src, size_t srclen, size_t& len) {
|
||||
return data;
|
||||
}
|
||||
|
||||
ubyte* WorldFiles::decompress(ubyte* src, size_t srclen, size_t dstlen) {
|
||||
ubyte* WorldFiles::decompress(const ubyte* src, size_t srclen, size_t dstlen) {
|
||||
ubyte* decompressed = new ubyte[dstlen];
|
||||
extrle::decode(src, srclen, decompressed);
|
||||
return decompressed;
|
||||
}
|
||||
|
||||
void WorldFiles::put(int x, int z, const ubyte* voxelData) {
|
||||
int regionX = floordiv(x, REGION_SIZE);
|
||||
int regionZ = floordiv(z, REGION_SIZE);
|
||||
int localX = x - (regionX * REGION_SIZE);
|
||||
int localZ = z - (regionZ * REGION_SIZE);
|
||||
|
||||
/* Writing Voxels */ {
|
||||
WorldRegion* region = getOrCreateRegion(regions, regionX, regionZ);
|
||||
region->setUnsaved(true);
|
||||
size_t compressedSize;
|
||||
ubyte* data = compress(voxelData, CHUNK_DATA_LEN, compressedSize);
|
||||
region->put(localX, localZ, data, compressedSize);
|
||||
}
|
||||
}
|
||||
|
||||
void WorldFiles::put(Chunk* chunk){
|
||||
assert(chunk != nullptr);
|
||||
|
||||
@@ -176,6 +191,21 @@ path WorldFiles::getRegionFilename(int x, int y) const {
|
||||
return path(filename);
|
||||
}
|
||||
|
||||
bool WorldFiles::parseRegionFilename(const string& name, int& x, int& y) {
|
||||
size_t sep = name.find('_');
|
||||
if (sep == string::npos || sep == 0 || sep == name.length()-1)
|
||||
return false;
|
||||
try {
|
||||
x = std::stoi(name.substr(0, sep));
|
||||
y = std::stoi(name.substr(sep+1));
|
||||
} catch (std::invalid_argument& err) {
|
||||
return false;
|
||||
} catch (std::out_of_range& err) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
path WorldFiles::getPlayerFile() const {
|
||||
return directory/path("player.json");
|
||||
}
|
||||
@@ -338,7 +368,8 @@ void WorldFiles::write(const World* world, const Content* content) {
|
||||
fs::create_directories(directory);
|
||||
}
|
||||
}
|
||||
writeWorldInfo(world);
|
||||
if (world)
|
||||
writeWorldInfo(world);
|
||||
if (generatorTestMode)
|
||||
return;
|
||||
writeIndices(content->indices);
|
||||
|
||||
+10
-5
@@ -49,7 +49,6 @@ public:
|
||||
|
||||
class WorldFiles {
|
||||
void writeWorldInfo(const World* world);
|
||||
std::filesystem::path getRegionsFolder() const;
|
||||
std::filesystem::path getLightsFolder() const;
|
||||
std::filesystem::path getRegionFilename(int x, int y) const;
|
||||
std::filesystem::path getPlayerFile() const;
|
||||
@@ -74,14 +73,14 @@ class WorldFiles {
|
||||
@param src source buffer
|
||||
@param srclen length of source buffer
|
||||
@param len (out argument) length of result buffer */
|
||||
ubyte* compress(ubyte* src, size_t srclen, size_t& len);
|
||||
ubyte* compress(const ubyte* src, size_t srclen, size_t& len);
|
||||
|
||||
/* Decompress buffer with extrle
|
||||
@param src compressed buffer
|
||||
@param srclen length of compressed buffer
|
||||
@param dstlen max expected length of source buffer
|
||||
*/
|
||||
ubyte* decompress(ubyte* src, size_t srclen, size_t dstlen);
|
||||
ubyte* decompress(const ubyte* src, size_t srclen, size_t dstlen);
|
||||
|
||||
ubyte* readChunkData(int x, int y,
|
||||
uint32_t& length,
|
||||
@@ -94,6 +93,9 @@ class WorldFiles {
|
||||
const std::filesystem::path& folder,
|
||||
int x, int z);
|
||||
public:
|
||||
static bool parseRegionFilename(const std::string& name, int& x, int& y);
|
||||
std::filesystem::path getRegionsFolder() const;
|
||||
|
||||
std::unordered_map<glm::ivec2, WorldRegion*> regions;
|
||||
std::unordered_map<glm::ivec2, WorldRegion*> lights;
|
||||
std::filesystem::path directory;
|
||||
@@ -105,8 +107,10 @@ public:
|
||||
~WorldFiles();
|
||||
|
||||
void put(Chunk* chunk);
|
||||
ubyte* getChunk(int x, int y);
|
||||
light_t* getLights(int x, int y);
|
||||
void put(int x, int z, const ubyte* voxelData);
|
||||
|
||||
ubyte* getChunk(int x, int z);
|
||||
light_t* getLights(int x, int z);
|
||||
|
||||
bool readWorldInfo(World* world);
|
||||
bool readPlayer(Player* player);
|
||||
@@ -115,6 +119,7 @@ public:
|
||||
WorldRegion* entry,
|
||||
std::filesystem::path file);
|
||||
void writePlayer(Player* player);
|
||||
/* @param world world info to save (nullable) */
|
||||
void write(const World* world, const Content* content);
|
||||
void writeIndices(const ContentIndices* indices);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user