2017-01-25 16:39:00 -05:00
|
|
|
#include "STDInclude.hpp"
|
|
|
|
|
|
|
|
namespace Components
|
|
|
|
{
|
|
|
|
unsigned int Friends::CurrentFriend;
|
|
|
|
std::recursive_mutex Friends::Mutex;
|
|
|
|
std::vector<Friends::Friend> Friends::FriendsList;
|
|
|
|
|
2017-01-29 11:16:09 -05:00
|
|
|
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);
|
|
|
|
|
2017-01-29 12:06:48 -05:00
|
|
|
std::vector<Friends::Friend> connectedList;
|
2017-01-29 11:16:09 -05:00
|
|
|
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)
|
|
|
|
{
|
2017-01-29 12:06:48 -05:00
|
|
|
if (entry.playing)
|
2017-01-29 11:16:09 -05:00
|
|
|
{
|
2017-01-29 12:06:48 -05:00
|
|
|
if (entry.server.getType() == Game::NA_BAD)
|
|
|
|
{
|
|
|
|
playingList.push_back(entry);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
connectedList.push_back(entry);
|
|
|
|
}
|
2017-01-29 11:16:09 -05:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-01-29 12:06:48 -05:00
|
|
|
onlineList.push_back(entry);
|
2017-01-29 11:16:09 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
offlineList.push_back(entry);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-01-29 12:06:48 -05:00
|
|
|
Friends::SortIndividualList(&connectedList);
|
2017-01-29 11:16:09 -05:00
|
|
|
Friends::SortIndividualList(&playingList);
|
|
|
|
Friends::SortIndividualList(&onlineList);
|
|
|
|
Friends::SortIndividualList(&offlineList);
|
|
|
|
|
|
|
|
Friends::FriendsList.clear();
|
|
|
|
|
2017-01-29 12:06:48 -05:00
|
|
|
Utils::Merge(&Friends::FriendsList, connectedList);
|
2017-01-29 11:16:09 -05:00
|
|
|
Utils::Merge(&Friends::FriendsList, playingList);
|
|
|
|
Utils::Merge(&Friends::FriendsList, onlineList);
|
|
|
|
Utils::Merge(&Friends::FriendsList, offlineList);
|
|
|
|
}
|
|
|
|
|
2017-01-25 16:39:00 -05:00
|
|
|
void Friends::UpdateUserInfo(SteamID user)
|
|
|
|
{
|
2017-01-28 18:31:11 -05:00
|
|
|
Proto::IPC::Function function;
|
|
|
|
|
2017-01-29 05:40:20 -05:00
|
|
|
function.set_name("getInfo");
|
2017-01-28 18:31:11 -05:00
|
|
|
*function.add_params() = Utils::String::VA("%llx", user.Bits);
|
|
|
|
|
2017-01-29 05:40:20 -05:00
|
|
|
*function.add_params() = "name";
|
|
|
|
*function.add_params() = "state";
|
|
|
|
*function.add_params() = "iw4x_name";
|
|
|
|
*function.add_params() = "iw4x_status";
|
|
|
|
*function.add_params() = "iw4x_rank";
|
|
|
|
*function.add_params() = "iw4x_server";
|
2017-01-29 12:06:48 -05:00
|
|
|
*function.add_params() = "iw4x_playing";
|
2017-01-28 18:31:11 -05:00
|
|
|
|
|
|
|
IPCHandler::SendWorker("friends", function.SerializeAsString());
|
2017-01-25 16:39:00 -05:00
|
|
|
}
|
|
|
|
|
2017-01-29 09:10:54 -05:00
|
|
|
void Friends::UpdateState()
|
|
|
|
{
|
|
|
|
Proto::IPC::Function function;
|
|
|
|
function.set_name("notifyChange");
|
|
|
|
IPCHandler::SendWorker("friends", function.SerializeAsString());
|
|
|
|
}
|
|
|
|
|
2017-01-29 11:16:09 -05:00
|
|
|
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();
|
|
|
|
}
|
|
|
|
|
2017-01-29 09:10:54 -05:00
|
|
|
void Friends::UpdateRank()
|
|
|
|
{
|
|
|
|
static Utils::Value<int> levelVal;
|
|
|
|
|
|
|
|
int experience = Game::Live_GetXp(0);
|
|
|
|
int prestige = Game::Live_GetPrestige(0);
|
|
|
|
int level = (experience & 0xFFFFFF) | ((prestige & 0xFF) << 24);
|
|
|
|
|
|
|
|
if(!levelVal.isValid() || levelVal.get() != level)
|
|
|
|
{
|
|
|
|
levelVal.set(level);
|
|
|
|
|
|
|
|
Proto::IPC::Function function;
|
|
|
|
function.set_name("setPresence");
|
|
|
|
*function.add_params() = "iw4x_rank";
|
|
|
|
*function.add_params() = std::string(reinterpret_cast<char*>(&level), 4);
|
|
|
|
|
|
|
|
IPCHandler::SendWorker("friends", function.SerializeAsString());
|
2017-01-29 09:26:46 -05:00
|
|
|
|
|
|
|
Friends::UpdateState();
|
2017-01-29 09:10:54 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-01-25 16:39:00 -05:00
|
|
|
void Friends::UpdateFriends()
|
|
|
|
{
|
2017-01-28 13:03:44 -05:00
|
|
|
Proto::IPC::Function function;
|
|
|
|
function.set_name("getFriends");
|
|
|
|
*function.add_params() = Utils::String::VA("%d", 4);
|
2017-01-25 16:39:00 -05:00
|
|
|
|
2017-01-28 13:03:44 -05:00
|
|
|
IPCHandler::SendWorker("friends", function.SerializeAsString());
|
2017-01-25 16:39:00 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
unsigned int Friends::GetFriendCount()
|
|
|
|
{
|
|
|
|
return Friends::FriendsList.size();
|
|
|
|
}
|
|
|
|
|
|
|
|
const char* Friends::GetFriendText(unsigned int index, int column)
|
|
|
|
{
|
|
|
|
std::lock_guard<std::recursive_mutex> _(Friends::Mutex);
|
|
|
|
if (index >= Friends::FriendsList.size()) return "";
|
|
|
|
|
|
|
|
auto user = Friends::FriendsList[index];
|
|
|
|
|
|
|
|
switch(column)
|
|
|
|
{
|
|
|
|
case 0:
|
|
|
|
{
|
|
|
|
static char buffer[0x100];
|
2017-01-26 06:42:42 -05:00
|
|
|
ZeroMemory(buffer, sizeof(buffer));
|
2017-01-25 16:39:00 -05:00
|
|
|
|
2017-01-26 06:42:42 -05:00
|
|
|
Game::Material* rankIcon = nullptr;
|
|
|
|
int rank = Game::CL_GetRankForXP(user.experience);
|
|
|
|
Game::CL_GetRankIcon(rank, user.prestige, &rankIcon);
|
2017-01-29 09:10:54 -05:00
|
|
|
if (!rankIcon) rankIcon = Game::DB_FindXAssetDefaultHeaderInternal(Game::XAssetType::ASSET_TYPE_MATERIAL).material;
|
2017-01-25 16:39:00 -05:00
|
|
|
|
2017-01-26 06:42:42 -05:00
|
|
|
buffer[0] = '^';
|
|
|
|
buffer[1] = 2;
|
2017-01-25 16:39:00 -05:00
|
|
|
|
|
|
|
// Icon size
|
2017-01-26 06:42:42 -05:00
|
|
|
char size = 0x30;
|
|
|
|
buffer[2] = size; // Width
|
|
|
|
buffer[3] = size; // Height
|
2017-01-25 16:39:00 -05:00
|
|
|
|
|
|
|
// Icon name length
|
2017-01-26 06:42:42 -05:00
|
|
|
buffer[4] = static_cast<char>(strlen(rankIcon->name));
|
2017-01-25 16:39:00 -05:00
|
|
|
|
2017-01-26 06:42:42 -05:00
|
|
|
strcat_s(buffer, rankIcon->name);
|
2017-01-29 09:10:54 -05:00
|
|
|
strcat_s(buffer, Utils::String::VA(" %i", (rank + 1)));
|
2017-01-25 16:39:00 -05:00
|
|
|
|
|
|
|
return buffer;
|
|
|
|
}
|
|
|
|
case 1:
|
|
|
|
return Utils::String::VA("%s", user.name.data());
|
|
|
|
|
|
|
|
case 2:
|
2017-01-29 11:16:09 -05:00
|
|
|
{
|
2017-01-29 12:06:48 -05:00
|
|
|
if(user.online)
|
2017-01-29 11:16:09 -05:00
|
|
|
{
|
2017-01-29 12:06:48 -05:00
|
|
|
if (user.playing)
|
2017-01-29 11:16:09 -05:00
|
|
|
{
|
2017-01-29 12:06:48 -05:00
|
|
|
if (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
|
|
|
|
{
|
|
|
|
return "Playing IW4x";
|
|
|
|
}
|
2017-01-29 11:16:09 -05:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-01-29 12:06:48 -05:00
|
|
|
return "Online";
|
2017-01-29 11:16:09 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return "Offline";
|
|
|
|
}
|
|
|
|
}
|
2017-01-25 16:39:00 -05:00
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
|
|
|
|
void Friends::SelectFriend(unsigned int index)
|
|
|
|
{
|
|
|
|
std::lock_guard<std::recursive_mutex> _(Friends::Mutex);
|
|
|
|
if (index >= Friends::FriendsList.size()) return;
|
|
|
|
|
|
|
|
Friends::CurrentFriend = index;
|
|
|
|
}
|
|
|
|
|
2017-01-28 13:03:44 -05:00
|
|
|
void Friends::NameResponse(std::vector<std::string> params)
|
|
|
|
{
|
|
|
|
if (params.size() >= 2)
|
|
|
|
{
|
|
|
|
std::lock_guard<std::recursive_mutex> _(Friends::Mutex);
|
|
|
|
|
|
|
|
SteamID id;
|
|
|
|
id.Bits = strtoull(params[0].data(), nullptr, 16);
|
|
|
|
|
|
|
|
for(auto& entry : Friends::FriendsList)
|
|
|
|
{
|
|
|
|
if(entry.userId.Bits == id.Bits)
|
|
|
|
{
|
|
|
|
entry.name = params[1];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-01-29 11:16:09 -05:00
|
|
|
|
|
|
|
void Friends::ParsePresence(std::vector<std::string> params, bool sort)
|
2017-01-28 18:31:11 -05:00
|
|
|
{
|
|
|
|
if (params.size() >= 3)
|
|
|
|
{
|
|
|
|
std::lock_guard<std::recursive_mutex> _(Friends::Mutex);
|
|
|
|
|
|
|
|
SteamID id;
|
|
|
|
id.Bits = strtoull(params[0].data(), nullptr, 16);
|
|
|
|
std::string key = params[1];
|
|
|
|
std::string value = params[2];
|
|
|
|
|
|
|
|
auto entry = std::find_if(Friends::FriendsList.begin(), Friends::FriendsList.end(), [id](Friends::Friend entry)
|
|
|
|
{
|
|
|
|
return (entry.userId.Bits == id.Bits);
|
|
|
|
});
|
|
|
|
|
|
|
|
if (entry == Friends::FriendsList.end()) return;
|
|
|
|
|
2017-01-29 11:16:09 -05:00
|
|
|
if (key == "iw4x_name")
|
2017-01-28 18:31:11 -05:00
|
|
|
{
|
2017-01-29 11:16:09 -05:00
|
|
|
entry->playerName = value;
|
2017-01-28 18:31:11 -05:00
|
|
|
}
|
2017-01-29 12:06:48 -05:00
|
|
|
else if (key == "iw4x_playing")
|
|
|
|
{
|
|
|
|
entry->playing = atoi(value.data()) == 1;
|
|
|
|
}
|
2017-01-29 05:40:20 -05:00
|
|
|
else if (key == "iw4x_server")
|
|
|
|
{
|
2017-01-29 11:16:09 -05:00
|
|
|
Network::Address oldAddress = entry->server;
|
|
|
|
|
|
|
|
if (value.empty())
|
|
|
|
{
|
|
|
|
entry->server.setType(Game::NA_BAD);
|
|
|
|
entry->serverName.clear();
|
|
|
|
}
|
|
|
|
else if (entry->server != value)
|
|
|
|
{
|
|
|
|
entry->server = value;
|
|
|
|
entry->serverName.clear();
|
|
|
|
}
|
2017-01-29 05:40:20 -05:00
|
|
|
|
2017-01-29 11:16:09 -05:00
|
|
|
if (entry->server.getType() != Game::NA_BAD && entry->server != oldAddress)
|
2017-01-29 05:40:20 -05:00
|
|
|
{
|
|
|
|
Node::AddNode(entry->server);
|
|
|
|
Network::SendCommand(entry->server, "getinfo", Utils::Cryptography::Rand::GenerateChallenge());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (key == "iw4x_rank")
|
2017-01-28 18:31:11 -05:00
|
|
|
{
|
2017-01-29 05:40:20 -05:00
|
|
|
if (value.size() == 4)
|
2017-01-28 18:31:11 -05:00
|
|
|
{
|
|
|
|
int data = *reinterpret_cast<int*>(const_cast<char*>(value.data()));
|
|
|
|
|
|
|
|
entry->experience = data & 0xFFFFFF;
|
|
|
|
entry->prestige = (data >> 24) & 0xFF;
|
|
|
|
}
|
|
|
|
}
|
2017-01-29 11:16:09 -05:00
|
|
|
|
|
|
|
if (sort) Friends::SortList();
|
2017-01-28 18:31:11 -05:00
|
|
|
}
|
|
|
|
}
|
2017-01-29 11:16:09 -05:00
|
|
|
|
|
|
|
void Friends::PresenceResponse(std::vector<std::string> params)
|
|
|
|
{
|
|
|
|
Friends::ParsePresence(params, true);
|
|
|
|
}
|
2017-01-28 13:03:44 -05:00
|
|
|
|
2017-01-29 05:40:20 -05:00
|
|
|
void Friends::InfoResponse(std::vector<std::string> params)
|
|
|
|
{
|
|
|
|
if (params.size() >= 1)
|
|
|
|
{
|
|
|
|
std::lock_guard<std::recursive_mutex> _(Friends::Mutex);
|
|
|
|
|
|
|
|
SteamID id;
|
|
|
|
id.Bits = strtoull(params[0].data(), nullptr, 16);
|
|
|
|
|
|
|
|
auto entry = std::find_if(Friends::FriendsList.begin(), Friends::FriendsList.end(), [id](Friends::Friend entry)
|
|
|
|
{
|
|
|
|
return (entry.userId.Bits == id.Bits);
|
|
|
|
});
|
|
|
|
|
|
|
|
if (entry == Friends::FriendsList.end()) return;
|
|
|
|
|
|
|
|
for(unsigned int i = 1; i < params.size(); i += 2)
|
|
|
|
{
|
|
|
|
if ((i + 1) >= params.size()) break;
|
|
|
|
std::string key = params[i];
|
|
|
|
std::string value = params[i + 1];
|
|
|
|
|
|
|
|
if(key == "name")
|
|
|
|
{
|
|
|
|
entry->name = value;
|
|
|
|
}
|
|
|
|
else if(key == "state")
|
|
|
|
{
|
|
|
|
entry->online = atoi(value.data()) != 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-01-29 11:16:09 -05:00
|
|
|
Friends::ParsePresence({ Utils::String::VA("%llx", id.Bits), key, value }, false);
|
2017-01-29 05:40:20 -05:00
|
|
|
}
|
|
|
|
}
|
2017-01-29 11:16:09 -05:00
|
|
|
|
|
|
|
Friends::SortList();
|
2017-01-29 05:40:20 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-01-28 13:03:44 -05:00
|
|
|
void Friends::FriendsResponse(std::vector<std::string> params)
|
|
|
|
{
|
|
|
|
std::lock_guard<std::recursive_mutex> _(Friends::Mutex);
|
|
|
|
|
|
|
|
auto oldFriends = Friends::FriendsList;
|
|
|
|
Friends::FriendsList.clear();
|
|
|
|
|
|
|
|
for (auto param : params)
|
|
|
|
{
|
|
|
|
SteamID id;
|
|
|
|
id.Bits = strtoull(param.data(), nullptr, 16);
|
|
|
|
|
|
|
|
Friends::Friend entry;
|
|
|
|
entry.userId = id;
|
|
|
|
entry.online = false;
|
2017-01-29 12:06:48 -05:00
|
|
|
entry.playing = false;
|
2017-01-28 13:03:44 -05:00
|
|
|
entry.prestige = 0;
|
|
|
|
entry.experience = 0;
|
2017-01-29 11:16:09 -05:00
|
|
|
entry.server.setType(Game::NA_BAD);
|
2017-01-28 13:03:44 -05:00
|
|
|
|
|
|
|
auto oldEntry = std::find_if(oldFriends.begin(), oldFriends.end(), [id](Friends::Friend entry)
|
|
|
|
{
|
|
|
|
return (entry.userId.Bits == id.Bits);
|
|
|
|
});
|
|
|
|
|
|
|
|
if (oldEntry != oldFriends.end()) entry = *oldEntry;
|
|
|
|
|
|
|
|
Friends::FriendsList.push_back(entry);
|
|
|
|
|
2017-01-29 05:40:20 -05:00
|
|
|
Friends::UpdateUserInfo(id);
|
2017-01-28 13:03:44 -05:00
|
|
|
|
2017-01-29 05:40:20 -05:00
|
|
|
Proto::IPC::Function function;
|
2017-01-28 13:03:44 -05:00
|
|
|
function.set_name("requestPresence");
|
|
|
|
*function.add_params() = Utils::String::VA("%llx", id.Bits);
|
|
|
|
IPCHandler::SendWorker("friends", function.SerializeAsString());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-01-29 11:16:09 -05:00
|
|
|
__declspec(naked) void Friends::DisconnectStub()
|
|
|
|
{
|
|
|
|
__asm
|
|
|
|
{
|
|
|
|
pushad
|
|
|
|
call Friends::ClearServer
|
|
|
|
popad
|
|
|
|
|
|
|
|
push 467CC0h
|
|
|
|
retn
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-01-25 16:39:00 -05:00
|
|
|
Friends::Friends()
|
|
|
|
{
|
2017-01-28 14:36:48 -05:00
|
|
|
Friends::UpdateFriends();
|
|
|
|
|
2017-01-29 11:16:09 -05:00
|
|
|
// Update state when connecting/disconnecting
|
|
|
|
Utils::Hook(0x403582, Friends::DisconnectStub, HOOK_CALL).install()->quick();
|
|
|
|
Utils::Hook(0x4CD023, Friends::SetServer, HOOK_JUMP).install()->quick();
|
|
|
|
|
2017-01-28 16:01:49 -05:00
|
|
|
auto fInterface = IPCHandler::NewInterface("steamCallbacks");
|
|
|
|
|
2017-01-25 16:39:00 -05:00
|
|
|
// Callback to update user information
|
2017-01-28 18:31:11 -05:00
|
|
|
fInterface->map("336", [](std::vector<std::string> params)
|
2017-01-25 16:39:00 -05:00
|
|
|
{
|
2017-01-28 16:01:49 -05:00
|
|
|
if (params.size() >= 1 && params[0].size() == sizeof(Friends::FriendRichPresenceUpdate))
|
|
|
|
{
|
|
|
|
const Friends::FriendRichPresenceUpdate* update = reinterpret_cast<const Friends::FriendRichPresenceUpdate*>(params[0].data());
|
|
|
|
Friends::UpdateUserInfo(update->m_steamIDFriend);
|
|
|
|
}
|
2017-01-25 16:39:00 -05:00
|
|
|
});
|
|
|
|
|
|
|
|
// Persona state has changed
|
2017-01-28 16:01:49 -05:00
|
|
|
fInterface->map("304", [](std::vector<std::string> params)
|
2017-01-25 16:39:00 -05:00
|
|
|
{
|
2017-01-28 16:01:49 -05:00
|
|
|
if(params.size() >= 1 && params[0].size() == sizeof(Friends::PersonaStateChange))
|
|
|
|
{
|
|
|
|
const Friends::PersonaStateChange* state = reinterpret_cast<const Friends::PersonaStateChange*>(params[0].data());
|
|
|
|
|
|
|
|
Proto::IPC::Function function;
|
|
|
|
function.set_name("requestPresence");
|
|
|
|
*function.add_params() = Utils::String::VA("%llx", state->m_ulSteamID.Bits);
|
|
|
|
IPCHandler::SendWorker("friends", function.SerializeAsString());
|
|
|
|
}
|
2017-01-25 16:39:00 -05:00
|
|
|
});
|
|
|
|
|
|
|
|
UIScript::Add("LoadFriends", [](UIScript::Token)
|
|
|
|
{
|
|
|
|
Friends::UpdateFriends();
|
|
|
|
});
|
|
|
|
|
2017-01-29 11:16:09 -05:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2017-01-29 09:10:54 -05:00
|
|
|
QuickPatch::OnFrame([]()
|
|
|
|
{
|
|
|
|
if(*reinterpret_cast<bool*>(0x1AD5690)) // LiveStorage_DoWeHaveStats
|
|
|
|
{
|
|
|
|
Friends::UpdateRank();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2017-01-26 16:14:44 -05:00
|
|
|
UIFeeder::Add(6.0f, Friends::GetFriendCount, Friends::GetFriendText, Friends::SelectFriend);
|
2017-01-28 09:51:50 -05:00
|
|
|
|
2017-01-28 16:01:49 -05:00
|
|
|
fInterface = IPCHandler::NewInterface("friends");
|
2017-01-28 13:03:44 -05:00
|
|
|
fInterface->map("friendsResponse", Friends::FriendsResponse);
|
|
|
|
fInterface->map("nameResponse", Friends::NameResponse);
|
2017-01-28 18:31:11 -05:00
|
|
|
fInterface->map("presenceResponse", Friends::PresenceResponse);
|
2017-01-29 05:40:20 -05:00
|
|
|
fInterface->map("infoResponse", Friends::InfoResponse);
|
2017-01-29 12:06:48 -05:00
|
|
|
|
|
|
|
Proto::IPC::Function function;
|
|
|
|
function.set_name("setPresence");
|
|
|
|
*function.add_params() = "iw4x_playing";
|
|
|
|
*function.add_params() = "1";
|
|
|
|
|
|
|
|
IPCHandler::SendWorker("friends", function.SerializeAsString());
|
2017-01-25 16:39:00 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
Friends::~Friends()
|
|
|
|
{
|
|
|
|
{
|
|
|
|
std::lock_guard<std::recursive_mutex> _(Friends::Mutex);
|
|
|
|
Friends::FriendsList.clear();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|