diff --git a/core/smn_core.cpp b/core/smn_core.cpp index e5791c52..966b635c 100644 --- a/core/smn_core.cpp +++ b/core/smn_core.cpp @@ -339,7 +339,8 @@ static cell_t MarkNativeAsOptional(IPluginContext *pContext, const cell_t *param pContext->LocalToString(params[1], &name); if (pContext->FindNativeByName(name, &idx) != SP_ERROR_NONE) { - return pContext->ThrowNativeError("Unable to find native \"%s\"", name); + /* Oops! This HAS to silently fail! */ + return 0; } ctx->natives[idx].flags |= SP_NTVFLAG_OPTIONAL; @@ -359,6 +360,14 @@ static cell_t RegPluginLibrary(IPluginContext *pContext, const cell_t *params) return 1; } +static cell_t LibraryExists(IPluginContext *pContext, const cell_t *params) +{ + char *str; + pContext->LocalToString(params[1], &str); + + return g_PluginSys.LibraryExists(str) ? 1 : 0; +} + REGISTER_NATIVES(coreNatives) { {"AutoExecConfig", AutoExecConfig}, @@ -376,5 +385,6 @@ REGISTER_NATIVES(coreNatives) {"FormatTime", FormatTime}, {"MarkNativeAsOptional", MarkNativeAsOptional}, {"RegPluginLibrary", RegPluginLibrary}, + {"LibraryExists", LibraryExists}, {NULL, NULL}, }; diff --git a/core/systems/PluginSys.cpp b/core/systems/PluginSys.cpp index 5b60ea53..f0976cfa 100644 --- a/core/systems/PluginSys.cpp +++ b/core/systems/PluginSys.cpp @@ -425,15 +425,31 @@ bool CPlugin::IsDebugging() return ((m_ctx.ctx->flags & SP_FLAG_DEBUG) == SP_FLAG_DEBUG); } +void CPlugin::LibraryActions(bool dropping) +{ + List::iterator iter; + for (iter = m_Libraries.begin(); + iter != m_Libraries.end(); + iter++) + { + g_PluginSys.OnLibraryAction((*iter).c_str(), dropping); + } +} + bool CPlugin::SetPauseState(bool paused) { - if (paused && GetStatus() != Plugin_Paused) + if (paused && GetStatus() != Plugin_Running) { return false; - } else if (!paused && GetStatus() != Plugin_Running) { + } else if (!paused && GetStatus() != Plugin_Paused) { return false; } + if (paused) + { + LibraryActions(true); + } + IPluginFunction *pFunction = m_ctx.base->GetFunctionByName("OnPluginPauseChange"); if (pFunction) { @@ -453,6 +469,11 @@ bool CPlugin::SetPauseState(bool paused) g_PluginSys._SetPauseState(this, paused); + if (!paused) + { + LibraryActions(false); + } + return true; } @@ -1253,6 +1274,15 @@ bool CPluginManager::RunSecondPass(CPlugin *pPlugin, char *error, size_t maxleng } } + /* Go through our libraries and tell other plugins they're added */ + List::iterator s_iter; + for (s_iter = pPlugin->m_Libraries.begin(); + s_iter != pPlugin->m_Libraries.end(); + s_iter++) + { + OnLibraryAction((*s_iter).c_str(), false); + } + return true; } @@ -1395,6 +1425,15 @@ bool CPluginManager::UnloadPlugin(IPlugin *plugin) m_plugins.remove(pPlugin); sm_trie_delete(m_LoadLookup, pPlugin->m_filename); + /* Go through our libraries and tell other plugins they're gone */ + List::iterator s_iter; + for (s_iter = pPlugin->m_Libraries.begin(); + s_iter != pPlugin->m_Libraries.end(); + s_iter++) + { + OnLibraryAction((*s_iter).c_str(), true); + } + /* Go through all dependent plugins and tell them this plugin is now gone */ List::iterator pl_iter; CPlugin *pOther; @@ -2190,9 +2229,88 @@ CPlugin *CPluginManager::GetPluginFromIdentity(IdentityToken_t *pToken) return (CPlugin *)(pToken->ptr); } -void CPluginManager::ExecAndGenPluginConfs() +void CPluginManager::OnLibraryAction(const char *lib, bool drop) { List::iterator iter; - //for (iter = + struct _pl + { + cell_t name; + cell_t file; + cell_t required; + } *plc; + + const char *name = drop ? "OnLibraryRemoved" : "OnLibraryAdded"; + + for (iter=m_plugins.begin(); + iter!=m_plugins.end(); + iter++) + { + CPlugin *pl = (*iter); + if (pl->GetStatus() != Plugin_Running) + { + continue; + } + IPluginContext *pContext = pl->GetBaseContext(); + IPluginFunction *pf = pContext->GetFunctionByName(name); + if (!pf) + { + continue; + } + sp_context_t *ctx = pContext->GetContext(); + uint32_t num_vars = pContext->GetPubVarsNum(); + for (uint32_t i=0; iGetPubvarByIndex(i, &pubvar) != SP_ERROR_NONE) + { + continue; + } + if (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); + } + } +} + +bool CPluginManager::LibraryExists(const char *lib) +{ + List::iterator iter; + + for (iter=m_plugins.begin(); + iter!=m_plugins.end(); + iter++) + { + CPlugin *pl = (*iter); + if (pl->GetStatus() != Plugin_Running) + { + continue; + } + List::iterator s_iter; + for (s_iter = pl->m_Libraries.begin(); + s_iter != pl->m_Libraries.end(); + s_iter++) + { + if ((*s_iter).compare(lib) == 0) + { + return true; + } + } + } + + return false; } diff --git a/core/systems/PluginSys.h b/core/systems/PluginSys.h index d8292242..9b0f0628 100644 --- a/core/systems/PluginSys.h +++ b/core/systems/PluginSys.h @@ -250,6 +250,7 @@ public: { m_Libraries.push_back(name); } + void LibraryActions(bool dropping); protected: void UpdateInfo(); void SetTimeStamp(time_t t); @@ -398,6 +399,9 @@ public: void Shutdown(); + void OnLibraryAction(const char *lib, bool drop); + + bool LibraryExists(const char *lib); private: LoadRes _LoadPlugin(CPlugin **pPlugin, const char *path, bool debug, PluginType type, char error[], size_t maxlength); @@ -434,8 +438,6 @@ private: bool FindOrRequirePluginDeps(CPlugin *pPlugin, char *error, size_t maxlength); void _SetPauseState(CPlugin *pPlugin, bool pause); - - void ExecAndGenPluginConfs(); protected: /** * Caching internal objects diff --git a/plugins/include/sourcemod.inc b/plugins/include/sourcemod.inc index 1f5ff435..14db8693 100644 --- a/plugins/include/sourcemod.inc +++ b/plugins/include/sourcemod.inc @@ -348,5 +348,29 @@ native MarkNativeAsOptional(const String:name[]); */ native RegPluginLibrary(const String:name[]); +/** + * Returns whether a library exists. + * + * @param name Library name. + * @return True if exists, false otherwise. + */ +native bool:LibraryExists(const String:name[]); + +/** + * Called after a library (plugin) is added that the + * current plugin references optionally. + * + * @param name Library name. + */ +forward OnLibraryAdded(const String:name[]); + +/** + * Called right before a library (plugin) is removed that the + * current plugin references optionally. + * + * @param name Library name. + */ +forward OnLibraryRemoved(const String:name[]); + #include #include