diff --git a/src/client/ClientServices.cpp b/src/client/ClientServices.cpp index bfb1d39..ed76def 100644 --- a/src/client/ClientServices.cpp +++ b/src/client/ClientServices.cpp @@ -142,6 +142,12 @@ const char* ClientServices::GetErrorToken(uint32_t token) { } } +bool ClientServices::ValidDisconnect(const void* client) { + STORM_ASSERT(client); + STORM_ASSERT(ClientServices::s_currentConnection); + return client == ClientServices::s_currentConnection; +} + void ClientServices::ConnectToSelectedServer() { if (!ClientServices::s_selectRealmInfoValid && !ClientServices::SetSelectedRealmInfo(0)) { ClientServices::Connection()->Complete(0, 39); diff --git a/src/client/ClientServices.hpp b/src/client/ClientServices.hpp index 91b08a5..0e96354 100644 --- a/src/client/ClientServices.hpp +++ b/src/client/ClientServices.hpp @@ -33,6 +33,7 @@ class ClientServices : public LoginResponse { // Static functions static const char* GetErrorToken(uint32_t token); + static bool ValidDisconnect(const void* client); static void ConnectToSelectedServer(); static ClientConnection* Connection(); static ClientServices* GetInstance(); diff --git a/src/console/Line.cpp b/src/console/Line.cpp index 3a2bdc0..847db3c 100644 --- a/src/console/Line.cpp +++ b/src/console/Line.cpp @@ -171,6 +171,19 @@ void ConsoleWriteA(const char* str, COLOR_T color, ...) { } } +void ConsolePrintf(char const* str, ...) { + char buffer[4096] = { 0 }; + + if (str != nullptr && str[0] != '\0') { + va_list list; + va_start(list, str); + vsnprintf(buffer, sizeof(buffer), str, list); + va_end(list); + + ConsoleWrite(buffer, DEFAULT_COLOR); + } +} + void MoveLinePtr(int32_t direction, int32_t modifier) { CONSOLELINE* lineptr = s_currlineptr; diff --git a/src/console/Line.hpp b/src/console/Line.hpp index f0419a3..7b60a7d 100644 --- a/src/console/Line.hpp +++ b/src/console/Line.hpp @@ -11,6 +11,7 @@ void ConsoleWrite(const char* str, COLOR_T color); void ConsoleWriteA(const char* str, COLOR_T color, ...); +void ConsolePrintf(char const* str, ...); void PasteInInputLine(char* characters); diff --git a/src/glue/CGlueMgr.cpp b/src/glue/CGlueMgr.cpp index f747e62..2e6227a 100644 --- a/src/glue/CGlueMgr.cpp +++ b/src/glue/CGlueMgr.cpp @@ -1,6 +1,7 @@ #include "glue/CGlueMgr.hpp" #include "glue/CRealmList.hpp" #include "glue/CCharacterSelection.hpp" +#include "console/Console.hpp" #include "client/Client.hpp" #include "client/ClientServices.hpp" #include "gx/Coordinate.hpp" @@ -67,6 +68,7 @@ int32_t CGlueMgr::m_reload; int32_t CGlueMgr::m_scandllOkayToLogIn = 1; // TODO float CGlueMgr::m_screenHeight; float CGlueMgr::m_screenWidth; +int32_t CGlueMgr::m_clientKickReason; int32_t CGlueMgr::m_showedDisconnect; CSimpleTop* CGlueMgr::m_simpleTop; int32_t CGlueMgr::m_suspended; @@ -229,6 +231,63 @@ void CGlueMgr::GetCharacterList() { } } +int32_t CGlueMgr::NetDisconnectHandler(const void* eventData, void*) { + bool v11 = CGlueMgr::m_idleState != IDLE_ACCOUNT_LOGIN; + + CGlueMgr::m_idleState = IDLE_NONE; + CGlueMgr::m_showedDisconnect = 0; + + if (CGlueMgr::m_disconnectPending) { + ConsolePrintf("CGlueMgr::NetDisconnectHandler: Disconnect pending"); + CGlueMgr::m_disconnectPending = 0; + + if (CGlueMgr::m_reconnect) { + CGlueMgr::m_reconnect = 0; + CGlueMgr::m_idleState = IDLE_ACCOUNT_LOGIN; + CGlueMgr::m_showedDisconnect = 0; + auto text = FrameScript_GetText("GAME_SERVER_LOGIN", -1, GENDER_NOT_APPLICABLE); + FrameScript_SignalEvent(3u, "%s%s", "CANCEL", text); + ClientServices::Connection()->Connect(); + return 1; + } + return 1; + } + if (!ClientServices::ValidDisconnect(eventData)) { + ConsolePrintf("CGlueMgr::NetDisconnectHandler: Invalid disconnect"); + return 1; + } + // TODO: ClientDestroyGame(0, 1, 0); + // TODO: EventSetMouseMode(0, 0); + + if (CGlueMgr::m_suspended) { + CGlueMgr::Resume(); + } + + if (v11) { + ConsolePrintf("CGlueMgr::NetDisconnectHandler: Displaying script"); +LABEL_14: + FrameScript_SignalEvent(2u, "%d", CGlueMgr::m_clientKickReason); + goto LABEL_15; + } + ConsolePrintf("CGlueMgr::NetDisconnectHandler: NOT displaying script"); + + WOWCS_OPS op; + const char* msg; + int32_t result; + int32_t errorCode; + int32_t complete = ClientServices::Connection()->PollStatus(op, &msg, result, errorCode); + + if (!complete || result) { + ClientServices::SelectRealm(""); + goto LABEL_14; + } + FrameScript_SignalEvent(3u, "%s%s", "OKAY", msg); + +LABEL_15: + ClientServices::LoginConnection()->Logoff(); + return 1; +} + // TODO a1: const EVENT_DATA_IDLE* int32_t CGlueMgr::Idle(const void* a1, void* a2) { // TODO: diff --git a/src/glue/CGlueMgr.hpp b/src/glue/CGlueMgr.hpp index cd783b8..1b523ec 100644 --- a/src/glue/CGlueMgr.hpp +++ b/src/glue/CGlueMgr.hpp @@ -59,6 +59,7 @@ class CGlueMgr { static int32_t m_scandllOkayToLogIn; static float m_screenHeight; static float m_screenWidth; + static int32_t m_clientKickReason; static int32_t m_showedDisconnect; static CSimpleTop* m_simpleTop; static int32_t m_suspended; @@ -78,6 +79,7 @@ class CGlueMgr { static int32_t HandleDisplaySizeChanged(const CSizeEvent& event); static void GetRealmList(bool showProgress); static void GetCharacterList(); + static int32_t NetDisconnectHandler(const void* eventData, void*); static int32_t Idle(const void* a1, void* a2); static void Initialize(); static void InitCursor(); diff --git a/src/net/CMakeLists.txt b/src/net/CMakeLists.txt index 13f2a67..1a0d0ac 100644 --- a/src/net/CMakeLists.txt +++ b/src/net/CMakeLists.txt @@ -32,6 +32,7 @@ target_include_directories(net target_link_libraries(net PRIVATE client + console event PUBLIC bc diff --git a/src/net/connection/NetClient.cpp b/src/net/connection/NetClient.cpp index c33f704..6d67899 100644 --- a/src/net/connection/NetClient.cpp +++ b/src/net/connection/NetClient.cpp @@ -1,5 +1,7 @@ #include "net/connection/NetClient.hpp" #include "net/connection/WowConnection.hpp" +#include "glue/CGlueMgr.hpp" +#include "console/Line.hpp" #include #include #include @@ -232,17 +234,17 @@ int32_t NetClient::HandleCantConnect() { } int32_t NetClient::HandleConnect() { - // TODO push obj mgr + this->PushObjMgr(); this->m_netState = NS_CONNECTED; - // TODO pop obj mgr + this->PopObjMgr(); return 1; } int32_t NetClient::HandleData(uint32_t timeReceived, void* data, int32_t size) { - // TODO push obj mgr + this->PushObjMgr(); CDataStore msg; msg.m_data = static_cast(data); @@ -252,13 +254,21 @@ int32_t NetClient::HandleData(uint32_t timeReceived, void* data, int32_t size) { this->ProcessMessage(timeReceived, &msg, 0); - // TODO pop obj mgr + this->PopObjMgr(); return 1; } int32_t NetClient::HandleDisconnect() { - // TODO + this->PushObjMgr(); + + STORM_ASSERT(this->m_netState == NS_CONNECTED || this->m_netState == NS_DISCONNECTING); + + this->m_netState = NS_INITIALIZED; + ConsolePrintf("NetClient::HandleDisconnect()"); + CGlueMgr::NetDisconnectHandler(this, nullptr); + + this->PopObjMgr(); return 1; } @@ -358,6 +368,59 @@ void NetClient::SetLoginData(LoginData* loginData) { memcpy(&this->m_loginData, loginData, sizeof(this->m_loginData)); } +void NetClient::DisplayNetworkStats() { + this->m_pingLock.Enter(); + OsGetAsyncTimeMs(); + + float bandwidthIn; + float bandwidthOut; + uint32_t latency; + this->GetNetStats(bandwidthIn, bandwidthOut, latency); + + this->m_pingLock.Leave(); +} + +void NetClient::GetNetStats(float& bandwidthIn, float& bandwidthOut, uint32_t& latency) { + this->m_pingLock.Enter(); + + double v5 = (double)(OsGetAsyncTimeMs() - this->m_connectedTimestamp) * 0.001; + bandwidthIn = (double)this->m_bytesReceived * 0.0009765625 / v5; + bandwidthOut = (double)this->m_bytesSent * 0.0009765625 / v5; + + uint32_t latencyStart = this->m_latencyStart; + uint32_t latencyEnd = this->m_latencyEnd; + + uint32_t v6 = 0; + uint32_t v9 = 0; + + while (latencyStart != latencyEnd) { + if (latencyStart >= 16) { + latencyStart = 0; + if (!latencyEnd) + break; + } + v9 += this->m_latency[latencyStart]; + ++v6; + ++latencyStart; + } ; + + if (!v6) { + latency = 0; + } else { + latency = v9 / v6; + } + + this->m_pingLock.Leave(); +} + +void NetClient::PushObjMgr() { + // TODO +} + +void NetClient::PopObjMgr() { + // TODO +} + void NetClient::SetMessageHandler(NETMESSAGE msgId, MESSAGE_HANDLER handler, void* param) { this->m_handlers[msgId] = handler; this->m_handlerParams[msgId] = param; @@ -387,7 +450,10 @@ void NetClient::WCConnected(WowConnection* conn, WowConnection* inbound, uint32_ } void NetClient::WCDisconnected(WowConnection* conn, uint32_t timeStamp, NETCONNADDR* addr) { - // TODO + this->DisplayNetworkStats(); + if (this->m_netEventQueue) { + this->m_netEventQueue->AddEvent(EVENT_ID_NET_DISCONNECT, conn, this, nullptr, 0); + } } void NetClient::WCMessageReady(WowConnection* conn, uint32_t timeStamp, CDataStore* msg) { diff --git a/src/net/connection/NetClient.hpp b/src/net/connection/NetClient.hpp index d6b587c..03cf438 100644 --- a/src/net/connection/NetClient.hpp +++ b/src/net/connection/NetClient.hpp @@ -79,6 +79,10 @@ class NetClient : public WowConnectionResponse { void SetDelete(); void SetLoginData(LoginData* loginData); void SetMessageHandler(NETMESSAGE msgId, MESSAGE_HANDLER handler, void* param); + void DisplayNetworkStats(); + void GetNetStats(float& bandwidthIn, float& bandwidthOut, uint32_t& latency); + void PushObjMgr(); + void PopObjMgr(); private: // Static variables diff --git a/src/net/connection/WowConnection.cpp b/src/net/connection/WowConnection.cpp index 54d5df2..78cf4fb 100644 --- a/src/net/connection/WowConnection.cpp +++ b/src/net/connection/WowConnection.cpp @@ -341,8 +341,7 @@ void WowConnection::DoDisconnect() { this->m_lock.Leave(); if (this->m_response && this->m_sock >= 0) { - // TODO - // this->m_response->Vfunc4(this, OsGetAsyncTimeMsPrecise()); + this->m_response->WCDisconnected(this, OsGetAsyncTimeMsPrecise(), &this->m_peer); } this->m_lock.Enter();