From 412dbe3d332420e1dc756dbe830747dc39111a30 Mon Sep 17 00:00:00 2001 From: momo5502 Date: Sun, 27 Dec 2015 03:56:00 +0100 Subject: [PATCH] Dedicated party stuff. --- iw4/Components/Colors.cpp | 2 +- iw4/Components/Dedicated.cpp | 113 ++++++++++++++++++++++ iw4/Components/Dedicated.hpp | 16 +++ iw4/Components/Dvar.cpp | 22 ++++- iw4/Components/Dvar.hpp | 16 ++- iw4/Components/Loader.cpp | 1 + iw4/Components/Loader.hpp | 1 + iw4/Components/Localization.cpp | 2 +- iw4/Components/Party.cpp | 103 +++++++++++++++++++- iw4/Components/Party.hpp | 5 + iw4/Components/QuickPatch.cpp | 21 +++- iw4/Components/Window.cpp | 2 +- iw4/Game/Functions.cpp | 7 ++ iw4/Game/Functions.hpp | 12 +++ iw4/Game/Structs.hpp | 26 +++++ iw4/STDInclude.hpp | 8 +- iw4/Steam/Interfaces/SteamMatchmaking.cpp | 39 ++++++-- iw4/Steam/Interfaces/SteamMatchmaking.hpp | 19 ++++ iw4/Steam/Interfaces/SteamUser.cpp | 2 +- iw4/Steam/Steam.cpp | 72 +++++++++++++- iw4/Steam/Steam.hpp | 46 ++++++++- iw4/Utils/Hooking.hpp | 9 ++ iw4/iw4.vcxproj | 3 + iw4/iw4.vcxproj.filters | 6 ++ iw4/iw4.vcxproj.user | 1 + 25 files changed, 525 insertions(+), 29 deletions(-) create mode 100644 iw4/Components/Dedicated.cpp create mode 100644 iw4/Components/Dedicated.hpp diff --git a/iw4/Components/Colors.cpp b/iw4/Components/Colors.cpp index ae6e535a..4e623297 100644 --- a/iw4/Components/Colors.cpp +++ b/iw4/Components/Colors.cpp @@ -107,6 +107,6 @@ namespace Components Renderer::OnFrame(Colors::UpdateColorTable); // Register dvar - Colors::NewColors = Dvar::Var::Register("cg_newColors", true, Game::dvar_flag::DVAR_FLAG_SAVED, "Use WarfareČ color code style."); + Colors::NewColors = Dvar::Register("cg_newColors", true, Game::dvar_flag::DVAR_FLAG_SAVED, "Use WarfareČ color code style."); } } diff --git a/iw4/Components/Dedicated.cpp b/iw4/Components/Dedicated.cpp new file mode 100644 index 00000000..0fd80f76 --- /dev/null +++ b/iw4/Components/Dedicated.cpp @@ -0,0 +1,113 @@ +#include "..\STDInclude.hpp" + +namespace Components +{ + Dvar::Var Dedicated::Dedi; + + bool Dedicated::IsDedicated() + { + return (Dedicated::Dedi.Get() != 0); + } + + void Dedicated::InitDedicatedServer() + { + const char* fastfiles[7] = + { + "code_post_gfx_mp", + "localized_code_post_gfx_mp", + "ui_mp", + "localized_ui_mp", + "common_mp", + "localized_common_mp", + "patch_mp" + }; + + memcpy((void*)0x66E1CB0, &fastfiles, sizeof(fastfiles)); + Game::LoadInitialFF(); + + Utils::Hook::Call(0x4F84C0); + } + + Dedicated::Dedicated() + { + Dedicated::Dedi = Dvar::Register("dedicated", 0, 0, 2, Game::dvar_flag::DVAR_FLAG_SERVERINFO | Game::dvar_flag::DVAR_FLAG_WRITEPROTECTED, "Start as dedicated"); + + // TODO: Beautify! + char* cmd = GetCommandLineA(); + char* value = strstr(cmd, " dedicated"); + + if (value) + { + value += 10; + + while (*value == ' ' || *value == '"') + value++; + + char num[2] = { 0, 0 }; + num[0] = *value; + + int dediVal = atoi(num); + + if (dediVal && dediVal < 3) + { + Dedicated::Dedi.SetRaw(dediVal); + } + } + + if (Dedicated::IsDedicated()) + { + Utils::Hook(0x60BE98, Dedicated::InitDedicatedServer, HOOK_CALL).Install()->Quick(); + + Utils::Hook::Set(0x683370, 0xC3); // steam sometimes doesn't like the server + + Utils::Hook::Set(0x5B4FF0, 0xC3); // self-registration on party + Utils::Hook::Set(0x426130, 0xC3); // other party stuff? + + Utils::Hook::Set(0x4D7030, 0xC3); // upnp stuff + + Utils::Hook::Set(0x4B0FC3, 0x04); // make CL_Frame do client packets, even for game state 9 + Utils::Hook::Set(0x4F5090, 0xC3); // init sound system (1) + Utils::Hook::Set(0x507B80, 0xC3); // start render thread + Utils::Hook::Set(0x4F84C0, 0xC3); // R_Init caller + Utils::Hook::Set(0x46A630, 0xC3); // init sound system (2) + Utils::Hook::Set(0x41FDE0, 0xC3); // Com_Frame audio processor? + Utils::Hook::Set(0x41B9F0, 0xC3); // called from Com_Frame, seems to do renderer stuff + Utils::Hook::Set(0x41D010, 0xC3); // CL_CheckForResend, which tries to connect to the local server constantly + Utils::Hook::Set(0x62B6C0, 0xC3); // UI expression 'DebugPrint', mainly to prevent some console spam + + Utils::Hook::Set(0x468960, 0xC3); // some mixer-related function called on shutdown + Utils::Hook::Set(0x60AD90, 0); // masterServerName flags + + Utils::Hook::Nop(0x4DCEC9, 2); // some check preventing proper game functioning + Utils::Hook::Nop(0x507C79, 6); // another similar bsp check + Utils::Hook::Nop(0x414E4D, 6); // unknown check in SV_ExecuteClientMessage (0x20F0890 == 0, related to client->f_40) + Utils::Hook::Nop(0x4DCEE9, 5); // some deinit renderer function + Utils::Hook::Nop(0x59A896, 5); // warning message on a removed subsystem + Utils::Hook::Nop(0x4B4EEF, 5); // same as above + Utils::Hook::Nop(0x64CF77, 5); // function detecting video card, causes Direct3DCreate9 to be called + Utils::Hook::Nop(0x60BC52, 0x15); // recommended settings check + + // isHost script call return 0 + Utils::Hook::Set(0x5DEC04, 0); + + // map_rotate func + //*(DWORD*)0x4152E8 = (DWORD)SV_MapRotate_f; + + // sv_network_fps max 1000, and uncheat + Utils::Hook::Set(0x4D3C67, 0); // ? + Utils::Hook::Set(0x4D3C69, 1000); + + // r_loadForRenderer default to 0 + Utils::Hook::Set(0x519DDF, 0); + + // disable cheat protection on onlinegame + Utils::Hook::Set(0x404CF7, 0x80); + + // some d3d9 call on error + Utils::Hook::Set(0x508470, 0xC3); + + // stop saving a config_mp.cfg + Utils::Hook::Set(0x60B240, 0xC3); + } + } +} diff --git a/iw4/Components/Dedicated.hpp b/iw4/Components/Dedicated.hpp new file mode 100644 index 00000000..f494de8f --- /dev/null +++ b/iw4/Components/Dedicated.hpp @@ -0,0 +1,16 @@ +namespace Components +{ + class Dedicated : public Component + { + public: + Dedicated(); + const char* GetName() { return "Dedicated"; }; + + static bool IsDedicated(); + + private: + static Dvar::Var Dedi; + + static void InitDedicatedServer(); + }; +} diff --git a/iw4/Components/Dvar.cpp b/iw4/Components/Dvar.cpp index 7070d98a..c66adfab 100644 --- a/iw4/Components/Dvar.cpp +++ b/iw4/Components/Dvar.cpp @@ -100,20 +100,32 @@ namespace Components } } - template<> static Dvar::Var Dvar::Var::Register(const char* name, bool value, Game::dvar_flag flag, const char* description) + void Dvar::Var::SetRaw(int integer) { - return Game::Dvar_RegisterBool(name, value, flag, description); + if (this->dvar) + { + this->dvar->current.integer = integer; + } } - template<> static Dvar::Var Dvar::Var::Register(const char* name, const char* value, Game::dvar_flag flag, const char* description) + + template<> static Dvar::Var Dvar::Register(const char* name, bool value, Dvar::Flag flag, const char* description) { - return Game::Dvar_RegisterString(name, value, flag, description); + return Game::Dvar_RegisterBool(name, value, flag.val, description); + } + template<> static Dvar::Var Dvar::Register(const char* name, const char* value, Dvar::Flag flag, const char* description) + { + return Game::Dvar_RegisterString(name, value, flag.val, description); + } + template<> static Dvar::Var Dvar::Register(const char* name, int value, int min, int max, Dvar::Flag flag, const char* description) + { + return Game::Dvar_RegisterInt(name, value, min, max, flag.val, description); } Game::dvar_t* Dvar::RegisterName(const char* name, const char* default, Game::dvar_flag flag, const char* description) { // TODO: Register string dvars here - return Dvar::Var::Register(name, "Unknown Soldier", (Game::dvar_flag)(flag | Game::dvar_flag::DVAR_FLAG_SAVED), description).Get(); + return Dvar::Register(name, "Unknown Soldier", Dvar::Flag(flag | Game::dvar_flag::DVAR_FLAG_SAVED).val, description).Get(); } Dvar::Dvar() diff --git a/iw4/Components/Dvar.hpp b/iw4/Components/Dvar.hpp index c2c23b85..7b4f026f 100644 --- a/iw4/Components/Dvar.hpp +++ b/iw4/Components/Dvar.hpp @@ -3,6 +3,14 @@ namespace Components class Dvar : public Component { public: + struct Flag + { + Flag(Game::dvar_flag flag) : val(flag){}; + Flag(int flag) : Flag((Game::dvar_flag)flag) {}; + + Game::dvar_flag val; + }; + class Var { public: @@ -21,8 +29,8 @@ namespace Components void Set(int integer); void Set(float value); - // Only strings and bools use this type of declaration - template static Var Register(const char* name, T value, Game::dvar_flag flag, const char* description); + // TODO: Add others + void SetRaw(int integer); private: Game::dvar_t* dvar; @@ -31,6 +39,10 @@ namespace Components Dvar(); const char* GetName() { return "Dvar"; }; + // Only strings and bools use this type of declaration + template static Var Register(const char* name, T value, Flag flag, const char* description); + template static Var Register(const char* name, T value, T min, T max, Flag flag, const char* description); + private: static Game::dvar_t* RegisterName(const char* name, const char* default, Game::dvar_flag flag, const char* description); }; diff --git a/iw4/Components/Loader.cpp b/iw4/Components/Loader.cpp index bc9849a6..18fb9300 100644 --- a/iw4/Components/Loader.cpp +++ b/iw4/Components/Loader.cpp @@ -18,6 +18,7 @@ namespace Components Loader::Register(new Network()); Loader::Register(new RawFiles()); Loader::Register(new Renderer()); + Loader::Register(new Dedicated()); Loader::Register(new FastFiles()); Loader::Register(new Materials()); Loader::Register(new FileSystem()); diff --git a/iw4/Components/Loader.hpp b/iw4/Components/Loader.hpp index 2771b3fa..e6efd466 100644 --- a/iw4/Components/Loader.hpp +++ b/iw4/Components/Loader.hpp @@ -32,6 +32,7 @@ namespace Components #include "Party.hpp" // Destroys the order, but requires network classes :D #include "RawFiles.hpp" #include "Renderer.hpp" +#include "Dedicated.hpp" #include "FastFiles.hpp" #include "Materials.hpp" #include "FileSystem.hpp" diff --git a/iw4/Components/Localization.cpp b/iw4/Components/Localization.cpp index 5bc5ef4f..36c83a83 100644 --- a/iw4/Components/Localization.cpp +++ b/iw4/Components/Localization.cpp @@ -34,7 +34,7 @@ namespace Components Utils::Hook(0x629B90, Localization::Get, HOOK_JUMP).Install()->Quick(); //Localization::Set("MENU_MULTIPLAYER_CAPS", "^5Fotze"); - Localization::UseLocalization = Dvar::Var::Register("ui_localize", true, Game::dvar_flag::DVAR_FLAG_NONE, "Use localization strings"); + Localization::UseLocalization = Dvar::Register("ui_localize", true, Game::dvar_flag::DVAR_FLAG_NONE, "Use localization strings"); } Localization::~Localization() diff --git a/iw4/Components/Party.cpp b/iw4/Components/Party.cpp index 5b4f0f87..4fab07d0 100644 --- a/iw4/Components/Party.cpp +++ b/iw4/Components/Party.cpp @@ -3,6 +3,19 @@ namespace Components { Party::JoinContainer Party::Container; + std::map Party::LobbyMap; + + SteamID Party::GenerateLobbyId() + { + SteamID id; + + id.m_comp.m_unAccountID = Game::Com_Milliseconds(); + id.m_comp.m_EUniverse = 1; + id.m_comp.m_EAccountType = 8; + id.m_comp.m_unAccountInstance = 0x40000; + + return id; + } void Party::Connect(Network::Address target) { @@ -16,6 +29,42 @@ namespace Components Command::Execute("openmenu popup_reconnectingtoparty"); } + const char* Party::GetLobbyInfo(SteamID lobby, std::string key) + { + if (Party::LobbyMap.find(lobby.m_Bits) != Party::LobbyMap.end()) + { + Network::Address address = Party::LobbyMap[lobby.m_Bits]; + + if (key == "addr") + { + return Utils::VA("%d", address.Get()->ip[0] | (address.Get()->ip[1] << 8) | (address.Get()->ip[2] << 16) | (address.Get()->ip[3] << 24)); + } + else if (key =="port") + { + return Utils::VA("%d", htons(address.GetPort())); + } + } + + return "212"; + } + + void Party::RemoveLobby(SteamID lobby) + { + if (Party::LobbyMap.find(lobby.m_Bits) != Party::LobbyMap.end()) + { + Party::LobbyMap.erase(Party::LobbyMap.find(lobby.m_Bits)); + } + } + + Game::netadr_t* PartyHost_GetMemberAddressBySlotInState(int unk, void *party, const int slot) + { + Game::netadr_t* addr = Game::PartyHost_GetMemberAddressBySlot(unk, party, slot); + + OutputDebugStringA(Network::Address(addr).GetString()); + + return addr; + } + Party::Party() { // various changes to SV_DirectConnect-y stuff to allow non-party joinees @@ -29,6 +78,36 @@ namespace Components Utils::Hook::Set(0x5AC2CF, 0xEB); // CL_ParseGamestate Utils::Hook::Set(0x5AC2C3, 0xEB); // CL_ParseGamestate + // AnonymousAddRequest + Utils::Hook::Set(0x5B5E18, 0xEB); + Utils::Hook::Set(0x5B5E64, 0xEB); + Utils::Hook::Nop(0x5B5E5C, 2); + + // HandleClientHandshake + Utils::Hook::Set(0x5B6EA5, 0xEB); + Utils::Hook::Set(0x5B6EF3, 0xEB); + Utils::Hook::Nop(0x5B6EEB, 2); + + // Allow local connections + Utils::Hook::Set(0x4D43DA, 0xEB); + + // LobbyID mismatch + Utils::Hook::Nop(0x4E50D6, 2); + Utils::Hook::Set(0x4E50DA, 0xEB); + + // causes 'does current Steam lobby match' calls in Steam_JoinLobby to be ignored + Utils::Hook::Set(0x49D007, 0xEB); + + // functions checking party heartbeat timeouts, cause random issues + Utils::Hook::Nop(0x4E532D, 5); + Utils::Hook::Nop(0x4CAA5D, 5); + + // Steam_JoinLobby call causes migration + Utils::Hook::Nop(0x5AF851, 5); + Utils::Hook::Set(0x5AF85B, 0xEB); + + Utils::Hook(0x5B5544, PartyHost_GetMemberAddressBySlotInState, HOOK_CALL).Install()->Quick(); + Command::Add("connect", [] (Command::Params params) { if (params.Length() < 2) @@ -39,6 +118,28 @@ namespace Components Party::Connect(Network::Address(params[1])); }); + Command::Add("connect2", [] (Command::Params params) + { + if (params.Length() < 2) + { + return; + } + + Network::Address address(params[1]); + + SteamID id = Party::GenerateLobbyId(); + + Party::LobbyMap[id.m_Bits] = address; + + OutputDebugStringA(Utils::VA("Mapping %llX -> %s", id.m_Bits, address.GetString())); + + Game::Steam_JoinLobby(id, 0); + + // Callback not registered on first try + // TODO: Fix :D + if (Party::LobbyMap.size() <= 1) Game::Steam_JoinLobby(id, 0); + }); + Renderer::OnFrame([] () { if (!Party::Container.Valid) return; @@ -128,6 +229,6 @@ namespace Components Party::~Party() { - + Party::LobbyMap.clear(); } } diff --git a/iw4/Components/Party.hpp b/iw4/Components/Party.hpp index 9f2d6237..e4893e2b 100644 --- a/iw4/Components/Party.hpp +++ b/iw4/Components/Party.hpp @@ -8,6 +8,8 @@ namespace Components const char* GetName() { return "Party"; }; static void Connect(Network::Address target); + static const char* GetLobbyInfo(SteamID lobby, std::string key); + static void RemoveLobby(SteamID lobby); private: struct JoinContainer @@ -19,5 +21,8 @@ namespace Components }; static JoinContainer Container; + static std::map LobbyMap; + + static SteamID GenerateLobbyId(); }; } diff --git a/iw4/Components/QuickPatch.cpp b/iw4/Components/QuickPatch.cpp index 08f37871..522f1d60 100644 --- a/iw4/Components/QuickPatch.cpp +++ b/iw4/Components/QuickPatch.cpp @@ -17,17 +17,34 @@ namespace Components Utils::Hook::Nop(0x451145, 5); Utils::Hook::Set(0x45114C, 0xEB); + // Apply new playlist + char* playlist = "mp_playlists_dlc2"; + Utils::Hook::Set(0x494803, playlist); + Utils::Hook::Set(0x4C6EC1, playlist); + Utils::Hook::Set(0x4CF7F9, playlist); + Utils::Hook::Set(0x4D6E63, playlist); + Utils::Hook::Set(0x4D7358, playlist); + Utils::Hook::Set(0x4D73C8, playlist); + Utils::Hook::Set(0x4F4EA1, playlist); + Utils::Hook::Set(0x4D47FB, "mp_playlists_dlc2.ff"); + Utils::Hook::Set(0x60B06E, "playlists.patch2"); + // disable playlist download function Utils::Hook::Set(0x4D4790, 0xC3); // disable playlist.ff loading function - Utils::Hook::Set(0x4D6E60, 0xC3); + //Utils::Hook::Set(0x4D6E60, 0xC3); + + // Load playlist, but don't delete it + Utils::Hook::Nop(0x4D6EBB, 5); + Utils::Hook::Nop(0x4D6E67, 5); + Utils::Hook::Nop(0x4D6E71, 2); // playlist dvar 'validity check' Utils::Hook::Set(0x4B1170, 0xC3); //Got playlists is true - Utils::Hook::Set(0x1AD3680, true); + //Utils::Hook::Set(0x1AD3680, true); // LSP disabled Utils::Hook::Set(0x435950, 0xC3); // LSP HELLO diff --git a/iw4/Components/Window.cpp b/iw4/Components/Window.cpp index 8c93be99..26332fa9 100644 --- a/iw4/Components/Window.cpp +++ b/iw4/Components/Window.cpp @@ -21,7 +21,7 @@ namespace Components Window::Window() { // Borderless window - Window::NoBorder = Dvar::Var::Register("r_noborder", true, Game::dvar_flag::DVAR_FLAG_SAVED, "Do not use a border in windowed mode"); + Window::NoBorder = Dvar::Register("r_noborder", true, Game::dvar_flag::DVAR_FLAG_SAVED, "Do not use a border in windowed mode"); Utils::Hook(0x507643, Window::StyleHookStub, HOOK_CALL).Install()->Quick(); } } diff --git a/iw4/Game/Functions.cpp b/iw4/Game/Functions.cpp index 762983e7..40152816 100644 --- a/iw4/Game/Functions.cpp +++ b/iw4/Game/Functions.cpp @@ -61,6 +61,9 @@ namespace Game NET_CompareAdr_t NET_CompareAdr = (NET_CompareAdr_t)0x4D0AA0; NET_StringToAdr_t NET_StringToAdr = (NET_StringToAdr_t)0x409010; + Live_MPAcceptInvite_t Live_MPAcceptInvite = (Live_MPAcceptInvite_t)0x420A6D; + + LoadInitialFF_t LoadInitialFF = (LoadInitialFF_t)0x506AC0; LoadModdableRawfile_t LoadModdableRawfile = (LoadModdableRawfile_t)0x61ABC0; sendOOB_t OOBPrint = (sendOOB_t)0x4AEF00; @@ -69,12 +72,16 @@ namespace Game PC_ReadTokenHandle_t PC_ReadTokenHandle = (PC_ReadTokenHandle_t)0x4D2060; PC_SourceError_t PC_SourceError = (PC_SourceError_t)0x467A00; + PartyHost_GetMemberAddressBySlot_t PartyHost_GetMemberAddressBySlot = (PartyHost_GetMemberAddressBySlot_t)0x44E100; + Script_Alloc_t Script_Alloc = (Script_Alloc_t)0x422E70; Script_SetupTokens_t Script_SetupTokens = (Script_SetupTokens_t)0x4E6950; Script_CleanString_t Script_CleanString = (Script_CleanString_t)0x498220; SetConsole_t SetConsole = (SetConsole_t)0x44F060; + Steam_JoinLobby_t Steam_JoinLobby = (Steam_JoinLobby_t)0x49CF70; + UI_AddMenuList_t UI_AddMenuList = (UI_AddMenuList_t)0x4533C0; Win_GetLanguage_t Win_GetLanguage = (Win_GetLanguage_t)0x45CBA0; diff --git a/iw4/Game/Functions.hpp b/iw4/Game/Functions.hpp index 512ecc94..b8436f50 100644 --- a/iw4/Game/Functions.hpp +++ b/iw4/Game/Functions.hpp @@ -139,6 +139,12 @@ namespace Game typedef bool(__cdecl * NET_StringToAdr_t)(const char*, netadr_t*); extern NET_StringToAdr_t NET_StringToAdr; + typedef void(__cdecl * Live_MPAcceptInvite_t)(_XSESSION_INFO *hostInfo, const int controllerIndex, bool fromGameInvite); + extern Live_MPAcceptInvite_t Live_MPAcceptInvite; + + typedef void(*LoadInitialFF_t)(void); + extern LoadInitialFF_t LoadInitialFF; + typedef void* (__cdecl * LoadModdableRawfile_t)(int a1, const char* filename); extern LoadModdableRawfile_t LoadModdableRawfile; @@ -154,6 +160,9 @@ namespace Game typedef void(__cdecl * PC_SourceError_t)(int, const char*, ...); extern PC_SourceError_t PC_SourceError; + typedef netadr_t *(__cdecl * PartyHost_GetMemberAddressBySlot_t)(int unk, void *party, const int slot); + extern PartyHost_GetMemberAddressBySlot_t PartyHost_GetMemberAddressBySlot; + typedef script_t* (__cdecl * Script_Alloc_t)(int length); extern Script_Alloc_t Script_Alloc; @@ -166,6 +175,9 @@ namespace Game typedef void(__cdecl * SetConsole_t)(const char* cvar, const char* value); extern SetConsole_t SetConsole; + typedef void(__cdecl * Steam_JoinLobby_t)(SteamID, char); + extern Steam_JoinLobby_t Steam_JoinLobby; + typedef void(__cdecl * UI_AddMenuList_t)(UiContext *dc, MenuList *menuList, int close); extern UI_AddMenuList_t UI_AddMenuList; diff --git a/iw4/Game/Structs.hpp b/iw4/Game/Structs.hpp index 7503d370..34187667 100644 --- a/iw4/Game/Structs.hpp +++ b/iw4/Game/Structs.hpp @@ -890,4 +890,30 @@ namespace Game unsigned __int16 nextOverride; unsigned __int16 usageFrame; }; + + struct XNKID + { + char ab[8]; + }; + + struct XNADDR + { + in_addr ina; + in_addr inaOnline; + unsigned __int16 wPortOnline; + char abEnet[6]; + char abOnline[20]; + }; + + struct XNKEY + { + char ab[16]; + }; + + struct _XSESSION_INFO + { + XNKID sessionID; + XNADDR hostAddress; + XNKEY keyExchangeKey; + }; } diff --git a/iw4/STDInclude.hpp b/iw4/STDInclude.hpp index bc5e9e6d..8883ccb4 100644 --- a/iw4/STDInclude.hpp +++ b/iw4/STDInclude.hpp @@ -8,9 +8,11 @@ #include #include #include +#include #pragma comment(lib, "Winmm.lib") #pragma comment(lib, "Crypt32.lib") +#pragma comment(lib, "Ws2_32.lib") #include #include @@ -21,12 +23,12 @@ #include #include -#include "Game\Structs.hpp" -#include "Game\Functions.hpp" - #include "Utils\Utils.hpp" #include "Utils\Hooking.hpp" #include "Steam\Steam.hpp" +#include "Game\Structs.hpp" +#include "Game\Functions.hpp" + #include "Components\Loader.hpp" diff --git a/iw4/Steam/Interfaces/SteamMatchmaking.cpp b/iw4/Steam/Interfaces/SteamMatchmaking.cpp index d6199d93..1986a2bb 100644 --- a/iw4/Steam/Interfaces/SteamMatchmaking.cpp +++ b/iw4/Steam/Interfaces/SteamMatchmaking.cpp @@ -24,7 +24,6 @@ namespace Steam unsigned __int64 Matchmaking::RequestLobbyList() { - // TODO: Implement return 0; } @@ -51,18 +50,42 @@ namespace Steam unsigned __int64 Matchmaking::CreateLobby(int eLobbyType, int cMaxMembers) { - // TODO: Implement - return 0; + uint64_t result = Callbacks::RegisterCall(); + LobbyCreated* retvals = new LobbyCreated; + SteamID id; + + id.m_comp.m_unAccountID = 1337132; + id.m_comp.m_EUniverse = 1; + id.m_comp.m_EAccountType = 8; + id.m_comp.m_unAccountInstance = 0x40000; + + retvals->m_eResult = 1; + retvals->m_ulSteamIDLobby = id; + + Callbacks::ReturnCall(retvals, sizeof(LobbyCreated), LobbyCreated::CallbackID, result); + + Matchmaking::JoinLobby(id); + + return result; } unsigned __int64 Matchmaking::JoinLobby(SteamID steamIDLobby) { - // TODO: Implement - return 0; + uint64_t result = Callbacks::RegisterCall(); + LobbyEnter* retvals = new LobbyEnter; + retvals->m_bLocked = false; + retvals->m_EChatRoomEnterResponse = 1; + retvals->m_rgfChatPermissions = 0xFFFFFFFF; + retvals->m_ulSteamIDLobby = steamIDLobby; + + Callbacks::ReturnCall(retvals, sizeof(LobbyEnter), LobbyEnter::CallbackID, result); + + return result; } void Matchmaking::LeaveLobby(SteamID steamIDLobby) { + Components::Party::RemoveLobby(steamIDLobby); } bool Matchmaking::InviteUserToLobby(SteamID steamIDLobby, SteamID steamIDInvitee) @@ -77,12 +100,12 @@ namespace Steam SteamID Matchmaking::GetLobbyMemberByIndex(SteamID steamIDLobby, int iMember) { - return SteamID(); + return SteamUser()->GetSteamID(); } const char *Matchmaking::GetLobbyData(SteamID steamIDLobby, const char *pchKey) { - return ""; + return Components::Party::GetLobbyInfo(steamIDLobby, pchKey); } bool Matchmaking::SetLobbyData(SteamID steamIDLobby, const char *pchKey, const char *pchValue) @@ -160,7 +183,7 @@ namespace Steam SteamID Matchmaking::GetLobbyOwner(SteamID steamIDLobby) { - return SteamID(); + return SteamUser()->GetSteamID(); } bool Matchmaking::SetLobbyOwner(SteamID steamIDLobby, SteamID steamIDNewOwner) diff --git a/iw4/Steam/Interfaces/SteamMatchmaking.hpp b/iw4/Steam/Interfaces/SteamMatchmaking.hpp index 382643d8..f8dc9106 100644 --- a/iw4/Steam/Interfaces/SteamMatchmaking.hpp +++ b/iw4/Steam/Interfaces/SteamMatchmaking.hpp @@ -1,5 +1,24 @@ namespace Steam { + struct LobbyCreated + { + enum { CallbackID = 513 }; + + int m_eResult; + int m_pad; + SteamID m_ulSteamIDLobby; + }; + + struct LobbyEnter + { + enum { CallbackID = 504 }; + + SteamID m_ulSteamIDLobby; + int m_rgfChatPermissions; + bool m_bLocked; + int m_EChatRoomEnterResponse; + }; + class Matchmaking { public: diff --git a/iw4/Steam/Interfaces/SteamUser.cpp b/iw4/Steam/Interfaces/SteamUser.cpp index 9f7f112a..9071c6ac 100644 --- a/iw4/Steam/Interfaces/SteamUser.cpp +++ b/iw4/Steam/Interfaces/SteamUser.cpp @@ -26,7 +26,7 @@ namespace Steam CryptProtectData(&Data[0], NULL, NULL, NULL, NULL, CRYPTPROTECT_LOCAL_MACHINE, &Data[1]); - subId = ::Utils::OneAtATime((char*)Data[1].pbData, 52); //(Game::Com_Milliseconds() + timeGetTime()); + subId = /*::Utils::OneAtATime((char*)Data[1].pbData, 52); */(Game::Com_Milliseconds() + timeGetTime()); } id.m_Bits = 0x110000100000000 | subId; diff --git a/iw4/Steam/Steam.cpp b/iw4/Steam/Steam.cpp index 8a0bfca5..35cd48d3 100644 --- a/iw4/Steam/Steam.cpp +++ b/iw4/Steam/Steam.cpp @@ -3,6 +3,71 @@ namespace Steam { + uint64_t Callbacks::CallID = 0; + std::map Callbacks::Calls; + std::map Callbacks::ResultHandlers; + std::vector Callbacks::Results; + std::vector Callbacks::CallbackList; + + uint64_t Callbacks::RegisterCall() + { + Callbacks::Calls[Callbacks::CallID] = false; + return Callbacks::CallID++; + } + + void Callbacks::RegisterCallback(Callbacks::Base* handler, int callback) + { + handler->SetICallback(callback); + Callbacks::CallbackList.push_back(handler); + } + + void Callbacks::RegisterCallResult(uint64_t call, Callbacks::Base* result) + { + OutputDebugStringA(::Utils::VA("Registering result: %d", result->GetICallback())); + + Callbacks::ResultHandlers[call] = result; + } + + void Callbacks::ReturnCall(void* data, int size, int type, uint64_t call) + { + Callbacks::Result result; + + Callbacks::Calls[call] = true; + + result.call = call; + result.data = data; + result.size = size; + result.type = type; + + Callbacks::Results.push_back(result); + } + + void Callbacks::RunCallbacks() + { + for (auto result : Callbacks::Results) + { + if (Callbacks::ResultHandlers.find(result.call) != Callbacks::ResultHandlers.end()) + { + Callbacks::ResultHandlers[result.call]->Run(result.data, false, result.call); + } + + for (auto callback : Callbacks::CallbackList) + { + if (callback && callback->GetICallback() == result.type) + { + callback->Run(result.data, false, 0); + } + } + + if (result.data) + { + delete[] result.data; + } + } + + Callbacks::Results.clear(); + } + extern "C" { bool SteamAPI_Init() @@ -10,16 +75,19 @@ namespace Steam return true; } - void SteamAPI_RegisterCallResult() + void SteamAPI_RegisterCallResult(Callbacks::Base* result, uint64_t call) { + Callbacks::RegisterCallResult(call, result); } - void SteamAPI_RegisterCallback() + void SteamAPI_RegisterCallback(Callbacks::Base* handler, int callback) { + Callbacks::RegisterCallback(handler, callback); } void SteamAPI_RunCallbacks() { + Callbacks::RunCallbacks(); } void SteamAPI_Shutdown() diff --git a/iw4/Steam/Steam.hpp b/iw4/Steam/Steam.hpp index 341b0332..ad4a4be5 100644 --- a/iw4/Steam/Steam.hpp +++ b/iw4/Steam/Steam.hpp @@ -26,9 +26,51 @@ typedef union namespace Steam { + class Callbacks + { + public: + class Base + { + public: + Base() : Flags(0), Callback(0) {}; + + virtual void Run(void *pvParam) = 0; + virtual void Run(void *pvParam, bool bIOFailure, uint64_t hSteamAPICall) = 0; + virtual int GetCallbackSizeBytes() = 0; + + int GetICallback() { return Callback; } + void SetICallback(int iCallback) { Callback = iCallback; } + + protected: + unsigned char Flags; + int Callback; + }; + + struct Result + { + void* data; + int size; + int type; + uint64_t call; + }; + + static uint64_t RegisterCall(); + static void RegisterCallback(Base* handler, int callback); + static void RegisterCallResult(uint64_t call, Base* result); + static void ReturnCall(void* data, int size, int type, uint64_t call); + static void RunCallbacks(); + + private: + static uint64_t CallID; + static std::map Calls; + static std::map ResultHandlers; + static std::vector Results; + static std::vector CallbackList; + }; + STEAM_EXPORT bool SteamAPI_Init(); - STEAM_EXPORT void SteamAPI_RegisterCallResult(); - STEAM_EXPORT void SteamAPI_RegisterCallback(); + STEAM_EXPORT void SteamAPI_RegisterCallResult(Callbacks::Base* result, uint64_t call); + STEAM_EXPORT void SteamAPI_RegisterCallback(Callbacks::Base* handler, int callback); STEAM_EXPORT void SteamAPI_RunCallbacks(); STEAM_EXPORT void SteamAPI_Shutdown(); STEAM_EXPORT void SteamAPI_UnregisterCallResult(); diff --git a/iw4/Utils/Hooking.hpp b/iw4/Utils/Hooking.hpp index 95732731..bad657c9 100644 --- a/iw4/Utils/Hooking.hpp +++ b/iw4/Utils/Hooking.hpp @@ -22,6 +22,15 @@ namespace Utils void* GetAddress(); void Quick(); + template static T Call(DWORD function) + { + __asm + { + mov eax, function + call eax + } + } + static void Nop(void* place, size_t length); static void Nop(DWORD place, size_t length); diff --git a/iw4/iw4.vcxproj b/iw4/iw4.vcxproj index 100d4d6f..5a8ca7e6 100644 --- a/iw4/iw4.vcxproj +++ b/iw4/iw4.vcxproj @@ -39,6 +39,7 @@ true WIN32;NDEBUG;_WINDOWS;_USRDLL;IW4_EXPORTS;%(PreprocessorDefinitions) true + true Windows @@ -55,6 +56,7 @@ + @@ -91,6 +93,7 @@ + diff --git a/iw4/iw4.vcxproj.filters b/iw4/iw4.vcxproj.filters index f3c559b3..3c465967 100644 --- a/iw4/iw4.vcxproj.filters +++ b/iw4/iw4.vcxproj.filters @@ -128,6 +128,9 @@ Source\Components\Modules + + Source\Components\Modules + @@ -232,5 +235,8 @@ Source\Components\Modules + + Source\Components\Modules + \ No newline at end of file diff --git a/iw4/iw4.vcxproj.user b/iw4/iw4.vcxproj.user index 7cccaf23..a1b5683e 100644 --- a/iw4/iw4.vcxproj.user +++ b/iw4/iw4.vcxproj.user @@ -4,5 +4,6 @@ iw4m.exe D:\Games\SteamLibrary\steamapps\common\Call of Duty Modern Warfare 2\ WindowsLocalDebugger + +set dedicated 0 \ No newline at end of file