Ticket #3700: 3700.3.patch

File 3700.3.patch, 26.4 KB (added by Andy Alt, 7 years ago)

minor changes from the previous version, for the purpose of clarity as elexis and I discuss it further on IRC

  • source/gui/scripting/ScriptFunctions.cpp

     
    349349    }
    350350
    351351    g_Game = new CGame();
    352     g_NetClient = new CNetClient(g_Game, true);
     352    g_NetClient = new CNetClientWorker(g_Game, true);
    353353    g_NetClient->SetUserName(playerName);
    354354
    355355    if (!g_NetClient->SetupConnection("127.0.0.1", serverPort))
     
    367367    ENSURE(!g_Game);
    368368
    369369    g_Game = new CGame();
    370     g_NetClient = new CNetClient(g_Game, false);
     370    g_NetClient = new CNetClientWorker(g_Game, false);
    371371    g_NetClient->SetUserName(playerName);
    372372    if (!g_NetClient->SetupConnection(serverAddress, serverPort))
    373373    {
  • source/network/NetClient.cpp

     
    4545{
    4646    NONCOPYABLE(CNetFileReceiveTask_ClientRejoin);
    4747public:
    48     CNetFileReceiveTask_ClientRejoin(CNetClient& client)
     48    CNetFileReceiveTask_ClientRejoin(CNetClientWorker& client)
    4949        : m_Client(client)
    5050    {
    5151    }
     
    6363    }
    6464
    6565private:
    66     CNetClient& m_Client;
     66    CNetClientWorker& m_Client;
    6767};
    6868
    69 CNetClient::CNetClient(CGame* game, bool isLocalClient) :
     69CNetClientWorker::CNetClientWorker(CGame* game, bool isLocalClient) :
    7070    m_Session(NULL),
    7171    m_UserName(L"anonymous"),
    7272    m_GUID(ps_generate_guid()), m_HostID((u32)-1), m_ClientTurnManager(NULL), m_Game(game),
     
    7979
    8080    void* context = this;
    8181
    82     JS_AddExtraGCRootsTracer(GetScriptInterface().GetJSRuntime(), CNetClient::Trace, this);
     82    JS_AddExtraGCRootsTracer(GetScriptInterface().GetJSRuntime(), CNetClientWorker::Trace, this);
    8383
    8484    // Set up transitions for session
    8585    AddTransition(NCS_UNCONNECTED, (uint)NMT_CONNECT_COMPLETE, NCS_CONNECT, (void*)&OnConnect, context);
     
    139139    SetFirstState(NCS_UNCONNECTED);
    140140}
    141141
    142 CNetClient::~CNetClient()
     142CNetClientWorker::~CNetClientWorker()
    143143{
    144144    DestroyConnection();
    145     JS_RemoveExtraGCRootsTracer(GetScriptInterface().GetJSRuntime(), CNetClient::Trace, this);
     145    JS_RemoveExtraGCRootsTracer(GetScriptInterface().GetJSRuntime(), CNetClientWorker::Trace, this);
     146
     147    /*  if (m_State != SERVER_STATE_UNCONNECTED)
     148    {
     149        // Tell the thread to shut down
     150        {
     151            CScopeLock lock(m_WorkerMutex);
     152            m_Shutdown = true;
     153        }
     154
     155        // Wait for it to shut down cleanly
     156        pthread_join(m_WorkerThread, NULL);
     157    }
     158
     159    // Clean up resources
     160
     161    delete m_Stats;
     162
     163    for (CNetServerSession* session : m_Sessions)
     164    {
     165        session->DisconnectNow(NDR_SERVER_SHUTDOWN);
     166        delete session;
     167    }
     168
     169    if (m_Host)
     170        enet_host_destroy(m_Host);
     171
     172    delete m_ServerTurnManager; */
    146173}
    147174
    148 void CNetClient::TraceMember(JSTracer *trc)
     175void CNetClientWorker::TraceMember(JSTracer *trc)
    149176{
    150177    for (JS::Heap<JS::Value>& guiMessage : m_GuiMessageQueue)
    151178        JS_CallValueTracer(trc, &guiMessage, "m_GuiMessageQueue");
    152179}
    153180
    154 void CNetClient::SetUserName(const CStrW& username)
     181void CNetClientWorker::SetUserName(const CStrW& username)
    155182{
    156183    ENSURE(!m_Session); // must be called before we start the connection
    157184
     
    158185    m_UserName = username;
    159186}
    160187
    161 bool CNetClient::SetupConnection(const CStr& server, const u16 port)
     188bool CNetClientWorker::SetupConnection(const CStr& server, const u16 port)
    162189{
    163190    CNetClientSession* session = new CNetClientSession(*this);
    164191    bool ok = session->Connect(server, port, m_IsLocalClient);
    165192    SetAndOwnSession(session);
     193
     194    //m_State = SERVER_STATE_PREGAME;
     195
     196    // Launch the worker thread
     197    int ret = pthread_create(&m_WorkerThread, NULL, &RunThread, this);
     198    ENSURE(ret == 0);
     199
    166200    return ok;
    167201}
    168202
    169 void CNetClient::SetAndOwnSession(CNetClientSession* session)
     203void CNetClientWorker::SetAndOwnSession(CNetClientSession* session)
    170204{
    171205    delete m_Session;
    172206    m_Session = session;
    173207}
    174208
    175 void CNetClient::DestroyConnection()
     209void CNetClientWorker::DestroyConnection()
    176210{
    177211    // Send network messages from the current frame before connection is destroyed.
    178212    if (m_ClientTurnManager)
     
    183217    SAFE_DELETE(m_Session);
    184218}
    185219
    186 void CNetClient::Poll()
     220void CNetClientWorker::Poll()
    187221{
    188222    if (!m_Session)
    189223        return;
     
    192226    m_Session->Poll();
    193227}
    194228
    195 void CNetClient::CheckServerConnection()
     229void* CNetClientWorker::RunThread(void* data)
    196230{
     231    debug_SetThreadName("NetClient");
     232
     233    static_cast<CNetClientWorker*>(data)->Run();
     234
     235    return NULL;
     236}
     237
     238void CNetClientWorker::Run()
     239{
     240    // The script runtime uses the profiler and therefore the thread must be registered before the runtime is created
     241    g_Profiler2.RegisterCurrentThread("Net client");
     242
     243    // To avoid the need for JS_SetContextThread, we create and use and destroy
     244    // the script interface entirely within this network thread
     245    m_ScriptInterface = new ScriptInterface("Engine", "Net client", ScriptInterface::CreateRuntime(g_ScriptRuntime));
     246    m_GameAttributes.init(m_ScriptInterface->GetJSRuntime(), JS::UndefinedValue());
     247
     248    while (true)
     249    {
     250        if (!RunStep())
     251            break;
     252
     253        // Implement autostart mode
     254        //if (m_State == CLIENT_STATE_PREGAME && (int)m_PlayerAssignments.size() == m_AutostartPlayers)
     255        //  StartGame();
     256
     257        // Update profiler stats
     258        //m_Stats->LatchHostState(m_Host);
     259    }
     260}
     261
     262bool CNetClientWorker::RunStep()
     263{
     264    // Check for messages from the game thread.
     265    // (Do as little work as possible while the mutex is held open,
     266    // to avoid performance problems and deadlocks.)
     267
     268    CheckServerConnection();
     269
     270    return true;
     271}
     272
     273void CNetClientWorker::CheckServerConnection()
     274{
    197275    // Trigger local warnings if the connection to the server is bad.
    198276    // At most once per second.
    199277    std::time_t now = std::time(nullptr);
     
    227305    }
    228306}
    229307
    230 void CNetClient::Flush()
     308void CNetClientWorker::Flush()
    231309{
    232310    if (m_Session)
    233311        m_Session->Flush();
    234312}
    235313
    236 void CNetClient::GuiPoll(JS::MutableHandleValue ret)
     314void CNetClientWorker::GuiPoll(JS::MutableHandleValue ret)
    237315{
    238316    if (m_GuiMessageQueue.empty())
    239317    {
     
    245323    m_GuiMessageQueue.pop_front();
    246324}
    247325
    248 void CNetClient::PushGuiMessage(const JS::HandleValue message)
     326void CNetClientWorker::PushGuiMessage(const JS::HandleValue message)
    249327{
    250328    ENSURE(!message.isUndefined());
    251329
     
    252330    m_GuiMessageQueue.push_back(JS::Heap<JS::Value>(message));
    253331}
    254332
    255 std::string CNetClient::TestReadGuiMessages()
     333std::string CNetClientWorker::TestReadGuiMessages()
    256334{
    257335    JSContext* cx = GetScriptInterface().GetContext();
    258336    JSAutoRequest rq(cx);
     
    269347    return r;
    270348}
    271349
    272 ScriptInterface& CNetClient::GetScriptInterface()
     350ScriptInterface& CNetClientWorker::GetScriptInterface()
    273351{
    274352    return m_Game->GetSimulation2()->GetScriptInterface();
    275353}
    276354
    277 void CNetClient::PostPlayerAssignmentsToScript()
     355void CNetClientWorker::PostPlayerAssignmentsToScript()
    278356{
    279357    JSContext* cx = GetScriptInterface().GetContext();
    280358    JSAutoRequest rq(cx);
     
    298376    PushGuiMessage(msg);
    299377}
    300378
    301 bool CNetClient::SendMessage(const CNetMessage* message)
     379bool CNetClientWorker::SendMessage(const CNetMessage* message)
    302380{
    303381    if (!m_Session)
    304382        return false;
     
    306384    return m_Session->SendMessage(message);
    307385}
    308386
    309 void CNetClient::HandleConnect()
     387void CNetClientWorker::HandleConnect()
    310388{
    311389    Update((uint)NMT_CONNECT_COMPLETE, NULL);
    312390}
    313391
    314 void CNetClient::HandleDisconnect(u32 reason)
     392void CNetClientWorker::HandleDisconnect(u32 reason)
    315393{
    316394    JSContext* cx = GetScriptInterface().GetContext();
    317395    JSAutoRequest rq(cx);
     
    328406    SetCurrState(NCS_UNCONNECTED);
    329407}
    330408
    331 void CNetClient::SendGameSetupMessage(JS::MutableHandleValue attrs, ScriptInterface& scriptInterface)
     409void CNetClientWorker::SendGameSetupMessage(JS::MutableHandleValue attrs, ScriptInterface& scriptInterface)
    332410{
    333411    CGameSetupMessage gameSetup(scriptInterface);
    334412    gameSetup.m_Data = attrs;
     
    335413    SendMessage(&gameSetup);
    336414}
    337415
    338 void CNetClient::SendAssignPlayerMessage(const int playerID, const CStr& guid)
     416void CNetClientWorker::SendAssignPlayerMessage(const int playerID, const CStr& guid)
    339417{
    340418    CAssignPlayerMessage assignPlayer;
    341419    assignPlayer.m_PlayerID = playerID;
     
    343421    SendMessage(&assignPlayer);
    344422}
    345423
    346 void CNetClient::SendChatMessage(const std::wstring& text)
     424void CNetClientWorker::SendChatMessage(const std::wstring& text)
    347425{
    348426    CChatMessage chat;
    349427    chat.m_Message = text;
     
    350428    SendMessage(&chat);
    351429}
    352430
    353 void CNetClient::SendReadyMessage(const int status)
     431void CNetClientWorker::SendReadyMessage(const int status)
    354432{
    355433    CReadyMessage readyStatus;
    356434    readyStatus.m_Status = status;
     
    357435    SendMessage(&readyStatus);
    358436}
    359437
    360 void CNetClient::SendClearAllReadyMessage()
     438void CNetClientWorker::SendClearAllReadyMessage()
    361439{
    362440    CClearAllReadyMessage clearAllReady;
    363441    SendMessage(&clearAllReady);
    364442}
    365443
    366 void CNetClient::SendStartGameMessage()
     444void CNetClientWorker::SendStartGameMessage()
    367445{
    368446    CGameStartMessage gameStart;
    369447    SendMessage(&gameStart);
    370448}
    371449
    372 void CNetClient::SendRejoinedMessage()
     450void CNetClientWorker::SendRejoinedMessage()
    373451{
    374452    CRejoinedMessage rejoinedMessage;
    375453    SendMessage(&rejoinedMessage);
    376454}
    377455
    378 void CNetClient::SendKickPlayerMessage(const CStrW& playerName, bool ban)
     456void CNetClientWorker::SendKickPlayerMessage(const CStrW& playerName, bool ban)
    379457{
    380458    CKickedMessage kickPlayer;
    381459    kickPlayer.m_Name = playerName;
     
    383461    SendMessage(&kickPlayer);
    384462}
    385463
    386 void CNetClient::SendPausedMessage(bool pause)
     464void CNetClientWorker::SendPausedMessage(bool pause)
    387465{
    388466    CClientPausedMessage pausedMessage;
    389467    pausedMessage.m_Pause = pause;
     
    390468    SendMessage(&pausedMessage);
    391469}
    392470
    393 bool CNetClient::HandleMessage(CNetMessage* message)
     471bool CNetClientWorker::HandleMessage(CNetMessage* message)
    394472{
    395473    // Handle non-FSM messages first
    396474
     
    433511    return ok;
    434512}
    435513
    436 void CNetClient::LoadFinished()
     514void CNetClientWorker::LoadFinished()
    437515{
    438516    JSContext* cx = GetScriptInterface().GetContext();
    439517    JSAutoRequest rq(cx);
     
    476554    SendMessage(&loaded);
    477555}
    478556
    479 bool CNetClient::OnConnect(void* context, CFsmEvent* event)
     557bool CNetClientWorker::OnConnect(void* context, CFsmEvent* event)
    480558{
    481559    ENSURE(event->GetType() == (uint)NMT_CONNECT_COMPLETE);
    482560
    483     CNetClient* client = (CNetClient*)context;
     561    CNetClientWorker* client = (CNetClientWorker*)context;
    484562
    485563    JSContext* cx = client->GetScriptInterface().GetContext();
    486564    JSAutoRequest rq(cx);
     
    492570    return true;
    493571}
    494572
    495 bool CNetClient::OnHandshake(void* context, CFsmEvent* event)
     573bool CNetClientWorker::OnHandshake(void* context, CFsmEvent* event)
    496574{
    497575    ENSURE(event->GetType() == (uint)NMT_SERVER_HANDSHAKE);
    498576
    499     CNetClient* client = (CNetClient*)context;
     577    CNetClientWorker* client = (CNetClientWorker*)context;
    500578
    501579    CCliHandshakeMessage handshake;
    502580    handshake.m_MagicResponse = PS_PROTOCOL_MAGIC_RESPONSE;
     
    507585    return true;
    508586}
    509587
    510 bool CNetClient::OnHandshakeResponse(void* context, CFsmEvent* event)
     588bool CNetClientWorker::OnHandshakeResponse(void* context, CFsmEvent* event)
    511589{
    512590    ENSURE(event->GetType() == (uint)NMT_SERVER_HANDSHAKE_RESPONSE);
    513591
    514     CNetClient* client = (CNetClient*)context;
     592    CNetClientWorker* client = (CNetClientWorker*)context;
    515593
    516594    CAuthenticateMessage authenticate;
    517595    authenticate.m_GUID = client->m_GUID;
     
    523601    return true;
    524602}
    525603
    526 bool CNetClient::OnAuthenticate(void* context, CFsmEvent* event)
     604bool CNetClientWorker::OnAuthenticate(void* context, CFsmEvent* event)
    527605{
    528606    ENSURE(event->GetType() == (uint)NMT_AUTHENTICATE_RESULT);
    529607
    530     CNetClient* client = (CNetClient*)context;
     608    CNetClientWorker* client = (CNetClientWorker*)context;
    531609
    532610    JSContext* cx = client->GetScriptInterface().GetContext();
    533611    JSAutoRequest rq(cx);
     
    547625    return true;
    548626}
    549627
    550 bool CNetClient::OnChat(void* context, CFsmEvent* event)
     628bool CNetClientWorker::OnChat(void* context, CFsmEvent* event)
    551629{
    552630    ENSURE(event->GetType() == (uint)NMT_CHAT);
    553631
    554     CNetClient* client = (CNetClient*)context;
     632    CNetClientWorker* client = (CNetClientWorker*)context;
    555633    JSContext* cx = client->GetScriptInterface().GetContext();
    556634    JSAutoRequest rq(cx);
    557635
     
    566644    return true;
    567645}
    568646
    569 bool CNetClient::OnReady(void* context, CFsmEvent* event)
     647bool CNetClientWorker::OnReady(void* context, CFsmEvent* event)
    570648{
    571649    ENSURE(event->GetType() == (uint)NMT_READY);
    572650
    573     CNetClient* client = (CNetClient*)context;
     651    CNetClientWorker* client = (CNetClientWorker*)context;
    574652    JSContext* cx = client->GetScriptInterface().GetContext();
    575653    JSAutoRequest rq(cx);
    576654
     
    585663    return true;
    586664}
    587665
    588 bool CNetClient::OnGameSetup(void* context, CFsmEvent* event)
     666bool CNetClientWorker::OnGameSetup(void* context, CFsmEvent* event)
    589667{
    590668    ENSURE(event->GetType() == (uint)NMT_GAME_SETUP);
    591669
    592     CNetClient* client = (CNetClient*)context;
     670    CNetClientWorker* client = (CNetClientWorker*)context;
    593671    JSContext* cx = client->GetScriptInterface().GetContext();
    594672    JSAutoRequest rq(cx);
    595673
     
    605683    return true;
    606684}
    607685
    608 bool CNetClient::OnPlayerAssignment(void* context, CFsmEvent* event)
     686bool CNetClientWorker::OnPlayerAssignment(void* context, CFsmEvent* event)
    609687{
    610688    ENSURE(event->GetType() == (uint)NMT_PLAYER_ASSIGNMENT);
    611689
    612     CNetClient* client = (CNetClient*)context;
     690    CNetClientWorker* client = (CNetClientWorker*)context;
    613691
    614692    CPlayerAssignmentMessage* message = (CPlayerAssignmentMessage*)event->GetParamRef();
    615693
     
    632710    return true;
    633711}
    634712
    635 bool CNetClient::OnGameStart(void* context, CFsmEvent* event)
     713bool CNetClientWorker::OnGameStart(void* context, CFsmEvent* event)
    636714{
    637715    ENSURE(event->GetType() == (uint)NMT_GAME_START);
    638716
    639     CNetClient* client = (CNetClient*)context;
     717    CNetClientWorker* client = (CNetClientWorker*)context;
    640718    JSContext* cx = client->GetScriptInterface().GetContext();
    641719    JSAutoRequest rq(cx);
    642720
     
    658736    return true;
    659737}
    660738
    661 bool CNetClient::OnJoinSyncStart(void* context, CFsmEvent* event)
     739bool CNetClientWorker::OnJoinSyncStart(void* context, CFsmEvent* event)
    662740{
    663741    ENSURE(event->GetType() == (uint)NMT_JOIN_SYNC_START);
    664742
    665     CNetClient* client = (CNetClient*)context;
     743    CNetClientWorker* client = (CNetClientWorker*)context;
    666744
    667745    // The server wants us to start downloading the game state from it, so do so
    668746    client->m_Session->GetFileTransferer().StartTask(
     
    672750    return true;
    673751}
    674752
    675 bool CNetClient::OnJoinSyncEndCommandBatch(void* context, CFsmEvent* event)
     753bool CNetClientWorker::OnJoinSyncEndCommandBatch(void* context, CFsmEvent* event)
    676754{
    677755    ENSURE(event->GetType() == (uint)NMT_END_COMMAND_BATCH);
    678756
    679     CNetClient* client = (CNetClient*)context;
     757    CNetClientWorker* client = (CNetClientWorker*)context;
    680758
    681759    CEndCommandBatchMessage* endMessage = (CEndCommandBatchMessage*)event->GetParamRef();
    682760
     
    688766    return true;
    689767}
    690768
    691 bool CNetClient::OnRejoined(void* context, CFsmEvent* event)
     769bool CNetClientWorker::OnRejoined(void* context, CFsmEvent* event)
    692770{
    693771    ENSURE(event->GetType() == (uint)NMT_REJOINED);
    694772
    695     CNetClient* client = (CNetClient*)context;
     773    CNetClientWorker* client = (CNetClientWorker*)context;
    696774    JSContext* cx = client->GetScriptInterface().GetContext();
    697775    JSAutoRequest rq(cx);
    698776
     
    705783    return true;
    706784}
    707785
    708 bool CNetClient::OnKicked(void *context, CFsmEvent* event)
     786bool CNetClientWorker::OnKicked(void *context, CFsmEvent* event)
    709787{
    710788    ENSURE(event->GetType() == (uint)NMT_KICKED);
    711789
    712     CNetClient* client = (CNetClient*)context;
     790    CNetClientWorker* client = (CNetClientWorker*)context;
    713791    JSContext* cx = client->GetScriptInterface().GetContext();
    714792    JSAutoRequest rq(cx);
    715793
     
    725803    return true;
    726804}
    727805
    728 bool CNetClient::OnClientTimeout(void *context, CFsmEvent* event)
     806bool CNetClientWorker::OnClientTimeout(void *context, CFsmEvent* event)
    729807{
    730808    // Report the timeout of some other client
    731809
    732810    ENSURE(event->GetType() == (uint)NMT_CLIENT_TIMEOUT);
    733811
    734     CNetClient* client = (CNetClient*)context;
     812    CNetClientWorker* client = (CNetClientWorker*)context;
    735813    JSContext* cx = client->GetScriptInterface().GetContext();
    736814    JSAutoRequest rq(cx);
    737815
     
    749827    return true;
    750828}
    751829
    752 bool CNetClient::OnClientPerformance(void *context, CFsmEvent* event)
     830bool CNetClientWorker::OnClientPerformance(void *context, CFsmEvent* event)
    753831{
    754832    // Performance statistics for one or multiple clients
    755833
    756834    ENSURE(event->GetType() == (uint)NMT_CLIENT_PERFORMANCE);
    757835
    758     CNetClient* client = (CNetClient*)context;
     836    CNetClientWorker* client = (CNetClientWorker*)context;
    759837    JSContext* cx = client->GetScriptInterface().GetContext();
    760838    JSAutoRequest rq(cx);
    761839
     
    780858    return true;
    781859}
    782860
    783 bool CNetClient::OnClientsLoading(void *context, CFsmEvent *event)
     861bool CNetClientWorker::OnClientsLoading(void *context, CFsmEvent *event)
    784862{
    785863    ENSURE(event->GetType() == (uint)NMT_CLIENTS_LOADING);
    786864
     
    791869    for (const CClientsLoadingMessage::S_m_Clients& client : message->m_Clients)
    792870        guids.push_back(client.m_GUID);
    793871
    794     CNetClient* client = (CNetClient*)context;
     872    CNetClientWorker* client = (CNetClientWorker*)context;
    795873    JSContext* cx = client->GetScriptInterface().GetContext();
    796874    JSAutoRequest rq(cx);
    797875
     
    802880    return true;
    803881}
    804882
    805 bool CNetClient::OnClientPaused(void *context, CFsmEvent *event)
     883bool CNetClientWorker::OnClientPaused(void *context, CFsmEvent *event)
    806884{
    807885    ENSURE(event->GetType() == (uint)NMT_CLIENT_PAUSED);
    808886
    809     CNetClient* client = (CNetClient*)context;
     887    CNetClientWorker* client = (CNetClientWorker*)context;
    810888    JSContext* cx = client->GetScriptInterface().GetContext();
    811889    JSAutoRequest rq(cx);
    812890
     
    821899    return true;
    822900}
    823901
    824 bool CNetClient::OnLoadedGame(void* context, CFsmEvent* event)
     902bool CNetClientWorker::OnLoadedGame(void* context, CFsmEvent* event)
    825903{
    826904    ENSURE(event->GetType() == (uint)NMT_LOADED_GAME);
    827905
    828     CNetClient* client = (CNetClient*)context;
     906    CNetClientWorker* client = (CNetClientWorker*)context;
    829907    JSContext* cx = client->GetScriptInterface().GetContext();
    830908    JSAutoRequest rq(cx);
    831909
     
    844922    return true;
    845923}
    846924
    847 bool CNetClient::OnInGame(void *context, CFsmEvent* event)
     925bool CNetClientWorker::OnInGame(void *context, CFsmEvent* event)
    848926{
    849927    // TODO: should split each of these cases into a separate method
    850928
    851     CNetClient* client = (CNetClient*)context;
     929    CNetClientWorker* client = (CNetClientWorker*)context;
    852930
    853931    CNetMessage* message = (CNetMessage*)event->GetParamRef();
    854932    if (message)
     
    872950
    873951    return true;
    874952}
     953
     954CNetClient::CNetClient(CGame* game, bool isLocalClient) :
     955    m_Worker(new CNetClient(autostartPlayers))
     956{
     957}
     958
     959CNetClient::~CNetClient()
     960{
     961    delete m_Worker;
     962}
     963
     964void CNetClient::DestroyConnection()
     965{
     966}
     967
     968void CNetClient::TraceMember(JSTracer *trc)
     969{
     970}
     971
     972void CNetClient::SetUserName(const CStrW& username)
     973{
     974    m_Worker->username = username;
     975}
     976
     977bool CNetClient::SetupConnection(const u16 port)
     978{
     979    return m_Worker->SetupConnection(port);
     980}
     981
     982
     983
     984
  • source/network/NetClient.h

     
    2323#include "network/NetHost.h"
    2424#include "scriptinterface/ScriptVal.h"
    2525
     26#include "ps/ThreadUtil.h"
    2627#include "ps/CStr.h"
    2728
    2829#include <deque>
     
    3334class CNetServer;
    3435class ScriptInterface;
    3536
     37class CNetClientWorker;
     38
    3639// NetClient session FSM states
    3740enum
    3841{
     
    107110     */
    108111    void DestroyConnection();
    109112
     113private:
     114    CStr m_GUID;
     115    CNetClientWorker* m_Worker;
     116};
     117
     118/**
     119 * Network client worker thread.
     120 *
     121 * Thread-safety:
     122 *
     123 *
     124 */
     125class CNetClientWorker : public CFsm
     126{
     127    NONCOPYABLE(CNetClientWorker);
     128
     129public:
    110130    /**
     131     * Returns the GUID of the local client.
     132     * Used for distinguishing observers.
     133     */
     134    CStr GetGUID() const { return m_GUID; }
     135
     136    /**
     137     * Send a message to the server.
     138     * @param message message to send
     139     * @return true on success
     140     */
     141    bool SendMessage(const CNetMessage* message);
     142
     143    /**
     144     * Call when the network connection has been successfully initiated.
     145     */
     146    void HandleConnect();
     147
     148    /**
     149     * Call when the network connection has been lost.
     150     */
     151    void HandleDisconnect(u32 reason);
     152
     153    /**
     154     * Call when a message has been received from the network.
     155     */
     156    bool HandleMessage(CNetMessage* message);
     157
     158    /**
     159     * Get the script interface associated with this network client,
     160     * which is equivalent to the one used by the CGame in the constructor.
     161     */
     162    ScriptInterface& GetScriptInterface();
     163
     164private:
     165    friend class CNetClient;
     166    friend class CNetFileReceiveTask_ClientRejoin;
     167
     168    CNetClientWorker(CGame* game, bool isLocalClient);
     169  ~CNetClientWorker();
     170
     171    /**
     172     * We assume that adding a tracing function that's only called
     173     * during GC is better for performance than using a
     174     * PersistentRooted<T> where each value needs to be added to
     175     * the root set.
     176     */
     177    static void Trace(JSTracer *trc, void *data)
     178    {
     179        reinterpret_cast<CNetClientWorker*>(data)->TraceMember(trc);
     180    }
     181
     182    void TraceMember(JSTracer *trc);
     183
     184    void SetUserName(const CStrW& username);
     185
     186    bool SetupConnection(const CStr& server, const u16 port);
     187
     188    /**
     189     * Destroy the connection to the server.
     190     * This client probably cannot be used again.
     191     */
     192    void DestroyConnection();
     193
     194    /**
    111195     * Poll the connection for messages from the server and process them, and send
    112196     * any queued messages.
    113197     * This must be called frequently (i.e. once per frame).
     
    154238    std::string TestReadGuiMessages();
    155239
    156240    /**
    157      * Get the script interface associated with this network client,
    158      * which is equivalent to the one used by the CGame in the constructor.
    159      */
    160     ScriptInterface& GetScriptInterface();
    161 
    162     /**
    163      * Send a message to the server.
    164      * @param message message to send
    165      * @return true on success
    166      */
    167     bool SendMessage(const CNetMessage* message);
    168 
    169     /**
    170      * Call when the network connection has been successfully initiated.
    171      */
    172     void HandleConnect();
    173 
    174     /**
    175      * Call when the network connection has been lost.
    176      */
    177     void HandleDisconnect(u32 reason);
    178 
    179     /**
    180      * Call when a message has been received from the network.
    181      */
    182     bool HandleMessage(CNetMessage* message);
    183 
    184     /**
    185241     * Call when the game has started and all data files have been loaded,
    186242     * to signal to the server that we are ready to begin the game.
    187243     */
     
    215271     */
    216272    void SendPausedMessage(bool pause);
    217273
    218 private:
    219274    // Net message / FSM transition handlers
    220275    static bool OnConnect(void* context, CFsmEvent* event);
    221276    static bool OnHandshake(void* context, CFsmEvent* event);
     
    282337
    283338    /// Time when the server was last checked for timeouts and bad latency
    284339    std::time_t m_LastConnectionCheck;
     340
     341        // Thread-related stuff:
     342
     343    static void* RunThread(void* data);
     344    void Run();
     345    bool RunStep();
     346
     347    pthread_t m_WorkerThread;
     348    CMutex m_WorkerMutex;
     349
     350    bool m_Shutdown; // protected by m_WorkerMutex
     351
     352    // Queues for messages sent by the game thread:
     353    std::vector<bool> m_StartGameQueue; // protected by m_WorkerMutex
     354    std::vector<std::string> m_GameAttributesQueue; // protected by m_WorkerMutex
     355    std::vector<u32> m_TurnLengthQueue; // protected by m_WorkerMutex
    285356};
    286357
    287358/// Global network client for the standard game
  • source/network/NetClientTurnManager.cpp

     
    3333#define NETCLIENTTURN_LOG(...)
    3434#endif
    3535
    36 CNetClientTurnManager::CNetClientTurnManager(CSimulation2& simulation, CNetClient& client, int clientId, IReplayLogger& replay)
     36CNetClientTurnManager::CNetClientTurnManager(CSimulation2& simulation, CNetClientWorker& client, int clientId, IReplayLogger& replay)
    3737    : CTurnManager(simulation, DEFAULT_TURN_LENGTH_MP, clientId, replay), m_NetClient(client)
    3838{
    3939}
  • source/network/NetClientTurnManager.h

     
    2121#include "simulation2/system/TurnManager.h"
    2222#include "NetMessage.h"
    2323
    24 class CNetClient;
     24class CNetClientWorker;
    2525
    2626/**
    2727 * Implementation of CTurnManager for network clients.
     
    3030{
    3131    NONCOPYABLE(CNetClientTurnManager);
    3232public:
    33     CNetClientTurnManager(CSimulation2& simulation, CNetClient& client, int clientId, IReplayLogger& replay);
     33    CNetClientTurnManager(CSimulation2& simulation, CNetClientWorker& client, int clientId, IReplayLogger& replay);
    3434
    3535    void OnSimulationMessage(CSimulationMessage* msg) override;
    3636
     
    4848
    4949    void NotifyFinishedUpdate(u32 turn) override;
    5050
    51     CNetClient& m_NetClient;
     51    CNetClientWorker& m_NetClient;
    5252};
    5353
    5454#endif // INCLUDED_NETCLIENTTURNMANAGER
  • source/network/NetSession.cpp

     
    3232
    3333static const int CHANNEL_COUNT = 1;
    3434
    35 CNetClientSession::CNetClientSession(CNetClient& client) :
     35CNetClientSession::CNetClientSession(CNetClientWorker& client) :
    3636    m_Client(client), m_FileTransferer(this), m_Host(NULL), m_Server(NULL), m_Stats(NULL)
    3737{
    3838}
  • source/network/NetSession.h

     
    3434 */
    3535extern const u32 MAXIMUM_HOST_TIMEOUT;
    3636
    37 class CNetClient;
     37class CNetClientWorker;
    3838class CNetServerWorker;
    3939
    4040class CNetStatsTable;
     
    6767    NONCOPYABLE(CNetClientSession);
    6868
    6969public:
    70     CNetClientSession(CNetClient& client);
     70    CNetClientSession(CNetClientWorker& client);
    7171    ~CNetClientSession();
    7272
    7373    bool Connect(const CStr& server, const u16 port, const bool isLocalClient);
     
    106106    CNetFileTransferer& GetFileTransferer() { return m_FileTransferer; }
    107107
    108108private:
    109     CNetClient& m_Client;
     109    CNetClientWorker& m_Client;
    110110
    111111    CNetFileTransferer m_FileTransferer;
    112112
  • source/ps/GameSetup/GameSetup.cpp

     
    14981498        bool ok = g_NetServer->SetupConnection(PS_DEFAULT_PORT);
    14991499        ENSURE(ok);
    15001500
    1501         g_NetClient = new CNetClient(g_Game, true);
     1501        g_NetClient = new CNetClientWorker(g_Game, true);
    15021502        g_NetClient->SetUserName(userName);
    15031503        g_NetClient->SetupConnection("127.0.0.1", PS_DEFAULT_PORT);
    15041504    }
     
    15061506    {
    15071507        InitPs(true, L"page_loading.xml", &scriptInterface, mpInitData);
    15081508
    1509         g_NetClient = new CNetClient(g_Game, false);
     1509        g_NetClient = new CNetClientWorker(g_Game, false);
    15101510        g_NetClient->SetUserName(userName);
    15111511
    15121512        CStr ip = args.Get("autostart-client");