diff --git a/core/PluginSys.cpp b/core/PluginSys.cpp index c7eb95db..81bbd832 100644 --- a/core/PluginSys.cpp +++ b/core/PluginSys.cpp @@ -57,6 +57,7 @@ CPlugin::CPlugin(const char *file) m_type = PluginType_Private; m_status = Plugin_Uncompiled; + m_bSilentlyFailed = false; m_serial = ++MySerial; m_pRuntime = NULL; m_errormsg[256] = '\0'; @@ -386,22 +387,27 @@ void CPlugin::Call_OnAllPluginsLoaded() } } -bool CPlugin::Call_AskPluginLoad(char *error, size_t maxlength) +APLRes CPlugin::Call_AskPluginLoad(char *error, size_t maxlength) { if (m_status != Plugin_Created) { - return false; + return APLRes_Failure; } m_status = Plugin_Loaded; int err; cell_t result; - IPluginFunction *pFunction = m_pRuntime->GetFunctionByName("AskPluginLoad"); + bool haveNewAPL = false; + IPluginFunction *pFunction = m_pRuntime->GetFunctionByName("AskPluginLoad2"); - if (!pFunction) + if (pFunction) { - return true; + haveNewAPL = true; + } + else if (!(pFunction = m_pRuntime->GetFunctionByName("AskPluginLoad"))) + { + return APLRes_Success; } pFunction->PushCell(m_handle); @@ -410,15 +416,21 @@ bool CPlugin::Call_AskPluginLoad(char *error, size_t maxlength) pFunction->PushCell(maxlength); if ((err=pFunction->Execute(&result)) != SP_ERROR_NONE) { - return false; + return APLRes_Failure; } - if (!result || m_status != Plugin_Loaded) + if (haveNewAPL) { - return false; + return (APLRes)result; + } + else if (result) + { + return APLRes_Success; + } + else + { + return APLRes_Failure; } - - return true; } void *CPlugin::GetPluginStructure() @@ -470,6 +482,11 @@ PluginStatus CPlugin::GetStatus() return m_status; } +bool CPlugin::IsSilentlyFailed() +{ + return m_bSilentlyFailed; +} + bool CPlugin::IsDebugging() { if (m_pRuntime == NULL) @@ -480,6 +497,11 @@ bool CPlugin::IsDebugging() return true; } +void CPlugin::SetSilentlyFailed(bool sf) +{ + m_bSilentlyFailed = sf; +} + void CPlugin::LibraryActions(bool dropping) { List::iterator iter; @@ -1004,20 +1026,31 @@ LoadRes CPluginManager::_LoadPlugin(CPlugin **_plugin, const char *path, bool de } } + LoadRes loadFailure = LoadRes_Failure; /* Get the status */ if (pPlugin->GetStatus() == Plugin_Created) { /* First native pass - add anything from Core */ g_ShareSys.BindNativesToPlugin(pPlugin, true); pPlugin->InitIdentity(); - if (pPlugin->Call_AskPluginLoad(error, maxlength)) + APLRes result = pPlugin->Call_AskPluginLoad(error, maxlength); + switch (result) { + case APLRes_Success: /* Autoload any modules */ LoadOrRequireExtensions(pPlugin, 1, error, maxlength); - } - else - { + break; + case APLRes_Failure: pPlugin->SetErrorState(Plugin_Failed, "%s", error); + loadFailure = LoadRes_Failure; + break; + case APLRes_SilentFailure: + pPlugin->SetErrorState(Plugin_Failed, "%s", error); + loadFailure = LoadRes_SilentFailure; + pPlugin->SetSilentlyFailed(true); + break; + default: + assert(false); } } @@ -1030,7 +1063,7 @@ LoadRes CPluginManager::_LoadPlugin(CPlugin **_plugin, const char *path, bool de *_plugin = pPlugin; } - return (pPlugin->GetStatus() == Plugin_Loaded) ? LoadRes_Successful : LoadRes_Failure; + return (pPlugin->GetStatus() == Plugin_Loaded) ? LoadRes_Successful : loadFailure; } IPlugin *CPluginManager::LoadPlugin(const char *path, bool debug, PluginType type, char error[], size_t maxlength, bool *wasloaded) @@ -1095,7 +1128,7 @@ void CPluginManager::LoadAutoPlugin(const char *plugin) error); } - if (res == LoadRes_Successful || res == LoadRes_Failure) + if (res == LoadRes_Successful || res == LoadRes_Failure || res == LoadRes_SilentFailure) { AddPlugin(pl); } @@ -1951,7 +1984,7 @@ void CPluginManager::OnRootConsoleCommand(const char *cmdname, const CCommand &c assert(pl->GetStatus() != Plugin_Created); int len = 0; const sm_plugininfo_t *info = pl->GetPublicInfo(); - if (pl->GetStatus() != Plugin_Running) + if (pl->GetStatus() != Plugin_Running && !pl->IsSilentlyFailed()) { len += UTIL_Format(buffer, sizeof(buffer), " %02d <%s>", id, GetStatusText(pl->GetStatus())); @@ -1967,6 +2000,8 @@ void CPluginManager::OnRootConsoleCommand(const char *cmdname, const CCommand &c } if (pl->GetStatus() < Plugin_Created) { + if (pl->IsSilentlyFailed()) + len += UTIL_Format(&buffer[len], sizeof(buffer)-len, " Disabled:"); len += UTIL_Format(&buffer[len], sizeof(buffer)-len, " \"%s\"", (IS_STR_FILLED(info->name)) ? info->name : pl->GetFilename()); if (IS_STR_FILLED(info->version)) { diff --git a/core/PluginSys.h b/core/PluginSys.h index d40cff17..d1b37dd5 100644 --- a/core/PluginSys.h +++ b/core/PluginSys.h @@ -117,9 +117,17 @@ enum LoadRes LoadRes_Successful, LoadRes_AlreadyLoaded, LoadRes_Failure, + LoadRes_SilentFailure, LoadRes_NeverLoad }; +enum APLRes +{ + APLRes_Success, + APLRes_Failure, + APLRes_SilentFailure +}; + struct AutoConfig { String autocfg; @@ -146,6 +154,8 @@ public: const char *GetFilename(); bool IsDebugging(); PluginStatus GetStatus(); + bool IsSilentlyFailed(); + void SetSilentlyFailed(bool sf); const sm_plugininfo_t *GetPublicInfo(); bool SetPauseState(bool paused); unsigned int GetSerial(); @@ -183,7 +193,7 @@ public: * * If the error buffer is NULL, the error message is cached locally. */ - bool Call_AskPluginLoad(char *error, size_t maxlength); + APLRes Call_AskPluginLoad(char *error, size_t maxlength); /** * Calls the OnPluginStart function. @@ -247,6 +257,7 @@ private: PluginType m_type; char m_filename[PLATFORM_MAX_PATH]; PluginStatus m_status; + bool m_bSilentlyFailed; unsigned int m_serial; sm_plugininfo_t m_info; char m_errormsg[256]; diff --git a/plugins/include/sourcemod.inc b/plugins/include/sourcemod.inc index c72d0512..3afb5208 100644 --- a/plugins/include/sourcemod.inc +++ b/plugins/include/sourcemod.inc @@ -74,6 +74,13 @@ struct Plugin #include #include +enum APLRes +{ + APLRes_Success = 0, /**< Plugin should load */ + APLRes_Failure, /**< Plugin shouldn't load and should display an error */ + APLRes_SilentFailure /**< Plugin shouldn't load but do so silently */ +}; + /** * Declare this as a struct in your plugin to expose its information. * Example: @@ -101,26 +108,35 @@ public Plugin:myinfo; * @noreturn */ forward OnPluginStart(); - + +/** + * @deprecated Use AskPluginLoad2() instead. + * If a plugin contains both AskPluginLoad() and AskPluginLoad2(), the former will + * not be called, but old plugins with only AskPluginLoad() will work. + */ +#pragma deprecated Use AskPluginLoad2() instead +forward bool:AskPluginLoad(Handle:myself, bool:late, String:error[], err_max); + /** * Called before OnPluginStart, in case the plugin wants to check for load failure. * This is called even if the plugin type is "private." Any natives from modules are * not available at this point. Thus, this forward should only be used for explicit - * pre-emptive things, such as adding dynamic natives, or setting certain types of load filters. + * pre-emptive things, such as adding dynamic natives, setting certain types of load + * filters (such as not loading the plugin for certain games). * * @note It is not safe to call externally resolved natives until OnPluginStart(). * @note Any sort of RTE in this function will cause the plugin to fail loading. - * @note You MUST remember to return SOMETHING here. The act of not returning is - * equivalent to returning 0 (false). If you forgot to return, it will - * cause your plugin to not load with a very strange error message. + * @note If you do not return anything, it is treated like returning success. + * @note If a plugin has an AskPluginLoad2(), AskPluginLoad() will not be called. + * * * @param myself Handle to the plugin. * @param late Whether or not the plugin was loaded "late" (after map load). * @param error Error message buffer in case load failed. * @param err_max Maximum number of characters for error message buffer. - * @return True if load success, false otherwise. + * @return APLRes_Success for load success, APLRes_Failure or APLRes_SilentFailure otherwise */ -forward bool:AskPluginLoad(Handle:myself, bool:late, String:error[], err_max); +forward APLRes:AskPluginLoad2(Handle:myself, bool:late, String:error[], err_max); /** * Called when the plugin is about to be unloaded.