[Friends] First working version of the friend system
This commit is contained in:
parent
f20fa5763c
commit
22b91c7a77
@ -6,6 +6,59 @@ namespace Components
|
|||||||
std::recursive_mutex Friends::Mutex;
|
std::recursive_mutex Friends::Mutex;
|
||||||
std::vector<Friends::Friend> Friends::FriendsList;
|
std::vector<Friends::Friend> Friends::FriendsList;
|
||||||
|
|
||||||
|
void Friends::SortIndividualList(std::vector<Friends::Friend>* list)
|
||||||
|
{
|
||||||
|
qsort(list->data(), list->size(), sizeof(Friends::Friend), [](const void* first, const void* second)
|
||||||
|
{
|
||||||
|
const Friends::Friend* friend1 = static_cast<const Friends::Friend*>(first);
|
||||||
|
const Friends::Friend* friend2 = static_cast<const Friends::Friend*>(second);
|
||||||
|
|
||||||
|
std::string name1 = Utils::String::ToLower(Colors::Strip(friend1->name));
|
||||||
|
std::string name2 = Utils::String::ToLower(Colors::Strip(friend2->name));
|
||||||
|
|
||||||
|
return name1.compare(name2);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void Friends::SortList()
|
||||||
|
{
|
||||||
|
std::lock_guard<std::recursive_mutex> _(Friends::Mutex);
|
||||||
|
|
||||||
|
std::vector<Friends::Friend> playingList;
|
||||||
|
std::vector<Friends::Friend> onlineList;
|
||||||
|
std::vector<Friends::Friend> offlineList;
|
||||||
|
|
||||||
|
// Split up the list
|
||||||
|
for(auto entry : Friends::FriendsList)
|
||||||
|
{
|
||||||
|
if(entry.online)
|
||||||
|
{
|
||||||
|
if(entry.server.getType() == Game::NA_BAD)
|
||||||
|
{
|
||||||
|
onlineList.push_back(entry);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
playingList.push_back(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
offlineList.push_back(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Friends::SortIndividualList(&playingList);
|
||||||
|
Friends::SortIndividualList(&onlineList);
|
||||||
|
Friends::SortIndividualList(&offlineList);
|
||||||
|
|
||||||
|
Friends::FriendsList.clear();
|
||||||
|
|
||||||
|
Utils::Merge(&Friends::FriendsList, playingList);
|
||||||
|
Utils::Merge(&Friends::FriendsList, onlineList);
|
||||||
|
Utils::Merge(&Friends::FriendsList, offlineList);
|
||||||
|
}
|
||||||
|
|
||||||
void Friends::UpdateUserInfo(SteamID user)
|
void Friends::UpdateUserInfo(SteamID user)
|
||||||
{
|
{
|
||||||
Proto::IPC::Function function;
|
Proto::IPC::Function function;
|
||||||
@ -30,6 +83,42 @@ namespace Components
|
|||||||
IPCHandler::SendWorker("friends", function.SerializeAsString());
|
IPCHandler::SendWorker("friends", function.SerializeAsString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Friends::UpdateHostname(Network::Address server, std::string hostname)
|
||||||
|
{
|
||||||
|
std::lock_guard<std::recursive_mutex> _(Friends::Mutex);
|
||||||
|
|
||||||
|
for(auto& entry : Friends::FriendsList)
|
||||||
|
{
|
||||||
|
if(entry.server == server)
|
||||||
|
{
|
||||||
|
entry.serverName = hostname;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Friends::SetServer()
|
||||||
|
{
|
||||||
|
Proto::IPC::Function function;
|
||||||
|
function.set_name("setPresence");
|
||||||
|
*function.add_params() = "iw4x_server";
|
||||||
|
*function.add_params() = Network::Address(*Game::connectedHost).getString();//reinterpret_cast<char*>(0x7ED3F8);
|
||||||
|
|
||||||
|
IPCHandler::SendWorker("friends", function.SerializeAsString());
|
||||||
|
|
||||||
|
Friends::UpdateState();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Friends::ClearServer()
|
||||||
|
{
|
||||||
|
Proto::IPC::Function function;
|
||||||
|
function.set_name("setPresence");
|
||||||
|
*function.add_params() = "iw4x_server";
|
||||||
|
|
||||||
|
IPCHandler::SendWorker("friends", function.SerializeAsString());
|
||||||
|
|
||||||
|
Friends::UpdateState();
|
||||||
|
}
|
||||||
|
|
||||||
void Friends::UpdateRank()
|
void Friends::UpdateRank()
|
||||||
{
|
{
|
||||||
static Utils::Value<int> levelVal;
|
static Utils::Value<int> levelVal;
|
||||||
@ -64,7 +153,6 @@ namespace Components
|
|||||||
|
|
||||||
unsigned int Friends::GetFriendCount()
|
unsigned int Friends::GetFriendCount()
|
||||||
{
|
{
|
||||||
std::lock_guard<std::recursive_mutex> _(Friends::Mutex);
|
|
||||||
return Friends::FriendsList.size();
|
return Friends::FriendsList.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -107,7 +195,27 @@ namespace Components
|
|||||||
return Utils::String::VA("%s", user.name.data());
|
return Utils::String::VA("%s", user.name.data());
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
return "Trickshot Isnipe server";
|
{
|
||||||
|
if(user.online && user.server.getType() != Game::NA_BAD)
|
||||||
|
{
|
||||||
|
if(user.serverName.empty())
|
||||||
|
{
|
||||||
|
return Utils::String::VA("Playing on %s", user.server.getCString());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return Utils::String::VA("Playing on %s", user.serverName.data());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(user.online)
|
||||||
|
{
|
||||||
|
return "Online";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return "Offline";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@ -143,8 +251,8 @@ namespace Components
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Friends::PresenceResponse(std::vector<std::string> params)
|
void Friends::ParsePresence(std::vector<std::string> params, bool sort)
|
||||||
{
|
{
|
||||||
if (params.size() >= 3)
|
if (params.size() >= 3)
|
||||||
{
|
{
|
||||||
@ -162,15 +270,26 @@ namespace Components
|
|||||||
|
|
||||||
if (entry == Friends::FriendsList.end()) return;
|
if (entry == Friends::FriendsList.end()) return;
|
||||||
|
|
||||||
if (key == "iw4x_status")
|
if (key == "iw4x_name")
|
||||||
{
|
{
|
||||||
entry->statusName = value;
|
entry->playerName = value;
|
||||||
}
|
}
|
||||||
else if (key == "iw4x_server")
|
else if (key == "iw4x_server")
|
||||||
{
|
{
|
||||||
entry->server = value;
|
Network::Address oldAddress = entry->server;
|
||||||
|
|
||||||
if (entry->server.getType() != Game::NA_BAD)
|
if (value.empty())
|
||||||
|
{
|
||||||
|
entry->server.setType(Game::NA_BAD);
|
||||||
|
entry->serverName.clear();
|
||||||
|
}
|
||||||
|
else if (entry->server != value)
|
||||||
|
{
|
||||||
|
entry->server = value;
|
||||||
|
entry->serverName.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entry->server.getType() != Game::NA_BAD && entry->server != oldAddress)
|
||||||
{
|
{
|
||||||
Node::AddNode(entry->server);
|
Node::AddNode(entry->server);
|
||||||
Network::SendCommand(entry->server, "getinfo", Utils::Cryptography::Rand::GenerateChallenge());
|
Network::SendCommand(entry->server, "getinfo", Utils::Cryptography::Rand::GenerateChallenge());
|
||||||
@ -186,8 +305,15 @@ namespace Components
|
|||||||
entry->prestige = (data >> 24) & 0xFF;
|
entry->prestige = (data >> 24) & 0xFF;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sort) Friends::SortList();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Friends::PresenceResponse(std::vector<std::string> params)
|
||||||
|
{
|
||||||
|
Friends::ParsePresence(params, true);
|
||||||
|
}
|
||||||
|
|
||||||
void Friends::InfoResponse(std::vector<std::string> params)
|
void Friends::InfoResponse(std::vector<std::string> params)
|
||||||
{
|
{
|
||||||
@ -221,9 +347,11 @@ namespace Components
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Friends::PresenceResponse({ Utils::String::VA("%llx", id.Bits), key, value });
|
Friends::ParsePresence({ Utils::String::VA("%llx", id.Bits), key, value }, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Friends::SortList();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -244,6 +372,7 @@ namespace Components
|
|||||||
entry.online = false;
|
entry.online = false;
|
||||||
entry.prestige = 0;
|
entry.prestige = 0;
|
||||||
entry.experience = 0;
|
entry.experience = 0;
|
||||||
|
entry.server.setType(Game::NA_BAD);
|
||||||
|
|
||||||
auto oldEntry = std::find_if(oldFriends.begin(), oldFriends.end(), [id](Friends::Friend entry)
|
auto oldEntry = std::find_if(oldFriends.begin(), oldFriends.end(), [id](Friends::Friend entry)
|
||||||
{
|
{
|
||||||
@ -263,10 +392,27 @@ namespace Components
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
__declspec(naked) void Friends::DisconnectStub()
|
||||||
|
{
|
||||||
|
__asm
|
||||||
|
{
|
||||||
|
pushad
|
||||||
|
call Friends::ClearServer
|
||||||
|
popad
|
||||||
|
|
||||||
|
push 467CC0h
|
||||||
|
retn
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Friends::Friends()
|
Friends::Friends()
|
||||||
{
|
{
|
||||||
Friends::UpdateFriends();
|
Friends::UpdateFriends();
|
||||||
|
|
||||||
|
// Update state when connecting/disconnecting
|
||||||
|
Utils::Hook(0x403582, Friends::DisconnectStub, HOOK_CALL).install()->quick();
|
||||||
|
Utils::Hook(0x4CD023, Friends::SetServer, HOOK_JUMP).install()->quick();
|
||||||
|
|
||||||
auto fInterface = IPCHandler::NewInterface("steamCallbacks");
|
auto fInterface = IPCHandler::NewInterface("steamCallbacks");
|
||||||
|
|
||||||
// Callback to update user information
|
// Callback to update user information
|
||||||
@ -298,6 +444,23 @@ namespace Components
|
|||||||
Friends::UpdateFriends();
|
Friends::UpdateFriends();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
UIScript::Add("JoinFriend", [](UIScript::Token)
|
||||||
|
{
|
||||||
|
std::lock_guard<std::recursive_mutex> _(Friends::Mutex);
|
||||||
|
if (Friends::CurrentFriend >= Friends::FriendsList.size()) return;
|
||||||
|
|
||||||
|
auto& user = Friends::FriendsList[Friends::CurrentFriend];
|
||||||
|
|
||||||
|
if(user.online && user.server.getType() != Game::NA_BAD)
|
||||||
|
{
|
||||||
|
Party::Connect(user.server);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Command::Execute("snd_playLocal exit_prestige", false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
QuickPatch::OnFrame([]()
|
QuickPatch::OnFrame([]()
|
||||||
{
|
{
|
||||||
if(*reinterpret_cast<bool*>(0x1AD5690)) // LiveStorage_DoWeHaveStats
|
if(*reinterpret_cast<bool*>(0x1AD5690)) // LiveStorage_DoWeHaveStats
|
||||||
|
@ -14,6 +14,7 @@ namespace Components
|
|||||||
|
|
||||||
static void UpdateFriends();
|
static void UpdateFriends();
|
||||||
static void UpdateRank();
|
static void UpdateRank();
|
||||||
|
static void UpdateHostname(Network::Address server, std::string hostname);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
#pragma pack(push, 4)
|
#pragma pack(push, 4)
|
||||||
@ -35,8 +36,9 @@ namespace Components
|
|||||||
public:
|
public:
|
||||||
SteamID userId;
|
SteamID userId;
|
||||||
std::string name;
|
std::string name;
|
||||||
|
std::string playerName;
|
||||||
Network::Address server;
|
Network::Address server;
|
||||||
std::string statusName;
|
std::string serverName;
|
||||||
bool online;
|
bool online;
|
||||||
int experience;
|
int experience;
|
||||||
int prestige;
|
int prestige;
|
||||||
@ -46,13 +48,22 @@ namespace Components
|
|||||||
static std::recursive_mutex Mutex;
|
static std::recursive_mutex Mutex;
|
||||||
static std::vector<Friend> FriendsList;
|
static std::vector<Friend> FriendsList;
|
||||||
|
|
||||||
|
static void DisconnectStub();
|
||||||
|
static void ClearServer();
|
||||||
|
static void SetServer();
|
||||||
|
|
||||||
static void UpdateUserInfo(SteamID user);
|
static void UpdateUserInfo(SteamID user);
|
||||||
static void UpdateState();
|
static void UpdateState();
|
||||||
|
|
||||||
|
static void SortList();
|
||||||
|
static void SortIndividualList(std::vector<Friend>* list);
|
||||||
|
|
||||||
static unsigned int GetFriendCount();
|
static unsigned int GetFriendCount();
|
||||||
static const char* GetFriendText(unsigned int index, int column);
|
static const char* GetFriendText(unsigned int index, int column);
|
||||||
static void SelectFriend(unsigned int index);
|
static void SelectFriend(unsigned int index);
|
||||||
|
|
||||||
|
static void ParsePresence(std::vector<std::string> params, bool sort);
|
||||||
|
|
||||||
static void FriendsResponse(std::vector<std::string> params);
|
static void FriendsResponse(std::vector<std::string> params);
|
||||||
static void NameResponse(std::vector<std::string> params);
|
static void NameResponse(std::vector<std::string> params);
|
||||||
static void PresenceResponse(std::vector<std::string> params);
|
static void PresenceResponse(std::vector<std::string> params);
|
||||||
|
@ -451,6 +451,7 @@ namespace Components
|
|||||||
}
|
}
|
||||||
|
|
||||||
ServerList::Insert(address, info);
|
ServerList::Insert(address, info);
|
||||||
|
Friends::UpdateHostname(address, info.get("hostname"));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,9 +76,9 @@ namespace Handlers
|
|||||||
|
|
||||||
void Friends::setPresence(Worker::Endpoint /*endpoint*/, std::vector<std::string> params)
|
void Friends::setPresence(Worker::Endpoint /*endpoint*/, std::vector<std::string> params)
|
||||||
{
|
{
|
||||||
if (params.size() >= 2 && Steam::Proxy::SteamFriends)
|
if (params.size() >= 1 && Steam::Proxy::SteamFriends)
|
||||||
{
|
{
|
||||||
Steam::Proxy::SteamFriends->SetRichPresence(params[0].data(), params[1].data());
|
Steam::Proxy::SteamFriends->SetRichPresence(params[0].data(), (params.size() >= 2 ? params[1].data() : nullptr));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -141,14 +141,6 @@ namespace Handlers
|
|||||||
{
|
{
|
||||||
*response.add_params() = Utils::String::VA("%d", Steam::Proxy::SteamFriends->GetFriendPersonaState(id));
|
*response.add_params() = Utils::String::VA("%d", Steam::Proxy::SteamFriends->GetFriendPersonaState(id));
|
||||||
}
|
}
|
||||||
/*else if (key == "iw4x_rank") // This is just a test
|
|
||||||
{
|
|
||||||
int experience = Utils::Cryptography::Rand::GenerateInt() % (2516000 + 1);
|
|
||||||
int prestige = Utils::Cryptography::Rand::GenerateInt() % (10 + 1);
|
|
||||||
|
|
||||||
int data = (experience & 0xFFFFFF) | ((prestige & 0xFF) << 24);
|
|
||||||
*response.add_params() = std::string(reinterpret_cast<char*>(&data), 4);
|
|
||||||
}*/
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
*response.add_params() = Steam::Proxy::SteamFriends->GetFriendRichPresence(id, key.data());
|
*response.add_params() = Steam::Proxy::SteamFriends->GetFriendRichPresence(id, key.data());
|
||||||
@ -180,7 +172,7 @@ namespace Handlers
|
|||||||
{
|
{
|
||||||
if(Steam::Proxy::SteamFriends)
|
if(Steam::Proxy::SteamFriends)
|
||||||
{
|
{
|
||||||
Steam::Proxy::SteamFriends->ClearRichPresence();
|
Steam::Proxy::SteamFriends->SetRichPresence("iw4x_server", nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(Steam::Proxy::SteamLegacyFriends)
|
if(Steam::Proxy::SteamLegacyFriends)
|
||||||
|
Loading…
Reference in New Issue
Block a user