Skip to content

Commit

Permalink
Moved some state handling code into WorldState, sort of, most of it s…
Browse files Browse the repository at this point in the history
…till just goes into the global Squirrel VM
  • Loading branch information
Grumbel committed Aug 11, 2014
1 parent 7824178 commit a1fdbb9
Show file tree
Hide file tree
Showing 4 changed files with 221 additions and 110 deletions.
111 changes: 6 additions & 105 deletions src/supertux/world.cpp
Expand Up @@ -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"
Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -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 << "': " <<PHYSFS_getLastError();
throw std::runtime_error(msg.str());
}
}

if(!PHYSFS_isDirectory(dirname.c_str()))
{
std::ostringstream msg;
msg << "Savegame path '" << dirname << "' is not a directory";
throw std::runtime_error(msg.str());
}
}

HSQUIRRELVM vm = scripting::global_vm;

lisp::Writer writer(m_savegame_filename);

writer.start_list("supertux-savegame");
writer.write("version", 1);

using namespace worldmap;
if(WorldMap::current() != NULL)
{
std::ostringstream title;
title << WorldMap::current()->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
Expand All @@ -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<int>(m_levels.size());
}

int
Expand Down
9 changes: 4 additions & 5 deletions src/supertux/world.hpp
Expand Up @@ -23,8 +23,7 @@
#include <vector>

#include "util/currenton.hpp"

class PlayerStatus;
#include "supertux/world_state.hpp"

class World : public Currenton<World>
{
Expand All @@ -47,14 +46,14 @@ class World : public Currenton<World>
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();

Expand All @@ -69,7 +68,7 @@ class World : public Currenton<World>
HSQOBJECT m_world_thread;
std::string m_title;
std::string m_description;
std::unique_ptr<PlayerStatus> m_player_status;
std::unique_ptr<WorldState> m_world_state;

bool m_hide_from_contribs;
bool m_is_levelset;
Expand Down
165 changes: 165 additions & 0 deletions src/supertux/world_state.cpp
@@ -0,0 +1,165 @@
// SuperTux
// Copyright (C) 2006 Matthias Braun <matze@braunis.de>
// 2014 Ingo Ruhnke <grumbel@gmx.de>
//
// 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 <http://www.gnu.org/licenses/>.

#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 << "': " <<PHYSFS_getLastError();
throw std::runtime_error(msg.str());
}
}

if(!PHYSFS_isDirectory(dirname.c_str()))
{
std::ostringstream msg;
msg << "Savegame path '" << dirname << "' is not a directory";
throw std::runtime_error(msg.str());
}
}

HSQUIRRELVM vm = scripting::global_vm;

lisp::Writer writer(filename);

writer.start_list("supertux-savegame");
writer.write("version", 1);

using namespace worldmap;
if(WorldMap::current() != NULL)
{
std::ostringstream title;
title << WorldMap::current()->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 */
46 changes: 46 additions & 0 deletions src/supertux/world_state.hpp
@@ -0,0 +1,46 @@
// SuperTux
// Copyright (C) 2006 Matthias Braun <matze@braunis.de>
// 2014 Ingo Ruhnke <grumbel@gmx.de>
//
// 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 <http://www.gnu.org/licenses/>.

#ifndef HEADER_SUPERTUX_SUPERTUX_WORLD_STATE_HPP
#define HEADER_SUPERTUX_SUPERTUX_WORLD_STATE_HPP

#include <string>
#include <memory>

class PlayerStatus;

class WorldState
{
private:
std::unique_ptr<PlayerStatus> 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 */

0 comments on commit a1fdbb9

Please sign in to comment.