Merge branch 'friendhandler' into 'develop'
Friendhandler
This commit is contained in:
commit
1e72fe51be
@ -6,42 +6,9 @@ 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::UpdateUserInfo(SteamID user)
|
void Friends::SortIndividualList(std::vector<Friends::Friend>* list)
|
||||||
{
|
{
|
||||||
if (!Steam::Proxy::SteamFriends) return;
|
qsort(list->data(), list->size(), sizeof(Friends::Friend), [](const void* first, const void* second)
|
||||||
std::lock_guard<std::recursive_mutex> _(Friends::Mutex);
|
|
||||||
|
|
||||||
Friends::Friend userInfo;
|
|
||||||
|
|
||||||
auto i = std::find_if(Friends::FriendsList.begin(), Friends::FriendsList.end(), [user] (Friends::Friend entry)
|
|
||||||
{
|
|
||||||
return (entry.userId.Bits == user.Bits);
|
|
||||||
});
|
|
||||||
|
|
||||||
if(i != Friends::FriendsList.end())
|
|
||||||
{
|
|
||||||
userInfo = *i;
|
|
||||||
}
|
|
||||||
|
|
||||||
userInfo.userId = user;
|
|
||||||
userInfo.online = Steam::Proxy::SteamFriends->GetFriendPersonaState(user) != 0;
|
|
||||||
userInfo.name = Steam::Proxy::SteamFriends->GetFriendPersonaName(user);
|
|
||||||
userInfo.statusName = Steam::Proxy::SteamFriends->GetFriendRichPresence(user, "iw4x_status");
|
|
||||||
userInfo.prestige = Utils::Cryptography::Rand::GenerateInt() % (10 + 1);
|
|
||||||
userInfo.experience = Utils::Cryptography::Rand::GenerateInt() % (2516000 + 1);
|
|
||||||
|
|
||||||
//if (!userInfo.online) return;
|
|
||||||
|
|
||||||
if (i != Friends::FriendsList.end())
|
|
||||||
{
|
|
||||||
*i = userInfo;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Friends::FriendsList.push_back(userInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
qsort(Friends::FriendsList.data(), Friends::FriendsList.size(), sizeof(Friends::Friend), [](const void* first, const void* second)
|
|
||||||
{
|
{
|
||||||
const Friends::Friend* friend1 = static_cast<const Friends::Friend*>(first);
|
const Friends::Friend* friend1 = static_cast<const Friends::Friend*>(first);
|
||||||
const Friends::Friend* friend2 = static_cast<const Friends::Friend*>(second);
|
const Friends::Friend* friend2 = static_cast<const Friends::Friend*>(second);
|
||||||
@ -53,40 +20,139 @@ namespace Components
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void Friends::UpdateFriends()
|
void Friends::SortList()
|
||||||
{
|
{
|
||||||
if (!Steam::Proxy::SteamFriends) return;
|
|
||||||
std::lock_guard<std::recursive_mutex> _(Friends::Mutex);
|
std::lock_guard<std::recursive_mutex> _(Friends::Mutex);
|
||||||
|
|
||||||
auto listCopy = Friends::FriendsList;
|
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();
|
Friends::FriendsList.clear();
|
||||||
|
|
||||||
int count = Steam::Proxy::SteamFriends->GetFriendCount(4);
|
Utils::Merge(&Friends::FriendsList, playingList);
|
||||||
Friends::FriendsList.reserve(count);
|
Utils::Merge(&Friends::FriendsList, onlineList);
|
||||||
|
Utils::Merge(&Friends::FriendsList, offlineList);
|
||||||
|
}
|
||||||
|
|
||||||
for(int i = 0; i < count; ++i)
|
void Friends::UpdateUserInfo(SteamID user)
|
||||||
|
{
|
||||||
|
Proto::IPC::Function function;
|
||||||
|
|
||||||
|
function.set_name("getInfo");
|
||||||
|
*function.add_params() = Utils::String::VA("%llx", user.Bits);
|
||||||
|
|
||||||
|
*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";
|
||||||
|
|
||||||
|
IPCHandler::SendWorker("friends", function.SerializeAsString());
|
||||||
|
}
|
||||||
|
|
||||||
|
void Friends::UpdateState()
|
||||||
|
{
|
||||||
|
Proto::IPC::Function function;
|
||||||
|
function.set_name("notifyChange");
|
||||||
|
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)
|
||||||
{
|
{
|
||||||
SteamID friendId = Steam::Proxy::SteamFriends->GetFriendByIndex(i, 4);
|
if(entry.server == server)
|
||||||
//if(!Steam::Proxy::SteamFriends->GetFriendPersonaState(friendId)) continue; // Offline
|
|
||||||
|
|
||||||
auto entry = std::find_if(listCopy.begin(), listCopy.end(), [friendId](Friends::Friend entry)
|
|
||||||
{
|
{
|
||||||
return (entry.userId.Bits == friendId.Bits);
|
entry.serverName = hostname;
|
||||||
});
|
|
||||||
|
|
||||||
if (entry != listCopy.end())
|
|
||||||
{
|
|
||||||
Friends::FriendsList.push_back(*entry);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Friends::UpdateUserInfo(friendId);
|
|
||||||
Steam::Proxy::SteamFriends->RequestFriendRichPresence(friendId);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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()
|
||||||
|
{
|
||||||
|
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());
|
||||||
|
|
||||||
|
Friends::UpdateState();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Friends::UpdateFriends()
|
||||||
|
{
|
||||||
|
Proto::IPC::Function function;
|
||||||
|
function.set_name("getFriends");
|
||||||
|
*function.add_params() = Utils::String::VA("%d", 4);
|
||||||
|
|
||||||
|
IPCHandler::SendWorker("friends", function.SerializeAsString());
|
||||||
|
}
|
||||||
|
|
||||||
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,6 +173,7 @@ namespace Components
|
|||||||
Game::Material* rankIcon = nullptr;
|
Game::Material* rankIcon = nullptr;
|
||||||
int rank = Game::CL_GetRankForXP(user.experience);
|
int rank = Game::CL_GetRankForXP(user.experience);
|
||||||
Game::CL_GetRankIcon(rank, user.prestige, &rankIcon);
|
Game::CL_GetRankIcon(rank, user.prestige, &rankIcon);
|
||||||
|
if (!rankIcon) rankIcon = Game::DB_FindXAssetDefaultHeaderInternal(Game::XAssetType::ASSET_TYPE_MATERIAL).material;
|
||||||
|
|
||||||
buffer[0] = '^';
|
buffer[0] = '^';
|
||||||
buffer[1] = 2;
|
buffer[1] = 2;
|
||||||
@ -120,7 +187,7 @@ namespace Components
|
|||||||
buffer[4] = static_cast<char>(strlen(rankIcon->name));
|
buffer[4] = static_cast<char>(strlen(rankIcon->name));
|
||||||
|
|
||||||
strcat_s(buffer, rankIcon->name);
|
strcat_s(buffer, rankIcon->name);
|
||||||
strcat_s(buffer, Utils::String::VA(" %i", rank));
|
strcat_s(buffer, Utils::String::VA(" %i", (rank + 1)));
|
||||||
|
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
@ -128,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;
|
||||||
@ -145,20 +232,211 @@ 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_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();
|
||||||
|
}
|
||||||
|
|
||||||
|
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.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()
|
||||||
|
{
|
||||||
|
__asm
|
||||||
|
{
|
||||||
|
pushad
|
||||||
|
call Friends::ClearServer
|
||||||
|
popad
|
||||||
|
|
||||||
|
push 467CC0h
|
||||||
|
retn
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Friends::Friends()
|
Friends::Friends()
|
||||||
{
|
{
|
||||||
|
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");
|
||||||
|
|
||||||
// Callback to update user information
|
// Callback to update user information
|
||||||
Steam::Proxy::RegisterCallback(336, [](void* data)
|
fInterface->map("336", [](std::vector<std::string> params)
|
||||||
{
|
{
|
||||||
Friends::FriendRichPresenceUpdate* update = static_cast<Friends::FriendRichPresenceUpdate*>(data);
|
if (params.size() >= 1 && params[0].size() == sizeof(Friends::FriendRichPresenceUpdate))
|
||||||
Friends::UpdateUserInfo(update->m_steamIDFriend);
|
{
|
||||||
|
const Friends::FriendRichPresenceUpdate* update = reinterpret_cast<const Friends::FriendRichPresenceUpdate*>(params[0].data());
|
||||||
|
Friends::UpdateUserInfo(update->m_steamIDFriend);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Persona state has changed
|
// Persona state has changed
|
||||||
Steam::Proxy::RegisterCallback(304, [](void* data)
|
fInterface->map("304", [](std::vector<std::string> params)
|
||||||
{
|
{
|
||||||
Friends::PersonaStateChange* state = static_cast<Friends::PersonaStateChange*>(data);
|
if(params.size() >= 1 && params[0].size() == sizeof(Friends::PersonaStateChange))
|
||||||
if(Steam::Proxy::SteamFriends) Steam::Proxy::SteamFriends->RequestFriendRichPresence(state->m_ulSteamID);
|
{
|
||||||
|
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)
|
||||||
@ -166,19 +444,42 @@ 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([]()
|
||||||
|
{
|
||||||
|
if(*reinterpret_cast<bool*>(0x1AD5690)) // LiveStorage_DoWeHaveStats
|
||||||
|
{
|
||||||
|
Friends::UpdateRank();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
UIFeeder::Add(6.0f, Friends::GetFriendCount, Friends::GetFriendText, Friends::SelectFriend);
|
UIFeeder::Add(6.0f, Friends::GetFriendCount, Friends::GetFriendText, Friends::SelectFriend);
|
||||||
|
|
||||||
|
fInterface = IPCHandler::NewInterface("friends");
|
||||||
|
fInterface->map("friendsResponse", Friends::FriendsResponse);
|
||||||
|
fInterface->map("nameResponse", Friends::NameResponse);
|
||||||
|
fInterface->map("presenceResponse", Friends::PresenceResponse);
|
||||||
|
fInterface->map("infoResponse", Friends::InfoResponse);
|
||||||
}
|
}
|
||||||
|
|
||||||
Friends::~Friends()
|
Friends::~Friends()
|
||||||
{
|
{
|
||||||
Steam::Proxy::UnregisterCallback(304);
|
|
||||||
Steam::Proxy::UnregisterCallback(336);
|
|
||||||
|
|
||||||
if (Steam::Proxy::SteamFriends)
|
|
||||||
{
|
|
||||||
Steam::Proxy::SteamFriends->SetRichPresence("iw4x_status", nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
{
|
||||||
std::lock_guard<std::recursive_mutex> _(Friends::Mutex);
|
std::lock_guard<std::recursive_mutex> _(Friends::Mutex);
|
||||||
Friends::FriendsList.clear();
|
Friends::FriendsList.clear();
|
||||||
|
@ -13,13 +13,17 @@ namespace Components
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void UpdateFriends();
|
static void UpdateFriends();
|
||||||
|
static void UpdateRank();
|
||||||
|
static void UpdateHostname(Network::Address server, std::string hostname);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
#pragma pack(push, 4)
|
||||||
struct FriendRichPresenceUpdate
|
struct FriendRichPresenceUpdate
|
||||||
{
|
{
|
||||||
SteamID m_steamIDFriend; // friend who's rich presence has changed
|
SteamID m_steamIDFriend; // friend who's rich presence has changed
|
||||||
int32_t m_nAppID; // the appID of the game (should always be the current game)
|
int32_t m_nAppID; // the appID of the game (should always be the current game)
|
||||||
};
|
};
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
struct PersonaStateChange
|
struct PersonaStateChange
|
||||||
{
|
{
|
||||||
@ -32,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;
|
||||||
@ -43,10 +48,25 @@ 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 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 NameResponse(std::vector<std::string> params);
|
||||||
|
static void PresenceResponse(std::vector<std::string> params);
|
||||||
|
static void InfoResponse(std::vector<std::string> params);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -8,12 +8,22 @@ namespace Components
|
|||||||
std::unique_ptr<Utils::IPC::BidirectionalChannel> IPCHandler::WorkerChannel;
|
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)
|
void IPCHandler::SendWorker(std::string message, std::string data)
|
||||||
{
|
{
|
||||||
IPCHandler::InitChannels();
|
IPCHandler::InitChannels();
|
||||||
|
if (!Singleton::IsFirstInstance()) return;
|
||||||
|
|
||||||
Proto::IPC::Command command;
|
Proto::IPC::Command command;
|
||||||
command.set_command(message);
|
command.set_name(message);
|
||||||
command.set_data(data);
|
command.set_data(data);
|
||||||
|
|
||||||
IPCHandler::WorkerChannel->send(command.SerializeAsString());
|
IPCHandler::WorkerChannel->send(command.SerializeAsString());
|
||||||
@ -24,7 +34,7 @@ namespace Components
|
|||||||
IPCHandler::InitChannels();
|
IPCHandler::InitChannels();
|
||||||
|
|
||||||
Proto::IPC::Command command;
|
Proto::IPC::Command command;
|
||||||
command.set_command(message);
|
command.set_name(message);
|
||||||
command.set_data(data);
|
command.set_data(data);
|
||||||
|
|
||||||
IPCHandler::ClientChannel->send(command.SerializeAsString());
|
IPCHandler::ClientChannel->send(command.SerializeAsString());
|
||||||
@ -42,9 +52,12 @@ namespace Components
|
|||||||
|
|
||||||
void IPCHandler::InitChannels()
|
void IPCHandler::InitChannels()
|
||||||
{
|
{
|
||||||
if (!IPCHandler::WorkerChannel)
|
if (Singleton::IsFirstInstance())
|
||||||
{
|
{
|
||||||
IPCHandler::WorkerChannel.reset(new Utils::IPC::BidirectionalChannel("IW4x-Worker-Channel", !Worker::IsWorker()));
|
if (!IPCHandler::WorkerChannel)
|
||||||
|
{
|
||||||
|
IPCHandler::WorkerChannel.reset(new Utils::IPC::BidirectionalChannel("IW4x-Worker-Channel", !Worker::IsWorker()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!IPCHandler::ClientChannel)
|
if (!IPCHandler::ClientChannel)
|
||||||
@ -55,6 +68,8 @@ namespace Components
|
|||||||
|
|
||||||
void IPCHandler::StartWorker()
|
void IPCHandler::StartWorker()
|
||||||
{
|
{
|
||||||
|
if (!Singleton::IsFirstInstance()) return;
|
||||||
|
|
||||||
STARTUPINFOA sInfo;
|
STARTUPINFOA sInfo;
|
||||||
PROCESS_INFORMATION pInfo;
|
PROCESS_INFORMATION pInfo;
|
||||||
|
|
||||||
@ -78,7 +93,7 @@ namespace Components
|
|||||||
Proto::IPC::Command command;
|
Proto::IPC::Command command;
|
||||||
if(command.ParseFromString(packet))
|
if(command.ParseFromString(packet))
|
||||||
{
|
{
|
||||||
auto callback = IPCHandler::ClientCallbacks.find(command.command());
|
auto callback = IPCHandler::ClientCallbacks.find(command.name());
|
||||||
if (callback != IPCHandler::ClientCallbacks.end())
|
if (callback != IPCHandler::ClientCallbacks.end())
|
||||||
{
|
{
|
||||||
callback->second(command.data());
|
callback->second(command.data());
|
||||||
@ -90,6 +105,7 @@ namespace Components
|
|||||||
void IPCHandler::HandleWorker()
|
void IPCHandler::HandleWorker()
|
||||||
{
|
{
|
||||||
IPCHandler::InitChannels();
|
IPCHandler::InitChannels();
|
||||||
|
if (!Singleton::IsFirstInstance()) return;
|
||||||
|
|
||||||
std::string packet;
|
std::string packet;
|
||||||
if (IPCHandler::WorkerChannel->receive(&packet))
|
if (IPCHandler::WorkerChannel->receive(&packet))
|
||||||
@ -97,11 +113,16 @@ namespace Components
|
|||||||
Proto::IPC::Command command;
|
Proto::IPC::Command command;
|
||||||
if (command.ParseFromString(packet))
|
if (command.ParseFromString(packet))
|
||||||
{
|
{
|
||||||
auto callback = IPCHandler::WorkerCallbacks.find(command.command());
|
auto callback = IPCHandler::WorkerCallbacks.find(command.name());
|
||||||
|
auto fInterface = IPCHandler::FunctionInterfaces.find(command.name());
|
||||||
if (callback != IPCHandler::WorkerCallbacks.end())
|
if (callback != IPCHandler::WorkerCallbacks.end())
|
||||||
{
|
{
|
||||||
callback->second(command.data());
|
callback->second(command.data());
|
||||||
}
|
}
|
||||||
|
else if(fInterface != IPCHandler::FunctionInterfaces.end())
|
||||||
|
{
|
||||||
|
fInterface->second->handle(command.data());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -122,7 +143,12 @@ namespace Components
|
|||||||
|
|
||||||
IPCHandler::~IPCHandler()
|
IPCHandler::~IPCHandler()
|
||||||
{
|
{
|
||||||
|
IPCHandler::FunctionInterfaces.clear();
|
||||||
|
|
||||||
IPCHandler::WorkerCallbacks.clear();
|
IPCHandler::WorkerCallbacks.clear();
|
||||||
IPCHandler::ClientCallbacks.clear();
|
IPCHandler::ClientCallbacks.clear();
|
||||||
|
|
||||||
|
IPCHandler::WorkerChannel.release();
|
||||||
|
IPCHandler::ClientChannel.release();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,34 @@ 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();
|
||||||
@ -20,12 +48,16 @@ namespace Components
|
|||||||
static void OnWorker(std::string message, Callback callback);
|
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> 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> 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 InitChannels();
|
static void InitChannels();
|
||||||
static void StartWorker();
|
static void StartWorker();
|
||||||
|
@ -451,6 +451,7 @@ namespace Components
|
|||||||
}
|
}
|
||||||
|
|
||||||
ServerList::Insert(address, info);
|
ServerList::Insert(address, info);
|
||||||
|
Friends::UpdateHostname(address, info.get("hostname"));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,7 +106,9 @@ namespace Components
|
|||||||
static std::string outputBuffer;
|
static std::string outputBuffer;
|
||||||
outputBuffer.clear();
|
outputBuffer.clear();
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
Logger::Print("Executing RCon request from %s: %s\n", address.getCString(), command.data());
|
Logger::Print("Executing RCon request from %s: %s\n", address.getCString(), command.data());
|
||||||
|
#endif
|
||||||
|
|
||||||
Logger::PipeOutput([] (std::string output)
|
Logger::PipeOutput([] (std::string output)
|
||||||
{
|
{
|
||||||
|
@ -164,6 +164,8 @@ namespace Game
|
|||||||
|
|
||||||
Live_MPAcceptInvite_t Live_MPAcceptInvite = Live_MPAcceptInvite_t(0x420A6D);
|
Live_MPAcceptInvite_t Live_MPAcceptInvite = Live_MPAcceptInvite_t(0x420A6D);
|
||||||
Live_GetMapIndex_t Live_GetMapIndex = Live_GetMapIndex_t(0x4F6440);
|
Live_GetMapIndex_t Live_GetMapIndex = Live_GetMapIndex_t(0x4F6440);
|
||||||
|
Live_GetPrestige_t Live_GetPrestige = Live_GetPrestige_t(0x430F90);
|
||||||
|
Live_GetXp_t Live_GetXp = Live_GetXp_t(0x404C60);
|
||||||
|
|
||||||
LoadModdableRawfile_t LoadModdableRawfile = LoadModdableRawfile_t(0x61ABC0);
|
LoadModdableRawfile_t LoadModdableRawfile = LoadModdableRawfile_t(0x61ABC0);
|
||||||
|
|
||||||
@ -461,6 +463,24 @@ namespace Game
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
XAssetHeader DB_FindXAssetDefaultHeaderInternal(XAssetType _type)
|
||||||
|
{
|
||||||
|
// ReSharper disable once CppEntityNeverUsed
|
||||||
|
static int func = 0x5BB210;
|
||||||
|
XAssetHeader result;
|
||||||
|
|
||||||
|
__asm
|
||||||
|
{
|
||||||
|
push edi
|
||||||
|
mov edi, _type
|
||||||
|
call func
|
||||||
|
pop edi
|
||||||
|
mov result, eax
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
void FS_AddLocalizedGameDirectory(const char *path, const char *dir)
|
void FS_AddLocalizedGameDirectory(const char *path, const char *dir)
|
||||||
{
|
{
|
||||||
__asm
|
__asm
|
||||||
|
@ -412,6 +412,12 @@ namespace Game
|
|||||||
typedef int(__cdecl * Live_GetMapIndex_t)(const char* mapname);
|
typedef int(__cdecl * Live_GetMapIndex_t)(const char* mapname);
|
||||||
extern Live_GetMapIndex_t Live_GetMapIndex;
|
extern Live_GetMapIndex_t Live_GetMapIndex;
|
||||||
|
|
||||||
|
typedef int(__cdecl * Live_GetPrestige_t)(int controllerIndex);
|
||||||
|
extern Live_GetPrestige_t Live_GetPrestige;
|
||||||
|
|
||||||
|
typedef int(__cdecl * Live_GetXp_t)(int controllerIndex);
|
||||||
|
extern Live_GetXp_t Live_GetXp;
|
||||||
|
|
||||||
typedef char* (__cdecl * LoadModdableRawfile_t)(int a1, const char* filename);
|
typedef char* (__cdecl * LoadModdableRawfile_t)(int a1, const char* filename);
|
||||||
extern LoadModdableRawfile_t LoadModdableRawfile;
|
extern LoadModdableRawfile_t LoadModdableRawfile;
|
||||||
|
|
||||||
@ -697,6 +703,7 @@ namespace Game
|
|||||||
const char *DB_GetXAssetName(XAsset *asset);
|
const char *DB_GetXAssetName(XAsset *asset);
|
||||||
XAssetType DB_GetXAssetNameType(const char* name);
|
XAssetType DB_GetXAssetNameType(const char* name);
|
||||||
bool DB_IsZoneLoaded(const char* zone);
|
bool DB_IsZoneLoaded(const char* zone);
|
||||||
|
XAssetHeader DB_FindXAssetDefaultHeaderInternal(XAssetType type);
|
||||||
|
|
||||||
void FS_AddLocalizedGameDirectory(const char *path, const char *dir);
|
void FS_AddLocalizedGameDirectory(const char *path, const char *dir);
|
||||||
|
|
||||||
|
@ -4,6 +4,12 @@ package Proto.IPC;
|
|||||||
|
|
||||||
message Command
|
message Command
|
||||||
{
|
{
|
||||||
bytes command = 1;
|
bytes name = 1;
|
||||||
bytes data = 2;
|
bytes data = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message Function
|
||||||
|
{
|
||||||
|
bytes name = 1;
|
||||||
|
repeated bytes params = 2;
|
||||||
|
}
|
||||||
|
@ -31,6 +31,7 @@
|
|||||||
#include <future>
|
#include <future>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
#include <queue>
|
||||||
|
|
||||||
// Experimental C++17 features
|
// Experimental C++17 features
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
|
@ -105,4 +105,14 @@ namespace Steam
|
|||||||
virtual uint64_t IsFollowing(SteamID steamID) = 0;
|
virtual uint64_t IsFollowing(SteamID steamID) = 0;
|
||||||
virtual uint64_t EnumerateFollowingList(uint32_t unStartIndex) = 0;
|
virtual uint64_t EnumerateFollowingList(uint32_t unStartIndex) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class Friends2
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual const char *GetPersonaName() = 0;
|
||||||
|
virtual void SetPersonaName(const char *pchPersonaName) = 0;
|
||||||
|
virtual int GetPersonaState() = 0;
|
||||||
|
virtual void SetPersonaState(int ePersonaState) = 0;
|
||||||
|
// [...]
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,7 @@ namespace Steam
|
|||||||
void* Proxy::SteamUser = nullptr;
|
void* Proxy::SteamUser = nullptr;
|
||||||
|
|
||||||
Friends15* Proxy::SteamFriends = nullptr;
|
Friends15* Proxy::SteamFriends = nullptr;
|
||||||
|
Friends2* Proxy::SteamLegacyFriends = nullptr;
|
||||||
Utils* Proxy::SteamUtils = nullptr;
|
Utils* Proxy::SteamUtils = nullptr;
|
||||||
|
|
||||||
uint32_t Proxy::AppId = 0;
|
uint32_t Proxy::AppId = 0;
|
||||||
@ -82,7 +83,7 @@ namespace Steam
|
|||||||
Proxy::Callbacks.erase(callId);
|
Proxy::Callbacks.erase(callId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Proxy::RunCallback(int32_t callId, void* data)
|
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);
|
||||||
|
|
||||||
@ -91,6 +92,11 @@ 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()
|
||||||
@ -110,7 +116,7 @@ namespace Steam
|
|||||||
#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);
|
Proxy::RunCallback(message.m_iCallback, message.m_pubParam, message.m_cubParam);
|
||||||
Proxy::SteamFreeLastCallback(Proxy::SteamPipe);
|
Proxy::SteamFreeLastCallback(Proxy::SteamPipe);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -151,7 +157,7 @@ namespace Steam
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
Proxy::RunCallback(call.callId, buffer);
|
Proxy::RunCallback(call.callId, buffer, call.dataSize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -203,6 +209,9 @@ namespace Steam
|
|||||||
Proxy::SteamFriends = reinterpret_cast<Friends15*>(Proxy::SteamClient->GetISteamFriends(Proxy::SteamUser, Proxy::SteamPipe, "SteamFriends015"));
|
Proxy::SteamFriends = reinterpret_cast<Friends15*>(Proxy::SteamClient->GetISteamFriends(Proxy::SteamUser, Proxy::SteamPipe, "SteamFriends015"));
|
||||||
if (!Proxy::SteamFriends) return false;
|
if (!Proxy::SteamFriends) return false;
|
||||||
|
|
||||||
|
Proxy::SteamLegacyFriends = reinterpret_cast<Friends2*>(Proxy::SteamClient->GetISteamFriends(Proxy::SteamUser, Proxy::SteamPipe, "SteamFriends002"));
|
||||||
|
if (!Proxy::SteamLegacyFriends) return false;
|
||||||
|
|
||||||
Proxy::SteamUtils = reinterpret_cast<Utils*>(Proxy::SteamClient->GetISteamFriends(Proxy::SteamUser, Proxy::SteamPipe, "SteamUtils005"));
|
Proxy::SteamUtils = reinterpret_cast<Utils*>(Proxy::SteamClient->GetISteamFriends(Proxy::SteamUser, Proxy::SteamPipe, "SteamUtils005"));
|
||||||
if (!Proxy::SteamUtils) return false;
|
if (!Proxy::SteamUtils) return false;
|
||||||
|
|
||||||
|
@ -353,6 +353,7 @@ namespace Steam
|
|||||||
static void UnregisterCallback(int32_t callId);
|
static void UnregisterCallback(int32_t callId);
|
||||||
|
|
||||||
static Friends15* SteamFriends;
|
static Friends15* SteamFriends;
|
||||||
|
static Friends2* SteamLegacyFriends;
|
||||||
static Utils* SteamUtils;
|
static Utils* SteamUtils;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -396,7 +397,7 @@ namespace Steam
|
|||||||
static std::function<SteamFreeLastCallbackFn> SteamFreeLastCallback;
|
static std::function<SteamFreeLastCallbackFn> SteamFreeLastCallback;
|
||||||
static std::function<SteamGetAPICallResultFn> SteamGetAPICallResult;
|
static std::function<SteamGetAPICallResultFn> SteamGetAPICallResult;
|
||||||
|
|
||||||
static void RunCallback(int32_t callId, void* data);
|
static void RunCallback(int32_t callId, void* data, size_t size);
|
||||||
|
|
||||||
static void UnregisterCalls();
|
static void UnregisterCalls();
|
||||||
|
|
||||||
|
@ -4,14 +4,26 @@ namespace Utils
|
|||||||
{
|
{
|
||||||
namespace IPC
|
namespace IPC
|
||||||
{
|
{
|
||||||
Channel::Channel(std::string _name, int _queueSize, int _bufferSize, bool _remove) : name(_name), remove(_remove)
|
Channel::Channel(std::string _name, int _queueSize, int _bufferSize, bool _remove) : terminateQueue(false), remove(_remove), name(_name)
|
||||||
{
|
{
|
||||||
if(this->remove) boost::interprocess::message_queue::remove(this->name.data());
|
if(this->remove) boost::interprocess::message_queue::remove(this->name.data());
|
||||||
queue.reset(new boost::interprocess::message_queue(boost::interprocess::open_or_create, this->name.data(), _queueSize, _bufferSize + sizeof(Channel::Header)));
|
queue.reset(new boost::interprocess::message_queue(boost::interprocess::open_or_create, this->name.data(), _queueSize, _bufferSize + sizeof(Channel::Header)));
|
||||||
|
|
||||||
|
this->queueThread = std::thread(&Channel::queueWorker, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
Channel::~Channel()
|
Channel::~Channel()
|
||||||
{
|
{
|
||||||
|
std::unique_lock<std::mutex> lock(this->queueMutex);
|
||||||
|
this->terminateQueue = true;
|
||||||
|
this->queueEvent.notify_all();
|
||||||
|
lock.unlock();
|
||||||
|
|
||||||
|
if (this->queueThread.joinable())
|
||||||
|
{
|
||||||
|
this->queueThread.join();
|
||||||
|
}
|
||||||
|
|
||||||
if (this->remove) boost::interprocess::message_queue::remove(this->name.data());
|
if (this->remove) boost::interprocess::message_queue::remove(this->name.data());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,19 +96,47 @@ namespace Utils
|
|||||||
std::string buffer;
|
std::string buffer;
|
||||||
buffer.append(reinterpret_cast<char*>(&header), sizeof(Channel::Header));
|
buffer.append(reinterpret_cast<char*>(&header), sizeof(Channel::Header));
|
||||||
buffer.append(data.data() + sentSize, header.fragmentSize);
|
buffer.append(data.data() + sentSize, header.fragmentSize);
|
||||||
Channel::sendMessage(buffer);
|
Channel::enqueueMessage(buffer);
|
||||||
|
|
||||||
sentSize += header.fragmentSize;
|
sentSize += header.fragmentSize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Channel::sendMessage(std::string data)
|
void Channel::enqueueMessage(std::string data)
|
||||||
{
|
{
|
||||||
if (data.size() <= this->queue->get_max_msg_size())
|
if (data.size() <= this->queue->get_max_msg_size())
|
||||||
{
|
{
|
||||||
while (!this->queue->try_send(data.data(), data.size(), 0))
|
std::lock_guard<std::mutex> _(this->queueMutex);
|
||||||
|
this->internalQueue.push(data);
|
||||||
|
this->queueEvent.notify_all();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Channel::queueWorker()
|
||||||
|
{
|
||||||
|
while (!this->terminateQueue)
|
||||||
|
{
|
||||||
|
std::unique_lock<std::mutex> lock(this->queueMutex);
|
||||||
|
|
||||||
|
while(!this->terminateQueue && this->internalQueue.empty())
|
||||||
{
|
{
|
||||||
std::this_thread::sleep_for(100us);
|
this->queueEvent.wait(lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
while(!this->terminateQueue && !this->internalQueue.empty())
|
||||||
|
{
|
||||||
|
std::string data = this->internalQueue.front();
|
||||||
|
this->internalQueue.pop();
|
||||||
|
|
||||||
|
if (data.size() <= this->queue->get_max_msg_size())
|
||||||
|
{
|
||||||
|
while (!this->terminateQueue && !this->queue->try_send(data.data(), data.size(), 0))
|
||||||
|
{
|
||||||
|
lock.unlock();
|
||||||
|
std::this_thread::sleep_for(1000us);
|
||||||
|
lock.lock();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -45,7 +45,14 @@ namespace Utils
|
|||||||
unsigned int fragmentPart;
|
unsigned int fragmentPart;
|
||||||
};
|
};
|
||||||
|
|
||||||
void sendMessage(std::string data);
|
void enqueueMessage(std::string data);
|
||||||
|
void queueWorker();
|
||||||
|
|
||||||
|
bool terminateQueue;
|
||||||
|
std::condition_variable queueEvent;
|
||||||
|
std::mutex queueMutex;
|
||||||
|
std::thread queueThread;
|
||||||
|
std::queue<std::string> internalQueue;
|
||||||
|
|
||||||
bool remove;
|
bool remove;
|
||||||
std::unique_ptr<boost::interprocess::message_queue> queue;
|
std::unique_ptr<boost::interprocess::message_queue> queue;
|
||||||
|
183
src/Worker/Handlers/Friends.cpp
Normal file
183
src/Worker/Handlers/Friends.cpp
Normal file
@ -0,0 +1,183 @@
|
|||||||
|
#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);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(Steam::Proxy::SteamLegacyFriends)
|
||||||
|
{
|
||||||
|
Steam::Proxy::SteamLegacyFriends->SetPersonaState(this->personaState);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
30
src/Worker/Handlers/Friends.hpp
Normal file
30
src/Worker/Handlers/Friends.hpp
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
#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);
|
||||||
|
};
|
||||||
|
}
|
55
src/Worker/Handlers/SteamCallbacks.cpp
Normal file
55
src/Worker/Handlers/SteamCallbacks.cpp
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
#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()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
22
src/Worker/Handlers/SteamCallbacks.hpp
Normal file
22
src/Worker/Handlers/SteamCallbacks.hpp
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
#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);
|
||||||
|
};
|
||||||
|
}
|
@ -2,14 +2,16 @@
|
|||||||
|
|
||||||
namespace Worker
|
namespace Worker
|
||||||
{
|
{
|
||||||
|
Utils::IPC::BidirectionalChannel* Runner::Channel;
|
||||||
|
|
||||||
Runner::Runner(int pid) : processId(pid), terminate(false)
|
Runner::Runner(int pid) : processId(pid), terminate(false)
|
||||||
{
|
{
|
||||||
|
Runner::Channel = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
Runner::~Runner()
|
Runner::~Runner()
|
||||||
{
|
{
|
||||||
|
Runner::Channel = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Runner::run()
|
void Runner::run()
|
||||||
@ -37,10 +39,16 @@ namespace Worker
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Runner::attachHandler(Runner::Handler* handler)
|
||||||
|
{
|
||||||
|
this->handlers[handler->getCommand()] = std::shared_ptr<Runner::Handler>(handler);
|
||||||
|
}
|
||||||
|
|
||||||
void Runner::worker()
|
void Runner::worker()
|
||||||
{
|
{
|
||||||
printf("Worker started\n");
|
printf("Worker started\n");
|
||||||
Utils::IPC::BidirectionalChannel channel("IW4x-Worker-Channel", !Worker::IsWorker());
|
Utils::IPC::BidirectionalChannel channel("IW4x-Worker-Channel", !Worker::IsWorker());
|
||||||
|
Runner::Channel = &channel;
|
||||||
|
|
||||||
while (!this->terminate)
|
while (!this->terminate)
|
||||||
{
|
{
|
||||||
@ -49,13 +57,26 @@ namespace Worker
|
|||||||
std::string buffer;
|
std::string buffer;
|
||||||
if (channel.receive(&buffer))
|
if (channel.receive(&buffer))
|
||||||
{
|
{
|
||||||
printf("Data received: %s\n", buffer.data());
|
Proto::IPC::Command command;
|
||||||
channel.send("OK " + buffer);
|
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);
|
std::this_thread::sleep_for(1ms);
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("Terminating worker\n");
|
printf("Terminating worker\n");
|
||||||
|
Runner::Channel = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,18 +2,57 @@
|
|||||||
|
|
||||||
namespace Worker
|
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
|
class Runner
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
class Handler
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ~Handler() {};
|
||||||
|
virtual std::string getCommand() = 0;
|
||||||
|
virtual void handle(Endpoint endpoint, std::string data) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
Runner(int pid);
|
Runner(int pid);
|
||||||
~Runner();
|
~Runner();
|
||||||
|
|
||||||
void run();
|
void run();
|
||||||
|
|
||||||
|
void attachHandler(Runner::Handler* handler);
|
||||||
|
|
||||||
|
static Utils::IPC::BidirectionalChannel* Channel;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void worker();
|
void worker();
|
||||||
|
|
||||||
int processId;
|
int processId;
|
||||||
bool terminate;
|
bool terminate;
|
||||||
|
std::unordered_map<std::string, std::shared_ptr<Handler>> handlers;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#include "Handlers/Friends.hpp"
|
||||||
|
#include "Handlers/SteamCallbacks.hpp"
|
||||||
|
@ -7,6 +7,8 @@ namespace Worker
|
|||||||
int __stdcall EntryPoint(HINSTANCE /*hInstance*/, HINSTANCE /*hPrevInstance*/, char* /*lpCmdLine*/, int /*nCmdShow*/)
|
int __stdcall EntryPoint(HINSTANCE /*hInstance*/, HINSTANCE /*hPrevInstance*/, char* /*lpCmdLine*/, int /*nCmdShow*/)
|
||||||
{
|
{
|
||||||
Runner runner(Worker::ProcessId);
|
Runner runner(Worker::ProcessId);
|
||||||
|
runner.attachHandler(new Handlers::Friends());
|
||||||
|
runner.attachHandler(new Handlers::SteamCallbacks());
|
||||||
runner.run();
|
runner.run();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user