diff --git a/core/logic/PluginSys.cpp b/core/logic/PluginSys.cpp index ffdb2b97..5aa07bbc 100644 --- a/core/logic/PluginSys.cpp +++ b/core/logic/PluginSys.cpp @@ -1122,9 +1122,8 @@ bool CPluginManager::FindOrRequirePluginDeps(CPlugin *pPlugin, char *error, size return true; } -bool CPluginManager::LoadOrRequireExtensions(CPlugin *pPlugin, unsigned int pass, char *error, size_t maxlength) +bool CPlugin::ForEachExtVar(const ExtVarCallback& callback) { - /* Find any extensions this plugin needs */ struct _ext { cell_t name; @@ -1133,7 +1132,7 @@ bool CPluginManager::LoadOrRequireExtensions(CPlugin *pPlugin, unsigned int pass cell_t required; } *ext; - IPluginContext *pBase = pPlugin->GetBaseContext(); + IPluginContext *pBase = GetBaseContext(); for (uint32_t i = 0; i < pBase->GetPubVarsNum(); i++) { sp_pubvar_t *pubvar; @@ -1145,29 +1144,42 @@ bool CPluginManager::LoadOrRequireExtensions(CPlugin *pPlugin, unsigned int pass ext = (_ext *)pubvar->offs; - char *file, *name; - if (pBase->LocalToString(ext->file, &file) != SP_ERROR_NONE) + ExtVar var; + if (pBase->LocalToString(ext->file, &var.file) != SP_ERROR_NONE) continue; - if (pBase->LocalToString(ext->name, &name) != SP_ERROR_NONE) + if (pBase->LocalToString(ext->name, &var.name) != SP_ERROR_NONE) continue; + var.autoload = !!ext->autoload; + var.required = !!ext->required; + if (!callback(pubvar, var)) + return false; + } + return true; +} + +bool CPluginManager::LoadOrRequireExtensions(CPlugin *pPlugin, unsigned int pass, char *error, size_t maxlength) +{ + auto callback = [pPlugin, pass, error, maxlength] + (const sp_pubvar_t *pubvar, const CPlugin::ExtVar& ext) -> bool + { char path[PLATFORM_MAX_PATH]; if (pass == 1) { /* Attempt to auto-load if necessary */ - if (ext->autoload) { - libsys->PathFormat(path, PLATFORM_MAX_PATH, "%s", file); - g_Extensions.LoadAutoExtension(path, !!ext->required); + if (ext.autoload) { + libsys->PathFormat(path, PLATFORM_MAX_PATH, "%s", ext.file); + g_Extensions.LoadAutoExtension(path, ext.required); } } else if (pass == 2) { /* Is this required? */ - if (ext->required) { - libsys->PathFormat(path, PLATFORM_MAX_PATH, "%s", file); + if (ext.required) { + libsys->PathFormat(path, PLATFORM_MAX_PATH, "%s", ext.file); IExtension *pExt = g_Extensions.FindExtensionByFile(path); if (!pExt) - pExt = g_Extensions.FindExtensionByName(name); + pExt = g_Extensions.FindExtensionByName(ext.name); if (!pExt || !pExt->IsRunning(nullptr, 0)) { - ke::SafeSprintf(error, maxlength, "Required extension \"%s\" file(\"%s\") not running", name, file); + ke::SafeSprintf(error, maxlength, "Required extension \"%s\" file(\"%s\") not running", ext.name, ext.file); return false; } g_Extensions.BindChildPlugin(pExt, pPlugin); @@ -1175,7 +1187,7 @@ bool CPluginManager::LoadOrRequireExtensions(CPlugin *pPlugin, unsigned int pass char buffer[64]; ke::SafeSprintf(buffer, sizeof(buffer), "__ext_%s_SetNTVOptional", &pubvar->name[6]); - if (IPluginFunction *pFunc = pBase->GetFunctionByName(buffer)) { + if (IPluginFunction *pFunc = pPlugin->GetBaseContext()->GetFunctionByName(buffer)) { cell_t res; if (pFunc->Execute(&res) != SP_ERROR_NONE) { ke::SafeSprintf(error, maxlength, "Fatal error during plugin initialization (ext req)"); @@ -1184,9 +1196,9 @@ bool CPluginManager::LoadOrRequireExtensions(CPlugin *pPlugin, unsigned int pass } } } - } + }; - return true; + return pPlugin->ForEachExtVar(ke::Move(callback)); } CPlugin *CPluginManager::CompileAndPrep(const char *path, char *error, size_t maxlength) diff --git a/core/logic/PluginSys.h b/core/logic/PluginSys.h index e4f032b0..73c1a021 100644 --- a/core/logic/PluginSys.h +++ b/core/logic/PluginSys.h @@ -53,6 +53,7 @@ #include "PhraseCollection.h" #include #include +#include class CPlayer; @@ -155,6 +156,16 @@ public: CNativeOwner *ToNativeOwner() { return this; } + + struct ExtVar { + char *name; + char *file; + bool autoload; + bool required; + }; + + typedef ke::Lambda ExtVarCallback; + bool ForEachExtVar(const ExtVarCallback& callback); public: /** * Creates a plugin object with default values.