X-Git-Url: http://git.localhorst.tv/?a=blobdiff_plain;f=src%2Fworld%2FWorldSave.cpp;h=d0e8112e1d3b2e7cb48d865f688ff28f64938294;hb=d02daa5a4805dc3184884f3a7cd7620e5787adcb;hp=2bfa818017e675e5b26cdfcade708e3af1da426f;hpb=39df551265bff648c1ac166043bb4b046122cc8d;p=blank.git diff --git a/src/world/WorldSave.cpp b/src/world/WorldSave.cpp index 2bfa818..d0e8112 100644 --- a/src/world/WorldSave.cpp +++ b/src/world/WorldSave.cpp @@ -5,7 +5,9 @@ #include #include #include +#include #include +#include using namespace std; @@ -14,7 +16,10 @@ namespace blank { WorldSave::WorldSave(const string &path) : root_path(path) -, conf_path(path + "world.conf") { +, conf_path(path + "world.conf") +, chunk_path(path + "chunks/%d/%d/%d.gz") +, chunk_bufsiz(chunk_path.length() + 3 * std::numeric_limits::digits10) +, chunk_buf(new char[chunk_bufsiz]) { } @@ -24,22 +29,6 @@ bool WorldSave::Exists() const noexcept { } -void WorldSave::Create(const World::Config &conf) const { - cout << "creating world save" << endl; - - if (!make_dirs(root_path)) { - throw runtime_error("failed to create world save directory"); - } - - ofstream out(conf_path); - out << "seed = " << conf.gen.seed << endl; - out.close(); - - if (!out) { - throw runtime_error("failed to write world config"); - } -} - void WorldSave::Read(World::Config &conf) const { cout << "reading world save" << endl; @@ -81,4 +70,76 @@ void WorldSave::Read(World::Config &conf) const { } } +void WorldSave::Write(const World::Config &conf) const { + cout << "writing world save" << endl; + + if (!make_dirs(root_path)) { + throw runtime_error("failed to create world save directory"); + } + + ofstream out(conf_path); + out << "seed = " << conf.gen.seed << endl; + out.close(); + + if (!out) { + throw runtime_error("failed to write world config"); + } +} + + +bool WorldSave::Exists(const Chunk::Pos &pos) const noexcept { + return is_file(ChunkPath(pos)); +} + +void WorldSave::Read(Chunk &chunk) const { + const char *path = ChunkPath(chunk.Position()); + gzFile file = gzopen(path, "r"); + if (!file) { + throw runtime_error("failed to open chunk file"); + } + if (gzread(file, chunk.BlockData(), Chunk::BlockSize()) != Chunk::BlockSize()) { + throw runtime_error("failed to read chunk from file"); + } + if (gzclose(file) != Z_OK) { + throw runtime_error("failed to read chunk file"); + } + chunk.InvalidateModel(); + chunk.ClearSave(); +} + +void WorldSave::Write(Chunk &chunk) const { + const char *path = ChunkPath(chunk.Position()); + gzFile file = gzopen(path, "w"); + if (!file) { + // check if it's because of a missing path component + if (errno != ENOENT) { + // nope, fatal + throw runtime_error(strerror(errno)); + } + string dir_path(path); + dir_path.erase(dir_path.find_last_of("\\/")); + if (!make_dirs(dir_path)) { + throw runtime_error("failed to create dir for chunk file"); + } + file = gzopen(path, "w"); + if (!file) { + throw runtime_error("failed to open chunk file"); + } + } + if (gzwrite(file, chunk.BlockData(), Chunk::BlockSize()) == 0) { + gzclose(file); // if this fails, it can't be helped + throw runtime_error("failed to write chunk to file"); + } + if (gzclose(file) != Z_OK) { + throw runtime_error("failed to write chunk file"); + } + chunk.ClearSave(); +} + + +const char *WorldSave::ChunkPath(const Chunk::Pos &pos) const { + snprintf(chunk_buf.get(), chunk_bufsiz, chunk_path.c_str(), pos.x, pos.y, pos.z); + return chunk_buf.get(); +} + }