From aab0eeaa1ee5de3f41a0aa0685ea35f08735ab05 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Mon, 27 Aug 2007 02:00:37 +0000 Subject: [PATCH] - implemented amb855 - LogAction() - changed base plugins to use LogAction() where appropriate --HG-- extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%401384 --- core/Logger.cpp | 67 +++++++++++------ core/Logger.h | 3 + core/smn_core.cpp | 132 ++++++++++++++++++++++++++++++++++ core/smn_filesystem.cpp | 84 ++++++++++++++++++++-- plugins/basechat.sp | 22 +++--- plugins/basecommands.sp | 26 +++---- plugins/basefuncommands.sp | 8 +-- plugins/basefunvotes.sp | 22 ++++-- plugins/basevotes.sp | 16 +++-- plugins/include/core.inc | 10 +++ plugins/include/files.inc | 25 +++++++ plugins/include/sourcemod.inc | 70 +++++++++++++++++- 12 files changed, 419 insertions(+), 66 deletions(-) diff --git a/core/Logger.cpp b/core/Logger.cpp index d1b16f3d..4204275c 100644 --- a/core/Logger.cpp +++ b/core/Logger.cpp @@ -228,6 +228,39 @@ 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::LogToOpenFileEx(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); + g_SMAPI->ConPrintf("L %s: %s\n", date, buffer); +} + void Logger::LogMessage(const char *vafmt, ...) { if (!m_Active) @@ -250,17 +283,9 @@ void Logger::LogMessage(const char *vafmt, ...) _NewMapFile(); } - char msg[3072]; - va_list ap; - va_start(ap, vafmt); - vsnprintf(msg, sizeof(msg), vafmt, ap); - va_end(ap); - - char date[32]; time_t t; GetAdjustedTime(&t); tm *curtime = localtime(&t); - strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime); FILE *fp = NULL; if (m_Mode == LoggingMode_PerMap) @@ -291,16 +316,20 @@ void Logger::LogMessage(const char *vafmt, ...) { 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, SVN_FULL_VERSION); } - fprintf(fp, "L %s: %s\n", date, msg); + va_list ap; + va_start(ap, vafmt); + LogToOpenFileEx(fp, vafmt, ap); + va_end(ap); fclose(fp); } else { goto print_error; } - g_SMAPI->ConPrintf("L %s: %s\n", date, msg); return; print_error: g_SMAPI->ConPrint("[SM] Unexpected fatal logging error. SourceMod logging disabled.\n"); @@ -318,9 +347,6 @@ void Logger::LogError(const char *vafmt, ...) GetAdjustedTime(&t); tm *curtime = localtime(&t); - char date[32]; - strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime); - if (curtime->tm_mday != m_CurDay) { char _filename[256]; @@ -330,30 +356,27 @@ void Logger::LogError(const char *vafmt, ...) m_ErrMapStart = false; } - char msg[3072]; - va_list ap; - va_start(ap, vafmt); - vsnprintf(msg, sizeof(msg), vafmt, ap); - va_end(ap); - 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; } - fprintf(fp, "L %s: %s\n", date, msg); + va_list ap; + va_start(ap, vafmt); + LogToOpenFileEx(fp, vafmt, ap); + va_end(ap); fclose(fp); } else { g_SMAPI->ConPrint("[SM] Unexpected fatal logging error. SourceMod logging disabled.\n"); m_Active = false; return; } - - g_SMAPI->ConPrintf("L %s: %s\n", date, msg); } void Logger::MapChange(const char *mapname) diff --git a/core/Logger.h b/core/Logger.h index 40fcf49a..0f6e22ed 100644 --- a/core/Logger.h +++ b/core/Logger.h @@ -32,6 +32,7 @@ #ifndef _INCLUDE_SOURCEMOD_CLOGGER_H_ #define _INCLUDE_SOURCEMOD_CLOGGER_H_ +#include #include #include "sm_globals.h" @@ -75,6 +76,8 @@ public: void LogMessage(const char *msg, ...); void LogError(const char *msg, ...); void LogFatal(const char *msg, ...); + void LogToOpenFile(FILE *fp, const char *msg, ...); + void LogToOpenFileEx(FILE *fp, const char *msg, va_list ap); void MapChange(const char *mapname); const char *GetLogFileName(LogType type) const; LoggingMode GetLoggingMode() const; diff --git a/core/smn_core.cpp b/core/smn_core.cpp index ad988d6d..766fc197 100644 --- a/core/smn_core.cpp +++ b/core/smn_core.cpp @@ -39,6 +39,8 @@ #include "HandleSys.h" #include "LibrarySys.h" #include "TimerSys.h" +#include "ForwardSys.h" +#include "Logger.h" #if defined PLATFORM_WINDOWS #include @@ -50,6 +52,7 @@ 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; class CoreNativeHelpers : public SMGlobalClass, @@ -63,6 +66,16 @@ public: hacc.access[HandleAccess_Clone] = HANDLE_RESTRICT_IDENTITY|HANDLE_RESTRICT_OWNER; g_PlIter = g_HandleSys.CreateType("PluginIterator", this, 0, NULL, NULL, g_pCoreIdent, NULL); + + g_OnLogAction = g_Forwards.CreateForward("OnLogAction", + ET_Hook, + 5, + NULL, + Param_Cell, + Param_Cell, + Param_Cell, + Param_Cell, + Param_String); } void OnHandleDestroy(HandleType_t type, void *object) { @@ -71,10 +84,44 @@ public: } void OnSourceModShutdown() { + g_Forwards.ReleaseForward(g_OnLogAction); g_HandleSys.RemoveType(g_PlIter, g_pCoreIdent); } } g_CoreNativeHelpers; +void LogAction(Handle_t hndl, int type, int client, int target, const char *message) +{ + if (!g_OnLogAction->GetFunctionCount()) + { + return; + } + + cell_t result = 0; + g_OnLogAction->PushCell(hndl); + g_OnLogAction->PushCell(type); + g_OnLogAction->PushCell(client); + g_OnLogAction->PushCell(target); + g_OnLogAction->PushString(message); + g_OnLogAction->Execute(&result); + + if (result >= (ResultType)Pl_Handled) + { + return; + } + + const char *logtag = "SM"; + if (type == 2) + { + HandleError err; + IPlugin *pPlugin = g_PluginSys.PluginFromHandle(hndl, &err); + if (pPlugin) + { + logtag = pPlugin->GetFilename(); + } + } + + g_Logger.LogMessage("[%s] %s", logtag, message); +} static cell_t ThrowError(IPluginContext *pContext, const cell_t *params) { @@ -420,6 +467,88 @@ static cell_t LibraryExists(IPluginContext *pContext, const cell_t *params) return g_PluginSys.LibraryExists(str) ? 1 : 0; } +static cell_t sm_LogAction(IPluginContext *pContext, const cell_t *params) +{ + char buffer[2048]; + g_SourceMod.SetGlobalTarget(LANG_SERVER); + g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 3); + + if (pContext->GetContext()->n_err != SP_ERROR_NONE) + { + return 0; + } + + CPlugin *pPlugin = g_PluginSys.GetPluginByCtx(pContext->GetContext()); + + LogAction(pPlugin->GetMyHandle(), 2, params[1], params[2], buffer); + + return 1; +} + +static cell_t LogToFile(IPluginContext *pContext, const cell_t *params) +{ + char *file; + pContext->LocalToString(params[1], &file); + + char path[PLATFORM_MAX_PATH]; + g_SourceMod.BuildPath(Path_Game, path, sizeof(path), "%s", file); + + FILE *fp = fopen(path, "at"); + if (!fp) + { + return pContext->ThrowNativeError("Could not open file \"%s\"", path); + } + + char buffer[2048]; + g_SourceMod.SetGlobalTarget(LANG_SERVER); + g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2); + + if (pContext->GetContext()->n_err != SP_ERROR_NONE) + { + fclose(fp); + return 0; + } + + CPlugin *pPlugin = g_PluginSys.GetPluginByCtx(pContext->GetContext()); + + g_Logger.LogToOpenFile(fp, "[%s] %s", pPlugin->GetFilename(), buffer); + + fclose(fp); + + return 1; +} + +static cell_t LogToFileEx(IPluginContext *pContext, const cell_t *params) +{ + char *file; + pContext->LocalToString(params[1], &file); + + char path[PLATFORM_MAX_PATH]; + g_SourceMod.BuildPath(Path_Game, path, sizeof(path), "%s", file); + + FILE *fp = fopen(path, "at"); + if (!fp) + { + return pContext->ThrowNativeError("Could not open file \"%s\"", path); + } + + char buffer[2048]; + g_SourceMod.SetGlobalTarget(LANG_SERVER); + g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2); + + if (pContext->GetContext()->n_err != SP_ERROR_NONE) + { + fclose(fp); + return 0; + } + + g_Logger.LogToOpenFile(fp, "%s", buffer); + + fclose(fp); + + return 1; +} + REGISTER_NATIVES(coreNatives) { {"AutoExecConfig", AutoExecConfig}, @@ -438,5 +567,8 @@ REGISTER_NATIVES(coreNatives) {"MarkNativeAsOptional", MarkNativeAsOptional}, {"RegPluginLibrary", RegPluginLibrary}, {"LibraryExists", LibraryExists}, + {"LogAction", sm_LogAction}, + {"LogToFile", LogToFile}, + {"LogToFileEx", LogToFileEx}, {NULL, NULL}, }; diff --git a/core/smn_filesystem.cpp b/core/smn_filesystem.cpp index c89d4513..f5e36bda 100644 --- a/core/smn_filesystem.cpp +++ b/core/smn_filesystem.cpp @@ -69,8 +69,7 @@ public: g_LibSys.CloseDirectory(pDir); } } -}; - +} s_FileNatives; static cell_t sm_OpenDirectory(IPluginContext *pContext, const cell_t *params) { @@ -503,6 +502,11 @@ static cell_t sm_LogToGame(IPluginContext *pContext, const cell_t *params) char buffer[1024]; size_t len = g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 1); + if (pContext->GetContext()->n_err != SP_ERROR_NONE) + { + return 0; + } + if (len >= sizeof(buffer)-2) { buffer[1022] = '\n'; @@ -524,7 +528,12 @@ static cell_t sm_LogMessage(IPluginContext *pContext, const cell_t *params) char buffer[1024]; g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 1); - IPlugin *pPlugin = g_PluginSys.FindPluginByContext(pContext->GetContext()); + if (pContext->GetContext()->n_err != SP_ERROR_NONE) + { + return 0; + } + + CPlugin *pPlugin = g_PluginSys.GetPluginByCtx(pContext->GetContext()); g_Logger.LogMessage("[%s] %s", pPlugin->GetFilename(), buffer); return 1; @@ -537,7 +546,12 @@ static cell_t sm_LogError(IPluginContext *pContext, const cell_t *params) char buffer[1024]; g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 1); - IPlugin *pPlugin = g_PluginSys.FindPluginByContext(pContext->GetContext()); + if (pContext->GetContext()->n_err != SP_ERROR_NONE) + { + return 0; + } + + CPlugin *pPlugin = g_PluginSys.GetPluginByCtx(pContext->GetContext()); g_Logger.LogError("[%s] %s", pPlugin->GetFilename(), buffer); return 1; @@ -586,7 +600,66 @@ static cell_t sm_GetFileTime(IPluginContext *pContext, const cell_t *params) return -1; } -static FileNatives s_FileNatives; +static cell_t sm_LogToOpenFile(IPluginContext *pContext, const cell_t *params) +{ + Handle_t hndl = static_cast(params[1]); + HandleError herr; + HandleSecurity sec; + FILE *pFile; + + sec.pOwner = NULL; + sec.pIdentity = g_pCoreIdent; + + if ((herr=g_HandleSys.ReadHandle(hndl, g_FileType, &sec, (void **)&pFile)) + != HandleError_None) + { + return pContext->ThrowNativeError("Invalid file handle %x (error %d)", hndl, herr); + } + + char buffer[2048]; + g_SourceMod.SetGlobalTarget(LANG_SERVER); + g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2); + + if (pContext->GetContext()->n_err != SP_ERROR_NONE) + { + return 0; + } + + CPlugin *pPlugin = g_PluginSys.GetPluginByCtx(pContext->GetContext()); + g_Logger.LogToOpenFile(pFile, "[%s] %s", pPlugin->GetFilename(), buffer); + + return 1; +} + +static cell_t sm_LogToOpenFileEx(IPluginContext *pContext, const cell_t *params) +{ + Handle_t hndl = static_cast(params[1]); + HandleError herr; + HandleSecurity sec; + FILE *pFile; + + sec.pOwner = NULL; + sec.pIdentity = g_pCoreIdent; + + if ((herr=g_HandleSys.ReadHandle(hndl, g_FileType, &sec, (void **)&pFile)) + != HandleError_None) + { + return pContext->ThrowNativeError("Invalid file handle %x (error %d)", hndl, herr); + } + + char buffer[2048]; + g_SourceMod.SetGlobalTarget(LANG_SERVER); + g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2); + + if (pContext->GetContext()->n_err != SP_ERROR_NONE) + { + return 0; + } + + g_Logger.LogToOpenFile(pFile, "%s", buffer); + + return 1; +} REGISTER_NATIVES(filesystem) { @@ -610,5 +683,6 @@ REGISTER_NATIVES(filesystem) {"LogError", sm_LogError}, {"FlushFile", sm_FlushFile}, {"GetFileTime", sm_GetFileTime}, + {"LogToOpenFile", sm_LogToOpenFile}, {NULL, NULL}, }; diff --git a/plugins/basechat.sp b/plugins/basechat.sp index ade38358..57a20831 100644 --- a/plugins/basechat.sp +++ b/plugins/basechat.sp @@ -112,12 +112,12 @@ public Action:Command_SayChat(client, args) if (msgStart == 1 && CheckAdminForChat(client)) // sm_say alias { SendChatToAll(name, message); - LogMessage("%L triggered sm_say (text %s)", client, message); + LogAction(client, -1, "%L triggered sm_say (text %s)", client, message); } else if (msgStart == 3 && CheckAdminForChat(client)) // sm_csay alias { PrintCenterTextAll("%s: %s", name, message); - LogMessage("%L triggered sm_csay (text %s)", client, text); + LogAction(client, -1, "%L triggered sm_csay (text %s)", client, text); } else if (msgStart == 2 && (CheckAdminForChat(client) || GetConVarBool(g_Cvar_Psaymode))) // sm_psay alias { @@ -143,7 +143,7 @@ public Action:Command_SayChat(client, args) PrintToChat(target, "(Private to %s) %s: %s", name2, name, message[len]); } - LogMessage("%L triggered sm_psay to %L (text %s)", client, target, message); + LogAction(client, -1, "%L triggered sm_psay to %L (text %s)", client, target, message); } else return Plugin_Continue; @@ -176,7 +176,7 @@ public Action:Command_SayAdmin(client, args) GetClientName(client, name, sizeof(name)); SendChatToAdmins(name, message); - LogMessage("%L triggered sm_chat (text %s)", client, message); + LogAction(client, -1, "%L triggered sm_chat (text %s)", client, message); return Plugin_Handled; } @@ -196,7 +196,7 @@ public Action:Command_SmSay(client, args) GetClientName(client, name, sizeof(name)); SendChatToAll(name, text); - LogMessage("%L triggered sm_say (text %s)", client, text); + LogAction(client, -1, "%L triggered sm_say (text %s)", client, text); return Plugin_Handled; } @@ -216,7 +216,7 @@ public Action:Command_SmCsay(client, args) GetClientName(client, name, sizeof(name)); PrintCenterTextAll("%s: %s", name, text); - LogMessage("%L triggered sm_csay (text %s)", client, text); + LogAction(client, -1, "%L triggered sm_csay (text %s)", client, text); return Plugin_Handled; } @@ -236,7 +236,7 @@ public Action:Command_SmHsay(client, args) GetClientName(client, name, sizeof(name)); PrintHintTextToAll("%s: %s", name, text); - LogMessage("%L triggered sm_hsay (text %s)", client, text); + LogAction(client, -1, "%L triggered sm_hsay (text %s)", client, text); return Plugin_Handled; } @@ -264,7 +264,7 @@ public Action:Command_SmTsay(client, args) else SendDialogToAll(color, "%s: %s", name, text[len]); - LogMessage("%L triggered sm_tsay (text %s)", client, text); + LogAction(client, -1, "%L triggered sm_tsay (text %s)", client, text); return Plugin_Handled; } @@ -284,7 +284,7 @@ public Action:Command_SmChat(client, args) GetClientName(client, name, sizeof(name)); SendChatToAdmins(name, text); - LogMessage("%L triggered sm_chat (text %s)", client, text); + LogAction(client, -1, "%L triggered sm_chat (text %s)", client, text); return Plugin_Handled; } @@ -323,7 +323,7 @@ public Action:Command_SmPsay(client, args) PrintToChat(target, "(Private: %s) %s: %s", name2, name, message); } - LogMessage("%L triggered sm_psay to %L (text %s)", client, target, message); + LogAction(client, -1, "%L triggered sm_psay to %L (text %s)", client, target, message); return Plugin_Handled; } @@ -344,7 +344,7 @@ public Action:Command_SmMsay(client, args) SendPanelToAll(name, text); - LogMessage("%L triggered sm_msay (text %s)", client, text); + LogAction(client, -1, "%L triggered sm_msay (text %s)", client, text); return Plugin_Handled; } diff --git a/plugins/basecommands.sp b/plugins/basecommands.sp index 0a62404d..29580132 100644 --- a/plugins/basecommands.sp +++ b/plugins/basecommands.sp @@ -76,7 +76,7 @@ public Action:Command_ReloadAdmins(client, args) DumpAdminCache(AdminCache_Groups, true); DumpAdminCache(AdminCache_Overrides, true); - LogMessage("\"%L\" refreshed the admin cache.", client); + LogAction(client, -1, "\"%L\" refreshed the admin cache.", client); ReplyToCommand(client, "[SM] %t", "Admin cache refreshed"); return Plugin_Handled; @@ -113,16 +113,16 @@ public Action:Command_BanIp(client, args) has_rcon = (id == INVALID_ADMIN_ID) ? false : GetAdminFlag(id, Admin_RCON); } - new bool:hit_client = false; + new hit_client = -1; if (numClients == 1 && !IsFakeClient(clients[0]) && (has_rcon || CanUserTarget(client, clients[0]))) { GetClientIP(clients[0], arg, sizeof(arg)); - hit_client = true; + hit_client = clients[0]; } - if (!hit_client && !has_rcon) + if (hit_client == -1 && !has_rcon) { ReplyToCommand(client, "[SM] %t", "No Access"); return Plugin_Handled; @@ -146,7 +146,7 @@ public Action:Command_BanIp(client, args) if (act < Plugin_Handled) { - LogMessage("\"%L\" added ban (minutes \"%d\") (ip \"%s\") (reason \"%s\")", client, minutes, arg, reason); + LogAction(client, hit_client, "\"%L\" added ban (minutes \"%d\") (ip \"%s\") (reason \"%s\")", client, minutes, arg, reason); ReplyToCommand(client, "[SM] %t", "Ban added"); } @@ -189,7 +189,7 @@ public Action:Command_AddBan(client, args) if (act < Plugin_Handled) { - LogMessage("\"%L\" added ban (minutes \"%d\") (id \"%s\") (reason \"%s\")", client, minutes, arg, reason); + LogAction(client, -1, "\"%L\" added ban (minutes \"%d\") (id \"%s\") (reason \"%s\")", client, minutes, arg, reason); ReplyToCommand(client, "[SM] %t", "Ban added"); } @@ -243,7 +243,7 @@ public Action:Command_Unban(client, args) if (act < Plugin_Handled) { - LogMessage("\"%L\" removed ban (filter \"%s\")", client, new_arg); + LogAction(client, -1, "\"%L\" removed ban (filter \"%s\")", client, new_arg); ReplyToCommand(client, "[SM] %t", "Removed bans matching", new_arg); } @@ -317,7 +317,7 @@ public Action:Command_Ban(client, args) ShowActivity(client, "%t", "Banned player reason", arg, time, reason); } } - LogMessage("\"%L\" banned \"%L\" (minutes \"%d\") (reason \"%s\")", client, target, time, reason); + LogAction(client, target, "\"%L\" banned \"%L\" (minutes \"%d\") (reason \"%s\")", client, target, time, reason); } if (act < Plugin_Stop) @@ -491,7 +491,7 @@ public Action:Command_ExecCfg(client, args) ShowActivity(client, "%t", "Executed config", path[4]); - LogMessage("\"%L\" executed config (file \"%s\")", client, path[4]); + LogAction(client, -1, "\"%L\" executed config (file \"%s\")", client, path[4]); ServerCommand("exec \"%s\"", path[4]); @@ -569,7 +569,7 @@ public Action:Command_Cvar(client, args) ReplyToCommand(client, "[SM] %t", "Cvar changed", cvarname, value); } - LogMessage("\"%L\" changed cvar (cvar \"%s\") (value \"%s\")", client, cvarname, value); + LogAction(client, -1, "\"%L\" changed cvar (cvar \"%s\") (value \"%s\")", client, cvarname, value); SetConVarString(hndl, value, true); @@ -587,7 +587,7 @@ public Action:Command_Rcon(client, args) decl String:argstring[255]; GetCmdArgString(argstring, sizeof(argstring)); - LogMessage("\"%L\" console command (cmdline \"%s\")", client, argstring); + LogAction(client, -1, "\"%L\" console command (cmdline \"%s\")", client, argstring); ServerCommand("%s", argstring); @@ -613,7 +613,7 @@ public Action:Command_Map(client, args) ShowActivity(client, "%t", "Changing map", map); - LogMessage("\"%L\" changed map to \"%s\"", client, map); + LogAction(client, -1, "\"%L\" changed map to \"%s\"", client, map); new Handle:dp; CreateDataTimer(3.0, Timer_ChangeMap, dp); @@ -665,7 +665,7 @@ public Action:Command_Kick(client, args) } ShowActivity(client, "%t", "Kicked player", arg); - LogMessage("\"%L\" kicked \"%L\" (reason \"%s\")", client, target, Arguments[len]); + LogAction(client, target, "\"%L\" kicked \"%L\" (reason \"%s\")", client, target, Arguments[len]); KickClient(target, "%s", Arguments[len]); diff --git a/plugins/basefuncommands.sp b/plugins/basefuncommands.sp index 6c1c833a..0d313264 100644 --- a/plugins/basefuncommands.sp +++ b/plugins/basefuncommands.sp @@ -95,7 +95,7 @@ public Action:Command_Play(client, args) GetClientName(target, Arg, sizeof(Arg)); ShowActivity(client, "%t", "Played Sound", Arg); - LogMessage("\"%L\" played sound on \"%L\" (file \"%s\")", client, target, Arguments[len]); + LogAction(client, target, "\"%L\" played sound on \"%L\" (file \"%s\")", client, target, Arguments[len]); ClientCommand(target, "playgamesound \"%s\"", Arguments[len]); @@ -140,7 +140,7 @@ public Action:Command_Burn(client, args) } ShowActivity(client, "%t", "Ignited player", arg); - LogMessage("\"%L\" ignited \"%L\" (seconds \"%f\")", client, target, seconds); + LogAction(client, target, "\"%L\" ignited \"%L\" (seconds \"%f\")", client, target, seconds); IgniteEntity(target, seconds); return Plugin_Handled; @@ -184,7 +184,7 @@ public Action:Command_Slap(client, args) } ShowActivity(client, "%t", "Slapped player", arg); - LogMessage("\"%L\" slapped \"%L\" (damage \"%d\")", client, target, damage); + LogAction(client, target, "\"%L\" slapped \"%L\" (damage \"%d\")", client, target, damage); SlapPlayer(target, damage, true); return Plugin_Handled; @@ -216,7 +216,7 @@ public Action:Command_Slay(client, args) } ShowActivity(client, "%t", "Slayed player", arg); - LogMessage("\"%L\" slayed \"%L\"", client, target); + LogAction(client, target, "\"%L\" slayed \"%L\"", client, target); ForcePlayerSuicide(target); return Plugin_Handled; diff --git a/plugins/basefunvotes.sp b/plugins/basefunvotes.sp index 762de039..0300d8ba 100644 --- a/plugins/basefunvotes.sp +++ b/plugins/basefunvotes.sp @@ -156,6 +156,7 @@ public Action:Command_VoteGravity(client, args) } } + LogAction(client, -1, "\"%L\" initiated a gravity vote.", client); ShowActivity(client, "%t", "Initiated Vote Gravity"); g_voteType = voteType:gravity; @@ -226,6 +227,7 @@ public Action:Command_VoteBurn(client, args) g_voteClient[VOTE_CLIENTID] = target; GetClientName(target, g_voteInfo[VOTE_NAME], sizeof(g_voteInfo[])); + LogAction(client, target, "\"%L\" initiated a burn vote against \"%L\"", client, target); ShowActivity(client, "%t", "Initiated Vote Burn", g_voteInfo[VOTE_NAME]); g_voteType = voteType:burn; @@ -279,6 +281,7 @@ public Action:Command_VoteSlay(client, args) g_voteClient[VOTE_CLIENTID] = target; GetClientName(target, g_voteInfo[VOTE_NAME], sizeof(g_voteInfo[])); + LogAction(client, target, "\"%L\" initiated a slay vote against \"%L\"", client, target); ShowActivity(client, "%t", "Initiated Vote Slay", g_voteInfo[VOTE_NAME]); g_voteType = voteType:slay; @@ -312,6 +315,7 @@ public Action:Command_VoteAlltalk(client, args) return Plugin_Handled; } + LogAction(client, -1, "\"%L\" initiated an alltalk vote.", client); ShowActivity(client, "%t", "Initiated Vote Alltalk"); g_voteType = voteType:alltalk; @@ -355,6 +359,7 @@ public Action:Command_VoteFF(client, args) return Plugin_Handled; } + LogAction(client, -1, "\"%L\" initiated a friendly fire vote.", client); ShowActivity(client, "%t", "Initiated Vote FF"); g_voteType = voteType:ff; @@ -433,11 +438,16 @@ public Handler_VoteCallback(Handle:menu, MenuAction:action, param1, param2) percent = GetVotePercent(votes, totalVotes); limit = GetConVarFloat(g_Cvar_Limits[g_voteType]); + + /* :TODO: g_voteClient[userid] needs to be checked. + */ // A multi-argument vote is "always successful", but have to check if its a Yes/No vote. if ((strcmp(item, VOTE_YES) == 0 && FloatCompare(percent,limit) < 0 && param1 == 0) || (strcmp(item, VOTE_NO) == 0 && param1 == 1)) { - LogMessage("Vote failed."); + /* :TODO: g_voteClient[userid] should be used here and set to -1 if not applicable. + */ + LogAction(-1, -1, "Vote failed."); PrintToChatAll("[SM] %t", "Vote Failed", RoundToNearest(100.0*limit), RoundToNearest(100.0*percent), totalVotes); } else @@ -449,14 +459,14 @@ public Handler_VoteCallback(Handle:menu, MenuAction:action, param1, param2) case (voteType:gravity): { PrintToChatAll("[SM] %t", "Cvar changed", "sv_gravity", item); - LogMessage("Changing gravity to %s due to vote.", item); + LogAction(-1, -1, "Changing gravity to %s due to vote.", item); SetConVarInt(g_Cvar_Gravity, StringToInt(item)); } case (voteType:burn): { PrintToChatAll("[SM] %t", "Ignited player", g_voteInfo[VOTE_NAME]); - LogMessage("Vote burn successful, igniting \"%L\"", g_voteClient[VOTE_CLIENTID]); + LogAction(-1, g_voteClient[VOTE_CLIENTID], "Vote burn successful, igniting \"%L\"", g_voteClient[VOTE_CLIENTID]); IgniteEntity(g_voteClient[VOTE_CLIENTID], 19.8); } @@ -464,7 +474,7 @@ public Handler_VoteCallback(Handle:menu, MenuAction:action, param1, param2) case (voteType:slay): { PrintToChatAll("[SM] %t", "Slayed player", g_voteInfo[VOTE_NAME]); - LogMessage("Vote slay successful, slaying \"%L\"", g_voteClient[VOTE_CLIENTID]); + LogAction(-1, g_voteClient[VOTE_CLIENTID], "Vote slay successful, slaying \"%L\"", g_voteClient[VOTE_CLIENTID]); ExtinguishEntity(g_voteClient[VOTE_CLIENTID]); ForcePlayerSuicide(g_voteClient[VOTE_CLIENTID]); @@ -473,14 +483,14 @@ public Handler_VoteCallback(Handle:menu, MenuAction:action, param1, param2) case (voteType:alltalk): { PrintToChatAll("[SM] %t", "Cvar changed", "sv_alltalk", (GetConVarBool(g_Cvar_Alltalk) ? "0" : "1")); - LogMessage("Changing alltalk to %s due to vote.", (GetConVarBool(g_Cvar_Alltalk) ? "0" : "1")); + LogAction(-1, -1, "Changing alltalk to %s due to vote.", (GetConVarBool(g_Cvar_Alltalk) ? "0" : "1")); SetConVarBool(g_Cvar_Alltalk, !GetConVarBool(g_Cvar_Alltalk)); } case (voteType:ff): { PrintToChatAll("[SM] %t", "Cvar changed", "mp_friendlyfire", (GetConVarBool(g_Cvar_FF) ? "0" : "1")); - LogMessage("Changing friendly fire to %s due to vote.", (GetConVarBool(g_Cvar_FF) ? "0" : "1")); + LogAction(-1, -1, "Changing friendly fire to %s due to vote.", (GetConVarBool(g_Cvar_FF) ? "0" : "1")); SetConVarBool(g_Cvar_FF, !GetConVarBool(g_Cvar_FF)); } } diff --git a/plugins/basevotes.sp b/plugins/basevotes.sp index e34b0e41..e5124248 100644 --- a/plugins/basevotes.sp +++ b/plugins/basevotes.sp @@ -148,6 +148,7 @@ public Action:Command_Votemap(client, args) } } + LogAction(client, -1, "\"%L\" initiated a map vote.", client); ShowActivity(client, "%t", "Initiated Vote Map"); g_voteType = voteType:map; @@ -217,6 +218,7 @@ public Action:Command_Vote(client, args) } } + LogAction(client, -1, "\"%L\" initiated a generic vote.", client); ShowActivity(client, "%t", "Initiate Vote", g_voteArg); g_voteType = voteType:question; @@ -287,6 +289,7 @@ public Action:Command_Votekick(client, args) GetClientName(target, g_voteInfo[VOTE_NAME], sizeof(g_voteInfo[])); + LogAction(client, target, "\"%L\" initiated a kick vote against \"%L\"", client, target); ShowActivity(client, "%t", "Initiated Vote Kick", g_voteInfo[VOTE_NAME]); g_voteType = voteType:kick; @@ -347,6 +350,7 @@ public Action:Command_Voteban(client, args) GetClientAuthString(target, g_voteInfo[VOTE_AUTHID], sizeof(g_voteInfo[])); GetClientIP(target, g_voteInfo[VOTE_IP], sizeof(g_voteInfo[])); + LogAction(client, target, "\"%L\" initiated a ban vote against \"%L\"", client, target); ShowActivity(client, "%t", "Initiated Vote Ban", g_voteInfo[VOTE_NAME]); g_voteType = voteType:ban; @@ -421,11 +425,15 @@ public Handler_VoteCallback(Handle:menu, MenuAction:action, param1, param2) { limit = GetConVarFloat(g_Cvar_Limits[g_voteType]); } + + /* :TODO: g_voteClient[userid] needs to be checked */ // A multi-argument vote is "always successful", but have to check if its a Yes/No vote. if ((strcmp(item, VOTE_YES) == 0 && FloatCompare(percent,limit) < 0 && param1 == 0) || (strcmp(item, VOTE_NO) == 0 && param1 == 1)) { - LogMessage("Vote failed."); + /* :TODO: g_voteClient[userid] should be used here and set to -1 if not applicable. + */ + LogAction(-1, -1, "Vote failed."); PrintToChatAll("[SM] %t", "Vote Failed", RoundToNearest(100.0*limit), RoundToNearest(100.0*percent), totalVotes); } else @@ -446,7 +454,7 @@ public Handler_VoteCallback(Handle:menu, MenuAction:action, param1, param2) case (voteType:map): { - LogMessage("Changing map to %s due to vote.", item); + LogAction(-1, -1, "Changing map to %s due to vote.", item); PrintToChatAll("[SM] %t", "Changing map", item); new Handle:dp; CreateDataTimer(5.0, Timer_ChangeMap, dp); @@ -461,7 +469,7 @@ public Handler_VoteCallback(Handle:menu, MenuAction:action, param1, param2) } PrintToChatAll("[SM] %t", "Kicked player", g_voteInfo[VOTE_NAME]); - LogMessage("Vote kick successful, kicked \"%L\" (reason \"%s\")", g_voteClient[VOTE_CLIENTID], g_voteArg); + LogAction(-1, g_voteClient[VOTE_CLIENTID], "Vote kick successful, kicked \"%L\" (reason \"%s\")", g_voteClient[VOTE_CLIENTID], g_voteArg); ServerCommand("kickid %d \"%s\"", g_voteClient[VOTE_USERID], g_voteArg); } @@ -482,7 +490,7 @@ public Handler_VoteCallback(Handle:menu, MenuAction:action, param1, param2) } PrintToChatAll("[SM] %t", "Banned player", g_voteInfo[VOTE_NAME], 30); - LogMessage("Vote ban successful, banned \"%L\" (minutes \"30\") (reason \"%s\")", g_voteClient[VOTE_CLIENTID], g_voteArg); + LogAction(-1, g_voteClient[VOTE_CLIENTID], "Vote ban successful, banned \"%L\" (minutes \"30\") (reason \"%s\")", g_voteClient[VOTE_CLIENTID], g_voteArg); ServerCommand("banid %d %s", 30, g_voteClient[VOTE_AUTHID]); ServerCommand("kickid %d \"%s\"", g_voteClient[VOTE_USERID], g_voteArg); diff --git a/plugins/include/core.inc b/plugins/include/core.inc index 0526d73d..df31a96b 100644 --- a/plugins/include/core.inc +++ b/plugins/include/core.inc @@ -62,6 +62,16 @@ enum Action Plugin_Stop = 4, /**< Immediately stop the hook chain and handle the original */ }; +/** + * Specifies identity types. + */ +enum Identity +{ + Identity_Core = 0, + Identity_Extension = 1, + Identity_Plugin = 2 +}; + public PlVers:__version = { version = SOURCEMOD_PLUGINAPI_VERSION, diff --git a/plugins/include/files.inc b/plugins/include/files.inc index 7ed9d818..6dacc5ed 100644 --- a/plugins/include/files.inc +++ b/plugins/include/files.inc @@ -232,3 +232,28 @@ native bool:WriteFileLine(Handle:hndl, const String:format[], any:...); * @return Time value, or -1 on failure. */ native GetFileTime(const String:file[], FileTimeMode:tmode); + +/** + * Same as LogToFile(), except uses an open file Handle. The file must + * be opened in text appending mode. + * + * @param hndl Handle to the file. + * @param message Message format. + * @param ... Message format parameters. + * @noreturn + * @error Invalid Handle. + */ +native LogToOpenFile(Handle:hndl, const String:message[], any:...); + +/** + * Same as LogToFileEx(), except uses an open file Handle. The file must + * be opened in text appending mode. + * + * @param hndl Handle to the file. + * @param message Message format. + * @param ... Message format parameters. + * @noreturn + * @error Invalid Handle. + */ +native LogToOpenFileEx(Handle:hndl, const String:message[], any:...); + diff --git a/plugins/include/sourcemod.inc b/plugins/include/sourcemod.inc index 5a8750d8..9496a6ca 100644 --- a/plugins/include/sourcemod.inc +++ b/plugins/include/sourcemod.inc @@ -166,6 +166,26 @@ forward OnServerCfg(); */ forward OnAllPluginsLoaded(); +/** + * Called when an action is going to be logged. + * + * @param source Handle to the object logging the action, or INVALID_HANDLE + * if Core is logging the action. + * @param ident Type of object logging the action (plugin, ext, or core). + * @param client Client the action is from; 0 for server, -1 if not applicable. + * @param target Client the action is targetting, or -1 if not applicable. + * @param message Message that is being logged. + * @return Plugin_Continue will cause Core to defaulty log the message. + * Plugin_Handled will stop Core from logging the message. + * Plugin_Stop is the same as Handled, but prevents any other + * plugins from handling the message. + */ +forward Action:OnLogAction(Handle:source, + Identity:ident, + client, + target, + const String:message[]); + /** * Returns the calling plugin's Handle. * @@ -264,7 +284,8 @@ native SetFailState(const String:string[]); native ThrowError(const String:fmt[], any:...); /** - * Logs a plugin message to the SourceMod logs. + * Logs a plugin message to the SourceMod logs. The log message will be + * prefixed by the plugin's logtag (filename). * * @param format String format. * @param ... Format arguments. @@ -272,6 +293,53 @@ native ThrowError(const String:fmt[], any:...); */ native LogMessage(const String:format[], any:...); +/** + * Logs a message to the SourceMod logs without any plugin logtag. This is + * useful for re-routing messages from other plugins, for example, messages + * from LogAction(). + * + * @param format String format. + * @param ... Format arguments. + * @noreturn + */ +native LogMessageEx(const String:format[], any:...); + +/** + * Logs a message to any file. The log message will be in the normal + * SourceMod format, with the plugin logtag prepended. + * + * @param file File to write the log message in. + * @param format String format. + * @param ... Format arguments. + * @noreturn + * @error File could not be opened/written. + */ +native LogToFile(const String:file[], const String:format[], any:...); + +/** + * Same as LogToFile(), except no plugin logtag is prepended. + * + * @param file File to write the log message in. + * @param format String format. + * @param ... Format arguments. + * @noreturn + * @error File could not be opened/written. + */ +native LogToFileEx(const String:file[], const String:format[], any:...); + +/** + * Logs an action from a command or event whereby interception and routing may + * be important. This is intended to be a logging version of ShowActivity(). + * + * @param client Client performing the action, 0 for server, or -1 if not + * applicable. + * @param target Client being targetted, or -1 if not applicable. + * @param message Message format. + * @param ... Message formatting parameters. + * @noreturn + */ +native LogAction(client, target, const String:message[], any:...); + /** * Logs a plugin error message to the SourceMod logs. *