diff --git a/iw4/Components/Network.cpp b/iw4/Components/Network.cpp index 059c1890..a76d81a4 100644 --- a/iw4/Components/Network.cpp +++ b/iw4/Components/Network.cpp @@ -119,10 +119,30 @@ namespace Components { OutputDebugStringA(Utils::VA("getinfo received: %s!", address.GetString())); + int clientCount = 0; + + for (int i = 0; i < *Game::svs_numclients; i++) + { + if (Game::svs_clients[i].state >= 3) + { + clientCount++; + } + } + + auto data = std::string(message->data); + auto challenge = data.substr(data.find_first_of(" \n") + 1); + challenge = challenge.substr(0, challenge.find_first_of(" \n")); + Utils::InfoString info; - info.Set("mapname", "mp_rust"); - info.Set("gamename", "tdm"); - info.Set("testKey", "testVal"); + info.Set("challenge", challenge.data()); // TODO: Fill! + info.Set("gamename", "IW4"); + info.Set("hostname", Dvar::Var("sv_hostname").Get()); + info.Set("mapname", Dvar::Var("mapname").Get()); + info.Set("gametype", Dvar::Var("g_gametype").Get()); + info.Set("fs_game", Dvar::Var("fs_game").Get()); + info.Set("xuid", Utils::VA("%llX", Steam::SteamUser()->GetSteamID().m_Bits)); + info.Set("clients", Utils::VA("%i", clientCount)); + info.Set("sv_maxclients", Utils::VA("%i", *Game::svs_numclients)); Network::Send(Game::NS_CLIENT, address, Utils::VA("infoResponse\n%s\n", info.Build().data())); }); diff --git a/iw4/Game/Functions.cpp b/iw4/Game/Functions.cpp index 6cd908cb..bc7fde52 100644 --- a/iw4/Game/Functions.cpp +++ b/iw4/Game/Functions.cpp @@ -67,6 +67,9 @@ namespace Game source_t **sourceFiles = (source_t **)0x7C4A98; keywordHash_t **menuParseKeywordHash = (keywordHash_t **)0x63AE928; + int* svs_numclients = (int*)0x31D938C; + client_t* svs_clients = (client_t*)0x31D9390; + void* ReallocateAssetPool(XAssetType type, unsigned int newSize) { int elSize = DB_GetXAssetSizeHandlers[type](); diff --git a/iw4/Game/Functions.hpp b/iw4/Game/Functions.hpp index 511dd6b7..70717d5e 100644 --- a/iw4/Game/Functions.hpp +++ b/iw4/Game/Functions.hpp @@ -121,6 +121,9 @@ namespace Game extern DWORD* cmd_argc; extern char*** cmd_argv; + extern int* svs_numclients; + extern client_t* svs_clients; + extern source_t **sourceFiles; extern keywordHash_t **menuParseKeywordHash; diff --git a/iw4/Game/Structs.hpp b/iw4/Game/Structs.hpp index 10f81963..691e49fc 100644 --- a/iw4/Game/Structs.hpp +++ b/iw4/Game/Structs.hpp @@ -638,6 +638,45 @@ namespace Game int readcount; // 28 } msg_t; +#pragma pack(push, 1) + typedef struct client_s + { + // 0 + int state; + // 4 + char pad[36]; + // 40 + netadr_t adr; + // 60 + char pad1[1568]; + // 1628 + char connectInfoString[1024]; + // 2652 + char pad2[133192]; + // 135844 + char name[16]; + // 135860 + char pad3[12]; + // 135872 + int snapNum; + // 135876 + int pad4; + // 135880 + short ping; + // 135882 + //char pad5[142390]; + char pad5[133158]; + // 269040 + int isBot; + // 269044 + char pad6[9228]; + // 278272 + __int64 steamid; + // 278280 + char pad7[403592]; + } client_t; +#pragma pack(pop) + // Q3TA precompiler code //undef if binary numbers of the form 0b... or 0B... are not allowed diff --git a/iw4/STDInclude.hpp b/iw4/STDInclude.hpp index 980e8d69..eba6c50f 100644 --- a/iw4/STDInclude.hpp +++ b/iw4/STDInclude.hpp @@ -5,6 +5,9 @@ #include #include #include +#include + +#pragma comment(lib, "Crypt32.lib") #include #include diff --git a/iw4/Steam/Interfaces/SteamUser.cpp b/iw4/Steam/Interfaces/SteamUser.cpp index b0f56bef..71330562 100644 --- a/iw4/Steam/Interfaces/SteamUser.cpp +++ b/iw4/Steam/Interfaces/SteamUser.cpp @@ -15,7 +15,16 @@ namespace Steam SteamID User::GetSteamID() { SteamID id; - id.m_Bits = 0x110000100000000 | 0x1337; + + DATA_BLOB DataIn; + DATA_BLOB DataOut; + + DataIn.pbData = (BYTE *)"AAAAAAAAAA"; + DataIn.cbData = 10; + + CryptProtectData(&DataIn, NULL, NULL, NULL, NULL, CRYPTPROTECT_LOCAL_MACHINE, &DataOut); + + id.m_Bits = 0x110000100000000 | ::Utils::OneAtATime((char*)DataOut.pbData, 52); return id; } diff --git a/iw4/Utils/Utils.cpp b/iw4/Utils/Utils.cpp index c8de385b..a924646a 100644 --- a/iw4/Utils/Utils.cpp +++ b/iw4/Utils/Utils.cpp @@ -59,6 +59,21 @@ namespace Utils } } + unsigned int OneAtATime(char *key, size_t len) + { + unsigned int hash, i; + for (hash = i = 0; i < len; ++i) + { + hash += key[i]; + hash += (hash << 10); + hash ^= (hash >> 6); + } + hash += (hash << 3); + hash ^= (hash >> 11); + hash += (hash << 15); + return hash; + } + // Infostring class void InfoString::Set(std::string key, std::string value) { diff --git a/iw4/Utils/Utils.hpp b/iw4/Utils/Utils.hpp index 4ba36bdd..8d61dad7 100644 --- a/iw4/Utils/Utils.hpp +++ b/iw4/Utils/Utils.hpp @@ -5,6 +5,7 @@ namespace Utils bool EndsWith(const char* heystack, const char* needle); std::vector Explode(const std::string& str, const std::string& delimiters); void Replace(std::string &string, std::string find, std::string replace); + unsigned int OneAtATime(char *key, size_t len); class InfoString {