diff --git a/server/src/world/worldloader.cpp b/server/src/world/worldloader.cpp index 7f7b94ba..173a57ac 100644 --- a/server/src/world/worldloader.cpp +++ b/server/src/world/worldloader.cpp @@ -43,6 +43,7 @@ using nlohmann::json; WorldLoader::WorldLoader(const std::filesystem::path& path) : + m_path{path}, m_world{World::create()} { m_states = json::object(); @@ -186,3 +187,14 @@ void WorldLoader::loadObject(ObjectData& objectData) objectData.loaded = true; } +bool WorldLoader::readFile(const std::filesystem::path& filename, std::string& data) +{ + std::ifstream file(m_path / filename, std::ios::in | std::ios::binary | std::ios::ate); + if(!file.is_open()) + return false; + const size_t size = file.tellg(); + data.resize(size); + file.seekg(std::ios::beg); + file.read(data.data(), size); + return true; +} diff --git a/server/src/world/worldloader.hpp b/server/src/world/worldloader.hpp index 73989da7..e3086871 100644 --- a/server/src/world/worldloader.hpp +++ b/server/src/world/worldloader.hpp @@ -43,6 +43,7 @@ class WorldLoader bool loaded; }; + const std::filesystem::path& m_path; std::shared_ptr m_world; std::unordered_map m_objects; nlohmann::json m_states; @@ -57,6 +58,8 @@ class WorldLoader ObjectPtr getObject(std::string_view id); nlohmann::json getState(const std::string& id) const; + + bool readFile(const std::filesystem::path& filename, std::string& data); }; #endif diff --git a/server/src/world/worldsaver.cpp b/server/src/world/worldsaver.cpp index d6d88540..297aad37 100644 --- a/server/src/world/worldsaver.cpp +++ b/server/src/world/worldsaver.cpp @@ -24,10 +24,12 @@ #include #include #include "world.hpp" +#include "../utils/sha1.hpp" using nlohmann::json; -WorldSaver::WorldSaver(const World& world) +WorldSaver::WorldSaver(const World& world) : + m_path{std::filesystem::path(world.m_filename).remove_filename()} { m_states = json::object(); json data = json::object(); @@ -62,6 +64,8 @@ WorldSaver::WorldSaver(const World& world) saveToDisk(data, world.m_filename); saveToDisk(state, world.m_filenameState); + deleteFiles(); + writeFiles(); } json WorldSaver::saveObject(const ObjectPtr& object) @@ -77,6 +81,32 @@ json WorldSaver::saveObject(const ObjectPtr& object) return objectData; } +void WorldSaver::deleteFile(std::filesystem::path filename) +{ + m_deleteFiles.emplace_back(std::move(filename)); +} + +void WorldSaver::writeFile(std::filesystem::path filename, std::string data) +{ + m_writeFiles.push_back({std::move(filename), std::move(data)}); +} + +void WorldSaver::deleteFiles() +{ + for(const auto& filename : m_deleteFiles) + { + std::error_code ec; + std::filesystem::remove(m_path / filename, ec); + //! \todo report error if removal fails of existing file + } +} + +void WorldSaver::writeFiles() +{ + for(const auto& file : m_writeFiles) + saveToDisk(file.second, m_path / file.first); +} + void WorldSaver::saveToDisk(const json& data, const std::filesystem::path& filename) { std::filesystem::path dir = std::filesystem::path(filename).remove_filename(); @@ -94,3 +124,26 @@ void WorldSaver::saveToDisk(const json& data, const std::filesystem::path& filen throw std::runtime_error("file not open"); //Traintastic::instance->console->critical(classId, "Can't write to world file"); } + +void WorldSaver::saveToDisk(const std::string& data, const std::filesystem::path& filename) +{ + if(std::filesystem::exists(filename) && + std::filesystem::file_size(filename) == data.size() && + Sha1::of(filename) == Sha1::of(data)) + return; + + std::filesystem::path dir = std::filesystem::path(filename).remove_filename(); + std::string s = dir.string(); + if(!std::filesystem::is_directory(dir)) + std::filesystem::create_directories(dir); + + std::ofstream file(filename); + if(file.is_open()) + { + file << data; + //Traintastic::instance->console->notice(classId, "Saved world " + name.value()); + } + else + throw std::runtime_error("file not open"); + //Traintastic::instance->console->critical(classId, "Can't write to world file"); +} diff --git a/server/src/world/worldsaver.hpp b/server/src/world/worldsaver.hpp index d393e25c..67afe765 100644 --- a/server/src/world/worldsaver.hpp +++ b/server/src/world/worldsaver.hpp @@ -23,6 +23,7 @@ #ifndef TRAINTASTIC_SERVER_WORLD_WORLDSAVER_HPP #define TRAINTASTIC_SERVER_WORLD_WORLDSAVER_HPP +#include #include "../core/objectptr.hpp" #include "../core/stdfilesystem.hpp" #include "../utils/json.hpp" @@ -33,13 +34,22 @@ class WorldSaver { private: nlohmann::json m_states; + const std::filesystem::path m_path; + std::list m_deleteFiles; + std::list> m_writeFiles; + void deleteFiles(); + void writeFiles(); void saveToDisk(const nlohmann::json& data, const std::filesystem::path& filename); + void saveToDisk(const std::string& data, const std::filesystem::path& filename); public: WorldSaver(const World& world); nlohmann::json saveObject(const ObjectPtr& object); + + void deleteFile(std::filesystem::path filename); + void writeFile(std::filesystem::path filename, std::string data); }; #endif