From c5d0848177f3dd80fd8bca999ad6492c632341b3 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Thu, 18 Jan 2007 23:28:14 +0000 Subject: [PATCH] finished most of the extension system --HG-- extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%40320 --- TODO.txt | 3 +- core/interfaces/IExtensionSys.h | 9 ++ core/sourcemod.cpp | 23 ++-- core/sourcemod.h | 6 -- core/systems/ExtensionSys.cpp | 155 ++++++++++++++++++++++++--- core/systems/ExtensionSys.h | 7 ++ core/systems/PluginSys.cpp | 180 ++++++++++++++++++++++---------- core/systems/PluginSys.h | 14 ++- core/systems/ShareSys.cpp | 2 +- extensions/sdk/extension.h | 10 ++ extensions/sdk/smsdk_ext.cpp | 4 +- extensions/sdk/smsdk_ext.h | 1 + 12 files changed, 322 insertions(+), 92 deletions(-) diff --git a/TODO.txt b/TODO.txt index 73923ed6..2323d7f6 100644 --- a/TODO.txt +++ b/TODO.txt @@ -1,9 +1,10 @@ things to do for a release, in priority X finish plugin unloading X URGENT: fix compiler's sizeof(), add cellsof - - do module api + X do module api X finish plugin pausing/unpausing, forwards must block execution - do admin api + - make "mapupdated" plugins work as intended (reload on mapchange if newer) X add debugging output to logger - finish ML api, expose through interface X add error messages to format routine diff --git a/core/interfaces/IExtensionSys.h b/core/interfaces/IExtensionSys.h index fc1a68f6..36c5430d 100644 --- a/core/interfaces/IExtensionSys.h +++ b/core/interfaces/IExtensionSys.h @@ -67,6 +67,15 @@ namespace SourceMod * @param iter Pointer to iterator to free. */ virtual void FreeDependencyIterator(ITERATOR *iter) =0; + + /** + * @brief Queries the extension to see its run state. + * + * @param error Error buffer (may be NULL). + * @param maxlength Maximum length of buffer. + * @return True if extension is okay, false if not okay. + */ + virtual bool IsRunning(char *error, size_t maxlength) =0; }; #define SMINTERFACE_EXTENSIONAPI_VERSION 1 diff --git a/core/sourcemod.cpp b/core/sourcemod.cpp index 11ea03d1..2581a7f4 100644 --- a/core/sourcemod.cpp +++ b/core/sourcemod.cpp @@ -7,6 +7,7 @@ #include "PluginSys.h" #include "ShareSys.h" #include "CLogger.h" +#include "ExtensionSys.h" SH_DECL_HOOK6(IServerGameDLL, LevelInit, SH_NOATTRIB, false, bool, const char *, const char *, const char *, const char *, bool, bool); @@ -131,13 +132,11 @@ void SourceModBase::StartSourceMod(bool late) /* First initialize the global hooks we need */ SH_ADD_HOOK_MEMFUNC(IServerGameDLL, LevelInit, gamedll, this, &SourceModBase::LevelInit, false); - m_IsLateLoadInMap = late; - /* Notify! */ SMGlobalClass *pBase = SMGlobalClass::head; while (pBase) { - pBase->OnSourceModStartup(m_IsLateLoadInMap); + pBase->OnSourceModStartup(false); pBase = pBase->m_pGlobalClassNext; } @@ -156,7 +155,6 @@ void SourceModBase::StartSourceMod(bool late) bool SourceModBase::LevelInit(char const *pMapName, char const *pMapEntities, char const *pOldLevel, char const *pLandmarkName, bool loadGame, bool background) { m_IsMapLoading = true; - m_IsLateLoadInMap = false; g_Logger.MapChange(pMapName); @@ -167,6 +165,11 @@ bool SourceModBase::LevelInit(char const *pMapName, char const *pMapEntities, ch RETURN_META_VALUE(MRES_IGNORED, true); } +bool SourceModBase::IsMapLoading() +{ + return m_IsMapLoading; +} + void SourceModBase::DoGlobalPluginLoads() { char config_path[PLATFORM_MAX_PATH]; @@ -181,10 +184,17 @@ void SourceModBase::DoGlobalPluginLoads() "%s/plugins", GetSMBaseDir()); + /* Run the first pass */ g_PluginSys.LoadAll_FirstPass(config_path, plugins_path); + /* Mark any extensions as loaded */ + g_Extensions.MarkAllLoaded(); + /* No modules yet, it's safe to call this from here */ g_PluginSys.LoadAll_SecondPass(); + + /* Re-mark any extensions as loaded */ + g_Extensions.MarkAllLoaded(); } void SourceModBase::CloseSourceMod() @@ -209,11 +219,6 @@ void SourceModBase::CloseSourceMod() ShutdownJIT(); } -bool SourceModBase::IsLateLoadInMap() -{ - return m_IsLateLoadInMap; -} - const char *SourceModBase::GetSMBaseDir() { return m_SMBaseDir; diff --git a/core/sourcemod.h b/core/sourcemod.h index 38a3d217..9b7aa24e 100644 --- a/core/sourcemod.h +++ b/core/sourcemod.h @@ -46,11 +46,6 @@ public: * @brief Returns the base folder for file natives. */ const char *GetBaseDir(); - - /** - * @brief Returns whether our load in this map is late. - */ - bool IsLateLoadInMap(); private: /** * @brief Loading plugins @@ -59,7 +54,6 @@ private: private: char m_SMBaseDir[PLATFORM_MAX_PATH+1]; bool m_IsMapLoading; - bool m_IsLateLoadInMap; }; extern SourceModBase g_SourceMod; diff --git a/core/systems/ExtensionSys.cpp b/core/systems/ExtensionSys.cpp index 7cf0461b..a0f2407d 100644 --- a/core/systems/ExtensionSys.cpp +++ b/core/systems/ExtensionSys.cpp @@ -17,6 +17,7 @@ CExtension::CExtension(const char *filename, char *error, size_t err_max) m_pIdentToken = NULL; m_PlId = 0; unload_code = 0; + m_FullyLoaded = false; char path[PLATFORM_MAX_PATH+1]; g_LibSys.PathFormat(path, PLATFORM_MAX_PATH, "%s/extensions/%s", g_SourceMod.GetSMBaseDir(), filename); @@ -56,7 +57,7 @@ CExtension::CExtension(const char *filename, char *error, size_t err_max) m_pIdentToken = g_ShareSys.CreateIdentity(g_ExtType); - if (!m_pAPI->OnExtensionLoad(this, &g_ShareSys, error, err_max, g_SourceMod.IsLateLoadInMap())) + if (!m_pAPI->OnExtensionLoad(this, &g_ShareSys, error, err_max, !g_SourceMod.IsMapLoading())) { if (m_pAPI->IsMetamodExtension()) { @@ -73,6 +74,12 @@ CExtension::CExtension(const char *filename, char *error, size_t err_max) g_ShareSys.DestroyIdentity(m_pIdentToken); m_pIdentToken = NULL; return; + } else { + /* Check if we're past load time */ + if (!g_SourceMod.IsMapLoading()) + { + m_pAPI->OnExtensionsAllLoaded(); + } } } @@ -98,6 +105,16 @@ CExtension::~CExtension() } } +void CExtension::MarkAllLoaded() +{ + assert(m_FullyLoaded == false); + if (!m_FullyLoaded) + { + m_FullyLoaded = true; + m_pAPI->OnExtensionsAllLoaded(); + } +} + void CExtension::AddPlugin(IPlugin *pPlugin) { m_Plugins.push_back(pPlugin); @@ -204,6 +221,20 @@ void CExtension::AddInterface(SMInterface *pInterface) m_Interfaces.push_back(pInterface); } +bool CExtension::IsRunning(char *error, size_t maxlength) +{ + if (!IsLoaded()) + { + if (error) + { + snprintf(error, maxlength, "%s", m_Error.c_str()); + } + return false; + } + + return m_pAPI->QueryRunning(error, maxlength); +} + /********************* * EXTENSION MANAGER * *********************/ @@ -224,6 +255,13 @@ void CExtensionManager::OnSourceModShutdown() IExtension *CExtensionManager::LoadAutoExtension(const char *path) { + if (!strstr(path, "." PLATFORM_LIB_EXT)) + { + char newpath[PLATFORM_MAX_PATH+1]; + snprintf(newpath, PLATFORM_MAX_PATH, "%s.%s", path, PLATFORM_LIB_EXT); + return LoadAutoExtension(newpath); + } + IExtension *pAlready; if ((pAlready=FindExtensionByFile(path)) != NULL) { @@ -249,6 +287,13 @@ IExtension *CExtensionManager::FindExtensionByFile(const char *file) List::iterator iter; CExtension *pExt; + if (!strstr(file, "." PLATFORM_LIB_EXT)) + { + char path[PLATFORM_MAX_PATH]; + snprintf(path, PLATFORM_MAX_PATH, "%s.%s", file, PLATFORM_LIB_EXT); + return FindExtensionByFile(path); + } + /* Make sure the file direction is right */ char path[PLATFORM_MAX_PATH+1]; g_LibSys.PathFormat(path, PLATFORM_MAX_PATH, "%s", file); @@ -315,6 +360,8 @@ IExtension *CExtensionManager::LoadExtension(const char *file, ExtensionLifetime return NULL; } + /* :TODO: do QueryRunning check if the map is loaded */ + m_Libs.push_back(pExt); return pExt; @@ -372,6 +419,47 @@ CExtension *CExtensionManager::FindByOrder(unsigned int num) return NULL; } +void CExtensionManager::BindAllNativesToPlugin(IPlugin *pPlugin) +{ + List::iterator iter; + CExtension *pExt; + IPluginContext *pContext = pPlugin->GetBaseContext(); + for (iter=m_Libs.begin(); iter!=m_Libs.end(); iter++) + { + pExt = (*iter); + if (!pExt->IsLoaded()) + { + continue; + } + if (!pExt->m_Natives.size()) + { + continue; + } + bool set = false; + List::iterator n_iter; + const sp_nativeinfo_t *natives; + for (n_iter = pExt->m_Natives.begin(); + n_iter != pExt->m_Natives.end(); + n_iter++) + { + natives = (*n_iter); + unsigned int i=0; + while (natives[i].func != NULL && natives[i].name != NULL) + { + if (pContext->BindNative(&natives[i++]) == SP_ERROR_NONE) + { + set = true; + } + } + } + if (set && (pExt->m_Plugins.find(pPlugin) == pExt->m_Plugins.end())) + { + /* For now, mark this plugin as a requirement. Later we'll introduce native filtering. */ + pExt->m_Plugins.push_back(pPlugin); + } + } +} + bool CExtensionManager::UnloadExtension(IExtension *_pExt) { if (!_pExt) @@ -449,6 +537,33 @@ bool CExtensionManager::UnloadExtension(IExtension *_pExt) return true; } +void CExtensionManager::AddNatives(IExtension *pOwner, const sp_nativeinfo_t *natives) +{ + CExtension *pExt = (CExtension *)pOwner; + + pExt->m_Natives.push_back(natives); +} + +void CExtensionManager::MarkAllLoaded() +{ + List::iterator iter; + CExtension *pExt; + + for (iter=m_Libs.begin(); iter!=m_Libs.end(); iter++) + { + pExt = (*iter); + if (!pExt->IsLoaded()) + { + continue; + } + if (pExt->m_FullyLoaded) + { + continue; + } + pExt->MarkAllLoaded(); + } +} + void CExtensionManager::OnRootConsoleCommand(const char *cmd, unsigned int argcount) { if (argcount >= 3) @@ -482,11 +597,17 @@ void CExtensionManager::OnRootConsoleCommand(const char *cmd, unsigned int argco pExt = (*iter); if (pExt->IsLoaded()) { - IExtensionInterface *pAPI = pExt->GetAPI(); - const char *name = pAPI->GetExtensionName(); - const char *version = pAPI->GetExtensionVerString(); - const char *descr = pAPI->GetExtensionDescription(); - g_RootMenu.ConsolePrint("[%02d] %s (%s): %s", num, name, version, descr); + char error[255]; + if (!pExt->IsRunning(error, sizeof(error))) + { + g_RootMenu.ConsolePrint("[%02d] file \"%s\": %s", num, pExt->GetFilename(), error); + } else { + IExtensionInterface *pAPI = pExt->GetAPI(); + const char *name = pAPI->GetExtensionName(); + const char *version = pAPI->GetExtensionVerString(); + const char *descr = pAPI->GetExtensionDescription(); + g_RootMenu.ConsolePrint("[%02d] %s (%s): %s", num, name, version, descr); + } } else { g_RootMenu.ConsolePrint("[%02d] file \"%s\": %s", num, pExt->GetFilename(), pExt->m_Error.c_str()); } @@ -542,13 +663,21 @@ void CExtensionManager::OnRootConsoleCommand(const char *cmd, unsigned int argco g_RootMenu.ConsolePrint(" File: %s", pExt->GetFilename()); g_RootMenu.ConsolePrint(" Loaded: No (%s)", pExt->m_Error.c_str()); } else { - IExtensionInterface *pAPI = pExt->GetAPI(); - g_RootMenu.ConsolePrint(" File: %s", pExt->GetFilename()); - g_RootMenu.ConsolePrint(" Loaded: Yes (version %s)", pAPI->GetExtensionVerString()); - g_RootMenu.ConsolePrint(" Name: %s (%s)", pAPI->GetExtensionName(), pAPI->GetExtensionDescription()); - g_RootMenu.ConsolePrint(" Author: %s (%s)", pAPI->GetExtensionAuthor(), pAPI->GetExtensionURL()); - g_RootMenu.ConsolePrint(" Binary info: API version %d (compiled %s)", pAPI->GetExtensionVersion(), pAPI->GetExtensionDateString()); - g_RootMenu.ConsolePrint(" Metamod enabled: %s", pAPI->IsMetamodExtension() ? "yes" : "no"); + char error[255]; + if (!pExt->IsRunning(error, sizeof(error))) + { + g_RootMenu.ConsolePrint(" File: %s", pExt->GetFilename()); + g_RootMenu.ConsolePrint(" Loaded: Yes"); + g_RootMenu.ConsolePrint(" Running: No (%s)", error); + } else { + IExtensionInterface *pAPI = pExt->GetAPI(); + g_RootMenu.ConsolePrint(" File: %s", pExt->GetFilename()); + g_RootMenu.ConsolePrint(" Loaded: Yes (version %s)", pAPI->GetExtensionVerString()); + g_RootMenu.ConsolePrint(" Name: %s (%s)", pAPI->GetExtensionName(), pAPI->GetExtensionDescription()); + g_RootMenu.ConsolePrint(" Author: %s (%s)", pAPI->GetExtensionAuthor(), pAPI->GetExtensionURL()); + g_RootMenu.ConsolePrint(" Binary info: API version %d (compiled %s)", pAPI->GetExtensionVersion(), pAPI->GetExtensionDateString()); + g_RootMenu.ConsolePrint(" Metamod enabled: %s", pAPI->IsMetamodExtension() ? "yes" : "no"); + } } return; } else if (strcmp(cmd, "unload") == 0) { diff --git a/core/systems/ExtensionSys.h b/core/systems/ExtensionSys.h index ec3d9a05..f3afc978 100644 --- a/core/systems/ExtensionSys.h +++ b/core/systems/ExtensionSys.h @@ -28,12 +28,14 @@ public: //IExtension ITERATOR *FindFirstDependency(IExtension **pOwner, SMInterface **pInterface); bool FindNextDependency(ITERATOR *iter, IExtension **pOwner, SMInterface **pInterface); void FreeDependencyIterator(ITERATOR *iter); + bool IsRunning(char *error, size_t maxlength); public: void SetError(const char *error); void AddDependency(IfaceInfo *pInfo); void AddInterface(SMInterface *pInterface); void AddPlugin(IPlugin *pPlugin); void RemovePlugin(IPlugin *pPlugin); + void MarkAllLoaded(); private: IdentityToken_t *m_pIdentToken; IExtensionInterface *m_pAPI; @@ -43,8 +45,10 @@ private: List m_Deps; List m_Interfaces; List m_Plugins; + List m_Natives; PluginId m_PlId; unsigned int unload_code; + bool m_FullyLoaded; }; class CExtensionManager : @@ -73,6 +77,9 @@ public: void BindDependency(IExtension *pOwner, IfaceInfo *pInfo); void AddInterface(IExtension *pOwner, SMInterface *pInterface); void BindChildPlugin(IExtension *pParent, IPlugin *pPlugin); + void AddNatives(IExtension *pOwner, const sp_nativeinfo_t *natives); + void BindAllNativesToPlugin(IPlugin *pPlugin); + void MarkAllLoaded(); private: CExtension *FindByOrder(unsigned int num); private: diff --git a/core/systems/PluginSys.cpp b/core/systems/PluginSys.cpp index aaef6ef7..bb168ffb 100644 --- a/core/systems/PluginSys.cpp +++ b/core/systems/PluginSys.cpp @@ -693,7 +693,6 @@ void CPluginManager::LoadPluginsFromDir(const char *basedir, const char *localpa } //well i have discovered that gabe newell is very fat, so i wrote this comment now -//:TODO: remove this function, create a better wrapper for LoadPlugin()/LoadAutoPlugin() bool CPluginManager::_LoadPlugin(CPlugin **_plugin, const char *path, bool debug, PluginType type, char error[], size_t err_max) { /** @@ -777,7 +776,11 @@ bool CPluginManager::_LoadPlugin(CPlugin **_plugin, const char *path, bool debug { AddCoreNativesToPlugin(pPlugin); pPlugin->InitIdentity(); - pPlugin->Call_AskPluginLoad(error, err_max); + if (pPlugin->Call_AskPluginLoad(error, err_max)) + { + /* Autoload any modules */ + LoadOrRequireExtensions(pPlugin, 1, error, err_max); + } } if (_plugin) @@ -800,6 +803,16 @@ IPlugin *CPluginManager::LoadPlugin(const char *path, bool debug, PluginType typ AddPlugin(pl); + /* Run second pass if we need to */ + if (IsLateLoadTime() && pl->GetStatus() == Plugin_Loaded) + { + if (!RunSecondPass(pl, error, err_max)) + { + UnloadPlugin(pl); + return NULL; + } + } + return pl; } @@ -837,20 +850,25 @@ void CPluginManager::LoadAll_SecondPass() List::iterator iter; CPlugin *pPlugin; + char error[256]; for (iter=m_plugins.begin(); iter!=m_plugins.end(); iter++) { pPlugin = (*iter); if (pPlugin->GetStatus() == Plugin_Loaded) { - /* :TODO: fix */ - RunSecondPass(pPlugin, NULL, 0); + error[0] = '\0'; + if (!RunSecondPass(pPlugin, error, sizeof(error))) + { + g_Logger.LogError("[SM] Unable to load plugin \"%s\": %s", pPlugin->GetFilename(), error); + pPlugin->SetErrorState(Plugin_Failed, "%s", error); + } } } m_AllPluginsLoaded = true; } -bool CPluginManager::RunSecondPass(CPlugin *pPlugin, char *error, size_t maxlength) +bool CPluginManager::LoadOrRequireExtensions(CPlugin *pPlugin, unsigned int pass, char *error, size_t maxlength) { /* Find any extensions this plugin needs */ struct _ext @@ -888,36 +906,75 @@ bool CPluginManager::RunSecondPass(CPlugin *pPlugin, char *error, size_t maxleng { continue; } - snprintf(path, PLATFORM_MAX_PATH, "%s.%s", file, PLATFORM_LIB_EXT); - pExt = NULL; - /* Attempt to auto-load if necessary */ - if (ext->autoload) + if (pass == 1) { - pExt = g_Extensions.LoadAutoExtension(path); - } - /* See if we can find a similar extension */ - if (ext->required && !pExt) - { - if ((pExt = g_Extensions.FindExtensionByFile(path)) == NULL) + /* Attempt to auto-load if necessary */ + if (ext->autoload) { - pExt = g_Extensions.FindExtensionByName(name); + g_LibSys.PathFormat(path, PLATFORM_MAX_PATH, "%s", file); + g_Extensions.LoadAutoExtension(path); + } + } else if (pass == 2) { + /* Is this required? */ + if (ext->required) + { + g_LibSys.PathFormat(path, PLATFORM_MAX_PATH, "%s", file); + if ((pExt = g_Extensions.FindExtensionByFile(path)) == NULL) + { + pExt = g_Extensions.FindExtensionByName(name); + } + /* :TODO: should we bind to unloaded extensions? + * Currently the extension manager will ignore this. + */ + if (!pExt || !pExt->IsRunning(NULL, 0)) + { + if (error) + { + snprintf(error, maxlength, "Required extension \"%s\" file(\"%s\") not running", name, file); + } + pPlugin->m_status = Plugin_Failed; + return false; + } else { + g_Extensions.BindChildPlugin(pExt, pPlugin); + } } } - /* If we're requiring and got an extension and it's loaded, bind it */ - if (ext->required && pExt && pExt->IsLoaded()) + } + } + + return true; +} + +bool CPluginManager::RunSecondPass(CPlugin *pPlugin, char *error, size_t maxlength) +{ + /* Second pass for extension requirements */ + if (!LoadOrRequireExtensions(pPlugin, 2, error, maxlength)) + { + return false; + } + + /* Bind all extra natives */ + g_Extensions.BindAllNativesToPlugin(pPlugin); + + /* Find any unbound natives + * Right now, these are not allowed + */ + IPluginContext *pContext = pPlugin->GetBaseContext(); + uint32_t num = pContext->GetNativesNum(); + sp_native_t *native; + for (unsigned int i=0; iGetNativeByIndex(i, &native) != SP_ERROR_NONE) + { + break; + } + if (native->status == SP_NATIVE_UNBOUND) + { + if (error) { - g_Extensions.BindChildPlugin(pExt, pPlugin); - } - /* If we're requiring and we didn't get an extension or it's not loaded, error */ - if (ext->required && (!pExt || !pExt->IsLoaded())) - { - if (error) - { - snprintf(error, maxlength, "Required extension \"%s\" (file \"%s\") not found", name, file); - } - pPlugin->m_status = Plugin_Failed; - return false; + snprintf(error, maxlength, "Native \"%s\" was not found.", native->name); } + return false; } } @@ -1268,7 +1325,7 @@ bool CPluginManager::TestAliasMatch(const char *alias, const char *localpath) bool CPluginManager::IsLateLoadTime() const { - return (m_AllPluginsLoaded || g_SourceMod.IsLateLoadInMap()); + return (m_AllPluginsLoaded || !g_SourceMod.IsMapLoading()); } void CPluginManager::OnSourceModAllInitialized() @@ -1486,40 +1543,49 @@ void CPluginManager::OnRootConsoleCommand(const char *command, unsigned int argc return; } - IPluginIterator *iter = GetPluginIterator(); - for (; iter->MorePlugins() && idNextPlugin(), id++) {} - - IPlugin *pl = iter->GetPlugin(); + CPlugin *pl = GetPluginByOrder(num); const sm_plugininfo_t *info = pl->GetPublicInfo(); g_RootMenu.ConsolePrint(" Filename: %s", pl->GetFilename()); - if (IS_STR_FILLED(info->name)) - { - g_RootMenu.ConsolePrint(" Title: %s", info->name); - } - if (IS_STR_FILLED(info->author)) - { - g_RootMenu.ConsolePrint(" Author: %s", info->author); - } - if (IS_STR_FILLED(info->version)) - { - g_RootMenu.ConsolePrint(" Version: %s", info->version); - } - if (IS_STR_FILLED(info->description)) - { - g_RootMenu.ConsolePrint(" Description: %s", info->description); - } - if (IS_STR_FILLED(info->url)) - { - g_RootMenu.ConsolePrint(" URL: %s", info->url); - } - if (pl->GetStatus() >= Plugin_Error) + if (pl->GetStatus() <= Plugin_Error) { + if (IS_STR_FILLED(info->name)) + { + g_RootMenu.ConsolePrint(" Title: %s", info->name); + } + if (IS_STR_FILLED(info->version)) + { + g_RootMenu.ConsolePrint(" Version: %s", info->version); + } + if (IS_STR_FILLED(info->url)) + { + g_RootMenu.ConsolePrint(" URL: %s", info->url); + } + if (IS_STR_FILLED(info->author)) + { + g_RootMenu.ConsolePrint(" Author: %s", info->author); + } + if (IS_STR_FILLED(info->version)) + { + g_RootMenu.ConsolePrint(" Version: %s", info->version); + } + if (IS_STR_FILLED(info->description)) + { + g_RootMenu.ConsolePrint(" Description: %s", info->description); + } g_RootMenu.ConsolePrint(" Debugging: %s", pl->IsDebugging() ? "yes" : "no"); + g_RootMenu.ConsolePrint(" Paused: %s", pl->GetStatus() == Plugin_Running ? "yes" : "no"); + } else { + g_RootMenu.ConsolePrint(" Load error: %s", pl->m_errormsg); + g_RootMenu.ConsolePrint(" File info: (title \"%s\") (version \"%s\")", + info->name ? info->name : "", + info->version ? info->version : ""); + if (IS_STR_FILLED(info->url)) + { + g_RootMenu.ConsolePrint(" File URL: %s", info->url); + } } - iter->Release(); - return; } else if (strcmp(cmd, "debug") == 0) { if (argcount < 5) diff --git a/core/systems/PluginSys.h b/core/systems/PluginSys.h index 2452dc7f..5e804503 100644 --- a/core/systems/PluginSys.h +++ b/core/systems/PluginSys.h @@ -149,13 +149,13 @@ public: void Call_OnPluginUnload(); /** - * Toggles debug mode in the plugin - */ + * Toggles debug mode in the plugin + */ bool ToggleDebugMode(bool debug, char *error, size_t maxlength); /** - * Returns true if a plugin is usable. - */ + * Returns true if a plugin is usable. + */ bool IsRunnable() const; public: time_t HasUpdatedFile(); @@ -277,6 +277,7 @@ public: * Gets status text for a status code */ const char *GetStatusText(PluginStatus status); + private: bool _LoadPlugin(CPlugin **pPlugin, const char *path, bool debug, PluginType type, char error[], size_t err_max); @@ -301,6 +302,11 @@ private: * Adds any globally registered natives to a plugin */ void AddCoreNativesToPlugin(CPlugin *pPlugin); + + /** + * Runs an extension pass on a plugin. + */ + bool LoadOrRequireExtensions(CPlugin *pPlugin, unsigned int pass, char *error, size_t maxlength); protected: /** * Caching internal objects diff --git a/core/systems/ShareSys.cpp b/core/systems/ShareSys.cpp index df8c719c..5d7bb335 100644 --- a/core/systems/ShareSys.cpp +++ b/core/systems/ShareSys.cpp @@ -161,7 +161,7 @@ bool ShareSystem::RequestInterface(const char *iface_name, void ShareSystem::AddNatives(IExtension *myself, const sp_nativeinfo_t *natives) { - + g_Extensions.AddNatives(myself, natives); } void ShareSystem::DestroyIdentity(IdentityToken_t *identity) diff --git a/extensions/sdk/extension.h b/extensions/sdk/extension.h index d93261e1..7d0fc767 100644 --- a/extensions/sdk/extension.h +++ b/extensions/sdk/extension.h @@ -27,6 +27,7 @@ public: /** * @brief This is called once all known extensions have been loaded. + * Note: It is is a good idea to add natives here, if any are provided. */ //virtual void SDK_OnAllLoaded(); @@ -34,6 +35,15 @@ public: * @brief Called when the pause state is changed. */ //virtual void SDK_OnPauseChange(bool paused); + + /** + * @brief this is called when Core wants to know if your extension is working. + * + * @param error Error message buffer. + * @param err_max Size of error message buffer. + * @return True if working, false otherwise. + */ + //virtual void QueryRunning(char *error, size_t maxlength); public: #if defined SMEXT_CONF_METAMOD /** diff --git a/extensions/sdk/smsdk_ext.cpp b/extensions/sdk/smsdk_ext.cpp index b325a682..3bd1ffe2 100644 --- a/extensions/sdk/smsdk_ext.cpp +++ b/extensions/sdk/smsdk_ext.cpp @@ -24,9 +24,9 @@ bool SDKExtension::OnExtensionLoad(IExtension *me, IShareSys *sys, char *error, g_pShareSys = sys; myself = me; +#if defined SMEXT_CONF_METAMOD m_WeAreUnloaded = true; -#if defined SMEXT_CONF_METAMOD if (!m_SourceMMLoaded) { if (error) @@ -41,7 +41,9 @@ bool SDKExtension::OnExtensionLoad(IExtension *me, IShareSys *sys, char *error, if (SDK_OnLoad(error, err_max, late)) { +#if defined SMEXT_CONF_METAMOD m_WeAreUnloaded = true; +#endif return true; } diff --git a/extensions/sdk/smsdk_ext.h b/extensions/sdk/smsdk_ext.h index 7060cb1c..f4d30711 100644 --- a/extensions/sdk/smsdk_ext.h +++ b/extensions/sdk/smsdk_ext.h @@ -13,6 +13,7 @@ #endif using namespace SourceMod; +using namespace SourcePawn; class SDKExtension : #if defined SMEXT_CONF_METAMOD