//=============================================================================// // // Purpose: General system utilities. // //=============================================================================// #include "core/stdafx.h" #include "core/logdef.h" #include "tier0/commandline.h" #include "tier1/cvar.h" #include "engine/common.h" #include "engine/host_state.h" #include "engine/sys_utils.h" #include "engine/cmodel_bsp.h" #ifdef DEDICATED #include "engine/sv_rcon.h" #else #include "vgui/vgui_debugpanel.h" #include "gameui/IConsole.h" #endif // !DEDICATED //----------------------------------------------------------------------------- // Purpose: Exit engine with error // Input : *error - // ... - // Output : void Sys_Error //----------------------------------------------------------------------------- void HSys_Error(char* fmt, ...) { static char buf[1024] = {}; va_list args{}; va_start(args, fmt); vsnprintf(buf, sizeof(buf), fmt, args); buf[sizeof(buf) -1] = 0; va_end(args); DevMsg(eDLL_T::ENGINE, "%s\n", buf); return Sys_Error(buf); } //----------------------------------------------------------------------------- // Purpose: Show warning in the console, exit engine with error when level 5 // Input : level - // *error - ... - // Output : void* Sys_Warning //----------------------------------------------------------------------------- void* HSys_Warning(int level, char* fmt, ...) { static char buf[1024] = {}; {///////////////////////////// va_list args{}; va_start(args, fmt); vsnprintf(buf, sizeof(buf), fmt, args); buf[sizeof(buf) - 1] = 0; va_end(args); }///////////////////////////// Warning(eDLL_T::NONE, "Warning(%d):%s\n", level, buf); // TODO: Color return Sys_Warning(level, buf); } #ifndef DEDICATED //----------------------------------------------------------------------------- // Purpose: Builds log to be displayed on the screen // Input : pos - // *fmt - ... - // Output : void NPrintf //----------------------------------------------------------------------------- void HCon_NPrintf(int pos, const char* fmt, ...) { if (cl_showhoststats->GetBool()) { static char buf[1024] = {}; {///////////////////////////// va_list args{}; va_start(args, fmt); vsnprintf(buf, sizeof(buf), fmt, args); buf[sizeof(buf) - 1] = 0; va_end(args); }///////////////////////////// snprintf((char*)g_pLogSystem.m_pszCon_NPrintf_Buf, 4096, buf); } } #endif // !DEDICATED //----------------------------------------------------------------------------- // Purpose: Show logs to all console interfaces // Input : idx - // *fmt - ... - //----------------------------------------------------------------------------- void DevMsg(eDLL_T idx, const char* fmt, ...) { static char szBuf[2048] = {}; static std::string svOut; static std::string svAnsiOut; static std::regex rxAnsiExp("\\\033\\[.*?m"); static std::shared_ptr iconsole = spdlog::get("game_console"); static std::shared_ptr wconsole = spdlog::get("win_console"); static std::shared_ptr sqlogger = spdlog::get("dev_message_logger"); {///////////////////////////// va_list args{}; va_start(args, fmt); vsnprintf(szBuf, sizeof(szBuf), fmt, args); szBuf[sizeof(szBuf) - 1] = 0; va_end(args); }///////////////////////////// svOut = sDLL_T[static_cast(idx)].c_str(); svOut.append(szBuf); svOut = std::regex_replace(svOut, rxAnsiExp, ""); char szNewLine = svOut.back(); if (szNewLine != '\n') { svOut.append("\n"); } if (!g_bSpdLog_UseAnsiClr) { wconsole->debug(svOut); #ifdef DEDICATED g_pRConServer->Send(svOut.c_str()); #endif // DEDICATED } else { svAnsiOut = sANSI_DLL_T[static_cast(idx)].c_str(); svAnsiOut.append(szBuf); char szNewLine = svAnsiOut.back(); if (szNewLine != '\n') { svAnsiOut.append("\n"); } wconsole->debug(svAnsiOut); #ifdef DEDICATED g_pRConServer->Send(svAnsiOut.c_str()); #endif // DEDICATED } sqlogger->debug(svOut); #ifndef DEDICATED iconsole->info(svOut); std::string s = g_spd_sys_w_oss.str(); int nLog = static_cast(idx) + 3; // RUI log enum is shifted by 3 for scripts. LogType_t tLog = static_cast(nLog); g_pLogSystem.AddLog(tLog, s); g_pIConsole->m_ivConLog.push_back(Strdup(s.c_str())); g_spd_sys_w_oss.str(""); g_spd_sys_w_oss.clear(); #endif // !DEDICATED } //----------------------------------------------------------------------------- // Purpose: Print engine and SDK errors // Input : idx - // *fmt - ... - //----------------------------------------------------------------------------- void Warning(eDLL_T idx, const char* fmt, ...) { static char szBuf[2048] = {}; static std::string svOut; static std::string svAnsiOut; static std::regex rxAnsiExp("\\\033\\[.*?m"); static std::shared_ptr iconsole = spdlog::get("game_console"); static std::shared_ptr wconsole = spdlog::get("win_console"); static std::shared_ptr sqlogger = spdlog::get("warn_message_logger"); {///////////////////////////// va_list args{}; va_start(args, fmt); vsnprintf(szBuf, sizeof(szBuf), fmt, args); szBuf[sizeof(szBuf) - 1] = 0; va_end(args); }///////////////////////////// svOut = sDLL_T[static_cast(idx)].c_str(); svOut.append(szBuf); svOut = std::regex_replace(svOut, rxAnsiExp, ""); char szNewLine = svOut.back(); if (szNewLine != '\n') { svOut.append("\n"); } if (!g_bSpdLog_UseAnsiClr) { wconsole->debug(svOut); #ifdef DEDICATED g_pRConServer->Send(svOut.c_str()); #endif // DEDICATED } else { svAnsiOut = sANSI_DLL_T[static_cast(idx)].c_str(); svAnsiOut.append(g_svYellowF.c_str()); svAnsiOut.append(szBuf); char szNewLine = svAnsiOut.back(); if (szNewLine != '\n') { svAnsiOut.append("\n"); } wconsole->debug(svAnsiOut); #ifdef DEDICATED g_pRConServer->Send(svAnsiOut.c_str()); #endif // DEDICATED } sqlogger->debug(svOut); #ifndef DEDICATED iconsole->info(svOut); std::string s = g_spd_sys_w_oss.str(); g_pLogSystem.AddLog(LogType_t::WARNING_C, s); g_pIConsole->m_ivConLog.push_back(Strdup(s.c_str())); g_spd_sys_w_oss.str(""); g_spd_sys_w_oss.clear(); #endif // !DEDICATED } //----------------------------------------------------------------------------- // Purpose: Print engine and SDK errors // Input : idx - // *fmt - ... - //----------------------------------------------------------------------------- void Error(eDLL_T idx, const char* fmt, ...) { static char szBuf[2048] = {}; static std::string svOut; static std::string svAnsiOut; static std::regex rxAnsiExp("\\\033\\[.*?m"); static std::shared_ptr iconsole = spdlog::get("game_console"); static std::shared_ptr wconsole = spdlog::get("win_console"); static std::shared_ptr sqlogger = spdlog::get("error_message_logger"); {///////////////////////////// va_list args{}; va_start(args, fmt); vsnprintf(szBuf, sizeof(szBuf), fmt, args); szBuf[sizeof(szBuf) - 1] = 0; va_end(args); }///////////////////////////// svOut = sDLL_T[static_cast(idx)].c_str(); svOut.append(szBuf); svOut = std::regex_replace(svOut, rxAnsiExp, ""); char szNewLine = svOut.back(); if (szNewLine != '\n') { svOut.append("\n"); } if (!g_bSpdLog_UseAnsiClr) { wconsole->debug(svOut); #ifdef DEDICATED g_pRConServer->Send(svOut.c_str()); #endif // DEDICATED } else { svAnsiOut = sANSI_DLL_T[static_cast(idx)].c_str(); svAnsiOut.append(g_svRedF.c_str()); svAnsiOut.append(szBuf); char szNewLine = svAnsiOut.back(); if (szNewLine != '\n') { svAnsiOut.append("\n"); } wconsole->debug(svAnsiOut); #ifdef DEDICATED g_pRConServer->Send(svAnsiOut.c_str()); #endif // DEDICATED } sqlogger->debug(svOut); #ifndef DEDICATED iconsole->info(svOut); std::string s = g_spd_sys_w_oss.str(); g_pLogSystem.AddLog(LogType_t::ERROR_C, s); g_pIConsole->m_ivConLog.push_back(Strdup(s.c_str())); g_spd_sys_w_oss.str(""); g_spd_sys_w_oss.clear(); #endif // !DEDICATED } //----------------------------------------------------------------------------- // Purpose: Load assets from a custom directory if file exists // Input : *lpFileName - // a2 - *a3 - // Output : void* Sys_LoadAssetHelper //----------------------------------------------------------------------------- void* HSys_LoadAssetHelper(const CHAR* lpFileName, std::int64_t a2, LARGE_INTEGER* a3) { std::string mod_file; std::string base_file = lpFileName; const std::string mod_dir = "paks\\Win32\\"; const std::string base_dir = "paks\\Win64\\"; static bool bBasePaksLoaded = false; if (g_pHostState) { std::string svLevelName = g_pHostState->m_levelName; std::string svMapPakName = svLevelName + ".rpak"; if (!g_bLevelResourceInitialized && !g_pHostState->m_bActiveGame && bBasePaksLoaded || !strcmp(std::string(lpFileName).erase(0, 11).c_str(), "mp_lobby.rpak")) { // Attempt to load level dependencies if they exist. MOD_PreloadPak(svLevelName); // By the time mp_lobby.rpak is loaded, all the base paks are loaded as well and we can load anything else. bBasePaksLoaded = true; g_bLevelResourceInitialized = true; } } if (strstr(lpFileName, base_dir.c_str())) { base_file.erase(0, 11); // Erase 'base_dir'. mod_file = mod_dir + base_file; // Prepend 'mod_dir'. if (FileExists(mod_file.c_str())) { // Load decompressed pak files from 'mod_dir'. DevMsg(eDLL_T::RTECH, "Loading pak: '%s'\n", mod_file.c_str()); return Sys_LoadAssetHelper(mod_file.c_str(), a2, a3); } } if (strstr(lpFileName, base_dir.c_str())) { DevMsg(eDLL_T::RTECH, "Loading pak: '%s'\n", lpFileName); } return Sys_LoadAssetHelper(lpFileName, a2, a3); } void SysUtils_Attach() { DetourAttach((LPVOID*)&Sys_Error, &HSys_Error); DetourAttach((LPVOID*)&Sys_Warning, &HSys_Warning); DetourAttach((LPVOID*)&Sys_LoadAssetHelper, &HSys_LoadAssetHelper); #ifndef DEDICATED DetourAttach((LPVOID*)&Con_NPrintf, &HCon_NPrintf); #endif // !DEDICATED } void SysUtils_Detach() { DetourDetach((LPVOID*)&Sys_Error, &HSys_Error); DetourDetach((LPVOID*)&Sys_Warning, &HSys_Warning); DetourDetach((LPVOID*)&Sys_LoadAssetHelper, &HSys_LoadAssetHelper); #ifndef DEDICATED DetourDetach((LPVOID*)&Con_NPrintf, &HCon_NPrintf); #endif // !DEDICATED }