From c803eb8328425e8b23c81841e0057a9a2dbcfdd4 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Mon, 15 Oct 2007 04:06:57 +0000 Subject: [PATCH] fixed an overall deficiency where libraries did not include extensions. extensions can now mark themselves as libraries, and they thus become fully optional just as plugins do. additionally, a bug was fixed where plugins could be accidentally marked as required instead of optional. these changes resulted in a bcompat API bump to the extension/sharesys interface. --HG-- extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%401578 --- core/systems/ExtensionSys.cpp | 32 +++++++- core/systems/ExtensionSys.h | 3 + core/systems/PluginSys.cpp | 100 +++++++++++++++++++------ core/systems/PluginSys.h | 2 +- core/systems/ShareSys.cpp | 4 + core/systems/ShareSys.h | 1 + extensions/topmenus/extension.cpp | 2 + extensions/topmenus/sdk/smsdk_config.h | 2 +- plugins/include/adminmenu.inc | 3 +- plugins/include/sourcemod.inc | 10 ++- plugins/include/topmenus.inc | 13 +++- public/IExtensionSys.h | 2 +- public/IShareSys.h | 8 ++ 13 files changed, 147 insertions(+), 35 deletions(-) diff --git a/core/systems/ExtensionSys.cpp b/core/systems/ExtensionSys.cpp index 6618f1c9..f0ec6af0 100644 --- a/core/systems/ExtensionSys.cpp +++ b/core/systems/ExtensionSys.cpp @@ -340,6 +340,11 @@ bool CExtension::IsRunning(char *error, size_t maxlength) return m_pAPI->QueryRunning(error, maxlength); } +void CExtension::AddLibrary(const char *library) +{ + m_Libraries.push_back(library); +} + /********************* * EXTENSION MANAGER * *********************/ @@ -628,7 +633,9 @@ void CExtensionManager::BindAllNativesToPlugin(IPlugin *pPlugin) { WeakNative wkn = WeakNative((CPlugin *)pPlugin, i); x_native->owner->m_WeakNatives.push_back(wkn); - } else if (exts.find(x_native->owner) == exts.end()) { + } + else if (exts.find(x_native->owner) == exts.end()) + { exts.push_back(x_native->owner); } } @@ -677,6 +684,14 @@ bool CExtensionManager::UnloadExtension(IExtension *_pExt) p_iter = pExt->m_Plugins.erase(p_iter); } + List::iterator s_iter; + for (s_iter = pExt->m_Libraries.begin(); + s_iter != pExt->m_Libraries.end(); + s_iter++) + { + g_PluginSys.OnLibraryAction((*s_iter).c_str(), false, true); + } + /* Unbound weak natives */ List::iterator wkn_iter; for (wkn_iter=pExt->m_WeakNatives.begin(); wkn_iter!=pExt->m_WeakNatives.end(); wkn_iter++) @@ -718,7 +733,9 @@ bool CExtensionManager::UnloadExtension(IExtension *_pExt) } pAPI->NotifyInterfaceDrop((*i_iter).iface); i_iter = pDep->m_Deps.erase(i_iter); - } else { + } + else + { i_iter++; } } @@ -729,7 +746,9 @@ bool CExtensionManager::UnloadExtension(IExtension *_pExt) if ((*i_iter).owner == pExt) { i_iter = pDep->m_ChildDeps.erase(i_iter); - } else { + } + else + { i_iter++; } } @@ -1092,3 +1111,10 @@ CExtensionManager::CExtensionManager() CExtensionManager::~CExtensionManager() { } + +void CExtensionManager::AddLibrary(IExtension *pSource, const char *library) +{ + CExtension *pExt = (CExtension *)pSource; + pExt->AddLibrary(library); + g_PluginSys.OnLibraryAction(library, false, false); +} diff --git a/core/systems/ExtensionSys.h b/core/systems/ExtensionSys.h index 579f625a..8ad05a8d 100644 --- a/core/systems/ExtensionSys.h +++ b/core/systems/ExtensionSys.h @@ -78,6 +78,7 @@ public: void AddPlugin(IPlugin *pPlugin); void RemovePlugin(IPlugin *pPlugin); void MarkAllLoaded(); + void AddLibrary(const char *library); private: bool Load(char *error, size_t maxlength); private: @@ -93,6 +94,7 @@ private: List m_Plugins; List m_Natives; List m_WeakNatives; + List m_Libraries; PluginId m_PlId; unsigned int unload_code; bool m_FullyLoaded; @@ -132,6 +134,7 @@ public: void MarkAllLoaded(); void AddDependency(IExtension *pSource, const char *file, bool required, bool autoload); void TryAutoload(); + void AddLibrary(IExtension *pSource, const char *library); public: CExtension *GetExtensionFromIdent(IdentityToken_t *ptr); void Shutdown(); diff --git a/core/systems/PluginSys.cpp b/core/systems/PluginSys.cpp index 1934e25e..e50147df 100644 --- a/core/systems/PluginSys.cpp +++ b/core/systems/PluginSys.cpp @@ -466,7 +466,7 @@ void CPlugin::LibraryActions(bool dropping) iter != m_Libraries.end(); iter++) { - g_PluginSys.OnLibraryAction((*iter).c_str(), dropping); + g_PluginSys.OnLibraryAction((*iter).c_str(), true, dropping); } } @@ -988,7 +988,9 @@ LoadRes CPluginManager::_LoadPlugin(CPlugin **_plugin, const char *path, bool de { /* Autoload any modules */ LoadOrRequireExtensions(pPlugin, 1, error, maxlength); - } else { + } + else + { pPlugin->SetErrorState(Plugin_Failed, "%s", error); } } @@ -1156,12 +1158,16 @@ bool CPluginManager::FindOrRequirePluginDeps(CPlugin *pPlugin, char *error, size return false; } } - } else { + } + else + { /* Check that we aren't registering the same library twice */ if (pPlugin->m_RequiredLibs.find(name) == pPlugin->m_RequiredLibs.end()) { pPlugin->m_RequiredLibs.push_back(name); - } else { + } + else + { continue; } List::iterator iter; @@ -1237,7 +1243,9 @@ bool CPluginManager::LoadOrRequireExtensions(CPlugin *pPlugin, unsigned int pass g_LibSys.PathFormat(path, PLATFORM_MAX_PATH, "%s", file); g_Extensions.LoadAutoExtension(path); } - } else if (pass == 2) { + } + else if (pass == 2) + { /* Is this required? */ if (ext->required) { @@ -1256,10 +1264,32 @@ bool CPluginManager::LoadOrRequireExtensions(CPlugin *pPlugin, unsigned int pass snprintf(error, maxlength, "Required extension \"%s\" file(\"%s\") not running", name, file); } return false; - } else { + } + else + { g_Extensions.BindChildPlugin(pExt, pPlugin); } } + else + { + IPluginFunction *pFunc; + char buffer[64]; + UTIL_Format(buffer, sizeof(buffer), "__ext_%s_SetNTVOptional", &pubvar->name[6]); + + if ((pFunc = pBase->GetFunctionByName(buffer)) != NULL) + { + cell_t res; + pFunc->Execute(&res); + if (pPlugin->GetContext()->n_err != SP_ERROR_NONE) + { + if (error) + { + UTIL_Format(error, maxlength, "Fatal error during plugin initialization (ext req)"); + } + return false; + } + } + } } } } @@ -1277,13 +1307,14 @@ bool CPluginManager::RunSecondPass(CPlugin *pPlugin, char *error, size_t maxleng /* Bind all extra natives */ g_Extensions.BindAllNativesToPlugin(pPlugin); - AddFakeNativesToPlugin(pPlugin); if (!FindOrRequirePluginDeps(pPlugin, error, maxlength)) { return false; } + AddFakeNativesToPlugin(pPlugin); + /* Find any unbound natives * Right now, these are not allowed */ @@ -1345,7 +1376,7 @@ bool CPluginManager::RunSecondPass(CPlugin *pPlugin, char *error, size_t maxleng s_iter != pPlugin->m_Libraries.end(); s_iter++) { - OnLibraryAction((*s_iter).c_str(), false); + OnLibraryAction((*s_iter).c_str(), true, false); } return true; @@ -1505,7 +1536,7 @@ bool CPluginManager::UnloadPlugin(IPlugin *plugin) s_iter != pPlugin->m_Libraries.end(); s_iter++) { - OnLibraryAction((*s_iter).c_str(), true); + OnLibraryAction((*s_iter).c_str(), true, true); } /* Go through all dependent plugins and tell them this plugin is now gone */ @@ -2409,7 +2440,7 @@ CPlugin *CPluginManager::GetPluginFromIdentity(IdentityToken_t *pToken) return (CPlugin *)(pToken->ptr); } -void CPluginManager::OnLibraryAction(const char *lib, bool drop) +void CPluginManager::OnLibraryAction(const char *lib, bool is_a_plugin, bool drop) { List::iterator iter; @@ -2420,6 +2451,14 @@ void CPluginManager::OnLibraryAction(const char *lib, bool drop) cell_t required; } *plc; + struct _ext + { + cell_t name; + cell_t file; + cell_t autoload; + cell_t required; + } *ext; + const char *name = drop ? "OnLibraryRemoved" : "OnLibraryAdded"; for (iter=m_plugins.begin(); @@ -2445,23 +2484,38 @@ void CPluginManager::OnLibraryAction(const char *lib, bool drop) { continue; } - if (strncmp(pubvar->name, "__pl_", 5) != 0) + if (is_a_plugin && strncmp(pubvar->name, "__pl_", 5) == 0) { - continue; + plc = (_pl *)pubvar->offs; + if (plc->required) + { + continue; + } + char *str; + pContext->LocalToString(plc->name, &str); + if (strcmp(str, lib) != 0) + { + continue; + } + pf->PushString(lib); + pf->Execute(NULL); } - plc = (_pl *)pubvar->offs; - if (plc->required) + else if (!is_a_plugin && strncmp(pubvar->name, "__ext_", 6) == 0) { - continue; + ext = (_ext *)pubvar->offs; + if (ext->required) + { + continue; + } + char *str; + pContext->LocalToString(ext->name, &str); + if (strcmp(str, lib) != 0) + { + continue; + } + pf->PushString(lib); + pf->Execute(NULL); } - char *str; - pContext->LocalToString(plc->name, &str); - if (strcmp(str, lib) != 0) - { - continue; - } - pf->PushString(lib); - pf->Execute(NULL); } } } diff --git a/core/systems/PluginSys.h b/core/systems/PluginSys.h index a0dd9f55..a0a1f50c 100644 --- a/core/systems/PluginSys.h +++ b/core/systems/PluginSys.h @@ -431,7 +431,7 @@ public: void Shutdown(); - void OnLibraryAction(const char *lib, bool drop); + void OnLibraryAction(const char *lib, bool is_a_plugin, bool drop); bool LibraryExists(const char *lib); diff --git a/core/systems/ShareSys.cpp b/core/systems/ShareSys.cpp index 2f790bcc..1154e4d4 100644 --- a/core/systems/ShareSys.cpp +++ b/core/systems/ShareSys.cpp @@ -239,3 +239,7 @@ void ShareSystem::AddDependency(IExtension *myself, const char *filename, bool r g_Extensions.AddDependency(myself, filename, require, autoload); } +void ShareSystem::RegisterLibrary(IExtension *myself, const char *name) +{ + g_Extensions.AddLibrary(myself, name); +} diff --git a/core/systems/ShareSys.h b/core/systems/ShareSys.h index 433506c3..6c34f618 100644 --- a/core/systems/ShareSys.h +++ b/core/systems/ShareSys.h @@ -80,6 +80,7 @@ public: //IShareSys void DestroyIdentType(IdentityType_t type); void DestroyIdentity(IdentityToken_t *identity); void AddDependency(IExtension *myself, const char *filename, bool require, bool autoload); + void RegisterLibrary(IExtension *myself, const char *name); public: //SMGlobalClass /* Pre-empt in case anything tries to register idents early */ void OnSourceModStartup(bool late); diff --git a/extensions/topmenus/extension.cpp b/extensions/topmenus/extension.cpp index 4ad67705..c7761293 100644 --- a/extensions/topmenus/extension.cpp +++ b/extensions/topmenus/extension.cpp @@ -52,6 +52,8 @@ bool TopMenuExtension::SDK_OnLoad(char *error, size_t maxlength, bool late) Initialize_Natives(); + sharesys->RegisterLibrary(myself, "TopMenus"); + return true; } diff --git a/extensions/topmenus/sdk/smsdk_config.h b/extensions/topmenus/sdk/smsdk_config.h index 602cff62..3da0e133 100644 --- a/extensions/topmenus/sdk/smsdk_config.h +++ b/extensions/topmenus/sdk/smsdk_config.h @@ -42,7 +42,7 @@ /* Basic information exposed publicly */ #define SMEXT_CONF_NAME "Top Menus" #define SMEXT_CONF_DESCRIPTION "Creates sorted nested menus" -#define SMEXT_CONF_VERSION "1.0.0.0" +#define SMEXT_CONF_VERSION SVN_FULL_VERSION #define SMEXT_CONF_AUTHOR "AlliedModders" #define SMEXT_CONF_URL "http://www.sourcemod.net/" #define SMEXT_CONF_LOGTAG "MAINMENU" diff --git a/plugins/include/adminmenu.inc b/plugins/include/adminmenu.inc index ff8dab4c..bbb0500f 100644 --- a/plugins/include/adminmenu.inc +++ b/plugins/include/adminmenu.inc @@ -126,9 +126,10 @@ public SharedPlugin:__pl_adminmenu = #endif }; +#if !defined REQUIRE_PLUGIN public __pl_adminmenu_SetNTVOptional() { MarkNativeAsOptional("GetAdminTopMenu"); MarkNativeAsOptional("AddTargetsToMenu"); } - +#endif diff --git a/plugins/include/sourcemod.inc b/plugins/include/sourcemod.inc index 52f268e0..aa33535a 100644 --- a/plugins/include/sourcemod.inc +++ b/plugins/include/sourcemod.inc @@ -467,16 +467,18 @@ native bool:LibraryExists(const String:name[]); native GetExtensionFileStatus(const String:name[], String:error[]="", maxlength=0); /** - * Called after a library (plugin) is added that the - * current plugin references optionally. + * Called after a library is added that the current plugin references + * optionally. A library is either a plugin name or extension name, as + * exposed via its include file. * * @param name Library name. */ forward OnLibraryAdded(const String:name[]); /** - * Called right before a library (plugin) is removed that the - * current plugin references optionally. + * Called right before a library is removed that the current plugin references + * optionally. A library is either a plugin name or extension name, as + * exposed via its include file. * * @param name Library name. */ diff --git a/plugins/include/topmenus.inc b/plugins/include/topmenus.inc index a99b834f..a71192cf 100644 --- a/plugins/include/topmenus.inc +++ b/plugins/include/topmenus.inc @@ -225,7 +225,7 @@ native TopMenuObject:FindTopMenuCategory(Handle:topmenu, const String:name[]); /** * Do not edit below this line! */ -public Extension:__ext_cstrike = +public Extension:__ext_topmenus = { name = "TopMenus", file = "topmenus.ext", @@ -241,3 +241,14 @@ public Extension:__ext_cstrike = #endif }; +#if !defined REQUIRE_EXTENSIONS +public __ext_topmenus_SetNTVOptional() +{ + MarkNativeAsOptional("CreateTopMenu"); + MarkNativeAsOptional("LoadTopMenuConfig"); + MarkNativeAsOptional("AddToTopMenu"); + MarkNativeAsOptional("RemoveFromTopMenu"); + MarkNativeAsOptional("DisplayTopMenu"); + MarkNativeAsOptional("FindTopMenuCategory"); +} +#endif diff --git a/public/IExtensionSys.h b/public/IExtensionSys.h index 2d2c4dae..3a7fe58c 100644 --- a/public/IExtensionSys.h +++ b/public/IExtensionSys.h @@ -117,7 +117,7 @@ namespace SourceMod /** * @brief Version code of the IExtensionInterface API itself. */ - #define SMINTERFACE_EXTENSIONAPI_VERSION 1 + #define SMINTERFACE_EXTENSIONAPI_VERSION 2 /** * @brief The interface an extension must expose. diff --git a/public/IShareSys.h b/public/IShareSys.h index 4654e82e..c97db5e5 100644 --- a/public/IShareSys.h +++ b/public/IShareSys.h @@ -192,6 +192,14 @@ namespace SourceMod * @param autoload Whether or not to autoload this extension. */ virtual void AddDependency(IExtension *myself, const char *filename, bool require, bool autoload) =0; + + /** + * @brief Registers a library name to an extension. + * + * @param myself Extension to register library to. + * @param name Library name. + */ + virtual void RegisterLibrary(IExtension *myself, const char *name) =0; }; }