Add AskPluginLoad2() to allow silent failure, deprecate AskPluginLoad() (bug 3716, r=dvander)

This commit is contained in:
Fyren 2009-03-18 19:20:40 -07:00
parent 81e30e75c4
commit d7917a6a9a
3 changed files with 87 additions and 25 deletions

View File

@ -57,6 +57,7 @@ CPlugin::CPlugin(const char *file)
m_type = PluginType_Private; m_type = PluginType_Private;
m_status = Plugin_Uncompiled; m_status = Plugin_Uncompiled;
m_bSilentlyFailed = false;
m_serial = ++MySerial; m_serial = ++MySerial;
m_pRuntime = NULL; m_pRuntime = NULL;
m_errormsg[256] = '\0'; 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) if (m_status != Plugin_Created)
{ {
return false; return APLRes_Failure;
} }
m_status = Plugin_Loaded; m_status = Plugin_Loaded;
int err; int err;
cell_t result; 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); pFunction->PushCell(m_handle);
@ -410,15 +416,21 @@ bool CPlugin::Call_AskPluginLoad(char *error, size_t maxlength)
pFunction->PushCell(maxlength); pFunction->PushCell(maxlength);
if ((err=pFunction->Execute(&result)) != SP_ERROR_NONE) 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() void *CPlugin::GetPluginStructure()
@ -470,6 +482,11 @@ PluginStatus CPlugin::GetStatus()
return m_status; return m_status;
} }
bool CPlugin::IsSilentlyFailed()
{
return m_bSilentlyFailed;
}
bool CPlugin::IsDebugging() bool CPlugin::IsDebugging()
{ {
if (m_pRuntime == NULL) if (m_pRuntime == NULL)
@ -480,6 +497,11 @@ bool CPlugin::IsDebugging()
return true; return true;
} }
void CPlugin::SetSilentlyFailed(bool sf)
{
m_bSilentlyFailed = sf;
}
void CPlugin::LibraryActions(bool dropping) void CPlugin::LibraryActions(bool dropping)
{ {
List<String>::iterator iter; List<String>::iterator iter;
@ -1004,20 +1026,31 @@ LoadRes CPluginManager::_LoadPlugin(CPlugin **_plugin, const char *path, bool de
} }
} }
LoadRes loadFailure = LoadRes_Failure;
/* Get the status */ /* Get the status */
if (pPlugin->GetStatus() == Plugin_Created) if (pPlugin->GetStatus() == Plugin_Created)
{ {
/* First native pass - add anything from Core */ /* First native pass - add anything from Core */
g_ShareSys.BindNativesToPlugin(pPlugin, true); g_ShareSys.BindNativesToPlugin(pPlugin, true);
pPlugin->InitIdentity(); pPlugin->InitIdentity();
if (pPlugin->Call_AskPluginLoad(error, maxlength)) APLRes result = pPlugin->Call_AskPluginLoad(error, maxlength);
switch (result)
{ {
case APLRes_Success:
/* Autoload any modules */ /* Autoload any modules */
LoadOrRequireExtensions(pPlugin, 1, error, maxlength); LoadOrRequireExtensions(pPlugin, 1, error, maxlength);
} break;
else case APLRes_Failure:
{
pPlugin->SetErrorState(Plugin_Failed, "%s", error); 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; *_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) 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); error);
} }
if (res == LoadRes_Successful || res == LoadRes_Failure) if (res == LoadRes_Successful || res == LoadRes_Failure || res == LoadRes_SilentFailure)
{ {
AddPlugin(pl); AddPlugin(pl);
} }
@ -1951,7 +1984,7 @@ void CPluginManager::OnRootConsoleCommand(const char *cmdname, const CCommand &c
assert(pl->GetStatus() != Plugin_Created); assert(pl->GetStatus() != Plugin_Created);
int len = 0; int len = 0;
const sm_plugininfo_t *info = pl->GetPublicInfo(); 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())); 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->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()); len += UTIL_Format(&buffer[len], sizeof(buffer)-len, " \"%s\"", (IS_STR_FILLED(info->name)) ? info->name : pl->GetFilename());
if (IS_STR_FILLED(info->version)) if (IS_STR_FILLED(info->version))
{ {

View File

@ -117,9 +117,17 @@ enum LoadRes
LoadRes_Successful, LoadRes_Successful,
LoadRes_AlreadyLoaded, LoadRes_AlreadyLoaded,
LoadRes_Failure, LoadRes_Failure,
LoadRes_SilentFailure,
LoadRes_NeverLoad LoadRes_NeverLoad
}; };
enum APLRes
{
APLRes_Success,
APLRes_Failure,
APLRes_SilentFailure
};
struct AutoConfig struct AutoConfig
{ {
String autocfg; String autocfg;
@ -146,6 +154,8 @@ public:
const char *GetFilename(); const char *GetFilename();
bool IsDebugging(); bool IsDebugging();
PluginStatus GetStatus(); PluginStatus GetStatus();
bool IsSilentlyFailed();
void SetSilentlyFailed(bool sf);
const sm_plugininfo_t *GetPublicInfo(); const sm_plugininfo_t *GetPublicInfo();
bool SetPauseState(bool paused); bool SetPauseState(bool paused);
unsigned int GetSerial(); unsigned int GetSerial();
@ -183,7 +193,7 @@ public:
* *
* If the error buffer is NULL, the error message is cached locally. * 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. * Calls the OnPluginStart function.
@ -247,6 +257,7 @@ private:
PluginType m_type; PluginType m_type;
char m_filename[PLATFORM_MAX_PATH]; char m_filename[PLATFORM_MAX_PATH];
PluginStatus m_status; PluginStatus m_status;
bool m_bSilentlyFailed;
unsigned int m_serial; unsigned int m_serial;
sm_plugininfo_t m_info; sm_plugininfo_t m_info;
char m_errormsg[256]; char m_errormsg[256];

View File

@ -74,6 +74,13 @@ struct Plugin
#include <commandfilters> #include <commandfilters>
#include <nextmap> #include <nextmap>
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. * Declare this as a struct in your plugin to expose its information.
* Example: * Example:
@ -102,25 +109,34 @@ public Plugin:myinfo;
*/ */
forward OnPluginStart(); 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. * 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 * 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 * 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 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 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 * @note If you do not return anything, it is treated like returning success.
* equivalent to returning 0 (false). If you forgot to return, it will * @note If a plugin has an AskPluginLoad2(), AskPluginLoad() will not be called.
* cause your plugin to not load with a very strange error message. *
* *
* @param myself Handle to the plugin. * @param myself Handle to the plugin.
* @param late Whether or not the plugin was loaded "late" (after map load). * @param late Whether or not the plugin was loaded "late" (after map load).
* @param error Error message buffer in case load failed. * @param error Error message buffer in case load failed.
* @param err_max Maximum number of characters for error message buffer. * @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. * Called when the plugin is about to be unloaded.