Merge remote-tracking branch 'origin/develop' into 191-dedicated-server-optimization

# Conflicts:
#	src/Components/Modules/News.cpp
This commit is contained in:
momo5502 2017-02-25 13:00:56 +01:00
commit 741d5788bd
16 changed files with 317 additions and 46 deletions

View File

@ -12,6 +12,11 @@ namespace Components
return Loader::Pregame; return Loader::Pregame;
} }
bool Loader::IsPostgame()
{
return Loader::Postgame;
}
void Loader::Initialize() void Loader::Initialize()
{ {
Loader::Pregame = true; Loader::Pregame = true;
@ -93,7 +98,7 @@ namespace Components
void Loader::Uninitialize() void Loader::Uninitialize()
{ {
Loader::PreDestroy(); Loader::PreDestroyNoPostGame();
std::reverse(Loader::Components.begin(), Loader::Components.end()); std::reverse(Loader::Components.begin(), Loader::Components.end());
for (auto component : Loader::Components) for (auto component : Loader::Components)
@ -119,14 +124,32 @@ namespace Components
{ {
Loader::Postgame = true; Loader::Postgame = true;
std::reverse(Loader::Components.begin(), Loader::Components.end()); auto components = Loader::Components;
for (auto component : Loader::Components)
std::reverse(components.begin(), components.end());
for (auto component : components)
{ {
component->preDestroy(); component->preDestroy();
} }
} }
} }
void Loader::PreDestroyNoPostGame()
{
if (!Loader::Postgame)
{
auto components = Loader::Components;
std::reverse(components.begin(), components.end());
for (auto component : components)
{
component->preDestroy();
}
Loader::Postgame = true;
}
}
bool Loader::PerformUnitTests() bool Loader::PerformUnitTests()
{ {
bool result = true; bool result = true;

View File

@ -25,11 +25,13 @@ namespace Components
static void Initialize(); static void Initialize();
static void Uninitialize(); static void Uninitialize();
static void PreDestroy(); static void PreDestroy();
static void PreDestroyNoPostGame();
static bool PerformUnitTests(); static bool PerformUnitTests();
static bool PerformingUnitTests(); static bool PerformingUnitTests();
static void Register(Component* component); static void Register(Component* component);
static bool IsPregame(); static bool IsPregame();
static bool IsPostgame();
static Utils::Memory::Allocator* GetAlloctor(); static Utils::Memory::Allocator* GetAlloctor();

View File

@ -66,8 +66,8 @@ namespace Components
} }
else else
{ {
//maxclientCount = Dvar::Var("sv_maxclients").get<int>(); maxclientCount = Dvar::Var("party_maxplayers").get<int>();
maxclientCount = Game::Party_GetMaxPlayers(*Game::partyIngame); //maxclientCount = Game::Party_GetMaxPlayers(*Game::partyIngame);
clientCount = Game::PartyHost_CountMembers(reinterpret_cast<Game::PartyData_s*>(0x1081C00)); clientCount = Game::PartyHost_CountMembers(reinterpret_cast<Game::PartyData_s*>(0x1081C00));
} }

View File

@ -195,8 +195,50 @@ namespace Components
Logger::MessageMutex.unlock(); Logger::MessageMutex.unlock();
} }
void Logger::RedirectOSPath(const char* file, char* folder)
{
if (Dvar::Var("g_log").get<std::string>() == file)
{
if (folder != "userraw"s)
{
if (Dvar::Var("g_log").get<bool>())
{
strcpy_s(folder, 256, "userraw");
}
}
}
}
__declspec(naked) void Logger::BuildOSPathStub()
{
__asm
{
pushad
push [esp + 28h]
push [esp + 30h]
call Logger::RedirectOSPath
add esp, 8h
popad
mov eax, [esp + 8h]
push ebp
push esi
mov esi, [esp + 0Ch]
push 64213Fh
retn
}
}
Logger::Logger() Logger::Logger()
{ {
Dvar::Register<bool>("iw4x_onelog", false, Game::dvar_flag::DVAR_FLAG_LATCHED | Game::dvar_flag::DVAR_FLAG_SAVED, "Only write the game log to the 'userraw' OS folder");
Utils::Hook(0x642139, Logger::BuildOSPathStub, HOOK_JUMP).install()->quick();
Logger::PipeOutput(nullptr); Logger::PipeOutput(nullptr);
QuickPatch::OnFrame(Logger::Frame); QuickPatch::OnFrame(Logger::Frame);

View File

@ -39,6 +39,9 @@ namespace Components
static void PrintMessagePipe(const char* data); static void PrintMessagePipe(const char* data);
static void EnqueueMessage(std::string message); static void EnqueueMessage(std::string message);
static void BuildOSPathStub();
static void RedirectOSPath(const char* file, char* folder);
static void NetworkLog(const char* data, bool gLog); static void NetworkLog(const char* data, bool gLog);
static std::string Format(const char** message); static std::string Format(const char** message);

View File

@ -169,9 +169,9 @@ namespace Components
return menu; return menu;
} }
std::vector<Game::menuDef_t*> Menus::LoadMenu(std::string menu) std::vector<std::pair<bool, Game::menuDef_t*>> Menus::LoadMenu(std::string menu)
{ {
std::vector<Game::menuDef_t*> menus; std::vector<std::pair<bool, Game::menuDef_t*>> menus;
FileSystem::File menuFile(menu); FileSystem::File menuFile(menu);
if (menuFile.exists()) if (menuFile.exists())
@ -200,7 +200,7 @@ namespace Components
if (!_stricmp(token.string, "menudef")) if (!_stricmp(token.string, "menudef"))
{ {
Game::menuDef_t* menudef = Menus::ParseMenu(handle); Game::menuDef_t* menudef = Menus::ParseMenu(handle);
if (menudef) menus.push_back(menudef); if (menudef) menus.push_back({ true, menudef }); // Custom menu
} }
} }
@ -211,9 +211,9 @@ namespace Components
return menus; return menus;
} }
std::vector<Game::menuDef_t*> Menus::LoadMenu(Game::menuDef_t* menudef) std::vector<std::pair<bool, Game::menuDef_t*>> Menus::LoadMenu(Game::menuDef_t* menudef)
{ {
std::vector<Game::menuDef_t*> menus = Menus::LoadMenu(Utils::String::VA("ui_mp\\%s.menu", menudef->window.name)); std::vector<std::pair<bool, Game::menuDef_t*>> menus = Menus::LoadMenu(Utils::String::VA("ui_mp\\%s.menu", menudef->window.name));
if (menus.empty()) if (menus.empty())
{ {
@ -222,11 +222,11 @@ namespace Components
// //
// if (originalMenu) // if (originalMenu)
// { // {
// menus.push_back(originalMenu); // menus.push_back({ false, originalMenu });
// } // }
// else // else
// { // {
menus.push_back(menudef); menus.push_back({ false, menudef }); // Native menu
// } // }
} }
@ -235,7 +235,7 @@ namespace Components
Game::MenuList* Menus::LoadScriptMenu(const char* menu) Game::MenuList* Menus::LoadScriptMenu(const char* menu)
{ {
std::vector<Game::menuDef_t*> menus = Menus::LoadMenu(menu); std::vector<std::pair<bool, Game::menuDef_t*>> menus = Menus::LoadMenu(menu);
if (menus.empty()) return nullptr; if (menus.empty()) return nullptr;
// Allocate new menu list // Allocate new menu list
@ -253,7 +253,10 @@ namespace Components
newList->menuCount = menus.size(); newList->menuCount = menus.size();
// Copy new menus // Copy new menus
std::memcpy(newList->menus, menus.data(), menus.size() * sizeof(Game::menuDef_t *)); for(unsigned int i = 0; i < menus.size(); ++i)
{
newList->menus[i] = menus[i].second;
}
Menus::RemoveMenuList(newList->name); Menus::RemoveMenuList(newList->name);
Menus::MenuListList[newList->name] = newList; Menus::MenuListList[newList->name] = newList;
@ -261,14 +264,60 @@ namespace Components
return newList; return newList;
} }
void Menus::SafeMergeMenus(std::vector<std::pair<bool, Game::menuDef_t*>>* menus, std::vector<std::pair<bool, Game::menuDef_t*>> newMenus)
{
// Check if we overwrote a menu
for (unsigned int i = 0; i < menus->size(); ++i)
{
// Try to find the native menu
bool found = !menus->at(i).first; // Only if custom menu, try to find it
// If there is none, try to find a custom menu
if (!found)
{
for (auto& entry : Menus::MenuList)
{
if (menus->at(i).second == entry.second)
{
found = true;
break;
}
}
}
// Remove the menu if it has been deallocated (not found)
if (!found)
{
menus->erase(menus->begin() + i);
--i;
continue;
}
// Remove the menu if it has been loaded twice
for (auto& newMenu : newMenus)
{
if (menus->at(i).second->window.name == std::string(newMenu.second->window.name))
{
Menus::RemoveMenu(menus->at(i).second);
menus->erase(menus->begin() + i);
--i;
break;
}
}
}
Utils::Merge(menus, newMenus);
}
Game::MenuList* Menus::LoadMenuList(Game::MenuList* menuList) Game::MenuList* Menus::LoadMenuList(Game::MenuList* menuList)
{ {
std::vector<Game::menuDef_t*> menus; std::vector<std::pair<bool, Game::menuDef_t*>> menus;
for (int i = 0; i < menuList->menuCount; ++i) for (int i = 0; i < menuList->menuCount; ++i)
{ {
if (!menuList->menus[i]) continue; if (!menuList->menus[i]) continue;
Utils::Merge(&menus, Menus::LoadMenu(menuList->menus[i])); Menus::SafeMergeMenus(&menus, Menus::LoadMenu(menuList->menus[i]));
} }
// Load custom menus // Load custom menus
@ -279,14 +328,14 @@ namespace Components
bool hasMenu = false; bool hasMenu = false;
for(auto &loadedMenu : menus) for(auto &loadedMenu : menus)
{ {
if(loadedMenu->window.name == menu) if(loadedMenu.second->window.name == menu)
{ {
hasMenu = true; hasMenu = true;
break; break;
} }
} }
if(!hasMenu) Utils::Merge(&menus, Menus::LoadMenu(menu)); if (!hasMenu) Menus::SafeMergeMenus(&menus, Menus::LoadMenu(menu));
} }
} }
@ -306,7 +355,10 @@ namespace Components
newList->menuCount = size; newList->menuCount = size;
// Copy new menus // Copy new menus
std::memcpy(newList->menus, menus.data(), size * sizeof(Game::menuDef_t *)); for (unsigned int i = 0; i < menus.size(); ++i)
{
newList->menus[i] = menus[i].second;
}
Menus::RemoveMenuList(newList->name); Menus::RemoveMenuList(newList->name);
Menus::MenuListList[newList->name] = newList; Menus::MenuListList[newList->name] = newList;

View File

@ -29,8 +29,9 @@ namespace Components
static Game::MenuList* LoadMenuList(Game::MenuList* menuList); static Game::MenuList* LoadMenuList(Game::MenuList* menuList);
static Game::MenuList* LoadScriptMenu(const char* menu); static Game::MenuList* LoadScriptMenu(const char* menu);
static std::vector<Game::menuDef_t*> LoadMenu(Game::menuDef_t* menudef); static std::vector<std::pair<bool, Game::menuDef_t*>> LoadMenu(Game::menuDef_t* menudef);
static std::vector<Game::menuDef_t*> LoadMenu(std::string file); static std::vector<std::pair<bool, Game::menuDef_t*>> LoadMenu(std::string file);
static void SafeMergeMenus(std::vector<std::pair<bool, Game::menuDef_t*>>* menus, std::vector<std::pair<bool, Game::menuDef_t*>> newMenus);
static Game::script_t* LoadMenuScript(std::string name, std::string buffer); static Game::script_t* LoadMenuScript(std::string name, std::string buffer);
static int LoadMenuSource(std::string name, std::string buffer); static int LoadMenuSource(std::string name, std::string buffer);

View File

@ -7,6 +7,8 @@ namespace Components
bool News::Terminate; bool News::Terminate;
std::thread News::Thread; std::thread News::Thread;
std::string News::UpdaterArgs; std::string News::UpdaterArgs;
std::string News::UpdaterHash;
int News::UpdaterRefresh;
bool News::unitTest() bool News::unitTest()
{ {
@ -50,6 +52,56 @@ namespace Components
TerminateProcess(GetCurrentProcess(), exitCode); TerminateProcess(GetCurrentProcess(), exitCode);
} }
bool News::GetLatestUpdater()
{
if (Utils::IO::FileExists("updater.exe"))
{
// Generate hash of local updater.exe
std::string localUpdater = Utils::IO::ReadFile("updater.exe");
localUpdater = Utils::Cryptography::SHA1::Compute(localUpdater, true);
if (News::UpdaterHash.empty() || (News::UpdaterRefresh - Game::Sys_Milliseconds() > 900000)) // Check for updater Update every 15 mins max
{
News::UpdaterRefresh = Game::Sys_Milliseconds();
std::string data = Utils::Cache::GetFile("/json/updater"); // {"updater.exe":{"SHA1":"*HASH*"}}
std::string error;
json11::Json listData = json11::Json::parse(data, error);
if (error.empty() || listData.is_object())
{
News::UpdaterHash = listData["updater.exe"]["SHA1"].string_value();
}
}
if (!News::UpdaterHash.empty() && localUpdater != News::UpdaterHash)
{
remove("updater.exe");
}
}
if (!Utils::IO::FileExists("updater.exe"))
{
return News::DownloadUpdater();
}
return true;
}
bool News::DownloadUpdater()
{
std::string data = Utils::Cache::GetFile("/iw4/updater.exe");
if (!data.empty())
{
Utils::IO::WriteFile("updater.exe", data);
return true;
}
return false;
}
const char* News::GetNewsText() const char* News::GetNewsText()
{ {
return Localization::Get("MPUI_MOTD_TEXT"); return Localization::Get("MPUI_MOTD_TEXT");
@ -95,21 +147,18 @@ namespace Components
std::thread([]() std::thread([]()
{ {
std::string data = Utils::Cache::GetFile("/iw4/updater.exe"); if (News::GetLatestUpdater())
{
if (data.empty()) Console::SetSkipShutdown();
Command::Execute("wait 300; quit;", false);
}
else
{ {
Localization::ClearTemp(); Localization::ClearTemp();
News::UpdaterArgs.clear(); News::UpdaterArgs.clear();
Command::Execute("closemenu popup_reconnectingtoparty", false); Command::Execute("closemenu popup_reconnectingtoparty", false);
Game::ShowMessageBox("Failed to download the updater!", "Error"); Game::ShowMessageBox("Failed to download the updater!", "Error");
} }
else
{
Console::SetSkipShutdown();
Utils::IO::WriteFile("updater.exe", data);
Command::Execute("wait 300; quit;", false);
}
}).detach(); }).detach();
} }
@ -121,7 +170,8 @@ namespace Components
News::News() News::News()
{ {
News::UpdaterArgs.clear(); News::UpdaterArgs.clear();
News::UpdaterHash.clear();
News::UpdaterRefresh = 0;
if (ZoneBuilder::IsEnabled() || Dedicated::IsEnabled()) return; // Maybe also dedi? if (ZoneBuilder::IsEnabled() || Dedicated::IsEnabled()) return; // Maybe also dedi?
Dvar::Register<bool>("g_firstLaunch", true, Game::DVAR_FLAG_SAVED, ""); Dvar::Register<bool>("g_firstLaunch", true, Game::DVAR_FLAG_SAVED, "");
@ -152,10 +202,7 @@ namespace Components
Localization::Set("MPUI_CHANGELOG_TEXT", "Loading..."); Localization::Set("MPUI_CHANGELOG_TEXT", "Loading...");
Localization::Set("MPUI_MOTD_TEXT", NEWS_MOTD_DEFAULT); Localization::Set("MPUI_MOTD_TEXT", NEWS_MOTD_DEFAULT);
if (Utils::IO::FileExists("updater.exe")) //News::GetLatestUpdater();
{
remove("updater.exe");
}
// make newsfeed (ticker) menu items not cut off based on safe area // make newsfeed (ticker) menu items not cut off based on safe area
Utils::Hook::Nop(0x63892D, 5); Utils::Hook::Nop(0x63892D, 5);
@ -209,6 +256,7 @@ namespace Components
News::~News() News::~News()
{ {
News::UpdaterArgs.clear(); News::UpdaterArgs.clear();
News::UpdaterHash.clear();
} }
void News::preDestroy() void News::preDestroy()

View File

@ -20,8 +20,13 @@ namespace Components
private: private:
static std::string UpdaterArgs; static std::string UpdaterArgs;
static std::string UpdaterHash;
static int UpdaterRefresh;
static std::thread Thread; static std::thread Thread;
static bool Terminate; static bool Terminate;
static bool GetLatestUpdater();
static bool DownloadUpdater();
static void CheckForUpdate(); static void CheckForUpdate();
static void ExitProcessStub(unsigned int exitCode); static void ExitProcessStub(unsigned int exitCode);

View File

@ -302,8 +302,8 @@ namespace Components
} }
else else
{ {
//maxclientCount = Dvar::Var("sv_maxclients").get<int>(); maxclientCount = Dvar::Var("party_maxplayers").get<int>();
maxclientCount = Game::Party_GetMaxPlayers(*Game::partyIngame); //maxclientCount = Game::Party_GetMaxPlayers(*Game::partyIngame);
clientCount = Game::PartyHost_CountMembers(reinterpret_cast<Game::PartyData_s*>(0x1081C00)); clientCount = Game::PartyHost_CountMembers(reinterpret_cast<Game::PartyData_s*>(0x1081C00));
} }

View File

@ -116,8 +116,8 @@ namespace Components
if (!maxclientCount) if (!maxclientCount)
{ {
//maxclientCount = Dvar::Var("sv_maxclients").get<int>(); maxclientCount = Dvar::Var("party_maxplayers").get<int>();
maxclientCount = Game::Party_GetMaxPlayers(*Game::partyIngame); //maxclientCount = Game::Party_GetMaxPlayers(*Game::partyIngame);
} }
Utils::InfoString info(Game::Dvar_InfoString_Big(1024)); Utils::InfoString info(Game::Dvar_InfoString_Big(1024));

View File

@ -146,6 +146,8 @@ namespace Components
Toast::Toast() Toast::Toast()
{ {
if (Dedicated::IsEnabled()) return;
Toast::ToastHandler = new WinToastLib::WinToastHandler; Toast::ToastHandler = new WinToastLib::WinToastHandler;
WinToastLib::WinToast::instance()->setAppName(L"IW4x"); WinToastLib::WinToast::instance()->setAppName(L"IW4x");
@ -170,13 +172,28 @@ namespace Components
void Toast::preDestroy() void Toast::preDestroy()
{ {
// Destroying that on the main thread deadlocks, for whatever reason. if (Dedicated::IsEnabled()) return;
// Destroying that on the main thread deadlocks.
// I did not write the library, so whatever. // I did not write the library, so whatever.
std::thread([]() // If we are not in the postgame state,
// we are not allowed to spawn threads,
// so just don't uninitialize the library.
// That means we did not uninitialize the game
// correctly anyways.
if (Loader::IsPostgame())
{
std::thread([]()
{
delete WinToastLib::WinToast::instance();
delete Toast::ToastHandler;
Toast::ToastHandler = nullptr;
}).join();
}
else
{ {
delete WinToastLib::WinToast::instance();
delete Toast::ToastHandler; delete Toast::ToastHandler;
Toast::ToastHandler = nullptr; Toast::ToastHandler = nullptr;
}).join(); }
} }
} }

View File

@ -1,6 +1,6 @@
#pragma once #pragma once
#define PROTOCOL 0x93 #define PROTOCOL 0x94
#define NUM_CUSTOM_CLASSES 15 #define NUM_CUSTOM_CLASSES 15
// This allows us to compile our structures in IDA, for easier reversing :3 // This allows us to compile our structures in IDA, for easier reversing :3

View File

@ -18,6 +18,10 @@ namespace Steam
Utils* Proxy::SteamUtils = nullptr; Utils* Proxy::SteamUtils = nullptr;
User* Proxy::SteamUser_ = nullptr; User* Proxy::SteamUser_ = nullptr;
HANDLE Proxy::Process = nullptr;
HANDLE Proxy::CancelHandle = nullptr;
std::thread Proxy::WatchGuard;
uint32_t Proxy::AppId = 0; uint32_t Proxy::AppId = 0;
std::recursive_mutex Proxy::CallMutex; std::recursive_mutex Proxy::CallMutex;
@ -325,6 +329,41 @@ namespace Steam
Proxy::UnregisterCalls(); Proxy::UnregisterCalls();
} }
void Proxy::LaunchWatchGuard()
{
if (Proxy::WatchGuard.joinable()) return;
HKEY hRegKey;
DWORD pid = 0;
if (RegOpenKeyExA(HKEY_CURRENT_USER, STEAM_REGISTRY_PROCESS_PATH, 0, KEY_QUERY_VALUE, &hRegKey) != ERROR_SUCCESS) return;
DWORD dwLength = sizeof(pid);
RegQueryValueExA(hRegKey, "pid", nullptr, nullptr, reinterpret_cast<BYTE*>(&pid), &dwLength);
RegCloseKey(hRegKey);
Proxy::CancelHandle = CreateEventA(nullptr, TRUE, FALSE, "CancelEvent");
if (!Proxy::CancelHandle) return;
Proxy::Process = OpenProcess(SYNCHRONIZE, FALSE, pid);
if (!Proxy::Process) return;
Proxy::WatchGuard = std::thread([]()
{
HANDLE handles[] = { Proxy::Process, Proxy::CancelHandle };
DWORD result = WaitForMultipleObjects(ARRAYSIZE(handles), handles, FALSE, INFINITE);
CloseHandle(Proxy::Process);
CloseHandle(Proxy::CancelHandle);
if (result == WAIT_OBJECT_0)
{
Proxy::SteamPipe = nullptr;
Proxy::SteamUser = nullptr;
Proxy::Uninititalize();
}
});
}
void Proxy::StartSteamIfNecessary() void Proxy::StartSteamIfNecessary()
{ {
if (Proxy::GetSteamDirectory().empty() || !Steam::Enabled()) return; if (Proxy::GetSteamDirectory().empty() || !Steam::Enabled()) return;
@ -348,6 +387,11 @@ namespace Steam
CloseHandle(hProcess); CloseHandle(hProcess);
}); });
allocator.reference(allocator.allocate(1), [](void*)
{
Proxy::LaunchWatchGuard();
});
DWORD exitCode; DWORD exitCode;
if (!GetExitCodeProcess(process, &exitCode)) return; if (!GetExitCodeProcess(process, &exitCode)) return;
if (exitCode == STILL_ACTIVE) return; if (exitCode == STILL_ACTIVE) return;
@ -375,6 +419,8 @@ namespace Steam
while (!interval.elapsed(15s) && !Proxy::GetActiveUser()) std::this_thread::sleep_for(10ms); while (!interval.elapsed(15s) && !Proxy::GetActiveUser()) std::this_thread::sleep_for(10ms);
std::this_thread::sleep_for(1s); std::this_thread::sleep_for(1s);
} }
Proxy::LaunchWatchGuard();
} }
bool Proxy::Inititalize() bool Proxy::Inititalize()
@ -442,6 +488,30 @@ namespace Steam
void Proxy::Uninititalize() void Proxy::Uninititalize()
{ {
if(Proxy::WatchGuard.get_id() != std::this_thread::get_id() && Proxy::WatchGuard.joinable())
{
if (Proxy::CancelHandle)
{
SetEvent(Proxy::CancelHandle);
Proxy::WatchGuard.join();
}
else
{
Proxy::WatchGuard.detach();
}
}
Proxy::Process = nullptr;
Proxy::CancelHandle = nullptr;
Proxy::ClientEngine = nullptr;
Proxy::ClientUser = nullptr;
Proxy::ClientFriends = nullptr;
Proxy::SteamApps = nullptr;
Proxy::SteamFriends = nullptr;
Proxy::SteamUtils = nullptr;
Proxy::SteamUser_ = nullptr;
if (Proxy::SteamClient && Proxy::SteamPipe) if (Proxy::SteamClient && Proxy::SteamPipe)
{ {
if (Proxy::SteamUser) if (Proxy::SteamUser)
@ -452,6 +522,9 @@ namespace Steam
Proxy::SteamClient->ReleaseSteamPipe(Proxy::SteamPipe); Proxy::SteamClient->ReleaseSteamPipe(Proxy::SteamPipe);
} }
Proxy::SteamPipe = nullptr;
Proxy::SteamUser = nullptr;
Proxy::SteamClient = nullptr;
Proxy::Client = ::Utils::Library(); Proxy::Client = ::Utils::Library();
Proxy::Overlay = ::Utils::Library(); Proxy::Overlay = ::Utils::Library();
} }

View File

@ -302,6 +302,10 @@ namespace Steam
static void* SteamPipe; static void* SteamPipe;
static void* SteamUser; static void* SteamUser;
static HANDLE Process;
static HANDLE CancelHandle;
static std::thread WatchGuard;
static std::recursive_mutex CallMutex; static std::recursive_mutex CallMutex;
static std::vector<CallContainer> Calls; static std::vector<CallContainer> Calls;
static std::unordered_map<int32_t, void*> Callbacks; static std::unordered_map<int32_t, void*> Callbacks;
@ -314,6 +318,7 @@ namespace Steam
static void UnregisterCalls(); static void UnregisterCalls();
static void StartSteamIfNecessary(); static void StartSteamIfNecessary();
static void LaunchWatchGuard();
static void ResetActiveUser(); static void ResetActiveUser();
static uint32_t GetActiveUser(); static uint32_t GetActiveUser();

View File

@ -9,7 +9,7 @@ namespace Utils
bool IsWineEnvironment(); bool IsWineEnvironment();
template <typename T> void Merge(std::vector<T>* target, T* source, size_t length) template <typename T> inline void Merge(std::vector<T>* target, T* source, size_t length)
{ {
if (source) if (source)
{ {
@ -20,7 +20,7 @@ namespace Utils
} }
} }
template <typename T> void Merge(std::vector<T>* target, std::vector<T> source) template <typename T> inline void Merge(std::vector<T>* target, std::vector<T> source)
{ {
for (auto &entry : source) for (auto &entry : source)
{ {