From 6722c5f82b5ee8a442f89c1a1e77ed414e4b210d Mon Sep 17 00:00:00 2001 From: momo5502 Date: Fri, 15 Jan 2016 19:23:07 +0100 Subject: [PATCH] Fix connect issue --- src/Components/Modules/AssetHandler.cpp | 4 +- src/Components/Modules/Menus.cpp | 342 +++++++++++------------- src/Components/Modules/Menus.hpp | 16 +- src/Game/Functions.cpp | 1 + src/Game/Functions.hpp | 3 + src/Game/Structs.hpp | 2 +- 6 files changed, 162 insertions(+), 206 deletions(-) diff --git a/src/Components/Modules/AssetHandler.cpp b/src/Components/Modules/AssetHandler.cpp index 3e92aad4..d98b37f4 100644 --- a/src/Components/Modules/AssetHandler.cpp +++ b/src/Components/Modules/AssetHandler.cpp @@ -185,9 +185,11 @@ namespace Components { Game::XAssetHeader header = { 0 }; + bool OriginalState = AssetHandler::BypassState; + AssetHandler::BypassState = true; header = Game::DB_FindXAssetHeader(type, filename); - AssetHandler::BypassState = false; + if(!OriginalState) AssetHandler::BypassState = false; return header; } diff --git a/src/Components/Modules/Menus.cpp b/src/Components/Modules/Menus.cpp index f55ea39f..cfddb3a7 100644 --- a/src/Components/Modules/Menus.cpp +++ b/src/Components/Modules/Menus.cpp @@ -113,7 +113,7 @@ namespace Components return var; } - Game::menuDef_t* Menus::ParseMenu(int handle) + Game::menuDef_t* Menus::ParseMenu(std::string name, int handle) { Game::menuDef_t* menu = Utils::Memory::AllocateArray(1); if (!menu) return nullptr; @@ -167,8 +167,8 @@ namespace Components } } - Menus::RemoveMenu(menu->window.name); - Menus::MenuList[menu->window.name] = menu; + Menus::RemoveMenu(name); + Menus::MenuList[name] = menu; return menu; } @@ -185,6 +185,9 @@ namespace Components if (Menus::IsValidSourceHandle(handle)) { + // Sanitize event name + std::string menuName = menu; + while (true) { ZeroMemory(&token, sizeof(token)); @@ -203,7 +206,10 @@ namespace Components if (!_stricmp(token.string, "menudef")) { - Game::menuDef_t* menudef = Menus::ParseMenu(handle); + std::string name = menu; + if (menus.size()) name += Utils::VA("_%d", menus.size()); // Append its id inside the menufile, to keep track of it for later reloading + + Game::menuDef_t* menudef = Menus::ParseMenu(name, handle); if (menudef) menus.push_back(menudef); } } @@ -455,18 +461,18 @@ namespace Components Game::XAssetHeader Menus::MenuLoad(Game::XAssetType type, const char* filename) { - return { Menus::FindMenuByName(Game::uiContext, filename) }; + return { Game::Menus_FindByName(Game::uiContext, filename) }; } Game::XAssetHeader Menus::MenuFileLoad(Game::XAssetType type, const char* filename) { Game::XAssetHeader header = { 0 }; - // Check if we already loaded it and free it, seems like the game deallocated it - Menus::RemoveMenuList(Menus::MenuListList[filename]); - Game::MenuList* menuList = Game::DB_FindXAssetHeader(type, filename).menuList; header.menuList = menuList; + + // Free the last menulist, as we have to rebuild it with the new menus + Menus::RemoveMenuList(filename); if (menuList) { @@ -493,23 +499,146 @@ namespace Components return header; } - void Menus::AddMenuListHook(Game::UiContext *dc, Game::MenuList *menuList, int close) + void Menus::RefreshMenus() { - Menus::ReloadStack(dc); +// std::map BrokenMenuList = Menus::MenuList; +// std::map RemappedMenus; +// +// if (!BrokenMenuList.size()) return; +// +// for (auto &i = BrokenMenuList.begin(); i != BrokenMenuList.end(); i++) +// { +// Menus::RemoveMenu(i->second); +// auto menus = Menus::LoadMenu(i->first.data()); +// +// if (!menus.size()) +// { +// RemappedMenus[i->second] = nullptr; // Remap old menu to NULL, this might initially have been a menu inside a menu +// } +// else +// { +// RemappedMenus[i->second] = menus[0]; // Remap old menu to new menu +// } +// } +// +// // Correct map for menus inside menus ;) +// for (auto &i = RemappedMenus.begin(); i != RemappedMenus.end(); i++) +// { +// if (!i->second) // Menu is NULL, that means it was probably stored inside another one +// { +// // Find its name first +// std::string name; +// for (auto j = BrokenMenuList.begin(); j != BrokenMenuList.end(); j++) +// { +// if (i->first == j->second) +// { +// name = j->first; +// break; +// } +// } +// +// // Unable to find the name +// // It's actually not possible that this happens! +// if (!name.size()) break; +// +// // Now find the new by its name +// for (auto j = Menus::MenuList.begin(); j != Menus::MenuList.end(); j++) +// { +// // We have found it, insert it into the map +// if (j->first == name) +// { +// i->second = j->second; +// break; +// } +// } +// +// // No corresponding menu has been found, try loading the original one +// if (!i->second) +// { +// i->second = AssetHandler::FindOriginalAsset(Game::XAssetType::ASSET_TYPE_MENU, name.data()).menu; +// } +// } +// } +// +// // Replace the menus in the ui context +// for (int i = 0; i < Game::uiContext->menuCount; i++) +// { +// auto mapEntry = RemappedMenus.find(Game::uiContext->menus[i]); +// +// if (mapEntry != RemappedMenus.end()) +// { +// Game::uiContext->menus[i] = mapEntry->second; +// } +// } +// +// // Replace menus in our menulist list :P +// for (auto &i = Menus::MenuListList.begin(); i != Menus::MenuListList.end(); i++) +// { +// Game::MenuList* list = i->second; +// +// if (list && list->menus) +// { +// for (int j = 0; j < list->menuCount; j++) +// { +// auto mapEntry = RemappedMenus.find(list->menus[j]); +// +// if (mapEntry != RemappedMenus.end()) +// { +// list->menus[j] = mapEntry->second; +// } +// } +// } +// } - Game::MenuList* menus = Game::UI_LoadMenus("ui_mp/menus.txt", 3); + for (auto i = Menus::MenuList.begin(); i != Menus::MenuList.end();i++) + { + Menus::RemoveMenuFromContext(Game::uiContext, i->second); + } - Game::UI_AddMenuList(dc, menus, close); - Game::UI_AddMenuList(dc, menuList, close); + Menus::FreeEverything(); } - void Menus::RemoveFromStack(Game::UiContext *dc, Game::menuDef_t *menu) + void Menus::ReinitializeMenusStub() { - // Search menu in stack + Menus::RefreshMenus(); + + Utils::Hook::Call(0x401700)(); + } + + bool Menus::IsMenuVisible(Game::UiContext *dc, Game::menuDef_t *menu) + { + std::string _connect = "connect"; + + if (menu && menu->window.name) + { + if (menu->window.name == _connect) // Check if we're supposed to draw the loadscreen + { + Game::menuDef_t* originalConnect = AssetHandler::FindOriginalAsset(Game::XAssetType::ASSET_TYPE_MENU, "connect").menu; + + if (originalConnect == menu) // Check if we draw the original loadscreen + { + //if (Menus::MenuList.find("connect") != Menus::MenuList.end()) // Check if we have a custom loadscreen, to prevent drawing the original one ontop + for (auto i = Menus::MenuList.begin(); i != Menus::MenuList.end();i++) + { + if (i->second && i->second->window.name && i->second->window.name == _connect) // We have a custom connect menu, don't display the game's + { + return false; + } + } + } + } + } + + return Game::Menu_IsVisible(dc, menu); + } + + void Menus::RemoveMenuFromContext(Game::UiContext *dc, Game::menuDef_t *menu) + { + // Search menu in context int i = 0; for (; i < dc->menuCount; i++) { - if (dc->Menus[i] == menu) + if (dc->menus[i] == menu) { break; } @@ -520,178 +649,14 @@ namespace Components { for (; i < dc->menuCount - 1; i++) { - dc->Menus[i] = dc->Menus[i + 1]; + dc->menus[i] = dc->menus[i + 1]; } // Clear last menu - dc->Menus[--dc->menuCount] = 0; + dc->menus[--dc->menuCount] = 0; } } - void __declspec(naked) Menus::OpenMenuStub() - { - __asm - { - // Menu - mov eax, [esp + 8h] - push eax - - // Context - mov eax, [esp + 8h] - push eax - - call Menus::IsMenuAllowed - add esp, 8h - - test al, al - jnz continue - - retn - - continue: - push ecx - mov [esp], 0 - mov eax, 4B72F8h - jmp eax - } - } - - void __declspec(naked) Menus::CloseMenuStub() - { - __asm - { - // Menu - mov eax, [esp + 8h] - push eax - - // Context - mov eax, [esp + 8h] - push eax - - call Menus::IsMenuAllowed - add esp, 8h - - test al, al - jnz continue - - retn - - continue: - sub esp, 17Ch - mov eax, 430D56h - jmp eax - } - } - - bool Menus::ReloadMenu(Game::UiContext *dc, Game::menuDef_t *menu) - { - // Find the name of our destroyed menu - std::string name; - auto i = Menus::MenuList.begin(); - for (; i != Menus::MenuList.end(); i++) - { - if (i->second == menu) - { - name = i->first; - break; - } - } - - // We have found it, so we can remove and reload it - if (i != Menus::MenuList.end()) - { - Menus::FreeMenu(menu); - Menus::MenuList.erase(i); - - // Load original menu, in case we can't reload a custom one - Game::menuDef_t* newMenu = AssetHandler::FindOriginalAsset(Game::XAssetType::ASSET_TYPE_MENU, name.data()).menu; - - // Try reloading our custom menu - auto newMenus = Menus::LoadMenu(name); - if (newMenus.size()) newMenu = newMenus[0]; - - // Now replace the destroyed menu with the new one in the stack - for (int i = 0; i < dc->menuCount; i++) - { - if (dc->Menus[i] == menu) - { - dc->Menus[i] = newMenu; - } - } - - return true; - } - else - { - Menus::RemoveFromStack(dc, menu); - } - - return false; - } - - void Menus::ReloadStack(Game::UiContext *dc) - { - for (int i = 0; i < dc->menuCount; i++) - { - Game::menuDef_t* menu = dc->Menus[i]; - if (menu && menu->window.name && IsBadReadPtr(menu->window.name, 1)) // Sanity checks - { - Menus::ReloadMenu(dc, menu); - } - } - } - - Game::menuDef_t* Menus::FindMenuByName(Game::UiContext* dc, const char* name) - { - for (int i = 0; i < dc->menuCount; i++) - { - Game::menuDef_t* menu = dc->Menus[i]; - if (menu && menu->window.name && !IsBadReadPtr(menu->window.name, 1)) // Sanity checks - { - if (!_strnicmp(name, menu->window.name, 0x7FFFFFFF)) - { - return menu; - } - } - else - { - Menus::ReloadMenu(dc, menu); - } - } - - return nullptr; - } - - bool Menus::IsMenuAllowed(Game::UiContext *dc, Game::menuDef_t *menu) - { - if (menu && menu->window.name && !IsBadReadPtr(menu->window.name, 1)) - { - if (std::string(menu->window.name) == "connect") // Check if we're supposed to draw the loadscreen - { - Game::menuDef_t* originalConnect = AssetHandler::FindOriginalAsset(Game::XAssetType::ASSET_TYPE_MENU, "connect").menu; - - if (originalConnect == menu) // Check if we draw the original loadscreen - { - if (Menus::MenuList.find("connect") != Menus::MenuList.end()) // Check if we have a custom loadscreen, to prevent drawing the original one ontop - { - Menus::RemoveFromStack(dc, menu); - return false; - } - } - } - - return true; - } - - Menus::ReloadMenu(dc, menu); - return false; - } - - bool Menus::IsMenuVisible(Game::UiContext *dc, Game::menuDef_t *menu) - { - return (Menus::IsMenuAllowed(dc, menu) && Game::Menu_IsVisible(dc, menu)); - } - void Menus::Add(std::string menu) { Menus::CustomMenus.push_back(menu); @@ -714,17 +679,8 @@ namespace Components // Intercept menu painting Utils::Hook(0x4FFBDF, Menus::IsMenuVisible, HOOK_CALL).Install()->Quick(); - // Intercept menu closing - Utils::Hook(0x430D50, Menus::CloseMenuStub, HOOK_JUMP).Install()->Quick(); - - // Intercept menu opening - Utils::Hook(0x4B72F0, Menus::OpenMenuStub, HOOK_JUMP).Install()->Quick(); - - // Custom Menus_FindByName - Utils::Hook(0x487240, Menus::FindMenuByName, HOOK_JUMP).Install()->Quick(); - - // Load menus ingame - //Utils::Hook(0x41C178, Menus::AddMenuListHook, HOOK_CALL).Install()->Quick(); + // Reinitialize ui + Utils::Hook(0x4A58C3, Menus::ReinitializeMenusStub, HOOK_CALL).Install()->Quick(); // disable the 2 new tokens in ItemParse_rect Utils::Hook::Set(0x640693, 0xEB); diff --git a/src/Components/Modules/Menus.hpp b/src/Components/Modules/Menus.hpp index a635a4b8..86aa306c 100644 --- a/src/Components/Modules/Menus.hpp +++ b/src/Components/Modules/Menus.hpp @@ -1,4 +1,5 @@ #define MAX_SOURCEFILES 64 +#undef LoadMenu namespace Components { @@ -32,7 +33,7 @@ namespace Components static int ReserveSourceHandle(); static bool IsValidSourceHandle(int handle); - static Game::menuDef_t* ParseMenu(int handle); + static Game::menuDef_t* ParseMenu(std::string name, int handle); static void FreeMenuSource(int handle); @@ -44,19 +45,12 @@ namespace Components static void RemoveMenuList(std::string menuList); static void RemoveMenuList(Game::MenuList* menuList); - static void AddMenuListHook(Game::UiContext *dc, Game::MenuList *menuList, int close); - - static Game::menuDef_t* FindMenuByName(Game::UiContext* dc, const char* name); - static void RemoveFromStack(Game::UiContext *dc, Game::menuDef_t *menu); - - static bool IsMenuAllowed(Game::UiContext *dc, Game::menuDef_t *menu); static bool IsMenuVisible(Game::UiContext *dc, Game::menuDef_t *menu); - static void OpenMenuStub(); - static void CloseMenuStub(); + static void RemoveMenuFromContext(Game::UiContext *dc, Game::menuDef_t *menu); - static void ReloadStack(Game::UiContext *dc); - static bool ReloadMenu(Game::UiContext *dc, Game::menuDef_t *menu); + static void ReinitializeMenusStub(); + static void RefreshMenus(); // Ugly! static int KeywordHash(char* key); diff --git a/src/Game/Functions.cpp b/src/Game/Functions.cpp index e4765e97..4a69107a 100644 --- a/src/Game/Functions.cpp +++ b/src/Game/Functions.cpp @@ -63,6 +63,7 @@ namespace Game Menus_CloseAll_t Menus_CloseAll = (Menus_CloseAll_t)0x4BA5B0; Menus_OpenByName_t Menus_OpenByName = (Menus_OpenByName_t)0x4CCE60; + Menus_FindByName_t Menus_FindByName = (Menus_FindByName_t)0x487240; Menu_IsVisible_t Menu_IsVisible = (Menu_IsVisible_t)0x4D77D0; Menus_MenuIsInStack_t Menus_MenuIsInStack = (Menus_MenuIsInStack_t)0x47ACB0; diff --git a/src/Game/Functions.hpp b/src/Game/Functions.hpp index beb7afbc..6eae865b 100644 --- a/src/Game/Functions.hpp +++ b/src/Game/Functions.hpp @@ -148,6 +148,9 @@ namespace Game typedef int(__cdecl * Menus_OpenByName_t)(UiContext *dc, const char *p); extern Menus_OpenByName_t Menus_OpenByName; + typedef menuDef_t *(__cdecl * Menus_FindByName_t)(UiContext *dc, const char *name); + extern Menus_FindByName_t Menus_FindByName; + typedef bool(__cdecl * Menu_IsVisible_t)(UiContext *dc, menuDef_t *menu); extern Menu_IsVisible_t Menu_IsVisible; diff --git a/src/Game/Structs.hpp b/src/Game/Structs.hpp index e2d99998..546c4f0a 100644 --- a/src/Game/Structs.hpp +++ b/src/Game/Structs.hpp @@ -881,7 +881,7 @@ namespace Game // float FPS; // float blurRadiusOut; char pad[56]; - menuDef_t *Menus[512]; + menuDef_t *menus[512]; char pad2[512]; int menuCount; // Unsure if below is correct