diff --git a/core/AMBuilder b/core/AMBuilder index 7eb37f84..d9f62d83 100644 --- a/core/AMBuilder +++ b/core/AMBuilder @@ -31,7 +31,6 @@ project.sources += [ 'smn_console.cpp', 'UserMessages.cpp', 'MenuManager.cpp', - 'smn_core.cpp', 'smn_hudtext.cpp', 'smn_usermsgs.cpp', 'MenuStyle_Base.cpp', diff --git a/core/ConsoleDetours.cpp b/core/ConsoleDetours.cpp index 6c406666..fba52721 100644 --- a/core/ConsoleDetours.cpp +++ b/core/ConsoleDetours.cpp @@ -195,7 +195,7 @@ class GenericCommandHooker : public IConCommandLinkListener size_t index; if (!FindVtable(vtable, index)) { - g_Logger.LogError("Console detour tried to unhook command \"%s\" but it wasn't found", pBase->GetName()); + logger->LogError("Console detour tried to unhook command \"%s\" but it wasn't found", pBase->GetName()); return; } @@ -219,7 +219,7 @@ public: if (dispatch.thisptroffs < 0) { - g_Logger.LogError("Command filter could not determine ConCommand layout"); + logger->LogError("Command filter could not determine ConCommand layout"); return false; } @@ -228,7 +228,7 @@ public: if (!vtables.size()) { - g_Logger.LogError("Command filter could not find any cvars!"); + logger->LogError("Command filter could not find any cvars!"); return false; } diff --git a/core/CoreConfig.cpp b/core/CoreConfig.cpp index 42c30ab1..1cce9f4d 100644 --- a/core/CoreConfig.cpp +++ b/core/CoreConfig.cpp @@ -262,7 +262,7 @@ void CoreConfig::Initialize() { /* :TODO: This won't actually log or print anything :( - So fix that somehow */ const char *error = textparsers->GetSMCErrorString(err); - g_Logger.LogFatal("[SM] Error encountered parsing core config file: %s", error ? error : ""); + logger->LogFatal("[SM] Error encountered parsing core config file: %s", error ? error : ""); } } @@ -274,7 +274,7 @@ SMCResult CoreConfig::ReadSMC_KeyValue(const SMCStates *states, const char *key, if (err == ConfigResult_Reject) { /* This is a fatal error */ - g_Logger.LogFatal("Config error (key: %s) (value: %s) %s", key, value, error); + logger->LogFatal("Config error (key: %s) (value: %s) %s", key, value, error); } return SMCResult_Continue; @@ -469,7 +469,7 @@ bool SM_ExecuteConfig(IPlugin *pl, AutoConfig *cfg, bool can_create) } else { - g_Logger.LogError("Failed to auto generate config for %s, make sure the directory has write permission.", pl->GetFilename()); + logger->LogError("Failed to auto generate config for %s, make sure the directory has write permission.", pl->GetFilename()); return can_create; } } diff --git a/core/HalfLife2.cpp b/core/HalfLife2.cpp index da8935fe..9cc3bc51 100644 --- a/core/HalfLife2.cpp +++ b/core/HalfLife2.cpp @@ -168,7 +168,7 @@ void CHalfLife2::InitLogicalEntData() if (!addr) { // Key exists so notify if lookup fails, but try other method. - g_Logger.LogError("Failed lookup of gEntList directly - Reverting to lookup via LevelShutdown"); + logger->LogError("Failed lookup of gEntList directly - Reverting to lookup via LevelShutdown"); } else { @@ -186,7 +186,7 @@ void CHalfLife2::InitLogicalEntData() int offset; if (!g_pGameConf->GetOffset("gEntList", &offset)) { - g_Logger.LogError("Logical Entities not supported by this mod (gEntList) - Reverting to networkable entities only"); + logger->LogError("Logical Entities not supported by this mod (gEntList) - Reverting to networkable entities only"); return; } @@ -198,7 +198,7 @@ void CHalfLife2::InitLogicalEntData() // If we have g_EntList from either of the above methods, make sure we can get the offset from it to EntInfo as well if (g_EntList && !g_pGameConf->GetOffset("EntInfo", &entInfoOffset)) { - g_Logger.LogError("Logical Entities not supported by this mod (EntInfo) - Reverting to networkable entities only"); + logger->LogError("Logical Entities not supported by this mod (EntInfo) - Reverting to networkable entities only"); g_EntList = NULL; return; } @@ -211,7 +211,7 @@ void CHalfLife2::InitLogicalEntData() if (!g_EntList && !g_pEntInfoList) { - g_Logger.LogError("Failed lookup of gEntList - Reverting to networkable entities only"); + logger->LogError("Failed lookup of gEntList - Reverting to networkable entities only"); return; } } @@ -225,7 +225,7 @@ void CHalfLife2::InitCommandLine() ke::AutoPtr lib(g_LibSys.OpenLibrary(TIER0_NAME, error, sizeof(error))); if (lib == NULL) { - g_Logger.LogError("Could not load %s: %s", TIER0_NAME, error); + logger->LogError("Could not load %s: %s", TIER0_NAME, error); return; } @@ -242,7 +242,7 @@ void CHalfLife2::InitCommandLine() ke::AutoPtr lib(g_LibSys.OpenLibrary(VSTDLIB_NAME, error, sizeof(error))); if (lib == NULL) { - g_Logger.LogError("Could not load %s: %s", VSTDLIB_NAME, error); + logger->LogError("Could not load %s: %s", VSTDLIB_NAME, error); return; } @@ -251,7 +251,7 @@ void CHalfLife2::InitCommandLine() if (m_pGetCommandLine == NULL) { - g_Logger.LogError("Could not locate any command line functionality"); + logger->LogError("Could not locate any command line functionality"); } } diff --git a/core/Logger.cpp b/core/Logger.cpp index 20668fc4..9dd402d3 100644 --- a/core/Logger.cpp +++ b/core/Logger.cpp @@ -39,61 +39,12 @@ #include "logic_bridge.h" #include -Logger g_Logger; +bool g_in_game_log_hook = false; + +static LoggerCore g_LoggerCore; SH_DECL_HOOK1_void(IVEngineServer, LogPrint, SH_NOATTRIB, false, const char *); -/** - * :TODO: This should be creating the log folder if it doesn't exist - */ - -ConfigResult Logger::OnSourceModConfigChanged(const char *key, - const char *value, - ConfigSource source, - char *error, - size_t maxlength) -{ - if (strcasecmp(key, "Logging") == 0) - { - bool state; - - if (strcasecmp(value, "on") == 0) - { - state = true; - } else if (strcasecmp(value, "off") == 0) { - state = false; - } else { - UTIL_Format(error, maxlength, "Invalid value: must be \"on\" or \"off\""); - return ConfigResult_Reject; - } - - if (source == ConfigSource_Console) - { - state ? EnableLogging() : DisableLogging(); - } else { - m_InitialState = state; - } - - return ConfigResult_Accept; - } else if (strcasecmp(key, "LogMode") == 0) { - if (strcasecmp(value, "daily") == 0) - { - m_Mode = LoggingMode_Daily; - } else if (strcasecmp(value, "map") == 0) { - m_Mode = LoggingMode_PerMap; - } else if (strcasecmp(value, "game") == 0) { - m_Mode = LoggingMode_Game; - } else { - UTIL_Format(error, maxlength, "Invalid value: must be [daily|map|game]"); - return ConfigResult_Reject; - } - - return ConfigResult_Accept; - } - - return ConfigResult_Ignore; -} - static void HookLogPrint(const char *message) { g_in_game_log_hook = true; @@ -104,477 +55,16 @@ static void HookLogPrint(const char *message) RETURN_META(MRES_SUPERCEDE); } -void Logger::OnSourceModStartup(bool late) +void LoggerCore::OnSourceModStartup(bool late) { - InitLogger(m_Mode); - SH_ADD_HOOK(IVEngineServer, LogPrint, engine, SH_STATIC(HookLogPrint), false); } -void Logger::OnSourceModAllShutdown() +void LoggerCore::OnSourceModAllShutdown() { - CloseLogger(); SH_REMOVE_HOOK(IVEngineServer, LogPrint, engine, SH_STATIC(HookLogPrint), false); } -void Logger::OnSourceModLevelChange(const char *mapName) -{ - MapChange(mapName); -} - -void Logger::_NewMapFile() -{ - if (!m_Active) - { - return; - } - - /* Append "Log file closed" to previous log file */ - _CloseFile(); - - char _filename[256]; - int i = 0; - - time_t t; - GetAdjustedTime(&t); - tm *curtime = localtime(&t); - - while (true) - { - g_SourceMod.BuildPath(Path_SM, _filename, sizeof(_filename), "logs/L%02d%02d%03d.log", curtime->tm_mon + 1, curtime->tm_mday, i); - FILE *fp = fopen(_filename, "r"); - if (!fp) - { - break; - } - fclose(fp); - i++; - } - m_NrmFileName.assign(_filename); - - FILE *fp = fopen(m_NrmFileName.c_str(), "w"); - if (!fp) - { - char error[255]; - g_LibSys.GetPlatformError(error, sizeof(error)); - LogFatal("[SM] Unexpected fatal logging error (file \"%s\")", m_NrmFileName.c_str()); - LogFatal("[SM] Platform returned error: \"%s\"", error); - LogFatal("[SM] Logging has been disabled."); - m_Active = false; - return; - } else { - char date[32]; - strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime); - fprintf(fp, "L %s: SourceMod log file started (file \"L%02d%02d%03d.log\") (Version \"%s\")\n", date, curtime->tm_mon + 1, curtime->tm_mday, i, SOURCEMOD_VERSION); - fclose(fp); - } -} - -void Logger::_CloseFile() -{ - if (!m_Active) - { - return; - } - - FILE *fp = NULL; - if (!m_NrmFileName.empty()) - { - fp = fopen(m_NrmFileName.c_str(), "r+"); - if (fp) - { - fseek(fp, 0, SEEK_END); - LogMessage("Log file closed."); - fclose(fp); - } - m_NrmFileName.clear(); - } - - if (!m_ErrMapStart) - { - return; - } - fp = fopen(m_ErrFileName.c_str(), "r+"); - if (fp) - { - fseek(fp, 0, SEEK_END); - LogError("Error log file session closed."); - fclose(fp); - } - m_ErrFileName.clear(); -} - -void Logger::InitLogger(LoggingMode mode) -{ - m_Mode = mode; - m_Active = m_InitialState; - - time_t t; - GetAdjustedTime(&t); - tm *curtime = localtime(&t); - m_NrmCurDay = curtime->tm_mday; - m_ErrCurDay = curtime->tm_mday; - - char _filename[256]; - g_SourceMod.BuildPath(Path_SM, _filename, sizeof(_filename), "logs/errors_%04d%02d%02d.log", curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday); - m_ErrFileName.assign(_filename); - - switch (m_Mode) - { - case LoggingMode_PerMap: - { - if (!m_Active) - { - m_DelayedStart = true; - } - break; - } - case LoggingMode_Daily: - { - g_SourceMod.BuildPath(Path_SM, _filename, sizeof(_filename), "logs/L%04d%02d%02d.log", curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday); - m_NrmFileName.assign(_filename); - m_DailyPrintHdr = true; - break; - } - default: - { - /* do nothing... */ - break; - } - } -} - -void Logger::CloseLogger() -{ - _CloseFile(); -} - -void Logger::LogToOpenFile(FILE *fp, const char *msg, ...) -{ - if (!m_Active) - { - return; - } - - va_list ap; - va_start(ap, msg); - LogToOpenFileEx(fp, msg, ap); - va_end(ap); -} - -void Logger::LogToFileOnly(FILE *fp, const char *msg, ...) -{ - if (!m_Active) - { - return; - } - - va_list ap; - va_start(ap, msg); - LogToFileOnlyEx(fp, msg, ap); - va_end(ap); -} - -void Logger::LogToOpenFileEx(FILE *fp, const char *msg, va_list ap) -{ - if (!m_Active) - { - return; - } - - static ConVar *sv_logecho = icvar->FindVar("sv_logecho"); - - char buffer[3072]; - UTIL_FormatArgs(buffer, sizeof(buffer), msg, ap); - - char date[32]; - time_t t; - GetAdjustedTime(&t); - tm *curtime = localtime(&t); - strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime); - - fprintf(fp, "L %s: %s\n", date, buffer); - - if (!sv_logecho || sv_logecho->GetBool()) - { - g_SMAPI->ConPrintf("L %s: %s\n", date, buffer); - } -} - -void Logger::LogToFileOnlyEx(FILE *fp, const char *msg, va_list ap) -{ - if (!m_Active) - { - return; - } - - char buffer[3072]; - UTIL_FormatArgs(buffer, sizeof(buffer), msg, ap); - - char date[32]; - time_t t; - GetAdjustedTime(&t); - tm *curtime = localtime(&t); - strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime); - - fprintf(fp, "L %s: %s\n", date, buffer); - fflush(fp); -} - -void Logger::LogMessage(const char *vafmt, ...) -{ - va_list ap; - va_start(ap, vafmt); - LogMessageEx(vafmt, ap); - va_end(ap); -} - -void Logger::LogMessageEx(const char *vafmt, va_list ap) -{ - if (!m_Active) - { - return; - } - - if (m_Mode == LoggingMode_Game) - { - _PrintToGameLog(vafmt, ap); - return; - } - - if (m_DelayedStart) - { - m_DelayedStart = false; - _NewMapFile(); - } - - time_t t; - GetAdjustedTime(&t); - tm *curtime = localtime(&t); - - FILE *fp = NULL; - if (m_Mode == LoggingMode_PerMap) - { - fp = fopen(m_NrmFileName.c_str(), "a+"); - if (!fp) - { - _NewMapFile(); - fp = fopen(m_NrmFileName.c_str(), "a+"); - if (!fp) - { - goto print_error; - } - } - } else { - if (m_NrmCurDay != curtime->tm_mday) - { - char _filename[256]; - g_SourceMod.BuildPath(Path_SM, _filename, sizeof(_filename), "logs/L%04d%02d%02d.log", curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday); - m_NrmFileName.assign(_filename); - m_NrmCurDay = curtime->tm_mday; - m_DailyPrintHdr = true; - } - fp = fopen(m_NrmFileName.c_str(), "a+"); - } - - if (fp) - { - if (m_DailyPrintHdr) - { - char date[32]; - m_DailyPrintHdr = false; - strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime); - fprintf(fp, "L %s: SourceMod log file session started (file \"L%04d%02d%02d.log\") (Version \"%s\")\n", date, curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday, SOURCEMOD_VERSION); - } - LogToOpenFileEx(fp, vafmt, ap); - fclose(fp); - } else { - goto print_error; - } - - return; -print_error: - char error[255]; - g_LibSys.GetPlatformError(error, sizeof(error)); - LogFatal("[SM] Unexpected fatal logging error (file \"%s\")", m_NrmFileName.c_str()); - LogFatal("[SM] Platform returned error: \"%s\"", error); - LogFatal("[SM] Logging has been disabled."); - m_Active = false; -} - -void Logger::LogError(const char *vafmt, ...) -{ - va_list ap; - va_start(ap, vafmt); - LogErrorEx(vafmt, ap); - va_end(ap); -} - -void Logger::LogErrorEx(const char *vafmt, va_list ap) -{ - if (!m_Active) - { - return; - } - - time_t t; - GetAdjustedTime(&t); - tm *curtime = localtime(&t); - - if (curtime->tm_mday != m_ErrCurDay) - { - char _filename[256]; - g_SourceMod.BuildPath(Path_SM, _filename, sizeof(_filename), "logs/errors_%04d%02d%02d.log", curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday); - m_ErrFileName.assign(_filename); - m_ErrCurDay = curtime->tm_mday; - m_ErrMapStart = false; - } - - FILE *fp = fopen(m_ErrFileName.c_str(), "a+"); - if (fp) - { - if (!m_ErrMapStart) - { - char date[32]; - strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime); - fprintf(fp, "L %s: SourceMod error session started\n", date); - fprintf(fp, "L %s: Info (map \"%s\") (file \"errors_%04d%02d%02d.log\")\n", date, m_CurMapName.c_str(), curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday); - m_ErrMapStart = true; - } - LogToOpenFileEx(fp, vafmt, ap); - fclose(fp); - } - else - { - char error[255]; - g_LibSys.GetPlatformError(error, sizeof(error)); - LogFatal("[SM] Unexpected fatal logging error (file \"%s\")", m_NrmFileName.c_str()); - LogFatal("[SM] Platform returned error: \"%s\"", error); - LogFatal("[SM] Logging has been disabled."); - m_Active = false; - return; - } -} - -void Logger::MapChange(const char *mapname) -{ - m_CurMapName.assign(mapname); - - switch (m_Mode) - { - case LoggingMode_Daily: - { - LogMessage("-------- Mapchange to %s --------", mapname); - break; - } - case LoggingMode_PerMap: - { - _NewMapFile(); - break; - } - default: - { - /* Do nothing... */ - break; - } - } - - if (m_ErrMapStart) - { - LogError("Error log file session closed."); - } - m_ErrMapStart = false; -} - -void Logger::_PrintToGameLog(const char *fmt, va_list ap) -{ - char msg[3072]; - size_t len; - - len = vsnprintf(msg, sizeof(msg)-2, fmt, ap); - len = (len >= sizeof(msg)) ? (sizeof(msg) - 2) : len; - - msg[len++] = '\n'; - msg[len] = '\0'; - - Engine_LogPrintWrapper(msg); -} - -const char *Logger::GetLogFileName(LogType type) const -{ - switch (type) - { - case LogType_Normal: - { - return m_NrmFileName.c_str(); - } - case LogType_Error: - { - return m_ErrFileName.c_str(); - } - default: - { - return ""; - } - } -} - -LoggingMode Logger::GetLoggingMode() const -{ - return m_Mode; -} - -void Logger::EnableLogging() -{ - if (m_Active) - { - return; - } - m_Active = true; - LogMessage("[SM] Logging enabled manually by user."); -} - -void Logger::DisableLogging() -{ - if (!m_Active) - { - return; - } - LogMessage("[SM] Logging disabled manually by user."); - m_Active = false; -} - -void Logger::LogFatal(const char *msg, ...) -{ - va_list ap; - va_start(ap, msg); - LogFatalEx(msg, ap); - va_end(ap); -} - -void Logger::LogFatalEx(const char *msg, va_list ap) -{ - /* :TODO: make this print all pretty-like - * In fact, the pretty log printing function should be abstracted. - * It's already implemented twice which is bad. - */ - - char path[PLATFORM_MAX_PATH]; - - g_SourceMod.BuildPath(Path_Game, path, sizeof(path), "sourcemod_fatal.log"); - - FILE *fp = fopen(path, "at"); - if (fp) - { - m_Active = true; - LogToOpenFileEx(fp, msg, ap); - m_Active = false; - fclose(fp); - } -} - -bool g_in_game_log_hook = false; - void Engine_LogPrintWrapper(const char *msg) { if (g_in_game_log_hook) diff --git a/core/Logger.h b/core/Logger.h index 834492e9..a12dc9ef 100644 --- a/core/Logger.h +++ b/core/Logger.h @@ -38,76 +38,13 @@ using namespace SourceHook; -enum LogType +class LoggerCore : public SMGlobalClass { - LogType_Normal, - LogType_Error -}; - -enum LoggingMode -{ - LoggingMode_Daily, - LoggingMode_PerMap, - LoggingMode_Game -}; - -class Logger : public SMGlobalClass -{ -public: - Logger() : m_Mode(LoggingMode_Daily), m_ErrMapStart(false), - m_Active(false), m_DelayedStart(false), m_DailyPrintHdr(false), - m_InitialState(true) - { - } public: //SMGlobalClass - ConfigResult OnSourceModConfigChanged(const char *key, - const char *value, - ConfigSource source, - char *error, - size_t maxlength); void OnSourceModStartup(bool late); void OnSourceModAllShutdown(); - void OnSourceModLevelChange(const char *mapName); -public: - void InitLogger(LoggingMode mode); - void CloseLogger(); - void EnableLogging(); - void DisableLogging(); - void LogMessage(const char *msg, ...); - void LogMessageEx(const char *msg, va_list ap); - void LogError(const char *msg, ...); - void LogErrorEx(const char *msg, va_list ap); - void LogFatal(const char *msg, ...); - void LogFatalEx(const char *msg, va_list ap); - void LogToOpenFile(FILE *fp, const char *msg, ...); - void LogToOpenFileEx(FILE *fp, const char *msg, va_list ap); - /* This version does not print to console, and is thus thread-safe */ - void LogToFileOnly(FILE *fp, const char *msg, ...); - void LogToFileOnlyEx(FILE *fp, const char *msg, va_list ap); - void MapChange(const char *mapname); - const char *GetLogFileName(LogType type) const; - LoggingMode GetLoggingMode() const; -private: - void _CloseFile(); - void _NewMapFile(); - void _PrintToGameLog(const char *fmt, va_list ap); -private: - String m_NrmFileName; - String m_ErrFileName; - String m_CurMapName; - LoggingMode m_Mode; - int m_NrmCurDay; - int m_ErrCurDay; - bool m_ErrMapStart; - bool m_Active; - bool m_DelayedStart; - bool m_DailyPrintHdr; - bool m_InitialState; }; void Engine_LogPrintWrapper(const char *msg); -extern bool g_in_game_log_hook; -extern Logger g_Logger; - #endif // _INCLUDE_SOURCEMOD_CLOGGER_H_ diff --git a/core/NextMap.cpp b/core/NextMap.cpp index 92243008..126f8f66 100644 --- a/core/NextMap.cpp +++ b/core/NextMap.cpp @@ -36,6 +36,7 @@ #include "sm_stringutil.h" #include "sourcehook.h" #include "sm_srvcmds.h" +#include "logic_bridge.h" NextMapManager g_NextMap; @@ -130,7 +131,7 @@ void NextMapManager::HookChangeLevel(const char *map, const char *unknown, const { if (g_forcedChange) { - g_Logger.LogMessage("[SM] Changed map to \"%s\"", map); + logger->LogMessage("[SM] Changed map to \"%s\"", map); RETURN_META(MRES_IGNORED); } @@ -141,7 +142,7 @@ void NextMapManager::HookChangeLevel(const char *map, const char *unknown, const RETURN_META(MRES_IGNORED); } - g_Logger.LogMessage("[SM] Changed map to \"%s\"", newmap); + logger->LogMessage("[SM] Changed map to \"%s\"", newmap); UTIL_Format(m_tempChangeInfo.m_mapName, sizeof(m_tempChangeInfo.m_mapName), newmap); UTIL_Format(m_tempChangeInfo.m_changeReason, sizeof(m_tempChangeInfo.m_changeReason), "Normal level change"); diff --git a/core/PlayerManager.cpp b/core/PlayerManager.cpp index bc2c1038..587db7e5 100644 --- a/core/PlayerManager.cpp +++ b/core/PlayerManager.cpp @@ -1238,7 +1238,7 @@ void PlayerManager::OnClientSettingsChanged(edict_t *pEntity) if ((networkid_force = engine->GetClientConVarValue(client, "networkid_force")) && networkid_force[0] != '\0') { unsigned int accountId = pPlayer->GetSteamAccountID(); - g_Logger.LogMessage("\"%s<%d><>\" has bad networkid (id \"%s\") (ip \"%s\")", + logger->LogMessage("\"%s<%d><>\" has bad networkid (id \"%s\") (ip \"%s\")", new_name, pPlayer->GetUserId(), accountId & 1, accountId >> 1, networkid_force, pPlayer->GetIPAddress()); pPlayer->Kick("NetworkID spoofing detected."); diff --git a/core/logic/AMBuilder b/core/logic/AMBuilder index b38a0965..17a8eb3a 100644 --- a/core/logic/AMBuilder +++ b/core/logic/AMBuilder @@ -66,6 +66,8 @@ binary.sources += [ 'sm_trie.cpp', 'smn_console.cpp', 'ProfileTools.cpp', + 'Logger.cpp', + 'smn_core.cpp', ] if builder.target_platform == 'windows': binary.sources += ['thread/WinThreads.cpp'] diff --git a/core/logic/AdminCache.cpp b/core/logic/AdminCache.cpp index dc1094a5..a10ae6d1 100644 --- a/core/logic/AdminCache.cpp +++ b/core/logic/AdminCache.cpp @@ -198,11 +198,11 @@ private: if (!m_bFileNameLogged) { - smcore.LogError("[SM] Parse error(s) detected in file \"%s\":", m_File); + logger->LogError("[SM] Parse error(s) detected in file \"%s\":", m_File); m_bFileNameLogged = true; } - smcore.LogError("[SM] (Line %d): %s", states ? states->line : 0, buffer); + logger->LogError("[SM] (Line %d): %s", states ? states->line : 0, buffer); } private: bool m_bFileNameLogged; diff --git a/core/logic/Database.cpp b/core/logic/Database.cpp index e691bf28..99c13f10 100644 --- a/core/logic/Database.cpp +++ b/core/logic/Database.cpp @@ -89,11 +89,11 @@ void DBManager::OnSourceModLevelChange(const char *mapName) ke::AutoLock lock(&m_ConfigLock); if ((err = textparsers->ParseFile_SMC(m_Filename, this, &states)) != SMCError_Okay) { - smcore.LogError("[SM] Detected parse error(s) in file \"%s\"", m_Filename); + logger->LogError("[SM] Detected parse error(s) in file \"%s\"", m_Filename); if (err != SMCError_Custom) { const char *txt = textparsers->GetSMCErrorString(err); - smcore.LogError("[SM] Line %d: %s", states.line, txt); + logger->LogError("[SM] Line %d: %s", states.line, txt); } } } @@ -541,7 +541,7 @@ bool DBManager::AddToThreadQueue(IDBThreadOperation *op, PrioQueueLevel prio) { if (!s_OneTimeThreaderErrorMsg) { - smcore.LogError("[SM] Unable to create db threader (error unknown)"); + logger->LogError("[SM] Unable to create db threader (error unknown)"); s_OneTimeThreaderErrorMsg = true; } m_Worker = NULL; diff --git a/core/logic/DebugReporter.cpp b/core/logic/DebugReporter.cpp index efeea02d..ef5863ba 100644 --- a/core/logic/DebugReporter.cpp +++ b/core/logic/DebugReporter.cpp @@ -32,6 +32,7 @@ #include #include #include "DebugReporter.h" +#include "Logger.h" DebugReport g_DbgReporter; @@ -49,7 +50,7 @@ void DebugReport::OnDebugSpew(const char *msg, ...) smcore.FormatArgs(buffer, sizeof(buffer), msg, ap); va_end(ap); - smcore.Log("[SM] %s", buffer); + g_Logger.LogMessage("[SM] %s", buffer); } void DebugReport::GenerateError(IPluginContext *ctx, cell_t func_idx, int err, const char *message, ...) @@ -71,12 +72,12 @@ void DebugReport::GenerateErrorVA(IPluginContext *ctx, cell_t func_idx, int err, if (error) { - smcore.LogError("[SM] Plugin \"%s\" encountered error %d: %s", plname, err, error); + g_Logger.LogError("[SM] Plugin \"%s\" encountered error %d: %s", plname, err, error); } else { - smcore.LogError("[SM] Plugin \"%s\" encountered unknown error %d", plname, err); + g_Logger.LogError("[SM] Plugin \"%s\" encountered unknown error %d", plname, err); } - smcore.LogError("[SM] %s", buffer); + g_Logger.LogError("[SM] %s", buffer); if (func_idx != -1) { @@ -86,7 +87,7 @@ void DebugReport::GenerateErrorVA(IPluginContext *ctx, cell_t func_idx, int err, sp_public_t *function; if (ctx->GetRuntime()->GetPublicByIndex(func_idx, &function) == SP_ERROR_NONE) { - smcore.LogError("[SM] Unable to call function \"%s\" due to above error(s).", function->name); + g_Logger.LogError("[SM] Unable to call function \"%s\" due to above error(s).", function->name); } } } @@ -106,18 +107,18 @@ void DebugReport::GenerateCodeError(IPluginContext *pContext, uint32_t code_addr if (error) { - smcore.LogError("[SM] Plugin \"%s\" encountered error %d: %s", plname, err, error); + g_Logger.LogError("[SM] Plugin \"%s\" encountered error %d: %s", plname, err, error); } else { - smcore.LogError("[SM] Plugin \"%s\" encountered unknown error %d", plname, err); + g_Logger.LogError("[SM] Plugin \"%s\" encountered unknown error %d", plname, err); } - smcore.LogError("[SM] %s", buffer); + g_Logger.LogError("[SM] %s", buffer); IPluginDebugInfo *pDebug; if ((pDebug = pContext->GetRuntime()->GetDebugInfo()) == NULL) { - smcore.LogError("[SM] Debug mode is not enabled for \"%s\"", plname); - smcore.LogError("[SM] To enable debug mode, edit plugin_settings.cfg, or type: sm plugins debug %d on", + g_Logger.LogError("[SM] Debug mode is not enabled for \"%s\"", plname); + g_Logger.LogError("[SM] To enable debug mode, edit plugin_settings.cfg, or type: sm plugins debug %d on", _GetPluginIndex(pContext)); return; } @@ -125,9 +126,9 @@ void DebugReport::GenerateCodeError(IPluginContext *pContext, uint32_t code_addr const char *name; if (pDebug->LookupFunction(code_addr, &name) == SP_ERROR_NONE) { - smcore.LogError("[SM] Unable to call function \"%s\" due to above error(s).", name); + g_Logger.LogError("[SM] Unable to call function \"%s\" due to above error(s).", name); } else { - smcore.LogError("[SM] Unable to call function (name unknown, address \"%x\").", code_addr); + g_Logger.LogError("[SM] Unable to call function (name unknown, address \"%x\").", code_addr); } } @@ -139,7 +140,7 @@ void DebugReport::OnContextExecuteError(IPluginContext *ctx, IContextTrace *erro if (n_err != SP_ERROR_NATIVE) { - smcore.LogError("[SM] Plugin encountered error %d: %s", + g_Logger.LogError("[SM] Plugin encountered error %d: %s", n_err, error->GetErrorString()); } @@ -149,26 +150,26 @@ void DebugReport::OnContextExecuteError(IPluginContext *ctx, IContextTrace *erro const char *custerr; if ((custerr=error->GetCustomErrorString()) != NULL) { - smcore.LogError("[SM] Native \"%s\" reported: %s", lastname, custerr); + g_Logger.LogError("[SM] Native \"%s\" reported: %s", lastname, custerr); } else { - smcore.LogError("[SM] Native \"%s\" encountered a generic error.", lastname); + g_Logger.LogError("[SM] Native \"%s\" encountered a generic error.", lastname); } } if (!error->DebugInfoAvailable()) { - smcore.LogError("[SM] Debug mode is not enabled for \"%s\"", plname); - smcore.LogError("[SM] To enable debug mode, edit plugin_settings.cfg, or type: sm plugins debug %d on", + g_Logger.LogError("[SM] Debug mode is not enabled for \"%s\"", plname); + g_Logger.LogError("[SM] To enable debug mode, edit plugin_settings.cfg, or type: sm plugins debug %d on", _GetPluginIndex(ctx)); return; } CallStackInfo stk_info; int i = 0; - smcore.LogError("[SM] Displaying call stack trace for plugin \"%s\":", plname); + g_Logger.LogError("[SM] Displaying call stack trace for plugin \"%s\":", plname); while (error->GetTraceInfo(&stk_info)) { - smcore.LogError("[SM] [%d] Line %d, %s::%s()", + g_Logger.LogError("[SM] [%d] Line %d, %s::%s()", i++, stk_info.line, stk_info.filename, diff --git a/core/logic/ExtensionSys.cpp b/core/logic/ExtensionSys.cpp index cb7b5f0e..be327768 100644 --- a/core/logic/ExtensionSys.cpp +++ b/core/logic/ExtensionSys.cpp @@ -606,7 +606,7 @@ IExtension *CExtensionManager::LoadAutoExtension(const char *path, bool bErrorOn { if (bErrorOnMissing || libsys->IsPathFile(p->GetPath())) { - smcore.LogError("[SM] Unable to load extension \"%s\": %s", path, error); + logger->LogError("[SM] Unable to load extension \"%s\": %s", path, error); } p->SetError(error); diff --git a/core/logic/GameConfigs.cpp b/core/logic/GameConfigs.cpp index f13e9d30..12067853 100644 --- a/core/logic/GameConfigs.cpp +++ b/core/logic/GameConfigs.cpp @@ -301,8 +301,8 @@ SMCResult CGameConfig::ReadSMC_NewSection(const SMCStates *states, const char *n if (error[0] != '\0') { m_IgnoreLevel = 1; - smcore.LogError("[SM] Error while parsing CRC section for \"%s\" (%s):", m_Game, m_CurFile); - smcore.LogError("[SM] %s", error); + logger->LogError("[SM] Error while parsing CRC section for \"%s\" (%s):", m_Game, m_CurFile); + logger->LogError("[SM] %s", error); } else { m_ParseState = PSTATE_GAMEDEFS_CRC_BINARY; } @@ -335,8 +335,8 @@ SMCResult CGameConfig::ReadSMC_NewSection(const SMCStates *states, const char *n { if (strcmp(name, "linux") != 0 && strcmp(name, "windows") != 0 && strcmp(name, "mac") != 0) { - smcore.LogError("[SM] Error while parsing Address section for \"%s\" (%s):", m_Address, m_CurFile); - smcore.LogError("[SM] Unrecognized platform \"%s\"", name); + logger->LogError("[SM] Error while parsing Address section for \"%s\" (%s):", m_Address, m_CurFile); + logger->LogError("[SM] Unrecognized platform \"%s\"", name); } m_IgnoreLevel = 1; } @@ -435,7 +435,7 @@ SMCResult CGameConfig::ReadSMC_KeyValue(const SMCStates *states, const char *key } else { - smcore.LogError("[SM] Error parsing Address \"%s\", does not support more than %d read offsets (gameconf \"%s\")", m_Address, limit, m_CurFile); + logger->LogError("[SM] Error parsing Address \"%s\", does not support more than %d read offsets (gameconf \"%s\")", m_Address, limit, m_CurFile); } } else if (strcmp(key, "signature") == 0) { strncopy(m_AddressSignature, value, sizeof(m_AddressSignature)); @@ -503,7 +503,7 @@ SMCResult CGameConfig::ReadSMC_LeavingSection(const SMCStates *states) if (((strcmp(m_Game, "*") != 0) && strcmp(m_Game, "#default") != 0) && (!m_Offsets.retrieve(m_offset))) { - smcore.LogError("[SM] Unable to find property %s.%s (file \"%s\") (mod \"%s\")", + logger->LogError("[SM] Unable to find property %s.%s (file \"%s\") (mod \"%s\")", m_Class, m_Prop, m_CurFile, @@ -556,7 +556,7 @@ SMCResult CGameConfig::ReadSMC_LeavingSection(const SMCStates *states) void *final_addr = NULL; if (addrInBase == NULL) { - smcore.LogError("[SM] Unrecognized library \"%s\" (gameconf \"%s\")", + logger->LogError("[SM] Unrecognized library \"%s\" (gameconf \"%s\")", s_TempSig.library, m_CurFile); } @@ -570,7 +570,7 @@ SMCResult CGameConfig::ReadSMC_LeavingSection(const SMCStates *states) if (VirtualQuery(addrInBase, &mem, sizeof(mem))) final_addr = g_MemUtils.ResolveSymbol(mem.AllocationBase, &s_TempSig.sig[1]); else - smcore.LogError("[SM] Unable to find library \"%s\" in memory (gameconf \"%s\")", s_TempSig.library, m_File); + logger->LogError("[SM] Unable to find library \"%s\" in memory (gameconf \"%s\")", s_TempSig.library, m_File); #elif defined PLATFORM_POSIX Dl_info info; /* GNU only: returns 0 on error, inconsistent! >:[ */ @@ -585,12 +585,12 @@ SMCResult CGameConfig::ReadSMC_LeavingSection(const SMCStates *states) final_addr = dlsym(handle, &s_TempSig.sig[1]); dlclose(handle); } else { - smcore.LogError("[SM] Unable to load library \"%s\" (gameconf \"%s\")", + logger->LogError("[SM] Unable to load library \"%s\" (gameconf \"%s\")", s_TempSig.library, m_File); } } else { - smcore.LogError("[SM] Unable to find library \"%s\" in memory (gameconf \"%s\")", + logger->LogError("[SM] Unable to find library \"%s\" in memory (gameconf \"%s\")", s_TempSig.library, m_File); } @@ -827,8 +827,8 @@ bool CGameConfig::Reparse(char *error, size_t maxlength) { const char *msg = textparsers->GetSMCErrorString(err); - smcore.LogError("[SM] Error parsing master gameconf file \"%s\":", path); - smcore.LogError("[SM] Error %d on line %d, col %d: %s", + logger->LogError("[SM] Error parsing master gameconf file \"%s\":", path); + logger->LogError("[SM] Error %d on line %d, col %d: %s", err, state.line, state.col, @@ -915,8 +915,8 @@ bool CGameConfig::EnterFile(const char *file, char *error, size_t maxlength) { const char *msg = textparsers->GetSMCErrorString(err); - smcore.LogError("[SM] Error parsing gameconfig file \"%s\":", m_CurFile); - smcore.LogError("[SM] Error %d on line %d, col %d: %s", + logger->LogError("[SM] Error parsing gameconfig file \"%s\":", m_CurFile); + logger->LogError("[SM] Error %d on line %d, col %d: %s", err, state.line, state.col, diff --git a/core/logic/HandleSys.cpp b/core/logic/HandleSys.cpp index 2c43b9cc..4ec90627 100644 --- a/core/logic/HandleSys.cpp +++ b/core/logic/HandleSys.cpp @@ -957,8 +957,8 @@ bool HandleSystem::InitAccessDefaults(TypeAccess *pTypeAccess, HandleAccess *pHa } #define HANDLE_LOG_VERY_BAD(message, ...) \ - smcore.LogFatal(message, ##__VA_ARGS__); \ - smcore.LogError(message, ##__VA_ARGS__); + logger->LogFatal(message, ##__VA_ARGS__); \ + logger->LogError(message, ##__VA_ARGS__); bool HandleSystem::TryAndFreeSomeHandles() { diff --git a/core/logic/Logger.cpp b/core/logic/Logger.cpp new file mode 100644 index 00000000..c522b56d --- /dev/null +++ b/core/logic/Logger.cpp @@ -0,0 +1,551 @@ +/** + * vim: set ts=4 sw=4 : + * ============================================================================= + * SourceMod + * Copyright (C) 2004-2009 AlliedModders LLC. All rights reserved. + * ============================================================================= + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, version 3.0, as published by the + * Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + * + * As a special exception, AlliedModders LLC gives you permission to link the + * code of this program (as well as its derivative works) to "Half-Life 2," the + * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software + * by the Valve Corporation. You must obey the GNU General Public License in + * all respects for all other code used. Additionally, AlliedModders LLC grants + * this exception to all derivative works. AlliedModders LLC defines further + * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), + * or . + * + * Version: $Id$ + */ + +#include +#include +#include "Logger.h" +#include +#include + +Logger g_Logger; + +/** + * :TODO: This should be creating the log folder if it doesn't exist + */ + +ConfigResult Logger::OnSourceModConfigChanged(const char *key, + const char *value, + ConfigSource source, + char *error, + size_t maxlength) +{ + if (strcasecmp(key, "Logging") == 0) + { + bool state; + + if (strcasecmp(value, "on") == 0) + { + state = true; + } else if (strcasecmp(value, "off") == 0) { + state = false; + } else { + smcore.Format(error, maxlength, "Invalid value: must be \"on\" or \"off\""); + return ConfigResult_Reject; + } + + if (source == ConfigSource_Console) + { + state ? EnableLogging() : DisableLogging(); + } else { + m_InitialState = state; + } + + return ConfigResult_Accept; + } else if (strcasecmp(key, "LogMode") == 0) { + if (strcasecmp(value, "daily") == 0) + { + m_Mode = LoggingMode_Daily; + } else if (strcasecmp(value, "map") == 0) { + m_Mode = LoggingMode_PerMap; + } else if (strcasecmp(value, "game") == 0) { + m_Mode = LoggingMode_Game; + } else { + smcore.Format(error, maxlength, "Invalid value: must be [daily|map|game]"); + return ConfigResult_Reject; + } + + return ConfigResult_Accept; + } + + return ConfigResult_Ignore; +} + +void Logger::OnSourceModStartup(bool late) +{ + InitLogger(m_Mode); +} + +void Logger::OnSourceModAllShutdown() +{ + CloseLogger(); +} + +void Logger::OnSourceModLevelChange(const char *mapName) +{ + MapChange(mapName); +} + +void Logger::_NewMapFile() +{ + if (!m_Active) + { + return; + } + + /* Append "Log file closed" to previous log file */ + _CloseFile(); + + char _filename[256]; + int i = 0; + + time_t t = g_pSM->GetAdjustedTime(); + tm *curtime = localtime(&t); + + while (true) + { + g_pSM->BuildPath(Path_SM, _filename, sizeof(_filename), "logs/L%02d%02d%03d.log", curtime->tm_mon + 1, curtime->tm_mday, i); + FILE *fp = fopen(_filename, "r"); + if (!fp) + { + break; + } + fclose(fp); + i++; + } + m_NrmFileName.assign(_filename); + + FILE *fp = fopen(m_NrmFileName.c_str(), "w"); + if (!fp) + { + char error[255]; + libsys->GetPlatformError(error, sizeof(error)); + LogFatal("[SM] Unexpected fatal logging error (file \"%s\")", m_NrmFileName.c_str()); + LogFatal("[SM] Platform returned error: \"%s\"", error); + LogFatal("[SM] Logging has been disabled."); + m_Active = false; + return; + } else { + char date[32]; + strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime); + fprintf(fp, "L %s: SourceMod log file started (file \"L%02d%02d%03d.log\") (Version \"%s\")\n", date, curtime->tm_mon + 1, curtime->tm_mday, i, SOURCEMOD_VERSION); + fclose(fp); + } +} + +void Logger::_CloseFile() +{ + if (!m_Active) + { + return; + } + + FILE *fp = NULL; + if (!m_NrmFileName.empty()) + { + fp = fopen(m_NrmFileName.c_str(), "r+"); + if (fp) + { + fseek(fp, 0, SEEK_END); + LogMessage("Log file closed."); + fclose(fp); + } + m_NrmFileName.clear(); + } + + if (!m_ErrMapStart) + { + return; + } + fp = fopen(m_ErrFileName.c_str(), "r+"); + if (fp) + { + fseek(fp, 0, SEEK_END); + LogError("Error log file session closed."); + fclose(fp); + } + m_ErrFileName.clear(); +} + +void Logger::InitLogger(LoggingMode mode) +{ + m_Mode = mode; + m_Active = m_InitialState; + + time_t t = g_pSM->GetAdjustedTime(); + tm *curtime = localtime(&t); + m_NrmCurDay = curtime->tm_mday; + m_ErrCurDay = curtime->tm_mday; + + char _filename[256]; + g_pSM->BuildPath(Path_SM, _filename, sizeof(_filename), "logs/errors_%04d%02d%02d.log", curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday); + m_ErrFileName.assign(_filename); + + switch (m_Mode) + { + case LoggingMode_PerMap: + { + if (!m_Active) + { + m_DelayedStart = true; + } + break; + } + case LoggingMode_Daily: + { + g_pSM->BuildPath(Path_SM, _filename, sizeof(_filename), "logs/L%04d%02d%02d.log", curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday); + m_NrmFileName.assign(_filename); + m_DailyPrintHdr = true; + break; + } + default: + { + /* do nothing... */ + break; + } + } +} + +void Logger::CloseLogger() +{ + _CloseFile(); +} + +void Logger::LogToOpenFile(FILE *fp, const char *msg, ...) +{ + if (!m_Active) + { + return; + } + + va_list ap; + va_start(ap, msg); + LogToOpenFileEx(fp, msg, ap); + va_end(ap); +} + +void Logger::LogToFileOnly(FILE *fp, const char *msg, ...) +{ + if (!m_Active) + { + return; + } + + va_list ap; + va_start(ap, msg); + LogToFileOnlyEx(fp, msg, ap); + va_end(ap); +} + +void Logger::LogToOpenFileEx(FILE *fp, const char *msg, va_list ap) +{ + if (!m_Active) + { + return; + } + + static ConVar *sv_logecho = smcore.FindConVar("sv_logecho"); + + char buffer[3072]; + smcore.FormatArgs(buffer, sizeof(buffer), msg, ap); + + char date[32]; + time_t t = g_pSM->GetAdjustedTime(); + tm *curtime = localtime(&t); + strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime); + + fprintf(fp, "L %s: %s\n", date, buffer); + + if (!sv_logecho || smcore.GetCvarBool(sv_logecho)) + { + static char conBuffer[4096]; + smcore.Format(conBuffer, sizeof(conBuffer), "L %s: %s\n", date, buffer); + smcore.ConPrint(conBuffer); + } +} + +void Logger::LogToFileOnlyEx(FILE *fp, const char *msg, va_list ap) +{ + if (!m_Active) + { + return; + } + + char buffer[3072]; + smcore.FormatArgs(buffer, sizeof(buffer), msg, ap); + + char date[32]; + time_t t = g_pSM->GetAdjustedTime(); + tm *curtime = localtime(&t); + strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime); + + fprintf(fp, "L %s: %s\n", date, buffer); + fflush(fp); +} + +void Logger::LogMessage(const char *vafmt, ...) +{ + va_list ap; + va_start(ap, vafmt); + LogMessageEx(vafmt, ap); + va_end(ap); +} + +void Logger::LogMessageEx(const char *vafmt, va_list ap) +{ + if (!m_Active) + { + return; + } + + if (m_Mode == LoggingMode_Game) + { + _PrintToGameLog(vafmt, ap); + return; + } + + if (m_DelayedStart) + { + m_DelayedStart = false; + _NewMapFile(); + } + + time_t t = g_pSM->GetAdjustedTime(); + tm *curtime = localtime(&t); + + FILE *fp = NULL; + if (m_Mode == LoggingMode_PerMap) + { + fp = fopen(m_NrmFileName.c_str(), "a+"); + if (!fp) + { + _NewMapFile(); + fp = fopen(m_NrmFileName.c_str(), "a+"); + if (!fp) + { + goto print_error; + } + } + } else { + if (m_NrmCurDay != curtime->tm_mday) + { + char _filename[256]; + g_pSM->BuildPath(Path_SM, _filename, sizeof(_filename), "logs/L%04d%02d%02d.log", curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday); + m_NrmFileName.assign(_filename); + m_NrmCurDay = curtime->tm_mday; + m_DailyPrintHdr = true; + } + fp = fopen(m_NrmFileName.c_str(), "a+"); + } + + if (fp) + { + if (m_DailyPrintHdr) + { + char date[32]; + m_DailyPrintHdr = false; + strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime); + fprintf(fp, "L %s: SourceMod log file session started (file \"L%04d%02d%02d.log\") (Version \"%s\")\n", date, curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday, SOURCEMOD_VERSION); + } + LogToOpenFileEx(fp, vafmt, ap); + fclose(fp); + } else { + goto print_error; + } + + return; +print_error: + char error[255]; + libsys->GetPlatformError(error, sizeof(error)); + LogFatal("[SM] Unexpected fatal logging error (file \"%s\")", m_NrmFileName.c_str()); + LogFatal("[SM] Platform returned error: \"%s\"", error); + LogFatal("[SM] Logging has been disabled."); + m_Active = false; +} + +void Logger::LogError(const char *vafmt, ...) +{ + va_list ap; + va_start(ap, vafmt); + LogErrorEx(vafmt, ap); + va_end(ap); +} + +void Logger::LogErrorEx(const char *vafmt, va_list ap) +{ + if (!m_Active) + { + return; + } + + time_t t = g_pSM->GetAdjustedTime(); + tm *curtime = localtime(&t); + + if (curtime->tm_mday != m_ErrCurDay) + { + char _filename[256]; + g_pSM->BuildPath(Path_SM, _filename, sizeof(_filename), "logs/errors_%04d%02d%02d.log", curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday); + m_ErrFileName.assign(_filename); + m_ErrCurDay = curtime->tm_mday; + m_ErrMapStart = false; + } + + FILE *fp = fopen(m_ErrFileName.c_str(), "a+"); + if (fp) + { + if (!m_ErrMapStart) + { + char date[32]; + strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime); + fprintf(fp, "L %s: SourceMod error session started\n", date); + fprintf(fp, "L %s: Info (map \"%s\") (file \"errors_%04d%02d%02d.log\")\n", date, m_CurMapName.c_str(), curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday); + m_ErrMapStart = true; + } + LogToOpenFileEx(fp, vafmt, ap); + fclose(fp); + } + else + { + char error[255]; + libsys->GetPlatformError(error, sizeof(error)); + LogFatal("[SM] Unexpected fatal logging error (file \"%s\")", m_NrmFileName.c_str()); + LogFatal("[SM] Platform returned error: \"%s\"", error); + LogFatal("[SM] Logging has been disabled."); + m_Active = false; + return; + } +} + +void Logger::MapChange(const char *mapname) +{ + m_CurMapName.assign(mapname); + + switch (m_Mode) + { + case LoggingMode_Daily: + { + LogMessage("-------- Mapchange to %s --------", mapname); + break; + } + case LoggingMode_PerMap: + { + _NewMapFile(); + break; + } + default: + { + /* Do nothing... */ + break; + } + } + + if (m_ErrMapStart) + { + LogError("Error log file session closed."); + } + m_ErrMapStart = false; +} + +void Logger::_PrintToGameLog(const char *fmt, va_list ap) +{ + char msg[3072]; + size_t len; + + len = vsnprintf(msg, sizeof(msg)-2, fmt, ap); + len = (len >= sizeof(msg)) ? (sizeof(msg) - 2) : len; + + msg[len++] = '\n'; + msg[len] = '\0'; + + smcore.LogToGame(msg); +} + +const char *Logger::GetLogFileName(LogType type) const +{ + switch (type) + { + case LogType_Normal: + { + return m_NrmFileName.c_str(); + } + case LogType_Error: + { + return m_ErrFileName.c_str(); + } + default: + { + return ""; + } + } +} + +LoggingMode Logger::GetLoggingMode() const +{ + return m_Mode; +} + +void Logger::EnableLogging() +{ + if (m_Active) + { + return; + } + m_Active = true; + LogMessage("[SM] Logging enabled manually by user."); +} + +void Logger::DisableLogging() +{ + if (!m_Active) + { + return; + } + LogMessage("[SM] Logging disabled manually by user."); + m_Active = false; +} + +void Logger::LogFatal(const char *msg, ...) +{ + va_list ap; + va_start(ap, msg); + LogFatalEx(msg, ap); + va_end(ap); +} + +void Logger::LogFatalEx(const char *msg, va_list ap) +{ + /* :TODO: make this print all pretty-like + * In fact, the pretty log printing function should be abstracted. + * It's already implemented twice which is bad. + */ + + char path[PLATFORM_MAX_PATH]; + + g_pSM->BuildPath(Path_Game, path, sizeof(path), "sourcemod_fatal.log"); + + FILE *fp = fopen(path, "at"); + if (fp) + { + m_Active = true; + LogToOpenFileEx(fp, msg, ap); + m_Active = false; + fclose(fp); + } +} diff --git a/core/logic/Logger.h b/core/logic/Logger.h new file mode 100644 index 00000000..8d8ebcee --- /dev/null +++ b/core/logic/Logger.h @@ -0,0 +1,111 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * SourceMod + * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. + * ============================================================================= + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, version 3.0, as published by the + * Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + * + * As a special exception, AlliedModders LLC gives you permission to link the + * code of this program (as well as its derivative works) to "Half-Life 2," the + * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software + * by the Valve Corporation. You must obey the GNU General Public License in + * all respects for all other code used. Additionally, AlliedModders LLC grants + * this exception to all derivative works. AlliedModders LLC defines further + * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), + * or . + * + * Version: $Id$ + */ + +#ifndef _INCLUDE_SOURCEMOD_CLOGGER_H_ +#define _INCLUDE_SOURCEMOD_CLOGGER_H_ + +#include +#include + +#include "common_logic.h" + +using namespace SourceHook; + +enum LogType +{ + LogType_Normal, + LogType_Error +}; + +enum LoggingMode +{ + LoggingMode_Daily, + LoggingMode_PerMap, + LoggingMode_Game +}; + +class Logger : public SMGlobalClass, public ILogger +{ +public: + Logger() : m_Mode(LoggingMode_Daily), m_ErrMapStart(false), + m_Active(false), m_DelayedStart(false), m_DailyPrintHdr(false), + m_InitialState(true) + { + } +public: //SMGlobalClass + ConfigResult OnSourceModConfigChanged(const char *key, + const char *value, + ConfigSource source, + char *error, + size_t maxlength); + void OnSourceModStartup(bool late); + void OnSourceModAllShutdown(); + void OnSourceModLevelChange(const char *mapName); +public: + void InitLogger(LoggingMode mode); + void CloseLogger(); + void EnableLogging(); + void DisableLogging(); + void LogMessage(const char *msg, ...); + void LogMessageEx(const char *msg, va_list ap); + void LogError(const char *msg, ...); + void LogErrorEx(const char *msg, va_list ap); + void LogFatal(const char *msg, ...); + void LogFatalEx(const char *msg, va_list ap); + void LogToOpenFile(FILE *fp, const char *msg, ...); + void LogToOpenFileEx(FILE *fp, const char *msg, va_list ap); + /* This version does not print to console, and is thus thread-safe */ + void LogToFileOnly(FILE *fp, const char *msg, ...); + void LogToFileOnlyEx(FILE *fp, const char *msg, va_list ap); + void MapChange(const char *mapname); + const char *GetLogFileName(LogType type) const; + LoggingMode GetLoggingMode() const; +private: + void _CloseFile(); + void _NewMapFile(); + void _PrintToGameLog(const char *fmt, va_list ap); +private: + String m_NrmFileName; + String m_ErrFileName; + String m_CurMapName; + LoggingMode m_Mode; + int m_NrmCurDay; + int m_ErrCurDay; + bool m_ErrMapStart; + bool m_Active; + bool m_DelayedStart; + bool m_DailyPrintHdr; + bool m_InitialState; +}; + +extern Logger g_Logger; + +#endif // _INCLUDE_SOURCEMOD_CLOGGER_H_ diff --git a/core/logic/PluginSys.cpp b/core/logic/PluginSys.cpp index 2e7f45e4..c53d4fe3 100644 --- a/core/logic/PluginSys.cpp +++ b/core/logic/PluginSys.cpp @@ -42,6 +42,7 @@ #include "GameConfigs.h" #include "common_logic.h" #include "Translator.h" +#include "Logger.h" CPluginManager g_PluginSys; HandleType_t g_PluginType = 0; @@ -844,8 +845,8 @@ void CPluginManager::LoadPluginsFromDir(const char *basedir, const char *localpa { char error[256]; libsys->GetPlatformError(error, sizeof(error)); - smcore.LogError("[SM] Failure reading from plugins path: %s", localpath); - smcore.LogError("[SM] Platform returned error: %s", error); + g_Logger.LogError("[SM] Failure reading from plugins path: %s", localpath); + g_Logger.LogError("[SM] Platform returned error: %s", error); return; } @@ -990,9 +991,9 @@ LoadRes CPluginManager::_LoadPlugin(CPlugin **aResult, const char *path, bool de } else { if (bulletinUrl[0] != '\0') { - smcore.Log("%s: Known malware detected. See %s for more info, blocking disabled in core.cfg", pPlugin->GetFilename(), bulletinUrl); + g_Logger.LogMessage("%s: Known malware detected. See %s for more info, blocking disabled in core.cfg", pPlugin->GetFilename(), bulletinUrl); } else { - smcore.Log("%s: Possible malware or illegal plugin detected, blocking disabled in core.cfg", pPlugin->GetFilename()); + g_Logger.LogMessage("%s: Possible malware or illegal plugin detected, blocking disabled in core.cfg", pPlugin->GetFilename()); } } } @@ -1094,7 +1095,7 @@ void CPluginManager::LoadAutoPlugin(const char *plugin) if ((res=_LoadPlugin(&pl, plugin, false, PluginType_MapUpdated, error, sizeof(error))) == LoadRes_Failure) { - smcore.LogError("[SM] Failed to load plugin \"%s\": %s.", plugin, error); + g_Logger.LogError("[SM] Failed to load plugin \"%s\": %s.", plugin, error); pl->SetErrorState( pl->GetStatus() <= Plugin_Created ? Plugin_BadLoad : pl->GetStatus(), "%s", @@ -1136,7 +1137,7 @@ void CPluginManager::LoadAll_SecondPass() error[0] = '\0'; if (!RunSecondPass(pPlugin, error, sizeof(error))) { - smcore.LogError("[SM] Unable to load plugin \"%s\": %s", pPlugin->GetFilename(), error); + g_Logger.LogError("[SM] Unable to load plugin \"%s\": %s", pPlugin->GetFilename(), error); pPlugin->SetErrorState(Plugin_Failed, "%s", error); } } diff --git a/core/logic/Translator.cpp b/core/logic/Translator.cpp index c2910921..a1fdaf42 100644 --- a/core/logic/Translator.cpp +++ b/core/logic/Translator.cpp @@ -96,11 +96,11 @@ void CPhraseFile::ParseWarning(const char *message, ...) if (!m_FileLogged) { - smcore.LogError("[SM] Warning(s) encountered in translation file \"%s\"", m_File.c_str()); + logger->LogError("[SM] Warning(s) encountered in translation file \"%s\"", m_File.c_str()); m_FileLogged = true; } - smcore.LogError("[SM] %s", buffer); + logger->LogError("[SM] %s", buffer); } void CPhraseFile::ReparseFile() @@ -142,8 +142,8 @@ void CPhraseFile::ReparseFile() msg = m_ParseError.c_str(); } - smcore.LogError("[SM] Fatal error encountered parsing translation file \"%s\"", m_File.c_str()); - smcore.LogError("[SM] Error (line %d, column %d): %s", states.line, states.col, msg); + logger->LogError("[SM] Fatal error encountered parsing translation file \"%s\"", m_File.c_str()); + logger->LogError("[SM] Error (line %d, column %d): %s", states.line, states.col, msg); } const char *code; @@ -175,10 +175,10 @@ void CPhraseFile::ReparseFile() msg = m_ParseError.c_str(); } - smcore.LogError("[SM] Fatal error encountered parsing translation file \"%s/%s\"", + logger->LogError("[SM] Fatal error encountered parsing translation file \"%s/%s\"", code, m_File.c_str()); - smcore.LogError("[SM] Error (line %d, column %d): %s", + logger->LogError("[SM] Error (line %d, column %d): %s", states.line, states.col, msg); @@ -831,13 +831,13 @@ void Translator::RebuildLanguageDatabase() str_err = m_CustomError.c_str(); } - smcore.LogError("[SM] Failed to parse language header file: \"%s\"", path); - smcore.LogError("[SM] Parse error (line %d, column %d): %s", states.line, states.col, str_err); + logger->LogError("[SM] Failed to parse language header file: \"%s\"", path); + logger->LogError("[SM] Parse error (line %d, column %d): %s", states.line, states.col, str_err); } if (!m_LCodeLookup.retrieve(m_InitialLang, &m_ServerLang)) { - smcore.LogError("Server language was set to bad language \"%s\" -- reverting to English", m_InitialLang); + logger->LogError("Server language was set to bad language \"%s\" -- reverting to English", m_InitialLang); smcore.strncopy(m_InitialLang, "en", sizeof(m_InitialLang)); m_ServerLang = SOURCEMOD_LANGUAGE_ENGLISH; @@ -845,7 +845,7 @@ void Translator::RebuildLanguageDatabase() if (!m_Languages.size()) { - smcore.LogError("[SM] Fatal error, no languages found! Translation will not work."); + logger->LogError("[SM] Fatal error, no languages found! Translation will not work."); } for (size_t i=0; iLogError("[SM] Warning: Unrecognized section \"%s\" in languages.cfg", name); } return SMCResult_Continue; @@ -1025,11 +1025,11 @@ bool CoreTranslate(char *buffer, size_t maxlength, const char *format, unsigned { if (fail_phrase != NULL) { - smcore.LogError("[SM] Could not find core phrase: %s", fail_phrase); + logger->LogError("[SM] Could not find core phrase: %s", fail_phrase); } else { - smcore.LogError("[SM] Unknown fatal error while translating a core phrase."); + logger->LogError("[SM] Unknown fatal error while translating a core phrase."); } return false; diff --git a/core/logic/common_logic.cpp b/core/logic/common_logic.cpp index 7c988b5f..868f66df 100644 --- a/core/logic/common_logic.cpp +++ b/core/logic/common_logic.cpp @@ -50,6 +50,7 @@ #include "ForwardSys.h" #include "AdminCache.h" #include "ProfileTools.h" +#include "Logger.h" sm_core_t smcore; IHandleSys *handlesys = &g_HandleSys; @@ -72,6 +73,8 @@ ISourcePawnEngine *g_pSourcePawn; ISourcePawnEngine2 *g_pSourcePawn2; CNativeOwner g_CoreNatives; IScriptManager *scripts = &g_PluginSys; +IExtensionSys *extsys = &g_Extensions; +ILogger *logger = &g_Logger; static void AddCorePhraseFile(const char *filename) { @@ -140,6 +143,7 @@ static sm_logic_t logic = &g_Forwards, &g_Admins, NULL, + &g_Logger, -1.0f }; diff --git a/core/logic/common_logic.h b/core/logic/common_logic.h index f008d4e3..45f9fc64 100644 --- a/core/logic/common_logic.h +++ b/core/logic/common_logic.h @@ -53,6 +53,8 @@ extern IPlayerManager *playerhelpers; extern IAdminSystem *adminsys; extern IGameHelpers *gamehelpers; extern IScriptManager *scripts; +extern IExtensionSys *extsys; +extern ILogger *logger; #endif /* _INCLUDE_SOURCEMOD_COMMON_LOGIC_H_ */ diff --git a/core/logic/intercom.h b/core/logic/intercom.h index b28c5a91..2fa40410 100644 --- a/core/logic/intercom.h +++ b/core/logic/intercom.h @@ -52,7 +52,7 @@ using namespace SourceHook; * Add 1 to the RHS of this expression to bump the intercom file * This is to prevent mismatching core/logic binaries */ -#define SM_LOGIC_MAGIC (0x0F47C0DE - 28) +#define SM_LOGIC_MAGIC (0x0F47C0DE - 29) #if defined SM_LOGIC class IVEngineServer @@ -214,6 +214,14 @@ public: virtual void CallOnCoreMapEnd() = 0; }; +class ILogger +{ +public: + virtual void LogMessage(const char *msg, ...) = 0; + virtual void LogError(const char *msg, ...) = 0; + virtual void LogFatal(const char *msg, ...) = 0; +}; + class AutoPluginList { public: @@ -274,13 +282,10 @@ struct sm_core_t ConVar * (*FindConVar)(const char*); unsigned int (*strncopy)(char*, const char*, size_t); char * (*TrimWhitespace)(char *, size_t &); - void (*LogError)(const char*, ...); - void (*LogFatal)(const char*, ...); - void (*Log)(const char*, ...); - void (*LogToFile)(FILE *fp, const char*, ...); void (*LogToGame)(const char *message); void (*ConPrint)(const char *message); const char * (*GetCvarString)(ConVar*); + bool (*GetCvarBool)(ConVar*); size_t (*Format)(char*, size_t, const char*, ...); size_t (*FormatArgs)(char*, size_t, const char*,va_list ap); bool (*gnprintf)(char *, size_t, const char *, IPhraseCollection *, void **, @@ -326,7 +331,7 @@ struct sm_logic_t char *(*ReplaceEx)(char *, size_t, const char *, size_t, const char *, size_t, bool); size_t (*DecodeHexString)(unsigned char *, size_t, const char *); IGameConfig * (*GetCoreGameConfig)(); - bool (*OnLogPrint)(const char *msg); // true to supercede + bool (*OnLogPrint)(const char *msg); // true to supersede IDebugListener *debugger; void (*GenerateError)(IPluginContext *, cell_t, int, const char *, ...); void (*AddNatives)(sp_nativeinfo_t *natives); @@ -340,6 +345,7 @@ struct sm_logic_t IForwardManager *forwardsys; IAdminSystem *adminsys; IdentityToken_t *core_ident; + ILogger *logger; float sentinel; }; diff --git a/core/smn_core.cpp b/core/logic/smn_core.cpp similarity index 88% rename from core/smn_core.cpp rename to core/logic/smn_core.cpp index 4d301db4..50eb0e5d 100644 --- a/core/smn_core.cpp +++ b/core/logic/smn_core.cpp @@ -32,14 +32,14 @@ #include #include #include -#include "sm_stringutil.h" -#include "sm_globals.h" -#include "sourcemod.h" -#include "LibrarySys.h" -#include "TimerSys.h" +#include "common_logic.h" #include "Logger.h" + +#include +#include + +#include #include -#include "logic_bridge.h" #if defined PLATFORM_WINDOWS #include @@ -50,9 +50,11 @@ #endif HandleType_t g_PlIter; -ConVar sm_datetime_format("sm_datetime_format", "%m/%d/%Y - %H:%M:%S", 0, "Default formatting time rules"); + IForward *g_OnLogAction = NULL; +static ConVar *sm_datetime_format = NULL; + class CoreNativeHelpers : public SMGlobalClass, public IHandleTypeDispatch @@ -75,6 +77,8 @@ public: Param_Cell, Param_Cell, Param_String); + + sm_datetime_format = smcore.FindConVar("sm_datetime_format"); } void OnHandleDestroy(HandleType_t type, void *object) { @@ -119,14 +123,14 @@ void LogAction(Handle_t hndl, int type, int client, int target, const char *mess g_Logger.LogMessage("[%s] %s", logtag, message); } - -static cell_t ThrowError(IPluginContext *pContext, const cell_t *params) + + static cell_t ThrowError(IPluginContext *pContext, const cell_t *params) { char buffer[512]; - g_SourceMod.SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE); + g_pSM->SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE); - g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 1); + g_pSM->FormatString(buffer, sizeof(buffer), pContext, params, 1); if (pContext->GetLastNativeError() == SP_ERROR_NONE) { @@ -138,7 +142,7 @@ static cell_t ThrowError(IPluginContext *pContext, const cell_t *params) static cell_t GetTime(IPluginContext *pContext, const cell_t *params) { - time_t t = GetAdjustedTime(); + time_t t = g_pSM->GetAdjustedTime(); cell_t *addr; pContext->LocalToPhysAddr(params[1], &addr); @@ -168,14 +172,14 @@ static cell_t FormatTime(IPluginContext *pContext, const cell_t *params) if (format == NULL) { - format = const_cast(sm_datetime_format.GetString()); + format = const_cast(smcore.GetCvarString(sm_datetime_format)); } #if defined SUBPLATFORM_SECURECRT _invalid_parameter_handler handler = _set_invalid_parameter_handler(_ignore_invalid_parameter); #endif - time_t t = (params[4] == -1) ? GetAdjustedTime() : (time_t)params[4]; + time_t t = (params[4] == -1) ? g_pSM->GetAdjustedTime() : (time_t)params[4]; size_t written = strftime(buffer, params[2], format, localtime(&t)); #if defined SUBPLATFORM_SECURECRT @@ -384,7 +388,7 @@ static cell_t SetFailState(IPluginContext *pContext, const cell_t *params) { char buffer[2048]; - g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 1); + g_pSM->FormatString(buffer, sizeof(buffer), pContext, params, 1); if (pContext->GetLastNativeError() != SP_ERROR_NONE) { pPlugin->SetErrorState(Plugin_Error, "%s", str); @@ -433,14 +437,14 @@ static cell_t AutoExecConfig(IPluginContext *pContext, const cell_t *params) static char temp_file[PLATFORM_MAX_PATH]; char *ptr; - g_LibSys.GetFileFromPath(temp_str, sizeof(temp_str), plugin->GetFilename()); + libsys->GetFileFromPath(temp_str, sizeof(temp_str), plugin->GetFilename()); if ((ptr = strstr(temp_str, ".smx")) != NULL) { *ptr = '\0'; } /* We have the raw filename! */ - UTIL_Format(temp_file, sizeof(temp_file), "plugin.%s", temp_str); + g_pSM->Format(temp_file, sizeof(temp_file), "plugin.%s", temp_str); cfg = temp_file; } @@ -506,8 +510,8 @@ static cell_t LibraryExists(IPluginContext *pContext, const cell_t *params) static cell_t sm_LogAction(IPluginContext *pContext, const cell_t *params) { char buffer[2048]; - g_SourceMod.SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE); - g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 3); + g_pSM->SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE); + g_pSM->FormatString(buffer, sizeof(buffer), pContext, params, 3); if (pContext->GetLastNativeError() != SP_ERROR_NONE) { @@ -527,7 +531,7 @@ static cell_t LogToFile(IPluginContext *pContext, const cell_t *params) pContext->LocalToString(params[1], &file); char path[PLATFORM_MAX_PATH]; - g_SourceMod.BuildPath(Path_Game, path, sizeof(path), "%s", file); + g_pSM->BuildPath(Path_Game, path, sizeof(path), "%s", file); FILE *fp = fopen(path, "at"); if (!fp) @@ -536,8 +540,8 @@ static cell_t LogToFile(IPluginContext *pContext, const cell_t *params) } char buffer[2048]; - g_SourceMod.SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE); - g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2); + g_pSM->SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE); + g_pSM->FormatString(buffer, sizeof(buffer), pContext, params, 2); if (pContext->GetLastNativeError() != SP_ERROR_NONE) { @@ -560,7 +564,7 @@ static cell_t LogToFileEx(IPluginContext *pContext, const cell_t *params) pContext->LocalToString(params[1], &file); char path[PLATFORM_MAX_PATH]; - g_SourceMod.BuildPath(Path_Game, path, sizeof(path), "%s", file); + g_pSM->BuildPath(Path_Game, path, sizeof(path), "%s", file); FILE *fp = fopen(path, "at"); if (!fp) @@ -569,8 +573,8 @@ static cell_t LogToFileEx(IPluginContext *pContext, const cell_t *params) } char buffer[2048]; - g_SourceMod.SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE); - g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2); + g_pSM->SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE); + g_pSM->FormatString(buffer, sizeof(buffer), pContext, params, 2); if (pContext->GetLastNativeError() != SP_ERROR_NONE) { @@ -653,10 +657,10 @@ static cell_t RequireFeature(IPluginContext *pContext, const cell_t *params) char default_message[255]; SMPlugin *pPlugin = scripts->FindPluginByContext(pContext->GetContext()); - g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 3); + g_pSM->FormatString(buffer, sizeof(buffer), pContext, params, 3); if (pContext->GetLastNativeError() != SP_ERROR_NONE || buffer[0] == '\0') { - UTIL_Format(default_message, sizeof(default_message), "Feature \"%s\" not available", name); + g_pSM->Format(default_message, sizeof(default_message), "Feature \"%s\" not available", name); msg = default_message; } pPlugin->SetErrorState(Plugin_Error, "%s", msg); @@ -743,19 +747,19 @@ static cell_t StoreToAddress(IPluginContext *pContext, const cell_t *params) REGISTER_NATIVES(coreNatives) { - {"AutoExecConfig", AutoExecConfig}, - {"GetPluginFilename", GetPluginFilename}, - {"GetPluginInfo", GetPluginInfo}, - {"GetPluginIterator", GetPluginIterator}, - {"GetPluginStatus", GetPluginStatus}, - {"GetSysTickCount", GetSysTickCount}, + {"ThrowError", ThrowError}, {"GetTime", GetTime}, - {"IsPluginDebugging", IsPluginDebugging}, + {"FormatTime", FormatTime}, + {"GetPluginIterator", GetPluginIterator}, {"MorePlugins", MorePlugins}, {"ReadPlugin", ReadPlugin}, - {"ThrowError", ThrowError}, + {"GetPluginStatus", GetPluginStatus}, + {"GetPluginFilename", GetPluginFilename}, + {"IsPluginDebugging", IsPluginDebugging}, + {"GetPluginInfo", GetPluginInfo}, {"SetFailState", SetFailState}, - {"FormatTime", FormatTime}, + {"GetSysTickCount", GetSysTickCount}, + {"AutoExecConfig", AutoExecConfig}, {"MarkNativeAsOptional", MarkNativeAsOptional}, {"RegPluginLibrary", RegPluginLibrary}, {"LibraryExists", LibraryExists}, @@ -770,5 +774,4 @@ REGISTER_NATIVES(coreNatives) {"LoadFromAddress", LoadFromAddress}, {"StoreToAddress", StoreToAddress}, {NULL, NULL}, -}; - +}; \ No newline at end of file diff --git a/core/logic/smn_filesystem.cpp b/core/logic/smn_filesystem.cpp index 0fb7b16e..82430e52 100644 --- a/core/logic/smn_filesystem.cpp +++ b/core/logic/smn_filesystem.cpp @@ -38,6 +38,7 @@ #include #include #include "common_logic.h" +#include "Logger.h" #if defined PLATFORM_WINDOWS #include @@ -637,7 +638,7 @@ static cell_t sm_LogMessage(IPluginContext *pContext, const cell_t *params) } IPlugin *pPlugin = pluginsys->FindPluginByContext(pContext->GetContext()); - smcore.Log("[%s] %s", pPlugin->GetFilename(), buffer); + g_Logger.LogMessage("[%s] %s", pPlugin->GetFilename(), buffer); return 1; } @@ -655,7 +656,7 @@ static cell_t sm_LogError(IPluginContext *pContext, const cell_t *params) } IPlugin *pPlugin = pluginsys->FindPluginByContext(pContext->GetContext()); - smcore.LogError("[%s] %s", pPlugin->GetFilename(), buffer); + g_Logger.LogError("[%s] %s", pPlugin->GetFilename(), buffer); return 1; } @@ -708,7 +709,7 @@ static cell_t sm_LogToOpenFile(IPluginContext *pContext, const cell_t *params) } IPlugin *pPlugin = pluginsys->FindPluginByContext(pContext->GetContext()); - smcore.LogToFile(pFile, "[%s] %s", pPlugin->GetFilename(), buffer); + g_Logger.LogToOpenFile(pFile, "[%s] %s", pPlugin->GetFilename(), buffer); return 1; } @@ -738,7 +739,7 @@ static cell_t sm_LogToOpenFileEx(IPluginContext *pContext, const cell_t *params) return 0; } - smcore.LogToFile(pFile, "%s", buffer); + g_Logger.LogToOpenFile(pFile, "%s", buffer); return 1; } diff --git a/core/logic/smn_maplists.cpp b/core/logic/smn_maplists.cpp index 00a19a95..9faba5d8 100644 --- a/core/logic/smn_maplists.cpp +++ b/core/logic/smn_maplists.cpp @@ -202,8 +202,8 @@ public: { errmsg = "Unknown error"; } - smcore.LogError("[SM] Could not parse file \"%s\"", m_ConfigFile); - smcore.LogError("[SM] Error on line %d (col %d): %s", states.line, states.col, errmsg); + logger->LogError("[SM] Could not parse file \"%s\"", m_ConfigFile); + logger->LogError("[SM] Error on line %d (col %d): %s", states.line, states.col, errmsg); } else { diff --git a/core/logic/smn_players.cpp b/core/logic/smn_players.cpp index 55d4fcbf..47288f0a 100644 --- a/core/logic/smn_players.cpp +++ b/core/logic/smn_players.cpp @@ -120,7 +120,7 @@ public: //ICommandTargetProcessor Handle_t hndl = handlesys->CreateHandleEx(htCellArray, array, &sec, NULL, NULL); AutoHandleCloner ahc(hndl, sec); if (ahc.getClone() == BAD_HANDLE) { - smcore.LogError("[SM] Could not allocate a handle (%s, %d)", __FILE__, __LINE__); + logger->LogError("[SM] Could not allocate a handle (%s, %d)", __FILE__, __LINE__); delete array; return false; } diff --git a/core/logic_bridge.cpp b/core/logic_bridge.cpp index 057f660c..13fba9fe 100644 --- a/core/logic_bridge.cpp +++ b/core/logic_bridge.cpp @@ -86,6 +86,7 @@ IExtensionSys *extsys; IHandleSys *handlesys; IForwardManager *forwardsys; IAdminSystem *adminsys; +ILogger *logger; class VEngineServer_Logic : public IVEngineServer_Logic { @@ -251,46 +252,13 @@ static VPlayerInfo_Logic logic_playerinfo; static ConVar sm_show_activity("sm_show_activity", "13", FCVAR_SPONLY, "Activity display setting (see sourcemod.cfg)"); static ConVar sm_immunity_mode("sm_immunity_mode", "1", FCVAR_SPONLY, "Mode for deciding immunity protection"); +static ConVar sm_datetime_format("sm_datetime_format", "%m/%d/%Y - %H:%M:%S", 0, "Default formatting time rules"); static ConVar *find_convar(const char *name) { return icvar->FindVar(name); } -static void log_error(const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - g_Logger.LogErrorEx(fmt, ap); - va_end(ap); -} - -static void log_fatal(const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - g_Logger.LogFatalEx(fmt, ap); - va_end(ap); -} - -static void log_message(const char *fmt, ...) -{ - va_list ap; - va_start(ap, fmt); - g_Logger.LogMessageEx(fmt, ap); - va_end(ap); -} - -static void log_to_file(FILE *fp, const char *fmt, ...) -{ - va_list ap; - va_start(ap, fmt); - g_Logger.LogToOpenFileEx(fp, fmt, ap); - va_end(ap); -} - static void log_to_game(const char *message) { Engine_LogPrintWrapper(message); @@ -306,6 +274,11 @@ static const char *get_cvar_string(ConVar* cvar) return cvar->GetString(); } +static bool get_cvar_bool(ConVar* cvar) +{ + return cvar->GetBool(); +} + static bool get_game_name(char *buffer, size_t maxlength) { KeyValues *pGameInfo = new KeyValues("GameInfo"); @@ -561,13 +534,10 @@ static sm_core_t core_bridge = find_convar, strncopy, UTIL_TrimWhitespace, - log_error, - log_fatal, - log_message, - log_to_file, log_to_game, conprint, get_cvar_string, + get_cvar_bool, UTIL_Format, UTIL_FormatArgs, gnprintf, @@ -636,6 +606,7 @@ void InitLogicBridge() handlesys = logicore.handlesys; forwardsys = logicore.forwardsys; adminsys = logicore.adminsys; + logger = logicore.logger; } bool StartLogicBridge(char *error, size_t maxlength) diff --git a/core/logic_bridge.h b/core/logic_bridge.h index 76372a7c..34f6de1a 100644 --- a/core/logic_bridge.h +++ b/core/logic_bridge.h @@ -48,5 +48,6 @@ extern IExtensionSys *extsys; extern IHandleSys *handlesys; extern IForwardManager *forwardsys; extern IAdminSystem *adminsys; +extern ILogger *logger; #endif /* _INCLUDE_SOURCEMOD_LOGIC_BRIDGE_H_ */ diff --git a/core/smn_console.cpp b/core/smn_console.cpp index d92fc492..eda2529b 100644 --- a/core/smn_console.cpp +++ b/core/smn_console.cpp @@ -1216,7 +1216,7 @@ static cell_t AddCommandListener(IPluginContext *pContext, const cell_t *params) if (strcasecmp(name, "sm") == 0) { - g_Logger.LogError("Request to register \"sm\" command denied."); + logger->LogError("Request to register \"sm\" command denied."); return 0; } diff --git a/core/sourcemm_api.cpp b/core/sourcemm_api.cpp index 306965a8..15a679a4 100644 --- a/core/sourcemm_api.cpp +++ b/core/sourcemm_api.cpp @@ -167,7 +167,7 @@ void SourceMod_Core::OnVSPListening(IServerPluginCallbacks *iface) /* This shouldn't happen */ if (!iface) { - g_Logger.LogFatal("Metamod:Source version is out of date. SourceMod requires 1.4.2 or greater."); + logger->LogFatal("Metamod:Source version is out of date. SourceMod requires 1.4.2 or greater."); return; } diff --git a/core/sourcemod.cpp b/core/sourcemod.cpp index 32fa99ff..5d68eb1d 100644 --- a/core/sourcemod.cpp +++ b/core/sourcemod.cpp @@ -573,9 +573,9 @@ void SourceModBase::LogMessage(IExtension *pExt, const char *format, ...) if (tag) { - g_Logger.LogMessage("[%s] %s", tag, buffer); + logger->LogMessage("[%s] %s", tag, buffer); } else { - g_Logger.LogMessage("%s", buffer); + logger->LogMessage("%s", buffer); } } @@ -592,9 +592,9 @@ void SourceModBase::LogError(IExtension *pExt, const char *format, ...) if (tag) { - g_Logger.LogError("[%s] %s", tag, buffer); + logger->LogError("[%s] %s", tag, buffer); } else { - g_Logger.LogError("%s", buffer); + logger->LogError("%s", buffer); } }