From: Daniel Karbach Date: Mon, 10 Aug 2015 15:35:46 +0000 (+0200) Subject: try to get every chunk change saved to disk X-Git-Url: https://git.localhorst.tv/?a=commitdiff_plain;h=29ee0558fdd951b25f41005ed721241b1f28aefa;p=blank.git try to get every chunk change saved to disk --- diff --git a/TODO b/TODO index 4377b24..33a5c8d 100644 --- a/TODO +++ b/TODO @@ -27,7 +27,8 @@ command line persistence - add world shutdown state to save dirty chunks when exiting + merge IO counters, so number of operations per frame is kept + low, no matter what exactly is done store some kind of byte order mark? diff --git a/src/app/PreloadState.cpp b/src/app/PreloadState.cpp index 32d0b3a..389d331 100644 --- a/src/app/PreloadState.cpp +++ b/src/app/PreloadState.cpp @@ -3,8 +3,6 @@ #include "Environment.hpp" #include "../world/ChunkLoader.hpp" -#include - namespace blank { @@ -20,7 +18,10 @@ PreloadState::PreloadState(Environment &env, ChunkLoader &loader) } -void PreloadState::Handle(const SDL_Event &) { +void PreloadState::Handle(const SDL_Event &e) { + if (e.type == SDL_QUIT) { + env.state.PopAll(); + } } void PreloadState::Update(int dt) { diff --git a/src/app/UnloadState.cpp b/src/app/UnloadState.cpp new file mode 100644 index 0000000..49801bf --- /dev/null +++ b/src/app/UnloadState.cpp @@ -0,0 +1,46 @@ +#include "UnloadState.hpp" + +#include "Environment.hpp" +#include "../world/ChunkLoader.hpp" +#include "../world/WorldSave.hpp" + + +namespace blank { + +UnloadState::UnloadState(Environment &env, ChunkLoader &loader) +: env(env) +, loader(loader) +, font(env.assets.LoadFont("DejaVuSans", 24)) +, progress(font) +, cur(loader.Loaded().begin()) +, end(loader.Loaded().end()) +, done(0) +, total(loader.Loaded().size()) +, per_update(64) { + progress.Position(glm::vec3(0.0f), Gravity::CENTER); + progress.Template("Unloading chunks: %d/%d (%d%%)"); +} + + +void UnloadState::Handle(const SDL_Event &) { + // ignore everything +} + +void UnloadState::Update(int dt) { + for (std::size_t i = 0; i < per_update && cur != end; ++i, ++cur, ++done) { + if (cur->ShouldUpdateSave()) { + loader.SaveFile().Write(*cur); + } + } + if (cur == end) { + env.state.PopAll(); + } else { + progress.Update(done, total); + } +} + +void UnloadState::Render(Viewport &viewport) { + progress.Render(viewport); +} + +} diff --git a/src/app/UnloadState.hpp b/src/app/UnloadState.hpp new file mode 100644 index 0000000..56394bb --- /dev/null +++ b/src/app/UnloadState.hpp @@ -0,0 +1,44 @@ +#ifndef BLANK_APP_PRELOADSTATE_HPP_ +#define BLANK_APP_PRELOADSTATE_HPP_ + +#include "State.hpp" + +#include "../ui/Progress.hpp" +#include "../graphics/Font.hpp" + +#include +#include + + +namespace blank { + +class Chunk; +class ChunkLoader; +class Environment; + +class UnloadState +: public State { + +public: + UnloadState(Environment &, ChunkLoader &); + + void Handle(const SDL_Event &) override; + void Update(int dt) override; + void Render(Viewport &) override; + +private: + Environment &env; + ChunkLoader &loader; + Font font; + Progress progress; + std::list::iterator cur; + std::list::iterator end; + std::size_t done; + std::size_t total; + std::size_t per_update; + +}; + +} + +#endif diff --git a/src/app/WorldState.cpp b/src/app/WorldState.cpp index 12e142a..86e3eac 100644 --- a/src/app/WorldState.cpp +++ b/src/app/WorldState.cpp @@ -1,6 +1,7 @@ #include "WorldState.hpp" #include "Environment.hpp" +#include "UnloadState.hpp" #include @@ -41,6 +42,10 @@ void WorldState::Handle(const SDL_Event &event) { case SDL_MOUSEWHEEL: interface.Handle(event.wheel); break; + case SDL_QUIT: + // don't care about this leak just now + env.state.Switch(new UnloadState(env, world.Loader())); + break; default: break; } diff --git a/src/app/app.cpp b/src/app/app.cpp index f3c9115..4a4769b 100644 --- a/src/app/app.cpp +++ b/src/app/app.cpp @@ -96,9 +96,6 @@ void Application::HandleEvents() { void Application::Handle(const SDL_Event &event) { switch (event.type) { - case SDL_QUIT: - env.state.PopAll(); - break; case SDL_WINDOWEVENT: Handle(event.window); break; diff --git a/src/world/ChunkLoader.hpp b/src/world/ChunkLoader.hpp index 81e7178..7cc8dfc 100644 --- a/src/world/ChunkLoader.hpp +++ b/src/world/ChunkLoader.hpp @@ -33,6 +33,7 @@ public: void QueueSurrounding(const Chunk::Pos &); std::list &Loaded() noexcept { return loaded; } + const WorldSave &SaveFile() const noexcept { return save; } Chunk *Loaded(const Chunk::Pos &) noexcept; bool Queued(const Chunk::Pos &) noexcept; diff --git a/src/world/chunk.cpp b/src/world/chunk.cpp index 2d5b7ce..31dfe80 100644 --- a/src/world/chunk.cpp +++ b/src/world/chunk.cpp @@ -772,6 +772,10 @@ std::list::iterator ChunkLoader::Remove(std::list::iterator chunk) ++next; // unlink neighbors so they won't reference a dead chunk chunk->ClearNeighbors(); + // if it should be saved, do it now + if (chunk->ShouldUpdateSave()) { + save.Write(*chunk); + } // and move it from loaded to free list to_free.splice(to_free.end(), loaded, chunk); return next;