From 5b58252eb8805f45bf5f945c44c0647f6975ae7f Mon Sep 17 00:00:00 2001 From: Stijn Buys Date: Sun, 15 Jan 2012 16:56:37 +0000 Subject: Implemented game-specific load/save game methods. --- src/game/base/game.cc | 271 ++++++++-------------------------------------- src/game/base/game.h | 7 +- src/game/base/savegame.cc | 219 ++++++++++++++++++++++++++++++++++++- src/game/base/savegame.h | 5 + 4 files changed, 275 insertions(+), 227 deletions(-) (limited to 'src/game/base') diff --git a/src/game/base/game.cc b/src/game/base/game.cc index 1c68d11..fc87403 100644 --- a/src/game/base/game.cc +++ b/src/game/base/game.cc @@ -1721,6 +1721,19 @@ void Game::player_disconnect(core::Player *player) } } +// load singleplayer savegame +void Game::game_load(core::Player *player, filesystem::IniFile & inifile) +{ + if (player->control()) + return; + + if (!core::server()->mode() == core::GameServer::SinglePlayer) { + return; + } + + SaveGame::load_game(player, inifile); +} + void Game::player_load(core::Player *player) { if (!player->guid().is_valid()) { @@ -1730,226 +1743,45 @@ void Game::player_load(core::Player *player) if (player->control()) return; - if (core::server()->mode() == core::GameServer::MultiPlayer) { - - std::string guid(player->guid().str()); - std::string directory(guid.substr(0,4)); - - std::string filename; - filename.append("players"); - filename += '/'; - filename.append(directory); - filename += '/'; - filename.append(guid); - - filesystem::IniFile inifile; - inifile.open(filename); - if (!inifile.is_open()) { - return; - } - - con_debug << "player " << player->id() << ": " << "loading data" << std::endl; - - Ship *ship = 0; - long l; - bool b; - std::string str; - math::Vector3f v; - math::Vector3f location; - math::Axis axis; - bool ship_is_docked = false; - core::Zone *zone = 0; - core::Item *item = 0; - std::string itemtype; - std::string itemlabel; - - while (inifile.getline()) { - - if (inifile.got_section()) { - - if (inifile.got_section("player")) { - continue; - } else if (inifile.got_section("ship")) { - continue; - } else if (inifile.got_section("item")) { - if (ship) { - item = 0; - itemtype.clear(); - itemlabel.clear(); - } - continue; - } else { - inifile.unknown_section(); - } - - } else if (inifile.got_key()) { - - if (inifile.in_section("player")) { - - if (inifile.got_key_long("credits", l)) { - player->set_credits(l); - continue; - - } else if (inifile.got_key_string("name", str)) { - continue; - - } else { - inifile.unknown_key(); - } - - } else if (inifile.in_section("ship")) { - - if (inifile.got_key_label("model", str)) { - if (ship) { - continue; - } - - ShipModel *shipmodel = ShipModel::find(str); - if (!shipmodel) { - continue; - } - - ship = new Ship(player, shipmodel); - continue; - - } else if (inifile.got_key_label("zone", str)) { - zone = core::Zone::find(str); - continue; - - } else if (inifile.got_key_vector3f("location", location)) { - continue; - - } else if (inifile.got_key_vector3f("forward", axis[0])) { - continue; - - } else if (inifile.got_key_vector3f("left", axis[1])) { - continue; - - } else if (inifile.got_key_vector3f("up", axis[2])) { - continue; - - } else if (inifile.got_key_bool("docked", ship_is_docked)) { - continue; - - } else if (inifile.got_key_string("spawn", str)) { - if (str.size() < 3) { - inifile.unknown_error("spawn with invalid label '" + str + "'"); - continue; - } - size_t pos = str.find(':'); - if ((pos == std::string::npos) || (pos < 1) || (pos >= (str.size() - 1))) { - inifile.unknown_error("spawn with invalid label '" + str + "'"); - continue; - } - std::string zonelabel(str.substr(0, pos)); - std::string entitylabel(str.substr(pos + 1, str.size() - pos)); - - aux::to_label(zonelabel); - aux::to_label(entitylabel); - - core::Zone *spawn_zone = core::Zone::find(zonelabel); - if (!spawn_zone) { - inifile.unknown_error("spawn with invalid zone'" + zonelabel + "'"); - continue; - } - - core::Entity *spawn_entity = spawn_zone->find_entity(entitylabel); - if (!spawn_entity) { - inifile.unknown_error("spawn with invalid entity'" + str + "'"); - continue; - } - - if (!spawn_entity->flag_is_set(core::Entity::Dockable)) { - inifile.unknown_error("spawn '" + str + "' is not dockable"); - continue; - } - - if (ship) { - ship->set_spawn(spawn_entity); - } - } else { - inifile.unknown_key(); - } - - } else if (inifile.in_section("item")) { - - if (inifile.got_key_label("type", itemtype)) { - continue; - - } else if (inifile.got_key_label("label", itemlabel)) { - if (!item && ship) { - core::InfoType *item_infotype = core::InfoType::find(itemtype); - if (!itemtype.size() || !item_infotype) { - inifile.unknown_error("invalid item type '" + itemtype +"'"); - continue; - } - - core::Info *item_info = core::Info::find(item_infotype, itemlabel); - if (!itemlabel.size() || !item_info) { - inifile.unknown_error("invalid item label '" + itemlabel +"'"); - continue; - } - item = new core::Item(item_info); - ship->inventory()->add(item); - } - } else if (inifile.got_key_long("amount", l)) { - if (item) { - item->set_amount(l); - } - } else if (inifile.got_key_long("price", l)) { - if (item) { - item->set_price(l); - } - } else if (inifile.got_key_bool("tradeable", b)) { - if (item) { - if (b) { - item->set_flag(core::Item::Tradeable); - } else { - item->unset_flag(core::Item::Tradeable); - } - } - } else { - inifile.unknown_key(); - } - - } - } - } + if (!core::server()->mode() == core::GameServer::MultiPlayer) { + return; + } + + std::string guid(player->guid().str()); + std::string directory(guid.substr(0,4)); + + std::string filename; + filename.append("players"); + filename += '/'; + filename.append(directory); + filename += '/'; + filename.append(guid); - inifile.close(); - - if (ship) { - ship->inventory()->recalculate(); - ship->inventory()->set_dirty(); - - if (!zone) { - zone = Default::zone; - } - - if (!ship->spawn()) { - ship->set_spawn(Default::view); - } + filesystem::IniFile inifile; + inifile.open(filename); + if (!inifile.is_open()) { + return; + } + + con_debug << "player " << player->id() << ": " << "loading data" << std::endl; + + SaveGame::load_game(player, inifile); + + inifile.close(); +} - if (ship_is_docked) { - ship->set_zone(ship->spawn()->zone()); - ship->set_dock(ship->spawn()); - - player->set_control(ship); - player->set_view(ship->spawn()); - } else { - ship->set_location(location); - ship->set_axis(axis); - ship->set_state(core::Entity::Normal); - ship->set_zone(zone); - ship->reset(); +void Game::game_save(core::Player *player, std::ostream & os) +{ + if ((!player->control()) || (player->control()->moduletype() != ship_enttype)) { + return; + } - player->set_control(ship); - } - } + if (core::server()->mode() == core::GameServer::SinglePlayer) { + // save player data + SaveGame::player_to_stream(player, os); } - } - + void Game::player_save(core::Player *player) { if (!player->guid().is_valid()) { @@ -1997,15 +1829,6 @@ void Game::player_save(core::Player *player) // save player data SaveGame::player_to_stream(player, ofs); - - // save ship - // TODO iterate assets and save all ships - if (player->control()) { - SaveGame::ship_to_stream(static_cast(player->control()), ofs); - - assert(player->control()->inventory()); - SaveGame::inventory_to_stream(player->control()->inventory(), ofs); - } // close output stream ofs.close(); diff --git a/src/game/base/game.h b/src/game/base/game.h index 945671c..fb64798 100644 --- a/src/game/base/game.h +++ b/src/game/base/game.h @@ -79,7 +79,12 @@ public: /// save player data virtual void player_save(core::Player *player); - + /// singleplayer load game function + virtual void game_load(core::Player *player, filesystem::IniFile & inifile); + + /// singleplayer save game function + virtual void game_save(core::Player *player, std::ostream & os); + /* --- game variables -------------------------------------- */ /// game variable: maximum speed of the impulse drive diff --git a/src/game/base/savegame.cc b/src/game/base/savegame.cc index d9a7c4f..b6955e2 100644 --- a/src/game/base/savegame.cc +++ b/src/game/base/savegame.cc @@ -4,11 +4,217 @@ the terms and conditions of the GNU General Public License version 2 */ +#include "base/game.h" #include "base/savegame.h" #include "base/ship.h" namespace game { - + +void SaveGame::load_game(core::Player *player, filesystem::IniFile & inifile) +{ + Ship *ship = 0; + long l; + bool b; + std::string str; + math::Vector3f v; + math::Vector3f location; + math::Axis axis; + bool ship_is_docked = false; + core::Zone *zone = 0; + core::Item *item = 0; + std::string itemtype; + std::string itemlabel; + + while (inifile.getline()) { + + if (inifile.got_section()) { + + if (inifile.got_section("savegame")) { + // skip client description + continue; + } else if (inifile.got_section("player")) { + continue; + } else if (inifile.got_section("ship")) { + continue; + } else if (inifile.got_section("item")) { + if (ship) { + item = 0; + itemtype.clear(); + itemlabel.clear(); + } + continue; + } else { + inifile.unknown_section(); + } + + } else if (inifile.got_key()) { + + if (inifile.in_section("savegame")) { + // skip client description + continue; + + } else if (inifile.in_section("player")) { + + if (inifile.got_key_long("credits", l)) { + player->set_credits(l); + continue; + + } else if (inifile.got_key_string("name", str)) { + continue; + + } else { + inifile.unknown_key(); + } + + } else if (inifile.in_section("ship")) { + + if (inifile.got_key_label("model", str)) { + if (ship) { + continue; + } + + ShipModel *shipmodel = ShipModel::find(str); + if (!shipmodel) { + continue; + } + + ship = new Ship(player, shipmodel); + continue; + + } else if (inifile.got_key_label("zone", str)) { + zone = core::Zone::find(str); + continue; + + } else if (inifile.got_key_vector3f("location", location)) { + continue; + + } else if (inifile.got_key_vector3f("forward", axis[0])) { + continue; + + } else if (inifile.got_key_vector3f("left", axis[1])) { + continue; + + } else if (inifile.got_key_vector3f("up", axis[2])) { + continue; + + } else if (inifile.got_key_bool("docked", ship_is_docked)) { + continue; + + } else if (inifile.got_key_string("spawn", str)) { + if (str.size() < 3) { + inifile.unknown_error("spawn with invalid label '" + str + "'"); + continue; + } + size_t pos = str.find(':'); + if ((pos == std::string::npos) || (pos < 1) || (pos >= (str.size() - 1))) { + inifile.unknown_error("spawn with invalid label '" + str + "'"); + continue; + } + std::string zonelabel(str.substr(0, pos)); + std::string entitylabel(str.substr(pos + 1, str.size() - pos)); + + aux::to_label(zonelabel); + aux::to_label(entitylabel); + + core::Zone *spawn_zone = core::Zone::find(zonelabel); + if (!spawn_zone) { + inifile.unknown_error("spawn with invalid zone'" + zonelabel + "'"); + continue; + } + + core::Entity *spawn_entity = spawn_zone->find_entity(entitylabel); + if (!spawn_entity) { + inifile.unknown_error("spawn with invalid entity'" + str + "'"); + continue; + } + + if (!spawn_entity->flag_is_set(core::Entity::Dockable)) { + inifile.unknown_error("spawn '" + str + "' is not dockable"); + continue; + } + + if (ship) { + ship->set_spawn(spawn_entity); + } + } else { + inifile.unknown_key(); + } + + } else if (inifile.in_section("item")) { + + if (inifile.got_key_label("type", itemtype)) { + continue; + + } else if (inifile.got_key_label("label", itemlabel)) { + if (!item && ship) { + core::InfoType *item_infotype = core::InfoType::find(itemtype); + if (!itemtype.size() || !item_infotype) { + inifile.unknown_error("invalid item type '" + itemtype +"'"); + continue; + } + + core::Info *item_info = core::Info::find(item_infotype, itemlabel); + if (!itemlabel.size() || !item_info) { + inifile.unknown_error("invalid item label '" + itemlabel +"'"); + continue; + } + item = new core::Item(item_info); + ship->inventory()->add(item); + } + } else if (inifile.got_key_long("amount", l)) { + if (item) { + item->set_amount(l); + } + } else if (inifile.got_key_long("price", l)) { + if (item) { + item->set_price(l); + } + } else if (inifile.got_key_bool("tradeable", b)) { + if (item) { + if (b) { + item->set_flag(core::Item::Tradeable); + } else { + item->unset_flag(core::Item::Tradeable); + } + } + } else { + inifile.unknown_key(); + } + + } + } + } + + if (ship) { + ship->inventory()->recalculate(); + ship->inventory()->set_dirty(); + + if (!zone) { + zone = Default::zone; + } + + if (!ship->spawn()) { + ship->set_spawn(Default::view); + } + + if (ship_is_docked) { + ship->set_zone(ship->spawn()->zone()); + ship->set_dock(ship->spawn()); + + player->set_control(ship); + player->set_view(ship->spawn()); + } else { + ship->set_location(location); + ship->set_axis(axis); + ship->set_state(core::Entity::Normal); + ship->set_zone(zone); + ship->reset(); + + player->set_control(ship); + } + } +} + void SaveGame::player_to_stream(core::Player *player, std::ostream & os) { if (!os.good()) @@ -18,8 +224,17 @@ void SaveGame::player_to_stream(core::Player *player, std::ostream & os) // player name os << "name=" << player->name() << std::endl; // credit - os << "credits=" << player->credits() << std::endl; + os << "credits=" << player->credits() << std::endl; os << std::endl; + + + // save ship + // TODO iterate assets and save all ships + if (player->control()) { + ship_to_stream(static_cast(player->control()), os); + assert(player->control()->inventory()); + inventory_to_stream(player->control()->inventory(), os); + } } void SaveGame::ship_to_stream(Ship *ship, std::ostream & os) diff --git a/src/game/base/savegame.h b/src/game/base/savegame.h index 1f56ebc..06e4ee3 100644 --- a/src/game/base/savegame.h +++ b/src/game/base/savegame.h @@ -37,6 +37,11 @@ public: * @brief write inventory data to output stream, in .ini format */ static void inventory_to_stream(core::Inventory *inventory, std::ostream & os); + + /** + * @brief load a savegame from .ini file + * */ + static void load_game(core::Player *player, filesystem::IniFile & inifile); }; // class SaveGame -- cgit v1.2.3