[Friends] Display friends in blue

This commit is contained in:
momo5502 2017-01-29 21:49:48 +01:00
parent 41c9ec9d32
commit 3d8a1010c2
5 changed files with 147 additions and 23 deletions

View File

@ -5,6 +5,8 @@ namespace Components
Utils::Signal<Dedicated::Callback> Dedicated::FrameSignal; Utils::Signal<Dedicated::Callback> Dedicated::FrameSignal;
Utils::Signal<Dedicated::Callback> Dedicated::FrameOnceSignal; Utils::Signal<Dedicated::Callback> Dedicated::FrameOnceSignal;
SteamID Dedicated::PlayerGuids[18];
bool Dedicated::SendChat; bool Dedicated::SendChat;
bool Dedicated::IsEnabled() 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) void Dedicated::TimeWrapStub(int code, const char* message)
{ {
static bool partyEnable; static bool partyEnable;
@ -152,6 +173,48 @@ namespace Components
Game::Com_Error(code, message); 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() void Dedicated::MapRotate()
{ {
if (!Dedicated::IsEnabled() && Dvar::Var("sv_dontrotate").get<bool>()) if (!Dedicated::IsEnabled() && Dvar::Var("sv_dontrotate").get<bool>())
@ -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<bool>())
{
static Utils::Time::Interval interval;
if(interval.elapsed(15s))
{
interval.update();
Dedicated::TransmitGuids();
}
}
});
} }
Dedicated::~Dedicated() Dedicated::~Dedicated()

View File

@ -14,6 +14,8 @@ namespace Components
const char* getName() override { return "Dedicated"; }; const char* getName() override { return "Dedicated"; };
#endif #endif
static SteamID PlayerGuids[18];
static bool IsEnabled(); static bool IsEnabled();
static void Heartbeat(); static void Heartbeat();
@ -27,6 +29,9 @@ namespace Components
static bool SendChat; static bool SendChat;
static void OnServerCommandStub();
static int OnServerCommand();
static void MapRotate(); static void MapRotate();
static void FrameHandler(); static void FrameHandler();
static void FrameStub(); static void FrameStub();
@ -40,6 +45,8 @@ namespace Components
static void PreSayStub(); static void PreSayStub();
static void PostSayStub(); static void PostSayStub();
static void TransmitGuids();
static void TimeWrapStub(int code, const char* message); static void TimeWrapStub(int code, const char* message);
}; };
} }

View File

@ -83,6 +83,7 @@ namespace Components
*function.add_params() = "iw4x_rank"; *function.add_params() = "iw4x_rank";
*function.add_params() = "iw4x_server"; *function.add_params() = "iw4x_server";
*function.add_params() = "iw4x_playing"; *function.add_params() = "iw4x_playing";
*function.add_params() = "iw4x_guid";
IPCHandler::SendWorker("friends", function.SerializeAsString()); IPCHandler::SendWorker("friends", function.SerializeAsString());
} }
@ -107,29 +108,55 @@ namespace Components
} }
} }
void Friends::SetServer() void Friends::ClearPresence(std::string key)
{ {
Proto::IPC::Function function; Proto::IPC::Function function;
function.set_name("setPresence"); function.set_name("setPresence");
*function.add_params() = "iw4x_server"; *function.add_params() = key;
*function.add_params() = Network::Address(*Game::connectedHost).getString();//reinterpret_cast<char*>(0x7ED3F8);
IPCHandler::SendWorker("friends", function.SerializeAsString()); 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<char*>(0x7ED3F8)
Friends::UpdateState(); Friends::UpdateState();
} }
void Friends::ClearServer() void Friends::ClearServer()
{ {
Proto::IPC::Function function; Friends::ClearPresence("iw4x_server");
function.set_name("setPresence");
*function.add_params() = "iw4x_server";
IPCHandler::SendWorker("friends", function.SerializeAsString());
Friends::UpdateState(); Friends::UpdateState();
} }
bool Friends::IsClientInParty(int /*controller*/, int clientNum)
{
if (clientNum < 0 || clientNum >= ARRAYSIZE(Dedicated::PlayerGuids)) return false;
std::lock_guard<std::recursive_mutex> _(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() void Friends::UpdateRank()
{ {
static Utils::Value<int> levelVal; static Utils::Value<int> levelVal;
@ -142,13 +169,7 @@ namespace Components
{ {
levelVal.set(level); levelVal.set(level);
Proto::IPC::Function function; Friends::SetPresence("iw4x_rank", std::string(reinterpret_cast<char*>(&level), 4));
function.set_name("setPresence");
*function.add_params() = "iw4x_rank";
*function.add_params() = std::string(reinterpret_cast<char*>(&level), 4);
IPCHandler::SendWorker("friends", function.SerializeAsString());
Friends::UpdateState(); Friends::UpdateState();
} }
} }
@ -299,6 +320,10 @@ namespace Components
{ {
entry->playing = atoi(value.data()) == 1; entry->playing = atoi(value.data()) == 1;
} }
else if(key == "iw4x_guid")
{
entry->guid.Bits = strtoull(value.data(), nullptr, 16);
}
else if (key == "iw4x_server") else if (key == "iw4x_server")
{ {
Network::Address oldAddress = entry->server; Network::Address oldAddress = entry->server;
@ -439,6 +464,9 @@ namespace Components
Utils::Hook(0x403582, Friends::DisconnectStub, HOOK_CALL).install()->quick(); Utils::Hook(0x403582, Friends::DisconnectStub, HOOK_CALL).install()->quick();
Utils::Hook(0x4CD023, Friends::SetServer, HOOK_JUMP).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"); auto fInterface = IPCHandler::NewInterface("steamCallbacks");
// Callback to update user information // Callback to update user information
@ -503,12 +531,8 @@ namespace Components
fInterface->map("presenceResponse", Friends::PresenceResponse); fInterface->map("presenceResponse", Friends::PresenceResponse);
fInterface->map("infoResponse", Friends::InfoResponse); fInterface->map("infoResponse", Friends::InfoResponse);
Proto::IPC::Function function; Friends::SetPresence("iw4x_playing", "1");
function.set_name("setPresence"); Friends::SetPresence("iw4x_guid", Utils::String::VA("%llX", Steam::SteamUser()->GetSteamID().Bits));
*function.add_params() = "iw4x_playing";
*function.add_params() = "1";
IPCHandler::SendWorker("friends", function.SerializeAsString());
} }
Friends::~Friends() Friends::~Friends()

View File

@ -16,6 +16,9 @@ namespace Components
static void UpdateRank(); static void UpdateRank();
static void UpdateHostname(Network::Address server, std::string hostname); 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: private:
#pragma pack(push, 4) #pragma pack(push, 4)
struct FriendRichPresenceUpdate struct FriendRichPresenceUpdate
@ -35,6 +38,7 @@ namespace Components
{ {
public: public:
SteamID userId; SteamID userId;
SteamID guid;
std::string name; std::string name;
std::string playerName; std::string playerName;
Network::Address server; Network::Address server;
@ -53,6 +57,8 @@ namespace Components
static void ClearServer(); static void ClearServer();
static void SetServer(); static void SetServer();
static bool IsClientInParty(int controller, int clientNum);
static void UpdateUserInfo(SteamID user); static void UpdateUserInfo(SteamID user);
static void UpdateState(); static void UpdateState();

View File

@ -178,7 +178,7 @@ namespace Components
void Network::SendCommand(Game::netsrc_t type, Network::Address target, std::string command, std::string data) void Network::SendCommand(Game::netsrc_t type, Network::Address target, std::string command, std::string data)
{ {
// Use space as separator (possible separators are '\n', ' '). // 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; std::string packet;
packet.append(command); packet.append(command);
packet.append(" ", 1); packet.append(" ", 1);