From 3d8a1010c2d2cac9a9ba181157562cba0dd244df Mon Sep 17 00:00:00 2001 From: momo5502 Date: Sun, 29 Jan 2017 21:49:48 +0100 Subject: [PATCH] [Friends] Display friends in blue --- src/Components/Modules/Dedicated.cpp | 87 ++++++++++++++++++++++++++++ src/Components/Modules/Dedicated.hpp | 7 +++ src/Components/Modules/Friends.cpp | 68 +++++++++++++++------- src/Components/Modules/Friends.hpp | 6 ++ src/Components/Modules/Network.cpp | 2 +- 5 files changed, 147 insertions(+), 23 deletions(-) diff --git a/src/Components/Modules/Dedicated.cpp b/src/Components/Modules/Dedicated.cpp index ea2c5de1..7baad92c 100644 --- a/src/Components/Modules/Dedicated.cpp +++ b/src/Components/Modules/Dedicated.cpp @@ -5,6 +5,8 @@ namespace Components Utils::Signal Dedicated::FrameSignal; Utils::Signal Dedicated::FrameOnceSignal; + SteamID Dedicated::PlayerGuids[18]; + bool Dedicated::SendChat; bool Dedicated::IsEnabled() @@ -129,6 +131,25 @@ namespace Components } } + void Dedicated::TransmitGuids() + { + std::string list = Utils::String::VA("%c", 20); + + for (int i = 0; i < 18; i++) + { + if (Game::svs_clients[i].state >= 3) + { + list.append(Utils::String::VA(" %llX", Game::svs_clients[i].steamid)); + } + else + { + list.append(" 0"); + } + } + + Game::SV_GameSendServerCommand(-1, 0, list.data()); + } + void Dedicated::TimeWrapStub(int code, const char* message) { static bool partyEnable; @@ -152,6 +173,48 @@ namespace Components Game::Com_Error(code, message); } + __declspec(naked) void Dedicated::OnServerCommandStub() + { + __asm + { + push eax + pushad + + call Dedicated::OnServerCommand + + mov [esp + 20h], eax + popad + pop eax + + test al, al + jnz returnSafe + + push 5944AEh + retn + + returnSafe: + push 594536h + retn + } + } + + int Dedicated::OnServerCommand() + { + Command::ClientParams params; + + if (params.length() > 17 && params.get(0)[0] == 20) + { + for (int client = 0; client < 18; client++) + { + Dedicated::PlayerGuids[client].Bits = strtoull(params.get(client + 1), nullptr, 16); + } + + return 1; + } + + return 0; + } + void Dedicated::MapRotate() { if (!Dedicated::IsEnabled() && Dvar::Var("sv_dontrotate").get()) @@ -470,6 +533,30 @@ namespace Components }); }); } + else + { + for(int i = 0; i < ARRAYSIZE(Dedicated::PlayerGuids); ++i) + { + Dedicated::PlayerGuids[i].Bits = 0; + } + + // Intercept server commands + Utils::Hook(0x59449F, Dedicated::OnServerCommandStub, HOOK_JUMP).install()->quick(); + } + + QuickPatch::OnFrame([]() + { + if(Dvar::Var("sv_running").get()) + { + static Utils::Time::Interval interval; + + if(interval.elapsed(15s)) + { + interval.update(); + Dedicated::TransmitGuids(); + } + } + }); } Dedicated::~Dedicated() diff --git a/src/Components/Modules/Dedicated.hpp b/src/Components/Modules/Dedicated.hpp index b562c6c3..491b5063 100644 --- a/src/Components/Modules/Dedicated.hpp +++ b/src/Components/Modules/Dedicated.hpp @@ -14,6 +14,8 @@ namespace Components const char* getName() override { return "Dedicated"; }; #endif + static SteamID PlayerGuids[18]; + static bool IsEnabled(); static void Heartbeat(); @@ -27,6 +29,9 @@ namespace Components static bool SendChat; + static void OnServerCommandStub(); + static int OnServerCommand(); + static void MapRotate(); static void FrameHandler(); static void FrameStub(); @@ -40,6 +45,8 @@ namespace Components static void PreSayStub(); static void PostSayStub(); + static void TransmitGuids(); + static void TimeWrapStub(int code, const char* message); }; } diff --git a/src/Components/Modules/Friends.cpp b/src/Components/Modules/Friends.cpp index 4c77cc24..22e6735d 100644 --- a/src/Components/Modules/Friends.cpp +++ b/src/Components/Modules/Friends.cpp @@ -83,6 +83,7 @@ namespace Components *function.add_params() = "iw4x_rank"; *function.add_params() = "iw4x_server"; *function.add_params() = "iw4x_playing"; + *function.add_params() = "iw4x_guid"; IPCHandler::SendWorker("friends", function.SerializeAsString()); } @@ -107,29 +108,55 @@ namespace Components } } - void Friends::SetServer() + void Friends::ClearPresence(std::string key) { Proto::IPC::Function function; function.set_name("setPresence"); - *function.add_params() = "iw4x_server"; - *function.add_params() = Network::Address(*Game::connectedHost).getString();//reinterpret_cast(0x7ED3F8); + *function.add_params() = key; IPCHandler::SendWorker("friends", function.SerializeAsString()); + } + void Friends::SetPresence(std::string key, std::string value) + { + Proto::IPC::Function function; + function.set_name("setPresence"); + *function.add_params() = key; + *function.add_params() = value; + + IPCHandler::SendWorker("friends", function.SerializeAsString()); + } + + void Friends::SetServer() + { + Friends::SetPresence("iw4x_server", Network::Address(*Game::connectedHost).getString()); // reinterpret_cast(0x7ED3F8) Friends::UpdateState(); } void Friends::ClearServer() { - Proto::IPC::Function function; - function.set_name("setPresence"); - *function.add_params() = "iw4x_server"; - - IPCHandler::SendWorker("friends", function.SerializeAsString()); - + Friends::ClearPresence("iw4x_server"); Friends::UpdateState(); } + bool Friends::IsClientInParty(int /*controller*/, int clientNum) + { + if (clientNum < 0 || clientNum >= ARRAYSIZE(Dedicated::PlayerGuids)) return false; + + std::lock_guard _(Friends::Mutex); + SteamID guid = Dedicated::PlayerGuids[clientNum]; + + for (auto entry : Friends::FriendsList) + { + if (entry.guid.Bits == guid.Bits && entry.playing && entry.online) + { + return true; + } + } + + return false; + } + void Friends::UpdateRank() { static Utils::Value levelVal; @@ -142,13 +169,7 @@ namespace Components { levelVal.set(level); - Proto::IPC::Function function; - function.set_name("setPresence"); - *function.add_params() = "iw4x_rank"; - *function.add_params() = std::string(reinterpret_cast(&level), 4); - - IPCHandler::SendWorker("friends", function.SerializeAsString()); - + Friends::SetPresence("iw4x_rank", std::string(reinterpret_cast(&level), 4)); Friends::UpdateState(); } } @@ -299,6 +320,10 @@ namespace Components { entry->playing = atoi(value.data()) == 1; } + else if(key == "iw4x_guid") + { + entry->guid.Bits = strtoull(value.data(), nullptr, 16); + } else if (key == "iw4x_server") { Network::Address oldAddress = entry->server; @@ -439,6 +464,9 @@ namespace Components Utils::Hook(0x403582, Friends::DisconnectStub, HOOK_CALL).install()->quick(); Utils::Hook(0x4CD023, Friends::SetServer, HOOK_JUMP).install()->quick(); + // Show blue icons on the minimap + Utils::Hook(0x493130, Friends::IsClientInParty, HOOK_JUMP).install()->quick(); + auto fInterface = IPCHandler::NewInterface("steamCallbacks"); // Callback to update user information @@ -503,12 +531,8 @@ namespace Components fInterface->map("presenceResponse", Friends::PresenceResponse); fInterface->map("infoResponse", Friends::InfoResponse); - Proto::IPC::Function function; - function.set_name("setPresence"); - *function.add_params() = "iw4x_playing"; - *function.add_params() = "1"; - - IPCHandler::SendWorker("friends", function.SerializeAsString()); + Friends::SetPresence("iw4x_playing", "1"); + Friends::SetPresence("iw4x_guid", Utils::String::VA("%llX", Steam::SteamUser()->GetSteamID().Bits)); } Friends::~Friends() diff --git a/src/Components/Modules/Friends.hpp b/src/Components/Modules/Friends.hpp index 625725b5..cef1a983 100644 --- a/src/Components/Modules/Friends.hpp +++ b/src/Components/Modules/Friends.hpp @@ -16,6 +16,9 @@ namespace Components static void UpdateRank(); static void UpdateHostname(Network::Address server, std::string hostname); + static void SetPresence(std::string key, std::string value); + static void ClearPresence(std::string key); + private: #pragma pack(push, 4) struct FriendRichPresenceUpdate @@ -35,6 +38,7 @@ namespace Components { public: SteamID userId; + SteamID guid; std::string name; std::string playerName; Network::Address server; @@ -53,6 +57,8 @@ namespace Components static void ClearServer(); static void SetServer(); + static bool IsClientInParty(int controller, int clientNum); + static void UpdateUserInfo(SteamID user); static void UpdateState(); diff --git a/src/Components/Modules/Network.cpp b/src/Components/Modules/Network.cpp index 16d99732..d7d7fcc9 100644 --- a/src/Components/Modules/Network.cpp +++ b/src/Components/Modules/Network.cpp @@ -178,7 +178,7 @@ namespace Components void Network::SendCommand(Game::netsrc_t type, Network::Address target, std::string command, std::string data) { // Use space as separator (possible separators are '\n', ' '). - // Though, our handler only needs exactly 1 char as separator and doesn't which char it is + // Though, our handler only needs exactly 1 char as separator and doesn't care which char it is std::string packet; packet.append(command); packet.append(" ", 1);