From cd9fe7aee526f4eb0d7d8e670b2f1bebd6a0c661 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Sat, 11 Feb 2023 20:46:32 -0600 Subject: [PATCH] feat(client): implement realm enum callback --- src/client/ClientServices.cpp | 87 +++++++++++++++++++++++++- src/client/ClientServices.hpp | 7 +++ src/net/Types.hpp | 6 ++ src/net/connection/NetClient.cpp | 36 +++++++++++ src/net/connection/NetClient.hpp | 2 + src/net/connection/RealmConnection.cpp | 4 ++ src/net/connection/RealmConnection.hpp | 1 + src/net/connection/WowConnection.cpp | 4 ++ src/net/connection/WowConnection.hpp | 1 + 9 files changed, 147 insertions(+), 1 deletion(-) diff --git a/src/client/ClientServices.cpp b/src/client/ClientServices.cpp index a413066..3beb5bf 100644 --- a/src/client/ClientServices.cpp +++ b/src/client/ClientServices.cpp @@ -3,6 +3,7 @@ #include "glue/CGlueMgr.hpp" #include "net/Connection.hpp" #include "net/Login.hpp" +#include "util/CVar.hpp" #include #include #include @@ -15,6 +16,29 @@ ClientConnection* ClientServices::s_currentConnection; ClientServices* ClientServices::s_instance; Login* ClientServices::s_loginObj; bool ClientServices::s_newLogin; +CVar* ClientServices::s_realmNameVar; +REALM_INFO ClientServices::s_selectRealmInfo; +bool ClientServices::s_selectRealmInfoValid; + +void ClientServices::ConnectToSelectedServer() { + if (!ClientServices::s_selectRealmInfoValid && !ClientServices::SetSelectedRealmInfo(0)) { + // TODO ClientServices::Connection()->Sub6B10B0(0, 39); + return; + } + + if (ClientServices::Connection()->m_netState != NS_INITIALIZED) { + // TODO ClientServices::Connection()->Sub6B10B0(0, 39); + return; + } + + ClientServices::Connection()->SetSelectedRealm( + ClientServices::s_selectRealmInfo.uint130, + ClientServices::s_selectRealmInfo.uint134, + ClientServices::s_selectRealmInfo.sort + ); + + ClientServices::Connection()->NetClient::Connect(ClientServices::s_selectRealmInfo.address); +} ClientConnection* ClientServices::Connection() { // TODO assertion? @@ -34,6 +58,24 @@ ClientServices* ClientServices::GetInstance() { return ClientServices::s_instance; } +const char* ClientServices::GetSelectedRealmName() { + if (!ClientServices::s_realmNameVar) { + ClientServices::s_realmNameVar = CVar::Register( + "realmName", + "Last realm connected to", + 0, + "", + nullptr, + 6, + false, + nullptr, + false + ); + } + + return ClientServices::s_realmNameVar->GetString(); +} + void ClientServices::Initialize() { if (!g_clientConnection) { auto adapterMem = SMemAlloc(sizeof(ClientRealmResponseAdapter), __FILE__, __LINE__, 0x0); @@ -93,6 +135,27 @@ void ClientServices::SetAccountName(const char* accountName) { SStrCopy(ClientServices::s_accountName, accountName, sizeof(ClientServices::s_accountName)); } +int32_t ClientServices::SetSelectedRealmInfo(int32_t a1) { + auto instance = ClientServices::GetInstance(); + + for (uint32_t index = 0; index < instance->m_realmList.Count(); index++) { + auto& realmInfo = instance->m_realmList[index]; + + if (!SStrCmpI(realmInfo.name, ClientServices::GetSelectedRealmName(), STORM_MAX_STR) /* TODO SStrCmpUTF8I */) { + if (!(realmInfo.flags & 0x1) || a1) { + ClientServices::s_selectRealmInfoValid = true; + memcpy(&ClientServices::s_selectRealmInfo, &realmInfo, sizeof(ClientServices::s_selectRealmInfo)); + + return 1; + } + } + } + + ClientServices::s_selectRealmInfoValid = false; + + return 0; +} + int32_t ClientServices::GetLoginServerType() { if (!ClientServices::LoginConnection()) { return 0; @@ -129,5 +192,27 @@ void ClientServices::LoginServerStatus(LOGIN_STATE state, LOGIN_RESULT result, c } void ClientServices::RealmEnumCallback(uint32_t a2) { - // TODO + auto connection = ClientServices::Connection(); + + if (a2 == 1) { + // TODO + + return; + } + + if (a2 == 2 || a2 == 3 || a2 == 4) { + // TODO + + return; + } + + // TODO statusCop checks + + if (ClientServices::LoginConnection()->GetLoginServerType() == 1) { + // TODO Battlenet logic + + return; + } + + ClientServices::ConnectToSelectedServer(); } diff --git a/src/client/ClientServices.hpp b/src/client/ClientServices.hpp index 04eb202..83182ce 100644 --- a/src/client/ClientServices.hpp +++ b/src/client/ClientServices.hpp @@ -4,6 +4,7 @@ #include "net/login/LoginResponse.hpp" class ClientConnection; +class CVar; class Login; class RealmResponse; @@ -16,14 +17,20 @@ class ClientServices : public LoginResponse { static ClientServices* s_instance; static Login* s_loginObj; static bool s_newLogin; + static CVar* s_realmNameVar; + static REALM_INFO s_selectRealmInfo; + static bool s_selectRealmInfoValid; // Static functions + static void ConnectToSelectedServer(); static ClientConnection* Connection(); static ClientServices* GetInstance(); + static const char* GetSelectedRealmName(); static void Initialize(); static Login* LoginConnection(); static void Logon(const char* accountName, const char* password); static void SetAccountName(const char* accountName); + static int32_t SetSelectedRealmInfo(int32_t a1); // Virtual member functions virtual int32_t GetLoginServerType(); diff --git a/src/net/Types.hpp b/src/net/Types.hpp index 9619e0a..b93900b 100644 --- a/src/net/Types.hpp +++ b/src/net/Types.hpp @@ -1169,6 +1169,8 @@ enum NETSTATE { NS_UNINITIALIZED = 0, NS_INITIALIZING = 1, NS_INITIALIZED = 2, + NS_STATE_3 = 3, + NS_GETTING_REALMS = 4, }; enum WOW_CONN_STATE { @@ -1188,6 +1190,10 @@ enum WOWC_TYPE { WOWC_TYPE_STREAM = 1, }; +enum WC_ENCRYPT_TYPE { + WC_ENCRYPT_0 = 0, +}; + enum WC_SEND_RESULT { WC_SEND_SENT = 0, WC_SEND_QUEUED = 1, diff --git a/src/net/connection/NetClient.cpp b/src/net/connection/NetClient.cpp index fd99230..c347e1b 100644 --- a/src/net/connection/NetClient.cpp +++ b/src/net/connection/NetClient.cpp @@ -1,9 +1,11 @@ #include "net/connection/NetClient.hpp" #include "net/connection/WowConnection.hpp" +#include #include #include #include #include +#include HPROPCONTEXT s_propContext; @@ -15,6 +17,40 @@ void InitializePropContext() { } } +void NetClient::Connect(const char* addrStr) { + if (this->m_netState != NS_INITIALIZED) { + SErrDisplayAppFatal("Expected (m_netState == NS_INITIALIZED), got %d", this->m_netState); + } + + uint16_t port = 9090; + + char host[1024]; + SStrCopy(host, addrStr, sizeof(host)); + + auto portDelim = SStrChr(host, ':'); + if (portDelim) { + *portDelim = '\0'; + port = atoi(portDelim + 1); + } + + this->m_serverConnection->SetEncryptionType(WC_ENCRYPT_0); + this->m_netState = NS_INITIALIZED; + this->ConnectInternal(host, port); +} + +int32_t NetClient::ConnectInternal(const char* host, uint16_t port) { + if (this->m_netState != NS_INITIALIZED) { + SErrDisplayAppFatal("Expected (m_netState == NS_INITIALIZED), got %d", this->m_netState); + } + + this->m_netState = NS_GETTING_REALMS; + this->m_serverConnection->Connect(host, port, -1); + + // TODO + + return 1; +} + int32_t NetClient::Initialize() { STORM_ASSERT(this->m_netState == NS_UNINITIALIZED); diff --git a/src/net/connection/NetClient.hpp b/src/net/connection/NetClient.hpp index 0e2c881..f486028 100644 --- a/src/net/connection/NetClient.hpp +++ b/src/net/connection/NetClient.hpp @@ -50,6 +50,8 @@ class NetClient : public WowConnectionResponse { virtual void WCDataReady(WowConnection* conn, uint32_t timeStamp, uint8_t* data, int32_t len); // Member functions + void Connect(const char* addrStr); + int32_t ConnectInternal(const char* host, uint16_t port); int32_t Initialize(); void SetLoginData(LoginData* loginData); void SetMessageHandler(NETMESSAGE msgId, MESSAGE_HANDLER handler, void* param); diff --git a/src/net/connection/RealmConnection.cpp b/src/net/connection/RealmConnection.cpp index 68e87b7..373156f 100644 --- a/src/net/connection/RealmConnection.cpp +++ b/src/net/connection/RealmConnection.cpp @@ -27,3 +27,7 @@ RealmConnection::RealmConnection(RealmResponse* realmResponse) { // TODO } + +void RealmConnection::SetSelectedRealm(uint32_t a2, uint32_t a3, uint32_t a4) { + // TODO +} diff --git a/src/net/connection/RealmConnection.hpp b/src/net/connection/RealmConnection.hpp index 427bf96..7ebeccd 100644 --- a/src/net/connection/RealmConnection.hpp +++ b/src/net/connection/RealmConnection.hpp @@ -17,6 +17,7 @@ class RealmConnection : public NetClient { // Member functions RealmConnection(RealmResponse* realmResponse); + void SetSelectedRealm(uint32_t a2, uint32_t a3, uint32_t a4); }; #endif diff --git a/src/net/connection/WowConnection.cpp b/src/net/connection/WowConnection.cpp index 4de37d2..7b51ae7 100644 --- a/src/net/connection/WowConnection.cpp +++ b/src/net/connection/WowConnection.cpp @@ -527,6 +527,10 @@ WC_SEND_RESULT WowConnection::SendRaw(uint8_t* data, int32_t len, bool a4) { return WC_SEND_ERROR; } +void WowConnection::SetEncryptionType(WC_ENCRYPT_TYPE encryptType) { + // TODO +} + void WowConnection::SetState(WOW_CONN_STATE state) { WOW_CONN_STATE oldState = this->m_connState; this->m_connState = state; diff --git a/src/net/connection/WowConnection.hpp b/src/net/connection/WowConnection.hpp index 67d1fa1..ec521da 100644 --- a/src/net/connection/WowConnection.hpp +++ b/src/net/connection/WowConnection.hpp @@ -79,6 +79,7 @@ class WowConnection { void Release(); void ReleaseResponseRef(); WC_SEND_RESULT SendRaw(uint8_t* data, int32_t len, bool a4); + void SetEncryptionType(WC_ENCRYPT_TYPE encryptType); void SetState(WOW_CONN_STATE state); void SetType(WOWC_TYPE type); void StartConnect();