|
|
|
@@ -5,6 +5,7 @@
|
|
|
|
|
#include "sourcemm_api.h"
|
|
|
|
|
#include "PluginSys.h"
|
|
|
|
|
#include "sm_srvcmds.h"
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
|
|
|
|
|
CExtensionManager g_Extensions;
|
|
|
|
|
IdentityType_t g_ExtType;
|
|
|
|
@@ -15,6 +16,7 @@ CExtension::CExtension(const char *filename, char *error, size_t err_max)
|
|
|
|
|
m_pAPI = NULL;
|
|
|
|
|
m_pIdentToken = NULL;
|
|
|
|
|
m_PlId = 0;
|
|
|
|
|
unload_code = 0;
|
|
|
|
|
|
|
|
|
|
char path[PLATFORM_MAX_PATH+1];
|
|
|
|
|
g_LibSys.PathFormat(path, PLATFORM_MAX_PATH, "%s/extensions/%s", g_SourceMod.GetSMBaseDir(), filename);
|
|
|
|
@@ -349,6 +351,27 @@ void CExtensionManager::OnPluginDestroyed(IPlugin *plugin)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CExtension *CExtensionManager::FindByOrder(unsigned int num)
|
|
|
|
|
{
|
|
|
|
|
if (num < 1 || num > m_Libs.size())
|
|
|
|
|
{
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
List<CExtension *>::iterator iter = m_Libs.begin();
|
|
|
|
|
|
|
|
|
|
while (iter != m_Libs.end())
|
|
|
|
|
{
|
|
|
|
|
if (--num == 0)
|
|
|
|
|
{
|
|
|
|
|
return (*iter);
|
|
|
|
|
}
|
|
|
|
|
iter++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool CExtensionManager::UnloadExtension(IExtension *_pExt)
|
|
|
|
|
{
|
|
|
|
|
if (!_pExt)
|
|
|
|
@@ -376,9 +399,9 @@ bool CExtensionManager::UnloadExtension(IExtension *_pExt)
|
|
|
|
|
List<IPlugin *>::iterator p_iter = pExt->m_Plugins.begin();
|
|
|
|
|
while (p_iter != pExt->m_Plugins.end())
|
|
|
|
|
{
|
|
|
|
|
/* We have to manually unlink ourselves here, since we're no longer being managed */
|
|
|
|
|
g_PluginSys.UnloadPlugin((*p_iter));
|
|
|
|
|
/* It should already have been removed! */
|
|
|
|
|
assert(pExt->m_Plugins.find((*p_iter)) != pExt->m_Plugins.end());
|
|
|
|
|
p_iter = pExt->m_Plugins.erase(p_iter);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Notify and/or unload all dependencies */
|
|
|
|
@@ -392,6 +415,10 @@ bool CExtensionManager::UnloadExtension(IExtension *_pExt)
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
if (pDep == pExt)
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
/* Now, get its dependency list */
|
|
|
|
|
bool dropped = false;
|
|
|
|
|
List<IfaceInfo>::iterator i_iter = pDep->m_Deps.begin();
|
|
|
|
@@ -524,10 +551,122 @@ void CExtensionManager::OnRootConsoleCommand(const char *cmd, unsigned int argco
|
|
|
|
|
g_RootMenu.ConsolePrint(" Metamod enabled: %s", pAPI->IsMetamodExtension() ? "yes" : "no");
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
} else if (strcmp(cmd, "unload") == 0) {
|
|
|
|
|
if (argcount < 4)
|
|
|
|
|
{
|
|
|
|
|
g_RootMenu.ConsolePrint("[SM] Usage: sm unload <#> [code]");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const char *arg = g_RootMenu.GetArgument(3);
|
|
|
|
|
unsigned int num = atoi(arg);
|
|
|
|
|
CExtension *pExt = FindByOrder(num);
|
|
|
|
|
|
|
|
|
|
if (!pExt)
|
|
|
|
|
{
|
|
|
|
|
g_RootMenu.ConsolePrint("[SM] Extension number %d was not found.", num);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (argcount > 4 && pExt->unload_code)
|
|
|
|
|
{
|
|
|
|
|
const char *unload = g_RootMenu.GetArgument(4);
|
|
|
|
|
if (pExt->unload_code == atoi(unload))
|
|
|
|
|
{
|
|
|
|
|
char filename[PLATFORM_MAX_PATH+1];
|
|
|
|
|
snprintf(filename, PLATFORM_MAX_PATH, "%s", pExt->GetFilename());
|
|
|
|
|
UnloadExtension(pExt);
|
|
|
|
|
g_RootMenu.ConsolePrint("[SM] Extension %s is now unloaded.", filename);
|
|
|
|
|
} else {
|
|
|
|
|
g_RootMenu.ConsolePrint("[SM] Please try again, the correct unload code is \"%d\"", pExt->unload_code);
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!pExt->IsLoaded()
|
|
|
|
|
|| (!pExt->m_Deps.size() && !pExt->m_Plugins.size()))
|
|
|
|
|
{
|
|
|
|
|
char filename[PLATFORM_MAX_PATH+1];
|
|
|
|
|
snprintf(filename, PLATFORM_MAX_PATH, "%s", pExt->GetFilename());
|
|
|
|
|
UnloadExtension(pExt);
|
|
|
|
|
g_RootMenu.ConsolePrint("[SM] Extension %s is now unloaded.", filename);
|
|
|
|
|
return;
|
|
|
|
|
} else {
|
|
|
|
|
List<IPlugin *> plugins;
|
|
|
|
|
if (pExt->m_Deps.size())
|
|
|
|
|
{
|
|
|
|
|
g_RootMenu.ConsolePrint("[SM] Unloading %s will unload the following extensions: ", pExt->GetFilename());
|
|
|
|
|
List<CExtension *>::iterator iter;
|
|
|
|
|
CExtension *pOther;
|
|
|
|
|
/* Get list of all extensions */
|
|
|
|
|
for (iter=m_Libs.begin(); iter!=m_Libs.end(); iter++)
|
|
|
|
|
{
|
|
|
|
|
List<IfaceInfo>::iterator i_iter;
|
|
|
|
|
pOther = (*iter);
|
|
|
|
|
if (!pOther->IsLoaded() || pOther == pExt)
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
/* Get their dependencies */
|
|
|
|
|
for (i_iter=pOther->m_Deps.begin();
|
|
|
|
|
i_iter!=pOther->m_Deps.end();
|
|
|
|
|
i_iter++)
|
|
|
|
|
{
|
|
|
|
|
/* Is this dependency to us? */
|
|
|
|
|
if ((*i_iter).owner != pExt)
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
/* Will our dependent care? */
|
|
|
|
|
if (!pExt->GetAPI()->QueryInterfaceDrop((*i_iter).iface))
|
|
|
|
|
{
|
|
|
|
|
g_RootMenu.ConsolePrint(" -> %s", pExt->GetFilename());
|
|
|
|
|
/* Add to plugin unload list */
|
|
|
|
|
List<IPlugin *>::iterator p_iter;
|
|
|
|
|
for (p_iter=pOther->m_Plugins.begin();
|
|
|
|
|
p_iter!=pOther->m_Plugins.end();
|
|
|
|
|
p_iter++)
|
|
|
|
|
{
|
|
|
|
|
if (plugins.find((*p_iter)) == plugins.end())
|
|
|
|
|
{
|
|
|
|
|
plugins.push_back((*p_iter));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (pExt->m_Plugins.size())
|
|
|
|
|
{
|
|
|
|
|
g_RootMenu.ConsolePrint("[SM] Unloading %s will unload the following plugins: ", pExt->GetFilename());
|
|
|
|
|
List<IPlugin *>::iterator iter;
|
|
|
|
|
IPlugin *pPlugin;
|
|
|
|
|
for (iter = pExt->m_Plugins.begin(); iter != pExt->m_Plugins.end(); iter++)
|
|
|
|
|
{
|
|
|
|
|
pPlugin = (*iter);
|
|
|
|
|
if (plugins.find(pPlugin) == plugins.end())
|
|
|
|
|
{
|
|
|
|
|
plugins.push_back(pPlugin);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
for (iter = plugins.begin(); iter != plugins.end(); iter++)
|
|
|
|
|
{
|
|
|
|
|
pPlugin = (*iter);
|
|
|
|
|
g_RootMenu.ConsolePrint(" -> %s", pPlugin->GetFilename());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
srand(static_cast<int>(time(NULL)));
|
|
|
|
|
pExt->unload_code = (rand() % 877) + 123; //123 to 999
|
|
|
|
|
g_RootMenu.ConsolePrint("[SM] To verify unloading %s, please use the following: ", pExt->GetFilename());
|
|
|
|
|
g_RootMenu.ConsolePrint("[SM] sm exts unload %d %d", num, pExt->unload_code);
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
g_RootMenu.ConsolePrint("SourceMod Extensions Menu:");
|
|
|
|
|
g_RootMenu.DrawGenericOption("info", "Extra extension information");
|
|
|
|
|
g_RootMenu.DrawGenericOption("list", "List extensions");
|
|
|
|
|
g_RootMenu.DrawGenericOption("unload", "Unload an extension");
|
|
|
|
|
}
|
|
|
|
|