Index: source/gui/scripting/ScriptFunctions.cpp =================================================================== --- source/gui/scripting/ScriptFunctions.cpp (revision 19356) +++ source/gui/scripting/ScriptFunctions.cpp (working copy) @@ -349,7 +349,7 @@ } g_Game = new CGame(); - g_NetClient = new CNetClient(g_Game, true); + g_NetClient = new CNetClientWorker(g_Game, true); g_NetClient->SetUserName(playerName); if (!g_NetClient->SetupConnection("127.0.0.1", serverPort)) @@ -367,7 +367,7 @@ ENSURE(!g_Game); g_Game = new CGame(); - g_NetClient = new CNetClient(g_Game, false); + g_NetClient = new CNetClientWorker(g_Game, false); g_NetClient->SetUserName(playerName); if (!g_NetClient->SetupConnection(serverAddress, serverPort)) { Index: source/network/NetClient.cpp =================================================================== --- source/network/NetClient.cpp (revision 19356) +++ source/network/NetClient.cpp (working copy) @@ -45,7 +45,7 @@ { NONCOPYABLE(CNetFileReceiveTask_ClientRejoin); public: - CNetFileReceiveTask_ClientRejoin(CNetClient& client) + CNetFileReceiveTask_ClientRejoin(CNetClientWorker& client) : m_Client(client) { } @@ -63,10 +63,10 @@ } private: - CNetClient& m_Client; + CNetClientWorker& m_Client; }; -CNetClient::CNetClient(CGame* game, bool isLocalClient) : +CNetClientWorker::CNetClientWorker(CGame* game, bool isLocalClient) : m_Session(NULL), m_UserName(L"anonymous"), m_GUID(ps_generate_guid()), m_HostID((u32)-1), m_ClientTurnManager(NULL), m_Game(game), @@ -79,7 +79,7 @@ void* context = this; - JS_AddExtraGCRootsTracer(GetScriptInterface().GetJSRuntime(), CNetClient::Trace, this); + JS_AddExtraGCRootsTracer(GetScriptInterface().GetJSRuntime(), CNetClientWorker::Trace, this); // Set up transitions for session AddTransition(NCS_UNCONNECTED, (uint)NMT_CONNECT_COMPLETE, NCS_CONNECT, (void*)&OnConnect, context); @@ -139,13 +139,13 @@ SetFirstState(NCS_UNCONNECTED); } -CNetClient::~CNetClient() +CNetClientWorker::~CNetClientWorker() { DestroyConnection(); - JS_RemoveExtraGCRootsTracer(GetScriptInterface().GetJSRuntime(), CNetClient::Trace, this); + JS_RemoveExtraGCRootsTracer(GetScriptInterface().GetJSRuntime(), CNetClientWorker::Trace, this); } -void CNetClient::TraceMember(JSTracer *trc) +void CNetClientWorker::TraceMember(JSTracer *trc) { for (JS::Heap& guiMessage : m_GuiMessageQueue) JS_CallValueTracer(trc, &guiMessage, "m_GuiMessageQueue"); @@ -158,7 +158,7 @@ m_UserName = username; } -bool CNetClient::SetupConnection(const CStr& server, const u16 port) +bool CNetClientWorker::SetupConnection(const CStr& server, const u16 port) { CNetClientSession* session = new CNetClientSession(*this); bool ok = session->Connect(server, port, m_IsLocalClient); @@ -166,13 +166,13 @@ return ok; } -void CNetClient::SetAndOwnSession(CNetClientSession* session) +void CNetClientWorker::SetAndOwnSession(CNetClientSession* session) { delete m_Session; m_Session = session; } -void CNetClient::DestroyConnection() +void CNetClientWorker::DestroyConnection() { // Send network messages from the current frame before connection is destroyed. if (m_ClientTurnManager) @@ -183,7 +183,7 @@ SAFE_DELETE(m_Session); } -void CNetClient::Poll() +void CNetClientWorker::Poll() { if (!m_Session) return; @@ -192,7 +192,7 @@ m_Session->Poll(); } -void CNetClient::CheckServerConnection() +void CNetClientWorker::CheckServerConnection() { // Trigger local warnings if the connection to the server is bad. // At most once per second. @@ -227,13 +227,13 @@ } } -void CNetClient::Flush() +void CNetClientWorker::Flush() { if (m_Session) m_Session->Flush(); } -void CNetClient::GuiPoll(JS::MutableHandleValue ret) +void CNetClientWorker::GuiPoll(JS::MutableHandleValue ret) { if (m_GuiMessageQueue.empty()) { @@ -245,7 +245,7 @@ m_GuiMessageQueue.pop_front(); } -void CNetClient::PushGuiMessage(const JS::HandleValue message) +void CNetClientWorker::PushGuiMessage(const JS::HandleValue message) { ENSURE(!message.isUndefined()); @@ -252,7 +252,7 @@ m_GuiMessageQueue.push_back(JS::Heap(message)); } -std::string CNetClient::TestReadGuiMessages() +std::string CNetClientWorker::TestReadGuiMessages() { JSContext* cx = GetScriptInterface().GetContext(); JSAutoRequest rq(cx); @@ -269,12 +269,12 @@ return r; } -ScriptInterface& CNetClient::GetScriptInterface() +ScriptInterface& CNetClientWorker::GetScriptInterface() { return m_Game->GetSimulation2()->GetScriptInterface(); } -void CNetClient::PostPlayerAssignmentsToScript() +void CNetClientWorker::PostPlayerAssignmentsToScript() { JSContext* cx = GetScriptInterface().GetContext(); JSAutoRequest rq(cx); @@ -298,7 +298,7 @@ PushGuiMessage(msg); } -bool CNetClient::SendMessage(const CNetMessage* message) +bool CNetClientWorker::SendMessage(const CNetMessage* message) { if (!m_Session) return false; @@ -306,12 +306,12 @@ return m_Session->SendMessage(message); } -void CNetClient::HandleConnect() +void CNetClientWorker::HandleConnect() { Update((uint)NMT_CONNECT_COMPLETE, NULL); } -void CNetClient::HandleDisconnect(u32 reason) +void CNetClientWorker::HandleDisconnect(u32 reason) { JSContext* cx = GetScriptInterface().GetContext(); JSAutoRequest rq(cx); @@ -328,7 +328,7 @@ SetCurrState(NCS_UNCONNECTED); } -void CNetClient::SendGameSetupMessage(JS::MutableHandleValue attrs, ScriptInterface& scriptInterface) +void CNetClientWorker::SendGameSetupMessage(JS::MutableHandleValue attrs, ScriptInterface& scriptInterface) { CGameSetupMessage gameSetup(scriptInterface); gameSetup.m_Data = attrs; @@ -335,7 +335,7 @@ SendMessage(&gameSetup); } -void CNetClient::SendAssignPlayerMessage(const int playerID, const CStr& guid) +void CNetClientWorker::SendAssignPlayerMessage(const int playerID, const CStr& guid) { CAssignPlayerMessage assignPlayer; assignPlayer.m_PlayerID = playerID; @@ -343,7 +343,7 @@ SendMessage(&assignPlayer); } -void CNetClient::SendChatMessage(const std::wstring& text) +void CNetClientWorker::SendChatMessage(const std::wstring& text) { CChatMessage chat; chat.m_Message = text; @@ -350,7 +350,7 @@ SendMessage(&chat); } -void CNetClient::SendReadyMessage(const int status) +void CNetClientWorker::SendReadyMessage(const int status) { CReadyMessage readyStatus; readyStatus.m_Status = status; @@ -357,25 +357,25 @@ SendMessage(&readyStatus); } -void CNetClient::SendClearAllReadyMessage() +void CNetClientWorker::SendClearAllReadyMessage() { CClearAllReadyMessage clearAllReady; SendMessage(&clearAllReady); } -void CNetClient::SendStartGameMessage() +void CNetClientWorker::SendStartGameMessage() { CGameStartMessage gameStart; SendMessage(&gameStart); } -void CNetClient::SendRejoinedMessage() +void CNetClientWorker::SendRejoinedMessage() { CRejoinedMessage rejoinedMessage; SendMessage(&rejoinedMessage); } -void CNetClient::SendKickPlayerMessage(const CStrW& playerName, bool ban) +void CNetClientWorker::SendKickPlayerMessage(const CStrW& playerName, bool ban) { CKickedMessage kickPlayer; kickPlayer.m_Name = playerName; @@ -383,7 +383,7 @@ SendMessage(&kickPlayer); } -void CNetClient::SendPausedMessage(bool pause) +void CNetClientWorker::SendPausedMessage(bool pause) { CClientPausedMessage pausedMessage; pausedMessage.m_Pause = pause; @@ -390,7 +390,7 @@ SendMessage(&pausedMessage); } -bool CNetClient::HandleMessage(CNetMessage* message) +bool CNetClientWorker::HandleMessage(CNetMessage* message) { // Handle non-FSM messages first @@ -433,7 +433,7 @@ return ok; } -void CNetClient::LoadFinished() +void CNetClientWorker::LoadFinished() { JSContext* cx = GetScriptInterface().GetContext(); JSAutoRequest rq(cx); @@ -476,11 +476,11 @@ SendMessage(&loaded); } -bool CNetClient::OnConnect(void* context, CFsmEvent* event) +bool CNetClientWorker::OnConnect(void* context, CFsmEvent* event) { ENSURE(event->GetType() == (uint)NMT_CONNECT_COMPLETE); - CNetClient* client = (CNetClient*)context; + CNetClientWorker* client = (CNetClientWorker*)context; JSContext* cx = client->GetScriptInterface().GetContext(); JSAutoRequest rq(cx); @@ -492,11 +492,11 @@ return true; } -bool CNetClient::OnHandshake(void* context, CFsmEvent* event) +bool CNetClientWorker::OnHandshake(void* context, CFsmEvent* event) { ENSURE(event->GetType() == (uint)NMT_SERVER_HANDSHAKE); - CNetClient* client = (CNetClient*)context; + CNetClientWorker* client = (CNetClientWorker*)context; CCliHandshakeMessage handshake; handshake.m_MagicResponse = PS_PROTOCOL_MAGIC_RESPONSE; @@ -507,11 +507,11 @@ return true; } -bool CNetClient::OnHandshakeResponse(void* context, CFsmEvent* event) +bool CNetClientWorker::OnHandshakeResponse(void* context, CFsmEvent* event) { ENSURE(event->GetType() == (uint)NMT_SERVER_HANDSHAKE_RESPONSE); - CNetClient* client = (CNetClient*)context; + CNetClientWorker* client = (CNetClientWorker*)context; CAuthenticateMessage authenticate; authenticate.m_GUID = client->m_GUID; @@ -523,11 +523,11 @@ return true; } -bool CNetClient::OnAuthenticate(void* context, CFsmEvent* event) +bool CNetClientWorker::OnAuthenticate(void* context, CFsmEvent* event) { ENSURE(event->GetType() == (uint)NMT_AUTHENTICATE_RESULT); - CNetClient* client = (CNetClient*)context; + CNetClientWorker* client = (CNetClientWorker*)context; JSContext* cx = client->GetScriptInterface().GetContext(); JSAutoRequest rq(cx); @@ -547,11 +547,11 @@ return true; } -bool CNetClient::OnChat(void* context, CFsmEvent* event) +bool CNetClientWorker::OnChat(void* context, CFsmEvent* event) { ENSURE(event->GetType() == (uint)NMT_CHAT); - CNetClient* client = (CNetClient*)context; + CNetClientWorker* client = (CNetClientWorker*)context; JSContext* cx = client->GetScriptInterface().GetContext(); JSAutoRequest rq(cx); @@ -566,11 +566,11 @@ return true; } -bool CNetClient::OnReady(void* context, CFsmEvent* event) +bool CNetClientWorker::OnReady(void* context, CFsmEvent* event) { ENSURE(event->GetType() == (uint)NMT_READY); - CNetClient* client = (CNetClient*)context; + CNetClientWorker* client = (CNetClientWorker*)context; JSContext* cx = client->GetScriptInterface().GetContext(); JSAutoRequest rq(cx); @@ -585,11 +585,11 @@ return true; } -bool CNetClient::OnGameSetup(void* context, CFsmEvent* event) +bool CNetClientWorker::OnGameSetup(void* context, CFsmEvent* event) { ENSURE(event->GetType() == (uint)NMT_GAME_SETUP); - CNetClient* client = (CNetClient*)context; + CNetClientWorker* client = (CNetClientWorker*)context; JSContext* cx = client->GetScriptInterface().GetContext(); JSAutoRequest rq(cx); @@ -605,11 +605,11 @@ return true; } -bool CNetClient::OnPlayerAssignment(void* context, CFsmEvent* event) +bool CNetClientWorker::OnPlayerAssignment(void* context, CFsmEvent* event) { ENSURE(event->GetType() == (uint)NMT_PLAYER_ASSIGNMENT); - CNetClient* client = (CNetClient*)context; + CNetClientWorker* client = (CNetClientWorker*)context; CPlayerAssignmentMessage* message = (CPlayerAssignmentMessage*)event->GetParamRef(); @@ -632,11 +632,11 @@ return true; } -bool CNetClient::OnGameStart(void* context, CFsmEvent* event) +bool CNetClientWorker::OnGameStart(void* context, CFsmEvent* event) { ENSURE(event->GetType() == (uint)NMT_GAME_START); - CNetClient* client = (CNetClient*)context; + CNetClientWorker* client = (CNetClientWorker*)context; JSContext* cx = client->GetScriptInterface().GetContext(); JSAutoRequest rq(cx); @@ -658,11 +658,11 @@ return true; } -bool CNetClient::OnJoinSyncStart(void* context, CFsmEvent* event) +bool CNetClientWorker::OnJoinSyncStart(void* context, CFsmEvent* event) { ENSURE(event->GetType() == (uint)NMT_JOIN_SYNC_START); - CNetClient* client = (CNetClient*)context; + CNetClientWorker* client = (CNetClientWorker*)context; // The server wants us to start downloading the game state from it, so do so client->m_Session->GetFileTransferer().StartTask( @@ -672,11 +672,11 @@ return true; } -bool CNetClient::OnJoinSyncEndCommandBatch(void* context, CFsmEvent* event) +bool CNetClientWorker::OnJoinSyncEndCommandBatch(void* context, CFsmEvent* event) { ENSURE(event->GetType() == (uint)NMT_END_COMMAND_BATCH); - CNetClient* client = (CNetClient*)context; + CNetClientWorker* client = (CNetClientWorker*)context; CEndCommandBatchMessage* endMessage = (CEndCommandBatchMessage*)event->GetParamRef(); @@ -688,11 +688,11 @@ return true; } -bool CNetClient::OnRejoined(void* context, CFsmEvent* event) +bool CNetClientWorker::OnRejoined(void* context, CFsmEvent* event) { ENSURE(event->GetType() == (uint)NMT_REJOINED); - CNetClient* client = (CNetClient*)context; + CNetClientWorker* client = (CNetClientWorker*)context; JSContext* cx = client->GetScriptInterface().GetContext(); JSAutoRequest rq(cx); @@ -705,11 +705,11 @@ return true; } -bool CNetClient::OnKicked(void *context, CFsmEvent* event) +bool CNetClientWorker::OnKicked(void *context, CFsmEvent* event) { ENSURE(event->GetType() == (uint)NMT_KICKED); - CNetClient* client = (CNetClient*)context; + CNetClientWorker* client = (CNetClientWorker*)context; JSContext* cx = client->GetScriptInterface().GetContext(); JSAutoRequest rq(cx); @@ -725,13 +725,13 @@ return true; } -bool CNetClient::OnClientTimeout(void *context, CFsmEvent* event) +bool CNetClientWorker::OnClientTimeout(void *context, CFsmEvent* event) { // Report the timeout of some other client ENSURE(event->GetType() == (uint)NMT_CLIENT_TIMEOUT); - CNetClient* client = (CNetClient*)context; + CNetClientWorker* client = (CNetClientWorker*)context; JSContext* cx = client->GetScriptInterface().GetContext(); JSAutoRequest rq(cx); @@ -749,13 +749,13 @@ return true; } -bool CNetClient::OnClientPerformance(void *context, CFsmEvent* event) +bool CNetClientWorker::OnClientPerformance(void *context, CFsmEvent* event) { // Performance statistics for one or multiple clients ENSURE(event->GetType() == (uint)NMT_CLIENT_PERFORMANCE); - CNetClient* client = (CNetClient*)context; + CNetClientWorker* client = (CNetClientWorker*)context; JSContext* cx = client->GetScriptInterface().GetContext(); JSAutoRequest rq(cx); @@ -780,7 +780,7 @@ return true; } -bool CNetClient::OnClientsLoading(void *context, CFsmEvent *event) +bool CNetClientWorker::OnClientsLoading(void *context, CFsmEvent *event) { ENSURE(event->GetType() == (uint)NMT_CLIENTS_LOADING); @@ -791,7 +791,7 @@ for (const CClientsLoadingMessage::S_m_Clients& client : message->m_Clients) guids.push_back(client.m_GUID); - CNetClient* client = (CNetClient*)context; + CNetClientWorker* client = (CNetClientWorker*)context; JSContext* cx = client->GetScriptInterface().GetContext(); JSAutoRequest rq(cx); @@ -802,11 +802,11 @@ return true; } -bool CNetClient::OnClientPaused(void *context, CFsmEvent *event) +bool CNetClientWorker::OnClientPaused(void *context, CFsmEvent *event) { ENSURE(event->GetType() == (uint)NMT_CLIENT_PAUSED); - CNetClient* client = (CNetClient*)context; + CNetClientWorker* client = (CNetClientWorker*)context; JSContext* cx = client->GetScriptInterface().GetContext(); JSAutoRequest rq(cx); @@ -821,11 +821,11 @@ return true; } -bool CNetClient::OnLoadedGame(void* context, CFsmEvent* event) +bool CNetClientWorker::OnLoadedGame(void* context, CFsmEvent* event) { ENSURE(event->GetType() == (uint)NMT_LOADED_GAME); - CNetClient* client = (CNetClient*)context; + CNetClientWorker* client = (CNetClientWorker*)context; JSContext* cx = client->GetScriptInterface().GetContext(); JSAutoRequest rq(cx); @@ -844,11 +844,11 @@ return true; } -bool CNetClient::OnInGame(void *context, CFsmEvent* event) +bool CNetClientWorker::OnInGame(void *context, CFsmEvent* event) { // TODO: should split each of these cases into a separate method - CNetClient* client = (CNetClient*)context; + CNetClientWorker* client = (CNetClientWorker*)context; CNetMessage* message = (CNetMessage*)event->GetParamRef(); if (message) Index: source/network/NetClient.h =================================================================== --- source/network/NetClient.h (revision 19356) +++ source/network/NetClient.h (working copy) @@ -23,6 +23,7 @@ #include "network/NetHost.h" #include "scriptinterface/ScriptVal.h" +#include "ps/ThreadUtil.h" #include "ps/CStr.h" #include @@ -33,6 +34,8 @@ class CNetServer; class ScriptInterface; +class CNetClientWorker; + // NetClient session FSM states enum { @@ -54,14 +57,12 @@ * It provides an interface between the GUI, the network (via CNetClientSession), * and the game (via CGame and CNetClientTurnManager). */ -class CNetClient : public CFsm +class CNetClient { NONCOPYABLE(CNetClient); - friend class CNetFileReceiveTask_ClientRejoin; - public: - /** + /** * Construct a client associated with the given game object. * The game must exist for the lifetime of this object. */ @@ -70,6 +71,35 @@ virtual ~CNetClient(); /** + * Set the user's name that will be displayed to all players. + * This must not be called after the connection setup. + */ + void SetUserName(const CStrW& username); + + /** + * Set up a connection to the remote networked server. + * @param server IP address or host name to connect to + * @return true on success, false on connection failure + */ + bool SetupConnection(const CStr& server, const u16 port); + + private: + CNetClientWorker* m_Worker; +}; + +/** + * Network server worker thread. + * + * Thread-safety: + * + * + */ +class CNetClientWorker +{ + NONCOPYABLE(CNetClientWorker); + +public: + /** * We assume that adding a tracing function that's only called * during GC is better for performance than using a * PersistentRooted where each value needs to be added to @@ -77,18 +107,12 @@ */ static void Trace(JSTracer *trc, void *data) { - reinterpret_cast(data)->TraceMember(trc); + reinterpret_cast(data)->TraceMember(trc); } void TraceMember(JSTracer *trc); /** - * Set the user's name that will be displayed to all players. - * This must not be called after the connection setup. - */ - void SetUserName(const CStrW& username); - - /** * Returns the GUID of the local client. * Used for distinguishing observers. */ @@ -95,13 +119,6 @@ CStr GetGUID() const { return m_GUID; } /** - * Set up a connection to the remote networked server. - * @param server IP address or host name to connect to - * @return true on success, false on connection failure - */ - bool SetupConnection(const CStr& server, const u16 port); - - /** * Destroy the connection to the server. * This client probably cannot be used again. */ @@ -216,6 +233,19 @@ void SendPausedMessage(bool pause); private: + friend class CNetClient; + friend class CNetFileReceiveTask_ClientRejoin; + + CNetClientWorker(CGame* game, bool isLocalClient); + ~CNetClientWorker(); + + /** + * Set up a connection to the remote networked server. + * @param server IP address or host name to connect to + * @return true on success, false on connection failure + */ + bool SetupConnection(const CStr& server, const u16 port); + // Net message / FSM transition handlers static bool OnConnect(void* context, CFsmEvent* event); static bool OnHandshake(void* context, CFsmEvent* event); Index: source/network/NetClientTurnManager.cpp =================================================================== --- source/network/NetClientTurnManager.cpp (revision 19356) +++ source/network/NetClientTurnManager.cpp (working copy) @@ -33,7 +33,7 @@ #define NETCLIENTTURN_LOG(...) #endif -CNetClientTurnManager::CNetClientTurnManager(CSimulation2& simulation, CNetClient& client, int clientId, IReplayLogger& replay) +CNetClientTurnManager::CNetClientTurnManager(CSimulation2& simulation, CNetClientWorker& client, int clientId, IReplayLogger& replay) : CTurnManager(simulation, DEFAULT_TURN_LENGTH_MP, clientId, replay), m_NetClient(client) { } Index: source/network/NetClientTurnManager.h =================================================================== --- source/network/NetClientTurnManager.h (revision 19356) +++ source/network/NetClientTurnManager.h (working copy) @@ -21,7 +21,7 @@ #include "simulation2/system/TurnManager.h" #include "NetMessage.h" -class CNetClient; +class CNetClientWorker; /** * Implementation of CTurnManager for network clients. @@ -30,7 +30,7 @@ { NONCOPYABLE(CNetClientTurnManager); public: - CNetClientTurnManager(CSimulation2& simulation, CNetClient& client, int clientId, IReplayLogger& replay); + CNetClientTurnManager(CSimulation2& simulation, CNetClientWorker& client, int clientId, IReplayLogger& replay); void OnSimulationMessage(CSimulationMessage* msg) override; @@ -48,7 +48,7 @@ void NotifyFinishedUpdate(u32 turn) override; - CNetClient& m_NetClient; + CNetClientWorker& m_NetClient; }; #endif // INCLUDED_NETCLIENTTURNMANAGER Index: source/network/NetSession.cpp =================================================================== --- source/network/NetSession.cpp (revision 19356) +++ source/network/NetSession.cpp (working copy) @@ -32,7 +32,7 @@ static const int CHANNEL_COUNT = 1; -CNetClientSession::CNetClientSession(CNetClient& client) : +CNetClientSession::CNetClientSession(CNetClientWorker& client) : m_Client(client), m_FileTransferer(this), m_Host(NULL), m_Server(NULL), m_Stats(NULL) { } Index: source/network/NetSession.h =================================================================== --- source/network/NetSession.h (revision 19356) +++ source/network/NetSession.h (working copy) @@ -34,7 +34,7 @@ */ extern const u32 MAXIMUM_HOST_TIMEOUT; -class CNetClient; +class CNetClientWorker; class CNetServerWorker; class CNetStatsTable; @@ -67,7 +67,7 @@ NONCOPYABLE(CNetClientSession); public: - CNetClientSession(CNetClient& client); + CNetClientSession(CNetClientWorker& client); ~CNetClientSession(); bool Connect(const CStr& server, const u16 port, const bool isLocalClient); @@ -106,7 +106,7 @@ CNetFileTransferer& GetFileTransferer() { return m_FileTransferer; } private: - CNetClient& m_Client; + CNetClientWorker& m_Client; CNetFileTransferer m_FileTransferer; Index: source/ps/GameSetup/GameSetup.cpp =================================================================== --- source/ps/GameSetup/GameSetup.cpp (revision 19356) +++ source/ps/GameSetup/GameSetup.cpp (working copy) @@ -1498,7 +1498,7 @@ bool ok = g_NetServer->SetupConnection(PS_DEFAULT_PORT); ENSURE(ok); - g_NetClient = new CNetClient(g_Game, true); + g_NetClient = new CNetClientWorker(g_Game, true); g_NetClient->SetUserName(userName); g_NetClient->SetupConnection("127.0.0.1", PS_DEFAULT_PORT); } @@ -1506,7 +1506,7 @@ { InitPs(true, L"page_loading.xml", &scriptInterface, mpInitData); - g_NetClient = new CNetClient(g_Game, false); + g_NetClient = new CNetClientWorker(g_Game, false); g_NetClient->SetUserName(userName); CStr ip = args.Get("autostart-client");