finished most of the extension system

--HG--
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%40320
This commit is contained in:
David Anderson
2007-01-18 23:28:14 +00:00
parent 3bba8d6a2a
commit c5d0848177
12 changed files with 322 additions and 92 deletions
+123 -57
View File
@@ -693,7 +693,6 @@ void CPluginManager::LoadPluginsFromDir(const char *basedir, const char *localpa
}
//well i have discovered that gabe newell is very fat, so i wrote this comment now
//:TODO: remove this function, create a better wrapper for LoadPlugin()/LoadAutoPlugin()
bool CPluginManager::_LoadPlugin(CPlugin **_plugin, const char *path, bool debug, PluginType type, char error[], size_t err_max)
{
/**
@@ -777,7 +776,11 @@ bool CPluginManager::_LoadPlugin(CPlugin **_plugin, const char *path, bool debug
{
AddCoreNativesToPlugin(pPlugin);
pPlugin->InitIdentity();
pPlugin->Call_AskPluginLoad(error, err_max);
if (pPlugin->Call_AskPluginLoad(error, err_max))
{
/* Autoload any modules */
LoadOrRequireExtensions(pPlugin, 1, error, err_max);
}
}
if (_plugin)
@@ -800,6 +803,16 @@ IPlugin *CPluginManager::LoadPlugin(const char *path, bool debug, PluginType typ
AddPlugin(pl);
/* Run second pass if we need to */
if (IsLateLoadTime() && pl->GetStatus() == Plugin_Loaded)
{
if (!RunSecondPass(pl, error, err_max))
{
UnloadPlugin(pl);
return NULL;
}
}
return pl;
}
@@ -837,20 +850,25 @@ void CPluginManager::LoadAll_SecondPass()
List<CPlugin *>::iterator iter;
CPlugin *pPlugin;
char error[256];
for (iter=m_plugins.begin(); iter!=m_plugins.end(); iter++)
{
pPlugin = (*iter);
if (pPlugin->GetStatus() == Plugin_Loaded)
{
/* :TODO: fix */
RunSecondPass(pPlugin, NULL, 0);
error[0] = '\0';
if (!RunSecondPass(pPlugin, error, sizeof(error)))
{
g_Logger.LogError("[SM] Unable to load plugin \"%s\": %s", pPlugin->GetFilename(), error);
pPlugin->SetErrorState(Plugin_Failed, "%s", error);
}
}
}
m_AllPluginsLoaded = true;
}
bool CPluginManager::RunSecondPass(CPlugin *pPlugin, char *error, size_t maxlength)
bool CPluginManager::LoadOrRequireExtensions(CPlugin *pPlugin, unsigned int pass, char *error, size_t maxlength)
{
/* Find any extensions this plugin needs */
struct _ext
@@ -888,36 +906,75 @@ bool CPluginManager::RunSecondPass(CPlugin *pPlugin, char *error, size_t maxleng
{
continue;
}
snprintf(path, PLATFORM_MAX_PATH, "%s.%s", file, PLATFORM_LIB_EXT);
pExt = NULL;
/* Attempt to auto-load if necessary */
if (ext->autoload)
if (pass == 1)
{
pExt = g_Extensions.LoadAutoExtension(path);
}
/* See if we can find a similar extension */
if (ext->required && !pExt)
{
if ((pExt = g_Extensions.FindExtensionByFile(path)) == NULL)
/* Attempt to auto-load if necessary */
if (ext->autoload)
{
pExt = g_Extensions.FindExtensionByName(name);
g_LibSys.PathFormat(path, PLATFORM_MAX_PATH, "%s", file);
g_Extensions.LoadAutoExtension(path);
}
} else if (pass == 2) {
/* Is this required? */
if (ext->required)
{
g_LibSys.PathFormat(path, PLATFORM_MAX_PATH, "%s", file);
if ((pExt = g_Extensions.FindExtensionByFile(path)) == NULL)
{
pExt = g_Extensions.FindExtensionByName(name);
}
/* :TODO: should we bind to unloaded extensions?
* Currently the extension manager will ignore this.
*/
if (!pExt || !pExt->IsRunning(NULL, 0))
{
if (error)
{
snprintf(error, maxlength, "Required extension \"%s\" file(\"%s\") not running", name, file);
}
pPlugin->m_status = Plugin_Failed;
return false;
} else {
g_Extensions.BindChildPlugin(pExt, pPlugin);
}
}
}
/* If we're requiring and got an extension and it's loaded, bind it */
if (ext->required && pExt && pExt->IsLoaded())
}
}
return true;
}
bool CPluginManager::RunSecondPass(CPlugin *pPlugin, char *error, size_t maxlength)
{
/* Second pass for extension requirements */
if (!LoadOrRequireExtensions(pPlugin, 2, error, maxlength))
{
return false;
}
/* Bind all extra natives */
g_Extensions.BindAllNativesToPlugin(pPlugin);
/* Find any unbound natives
* Right now, these are not allowed
*/
IPluginContext *pContext = pPlugin->GetBaseContext();
uint32_t num = pContext->GetNativesNum();
sp_native_t *native;
for (unsigned int i=0; i<num; i++)
{
if (pContext->GetNativeByIndex(i, &native) != SP_ERROR_NONE)
{
break;
}
if (native->status == SP_NATIVE_UNBOUND)
{
if (error)
{
g_Extensions.BindChildPlugin(pExt, pPlugin);
}
/* If we're requiring and we didn't get an extension or it's not loaded, error */
if (ext->required && (!pExt || !pExt->IsLoaded()))
{
if (error)
{
snprintf(error, maxlength, "Required extension \"%s\" (file \"%s\") not found", name, file);
}
pPlugin->m_status = Plugin_Failed;
return false;
snprintf(error, maxlength, "Native \"%s\" was not found.", native->name);
}
return false;
}
}
@@ -1268,7 +1325,7 @@ bool CPluginManager::TestAliasMatch(const char *alias, const char *localpath)
bool CPluginManager::IsLateLoadTime() const
{
return (m_AllPluginsLoaded || g_SourceMod.IsLateLoadInMap());
return (m_AllPluginsLoaded || !g_SourceMod.IsMapLoading());
}
void CPluginManager::OnSourceModAllInitialized()
@@ -1486,40 +1543,49 @@ void CPluginManager::OnRootConsoleCommand(const char *command, unsigned int argc
return;
}
IPluginIterator *iter = GetPluginIterator();
for (; iter->MorePlugins() && id<num; iter->NextPlugin(), id++) {}
IPlugin *pl = iter->GetPlugin();
CPlugin *pl = GetPluginByOrder(num);
const sm_plugininfo_t *info = pl->GetPublicInfo();
g_RootMenu.ConsolePrint(" Filename: %s", pl->GetFilename());
if (IS_STR_FILLED(info->name))
{
g_RootMenu.ConsolePrint(" Title: %s", info->name);
}
if (IS_STR_FILLED(info->author))
{
g_RootMenu.ConsolePrint(" Author: %s", info->author);
}
if (IS_STR_FILLED(info->version))
{
g_RootMenu.ConsolePrint(" Version: %s", info->version);
}
if (IS_STR_FILLED(info->description))
{
g_RootMenu.ConsolePrint(" Description: %s", info->description);
}
if (IS_STR_FILLED(info->url))
{
g_RootMenu.ConsolePrint(" URL: %s", info->url);
}
if (pl->GetStatus() >= Plugin_Error)
if (pl->GetStatus() <= Plugin_Error)
{
if (IS_STR_FILLED(info->name))
{
g_RootMenu.ConsolePrint(" Title: %s", info->name);
}
if (IS_STR_FILLED(info->version))
{
g_RootMenu.ConsolePrint(" Version: %s", info->version);
}
if (IS_STR_FILLED(info->url))
{
g_RootMenu.ConsolePrint(" URL: %s", info->url);
}
if (IS_STR_FILLED(info->author))
{
g_RootMenu.ConsolePrint(" Author: %s", info->author);
}
if (IS_STR_FILLED(info->version))
{
g_RootMenu.ConsolePrint(" Version: %s", info->version);
}
if (IS_STR_FILLED(info->description))
{
g_RootMenu.ConsolePrint(" Description: %s", info->description);
}
g_RootMenu.ConsolePrint(" Debugging: %s", pl->IsDebugging() ? "yes" : "no");
g_RootMenu.ConsolePrint(" Paused: %s", pl->GetStatus() == Plugin_Running ? "yes" : "no");
} else {
g_RootMenu.ConsolePrint(" Load error: %s", pl->m_errormsg);
g_RootMenu.ConsolePrint(" File info: (title \"%s\") (version \"%s\")",
info->name ? info->name : "<none>",
info->version ? info->version : "<none>");
if (IS_STR_FILLED(info->url))
{
g_RootMenu.ConsolePrint(" File URL: %s", info->url);
}
}
iter->Release();
return;
} else if (strcmp(cmd, "debug") == 0) {
if (argcount < 5)