1.1 --- a/core/Logger.cpp Sun Mar 02 18:18:42 2008 +0000
1.2 +++ b/core/Logger.cpp Sun Mar 02 19:08:27 2008 +0000
1.3 @@ -434,7 +434,7 @@
1.4 msg[len++] = '\n';
1.5 msg[len] = '\0';
1.6
1.7 - engine->LogPrint(msg);
1.8 + Engine_LogPrintWrapper(msg);
1.9 }
1.10
1.11 const char *Logger::GetLogFileName(LogType type) const
1.12 @@ -505,3 +505,16 @@
1.13 }
1.14 }
1.15
1.16 +bool g_in_game_log_hook = false;
1.17 +
1.18 +void Engine_LogPrintWrapper(const char *msg)
1.19 +{
1.20 + if (g_in_game_log_hook)
1.21 + {
1.22 + ENGINE_CALL(LogPrint)(msg);
1.23 + }
1.24 + else
1.25 + {
1.26 + engine->LogPrint(msg);
1.27 + }
1.28 +}
2.1 --- a/core/Logger.h Sun Mar 02 18:18:42 2008 +0000
2.2 +++ b/core/Logger.h Sun Mar 02 19:08:27 2008 +0000
2.3 @@ -98,6 +98,9 @@
2.4 bool m_InitialState;
2.5 };
2.6
2.7 +void Engine_LogPrintWrapper(const char *msg);
2.8 +
2.9 +extern bool g_in_game_log_hook;
2.10 extern Logger g_Logger;
2.11
2.12 #endif // _INCLUDE_SOURCEMOD_CLOGGER_H_
3.1 --- a/core/smn_filesystem.cpp Sun Mar 02 18:18:42 2008 +0000
3.2 +++ b/core/smn_filesystem.cpp Sun Mar 02 19:08:27 2008 +0000
3.3 @@ -37,22 +37,40 @@
3.4 #include "Logger.h"
3.5 #include "PluginSys.h"
3.6 #include "sourcemm_api.h"
3.7 +#include "ForwardSys.h"
3.8 +
3.9 +SH_DECL_HOOK1_void(IVEngineServer, LogPrint, SH_NOATTRIB, false, const char *);
3.10
3.11 HandleType_t g_FileType;
3.12 HandleType_t g_DirType;
3.13 +IChangeableForward *g_pLogHook = NULL;
3.14
3.15 class FileNatives :
3.16 public SMGlobalClass,
3.17 - public IHandleTypeDispatch
3.18 + public IHandleTypeDispatch,
3.19 + public IPluginsListener
3.20 {
3.21 public:
3.22 + FileNatives()
3.23 + {
3.24 + m_bIsLoggingHooked = false;
3.25 + }
3.26 virtual void OnSourceModAllInitialized()
3.27 {
3.28 g_FileType = g_HandleSys.CreateType("File", this, 0, NULL, NULL, g_pCoreIdent, NULL);
3.29 g_DirType = g_HandleSys.CreateType("Directory", this, 0, NULL, NULL, g_pCoreIdent, NULL);
3.30 + g_pLogHook = g_Forwards.CreateForwardEx(NULL, ET_Hook, 1, NULL, Param_String);
3.31 + g_PluginSys.AddPluginsListener(this);
3.32 }
3.33 virtual void OnSourceModShutdown()
3.34 {
3.35 + g_PluginSys.RemovePluginsListener(this);
3.36 + if (m_bIsLoggingHooked)
3.37 + {
3.38 + SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, LogPrint, engine, this, &FileNatives::LogPrint, false);
3.39 + m_bIsLoggingHooked = false;
3.40 + }
3.41 + g_Forwards.ReleaseForward(g_pLogHook);
3.42 g_HandleSys.RemoveType(g_DirType, g_pCoreIdent);
3.43 g_HandleSys.RemoveType(g_FileType, g_pCoreIdent);
3.44 g_DirType = 0;
3.45 @@ -64,11 +82,59 @@
3.46 {
3.47 FILE *fp = (FILE *)object;
3.48 fclose(fp);
3.49 - } else if (type == g_DirType) {
3.50 + }
3.51 + else if (type == g_DirType)
3.52 + {
3.53 IDirectory *pDir = (IDirectory *)object;
3.54 g_LibSys.CloseDirectory(pDir);
3.55 }
3.56 }
3.57 + virtual void OnPluginDestroyed(IPlugin *plugin)
3.58 + {
3.59 + if (m_bIsLoggingHooked && g_pLogHook->GetFunctionCount() == 0)
3.60 + {
3.61 + SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, LogPrint, engine, this, &FileNatives::LogPrint, false);
3.62 + m_bIsLoggingHooked = false;
3.63 + }
3.64 + }
3.65 + virtual void AddLogHook(IPluginFunction *pFunc)
3.66 + {
3.67 + if (!m_bIsLoggingHooked)
3.68 + {
3.69 + SH_ADD_HOOK_MEMFUNC(IVEngineServer, LogPrint, engine, this, &FileNatives::LogPrint, false);
3.70 + m_bIsLoggingHooked = true;
3.71 + }
3.72 +
3.73 + g_pLogHook->AddFunction(pFunc);
3.74 + }
3.75 + virtual void RemoveLogHook(IPluginFunction *pFunc)
3.76 + {
3.77 + g_pLogHook->RemoveFunction(pFunc);
3.78 +
3.79 + if (m_bIsLoggingHooked && g_pLogHook->GetFunctionCount() == 0)
3.80 + {
3.81 + SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, LogPrint, engine, this, &FileNatives::LogPrint, false);
3.82 + m_bIsLoggingHooked = false;
3.83 + }
3.84 + }
3.85 + virtual void LogPrint(const char *msg)
3.86 + {
3.87 + cell_t result;
3.88 +
3.89 + result = 0;
3.90 +
3.91 + g_in_game_log_hook = true;
3.92 + g_pLogHook->PushString(msg);
3.93 + g_pLogHook->Execute(&result);
3.94 + g_in_game_log_hook = false;
3.95 +
3.96 + if (result >= Pl_Handled)
3.97 + {
3.98 + RETURN_META(MRES_SUPERCEDE);
3.99 + }
3.100 + }
3.101 +private:
3.102 + bool m_bIsLoggingHooked;
3.103 } s_FileNatives;
3.104
3.105 static cell_t sm_OpenDirectory(IPluginContext *pContext, const cell_t *params)
3.106 @@ -521,7 +587,7 @@
3.107 buffer[len] = '\0';
3.108 }
3.109
3.110 - engine->LogPrint(buffer);
3.111 + Engine_LogPrintWrapper(buffer);
3.112
3.113 return 1;
3.114 }
3.115 @@ -835,6 +901,34 @@
3.116 return (fwrite(buffer, sizeof(char), len, pFile) == len) ? 1 : 0;
3.117 }
3.118
3.119 +static cell_t sm_AddGameLogHook(IPluginContext *pContext, const cell_t *params)
3.120 +{
3.121 + IPluginFunction *pFunction;
3.122 +
3.123 + if ((pFunction=pContext->GetFunctionById(params[1])) == NULL)
3.124 + {
3.125 + return pContext->ThrowNativeError("Function id %x is invalid", params[1]);
3.126 + }
3.127 +
3.128 + s_FileNatives.AddLogHook(pFunction);
3.129 +
3.130 + return 1;
3.131 +}
3.132 +
3.133 +static cell_t sm_RemoveGameLogHook(IPluginContext *pContext, const cell_t *params)
3.134 +{
3.135 + IPluginFunction *pFunction;
3.136 +
3.137 + if ((pFunction=pContext->GetFunctionById(params[1])) == NULL)
3.138 + {
3.139 + return pContext->ThrowNativeError("Function id %x is invalid", params[1]);
3.140 + }
3.141 +
3.142 + s_FileNatives.RemoveLogHook(pFunction);
3.143 +
3.144 + return 1;
3.145 +}
3.146 +
3.147 REGISTER_NATIVES(filesystem)
3.148 {
3.149 {"OpenDirectory", sm_OpenDirectory},
3.150 @@ -863,5 +957,7 @@
3.151 {"ReadFileString", sm_ReadFileString},
3.152 {"WriteFile", sm_WriteFile},
3.153 {"WriteFileString", sm_WriteFileString},
3.154 + {"AddGameLogHook", sm_AddGameLogHook},
3.155 + {"RemoveGameLogHook", sm_RemoveGameLogHook},
3.156 {NULL, NULL},
3.157 };
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
4.2 +++ b/plugins/include/logging.inc Sun Mar 02 19:08:27 2008 +0000
4.3 @@ -0,0 +1,153 @@
4.4 +/**
4.5 + * vim: set ts=4 :
4.6 + * =============================================================================
4.7 + * SourceMod (C)2004-2007 AlliedModders LLC. All rights reserved.
4.8 + * =============================================================================
4.9 + *
4.10 + * This file is part of the SourceMod/SourcePawn SDK.
4.11 + *
4.12 + * This program is free software; you can redistribute it and/or modify it under
4.13 + * the terms of the GNU General Public License, version 3.0, as published by the
4.14 + * Free Software Foundation.
4.15 + *
4.16 + * This program is distributed in the hope that it will be useful, but WITHOUT
4.17 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
4.18 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
4.19 + * details.
4.20 + *
4.21 + * You should have received a copy of the GNU General Public License along with
4.22 + * this program. If not, see <http://www.gnu.org/licenses/>.
4.23 + *
4.24 + * As a special exception, AlliedModders LLC gives you permission to link the
4.25 + * code of this program (as well as its derivative works) to "Half-Life 2," the
4.26 + * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
4.27 + * by the Valve Corporation. You must obey the GNU General Public License in
4.28 + * all respects for all other code used. Additionally, AlliedModders LLC grants
4.29 + * this exception to all derivative works. AlliedModders LLC defines further
4.30 + * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
4.31 + * or <http://www.sourcemod.net/license.php>.
4.32 + *
4.33 + * Version: $Id$
4.34 + */
4.35 +
4.36 +#if defined _sm_logging_included
4.37 + #endinput
4.38 +#endif
4.39 +#define _sm_logging_included
4.40 +
4.41 +/**
4.42 + * Logs a plugin message to the SourceMod logs. The log message will be
4.43 + * prefixed by the plugin's logtag (filename).
4.44 + *
4.45 + * @param format String format.
4.46 + * @param ... Format arguments.
4.47 + * @noreturn
4.48 + */
4.49 +native LogMessage(const String:format[], any:...);
4.50 +
4.51 +/**
4.52 + * Logs a message to the SourceMod logs without any plugin logtag. This is
4.53 + * useful for re-routing messages from other plugins, for example, messages
4.54 + * from LogAction().
4.55 + *
4.56 + * @param format String format.
4.57 + * @param ... Format arguments.
4.58 + * @noreturn
4.59 + */
4.60 +native LogMessageEx(const String:format[], any:...);
4.61 +
4.62 +/**
4.63 + * Logs a message to any file. The log message will be in the normal
4.64 + * SourceMod format, with the plugin logtag prepended.
4.65 + *
4.66 + * @param file File to write the log message in.
4.67 + * @param format String format.
4.68 + * @param ... Format arguments.
4.69 + * @noreturn
4.70 + * @error File could not be opened/written.
4.71 + */
4.72 +native LogToFile(const String:file[], const String:format[], any:...);
4.73 +
4.74 +/**
4.75 + * Same as LogToFile(), except no plugin logtag is prepended.
4.76 + *
4.77 + * @param file File to write the log message in.
4.78 + * @param format String format.
4.79 + * @param ... Format arguments.
4.80 + * @noreturn
4.81 + * @error File could not be opened/written.
4.82 + */
4.83 +native LogToFileEx(const String:file[], const String:format[], any:...);
4.84 +
4.85 +/**
4.86 + * Logs an action from a command or event whereby interception and routing may
4.87 + * be important. This is intended to be a logging version of ShowActivity().
4.88 + *
4.89 + * @param client Client performing the action, 0 for server, or -1 if not
4.90 + * applicable.
4.91 + * @param target Client being targetted, or -1 if not applicable.
4.92 + * @param message Message format.
4.93 + * @param ... Message formatting parameters.
4.94 + * @noreturn
4.95 + */
4.96 +native LogAction(client, target, const String:message[], any:...);
4.97 +
4.98 +/**
4.99 + * Logs a plugin error message to the SourceMod logs.
4.100 + *
4.101 + * @param format String format.
4.102 + * @param ... Format arguments.
4.103 + * @noreturn
4.104 + */
4.105 +native LogError(const String:format[], any:...);
4.106 +
4.107 +/**
4.108 + * Called when an action is going to be logged.
4.109 + *
4.110 + * @param source Handle to the object logging the action, or INVALID_HANDLE
4.111 + * if Core is logging the action.
4.112 + * @param ident Type of object logging the action (plugin, ext, or core).
4.113 + * @param client Client the action is from; 0 for server, -1 if not applicable.
4.114 + * @param target Client the action is targetting, or -1 if not applicable.
4.115 + * @param message Message that is being logged.
4.116 + * @return Plugin_Continue will cause Core to defaulty log the message.
4.117 + * Plugin_Handled will stop Core from logging the message.
4.118 + * Plugin_Stop is the same as Handled, but prevents any other
4.119 + * plugins from handling the message.
4.120 + */
4.121 +forward Action:OnLogAction(Handle:source,
4.122 + Identity:ident,
4.123 + client,
4.124 + target,
4.125 + const String:message[]);
4.126 +
4.127 +/**
4.128 + * Called when a game log message is received.
4.129 + *
4.130 + * Any Log*() functions called within this callback will not recursively
4.131 + * pass through. That is, they will log directly, bypassing this callback.
4.132 + *
4.133 + * Note that this does not capture log messages from the engine. It only
4.134 + * captures log messages being sent from the game/mod itself.
4.135 + *
4.136 + * @param message Message contents.
4.137 + * @return Plugin_Handled or Plugin_Stop will prevent the message
4.138 + * from being written to the log file.
4.139 + */
4.140 +functag GameLogHook Action:public(const String:message[]);
4.141 +
4.142 +/**
4.143 + * Adds a game log hook.
4.144 + *
4.145 + * @param hook Hook function.
4.146 + * @noreturn
4.147 + */
4.148 +native AddGameLogHook(GameLogHook:hook);
4.149 +
4.150 +/**
4.151 + * Removes a game log hook.
4.152 + *
4.153 + * @param hook Hook function.
4.154 + * @noreturn
4.155 + */
4.156 +native RemoveGameLogHook(GameLogHook:hook);
5.1 --- a/plugins/include/sourcemod.inc Sun Mar 02 18:18:42 2008 +0000
5.2 +++ b/plugins/include/sourcemod.inc Sun Mar 02 19:08:27 2008 +0000
5.3 @@ -54,6 +54,7 @@
5.4 #include <handles>
5.5 #include <functions>
5.6 #include <files>
5.7 +#include <logging>
5.8 #include <timers>
5.9 #include <admin>
5.10 #include <dbi>
5.11 @@ -92,6 +93,10 @@
5.12 * If any run-time error is thrown during this callback, the plugin will be marked
5.13 * as failed.
5.14 *
5.15 + * It is not necessary to close any handles or remove hooks in this function.
5.16 + * SourceMod guarantees that plugin shutdown automatically and correctly releases
5.17 + * all resources.
5.18 + *
5.19 * @noreturn
5.20 */
5.21 forward OnPluginStart();
5.22 @@ -177,26 +182,6 @@
5.23 forward OnAllPluginsLoaded();
5.24
5.25 /**
5.26 - * Called when an action is going to be logged.
5.27 - *
5.28 - * @param source Handle to the object logging the action, or INVALID_HANDLE
5.29 - * if Core is logging the action.
5.30 - * @param ident Type of object logging the action (plugin, ext, or core).
5.31 - * @param client Client the action is from; 0 for server, -1 if not applicable.
5.32 - * @param target Client the action is targetting, or -1 if not applicable.
5.33 - * @param message Message that is being logged.
5.34 - * @return Plugin_Continue will cause Core to defaulty log the message.
5.35 - * Plugin_Handled will stop Core from logging the message.
5.36 - * Plugin_Stop is the same as Handled, but prevents any other
5.37 - * plugins from handling the message.
5.38 - */
5.39 -forward Action:OnLogAction(Handle:source,
5.40 - Identity:ident,
5.41 - client,
5.42 - target,
5.43 - const String:message[]);
5.44 -
5.45 -/**
5.46 * Returns the calling plugin's Handle.
5.47 *
5.48 * @return Handle of the calling plugin.
5.49 @@ -316,72 +301,6 @@
5.50 native ThrowError(const String:fmt[], any:...);
5.51
5.52 /**
5.53 - * Logs a plugin message to the SourceMod logs. The log message will be
5.54 - * prefixed by the plugin's logtag (filename).
5.55 - *
5.56 - * @param format String format.
5.57 - * @param ... Format arguments.
5.58 - * @noreturn
5.59 - */
5.60 -native LogMessage(const String:format[], any:...);
5.61 -
5.62 -/**
5.63 - * Logs a message to the SourceMod logs without any plugin logtag. This is
5.64 - * useful for re-routing messages from other plugins, for example, messages
5.65 - * from LogAction().
5.66 - *
5.67 - * @param format String format.
5.68 - * @param ... Format arguments.
5.69 - * @noreturn
5.70 - */
5.71 -native LogMessageEx(const String:format[], any:...);
5.72 -
5.73 -/**
5.74 - * Logs a message to any file. The log message will be in the normal
5.75 - * SourceMod format, with the plugin logtag prepended.
5.76 - *
5.77 - * @param file File to write the log message in.
5.78 - * @param format String format.
5.79 - * @param ... Format arguments.
5.80 - * @noreturn
5.81 - * @error File could not be opened/written.
5.82 - */
5.83 -native LogToFile(const String:file[], const String:format[], any:...);
5.84 -
5.85 -/**
5.86 - * Same as LogToFile(), except no plugin logtag is prepended.
5.87 - *
5.88 - * @param file File to write the log message in.
5.89 - * @param format String format.
5.90 - * @param ... Format arguments.
5.91 - * @noreturn
5.92 - * @error File could not be opened/written.
5.93 - */
5.94 -native LogToFileEx(const String:file[], const String:format[], any:...);
5.95 -
5.96 -/**
5.97 - * Logs an action from a command or event whereby interception and routing may
5.98 - * be important. This is intended to be a logging version of ShowActivity().
5.99 - *
5.100 - * @param client Client performing the action, 0 for server, or -1 if not
5.101 - * applicable.
5.102 - * @param target Client being targetted, or -1 if not applicable.
5.103 - * @param message Message format.
5.104 - * @param ... Message formatting parameters.
5.105 - * @noreturn
5.106 - */
5.107 -native LogAction(client, target, const String:message[], any:...);
5.108 -
5.109 -/**
5.110 - * Logs a plugin error message to the SourceMod logs.
5.111 - *
5.112 - * @param format String format.
5.113 - * @param ... Format arguments.
5.114 - * @noreturn
5.115 - */
5.116 -native LogError(const String:format[], any:...);
5.117 -
5.118 -/**
5.119 * Gets the system time as a unix timestamp.
5.120 *
5.121 * @param bigStamp Optional array to store the 64bit timestamp in.