#include "glue/CGlueMgr.hpp" #include "glue/CRealmList.hpp" #include "glue/CCharacterSelection.hpp" #include "glue/CCharacterCreation.hpp" #include "console/Console.hpp" #include "client/Client.hpp" #include "client/ClientServices.hpp" #include "gx/Coordinate.hpp" #include "gx/Device.hpp" #include "gx/CGVideoOptions.hpp" #include "math/Utils.hpp" #include "net/Connection.hpp" #include "net/Login.hpp" #include "sound/SI2.hpp" #include "ui/CSimpleModelFFX.hpp" #include "ui/CSimpleTop.hpp" #include "ui/FrameScript.hpp" #include "ui/FrameXML.hpp" #include "ui/Interface.hpp" #include "ui/ScriptFunctions.hpp" #include "console/CVar.hpp" #include "util/Filesystem.hpp" #include "util/SysMessage.hpp" #include #include unsigned char InterfaceKey[256] = { 0xC3, 0x5B, 0x50, 0x84, 0xB9, 0x3E, 0x32, 0x42, 0x8C, 0xD0, 0xC7, 0x48, 0xFA, 0x0E, 0x5D, 0x54, 0x5A, 0xA3, 0x0E, 0x14, 0xBA, 0x9E, 0x0D, 0xB9, 0x5D, 0x8B, 0xEE, 0xB6, 0x84, 0x93, 0x45, 0x75, 0xFF, 0x31, 0xFE, 0x2F, 0x64, 0x3F, 0x3D, 0x6D, 0x07, 0xD9, 0x44, 0x9B, 0x40, 0x85, 0x59, 0x34, 0x4E, 0x10, 0xE1, 0xE7, 0x43, 0x69, 0xEF, 0x7C, 0x16, 0xFC, 0xB4, 0xED, 0x1B, 0x95, 0x28, 0xA8, 0x23, 0x76, 0x51, 0x31, 0x57, 0x30, 0x2B, 0x79, 0x08, 0x50, 0x10, 0x1C, 0x4A, 0x1A, 0x2C, 0xC8, 0x8B, 0x8F, 0x05, 0x2D, 0x22, 0x3D, 0xDB, 0x5A, 0x24, 0x7A, 0x0F, 0x13, 0x50, 0x37, 0x8F, 0x5A, 0xCC, 0x9E, 0x04, 0x44, 0x0E, 0x87, 0x01, 0xD4, 0xA3, 0x15, 0x94, 0x16, 0x34, 0xC6, 0xC2, 0xC3, 0xFB, 0x49, 0xFE, 0xE1, 0xF9, 0xDA, 0x8C, 0x50, 0x3C, 0xBE, 0x2C, 0xBB, 0x57, 0xED, 0x46, 0xB9, 0xAD, 0x8B, 0xC6, 0xDF, 0x0E, 0xD6, 0x0F, 0xBE, 0x80, 0xB3, 0x8B, 0x1E, 0x77, 0xCF, 0xAD, 0x22, 0xCF, 0xB7, 0x4B, 0xCF, 0xFB, 0xF0, 0x6B, 0x11, 0x45, 0x2D, 0x7A, 0x81, 0x18, 0xF2, 0x92, 0x7E, 0x98, 0x56, 0x5D, 0x5E, 0x69, 0x72, 0x0A, 0x0D, 0x03, 0x0A, 0x85, 0xA2, 0x85, 0x9C, 0xCB, 0xFB, 0x56, 0x6E, 0x8F, 0x44, 0xBB, 0x8F, 0x02, 0x22, 0x68, 0x63, 0x97, 0xBC, 0x85, 0xBA, 0xA8, 0xF7, 0xB5, 0x40, 0x68, 0x3C, 0x77, 0x86, 0x6F, 0x4B, 0xD7, 0x88, 0xCA, 0x8A, 0xD7, 0xCE, 0x36, 0xF0, 0x45, 0x6E, 0xD5, 0x64, 0x79, 0x0F, 0x17, 0xFC, 0x64, 0xDD, 0x10, 0x6F, 0xF3, 0xF5, 0xE0, 0xA6, 0xC3, 0xFB, 0x1B, 0x8C, 0x29, 0xEF, 0x8E, 0xE5, 0x34, 0xCB, 0xD1, 0x2A, 0xCE, 0x79, 0xC3, 0x9A, 0x0D, 0x36, 0xEA, 0x01, 0xE0, 0xAA, 0x91, 0x20, 0x54, 0xF0, 0x72, 0xD8, 0x1E, 0xC7, 0x89, 0xD2 }; int32_t CGlueMgr::m_acceptedEULA = 1; // TODO int32_t CGlueMgr::m_acceptedTerminationWithoutNotice; int32_t CGlueMgr::m_acceptedTOS = 1; // TODO int32_t CGlueMgr::m_processServerAlert = 1; int32_t CGlueMgr::m_pendingTimerAlert; int32_t CGlueMgr::m_accountMsgAvailable; char CGlueMgr::m_accountName[1280]; float CGlueMgr::m_aspect; bool CGlueMgr::m_authenticated; char CGlueMgr::m_currentScreen[64]; MipBits* CGlueMgr::m_cursorMipBits; int32_t CGlueMgr::m_disconnectPending; int32_t CGlueMgr::m_displayingQueueDialog; CGlueMgr::GLUE_IDLE_STATE CGlueMgr::m_idleState; int32_t CGlueMgr::m_initialized; int32_t CGlueMgr::m_lastLoginResult; int32_t CGlueMgr::m_lastLoginState; int32_t CGlueMgr::m_loginResult; int32_t CGlueMgr::m_loginState; int32_t CGlueMgr::m_matrixChallengeCount; 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; float CGlueMgr::m_screenWidth; int32_t CGlueMgr::m_clientKickReason; int32_t CGlueMgr::m_showedDisconnect; CSimpleTop* CGlueMgr::m_simpleTop; int32_t CGlueMgr::m_suspended; int32_t CGlueMgr::m_surveyTimer; int32_t CGlueMgr::m_executedSurvey; int32_t CGlueMgr::m_surveyDownload; int32_t CGlueMgr::m_patchDownload; bool CGlueMgr::m_deleteLocalPatch; CHARACTER_INFO* CGlueMgr::m_characterInfo = nullptr; float CalculateAspectRatio() { auto widescreenVar = CVar::Lookup("widescreen"); auto resolutionVar = CVar::Lookup("gxResolution"); int32_t width = 4; int32_t height = 3; if (widescreenVar && widescreenVar->GetInt() && resolutionVar) { char separator; sscanf(resolutionVar->GetString(), "%d%c%d", &width, &separator, &height); } 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) { return; } CGlueMgr::m_lastLoginState = CGlueMgr::m_loginState; CGlueMgr::m_lastLoginResult = CGlueMgr::m_loginResult; // Authentication failure if (CGlueMgr::m_loginState == LOGIN_STATE_FAILED) { // Unknown result if (CGlueMgr::m_loginResult >= LOGIN_RESULT_MAX) { return; } // Parental control if (CGlueMgr::m_loginResult == LOGIN_PARENTALCONTROL) { auto resultStr = Grunt::g_LoginResultStringNames[LOGIN_PARENTALCONTROL]; auto resultText = FrameScript_GetText(resultStr, -1, GENDER_NOT_APPLICABLE); FrameScript_SignalEvent(3, "%s%s%s", "PARENTAL_CONTROL", resultText, "AUTH_PARENTAL_CONTROL_URL"); return; } // Other failures auto resultStr = Grunt::g_LoginResultStringNames[CGlueMgr::m_loginResult]; auto resultText = FrameScript_GetText(resultStr, -1, GENDER_NOT_APPLICABLE); const char* buttonText; if (false /* TODO SStrStrUTF8I(resultText, "") */) { buttonText = CGlueMgr::m_loginResult == LOGIN_FAILED ? "CONNECTION_HELP_HTML" : "OKAY_HTML"; } else { buttonText = CGlueMgr::m_loginResult == LOGIN_FAILED ? "CONNECTION_HELP" : "OKAY"; } FrameScript_SignalEvent(3, "%s%s", buttonText, resultText); return; } // Authentication in progress or success if (CGlueMgr::m_loginState != LOGIN_STATE_DISCONNECTED && CGlueMgr::m_loginState != LOGIN_STATE_SURVEY) { auto v3 = CGlueMgr::m_loginState < LOGIN_STATE_MAX; if (CGlueMgr::m_loginState == LOGIN_STATE_MATRIX || CGlueMgr::m_loginState == LOGIN_STATE_MATRIX_WAIT) { v3 = false; } if (CGlueMgr::m_loginState != LOGIN_STATE_TOKEN && CGlueMgr::m_loginState != LOGIN_STATE_TOKEN_WAIT && v3) { auto stateStr = Grunt::g_LoginStateStringNames[CGlueMgr::m_loginState]; auto stateText = FrameScript_GetText(stateStr, -1, GENDER_NOT_APPLICABLE); FrameScript_SignalEvent(3, "%s%s", "CANCEL", stateText); } } } int32_t CGlueMgr::HandleDisplaySizeChanged(const CSizeEvent& event) { if ( CGlueMgr::m_screenWidth > 0 && CGlueMgr::m_screenWidth == event.w && CGlueMgr::m_screenHeight > 0 && CGlueMgr::m_screenHeight == event.h ) { return 1; } CGlueMgr::m_screenWidth = event.w; CGlueMgr::m_screenHeight = event.h; float aspect = CalculateAspectRatio(); auto glueParent = static_cast(CScriptObject::GetScriptObjectByName("GlueParent", CSimpleFrame::GetObjectType())); if (glueParent) { glueParent->SetFrameScale(1.0f, true); CLayoutFrame::ResizePending(); } if (AreEqual(CGlueMgr::m_aspect, aspect, 0.0099999998)) { return 1; } CGlueMgr::m_aspect = aspect; CGlueMgr::m_reload = 1; return 1; } void CGlueMgr::GetRealmList(bool showProgress) { CGlueMgr::m_idleState = IDLE_REALM_LIST; CGlueMgr::m_showedDisconnect = 0; if (showProgress) { auto text = FrameScript_GetText("REALM_LIST_IN_PROGRESS", -1, FRAMESCRIPT_GENDER::GENDER_NOT_APPLICABLE); FrameScript_SignalEvent(3, "%s%s", "CANCEL", text); } ClientServices::GetRealmList(); } void CGlueMgr::GetCharacterList() { if (CGlueMgr::m_idleState != IDLE_WORLD_LOGIN) { CGlueMgr::m_idleState = IDLE_CHARACTER_LIST; auto text = FrameScript_GetText("CHAR_LIST_RETRIEVING", -1, GENDER_NOT_APPLICABLE); FrameScript_SignalEvent(3, "%s%s", "CANCEL", text); ClientServices::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"); FrameScript_SignalEvent(2u, "%d", CGlueMgr::m_clientKickReason); } else { 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(""); FrameScript_SignalEvent(2u, "%d", CGlueMgr::m_clientKickReason); } else { FrameScript_SignalEvent(3u, "%s%s", "OKAY", msg); } } ClientServices::LoginConnection()->Logoff(); return 1; } // TODO a1: const EVENT_DATA_IDLE* int32_t CGlueMgr::Idle(const void* a1, void* a2) { // TODO: // if (gxDevice->IsStereoEnabled) { // CGlueMgr::SetUIDepth(gxDevice->StereoGetConvergence); // } auto loginConnection = ClientServices::LoginConnection(); if (loginConnection) { // Virtual call (loginConnection + 184) leads to nullsub // Checked by tracing in debugger } if (CGlueMgr::m_processServerAlert) { // TODO: // v2 = SStrLen("SERVERALERT:"); // FrameScript_SignalEvent(0x15u, "%s", &CGlueMgr::m_serverAlert[(_DWORD)&v2[CGlueMgr::m_serverAlert[0] != -17 ? 0 : 3]]); CGlueMgr::m_processServerAlert = 0; } if (CGlueMgr::m_pendingTimerAlert) { FrameScript_SignalEvent(0x21u, "%d", CGlueMgr::m_pendingTimerAlert); CGlueMgr::m_pendingTimerAlert = 0; } // TODO: CKBPage::UpdateLoadingQueue(); if (CGlueMgr::m_idleState == IDLE_NONE) { if (CGlueMgr::m_reload) { if (!CGlueMgr::m_suspended) { CGlueMgr::Suspend(); CGlueMgr::Resume(); // TODO Sub4DA360(); CGlueMgr::SetScreen(CGlueMgr::m_currentScreen); } CGlueMgr::m_reload = 0; } if (CGlueMgr::m_accountMsgAvailable) { FrameScript_SignalEvent(0x22u, 0); CGlueMgr::m_accountMsgAvailable = 0; } // TODO CGlueMgr::HandleBattlenetDisconnect(); return 1; } // TODO: LOOP { ConsoleWrite(GRUNT DEBUG MESSAGE) } WOWCS_OPS op; const char* msg; int32_t result; int32_t errorCode; int32_t complete = ClientServices::Connection()->PollStatus(op, &msg, result, errorCode); switch (CGlueMgr::m_idleState) { case IDLE_LOGIN_SERVER_LOGIN: { CGlueMgr::PollLoginServerLogin(); break; } case IDLE_ACCOUNT_LOGIN: { CGlueMgr::PollAccountLogin(errorCode, msg, complete, result, op); break; } case IDLE_CHARACTER_LIST: { CGlueMgr::PollCharacterList(errorCode, msg, complete, result, op); break; } case IDLE_REALM_LIST: { CGlueMgr::PollRealmList(errorCode, msg, complete, result, op); break; } case IDLE_CREATE_CHARACTER: { CGlueMgr::PollCreateCharacter(errorCode, msg, complete, result, op); break; } case IDLE_DELETE_CHARACTER: { CGlueMgr::PollDeleteCharacter(errorCode, msg, complete, result, op); break; } case IDLE_ENTER_WORLD: { CGlueMgr::PollEnterWorld(); break; } case IDLE_WORLD_LOGIN: { FrameScript_SignalEvent(3u, "%s%s", "OKAY", msg); break; } case IDLE_12: { if (CGlueMgr::m_patchDownload) { CGlueMgr::PatchDownloadIdle(); } else if (CGlueMgr::m_surveyDownload) { CGlueMgr::SurveyDownloadIdle(); } break; } case IDLE_13: { CGlueMgr::PollUserSurvey(); break; } // TODO other idle states default: break; } return 1; } void CGlueMgr::Initialize() { CGlueMgr::m_initialized = 1; // TODO // - cvar stuff (tou, etc) CRect windowSize; g_theGxDevicePtr->CapsWindowSize(windowSize); CSizeEvent sizeEvent; sizeEvent.id = -1; sizeEvent.w = windowSize.maxX - windowSize.minX; sizeEvent.h = windowSize.maxY - windowSize.minY; CGlueMgr::HandleDisplaySizeChanged(sizeEvent); FrameXML_RegisterFactory("ModelFFX", &CSimpleModelFFX::Create, 0); CGlueMgr::Resume(); CRealmList::Initialize(); EventRegisterEx(EVENT_ID_IDLE, &CGlueMgr::Idle, 0, 0.0); // TODO // CGLCD::Initialize(); // sub_552380(); // TODO // - options changed warning stuff // TODO // AccountDataInitializeBasicSystem(); } void CGlueMgr::LoginServerLogin(const char* accountName, const char* password) { if (!CGlueMgr::m_scandllOkayToLogIn || !CGlueMgr::m_acceptedTOS || !CGlueMgr::m_acceptedEULA || CGlueMgr::m_idleState != IDLE_NONE) { return; } if (!accountName || !*accountName) { auto prompt = FrameScript_GetText("LOGIN_ENTER_NAME", -1, GENDER_NOT_APPLICABLE); FrameScript_SignalEvent(3, "%s%s", "OKAY", prompt); return; } if (!password || !*password) { auto prompt = FrameScript_GetText("LOGIN_ENTER_PASSWORD", -1, GENDER_NOT_APPLICABLE); FrameScript_SignalEvent(3, "%s%s", "OKAY", prompt); return; } CGlueMgr::m_loginResult = -1; CGlueMgr::m_loginState = -1; CGlueMgr::m_lastLoginResult = -1; CGlueMgr::m_lastLoginState = -1; CGlueMgr::m_authenticated = false; CGlueMgr::m_matrixRemaining = 0; CGlueMgr::m_idleState = IDLE_LOGIN_SERVER_LOGIN; CGlueMgr::m_showedDisconnect = 0; char* dest = CGlueMgr::m_accountName; for (const char* src = accountName; *src && dest < CGlueMgr::m_accountName + sizeof(CGlueMgr::m_accountName); src++, dest++) { if (src[0] == '|' && src[1] == '|') { src++; } *dest = *src; } *dest = '\0'; SStrUpper(CGlueMgr::m_accountName); // Show prompt FrameScript_SignalEvent(3, "%s", "CANCEL"); ClientServices::Logon(CGlueMgr::m_accountName, password); // Zero out password memset(const_cast(password), 0, SStrLen(password)); } void CGlueMgr::QuitGame() { ClientPostClose(0); } void CGlueMgr::EnterWorld() { // TODO: Proper implementation if (CCharacterSelection::GetNumCharacters() < 1) { return; } CGlueMgr::m_characterInfo = &CCharacterSelection::s_characterList[0].m_characterInfo; if (!m_characterInfo || !ClientServices::Connection()->IsConnected()) { return; } CGlueMgr::m_idleState = IDLE_ENTER_WORLD; CGlueMgr::m_showedDisconnect = 0; } void CGlueMgr::PollAccountLogin(int32_t errorCode, const char* msg, int32_t complete, int32_t result, WOWCS_OPS op) { auto login = ClientServices::LoginConnection(); if (login->GetLoginServerType() == 1 && CGlueMgr::m_loginState == LOGIN_STATE_FAILED) { CGlueMgr::DisplayLoginStatus(); ClientServices::Connection()->Cancel(2); login->Logoff(); CGlueMgr::m_idleState = IDLE_NONE; CGlueMgr::m_showedDisconnect = 0; return; } if (errorCode == 27) { // TODO AUTH_WAIT_QUEUE } else { if (CGlueMgr::m_displayingQueueDialog) { FrameScript_SignalEvent(3, "%s", "CANCEL"); CGlueMgr::m_displayingQueueDialog = 0; } FrameScript_SignalEvent(4, "%s", msg); } if (!complete) { return; } if (result == 0) { if (errorCode != 2) { // TODO // Select Error Description with or without URL } CGlueMgr::m_idleState = IDLE_NONE; CGlueMgr::m_showedDisconnect = 0; if (errorCode == 2) { CGlueMgr::m_disconnectPending = 1; ClientServices::Connection()->Disconnect(); } if (errorCode != 13) { CCharacterSelection::ClearCharacterList(); if (ClientServices::GetInstance()->m_realmList.Count()) { FrameScript_SignalEvent(5, nullptr); CRealmList::UpdateList(); } else { CGlueMgr::GetRealmList(true); } return; } if (!SStrCmpI(CGlueMgr::m_currentScreen, "charselect", STORM_MAX_STR)) { CGlueMgr::SetScreen("login"); return; } return; } if (op == COP_CONNECT) { // TODO: Correct arguments (they're not used inside method) ClientServices::Connection()->AccountLogin("", "", 0, 0); return; } CGlueMgr::SetScreen("charselect"); } void CGlueMgr::PollLoginServerLogin() { if (CGlueMgr::m_loginState != LOGIN_STATE_PIN_WAIT) { CGlueMgr::DisplayLoginStatus(); } // Open new client connection after successful authentication if (CGlueMgr::m_authenticated) { CGlueMgr::m_idleState = IDLE_NONE; CGlueMgr::m_showedDisconnect = 0; CGlueMgr::Sub4D8BA0(); CGlueMgr::m_authenticated = false; return; } switch (CGlueMgr::m_loginState) { case LOGIN_STATE_FAILED: { ClientServices::LoginConnection()->Logoff(); CGlueMgr::m_idleState = IDLE_NONE; CGlueMgr::m_showedDisconnect = 0; break; } case LOGIN_STATE_DOWNLOADFILE: { // TODO // Get String from Server's answer // v14 = (char *)(ClientServices::LoginConnection() + 3928); const char* v14 = ""; if (!SStrCmpI(v14, "Patch", STORM_MAX_STR)) { CGlueMgr::PatchDownloadStart(); } if (!SStrCmpI(v14, "Survey", STORM_MAX_STR)) { CGlueMgr::SurveyDownloadStart(); } break; } case LOGIN_STATE_PIN: { FrameScript_SignalEvent(5, nullptr); // TODO // Calling GruntLogin::GetPinInfo // v9 = (unsigned __int8 *)(*(int (__thiscall **)(int))(*(_DWORD *)v8 + 136))(v8); int32_t v9[10] = {}; FrameScript_SignalEvent(26, "%d%d%d%d%d%d%d%d%d%d", v9[0], v9[1], v9[2], v9[3], v9[4], v9[5], v9[6], v9[7], v9[8], v9[9]); CGlueMgr::m_loginState = LOGIN_STATE_PIN_WAIT; break; } case LOGIN_STATE_MATRIX: { // TODO // Calling GruntLogin::GetMatrixInfo // (*(void (__thiscall **)(int, int *, int *, int *, int *, unsigned __int8 *, _DWORD **))(*(_DWORD *)v10 + 160))(v10, &v73, &v69, &v72, &v70, &v77, &v75); CGlueMgr::m_matrixChallengeCount = 0; CGlueMgr::m_matrixRemaining = 0; CGlueMgr::m_loginState = LOGIN_STATE_MATRIX_WAIT; FrameScript_SignalEvent(5, 0); // TODO: FrameScript_SignalEvent(0x1Cu, "%d%d%d%d%b%d", v73, v69, v72, v70, v77, v75); break; } case LOGIN_STATE_TOKEN: { CGlueMgr::m_loginState = LOGIN_STATE_TOKEN_WAIT; FrameScript_SignalEvent(5, 0); FrameScript_SignalEvent(38, 0); break; } case LOGIN_STATE_CHECKINGVERSIONS: { uint8_t versionChecksum[20]; // TODO // uint8_t* versionChallenge = ClientServices::LoginConnection()->GetVersionChallenge(); // ChecksumExecutables(versionChallenge, 16, versionChecksum); ClientServices::LoginConnection()->ProveVersion(versionChecksum); break; } default: break; } } void CGlueMgr::PollCharacterList(int32_t errorCode, const char* msg, int32_t complete, int32_t result, WOWCS_OPS op) { FrameScript_SignalEvent(4, "%s", msg); if (CGlueMgr::HandleBattlenetDisconnect()) { CGlueMgr::m_idleState = IDLE_NONE; CGlueMgr::m_showedDisconnect = 0; } if (!complete) { return; } if (!result) { if (errorCode == 2) { CCharacterSelection::ClearCharacterList(); CGlueMgr::GetRealmList(true); } else { FrameScript_SignalEvent(3, "%s%s", "OKAY", msg); CGlueMgr::m_idleState = IDLE_NONE; CGlueMgr::m_showedDisconnect = 0; } return; } CGlueMgr::m_idleState = IDLE_NONE; CGlueMgr::m_showedDisconnect = 0; FrameScript_SignalEvent(5, nullptr); CCharacterSelection::UpdateCharacterList(); if (!CGlueMgr::m_accountMsgAvailable) { return; } FrameScript_SignalEvent(34, 0); CGlueMgr::m_accountMsgAvailable = 0; } void CGlueMgr::PollRealmList(int32_t errorCode, const char* msg, int32_t complete, int32_t result, WOWCS_OPS op) { FrameScript_SignalEvent(4u, "%s", msg); if (CGlueMgr::HandleBattlenetDisconnect()) { CGlueMgr::m_idleState = IDLE_NONE; CGlueMgr::m_showedDisconnect = 0; } if (!complete) { return; } if (result) { CGlueMgr::m_idleState = IDLE_NONE; CGlueMgr::m_showedDisconnect = 0; FrameScript_SignalEvent(5u, nullptr); CRealmList::UpdateList(); if (!CGlueMgr::m_accountMsgAvailable) return; FrameScript_SignalEvent(34u, nullptr); CGlueMgr::m_accountMsgAvailable = 0; } else { FrameScript_SignalEvent(3u, "%s%s", "OKAY", msg); CGlueMgr::m_idleState = IDLE_NONE; CGlueMgr::m_showedDisconnect = 0; } } void CGlueMgr::PollCreateCharacter(int32_t errorCode, const char* msg, int32_t complete, int32_t result, WOWCS_OPS op) { FrameScript_SignalEvent(4u, "%s", msg); if (CGlueMgr::HandleBattlenetDisconnect()) { CGlueMgr::m_idleState = IDLE_NONE; CGlueMgr::m_showedDisconnect = 0; } if (!complete) { return; } if (result) { CGlueMgr::m_idleState = IDLE_NONE; CGlueMgr::m_showedDisconnect = 0; FrameScript_SignalEvent(5u, 0); FrameScript_SignalEvent(0xCu, 0); CGlueMgr::SetScreen("charselect"); } else { FrameScript_SignalEvent(3u, "%s%s", "OKAY", msg); CGlueMgr::m_idleState = IDLE_NONE; CGlueMgr::m_showedDisconnect = 0; } } void CGlueMgr::PollDeleteCharacter(int32_t errorCode, const char* msg, int32_t complete, int32_t result, WOWCS_OPS op) { FrameScript_SignalEvent(4, "%s", msg); if (CGlueMgr::HandleBattlenetDisconnect()) { CGlueMgr::m_idleState = IDLE_NONE; CGlueMgr::m_showedDisconnect = 0; } if (!complete) { return; } if (result) { FrameScript_SignalEvent(13, 0); CGlueMgr::GetCharacterList(); return; } FrameScript_SignalEvent(3, "%s%s", "OKAY", msg); CGlueMgr::m_idleState = IDLE_NONE; CGlueMgr::m_showedDisconnect = 0; } void CGlueMgr::PollUserSurvey() { if (CGlueMgr::m_surveyDownload && false /* virtual call */) { if (CGlueMgr::m_executedSurvey) { // TODO } else { CGlueMgr::m_executedSurvey = 1; if (CGlueMgr::SurveyExecute()) { auto text = FrameScript_GetText("LOGIN_STATE_SURVEY", -1, FRAMESCRIPT_GENDER::GENDER_NOT_APPLICABLE); FrameScript_SignalEvent(3, "%s%s", "CANCEL", text); CGlueMgr::SurveySendResults(); // TODO: CGlueMgr::m_surveyTimer = OsGetAsyncTimeMs(); } } } } void CGlueMgr::CancelLogin() { if (CGlueMgr::m_idleState == IDLE_LOGIN_SERVER_LOGIN) { CGlueMgr::StatusDialogClick(); } } void CGlueMgr::InitCursor() { uint32_t width; uint32_t height; PIXEL_FORMAT format = PIXEL_ARGB8888; CGlueMgr::m_cursorMipBits = TextureLoadImage("Interface\\Cursor\\Point.blp", &width, &height, &format, nullptr, nullptr, nullptr, 0); STORM_ASSERT(width == 32); STORM_ASSERT(height == 32); STORM_ASSERT(format == PIXEL_ARGB8888); CGlueMgr::m_simpleTop->SetCursor(CGlueMgr::m_cursorMipBits); } void CGlueMgr::Resume() { CGlueMgr::m_disconnectPending = 0; CGlueMgr::m_reconnect = 0; CGlueMgr::m_idleState = IDLE_NONE; CGlueMgr::m_showedDisconnect = 0; CGlueMgr::m_characterInfo = nullptr; CGlueMgr::m_suspended = 0; CGlueMgr::m_reload = 0; CRect screenRect; g_theGxDevicePtr->CapsWindowSizeInScreenCoords(screenRect); CGlueMgr::m_screenWidth = screenRect.maxX - screenRect.minX; CGlueMgr::m_screenHeight = screenRect.maxY - screenRect.minY; CGlueMgr::m_aspect = CalculateAspectRatio(); CoordinateSetAspectRatio(CGlueMgr::m_aspect); // Create CSimpleTop auto m = SMemAlloc(sizeof(CSimpleTop), __FILE__, __LINE__, 0x0); auto top = new (m) CSimpleTop(); CGlueMgr::m_simpleTop = top; CGlueMgr::m_simpleTop->m_displaySizeCallback = &CGlueMgr::HandleDisplaySizeChanged; CGlueMgr::InitCursor(); // TODO // - setting mouse mode FrameScript_Flush(); SystemRegisterFunctions(); RegisterSimpleFrameScriptMethods(); GlueScriptEventsRegisterFunctions(); CharSelectRegisterScriptFunctions(); CharacterCreateRegisterScriptFunctions(); RealmListRegisterScriptFunctions(); SI2::RegisterScriptFunctions(); // TODO // AccountMsg_RegisterScriptFunctions(); CGVideoOptions::RegisterScriptFunctions(); // TODO // FrameScript::s_scriptFunctionsLoaded = 1; FrameScript_CreateEvents(g_glueScriptEvents, NUM_GLUE_SCRIPT_EVENTS); OsCreateDirectory("Logs", 0); CCharacterSelection::Initialize(); CCharacterCreation::Initialize(); CWOWClientStatus status; if (!SLogCreate("Logs\\GlueXML.log", 0, &status.m_logFile)) { SysMsgPrintf(SYSMSG_WARNING, "Cannot create WOWClient log file \"%s\"!", "Logs\\GlueXML.log"); } DeleteInterfaceFiles(); MD5_CTX md5; unsigned char digest1[16]; unsigned char digest2[16]; int32_t v8; unsigned char* v9; unsigned char* v10; MD5Init(&md5); switch (FrameXML_CheckSignature("Interface\\GlueXML\\GlueXML.toc", 0, InterfaceKey, digest1)) { case 0: status.Add(STATUS_WARNING, "GlueXML missing signature"); ClientPostClose(9); return; case 1: status.Add(STATUS_WARNING, "GlueXML has corrupt signature"); ClientPostClose(9); return; case 2: status.Add(STATUS_WARNING, "GlueXML is modified or corrupt"); ClientPostClose(9); return; case 3: FrameXML_FreeHashNodes(); FrameXML_CreateFrames("Interface\\GlueXML\\GlueXML.toc", 0, &md5, &status); MD5Final(digest2, &md5); v8 = 16; v9 = digest2; v10 = digest1; break; default: ClientPostClose(9); return; } // TODO // - some kind of digest validation? FrameScript_SignalEvent(22, nullptr); // TODO // CGlueMgr::InitializeFFX(); // TODO // ClientServices::SetMessageHandler(SMSG_CHARACTER_RENAME_RESULT, CGlueMgr::OnCharRenameResult, 0); // ClientServices::SetMessageHandler(SMSG_SET_PLAYER_DECLINED_NAMES_RESULT, CGlueMgr::OnCharDeclineResult, 0); // ClientServices::SetMessageHandler(SMSG_CHAR_CUSTOMIZE, CGlueMgr::OnCharCustomizeResult, 0); // ClientServices::SetMessageHandler(SMSG_REALM_SPLIT, CGlueMgr::OnRealmSplitMsg, 0); // ClientServices::SetMessageHandler(SMSG_KICK_REASON, CGlueMgr::OnKickReasonMsg, 0); // ClientServices::SetMessageHandler(SMSG_CHAR_FACTION_CHANGE, CGlueMgr::OnCharFactionChangeResult, 0); // TODO // CGlueMgr::m_pendingServerAlert = 1; // CGlueMgr::m_processServerAlert = 0; // CGlueMgr::m_serverAlert[0] = 0; // v21 = (const char *)ClientServices::GetServerAlertURL(); // v22 = (const CHAR *)FrameScript_GetText(v21, -1, 0); // if (!OsURLDownload(v22, CGlueMgr::ServerAlertURLCallback, 0)) { // CGlueMgr::m_pendingServerAlert = 0; // } } void CGlueMgr::SetCurrentAccount(const char* accountName) { SStrCopy(CGlueMgr::m_accountName, accountName, sizeof(CGlueMgr::m_accountName)); SStrUpper(CGlueMgr::m_accountName); } void CGlueMgr::SetLoginStateAndResult(LOGIN_STATE state, LOGIN_RESULT result, const char* addrStr, const char* stateStr, const char* resultStr, uint8_t flags) { // TODO // CGlueMgr::LogConnectionStatus("GRUNT: state: %s result: %s %s", a4); if (flags & 0x1) { CGlueMgr::m_accountMsgAvailable = 1; } if (state == LOGIN_STATE_AUTHENTICATED) { CGlueMgr::m_authenticated = true; } CGlueMgr::m_loginState = state; CGlueMgr::m_loginResult = result; } void CGlueMgr::SetScreen(const char* screen) { FrameScript_SignalEvent(0, "%s", screen); } void CGlueMgr::StatusDialogClick() { if (!SStrCmpI(CGlueMgr::m_currentScreen, "patchdownload", STORM_MAX_STR)) { CGlueMgr::SetScreen("login"); } switch (CGlueMgr::m_idleState) { case IDLE_NONE: { ClientServices::Connection()->Cleanup(); break; } case IDLE_LOGIN_SERVER_LOGIN: { ClientServices::LoginConnection()->Logoff(); CGlueMgr::m_showedDisconnect = 0; CGlueMgr::m_idleState = IDLE_NONE; break; } case IDLE_ACCOUNT_LOGIN: case IDLE_CHARACTER_LIST: { ClientServices::Connection()->Cancel(2); break; } case IDLE_REALM_LIST: case IDLE_CREATE_CHARACTER: case IDLE_DELETE_CHARACTER: case IDLE_ENTER_WORLD: { ClientServices::Connection()->Cancel(2); CGlueMgr::m_showedDisconnect = 0; CGlueMgr::m_idleState = IDLE_NONE; break; } case IDLE_7: case IDLE_8: case IDLE_9: { CGlueMgr::m_showedDisconnect = 0; CGlueMgr::m_idleState = IDLE_NONE; break; } case IDLE_WORLD_LOGIN: { CGlueMgr::m_showedDisconnect = 0; CGlueMgr::m_idleState = IDLE_NONE; CGlueMgr::GetCharacterList(); break; } case IDLE_12: case IDLE_13: { if (CGlueMgr::m_surveyDownload) { CGlueMgr::SurveyDownloadCancel(); CGlueMgr::m_showedDisconnect = 0; CGlueMgr::m_idleState = IDLE_NONE; } break; } } } void CGlueMgr::Sub4D8BA0() { if (CGlueMgr::m_idleState != IDLE_NONE) { return; } CGlueMgr::m_idleState = IDLE_ACCOUNT_LOGIN; CGlueMgr::m_showedDisconnect = 0; ClientServices::Connection()->Connect(); } void CGlueMgr::Suspend() { CGlueMgr::m_suspended = 1; // TODO if (CGlueMgr::m_simpleTop) { delete CGlueMgr::m_simpleTop; CGlueMgr::m_simpleTop = nullptr; } // TODO FrameXML_FreeHashNodes(); // TODO } void CGlueMgr::UpdateCurrentScreen(const char* screen) { // TODO SStrCopy(CGlueMgr::m_currentScreen, screen, sizeof(CGlueMgr::m_currentScreen)); // TODO } bool CGlueMgr::HandleBattlenetDisconnect() { return false; } void CGlueMgr::DeleteCharacter(uint64_t guid) { if (!guid) { return; } CGlueMgr::m_idleState = IDLE_DELETE_CHARACTER; CGlueMgr::m_showedDisconnect = 0; auto errorText = ClientServices::GetErrorToken(70); auto text = FrameScript_GetText(errorText, -1, GENDER_NOT_APPLICABLE); FrameScript_SignalEvent(3u, "%s%s", "CANCEL", text); ClientServices::CharacterDelete(guid); } void CGlueMgr::PollEnterWorld() { //if (!LoadingScreenDrawing()) // return; if (CGlueMgr::m_suspended) { CGlueMgr::m_idleState = IDLE_NONE; CGlueMgr::m_showedDisconnect = 0; //SI3::StopGlueMusic(3.0); //SI3::StopGlueAmbience(-1.0); ClientServices::CharacterLogin(CGlueMgr::m_characterInfo->guid, C3Vector()); return; } auto info = CGlueMgr::m_characterInfo; //if (*(_BYTE*)(info + 385)) // sub_4D9660(*(_BYTE*)(info + 377), (int)v51, *(_BYTE*)(info + 376), (int)&v68); CGlueMgr::Suspend(); ClientInitializeGame(info->mapID, info->position); } void CGlueMgr::SurveyDownloadStart() { } void CGlueMgr::SurveyDownloadCancel() { } void CGlueMgr::SurveyDownloadIdle() { } bool CGlueMgr::SurveyExecute() { return false; } void CGlueMgr::SurveySendResults() { } void CGlueMgr::PatchDownloadStart() { } void CGlueMgr::PatchDownloadIdle() { }