From a1fdbb967f60f37c81628a70fb88433916d61209 Mon Sep 17 00:00:00 2001 From: Ingo Ruhnke Date: Mon, 11 Aug 2014 05:10:07 +0200 Subject: [PATCH] Moved some state handling code into WorldState, sort of, most of it still just goes into the global Squirrel VM --- src/supertux/world.cpp | 111 ++--------------------- src/supertux/world.hpp | 9 +- src/supertux/world_state.cpp | 165 +++++++++++++++++++++++++++++++++++ src/supertux/world_state.hpp | 46 ++++++++++ 4 files changed, 221 insertions(+), 110 deletions(-) create mode 100644 src/supertux/world_state.cpp create mode 100644 src/supertux/world_state.hpp diff --git a/src/supertux/world.cpp b/src/supertux/world.cpp index f9bc52acb31..c2063a7362e 100644 --- a/src/supertux/world.cpp +++ b/src/supertux/world.cpp @@ -27,6 +27,7 @@ #include "supertux/screen_fade.hpp" #include "supertux/screen_manager.hpp" #include "supertux/world.hpp" +#include "supertux/world_state.hpp" #include "util/file_system.hpp" #include "util/reader.hpp" #include "util/string_util.hpp" @@ -58,7 +59,7 @@ World::World() : m_world_thread(), m_title(), m_description(), - m_player_status(new PlayerStatus), + m_world_state(new WorldState), m_hide_from_contribs(false), m_is_levelset(true) { @@ -157,113 +158,13 @@ World::run() void World::save_state() { - { // make sure the savegame directory exists - std::string dirname = FileSystem::dirname(m_savegame_filename); - if(!PHYSFS_exists(dirname.c_str())) - { - if(!PHYSFS_mkdir(dirname.c_str())) - { - std::ostringstream msg; - msg << "Couldn't create directory for savegames '" - << dirname << "': " <get_title(); - title << " (" << WorldMap::current()->solved_level_count() - << "/" << WorldMap::current()->level_count() << ")"; - writer.write("title", title.str()); - } - - writer.start_list("tux"); - m_player_status->write(writer); - writer.end_list("tux"); - - writer.start_list("state"); - - sq_pushroottable(vm); - sq_pushstring(vm, "state", -1); - if(SQ_SUCCEEDED(sq_get(vm, -2))) { - scripting::save_squirrel_table(vm, -1, writer); - sq_pop(vm, 1); - } - sq_pop(vm, 1); - writer.end_list("state"); - - writer.end_list("supertux-savegame"); + m_world_state->save(m_savegame_filename); } void World::load_state() { - if(!PHYSFS_exists(m_savegame_filename.c_str())) - { - log_info << m_savegame_filename << ": doesn't exist, not loading state" << std::endl; - } - else - { - try - { - HSQUIRRELVM vm = scripting::global_vm; - - lisp::Parser parser; - const lisp::Lisp* root = parser.parse(m_savegame_filename); - - const lisp::Lisp* lisp = root->get_lisp("supertux-savegame"); - if(lisp == NULL) - throw std::runtime_error("file is not a supertux-savegame file"); - - int version = 1; - lisp->get("version", version); - if(version != 1) - throw std::runtime_error("incompatible savegame version"); - - const lisp::Lisp* tux = lisp->get_lisp("tux"); - if(tux == NULL) - throw std::runtime_error("No tux section in savegame"); - m_player_status->read(*tux); - - const lisp::Lisp* state = lisp->get_lisp("state"); - if(state == NULL) - throw std::runtime_error("No state section in savegame"); - - sq_pushroottable(vm); - sq_pushstring(vm, "state", -1); - if(SQ_FAILED(sq_deleteslot(vm, -2, SQFalse))) - sq_pop(vm, 1); - - sq_pushstring(vm, "state", -1); - sq_newtable(vm); - scripting::load_squirrel_table(vm, -1, *state); - if(SQ_FAILED(sq_createslot(vm, -3))) - throw std::runtime_error("Couldn't create state table"); - sq_pop(vm, 1); - } - catch(const std::exception& e) - { - log_fatal << "Couldn't load savegame: " << e.what() << std::endl; - } - } + m_world_state->load(m_savegame_filename); } std::string @@ -272,10 +173,10 @@ World::get_level_filename(unsigned int i) const return FileSystem::join(m_basedir, m_levels[i]); } -unsigned int +int World::get_num_levels() const { - return m_levels.size(); + return static_cast(m_levels.size()); } int diff --git a/src/supertux/world.hpp b/src/supertux/world.hpp index 04fad22018b..a95264037d4 100644 --- a/src/supertux/world.hpp +++ b/src/supertux/world.hpp @@ -23,8 +23,7 @@ #include #include "util/currenton.hpp" - -class PlayerStatus; +#include "supertux/world_state.hpp" class World : public Currenton { @@ -47,14 +46,14 @@ class World : public Currenton void save_state(); void load_state(); - unsigned int get_num_levels() const; + int get_num_levels() const; int get_num_solved_levels() const; std::string get_level_filename(unsigned int i) const; std::string get_basedir() const; std::string get_title() const; - PlayerStatus* get_player_status() const { return m_player_status.get(); } + PlayerStatus* get_player_status() const { return m_world_state->get_player_status(); } void run(); @@ -69,7 +68,7 @@ class World : public Currenton HSQOBJECT m_world_thread; std::string m_title; std::string m_description; - std::unique_ptr m_player_status; + std::unique_ptr m_world_state; bool m_hide_from_contribs; bool m_is_levelset; diff --git a/src/supertux/world_state.cpp b/src/supertux/world_state.cpp new file mode 100644 index 00000000000..d0dbd8bc891 --- /dev/null +++ b/src/supertux/world_state.cpp @@ -0,0 +1,165 @@ +// SuperTux +// Copyright (C) 2006 Matthias Braun +// 2014 Ingo Ruhnke +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#include "supertux/world_state.hpp" + +#include "lisp/lisp.hpp" +#include "lisp/parser.hpp" +#include "lisp/writer.hpp" +#include "physfs/ifile_streambuf.hpp" +#include "scripting/serialize.hpp" +#include "scripting/squirrel_util.hpp" +#include "supertux/player_status.hpp" +#include "util/file_system.hpp" +#include "util/log.hpp" +#include "worldmap/worldmap.hpp" + +WorldState::WorldState() : + m_player_status(new PlayerStatus) +{ +} + +void +WorldState::load(const std::string& filename) +{ + if(!PHYSFS_exists(filename.c_str())) + { + log_info << filename << ": doesn't exist, not loading state" << std::endl; + } + else + { + try + { + HSQUIRRELVM vm = scripting::global_vm; + + lisp::Parser parser; + const lisp::Lisp* root = parser.parse(filename); + + const lisp::Lisp* lisp = root->get_lisp("supertux-savegame"); + if(lisp == NULL) + { + throw std::runtime_error("file is not a supertux-savegame file"); + } + else + { + int version = 1; + lisp->get("version", version); + if(version != 1) + { + throw std::runtime_error("incompatible savegame version"); + } + else + { + const lisp::Lisp* tux = lisp->get_lisp("tux"); + if(tux == NULL) + { + throw std::runtime_error("No tux section in savegame"); + } + { + m_player_status->read(*tux); + } + + const lisp::Lisp* state = lisp->get_lisp("state"); + if(state == NULL) + { + throw std::runtime_error("No state section in savegame"); + } + else + { + sq_pushroottable(vm); + sq_pushstring(vm, "state", -1); + if(SQ_FAILED(sq_deleteslot(vm, -2, SQFalse))) + sq_pop(vm, 1); + + sq_pushstring(vm, "state", -1); + sq_newtable(vm); + scripting::load_squirrel_table(vm, -1, *state); + if(SQ_FAILED(sq_createslot(vm, -3))) + throw std::runtime_error("Couldn't create state table"); + sq_pop(vm, 1); + } + } + } + } + catch(const std::exception& e) + { + log_fatal << "Couldn't load savegame: " << e.what() << std::endl; + } + } +} + +void +WorldState::save(const std::string& filename) +{ + { // make sure the savegame directory exists + std::string dirname = FileSystem::dirname(filename); + if(!PHYSFS_exists(dirname.c_str())) + { + if(!PHYSFS_mkdir(dirname.c_str())) + { + std::ostringstream msg; + msg << "Couldn't create directory for savegames '" + << dirname << "': " <get_title(); + title << " (" << WorldMap::current()->solved_level_count() + << "/" << WorldMap::current()->level_count() << ")"; + writer.write("title", title.str()); + } + + writer.start_list("tux"); + m_player_status->write(writer); + writer.end_list("tux"); + + writer.start_list("state"); + + sq_pushroottable(vm); + sq_pushstring(vm, "state", -1); + if(SQ_SUCCEEDED(sq_get(vm, -2))) + { + scripting::save_squirrel_table(vm, -1, writer); + sq_pop(vm, 1); + } + sq_pop(vm, 1); + writer.end_list("state"); + + writer.end_list("supertux-savegame"); +} + +/* EOF */ diff --git a/src/supertux/world_state.hpp b/src/supertux/world_state.hpp new file mode 100644 index 00000000000..a3d2c3eb881 --- /dev/null +++ b/src/supertux/world_state.hpp @@ -0,0 +1,46 @@ +// SuperTux +// Copyright (C) 2006 Matthias Braun +// 2014 Ingo Ruhnke +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#ifndef HEADER_SUPERTUX_SUPERTUX_WORLD_STATE_HPP +#define HEADER_SUPERTUX_SUPERTUX_WORLD_STATE_HPP + +#include +#include + +class PlayerStatus; + +class WorldState +{ +private: + std::unique_ptr m_player_status; + +public: + WorldState(); + + PlayerStatus* get_player_status() const { return m_player_status.get(); } + + void save(const std::string& filename); + void load(const std::string& filename); + +private: + WorldState(const WorldState&) = delete; + WorldState& operator=(const WorldState&) = delete; +}; + +#endif + +/* EOF */