/* base/savegame.cc This file is part of the Osirion project and is distributed under the terms and conditions of the GNU General Public License version 2 */ #include #include "base/faction.h" #include "base/game.h" #include "base/savegame.h" #include "base/ship.h" #include "base/weapon.h" #include "core/gameserver.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; float armor; float reputation; Faction *faction = 0; 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("reputation")) { faction = 0; 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 if (inifile.got_key_long("npckills", l)) { player->set_npckills(l); } else if (inifile.got_key_long("pvpkills", l)) { player->set_pvpkills(l); } else if (inifile.got_key_long("time", l)) { player->set_time_wasted(l); } else { inifile.unknown_key(); } } else if (inifile.in_section("reputation")) { if (inifile.got_key_label("faction", str)) { faction = Faction::find (str); if (!faction) { inifile.unknown_error("unknown faction '" + str + "'"); } continue; } else if (inifile.got_key_float("reputation", reputation)) { if (!faction) { inifile.unknown_error("reputation without faction"); } else if (faction == Faction::default_faction()) { inifile.unknown_error("ignoring reputation for default faction"); } else { player->reputation().set_reputation(faction, reputation); } } 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)) { if (!ship) { continue; } 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 (!ship) { continue; } if (!str.size()) { continue; } else 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->has_flag(core::Entity::Dockable)) { inifile.unknown_error("spawn '" + str + "' is not dockable"); continue; } if (ship) { ship->set_spawn(spawn_entity); } } else if (inifile.got_key_float("armor", armor)) { continue; } else { inifile.unknown_key(); } } else if (inifile.in_section("item")) { if (!ship) { continue; } if (inifile.got_key_label("type", itemtype)) { core::InfoType *item_infotype = core::InfoType::find(itemtype); if (!itemtype.size() || !item_infotype) { inifile.unknown_error("invalid item 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 if (inifile.got_key_long("slot", l)) { // verify item type const Weapon *weapon = ( item->info()->type() == Weapon::infotype() ? static_cast(item->info()) : 0); if ((l > 0) && ((size_t) l <= ship->slots()->size())) { // verify slot type core::Slot *slot = ship->slots()->operator[]((size_t) (l - 1)); if (slot && (slot->type() == weapon->slot_type())) { slot->set_item(item); slot->set_flag(core::Slot::Active); slot->set_flag(core::Slot::Mounted); item->set_flag(core::Item::Mounted); } } } else { inifile.unknown_key(); } } } } if (ship) { for (core::Inventory::Items::iterator it = ship->inventory()->items().begin(); it != ship->inventory()->items().end(); ++it) { core::Item *item = (*it); if (item->info()->type() == Weapon::infotype()) { const Weapon *weapon = static_cast(item->info()); item->set_price(weapon->price()); item->set_flag(core::Item::Unrestricted); switch (weapon->subtype()) { case Weapon::Cannon: item->set_flag(core::Item::Unique); item->set_flag(core::Item::Mountable); break; case Weapon::Turret: item->set_flag(core::Item::Unique); item->set_flag(core::Item::Mountable); break; default: break; } } } ship->inventory()->recalculate(); ship->inventory()->set_dirty(); ship->set_armor(armor); if (!zone) { zone = Default::zone; } if (!ship->spawn()) { ship->set_spawn(zone->default_view()); } if (!ship->spawn()) { ship->set_spawn(Default::zone->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_zone(zone); ship->set_state(core::Entity::Normal); ship->reset(); player->set_control(ship); } } // apply default reputation Faction::apply_default(player->reputation()); } void SaveGame::player_to_stream(core::Player *player, std::ostream & os) { if (!os.good()) return; os << "[player]" << std::endl; // player name os << "name=" << player->name() << std::endl; // credit os << "credits=" << player->credits() << std::endl; os << "npckills=" << player->npckills() << std::endl; os << "pvpkills=" << player->pvpkills() << std::endl; os << "time=" << player->time_wasted() + core::server()->timestamp() - player->time_joined() << std::endl; os << std::endl; // player reputation for (core::Reputation::FactionReps::const_iterator it = player->reputation().factionreps().begin(); it != player->reputation().factionreps().end(); ++it) { os << "[reputation]" << std::endl; os << "faction=" << (*it)->faction()->label() << std::endl; os << "reputation=" << (*it)->reputation() << 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()); ship_inventory_to_stream(static_cast(player->control()), os); } } void SaveGame::ship_to_stream(Ship *ship, std::ostream & os) { if (!os.good()) return; os << "[ship]" << std::endl; os << "model=" << ship->shipmodel()->label() << std::endl; // ship zone os << "zone=" << ship->zone()->label()<< std::endl; // ship location os << "location=" << ship->location() << std::endl; // ship orientation os << "forward=" << ship->axis().forward() << std::endl; os << "left=" << ship->axis().left() << std::endl; os << "up=" << ship->axis().up() << std::endl; // ship is docked at spawn on load os << "docked="; if (ship->dock() && (ship->dock() == ship->spawn())) { os << "yes"; } else if (ship->state() == core::Entity::Destroyed) { os << "yes"; } else { os << "no"; } os << std::endl; // ship spawn os << "spawn="; if (ship->spawn()) { os << ship->spawn()->zone()->label() << ":" << ship->spawn()->label(); } os << std::endl; os << "armor=" << ship->armor() << std::endl; } void SaveGame::ship_inventory_to_stream(Ship *ship, std::ostream & os) { core::Inventory *inventory = ship->inventory(); if (!os.good()) return; if(!inventory) return; for (core::Inventory::Items::const_iterator it = inventory->items().begin(); it != inventory->items().end(); ++it) { const core::Item *item = (*it); os << std::endl; os << "[item]" << std::endl; // item InfoType label os << "type=" << item->info()->type()->label() << std::endl; // item Info label os << "label=" << item->info()->label() << std::endl; os << "amount=" << item->amount() << std::endl; os << "price=" << item->price() << std::endl; if (item->has_flag(core::Item::Tradeable)) { os << "tradeable=" << (item->has_flag(core::Item::Tradeable) ? "yes" : "no") << std::endl; } if (item->has_flag(core::Item::Mounted)) { size_t slot_number = 0; for (core::Slots::iterator slot_it = ship->slots()->begin(); slot_it != ship->slots()->end(); ++slot_it) { slot_number++; if ((*slot_it)->item() == item) { os << "slot=" << slot_number << std::endl; } } } } } } // namespace game