void ResourcePool::Update() { //DebugLogger() << "ResourcePool::Update for type " << boost::lexical_cast<std::string>(m_type); // sum production from all ResourceCenters in each group, for resource point type appropriate for this pool MeterType meter_type = ResourceToMeter(m_type); MeterType target_meter_type = ResourceToTargetMeter(m_type); if (INVALID_METER_TYPE == meter_type || INVALID_METER_TYPE == target_meter_type) ErrorLogger() << "ResourcePool::Update() called when m_type can't be converted to a valid MeterType"; // zero to start... m_connected_object_groups_resource_output.clear(); m_connected_object_groups_resource_target_output.clear(); // temporary storage: indexed by group of systems, which objects // are located in that system group? std::map<std::set<int>, std::set<std::shared_ptr<const UniverseObject>>> system_groups_to_object_groups; // for every object, find if a connected system group contains the object's // system. If a group does, place the object into that system group's set // of objects. If no group contains the object, place the object in its own // single-object group. for (auto& obj : Objects().FindObjects<const UniverseObject>(m_object_ids)) { int object_id = obj->ID(); int object_system_id = obj->SystemID(); // can't generate resources when not in a system if (object_system_id == INVALID_OBJECT_ID) continue; // is object's system in a system group? std::set<int> object_system_group; for (const auto& sys_group : m_connected_system_groups) { if (sys_group.find(object_system_id) != sys_group.end()) { object_system_group = sys_group; break; } } // if object's system is not in a system group, add it as its // own entry in m_connected_object_groups_resource_output and m_connected_object_groups_resource_target_output // this will allow the object to use its own locally produced // resource when, for instance, distributing pp if (object_system_group.empty()) { object_system_group.insert(object_id); // just use this already-available set to store the object id, even though it is not likely actually a system float obj_output = obj->GetMeter(meter_type) ? obj->CurrentMeterValue(meter_type) : 0.0f; m_connected_object_groups_resource_output[object_system_group] = obj_output; float obj_target_output = obj->GetMeter(target_meter_type) ? obj->CurrentMeterValue(target_meter_type) : 0.0f; m_connected_object_groups_resource_target_output[object_system_group] = obj_target_output; continue; } // if resource center's system is in a system group, record which system // group that is for later system_groups_to_object_groups[object_system_group].insert(obj); } // sum the resource production for object groups, and store the total // group production, indexed by group of object ids for (auto& entry : system_groups_to_object_groups) { const auto& object_group = entry.second; std::set<int> object_group_ids; float total_group_output = 0.0f; float total_group_target_output = 0.0f; for (auto& obj : object_group) { if (obj->GetMeter(meter_type)) total_group_output += obj->CurrentMeterValue(meter_type); if (obj->GetMeter(target_meter_type)) total_group_target_output += obj->CurrentMeterValue(target_meter_type); object_group_ids.insert(obj->ID()); } m_connected_object_groups_resource_output[object_group_ids] = total_group_output; m_connected_object_groups_resource_target_output[object_group_ids] = total_group_target_output; } ChangedSignal(); }
int cmdRemovePath( ClientData client_data, Tcl_Interp *interp, int argc, CONST84 char *argv[]) { char *sw_marker = APP_SW_MARKER, /** arbitrary default **/ **pathlist; /** List of dirs **/ const char *delim = _colon; /** path delimiter **/ int numpaths, /** number of dirs in path **/ arg1 = 1, /** arg start **/ x; /** loop index **/ #if WITH_DEBUGGING_CALLBACK ErrorLogger( NO_ERR_START, LOC, _proc_cmdRemovePath, NULL); #endif /** ** Check arguments. There should be give 3 args: ** argv[0] - prepend/append/remove-path ** ... ** argv[n-1]- varname ** argv[n] - value **/ if(argc < 3) if( OK != ErrorLogger(ERR_USAGE,LOC,argv[0],"path-variable directory", NULL)) goto unwind0; /** ** Non-persist mode? **/ if (g_flags & M_NONPERSIST) { return (TCL_OK); } /** ** Display only ... ok, let's do so! **/ if(g_flags & M_DISPLAY) { fprintf( stderr, "%s\t ", argv[ 0]); while( --argc) fprintf( stderr, "%s ", *++argv); fprintf( stderr, "\n"); goto success0; } /** ** prepend or append. The default is append. **/ if( ! strncmp( argv[0], "pre", 3)) sw_marker = PRE_SW_MARKER; /** ** Check for the delimiter option **/ if(*(argv[arg1]) == '-') { if (!strcmp(argv[arg1], "-d")) { delim = argv[arg1+1]; arg1 += 2; } else if (!strcmp(argv[arg1], "--delim")) { delim = argv[arg1+1]; arg1 += 2; } else if (!strncmp(argv[arg1], "--delim=", 8)) { delim = argv[arg1]+8; arg1++; } } /** ** For switch state3, we're looking to remove the markers. **/ if( g_flags & M_SWSTATE3) argv[arg1+1] = sw_marker; /** ** Split the path into its components so each item can be removed ** individually from the variable. **/ if( !( pathlist = SplitIntoList( interp, (char *) argv[arg1+1], &numpaths, delim))) goto unwind0; /** ** Remove each item individually **/ for( x = 0; x < numpaths; x++) if(TCL_OK != Remove_Path(interp,(char *) argv[arg1],pathlist[x], sw_marker, delim)) goto unwind1; #if WITH_DEBUGGING_CALLBACK ErrorLogger( NO_ERR_END, LOC, _proc_cmdRemovePath, NULL); #endif /** ** Free resources **/ FreeList(pathlist, numpaths); success0: return( TCL_OK); /** -------- EXIT (SUCCESS) -------> **/ unwind1: FreeList(pathlist, numpaths); unwind0: return( TCL_ERROR); /** -------- EXIT (FAILURE) -------> **/ } /** End of 'cmdRemovePath' **/
std::string SupplyManager::Dump(int empire_id) const { std::string retval; try { for (const std::map<int, std::set<int>>::value_type& empire_supply : m_fleet_supplyable_system_ids) { if (empire_id != ALL_EMPIRES && empire_supply.first != empire_id) continue; retval += "Supplyable systems for empire " + std::to_string(empire_supply.first) + "\n"; for (int system_id : empire_supply.second) { std::shared_ptr<const System> sys = GetSystem(system_id); if (!sys) continue; retval += "\n" + sys->PublicName(empire_id) + " (" + std::to_string(sys->ID()) + ") "; retval += "\nTraversals from here to: "; for (const std::set<std::pair<int, int>>::value_type& trav : m_supply_starlane_traversals.at(empire_supply.first)) { if (trav.first == sys->ID()) { std::shared_ptr<const UniverseObject> obj = GetUniverseObject(trav.second); if (obj) retval += obj->PublicName(empire_id) + " (" + std::to_string(obj->ID()) + ") "; } } retval += "\n"; retval += "Traversals to here from: "; for (const std::set<std::pair<int, int>>::value_type& trav : m_supply_starlane_traversals.at(empire_supply.first)) { if (trav.second == sys->ID()) { std::shared_ptr<const UniverseObject> obj = GetUniverseObject(trav.first); if (obj) retval += obj->PublicName(empire_id) + " (" + std::to_string(obj->ID()) + ") "; } } retval += "\n"; retval += "Blocked Traversals from here to: "; for (const std::set<std::pair<int, int>>::value_type& trav : m_supply_starlane_obstructed_traversals.at(empire_supply.first)) { if (trav.first == sys->ID()) { std::shared_ptr<const UniverseObject> obj = GetUniverseObject(trav.second); if (obj) retval += obj->PublicName(empire_id) + " (" + std::to_string(obj->ID()) + ") "; } } retval += "\n"; retval += "Blocked Traversals to here from: "; for (const std::set<std::pair<int, int>>::value_type& trav : m_supply_starlane_obstructed_traversals.at(empire_supply.first)) { if (trav.second == sys->ID()) { std::shared_ptr<const UniverseObject> obj = GetUniverseObject(trav.first); if (obj) retval += obj->PublicName(empire_id) + " (" + std::to_string(obj->ID()) + ") "; } } retval += "\n"; } retval += "\n\n"; } for (const std::map<int, std::set<std::set<int>>>::value_type& empire_supply : m_resource_supply_groups) { retval += "Supply groups for empire " + std::to_string(empire_supply.first) + "\n"; for (const std::set<std::set<int>>::value_type& system_group : empire_supply.second) { retval += "group: "; for (int system_id : system_group) { std::shared_ptr<const System> sys = GetSystem(system_id); if (!sys) continue; retval += "\n" + sys->PublicName(empire_id) + " (" + std::to_string(sys->ID()) + ") "; } retval += "\n"; } retval += "\n\n"; } } catch (const std::exception& e) { ErrorLogger() << "SupplyManager::Dump caught exception: " << e.what(); } return retval; }
int cmdSystem( ClientData clientData, Tcl_Interp *interp, int argc, CONST84 char *argv[]) { int i; int saved_stdout; char buf[ MAX_ARGLIST]; char *bufp = buf; int total_len = 0, arg_len; #if WITH_DEBUGGING_CALLBACK ErrorLogger( NO_ERR_START, LOC, _proc_cmdSystem, NULL); #endif /** ** Whatis mode **/ if( g_flags & (M_WHATIS | M_HELP)) return( TCL_OK); /** -------- EXIT (SUCCESS) -------> **/ /** ** Display mode? **/ if( g_flags & M_DISPLAY) { fprintf( stderr, "%s\t\t ", argv[ 0]); for( i=1; i<argc; i++) fprintf( stderr, "%s ", argv[ i]); fprintf( stderr, "\n"); return( TCL_OK); /** ------- EXIT PROCEDURE -------> **/ } /** ** Prepare a buffer to hold the complete 'system' call ** Watch over the commands complete length while copying ... **/ for( i = 1; i<argc; i++) { total_len += (1 + (arg_len = strlen(argv[i]))); if( total_len > MAX_ARGLIST) { if( OK != ErrorLogger( ERR_ARGSTOLONG, LOC, argv[0], (sprintf( buf, "%d", total_len), buf), NULL)) return( TCL_ERROR); /** -------- EXIT (FAILURE) -------> **/ } /** ** Copy the argument ov the buffer and put a space at its end **/ memcpy( bufp, argv[i], arg_len); bufp += arg_len; memcpy( bufp, " ", 1); bufp += 1; } /** ** For Modules, stdout must be directed to stderr so it ** isn't parsed by the evaluating shell. We also must save it here so it ** can be restored after this command has been executed. **/ saved_stdout = TieStdout(); *(bufp-1) = '\0'; i = system( buf); /** ** Following the style of Tcl_ExecCmd, we can just return the ** raw result (appropriately shifted and masked) to Tcl **/ sprintf( buf, "%d", (0xff & (i >> 8))); Tcl_SetResult( interp, buf, TCL_VOLATILE); /* * Restore stdout. */ UnTieStdout( saved_stdout); #if WITH_DEBUGGING_CALLBACK ErrorLogger( NO_ERR_END, LOC, _proc_cmdSystem, NULL); #endif return( TCL_OK); } /** End of 'cmdSystem' **/
void ShipDesign::BuildStatCaches() { const HullType* hull = GetHullType(m_hull); if (!hull) { ErrorLogger() << "ShipDesign::BuildStatCaches couldn't get hull with name " << m_hull; return; } m_producible = hull->Producible(); m_detection = hull->Detection(); m_colony_capacity = hull->ColonyCapacity(); m_troop_capacity = hull->TroopCapacity(); m_stealth = hull->Stealth(); m_fuel = hull->Fuel(); m_shields = hull->Shields(); m_structure = hull->Structure(); m_speed = hull->Speed(); for (std::vector<std::string>::const_iterator it = m_parts.begin(); it != m_parts.end(); ++it) { if (it->empty()) continue; const PartType* part = GetPartType(*it); if (!part) { ErrorLogger() << "ShipDesign::BuildStatCaches couldn't get part with name " << *it; continue; } if (!part->Producible()) m_producible = false; switch (part->Class()) { case PC_SHORT_RANGE: case PC_MISSILES: case PC_FIGHTERS: case PC_POINT_DEFENSE: { m_is_armed = true; break; } case PC_COLONY: m_colony_capacity += part->Capacity(); break; case PC_TROOPS: m_troop_capacity += part->Capacity(); break; case PC_STEALTH: m_stealth += part->Capacity(); break; case PC_SPEED: m_speed += part->Capacity(); break; case PC_SHIELD: m_shields += part->Capacity(); break; case PC_FUEL: m_fuel += part->Capacity(); break; case PC_ARMOUR: m_structure += part->Capacity(); break; case PC_DETECTION: m_detection += part->Capacity(); break; case PC_BOMBARD: m_can_bombard = true; break; case PC_RESEARCH: m_research_generation += part->Capacity(); break; case PC_INDUSTRY: m_industry_generation += part->Capacity(); break; case PC_TRADE: m_trade_generation += part->Capacity(); break; case PC_PRODICTION_LOCATION: m_is_production_location = true; break; default: break; } } }
static void exchange( char **argv) { int bottom = first_nonopt; int middle = last_nonopt; int top = optind; char *tem; #ifdef _MODULES_DEF_H # if WITH_DEBUGGING_INIT ErrorLogger( NO_ERR_START, LOC, _proc_exchange, NULL); # endif #endif /** ** Exchange the shorter segment with the far end of the longer segment. ** That puts the shorter segment into the right place. ** It leaves the longer segment in the right place overall, ** but it consists of two parts that need to be swapped next. **/ while( top > middle && middle > bottom) { if( top - middle > middle - bottom) { /** ** Bottom segment is the short one. **/ int len = middle - bottom; register int i; /** ** Swap it with the top part of the top segment. **/ for( i = 0; i < len; i++) { tem = argv[bottom + i]; argv[bottom + i] = argv[top -( middle - bottom) + i]; argv[top -( middle - bottom) + i] = tem; } /** ** Exclude the moved bottom segment from further swapping. **/ top -= len; } else { /** ** Top segment is the short one. **/ int len = top - middle; register int i; /** ** Swap it with the bottom part of the bottom segment. **/ for( i = 0; i < len; i++) { tem = argv[bottom + i]; argv[bottom + i] = argv[middle + i]; argv[middle + i] = tem; } /** ** Exclude the moved top segment from further swapping. **/ bottom += len; } } /** while **/ /** ** Update records for the slots the non-options now occupy. **/ first_nonopt +=( optind - last_nonopt); last_nonopt = optind; #ifdef _MODULES_DEF_H # if WITH_DEBUGGING_INIT ErrorLogger( NO_ERR_END, LOC, _proc_exchange, NULL); # endif #endif } /** end of 'exchange' **/
void SpecialsPanel::Update() { //std::cout << "SpecialsPanel::Update" << std::endl; for (std::map<std::string, StatisticIcon*>::iterator it = m_icons.begin(); it != m_icons.end(); ++it) DeleteChild(it->second); m_icons.clear(); // get specials to display TemporaryPtr<const UniverseObject> obj = GetUniverseObject(m_object_id); if (!obj) { ErrorLogger() << "SpecialsPanel::Update couldn't get object with id " << m_object_id; return; } const std::map<std::string, std::pair<int, float> >& specials = obj->Specials(); // get specials and use them to create specials icons // for specials with a nonzero for (std::map<std::string, std::pair<int, float> >::const_iterator it = specials.begin(); it != specials.end(); ++it) { const Special* special = GetSpecial(it->first); StatisticIcon* graphic = 0; if (it->second.second > 0.0f) graphic = new StatisticIcon(ClientUI::SpecialIcon(special->Name()), it->second.second, 2, false); else graphic = new StatisticIcon(ClientUI::SpecialIcon(special->Name())); graphic->SetBrowseModeTime(GetOptionsDB().Get<int>("UI.tooltip-delay")); std::string desc = UserString(special->Description()); if (it->second.second > 0.0f) desc += "\n" + boost::io::str(FlexibleFormat(UserString("SPECIAL_CAPACITY")) % DoubleToString(it->second.second, 2, false)); if (it->second.first > 0) desc += "\n" + boost::io::str(FlexibleFormat(UserString("ADDED_ON_TURN")) % boost::lexical_cast<std::string>(it->second.first)); else desc += "\n" + UserString("ADDED_ON_INITIAL_TURN"); if (GetOptionsDB().Get<bool>("UI.autogenerated-effects-descriptions") && !special->Effects().empty()) { desc += boost::io::str(FlexibleFormat(UserString("ENC_EFFECTS_STR")) % AutoGeneratedDescription(special->Effects())); } graphic->SetBrowseInfoWnd(boost::shared_ptr<GG::BrowseInfoWnd>( new IconTextBrowseWnd(ClientUI::SpecialIcon(special->Name()), UserString(special->Name()), desc))); m_icons[it->first] = graphic; graphic->InstallEventFilter(this); } const GG::X AVAILABLE_WIDTH = Width() - EDGE_PAD; GG::X x(EDGE_PAD); GG::Y y(EDGE_PAD); for (std::map<std::string, StatisticIcon*>::iterator it = m_icons.begin(); it != m_icons.end(); ++it) { StatisticIcon* icon = it->second; icon->SizeMove(GG::Pt(x, y), GG::Pt(x,y) + GG::Pt(SPECIAL_ICON_WIDTH, SPECIAL_ICON_HEIGHT)); AttachChild(icon); x += SPECIAL_ICON_WIDTH + EDGE_PAD; if (x + SPECIAL_ICON_WIDTH + EDGE_PAD > AVAILABLE_WIDTH) { x = GG::X(EDGE_PAD); y += SPECIAL_ICON_HEIGHT + EDGE_PAD; } } if (m_icons.empty()) { Resize(GG::Pt(Width(), GG::Y0)); } else { Resize(GG::Pt(Width(), y + SPECIAL_ICON_HEIGHT + EDGE_PAD*2)); } }
void SaveGame(const std::string& filename, const ServerSaveGameData& server_save_game_data, const std::vector<PlayerSaveGameData>& player_save_game_data, const Universe& universe, const EmpireManager& empire_manager, const SpeciesManager& species_manager, const CombatLogManager& combat_log_manager, const GalaxySetupData& galaxy_setup_data, bool multiplayer) { ScopedTimer timer("SaveGame: " + filename, true); bool use_binary = GetOptionsDB().Get<bool>("binary-serialization"); DebugLogger() << "SaveGame(" << (use_binary ? "binary" : "zlib-xml") << ") filename: " << filename; GetUniverse().EncodingEmpire() = ALL_EMPIRES; DebugLogger() << "Compiling save empire and preview data"; std::map<int, SaveGameEmpireData> empire_save_game_data = CompileSaveGameEmpireData(empire_manager); SaveGamePreviewData save_preview_data; CompileSaveGamePreviewData(server_save_game_data, player_save_game_data, empire_save_game_data, save_preview_data); // reinterpret save game data as header data for uncompressed header std::vector<PlayerSaveHeaderData> player_save_header_data; for (std::vector<PlayerSaveGameData>::const_iterator it = player_save_game_data.begin(); it != player_save_game_data.end(); ++it) { player_save_header_data.push_back(*it); } try { fs::path path = FilenameToPath(filename); // A relative path should be relative to the save directory. if (path.is_relative()) { path = GetSaveDir() / path; DebugLogger() << "Made save path relative to save dir. Is now: " << path; } if (multiplayer) { // Make sure the path points into our save directory if (!IsInside(path, GetSaveDir())) { path = GetSaveDir() / path.filename(); } } // set up output archive / stream for saving fs::ofstream ofs(path, std::ios_base::binary); if (!ofs) throw std::runtime_error(UNABLE_TO_OPEN_FILE); if (use_binary) { DebugLogger() << "Creating binary oarchive"; freeorion_bin_oarchive boa(ofs); boa << BOOST_SERIALIZATION_NVP(save_preview_data); boa << BOOST_SERIALIZATION_NVP(galaxy_setup_data); boa << BOOST_SERIALIZATION_NVP(server_save_game_data); boa << BOOST_SERIALIZATION_NVP(player_save_header_data); boa << BOOST_SERIALIZATION_NVP(empire_save_game_data); boa << BOOST_SERIALIZATION_NVP(player_save_game_data); boa << BOOST_SERIALIZATION_NVP(empire_manager); boa << BOOST_SERIALIZATION_NVP(species_manager); boa << BOOST_SERIALIZATION_NVP(combat_log_manager); Serialize(boa, universe); DebugLogger() << "Done serializing"; } else { // Two-tier serialization: // main archive is uncompressed serialized header data first // then contains a string for compressed second archive // that contains the main gamestate info // allocate buffers for serialized gamestate DebugLogger() << "Allocating buffers for XML serialization..."; std::string serial_str, compressed_str; try { serial_str.reserve( std::pow(2.0, 29.0)); compressed_str.reserve(std::pow(2.0, 26.0)); } catch (...) { DebugLogger() << "Unable to preallocate full serialization buffers. Attempting serialization with dynamic buffer allocation."; } // wrap buffer string in iostream::stream to receive serialized data typedef boost::iostreams::back_insert_device<std::string> InsertDevice; InsertDevice serial_inserter(serial_str); boost::iostreams::stream<InsertDevice> s_sink(serial_inserter); // create archive with (preallocated) buffer... freeorion_xml_oarchive xoa(s_sink); // serialize main gamestate info xoa << BOOST_SERIALIZATION_NVP(player_save_game_data); xoa << BOOST_SERIALIZATION_NVP(empire_manager); xoa << BOOST_SERIALIZATION_NVP(species_manager); xoa << BOOST_SERIALIZATION_NVP(combat_log_manager); Serialize(xoa, universe); s_sink.flush(); // wrap gamestate string in iostream::stream to extract serialized data typedef boost::iostreams::basic_array_source<char> SourceDevice; SourceDevice source(serial_str.data(), serial_str.size()); boost::iostreams::stream<SourceDevice> s_source(source); // wrap compresed buffer string in iostream::streams to receive compressed string InsertDevice compressed_inserter(compressed_str); boost::iostreams::stream<InsertDevice> c_sink(compressed_inserter); // compression-filter gamestate into compressed string boost::iostreams::filtering_ostreambuf o; o.push(boost::iostreams::zlib_compressor()); o.push(c_sink); boost::iostreams::copy(s_source, o); c_sink.flush(); // write to save file: uncompressed header serialized data, with compressed main archive string at end... freeorion_xml_oarchive xoa2(ofs); // serialize uncompressed save header info xoa2 << BOOST_SERIALIZATION_NVP(save_preview_data); xoa2 << BOOST_SERIALIZATION_NVP(galaxy_setup_data); xoa2 << BOOST_SERIALIZATION_NVP(server_save_game_data); xoa2 << BOOST_SERIALIZATION_NVP(player_save_header_data); xoa2 << BOOST_SERIALIZATION_NVP(empire_save_game_data); // append compressed gamestate info xoa2 << BOOST_SERIALIZATION_NVP(compressed_str); } } catch (const std::exception& e) { ErrorLogger() << UserString("UNABLE_TO_WRITE_SAVE_FILE") << " SaveGame exception: " << ": " << e.what(); throw e; } DebugLogger() << "SaveGame : Successfully wrote save file"; }
void LoadGame(const std::string& filename, ServerSaveGameData& server_save_game_data, std::vector<PlayerSaveGameData>& player_save_game_data, Universe& universe, EmpireManager& empire_manager, SpeciesManager& species_manager, CombatLogManager& combat_log_manager, GalaxySetupData& galaxy_setup_data) { //boost::this_thread::sleep_for(boost::chrono::seconds(1)); ScopedTimer timer("LoadGame: " + filename, true); // player notifications if (ServerApp* server = ServerApp::GetApp()) server->Networking().SendMessage(TurnProgressMessage(Message::LOADING_GAME)); GetUniverse().EncodingEmpire() = ALL_EMPIRES; std::map<int, SaveGameEmpireData> ignored_save_game_empire_data; SaveGamePreviewData ignored_save_preview_data; std::vector<PlayerSaveHeaderData> ignored_player_save_header_data; empire_manager.Clear(); universe.Clear(); try { // set up input archive / stream for loading const fs::path path = FilenameToPath(filename); fs::ifstream ifs(path, std::ios_base::binary); if (!ifs) throw std::runtime_error(UNABLE_TO_OPEN_FILE); try { // first attempt binary deserialziation freeorion_bin_iarchive ia(ifs); DebugLogger() << "Reading binary iarchive"; ia >> BOOST_SERIALIZATION_NVP(ignored_save_preview_data); ia >> BOOST_SERIALIZATION_NVP(galaxy_setup_data); ia >> BOOST_SERIALIZATION_NVP(server_save_game_data); ia >> BOOST_SERIALIZATION_NVP(ignored_player_save_header_data); ia >> BOOST_SERIALIZATION_NVP(ignored_save_game_empire_data); ia >> BOOST_SERIALIZATION_NVP(player_save_game_data); ia >> BOOST_SERIALIZATION_NVP(empire_manager); ia >> BOOST_SERIALIZATION_NVP(species_manager); ia >> BOOST_SERIALIZATION_NVP(combat_log_manager); Deserialize(ia, universe); DebugLogger() << "Done deserializing"; } catch (...) { // if binary deserialization failed, try more-portable XML deserialization // reset to start of stream (attempted binary serialization will have consumed some input...) boost::iostreams::seek(ifs, 0, std::ios_base::beg); // allocate buffers for serialized gamestate DebugLogger() << "Allocating buffers for XML deserialization..."; std::string serial_str, compressed_str; try { serial_str.reserve( std::pow(2.0, 29.0)); compressed_str.reserve(std::pow(2.0, 26.0)); } catch (...) { DebugLogger() << "Unable to preallocate full deserialization buffers. Attempting deserialization with dynamic buffer allocation."; } // create archive with (preallocated) buffer... freeorion_xml_iarchive xia(ifs); // read from save file: uncompressed header serialized data, with compressed main archive string at end... // deserialize uncompressed save header info xia >> BOOST_SERIALIZATION_NVP(ignored_save_preview_data); xia >> BOOST_SERIALIZATION_NVP(galaxy_setup_data); xia >> BOOST_SERIALIZATION_NVP(server_save_game_data); xia >> BOOST_SERIALIZATION_NVP(ignored_player_save_header_data); xia >> BOOST_SERIALIZATION_NVP(ignored_save_game_empire_data); // extract compressed gamestate info xia >> BOOST_SERIALIZATION_NVP(compressed_str); // wrap compressed string in iostream::stream to extract compressed data typedef boost::iostreams::basic_array_source<char> SourceDevice; SourceDevice compressed_source(compressed_str.data(), compressed_str.size()); boost::iostreams::stream<SourceDevice> c_source(compressed_source); // wrap uncompressed buffer string in iostream::stream to receive decompressed string typedef boost::iostreams::back_insert_device<std::string> InsertDevice; InsertDevice serial_inserter(serial_str); boost::iostreams::stream<InsertDevice> s_sink(serial_inserter); // set up filter to decompress data boost::iostreams::filtering_istreambuf i; i.push(boost::iostreams::zlib_decompressor()); i.push(c_source); boost::iostreams::copy(i, s_sink); // The following line has been commented out because it caused an assertion in boost iostreams to fail // s_sink.flush(); // wrap uncompressed buffer string in iostream::stream to extract decompressed string SourceDevice serial_source(serial_str.data(), serial_str.size()); boost::iostreams::stream<SourceDevice> s_source(serial_source); // create archive with (preallocated) buffer... freeorion_xml_iarchive xia2(s_source); // deserialize main gamestate info xia2 >> BOOST_SERIALIZATION_NVP(player_save_game_data); xia2 >> BOOST_SERIALIZATION_NVP(empire_manager); xia2 >> BOOST_SERIALIZATION_NVP(species_manager); xia2 >> BOOST_SERIALIZATION_NVP(combat_log_manager); Deserialize(xia2, universe); } } catch (const std::exception& err) { ErrorLogger() << "LoadGame(...) failed! Error: " << err.what(); return; } DebugLogger() << "LoadGame : Successfully loaded save file"; }
int ModuleCmd_List( Tcl_Interp *interp, int argc, char *argv[]) { /** ** Get the list of loaded modules at first **/ char *loaded, *lmfiles; int i, count1, count2; char *list[ MOD_BUFSIZE]; char *files[ MOD_BUFSIZE]; char *tmplist[ MOD_BUFSIZE], *s; int len; #if WITH_DEBUGGING_MODULECMD ErrorLogger( NO_ERR_START, LOC, _proc_ModuleCmd_List, NULL); #endif lmfiles = getLMFILES( interp); loaded = getenv( "LOADEDMODULES"); if( !loaded || !*loaded) { if( sw_format & (SW_TERSE | SW_LONG | SW_HUMAN) ) fprintf(stderr, "No Modulefiles Currently Loaded.\n"); } else { /** ** Now tokenize it, form a list and print it out. **/ if( sw_format & SW_LONG ) { fprintf( stderr, long_header); } if( sw_format & (SW_TERSE | SW_LONG | SW_HUMAN) ) fprintf( stderr, "Currently Loaded Modulefiles:\n"); /** ** LOADEDMODULES and _LMFILES_ should provide a list of loaded ** modules and assigned files in the SAME ORDER ** but double check, because if they aren't you will get a crash. **/ count1 = 1; for( list[ 0] = xstrtok( loaded, ":"); list[ count1] = xstrtok( NULL, ":"); count1++ ); count2 = 1; for( files[ 0] = xstrtok( lmfiles, ":"); files[ count2] = xstrtok( NULL, ":"); count2++ ); if (count1 != count2) { ErrorLogger( ERR_ENVVAR, LOC, NULL); } /** ** We have to build a single list of files for each loaded entry ** in order to be able to figure out the length of the directory ** part **/ for( i=0; i<count1; i++) { len = strlen( files[i]) - strlen( list[i]); tmplist[i] = files[i]; /** ** We have to source all relevant .modulerc and .version files ** on the path **/ s = files[i] + len; while( s) { if( s = strchr( s, '/')) *s = '\0'; SourceRC( interp, files[i], modulerc_file); SourceVers( interp, files[i], list[i]); if( s) *s++ = '/'; } /** ** Print this guy **/ } print_aligned_files( interp, NULL, NULL, tmplist, count1, 1); } /** ** Return on success **/ #if WITH_DEBUGGING_MODULECMD ErrorLogger( NO_ERR_END, LOC, _proc_ModuleCmd_List, NULL); #endif return( TCL_OK); } /** End of 'ModuleCmd_List' **/
int mainSetupAndRun() { try { int colour_depth = GetOptionsDB().Get<int>("color-depth"); bool fullscreen = GetOptionsDB().Get<bool>("fullscreen"); bool fake_mode_change = GetOptionsDB().Get<bool>("fake-mode-change"); std::pair<int, int> width_height = HumanClientApp::GetWindowWidthHeight(); int width(width_height.first), height(width_height.second); std::pair<int, int> left_top = HumanClientApp::GetWindowLeftTop(); int left(left_top.first), top(left_top.second); int fullscreen_monitor_id = GetOptionsDB().Get<int>("fullscreen-monitor-id"); #ifdef FREEORION_WIN32 # ifdef IDI_ICON1 // set window icon to embedded application icon HWND hwnd; window->getCustomAttribute("WINDOW", &hwnd); HINSTANCE hInst = (HINSTANCE)GetModuleHandle(NULL); SetClassLong (hwnd, GCL_HICON, (LONG)LoadIcon (hInst, MAKEINTRESOURCE (IDI_ICON1))); # endif #endif parse::init(); HumanClientApp app(width_height.first, width_height.second, true, "FreeOrion " + FreeOrionVersionString(), left, top, fullscreen, fake_mode_change); if (GetOptionsDB().Get<bool>("quickstart")) { // immediately start the server, establish network connections, and // go into a single player game, using default universe options (a // standard quickstart, without requiring the user to click the // quickstart button). app.NewSinglePlayerGame(true); // acceptable to call before app() } std::string load_filename = GetOptionsDB().Get<std::string>("load"); if (!load_filename.empty()) { // immediately start the server, establish network connections, and // go into a single player game, loading the indicated file // (without requiring the user to click the load button). app.LoadSinglePlayerGame(load_filename); // acceptable to call before app() } // run rendering loop app(); // calls GUI::operator() which calls SDLGUI::Run() which starts rendering loop } catch (const HumanClientApp::CleanQuit&) { // do nothing std::cout << "mainSetupAndRun caught CleanQuit" << std::endl; } catch (const std::invalid_argument& e) { ErrorLogger() << "main() caught exception(std::invalid_argument): " << e.what(); std::cerr << "main() caught exception(std::invalid_arg): " << e.what() << std::endl; } catch (const std::runtime_error& e) { ErrorLogger() << "main() caught exception(std::runtime_error): " << e.what(); std::cerr << "main() caught exception(std::runtime_error): " << e.what() << std::endl; } catch (const boost::io::format_error& e) { ErrorLogger() << "main() caught exception(boost::io::format_error): " << e.what(); std::cerr << "main() caught exception(boost::io::format_error): " << e.what() << std::endl; } catch (const GG::ExceptionBase& e) { ErrorLogger() << "main() caught exception(" << e.type() << "): " << e.what(); std::cerr << "main() caught exception(" << e.type() << "): " << e.what() << std::endl; } catch (const std::exception& e) { ErrorLogger() << "main() caught exception(std::exception): " << e.what(); std::cerr << "main() caught exception(std::exception): " << e.what() << std::endl; } catch (...) { ErrorLogger() << "main() caught unknown exception."; std::cerr << "main() caught unknown exception." << std::endl; } return 0; }
void PlayerListWnd::PlayerRightClicked(GG::ListBox::iterator it, const GG::Pt& pt, const GG::Flags<GG::ModKey>& modkeys) { // check that a valid player was clicked and that it wasn't this client's own player int clicked_player_id = PlayerInRow(it); if (clicked_player_id == Networking::INVALID_PLAYER_ID) return; const ClientApp* app = ClientApp::GetApp(); if (!app) { ErrorLogger() << "PlayerListWnd::PlayerRightClicked couldn't get client app!"; return; } int client_player_id = app->PlayerID(); if (client_player_id == Networking::INVALID_PLAYER_ID) return; int client_empire_id = app->EmpireID(); // get empire id of clicked player const std::map<int, PlayerInfo>& players = app->Players(); std::map<int, PlayerInfo>::const_iterator clicked_player_it = players.find(clicked_player_id); if (clicked_player_it == players.end()) { ErrorLogger() << "PlayerListWnd::PlayerRightClicked couldn't find player with id " << clicked_player_id; return; } const PlayerInfo& clicked_player_info = clicked_player_it->second; int clicked_empire_id = clicked_player_info.empire_id; if (!GetEmpire(clicked_empire_id)) { ErrorLogger() << "PlayerListWnd::PlayerRightClicked tried to look up empire id " << clicked_empire_id << " for player " << clicked_player_id << " but couldn't find such an empire"; return; } GG::MenuItem menu_contents; if (app->GetClientType() == Networking::CLIENT_TYPE_HUMAN_PLAYER) { // get diplomatic status between client and clicked empires DiplomaticStatus diplo_status = Empires().GetDiplomaticStatus(clicked_empire_id, client_empire_id); if (diplo_status == INVALID_DIPLOMATIC_STATUS && clicked_player_id != client_player_id) { ErrorLogger() << "PlayerListWnd::PlayerRightClicked found invalid diplomatic status between client and clicked empires."; return; } DiplomaticMessage existing_message = Empires().GetDiplomaticMessage(clicked_empire_id, client_empire_id); // create popup menu with diplomacy options in it if ( client_empire_id != ALL_EMPIRES) { if (diplo_status == DIPLO_WAR) { if (existing_message.GetType() == DiplomaticMessage::PEACE_PROPOSAL) { // who sent message? if (existing_message.SenderEmpireID() == client_empire_id) menu_contents.next_level.push_back(GG::MenuItem(UserString("PEACE_PROPOSAL_CANEL"), 4, false, false)); else if (existing_message.SenderEmpireID() == clicked_empire_id) menu_contents.next_level.push_back(GG::MenuItem(UserString("PEACE_ACCEPT"), 3, false, false)); } else if (existing_message.GetType() == DiplomaticMessage::INVALID_DIPLOMATIC_MESSAGE_TYPE) { menu_contents.next_level.push_back(GG::MenuItem(UserString("PEACE_PROPOSAL"), 2, false, false)); } } else if (diplo_status == DIPLO_PEACE) { if (existing_message.GetType() == DiplomaticMessage::INVALID_DIPLOMATIC_MESSAGE_TYPE) menu_contents.next_level.push_back(GG::MenuItem(UserString("WAR_DECLARATION"), 1, false, false)); } } } menu_contents.next_level.push_back(GG::MenuItem(str(FlexibleFormat(UserString("ENC_LOOKUP")) % GetEmpire(clicked_empire_id)->Name()), 5, false, false)); ClientNetworking& net = HumanClientApp::GetApp()->Networking(); GG::PopupMenu popup(pt.x, pt.y, ClientUI::GetFont(), menu_contents, ClientUI::TextColor(), ClientUI::WndOuterBorderColor(), ClientUI::WndColor(), ClientUI::EditHiliteColor()); if (popup.Run()) { switch (popup.MenuID()) { case 1: { // WAR_DECLARATION net.SendMessage(DiplomacyMessage(client_player_id, clicked_player_id, WarDeclarationDiplomaticMessage(client_empire_id, clicked_empire_id))); break; } case 2: { // PEACE_PROPOSAL net.SendMessage(DiplomacyMessage(client_player_id, clicked_player_id, PeaceProposalDiplomaticMessage(client_empire_id, clicked_empire_id))); break; } case 3: { // PEACE_ACCEPT net.SendMessage(DiplomacyMessage(client_player_id, clicked_player_id, AcceptDiplomaticMessage(client_empire_id, clicked_empire_id))); break; } case 4: { // PEACE_PROPOSAL_CANEL net.SendMessage(DiplomacyMessage(client_player_id, clicked_player_id, CancelDiplomaticMessage(client_empire_id, clicked_empire_id))); break; } case 5: { // Pedia lookup ClientUI::GetClientUI()->ZoomToEmpire(clicked_empire_id); break; } default: break; } } }
/** * recursively creates dummy nodes between parent and child */ TechTreeLayout::Node::Node(Node* parent, Node* child, std::vector<Node*>& nodes) : m_depth(-1), m_row(-1), m_tech(), m_x(0), m_y(0), m_width(0), m_height(0), m_place_holder(true), m_children_rows(0), m_parents(), m_children(), m_primary_child(0), m_out_edges(), m_weight(LINE_CELL_HEIGHT) { assert(parent != 0 && child != 0); // ensure passed in nodes are valid if (!parent) ErrorLogger() << "Node::Node passed null parent"; if (!child) ErrorLogger() << "Node::Node passed null child"; if (!parent || !child) return; //DebugLogger() << "Node::Node given parent " << parent // << " and child: " << child; //DebugLogger() << "Node::Node given parent with depth " << parent->m_depth // << " and child with depth: " << child->m_depth; // ensure there is space to insert node between parent and child nodes if (child->m_depth <= parent->m_depth + 1) { ErrorLogger() << "no space to insert a dummy node!"; m_depth = child->m_depth; return; } //DebugLogger() << "Node::Node adding dummy node: " << this // << " between parent node tech: " << parent->m_tech // << " and child node tech: " << child->m_tech; // add node to main node bookkeeping nodes.push_back(this); // copy parent/child connectivity m_depth = parent->m_depth + 1; m_tech = child->m_tech; m_parents.push_back(parent); m_children.push_back(child); m_primary_child = child; // update child's parents to point to this node instead of input parent std::vector<Node*>& child_parents = child->m_parents; for (unsigned int i = 0; i < child_parents.size(); ++i) { Node*& child_parent_ref = child_parents[i]; if (child_parent_ref == parent) child_parent_ref = this; } // update parent's child node pointers to instead point to this node std::vector<Node*>& parent_children = parent->m_children; for (unsigned int i = 0; i < parent_children.size(); ++i) { Node*& parent_child_ref = parent_children[i]; if (parent_child_ref == child) parent_child_ref = this; } if (parent->m_primary_child == child) parent->m_primary_child = this; }
void AIClientApp::HandleMessage(const Message& msg) { //DebugLogger() << "AIClientApp::HandleMessage " << msg.Type(); switch (msg.Type()) { case Message::ERROR_MSG: { ErrorLogger() << "AIClientApp::HandleMessage : Received ERROR message from server: " << msg.Text(); break; } case Message::HOST_ID: { const std::string& text = msg.Text(); int host_id = Networking::INVALID_PLAYER_ID; if (text.empty()) { ErrorLogger() << "AIClientApp::HandleMessage for HOST_ID : Got empty message text?!"; } else { try { host_id = boost::lexical_cast<int>(text); } catch(const boost::bad_lexical_cast& ex) { ErrorLogger() << "AIClientApp::HandleMessage for HOST_ID : Couldn't parse message text \"" << text << "\": " << ex.what(); } } m_networking->SetHostPlayerID(host_id); break; } case Message::JOIN_GAME: { if (PlayerID() == Networking::INVALID_PLAYER_ID) { DebugLogger() << "AIClientApp::HandleMessage : Received JOIN_GAME acknowledgement"; try { int player_id; boost::uuids::uuid cookie; // ignore ExtractJoinAckMessageData(msg, player_id, cookie); m_networking->SetPlayerID(player_id); } catch(const boost::bad_lexical_cast& ex) { ErrorLogger() << "AIClientApp::HandleMessage for JOIN_GAME : Couldn't parse message text \"" << msg.Text() << "\": " << ex.what(); } } else { ErrorLogger() << "AIClientApp::HandleMessage : Received erroneous JOIN_GAME acknowledgement when already in a game"; } break; } case Message::GAME_START: { DebugLogger() << "AIClientApp::HandleMessage : Received GAME_START message; starting AI turn..."; bool single_player_game; // ignored bool loaded_game_data; bool ui_data_available; // ignored SaveGameUIData ui_data; // ignored bool state_string_available; // ignored, as save_state_string is sent even if not set by ExtractMessageData std::string save_state_string; m_empire_status.clear(); ExtractGameStartMessageData(msg, single_player_game, m_empire_id, m_current_turn, m_empires, m_universe, GetSpeciesManager(), GetCombatLogManager(), GetSupplyManager(), m_player_info, m_orders, loaded_game_data, ui_data_available, ui_data, state_string_available, save_state_string, m_galaxy_setup_data); DebugLogger() << "Extracted GameStart message for turn: " << m_current_turn << " with empire: " << m_empire_id; GetUniverse().InitializeSystemGraph(m_empire_id); DebugLogger() << "Message::GAME_START loaded_game_data: " << loaded_game_data; if (loaded_game_data) { TraceLogger() << "Message::GAME_START save_state_string: " << save_state_string; m_AI->ResumeLoadedGame(save_state_string); Orders().ApplyOrders(); } else { DebugLogger() << "Message::GAME_START Starting New Game!"; // % Distribution of aggression levels // Aggression : 0 1 2 3 4 5 (0=Beginner, 5=Maniacal) // __ __ __ __ __ __ //Max 0 :100 0 0 0 0 0 //Max 1 : 25 75 0 0 0 0 //Max 2 : 0 25 75 0 0 0 //Max 3 : 0 0 25 75 0 0 //Max 4 : 0 0 0 25 75 0 //Max 5 : 0 0 0 0 25 75 // Optional aggression table, possibly for 0.4.4+? // Aggression : 0 1 2 3 4 5 (0=Beginner, 5=Maniacal) // __ __ __ __ __ __ //Max 0 :100 0 0 0 0 0 //Max 1 : 25 75 0 0 0 0 //Max 2 : 8 17 75 0 0 0 //Max 3 : 0 8 17 75 0 0 //Max 4 : 0 0 8 17 75 0 //Max 5 : 0 0 0 8 17 75 const std::string g_seed = GetGalaxySetupData().m_seed; const std::string emp_name = GetEmpire(m_empire_id)->Name(); unsigned int my_seed = 0; try { // generate consistent my_seed values from galaxy seed & empire name. boost::hash<std::string> string_hash; std::size_t h = string_hash(g_seed); my_seed = 3 * static_cast<unsigned int>(h) * static_cast<unsigned int>(string_hash(emp_name)); DebugLogger() << "Message::GAME_START getting " << emp_name << " AI aggression, RNG Seed: " << my_seed; } catch (...) { DebugLogger() << "Message::GAME_START getting " << emp_name << " AI aggression, could not initialise RNG."; } int rand_num = 0; int this_aggr = m_max_aggression; if (this_aggr > 0 && my_seed > 0) { Seed(my_seed); rand_num = RandSmallInt(0, 99); // if it's in the top 25% then decrease aggression. if (rand_num > 74) this_aggr--; // Leaving the following as commented out code for now. Possibly for 0.4.4+? // in the top 8% ? decrease aggression again, unless it's already as low as it gets. // if (rand_num > 91 && this_aggr > 0) this_aggr--; } DebugLogger() << "Message::GAME_START setting AI aggression as " << this_aggr << " (from rnd " << rand_num << "; max aggression " << m_max_aggression << ")"; m_AI->SetAggression(this_aggr); m_AI->StartNewGame(); } m_AI->GenerateOrders(); break; } case Message::SAVE_GAME_COMPLETE: break; case Message::TURN_UPDATE: { //DebugLogger() << "AIClientApp::HandleMessage : extracting turn update message data"; ExtractTurnUpdateMessageData(msg, m_empire_id, m_current_turn, m_empires, m_universe, GetSpeciesManager(), GetCombatLogManager(), GetSupplyManager(), m_player_info); //DebugLogger() << "AIClientApp::HandleMessage : generating orders"; GetUniverse().InitializeSystemGraph(m_empire_id); m_AI->GenerateOrders(); //DebugLogger() << "AIClientApp::HandleMessage : done handling turn update message"; break; } case Message::TURN_PARTIAL_UPDATE: ExtractTurnPartialUpdateMessageData(msg, m_empire_id, m_universe); break; case Message::TURN_PROGRESS: { Message::TurnProgressPhase phase_id; ExtractTurnProgressMessageData(msg, phase_id); ClientApp::HandleTurnPhaseUpdate(phase_id); break; } case Message::PLAYER_STATUS: break; case Message::END_GAME: { DebugLogger() << "Message::END_GAME : Exiting"; DebugLogger() << "Acknowledge server shutdown message."; Networking().SendMessage(AIEndGameAcknowledgeMessage()); ExitApp(0); break; } case Message::PLAYER_CHAT: { std::string data; int player_id; boost::posix_time::ptime timestamp; ExtractServerPlayerChatMessageData(msg, player_id, timestamp, data); m_AI->HandleChatMessage(player_id, data); break; } case Message::DIPLOMACY: { DiplomaticMessage diplo_message; ExtractDiplomacyMessageData(msg, diplo_message); m_AI->HandleDiplomaticMessage(diplo_message); break; } case Message::DIPLOMATIC_STATUS: { DiplomaticStatusUpdateInfo diplo_update; ExtractDiplomaticStatusMessageData(msg, diplo_update); m_AI->HandleDiplomaticStatusUpdate(diplo_update); break; } case Message::LOGGER_CONFIG: { std::set<std::tuple<std::string, std::string, LogLevel>> options; ExtractLoggerConfigMessageData(msg, options); SetLoggerThresholds(options); break; } case Message::CHECKSUM: { TraceLogger() << "(AIClientApp) CheckSum."; VerifyCheckSum(msg); break; } default: { ErrorLogger() << "AIClientApp::HandleMessage : Received unknown Message type code " << msg.Type(); break; } } //DebugLogger() << "AIClientApp::HandleMessage done"; }
int cmdUname( ClientData client_data, Tcl_Interp *interp, int argc, CONST84 char *argv[]) { int length; #ifdef PHOSTNAME #ifndef HAVE_GETHOSTNAME FILE* hname; #endif #endif #if WITH_DEBUGGING_CALLBACK ErrorLogger( NO_ERR_START, LOC, _proc_cmdUname, NULL); #endif /** ** Parameter check. One parameter should be given providing a selector ** do differ between: **/ if( argc != 2) { if( OK != ErrorLogger( ERR_USAGE, LOC, argv[0], "member", NULL)) return( TCL_ERROR); /** -------- EXIT (FAILURE) -------> **/ } #ifdef HAVE_UNAME /** ** Proceed the system call **/ if( !namestruct_init && uname( &namestruct) < 0) { if( OK != ErrorLogger( ERR_UNAME, LOC, NULL)) return( TCL_ERROR); /** -------- EXIT (FAILURE) -------> **/ } #else /* not HAVE_UNAME */ /** ** If we do not have the uname system call, fixed values defined ** at compile time will be returned. The only differenc is the ** nodename, which may be seeked for using 'gethostname' or the ** PHOSTNAME file. **/ #ifdef HAVE_GETHOSTNAME if( -1 == gethostname( namestruct.nodename, NAMELEN)) if( OK != ErrorLogger( ERR_GETHOSTNAME, LOC, NULL)) return( TCL_ERROR); /** -------- EXIT (FAILURE) -------> **/ #else /* not HAVE_GETHOSTNAME */ #ifdef PHOSTNAME if( NULL == (hname = popen( PHOSTNAME, "r"))) { if( OK != ErrorLogger( ERR_POPEN, LOC, PHOSTNAME, "reading", NULL)) return( TCL_ERROR); /** -------- EXIT (FAILURE) -------> **/ } fgets( namestruct.nodename, NAMELEN, hname); namestruct.nodename[ strlen( namestruct.nodename)-1] = '\0'; if( -1 == pclose( hname)) if( OK != ErrorLogger( ERR_PCLOSE, LOC, PHOSTNAME, NULL)) return( TCL_ERROR); /** -------- EXIT (FAILURE) -------> **/ #endif /* not PHOSTNAME */ #endif /* not HAVE_GETHOSTNAME */ #endif /* not HAVE_UNAME */ /** ** Set up the domain name **/ #ifdef HAVE_GETDOMAINNAME if( !namestruct_init) if( -1 == getdomainname( domain, DOMAINLEN)) if( OK != ErrorLogger( ERR_GETDOMAINNAME, LOC, NULL)) return( TCL_ERROR); /** -------- EXIT (FAILURE) -------> **/ #endif /** ** Now the name structure surely IS initialized **/ namestruct_init = 1; /** ** Return the selected value **/ length = strlen( argv[1]); if( !strncmp( argv[1], "sysname", length)) { Tcl_SetResult( interp, namestruct.sysname, TCL_VOLATILE); } else if( !strncmp( argv[1], "nodename", length)) { Tcl_SetResult( interp, namestruct.nodename, TCL_VOLATILE); } else if( !strncmp( argv[1], "release", length)) { Tcl_SetResult( interp, namestruct.release, TCL_VOLATILE); } else if( !strncmp( argv[1], "version", length)) { Tcl_SetResult( interp, namestruct.version, TCL_VOLATILE); } else if( !strncmp( argv[1], "machine", length)) { Tcl_SetResult( interp, namestruct.machine, TCL_VOLATILE); } else if( !strncmp( argv[1], "domain", length)) { Tcl_SetResult( interp, domain, TCL_VOLATILE); } else { if( OK != ErrorLogger( ERR_USAGE, LOC, argv[0], "{sysname|nodename|" "release|version|machine|domain}", NULL)) return( TCL_ERROR); /** -------- EXIT (FAILURE) -------> **/ } #if WITH_DEBUGGING_CALLBACK ErrorLogger( NO_ERR_END, LOC, _proc_cmdUname, NULL); #endif return( TCL_OK); /** -------- EXIT (SUCCESS) -------> **/ } /** End of 'cmdUname' **/
int main(int argc, char* argv[]) { InitDirs(argv[0]); std::vector<std::string> args; for (int i = 0; i < argc; ++i) args.push_back(argv[i]); #else int wmain(int argc, wchar_t* argv[], wchar_t* envp[]) { // copy UTF-16 command line arguments to UTF-8 vector std::vector<std::string> args; for (int i = 0; i < argc; ++i) { std::wstring argi16(argv[i]); std::string argi8; utf8::utf16to8(argi16.begin(), argi16.end(), std::back_inserter(argi8)); args.push_back(argi8); } InitDirs((args.empty() ? "" : *args.begin())); #endif try { GetOptionsDB().AddFlag('h', "help", "Print this help message."); // read config.xml and set options entries from it, if present XMLDoc doc; { boost::filesystem::ifstream ifs(GetConfigPath()); if (ifs) { doc.ReadDoc(ifs); GetOptionsDB().SetFromXML(doc); } try { boost::filesystem::ifstream pifs(GetPersistentConfigPath()); if (pifs) { doc.ReadDoc(pifs); GetOptionsDB().SetFromXML(doc); } } catch (const std::exception&) { ErrorLogger() << "main() unable to read persistent option config file: " << GetPersistentConfigPath() << std::endl; } } GetOptionsDB().SetFromCommandLine(args); if (GetOptionsDB().Get<bool>("help")) { GetOptionsDB().GetUsage(std::cerr); return 0; } parse::init(); ServerApp g_app; g_app(); // Calls ServerApp::Run() to run app (intialization and main process loop) } catch (const std::invalid_argument& e) { ErrorLogger() << "main() caught exception(std::invalid_arg): " << e.what(); std::cerr << "main() caught exception(std::invalid_arg): " << e.what() << std::endl; return 1; } catch (const std::runtime_error& e) { ErrorLogger() << "main() caught exception(std::runtime_error): " << e.what(); std::cerr << "main() caught exception(std::runtime_error): " << e.what() << std::endl; return 1; } catch (const std::exception& e) { ErrorLogger() << "main() caught exception(std::exception): " << e.what(); std::cerr << "main() caught exception(std::exception): " << e.what() << std::endl; return 1; } catch (...) { ErrorLogger() << "main() caught unknown exception."; std::cerr << "main() caught unknown exception." << std::endl; return 1; } return 0; }
static int PerModuleHelp( Tcl_Interp *interp, int argc, char *argv[]) { Tcl_Interp *help_interp; Tcl_DString cmdbuf; int i, result; char modulefile[ MOD_BUFSIZE]; char modulename[ MOD_BUFSIZE]; /** ** Initialize the command buffer **/ Tcl_DStringInit( &cmdbuf); g_flags |= M_HELP; /** ** Handle each passed module file. Create a Tcl interpreter for each ** module file to be handled **/ for(i=0; i<argc; i++) { help_interp = EM_CreateInterp(); if( TCL_OK != (result = Module_Init( help_interp))) { EM_DeleteInterp( help_interp); result = TCL_ERROR; break; } /** ** locate the filename related to the passed module **/ if( Locate_ModuleFile( help_interp, argv[i], modulename, modulefile)) { if( OK != ErrorLogger( ERR_LOCATE, LOC, argv[i], NULL)) { g_retval = 1; continue; } EM_DeleteInterp( help_interp); } /** ** Now print the module specific help ... **/ g_current_module = modulename; fprintf( stderr, "\n----------- %s '%s' %.*s-------\n\n", _("Module Specific Help for"), g_current_module, (int)(20-strlen( g_current_module)), "--------------------"); result = CallModuleProcedure( help_interp, &cmdbuf, modulefile, "ModulesHelp", 1); /** ** If there hasn't been any help ... **/ if( result == TCL_ERROR) fprintf( stderr, "\t*** %s %s ***\n", _("No Module Specific Help for"), g_current_module); /** ** Finally clear up the Tcl interpreter and handle the next module **/ EM_DeleteInterp( help_interp); } /** ** Free the used command buffer and return on success **/ g_flags &= ~M_HELP; Tcl_DStringFree(&cmdbuf); return( TCL_OK); } /** End of 'PerModuleHelp' **/
void ShipDesignOrder::ExecuteImpl() const { ValidateEmpireID(); Universe& universe = GetUniverse(); Empire* empire = GetEmpire(EmpireID()); if (m_delete_design_from_empire) { // player is ordering empire to forget about a particular design if (!empire->ShipDesignKept(m_design_id)) { ErrorLogger() << "Tried to remove a ShipDesign that the empire wasn't remembering"; return; } empire->RemoveShipDesign(m_design_id); } else if (m_create_new_design) { // check if a design with this ID already exists if (universe.GetShipDesign(m_design_id)) { ErrorLogger() << "Tried to create a new ShipDesign with an id of an already-existing ShipDesign"; return; } ShipDesign* new_ship_design = new ShipDesign(m_name, m_description, m_designed_on_turn, EmpireID(), m_hull, m_parts, m_icon, m_3D_model, m_name_desc_in_stringtable, m_is_monster); universe.InsertShipDesignID(new_ship_design, m_design_id); universe.SetEmpireKnowledgeOfShipDesign(m_design_id, EmpireID()); empire->AddShipDesign(m_design_id); } else if (m_update_name_or_description) { // player is ordering empire to rename a design const std::set<int>& empire_known_design_ids = universe.EmpireKnownShipDesignIDs(EmpireID()); std::set<int>::iterator design_it = empire_known_design_ids.find(m_design_id); if (design_it == empire_known_design_ids.end()) { ErrorLogger() << "Tried to rename/redescribe a ShipDesign that this empire hasn't seen"; return; } const ShipDesign* design = GetShipDesign(*design_it); if (!design) { ErrorLogger() << "Tried to rename/redescribe a ShipDesign that doesn't exist (but this empire has seen it)!"; return; } if (design->DesignedByEmpire() != EmpireID()) { ErrorLogger() << "Tried to rename/redescribe a ShipDesign that isn't owned by this empire!"; return; } GetUniverse().RenameShipDesign(m_design_id, m_name, m_description); } else if (m_move_design) { //Move an existing design from its current location to just before the after_design if (!empire->ShipDesignKept(m_design_id)) { ErrorLogger() << "Tried to move a ShipDesign that the empire wasn't remembering"; return; } if (m_design_id == m_design_id_after) return; empire->RemoveShipDesign(m_design_id); empire->AddShipDesign(m_design_id, m_design_id_after); DebugLogger() << "Move Ship Design " << m_design_id << " to before " << m_design_id_after; } else { // player is ordering empire to retain a particular design, so that is can // be used to construct ships by that empire. // TODO: consider removing this order, so that an empire needs to use // espionage or trade to gain access to a ship design made by another // player // check if empire is already remembering the design if (empire->ShipDesignKept(m_design_id)) { ErrorLogger() << "Tried to remember a ShipDesign that was already being remembered"; return; } // check if the empire can see any objects that have this design (thus enabling it to be copied) const std::set<int>& empire_known_design_ids = universe.EmpireKnownShipDesignIDs(EmpireID()); if (empire_known_design_ids.find(m_design_id) != empire_known_design_ids.end()) { empire->AddShipDesign(m_design_id); } else { ErrorLogger() << "Tried to remember a ShipDesign that this empire hasn't seen"; return; } } }
static int _getopt_internal( int argc, char *const *argv, const char *optstring, const struct option *longopts, int *longind, int long_only) { optarg = NULL; #ifdef _MODULES_DEF_H # if WITH_DEBUGGING_INIT ErrorLogger( NO_ERR_START, LOC, _proc_getopt_internal, NULL); # endif #endif /** ** Initialization **/ if( optind == 0) { optstring = _getopt_initialize( optstring); optind = 1; /** Don't scan ARGV[0], the program name. **/ } if( nextchar == NULL || *nextchar == '\0') { /** ** Advance to the next ARGV-element. **/ if( ordering == PERMUTE) { /** ** If we have just processed some options following some non- ** options, exchange them so that the options come first. **/ if( first_nonopt != last_nonopt && last_nonopt != optind) exchange( (char **) argv); else if( last_nonopt != optind) first_nonopt = optind; /** ** Skip any additional non-options and extend the range of ** non-options previously skipped. **/ while( optind < argc && ( argv[optind][0] != '-' || argv[optind][1] == '\0')) optind++; last_nonopt = optind; } /** ** The special ARGV-element `--' means premature end of options. ** Skip it like a null option, then exchange with previous non- ** options ** as if it were an option, then skip everything else ** like a non-option. **/ if( optind != argc && !strcmp( argv[optind], "--")) { optind++; if( first_nonopt != last_nonopt && last_nonopt != optind) exchange((char **) argv); else if( first_nonopt == last_nonopt) first_nonopt = optind; last_nonopt = argc; optind = argc; } /** ** If we have done all the ARGV-elements, stop the scan and back ** over any non-options that we skipped and permuted. **/ if( optind == argc) { /** ** Set the next-arg-index to point at the non-options that we ** previously skipped, so the caller will digest them. **/ if( first_nonopt != last_nonopt) optind = first_nonopt; return( EOF); } /** ** If we have come to a non-option and did not permute it, ** either stop the scan or describe it to the caller and pass it by. **/ if( argv[optind][0] != '-' || argv[optind][1] == '\0') { if( ordering == REQUIRE_ORDER) return EOF; optarg = argv[optind++]; return( 1); } /** ** We have found another option-ARGV-element. ** Skip the initial punctuation. **/ nextchar =( argv[optind] + 1 + ( longopts != NULL && argv[optind][1] == '-')); } /** ** Decode the current option-ARGV-element. **/ /** ** Check whether the ARGV-element is a long option. ** ** If long_only and the ARGV-element has the form "-f", where f is ** a valid short option, don't consider it an abbreviated form of ** a long option that starts with f. Otherwise there would be no ** way to give the -f short option. ** ** On the other hand, if there's a long option "fubar" and ** the ARGV-element is "-fu", do consider that an abbreviation of ** the long option, just like "--fu", and not "-f" with arg "u". ** ** This distinction seems to be the most useful approach. **/ if( longopts != NULL &&( argv[optind][1] == '-' || ( long_only && ( argv[optind][2] || !my_index (optstring, argv[optind][1]))))) { char *nameend; const struct option *p; const struct option *pfound = NULL; int exact = 0; int ambig = 0; int indfound; int option_index; /** ** Skip the remaining characters of the long option upt to its ** names end( End of the option itsself or the '=' sign) **/ for( nameend = nextchar; *nameend && *nameend != '='; nameend++); /** ** Test all long options for either exact match or abbreviated ** matches. **/ for( p = longopts, option_index = 0; p->name; p++, option_index++) { if( !strncmp( p->name, nextchar, nameend - nextchar)) { if( nameend - nextchar == strlen( p->name)) { /** ** Exact match found. **/ pfound = p; indfound = option_index; exact = 1; break; } else if( pfound == NULL) { /** ** First nonexact match found. **/ pfound = p; indfound = option_index; } else /** ** Second or later nonexact match found. **/ ambig = 1; } /** if( !strncmp) **/ } /** for **/ /** ** Print an error message for ambigious abbreviations and exit ** on error **/ if( ambig && !exact) { if( opterr) #ifdef _MODULES_DEF_H ErrorLogger( ERR_OPT_AMBIG, LOC, argv[optind], NULL); #else fprintf( stderr, _("%s: option `%s' is ambiguous\n"), argv[0], argv[optind]); #endif nextchar += strlen( nextchar); optind++; return( '?'); } /** ** Longname found ? **/ if( pfound != NULL) { option_index = indfound; optind++; /** ** *nameend is != NULL if there is a value specified for ** the option: '--option=value' -> *nameend = '=' **/ if( *nameend) { /** ** Don't test has_arg with >, because some C compilers don't ** allow it to be used on enums. **/ if( pfound->has_arg) optarg = nameend + 1; else { if( opterr) /** ** ERROR: --option w/o argument **/ if( argv[optind - 1][1] == '-') #ifdef _MODULES_DEF_H ErrorLogger( ERR_OPT_NOARG, LOC, pfound->name, NULL); #else fprintf( stderr, _("%s: option `--%s' doesn't allow an argument\n"), argv[0], pfound->name); #endif /** ** ERROR: +option or -option w/o argument **/ else { #ifdef _MODULES_DEF_H char buffer[ BUFSIZ]; sprintf( buffer, "%c%s", argv[optind - 1][0], pfound->name); ErrorLogger( ERR_OPT_NOARG, LOC, buffer, NULL); #else fprintf( stderr, _("%s: option `%c%s' doesn't allow an argument\n"), argv[0], argv[optind - 1][0], pfound->name); #endif } nextchar += strlen( nextchar); return( '?'); } /** ** Options with arguments **/ } else if( pfound->has_arg == 1) {
void NewFleetOrder::ExecuteImpl() const { ValidateEmpireID(); if (m_system_id == INVALID_OBJECT_ID) { ErrorLogger() << "Empire attempted to create a new fleet outside a system"; return; } TemporaryPtr<System> system = GetSystem(m_system_id); if (!system) { ErrorLogger() << "Empire attempted to create a new fleet in a nonexistant system"; return; } if (m_fleet_names.empty()) return; if (m_fleet_names.size() != m_fleet_ids.size() || m_fleet_names.size() != m_ship_id_groups.size() || m_fleet_names.size() != m_aggressives.size()) { ErrorLogger() << "NewFleetOrder has inconsistent data container sizes..."; return; } GetUniverse().InhibitUniverseObjectSignals(true); std::vector<TemporaryPtr<Fleet> > created_fleets; created_fleets.reserve(m_fleet_names.size()); // create fleet for each group of ships for (int i = 0; i < static_cast<int>(m_fleet_names.size()); ++i) { const std::string& fleet_name = m_fleet_names[i]; int fleet_id = m_fleet_ids[i]; const std::vector<int>& ship_ids = m_ship_id_groups[i]; bool aggressive = m_aggressives[i]; if (ship_ids.empty()) continue; // nothing to do... // validate specified ships std::vector<TemporaryPtr<Ship> > validated_ships; std::vector<int> validated_ships_ids; for (unsigned int i = 0; i < ship_ids.size(); ++i) { // verify that empire is not trying to take ships from somebody else's fleet TemporaryPtr<Ship> ship = GetShip(ship_ids[i]); if (!ship) { ErrorLogger() << "Empire attempted to create a new fleet with an invalid ship"; continue; } if (!ship->OwnedBy(EmpireID())) { ErrorLogger() << "Empire attempted to create a new fleet with ships from another's fleet."; continue; } if (ship->SystemID() != m_system_id) { ErrorLogger() << "Empire attempted to make a new fleet from ship in the wrong system"; continue; } validated_ships.push_back(ship); validated_ships_ids.push_back(ship->ID()); } if (validated_ships.empty()) continue; // create fleet TemporaryPtr<Fleet> fleet = GetUniverse().CreateFleet(fleet_name, system->X(), system->Y(), EmpireID(), fleet_id); fleet->GetMeter(METER_STEALTH)->SetCurrent(Meter::LARGE_VALUE); fleet->SetAggressive(aggressive); // an ID is provided to ensure consistancy between server and client universes GetUniverse().SetEmpireObjectVisibility(EmpireID(), fleet->ID(), VIS_FULL_VISIBILITY); system->Insert(fleet); // new fleet will get same m_arrival_starlane as fleet of the first ship in the list. TemporaryPtr<Ship> firstShip = validated_ships[0]; TemporaryPtr<Fleet> firstFleet = GetFleet(firstShip->FleetID()); if (firstFleet) fleet->SetArrivalStarlane(firstFleet->ArrivalStarlane()); // remove ships from old fleet(s) and add to new for (std::vector<TemporaryPtr<Ship> >::iterator ship_it = validated_ships.begin(); ship_it != validated_ships.end(); ++ship_it) { TemporaryPtr<Ship> ship = *ship_it; if (TemporaryPtr<Fleet> old_fleet = GetFleet(ship->FleetID())) old_fleet->RemoveShip(ship->ID()); ship->SetFleetID(fleet->ID()); } fleet->AddShips(validated_ships_ids); created_fleets.push_back(fleet); } GetUniverse().InhibitUniverseObjectSignals(false); system->FleetsInsertedSignal(created_fleets); system->StateChangedSignal(); }
bool Planet::Colonize(int empire_id, const std::string& species_name, double population) { const Species* species = 0; // if desired pop > 0, we want a colony, not an outpost, so we need to do some checks if (population > 0.0) { // check if specified species exists and get reference species = GetSpecies(species_name); if (!species) { ErrorLogger() << "Planet::Colonize couldn't get species already on planet with name: " << species_name; return false; } // check if specified species can colonize this planet if (EnvironmentForSpecies(species_name) < PE_HOSTILE) { ErrorLogger() << "Planet::Colonize: can't colonize planet already populated by species " << species_name; return false; } } // reset the planet to unowned/unpopulated if (!OwnedBy(empire_id)) { Reset(); } else { PopCenter::Reset(); for (std::set<int>::const_iterator it = m_buildings.begin(); it != m_buildings.end(); ++it) if (TemporaryPtr<Building> building = GetBuilding(*it)) building->Reset(); m_just_conquered = false; m_is_about_to_be_colonized = false; m_is_about_to_be_invaded = false; m_is_about_to_be_bombarded = false; SetOwner(ALL_EMPIRES); } // if desired pop > 0, we want a colony, not an outpost, so we have to set the colony species if (population > 0.0) SetSpecies(species_name); // find a default focus. use first defined available focus. // AvailableFoci function should return a vector of all names of // available foci. std::vector<std::string> available_foci = AvailableFoci(); if (species && !available_foci.empty()) { bool found_preference = false; for (std::vector<std::string>::const_iterator it = available_foci.begin(); it != available_foci.end(); ++it) { if (!it->empty() && *it == species->PreferredFocus()) { SetFocus(*it); found_preference = true; break; } } if (!found_preference) SetFocus(*available_foci.begin()); } else { DebugLogger() << "Planet::Colonize unable to find a focus to set for species " << species_name; } // set colony population GetMeter(METER_POPULATION)->SetCurrent(population); GetMeter(METER_TARGET_POPULATION)->SetCurrent(population); BackPropagateMeters(); // set specified empire as owner SetOwner(empire_id); // if there are buildings on the planet, set the specified empire as their owner too std::vector<TemporaryPtr<Building> > buildings = Objects().FindObjects<Building>(BuildingIDs()); for (std::vector<TemporaryPtr<Building> >::iterator building_it = buildings.begin(); building_it != buildings.end(); ++building_it) { (*building_it)->SetOwner(empire_id); } return true; }
void FleetMoveOrder::ExecuteImpl() const { ValidateEmpireID(); TemporaryPtr<Fleet> fleet = GetFleet(FleetID()); if (!fleet) { ErrorLogger() << "Empire with id " << EmpireID() << " ordered fleet with id " << FleetID() << " to move, but no such fleet exists"; return; } TemporaryPtr<const System> destination_system = GetEmpireKnownSystem(DestinationSystemID(), EmpireID()); if (!destination_system) { ErrorLogger() << "Empire with id " << EmpireID() << " ordered fleet to move to system with id " << DestinationSystemID() << " but no such system is known to that empire"; return; } // reject empty routes if (m_route.empty()) { ErrorLogger() << "Empire with id " << EmpireID() << " ordered fleet to move on empty route"; return; } // verify that empire specified in order owns specified fleet if (!fleet->OwnedBy(EmpireID()) ) { ErrorLogger() << "Empire with id " << EmpireID() << " order to move but does not own fleet with id " << FleetID(); return; } // verify fleet route first system int fleet_sys_id = fleet->SystemID(); if (!m_append || fleet->TravelRoute().empty()) { if (fleet_sys_id != INVALID_OBJECT_ID) { // fleet is in a system. Its move path should also start from that system. if (fleet_sys_id != m_start_system) { ErrorLogger() << "Empire with id " << EmpireID() << " ordered a fleet to move from a system with id " << m_start_system << " that it is not at. Fleet is located at system with id " << fleet_sys_id; return; } } else { // fleet is not in a system. Its move path should start from the next system it is moving to. int next_system = fleet->NextSystemID(); if (next_system != m_start_system) { ErrorLogger() << "Empire with id " << EmpireID() << " ordered a fleet to move starting from a system with id " << m_start_system << ", but the fleet's next destination is system with id " << next_system; return; } } } else { // We should append and there is something to append to int last_system = fleet->TravelRoute().back(); if (last_system != m_start_system) { ErrorLogger() << "Empire with id " << EmpireID() << " ordered a fleet to continue from system with id " << m_start_system << ", but the fleet's current route won't lead there, it leads to system " << last_system; return; } } // convert list of ids to list of System std::list<int> route_list; if(m_append && !fleet->TravelRoute().empty()){ route_list = fleet->TravelRoute(); route_list.erase(--route_list.end());// Remove the last one since it is the first one of the other } std::copy(m_route.begin(), m_route.end(), std::back_inserter(route_list)); // validate route. Only allow travel between systems connected in series by starlanes known to this fleet's owner. // check destination validity: disallow movement that's out of range std::pair<int, int> eta = fleet->ETA(fleet->MovePath(route_list)); if (eta.first == Fleet::ETA_NEVER || eta.first == Fleet::ETA_OUT_OF_RANGE) { DebugLogger() << "FleetMoveOrder::ExecuteImpl rejected out of range move order"; return; } std::string waypoints; for (std::list<int>::iterator it = route_list.begin(); it != route_list.end(); ++it) { waypoints += std::string(" ") + boost::lexical_cast<std::string>(*it); } DebugLogger() << "FleetMoveOrder::ExecuteImpl Setting route of fleet " << fleet->ID() << " to " << waypoints; fleet->SetRoute(route_list); }
bool ShipDesign::ProductionLocation(int empire_id, int location_id) const { TemporaryPtr<const UniverseObject> location = GetUniverseObject(location_id); if (!location) return false; // currently ships can only be built at planets, and by species that are // not planetbound TemporaryPtr<const Planet> planet = boost::dynamic_pointer_cast<const Planet>(location); if (!planet) return false; const std::string& species_name = planet->SpeciesName(); if (species_name.empty()) return false; const Species* species = GetSpecies(species_name); if (!species) return false; if (!species->CanProduceShips()) return false; // also, species that can't colonize can't produce colony ships if (this->CanColonize() && !species->CanColonize()) return false; Empire* empire = GetEmpire(empire_id); if (!empire) { DebugLogger() << "ShipDesign::ProductionLocation: Unable to get pointer to empire " << empire_id; return false; } // get a source object, which is owned by the empire with the passed-in // empire id. this is used in conditions to reference which empire is // doing the producing. Ideally this will be the capital, but any object // owned by the empire will work. TemporaryPtr<const UniverseObject> source = SourceForEmpire(empire_id); // if this empire doesn't own ANYTHING, then how is it producing anyway? if (!source) return false; // apply hull location conditions to potential location const HullType* hull = GetHull(); if (!hull) { ErrorLogger() << "ShipDesign::ProductionLocation ShipDesign couldn't get its own hull with name " << m_hull; return false; } if (!hull->Location()->Eval(ScriptingContext(source), location)) return false; // apply external and internal parts' location conditions to potential location for (std::vector<std::string>::const_iterator part_it = m_parts.begin(); part_it != m_parts.end(); ++part_it) { std::string part_name = *part_it; if (part_name.empty()) continue; // empty slots don't limit build location const PartType* part = GetPartType(part_name); if (!part) { ErrorLogger() << "ShipDesign::ProductionLocation ShipDesign couldn't get part with name " << part_name; return false; } if (!part->Location()->Eval(ScriptingContext(source), location)) return false; } // location matched all hull and part conditions, so is a valid build location return true; }
void FleetTransferOrder::ExecuteImpl() const { ValidateEmpireID(); // look up the destination fleet TemporaryPtr<Fleet> target_fleet = GetFleet(DestinationFleet()); if (!target_fleet) { ErrorLogger() << "Empire attempted to move ships to a nonexistant fleet"; return; } // check that destination fleet is owned by empire if (!target_fleet->OwnedBy(EmpireID())) { ErrorLogger() << "Empire attempted to move ships to a fleet it does not own"; return; } // verify that fleet is in a system if (target_fleet->SystemID() == INVALID_OBJECT_ID) { ErrorLogger() << "Empire attempted to transfer ships to/from fleet(s) not in a system"; return; } // check that all ships are in the same system std::vector<TemporaryPtr<Ship> > ships = Objects().FindObjects<Ship>(m_add_ships); std::vector<TemporaryPtr<Ship> > validated_ships; validated_ships.reserve(m_add_ships.size()); std::vector<int> validated_ship_ids; validated_ship_ids.reserve(m_add_ships.size()); for (std::vector<TemporaryPtr<Ship> >::const_iterator it = ships.begin(); it != ships.end(); ++it) { TemporaryPtr<Ship> ship = *it; if (!ship->OwnedBy(EmpireID())) continue; if (ship->SystemID() != target_fleet->SystemID()) continue; if (ship->FleetID() == target_fleet->ID()) continue; validated_ships.push_back(ship); validated_ship_ids.push_back(ship->ID()); } if (validated_ships.empty()) return; GetUniverse().InhibitUniverseObjectSignals(true); // remove from old fleet(s) std::set<TemporaryPtr<Fleet> > modified_fleets; for (std::vector<TemporaryPtr<Ship> >::iterator it = validated_ships.begin(); it != validated_ships.end(); ++it) { TemporaryPtr<Ship> ship = *it; if (TemporaryPtr<Fleet> source_fleet = GetFleet(ship->FleetID())) { source_fleet->RemoveShip(ship->ID()); modified_fleets.insert(source_fleet); } ship->SetFleetID(target_fleet->ID()); } // add to new fleet target_fleet->AddShips(validated_ship_ids); GetUniverse().InhibitUniverseObjectSignals(false); // signal change to fleet states modified_fleets.insert(target_fleet); for (std::set<TemporaryPtr<Fleet> >::iterator it = modified_fleets.begin(); it != modified_fleets.end(); ++it) { TemporaryPtr<Fleet> modified_fleet = *it; if (!modified_fleet->Empty()) modified_fleet->StateChangedSignal(); // if modified fleet is empty, it should be immently destroyed, so that updating it now is redundant } }
int cmdSetPath(ClientData client_data, Tcl_Interp *interp, int argc, CONST84 char *argv[]) { Tcl_RegExp chkexpPtr; /** Regular expression for * marker checking **/ char *oldpath, /** Old value of 'var' **/ *newpath, /** New value of 'var' **/ *sw_marker = APP_SW_MARKER, /** arbitrary default **/ *startp = NULL, *endp = NULL, /** regexp match endpts **/ *qualifiedpath, /** List of dirs which * are NOT already in path **/ **pathlist; /** List of dirs **/ const char *delim = _colon; /** path delimiter **/ int append = 1, /** append or prepend **/ numpaths, /** number of dirs in path **/ qpathlen, /** qualifiedpath length **/ arg1 = 1, /** arg start **/ x; /** loop index **/ Tcl_Obj *np_obj; /** new path Tcl Obj **/ #if WITH_DEBUGGING_CALLBACK ErrorLogger(NO_ERR_START, LOC, _proc_cmdSetPath, NULL); #endif /* WITH_DEBUGGING_CALLBACK */ /** ** Whatis mode? **/ if (g_flags & (M_WHATIS | M_HELP)) { goto success0; } /** ** Check arguments. There should be at least 3 args: ** argv[0] - prepend/append ** ... ** argv[n-1]- varname ** argv[n] - value **/ if(argc < 3) { if (OK != ErrorLogger(ERR_USAGE, LOC, argv[0], " path-variable directory", NULL)) { goto unwind0; } } /** ** Should this guy be removed from the variable(?)... If yes, then do so! **/ if (g_flags & M_REMOVE) { return (cmdRemovePath(client_data, interp, argc, argv)); /** ----> **/ } /** ** prepend or append. The default is append. **/ if (!(append = !!strncmp(argv[0], "pre", 3))) { sw_marker = PRE_SW_MARKER; } /** ** Non-persist mode? **/ if (g_flags & M_NONPERSIST) { return (TCL_OK); } /** ** Display only ... ok, let us do so! **/ if (g_flags & M_DISPLAY) { fprintf(stderr, "%s\t ", argv[0]); while (--argc) { fprintf( stderr, "%s ", *++argv); } fprintf(stderr, "\n"); goto success0; } /** ** Check for the delimiter option **/ if (*(argv[arg1]) == '-') { if (!strcmp(argv[arg1], "-d")) { delim = argv[(arg1 + 1)]; arg1 += 2; } else if (!strcmp(argv[arg1], "--delim")) { delim = argv[(arg1 + 1)]; arg1 += 2; } else if (!strncmp(argv[arg1], "--delim=", 8)) { delim = (argv[arg1] + 8); arg1++; } } /** ** Get the old value of the variable. MANPATH defaults to a configure ** generated value. ** Put a \ in front of each '.' and '+'. ** (this is an intentional memory leak) **/ oldpath = EMGetEnv(interp, argv[arg1]); _TCLCHK(interp) if(!oldpath || !*oldpath) { null_free((void *) &oldpath); oldpath = ((!strcmp(argv[arg1], "MANPATH")) ? stringer(NULL, 0, DEFAULTMANPATH, NULL) : stringer(NULL, 0, "", NULL)); } /** ** Split the new path into its components directories so each ** directory can be checked to see whether it is already in the ** existing path. **/ if (!(pathlist = SplitIntoList(interp, (char *)argv[(arg1 + 1)], &numpaths, delim))) { goto unwind0; } /** ** Some space for the list of paths which ** are not already in the existing path. **/ if((char *) NULL == (qualifiedpath = stringer(NULL, 0, argv[(arg1 + 1)], delim, NULL))) { if (OK != ErrorLogger(ERR_STRING, LOC, NULL)) { goto unwind1; } } qpathlen = (int)(strlen(qualifiedpath) + 1); *qualifiedpath = '\0'; /** make sure null for later **/ for ((x = 0); (x < numpaths); x++) { regex_quote(pathlist[x], buffer, PATH_BUFLEN); /** ** Check to see if path is already in this path variable. ** It could be at the ** beginning ... ^path: ** middle ... :path: ** end ... :path$ ** only one ... ^path$ **/ if ((char *)NULL == (newpath = stringer(NULL, 0, "(^", buffer, delim, ")|(", delim, buffer, delim, ")|(", delim, buffer, "$)|(^", buffer, "$)", NULL))) { if (OK != ErrorLogger( ERR_STRING, LOC, NULL)) { goto unwind2; } } np_obj = Tcl_NewStringObj(newpath, (int)strlen(newpath)); chkexpPtr = Tcl_GetRegExpFromObj(interp, np_obj, TCL_REG_ADVANCED); _TCLCHK(interp) null_free((void *)&newpath); /** ** If the directory is not already in the path, ** add it to the qualified path. **/ if (!Tcl_RegExpExec(interp, chkexpPtr, oldpath, oldpath)) { if (!stringer((qualifiedpath + strlen(qualifiedpath)), (int)((unsigned long)qpathlen - strlen(qualifiedpath)), pathlist[x], delim, NULL)) { if (OK != ErrorLogger(ERR_STRING, LOC, NULL)) { goto unwind2; } } } } /** End of loop that checks for ** already existent path **/ /** ** If all of the directories in the new path already exist, ** exit doing nothing. **/ if (! *qualifiedpath) { goto success1; } /* remove trailing delimiter */ qualifiedpath[(strlen(qualifiedpath) - 1)] = '\0'; /** ** Some space for our newly created path. ** We size at the oldpath plus the addition. **/ if (!(newpath = stringer(NULL, (int)(strlen(oldpath) + strlen(qualifiedpath) + 2), NULL))) { if (OK != ErrorLogger(ERR_STRING, LOC, NULL)) { goto unwind2; } } *newpath = '\0'; /** ** Easy job to do, if the old path has not been set up so far ... **/ if (!strcmp(oldpath, "")) { strcpy(newpath, qualifiedpath); /** ** Otherwise we have to take care on prepending vs. appending ... ** If there is a append or prepend marker within the variable (see ** modules_def.h) the changes are made according to this markers. Other- ** wise append and prepend will be relative to the strings begin or end. **/ } else { Tcl_Obj *sw_obj = Tcl_NewStringObj(sw_marker, (int)strlen(sw_marker)); Tcl_RegExp markexpPtr = Tcl_GetRegExpFromObj(interp, sw_obj, TCL_REG_ADVANCED); _TCLCHK(interp) strcpy(newpath, oldpath); if (Tcl_RegExpExec(interp, markexpPtr, oldpath, oldpath)) { _TCLCHK(interp) Tcl_RegExpRange(markexpPtr, 0, (CONST84 char **)&startp, (CONST84 char **)&endp); /** ** Append/Prepend marker found **/ if (append) { char ch = *startp; *startp = '\0'; strcpy(newpath, oldpath); /** ** check that newpath has a value before adding delim **/ if ((strlen(newpath) > 0) && (newpath[(strlen(newpath) - 1)] != *delim)) { strcat(newpath, delim); } strcat(newpath, qualifiedpath); if (newpath[strlen(newpath)-1] != *delim) { strcat(newpath, delim); } *startp = ch; strcat(newpath, startp); } else { char ch = *endp; *endp = '\0'; strcpy(newpath, oldpath); if (newpath[strlen(newpath)-1] != *delim) { strcat(newpath, delim); } strcat(newpath, qualifiedpath); *endp = ch; strcat(newpath, endp); } } else { /** ** No marker set **/ if (append) { strcpy(newpath, oldpath); if (newpath[strlen(newpath)-1] != *delim) { strcat(newpath, delim); } strcat(newpath, qualifiedpath); } else { strcpy(newpath, qualifiedpath); if (*oldpath != *delim) { strcat(newpath, delim); } strcat(newpath, oldpath); } /* end "if (append)" */ } /** end "if (marker)" **/ } /** end "if (strcmp)" **/ /** ** Now the new value to be set resides in 'newpath'. Set it up. **/ moduleSetenv(interp, (char *)argv[arg1], newpath, 1); _TCLCHK(interp) #if WITH_DEBUGGING_CALLBACK ErrorLogger(NO_ERR_END, LOC, _proc_cmdSetPath, NULL); #endif /* WITH_DEBUGGING_CALLBACK */ /** ** Free resources **/ null_free((void *)&newpath); success1: null_free((void *)&oldpath); null_free((void *)&qualifiedpath); FreeList(pathlist, numpaths); success0: return (TCL_OK); /** -------- EXIT (SUCCESS) -------> **/ unwind2: null_free((void *)&qualifiedpath); unwind1: FreeList(pathlist, numpaths); unwind0: null_free((void *)&oldpath); return (TCL_ERROR); /** -------- EXIT (FAILURE) -------> **/ } /** End of 'cmdSetPath' **/
void ColonizeOrder::ExecuteImpl() const { ValidateEmpireID(); int empire_id = EmpireID(); TemporaryPtr<Ship> ship = GetShip(m_ship); if (!ship) { ErrorLogger() << "ColonizeOrder::ExecuteImpl couldn't get ship with id " << m_ship; return; } if (!ship->CanColonize()) { // verifies that species exists and can colonize and that ship can colonize ErrorLogger() << "ColonizeOrder::ExecuteImpl got ship that can't colonize"; return; } if (!ship->OwnedBy(empire_id)) { ErrorLogger() << "ColonizeOrder::ExecuteImpl got ship that isn't owned by the order-issuing empire"; return; } float colonist_capacity = ship->ColonyCapacity(); TemporaryPtr<Planet> planet = GetPlanet(m_planet); if (!planet) { ErrorLogger() << "ColonizeOrder::ExecuteImpl couldn't get planet with id " << m_planet; return; } if (planet->CurrentMeterValue(METER_POPULATION) > 0.0f) { ErrorLogger() << "ColonizeOrder::ExecuteImpl given planet that already has population"; return; } if (!planet->Unowned() && planet->Owner() != empire_id) { ErrorLogger() << "ColonizeOrder::ExecuteImpl given planet that owned by another empire"; return; } if (planet->OwnedBy(empire_id) && colonist_capacity == 0.0f) { ErrorLogger() << "ColonizeOrder::ExecuteImpl given planet that is already owned by empire and colony ship with zero capcity"; return; } if (GetUniverse().GetObjectVisibilityByEmpire(m_planet, empire_id) < VIS_PARTIAL_VISIBILITY) { ErrorLogger() << "ColonizeOrder::ExecuteImpl given planet that empire has insufficient visibility of"; return; } if (colonist_capacity > 0.0f && planet->EnvironmentForSpecies(ship->SpeciesName()) < PE_HOSTILE) { ErrorLogger() << "ColonizeOrder::ExecuteImpl nonzero colonist capacity and planet that ship's species can't colonize"; return; } int ship_system_id = ship->SystemID(); if (ship_system_id == INVALID_OBJECT_ID) { ErrorLogger() << "ColonizeOrder::ExecuteImpl given id of ship not in a system"; return; } int planet_system_id = planet->SystemID(); if (ship_system_id != planet_system_id) { ErrorLogger() << "ColonizeOrder::ExecuteImpl given ids of ship and planet not in the same system"; return; } if (planet->IsAboutToBeColonized()) { ErrorLogger() << "ColonizeOrder::ExecuteImpl given id planet that is already being colonized"; return; } planet->SetIsAboutToBeColonized(true); ship->SetColonizePlanet(m_planet); if (TemporaryPtr<Fleet> fleet = GetFleet(ship->FleetID())) fleet->StateChangedSignal(); }
static int Remove_Path(Tcl_Interp *interp, char *variable, char *item, char *sw_marker, const char *delim) { char *oldpath, /** current path **/ *olditem; /** item from path **/ int i = 0, /** counter **/ found = 0, /** flag to indicate item was found **/ pcount = 0, /** count of items in path **/ addsep = 0, /** flag to add separator **/ marked = 0, /** flag path contains sw_marker **/ oldpathlen = 0; Tcl_DString _newpath; Tcl_DString *newpath = &_newpath; Tcl_DStringInit(newpath); /** ** Get the current value of the "PATH" environment variable **/ oldpath = (char *)EMGetEnv(interp, variable); if (!oldpath || !*oldpath) { null_free((void *)&oldpath); _TCLCHK(interp); goto success0; /** -------- EXIT (SUCCESS) -------> **/ } /* copy oldpath to not mess with the TCL value of env(PATH) */ if (!(oldpath = stringer(NULL,0, oldpath, NULL))) { if (OK != ErrorLogger(ERR_STRING, LOC, NULL)) { goto unwind0; } } /* get length of oldpath before it gets modified by xstrtok */ oldpathlen = (int)strlen(oldpath); /* determine if sw_marker is in the path */ olditem = xstrtok(oldpath, delim); while (olditem) { if (!strcmp(olditem, sw_marker)) { marked = 1; } pcount++; olditem = xstrtok(NULL, delim); } /** pointer arithmetic on oldpath ** if olditem starts at terminating null string of oldpath, ** it means the last character in oldpath was ":", meaning ** the last element was the empty string. use <= to catch ** this case and process the last empty element */ for (olditem = oldpath; olditem <= oldpath + oldpathlen; olditem += strlen(olditem) + 1) { if (strcmp(olditem, item)) { /* not the droids we're looking for */ if (Tcl_DStringLength(newpath)) { if (!Tcl_DStringAppend(newpath, delim, 1)) if (OK != ErrorLogger(ERR_STRING, LOC, NULL)) goto unwind1; } if (!Tcl_DStringAppend(newpath, olditem, -1)) if (OK != ErrorLogger(ERR_STRING, LOC, NULL)) goto unwind1; } else { /* bingo! Don't add it to new path */ found++; if ((g_flags & M_SWSTATE1) && !marked) { /** ** In state1, we're actually replacing old paths with ** the markers for future appends and prepends. ** ** We only want to do this once to mark the location ** the module was formed around. **/ marked = 1; if (Tcl_DStringLength(newpath)) { if (!Tcl_DStringAppend (newpath, delim, 1)) if (OK != ErrorLogger(ERR_STRING, LOC, NULL)) goto unwind1; } if (!Tcl_DStringAppend(newpath, sw_marker, -1)) if (OK != ErrorLogger(ERR_STRING, LOC, NULL)) goto unwind1; } } } if (!found) { goto success1; } if (Tcl_DStringLength(newpath)) { /** ** Cache the set. Clear the variable from the unset table just ** in case it was previously unset. **/ store_hash_value(setenvHashTable, variable, Tcl_DStringValue(newpath)); clear_hash_value(unsetenvHashTable, variable); /** ** Store the new PATH value into the environment. **/ (void) EMSetEnv( interp, variable, Tcl_DStringValue(newpath)); _TCLCHK(interp); } else { /** ** In this case, I should go ahead and unset the variable ** from the environment because I'm removing the very last ** path. ** ** First I'm going to clear the variable from the ** setenvHashTable just in case its already been altered ** and had a significant value at the time. It's very ** possible that I'm removing the only two or three paths ** from this variable. If that's the case, then all the ** earlier paths were marked for output in this hashTable. ** ** Secondly, I actually mark the the environment variable ** to be unset when output. **/ clear_hash_value(setenvHashTable, variable); moduleUnsetenv(interp, variable); /** ** moduleUnsetenv doesn't unset the variable in the Tcl ** space because the $env variable might need to be ** used again in the modulefile for locating other ** paths. BUT, since this was a path-type environment ** variable, the user is expecting this to be empty ** after removing the only remaining path. So, I set ** the variable empty here. **/ (void) EMSetEnv( interp, variable, ""); _TCLCHK(interp); } /** ** Free what has been used and return on success **/ success1: null_free((void *)&oldpath); success0: Tcl_DStringFree(newpath); return (TCL_OK); /** -------- EXIT (SUCCESS) -------> **/ unwind1: null_free((void *)&oldpath); unwind0: Tcl_DStringFree(newpath); return (TCL_ERROR); /** -------- EXIT (FAILURE) -------> **/ } /** End of 'Remove_Path' **/
void InvadeOrder::ExecuteImpl() const { ValidateEmpireID(); int empire_id = EmpireID(); TemporaryPtr<Ship> ship = GetShip(m_ship); if (!ship) { ErrorLogger() << "InvadeOrder::ExecuteImpl couldn't get ship with id " << m_ship; return; } if (!ship->HasTroops()) { ErrorLogger() << "InvadeOrder::ExecuteImpl got ship that can't invade"; return; } if (!ship->OwnedBy(empire_id)) { ErrorLogger() << "InvadeOrder::ExecuteImpl got ship that isn't owned by the order-issuing empire"; return; } TemporaryPtr<Planet> planet = GetPlanet(m_planet); if (!planet) { ErrorLogger() << "InvadeOrder::ExecuteImpl couldn't get planet with id " << m_planet; return; } if (planet->Unowned() && planet->CurrentMeterValue(METER_POPULATION) == 0.0) { ErrorLogger() << "InvadeOrder::ExecuteImpl given unpopulated planet"; return; } if (planet->CurrentMeterValue(METER_SHIELD) > 0.0) { ErrorLogger() << "InvadeOrder::ExecuteImpl given planet with shield > 0"; return; } if (planet->OwnedBy(empire_id)) { ErrorLogger() << "InvadeOrder::ExecuteImpl given planet that is already owned by the order-issuing empire"; return; } if (!planet->Unowned() && Empires().GetDiplomaticStatus(planet->Owner(), empire_id) != DIPLO_WAR) { ErrorLogger() << "InvadeOrder::ExecuteImpl given planet owned by an empire not at war with order-issuing empire"; return; } if (GetUniverse().GetObjectVisibilityByEmpire(m_planet, empire_id) < VIS_BASIC_VISIBILITY) { ErrorLogger() << "InvadeOrder::ExecuteImpl given planet that empire reportedly has insufficient visibility of, but will be allowed to proceed pending investigation"; //return; } int ship_system_id = ship->SystemID(); if (ship_system_id == INVALID_OBJECT_ID) { ErrorLogger() << "InvadeOrder::ExecuteImpl given id of ship not in a system"; return; } int planet_system_id = planet->SystemID(); if (ship_system_id != planet_system_id) { ErrorLogger() << "InvadeOrder::ExecuteImpl given ids of ship and planet not in the same system"; return; } // note: multiple ships, from same or different empires, can invade the same planet on the same turn DebugLogger() << "InvadeOrder::ExecuteImpl set for ship " << m_ship << " " << ship->Name() << " to invade planet " << m_planet << " " << planet->Name(); planet->SetIsAboutToBeInvaded(true); ship->SetInvadePlanet(m_planet); if (TemporaryPtr<Fleet> fleet = GetFleet(ship->FleetID())) fleet->StateChangedSignal(); }
int cmdModuleWhatis( ClientData client_data, Tcl_Interp *interp, int argc, CONST84 char *argv[]) { int i = 1; #if WITH_DEBUGGING_CALLBACK ErrorLogger( NO_ERR_START, LOC, _proc_cmdModuleWhatis, NULL); #endif /** ** Help mode **/ if( g_flags & M_HELP) return( TCL_OK); /** -------- EXIT (SUCCESS) -------> **/ /** ** Parameter check **/ if( argc < 2) { if( OK != ErrorLogger( ERR_USAGE, LOC, argv[0], " string", NULL)) return( TCL_ERROR); /** -------- EXIT (FAILURE) -------> **/ } /** ** If we don't have any whatis list buffer until now, we will create one **/ if( !whatis) { whatis_size = WHATIS_FRAG; if((char **) NULL == (whatis = module_malloc(whatis_size * sizeof(char *)))){ ErrorLogger( ERR_ALLOC, LOC, NULL); return( TCL_ERROR); /** -------- EXIT (FAILURE) -------> **/ } } /** ** Display mode? **/ if( g_flags & M_DISPLAY) { fprintf( stderr, "%s\t ", argv[ 0]); for( i=1; i<argc; i++) fprintf( stderr, "%s ", argv[ i]); fprintf( stderr, "\n"); return( TCL_OK); /** ------- EXIT PROCEDURE -------> **/ } /** ** Check if printing is requested **/ if( g_flags & M_WHATIS ) { while( i < argc) { /** ** Conditionally we have to enlarge our buffer **/ while( whatis_ndx + 2 >= whatis_size) { whatis_size += WHATIS_FRAG; if(!(whatis = module_realloc( whatis, whatis_size * sizeof( char *)))) { ErrorLogger( ERR_ALLOC, LOC, NULL); return( TCL_ERROR); /** -------- EXIT (FAILURE) -------> **/ } } /** ** Put the string on the buffer **/ if((char *) NULL == (whatis[ whatis_ndx++] = strdup( argv[ i++]))) { if( OK != ErrorLogger( ERR_ALLOC, LOC, NULL)) return( TCL_ERROR); whatis_ndx--; } } /** while **/ } /** if **/ /** ** Put a trailing terminator on the buffer **/ whatis[ whatis_ndx] = (char *) NULL; #if WITH_DEBUGGING_CALLBACK ErrorLogger( NO_ERR_END, LOC, _proc_cmdModuleWhatis, NULL); #endif return( TCL_OK); } /** End of 'cmdModuleWhatis' **/
void SaveGame(const std::string& filename, const ServerSaveGameData& server_save_game_data, const std::vector<PlayerSaveGameData>& player_save_game_data, const Universe& universe, const EmpireManager& empire_manager, const SpeciesManager& species_manager, const CombatLogManager& combat_log_manager, const GalaxySetupData& galaxy_setup_data, bool multiplayer) { DebugLogger() << "SaveGame:: filename: " << filename; GetUniverse().EncodingEmpire() = ALL_EMPIRES; std::map<int, SaveGameEmpireData> empire_save_game_data = CompileSaveGameEmpireData(empire_manager); SaveGamePreviewData save_preview_data; CompileSaveGamePreviewData(server_save_game_data, player_save_game_data, empire_save_game_data, save_preview_data); try { fs::path path = FilenameToPath(filename); // A relative path should be relative to the save directory. if (path.is_relative()) { path = GetSaveDir()/path; DebugLogger() << "Made save path relative to save dir. Is now: " << path; } if (multiplayer) { // Make sure the path points into our save directory if (!IsInside(path, GetSaveDir())){ path = GetSaveDir() / path.filename(); } } fs::ofstream ofs(path, std::ios_base::binary); if (!ofs) throw std::runtime_error(UNABLE_TO_OPEN_FILE); if (GetOptionsDB().Get<bool>("binary-serialization")) { freeorion_bin_oarchive oa(ofs); oa << BOOST_SERIALIZATION_NVP(save_preview_data); oa << BOOST_SERIALIZATION_NVP(galaxy_setup_data); oa << BOOST_SERIALIZATION_NVP(server_save_game_data); oa << BOOST_SERIALIZATION_NVP(player_save_game_data); oa << BOOST_SERIALIZATION_NVP(empire_save_game_data); oa << BOOST_SERIALIZATION_NVP(empire_manager); oa << BOOST_SERIALIZATION_NVP(species_manager); oa << BOOST_SERIALIZATION_NVP(combat_log_manager); Serialize(oa, universe); } else { freeorion_xml_oarchive oa(ofs); oa << BOOST_SERIALIZATION_NVP(save_preview_data); oa << BOOST_SERIALIZATION_NVP(galaxy_setup_data); oa << BOOST_SERIALIZATION_NVP(server_save_game_data); oa << BOOST_SERIALIZATION_NVP(player_save_game_data); oa << BOOST_SERIALIZATION_NVP(empire_save_game_data); oa << BOOST_SERIALIZATION_NVP(empire_manager); oa << BOOST_SERIALIZATION_NVP(species_manager); oa << BOOST_SERIALIZATION_NVP(combat_log_manager); Serialize(oa, universe); } } catch (const std::exception& e) { ErrorLogger() << UserString("UNABLE_TO_WRITE_SAVE_FILE") << " SaveGame exception: " << ": " << e.what(); throw e; } }