Merge branch 'no-worker' into 'develop'
No worker
This commit is contained in:
commit
f3688ac106
2
deps/boost/core
vendored
2
deps/boost/core
vendored
@ -1 +1 @@
|
|||||||
Subproject commit f7183714c1661b3a1e84120091d634e6ad6d18d6
|
Subproject commit fa88cc32cfd39645a087365bffb81f1b1514899b
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace Components
|
namespace Components
|
||||||
{
|
{
|
||||||
|
int Friends::InitialState;
|
||||||
unsigned int Friends::CurrentFriend;
|
unsigned int Friends::CurrentFriend;
|
||||||
std::recursive_mutex Friends::Mutex;
|
std::recursive_mutex Friends::Mutex;
|
||||||
std::vector<Friends::Friend> Friends::FriendsList;
|
std::vector<Friends::Friend> Friends::FriendsList;
|
||||||
@ -32,28 +33,10 @@ namespace Components
|
|||||||
// Split up the list
|
// Split up the list
|
||||||
for(auto entry : Friends::FriendsList)
|
for(auto entry : Friends::FriendsList)
|
||||||
{
|
{
|
||||||
if(entry.online)
|
if(!entry.online) offlineList.push_back(entry);
|
||||||
{
|
else if(!entry.playing) onlineList.push_back(entry);
|
||||||
if (entry.playing)
|
else if (entry.server.getType() == Game::NA_BAD) playingList.push_back(entry);
|
||||||
{
|
else connectedList.push_back(entry);
|
||||||
if (entry.server.getType() == Game::NA_BAD)
|
|
||||||
{
|
|
||||||
playingList.push_back(entry);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
connectedList.push_back(entry);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
onlineList.push_back(entry);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
offlineList.push_back(entry);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Friends::SortIndividualList(&connectedList);
|
Friends::SortIndividualList(&connectedList);
|
||||||
@ -71,28 +54,55 @@ namespace Components
|
|||||||
|
|
||||||
void Friends::UpdateUserInfo(SteamID user)
|
void Friends::UpdateUserInfo(SteamID user)
|
||||||
{
|
{
|
||||||
Proto::IPC::Function function;
|
std::lock_guard<std::recursive_mutex> _(Friends::Mutex);
|
||||||
|
|
||||||
function.set_name("getInfo");
|
auto entry = std::find_if(Friends::FriendsList.begin(), Friends::FriendsList.end(), [user](Friends::Friend entry)
|
||||||
*function.add_params() = Utils::String::VA("%llx", user.Bits);
|
{
|
||||||
|
return (entry.userId.Bits == user.Bits);
|
||||||
|
});
|
||||||
|
|
||||||
*function.add_params() = "name";
|
if (entry == Friends::FriendsList.end() || !Steam::Proxy::SteamFriends) return;
|
||||||
*function.add_params() = "state";
|
|
||||||
*function.add_params() = "iw4x_name";
|
|
||||||
*function.add_params() = "iw4x_status";
|
|
||||||
*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());
|
entry->name = Steam::Proxy::SteamFriends->GetFriendPersonaName(user);
|
||||||
|
entry->playerName = Steam::Proxy::SteamFriends->GetFriendRichPresence(user, "iw4x_name");
|
||||||
|
entry->online = Steam::Proxy::SteamFriends->GetFriendPersonaState(user) != 0;
|
||||||
|
entry->playing = atoi(Steam::Proxy::SteamFriends->GetFriendRichPresence(user, "iw4x_playing")) == 1;
|
||||||
|
entry->guid.Bits = strtoull(Steam::Proxy::SteamFriends->GetFriendRichPresence(user, "iw4x_guid"), nullptr, 16);
|
||||||
|
entry->experience = atoi(Steam::Proxy::SteamFriends->GetFriendRichPresence(user, "iw4x_experience"));
|
||||||
|
entry->prestige = atoi(Steam::Proxy::SteamFriends->GetFriendRichPresence(user, "iw4x_prestige"));
|
||||||
|
|
||||||
|
std::string server = Steam::Proxy::SteamFriends->GetFriendRichPresence(user, "iw4x_server");
|
||||||
|
Network::Address oldAddress = entry->server;
|
||||||
|
|
||||||
|
if (server.empty())
|
||||||
|
{
|
||||||
|
entry->server.setType(Game::NA_BAD);
|
||||||
|
entry->serverName.clear();
|
||||||
|
}
|
||||||
|
else if (entry->server != server)
|
||||||
|
{
|
||||||
|
entry->server = server;
|
||||||
|
entry->serverName.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Block localhost
|
||||||
|
if (entry->server.getType() == Game::NA_LOOPBACK) entry->server.setType(Game::NA_BAD);
|
||||||
|
if (entry->server.getType() != Game::NA_BAD && entry->server != oldAddress)
|
||||||
|
{
|
||||||
|
Node::AddNode(entry->server);
|
||||||
|
Network::SendCommand(entry->server, "getinfo", Utils::Cryptography::Rand::GenerateChallenge());
|
||||||
|
}
|
||||||
|
|
||||||
|
Friends::SortList();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Friends::UpdateState()
|
void Friends::UpdateState()
|
||||||
{
|
{
|
||||||
Proto::IPC::Function function;
|
if(Steam::Proxy::SteamLegacyFriends)
|
||||||
function.set_name("notifyChange");
|
{
|
||||||
IPCHandler::SendWorker("friends", function.SerializeAsString());
|
int state = Steam::Proxy::SteamLegacyFriends->GetPersonaState();
|
||||||
|
Steam::Proxy::SteamLegacyFriends->SetPersonaState((state == 1 ? 2 : 1));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Friends::UpdateHostname(Network::Address server, std::string hostname)
|
void Friends::UpdateHostname(Network::Address server, std::string hostname)
|
||||||
@ -110,21 +120,18 @@ namespace Components
|
|||||||
|
|
||||||
void Friends::ClearPresence(std::string key)
|
void Friends::ClearPresence(std::string key)
|
||||||
{
|
{
|
||||||
Proto::IPC::Function function;
|
if (Steam::Proxy::SteamFriends)
|
||||||
function.set_name("setPresence");
|
{
|
||||||
*function.add_params() = key;
|
Steam::Proxy::SteamFriends->SetRichPresence(key.data(), nullptr);
|
||||||
|
}
|
||||||
IPCHandler::SendWorker("friends", function.SerializeAsString());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Friends::SetPresence(std::string key, std::string value)
|
void Friends::SetPresence(std::string key, std::string value)
|
||||||
{
|
{
|
||||||
Proto::IPC::Function function;
|
if (Steam::Proxy::SteamFriends)
|
||||||
function.set_name("setPresence");
|
{
|
||||||
*function.add_params() = key;
|
Steam::Proxy::SteamFriends->SetRichPresence(key.data(), value.data());
|
||||||
*function.add_params() = value;
|
}
|
||||||
|
|
||||||
IPCHandler::SendWorker("friends", function.SerializeAsString());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Friends::SetServer()
|
void Friends::SetServer()
|
||||||
@ -169,18 +176,47 @@ namespace Components
|
|||||||
{
|
{
|
||||||
levelVal.set(level);
|
levelVal.set(level);
|
||||||
|
|
||||||
Friends::SetPresence("iw4x_rank", std::string(reinterpret_cast<char*>(&level), 4));
|
Friends::SetPresence("iw4x_experience", Utils::String::VA("%d", experience));
|
||||||
|
Friends::SetPresence("iw4x_prestige", Utils::String::VA("%d", prestige));
|
||||||
Friends::UpdateState();
|
Friends::UpdateState();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Friends::UpdateFriends()
|
void Friends::UpdateFriends()
|
||||||
{
|
{
|
||||||
Proto::IPC::Function function;
|
std::lock_guard<std::recursive_mutex> _(Friends::Mutex);
|
||||||
function.set_name("getFriends");
|
if (!Steam::Proxy::SteamFriends) return;
|
||||||
*function.add_params() = Utils::String::VA("%d", 4);
|
|
||||||
|
|
||||||
IPCHandler::SendWorker("friends", function.SerializeAsString());
|
auto oldFriends = Friends::FriendsList;
|
||||||
|
Friends::FriendsList.clear();
|
||||||
|
|
||||||
|
int count = Steam::Proxy::SteamFriends->GetFriendCount(4);
|
||||||
|
|
||||||
|
for (int i = 0; i < count; ++i)
|
||||||
|
{
|
||||||
|
SteamID id = Steam::Proxy::SteamFriends->GetFriendByIndex(i, 4);
|
||||||
|
|
||||||
|
Friends::Friend entry;
|
||||||
|
entry.userId = id;
|
||||||
|
entry.online = false;
|
||||||
|
entry.playing = false;
|
||||||
|
entry.prestige = 0;
|
||||||
|
entry.experience = 0;
|
||||||
|
entry.server.setType(Game::NA_BAD);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
Friends::UpdateUserInfo(id);
|
||||||
|
|
||||||
|
Steam::Proxy::SteamFriends->RequestFriendRichPresence(id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int Friends::GetFriendCount()
|
unsigned int Friends::GetFriendCount()
|
||||||
@ -228,35 +264,11 @@ namespace Components
|
|||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
{
|
{
|
||||||
if(user.online)
|
if (!user.online) return "Offline";
|
||||||
{
|
if (!user.playing) return "Online";
|
||||||
if (user.playing)
|
if (user.server.getType() == Game::NA_BAD) return "Playing IW4x";
|
||||||
{
|
if (user.serverName.empty()) return Utils::String::VA("Playing on %s", user.server.getCString());
|
||||||
if (user.server.getType() != Game::NA_BAD)
|
return Utils::String::VA("Playing on %s", user.serverName.data());
|
||||||
{
|
|
||||||
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";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return "Online";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return "Offline";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -274,178 +286,6 @@ namespace Components
|
|||||||
Friends::CurrentFriend = index;
|
Friends::CurrentFriend = index;
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Friends::ParsePresence(std::vector<std::string> params, bool sort)
|
|
||||||
{
|
|
||||||
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;
|
|
||||||
|
|
||||||
if (key == "iw4x_name")
|
|
||||||
{
|
|
||||||
entry->playerName = value;
|
|
||||||
}
|
|
||||||
else if (key == "iw4x_playing")
|
|
||||||
{
|
|
||||||
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;
|
|
||||||
|
|
||||||
if (value.empty())
|
|
||||||
{
|
|
||||||
entry->server.setType(Game::NA_BAD);
|
|
||||||
entry->serverName.clear();
|
|
||||||
}
|
|
||||||
else if (entry->server != value)
|
|
||||||
{
|
|
||||||
entry->server = value;
|
|
||||||
entry->serverName.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Block localhost
|
|
||||||
if(entry->server.getType() == Game::NA_LOOPBACK) entry->server.setType(Game::NA_BAD);
|
|
||||||
|
|
||||||
if (entry->server.getType() != Game::NA_BAD && entry->server != oldAddress)
|
|
||||||
{
|
|
||||||
Node::AddNode(entry->server);
|
|
||||||
Network::SendCommand(entry->server, "getinfo", Utils::Cryptography::Rand::GenerateChallenge());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (key == "iw4x_rank")
|
|
||||||
{
|
|
||||||
if (value.size() == 4)
|
|
||||||
{
|
|
||||||
int data = *reinterpret_cast<int*>(const_cast<char*>(value.data()));
|
|
||||||
|
|
||||||
entry->experience = data & 0xFFFFFF;
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
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
|
|
||||||
{
|
|
||||||
Friends::ParsePresence({ Utils::String::VA("%llx", id.Bits), key, value }, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Friends::SortList();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
entry.playing = false;
|
|
||||||
entry.prestige = 0;
|
|
||||||
entry.experience = 0;
|
|
||||||
entry.server.setType(Game::NA_BAD);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
Friends::UpdateUserInfo(id);
|
|
||||||
|
|
||||||
Proto::IPC::Function function;
|
|
||||||
function.set_name("requestPresence");
|
|
||||||
*function.add_params() = Utils::String::VA("%llx", id.Bits);
|
|
||||||
IPCHandler::SendWorker("friends", function.SerializeAsString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
__declspec(naked) void Friends::DisconnectStub()
|
__declspec(naked) void Friends::DisconnectStub()
|
||||||
{
|
{
|
||||||
__asm
|
__asm
|
||||||
@ -461,7 +301,19 @@ namespace Components
|
|||||||
|
|
||||||
Friends::Friends()
|
Friends::Friends()
|
||||||
{
|
{
|
||||||
Friends::UpdateFriends();
|
// Callback to update user information
|
||||||
|
Steam::Proxy::RegisterCallback(336, [](void* data)
|
||||||
|
{
|
||||||
|
Friends::FriendRichPresenceUpdate* update = static_cast<Friends::FriendRichPresenceUpdate*>(data);
|
||||||
|
Friends::UpdateUserInfo(update->m_steamIDFriend);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Persona state has changed
|
||||||
|
Steam::Proxy::RegisterCallback(304, [](void* data)
|
||||||
|
{
|
||||||
|
Friends::PersonaStateChange* state = static_cast<Friends::PersonaStateChange*>(data);
|
||||||
|
if (Steam::Proxy::SteamFriends) Steam::Proxy::SteamFriends->RequestFriendRichPresence(state->m_ulSteamID);
|
||||||
|
});
|
||||||
|
|
||||||
// Update state when connecting/disconnecting
|
// Update state when connecting/disconnecting
|
||||||
Utils::Hook(0x403582, Friends::DisconnectStub, HOOK_CALL).install()->quick();
|
Utils::Hook(0x403582, Friends::DisconnectStub, HOOK_CALL).install()->quick();
|
||||||
@ -470,32 +322,6 @@ namespace Components
|
|||||||
// Show blue icons on the minimap
|
// Show blue icons on the minimap
|
||||||
Utils::Hook(0x493130, Friends::IsClientInParty, HOOK_JUMP).install()->quick();
|
Utils::Hook(0x493130, Friends::IsClientInParty, HOOK_JUMP).install()->quick();
|
||||||
|
|
||||||
auto fInterface = IPCHandler::NewInterface("steamCallbacks");
|
|
||||||
|
|
||||||
// Callback to update user information
|
|
||||||
fInterface->map("336", [](std::vector<std::string> params)
|
|
||||||
{
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Persona state has changed
|
|
||||||
fInterface->map("304", [](std::vector<std::string> params)
|
|
||||||
{
|
|
||||||
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());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
UIScript::Add("LoadFriends", [](UIScript::Token)
|
UIScript::Add("LoadFriends", [](UIScript::Token)
|
||||||
{
|
{
|
||||||
Friends::UpdateFriends();
|
Friends::UpdateFriends();
|
||||||
@ -528,18 +354,39 @@ namespace Components
|
|||||||
|
|
||||||
UIFeeder::Add(6.0f, Friends::GetFriendCount, Friends::GetFriendText, Friends::SelectFriend);
|
UIFeeder::Add(6.0f, Friends::GetFriendCount, Friends::GetFriendText, Friends::SelectFriend);
|
||||||
|
|
||||||
fInterface = IPCHandler::NewInterface("friends");
|
QuickPatch::OnShutdown([]()
|
||||||
fInterface->map("friendsResponse", Friends::FriendsResponse);
|
{
|
||||||
fInterface->map("nameResponse", Friends::NameResponse);
|
Friends::ClearPresence("iw4x_server");
|
||||||
fInterface->map("presenceResponse", Friends::PresenceResponse);
|
Friends::ClearPresence("iw4x_playing");
|
||||||
fInterface->map("infoResponse", Friends::InfoResponse);
|
|
||||||
|
|
||||||
Friends::SetPresence("iw4x_playing", "1");
|
Steam::Proxy::SteamFriends->ClearRichPresence();
|
||||||
Friends::SetPresence("iw4x_guid", Utils::String::VA("%llX", Steam::SteamUser()->GetSteamID().Bits));
|
|
||||||
|
if(Steam::Proxy::SteamLegacyFriends)
|
||||||
|
{
|
||||||
|
Steam::Proxy::SteamLegacyFriends->SetPersonaState(Friends::InitialState);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
QuickPatch::Once([]()
|
||||||
|
{
|
||||||
|
if (Steam::Proxy::SteamLegacyFriends)
|
||||||
|
{
|
||||||
|
Friends::InitialState = Steam::Proxy::SteamLegacyFriends->GetPersonaState();
|
||||||
|
}
|
||||||
|
|
||||||
|
Friends::SetPresence("iw4x_playing", "1");
|
||||||
|
Friends::SetPresence("iw4x_guid", Utils::String::VA("%llX", Steam::SteamUser()->GetSteamID().Bits));
|
||||||
|
//Friends::UpdateState(); // Don't update state yet, stats will do that
|
||||||
|
|
||||||
|
Friends::UpdateFriends();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Friends::~Friends()
|
Friends::~Friends()
|
||||||
{
|
{
|
||||||
|
Steam::Proxy::UnregisterCallback(336);
|
||||||
|
Steam::Proxy::UnregisterCallback(304);
|
||||||
|
|
||||||
{
|
{
|
||||||
std::lock_guard<std::recursive_mutex> _(Friends::Mutex);
|
std::lock_guard<std::recursive_mutex> _(Friends::Mutex);
|
||||||
Friends::FriendsList.clear();
|
Friends::FriendsList.clear();
|
||||||
|
@ -49,6 +49,7 @@ namespace Components
|
|||||||
int prestige;
|
int prestige;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static int InitialState;
|
||||||
static unsigned int CurrentFriend;
|
static unsigned int CurrentFriend;
|
||||||
static std::recursive_mutex Mutex;
|
static std::recursive_mutex Mutex;
|
||||||
static std::vector<Friend> FriendsList;
|
static std::vector<Friend> FriendsList;
|
||||||
@ -68,12 +69,5 @@ namespace Components
|
|||||||
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 NameResponse(std::vector<std::string> params);
|
|
||||||
static void PresenceResponse(std::vector<std::string> params);
|
|
||||||
static void InfoResponse(std::vector<std::string> params);
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -2,36 +2,12 @@
|
|||||||
|
|
||||||
namespace Components
|
namespace Components
|
||||||
{
|
{
|
||||||
std::unordered_map<std::string, IPCHandler::Callback> IPCHandler::WorkerCallbacks;
|
|
||||||
std::unordered_map<std::string, IPCHandler::Callback> IPCHandler::ClientCallbacks;
|
std::unordered_map<std::string, IPCHandler::Callback> IPCHandler::ClientCallbacks;
|
||||||
|
|
||||||
std::unique_ptr<Utils::IPC::BidirectionalChannel> IPCHandler::WorkerChannel;
|
|
||||||
std::unique_ptr<Utils::IPC::BidirectionalChannel> IPCHandler::ClientChannel;
|
std::unique_ptr<Utils::IPC::BidirectionalChannel> IPCHandler::ClientChannel;
|
||||||
|
|
||||||
std::unordered_map<std::string, std::shared_ptr<IPCHandler::FunctionInterface>> IPCHandler::FunctionInterfaces;
|
|
||||||
|
|
||||||
std::shared_ptr<IPCHandler::FunctionInterface> IPCHandler::NewInterface(std::string command)
|
|
||||||
{
|
|
||||||
std::shared_ptr<IPCHandler::FunctionInterface> fInterface(new IPCHandler::FunctionInterface());
|
|
||||||
IPCHandler::FunctionInterfaces[command] = fInterface;
|
|
||||||
return fInterface;
|
|
||||||
}
|
|
||||||
|
|
||||||
void IPCHandler::SendWorker(std::string message, std::string data)
|
|
||||||
{
|
|
||||||
IPCHandler::InitChannels();
|
|
||||||
if (!Singleton::IsFirstInstance()) return;
|
|
||||||
|
|
||||||
Proto::IPC::Command command;
|
|
||||||
command.set_name(message);
|
|
||||||
command.set_data(data);
|
|
||||||
|
|
||||||
IPCHandler::WorkerChannel->send(command.SerializeAsString());
|
|
||||||
}
|
|
||||||
|
|
||||||
void IPCHandler::SendClient(std::string message, std::string data)
|
void IPCHandler::SendClient(std::string message, std::string data)
|
||||||
{
|
{
|
||||||
IPCHandler::InitChannels();
|
IPCHandler::InitChannel();
|
||||||
|
|
||||||
Proto::IPC::Command command;
|
Proto::IPC::Command command;
|
||||||
command.set_name(message);
|
command.set_name(message);
|
||||||
@ -40,52 +16,22 @@ namespace Components
|
|||||||
IPCHandler::ClientChannel->send(command.SerializeAsString());
|
IPCHandler::ClientChannel->send(command.SerializeAsString());
|
||||||
}
|
}
|
||||||
|
|
||||||
void IPCHandler::OnWorker(std::string message, IPCHandler::Callback callback)
|
|
||||||
{
|
|
||||||
IPCHandler::WorkerCallbacks[message] = callback;
|
|
||||||
}
|
|
||||||
|
|
||||||
void IPCHandler::OnClient(std::string message, IPCHandler::Callback callback)
|
void IPCHandler::OnClient(std::string message, IPCHandler::Callback callback)
|
||||||
{
|
{
|
||||||
IPCHandler::ClientCallbacks[message] = callback;
|
IPCHandler::ClientCallbacks[message] = callback;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IPCHandler::InitChannels()
|
void IPCHandler::InitChannel()
|
||||||
{
|
{
|
||||||
if (Singleton::IsFirstInstance())
|
|
||||||
{
|
|
||||||
if (!IPCHandler::WorkerChannel)
|
|
||||||
{
|
|
||||||
IPCHandler::WorkerChannel.reset(new Utils::IPC::BidirectionalChannel("IW4x-Worker-Channel", !Worker::IsWorker()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!IPCHandler::ClientChannel)
|
if (!IPCHandler::ClientChannel)
|
||||||
{
|
{
|
||||||
IPCHandler::ClientChannel.reset(new Utils::IPC::BidirectionalChannel("IW4x-Client-Channel", Singleton::IsFirstInstance()));
|
IPCHandler::ClientChannel.reset(new Utils::IPC::BidirectionalChannel("IW4x-Client-Channel", Singleton::IsFirstInstance()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void IPCHandler::StartWorker()
|
|
||||||
{
|
|
||||||
if (!Singleton::IsFirstInstance()) return;
|
|
||||||
|
|
||||||
STARTUPINFOA sInfo;
|
|
||||||
PROCESS_INFORMATION pInfo;
|
|
||||||
|
|
||||||
ZeroMemory(&sInfo, sizeof(sInfo));
|
|
||||||
ZeroMemory(&pInfo, sizeof(pInfo));
|
|
||||||
sInfo.cb = sizeof(sInfo);
|
|
||||||
|
|
||||||
CreateProcessA("iw4x.exe", const_cast<char*>(Utils::String::VA("-parent %d", GetCurrentProcessId())), nullptr, nullptr, false, NULL, nullptr, nullptr, &sInfo, &pInfo);
|
|
||||||
|
|
||||||
if (pInfo.hThread && pInfo.hThread != INVALID_HANDLE_VALUE) CloseHandle(pInfo.hThread);
|
|
||||||
if (pInfo.hProcess && pInfo.hProcess != INVALID_HANDLE_VALUE) CloseHandle(pInfo.hProcess);
|
|
||||||
}
|
|
||||||
|
|
||||||
void IPCHandler::HandleClient()
|
void IPCHandler::HandleClient()
|
||||||
{
|
{
|
||||||
IPCHandler::InitChannels();
|
IPCHandler::InitChannel();
|
||||||
|
|
||||||
std::string packet;
|
std::string packet;
|
||||||
if(IPCHandler::ClientChannel->receive(&packet))
|
if(IPCHandler::ClientChannel->receive(&packet))
|
||||||
@ -102,53 +48,18 @@ namespace Components
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void IPCHandler::HandleWorker()
|
|
||||||
{
|
|
||||||
IPCHandler::InitChannels();
|
|
||||||
if (!Singleton::IsFirstInstance()) return;
|
|
||||||
|
|
||||||
std::string packet;
|
|
||||||
if (IPCHandler::WorkerChannel->receive(&packet))
|
|
||||||
{
|
|
||||||
Proto::IPC::Command command;
|
|
||||||
if (command.ParseFromString(packet))
|
|
||||||
{
|
|
||||||
auto callback = IPCHandler::WorkerCallbacks.find(command.name());
|
|
||||||
auto fInterface = IPCHandler::FunctionInterfaces.find(command.name());
|
|
||||||
if (callback != IPCHandler::WorkerCallbacks.end())
|
|
||||||
{
|
|
||||||
callback->second(command.data());
|
|
||||||
}
|
|
||||||
else if(fInterface != IPCHandler::FunctionInterfaces.end())
|
|
||||||
{
|
|
||||||
fInterface->second->handle(command.data());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
IPCHandler::IPCHandler()
|
IPCHandler::IPCHandler()
|
||||||
{
|
{
|
||||||
if (Dedicated::IsEnabled() || ZoneBuilder::IsEnabled() || Loader::PerformingUnitTests()) return;
|
if (Dedicated::IsEnabled() || ZoneBuilder::IsEnabled() || Loader::PerformingUnitTests()) return;
|
||||||
|
|
||||||
IPCHandler::InitChannels();
|
IPCHandler::InitChannel();
|
||||||
IPCHandler::StartWorker();
|
|
||||||
|
|
||||||
QuickPatch::OnFrame([]()
|
QuickPatch::OnFrame(IPCHandler::HandleClient);
|
||||||
{
|
|
||||||
IPCHandler::HandleWorker();
|
|
||||||
IPCHandler::HandleClient();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IPCHandler::~IPCHandler()
|
IPCHandler::~IPCHandler()
|
||||||
{
|
{
|
||||||
IPCHandler::FunctionInterfaces.clear();
|
|
||||||
|
|
||||||
IPCHandler::WorkerCallbacks.clear();
|
|
||||||
IPCHandler::ClientCallbacks.clear();
|
IPCHandler::ClientCallbacks.clear();
|
||||||
|
|
||||||
IPCHandler::WorkerChannel.release();
|
|
||||||
IPCHandler::ClientChannel.release();
|
IPCHandler::ClientChannel.release();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,34 +5,6 @@ namespace Components
|
|||||||
class IPCHandler : public Component
|
class IPCHandler : public Component
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
class FunctionInterface
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
typedef std::function<void(std::vector<std::string>)> Callback;
|
|
||||||
|
|
||||||
void map(std::string name, Callback function)
|
|
||||||
{
|
|
||||||
this->functions[name] = function;
|
|
||||||
}
|
|
||||||
|
|
||||||
void handle(std::string data)
|
|
||||||
{
|
|
||||||
Proto::IPC::Function function;
|
|
||||||
if (function.ParseFromString(data))
|
|
||||||
{
|
|
||||||
auto handler = this->functions.find(function.name());
|
|
||||||
if (handler != this->functions.end())
|
|
||||||
{
|
|
||||||
auto params = function.params();
|
|
||||||
handler->second(std::vector<std::string>(params.begin(), params.end()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::unordered_map<std::string, Callback> functions;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef Utils::Slot<void(std::string)> Callback;
|
typedef Utils::Slot<void(std::string)> Callback;
|
||||||
|
|
||||||
IPCHandler();
|
IPCHandler();
|
||||||
@ -42,27 +14,14 @@ namespace Components
|
|||||||
const char* getName() override { return "IPCHandler"; };
|
const char* getName() override { return "IPCHandler"; };
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void SendWorker(std::string message, std::string data);
|
|
||||||
static void SendClient(std::string message, std::string data);
|
static void SendClient(std::string message, std::string data);
|
||||||
|
|
||||||
static void OnWorker(std::string message, Callback callback);
|
|
||||||
static void OnClient(std::string message, Callback callback);
|
static void OnClient(std::string message, Callback callback);
|
||||||
|
|
||||||
static std::shared_ptr<FunctionInterface> NewInterface(std::string command);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static std::unique_ptr<Utils::IPC::BidirectionalChannel> WorkerChannel;
|
|
||||||
static std::unique_ptr<Utils::IPC::BidirectionalChannel> ClientChannel;
|
static std::unique_ptr<Utils::IPC::BidirectionalChannel> ClientChannel;
|
||||||
|
|
||||||
static std::unordered_map<std::string, Callback> WorkerCallbacks;
|
|
||||||
static std::unordered_map<std::string, Callback> ClientCallbacks;
|
static std::unordered_map<std::string, Callback> ClientCallbacks;
|
||||||
|
|
||||||
static std::unordered_map<std::string, std::shared_ptr<FunctionInterface>> FunctionInterfaces;
|
static void InitChannel();
|
||||||
|
|
||||||
static void InitChannels();
|
|
||||||
static void StartWorker();
|
|
||||||
|
|
||||||
static void HandleClient();
|
static void HandleClient();
|
||||||
static void HandleWorker();
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
42
src/Main.cpp
42
src/Main.cpp
@ -21,42 +21,26 @@ namespace Main
|
|||||||
|
|
||||||
Main::SetEnvironment();
|
Main::SetEnvironment();
|
||||||
Utils::Cryptography::Initialize();
|
Utils::Cryptography::Initialize();
|
||||||
|
Components::Loader::Initialize();
|
||||||
if(Worker::IsWorker())
|
|
||||||
{
|
|
||||||
Worker::Initialize();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Components::Loader::Initialize();
|
|
||||||
|
|
||||||
#if defined(DEBUG) || defined(FORCE_UNIT_TESTS)
|
#if defined(DEBUG) || defined(FORCE_UNIT_TESTS)
|
||||||
if (Components::Loader::PerformingUnitTests())
|
if (Components::Loader::PerformingUnitTests())
|
||||||
{
|
{
|
||||||
DWORD result = (Components::Loader::PerformUnitTests() ? 0 : -1);
|
DWORD result = (Components::Loader::PerformUnitTests() ? 0 : -1);
|
||||||
Components::Loader::Uninitialize();
|
Components::Loader::Uninitialize();
|
||||||
ExitProcess(result);
|
ExitProcess(result);
|
||||||
}
|
|
||||||
#else
|
|
||||||
if (Components::Flags::HasFlag("tests"))
|
|
||||||
{
|
|
||||||
Components::Logger::Print("Unit tests are disabled outside the debug environment!\n");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
if (Components::Flags::HasFlag("tests"))
|
||||||
|
{
|
||||||
|
Components::Logger::Print("Unit tests are disabled outside the debug environment!\n");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void Uninitialize()
|
void Uninitialize()
|
||||||
{
|
{
|
||||||
if(Worker::IsWorker())
|
Components::Loader::Uninitialize();
|
||||||
{
|
|
||||||
Worker::Uninitialize();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Components::Loader::Uninitialize();
|
|
||||||
}
|
|
||||||
|
|
||||||
Utils::Cache::Uninitialize();
|
Utils::Cache::Uninitialize();
|
||||||
google::protobuf::ShutdownProtobufLibrary();
|
google::protobuf::ShutdownProtobufLibrary();
|
||||||
}
|
}
|
||||||
|
@ -120,7 +120,6 @@ template <size_t S> class Sizer { };
|
|||||||
#include "Utils/Stream.hpp"
|
#include "Utils/Stream.hpp"
|
||||||
|
|
||||||
#include "Components/Loader.hpp"
|
#include "Components/Loader.hpp"
|
||||||
#include "Worker/Worker.hpp"
|
|
||||||
|
|
||||||
// Libraries
|
// Libraries
|
||||||
#pragma comment(lib, "Winmm.lib")
|
#pragma comment(lib, "Winmm.lib")
|
||||||
|
@ -83,7 +83,7 @@ namespace Steam
|
|||||||
Proxy::Callbacks.erase(callId);
|
Proxy::Callbacks.erase(callId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Proxy::RunCallback(int32_t callId, void* data, size_t size)
|
void Proxy::RunCallback(int32_t callId, void* data, size_t /*size*/)
|
||||||
{
|
{
|
||||||
std::lock_guard<std::recursive_mutex> _(Proxy::CallMutex);
|
std::lock_guard<std::recursive_mutex> _(Proxy::CallMutex);
|
||||||
|
|
||||||
@ -92,11 +92,6 @@ namespace Steam
|
|||||||
{
|
{
|
||||||
::Utils::Hook::Call<void(void*)>(callback->second)(data);
|
::Utils::Hook::Call<void(void*)>(callback->second)(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(Worker::IsWorker())
|
|
||||||
{
|
|
||||||
Handlers::SteamCallbacks::HandleCallback(callId, data, size);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Proxy::RunFrame()
|
void Proxy::RunFrame()
|
||||||
@ -115,7 +110,7 @@ namespace Steam
|
|||||||
printf("Callback dispatched: %d\n", message.m_iCallback);
|
printf("Callback dispatched: %d\n", message.m_iCallback);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//Steam::Callbacks::RunCallback(message.m_iCallback, message.m_pubParam);
|
Steam::Callbacks::RunCallback(message.m_iCallback, message.m_pubParam);
|
||||||
Proxy::RunCallback(message.m_iCallback, message.m_pubParam, message.m_cubParam);
|
Proxy::RunCallback(message.m_iCallback, message.m_pubParam, message.m_cubParam);
|
||||||
Proxy::SteamFreeLastCallback(Proxy::SteamPipe);
|
Proxy::SteamFreeLastCallback(Proxy::SteamPipe);
|
||||||
}
|
}
|
||||||
@ -165,7 +160,7 @@ namespace Steam
|
|||||||
Proxy::UnregisterCalls();
|
Proxy::UnregisterCalls();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Proxy::Inititalize(bool overlayOnly)
|
bool Proxy::Inititalize()
|
||||||
{
|
{
|
||||||
std::string directoy = Proxy::GetSteamDirectory();
|
std::string directoy = Proxy::GetSteamDirectory();
|
||||||
if (directoy.empty()) return false;
|
if (directoy.empty()) return false;
|
||||||
@ -174,7 +169,6 @@ namespace Steam
|
|||||||
|
|
||||||
Proxy::Overlay = ::Utils::Library(GAMEOVERLAY_LIB, false);
|
Proxy::Overlay = ::Utils::Library(GAMEOVERLAY_LIB, false);
|
||||||
if (!Proxy::Overlay.valid()) return false;
|
if (!Proxy::Overlay.valid()) return false;
|
||||||
if (overlayOnly) return true;
|
|
||||||
|
|
||||||
Proxy::Client = ::Utils::Library(STEAMCLIENT_LIB, false);
|
Proxy::Client = ::Utils::Library(STEAMCLIENT_LIB, false);
|
||||||
if (!Proxy::Client.valid()) return false;
|
if (!Proxy::Client.valid()) return false;
|
||||||
|
@ -334,7 +334,7 @@ namespace Steam
|
|||||||
class Proxy
|
class Proxy
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static bool Inititalize(bool overlayOnly = false);
|
static bool Inititalize();
|
||||||
static void Uninititalize();
|
static void Uninititalize();
|
||||||
|
|
||||||
static void SetGame(uint32_t appId);
|
static void SetGame(uint32_t appId);
|
||||||
|
@ -108,7 +108,7 @@ namespace Steam
|
|||||||
{
|
{
|
||||||
Proxy::SetGame(10190);
|
Proxy::SetGame(10190);
|
||||||
|
|
||||||
if (!Proxy::Inititalize(true))
|
if (!Proxy::Inititalize())
|
||||||
{
|
{
|
||||||
OutputDebugStringA("Steamproxy not initialized properly");
|
OutputDebugStringA("Steamproxy not initialized properly");
|
||||||
}
|
}
|
||||||
@ -129,7 +129,7 @@ namespace Steam
|
|||||||
void SteamAPI_RunCallbacks()
|
void SteamAPI_RunCallbacks()
|
||||||
{
|
{
|
||||||
Callbacks::RunCallbacks();
|
Callbacks::RunCallbacks();
|
||||||
//Proxy::RunFrame();
|
Proxy::RunFrame();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SteamAPI_Shutdown()
|
void SteamAPI_Shutdown()
|
||||||
|
@ -1,184 +0,0 @@
|
|||||||
#include "STDInclude.hpp"
|
|
||||||
|
|
||||||
namespace Handlers
|
|
||||||
{
|
|
||||||
void Friends::handle(Worker::Endpoint endpoint, std::string data)
|
|
||||||
{
|
|
||||||
Proto::IPC::Function function;
|
|
||||||
if (function.ParseFromString(data))
|
|
||||||
{
|
|
||||||
auto handler = this->functions.find(function.name());
|
|
||||||
if (handler != this->functions.end())
|
|
||||||
{
|
|
||||||
printf("Handing function %s\n", function.name().data());
|
|
||||||
|
|
||||||
auto params = function.params();
|
|
||||||
handler->second(endpoint, std::vector<std::string>(params.begin(), params.end()));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
printf("No handler for function %s\n", function.name().data());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Friends::addFunction(std::string function, Friends::Callback callback)
|
|
||||||
{
|
|
||||||
this->functions[function] = callback;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Friends::getFriends(Worker::Endpoint endpoint, std::vector<std::string> params)
|
|
||||||
{
|
|
||||||
if (params.size() >= 1 && Steam::Proxy::SteamFriends)
|
|
||||||
{
|
|
||||||
int flag = atoi(params[0].data());
|
|
||||||
int count = Steam::Proxy::SteamFriends->GetFriendCount(flag);
|
|
||||||
|
|
||||||
Proto::IPC::Function response;
|
|
||||||
response.set_name("friendsResponse");
|
|
||||||
|
|
||||||
for (int i = 0; i < count; ++i)
|
|
||||||
{
|
|
||||||
SteamID id = Steam::Proxy::SteamFriends->GetFriendByIndex(i, flag);
|
|
||||||
*response.add_params() = Utils::String::VA("%llX", id.Bits);
|
|
||||||
}
|
|
||||||
|
|
||||||
endpoint.send(this->getCommand(), response.SerializeAsString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Friends::getName(Worker::Endpoint endpoint, std::vector<std::string> params)
|
|
||||||
{
|
|
||||||
if(Steam::Proxy::SteamFriends)
|
|
||||||
{
|
|
||||||
std::string name;
|
|
||||||
SteamID id;
|
|
||||||
|
|
||||||
if(params.size() >= 1)
|
|
||||||
{
|
|
||||||
id.Bits = strtoull(params[0].data(), nullptr, 16);
|
|
||||||
name = Steam::Proxy::SteamFriends->GetFriendPersonaName(id);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
id.Bits = 0;
|
|
||||||
name = Steam::Proxy::SteamFriends->GetPersonaName();
|
|
||||||
}
|
|
||||||
|
|
||||||
Proto::IPC::Function response;
|
|
||||||
response.set_name("nameResponse");
|
|
||||||
*response.add_params() = Utils::String::VA("%llX", id.Bits);
|
|
||||||
*response.add_params() = name;
|
|
||||||
|
|
||||||
endpoint.send(this->getCommand(), response.SerializeAsString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Friends::setPresence(Worker::Endpoint /*endpoint*/, std::vector<std::string> params)
|
|
||||||
{
|
|
||||||
if (params.size() >= 1 && Steam::Proxy::SteamFriends)
|
|
||||||
{
|
|
||||||
Steam::Proxy::SteamFriends->SetRichPresence(params[0].data(), (params.size() >= 2 ? params[1].data() : nullptr));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Friends::getPresence(Worker::Endpoint endpoint, std::vector<std::string> params)
|
|
||||||
{
|
|
||||||
if (params.size() >= 2 && Steam::Proxy::SteamFriends)
|
|
||||||
{
|
|
||||||
SteamID id;
|
|
||||||
id.Bits = strtoull(params[0].data(), nullptr, 16);
|
|
||||||
|
|
||||||
Proto::IPC::Function response;
|
|
||||||
response.set_name("presenceResponse");
|
|
||||||
*response.add_params() = Utils::String::VA("%llX", id.Bits);
|
|
||||||
*response.add_params() = params[1].data();
|
|
||||||
*response.add_params() = Steam::Proxy::SteamFriends->GetFriendRichPresence(id, params[1].data());
|
|
||||||
|
|
||||||
endpoint.send(this->getCommand(), response.SerializeAsString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Friends::requestPresence(Worker::Endpoint /*endpoint*/, std::vector<std::string> params)
|
|
||||||
{
|
|
||||||
if (params.size() >= 1 && Steam::Proxy::SteamFriends)
|
|
||||||
{
|
|
||||||
SteamID id;
|
|
||||||
id.Bits = strtoull(params[0].data(), nullptr, 16);
|
|
||||||
|
|
||||||
Steam::Proxy::SteamFriends->RequestFriendRichPresence(id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Friends::notifyChange(Worker::Endpoint /*endpoint*/, std::vector<std::string> params)
|
|
||||||
{
|
|
||||||
// Ugly, but for now it works
|
|
||||||
int state = Steam::Proxy::SteamLegacyFriends->GetPersonaState();
|
|
||||||
Steam::Proxy::SteamLegacyFriends->SetPersonaState((state == 1 ? 2 : 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
void Friends::getInfo(Worker::Endpoint endpoint, std::vector<std::string> params)
|
|
||||||
{
|
|
||||||
if (params.size() >= 1 && Steam::Proxy::SteamFriends)
|
|
||||||
{
|
|
||||||
SteamID id;
|
|
||||||
id.Bits = strtoull(params[0].data(), nullptr, 16);
|
|
||||||
|
|
||||||
Proto::IPC::Function response;
|
|
||||||
response.set_name("infoResponse");
|
|
||||||
*response.add_params() = Utils::String::VA("%llX", id.Bits);
|
|
||||||
|
|
||||||
for(unsigned int i = 1; i < params.size(); ++i)
|
|
||||||
{
|
|
||||||
std::string key = params[i];
|
|
||||||
*response.add_params() = key;
|
|
||||||
|
|
||||||
if(key == "name")
|
|
||||||
{
|
|
||||||
*response.add_params() = Steam::Proxy::SteamFriends->GetFriendPersonaName(id);
|
|
||||||
}
|
|
||||||
else if(key == "state")
|
|
||||||
{
|
|
||||||
*response.add_params() = Utils::String::VA("%d", Steam::Proxy::SteamFriends->GetFriendPersonaState(id));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
*response.add_params() = Steam::Proxy::SteamFriends->GetFriendRichPresence(id, key.data());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
endpoint.send(this->getCommand(), response.SerializeAsString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Friends::Friends() : personaState(1)
|
|
||||||
{
|
|
||||||
using namespace std::placeholders;
|
|
||||||
this->addFunction("getFriends", std::bind(&Friends::getFriends, this, _1, _2));
|
|
||||||
this->addFunction("getName", std::bind(&Friends::getName, this, _1, _2));
|
|
||||||
this->addFunction("setPresence", std::bind(&Friends::setPresence, this, _1, _2));
|
|
||||||
this->addFunction("getPresence", std::bind(&Friends::getPresence, this, _1, _2));
|
|
||||||
this->addFunction("requestPresence", std::bind(&Friends::requestPresence, this, _1, _2));
|
|
||||||
this->addFunction("getInfo", std::bind(&Friends::getInfo, this, _1, _2));
|
|
||||||
this->addFunction("notifyChange", std::bind(&Friends::notifyChange, this, _1, _2));
|
|
||||||
|
|
||||||
if (Steam::Proxy::SteamLegacyFriends)
|
|
||||||
{
|
|
||||||
this->personaState = Steam::Proxy::SteamLegacyFriends->GetPersonaState();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Friends::~Friends()
|
|
||||||
{
|
|
||||||
if(Steam::Proxy::SteamFriends)
|
|
||||||
{
|
|
||||||
Steam::Proxy::SteamFriends->SetRichPresence("iw4x_server", nullptr);
|
|
||||||
Steam::Proxy::SteamFriends->SetRichPresence("iw4x_playing", nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(Steam::Proxy::SteamLegacyFriends)
|
|
||||||
{
|
|
||||||
Steam::Proxy::SteamLegacyFriends->SetPersonaState(this->personaState);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,30 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
namespace Handlers
|
|
||||||
{
|
|
||||||
class Friends : public Worker::Runner::Handler
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
typedef std::function<void(Worker::Endpoint, std::vector<std::string>)> Callback;
|
|
||||||
|
|
||||||
Friends();
|
|
||||||
~Friends();
|
|
||||||
|
|
||||||
std::string getCommand() override { return "friends"; };
|
|
||||||
void handle(Worker::Endpoint endpoint, std::string data) override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
int personaState;
|
|
||||||
|
|
||||||
std::unordered_map<std::string, Callback> functions;
|
|
||||||
void addFunction(std::string function, Callback callback);
|
|
||||||
|
|
||||||
void getFriends(Worker::Endpoint endpoint, std::vector<std::string> params);
|
|
||||||
void getName(Worker::Endpoint endpoint, std::vector<std::string> params);
|
|
||||||
void setPresence(Worker::Endpoint endpoint, std::vector<std::string> params);
|
|
||||||
void getPresence(Worker::Endpoint endpoint, std::vector<std::string> params);
|
|
||||||
void requestPresence(Worker::Endpoint endpoint, std::vector<std::string> params);
|
|
||||||
void getInfo(Worker::Endpoint endpoint, std::vector<std::string> params);
|
|
||||||
void notifyChange(Worker::Endpoint /*endpoint*/, std::vector<std::string> params);
|
|
||||||
};
|
|
||||||
}
|
|
@ -1,55 +0,0 @@
|
|||||||
#include "STDInclude.hpp"
|
|
||||||
|
|
||||||
namespace Handlers
|
|
||||||
{
|
|
||||||
void SteamCallbacks::handle(Worker::Endpoint endpoint, std::string data)
|
|
||||||
{
|
|
||||||
Proto::IPC::Function function;
|
|
||||||
if (function.ParseFromString(data))
|
|
||||||
{
|
|
||||||
auto handler = this->functions.find(function.name());
|
|
||||||
if (handler != this->functions.end())
|
|
||||||
{
|
|
||||||
printf("Handing function %s\n", function.name().data());
|
|
||||||
|
|
||||||
auto params = function.params();
|
|
||||||
handler->second(endpoint, std::vector<std::string>(params.begin(), params.end()));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
printf("No handler for function %s\n", function.name().data());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SteamCallbacks::addFunction(std::string function, Friends::Callback callback)
|
|
||||||
{
|
|
||||||
this->functions[function] = callback;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SteamCallbacks::HandleCallback(int32_t callId, void* data, size_t size)
|
|
||||||
{
|
|
||||||
if(Worker::Runner::Channel)
|
|
||||||
{
|
|
||||||
Proto::IPC::Function response;
|
|
||||||
response.set_name(Utils::String::VA("%d", callId));
|
|
||||||
response.add_params()->append(static_cast<char*>(data), size);
|
|
||||||
|
|
||||||
Proto::IPC::Command command;
|
|
||||||
command.set_name(SteamCallbacks().getCommand());
|
|
||||||
command.set_data(response.SerializeAsString());
|
|
||||||
|
|
||||||
Worker::Runner::Channel->send(command.SerializeAsString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SteamCallbacks::SteamCallbacks()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
SteamCallbacks::~SteamCallbacks()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,22 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
namespace Handlers
|
|
||||||
{
|
|
||||||
class SteamCallbacks : public Worker::Runner::Handler
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
typedef std::function<void(Worker::Endpoint, std::vector<std::string>)> Callback;
|
|
||||||
|
|
||||||
SteamCallbacks();
|
|
||||||
~SteamCallbacks();
|
|
||||||
|
|
||||||
std::string getCommand() override { return "steamCallbacks"; };
|
|
||||||
void handle(Worker::Endpoint endpoint, std::string data) override;
|
|
||||||
|
|
||||||
static void HandleCallback(int32_t callId, void* data, size_t size);
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::unordered_map<std::string, Callback> functions;
|
|
||||||
void addFunction(std::string function, Callback callback);
|
|
||||||
};
|
|
||||||
}
|
|
@ -1,113 +0,0 @@
|
|||||||
#include "STDInclude.hpp"
|
|
||||||
|
|
||||||
namespace Worker
|
|
||||||
{
|
|
||||||
Utils::IPC::BidirectionalChannel* Runner::Channel;
|
|
||||||
|
|
||||||
Runner::Runner(int pid) : processId(pid), terminate(false)
|
|
||||||
{
|
|
||||||
Runner::Channel = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
Runner::~Runner()
|
|
||||||
{
|
|
||||||
Runner::Channel = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Runner::run()
|
|
||||||
{
|
|
||||||
printf("Attaching to parent process %d...\n", this->processId);
|
|
||||||
HANDLE processHandle = OpenProcess(SYNCHRONIZE, FALSE, this->processId);
|
|
||||||
|
|
||||||
if ((!processHandle || processHandle == INVALID_HANDLE_VALUE))
|
|
||||||
{
|
|
||||||
printf("Passive attach failed, trying actively...\n");
|
|
||||||
|
|
||||||
if (!Runner::isProcessAlive())
|
|
||||||
{
|
|
||||||
printf("Unable to attach to parent process\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("Successfully attached to parent process\n");
|
|
||||||
printf("Starting worker...\n");
|
|
||||||
|
|
||||||
std::thread workerThread(&Runner::worker, this);
|
|
||||||
|
|
||||||
if (!processHandle || processHandle == INVALID_HANDLE_VALUE)
|
|
||||||
{
|
|
||||||
while(this->isProcessAlive())
|
|
||||||
{
|
|
||||||
std::this_thread::sleep_for(100ms);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
WaitForSingleObject(processHandle, INFINITE);
|
|
||||||
CloseHandle(processHandle);
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("Awaiting worker termination...\n");
|
|
||||||
this->terminate = true;
|
|
||||||
if (workerThread.joinable()) workerThread.join();
|
|
||||||
printf("Worker terminated\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
void Runner::attachHandler(Runner::Handler* handler)
|
|
||||||
{
|
|
||||||
this->handlers[handler->getCommand()] = std::shared_ptr<Runner::Handler>(handler);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Runner::isProcessAlive()
|
|
||||||
{
|
|
||||||
DWORD aProcesses[1024], cbNeeded;
|
|
||||||
if (!EnumProcesses(aProcesses, sizeof(aProcesses), &cbNeeded)) return false;
|
|
||||||
|
|
||||||
for(DWORD i = 0; i < cbNeeded / sizeof(DWORD); ++i)
|
|
||||||
{
|
|
||||||
if(aProcesses[i] == static_cast<DWORD>(this->processId))
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Runner::worker()
|
|
||||||
{
|
|
||||||
printf("Worker started\n");
|
|
||||||
Utils::IPC::BidirectionalChannel channel("IW4x-Worker-Channel", !Worker::IsWorker());
|
|
||||||
Runner::Channel = &channel;
|
|
||||||
|
|
||||||
while (!this->terminate)
|
|
||||||
{
|
|
||||||
Steam::Proxy::RunFrame();
|
|
||||||
|
|
||||||
std::string buffer;
|
|
||||||
if (channel.receive(&buffer))
|
|
||||||
{
|
|
||||||
Proto::IPC::Command command;
|
|
||||||
if(command.ParseFromString(buffer))
|
|
||||||
{
|
|
||||||
auto handler = this->handlers.find(command.name());
|
|
||||||
if (handler != this->handlers.end())
|
|
||||||
{
|
|
||||||
printf("Dispatching command %s to handler\n", command.name().data());
|
|
||||||
handler->second->handle(&channel, command.data());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
printf("No handler found for command %s\n", command.name().data());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::this_thread::sleep_for(1ms);
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("Terminating worker\n");
|
|
||||||
Runner::Channel = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,59 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
namespace Worker
|
|
||||||
{
|
|
||||||
class Endpoint
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Endpoint() : Endpoint(nullptr) {}
|
|
||||||
Endpoint(Utils::IPC::BidirectionalChannel* _channel) : channel(_channel) {}
|
|
||||||
Endpoint(const Endpoint& obj) : Endpoint(obj.channel) {}
|
|
||||||
|
|
||||||
void send(std::string message, std::string data)
|
|
||||||
{
|
|
||||||
if (this->channel)
|
|
||||||
{
|
|
||||||
Proto::IPC::Command command;
|
|
||||||
command.set_name(message);
|
|
||||||
command.set_data(data);
|
|
||||||
|
|
||||||
this->channel->send(command.SerializeAsString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
Utils::IPC::BidirectionalChannel* channel;
|
|
||||||
};
|
|
||||||
|
|
||||||
class Runner
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
class Handler
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
virtual ~Handler() {};
|
|
||||||
virtual std::string getCommand() = 0;
|
|
||||||
virtual void handle(Endpoint endpoint, std::string data) = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
Runner(int pid);
|
|
||||||
~Runner();
|
|
||||||
|
|
||||||
void run();
|
|
||||||
|
|
||||||
void attachHandler(Runner::Handler* handler);
|
|
||||||
|
|
||||||
static Utils::IPC::BidirectionalChannel* Channel;
|
|
||||||
|
|
||||||
private:
|
|
||||||
void worker();
|
|
||||||
bool isProcessAlive();
|
|
||||||
|
|
||||||
int processId;
|
|
||||||
bool terminate;
|
|
||||||
std::unordered_map<std::string, std::shared_ptr<Handler>> handlers;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#include "Handlers/Friends.hpp"
|
|
||||||
#include "Handlers/SteamCallbacks.hpp"
|
|
@ -1,67 +0,0 @@
|
|||||||
#include "STDInclude.hpp"
|
|
||||||
|
|
||||||
namespace Worker
|
|
||||||
{
|
|
||||||
int ProcessId;
|
|
||||||
|
|
||||||
int __stdcall EntryPoint(HINSTANCE /*hInstance*/, HINSTANCE /*hPrevInstance*/, char* /*lpCmdLine*/, int /*nCmdShow*/)
|
|
||||||
{
|
|
||||||
Runner runner(Worker::ProcessId);
|
|
||||||
runner.attachHandler(new Handlers::Friends());
|
|
||||||
runner.attachHandler(new Handlers::SteamCallbacks());
|
|
||||||
runner.run();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Initialize()
|
|
||||||
{
|
|
||||||
if(!Steam::Proxy::Inititalize())
|
|
||||||
{
|
|
||||||
printf("Failed to initialize worker!\n");
|
|
||||||
ExitProcess(1);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
#ifdef DEBUG
|
|
||||||
SetConsoleTitleA("IW4x: Worker");
|
|
||||||
#else
|
|
||||||
FreeConsole();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
Utils::Hook(0x6BABA1, Worker::EntryPoint, HOOK_CALL).install()->quick();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Uninitialize()
|
|
||||||
{
|
|
||||||
Steam::Proxy::Uninititalize();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ParseWorkerFlag()
|
|
||||||
{
|
|
||||||
char* command = "-parent ";
|
|
||||||
char* parentProc = strstr(GetCommandLineA(), command);
|
|
||||||
|
|
||||||
if (parentProc)
|
|
||||||
{
|
|
||||||
parentProc += strlen(command);
|
|
||||||
Worker::ProcessId = atoi(parentProc);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IsWorker()
|
|
||||||
{
|
|
||||||
static Utils::Value<bool> flag;
|
|
||||||
|
|
||||||
if (!flag.isValid())
|
|
||||||
{
|
|
||||||
flag.set(Worker::ParseWorkerFlag());
|
|
||||||
}
|
|
||||||
|
|
||||||
return flag.get();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
namespace Worker
|
|
||||||
{
|
|
||||||
void Initialize();
|
|
||||||
void Uninitialize();
|
|
||||||
|
|
||||||
bool IsWorker();
|
|
||||||
}
|
|
||||||
|
|
||||||
#include "Runner.hpp"
|
|
Loading…
Reference in New Issue
Block a user