mirror of
https://github.com/alliedmodders/metamod-source.git
synced 2025-01-31 20:52:18 +01:00
05d2af1eef
This only happened when there was more than one plugin that loaded this way. And the first plugin to load had to fail on OBV first so that OB could be tried. It was being permanently set to OB for future plugin loads and this caused problems.
844 lines
16 KiB
C++
844 lines
16 KiB
C++
/**
|
|
* vim: set ts=4 sw=4 tw=99 noet :
|
|
* ======================================================
|
|
* Metamod:Source
|
|
* Copyright (C) 2004-2009 AlliedModders LLC and authors.
|
|
* All rights reserved.
|
|
* ======================================================
|
|
*
|
|
* This software is provided 'as-is', without any express or implied warranty.
|
|
* In no event will the authors be held liable for any damages arising from
|
|
* the use of this software.
|
|
*
|
|
* Permission is granted to anyone to use this software for any purpose,
|
|
* including commercial applications, and to alter it and redistribute it
|
|
* freely, subject to the following restrictions:
|
|
*
|
|
* 1. The origin of this software must not be misrepresented; you must not
|
|
* claim that you wrote the original software. If you use this software in a
|
|
* product, an acknowledgment in the product documentation would be
|
|
* appreciated but is not required.
|
|
* 2. Altered source versions must be plainly marked as such, and must not be
|
|
* misrepresented as being the original software.
|
|
* 3. This notice may not be removed or altered from any source distribution.
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include "metamod_oslink.h"
|
|
#include "metamod.h"
|
|
#include "metamod_plugins.h"
|
|
#include "metamod_util.h"
|
|
|
|
/**
|
|
* @brief Implements functions from CPlugin.h
|
|
* @file CPlugin.cpp
|
|
*/
|
|
|
|
using namespace SourceMM;
|
|
|
|
#define ITER_PLEVENT(evn, plid) \
|
|
CPluginManager::CPlugin *_Xpl; \
|
|
SourceHook::List<IMetamodListener *>::iterator event; \
|
|
IMetamodListener *api; \
|
|
for (PluginIter iter = g_PluginMngr._begin(); iter != g_PluginMngr._end(); iter++) { \
|
|
_Xpl = (*iter); \
|
|
if (_Xpl->m_Id == plid) \
|
|
continue; \
|
|
for (event=_Xpl->m_Events.begin(); event!=_Xpl->m_Events.end(); event++) { \
|
|
api = (*event); \
|
|
api->evn(plid); \
|
|
} \
|
|
}
|
|
|
|
CPluginManager g_PluginMngr;
|
|
|
|
MetamodVersionInfo GlobVersionInfo =
|
|
{
|
|
METAMOD_API_MAJOR,
|
|
METAMOD_API_MINOR,
|
|
SH_IFACE_VERSION,
|
|
SH_IMPL_VERSION,
|
|
PLAPI_MIN_VERSION,
|
|
METAMOD_PLAPI_VERSION,
|
|
SOURCE_ENGINE_UNKNOWN,
|
|
NULL
|
|
};
|
|
|
|
CPluginManager::CPluginManager()
|
|
{
|
|
m_LastId = Pl_MinId;
|
|
m_AllLoaded = false;
|
|
}
|
|
|
|
CPluginManager::~CPluginManager()
|
|
{
|
|
SourceHook::List<CNameAlias *>::iterator iter;
|
|
|
|
for (iter = m_Aliases.begin(); iter != m_Aliases.end(); iter++)
|
|
{
|
|
delete (*iter);
|
|
}
|
|
|
|
m_Aliases.clear();
|
|
}
|
|
|
|
const char *CPluginManager::LookupAlias(const char *alias)
|
|
{
|
|
SourceHook::List<CNameAlias *>::iterator iter;
|
|
CNameAlias *p;
|
|
|
|
for (iter = m_Aliases.begin(); iter != m_Aliases.end(); iter++)
|
|
{
|
|
p = (*iter);
|
|
if (p->alias.compare(alias) == 0)
|
|
{
|
|
return p->value.c_str();
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
SourceHook::List<CNameAlias *>::iterator CPluginManager::_alias_begin()
|
|
{
|
|
return m_Aliases.begin();
|
|
}
|
|
|
|
SourceHook::List<CNameAlias *>::iterator CPluginManager::_alias_end()
|
|
{
|
|
return m_Aliases.end();
|
|
}
|
|
|
|
void CPluginManager::SetAlias(const char *alias, const char *value)
|
|
{
|
|
SourceHook::List<CNameAlias *>::iterator iter;
|
|
CNameAlias *p;
|
|
|
|
for (iter = m_Aliases.begin(); iter != m_Aliases.end(); iter++)
|
|
{
|
|
p = (*iter);
|
|
if (p->alias.compare(alias) == 0)
|
|
{
|
|
if (value[0] == '\0')
|
|
{
|
|
iter = m_Aliases.erase(iter);
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
p->value.assign(value);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (value[0] != '\0')
|
|
{
|
|
p = new CNameAlias;
|
|
|
|
p->alias.assign(alias);
|
|
p->value.assign(value);
|
|
|
|
m_Aliases.push_back(p);
|
|
}
|
|
}
|
|
|
|
CPluginManager::CPlugin::CPlugin() : m_Id(0), m_Source(0), m_API(NULL), m_Lib(NULL), m_UnloadFn(NULL)
|
|
{
|
|
|
|
}
|
|
|
|
PluginId CPluginManager::Load(const char *file, PluginId source, bool &already, char *error, size_t maxlen)
|
|
{
|
|
already = false;
|
|
//Check if we're about to reload an old plugin
|
|
PluginIter i = m_Plugins.begin();
|
|
while (i != m_Plugins.end())
|
|
{
|
|
if ((*i) && UTIL_PathCmp(file, (*i)->m_File.c_str()))
|
|
{
|
|
if ((*i)->m_Status < Pl_Paused)
|
|
{
|
|
//Attempt to load the plugin again
|
|
already = true;
|
|
i = m_Plugins.erase(i);
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
//No need to load it
|
|
already = true;
|
|
return (*i)->m_Id;
|
|
}
|
|
}
|
|
i++;
|
|
}
|
|
|
|
CPlugin *pl = _Load(file, source, error, maxlen);
|
|
|
|
if (!pl)
|
|
{
|
|
return Pl_BadLoad;
|
|
}
|
|
|
|
ITER_PLEVENT(OnPluginLoad, pl->m_Id);
|
|
|
|
return pl->m_Id;
|
|
}
|
|
|
|
CPluginManager::CPlugin *CPluginManager::FindById(PluginId id)
|
|
{
|
|
PluginIter i;
|
|
|
|
for (i=m_Plugins.begin(); i!=m_Plugins.end(); i++)
|
|
{
|
|
if ( (*i)->m_Id == id )\
|
|
{
|
|
return (*i);
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
void CPluginManager::SetAllLoaded()
|
|
{
|
|
if (m_AllLoaded)
|
|
{
|
|
return;
|
|
}
|
|
|
|
m_AllLoaded = true;
|
|
PluginIter i;
|
|
|
|
for (i=m_Plugins.begin(); i!=m_Plugins.end(); i++)
|
|
{
|
|
if ( (*i) && (*i)->m_Status == Pl_Running && (*i)->m_API )
|
|
{
|
|
//API 4 is when we added this callback
|
|
//Min version is now 5, so we ignore this check
|
|
//if ( (*i)->m_API->GetApiVersion() >= 004 )
|
|
(*i)->m_API->AllPluginsLoaded();
|
|
}
|
|
}
|
|
}
|
|
|
|
bool CPluginManager::Pause(PluginId id, char *error, size_t maxlen)
|
|
{
|
|
CPlugin *pl = FindById(id);
|
|
|
|
if (!pl)
|
|
{
|
|
UTIL_Format(error, maxlen, "Plugin id not found");
|
|
return false;
|
|
}
|
|
|
|
bool ret;
|
|
|
|
if ((ret=_Pause(pl, error, maxlen)) == true)
|
|
{
|
|
ITER_PLEVENT(OnPluginPause, pl->m_Id);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
bool CPluginManager::Unpause(PluginId id, char *error, size_t maxlen)
|
|
{
|
|
CPlugin *pl = FindById(id);
|
|
|
|
if (!pl)
|
|
{
|
|
UTIL_Format(error, maxlen, "Plugin id not found");
|
|
return false;
|
|
}
|
|
|
|
bool ret;
|
|
|
|
if ( (ret=_Unpause(pl, error, maxlen)) == true )
|
|
{
|
|
ITER_PLEVENT(OnPluginUnpause, pl->m_Id);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
bool CPluginManager::Unload(PluginId id, bool force, char *error, size_t maxlen)
|
|
{
|
|
CPlugin *pl = FindById(id);
|
|
|
|
if (!pl)
|
|
{
|
|
UTIL_Format(error, maxlen, "Plugin %d not found", id);
|
|
return false;
|
|
}
|
|
|
|
bool ret;
|
|
PluginId old_id = pl->m_Id;
|
|
if ( (ret=_Unload(pl, force, error, maxlen)) == true )
|
|
{
|
|
ITER_PLEVENT(OnPluginUnload, old_id);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
bool CPluginManager::Retry(PluginId id, char *error, size_t len)
|
|
{
|
|
PluginIter i;
|
|
char buffer[64];
|
|
for (i=m_Plugins.begin(); i!=m_Plugins.end(); i++)
|
|
{
|
|
if ( (*i) && (*i)->m_Id == id )
|
|
{
|
|
if ( (*i)->m_Status >= Pl_Paused)
|
|
{
|
|
UTIL_Format(error, len, "Plugin %d is already running.", id);
|
|
return false;
|
|
}
|
|
CPlugin *pl = _Load((*i)->m_File.c_str(), Pl_Console, error, len);
|
|
if (!pl)
|
|
{
|
|
return false;
|
|
}
|
|
if (pl->m_Status >= Pl_Paused)
|
|
{
|
|
//Now it gets crazy... unload the original copy.
|
|
_Unload( (*i), true, buffer, sizeof(buffer)-1 );
|
|
|
|
//Set the new copy's id
|
|
pl->m_Id = id;
|
|
|
|
//We just wasted an id... reclaim it
|
|
m_LastId--;
|
|
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
//don't really care about the buffer here
|
|
_Unload(pl, true, buffer, sizeof(buffer)-1);
|
|
|
|
//We just wasted an id... reclaim it
|
|
m_LastId--;
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
UTIL_Format(error, len, "Plugin %d not found,", id);
|
|
return false;
|
|
}
|
|
|
|
CPluginManager::CPlugin *CPluginManager::FindByAPI(ISmmPlugin *api)
|
|
{
|
|
PluginIter i;
|
|
|
|
//don't find bad plugins!
|
|
if (!api)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
for (i=m_Plugins.begin(); i!=m_Plugins.end(); i++)
|
|
{
|
|
if ((*i)->m_API == api)
|
|
{
|
|
return (*i);
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
int CPluginManager::GetPluginCount()
|
|
{
|
|
return (int)m_Plugins.size();
|
|
}
|
|
|
|
const char *CPluginManager::GetStatusText(CPlugin *pl)
|
|
{
|
|
switch (pl->m_Status)
|
|
{
|
|
case Pl_NotFound:
|
|
return "NOFILE";
|
|
case Pl_Error:
|
|
return "ERROR";
|
|
case Pl_Refused:
|
|
return "FAILED";
|
|
case Pl_Paused:
|
|
return "PAUSED";
|
|
case Pl_Running:
|
|
{
|
|
if (pl->m_API && pl->m_API->QueryRunning(NULL, 0))
|
|
{
|
|
return "STOPPED";
|
|
} else {
|
|
return "RUNNING";
|
|
}
|
|
}
|
|
default:
|
|
return "-";
|
|
}
|
|
}
|
|
|
|
CPluginManager::CPlugin *CPluginManager::_Load(const char *file, PluginId source, char *error, size_t maxlen)
|
|
{
|
|
FILE *fp;
|
|
CPlugin *pl;
|
|
|
|
pl = new CPlugin();
|
|
*error = '\0';
|
|
|
|
//Add plugin to list
|
|
pl->m_Id = m_LastId;
|
|
pl->m_File.assign(file);
|
|
m_Plugins.push_back(pl);
|
|
m_LastId++;
|
|
|
|
//Check if the file even exists
|
|
fp = fopen(file, "r");
|
|
if (!fp)
|
|
{
|
|
if (error)
|
|
{
|
|
UTIL_Format(error, maxlen, "File not found: %s", file);
|
|
}
|
|
pl->m_Status = Pl_NotFound;
|
|
}
|
|
|
|
if (fp)
|
|
{
|
|
fclose(fp);
|
|
fp = NULL;
|
|
|
|
//Load the file
|
|
pl->m_Lib = dlmount(file);
|
|
if (!pl->m_Lib)
|
|
{
|
|
if (error)
|
|
{
|
|
UTIL_Format(error, maxlen, "%s", dlerror());
|
|
}
|
|
pl->m_Status = Pl_Error;
|
|
}
|
|
else
|
|
{
|
|
pl->m_API = NULL;
|
|
|
|
/**
|
|
* First, try the new "advanced" interface
|
|
*/
|
|
METAMOD_FN_LOAD fnLoad = (METAMOD_FN_LOAD)dlsym(pl->m_Lib, "CreateInterface_MMS");
|
|
if (fnLoad != NULL)
|
|
{
|
|
if (GlobVersionInfo.source_engine == SOURCE_ENGINE_UNKNOWN)
|
|
{
|
|
GlobVersionInfo.source_engine = g_Metamod.GetSourceEngineBuild();
|
|
}
|
|
if (GlobVersionInfo.game_dir == NULL)
|
|
{
|
|
GlobVersionInfo.game_dir = strrchr(g_Metamod.GetBaseDir(), PATH_SEP_CHAR) + 1;
|
|
}
|
|
|
|
/* Build path information */
|
|
char file_path[256];
|
|
size_t len = g_Metamod.PathFormat(file_path, sizeof(file_path), "%s", file);
|
|
|
|
for (size_t i = len - 1; i >= 0 && i < len; i--)
|
|
{
|
|
if (_IsPathSepChar(file_path[i]))
|
|
{
|
|
file_path[i] = '\0';
|
|
break;
|
|
}
|
|
}
|
|
|
|
MetamodLoaderInfo info;
|
|
info.pl_file = file;
|
|
info.pl_path = file_path;
|
|
|
|
pl->m_API = fnLoad(&GlobVersionInfo, &info);
|
|
#if SOURCE_ENGINE == SE_ORANGEBOXVALVE
|
|
/* For plugin compat - try loading again using original OB if OB-Valve has failed */
|
|
if (pl->m_API == NULL)
|
|
{
|
|
GlobVersionInfo.source_engine = SOURCE_ENGINE_ORANGEBOX;
|
|
pl->m_API = fnLoad(&GlobVersionInfo, &info);
|
|
GlobVersionInfo.source_engine = SOURCE_ENGINE_ORANGEBOXVALVE;
|
|
}
|
|
#endif
|
|
pl->m_UnloadFn = (METAMOD_FN_UNLOAD)dlsym(pl->m_Lib, "UnloadInterface_MMS");
|
|
}
|
|
|
|
/**
|
|
* If we didn't get anything, try the normal/simple interface.
|
|
*/
|
|
if (pl->m_API == NULL)
|
|
{
|
|
CreateInterfaceFn pfn = (CreateInterfaceFn)(dlsym(pl->m_Lib, PL_EXPOSURE_C));
|
|
if (!pfn)
|
|
{
|
|
if (error)
|
|
{
|
|
UTIL_Format(error, maxlen, "Function %s not found", PL_EXPOSURE_C);
|
|
}
|
|
pl->m_Status = Pl_Error;
|
|
}
|
|
else
|
|
{
|
|
pl->m_API = static_cast<ISmmPlugin *>((pfn)(METAMOD_PLAPI_NAME, NULL));
|
|
|
|
if (!pl->m_API)
|
|
{
|
|
if (error)
|
|
{
|
|
UTIL_Format(error, maxlen, "Failed to get API");
|
|
}
|
|
pl->m_Status = Pl_Error;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (pl->m_API != NULL)
|
|
{
|
|
int api = pl->m_API->GetApiVersion();
|
|
if (api < PLAPI_MIN_VERSION)
|
|
{
|
|
if (error)
|
|
{
|
|
if (api == 13)
|
|
{
|
|
UTIL_Format(error, maxlen, "Plugin uses experimental Metamod build, probably 1.6.x (%d < %d)", api, PLAPI_MIN_VERSION);
|
|
}
|
|
else if (api <= 12 && api >= 7)
|
|
{
|
|
UTIL_Format(error, maxlen, "Older Metamod version required, probably 1.4.x (%d < %d)", api, PLAPI_MIN_VERSION);
|
|
}
|
|
else
|
|
{
|
|
UTIL_Format(error, maxlen, "Older Metamod version required, probably 1.0 (%d < %d)", api, PLAPI_MIN_VERSION);
|
|
}
|
|
}
|
|
pl->m_Status = Pl_Error;
|
|
}
|
|
else if (api > METAMOD_PLAPI_VERSION)
|
|
{
|
|
if (error)
|
|
{
|
|
UTIL_Format(error, maxlen, "Plugin requires newer Metamod version (%d > %d)", api, METAMOD_PLAPI_VERSION);
|
|
}
|
|
pl->m_Status = Pl_Error;
|
|
}
|
|
else
|
|
{
|
|
if (pl->m_API->Load(pl->m_Id, &g_Metamod, error, maxlen, m_AllLoaded))
|
|
{
|
|
pl->m_Status = Pl_Running;
|
|
if (m_AllLoaded)
|
|
{
|
|
pl->m_API->AllPluginsLoaded();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pl->m_Status = Pl_Refused;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (pl->m_Lib && (pl->m_Status < Pl_Paused))
|
|
{
|
|
pl->m_Events.clear();
|
|
g_SourceHook.UnloadPlugin(pl->m_Id);
|
|
UnregAllConCmds(pl);
|
|
|
|
if (pl->m_UnloadFn != NULL)
|
|
{
|
|
pl->m_UnloadFn();
|
|
}
|
|
|
|
dlclose(pl->m_Lib);
|
|
pl->m_Lib = NULL;
|
|
pl->m_API = NULL;
|
|
}
|
|
|
|
return pl;
|
|
}
|
|
|
|
bool CPluginManager::_Unload(CPluginManager::CPlugin *pl, bool force, char *error, size_t maxlen)
|
|
{
|
|
if (error)
|
|
{
|
|
*error = '\0';
|
|
}
|
|
|
|
if (pl->m_API && pl->m_Lib)
|
|
{
|
|
//Note, we'll always tell the plugin it will be unloading...
|
|
if (pl->m_API->Unload(error, maxlen) || force)
|
|
{
|
|
//Make sure to detach it from sourcehook!
|
|
g_SourceHook.UnloadPlugin(pl->m_Id);
|
|
|
|
pl->m_Events.clear();
|
|
|
|
UnregAllConCmds(pl);
|
|
|
|
if (pl->m_UnloadFn != NULL)
|
|
{
|
|
pl->m_UnloadFn();
|
|
}
|
|
|
|
//Clean up the DLL
|
|
dlclose(pl->m_Lib);
|
|
pl->m_Lib = NULL;
|
|
pl->m_API = NULL;
|
|
|
|
//Remove the plugin from the list
|
|
PluginIter i;
|
|
for (i=m_Plugins.begin(); i!=m_Plugins.end(); i++)
|
|
{
|
|
if ( (*i)->m_Id == pl->m_Id )
|
|
{
|
|
i = m_Plugins.erase(i);
|
|
break;
|
|
}
|
|
}
|
|
//Free its memory
|
|
delete pl;
|
|
|
|
return true;
|
|
}
|
|
} else {
|
|
//The plugin is not valid, and let's just remove it from the list anyway
|
|
PluginIter i;
|
|
for (i=m_Plugins.begin(); i!=m_Plugins.end(); i++)
|
|
{
|
|
if ( (*i)->m_Id == pl->m_Id )
|
|
{
|
|
i = m_Plugins.erase(i);
|
|
break;
|
|
}
|
|
}
|
|
delete pl;
|
|
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool CPluginManager::_Pause(CPluginManager::CPlugin *pl, char *error, size_t maxlen)
|
|
{
|
|
if (error)
|
|
{
|
|
*error = '\0';
|
|
}
|
|
|
|
if (pl->m_Status != Pl_Running || !pl->m_API)
|
|
{
|
|
if (error)
|
|
{
|
|
UTIL_Format(error, maxlen, "Plugin cannot be paused");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (pl->m_API->Pause(error, maxlen))
|
|
{
|
|
g_SourceHook.PausePlugin(pl->m_Id);
|
|
pl->m_Status = Pl_Paused;
|
|
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool CPluginManager::_Unpause(CPluginManager::CPlugin *pl, char *error, size_t maxlen)
|
|
{
|
|
if (error)
|
|
{
|
|
*error = '\0';
|
|
}
|
|
|
|
if (pl->m_Status != Pl_Paused || !pl->m_API)
|
|
{
|
|
if (error)
|
|
{
|
|
UTIL_Format(error, maxlen, "Plugin cannot be unpaused");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (pl->m_API->Unpause(error, maxlen))
|
|
{
|
|
g_SourceHook.UnpausePlugin(pl->m_Id);
|
|
pl->m_Status = Pl_Running;
|
|
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool CPluginManager::UnloadAll()
|
|
{
|
|
PluginIter i;
|
|
|
|
char error[128];
|
|
bool status = true;
|
|
|
|
while ((i = m_Plugins.begin()) != m_Plugins.end())
|
|
{
|
|
if ( !_Unload( (*i), true, error, sizeof(error)) )
|
|
{
|
|
status = false;
|
|
}
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
bool CPluginManager::Query(PluginId id, const char **file, Pl_Status *status, PluginId *source)
|
|
{
|
|
CPlugin *pl = FindById(id);
|
|
|
|
if (!pl)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (file != NULL)
|
|
{
|
|
*file = pl->m_File.c_str();
|
|
}
|
|
|
|
if (status != NULL)
|
|
{
|
|
*status = pl->m_Status;
|
|
}
|
|
|
|
if (source != NULL)
|
|
{
|
|
*source = pl->m_Source;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool CPluginManager::QueryRunning(PluginId id, char *error, size_t maxlength)
|
|
{
|
|
CPlugin *pl = FindById(id);
|
|
|
|
if (!pl || !pl->m_API)
|
|
{
|
|
if (error)
|
|
{
|
|
UTIL_Format(error, maxlength, "Plugin not valid");
|
|
}
|
|
return false;
|
|
}
|
|
|
|
return pl->m_API->QueryRunning(error, maxlength);
|
|
}
|
|
|
|
bool CPluginManager::QueryHandle(PluginId id, void **handle)
|
|
{
|
|
CPlugin *pl = FindById(id);
|
|
|
|
if (!pl)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (handle)
|
|
{
|
|
*handle = static_cast<void *>(pl->m_Lib);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
PluginIter CPluginManager::_begin()
|
|
{
|
|
return m_Plugins.begin();
|
|
}
|
|
|
|
PluginIter CPluginManager::_end()
|
|
{
|
|
return m_Plugins.end();
|
|
}
|
|
|
|
void CPluginManager::AddPluginCvar(ISmmPlugin *api, ConCommandBase *pCvar)
|
|
{
|
|
CPlugin *pl = FindByAPI(api);
|
|
|
|
if (!pl)
|
|
{
|
|
return;
|
|
}
|
|
|
|
pl->m_Cvars.push_back(pCvar);
|
|
}
|
|
|
|
void CPluginManager::AddPluginCmd(ISmmPlugin *api, ConCommandBase *pCmd)
|
|
{
|
|
CPlugin *pl = FindByAPI(api);
|
|
|
|
if (!pl)
|
|
{
|
|
return;
|
|
}
|
|
|
|
pl->m_Cmds.push_back(pCmd);
|
|
}
|
|
|
|
void CPluginManager::RemovePluginCvar(ISmmPlugin *api, ConCommandBase *pCvar)
|
|
{
|
|
CPlugin *pl = FindByAPI(api);
|
|
|
|
if (!pl)
|
|
{
|
|
return;
|
|
}
|
|
|
|
pl->m_Cvars.remove(pCvar);
|
|
}
|
|
|
|
void CPluginManager::RemovePluginCmd(ISmmPlugin *api, ConCommandBase *pCmd)
|
|
{
|
|
CPlugin *pl = FindByAPI(api);
|
|
|
|
if (!pl)
|
|
{
|
|
return;
|
|
}
|
|
|
|
pl->m_Cmds.remove(pCmd);
|
|
}
|
|
|
|
void CPluginManager::UnregAllConCmds(CPlugin *pl)
|
|
{
|
|
SourceHook::List<ConCommandBase *>::iterator i;
|
|
|
|
/* :TODO: */
|
|
for (i=pl->m_Cvars.begin(); i!=pl->m_Cvars.end(); i++)
|
|
{
|
|
g_Metamod.UnregisterConCommandBase(pl->m_Id, (*i) );
|
|
}
|
|
pl->m_Cvars.clear();
|
|
|
|
for (i=pl->m_Cmds.begin(); i!=pl->m_Cmds.end(); i++)
|
|
{
|
|
g_Metamod.UnregisterConCommandBase(pl->m_Id, (*i) );
|
|
}
|
|
pl->m_Cmds.clear();
|
|
}
|
|
|