Parse playlists file directly after loading it

No longer need a thread that loops and waits until its loaded into memory before parsing it.
This commit is contained in:
Kawe Mazidjatari 2022-05-28 17:07:30 +02:00
parent 79d602c274
commit e5e0d528f0
4 changed files with 47 additions and 41 deletions

View File

@ -194,7 +194,6 @@ FORCEINLINE void CHostState::Setup(void)
NET_GenerateKey(); NET_GenerateKey();
} }
ResetLevelName(); ResetLevelName();
KeyValues::Setup();
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------

View File

@ -310,10 +310,10 @@ void CBrowser::LaunchServer(void)
DevMsg(eDLL_T::ENGINE, "Starting server with name: \"%s\" map: \"%s\" playlist: \"%s\"\n", m_Server.svServerName.c_str(), m_Server.svMapName.c_str(), m_Server.svPlaylist.c_str()); DevMsg(eDLL_T::ENGINE, "Starting server with name: \"%s\" map: \"%s\" playlist: \"%s\"\n", m_Server.svServerName.c_str(), m_Server.svMapName.c_str(), m_Server.svPlaylist.c_str());
/* /*
* Playlist gets parsed in two instances, first in LoadPlaylist all the neccessary values. * Playlist gets parsed in two instances, first in KeyValues::ParsePlaylists with all the neccessary values.
* Then when you would normally call launchplaylist which calls StartPlaylist it would cmd call mp_gamemode which parses the gamemode specific part of the playlist.. * Then when you would normally call launchplaylist which calls StartPlaylist it would cmd call mp_gamemode which parses the gamemode specific part of the playlist..
*/ */
KeyValues_LoadPlaylist(m_Server.svPlaylist.c_str()); KeyValues_ParsePlaylists(m_Server.svPlaylist.c_str());
stringstream ssModeCommand; stringstream ssModeCommand;
ssModeCommand << "mp_gamemode " << m_Server.svPlaylist; ssModeCommand << "mp_gamemode " << m_Server.svPlaylist;
ProcessCommand(ssModeCommand.str().c_str()); ProcessCommand(ssModeCommand.str().c_str());

View File

@ -1214,37 +1214,22 @@ KeyValues* KeyValues::MakeCopy(void) const
return pNewKeyValue; return pNewKeyValue;
} }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void KeyValues::Setup(void)
{
std::thread t1(KeyValues::InitPlaylists); // Start thread to grab playlists.
t1.detach(); // Detach thread from current one.
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Purpose: Initializes the playlist // Purpose: Initializes the playlist
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void KeyValues::InitPlaylists(void) void KeyValues::InitPlaylists(void)
{ {
while (true) if (*g_pPlaylistKeyValues)
{ {
if (*g_pPlaylistKeyValues) KeyValues* pPlaylists = (*g_pPlaylistKeyValues)->FindKey("Playlists", false);
if (pPlaylists)
{ {
KeyValues* pPlaylists = (*g_pPlaylistKeyValues)->FindKey("Playlists", false); g_vAllPlaylists.clear();
if (pPlaylists) for (KeyValues* pSubKey = pPlaylists->GetFirstTrueSubKey(); pSubKey != nullptr; pSubKey = pSubKey->GetNextTrueSubKey())
{ {
g_vAllPlaylists.clear(); g_vAllPlaylists.push_back(pSubKey->GetName()); // Get all playlists.
for (KeyValues* pSubKey = pPlaylists->GetFirstTrueSubKey(); pSubKey != nullptr; pSubKey = pSubKey->GetNextTrueSubKey())
{
g_vAllPlaylists.push_back(pSubKey->GetName()); // Get all playlists.
}
break; // Break if playlist got filled.
} }
std::this_thread::sleep_for(std::chrono::milliseconds(50));
} }
std::this_thread::sleep_for(std::chrono::milliseconds(50));
} }
} }
@ -1277,10 +1262,24 @@ void KeyValues::InitFileSystem(void)
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Purpose: loads the playlist // Purpose: loads the playlists
// Input : *szPlaylist - // Input : *szPlaylist -
// Output : true on success, false on failure
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
bool KeyValues::LoadPlaylist(const char* szPlaylist) bool KeyValues::LoadPlaylists(const char* pszPlaylist)
{
bool bResults = KeyValues_LoadPlaylists(pszPlaylist);
KeyValues::InitPlaylists();
return bResults;
}
//-----------------------------------------------------------------------------
// Purpose: parses the playlists
// Input : *szPlaylist -
// Output : true on success, false on failure
//-----------------------------------------------------------------------------
bool KeyValues::ParsePlaylists(const char* pszPlaylist)
{ {
memset(g_pMapVPKCache, '\0', 0x40); // Clear VPK cache to prevent crash while loading playlist. memset(g_pMapVPKCache, '\0', 0x40); // Clear VPK cache to prevent crash while loading playlist.
@ -1294,7 +1293,7 @@ bool KeyValues::LoadPlaylist(const char* szPlaylist)
if (FileExists(sPlaylistPath)) if (FileExists(sPlaylistPath))
{ {
std::uint8_t verifyPlaylistIntegrity[] = // Very hacky way for alternative inline assembly for x64.. uint8_t verifyPlaylistIntegrity[] = // Very hacky way for alternative inline assembly for x64..
{ {
0x48, 0x8B, 0x45, 0x58, // mov rcx, playlist 0x48, 0x8B, 0x45, 0x58, // mov rcx, playlist
0xC7, 0x00, 0x00, 0x00, 0x00, // test playlist, playlist 0xC7, 0x00, 0x00, 0x00, 0x00, // test playlist, playlist
@ -1302,11 +1301,11 @@ bool KeyValues::LoadPlaylist(const char* szPlaylist)
}; };
void* verifyPlaylistIntegrityFn = nullptr; void* verifyPlaylistIntegrityFn = nullptr;
VirtualAlloc(verifyPlaylistIntegrity, 10, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); VirtualAlloc(verifyPlaylistIntegrity, 10, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
memcpy(&verifyPlaylistIntegrityFn, (const void*)verifyPlaylistIntegrity, 9); memcpy(&verifyPlaylistIntegrityFn, reinterpret_cast<const void*>(verifyPlaylistIntegrity), 9);
reinterpret_cast<void(*)()>(verifyPlaylistIntegrityFn)(); reinterpret_cast<void(*)()>(verifyPlaylistIntegrityFn)();
} }
return KeyValues_LoadPlaylist(szPlaylist); // Parse playlist. return KeyValues_ParsePlaylists(pszPlaylist); // Parse playlist.
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -1317,10 +1316,10 @@ bool KeyValues::LoadPlaylist(const char* szPlaylist)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
KeyValues* KeyValues::ReadKeyValuesFile(CFileSystem_Stdio* pFileSystem, const char* pFileName) KeyValues* KeyValues::ReadKeyValuesFile(CFileSystem_Stdio* pFileSystem, const char* pFileName)
{ {
static bool bInit{}; static bool bInitFileSystem{};
if (!bInit) if (!bInitFileSystem)
{ {
bInit = true; bInitFileSystem = true;
KeyValues::InitFileSystem(); KeyValues::InitFileSystem();
} }
return KeyValues_ReadKeyValuesFile(pFileSystem, pFileName); return KeyValues_ReadKeyValuesFile(pFileSystem, pFileName);
@ -1329,13 +1328,15 @@ KeyValues* KeyValues::ReadKeyValuesFile(CFileSystem_Stdio* pFileSystem, const ch
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
void CKeyValueSystem_Attach() void CKeyValueSystem_Attach()
{ {
DetourAttach((LPVOID*)&KeyValues_LoadPlaylist, &KeyValues::LoadPlaylist); DetourAttach((LPVOID*)&KeyValues_LoadPlaylists, &KeyValues::LoadPlaylists);
DetourAttach((LPVOID*)&KeyValues_ParsePlaylists, &KeyValues::ParsePlaylists);
DetourAttach((LPVOID*)&KeyValues_ReadKeyValuesFile, &KeyValues::ReadKeyValuesFile); DetourAttach((LPVOID*)&KeyValues_ReadKeyValuesFile, &KeyValues::ReadKeyValuesFile);
} }
void CKeyValueSystem_Detach() void CKeyValueSystem_Detach()
{ {
DetourDetach((LPVOID*)&KeyValues_LoadPlaylist, &KeyValues::LoadPlaylist); DetourDetach((LPVOID*)&KeyValues_LoadPlaylists, &KeyValues::LoadPlaylists);
DetourDetach((LPVOID*)&KeyValues_ParsePlaylists, &KeyValues::ParsePlaylists);
DetourDetach((LPVOID*)&KeyValues_ReadKeyValuesFile, &KeyValues::ReadKeyValuesFile); DetourDetach((LPVOID*)&KeyValues_ReadKeyValuesFile, &KeyValues::ReadKeyValuesFile);
} }

View File

@ -20,8 +20,11 @@ inline auto KeyValues_Init = p_KeyValues_Init.RCast<void* (*)(KeyValues* thisptr
inline CMemory p_KeyValues_FindKey; inline CMemory p_KeyValues_FindKey;
inline auto KeyValues_FindKey = p_KeyValues_FindKey.RCast<void* (*)(KeyValues* thisptr, const char* pkeyName, bool bCreate)>(); inline auto KeyValues_FindKey = p_KeyValues_FindKey.RCast<void* (*)(KeyValues* thisptr, const char* pkeyName, bool bCreate)>();
inline CMemory p_KeyValues_LoadPlaylist; inline CMemory p_KeyValues_LoadPlaylists;
inline auto KeyValues_LoadPlaylist = p_KeyValues_LoadPlaylist.RCast<bool (*)(const char* pszPlaylist)>(); inline auto KeyValues_LoadPlaylists = p_KeyValues_LoadPlaylists.RCast<bool (*)(const char* pszPlaylist)>();
inline CMemory p_KeyValues_ParsePlaylists;
inline auto KeyValues_ParsePlaylists = p_KeyValues_ParsePlaylists.RCast<bool (*)(const char* pszPlaylist)>();
inline CMemory p_KeyValues_GetCurrentPlaylist; inline CMemory p_KeyValues_GetCurrentPlaylist;
inline auto KeyValues_GetCurrentPlaylist = p_KeyValues_GetCurrentPlaylist.RCast<const char* (*)(void)>(); inline auto KeyValues_GetCurrentPlaylist = p_KeyValues_GetCurrentPlaylist.RCast<const char* (*)(void)>();
@ -137,10 +140,10 @@ public:
KeyValues* MakeCopy(void) const; KeyValues* MakeCopy(void) const;
// Initialization // Initialization
static void Setup(void);
static void InitPlaylists(void); static void InitPlaylists(void);
static void InitFileSystem(void); static void InitFileSystem(void);
static bool LoadPlaylist(const char* szPlaylist); static bool LoadPlaylists(const char* szPlaylist);
static bool ParsePlaylists(const char* szPlaylist);
static KeyValues* ReadKeyValuesFile(CFileSystem_Stdio* pFileSystem, const char* pFileName); static KeyValues* ReadKeyValuesFile(CFileSystem_Stdio* pFileSystem, const char* pFileName);
public: public:
@ -178,7 +181,8 @@ class VKeyValues : public IDetour
{ {
spdlog::debug("| FUN: KeyValues::Init : {:#18x} |\n", p_KeyValues_Init.GetPtr()); spdlog::debug("| FUN: KeyValues::Init : {:#18x} |\n", p_KeyValues_Init.GetPtr());
spdlog::debug("| FUN: KeyValues::FindKey : {:#18x} |\n", p_KeyValues_FindKey.GetPtr()); spdlog::debug("| FUN: KeyValues::FindKey : {:#18x} |\n", p_KeyValues_FindKey.GetPtr());
spdlog::debug("| FUN: KeyValues::LoadPlaylist : {:#18x} |\n", p_KeyValues_LoadPlaylist.GetPtr()); spdlog::debug("| FUN: KeyValues::LoadPlaylists : {:#18x} |\n", p_KeyValues_LoadPlaylists.GetPtr());
spdlog::debug("| FUN: KeyValues::ParsePlaylists : {:#18x} |\n", p_KeyValues_ParsePlaylists.GetPtr());
spdlog::debug("| FUN: KeyValues::GetCurrentPlaylist : {:#18x} |\n", p_KeyValues_GetCurrentPlaylist.GetPtr()); spdlog::debug("| FUN: KeyValues::GetCurrentPlaylist : {:#18x} |\n", p_KeyValues_GetCurrentPlaylist.GetPtr());
spdlog::debug("| FUN: KeyValues::ReadKeyValuesFile : {:#18x} |\n", p_KeyValues_ReadKeyValuesFile.GetPtr()); spdlog::debug("| FUN: KeyValues::ReadKeyValuesFile : {:#18x} |\n", p_KeyValues_ReadKeyValuesFile.GetPtr());
spdlog::debug("| VAR: g_pPlaylistKeyValues : {:#18x} |\n", reinterpret_cast<uintptr_t>(g_pPlaylistKeyValues)); spdlog::debug("| VAR: g_pPlaylistKeyValues : {:#18x} |\n", reinterpret_cast<uintptr_t>(g_pPlaylistKeyValues));
@ -197,11 +201,13 @@ class VKeyValues : public IDetour
p_KeyValues_GetCurrentPlaylist = g_mGameDll.FindPatternSIMD(reinterpret_cast<rsig_t>("\x48\x8B\x05\x00\x00\x00\x00\x48\x85\xC0\x75\x08\x48\x8D\x05\x00\x00\x00\x00\xC3\x0F\xB7\x50\x2A"), "xxx????xxxxxxxx????xxxxx"); p_KeyValues_GetCurrentPlaylist = g_mGameDll.FindPatternSIMD(reinterpret_cast<rsig_t>("\x48\x8B\x05\x00\x00\x00\x00\x48\x85\xC0\x75\x08\x48\x8D\x05\x00\x00\x00\x00\xC3\x0F\xB7\x50\x2A"), "xxx????xxxxxxxx????xxxxx");
p_KeyValues_ReadKeyValuesFile = g_mGameDll.FindPatternSIMD(reinterpret_cast<rsig_t>("\x48\x8B\xC4\x55\x53\x57\x41\x54\x48\x8D\x68\xA1"), "xxxxxxxxxxxx"); p_KeyValues_ReadKeyValuesFile = g_mGameDll.FindPatternSIMD(reinterpret_cast<rsig_t>("\x48\x8B\xC4\x55\x53\x57\x41\x54\x48\x8D\x68\xA1"), "xxxxxxxxxxxx");
#endif #endif
p_KeyValues_LoadPlaylist = g_mGameDll.FindPatternSIMD(reinterpret_cast<rsig_t>("\xE8\x00\x00\x00\x00\x80\x3D\x00\x00\x00\x00\x00\x74\x0C"), "x????xx?????xx").FollowNearCallSelf().GetPtr(); p_KeyValues_LoadPlaylists = g_mGameDll.FindPatternSIMD(reinterpret_cast<rsig_t>("\x48\x89\x5C\x24\x00\x48\x89\x6C\x24\x00\x56\x57\x41\x56\x48\x83\xEC\x40\x48\x8B\xF1"), "xxxx?xxxx?xxxxxxxxxxx");
p_KeyValues_ParsePlaylists = g_mGameDll.FindPatternSIMD(reinterpret_cast<rsig_t>("\xE8\x00\x00\x00\x00\x80\x3D\x00\x00\x00\x00\x00\x74\x0C"), "x????xx?????xx").FollowNearCallSelf();
KeyValues_Init = p_KeyValues_Init.RCast<void* (*)(KeyValues*, const char*, int64_t, bool)>(); /*40 53 48 83 EC 20 48 8B 05 ?? ?? ?? 01 48 8B D9 4C 8B C2*/ KeyValues_Init = p_KeyValues_Init.RCast<void* (*)(KeyValues*, const char*, int64_t, bool)>(); /*40 53 48 83 EC 20 48 8B 05 ?? ?? ?? 01 48 8B D9 4C 8B C2*/
KeyValues_FindKey = p_KeyValues_FindKey.RCast<void* (*)(KeyValues*, const char*, bool)>(); /*40 56 57 41 57 48 81 EC 30 01 00 00 45 0F B6 F8*/ KeyValues_FindKey = p_KeyValues_FindKey.RCast<void* (*)(KeyValues*, const char*, bool)>(); /*40 56 57 41 57 48 81 EC 30 01 00 00 45 0F B6 F8*/
KeyValues_LoadPlaylist = p_KeyValues_LoadPlaylist.RCast<bool (*)(const char*)>(); /*E8 ?? ?? ?? ?? 80 3D ?? ?? ?? ?? ?? 74 0C*/ KeyValues_LoadPlaylists = p_KeyValues_ParsePlaylists.RCast<bool (*)(const char*)>(); /*48 89 5C 24 ?? 48 89 6C 24 ?? 56 57 41 56 48 83 EC 40 48 8B F1*/
KeyValues_ParsePlaylists = p_KeyValues_ParsePlaylists.RCast<bool (*)(const char*)>(); /*E8 ?? ?? ?? ?? 80 3D ?? ?? ?? ?? ?? 74 0C*/
KeyValues_GetCurrentPlaylist = p_KeyValues_GetCurrentPlaylist.RCast<const char* (*)(void)>(); /*48 8B 05 ?? ?? ?? ?? 48 85 C0 75 08 48 8D 05 ?? ?? ?? ?? C3 0F B7 50 2A*/ KeyValues_GetCurrentPlaylist = p_KeyValues_GetCurrentPlaylist.RCast<const char* (*)(void)>(); /*48 8B 05 ?? ?? ?? ?? 48 85 C0 75 08 48 8D 05 ?? ?? ?? ?? C3 0F B7 50 2A*/
KeyValues_ReadKeyValuesFile = p_KeyValues_ReadKeyValuesFile.RCast<KeyValues* (*)(CFileSystem_Stdio*, const char*)>(); /*48 8B C4 55 53 57 41 54 48 8D 68 A1*/ KeyValues_ReadKeyValuesFile = p_KeyValues_ReadKeyValuesFile.RCast<KeyValues* (*)(CFileSystem_Stdio*, const char*)>(); /*48 8B C4 55 53 57 41 54 48 8D 68 A1*/
} }