//==== Copyright (c) 1996-2005, Valve Corporation, All rights reserved. =====// // // Purpose: // // $NoKeywords: $ // //===========================================================================// #include "core/stdafx.h" #include "core/logdef.h" #include "tier0/dbg.h" #include "tier0/platform.h" #include "tier0/threadtools.h" #include "tier0/commandline.h" #ifndef DEDICATED #include "vgui/vgui_debugpanel.h" #include "gameui/IConsole.h" #else #include "engine/server/sv_rcon.h" #endif #if defined( _X360 ) #include "xbox/xbox_console.h" #endif std::mutex s_LogMutex; //----------------------------------------------------------------------------- // True if -hushasserts was passed on command line. //----------------------------------------------------------------------------- bool HushAsserts() { #ifdef DBGFLAG_ASSERT static bool s_bHushAsserts = !!CommandLine()->FindParm("-hushasserts"); return s_bHushAsserts; #else return true; #endif } //----------------------------------------------------------------------------- // Templates to assist in validating pointers: //----------------------------------------------------------------------------- PLATFORM_INTERFACE void _AssertValidReadPtr(void* ptr, int count/* = 1*/) { #if defined( _WIN32 ) && !defined( _X360 ) Assert(!IsBadReadPtr(ptr, count)); #else Assert(!count || ptr); #endif } PLATFORM_INTERFACE void _AssertValidWritePtr(void* ptr, int count/* = 1*/) { #if defined( _WIN32 ) && !defined( _X360 ) Assert(!IsBadWritePtr(ptr, count)); #else Assert(!count || ptr); #endif } PLATFORM_INTERFACE void _AssertValidReadWritePtr(void* ptr, int count/* = 1*/) { #if defined( _WIN32 ) && !defined( _X360 ) Assert(!(IsBadWritePtr(ptr, count) || IsBadReadPtr(ptr, count))); #else Assert(!count || ptr); #endif } PLATFORM_INTERFACE void _AssertValidStringPtr(const TCHAR* ptr, int maxchar/* = 0xFFFFFF */) { #if defined( _WIN32 ) && !defined( _X360 ) #ifdef TCHAR_IS_CHAR Assert(!IsBadStringPtr(ptr, maxchar)); #else Assert(!IsBadStringPtrW(ptr, maxchar)); #endif #else Assert(ptr); #endif } PLATFORM_INTERFACE void AssertValidWStringPtr(const wchar_t* ptr, int maxchar/* = 0xFFFFFF */) { #if defined( _WIN32 ) && !defined( _X360 ) Assert(!IsBadStringPtrW(ptr, maxchar)); #else Assert(ptr); #endif } //----------------------------------------------------------------------------- // Purpose: Netconsole log // Input : context - // *fmt - ... - //----------------------------------------------------------------------------- void NetMsg(int context, const char* fmt, ...) { #ifndef DEDICATED static char szBuf[4096] = {}; static std::string svOut; 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 ntlogger = spdlog::get("net_con"); switch (context) { case -4: case -3: case -2: case -1: { s_LogMutex.lock(); {///////////////////////////// va_list args{}; va_start(args, fmt); vsnprintf(szBuf, sizeof(szBuf), fmt, args); szBuf[sizeof(szBuf) - 1] = '\0'; va_end(args); }///////////////////////////// svOut = szBuf; if (svOut.back() != '\n') { svOut.append("\n"); } ImVec4 color; if (svOut.find("\033[38;2;255;255;000m") != std::string::npos) { // Warning. color = ImVec4(1.00f, 1.00f, 0.00f, 0.80f); context = static_cast(LogType_t::WARNING_C); } else if (svOut.find("\033[38;2;255;000;000m") != std::string::npos) { // Error. color = ImVec4(1.00f, 0.00f, 0.00f, 0.80f); context = static_cast(LogType_t::ERROR_C); } else { switch (context) { case -3: // [ SERVER ] color = ImVec4(0.59f, 0.58f, 0.73f, 1.00f); break; case -2: // [ CLIENT ] color = ImVec4(0.59f, 0.58f, 0.63f, 1.00f); break; case -1: // [ UI ] color = ImVec4(0.59f, 0.48f, 0.53f, 1.00f); break; default: color = ImVec4(0.59f, 0.59f, 0.59f, 1.00f); break; } } if (g_bSpdLog_UseAnsiClr) { wconsole->debug(svOut); svOut = std::regex_replace(svOut, rxAnsiExp, ""); } else { svOut = std::regex_replace(svOut, rxAnsiExp, ""); wconsole->debug(svOut); } ntlogger->debug(svOut); iconsole->debug(svOut); g_pConsole->AddLog(ConLog_t(g_spd_sys_w_oss.str(), color)); g_pLogSystem.AddLog(static_cast(context), g_spd_sys_w_oss.str()); g_spd_sys_w_oss.str(""); g_spd_sys_w_oss.clear(); s_LogMutex.unlock(); break; } case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8: { s_LogMutex.lock(); {///////////////////////////// va_list args{}; va_start(args, fmt); vsnprintf(szBuf, sizeof(szBuf), fmt, args); szBuf[sizeof(szBuf) - 1] = '\0'; va_end(args); }///////////////////////////// svOut = szBuf; if (svOut.back() != '\n') { svOut.append("\n"); } ImVec4 color; if (svOut.find("\033[38;2;255;255;000;") != std::string::npos) { // Warning. color = ImVec4(1.00f, 1.00f, 0.00f, 0.80f); context = static_cast(LogType_t::WARNING_C); } else if (svOut.find("\033[38;2;255;000;000;") != std::string::npos) { // Error. color = ImVec4(1.00f, 0.00f, 0.00f, 0.80f); context = static_cast(LogType_t::ERROR_C); } else { switch (static_cast(context)) { case eDLL_T::SERVER: color = ImVec4(0.23f, 0.47f, 0.85f, 1.00f); break; case eDLL_T::CLIENT: color = ImVec4(0.46f, 0.46f, 0.46f, 1.00f); break; case eDLL_T::UI: color = ImVec4(0.59f, 0.35f, 0.46f, 1.00f); break; case eDLL_T::ENGINE: color = ImVec4(0.70f, 0.70f, 0.70f, 1.00f); break; case eDLL_T::FS: color = ImVec4(0.32f, 0.64f, 0.72f, 1.00f); break; case eDLL_T::RTECH: color = ImVec4(0.36f, 0.70f, 0.35f, 1.00f); break; case eDLL_T::MS: color = ImVec4(0.75f, 0.41f, 0.67f, 1.00f); break; case eDLL_T::NETCON: color = ImVec4(0.81f, 0.81f, 0.81f, 1.00f); break; case eDLL_T::COMMON: color = ImVec4(1.00f, 0.80f, 0.60f, 1.00f); break; default: color = ImVec4(0.81f, 0.81f, 0.81f, 1.00f); break; } } if (g_bSpdLog_UseAnsiClr) { wconsole->debug(svOut); svOut = std::regex_replace(svOut, rxAnsiExp, ""); } else { svOut = std::regex_replace(svOut, rxAnsiExp, ""); wconsole->debug(svOut); } ntlogger->debug(svOut); iconsole->info(svOut); g_pConsole->AddLog(ConLog_t(g_spd_sys_w_oss.str(), color)); g_pLogSystem.AddLog(static_cast(context), g_spd_sys_w_oss.str()); g_spd_sys_w_oss.str(""); g_spd_sys_w_oss.clear(); s_LogMutex.unlock(); break; } } #endif // !DEDICATED } //----------------------------------------------------------------------------- // Purpose: Show logs to all console interfaces // Input : context - // *fmt - ... - //----------------------------------------------------------------------------- void DevMsg(eDLL_T context, const char* fmt, ...) { static char szBuf[4096] = {}; 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("sdk_info"); s_LogMutex.lock(); {///////////////////////////// va_list args{}; va_start(args, fmt); vsnprintf(szBuf, sizeof(szBuf), fmt, args); szBuf[sizeof(szBuf) - 1] = '\0'; va_end(args); }///////////////////////////// svOut = Plat_GetProcessUpTime(); svOut.append(sDLL_T[static_cast(context)]); svOut.append(szBuf); svOut = std::regex_replace(svOut, rxAnsiExp, ""); if (svOut.back() != '\n') { svOut.append("\n"); } if (!g_bSpdLog_UseAnsiClr) { wconsole->debug(svOut); #ifdef DEDICATED RCONServer()->Send(svOut, "", sv_rcon::response_t::SERVERDATA_RESPONSE_CONSOLE_LOG, static_cast(context)); #endif // DEDICATED } else { svAnsiOut = Plat_GetProcessUpTime(); svAnsiOut.append(sANSI_DLL_T[static_cast(context)]); svAnsiOut.append(szBuf); if (svAnsiOut.back() != '\n') { svAnsiOut.append("\n"); } wconsole->debug(svAnsiOut); #ifdef DEDICATED RCONServer()->Send(svAnsiOut, "", sv_rcon::response_t::SERVERDATA_RESPONSE_CONSOLE_LOG, static_cast(context)); #endif // DEDICATED } sqlogger->debug(svOut); #ifndef DEDICATED iconsole->info(svOut); LogType_t tLog = static_cast(context); ImVec4 color; switch (context) { case eDLL_T::SERVER: color = ImVec4(0.23f, 0.47f, 0.85f, 1.00f); break; case eDLL_T::CLIENT: color = ImVec4(0.46f, 0.46f, 0.46f, 1.00f); break; case eDLL_T::UI: color = ImVec4(0.59f, 0.35f, 0.46f, 1.00f); break; case eDLL_T::ENGINE: color = ImVec4(0.70f, 0.70f, 0.70f, 1.00f); break; case eDLL_T::FS: color = ImVec4(0.32f, 0.64f, 0.72f, 1.00f); break; case eDLL_T::RTECH: color = ImVec4(0.36f, 0.70f, 0.35f, 1.00f); break; case eDLL_T::MS: color = ImVec4(0.75f, 0.41f, 0.67f, 1.00f); break; case eDLL_T::NETCON: color = ImVec4(0.81f, 0.81f, 0.81f, 1.00f); break; case eDLL_T::COMMON: color = ImVec4(1.00f, 0.80f, 0.60f, 1.00f); break; default: color = ImVec4(0.81f, 0.81f, 0.81f, 1.00f); break; } g_pConsole->AddLog(ConLog_t(g_spd_sys_w_oss.str(), color)); g_pLogSystem.AddLog(tLog, g_spd_sys_w_oss.str()); g_spd_sys_w_oss.str(""); g_spd_sys_w_oss.clear(); #endif // !DEDICATED s_LogMutex.unlock(); } //----------------------------------------------------------------------------- // Purpose: Print engine and SDK errors // Input : context - // *fmt - ... - //----------------------------------------------------------------------------- void Warning(eDLL_T context, const char* fmt, ...) { static char szBuf[4096] = {}; 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("sdk_warn"); s_LogMutex.lock(); {///////////////////////////// va_list args{}; va_start(args, fmt); vsnprintf(szBuf, sizeof(szBuf), fmt, args); szBuf[sizeof(szBuf) - 1] = '\0'; va_end(args); }///////////////////////////// svOut = Plat_GetProcessUpTime(); svOut.append(sDLL_T[static_cast(context)]); svOut.append(szBuf); svOut = std::regex_replace(svOut, rxAnsiExp, ""); if (svOut.back() != '\n') { svOut.append("\n"); } if (!g_bSpdLog_UseAnsiClr) { wconsole->debug(svOut); #ifdef DEDICATED RCONServer()->Send(svOut, "", sv_rcon::response_t::SERVERDATA_RESPONSE_CONSOLE_LOG, static_cast(context)); #endif // DEDICATED } else { svAnsiOut = Plat_GetProcessUpTime(); svAnsiOut.append(sANSI_DLL_T[static_cast(context)]); svAnsiOut.append(g_svYellowF); svAnsiOut.append(szBuf); if (svAnsiOut.back() != '\n') { svAnsiOut.append("\n"); } wconsole->debug(svAnsiOut); #ifdef DEDICATED RCONServer()->Send(svAnsiOut, "", sv_rcon::response_t::SERVERDATA_RESPONSE_CONSOLE_LOG, static_cast(context)); #endif // DEDICATED } sqlogger->debug(svOut); #ifndef DEDICATED iconsole->info(svOut); g_pConsole->AddLog(ConLog_t(g_spd_sys_w_oss.str(), ImVec4(1.00f, 1.00f, 0.00f, 0.80f))); g_pLogSystem.AddLog(LogType_t::WARNING_C, g_spd_sys_w_oss.str()); g_spd_sys_w_oss.str(""); g_spd_sys_w_oss.clear(); #endif // !DEDICATED s_LogMutex.unlock(); } //----------------------------------------------------------------------------- // Purpose: Print engine and SDK errors // Input : context - // *fmt - ... - //----------------------------------------------------------------------------- void Error(eDLL_T context, const char* fmt, ...) { static char szBuf[4096] = {}; 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("sdk_error"); s_LogMutex.lock(); {///////////////////////////// va_list args{}; va_start(args, fmt); vsnprintf(szBuf, sizeof(szBuf), fmt, args); szBuf[sizeof(szBuf) - 1] = '\0'; va_end(args); }///////////////////////////// svOut = Plat_GetProcessUpTime(); svOut.append(sDLL_T[static_cast(context)]); svOut.append(szBuf); svOut = std::regex_replace(svOut, rxAnsiExp, ""); if (svOut.back() != '\n') { svOut.append("\n"); } if (!g_bSpdLog_UseAnsiClr) { wconsole->debug(svOut); #ifdef DEDICATED RCONServer()->Send(svOut, "", sv_rcon::response_t::SERVERDATA_RESPONSE_CONSOLE_LOG, static_cast(context)); #endif // DEDICATED } else { svAnsiOut = Plat_GetProcessUpTime(); svAnsiOut.append(sANSI_DLL_T[static_cast(context)]); svAnsiOut.append(g_svRedF); svAnsiOut.append(szBuf); if (svAnsiOut.back() != '\n') { svAnsiOut.append("\n"); } wconsole->debug(svAnsiOut); #ifdef DEDICATED RCONServer()->Send(svAnsiOut, "", sv_rcon::response_t::SERVERDATA_RESPONSE_CONSOLE_LOG, static_cast(context)); #endif // DEDICATED } sqlogger->debug(svOut); #ifndef DEDICATED iconsole->info(svOut); g_pConsole->AddLog(ConLog_t(g_spd_sys_w_oss.str(), ImVec4(1.00f, 0.00f, 0.00f, 1.00f))); g_pLogSystem.AddLog(LogType_t::ERROR_C, g_spd_sys_w_oss.str()); g_spd_sys_w_oss.str(""); g_spd_sys_w_oss.clear(); #endif // !DEDICATED s_LogMutex.unlock(); }