Ticket #3556: t3556_dedicated_server_WIP_v0.2.patch

File t3556_dedicated_server_WIP_v0.2.patch, 23.1 KB (added by elexis, 8 years ago)

No more useless windows, only command line. Takes a fraction of a second to start. Changed to class structure.

  • binaries/system/readme.txt

    Basic gameplay:  
    44-autostart=...      load a map instead of showing main menu (see below)
    55-editor             launch the Atlas scenario editor
    66-mod=NAME           start the game using NAME mod
    77-quickstart         load faster (disables audio and some system info logging)
    88
     9Dedicated Server:
     10-dedicated-host                 starts a dedicated multiplayer server (without graphics)
     11                                please specify the mods, for example -mod="public"
     12-dedicated-lobby                advertize the game of the dedicated host in the lobby
     13
    914Autostart:
    1015-autostart="TYPEDIR/MAPNAME"    enables autostart and sets MAPNAME; TYPEDIR is skirmishes, scenarios, or random
    1116-autostart-ai=PLAYER:AI         sets the AI for PLAYER (e.g. 2:petra)
    1217-autostart-aidiff=PLAYER:DIFF   sets the DIFFiculty of PLAYER's AI (0: sandbox, 5: very hard)
    1318-autostart-civ=PLAYER:CIV       sets PLAYER's civilisation to CIV (skirmish and random maps only)
  • source/main.cpp

    static void RunGameOrAtlas(int argc, con  
    527527        {
    528528            flags &= ~INIT_MODS;
    529529            Shutdown(SHUTDOWN_FROM_CONFIG);
    530530            continue;
    531531        }
     532
     533        if (args.Has("dedicated-host"))
     534        {
     535            (new CDedicatedServer())->StartHosting();
     536            while (true)
     537                SDL_Delay(100); // TODO: optimize this value
     538            continue;
     539        }
     540
    532541        InitGraphics(args, 0);
     542
    533543        MainControllerInit();
    534544        while (!quit)
    535545            Frame();
    536546        Shutdown(0);
    537547        MainControllerShutdown();
  • source/network/DedicatedServer.cpp

     
     1/* Copyright (C) 2015 Wildfire Games.
     2 * This file is part of 0 A.D.
     3 *
     4 * 0 A.D. is free software: you can redistribute it and/or modify
     5 * it under the terms of the GNU General Public License as published by
     6 * the Free Software Foundation, either version 2 of the License, or
     7 * (at your option) any later version.
     8 *
     9 * 0 A.D. is distributed in the hope that it will be useful,
     10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     12 * GNU General Public License for more details.
     13 *
     14 * You should have received a copy of the GNU General Public License
     15 * along with 0 A.D.  If not, see <http://www.gnu.org/licenses/>.
     16 */
     17
     18// TODO: use lobby
     19// TODO: manage SERVER_STATE
     20// TODO: we should let the clients chose their civs and team numbers (but nothing else) via the regular GUI elements
     21// TODO: use ReplayLogger
     22// TODO: end the game when somebody won or everybody left
     23// TODO: start a new game after one finished
     24
     25// TODO: #include "precompiled.h" ??
     26//#include "DedicatedServer.h"
     27#include "NetServer.h"
     28
     29#include "ps/CLogger.h"
     30
     31CDedicatedServer::CDedicatedServer()
     32{
     33}
     34
     35CDedicatedServer::~CDedicatedServer()
     36{
     37}
     38
     39void CDedicatedServer::StartHosting()
     40{
     41    LOGERROR("[HOST] Starting dedicated host");
     42
     43    g_NetServer = new CNetServer(true);
     44
     45    if (!g_NetServer->m_Worker->SetupConnection())
     46    {
     47        LOGERROR("ERROR: Could not start the server!");
     48        delete g_NetServer;
     49    }
     50}
     51
     52void CDedicatedServer::Initialize()
     53{
     54    LOGERROR("[HOST] Initializing dedicated servers");
     55
     56    m_Worker = g_NetServer->m_Worker;
     57    m_ScriptInterface = g_NetServer->m_Worker->m_ScriptInterface;
     58
     59    CStrW serverName(L"Autohost");
     60    //if (g_args.Has("dedicated-host-name"))
     61    //  serverName = wstring_from_utf8(g_args.Get("dedicated-host-name"));
     62    JSContext* cx = m_ScriptInterface->GetContext();
     63    JSAutoRequest rq(cx);
     64
     65    // Needs to be kept in sync with gamesetup.js
     66    // TODO: load from a JSON file
     67    JS::RootedValue attribs(cx);
     68    JS::RootedValue settings(cx);
     69    JS::RootedValue playerAssignments(cx);
     70    JS::RootedValue PlayerData(cx);
     71    JS::RootedValue VictoryScripts(cx);
     72
     73    m_ScriptInterface->Eval("({})", &attribs);
     74    m_ScriptInterface->Eval("({})", &settings);
     75    m_ScriptInterface->Eval("({})", &playerAssignments);
     76    m_ScriptInterface->Eval("([])", &PlayerData);
     77    m_ScriptInterface->Eval("([\"scripts/TriggerHelper.js\",\"scripts/ConquestCommon.js\",\"scripts/Conquest.js\"])", &VictoryScripts);
     78
     79    m_ScriptInterface->SetProperty(settings, "AISeed", rand());
     80    m_ScriptInterface->SetProperty(settings, "Seed", rand());
     81    m_ScriptInterface->SetProperty(settings, "Ceasefire", 0);
     82    m_ScriptInterface->SetProperty(settings, "CheatsEnabled", false);
     83    m_ScriptInterface->SetProperty(settings, "GameType", std::wstring(L"conquest"));
     84    m_ScriptInterface->SetProperty(settings, "PlayerData", PlayerData);
     85    m_ScriptInterface->SetProperty(settings, "PopulationCap", 300);
     86    m_ScriptInterface->SetProperty(settings, "Size", 320); // map size 4
     87    m_ScriptInterface->SetProperty(settings, "StartingResources", 500); // medium res for nomad
     88    m_ScriptInterface->SetProperty(settings, "VictoryScripts", VictoryScripts);
     89// disable treasure, no revealed map, no explored map
     90    // "timestamp": "1446043600",
     91    // "engine_version": "0.0.19",
     92    // "mods": ["mod","public"]
     93    //"Preview": "acropolis_bay.png",
     94    //CircularMap
     95    //Description
     96    m_ScriptInterface->SetProperty(attribs, "gameSpeed", 1);
     97    m_ScriptInterface->SetProperty(attribs, "isNetworked", true);
     98    m_ScriptInterface->SetProperty(attribs, "map", std::wstring(L"random"));
     99    m_ScriptInterface->SetProperty(attribs, "mapFilter", std::wstring(L"default"));
     100    m_ScriptInterface->SetProperty(attribs, "mapPath", std::wstring(L"maps/random/"));
     101    m_ScriptInterface->SetProperty(attribs, "mapType", std::wstring(L"random"));
     102    m_ScriptInterface->SetProperty(attribs, "matchID", ps_generate_guid().FromUTF8());
     103    m_ScriptInterface->SetProperty(attribs, "playerAssignments", playerAssignments);
     104    m_ScriptInterface->SetProperty(attribs, "serverName", serverName);
     105    m_ScriptInterface->SetProperty(attribs, "settings", settings);
     106
     107    m_Worker->UpdateGameAttributes(&attribs);
     108}
     109
     110void CDedicatedServer::UpdatePlayerAssignments()
     111{
     112    JSContext* cx = m_ScriptInterface->GetContext();
     113    JSAutoRequest rq(cx);
     114
     115    JS::RootedValue attribs(cx);
     116    JS::RootedValue settings(cx);
     117    JS::RootedValue PlayerData(cx);
     118
     119    attribs.set(m_Worker->m_GameAttributes.get());
     120    m_ScriptInterface->GetProperty(attribs, "settings", &settings);
     121    m_ScriptInterface->Eval("([])", &PlayerData);
     122
     123    // Find all player IDs in active use
     124/*  std::set<i32> usedIDs;
     125    for (PlayerAssignmentMap::iterator it = m_Worker->.m_PlayerAssignments.begin(); it != m_PlayerAssignments.end(); ++it)
     126        if (it->second.m_Enabled && it->second.m_PlayerID != -1)
     127            usedIDs.insert(it->second.m_PlayerID);
     128*/
     129    // Update player data
     130    for (u8 i=0; i<m_Worker->m_PlayerAssignments.size(); i++)
     131    {
     132        JS::RootedValue player(cx);
     133        m_ScriptInterface->Eval("({})", &player);
     134        //m_ScriptInterface->SetProperty(player, "Name", "Some player");
     135        m_ScriptInterface->SetProperty(player, "Team", -1);
     136        m_ScriptInterface->SetProperty(player, "Civ", std::wstring(L"random"));
     137        m_ScriptInterface->SetProperty(player, "AI", std::wstring(L""));
     138        m_ScriptInterface->SetProperty(player, "AiDiff", 3);
     139        m_ScriptInterface->SetPropertyInt(PlayerData, i, player);
     140    }
     141    m_ScriptInterface->SetProperty(settings, "PlayerData", PlayerData);
     142
     143    // Limit pop cap according to playercount
     144    std::map<int,int> popCaps = {
     145       {1, 300}, // 600 pop total, 700 with wonder
     146       {2, 300}, // 600 pop total, 750 with wonder
     147       {3, 200}, // 600 pop total, 750 with wonder
     148       {4, 200}, // 800 pop total, 1000 with wonder
     149       {5, 150}, // 750 pop total, 1000 with wonder
     150       {6, 150}, // 900 pop total, 1200 with wonder
     151       {7, 100}, // 700 pop total, 1050 with wonder
     152       {8, 100}  // 800 pop total, 1200 with wonder
     153    };
     154    m_ScriptInterface->SetProperty(settings, "PopulationCap", popCaps[m_Worker->m_PlayerAssignments.size()]);
     155
     156    // TODO: send chat that pop cap has been adopted
     157
     158    m_ScriptInterface->SetProperty(attribs, "settings", settings);
     159
     160    m_Worker->UpdateGameAttributes(&attribs);
     161
     162    // Sends the player assignments
     163    m_Worker->ClearAllPlayerReady();
     164}
     165
     166void CDedicatedServer::OnChat(CNetServerSession* session, CChatMessage* message)
     167{
     168    LOGERROR("[HOST] %s: %s", utf8_from_wstring(session->GetUserName().c_str()), utf8_from_wstring(message->m_Message));
     169}
     170
     171void CDedicatedServer::OnReady(CNetServerSession* session, CReadyMessage* message)
     172{
     173    LOGERROR("[HOST] %s is %s", utf8_from_wstring(session->GetUserName().c_str()), message->m_Status ? "ready " : "not ready");
     174    // TODO if all ready: m_Worker->StartGame();
     175}
     176
     177void CDedicatedServer::OnUserJoin(CNetServerSession* session)
     178{
     179    // TODO: if game has started, show "is starting to rejoin"
     180    LOGERROR("[HOST] %s has joined (%s)", utf8_from_wstring(session->GetUserName()).c_str(), session->GetIPAddress().c_str());
     181    ++m_PlayerCount;
     182    UpdatePlayerAssignments();
     183}
     184
     185void CDedicatedServer::OnUserLeave(CNetServerSession* session)
     186{
     187    LOGERROR("[HOST] %s has left", utf8_from_wstring(session->GetUserName()));
     188    --m_PlayerCount;
     189    UpdatePlayerAssignments();
     190}
     191
     192void CDedicatedServer::OnUserRejoined(CNetServerSession* session)
     193{
     194    LOGERROR("[HOST] %s has finished rejoining.", utf8_from_wstring(m_Worker->m_PlayerAssignments[session->GetGUID()].m_Name.c_str()));
     195}
     196
     197void CDedicatedServer::OnStartGame()
     198{
     199    LOGERROR("[HOST] The game has started.");
     200}
  • source/network/DedicatedServer.h

     
     1/* Copyright (C) 2015 Wildfire Games.
     2 * This file is part of 0 A.D.
     3 *
     4 * 0 A.D. is free software: you can redistribute it and/or modify
     5 * it under the terms of the GNU General Public License as published by
     6 * the Free Software Foundation, either version 2 of the License, or
     7 * (at your option) any later version.
     8 *
     9 * 0 A.D. is distributed in the hope that it will be useful,
     10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     12 * GNU General Public License for more details.
     13 *
     14 * You should have received a copy of the GNU General Public License
     15 * along with 0 A.D.  If not, see <http://www.gnu.org/licenses/>.
     16 */
     17
     18// TODO: some ifndef define NETSERVER_H ?
     19
     20#include "NetServer.h"
     21#include "NetSession.h"
     22#include "NetMessage.h"
     23
     24#include "ps/GUID.h"
     25#include "scriptinterface/ScriptInterface.h"
     26
     27/**
     28 * Contains functions used by the dedicated server.
     29 */
     30class CDedicatedServer
     31{
     32    NONCOPYABLE(CDedicatedServer);
     33
     34private:
     35    friend class NetServer;
     36    friend class NetServerWorker;
     37
     38    /**
     39     * Used to control the server.
     40     */
     41    CNetServerWorker* m_Worker = nullptr;
     42
     43    /**
     44     * Used to control the server.
     45     */
     46    ScriptInterface* m_ScriptInterface = nullptr;
     47
     48    bool m_IsHosting = false;
     49
     50    /**
     51     * Used to setup the game.
     52     */
     53    u8 m_PlayerCount = 0;
     54
     55public:
     56
     57    CDedicatedServer();
     58    ~CDedicatedServer();
     59
     60    /**
     61     * Create the host. Starts listening on UDP port 20595 for player connects.
     62     */
     63    void StartHosting();
     64
     65    /*
     66     * Contains the default gamesetup atributes. Called after CNetServerWorker::Run() initializes the ScriptInterface.
     67     */
     68    void Initialize();
     69
     70    /**
     71     * Sets the number of players to the number of connected clients,
     72     * assigns unassigned players to unassigned slots,
     73     * reduces the population count accordingly,
     74     * resets ready states,
     75     * sends the player assignments.
     76     */
     77    void UpdatePlayerAssignments();
     78
     79    /**
     80     * Updates the player assignments.
     81     */
     82    void OnUserJoin(CNetServerSession* session);
     83
     84    /**
     85     * Updates the player assignments.
     86     */
     87    void OnUserLeave(CNetServerSession* session);
     88
     89    /**
     90     * Lets the users chose their own civs and team numbers.
     91     */
     92    void OnChat(CNetServerSession* session, CChatMessage* message);
     93
     94    /**
     95     * Starts the game if all players are ready.
     96     */
     97    void OnReady(CNetServerSession* session, CReadyMessage* message);
     98
     99    /**
     100     * Used for logging only.
     101     */
     102    void OnStartGame();
     103
     104    /**
     105     * Used for logging only.
     106     */
     107    void OnUserRejoined(CNetServerSession* session);
     108};
  • source/network/NetServer.cpp

    public:  
    106106        CJoinSyncStartMessage message;
    107107        session->SendMessage(&message);
    108108    }
    109109
    110110private:
     111
    111112    CNetServerWorker& m_Server;
    112113    u32 m_RejoinerHostID;
    113114};
    114115
    115116/*
    116117 * XXX: We use some non-threadsafe functions from the worker thread.
    117118 * See http://trac.wildfiregames.com/ticket/654
    118119 */
    119120
    120 CNetServerWorker::CNetServerWorker(int autostartPlayers) :
     121CNetServerWorker::CNetServerWorker(bool isDedicated, int autostartPlayers) :
     122    m_DedicatedServer(isDedicated ? new CDedicatedServer() : NULL),
    121123    m_AutostartPlayers(autostartPlayers),
    122124    m_Shutdown(false),
    123125    m_ScriptInterface(NULL),
    124126    m_NextHostID(1), m_Host(NULL), m_Stats(NULL)
    125127{
    CNetServerWorker::~CNetServerWorker()  
    159161    {
    160162        enet_host_destroy(m_Host);
    161163    }
    162164
    163165    delete m_ServerTurnManager;
     166    delete m_DedicatedServer;
    164167}
    165168
    166169bool CNetServerWorker::SetupConnection()
    167170{
    168171    ENSURE(m_State == SERVER_STATE_UNCONNECTED);
    void* CNetServerWorker::RunThread(void*  
    364367
    365368void CNetServerWorker::Run()
    366369{
    367370    // The script runtime uses the profiler and therefore the thread must be registered before the runtime is created
    368371    g_Profiler2.RegisterCurrentThread("Net server");
    369    
     372
    370373    // To avoid the need for JS_SetContextThread, we create and use and destroy
    371374    // the script interface entirely within this network thread
    372375    m_ScriptInterface = new ScriptInterface("Engine", "Net server", ScriptInterface::CreateRuntime(g_ScriptRuntime));
    373376    m_GameAttributes.set(m_ScriptInterface->GetJSRuntime(), JS::UndefinedValue());
    374377
     378    if (m_DedicatedServer)
     379        m_DedicatedServer->Initialize();
     380
    375381    while (true)
    376382    {
    377383        if (!RunStep())
    378384            break;
    379385
    bool CNetServerWorker::HandleConnect(CNe  
    617623    return session->SendMessage(&handshake);
    618624}
    619625
    620626void CNetServerWorker::OnUserJoin(CNetServerSession* session)
    621627{
    622     AddPlayer(session->GetGUID(), session->GetUserName());
     628    if (m_DedicatedServer)
     629        m_DedicatedServer->OnUserJoin(session);
     630    else
     631        AddPlayer(session->GetGUID(), session->GetUserName());
    623632
    624633    CGameSetupMessage gameSetupMessage(GetScriptInterface());
    625634    gameSetupMessage.m_Data = m_GameAttributes.get();
    626635    session->SendMessage(&gameSetupMessage);
    627636
    void CNetServerWorker::OnUserJoin(CNetSe  
    630639    session->SendMessage(&assignMessage);
    631640}
    632641
    633642void CNetServerWorker::OnUserLeave(CNetServerSession* session)
    634643{
    635     RemovePlayer(session->GetGUID());
     644    if (m_DedicatedServer)
     645        m_DedicatedServer->OnUserLeave(session);
     646    else
     647        RemovePlayer(session->GetGUID());
    636648
    637649    if (m_ServerTurnManager && session->GetCurrState() != NSS_JOIN_SYNCING)
    638650        m_ServerTurnManager->UninitialiseClient(session->GetHostID()); // TODO: only for non-observers
    639651
    640652    // TODO: ought to switch the player controlled by that client
    bool CNetServerWorker::OnAuthenticate(vo  
    858870        // Request a copy of the current game state from an existing player,
    859871        // so we can send it on to the new player
    860872
    861873        // Assume session 0 is most likely the local player, so they're
    862874        // the most efficient client to request a copy from
     875
     876        // TODO: When using a dedicated server we should use the client that didn't reconnect for the longest time
    863877        CNetServerSession* sourceSession = server.m_Sessions.at(0);
    864878        sourceSession->GetFileTransferer().StartTask(
    865879            shared_ptr<CNetFileReceiveTask>(new CNetFileReceiveTask_ServerRejoin(server, newHostID))
    866880        );
    867881
    bool CNetServerWorker::OnChat(void* cont  
    918932
    919933    CChatMessage* message = (CChatMessage*)event->GetParamRef();
    920934
    921935    message->m_GUID = session->GetGUID();
    922936
     937    if (server.m_DedicatedServer)
     938        server.m_DedicatedServer->OnChat(session, message);
     939
    923940    server.Broadcast(message);
    924941
    925942    return true;
    926943}
    927944
    bool CNetServerWorker::OnReady(void* con  
    936953
    937954    message->m_GUID = session->GetGUID();
    938955
    939956    server.Broadcast(message);
    940957
     958    if (server.m_DedicatedServer)
     959        server.m_DedicatedServer->OnReady(session, message);
     960
    941961    return true;
    942962}
    943963
    944964bool CNetServerWorker::OnLoadedGame(void* context, CFsmEvent* event)
    945965{
    bool CNetServerWorker::OnRejoined(void*  
    10171037
    10181038    CRejoinedMessage* message = (CRejoinedMessage*)event->GetParamRef();
    10191039
    10201040    message->m_GUID = session->GetGUID();
    10211041
     1042    if (server.m_DedicatedServer)
     1043        server.m_DedicatedServer->OnUserRejoined(session);
     1044
    10221045    server.Broadcast(message);
    10231046
    10241047    return true;
    10251048}
    10261049
    void CNetServerWorker::CheckGameLoadStat  
    10511074    m_State = SERVER_STATE_INGAME;
    10521075}
    10531076
    10541077void CNetServerWorker::StartGame()
    10551078{
     1079    if (m_DedicatedServer)
     1080        m_DedicatedServer->OnStartGame();
     1081
    10561082    m_ServerTurnManager = new CNetServerTurnManager(*this);
    10571083
    10581084    for (size_t i = 0; i < m_Sessions.size(); ++i)
    10591085        m_ServerTurnManager->InitialiseClient(m_Sessions[i]->GetHostID(), 0); // TODO: only for non-observers
    10601086
    void CNetServerWorker::UpdateGameAttribu  
    10811107    m_GameAttributes.set(m_ScriptInterface->GetJSRuntime(), attrs);
    10821108
    10831109    if (!m_Host)
    10841110        return;
    10851111
     1112    if (m_DedicatedServer)
     1113        LOGMESSAGE("[HOST] The game settings have been updated.");
     1114
    10861115    CGameSetupMessage gameSetupMessage(GetScriptInterface());
    10871116    gameSetupMessage.m_Data.set(m_GameAttributes.get());
    10881117    Broadcast(&gameSetupMessage);
    10891118}
    10901119
    CStrW CNetServerWorker::DeduplicatePlaye  
    11361165}
    11371166
    11381167
    11391168
    11401169
    1141 CNetServer::CNetServer(int autostartPlayers) :
    1142     m_Worker(new CNetServerWorker(autostartPlayers))
     1170CNetServer::CNetServer(bool isDedicated, int autostartPlayers) :
     1171    m_Worker(new CNetServerWorker(isDedicated, autostartPlayers))
    11431172{
    11441173}
    11451174
    11461175CNetServer::~CNetServer()
    11471176{
  • source/network/NetServer.h

     
    1616 */
    1717
    1818#ifndef NETSERVER_H
    1919#define NETSERVER_H
    2020
     21#include "DedicatedServer.h"
    2122#include "NetFileTransfer.h"
    2223#include "NetHost.h"
    2324
    2425#include "lib/config2.h"
    2526#include "ps/ThreadUtil.h"
    enum NetServerSessionState  
    8990    NSS_INGAME
    9091};
    9192
    9293/**
    9394 * Network server interface. Handles all the coordination between players.
    94  * One person runs this object, and every player (including the host) connects their CNetClient to it.
     95 * The host runs this object and every player connects their CNetClient to it.
     96 * If it is a dedicated server, the host will not be a player (nor observer).
    9597 *
    96  * The actual work is performed by CNetServerWorker in a separate thread.
     98 * The actual work is performed by CNetServerWorker and CDedicatedServer in a separate thread.
    9799 */
    98100class CNetServer
    99101{
    100102    NONCOPYABLE(CNetServer);
    101103public:
    102104    /**
    103105     * Construct a new network server.
     106     *
     107     * @param dedicated Whether or not to use dedicated mode (i.e. no graphics and no local simulation).
     108     *
    104109     * @param autostartPlayers if positive then StartGame will be called automatically
    105110     * once this many players are connected (intended for the command-line testing mode).
    106111     */
    107     CNetServer(int autostartPlayers = -1);
     112    CNetServer(bool dedicated = false, int autostartPlayers = -1);
    108113
    109114    ~CNetServer();
    110115
    111116    /**
    112117     * Begin listening for network connections.
    public:  
    153158     * TODO: we should replace this with some adapative lag-dependent computation.
    154159     */
    155160    void SetTurnLength(u32 msecs);
    156161
    157162private:
     163
     164    friend class CDedicatedServer;
     165
    158166    CNetServerWorker* m_Worker;
    159167};
    160168
    161169/**
    162170 * Network server worker thread.
    public:  
    187195     * (i.e. are in the pre-game or in-game states).
    188196     */
    189197    bool Broadcast(const CNetMessage* message);
    190198
    191199private:
     200    friend class CDedicatedServer;
    192201    friend class CNetServer;
    193202    friend class CNetFileReceiveTask_ServerRejoin;
    194203
    195     CNetServerWorker(int autostartPlayers);
     204    CNetServerWorker(bool dedicated, int autostartPlayers);
    196205    ~CNetServerWorker();
    197206
    198207    /**
    199208     * Begin listening for network connections.
    200209     * @return true on success, false on error (e.g. port already in use)
    private:  
    299308    CStrW m_ServerName;
    300309    CStrW m_WelcomeMessage;
    301310
    302311    u32 m_NextHostID;
    303312
     313    CDedicatedServer* m_DedicatedServer;
     314
    304315    CNetServerTurnManager* m_ServerTurnManager;
    305316
    306317    /**
    307318     * A copy of all simulation commands received so far, indexed by
    308319     * turn number, to simplify support for rejoining etc.
  • source/network/NetSession.cpp

    bool CNetClientSession::Connect(u16 port  
    7676        g_ProfileViewer.AddRootTable(m_Stats);
    7777
    7878    return true;
    7979}
    8080
     81CStr CNetServerSession::GetIPAddress()
     82{
     83    char ipAddress[256] = "(error)";
     84    enet_address_get_host_ip(&(m_Peer->address), ipAddress, ARRAY_SIZE(ipAddress));
     85    return CStr(ipAddress);
     86}
     87
    8188void CNetClientSession::Disconnect(u32 reason)
    8289{
    8390    ENSURE(m_Host && m_Server);
    8491
    8592    // TODO: ought to do reliable async disconnects, probably
  • source/network/NetSession.h

    public:  
    120120    void SetUserName(const CStrW& name) { m_UserName = name; }
    121121
    122122    u32 GetHostID() const { return m_HostID; }
    123123    void SetHostID(u32 id) { m_HostID = id; }
    124124
     125    /**
     126     * Returns the IP address of the client.
     127     */
     128    CStr GetIPAddress();
     129
    125130    /**
    126131     * Sends a disconnection notification to the client,
    127132     * and sends a NMT_CONNECTION_LOST message to the session FSM.
    128133     * The server will receive a disconnection notification after a while.
    129134     * The server will not receive any further messages sent via this session.
  • source/network/NetTurnManager.cpp

    void CNetServerTurnManager::NotifyFinish  
    630630    {
    631631        if (it->first > newest)
    632632            break;
    633633
    634634        // Assume the host is correct (maybe we should choose the most common instead to help debugging)
     635        // TODO: for dedicated hosts, we have to chose the hash of a client that didn't rejoin for the longest period
    635636        std::string expected = it->second.begin()->second;
    636637
    637638        // Find all players that are OOS on that turn
    638639        std::vector<CStrW> OOSPlayerNames;
    639640        for (std::map<int, std::string>::iterator cit = it->second.begin(); cit != it->second.end(); ++cit)
  • source/ps/GameSetup/GameSetup.cpp

    bool Init(const CmdLineArgs& args, int f  
    933933    }
    934934
    935935    CNetHost::Initialize();
    936936
    937937#if CONFIG2_AUDIO
    938     ISoundManager::CreateSoundManager();
     938    if (!args.Has("dedicated-host"))
     939        ISoundManager::CreateSoundManager();
    939940#endif
    940941
    941942    // Check if there are mods specified on the command line,
    942943    // or if we already set the mods (~INIT_MODS),
    943944    // else check if there are mods that should be loaded specified