From 0aadfbdfabb06cd10a378087311a97e710873739 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Thu, 15 Mar 2007 20:10:25 +0000 Subject: [PATCH] added natives for iterating plugins and retrieving plugin info --HG-- extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%40624 --- core/smn_core.cpp | 212 ++++++++++++++++++++++++++++++++++ plugins/include/core.inc | 29 +++++ plugins/include/sourcemod.inc | 68 +++++++++++ 3 files changed, 309 insertions(+) diff --git a/core/smn_core.cpp b/core/smn_core.cpp index c37dbd95..d1849343 100644 --- a/core/smn_core.cpp +++ b/core/smn_core.cpp @@ -14,6 +14,36 @@ #include #include "sm_globals.h" #include "sourcemod.h" +#include "PluginSys.h" +#include "HandleSys.h" + +HandleType_t g_PlIter; + + +class CoreNativeHelpers : + public SMGlobalClass, + public IHandleTypeDispatch +{ +public: + void OnSourceModAllInitialized() + { + HandleAccess hacc; + g_HandleSys.InitAccessDefaults(NULL, &hacc); + hacc.access[HandleAccess_Clone] = HANDLE_RESTRICT_IDENTITY|HANDLE_RESTRICT_OWNER; + + g_PlIter = g_HandleSys.CreateType("PluginIterator", this, 0, NULL, NULL, g_pCoreIdent, NULL); + } + void OnHandleDestroy(HandleType_t type, void *object) + { + IPluginIterator *iter = (IPluginIterator *)object; + iter->Release(); + } + void OnSourceModShutdown() + { + g_HandleSys.RemoveType(g_PlIter, g_pCoreIdent); + } +} g_CoreNativeHelpers; + static cell_t ThrowError(IPluginContext *pContext, const cell_t *params) { @@ -40,9 +70,191 @@ static cell_t GetTime(IPluginContext *pContext, const cell_t *params) return static_cast(t); } +static cell_t GetPluginIterator(IPluginContext *pContext, const cell_t *params) +{ + IPluginIterator *iter = g_PluginSys.GetPluginIterator(); + + Handle_t hndl = g_HandleSys.CreateHandle(g_PlIter, iter, pContext->GetIdentity(), g_pCoreIdent, NULL); + + if (hndl == BAD_HANDLE) + { + iter->Release(); + } + + return hndl; +} + +static cell_t MorePlugins(IPluginContext *pContext, const cell_t *params) +{ + Handle_t hndl = (Handle_t)params[1]; + HandleError err; + IPluginIterator *pIter; + + HandleSecurity sec; + sec.pIdentity = g_pCoreIdent; + sec.pOwner = pContext->GetIdentity(); + + if ((err=g_HandleSys.ReadHandle(hndl, g_PlIter, &sec, (void **)&pIter)) != HandleError_None) + { + return pContext->ThrowNativeError("Could not read Handle %x (error %d)", hndl, err); + } + + return pIter->MorePlugins() ? 1 : 0; +} + +static cell_t ReadPlugin(IPluginContext *pContext, const cell_t *params) +{ + Handle_t hndl = (Handle_t)params[1]; + HandleError err; + IPluginIterator *pIter; + + HandleSecurity sec; + sec.pIdentity = g_pCoreIdent; + sec.pOwner = pContext->GetIdentity(); + + if ((err=g_HandleSys.ReadHandle(hndl, g_PlIter, &sec, (void **)&pIter)) != HandleError_None) + { + return pContext->ThrowNativeError("Could not read Handle %x (error %d)", hndl, err); + } + + CPlugin *pPlugin = (CPlugin *)pIter->GetPlugin(); + if (!pPlugin) + { + return BAD_HANDLE; + } + + pIter->NextPlugin(); + + return pPlugin->GetMyHandle(); +} + +CPlugin *GetPluginFromHandle(IPluginContext *pContext, Handle_t hndl) +{ + if (hndl == BAD_HANDLE) + { + return g_PluginSys.GetPluginByCtx(pContext->GetContext()); + } else { + HandleError err; + CPlugin *pPlugin = (CPlugin *)g_PluginSys.PluginFromHandle(hndl, &err); + if (!pPlugin) + { + pContext->ThrowNativeError("Could not read Handle %x (error %d)", hndl, err); + } + return pPlugin; + } +} + +static cell_t GetPluginStatus(IPluginContext *pContext, const cell_t *params) +{ + CPlugin *pPlugin = GetPluginFromHandle(pContext, params[1]); + if (!pPlugin) + { + return 0; + } + + return pPlugin->GetStatus(); +} + +static cell_t GetPluginFilename(IPluginContext *pContext, const cell_t *params) +{ + CPlugin *pPlugin = GetPluginFromHandle(pContext, params[1]); + if (!pPlugin) + { + return 0; + } + + pContext->StringToLocalUTF8(params[2], params[3], pPlugin->GetFilename(), NULL); + + return 1; +} + +static cell_t IsPluginDebugging(IPluginContext *pContext, const cell_t *params) +{ + CPlugin *pPlugin = GetPluginFromHandle(pContext, params[1]); + if (!pPlugin) + { + return 0; + } + + return pPlugin->IsDebugging() ? 1 : 0; +} + +/* Local to plugins only */ +enum PluginInfo +{ + PlInfo_Name, /**< Plugin name */ + PlInfo_Author, /**< Plugin author */ + PlInfo_Description, /**< Plugin description */ + PlInfo_Version, /**< Plugin verison */ + PlInfo_URL, /**< Plugin URL */ +}; + +static cell_t GetPluginInfo(IPluginContext *pContext, const cell_t *params) +{ + CPlugin *pPlugin = GetPluginFromHandle(pContext, params[1]); + if (!pPlugin) + { + return 0; + } + + const sm_plugininfo_t *info = pPlugin->GetPublicInfo(); + + if (!info) + { + return 0; + } + + const char *str = NULL; + + switch ((PluginInfo)params[2]) + { + case PlInfo_Name: + { + str = info->name; + break; + } + case PlInfo_Author: + { + str = info->author; + break; + } + case PlInfo_Description: + { + str = info->description; + break; + } + case PlInfo_Version: + { + str = info->version; + break; + } + case PlInfo_URL: + { + str = info->url; + break; + } + } + + if (!str || str[0] == '\0') + { + return 0; + } + + pContext->StringToLocalUTF8(params[3], params[4], str, NULL); + + return 1; +} + REGISTER_NATIVES(coreNatives) { + {"GetPluginFilename", GetPluginFilename}, + {"GetPluginInfo", GetPluginInfo}, + {"GetPluginIterator", GetPluginIterator}, + {"GetPluginStatus", GetPluginStatus}, {"GetTime", GetTime}, + {"IsPluginDebugging", IsPluginDebugging}, + {"MorePlugins", MorePlugins}, + {"ReadPlugin", ReadPlugin}, {"ThrowError", ThrowError}, {NULL, NULL}, }; diff --git a/plugins/include/core.inc b/plugins/include/core.inc index f5aed571..19843503 100644 --- a/plugins/include/core.inc +++ b/plugins/include/core.inc @@ -43,6 +43,35 @@ public PlVers:__version = filevers = SOURCEMOD_VERSION }; +/** + * Plugin status values. + */ +enum PluginStatus +{ + Plugin_Running=0, /**< Plugin is running */ + /* All states below are "temporarily" unexecutable */ + Plugin_Paused, /**< Plugin is loaded but paused */ + Plugin_Error, /**< Plugin is loaded but errored/locked */ + /* All states below do not have all natives */ + Plugin_Loaded, /**< Plugin has passed loading and can be finalized */ + Plugin_Failed, /**< Plugin has a fatal failure */ + Plugin_Created, /**< Plugin is created but not initialized */ + Plugin_Uncompiled, /**< Plugin is not yet compiled by the JIT */ + Plugin_BadLoad, /**< Plugin failed to load */ +}; + +/** + * Plugin information properties. + */ +enum PluginInfo +{ + PlInfo_Name, /**< Plugin name */ + PlInfo_Author, /**< Plugin author */ + PlInfo_Description, /**< Plugin description */ + PlInfo_Version, /**< Plugin verison */ + PlInfo_URL, /**< Plugin URL */ +}; + struct Extension { const String:name[], /* Short name */ diff --git a/plugins/include/sourcemod.inc b/plugins/include/sourcemod.inc index ba0d0a00..b6fffb69 100644 --- a/plugins/include/sourcemod.inc +++ b/plugins/include/sourcemod.inc @@ -108,6 +108,74 @@ forward OnGameFrame(); */ native Handle:GetMyHandle(); +/** + * Returns an iterator that can be used to search through plugins. + * + * @return Handle to iterate with. Must be closed via + * CloseHandle(). + * @error Invalid Handle. + */ +native Handle:GetPluginIterator(); + +/** + * Returns whether there are more plugins available in the iterator. + * + * @param iter Handle to the plugin iterator. + * @return True on more plugins, false otherwise. + * @error Invalid Handle. + */ +native bool:MorePlugins(Handle:iter); + +/** + * Returns the current plugin in the iterator and advances the iterator. + * + * @param iter Handle to the plugin iterator. + * @return Current plugin the iterator is at, before + * the iterator is advanced. + * @error Invalid Handle. + */ +native Handle:ReadPlugin(Handle:iter); + +/** + * Returns a plugin's status. + * + * @param plugin Plugin Handle (INVALID_HANDLE uses the calling plugin). + * @return Status code for the plugin. + * @error Invalid Handle. + */ +native PluginStatus:GetPluginStatus(Handle:plugin); + +/** + * Retrieves a plugin's file name relative to the plugins folder. + * + * @param plugin Plugin Handle (INVALID_HANDLE uses the calling plugin). + * @param buffer Buffer to the store the file name. + * @param maxlength Maximum length of the name buffer. + * @noreturn + * @error Invalid Handle. + */ +native GetPluginFilename(Handle:plugin, String:buffer[], maxlength); + +/** + * Retrieves whether or not a plugin is being debugged. + * + * @param plugin Plugin Handle (INVALID_HANDLE uses the calling plugin). + * @return True if being debugged, false otherwise. + * @error Invalid Handle. + */ +native bool:IsPluginDebugging(Handle:hndl); + +/** + * Retrieves a plugin's public info. + * + * @param plugin Plugin Handle (INVALID_HANDLE uses the calling plugin). + * @param info Plugin info property to retrieve. + * @param buffer Buffer to store info in. + * @param maxlength Maximum length of buffer. + * @return True on success, false if property is not available. + * @error Invalid Handle. + */ +native bool:GetPluginInfo(Handle:plugin, PluginInfo:info, String:buffer[], maxlength); /** * Aborts the current callback and throws an error. This function