core/systems/PluginSys.cpp
changeset 315 5f48300aa103
parent 311 31192ed0fe13
child 317 e5342c8a0cf4
     1.1 --- a/core/systems/PluginSys.cpp	Thu Jan 18 21:07:10 2007 +0000
     1.2 +++ b/core/systems/PluginSys.cpp	Thu Jan 18 23:28:14 2007 +0000
     1.3 @@ -693,7 +693,6 @@
     1.4  }
     1.5  
     1.6  //well i have discovered that gabe newell is very fat, so i wrote this comment now
     1.7 -//:TODO: remove this function, create a better wrapper for LoadPlugin()/LoadAutoPlugin()
     1.8  bool CPluginManager::_LoadPlugin(CPlugin **_plugin, const char *path, bool debug, PluginType type, char error[], size_t err_max)
     1.9  {
    1.10  	/**
    1.11 @@ -777,7 +776,11 @@
    1.12  	{
    1.13  		AddCoreNativesToPlugin(pPlugin);
    1.14  		pPlugin->InitIdentity();
    1.15 -		pPlugin->Call_AskPluginLoad(error, err_max);
    1.16 +		if (pPlugin->Call_AskPluginLoad(error, err_max))
    1.17 +		{
    1.18 +			/* Autoload any modules */
    1.19 +			LoadOrRequireExtensions(pPlugin, 1, error, err_max);
    1.20 +		}
    1.21  	}
    1.22  
    1.23  	if (_plugin)
    1.24 @@ -800,6 +803,16 @@
    1.25  
    1.26  	AddPlugin(pl);
    1.27  
    1.28 +	/* Run second pass if we need to */
    1.29 +	if (IsLateLoadTime() && pl->GetStatus() == Plugin_Loaded)
    1.30 +	{
    1.31 +		if (!RunSecondPass(pl, error, err_max))
    1.32 +		{
    1.33 +			UnloadPlugin(pl);
    1.34 +			return NULL;
    1.35 +		}
    1.36 +	}
    1.37 +
    1.38  	return pl;
    1.39  }
    1.40  
    1.41 @@ -837,20 +850,25 @@
    1.42  	List<CPlugin *>::iterator iter;
    1.43  	CPlugin *pPlugin;
    1.44  
    1.45 +	char error[256];
    1.46  	for (iter=m_plugins.begin(); iter!=m_plugins.end(); iter++)
    1.47  	{
    1.48  		pPlugin = (*iter);
    1.49  		if (pPlugin->GetStatus() == Plugin_Loaded)
    1.50  		{
    1.51 -			/* :TODO: fix */
    1.52 -			RunSecondPass(pPlugin, NULL, 0);
    1.53 +			error[0] = '\0';
    1.54 +			if (!RunSecondPass(pPlugin, error, sizeof(error)))
    1.55 +			{
    1.56 +				g_Logger.LogError("[SM] Unable to load plugin \"%s\": %s", pPlugin->GetFilename(), error);
    1.57 +				pPlugin->SetErrorState(Plugin_Failed, "%s", error);
    1.58 +			}
    1.59  		}
    1.60  	}
    1.61  
    1.62  	m_AllPluginsLoaded = true;
    1.63  }
    1.64  
    1.65 -bool CPluginManager::RunSecondPass(CPlugin *pPlugin, char *error, size_t maxlength)
    1.66 +bool CPluginManager::LoadOrRequireExtensions(CPlugin *pPlugin, unsigned int pass, char *error, size_t maxlength)
    1.67  {
    1.68  	/* Find any extensions this plugin needs */
    1.69  	struct _ext
    1.70 @@ -888,36 +906,75 @@
    1.71  			{
    1.72  				continue;
    1.73  			}
    1.74 -			snprintf(path, PLATFORM_MAX_PATH, "%s.%s", file, PLATFORM_LIB_EXT);
    1.75 -			pExt = NULL;
    1.76 -			/* Attempt to auto-load if necessary */
    1.77 -			if (ext->autoload)
    1.78 +			if (pass == 1)
    1.79  			{
    1.80 -				pExt = g_Extensions.LoadAutoExtension(path);
    1.81 -			}
    1.82 -			/* See if we can find a similar extension */
    1.83 -			if (ext->required && !pExt)
    1.84 -			{
    1.85 -				if ((pExt = g_Extensions.FindExtensionByFile(path)) == NULL)
    1.86 +				/* Attempt to auto-load if necessary */
    1.87 +				if (ext->autoload)
    1.88 +				{
    1.89 +					g_LibSys.PathFormat(path, PLATFORM_MAX_PATH, "%s", file);
    1.90 +					g_Extensions.LoadAutoExtension(path);
    1.91 +				}
    1.92 +			} else if (pass == 2) {
    1.93 +				/* Is this required? */
    1.94 +				if (ext->required)
    1.95  				{
    1.96 -					pExt = g_Extensions.FindExtensionByName(name);
    1.97 +					g_LibSys.PathFormat(path, PLATFORM_MAX_PATH, "%s", file);
    1.98 +					if ((pExt = g_Extensions.FindExtensionByFile(path)) == NULL)
    1.99 +					{
   1.100 +						pExt = g_Extensions.FindExtensionByName(name);
   1.101 +					}
   1.102 +					/* :TODO: should we bind to unloaded extensions?
   1.103 +					 * Currently the extension manager will ignore this.
   1.104 +					 */
   1.105 +					if (!pExt || !pExt->IsRunning(NULL, 0))
   1.106 +					{
   1.107 +						if (error)
   1.108 +						{
   1.109 +							snprintf(error, maxlength, "Required extension \"%s\" file(\"%s\") not running", name, file);
   1.110 +						}
   1.111 +						pPlugin->m_status = Plugin_Failed;
   1.112 +						return false;
   1.113 +					} else {
   1.114 +						g_Extensions.BindChildPlugin(pExt, pPlugin);
   1.115 +					}
   1.116  				}
   1.117  			}
   1.118 -			/* If we're requiring and got an extension and it's loaded, bind it */
   1.119 -			if (ext->required && pExt && pExt->IsLoaded())
   1.120 -			{
   1.121 -				g_Extensions.BindChildPlugin(pExt, pPlugin);
   1.122 -			}
   1.123 -			/* If we're requiring and we didn't get an extension or it's not loaded, error */
   1.124 -			if (ext->required && (!pExt || !pExt->IsLoaded()))
   1.125 +		}
   1.126 +	}
   1.127 +
   1.128 +	return true;
   1.129 +}
   1.130 +
   1.131 +bool CPluginManager::RunSecondPass(CPlugin *pPlugin, char *error, size_t maxlength)
   1.132 +{
   1.133 +	/* Second pass for extension requirements */
   1.134 +	if (!LoadOrRequireExtensions(pPlugin, 2, error, maxlength))
   1.135 +	{
   1.136 +		return false;
   1.137 +	}
   1.138 +
   1.139 +	/* Bind all extra natives */
   1.140 +	g_Extensions.BindAllNativesToPlugin(pPlugin);
   1.141 +
   1.142 +	/* Find any unbound natives
   1.143 +	 * Right now, these are not allowed
   1.144 +	 */
   1.145 +	IPluginContext *pContext = pPlugin->GetBaseContext();
   1.146 +	uint32_t num = pContext->GetNativesNum();
   1.147 +	sp_native_t *native;
   1.148 +	for (unsigned int i=0; i<num; i++)
   1.149 +	{
   1.150 +		if (pContext->GetNativeByIndex(i, &native) != SP_ERROR_NONE)
   1.151 +		{
   1.152 +			break;
   1.153 +		}
   1.154 +		if (native->status == SP_NATIVE_UNBOUND)
   1.155 +		{
   1.156 +			if (error)
   1.157  			{
   1.158 -				if (error)
   1.159 -				{
   1.160 -					snprintf(error, maxlength, "Required extension \"%s\" (file \"%s\") not found", name, file);
   1.161 -				}
   1.162 -				pPlugin->m_status = Plugin_Failed;
   1.163 -				return false;
   1.164 +				snprintf(error, maxlength, "Native \"%s\" was not found.", native->name);
   1.165  			}
   1.166 +			return false;
   1.167  		}
   1.168  	}
   1.169  
   1.170 @@ -1268,7 +1325,7 @@
   1.171  
   1.172  bool CPluginManager::IsLateLoadTime() const
   1.173  {
   1.174 -	return (m_AllPluginsLoaded || g_SourceMod.IsLateLoadInMap());
   1.175 +	return (m_AllPluginsLoaded || !g_SourceMod.IsMapLoading());
   1.176  }
   1.177  
   1.178  void CPluginManager::OnSourceModAllInitialized()
   1.179 @@ -1486,39 +1543,48 @@
   1.180  				return;
   1.181  			}
   1.182  
   1.183 -			IPluginIterator *iter = GetPluginIterator();
   1.184 -			for (; iter->MorePlugins() && id<num; iter->NextPlugin(), id++) {}
   1.185 -
   1.186 -			IPlugin *pl = iter->GetPlugin();
   1.187 +			CPlugin *pl = GetPluginByOrder(num);
   1.188  			const sm_plugininfo_t *info = pl->GetPublicInfo();
   1.189  
   1.190  			g_RootMenu.ConsolePrint("  Filename: %s", pl->GetFilename());
   1.191 -			if (IS_STR_FILLED(info->name))
   1.192 -			{
   1.193 -				g_RootMenu.ConsolePrint("  Title: %s", info->name);
   1.194 -			}
   1.195 -			if (IS_STR_FILLED(info->author))
   1.196 +			if (pl->GetStatus() <= Plugin_Error)
   1.197  			{
   1.198 -				g_RootMenu.ConsolePrint("  Author: %s", info->author);
   1.199 -			}
   1.200 -			if (IS_STR_FILLED(info->version))
   1.201 -			{
   1.202 -				g_RootMenu.ConsolePrint("  Version: %s", info->version);
   1.203 +				if (IS_STR_FILLED(info->name))
   1.204 +				{
   1.205 +					g_RootMenu.ConsolePrint("  Title: %s", info->name);
   1.206 +				}
   1.207 +				if (IS_STR_FILLED(info->version))
   1.208 +				{
   1.209 +					g_RootMenu.ConsolePrint("  Version: %s", info->version);
   1.210 +				}
   1.211 +				if (IS_STR_FILLED(info->url))
   1.212 +				{
   1.213 +					g_RootMenu.ConsolePrint("  URL: %s", info->url);
   1.214 +				}
   1.215 +				if (IS_STR_FILLED(info->author))
   1.216 +				{
   1.217 +					g_RootMenu.ConsolePrint("  Author: %s", info->author);
   1.218 +				}
   1.219 +				if (IS_STR_FILLED(info->version))
   1.220 +				{
   1.221 +					g_RootMenu.ConsolePrint("  Version: %s", info->version);
   1.222 +				}
   1.223 +				if (IS_STR_FILLED(info->description))
   1.224 +				{
   1.225 +					g_RootMenu.ConsolePrint("  Description: %s", info->description);
   1.226 +				}	
   1.227 +				g_RootMenu.ConsolePrint("  Debugging: %s", pl->IsDebugging() ? "yes" : "no");
   1.228 +				g_RootMenu.ConsolePrint("  Paused: %s", pl->GetStatus() == Plugin_Running ? "yes" : "no");
   1.229 +			} else {
   1.230 +				g_RootMenu.ConsolePrint("  Load error: %s", pl->m_errormsg);
   1.231 +				g_RootMenu.ConsolePrint("  File info: (title \"%s\") (version \"%s\")", 
   1.232 +										info->name ? info->name : "<none>",
   1.233 +										info->version ? info->version : "<none>");
   1.234 +				if (IS_STR_FILLED(info->url))
   1.235 +				{
   1.236 +					g_RootMenu.ConsolePrint("  File URL: %s", info->url);
   1.237 +				}
   1.238  			}
   1.239 -			if (IS_STR_FILLED(info->description))
   1.240 -			{
   1.241 -				g_RootMenu.ConsolePrint("  Description: %s", info->description);
   1.242 -			}
   1.243 -			if (IS_STR_FILLED(info->url))
   1.244 -			{
   1.245 -				g_RootMenu.ConsolePrint("  URL: %s", info->url);
   1.246 -			}
   1.247 -			if (pl->GetStatus() >= Plugin_Error)
   1.248 -			{
   1.249 -				g_RootMenu.ConsolePrint("  Debugging: %s", pl->IsDebugging() ? "yes" : "no");
   1.250 -			}
   1.251 -
   1.252 -			iter->Release();
   1.253  
   1.254  			return;
   1.255  		} else if (strcmp(cmd, "debug") == 0) {