Beispiel #1
0
//////////////////////////////////////////////////
// ResearchWnd                                  //
//////////////////////////////////////////////////
ResearchWnd::ResearchWnd(GG::X w, GG::Y h) :
    GG::Wnd(GG::X0, GG::Y0, w, h, GG::INTERACTIVE | GG::ONTOP),
    m_research_info_panel(0),
    m_queue_lb(0),
    m_tech_tree_wnd(0),
    m_enabled(false)
{
    m_research_info_panel = new ProductionInfoPanel(GG::X(GetOptionsDB().Get<int>("UI.queue-width")), GG::Y(200),
                                                    UserString("RESEARCH_INFO_PANEL_TITLE"),
                                                    UserString("RESEARCH_INFO_RP"),
                                                    OUTER_LINE_THICKNESS, ClientUI::KnownTechFillColor(),
                                                    ClientUI::KnownTechTextAndBorderColor());

    m_queue_lb = new QueueListBox(GG::X(2),
                                  m_research_info_panel->Height(),
                                  m_research_info_panel->Width() - 4,
                                  ClientSize().y - 4 - m_research_info_panel->Height(),
                                  "RESEARCH_QUEUE_ROW",
                                  UserString("RESEARCH_QUEUE_PROMPT"));
    m_queue_lb->SetStyle(GG::LIST_NOSORT | GG::LIST_NOSEL | GG::LIST_USERDELETE);

    GG::Connect(m_queue_lb->QueueItemMovedSignal,       &ResearchWnd::QueueItemMoved,               this);
    GG::Connect(m_queue_lb->LeftClickedSignal,          &ResearchWnd::QueueItemClickedSlot,         this);
    GG::Connect(m_queue_lb->DoubleClickedSignal,        &ResearchWnd::QueueItemDoubleClickedSlot,   this);


    GG::Pt tech_tree_wnd_size = ClientSize() - GG::Pt(m_research_info_panel->Width(), GG::Y0);
    m_tech_tree_wnd = new TechTreeWnd(tech_tree_wnd_size.x, tech_tree_wnd_size.y);

    GG::Connect(m_tech_tree_wnd->AddTechsToQueueSignal, &ResearchWnd::AddTechsToQueueSlot,          this);


    AttachChild(m_research_info_panel);
    AttachChild(m_queue_lb);
    AttachChild(m_tech_tree_wnd);

    SetChildClippingMode(ClipToClient);

    DoLayout();
}
Beispiel #2
0
boost::statechart::result PlayingTurn::react(const SaveGameComplete& msg) {
    TraceLogger(FSM) << "(HumanClientFSM) PlayingTurn.SaveGameComplete";

    std::string save_filename;
    int bytes_written;
    ExtractServerSaveGameCompleteMessageData(msg.m_message, save_filename, bytes_written);

    Client().GetClientUI().GetMessageWnd()->HandleGameStatusUpdate(
        boost::io::str(FlexibleFormat(UserString("SERVER_SAVE_COMPLETE")) % save_filename % bytes_written) + "\n");

    Client().SaveGameCompleted();

    // auto quit save has completed, close the app
    if (Client().GetApp()->GetClientType() == Networking::CLIENT_TYPE_HUMAN_PLAYER
        && Client().AutoTurnsLeft() <= 0
        && GetOptionsDB().Get<bool>("auto-quit"))
    {
        DebugLogger(FSM) << "auto-quit save completed, ending game.";
        Client().ExitApp(0);
    }

    return discard_event();
}
Beispiel #3
0
Encyclopedia::Encyclopedia() :
    articles()
{
    try {
        parse::encyclopedia_articles(*this);
    } catch (const std::exception& e) {
        ErrorLogger() << "Failed parsing encyclopedia articles: error: " << e.what();
        throw e;
    }

    if (GetOptionsDB().Get<bool>("verbose-logging")) {
        DebugLogger() << "(Category) Encyclopedia Articles:";
        for (std::map<std::string, std::vector<EncyclopediaArticle> >::const_iterator
             category_it = articles.begin(); category_it != articles.end(); ++category_it)
        {
            const std::string& category = category_it->first;
            const std::vector<EncyclopediaArticle>& article_vec = category_it->second;
            for (std::vector<EncyclopediaArticle>::const_iterator article_it = article_vec.begin();
                 article_it != article_vec.end(); ++article_it)
            { DebugLogger() << "(" << UserString(category) << ") : " << UserString(article_it->name); }
        }
    }
}
Beispiel #4
0
//////////////////////////////////////////////////
// ProductionWnd                                //
//////////////////////////////////////////////////
ProductionWnd::ProductionWnd(GG::X w, GG::Y h) :
    GG::Wnd(GG::X0, GG::Y0, w, h, GG::INTERACTIVE | GG::ONTOP),
    m_production_info_panel(0),
    m_queue_wnd(0),
    m_build_designator_wnd(0),
    m_order_issuing_enabled(false),
    m_empire_shown_id(ALL_EMPIRES)
{
    //DebugLogger() << "ProductionWindow:  app-width: "<< GetOptionsDB().Get<int>("app-width")
    //              << " ; windowed width: " << GetOptionsDB().Get<int>("app-width-windowed");

    GG::X queue_width(GetOptionsDB().Get<int>("UI.queue-width"));
    GG::Y info_height(ClientUI::Pts()*8);

    m_production_info_panel = new ProductionInfoPanel(UserString("PRODUCTION_WND_TITLE"), UserString("PRODUCTION_INFO_PP"),
                                                      GG::X0, GG::Y0, queue_width, info_height,
                                                      "production.InfoPanel");
    m_queue_wnd = new ProductionQueueWnd(GG::X0, info_height, queue_width, ClientSize().y - info_height);
    m_build_designator_wnd = new BuildDesignatorWnd(ClientSize().x, ClientSize().y);

    SetChildClippingMode(ClipToClient);

    GG::Connect(m_build_designator_wnd->AddBuildToQueueSignal,              &ProductionWnd::AddBuildToQueueSlot, this);
    GG::Connect(m_build_designator_wnd->BuildQuantityChangedSignal,         &ProductionWnd::ChangeBuildQuantitySlot, this);
    GG::Connect(m_build_designator_wnd->SystemSelectedSignal,               SystemSelectedSignal);
    GG::Connect(m_queue_wnd->GetQueueListBox()->QueueItemMovedSignal,       &ProductionWnd::QueueItemMoved, this);
    GG::Connect(m_queue_wnd->GetQueueListBox()->QueueItemDeletedSignal,     &ProductionWnd::DeleteQueueItem, this);
    GG::Connect(m_queue_wnd->GetQueueListBox()->LeftClickedSignal,          &ProductionWnd::QueueItemClickedSlot, this);
    GG::Connect(m_queue_wnd->GetQueueListBox()->DoubleClickedSignal,        &ProductionWnd::QueueItemDoubleClickedSlot, this);
    GG::Connect(m_queue_wnd->GetQueueListBox()->QueueItemRalliedToSignal,   &ProductionWnd::QueueItemRallied, this);
    GG::Connect(m_queue_wnd->GetQueueListBox()->ShowPediaSignal,            &ProductionWnd::ShowPedia, this);
    GG::Connect(m_queue_wnd->GetQueueListBox()->QueueItemPausedSignal,      &ProductionWnd::QueueItemPaused, this);

    AttachChild(m_production_info_panel);
    AttachChild(m_queue_wnd);
    AttachChild(m_build_designator_wnd);
}
Beispiel #5
0
InGameMenu::InGameMenu():
    CUIWnd(UserString("GAME_MENU_WINDOW_TITLE"),
           GG::INTERACTIVE | GG::MODAL)
{
    m_save_btn = new CUIButton(UserString("GAME_MENU_SAVE"));
    m_load_btn = new CUIButton(UserString("GAME_MENU_LOAD"));
    m_options_btn = new CUIButton(UserString("INTRO_BTN_OPTIONS"));
    m_exit_btn = new CUIButton(UserString("GAME_MENU_RESIGN"));
    m_done_btn = new CUIButton(UserString("DONE"));

    AttachChild(m_save_btn);
    AttachChild(m_load_btn);
    AttachChild(m_options_btn);
    AttachChild(m_exit_btn);
    AttachChild(m_done_btn);

    GG::Connect(m_save_btn->LeftClickedSignal,      &InGameMenu::Save,      this);
    GG::Connect(m_load_btn->LeftClickedSignal,      &InGameMenu::Load,      this);
    GG::Connect(m_options_btn->LeftClickedSignal,   &InGameMenu::Options,   this);
    GG::Connect(m_exit_btn->LeftClickedSignal,      &InGameMenu::Exit,      this);
    GG::Connect(m_done_btn->LeftClickedSignal,      &InGameMenu::Done,      this);

    if (!HumanClientApp::GetApp()->SinglePlayerGame()) {
        // need lobby to load a multiplayer game; menu load of a file is insufficient
        m_load_btn->Disable();
    }

    if (!HumanClientApp::GetApp()->CanSaveNow()) {
        m_save_btn->Disable();
        m_save_btn->SetBrowseModeTime(GetOptionsDB().Get<int>("UI.tooltip-delay"));
        m_save_btn->SetBrowseInfoWnd(boost::shared_ptr<GG::BrowseInfoWnd>(
            new TextBrowseWnd(UserString("BUTTON_DISABLED"), UserString("SAVE_DISABLED_BROWSE_TEXT"), GG::X(400))));
    }

    ResetDefaultPosition();
    DoLayout();
}
Beispiel #6
0
SpeciesManager::SpeciesManager() {
    if (s_instance)
        throw std::runtime_error("Attempted to create more than one SpeciesManager.");
    s_instance = this;

    try {
        parse::species(m_species);
    } catch (const std::exception& e) {
        ErrorLogger() << "Failed parsing species: error: " << e.what();
        throw e;
    }

    if (GetOptionsDB().Get<bool>("verbose-logging")) {
        DebugLogger() << "Species:";
        for (iterator it = begin(); it != end(); ++it) {
            const Species* s = it->second;
            DebugLogger() << " ... " << s->Name() << "  \t" <<
                (s->Playable() ?        "Playable " : "         ") <<
                (s->Native() ?          "Native " : "       ") <<
                (s->CanProduceShips() ? "CanProduceShips " : "                ") <<
                (s->CanColonize() ?     "CanColonize " : "            ");
        }
    }
}
Beispiel #7
0
void HumanClientApp::StartServer() {
    std::string SERVER_CLIENT_EXE = ServerClientExe();
    DebugLogger() << "HumanClientApp::StartServer: " << SERVER_CLIENT_EXE;

#ifdef FREEORION_MACOSX
    // On OSX set environment variable DYLD_LIBRARY_PATH to python framework folder
    // bundled with app, so the dynamic linker uses the bundled python library.
    // Otherwise the dynamic linker will look for a correct python lib in system
    // paths, and if it can't find it, throw an error and terminate!
    // Setting environment variable here, spawned child processes will inherit it.
    setenv("DYLD_LIBRARY_PATH", GetPythonHome().string().c_str(), 1);
#endif

    std::vector<std::string> args;
    std::string ai_config = GetOptionsDB().Get<std::string>("ai-config");
    std::string ai_path = GetOptionsDB().Get<std::string>("ai-path");
    args.push_back("\"" + SERVER_CLIENT_EXE + "\"");
    args.push_back("--resource-dir");
    args.push_back("\"" + GetOptionsDB().Get<std::string>("resource-dir") + "\"");
    args.push_back("--log-level");
    args.push_back(GetOptionsDB().Get<std::string>("log-level"));
    if (GetOptionsDB().Get<bool>("test-3d-combat"))
        args.push_back("--test-3d-combat");
    if (ai_path != GetOptionsDB().GetDefaultValueString("ai-path")) {
        args.push_back("--ai-path");
        args.push_back(ai_path);
        DebugLogger() << "ai-path set to '" << ai_path << "'";
    }
    if (!ai_config.empty()) {
        args.push_back("--ai-config");
        args.push_back(ai_config);
        DebugLogger() << "ai-config set to '" << ai_config << "'";
    } else {
        DebugLogger() << "ai-config not set.";
    }
    m_server_process = Process(SERVER_CLIENT_EXE, args);
}
Beispiel #8
0
HumanClientApp::HumanClientApp(int width, int height, bool calculate_fps, const std::string& name,
                               int x, int y, bool fullscreen, bool fake_mode_change) :
    ClientApp(),
    SDLGUI(width, height, calculate_fps, name, x, y, fullscreen, fake_mode_change),
    m_fsm(0),
    m_single_player_game(true),
    m_game_started(false),
    m_connected(false),
    m_auto_turns(0),
    m_have_window_focus(true)
{
#ifdef ENABLE_CRASH_BACKTRACE
    signal(SIGSEGV, SigHandler);
#endif
#ifdef FREEORION_MACOSX
    SDL_SetHint(SDL_HINT_MAC_CTRL_CLICK_EMULATE_RIGHT_CLICK, "1");
#endif
    m_fsm = new HumanClientFSM(*this);

    const std::string HUMAN_CLIENT_LOG_FILENAME((GetUserDir() / "freeorion.log").string());

    InitLogger(HUMAN_CLIENT_LOG_FILENAME, "Client");

    try {
        DebugLogger() << "GL Version String: " << GetGLVersionString();
    } catch (...) {
        ErrorLogger() << "Unable to get GL Version String?";
    }

    LogDependencyVersions();

    boost::shared_ptr<GG::StyleFactory> style(new CUIStyle());
    SetStyleFactory(style);

    SetMinDragTime(0);

    m_ui = boost::shared_ptr<ClientUI>(new ClientUI());

    if ((GetOptionsDB().Get<bool>("UI.sound.music-enabled")))
        Sound::GetSound().PlayMusic(GetOptionsDB().Get<std::string>("UI.sound.bg-music"), -1);

    Sound::GetSound().SetMusicVolume(GetOptionsDB().Get<int>("UI.sound.music-volume"));
    Sound::GetSound().SetUISoundsVolume(GetOptionsDB().Get<int>("UI.sound.volume"));

    EnableFPS();
    UpdateFPSLimit();
    GG::Connect(GetOptionsDB().OptionChangedSignal("show-fps"), &HumanClientApp::UpdateFPSLimit, this);

    boost::shared_ptr<GG::BrowseInfoWnd> default_browse_info_wnd(
        new GG::TextBoxBrowseInfoWnd(GG::X(400), ClientUI::GetFont(),
                                     GG::Clr(0, 0, 0, 200), ClientUI::WndOuterBorderColor(), ClientUI::TextColor(),
                                     GG::FORMAT_LEFT | GG::FORMAT_WORDBREAK, 1));
    GG::Wnd::SetDefaultBrowseInfoWnd(default_browse_info_wnd);

    boost::shared_ptr<GG::Texture> cursor_texture = m_ui->GetTexture(ClientUI::ArtDir() / "cursors" / "default_cursor.png");
    SetCursor(boost::shared_ptr<GG::TextureCursor>(new GG::TextureCursor(cursor_texture, GG::Pt(GG::X(6), GG::Y(3)))));
    RenderCursor(true);

    EnableKeyPressRepeat(GetOptionsDB().Get<int>("UI.keypress-repeat-delay"),
                         GetOptionsDB().Get<int>("UI.keypress-repeat-interval"));
    EnableMouseButtonDownRepeat(GetOptionsDB().Get<int>("UI.mouse-click-repeat-delay"),
                                GetOptionsDB().Get<int>("UI.mouse-click-repeat-interval"));

    GG::Connect(WindowResizedSignal,    &HumanClientApp::HandleWindowResize,    this);
    GG::Connect(FocusChangedSignal,     &HumanClientApp::HandleFocusChange,     this);
    GG::Connect(WindowMovedSignal,      &HumanClientApp::HandleWindowMove,      this);
    /* TODO: Wire these signals if theyare needed
    GG::Connect(WindowClosingSignal,    &HumanClientApp::HandleWindowClosing,   this);
    GG::Connect(WindowClosedSignal,     &HumanClientApp::HandleWindowClose,     this);
    */

    SetStringtableDependentOptionDefaults();
    SetGLVersionDependentOptionDefaults();

    this->SetMouseLRSwapped(GetOptionsDB().Get<bool>("UI.swap-mouse-lr"));

    std::map<std::string, std::map<int, int> > named_key_maps;
    parse::keymaps(GetResourceDir() / "keymaps.txt", named_key_maps);
    if (GetOptionsDB().Get<bool>("verbose-logging")) {
        DebugLogger() << "Keymaps:";
        for (std::map<std::string, std::map<int, int> >::const_iterator km_it = named_key_maps.begin();
             km_it != named_key_maps.end(); ++km_it)
        {
            DebugLogger() << "Keymap name = \"" << km_it->first << "\"";
            const std::map<int, int>& key_map = km_it->second;
            for (std::map<int, int>::const_iterator keys_it = key_map.begin(); keys_it != key_map.end(); ++keys_it)
                DebugLogger() << "    " << char(keys_it->first) << " : " << char(keys_it->second);
        }
    }
    std::map<std::string, std::map<int, int> >::const_iterator km_it = named_key_maps.find("TEST");
    if (km_it != named_key_maps.end()) {
        const std::map<int, int> int_key_map = km_it->second;
        std::map<GG::Key, GG::Key> key_map;
        for (std::map<int, int>::const_iterator key_int_it = int_key_map.begin();
             key_int_it != int_key_map.end(); ++key_int_it)
        { key_map[GG::Key(key_int_it->first)] = GG::Key(key_int_it->second); }
        this->SetKeyMap(key_map);
    }

    ConnectKeyboardAcceleratorSignals();

    InitAutoTurns(GetOptionsDB().Get<int>("auto-advance-n-turns"));

    if (fake_mode_change && !FramebuffersAvailable()) {
        ErrorLogger() << "Requested fake mode changes, but the framebuffer opengl extension is not available. Ignoring.";
    }
    m_fsm->initiate();
}
 void Set(const std::string& option, bool value) {
     GetOptionsDB().Set(OPTIONS_ROOT + option, value);
     GetOptionsDB().Commit();
 }
 bool Get(const std::string& option) const {
     return GetOptionsDB().Get<bool>(OPTIONS_ROOT + option);
 }
Beispiel #11
0
void FleetButton::PlayFleetButtonOpenSound()
{ Sound::GetSound().PlaySound(GetOptionsDB().Get<std::string>("UI.sound.fleet-button-click"), true); }
Beispiel #12
0
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;
}
Beispiel #13
0
void HumanClientApp::Autosave() {
    // autosave only on appropriate turn numbers, and when enabled for current
    // game type (single vs. multiplayer)
    int autosave_turns = GetOptionsDB().Get<int>("autosave.turns");
    if (autosave_turns < 1)
        return;     // avoid divide by zero
    if (CurrentTurn() % autosave_turns != 0 && CurrentTurn() != 1)
        return;     // turns divisible by autosave_turns, and first turn, have autosaves done
    if (m_single_player_game && !GetOptionsDB().Get<bool>("autosave.single-player"))
        return;
    if (!m_single_player_game && !GetOptionsDB().Get<bool>("autosave.multiplayer"))
        return;

    const char* legal_chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890_-";

    // get empire name, filtered for filename acceptability
    int client_empire_id = EmpireID();
    const Empire* empire = GetEmpire(client_empire_id);
    std::string empire_name;
    if (empire)
        empire_name = empire->Name();
    else
        empire_name = UserString("OBSERVER");
    std::string::size_type first_good_empire_char = empire_name.find_first_of(legal_chars);
    if (first_good_empire_char == std::string::npos) {
        empire_name.clear();
    } else {
        std::string::size_type first_bad_empire_char = empire_name.find_first_not_of(legal_chars, first_good_empire_char);
        empire_name = empire_name.substr(first_good_empire_char, first_bad_empire_char - first_good_empire_char);
    }

    // get player name, also filtered
    std::string player_name;
    if (empire)
        player_name = empire->PlayerName();
    std::string::size_type first_good_player_char = player_name.find_first_of(legal_chars);
    if (first_good_player_char == std::string::npos) {
        player_name.clear();
    } else {
        std::string::size_type first_bad_player_char = player_name.find_first_not_of(legal_chars, first_good_player_char);
        player_name = player_name.substr(first_good_player_char, first_bad_player_char - first_good_player_char);
    }

    // select filename extension
    std::string extension;
    if (m_single_player_game)
        extension = SP_SAVE_FILE_EXTENSION;
    else
        extension = MP_SAVE_FILE_EXTENSION;

    // Add timestamp to autosave generated files
    std::string datetime_str = FilenameTimestamp();

    boost::filesystem::path autosave_dir_path(GetSaveDir() / "auto");

    std::string save_filename = boost::io::str(boost::format("FreeOrion_%s_%s_%04d_%s%s") % player_name % empire_name % CurrentTurn() % datetime_str % extension);
    boost::filesystem::path save_path(autosave_dir_path / save_filename);
    std::string path_string = PathString(save_path);

    try {
        // ensure autosave directory exists
        if (!exists(autosave_dir_path))
            boost::filesystem::create_directories(autosave_dir_path);
    } catch (const std::exception& e) {
        ErrorLogger() << "Autosave unable to check / create autosave directory: " << e.what();
        std::cerr << "Autosave unable to check / create autosave directory: " << e.what() << std::endl;
    }

    // check for and remove excess oldest autosaves
    int max_autosaves = GetOptionsDB().Get<int>("autosave.limit");
    RemoveOldestFiles(max_autosaves, autosave_dir_path);

    // create new save
    DebugLogger() << "Autosaving to: " << path_string;
    try {
        SaveGame(path_string);
    } catch (const std::exception& e) {
        ErrorLogger() << "Autosave failed: " << e.what();
        std::cerr << "Autosave failed: " << e.what() << std::endl;
    }
}
Beispiel #14
0
std::pair<int, int> HumanClientApp::GetWindowWidthHeight() {
    int width(800), height(600);

    bool fullscreen = GetOptionsDB().Get<bool>("fullscreen");
    if (!fullscreen) {
        width = GetOptionsDB().Get<int>("app-width-windowed");
        height = GetOptionsDB().Get<int>("app-height-windowed");
        return std::make_pair(width, height);
    }

    bool reset_fullscreen = GetOptionsDB().Get<bool>("reset-fullscreen-size");
    if (!reset_fullscreen) {
        width = GetOptionsDB().Get<int>("app-width");
        height = GetOptionsDB().Get<int>("app-height");
        return std::make_pair(width, height);
    }

    GetOptionsDB().Set<bool>("reset-fullscreen-size", false);
    GG::Pt default_resolution = GetDefaultResolutionStatic(GetOptionsDB().Get<int>("fullscreen-monitor-id"));
    GetOptionsDB().Set("app-width", Value(default_resolution.x));
    GetOptionsDB().Set("app-height", Value(default_resolution.y));
    GetOptionsDB().Commit();
    return std::make_pair(Value(default_resolution.x), Value(default_resolution.y));
}
Beispiel #15
0
 ~ScopedTimerImpl() {
     if (m_timer.elapsed() * 1000.0 > 1 && ( m_always_output || GetOptionsDB().Get<bool>("verbose-logging")))
         Logger().debugStream() << m_name << " time: " << (m_timer.elapsed() * 1000.0);
 }
Beispiel #16
0
/////////////////////////////////
// IntroScreen
/////////////////////////////////
IntroScreen::IntroScreen() :
    GG::Wnd(GG::X0, GG::Y0, GG::GUI::GetGUI()->AppWidth(), GG::GUI::GetGUI()->AppHeight(), GG::Flags<GG::WndFlag>()),
    m_single_player(0),
    m_quick_start(0),
    m_multi_player(0),
    m_load_game(0),
    m_options(0),
    m_about(0),
    m_credits(0),
    m_exit_game(0),
    m_credits_wnd(0),
    m_menu(0),
    m_splash(0),
    m_logo(0),
    m_version(0)
{
    m_menu = new CUIWnd(UserString("INTRO_WINDOW_TITLE"), GG::X1, GG::Y1,
                        MAIN_MENU_WIDTH, MAIN_MENU_HEIGHT, GG::ONTOP | GG::INTERACTIVE);

    m_splash = new GG::StaticGraphic(GG::X0, GG::Y0, Width(), Height(),
                                     ClientUI::GetTexture(ClientUI::ArtDir() / "splash.png"),
                                     GG::GRAPHIC_FITGRAPHIC, GG::INTERACTIVE);

    m_logo = new GG::StaticGraphic(GG::X0, GG::Y0, Width(), Height() / 10,
                                   ClientUI::GetTexture(ClientUI::ArtDir() / "logo.png"),
                                   GG::GRAPHIC_FITGRAPHIC | GG::GRAPHIC_PROPSCALE);

    m_version = new GG::TextControl(GG::X0, GG::Y0, FreeOrionVersionString(), ClientUI::GetFont(), ClientUI::TextColor());
    m_version->MoveTo(GG::Pt(Width() - m_version->Width(), Height() - m_version->Height()));

    AttachChild(m_splash);
    m_splash->AttachChild(m_logo);
    m_splash->AttachChild(m_menu);
    m_splash->AttachChild(m_version);

    //size calculation consts and variables
    const GG::X MIN_BUTTON_WIDTH(160);
    const GG::Y MIN_BUTTON_HEIGHT(40);
    const GG::X H_BUTTON_MARGIN(16); //horizontal empty space
    const GG::Y V_BUTTON_MARGIN(16); //vertical empty space
    GG::X button_width(0); //width of the buttons
    GG::Y button_height(0); //height of the buttons
    const GG::X H_MAINMENU_MARGIN(40); //horizontal empty space
    const GG::Y V_MAINMENU_MARGIN(40); //vertical empty space
    GG::X mainmenu_width(0);  //width of the mainmenu
    GG::Y mainmenu_height(0); //height of the mainmenu

    //calculate necessary button width
    boost::shared_ptr<GG::Font> font = ClientUI::GetFont();
    button_width = std::max(font->TextExtent(UserString("INTRO_BTN_SINGLE_PLAYER")).x, button_width);
    button_width = std::max(font->TextExtent(UserString("INTRO_BTN_QUICK_START")).x, button_width);
    button_width = std::max(font->TextExtent(UserString("INTRO_BTN_MULTI_PLAYER")).x, button_width);
    button_width = std::max(font->TextExtent(UserString("INTRO_BTN_LOAD_GAME")).x, button_width);
    button_width = std::max(font->TextExtent(UserString("INTRO_BTN_OPTIONS")).x, button_width);
    button_width = std::max(font->TextExtent(UserString("INTRO_BTN_ABOUT")).x, button_width);
    button_width = std::max(font->TextExtent(UserString("INTRO_BTN_CREDITS")).x, button_width);
    button_width = std::max(font->TextExtent(UserString("INTRO_BTN_EXIT")).x, button_width);
    button_width += H_BUTTON_MARGIN;
    button_width = std::max(MIN_BUTTON_WIDTH, button_width);
    //calculate  necessary button height
    button_height = std::max(MIN_BUTTON_HEIGHT, font->Height() + V_BUTTON_MARGIN);
    //culate window width and height
    mainmenu_width  =        button_width  + H_MAINMENU_MARGIN;
    mainmenu_height = 8.75 * button_height + V_MAINMENU_MARGIN; // 8 rows + 0.75 before exit button

    // position menu window
    GG::Pt ul(Width()  * GetOptionsDB().Get<double>("UI.main-menu.x") - mainmenu_width/2,
              Height() * GetOptionsDB().Get<double>("UI.main-menu.y") - mainmenu_height/2);
    GG::Pt lr(Width()  * GetOptionsDB().Get<double>("UI.main-menu.x") + mainmenu_width/2,
              Height() * GetOptionsDB().Get<double>("UI.main-menu.y") + mainmenu_height/2);

    m_menu->SizeMove(ul, lr);

    //create buttons
    GG::Y button_y(12); //relativ buttonlocation
    GG::X button_x(15);
    m_single_player =   new CUIButton(button_x, button_y, button_width, UserString("INTRO_BTN_SINGLE_PLAYER"));
    button_y += button_height;
    m_quick_start =     new CUIButton(button_x, button_y, button_width, UserString("INTRO_BTN_QUICK_START"));
    button_y += button_height;
    m_multi_player =    new CUIButton(button_x, button_y, button_width, UserString("INTRO_BTN_MULTI_PLAYER"));
    button_y += button_height;
    m_load_game =       new CUIButton(button_x, button_y, button_width, UserString("INTRO_BTN_LOAD_GAME"));
    button_y += button_height;
    m_options =         new CUIButton(button_x, button_y, button_width, UserString("INTRO_BTN_OPTIONS"));
    button_y += button_height;
    m_about =           new CUIButton(button_x, button_y, button_width, UserString("INTRO_BTN_ABOUT"));
    button_y += button_height;
    m_credits =         new CUIButton(button_x, button_y, button_width, UserString("INTRO_BTN_CREDITS"));
    button_y += 1.75 * button_height;
    m_exit_game =       new CUIButton(button_x, button_y, button_width, UserString("INTRO_BTN_EXIT"));

    //attach buttons
    m_menu->AttachChild(m_single_player);
    m_menu->AttachChild(m_quick_start);
    m_menu->AttachChild(m_multi_player);
    m_menu->AttachChild(m_load_game);
    m_menu->AttachChild(m_options);
    m_menu->AttachChild(m_about);
    m_menu->AttachChild(m_credits);
    m_menu->AttachChild(m_exit_game);

    //connect signals and slots
    GG::Connect(m_single_player->ClickedSignal, &IntroScreen::OnSinglePlayer,   this);
    GG::Connect(m_quick_start->ClickedSignal,   &IntroScreen::OnQuickStart,     this);
    GG::Connect(m_multi_player->ClickedSignal,  &IntroScreen::OnMultiPlayer,    this);
    GG::Connect(m_load_game->ClickedSignal,     &IntroScreen::OnLoadGame,       this);
    GG::Connect(m_options->ClickedSignal,       &IntroScreen::OnOptions,        this);
    GG::Connect(m_about->ClickedSignal,         &IntroScreen::OnAbout,          this);
    GG::Connect(m_credits->ClickedSignal,       &IntroScreen::OnCredits,        this);
    GG::Connect(m_exit_game->ClickedSignal,     &IntroScreen::OnExitGame,       this);
}
Beispiel #17
0
void FleetButton::Init(const std::vector<int>& fleet_IDs, SizeType size_type) {
    //std::cout << "FleetButton::Init" << std::endl;

    // get fleets
    std::vector<TemporaryPtr<const Fleet> > fleets;
    for (std::vector<int>::const_iterator it = fleet_IDs.begin(); it != fleet_IDs.end(); ++it) {
        TemporaryPtr<const Fleet> fleet = GetFleet(*it);
        if (!fleet) {
            ErrorLogger() << "FleetButton::FleetButton couldn't get fleet with id " << *it;
            continue;
        }
        m_fleets.push_back(*it);
        fleets.push_back(fleet);
    }

    // determine owner(s) of fleet(s).  Only care whether or not there is more than one owner, as owner
    // is used to determine colouration
    int owner_id = ALL_EMPIRES;
    int multiple_owners = false;
    if (fleets.empty()) {
        // leave as ALL_EMPIRES
    } else if (fleets.size() == 1) {
        owner_id = (*fleets.begin())->Owner();
    } else {
        owner_id = (*fleets.begin())->Owner();
        // use ALL_EMPIRES if there are multiple owners (including no owner and an owner)
        for (std::vector<TemporaryPtr<const Fleet> >::const_iterator it = fleets.begin(); it != fleets.end(); ++it) {
            TemporaryPtr<const Fleet> fleet = *it;
            if (fleet->Owner() != owner_id) {
                owner_id = ALL_EMPIRES;
                multiple_owners = true;
                break;
            }
        }
    }


    // get fleet colour
    if (multiple_owners) {
        SetColor(GG::CLR_WHITE);
    } else if (owner_id == ALL_EMPIRES) {
        // all ships owned by now empire
        bool monsters = true;
        // find if any ship in fleets in button is not a monster
        for (std::vector<TemporaryPtr<const Fleet> >::const_iterator it = fleets.begin(); it != fleets.end(); ++it) {
            TemporaryPtr<const Fleet> fleet = *it;
            for (std::set<int>::const_iterator ship_it = fleet->ShipIDs().begin();
                    ship_it != fleet->ShipIDs().end(); ++ship_it)
            {
                if (TemporaryPtr<const Ship> ship = GetShip(*ship_it)) {
                    if (!ship->IsMonster()) {
                        monsters = false;
                        break;
                    }
                }
            }
        }

        if (monsters)
            SetColor(GG::CLR_RED);
        else
            SetColor(GG::CLR_WHITE);
    } else {
        // single empire owner
        if (const Empire* empire = GetEmpire(owner_id))
            SetColor(empire->Color());
        else
            SetColor(GG::CLR_GRAY); // should never be necessary... but just in case
    }


    // determine direction button should be rotated to orient along a starlane
    GLfloat pointing_angle = 0.0f;

    TemporaryPtr<const Fleet> first_fleet;
    if (!m_fleets.empty())
        first_fleet = *fleets.begin();
    if (first_fleet && first_fleet->SystemID() == INVALID_OBJECT_ID && first_fleet->NextSystemID() != INVALID_OBJECT_ID) {
        int next_sys_id = first_fleet->NextSystemID();
        if (TemporaryPtr<const UniverseObject> obj = GetUniverseObject(next_sys_id)) {
            // fleet is not in a system and has a valid next destination, so can orient it in that direction
            // fleet icons might not appear on the screen in the exact place corresponding to their
            // actual universe position, but if they're moving along a starlane, this code will assume
            // their apparent position will only be different from their true position in a direction
            // parallel with the starlane, so the direction from their true position to their destination
            // position can be used to get a direction vector to orient the icon
            float dest_x = obj->X(), dest_y = obj->Y();
            float cur_x = first_fleet->X(), cur_y = first_fleet->Y();
            const MapWnd* map_wnd = ClientUI::GetClientUI()->GetMapWnd();
            GG::Pt dest = map_wnd->ScreenCoordsFromUniversePosition(dest_x, dest_y);
            GG::Pt cur = map_wnd->ScreenCoordsFromUniversePosition(cur_x, cur_y);
            GG::Pt direction_vector = dest - cur;

            if (direction_vector.x != GG::X0 || direction_vector.y != GG::Y0)
                pointing_angle = 360.0f / TWO_PI * std::atan2(static_cast<float>(Value(direction_vector.y)), static_cast<float>(Value(direction_vector.x))) + 90;
        }
    }


    // select icon(s) for fleet(s)
    int num_ships = 0;
    for (std::vector<TemporaryPtr<const Fleet> >::const_iterator it = fleets.begin(); it != fleets.end(); ++it) {
        TemporaryPtr<const Fleet> fleet = *it;
        if (fleet)
            num_ships += fleet->NumShips();
    }
    boost::shared_ptr<GG::Texture> size_texture = FleetSizeIcon(num_ships, size_type);
    std::vector<boost::shared_ptr<GG::Texture> > head_textures = FleetHeadIcons(fleets, size_type);


    // add RotatingGraphics for all icons needed
    if (size_texture) {
        RotatingGraphic* icon = new RotatingGraphic(size_texture, GG::GRAPHIC_FITGRAPHIC | GG::GRAPHIC_PROPSCALE);
        icon->SetPhaseOffset(pointing_angle);
        icon->SetRPM(0.0f);
        icon->SetColor(this->Color());
        m_icons.push_back(icon);
        Resize(GG::Pt(size_texture->DefaultWidth(), size_texture->DefaultHeight()));
        AttachChild(icon);
    }

    for (std::vector<boost::shared_ptr<GG::Texture> >::const_iterator it = head_textures.begin();
            it != head_textures.end(); ++it)
    {
        RotatingGraphic* icon = new RotatingGraphic(*it, GG::GRAPHIC_FITGRAPHIC | GG::GRAPHIC_PROPSCALE);
        icon->SetPhaseOffset(pointing_angle);
        icon->SetRPM(0.0f);
        icon->SetColor(this->Color());
        m_icons.push_back(icon);
        if (Width() < (*it)->DefaultWidth())
            Resize(GG::Pt((*it)->DefaultWidth(), (*it)->DefaultHeight()));
        AttachChild(icon);
    }

    // set up selection indicator
    m_selection_indicator = new RotatingGraphic(FleetSelectionIndicatorIcon(), GG::GRAPHIC_FITGRAPHIC | GG::GRAPHIC_PROPSCALE);
    m_selection_indicator->SetRPM(ClientUI::SystemSelectionIndicatorRPM());

    LayoutIcons();

    // Scanlines for not currently-visible objects?
    int empire_id = HumanClientApp::GetApp()->EmpireID();
    if (empire_id == ALL_EMPIRES || !GetOptionsDB().Get<bool>("UI.system-fog-of-war"))
        return;

    bool at_least_one_fleet_visible = false;
    for (std::vector<int>::const_iterator it = m_fleets.begin(); it != m_fleets.end(); ++it) {
        if (GetUniverse().GetObjectVisibilityByEmpire(*it, empire_id) >= VIS_BASIC_VISIBILITY) {
            at_least_one_fleet_visible = true;
            break;
        }
    }

    // Create scanline renderer control
    m_scanline_control = new ScanlineControl(GG::X0, GG::Y0, Width(), Height());

    if (!at_least_one_fleet_visible)
        AttachChild(m_scanline_control);
}
Beispiel #18
0
 bool ShouldOutput(const boost::chrono::nanoseconds & duration) {
     return (duration >= m_threshold && (m_enable_output || GetOptionsDB().Get<bool>("verbose-logging")));
 }
Beispiel #19
0
int mainConfigOptionsSetup(const std::vector<std::string>& args) {
    InitDirs((args.empty() ? "" : *args.begin()));

    // read and process command-line arguments, if any
    try {
        // add entries in options DB that have no other obvious place
        GetOptionsDB().AddFlag('h', "help",                 UserStringNop("OPTIONS_DB_HELP"),                  false);
        GetOptionsDB().AddFlag('g', "generate-config-xml",  UserStringNop("OPTIONS_DB_GENERATE_CONFIG_XML"),   false);
        GetOptionsDB().AddFlag('f', "fullscreen",           UserStringNop("OPTIONS_DB_FULLSCREEN"),            STORE_FULLSCREEN_FLAG);
        GetOptionsDB().Add("reset-fullscreen-size",         UserStringNop("OPTIONS_DB_RESET_FSSIZE"),          true);
        GetOptionsDB().Add<bool>("fake-mode-change",        UserStringNop("OPTIONS_DB_FAKE_MODE_CHANGE"),     FAKE_MODE_CHANGE_FLAG);
        GetOptionsDB().Add<int>("fullscreen-monitor-id",    UserStringNop("OPTIONS_DB_FULLSCREEN_MONITOR_ID"), 0, RangedValidator<int>(0, 5));
        GetOptionsDB().AddFlag('q', "quickstart",           UserStringNop("OPTIONS_DB_QUICKSTART"),            false);
        GetOptionsDB().AddFlag("auto-quit",                 UserStringNop("OPTIONS_DB_AUTO_QUIT"),             false);
        GetOptionsDB().Add<int>("auto-advance-n-turns",     UserStringNop("OPTIONS_DB_AUTO_N_TURNS"),          0, RangedValidator<int>(0, 400), false);
        GetOptionsDB().Add<std::string>("load",             UserStringNop("OPTIONS_DB_LOAD"),                  "", Validator<std::string>(), false);
        GetOptionsDB().Add("UI.sound.music-enabled",        UserStringNop("OPTIONS_DB_MUSIC_ON"),              true);
        GetOptionsDB().Add("UI.sound.enabled",              UserStringNop("OPTIONS_DB_SOUND_ON"),              true);
        GetOptionsDB().Add<std::string>("version-string",   UserStringNop("OPTIONS_DB_VERSION_STRING"),
                                        FreeOrionVersionString(),   Validator<std::string>(),                  true);
        GetOptionsDB().AddFlag('r', "render-simple",        UserStringNop("OPTIONS_DB_RENDER_SIMPLE"),         false);

        // Add the keyboard shortcuts
        Hotkey::AddOptions(GetOptionsDB());


        // read config.xml and set options entries from it, if present
        {
            XMLDoc doc;
            try {
                boost::filesystem::ifstream ifs(GetConfigPath());
                if (ifs) {
                    doc.ReadDoc(ifs);
                    // reject config files from out-of-date version
                    if (doc.root_node.ContainsChild("version-string") &&
                        doc.root_node.Child("version-string").Text() == FreeOrionVersionString())
                    {
                        GetOptionsDB().SetFromXML(doc);
                    }
                }
            } catch (const std::exception&) {
                std::cerr << UserString("UNABLE_TO_READ_CONFIG_XML") << std::endl;
            }
        }


        // override previously-saved and default options with command line parameters and flags
        GetOptionsDB().SetFromCommandLine(args);


        // Handle the case where the resource-dir does not exist anymore
        // gracefully by resetting it to the standard path into the
        // application bundle.  This may happen if a previous installed
        // version of FreeOrion was residing in a different directory.
        if (!boost::filesystem::exists(GetResourceDir()) ||
            !boost::filesystem::exists(GetResourceDir() / "credits.xml") ||
            !boost::filesystem::exists(GetResourceDir() / "data" / "art" / "misc" / "missing.png"))
        {
            DebugLogger() << "Resources directory from config.xml missing or does not contain expected files. Resetting to default.";

            GetOptionsDB().Set<std::string>("resource-dir", "");

            // double-check that resetting actually fixed things...
            if (!boost::filesystem::exists(GetResourceDir()) ||
                !boost::filesystem::exists(GetResourceDir() / "credits.xml") ||
                !boost::filesystem::exists(GetResourceDir() / "data" / "art" / "misc" / "missing.png"))
            {
                DebugLogger() << "Default Resources directory missing or does not contain expected files. Cannot start game.";
                throw std::runtime_error("Unable to load game resources at default location: " +
                                         PathString(GetResourceDir()) + " : Install may be broken.");
            }
        }


        // did the player request generation of config.xml, saving the default (or current) options to disk?
        if (GetOptionsDB().Get<bool>("generate-config-xml")) {
            try {
                GetOptionsDB().Commit();
            } catch (const std::exception&) {
                std::cerr << UserString("UNABLE_TO_WRITE_CONFIG_XML") << std::endl;
            }
        }

        if (GetOptionsDB().Get<bool>("render-simple")) {
            GetOptionsDB().Set<bool>("UI.galaxy-gas-background",false);
            GetOptionsDB().Set<bool>("UI.galaxy-starfields",    false);
            GetOptionsDB().Set<bool>("show-fps",                true);
        }

    } catch (const std::invalid_argument& e) {
        std::cerr << "main() caught exception(std::invalid_argument): " << e.what() << std::endl;
        boost::this_thread::sleep(boost::posix_time::seconds(3));
        return 1;
    } catch (const std::runtime_error& e) {
        std::cerr << "main() caught exception(std::runtime_error): " << e.what() << std::endl;
        boost::this_thread::sleep(boost::posix_time::seconds(3));
        return 1;
    } catch (const std::exception& e) {
        std::cerr << "main() caught exception(std::exception): " << e.what() << std::endl;
        boost::this_thread::sleep(boost::posix_time::seconds(3));
        return 1;
    } catch (...) {
        std::cerr << "main() caught unknown exception." << std::endl;
        return 1;
    }

    return 0;
}
Beispiel #20
0
void HumanClientApp::NewSinglePlayerGame(bool quickstart) {
    if (!GetOptionsDB().Get<bool>("force-external-server")) {
        try {
            StartServer();
        } catch (const std::runtime_error& err) {
            ErrorLogger() << "HumanClientApp::NewSinglePlayerGame : Couldn't start server.  Got error message: " << err.what();
            ClientUI::MessageBox(UserString("SERVER_WONT_START"), true);
            return;
        }
    }

    bool ended_with_ok = false;
    if (!quickstart) {
        GalaxySetupWnd galaxy_wnd;
        galaxy_wnd.Run();
        ended_with_ok = galaxy_wnd.EndedWithOk();
    }

    bool failed = false;
    unsigned int start_time = Ticks();
    while (!m_networking.ConnectToLocalHostServer(boost::posix_time::seconds(2))) {
        if (SERVER_CONNECT_TIMEOUT < Ticks() - start_time) {
            ClientUI::MessageBox(UserString("ERR_CONNECT_TIMED_OUT"), true);
            failed = true;
            break;
        }
    }
    m_connected = !failed;
    if (!failed && (quickstart || ended_with_ok)) {
        DebugLogger() << "HumanClientApp::NewSinglePlayerGame : Connected to server";

        SinglePlayerSetupData setup_data;
        setup_data.m_new_game = true;
        setup_data.m_filename.clear();  // not used for new game

        // get values stored in options from previous time game was run or
        // from just having run GalaxySetupWnd

        // GalaxySetupData
        setup_data.m_seed =             GetOptionsDB().Get<std::string>("GameSetup.seed");
        setup_data.m_size =             GetOptionsDB().Get<int>("GameSetup.stars");
        setup_data.m_shape =            GetOptionsDB().Get<Shape>("GameSetup.galaxy-shape");
        setup_data.m_age =              GetOptionsDB().Get<GalaxySetupOption>("GameSetup.galaxy-age");
        setup_data.m_starlane_freq =    GetOptionsDB().Get<GalaxySetupOption>("GameSetup.starlane-frequency");
        setup_data.m_planet_density =   GetOptionsDB().Get<GalaxySetupOption>("GameSetup.planet-density");
        setup_data.m_specials_freq =    GetOptionsDB().Get<GalaxySetupOption>("GameSetup.specials-frequency");
        setup_data.m_monster_freq =     GetOptionsDB().Get<GalaxySetupOption>("GameSetup.monster-frequency");
        setup_data.m_native_freq =      GetOptionsDB().Get<GalaxySetupOption>("GameSetup.native-frequency");
        setup_data.m_ai_aggr =          GetOptionsDB().Get<Aggression>("GameSetup.ai-aggression");

        // SinglePlayerSetupData contains a map of PlayerSetupData, for
        // the human and AI players.  Need to compile this information
        // from the specified human options and number of requested AIs

        // Human player setup data first

        PlayerSetupData human_player_setup_data;
        human_player_setup_data.m_player_name = GetOptionsDB().Get<std::string>("GameSetup.player-name");
        human_player_setup_data.m_empire_name = GetOptionsDB().Get<std::string>("GameSetup.empire-name");

        // DB stores index into array of available colours, so need to get that array to look up value of index.
        // if stored value is invalid, use a default colour
        const std::vector<GG::Clr>& empire_colours = EmpireColors();
        int colour_index = GetOptionsDB().Get<int>("GameSetup.empire-color");
        if (colour_index >= 0 && colour_index < static_cast<int>(empire_colours.size()))
            human_player_setup_data.m_empire_color = empire_colours[colour_index];
        else
            human_player_setup_data.m_empire_color = GG::CLR_GREEN;

        human_player_setup_data.m_starting_species_name = GetOptionsDB().Get<std::string>("GameSetup.starting-species");
        if (human_player_setup_data.m_starting_species_name == "1")
            human_player_setup_data.m_starting_species_name = "SP_HUMAN";   // kludge / bug workaround for bug with options storage and retreival.  Empty-string options are stored, but read in as "true" boolean, and converted to string equal to "1"

        if (!GetSpecies(human_player_setup_data.m_starting_species_name)) {
            const SpeciesManager& sm = GetSpeciesManager();
            if (sm.NumPlayableSpecies() < 1)
                human_player_setup_data.m_starting_species_name.clear();
            else
                human_player_setup_data.m_starting_species_name = sm.playable_begin()->first;
            }

        human_player_setup_data.m_save_game_empire_id = ALL_EMPIRES; // not used for new games
        human_player_setup_data.m_client_type = Networking::CLIENT_TYPE_HUMAN_PLAYER;

        // add to setup data players
        setup_data.m_players.push_back(human_player_setup_data);

        // AI player setup data.  One entry for each requested AI

        int num_AIs = GetOptionsDB().Get<int>("GameSetup.ai-players");
        for (int ai_i = 1; ai_i <= num_AIs; ++ai_i) {
            PlayerSetupData ai_setup_data;

            ai_setup_data.m_player_name = "AI_" + boost::lexical_cast<std::string>(ai_i);
            ai_setup_data.m_empire_name.clear();                // leave blank, to be set by server in Universe::GenerateEmpires
            ai_setup_data.m_empire_color = GG::CLR_ZERO;        // to be set by server
            ai_setup_data.m_starting_species_name.clear();      // leave blank, to be set by server
            ai_setup_data.m_save_game_empire_id = ALL_EMPIRES;  // not used for new games
            ai_setup_data.m_client_type = Networking::CLIENT_TYPE_AI_PLAYER;

            setup_data.m_players.push_back(ai_setup_data);
        }

        m_networking.SendMessage(HostSPGameMessage(setup_data));
        m_fsm->process_event(HostSPGameRequested());
    } else {
        DebugLogger() << "HumanClientApp::NewSinglePlayerGame killing server due to canceled game or server connection failure";
        if (m_networking.Connected()) {
            DebugLogger() << "HumanClientApp::NewSinglePlayerGame Sending server shutdown message.";
            m_networking.SendMessage(ShutdownServerMessage(m_networking.PlayerID()));
            boost::this_thread::sleep(boost::posix_time::seconds(1));
            m_networking.DisconnectFromServer();
            if (!m_networking.Connected())
                DebugLogger() << "HumanClientApp::NewSinglePlayerGame Disconnected from server.";
            else
                ErrorLogger() << "HumanClientApp::NewSinglePlayerGame Unexpectedly still connected to server...?";
        }
        KillServer();
    }
}
Beispiel #21
0
void HumanClientApp::LoadSinglePlayerGame(std::string filename/* = ""*/) {
    DebugLogger() << "HumanClientApp::LoadSinglePlayerGame";

    if (!filename.empty()) {
        if (!exists(FilenameToPath(filename))) {
            std::string msg = "HumanClientApp::LoadSinglePlayerGame() given a nonexistent file \""
                            + filename + "\" to load; aborting.";
            DebugLogger() << msg;
            std::cerr << msg << '\n';
            abort();
        }
    } else {
        try {
            SaveFileDialog sfd(SP_SAVE_FILE_EXTENSION, true);
            sfd.Run();
            if (!sfd.Result().empty())
                filename = sfd.Result();
        } catch (const std::exception& e) {
            ClientUI::MessageBox(e.what(), true);
        }
    }

    if (filename.empty()) {
        DebugLogger() << "HumanClientApp::LoadSinglePlayerGame has empty filename. Aborting load.";
        return;
    }

    // end any currently-playing game before loading new one
    if (m_game_started) {
        EndGame();
        // delay to make sure old game is fully cleaned up before attempting to start a new one
        boost::this_thread::sleep(boost::posix_time::seconds(3));
    } else {
        DebugLogger() << "HumanClientApp::LoadSinglePlayerGame() not already in a game, so don't need to end it";
    }

    if (!GetOptionsDB().Get<bool>("force-external-server")) {
        DebugLogger() << "HumanClientApp::LoadSinglePlayerGame() Starting server";
        StartServer();
        DebugLogger() << "HumanClientApp::LoadSinglePlayerGame() Server started";
    } else {
        DebugLogger() << "HumanClientApp::LoadSinglePlayerGame() assuming external server will be available";
    }

    DebugLogger() << "HumanClientApp::LoadSinglePlayerGame() Connecting to server";
    unsigned int start_time = Ticks();
    while (!m_networking.ConnectToLocalHostServer()) {
        if (SERVER_CONNECT_TIMEOUT < Ticks() - start_time) {
            ErrorLogger() << "HumanClientApp::LoadSinglePlayerGame() server connecting timed out";
            ClientUI::MessageBox(UserString("ERR_CONNECT_TIMED_OUT"), true);
            KillServer();
            return;
        }
    }

    DebugLogger() << "HumanClientApp::LoadSinglePlayerGame() Connected to server";

    m_connected = true;
    m_networking.SetPlayerID(Networking::INVALID_PLAYER_ID);
    m_networking.SetHostPlayerID(Networking::INVALID_PLAYER_ID);
    SetEmpireID(ALL_EMPIRES);

    SinglePlayerSetupData setup_data;
    // leving GalaxySetupData information default / blank : not used when loading a game
    setup_data.m_new_game = false;
    setup_data.m_filename = filename;
    // leving setup_data.m_players empty : not specified when loading a game, as server will generate from save file


    m_networking.SendMessage(HostSPGameMessage(setup_data));
    m_fsm->process_event(HostSPGameRequested());
}
Beispiel #22
0
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";
}
Beispiel #23
0
bool HumanClientApp::ToggleFullscreen() {
    bool fs = GetOptionsDB().Get<bool>("fullscreen");
    GetOptionsDB().Set<bool>("fullscreen", !fs);
    Reinitialize();
    return true;
}
Beispiel #24
0
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")) % EffectsDescription(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));
    }
}
ServerConnectWnd::ServerConnectWnd() : 
    CUIWnd(UserString("SCONNECT_WINDOW_TITLE"),
           (GG::GUI::GetGUI()->AppWidth() - WINDOW_WIDTH) / 2, (GG::GUI::GetGUI()->AppHeight() - WINDOW_HEIGHT) / 2,
           WINDOW_WIDTH, WINDOW_HEIGHT, GG::INTERACTIVE | GG::MODAL),
    m_host_or_join_radio_group(0),
    m_LAN_game_label(0),
    m_servers_lb(0),
    m_find_LAN_servers_bn(0),
    m_internet_game_label(0),
    m_IP_address_edit(0),
    m_player_name_edit(0),
    m_ok_bn(0),
    m_cancel_bn(0)
{
    Sound::TempUISoundDisabler sound_disabler;

    boost::shared_ptr<GG::Font> font = ClientUI::GetFont();
    GG::TextControl* player_name_label = new GG::TextControl(GG::X0, GG::Y0, GG::X1, GG::Y1, UserString("PLAYER_NAME_LABEL"), font, ClientUI::TextColor(), GG::FORMAT_LEFT);
    m_player_name_edit = new CUIEdit(GG::X0, GG::Y0, GG::X1, GetOptionsDB().Get<std::string>("multiplayersetup.player-name"));
    m_host_or_join_radio_group = new GG::RadioButtonGroup(GG::X0, GG::Y0, GG::X1, GG::Y1, GG::VERTICAL);
    m_host_or_join_radio_group->AddButton(new CUIStateButton(UserString("HOST_GAME_BN"), GG::X0, GG::Y0, GG::X1, GG::Y1, GG::FORMAT_LEFT, GG::SBSTYLE_3D_RADIO));
    m_host_or_join_radio_group->AddButton(new CUIStateButton(UserString("JOIN_GAME_BN"), GG::X0, GG::Y0, GG::X1, GG::Y1, GG::FORMAT_LEFT, GG::SBSTYLE_3D_RADIO));
    m_LAN_game_label = new GG::TextControl(GG::X0, GG::Y0, UserString("LAN_GAME_LABEL"), font, ClientUI::TextColor(), GG::FORMAT_LEFT);
    m_servers_lb = new CUIListBox(GG::X0, GG::Y0, GG::X1, GG::Y1);
    m_servers_lb->SetStyle(GG::LIST_NOSORT | GG::LIST_SINGLESEL);
    m_find_LAN_servers_bn = new CUIButton(UserString("REFRESH_LIST_BN"));
    m_internet_game_label = new GG::TextControl(GG::X0, GG::Y0, UserString("INTERNET_GAME_LABEL"), font, ClientUI::TextColor(), GG::FORMAT_LEFT);
    m_IP_address_edit = new CUIEdit(GG::X0, GG::Y0, GG::X1, GetOptionsDB().Get<std::string>("multiplayersetup.host-address"));
    m_ok_bn = new CUIButton(UserString("OK"));
    m_cancel_bn = new CUIButton(UserString("CANCEL"));

    const GG::X OK_CANCEL_BUTTON_WIDTH(80);
    const int CONTROL_MARGIN = 5;

    GG::Layout* layout = new GG::Layout(GG::X0, GG::Y0, GG::X1, GG::Y1, 8, 4, CONTROL_MARGIN);
    layout->SetMinimumColumnWidth(0, player_name_label->MinUsableSize().x + CONTROL_MARGIN);
    layout->SetColumnStretch(1, 1.0);
    layout->SetMinimumColumnWidth(2, OK_CANCEL_BUTTON_WIDTH + CONTROL_MARGIN);
    layout->SetMinimumColumnWidth(3, OK_CANCEL_BUTTON_WIDTH + CONTROL_MARGIN);
    layout->SetMinimumRowHeight(0, m_player_name_edit->Height() + CONTROL_MARGIN);
    layout->SetMinimumRowHeight(1, m_host_or_join_radio_group->MinUsableSize().y);
    layout->SetMinimumRowHeight(2, m_LAN_game_label->Height() + (2 * CONTROL_MARGIN));
    layout->SetRowStretch(3, 1.0);
    layout->SetMinimumRowHeight(4, m_find_LAN_servers_bn->Height() + CONTROL_MARGIN);
    layout->SetMinimumRowHeight(5, m_internet_game_label->Height() + CONTROL_MARGIN);
    layout->SetMinimumRowHeight(6, m_IP_address_edit->Height() + CONTROL_MARGIN);
    layout->SetMinimumRowHeight(7, m_ok_bn->Height() + CONTROL_MARGIN);

    layout->Add(player_name_label, 0, 0, 1, 1, GG::ALIGN_VCENTER);
    layout->Add(m_player_name_edit, 0, 1, 1, 3, GG::ALIGN_VCENTER);
    layout->Add(m_host_or_join_radio_group, 1, 0, 1, 4);
    layout->Add(m_LAN_game_label, 2, 0, 1, 4, GG::ALIGN_BOTTOM);
    layout->Add(m_servers_lb, 3, 0, 1, 4);
    layout->Add(m_find_LAN_servers_bn, 4, 3);
    layout->Add(m_internet_game_label, 5, 0, 1, 4);
    layout->Add(m_IP_address_edit, 6, 0, 1, 4);
    layout->Add(m_ok_bn, 7, 2);
    layout->Add(m_cancel_bn, 7, 3);

    SetLayout(layout);

    m_LAN_servers = HumanClientApp::GetApp()->Networking().DiscoverLANServers();
    Init();
}
Beispiel #26
0
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);
            }
        }

        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) {
        Logger().errorStream() << "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) {
        Logger().errorStream() << "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) {
        Logger().errorStream() << "main() caught exception(std::exception): " << e.what();
        std::cerr << "main() caught exception(std::exception): " << e.what() << std::endl;
        return 1;
    } catch (...) {
        Logger().errorStream() << "main() caught unknown exception.";
        std::cerr << "main() caught unknown exception." << std::endl;
        return 1;
    }

    return 0;
}
Beispiel #27
0
void AutoResolveCombat(CombatInfo& combat_info) {
    if (combat_info.objects.Empty())
        return;

    const System* system = combat_info.objects.Object<System>(combat_info.system_id);
    if (!system)
        Logger().errorStream() << "AutoResolveCombat couldn't get system with id " << combat_info.system_id;
    else
        Logger().debugStream() << "AutoResolveCombat at " << system->Name();

    if (GetOptionsDB().Get<bool>("verbose-logging")) {
        Logger().debugStream() << "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%";
        Logger().debugStream() << "AutoResolveCombat objects before resolution: " << combat_info.objects.Dump();
    }

    // reasonably unpredictable but reproducible random seeding
    const int base_seed = combat_info.objects.begin()->first + CurrentTurn();


    // compile list of valid objects to attack or be attacked in this combat
    std::set<int> valid_target_object_ids;                          // all objects that can be attacked
    std::set<int> valid_attacker_object_ids;                        // all objects that can attack
    std::map<int, std::set<int> > empire_valid_attacker_object_ids; // objects that can attack that each empire owns
    float monster_detection = 0.0;

    for (ObjectMap::iterator it = combat_info.objects.begin(); it != combat_info.objects.end(); ++it) {
        const UniverseObject* obj = it->second;
        //Logger().debugStream() << "Considerting object " << obj->Name() << " owned by " << obj->Owner();
        if (ObjectCanAttack(obj)) {
            //Logger().debugStream() << "... can attack";
            valid_attacker_object_ids.insert(it->first);
            empire_valid_attacker_object_ids[obj->Owner()].insert(it->first);
        }
        if (ObjectCanBeAttacked(obj)) {
            //Logger().debugStream() << "... can be attacked";
            valid_target_object_ids.insert(it->first);
        }
        if (obj->Unowned() && obj->ObjectType() == OBJ_SHIP)
            monster_detection = std::max(monster_detection, obj->CurrentMeterValue(METER_DETECTION));
    }


    // map from empire to set of IDs of objects that empire's objects
    // could potentially target.
    std::map<int, std::set<int> > empire_valid_target_object_ids;   // objects that each empire can attack
    for (std::set<int>::const_iterator target_it = valid_target_object_ids.begin();
         target_it != valid_target_object_ids.end(); ++target_it)
    {
        int object_id = *target_it;
        const UniverseObject* obj = combat_info.objects.Object(object_id);
        //Logger().debugStream() << "Considering attackability of object " << obj->Name() << " owned by " << obj->Owner();

        // for all empires, can they attack this object?
        for (std::set<int>::const_iterator empire_it = combat_info.empire_ids.begin();
             empire_it != combat_info.empire_ids.end(); ++empire_it)
        {
            int attacking_empire_id = *empire_it;
            if (attacking_empire_id == ALL_EMPIRES) {
                if (ObjectAttackableByMonsters(obj, monster_detection)) {
                    //Logger().debugStream() << "object: " << obj->Name() << " attackable by monsters";
                    empire_valid_target_object_ids[ALL_EMPIRES].insert(object_id);
                }

            } else {
                // call function to find if empires can attack objects...
                if (ObjectAttackableByEmpire(obj, attacking_empire_id)) {
                    //Logger().debugStream() << "object: " << obj->Name() << " attackable by empire " << attacking_empire_id;
                    empire_valid_target_object_ids[attacking_empire_id].insert(object_id);
                }
            }
        }
    }


    // Each combat "round" a randomly-selected object in the battle attacks
    // something, if it is able to do so.  The number of rounds scales with the
    // number of objects, so the total actions per object is independent of
    // number of objects in the battle
    const int NUM_COMBAT_ROUNDS = 3*valid_attacker_object_ids.size();

    for (int round = 1; round <= NUM_COMBAT_ROUNDS; ++round) {
        Seed(base_seed + round);    // ensure each combat round produces different results

        // ensure something can attack and something can be attacked
        if (valid_attacker_object_ids.empty()) {
            Logger().debugStream() << "Nothing left can attack; combat over";
            break;
        }
        if (empire_valid_target_object_ids.empty()) {
            Logger().debugStream() << "Nothing left can be attacked; combat over";
            break;
        }
        // empires may have valid targets, but nothing to attack with.  If all
        // empires have no attackers or no valid targers, combat is over
        bool someone_can_attack_something = false;
        for (std::map<int, std::set<int> >::const_iterator attacker_it = empire_valid_attacker_object_ids.begin();
             attacker_it != empire_valid_attacker_object_ids.end(); ++attacker_it)
        {
            if (empire_valid_target_object_ids.find(attacker_it->first) != empire_valid_target_object_ids.end()) {
                someone_can_attack_something = true;
                break;
            }
        }
        if (!someone_can_attack_something) {
            Logger().debugStream() << "No empire has valid targets and something to attack with; combat over.";
            break;
        }

        Logger().debugStream() << "Combat at " << system->Name() << " (" << combat_info.system_id << ") Round " << round;

        // select attacking object in battle
        SmallIntDistType attacker_id_num_dist = SmallIntDist(0, valid_attacker_object_ids.size() - 1);
        std::set<int>::const_iterator attacker_it = valid_attacker_object_ids.begin();
        std::advance(attacker_it, attacker_id_num_dist());
        assert(attacker_it != valid_attacker_object_ids.end());
        int attacker_id = *attacker_it;

        UniverseObject* attacker = combat_info.objects.Object(attacker_id);
        if (!attacker) {
            Logger().errorStream() << "AutoResolveCombat couldn't get object with id " << attacker_id;
            continue;
        }
        Logger().debugStream() << "Attacker: " << attacker->Name();


        Ship* attack_ship = universe_object_cast<Ship*>(attacker);
        Planet* attack_planet = universe_object_cast<Planet*>(attacker);

        // loop over weapons of attacking object.  each gets a shot at a
        // randomly selected target object
        std::vector<PartAttackInfo> weapons;

        if (attack_ship) {
            weapons = ShipWeaponsStrengths(attack_ship);
            for (std::vector<PartAttackInfo>::const_iterator part_it = weapons.begin();
                 part_it != weapons.end(); ++part_it)
            {
                Logger().debugStream() << "weapon: " << part_it->part_type_name <<
                                          " attack: " << part_it->part_attack;
            }
        } else if (attack_planet) { // treat planet defenses as short range
            weapons.push_back(PartAttackInfo(PC_SHORT_RANGE, "", attack_planet->CurrentMeterValue(METER_DEFENSE)));
        }

        if (weapons.empty()) {
            Logger().debugStream() << "no weapons' can't attack";
            continue;   // no ability to attack!
        }

        for (std::vector<PartAttackInfo>::const_iterator weapon_it = weapons.begin();
             weapon_it != weapons.end(); ++weapon_it)
        {
            // select object from valid targets for this object's owner   TODO: with this weapon...
            Logger().debugStream() << "Attacking with weapon " << weapon_it->part_type_name << " with power " << weapon_it->part_attack;

            // get valid targets set for attacker owner.  need to do this for
            // each weapon that is attacking, as the previous shot might have
            // destroyed something
            int attacker_owner_id = attacker->Owner();

            std::map<int, std::set<int> >::iterator target_vec_it = empire_valid_target_object_ids.find(attacker_owner_id);
            if (target_vec_it == empire_valid_target_object_ids.end()) {
                Logger().debugStream() << "No targets for attacker with id: " << attacker_owner_id;
                break;
            }

            const std::set<int>& valid_target_ids = target_vec_it->second;
            if (valid_target_ids.empty())
                break; // should be redundant with this entry being erased when emptied


            // select target object
            SmallIntDistType target_id_num_dist = SmallIntDist(0, valid_target_ids.size() - 1);
            std::set<int>::const_iterator target_it = valid_target_ids.begin();
            std::advance(target_it, target_id_num_dist());
            assert(target_it != valid_target_ids.end());
            int target_id = *target_it;

            UniverseObject* target = combat_info.objects.Object(target_id);
            if (!target) {
                Logger().errorStream() << "AutoResolveCombat couldn't get target object with id " << target_id;
                continue;
            }
            Logger().debugStream() << "Target: " << target->Name();


            // do actual attacks, and mark attackers as valid targets for attacked object's owners
            if (attack_ship) {
                if (Ship* target_ship = universe_object_cast<Ship*>(target)) {
                    AttackShipShip(attack_ship, weapon_it->part_attack, target_ship, combat_info.damaged_object_ids);
                    empire_valid_target_object_ids[target_ship->Owner()].insert(attacker_id);
                } else if (Planet* target_planet = universe_object_cast<Planet*>(target)) {
                    AttackShipPlanet(attack_ship, weapon_it->part_attack,  target_planet, combat_info.damaged_object_ids);
                    empire_valid_target_object_ids[target_planet->Owner()].insert(attacker_id);
                }
            } else if (attack_planet) {
                if (Ship* target_ship = universe_object_cast<Ship*>(target)) {
                    AttackPlanetShip(attack_planet, target_ship, combat_info.damaged_object_ids);
                    empire_valid_target_object_ids[target_ship->Owner()].insert(attacker_id);
                } else if (Planet* target_planet = universe_object_cast<Planet*>(target)) {
                    AttackPlanetPlanet(attack_planet, target_planet, combat_info.damaged_object_ids);
                    empire_valid_target_object_ids[target_planet->Owner()].insert(attacker_id);
                }
            }


            // check for destruction of target object
            if (target->ObjectType() == OBJ_SHIP) {
                if (target->CurrentMeterValue(METER_STRUCTURE) <= 0.0) {
                    Logger().debugStream() << "!! Target Ship is destroyed!";
                    // object id destroyed
                    combat_info.destroyed_object_ids.insert(target_id);
                    // all empires in battle know object was destroyed
                    for (std::set<int>::const_iterator it = combat_info.empire_ids.begin();
                         it != combat_info.empire_ids.end(); ++it)
                    {
                        int empire_id = *it;
                        if (empire_id != ALL_EMPIRES)
                            combat_info.destroyed_object_knowers[empire_id].insert(target_id);
                    }

                    // remove destroyed ship's ID from lists of valid attackers and targets
                    valid_attacker_object_ids.erase(target_id);
                    valid_target_object_ids.erase(target_id);   // probably not necessary as this set isn't used in this loop

                    for (target_vec_it = empire_valid_target_object_ids.begin();
                         target_vec_it != empire_valid_target_object_ids.end(); ++target_vec_it)
                    { target_vec_it->second.erase(target_id); }

                    for (target_vec_it = empire_valid_attacker_object_ids.begin();
                         target_vec_it != empire_valid_attacker_object_ids.end(); ++target_vec_it)
                    { target_vec_it->second.erase(target_id); } // TODO: only erase from owner's entry in this list
                }

            } else if (target->ObjectType() == OBJ_PLANET) {
                if (target->CurrentMeterValue(METER_SHIELD) <= 0.0 &&
                    target->CurrentMeterValue(METER_DEFENSE) <= 0.0 &&
                    target->CurrentMeterValue(METER_CONSTRUCTION) <= 0.0)
                {
                    Logger().debugStream() << "!! Target Planet is knocked out of battle";

                    // remove disabled planet's ID from lists of valid attackers and targets
                    valid_attacker_object_ids.erase(target_id);
                    valid_target_object_ids.erase(target_id);   // probably not necessary as this set isn't used in this loop

                    for (target_vec_it = empire_valid_target_object_ids.begin();
                         target_vec_it != empire_valid_target_object_ids.end(); ++target_vec_it)
                    { target_vec_it->second.erase(target_id); }

                    for (target_vec_it = empire_valid_attacker_object_ids.begin();
                         target_vec_it != empire_valid_attacker_object_ids.end(); ++target_vec_it)
                    { target_vec_it->second.erase(target_id); } // TODO: only erase from owner's entry in this list
                }
            }

            // check if any empire has no remaining target or attacker objects.
            // If so, remove that empire's entry
            std::map<int, std::set<int> > temp = empire_valid_target_object_ids;
            for (target_vec_it = empire_valid_target_object_ids.begin();
                 target_vec_it != empire_valid_target_object_ids.end(); ++target_vec_it)
            {
                if (target_vec_it->second.empty()) {
                    temp.erase(target_vec_it->first);
                    Logger().debugStream() << "No valid targets left for empire with id: " << target_vec_it->first;
                }
            }
            empire_valid_target_object_ids = temp;

            temp = empire_valid_attacker_object_ids;
            for (target_vec_it = empire_valid_attacker_object_ids.begin();
                 target_vec_it != empire_valid_attacker_object_ids.end(); ++target_vec_it)
            {
                if (target_vec_it->second.empty()) {
                    temp.erase(target_vec_it->first);
                    Logger().debugStream() << "No valid attacking objects left for empire with id: " << target_vec_it->first;
                }
            }
            empire_valid_attacker_object_ids = temp;
        } // end for over weapons
    } // end for over combat arounds

    // ensure every participant knows what happened.
    // TODO: assemble list of objects to copy for each empire.  this should
    //       include objects the empire already knows about with standard
    //       visibility system, and also any objects the empire knows are
    //       destroyed or
    for (std::map<int, ObjectMap>::iterator it = combat_info.empire_known_objects.begin();
         it != combat_info.empire_known_objects.end(); ++it)
    { it->second.Copy(combat_info.objects); }

    if (GetOptionsDB().Get<bool>("verbose-logging"))
        Logger().debugStream() << "AutoResolveCombat objects after resolution: " << combat_info.objects.Dump();
}
Beispiel #28
0
void FleetButton::Init(const std::vector<int>& fleet_IDs, SizeType size_type) {
    if (!scanline_shader && GetOptionsDB().Get<bool>("UI.system-fog-of-war")) {
        boost::filesystem::path shader_path = GetRootDataDir() / "default" / "shaders" / "scanlines.frag";
        std::string shader_text;
        ReadFile(shader_path, shader_text);
        scanline_shader = boost::shared_ptr<ShaderProgram>(
            ShaderProgram::shaderProgramFactory("", shader_text));
    }

    // get fleets
    std::vector<TemporaryPtr<const Fleet> > fleets;
    for (std::vector<int>::const_iterator it = fleet_IDs.begin(); it != fleet_IDs.end(); ++it) {
        TemporaryPtr<const Fleet> fleet = GetFleet(*it);
        if (!fleet) {
            Logger().errorStream() << "FleetButton::FleetButton couldn't get fleet with id " << *it;
            continue;
        }
        m_fleets.push_back(*it);
        fleets.push_back(fleet);
    }

    // determine owner(s) of fleet(s).  Only care whether or not there is more than one owner, as owner
    // is used to determine colouration
    int owner_id = ALL_EMPIRES;
    int multiple_owners = false;
    if (fleets.empty()) {
        // leave as ALL_EMPIRES
    } else if (fleets.size() == 1) {
        owner_id = (*fleets.begin())->Owner();
    } else {
        owner_id = (*fleets.begin())->Owner();
        // use ALL_EMPIRES if there are multiple owners (including no owner and an owner)
        for (std::vector<TemporaryPtr<const Fleet> >::const_iterator it = fleets.begin(); it != fleets.end(); ++it) {
            TemporaryPtr<const Fleet> fleet = *it;
            if (fleet->Owner() != owner_id) {
                owner_id = ALL_EMPIRES;
                multiple_owners = true;
                break;
            }
        }
    }


    // get fleet colour
    if (multiple_owners) {
        SetColor(GG::CLR_WHITE);
    } else if (owner_id == ALL_EMPIRES) {
        // all ships owned by now empire
        bool monsters = true;
        // find if any ship in fleets in button is not a monster
        for (std::vector<TemporaryPtr<const Fleet> >::const_iterator it = fleets.begin(); it != fleets.end(); ++it) {
            TemporaryPtr<const Fleet> fleet = *it;
            for (std::set<int>::const_iterator ship_it = fleet->ShipIDs().begin();
                 ship_it != fleet->ShipIDs().end(); ++ship_it)
            {
                if (TemporaryPtr<const Ship> ship = GetShip(*ship_it)) {
                    if (!ship->IsMonster()) {
                        monsters = false;
                        break;
                    }
                }
            }
        }

        if (monsters)
            SetColor(GG::CLR_RED);
        else
            SetColor(GG::CLR_WHITE);

    } else {
        // single empire owner
        if (const Empire* empire = Empires().Lookup(owner_id))
            SetColor(empire->Color());
        else
            SetColor(GG::CLR_GRAY); // should never be necessary... but just in case
    }


    // select icon(s) for fleet(s)
    int num_ships = 0;
    for (std::vector<TemporaryPtr<const Fleet> >::const_iterator it = fleets.begin(); it != fleets.end(); ++it) {
        TemporaryPtr<const Fleet> fleet = *it;
        if (fleet)
            num_ships += fleet->NumShips();
    }
    m_size_icon = FleetSizeIcon(num_ships, size_type);
    m_head_icons = FleetHeadIcons(fleets, size_type);

    // resize to fit icon by first determining necessary size, and then resizing
    GG::X texture_width(0);
    GG::Y texture_height(0);

    if (!m_head_icons.empty()) {
        texture_width = m_head_icons.front()->DefaultWidth();
        texture_height = m_head_icons.front()->DefaultHeight();
    }
    if (m_size_icon) {
        texture_width = std::max(texture_width, m_size_icon->DefaultWidth());
        texture_height = std::max(texture_height, m_size_icon->DefaultHeight());
    }


    // determine if fleet icon should be rotated.  this should be done if the fleet is moving along
    // a starlane, which is the case if the fleet is not in a system and has a valid next system
    GG::Pt direction_vector(GG::X(0), GG::Y(1));    // default, unrotated button orientation

    TemporaryPtr<const Fleet> first_fleet;
    if (!m_fleets.empty())
        first_fleet = *fleets.begin();
    
    if (first_fleet && first_fleet->SystemID() == INVALID_OBJECT_ID) {
        int next_sys_id = first_fleet->NextSystemID();
        if (TemporaryPtr<const UniverseObject> obj = GetUniverseObject(next_sys_id)) {
            // fleet is not in a system and has a valid next destination, so can orient it in that direction
            // fleet icons might not appear on the screen in the exact place corresponding to their 
            // actual universe position, but if they're moving along a starlane, this code will assume
            // their apparent position will only be different from their true position in a direction
            // parallel with the starlane, so the direction from their true position to their destination
            // position can be used to get a direction vector to orient the icon
            double dest_x = obj->X(), dest_y = obj->Y();
            double cur_x = first_fleet->X(), cur_y = first_fleet->Y();
            const MapWnd* map_wnd = ClientUI::GetClientUI()->GetMapWnd();
            GG::Pt dest = map_wnd->ScreenCoordsFromUniversePosition(dest_x, dest_y);
            GG::Pt cur = map_wnd->ScreenCoordsFromUniversePosition(cur_x, cur_y);
            direction_vector = dest - cur;
        }
    }

    // check for unrotated texture
    if (Value(direction_vector.x) == 0) {
        // not rotated.  can do simple texture blits
        m_vertex_components.clear();
    } else {
        // texture is rotated, so need some extra math
        // get rotated corner vetex x and y components (x1, y1, x2, y2, x3, y3, x4, y4) for texture of appropriate size
        m_vertex_components = VectorAlignedQuadVertices(direction_vector, Value(texture_height), Value(texture_width));
    }

    // size icon according to texture size (average two dimensions)
    int diameter = static_cast<int>((Value(texture_width) + Value(texture_height)) / 2.0);
    Resize(GG::Pt(GG::X(diameter), GG::Y(diameter)));

    // get selection indicator texture
    m_selection_texture = ClientUI::GetTexture(ClientUI::ArtDir() / "icons" / "fleet" / "fleet_selection.png", true);
}
Beispiel #29
0
void Sound::Impl::PlaySound(const boost::filesystem::path& path, bool is_ui_sound/* = false*/) {
    if (!m_initialized || !GetOptionsDB().Get<bool>("UI.sound.enabled") || (is_ui_sound && UISoundsTemporarilyDisabled()))
        return;

    std::string filename = PathString(path);
    ALuint current_buffer;
    ALenum source_state;
    ALsizei ogg_freq;
    FILE *file = nullptr;
    int m_i;
    bool found_buffer = false;
    bool found_source = false;

#ifdef FREEORION_WIN32
    ov_callbacks callbacks = {

    (size_t (*)(void *, size_t, size_t, void *))  fread,

    (int (*)(void *, ogg_int64_t, int))           _fseek64_wrap,

    (int (*)(void *))                             fclose,

    (long (*)(void *))                            ftell

    };
#endif

    if (alcGetCurrentContext()) {
        /* First check if the sound data of the file we want to play is already buffered somewhere */
        std::map<std::string, ALuint>::iterator it = m_buffers.find(filename);
        if (it != m_buffers.end()) {
            current_buffer = it->second;
            found_buffer = true;
        } else {
            if ((file = fopen(filename.c_str(), "rb")) != nullptr) { // make sure we CAN open it
                OggVorbis_File ogg_file;
                vorbis_info *vorbis_info;
                ALenum ogg_format;
#ifdef FREEORION_WIN32
                if (!(ov_test_callbacks(file, &ogg_file, nullptr, 0, callbacks))) // check if it's a proper ogg
#else
                if (!(ov_test(file, &ogg_file, nullptr, 0))) // check if it's a proper ogg
#endif
                {
                    ov_test_open(&ogg_file); // it is, now fully open the file
                    /* now we need to take some info we will need later */
                    vorbis_info = ov_info(&ogg_file, -1);
                    if (vorbis_info->channels == 1)
                        ogg_format = AL_FORMAT_MONO16;
                    else
                        ogg_format = AL_FORMAT_STEREO16;
                    ogg_freq = vorbis_info->rate;
                    ogg_int64_t byte_size = ov_pcm_total(&ogg_file, -1) * vorbis_info->channels * 2;
                    if (byte_size <= 1024 * 1024 * 1024) {
                        /* fill up the buffers and queue them up for the first time */
                        ALuint sound_handle;
                        alGenBuffers(1, &sound_handle);

                        int loop = 0;

                        RefillBuffer(&ogg_file, ogg_format, ogg_freq, sound_handle, byte_size, loop);

                        current_buffer = sound_handle;
                        found_buffer = true;
                        m_buffers.insert(std::make_pair(filename, sound_handle));
                    }
                    else
                    {
                        ErrorLogger() << "PlaySound: unable to open file " << filename.c_str() << " too big to buffer. Aborting\n";
                    }
                    ov_clear(&ogg_file);
                }
                else
                {
                    ErrorLogger() << "PlaySound: unable to open file " << filename.c_str() << " possibly not a .ogg vorbis file. Aborting\n";
                }
            }
        }
        if (found_buffer) {
            /* Now that we have the buffer, we need to find a source to send it to */
            for (m_i = 1; m_i < NUM_SOURCES; ++m_i) {   // as we're playing sounds we start at 1. 0 is reserved for music
                alGetSourcei(m_sources[m_i], AL_SOURCE_STATE, &source_state);
                if ((source_state != AL_PLAYING) && (source_state != AL_PAUSED)) {
                    found_source = true;
                    alSourcei(m_sources[m_i], AL_BUFFER, current_buffer);
                    alSourcePlay(m_sources[m_i]);
                    break; // so that the sound won't block all the sources
                }
            }
            if (!found_source)
                ErrorLogger() << "PlaySound: Could not find aviable source - playback aborted\n";
        }
        source_state = alGetError();
        if (source_state != AL_NONE)
            ErrorLogger() << "PlaySound: OpenAL ERROR: " << alGetString(source_state);
            /* it's important to check for errors, as some functions won't work properly if
             * they're called when there is a unchecked previous error. */
    }
}
Beispiel #30
0
void FleetButton::PlayFleetButtonRolloverSound()
{ Sound::GetSound().PlaySound(GetOptionsDB().Get<std::string>("UI.sound.fleet-button-rollover"), true); }