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_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<String>::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))
{

View File

@ -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];

View File

@ -74,6 +74,13 @@ struct Plugin
#include <commandfilters>
#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.
* 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.