diff --git a/src/client/ClientServices.cpp b/src/client/ClientServices.cpp index 9c073fa..6a9d4ae 100644 --- a/src/client/ClientServices.cpp +++ b/src/client/ClientServices.cpp @@ -139,6 +139,10 @@ void ClientServices::Logon(const char* accountName, const char* password) { ClientServices::s_loginObj->Logon(nullptr, nullptr); } +void ClientServices::SelectRealm(const char* realmName) { + // TODO +} + void ClientServices::SetAccountName(const char* accountName) { SStrCopy(ClientServices::s_accountName, accountName, sizeof(ClientServices::s_accountName)); } diff --git a/src/client/ClientServices.hpp b/src/client/ClientServices.hpp index 0d96965..af9befa 100644 --- a/src/client/ClientServices.hpp +++ b/src/client/ClientServices.hpp @@ -30,6 +30,7 @@ class ClientServices : public LoginResponse { static void Initialize(); static Login* LoginConnection(); static void Logon(const char* accountName, const char* password); + static void SelectRealm(const char* realmName); static void SetAccountName(const char* accountName); static int32_t SetSelectedRealmInfo(int32_t a1); diff --git a/src/glue/CGlueMgr.cpp b/src/glue/CGlueMgr.cpp index 5b87912..bc66747 100644 --- a/src/glue/CGlueMgr.cpp +++ b/src/glue/CGlueMgr.cpp @@ -47,6 +47,7 @@ char CGlueMgr::m_accountName[1280]; float CGlueMgr::m_aspect; bool CGlueMgr::m_authenticated; char CGlueMgr::m_currentScreen[64]; +int32_t CGlueMgr::m_disconnectPending; int32_t CGlueMgr::m_displayingQueueDialog; CGlueMgr::GLUE_IDLE_STATE CGlueMgr::m_idleState; int32_t CGlueMgr::m_initialized; @@ -55,6 +56,7 @@ int32_t CGlueMgr::m_lastLoginState; int32_t CGlueMgr::m_loginResult; int32_t CGlueMgr::m_loginState; int32_t CGlueMgr::m_matrixRemaining; +int32_t CGlueMgr::m_reconnect; int32_t CGlueMgr::m_reload; int32_t CGlueMgr::m_scandllOkayToLogIn = 1; // TODO float CGlueMgr::m_screenHeight; @@ -78,6 +80,31 @@ float CalculateAspectRatio() { return static_cast(width) / static_cast(height); } +void CGlueMgr::ChangeRealm(const REALM_INFO* realmInfo) { + if (!realmInfo) { + return; + } + + ClientServices::SelectRealm(realmInfo->name); + + if (ClientServices::Connection()->IsConnected()) { + CGlueMgr::m_disconnectPending = 1; + CGlueMgr::m_reconnect = 1; + + ClientServices::Connection()->Disconnect(); + + return; + } + + CGlueMgr::m_idleState = IDLE_ACCOUNT_LOGIN; + CGlueMgr::m_showedDisconnect = 0; + + auto text = FrameScript_GetText("GAME_SERVER_LOGIN", -1, GENDER_NOT_APPLICABLE); + FrameScript_SignalEvent(3, "%s%s", "CANCEL", text); + + ClientServices::Connection()->Connect(); +} + void CGlueMgr::DisplayLoginStatus() { // No change if (CGlueMgr::m_lastLoginState == CGlueMgr::m_loginState && CGlueMgr::m_lastLoginResult == CGlueMgr::m_loginResult) { diff --git a/src/glue/CGlueMgr.hpp b/src/glue/CGlueMgr.hpp index 36d2fba..0ae8284 100644 --- a/src/glue/CGlueMgr.hpp +++ b/src/glue/CGlueMgr.hpp @@ -36,6 +36,7 @@ class CGlueMgr { static float m_aspect; static bool m_authenticated; static char m_currentScreen[]; + static int32_t m_disconnectPending; static int32_t m_displayingQueueDialog; static GLUE_IDLE_STATE m_idleState; static int32_t m_initialized; @@ -44,6 +45,7 @@ class CGlueMgr { static int32_t m_loginResult; static int32_t m_loginState; static int32_t m_matrixRemaining; + static int32_t m_reconnect; static int32_t m_reload; static int32_t m_scandllOkayToLogIn; static float m_screenHeight; @@ -53,6 +55,7 @@ class CGlueMgr { static int32_t m_suspended; // Static functions + static void ChangeRealm(const REALM_INFO* realmInfo); static void DisplayLoginStatus(); // TODO a1: const EVENT_DATA_IDLE* static int32_t HandleDisplaySizeChanged(const CSizeEvent& event); diff --git a/src/net/connection/ClientConnection.cpp b/src/net/connection/ClientConnection.cpp index 01a0de0..f1077ae 100644 --- a/src/net/connection/ClientConnection.cpp +++ b/src/net/connection/ClientConnection.cpp @@ -141,6 +141,15 @@ void ClientConnection::Connect() { ClientServices::LoginConnection()->GetRealmList(); } +int32_t ClientConnection::Disconnect() { + // TODO + return 0; +} + +int32_t ClientConnection::IsConnected() { + return this->m_connected; +} + int32_t ClientConnection::PollStatus(WOWCS_OPS& op, const char** msg, int32_t& result, int32_t& errorCode) { op = this->m_statusCop; errorCode = this->m_errorCode; diff --git a/src/net/connection/ClientConnection.hpp b/src/net/connection/ClientConnection.hpp index 7df58e9..3bc408b 100644 --- a/src/net/connection/ClientConnection.hpp +++ b/src/net/connection/ClientConnection.hpp @@ -9,6 +9,7 @@ class RealmResponse; class ClientConnection : public RealmConnection { public: // Member variables + int32_t m_connected = 0; int32_t m_statusComplete = 1; int32_t m_statusResult = 1; WOWCS_OPS m_statusCop = COP_NONE; @@ -22,6 +23,8 @@ class ClientConnection : public RealmConnection { void Cancel(int32_t errorCode); void Cleanup(); void Connect(); + int32_t Disconnect(); + int32_t IsConnected(); int32_t PollStatus(WOWCS_OPS& op, const char** msg, int32_t& result, int32_t& errorCode); void SetStatus(int32_t result, int32_t errorCode); }; diff --git a/src/ui/ScriptFunctionsRealmList.cpp b/src/ui/ScriptFunctionsRealmList.cpp index b6364cd..ab98551 100644 --- a/src/ui/ScriptFunctionsRealmList.cpp +++ b/src/ui/ScriptFunctionsRealmList.cpp @@ -1,6 +1,7 @@ #include "ui/ScriptFunctions.hpp" #include "client/ClientServices.hpp" #include "db/Db.hpp" +#include "glue/CGlueMgr.hpp" #include "glue/CRealmList.hpp" #include "util/StringTo.hpp" #include "ui/Types.hpp" @@ -190,7 +191,50 @@ int32_t Script_GetRealmInfo(lua_State* L) { } int32_t Script_ChangeRealm(lua_State* L) { - WHOA_UNIMPLEMENTED(); + if (!lua_isnumber(L, 1)) { + return luaL_error(L, "Usage: ChangeRealm(category, index)"); + } + + REALM_INFO* realmInfo = nullptr; + + if (lua_isnumber(L, 2)) { + int32_t categoryIndex = lua_tonumber(L, 1) - 1; + categoryIndex = CRealmList::Sub4DE910(categoryIndex); + + CRealmList::s_selectedCategory = categoryIndex; + + auto realmCategory = categoryIndex < CRealmList::s_categories.Count() + ? CRealmList::s_categories[categoryIndex] + : nullptr; + int32_t realmIndex = lua_tonumber(L, 2) - 1; + + if (realmCategory && realmIndex < realmCategory->uint14) { + realmInfo = ClientServices::GetRealmInfoByIndex(realmCategory->m_realms[realmIndex]); + } + } else { + int32_t realmIndex = lua_tonumber(L, 1) - 1; + + for (int32_t i = 0; i < CRealmList::s_categories.Count(); i++) { + auto realmCategory = CRealmList::s_categories[i]; + if (realmCategory) { + if (realmCategory->uint14 > realmIndex) { + realmInfo = ClientServices::GetRealmInfoByIndex(realmCategory->m_realms[realmIndex]); + } else { + realmIndex -= realmCategory->uint14; + } + } + } + } + + if (realmInfo) { + if (CRealmList::s_preferredCategory == -1) { + CRealmList::s_preferredCategory = 0; + } + + CGlueMgr::ChangeRealm(realmInfo); + } + + return 0; } int32_t Script_GetRealmCategories(lua_State* L) {