void HumanClientApp::MultiPlayerGame() {
    if (m_networking.Connected()) {
        ErrorLogger() << "HumanClientApp::MultiPlayerGame aborting because already connected to a server";
        return;
    }

    ServerConnectWnd server_connect_wnd;
    server_connect_wnd.Run();

    std::string server_name = server_connect_wnd.Result().second;

    if (server_name.empty())
        return;

    if (server_name == "HOST GAME SELECTED") {
        if (!GetOptionsDB().Get<bool>("force-external-server")) {
            try {
                StartServer();
                FreeServer();
            } catch (const std::runtime_error& err) {
                ErrorLogger() << "Couldn't start server.  Got error message: " << err.what();
                ClientUI::MessageBox(UserString("SERVER_WONT_START"), true);
                return;
            }
            server_name = "localhost";
        }
        server_name = GetOptionsDB().Get<std::string>("external-server-address");
    }

    unsigned int start_time = Ticks();
    while (!m_networking.ConnectToServer(server_name, boost::posix_time::seconds(2))) {
        if (SERVER_CONNECT_TIMEOUT < Ticks() - start_time) {
            ClientUI::MessageBox(UserString("ERR_CONNECT_TIMED_OUT"), true);
            if (server_connect_wnd.Result().second == "HOST GAME SELECTED")
                KillServer();
            return;
        }
    }

    if (server_connect_wnd.Result().second == "HOST GAME SELECTED") {
        m_networking.SendMessage(HostMPGameMessage(server_connect_wnd.Result().first));
        m_fsm->process_event(HostMPGameRequested());
    } else {
        m_networking.SendMessage(JoinGameMessage(server_connect_wnd.Result().first, Networking::CLIENT_TYPE_HUMAN_PLAYER));
        m_fsm->process_event(JoinMPGameRequested());
    }
    m_connected = true;
}
void AIClientApp::Run() {
    ConnectToServer();

    try {
        StartPythonAI();

        // join game
        Networking().SendMessage(JoinGameMessage(PlayerName(),
                                                 Networking::CLIENT_TYPE_AI_PLAYER,
                                                 boost::uuids::nil_uuid()));

        // Start parsing content
        StartBackgroundParsing();

        // respond to messages until disconnected
        while (1) {
            try {

                if (!Networking().IsRxConnected())
                    break;
                if (const auto msg = Networking().GetMessage())
                    HandleMessage(*msg);
                else
                    std::this_thread::sleep_for(std::chrono::milliseconds(10));

            } catch (const boost::python::error_already_set&) {
                /* If the python interpreter is still running then keep
                   going, otherwise exit.*/
                m_AI->HandleErrorAlreadySet();
                if (!m_AI->IsPythonRunning())
                    throw;
            }
        }
    } catch (const NormalExitException&) {
        // intentionally empty.
    } catch (const boost::python::error_already_set&) {
        HandlePythonAICrash();
    }

    Networking().DisconnectFromServer();
}