From c52389ea227b8071c3be795a72f89fa776063951 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Sat, 22 Sep 2007 18:08:30 +0000 Subject: [PATCH] nearly complete rewrite of Metamod:Source, API is the same but internally all engine/game functionality is abstracted. i also renamed files to make everything look a bit more conformant --HG-- branch : sourcemm-1.6.0 rename : sourcemm/sourcemm.cpp => sourcemm/metamod.cpp rename : sourcemm/sourcemm.h => sourcemm/metamod.h extra : convert_revision : svn%3Ac2935e3e-5518-0410-8daf-afa5dab7d4e3/branches/sourcemm-1.6.0%40427 --- sourcemm/CPlugin.cpp | 649 --------- sourcemm/CSmmAPI.cpp | 680 ---------- sourcemm/CSmmAPI.h | 97 -- sourcemm/ISmmAPI.h | 7 +- sourcemm/concommands.h | 53 - sourcemm/convar_smm.h | 523 -------- sourcemm/metamod.cpp | 1182 +++++++++++++++++ sourcemm/metamod.h | 88 ++ .../{concommands.cpp => metamod_console.cpp} | 545 ++++---- sourcemm/metamod_console.h | 19 + sourcemm/{CPlugin.h => metamod_plugins.h} | 5 +- sourcemm/{util.cpp => metamod_util.cpp} | 2 +- sourcemm/{util.h => metamod_util.h} | 0 sourcemm/msvc8/sourcemm.vcproj | 62 +- sourcemm/oslink.cpp | 21 + sourcemm/sample_mm/LICENSE.txt | 29 - sourcemm/sample_mm/Makefile | 67 - sourcemm/sample_mm/SamplePlugin.cpp | 237 ---- sourcemm/sample_mm/SamplePlugin.h | 132 -- sourcemm/sample_mm/cvars.cpp | 27 - sourcemm/sample_mm/cvars.h | 24 - sourcemm/sample_mm/msvc8/sample_mm.sln | 20 - sourcemm/sample_mm/msvc8/sample_mm.vcproj | 222 ---- sourcemm/sourcemm.cpp | 710 ---------- sourcemm/sourcemm.h | 131 -- sourcemm/stub_mm/LICENSE.txt | 29 - sourcemm/stub_mm/Makefile | 66 - sourcemm/stub_mm/msvc8/stub_mm.sln | 20 - sourcemm/stub_mm/msvc8/stub_mm.vcproj | 214 --- sourcemm/stub_mm/stub_mm.cpp | 105 -- sourcemm/stub_mm/stub_mm.h | 45 - sourcemm/vsp_listener.cpp | 152 --- sourcemm/vsp_listener.h | 49 - 33 files changed, 1569 insertions(+), 4643 deletions(-) delete mode 100644 sourcemm/CPlugin.cpp delete mode 100644 sourcemm/CSmmAPI.cpp delete mode 100644 sourcemm/CSmmAPI.h delete mode 100644 sourcemm/concommands.h delete mode 100644 sourcemm/convar_smm.h create mode 100644 sourcemm/metamod.cpp create mode 100644 sourcemm/metamod.h rename sourcemm/{concommands.cpp => metamod_console.cpp} (60%) create mode 100644 sourcemm/metamod_console.h rename sourcemm/{CPlugin.h => metamod_plugins.h} (98%) rename sourcemm/{util.cpp => metamod_util.cpp} (99%) rename sourcemm/{util.h => metamod_util.h} (100%) delete mode 100644 sourcemm/sample_mm/LICENSE.txt delete mode 100644 sourcemm/sample_mm/Makefile delete mode 100644 sourcemm/sample_mm/SamplePlugin.cpp delete mode 100644 sourcemm/sample_mm/SamplePlugin.h delete mode 100644 sourcemm/sample_mm/cvars.cpp delete mode 100644 sourcemm/sample_mm/cvars.h delete mode 100644 sourcemm/sample_mm/msvc8/sample_mm.sln delete mode 100644 sourcemm/sample_mm/msvc8/sample_mm.vcproj delete mode 100644 sourcemm/sourcemm.cpp delete mode 100644 sourcemm/sourcemm.h delete mode 100644 sourcemm/stub_mm/LICENSE.txt delete mode 100644 sourcemm/stub_mm/Makefile delete mode 100644 sourcemm/stub_mm/msvc8/stub_mm.sln delete mode 100644 sourcemm/stub_mm/msvc8/stub_mm.vcproj delete mode 100644 sourcemm/stub_mm/stub_mm.cpp delete mode 100644 sourcemm/stub_mm/stub_mm.h delete mode 100644 sourcemm/vsp_listener.cpp delete mode 100644 sourcemm/vsp_listener.h diff --git a/sourcemm/CPlugin.cpp b/sourcemm/CPlugin.cpp deleted file mode 100644 index bb61d3c..0000000 --- a/sourcemm/CPlugin.cpp +++ /dev/null @@ -1,649 +0,0 @@ -/* ======== SourceMM ======== - * Copyright (C) 2004-2007 Metamod:Source Development Team - * No warranties of any kind - * - * License: zlib/libpng - * - * Author(s): David "BAILOPAN" Anderson - * ============================ - */ - -#include "CPlugin.h" -#include "CSmmAPI.h" -#include "sourcemm.h" -#include "concommands.h" - -/** - * @brief Implements functions from CPlugin.h - * @file CPlugin.cpp - */ - -using namespace SourceMM; - -#define ITER_PLEVENT(evn, plid) \ - CPluginManager::CPlugin *_Xpl; \ - SourceHook::List::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; - -CPluginManager::CPluginManager() -{ - m_LastId = Pl_MinId; - m_AllLoaded = false; -} - -CPluginManager::~CPluginManager() -{ - SourceHook::List::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::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::iterator CPluginManager::_alias_begin() -{ - return m_Aliases.begin(); -} - -SourceHook::List::iterator CPluginManager::_alias_end() -{ - return m_Aliases.end(); -} - -void CPluginManager::SetAlias(const char *alias, const char *value) -{ - SourceHook::List::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) -{ - -} - -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() -{ - 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 { - 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((pfn)(PLAPI_NAME, NULL)); - if (!pl->m_API) - { - if (error) - UTIL_Format(error, maxlen, "Failed to get API"); - pl->m_Status = Pl_Error; - } else { - int api = pl->m_API->GetApiVersion(); - if (api < PLAPI_MIN_VERSION) - { - if (error) - UTIL_Format(error, maxlen, "Plugin API %d is out of date with required minimum (%d)", api, PLAPI_MIN_VERSION); - pl->m_Status = Pl_Error; - } else if (api > PLAPI_VERSION) { - if (error) - UTIL_Format(error, maxlen, "Plugin API %d is newer than internal version (%d)", api, PLAPI_VERSION); - pl->m_Status = Pl_Error; - } else { - if (pl->m_API->Load(pl->m_Id, static_cast(&g_SmmAPI), error, maxlen, m_AllLoaded)) - { - pl->m_Status = Pl_Running; - if (m_AllLoaded) - { - //API 4 is when we added this callback - //Removing this code as the min version is now 5 - //if (pl->m_API->GetApiVersion() >= 4) - 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); - - 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); - - UnregAllConCmds(pl); - - //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; - - file = pl->m_File.c_str(); - status = pl->m_Status; - 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; - } - - handle = static_cast(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::iterator i; - - for (i=pl->m_Cvars.begin(); i!=pl->m_Cvars.end(); i++) - g_SMConVarAccessor.Unregister(pl->m_Id, (*i) ); - - pl->m_Cvars.clear(); - - for (i=pl->m_Cmds.begin(); i!=pl->m_Cmds.end(); i++) - g_SMConVarAccessor.Unregister(pl->m_Id, (*i) ); - - pl->m_Cmds.clear(); -} diff --git a/sourcemm/CSmmAPI.cpp b/sourcemm/CSmmAPI.cpp deleted file mode 100644 index 459e585..0000000 --- a/sourcemm/CSmmAPI.cpp +++ /dev/null @@ -1,680 +0,0 @@ -/* ======== SourceMM ======== - * Copyright (C) 2004-2007 Metamod:Source Development Team - * No warranties of any kind - * - * License: zlib/libpng - * - * Author(s): David "BAILOPAN" Anderson - * ============================ - */ - -#include "convar_smm.h" -#include "CSmmAPI.h" -#include "sourcemm.h" -#include "concommands.h" -#include "CPlugin.h" -#include "vsp_listener.h" - -/** - * @brief Implementation of main API interface - * @file CSmmAPI.cpp - */ - -using namespace SourceMM; - -CSmmAPI g_SmmAPI; - -CSmmAPI::CSmmAPI() -{ - m_ConPrintf = NULL; - m_CmdCache = false; - m_MsgCount = -1; - m_VSP = false; -} - -CSmmAPI::~CSmmAPI() -{ - m_UserMessages.RemoveAll(); -} - -void CSmmAPI::LogMsg(ISmmPlugin *pl, const char *msg, ...) -{ - va_list ap; - static char buffer[2048]; - - va_start(ap, msg); - UTIL_FormatArgs(buffer, sizeof(buffer), msg, ap); - va_end(ap); - - LogMessage("[%s] %s", pl->GetLogTag(), buffer); -} - -CreateInterfaceFn CSmmAPI::engineFactory(bool syn) -{ - if (syn) - return EngineFactory; - return g_Engine.engineFactory; -} - -CreateInterfaceFn CSmmAPI::physicsFactory(bool syn) -{ - if (syn) - return PhysicsFactory; - return g_Engine.physicsFactory; -} - -CreateInterfaceFn CSmmAPI::fileSystemFactory(bool syn) -{ - if (syn) - return FileSystemFactory; - return g_Engine.fileSystemFactory; -} - -CreateInterfaceFn CSmmAPI::serverFactory(bool syn) -{ - if (syn) - return CreateInterface; - return g_GameDll.factory; -} - -CGlobalVars *CSmmAPI::pGlobals() -{ - return g_Engine.pGlobals; -} - -void CSmmAPI::SetLastMetaReturn(META_RES res) -{ - m_Res = res; -} - -META_RES CSmmAPI::GetLastMetaReturn() -{ - return m_Res; -} - -IConCommandBaseAccessor *CSmmAPI::GetCvarBaseAccessor() -{ - return static_cast(&g_SMConVarAccessor); -} - -bool CSmmAPI::RegisterConCmdBase(ISmmPlugin *plugin, ConCommandBase *pCommand) -{ - if (pCommand->IsCommand()) - { - g_PluginMngr.AddPluginCmd(plugin, pCommand); - } else { - g_PluginMngr.AddPluginCvar(plugin, pCommand); - } - - return g_SMConVarAccessor.Register(pCommand); -} - -void CSmmAPI::UnregisterConCmdBase(ISmmPlugin *plugin, ConCommandBase *pCommand) -{ - if (pCommand->IsCommand()) - { - g_PluginMngr.RemovePluginCmd(plugin, pCommand); - } else { - g_PluginMngr.RemovePluginCvar(plugin, pCommand); - } - - g_SMConVarAccessor.Unregister(g_PluginMngr.FindByAPI(plugin)->m_Id, pCommand); -} - -void CSmmAPI::ConPrint(const char *fmt) -{ - (m_ConPrintf)("%s", fmt); -} - -void CSmmAPI::ConPrintf(const char *fmt, ...) -{ - va_list ap; - static char buffer[4096]; - - va_start(ap, fmt); - UTIL_FormatArgs(buffer, sizeof(buffer), fmt, ap); - va_end(ap); - - (m_ConPrintf)("%s", buffer); -} - -void CSmmAPI::AddListener(ISmmPlugin *plugin, IMetamodListener *pListener) -{ - CPluginManager::CPlugin *pl = g_PluginMngr.FindByAPI(plugin); - - pl->m_Events.push_back(pListener); -} - -void *CSmmAPI::MetaFactory(const char *iface, int *_ret, PluginId *id) -{ - if (id) - { - *id = 0; - } - - if (!iface) - { - return NULL; - } - - //first check ours... we get first chance! - if (strcmp(iface, MMIFACE_SOURCEHOOK) == 0) - { - if (_ret) - { - *_ret = IFACE_OK; - } - return static_cast(static_cast(&g_SourceHook)); - } else if (strcmp(iface, MMIFACE_PLMANAGER) == 0) { - if (_ret) - { - *_ret = IFACE_OK; - } - return static_cast(static_cast(&g_PluginMngr)); - } - - CPluginManager::CPlugin *pl; - SourceHook::List::iterator event; - IMetamodListener *api; - int ret = 0; - void *val = NULL; - - for (PluginIter iter = g_PluginMngr._begin(); iter != g_PluginMngr._end(); iter++) - { - pl = (*iter); - for (event=pl->m_Events.begin(); event!=pl->m_Events.end(); event++) - { - api = (*event); - ret = IFACE_FAILED; - if ( (val=api->OnMetamodQuery(iface, &ret)) != NULL ) - { - if (_ret) - *_ret = ret; - if (id) - *id = pl->m_Id; - return val; - } - } - } - - if (_ret) - *_ret = IFACE_FAILED; - - return NULL; -} - -////////////////////////////////////////////////////////////////////////// -//THERE BE HAX HERE!!!! DON'T TELL ALFRED, BUT GABE WANTED IT THAT WAY. // -// (note: you can find the offset by looking for the text // -// "Echo text to console", you'll find the callback cmd pushed on the // -// stack.) // -////////////////////////////////////////////////////////////////////////// - -#define SIGLEN 8 -#define ENGINE486_SIG "\x55\x89\xE5\x53\x83\xEC\x14\xBB" -#define ENGINE486_OFFS 40 -#define ENGINE686_SIG "\x53\x83\xEC\x08\xBB\x01\x00\x00" -#define ENGINE686_OFFS 50 -#define ENGINEAMD_SIG "\x53\x51\xBB\x01\x00\x00\x00\x51" -#define ENGINEAMD_OFFS 47 -#define ENGINEW32_SIG "\xA1\x2A\x2A\x2A\x2A\x56\xBE\x01" -#define ENGINEW32_OFFS 38 -#define IA32_CALL 0xE8 - -bool vcmp(const void *_addr1, const void *_addr2, size_t len) -{ - unsigned char *addr1 = (unsigned char *)_addr1; - unsigned char *addr2 = (unsigned char *)_addr2; - - for (size_t i=0; iGetCommands(); - unsigned char *ptr = NULL; - FnCommandCallback callback = NULL; - int offs = 0; - - while (pBase) - { - if ( strcmp(pBase->GetName(), "echo") == 0 ) - { - //callback = //*((FnCommandCallback *)((char *)pBase + offsetof(ConCommand, m_fnCommandCallback))); - callback = ((ConCommand *)pBase)->GetCallback(); - ptr = (unsigned char *)callback; - #ifdef OS_LINUX - if (vcmp(ptr, ENGINE486_SIG, SIGLEN)) - { - offs = ENGINE486_OFFS; - } - else if (vcmp(ptr, ENGINE686_SIG, SIGLEN)) - { - offs = ENGINE686_OFFS; - } - else if (vcmp(ptr, ENGINEAMD_SIG, SIGLEN)) - { - offs = ENGINEAMD_OFFS; - } - #elif defined OS_WIN32 // Only one Windows engine binary so far... - if (vcmp(ptr, ENGINEW32_SIG, SIGLEN)) - { - offs = ENGINEW32_OFFS; - } - #endif - - if (!offs || ptr[offs - 1] != IA32_CALL) - { - m_ConPrintf = (CONPRINTF_FUNC)Msg; - return false; - } - //get the relative offset - m_ConPrintf = *((CONPRINTF_FUNC *)(ptr + offs)); - //add the base offset, to the ip (which is the address+offset + 4 bytes for next instruction) - m_ConPrintf = (CONPRINTF_FUNC)((unsigned long)m_ConPrintf + (unsigned long)(ptr + offs) + 4); - - m_CmdCache = true; - - return true; - } - pBase = const_cast(pBase->GetNext()); - } - - m_ConPrintf = (CONPRINTF_FUNC)Msg; - - return false; -} - -bool CSmmAPI::CmdCacheSuccessful() -{ - return m_CmdCache; -} - -void CSmmAPI::GetApiVersions(int &major, int &minor, int &plvers, int &plmin) -{ - major = SM_VERS_API_MAJOR; - minor = SM_VERS_API_MINOR; - plvers = PLAPI_VERSION; - plmin = PLAPI_MIN_VERSION; -} - -void CSmmAPI::GetShVersions(int &shvers, int &shimpl) -{ - shvers = SH_IFACE_VERSION; - shimpl = SH_IMPL_VERSION; -} - -int CSmmAPI::FormatIface(char iface[], unsigned int maxlength) -{ - int length = (int)strlen(iface); - int i; - int num = 0; - - for (i = length - 1; i >= 0; i--) - { - if (!isdigit(iface[i])) - { - if (i != length - 1) - { - num = 1; - } - break; - } - } - - if ( (num && ((int)maxlength <= length)) || (!num && ((int)maxlength <= length + 3)) ) - { - return -1; - } - - if (i != length - 1) - num = atoi(&(iface[++i])); - - num++; - - snprintf(&(iface[i]), 4, "%03d", num); - - return num; -} - -void *CSmmAPI::InterfaceSearch(CreateInterfaceFn fn, const char *iface, int max, int *ret) -{ - char _if[256]; /* assume no interface goes beyond this */ - size_t len = strlen(iface); - int num = 0; - void *pf = NULL; - - if (max > 999) - max = 999; - - if (len + 4 > sizeof(_if)) - { - if (ret) - { - *ret = IFACE_FAILED; - } - return NULL; - } - - strcpy(_if, iface); - - do - { - if ( (pf = (fn)(_if, ret)) != NULL ) - break; - if (num > max) - break; - } while (( num = FormatIface(_if, len+1) )); - - return pf; -} - -void *CSmmAPI::VInterfaceMatch(CreateInterfaceFn fn, const char *iface, int min) -{ - char buffer[256]; /* assume no interface will go beyond this */ - size_t len = strlen(iface); - int ret; /* just in case something doesn't handle NULL properly */ - - if (len > sizeof(buffer) - 4) - { - return NULL; - } - - strcpy(buffer, iface); - - if (min != -1) - { - char *ptr = &buffer[len - 1]; - int digits = 0; - while (isdigit(*ptr) && digits <=3) - { - *ptr = '\0'; - digits++; - ptr--; - } - if (digits != 3) - { - /* for now, assume this is an error */ - strcpy(buffer, iface); - } else { - char num[4]; - min = (min == 0) ? 1 : min; - snprintf(num, sizeof(num), "%03d", min); - strcat(buffer, num); - } - } - - return InterfaceSearch(fn, buffer, IFACE_MAXNUM, &ret); -} - -const char *CSmmAPI::GetBaseDir() -{ - return g_ModPath.c_str(); -} - -void CSmmAPI::PathFormat(char *buffer, size_t len, const char *fmt, ...) -{ - va_list ap; - va_start(ap, fmt); - size_t mylen = UTIL_FormatArgs(buffer, len, fmt, ap); - va_end(ap); - - for (size_t i = 0; i < mylen; i++) - { - if (buffer[i] == ALT_SEP_CHAR) - { - buffer[i] = PATH_SEP_CHAR; - } - } -} - -void CSmmAPI::ClientConPrintf(edict_t *client, const char *fmt, ...) -{ - va_list ap; - static char buffer[4096]; - - va_start(ap, fmt); - UTIL_FormatArgs(buffer, sizeof(buffer), fmt, ap); - va_end(ap); - - g_Engine.engine->ClientPrintf(client, buffer); -} - -void CSmmAPI::LoadAsVSP() -{ - size_t len; - char engine_file[PATH_SIZE]; - char engine_path[PATH_SIZE]; - char rel_path[PATH_SIZE * 2]; - - GetFileOfAddress(g_Engine.engine, engine_file, sizeof(engine_file)); - - /* Chop off the "engine" file part */ - len = strlen(engine_file); - for (size_t i = len - 1; i >= 0 && i < len; i--) - { - if (engine_file[i] == '/' - || engine_file[i] == '\\') - { - engine_file[i] = '\0'; - break; - } - } - abspath(engine_path, engine_file); - - const char *usepath = g_SmmPath.c_str(); - if (UTIL_Relatize(rel_path, sizeof(rel_path), engine_path, g_SmmPath.c_str())) - { - usepath = rel_path; - } - - char command[PATH_SIZE * 2]; - g_VspListener.SetLoadable(true); - UTIL_Format(command, sizeof(command), "plugin_load \"%s\"\n", usepath); - g_Engine.engine->ServerCommand(command); -} - -void CSmmAPI::EnableVSPListener() -{ - /* If GameInit already passed and we're not already enabled or loaded, go ahead and LoadAsVSP load */ - if (bGameInit && !m_VSP && !g_VspListener.IsLoaded()) - { - LoadAsVSP(); - } - m_VSP = true; -} - -int CSmmAPI::GetGameDLLVersion() -{ - return g_GameDllVersion; -} - -////////////////////////////////////////////////////////////////////// -// EVEN MORE HACKS HERE! YOU HAVE BEEN WARNED! // -// Signatures necessary in finding the pointer to the CUtlDict that // -// stores user message information. // -// IServerGameDLL::GetUserMessageInfo() normally crashes with bad // -// message indices. This is our answer to it. Yuck! <:-( // -////////////////////////////////////////////////////////////////////// -#ifdef OS_WIN32 - /* General Windows sig */ - #define MSGCLASS_SIGLEN 7 - #define MSGCLASS_SIG "\x8B\x0D\x2A\x2A\x2A\x2A\x56" - #define MSGCLASS_OFFS 2 - - /* Dystopia Wimdows hack */ - #define MSGCLASS2_SIGLEN 16 - #define MSGCLASS2_SIG "\x56\x8B\x74\x24\x2A\x85\xF6\x7C\x2A\x3B\x35\x2A\x2A\x2A\x2A\x7D" - #define MSGCLASS2_OFFS 11 - - /* Windows frame pointer sig */ - #define MSGCLASS3_SIGLEN 18 - #define MSGCLASS3_SIG "\x55\x8B\xEC\x51\x89\x2A\x2A\x8B\x2A\x2A\x50\x8B\x0D\x2A\x2A\x2A\x2A\xE8" - #define MSGCLASS3_OFFS 13 -#elif defined OS_LINUX - /* No frame pointer sig */ - #define MSGCLASS_SIGLEN 14 - #define MSGCLASS_SIG "\x53\x83\xEC\x2A\x8B\x2A\x2A\x2A\xA1\x2A\x2A\x2A\x2A\x89" - #define MSGCLASS_OFFS 9 - - /* Frame pointer sig */ - #define MSGCLASS2_SIGLEN 16 - #define MSGCLASS2_SIG "\x55\x89\xE5\x53\x83\xEC\x2A\x8B\x2A\x2A\xA1\x2A\x2A\x2A\x2A\x89" - #define MSGCLASS2_OFFS 11 -#endif - -/* This is the ugliest function in all of SourceMM */ -/* :TODO: Make this prettier */ -bool CSmmAPI::CacheUserMessages() -{ - SourceHook::MemFuncInfo info = {true, -1, 0, 0}; - SourceHook::GetFuncInfo(&IServerGameDLL::GetUserMessageInfo, info); - - /* Get address of original GetUserMessageInfo() */ - char *vfunc = reinterpret_cast(g_GameDllPatch->GetOrigFunc(info.vtbloffs, info.vtblindex)); - - /* If we can't get original function, that means there's no hook */ - if (vfunc == NULL) - { - /* Get virtual function address 'manually' then */ - char *adjustedptr = reinterpret_cast(g_GameDll.pGameDLL) + info.thisptroffs + info.vtbloffs; - char **vtable = *reinterpret_cast(adjustedptr); - - vfunc = vtable[info.vtblindex]; - } - - /* Oh dear, we have a relative jump on our hands - * PVK II on Windows made me do this, but I suppose it doesn't hurt to check this on Linux too... - */ - if (*vfunc == '\xE9') - { - /* Get address from displacement... - * - * Add 5 because it's relative to next instruction: - * Opcode <1 byte> + 32-bit displacement <4 bytes> - */ - vfunc = vfunc + *reinterpret_cast(vfunc + 1) + 5; - } - - UserMsgDict *dict = NULL; - - if (vcmp(vfunc, MSGCLASS_SIG, MSGCLASS_SIGLEN)) - { - /* Get address of CUserMessages instance */ - char **userMsgClass = *reinterpret_cast(vfunc + MSGCLASS_OFFS); - - /* Get address of CUserMessages::m_UserMessages */ - dict = reinterpret_cast(*userMsgClass); - } else if (vcmp(vfunc, MSGCLASS2_SIG, MSGCLASS2_SIGLEN)) { - #ifdef OS_WIN32 - /* If we get here, the code is possibly inlined like in Dystopia */ - - /* Get the address of the CUtlRBTree */ - char *rbtree = *reinterpret_cast(vfunc + MSGCLASS2_OFFS); - - /* CUtlDict should be 8 bytes before the CUtlRBTree (hacktacular!) */ - dict = reinterpret_cast(rbtree - 8); - #elif defined OS_LINUX - /* Get address of CUserMessages instance */ - char **userMsgClass = *reinterpret_cast(vfunc + MSGCLASS2_OFFS); - - /* Get address of CUserMessages::m_UserMessages */ - dict = reinterpret_cast(*userMsgClass); - #endif - #ifdef OS_WIN32 - } else if (vcmp(vfunc, MSGCLASS3_SIG, MSGCLASS3_SIGLEN)) { - /* Get address of CUserMessages instance */ - char **userMsgClass = *reinterpret_cast(vfunc + MSGCLASS3_OFFS); - - /* Get address of CUserMessages::m_UserMessages */ - dict = reinterpret_cast(*userMsgClass); - #endif - } - - if (dict) - { - m_MsgCount = dict->Count(); - - /* Ensure that count is within bounds of an unsigned byte, because that's what engine supports */ - if (m_MsgCount < 0 || m_MsgCount > 255) - { - m_MsgCount = -1; - return false; - } - - UserMessage *msg; - - /* Cache messages in our CUtlDict */ - for (int i = 0; i < m_MsgCount; i++) - { - msg = dict->Element(i); - m_UserMessages.Insert(msg->name, msg); - } - - return true; - } - - return false; -} - -bool CSmmAPI::MsgCacheSuccessful() -{ - return m_MsgCount > -1; -} - -int CSmmAPI::GetUserMessageCount() -{ - return m_MsgCount; -} - -int CSmmAPI::FindUserMessage(const char *name, int *size) -{ - int index = m_UserMessages.Find(name); - - if (size && index > -1) - { - UserMessage *msg = m_UserMessages.Element(index); - *size = msg->size; - } - - return index; -} - -const char *CSmmAPI::GetUserMessage(int index, int *size) -{ - if (m_MsgCount <= 0 || index < 0 || index >= m_MsgCount) - { - return NULL; - } - - UserMessage *msg = m_UserMessages.Element(index); - - if (size) - { - *size = msg->size; - } - - return msg->name; -} - -int CSmmAPI::GetVSPVersion() -{ - return g_VspVersion; -} - -int CSmmAPI::GetSourceEngineBuild() -{ - return g_SourceEngineVersion; -} diff --git a/sourcemm/CSmmAPI.h b/sourcemm/CSmmAPI.h deleted file mode 100644 index 98f9563..0000000 --- a/sourcemm/CSmmAPI.h +++ /dev/null @@ -1,97 +0,0 @@ -/* ======== SourceMM ======== - * Copyright (C) 2004-2007 Metamod:Source Development Team - * No warranties of any kind - * - * License: zlib/libpng - * - * Author(s): David "BAILOPAN" Anderson - * ============================ - */ - -#ifndef _INCLUDE_CSMM_API_H -#define _INCLUDE_CSMM_API_H - -/** - * @brief Header for CSmmAPI implementation - * @file CSmmAPI.h - */ - -#include "ISmmAPI.h" -#include - -struct UserMessage -{ - int size; - const char *name; -}; - -typedef CUtlDict UserMsgDict; - -typedef void (*CONPRINTF_FUNC)(const char *, ...); - -class CSmmAPI : public ISmmAPI -{ -public: - CSmmAPI(); - ~CSmmAPI(); -public: - void LogMsg(ISmmPlugin *pl, const char *msg, ...); -public: - CreateInterfaceFn engineFactory(bool syn=true); - CreateInterfaceFn physicsFactory(bool syn=true); - CreateInterfaceFn fileSystemFactory(bool syn=true); - CreateInterfaceFn serverFactory(bool syn=true); - CGlobalVars *pGlobals(); - void SetLastMetaReturn(META_RES res); - META_RES GetLastMetaReturn(); - IConCommandBaseAccessor *GetCvarBaseAccessor(); - bool RegisterConCmdBase(ISmmPlugin *plugin, ConCommandBase *pCommand); - void UnregisterConCmdBase(ISmmPlugin *plugin, ConCommandBase *pCommand); - void ConPrint(const char *fmt); - void ConPrintf(const char *fmt, ...); - bool RemotePrintingAvailable() - { - return CmdCacheSuccessful(); - } - virtual void GetApiVersions(int &major, int &minor, int &plvers, int &plmin); - virtual void GetShVersions(int &shvers, int &shimpl); - virtual void AddListener(ISmmPlugin *plugin, IMetamodListener *pListener); - virtual void *MetaFactory(const char *iface, int *ret, PluginId *id); - virtual int FormatIface(char buffer[], unsigned int maxlength); - virtual void *InterfaceSearch(CreateInterfaceFn fn, const char *iface, int max, int *ret); - virtual const char *GetBaseDir(); - virtual void PathFormat(char *buffer, size_t len, const char *fmt, ...); - void ClientConPrintf(edict_t *client, const char *fmt, ...); - void *VInterfaceMatch(CreateInterfaceFn fn, const char *iface, int min=-1); - void EnableVSPListener(); - int GetGameDLLVersion(); - int GetUserMessageCount(); - int FindUserMessage(const char *name, int *size=NULL); - const char *GetUserMessage(int index, int *size=NULL); - int GetVSPVersion(); - int GetSourceEngineBuild(); -public: - bool CacheCmds(); - bool CmdCacheSuccessful(); - void LoadAsVSP(); - bool VSPEnabled() - { - return m_VSP; - } - bool CacheUserMessages(); - bool MsgCacheSuccessful(); -private: - META_RES m_Res; - CONPRINTF_FUNC m_ConPrintf; - bool m_CmdCache; - bool m_VSP; - int m_MsgCount; - UserMsgDict m_UserMessages; -}; - -extern CSmmAPI g_SmmAPI; - -#define CONMSG g_SmmAPI.ConPrintf -#define CLIENT_CONMSG g_SmmAPI.ClientConPrintf - -#endif //_INCLUDE_CSMM_API_H diff --git a/sourcemm/ISmmAPI.h b/sourcemm/ISmmAPI.h index e6f7c70..d581a12 100644 --- a/sourcemm/ISmmAPI.h +++ b/sourcemm/ISmmAPI.h @@ -35,9 +35,10 @@ class ISmmPlugin; #define MMIFACE_PLMANAGER "IPluginManager" /**< SourceMM Plugin Functions */ #define IFACE_MAXNUM 999 /**< Maximum interface version */ -#define SOURCE_ENGINE_ORIGINAL 0 /**< Original Source Engine (used by The Ship) */ -#define SOURCE_ENGINE_EPISODEONE 1 /**< Episode 1 Source Engine (second major SDK) */ -#define SOURCE_ENGINE_ORANGEBOX 2 /**< Orange Box Source Engine (third major SDK) */ +#define SOURCE_ENGINE_UNKNOWN 0 /**< Could not determine the engine version */ +#define SOURCE_ENGINE_ORIGINAL 1 /**< Original Source Engine (used by The Ship) */ +#define SOURCE_ENGINE_EPISODEONE 2 /**< Episode 1 Source Engine (second major SDK) */ +#define SOURCE_ENGINE_ORANGEBOX 3 /**< Orange Box Source Engine (third major SDK) */ class ISmmAPI { diff --git a/sourcemm/concommands.h b/sourcemm/concommands.h deleted file mode 100644 index 0817afb..0000000 --- a/sourcemm/concommands.h +++ /dev/null @@ -1,53 +0,0 @@ -/* ======== SourceMM ======== - * Copyright (C) 2004-2007 Metamod:Source Development Team - * No warranties of any kind - * - * License: zlib/libpng - * - * Author(s): David "BAILOPAN" Anderson - * ============================ - */ - -#ifndef _INCLUDE_CONCOMMANDS_H -#define _INCLUDE_CONCOMMANDS_H - -/** - * @brief Header for console commands - * @file concommands.h - */ - -#include -#include -#include "sourcemm.h" -#include "convar_smm.h" -#include "sh_list.h" - -class SMConVarAccessor : public IConCommandBaseAccessor -{ - SourceHook::List m_RegisteredCommands; -public: - virtual bool RegisterConCommandBase(ConCommandBase *pCommand); - bool Register(ConCommandBase *pCommand); - void MarkCommandsAsGameDLL(); - void Unregister(PluginId id, ConCommandBase *pCommand); - void UnregisterGameDLLCommands(); -}; - -class CAlwaysRegisterableCommand : public ConCommandBase -{ - ICvar *m_pICvar; -public: - CAlwaysRegisterableCommand(); - bool IsRegistered( void ) const; - // If already registered, removes us - // Then it registers us again - void BringToFront(); -}; - -void ClientCommand_handler(edict_t *client); - -const char *GetPluginsFile(); - -extern SMConVarAccessor g_SMConVarAccessor; - -#endif //_INCLUDE_CONCOMMANDS_H diff --git a/sourcemm/convar_smm.h b/sourcemm/convar_smm.h deleted file mode 100644 index 26abce9..0000000 --- a/sourcemm/convar_smm.h +++ /dev/null @@ -1,523 +0,0 @@ -//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $Workfile: $ -// $Date$ -// -//----------------------------------------------------------------------------- -// $NoKeywords: $ -//=============================================================================// - -#ifndef CONVAR_H -#define CONVAR_H -#if _WIN32 -#pragma once -#endif - -#include "tier0/dbg.h" - -#ifdef _WIN32 -#define FORCEINLINE_CVAR FORCEINLINE -#elif _LINUX -#define FORCEINLINE_CVAR __inline__ FORCEINLINE -#else -#error "implement me" -#endif - -// The default, no flags at all -#define FCVAR_NONE 0 - -// Command to ConVars and ConCommands -// ConVar Systems -#define FCVAR_UNREGISTERED (1<<0) // If this is set, don't add to linked list, etc. -#define FCVAR_LAUNCHER (1<<1) // defined by launcher -#define FCVAR_GAMEDLL (1<<2) // defined by the game DLL -#define FCVAR_CLIENTDLL (1<<3) // defined by the client DLL -#define FCVAR_MATERIAL_SYSTEM (1<<4) // Defined by the material system. -#define FCVAR_DATACACHE (1<<19) // Defined by the datacache system. -#define FCVAR_STUDIORENDER (1<<15) // Defined by the studiorender system. -#define FCVAR_FILESYSTEM (1<<21) // Defined by the file system. -#define FCVAR_PLUGIN (1<<18) // Defined by a 3rd party plugin. -#define FCVAR_TOOLSYSTEM (1<<20) // Defined by an IToolSystem library -#define FCVAR_SOUNDSYSTEM (1<<23) // Defined by the soundsystem library -#define FCVAR_INPUTSYSTEM (1<<25) // Defined by the inputsystem dll -#define FCVAR_NETWORKSYSTEM (1<<26) // Defined by the network system -// NOTE!! if you add a cvar system, add it here too!!!! -// the engine lacks a cvar flag, but needs it for xbox -// an engine cvar is thus a cvar not marked with any other system -#define FCVAR_NON_ENGINE ((FCVAR_LAUNCHER|FCVAR_GAMEDLL|FCVAR_CLIENTDLL|FCVAR_MATERIAL_SYSTEM|FCVAR_DATACACHE|FCVAR_STUDIORENDER|FCVAR_FILESYSTEM|FCVAR_PLUGIN|FCVAR_TOOLSYSTEM|FCVAR_SOUNDSYSTEM|FCVAR_INPUTSYSTEM|FCVAR_NETWORKSYSTEM)) - -// ConVar only -#define FCVAR_PROTECTED (1<<5) // It's a server cvar, but we don't send the data since it's a password, etc. Sends 1 if it's not bland/zero, 0 otherwise as value -#define FCVAR_SPONLY (1<<6) // This cvar cannot be changed by clients connected to a multiplayer server. -#define FCVAR_ARCHIVE (1<<7) // set to cause it to be saved to vars.rc -#define FCVAR_NOTIFY (1<<8) // notifies players when changed -#define FCVAR_USERINFO (1<<9) // changes the client's info string -#define FCVAR_CHEAT (1<<14) // Only useable in singleplayer / debug / multiplayer & sv_cheats - -#define FCVAR_PRINTABLEONLY (1<<10) // This cvar's string cannot contain unprintable characters ( e.g., used for player name etc ). -#define FCVAR_UNLOGGED (1<<11) // If this is a FCVAR_SERVER, don't log changes to the log file / console if we are creating a log -#define FCVAR_NEVER_AS_STRING (1<<12) // never try to print that cvar - -// It's a ConVar that's shared between the client and the server. -// At signon, the values of all such ConVars are sent from the server to the client (skipped for local -// client, of course ) -// If a change is requested it must come from the console (i.e., no remote client changes) -// If a value is changed while a server is active, it's replicated to all connected clients -#define FCVAR_REPLICATED (1<<13) // server setting enforced on clients, TODO rename to FCAR_SERVER at some time -#define FCVAR_DEMO (1<<16) // record this cvar when starting a demo file -#define FCVAR_DONTRECORD (1<<17) // don't record these command in demofiles - -#define FCVAR_NOT_CONNECTED (1<<22) // cvar cannot be changed by a client that is connected to a server - -#define FCVAR_ARCHIVE_XBOX (1<<24) // cvar written to config.cfg on the Xbox - - -// #define FCVAR_AVAILABLE (1<<27) -// #define FCVAR_AVAILABLE (1<<28) -// #define FCVAR_AVAILABLE (1<<29) -// #define FCVAR_AVAILABLE (1<<30) -// #define FCVAR_AVAILABLE (1<<31) - - -class ConVar; -class ConCommand; -class ConCommandBase; - -// Any executable that wants to use ConVars need to implement one of -// these to hook up access to console variables. -class IConCommandBaseAccessor -{ -public: - // Flags is a combination of FCVAR flags in cvar.h. - // hOut is filled in with a handle to the variable. - virtual bool RegisterConCommandBase( ConCommandBase *pVar )=0; -}; - - -// You don't have to instantiate one of these, just call its -// OneTimeInit function when your executable is initializing. -class ConCommandBaseMgr -{ -public: - // Call this ONCE when the executable starts up. - static void OneTimeInit( IConCommandBaseAccessor *pAccessor ); -#ifdef _XBOX - static bool Fixup( ConCommandBase* pConCommandBase ); -#ifndef _RETAIL - static void PublishCommands( bool bForce ); -#endif -#endif -}; - -// Called when a ConVar changes value -typedef void ( *FnChangeCallback )( ConVar *var, char const *pOldString ); - -// Called when a ConCommand needs to execute -typedef void ( *FnCommandCallback )( void ); - -#define COMMAND_COMPLETION_MAXITEMS 64 -#define COMMAND_COMPLETION_ITEM_LENGTH 64 - -// Returns 0 to COMMAND_COMPLETION_MAXITEMS worth of completion strings -typedef int ( *FnCommandCompletionCallback )( char const *partial, char commands[ COMMAND_COMPLETION_MAXITEMS ][ COMMAND_COMPLETION_ITEM_LENGTH ] ); - -//----------------------------------------------------------------------------- -// Purpose: The base console invoked command/cvar interface -//----------------------------------------------------------------------------- -class ConCommandBase -{ - friend class ConCommandBaseMgr; - friend class CCvar; - friend class ConVar; - friend class ConCommand; - -public: - ConCommandBase( void ); - ConCommandBase( char const *pName, char const *pHelpString = 0, - int flags = 0 ); - - virtual ~ConCommandBase( void ); - - virtual bool IsCommand( void ) const; - - // Check flag - virtual bool IsBitSet( int flag ) const; - // Set flag - virtual void AddFlags( int flags ); - - // Return name of cvar - virtual char const *GetName( void ) const; - - // Return help text for cvar - virtual char const *GetHelpText( void ) const; - - // Deal with next pointer - const ConCommandBase *GetNext( void ) const; - void SetNext( ConCommandBase *next ); - - virtual bool IsRegistered( void ) const; - - // Global methods - static ConCommandBase const *GetCommands( void ); - static void AddToList( ConCommandBase *var ); - static void RemoveFlaggedCommands( int flag ); - static void RevertFlaggedCvars( int flag ); - static ConCommandBase const *FindCommand( char const *name ); - -protected: - virtual void Create( char const *pName, char const *pHelpString = 0, - int flags = 0 ); - - // Used internally by OneTimeInit to initialize. - virtual void Init(); - - // Internal copy routine ( uses new operator from correct module ) - char *CopyString( char const *from ); - - // Next ConVar in chain - ConCommandBase *m_pNext; - -private: - // Has the cvar been added to the global list? - bool m_bRegistered; - - // Static data - char const *m_pszName; - char const *m_pszHelpString; - - // ConVar flags - int m_nFlags; - -protected: - - // ConVars add themselves to this list for the executable. Then ConVarMgr::Init() runs through - // all the console variables and registers them. - static ConCommandBase *s_pConCommandBases; - - // ConVars in this executable use this 'global' to access values. - static IConCommandBaseAccessor *s_pAccessor; -}; - -//----------------------------------------------------------------------------- -// Purpose: The console invoked command -//----------------------------------------------------------------------------- -class ConCommand : public ConCommandBase -{ -friend class ConCommandBaseMgr; -friend class CCvar; -#ifdef _STATIC_LINKED -friend class G_ConCommand; -friend class C_ConCommand; -friend class M_ConCommand; -friend class S_ConCommand; -friend class D_ConCommand; -#endif - -public: - typedef ConCommandBase BaseClass; - - ConCommand( void ); - ConCommand( char const *pName, FnCommandCallback callback, - char const *pHelpString = 0, int flags = 0, FnCommandCompletionCallback completionFunc = 0 ); - - virtual ~ConCommand( void ); - - virtual bool IsCommand( void ) const; - - virtual int AutoCompleteSuggest( char const *partial, char commands[ COMMAND_COMPLETION_MAXITEMS ][ COMMAND_COMPLETION_ITEM_LENGTH ] ); - - virtual bool CanAutoComplete( void ); - - // Invoke the function - virtual void Dispatch( void ); -private: - virtual void Create( char const *pName, FnCommandCallback callback, - char const *pHelpString = 0, int flags = 0, FnCommandCompletionCallback completionFunc = 0 ); - - // Call this function when executing the command - FnCommandCallback m_fnCommandCallback; - - FnCommandCompletionCallback m_fnCompletionCallback; - bool m_bHasCompletionCallback; -public: - FnCommandCallback GetCallback() { return m_fnCommandCallback; } -}; - -//----------------------------------------------------------------------------- -// Purpose: A console variable -//----------------------------------------------------------------------------- -class ConVar : public ConCommandBase -{ -friend class ConCommandBaseMgr; -friend class CCvar; -friend class CDefaultCvar; -#ifdef _STATIC_LINKED -friend class G_ConVar; -friend class C_ConVar; -friend class M_ConVar; -friend class S_ConVar; -friend class D_ConVar; -#endif - -public: - typedef ConCommandBase BaseClass; - - ConVar( char const *pName, char const *pDefaultValue, int flags = 0); - - ConVar( char const *pName, char const *pDefaultValue, int flags, - char const *pHelpString ); - ConVar( char const *pName, char const *pDefaultValue, int flags, - char const *pHelpString, bool bMin, float fMin, bool bMax, float fMax ); - ConVar( char const *pName, char const *pDefaultValue, int flags, - char const *pHelpString, FnChangeCallback callback ); - ConVar( char const *pName, char const *pDefaultValue, int flags, - char const *pHelpString, bool bMin, float fMin, bool bMax, float fMax, - FnChangeCallback callback ); - - virtual ~ConVar( void ); - - virtual bool IsBitSet( int flag ) const; - virtual char const* GetHelpText( void ) const; - virtual bool IsRegistered( void ) const; - virtual char const *GetName( void ) const; - virtual void AddFlags( int flags ); - virtual bool IsCommand( void ) const; - - // Install a change callback (there shouldn't already be one....) - void InstallChangeCallback( FnChangeCallback callback ); - - // Retrieve value - FORCEINLINE_CVAR float GetFloat( void ) const; - FORCEINLINE_CVAR int GetInt( void ) const; - FORCEINLINE_CVAR bool GetBool() const { return !!GetInt(); } - FORCEINLINE_CVAR char const *GetString( void ) const; - - // Any function that allocates/frees memory needs to be virtual or else you'll have crashes - // from alloc/free across dll/exe boundaries. - - // These just call into the IConCommandBaseAccessor to check flags and set the var (which ends up calling InternalSetValue). - virtual void SetValue( char const *value ); - virtual void SetValue( float value ); - virtual void SetValue( int value ); - - // Reset to default value - void Revert( void ); - - // True if it has a min/max setting - bool GetMin( float& minVal ) const; - bool GetMax( float& maxVal ) const; - char const *GetDefault( void ) const; - - static void RevertAll( void ); -private: - // Called by CCvar when the value of a var is changing. - virtual void InternalSetValue(char const *value); - // For CVARs marked FCVAR_NEVER_AS_STRING - virtual void InternalSetFloatValue( float fNewValue ); - virtual void InternalSetIntValue( int nValue ); - - virtual bool ClampValue( float& value ); - virtual void ChangeStringValue( char const *tempVal ); - - virtual void Create( char const *pName, char const *pDefaultValue, int flags = 0, - char const *pHelpString = 0, bool bMin = false, float fMin = 0.0, - bool bMax = false, float fMax = false, FnChangeCallback callback = 0 ); - - // Used internally by OneTimeInit to initialize. - virtual void Init(); - -private: - - // This either points to "this" or it points to the original declaration of a ConVar. - // This allows ConVars to exist in separate modules, and they all use the first one to be declared. - // m_pParent->m_pParent must equal m_pParent (ie: m_pParent must be the root, or original, ConVar). - ConVar *m_pParent; - - // Static data - char const *m_pszDefaultValue; - - // Value - // Dynamically allocated - char *m_pszString; - int m_StringLength; - - // Values - float m_fValue; - int m_nValue; - - // Min/Max values - bool m_bHasMin; - float m_fMinVal; - bool m_bHasMax; - float m_fMaxVal; - - // Call this function when ConVar changes - FnChangeCallback m_fnChangeCallback; -}; - - -//----------------------------------------------------------------------------- -// Purpose: Return ConVar value as a float -// Output : float -//----------------------------------------------------------------------------- -FORCEINLINE_CVAR float ConVar::GetFloat( void ) const -{ - return m_pParent->m_fValue; -} - -//----------------------------------------------------------------------------- -// Purpose: Return ConVar value as an int -// Output : int -//----------------------------------------------------------------------------- -FORCEINLINE_CVAR int ConVar::GetInt( void ) const -{ - return m_pParent->m_nValue; -} - - -//----------------------------------------------------------------------------- -// Purpose: Return ConVar value as a string, return "" for bogus string pointer, etc. -// Output : char const * -//----------------------------------------------------------------------------- -FORCEINLINE_CVAR char const *ConVar::GetString( void ) const -{ - if ( m_nFlags & FCVAR_NEVER_AS_STRING ) - { - return "FCVAR_NEVER_AS_STRING"; - } - - return ( m_pParent->m_pszString ) ? m_pParent->m_pszString : ""; -} - - -#ifdef _STATIC_LINKED -// identifies subsystem via piggybacking constructors with flags -class G_ConCommand : public ConCommand -{ -public: - G_ConCommand(char const *pName, FnCommandCallback callback, char const *pHelpString = 0, int flags = 0, FnCommandCompletionCallback completionFunc = 0 ) : ConCommand(pName, callback, pHelpString, flags|FCVAR_GAMEDLL, completionFunc) {} -}; - -class C_ConCommand : public ConCommand -{ -public: - C_ConCommand(char const *pName, FnCommandCallback callback, char const *pHelpString = 0, int flags = 0, FnCommandCompletionCallback completionFunc = 0 ) : ConCommand(pName, callback, pHelpString, flags|FCVAR_CLIENTDLL, completionFunc) {} -}; - -class M_ConCommand : public ConCommand -{ -public: - M_ConCommand(char const *pName, FnCommandCallback callback, char const *pHelpString = 0, int flags = 0, FnCommandCompletionCallback completionFunc = 0 ) : ConCommand(pName, callback, pHelpString, flags|FCVAR_MATERIAL_SYSTEM, completionFunc) {} -}; - -class S_ConCommand : public ConCommand -{ -public: - S_ConCommand(char const *pName, FnCommandCallback callback, char const *pHelpString = 0, int flags = 0, FnCommandCompletionCallback completionFunc = 0 ) : ConCommand(pName, callback, pHelpString, flags|FCVAR_STUDIORENDER, completionFunc) {} -}; - -class D_ConCommand : public ConCommand -{ -public: - D_ConCommand(char const *pName, FnCommandCallback callback, char const *pHelpString = 0, int flags = 0, FnCommandCompletionCallback completionFunc = 0 ) : ConCommand(pName, callback, pHelpString, flags|FCVAR_DATACACHE, completionFunc) {} -}; - -typedef void ( *G_FnChangeCallback )( G_ConVar *var, char const *pOldString ); -typedef void ( *C_FnChangeCallback )( C_ConVar *var, char const *pOldString ); -typedef void ( *M_FnChangeCallback )( M_ConVar *var, char const *pOldString ); -typedef void ( *S_FnChangeCallback )( S_ConVar *var, char const *pOldString ); -typedef void ( *D_FnChangeCallback )( D_ConVar *var, char const *pOldString ); - -class G_ConVar : public ConVar -{ -public: - G_ConVar( char const *pName, char const *pDefaultValue, int flags = 0) : ConVar(pName, pDefaultValue, flags|FCVAR_GAMEDLL) {} - G_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString ) : ConVar(pName, pDefaultValue, flags|FCVAR_GAMEDLL, pHelpString ) {} - G_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, bool bMin, float fMin, bool bMax, float fMax ) : ConVar(pName, pDefaultValue, flags|FCVAR_GAMEDLL, pHelpString, bMin, fMin, bMax, fMax) {} - G_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, G_FnChangeCallback callback ) : ConVar(pName, pDefaultValue, flags|FCVAR_GAMEDLL, pHelpString, (FnChangeCallback)callback ) {} - G_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, bool bMin, float fMin, bool bMax, float fMax, G_FnChangeCallback callback ) : ConVar(pName, pDefaultValue, flags|FCVAR_GAMEDLL, pHelpString, bMin, fMin, bMax, fMax, (FnChangeCallback)callback ) {} -}; - -class C_ConVar : public ConVar -{ -public: - C_ConVar( char const *pName, char const *pDefaultValue, int flags = 0) : ConVar(pName, pDefaultValue, flags|FCVAR_CLIENTDLL) {} - C_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString ) : ConVar(pName, pDefaultValue, flags|FCVAR_CLIENTDLL, pHelpString ) {} - C_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, bool bMin, float fMin, bool bMax, float fMax ) : ConVar(pName, pDefaultValue, flags|FCVAR_CLIENTDLL, pHelpString, bMin, fMin, bMax, fMax) {} - C_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, C_FnChangeCallback callback ) : ConVar(pName, pDefaultValue, flags|FCVAR_CLIENTDLL, pHelpString, (FnChangeCallback)callback ) {} - C_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, bool bMin, float fMin, bool bMax, float fMax, C_FnChangeCallback callback ) : ConVar(pName, pDefaultValue, flags|FCVAR_CLIENTDLL, pHelpString, bMin, fMin, bMax, fMax, (FnChangeCallback)callback ) {} -}; - -class M_ConVar : public ConVar -{ -public: - M_ConVar( char const *pName, char const *pDefaultValue, int flags = 0) : ConVar(pName, pDefaultValue, flags|FCVAR_MATERIAL_SYSTEM) {} - M_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString ) : ConVar(pName, pDefaultValue, flags|FCVAR_MATERIAL_SYSTEM, pHelpString ) {} - M_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, bool bMin, float fMin, bool bMax, float fMax ) : ConVar(pName, pDefaultValue, flags|FCVAR_MATERIAL_SYSTEM, pHelpString, bMin, fMin, bMax, fMax) {} - M_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, M_FnChangeCallback callback ) : ConVar(pName, pDefaultValue, flags|FCVAR_MATERIAL_SYSTEM, pHelpString, (FnChangeCallback)callback ) {} - M_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, bool bMin, float fMin, bool bMax, float fMax, M_FnChangeCallback callback ) : ConVar(pName, pDefaultValue, flags|FCVAR_MATERIAL_SYSTEM, pHelpString, bMin, fMin, bMax, fMax, (FnChangeCallback)callback ) {} -}; - -class S_ConVar : public ConVar -{ -public: - S_ConVar( char const *pName, char const *pDefaultValue, int flags = 0) : ConVar(pName, pDefaultValue, flags|FCVAR_STUDIORENDER) {} - S_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString ) : ConVar(pName, pDefaultValue, flags|FCVAR_STUDIORENDER, pHelpString ) {} - S_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, bool bMin, float fMin, bool bMax, float fMax ) : ConVar(pName, pDefaultValue, flags|FCVAR_STUDIORENDER, pHelpString, bMin, fMin, bMax, fMax) {} - S_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, M_FnChangeCallback callback ) : ConVar(pName, pDefaultValue, flags|FCVAR_STUDIORENDER, pHelpString, (FnChangeCallback)callback ) {} - S_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, bool bMin, float fMin, bool bMax, float fMax, S_FnChangeCallback callback ) : ConVar(pName, pDefaultValue, flags|FCVAR_STUDIORENDER, pHelpString, bMin, fMin, bMax, fMax, (FnChangeCallback)callback ) {} -}; - -class D_ConVar : public ConVar -{ -public: - D_ConVar( char const *pName, char const *pDefaultValue, int flags = 0) : ConVar(pName, pDefaultValue, flags|FCVAR_DATACACHE) {} - D_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString ) : ConVar(pName, pDefaultValue, flags|FCVAR_DATACACHE, pHelpString ) {} - D_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, bool bMin, float fMin, bool bMax, float fMax ) : ConVar(pName, pDefaultValue, flags|FCVAR_DATACACHE, pHelpString, bMin, fMin, bMax, fMax) {} - D_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, M_FnChangeCallback callback ) : ConVar(pName, pDefaultValue, flags|FCVAR_DATACACHE, pHelpString, (FnChangeCallback)callback ) {} - D_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, bool bMin, float fMin, bool bMax, float fMax, D_FnChangeCallback callback ) : ConVar(pName, pDefaultValue, flags|FCVAR_DATACACHE, pHelpString, bMin, fMin, bMax, fMax, (FnChangeCallback)callback ) {} -}; - -// redirect these declarations to their specific subsystem -#ifdef GAME_DLL -#define ConCommand G_ConCommand -#define ConVar G_ConVar -#endif -#ifdef CLIENT_DLL -#define ConCommand C_ConCommand -#define ConVar C_ConVar -#endif -#ifdef MATERIALSYSTEM_DLL -#define ConCommand M_ConCommand -#define ConVar M_ConVar -#endif -#ifdef STUDIORENDER_DLL -#define ConCommand S_ConCommand -#define ConVar S_ConVar -#endif -#ifdef DATACACHE_DLL -#define ConCommand D_ConCommand -#define ConVar D_ConVar -#endif -#endif // _STATIC_LINKED - -//----------------------------------------------------------------------------- -// Purpose: Utility to quicky generate a simple console command -//----------------------------------------------------------------------------- -#define CON_COMMAND( name, description ) \ - static void name(); \ - static ConCommand name##_command( #name, name, description ); \ - static void name() - -//----------------------------------------------------------------------------- -// Purpose: Utility to quicky generate a simple console command -//----------------------------------------------------------------------------- -#define CON_COMMAND_F( name, description, flags ) \ - static void name(); \ - static ConCommand name##_command( #name, name, description, flags ); \ - static void name() - - -#endif // CONVAR_H diff --git a/sourcemm/metamod.cpp b/sourcemm/metamod.cpp new file mode 100644 index 0000000..82081d4 --- /dev/null +++ b/sourcemm/metamod.cpp @@ -0,0 +1,1182 @@ +/* ======== SourceMM ======== + * Copyright (C) 2004-2007 Metamod:Source Development Team + * No warranties of any kind + * + * License: zlib/libpng + * + * Author(s): David "BAILOPAN" Anderson + * Contributor(s): Scott "Damaged Soul" Ehlert + * : Pavol "PM OnoTo" Marko + * ============================ + */ + +#if defined _DEBUG +#define DEBUG2 +#undef _DEBUG +#endif +#include +#include +#include "metamod.h" +#include "metamod_provider.h" +#include "metamod_plugins.h" +#include "metamod_util.h" +#include "metamod_console.h" +#if defined DEBUG2 +#undef DEBUG2 +#define _DEBUG +#endif + +using namespace SourceMM; +using namespace SourceHook; + +/** + * @brief Implementation of main SourceMM GameDLL functionality + * @file sourcemm.cpp + */ +IMetamodSourceProvider *provider = NULL; + +SH_DECL_MANUALHOOK4(SGD_DLLInit, 0, 0, 0, bool, CreateInterfaceFn, CreateInterfaceFn, CreateInterfaceFn, CGlobalVars *); +SH_DECL_MANUALHOOK0(SGD_GameInit, 0, 0, 0, bool); +SH_DECL_MANUALHOOK6(SGD_LevelInit, 0, 0, 0, bool, const char *, const char *, const char *, const char *, bool, bool); +SH_DECL_MANUALHOOK0_void(SGD_LevelShutdown, 0, 0, 0); +SH_DECL_MANUALHOOK0_void(SGD_DLLShutdown, 0, 0, 0); + +bool Handler_DLLInit(CreateInterfaceFn engineFactory, CreateInterfaceFn physicsFactory, CreateInterfaceFn filesystemFactory, CGlobalVars *pGlobals); +bool Handler_DLLInit_Post(CreateInterfaceFn engineFactory, CreateInterfaceFn physicsFactory, CreateInterfaceFn filesystemFactory, CGlobalVars *pGlobals); +void Handler_DLLShutdown(); +void Handler_LevelShutdown(); +bool Handler_LevelInit(char const *pMapName, char const *pMapEntities, char const *pOldLevel, char const *pLandmarkName, bool loadGame, bool background); +bool Handler_GameInit(); +void InitializeVSP(); + +struct game_dll_t +{ + HINSTANCE lib; + CreateInterfaceFn factory; +}; + +SourceHook::CallClass *g_GameDllPatch; +String mod_path; +String metamod_path; +String full_bin_path; +bool parsed_game_info = false; +int vsp_version = 0; +int gamedll_version = 0; +int engine_build = SOURCE_ENGINE_UNKNOWN; +List gamedll_list; +bool is_gamedll_loaded = false; +bool in_first_level = true; +bool is_game_init = false; +bool vsp_load_attempted = false; +bool vsp_load_requested = false; +bool vsp_loaded = false; +game_dll_t gamedll_info; +ConVar *metamod_version = NULL; +ConVar *mm_pluginsfile = NULL; +IServerGameDLL *server = NULL; +CreateInterfaceFn engine_factory = NULL; +CreateInterfaceFn physics_factory = NULL; +CreateInterfaceFn filesystem_factory = NULL; +CGlobalVars *gpGlobals = NULL; +SourceHook::CSourceHookImpl g_SourceHook; +SourceHook::ISourceHook *g_SHPtr = &g_SourceHook; +PluginId g_PLID = Pl_Console; +META_RES last_meta_res; + +MetamodSource g_Metamod; + +void ClearGamedllList(); + +/* Helper Macro */ +#define IFACE_MACRO(orig,nam) \ + CPluginManager::CPlugin *pl; \ + SourceHook::List::iterator event; \ + IMetamodListener *api; \ + int mret = 0; \ + void *val = NULL; \ + for (PluginIter iter = g_PluginMngr._begin(); iter != g_PluginMngr._end(); iter++) { \ + pl = (*iter); \ + for (event=pl->m_Events.begin(); event!=pl->m_Events.end(); event++) { \ + api = (*event); \ + mret = IFACE_FAILED; \ + if ( (val=api->On##nam##Query(iface, &mret)) != NULL ) { \ + if (ret) *ret = mret; \ + return val; \ + } \ + } \ + } \ + return (orig)(iface, ret); + +#define ITER_EVENT(evn, args) \ + CPluginManager::CPlugin *pl; \ + SourceHook::List::iterator event; \ + IMetamodListener *api; \ + for (PluginIter iter = g_PluginMngr._begin(); iter != g_PluginMngr._end(); iter++) { \ + pl = (*iter); \ + for (event=pl->m_Events.begin(); event!=pl->m_Events.end(); event++) { \ + api = (*event); \ + api->evn args; \ + } \ + } + +/* Initialize everything here */ +void InitMainStates() +{ + char full_path[PATH_SIZE] = {0}; + GetFileOfAddress((void *)gamedll_info.factory, full_path, sizeof(full_path)); + full_bin_path.assign(full_path); + + /* Like Metamod, reload plugins at the end of the map. + * This is so plugins can hook everything on load, BUT, new plugins will be reloaded + * if the server is shut down (silly, but rare case). + */ + in_first_level = true; + + SourceHook::MemFuncInfo info; + + if (!provider->GetHookInfo(ProvidedHook_DLLInit, &info)) + { + provider->DisplayError("Metamod:Source could not find a valid hook for IServerGameDLL::DLLInit"); + } + SH_MANUALHOOK_RECONFIGURE(SGD_DLLInit, info.vtblindex, info.vtbloffs, info.thisptroffs); + SH_ADD_MANUALHOOK_STATICFUNC(SGD_DLLInit, server, Handler_DLLInit, false); + SH_ADD_MANUALHOOK_STATICFUNC(SGD_DLLInit, server, Handler_DLLInit_Post, true); + + if (!provider->GetHookInfo(ProvidedHook_GameInit, &info)) + { + provider->DisplayError("Metamod:Source could not find a valid hook for IServerGameDLL::GameInit"); + } + SH_MANUALHOOK_RECONFIGURE(SGD_GameInit, info.vtblindex, info.vtbloffs, info.thisptroffs); + SH_ADD_MANUALHOOK_STATICFUNC(SGD_GameInit, server, Handler_GameInit, false); + + if (!provider->GetHookInfo(ProvidedHook_LevelInit, &info)) + { + provider->DisplayError("Metamod:Source could not find a valid hook for IServerGameDLL::LevelInit"); + } + SH_MANUALHOOK_RECONFIGURE(SGD_LevelInit, info.vtblindex, info.vtbloffs, info.thisptroffs); + SH_ADD_MANUALHOOK_STATICFUNC(SGD_LevelInit, server, Handler_LevelInit, true); + + if (!provider->GetHookInfo(ProvidedHook_LevelShutdown, &info)) + { + provider->DisplayError("Metamod:Source could not find a valid hook for IServerGameDLL::LevelShutdown"); + } + SH_MANUALHOOK_RECONFIGURE(SGD_LevelShutdown, info.vtblindex, info.vtbloffs, info.thisptroffs); + SH_ADD_MANUALHOOK_STATICFUNC(SGD_LevelShutdown, server, Handler_LevelShutdown, true); + + if (!provider->GetHookInfo(ProvidedHook_DLLShutdown, &info)) + { + provider->DisplayError("Metamod:Source could not find a valid hook for IServerGameDLL::DLLShutdown"); + } + SH_MANUALHOOK_RECONFIGURE(SGD_DLLShutdown, info.vtblindex, info.vtbloffs, info.thisptroffs); + SH_ADD_MANUALHOOK_STATICFUNC(SGD_DLLShutdown, server, Handler_DLLShutdown, false); +} + +/* This is where the magic happens */ +SMM_API void *CreateInterface(const char *iface, int *ret) +{ + /* Prevent loading of self as a SourceMM plugin or Valve server plugin :x */ + if (strcmp(iface, PLAPI_NAME) == 0) + { + provider->DisplayWarning("Do not try loading Metamod:Source as a plugin.\n"); + + if (ret) + { + *ret = IFACE_FAILED; + } + + return NULL; + } + + if (strncmp(iface, "ISERVERPLUGINCALLBACKS", 22) == 0) + { + IServerPluginCallbacks *pCallbacks = provider->GetVSPCallbacks(iface); + + if (pCallbacks && vsp_version == 0) + { + vsp_version = atoi(&iface[22]); + } + + if (pCallbacks && ret) + { + *ret = pCallbacks ? IFACE_OK : IFACE_FAILED; + } + + return pCallbacks; + } + + if (!parsed_game_info) + { + parsed_game_info = true; + const char *game_dir = NULL; + char game_path[PATH_SIZE]; + char mm_path[PATH_SIZE]; + + /* Get path to SourceMM DLL */ + if (!GetFileOfAddress((void *)CreateInterface, mm_path, sizeof(mm_path))) + { + provider->DisplayError("GetFileOfAddress() failed! Metamod cannot load.\n"); + return NULL; + } + + metamod_path.assign(mm_path); + + /* Get value of -game from command line, defaulting to hl2 as engine seems to do */ + game_dir = provider->GetCommandLineValue("-game", "hl2"); + + /* Get absolute path */ + abspath(game_path, game_dir); + mod_path.assign(game_path); + + char temp_path[PATH_SIZE]; + + /* Path to gameinfo.txt */ + g_Metamod.PathFormat(temp_path, PATH_SIZE, "%s/%s", mod_path.c_str(), "gameinfo.txt"); + + FILE *fp = fopen(temp_path, "rt"); + + if (!fp) + { + provider->DisplayError("Unable to open gameinfo.txt! Metamod cannot load.\n"); + return NULL; + } + + char buffer[255]; + char key[128], val[128]; + bool search = false; + bool gamebin = false; + char *ptr; + const char *lptr; + char cur_path[PATH_SIZE]; + + getcwd(cur_path, PATH_SIZE); + + while (!feof(fp) && fgets(buffer, sizeof(buffer), fp) != NULL) + { + UTIL_TrimComments(buffer); + UTIL_TrimLeft(buffer); + UTIL_TrimRight(buffer); + + if (stricmp(buffer, "SearchPaths") == 0) + { + search = true; + } + + if (!search) + { + continue; + } + + UTIL_KeySplit(buffer, key, sizeof(key) - 1, val, sizeof(val) - 1); + if (stricmp(key, "Game") == 0 || stricmp(key, "GameBin") == 0) + { + if (stricmp(key, "Game") == 0) + { + gamebin = false; + } + else + { + gamebin = true; + } + + if (strncmp(val, "|gameinfo_path|", sizeof("|gameinfo_path|") - 1) == 0) + { + ptr = &(val[sizeof("|gameinfo_path|") - 1]); + if (ptr[0] == '.') + { + ptr++; + } + lptr = mod_path.c_str(); + } else { + ptr = val; + lptr = cur_path; + } + + size_t ptr_len = strlen(ptr); + if (ptr[ptr_len] == '/' || ptr[ptr_len] == '\\') + { + ptr[--ptr_len] = '\0'; + } + + /* No need to append "bin" if key is GameBin */ + if (gamebin) + { + g_Metamod.PathFormat(temp_path, PATH_SIZE, "%s/%s/%s", lptr, ptr, SERVER_DLL); + } + else if (!ptr[0]) + { + g_Metamod.PathFormat(temp_path, PATH_SIZE, "%s/%s/%s", lptr, "bin", SERVER_DLL); + } + else + { + g_Metamod.PathFormat(temp_path, PATH_SIZE, "%s/%s/%s/%s", lptr, ptr, "bin", SERVER_DLL); + } + + /* If not path to SourceMM... */ + if (!UTIL_PathCmp(mm_path, temp_path)) + { + FILE *temp_fp = fopen(temp_path, "rb"); + if (!temp_fp) + { + continue; + } + fclose(temp_fp); + + /* Search for a matching game dll */ + List::iterator iter; + game_dll_t *pCheck; + bool found = false; + for (iter = gamedll_list.begin(); iter != gamedll_list.end(); iter++) + { + pCheck = (*iter); + if (GetFileOfAddress((void *)pCheck->factory, buffer, sizeof(buffer))) + { + if (UTIL_PathCmp(temp_path, buffer)) + { + found = true; + break; + } + } + } + + if (found) + { + continue; + } + + HINSTANCE gamedll = dlmount(temp_path); + if (gamedll == NULL) + { + continue; + } + + CreateInterfaceFn fn = (CreateInterfaceFn)dlsym(gamedll, "CreateInterface"); + if (fn == NULL) + { + dlclose(gamedll); + continue; + } + + game_dll_t *pInfo = new game_dll_t; + pInfo->factory = fn; + pInfo->lib = gamedll; + gamedll_list.push_back(pInfo); + break; + } + } + } + fclose(fp); + } + + if (!is_gamedll_loaded) + { + if (strncmp(iface, "ServerGameDLL", 13) == 0) + { + List::iterator iter; + game_dll_t *pInfo; + for (iter=gamedll_list.begin(); iter!=gamedll_list.end(); iter++) + { + pInfo = (*iter); + if ((server = (IServerGameDLL *)((pInfo->factory)(iface, ret))) != NULL) + { + if ((gamedll_version = provider->TryServerGameDLL(iface)) != 0) + { + /* We have a match. Erase us from the list and save our info. */ + gamedll_list.erase(iter); + gamedll_info = *pInfo; + delete pInfo; + is_gamedll_loaded = true; + break; + } + /* :TODO: error otherwise? */ + } + } + + if (is_gamedll_loaded) + { + ClearGamedllList(); + InitMainStates(); + } + else + { + if (ret) + { + *ret = IFACE_FAILED; + } + return NULL; + } + } + else + { + /* wtf do we do... */ + /* :TODO: .. something a bit more intelligent? */ + provider->DisplayError("Engine requested unknown interface before GameDLL was known!\n"); + return NULL; + } + } + + /* If we got here, there's definitely a GameDLL */ + IFACE_MACRO(gamedll_info.factory, GameDLL); +} + +void ClearGamedllList() +{ + List::iterator iter; + + game_dll_t *pInfo; + for (iter = gamedll_list.begin(); iter != gamedll_list.end(); iter++) + { + pInfo = (*iter); + dlclose(pInfo->lib); + delete pInfo; + } + + gamedll_list.clear(); +} + +int LoadPluginsFromFile(const char *_file) +{ + FILE *fp; + int total = 0, skipped=0; + PluginId id; + bool already; + + fp = fopen(_file, "rt"); + if (!fp) + { + LogMessage("[META] Could not open plugins file %s\n", _file); + return -1; + } + + char buffer[255], error[255], full_path[255]; + const char *ptr, *ext, *file; + size_t length; + while (!feof(fp) && fgets(buffer, sizeof(buffer), fp) != NULL) + { + UTIL_TrimLeft(buffer); + UTIL_TrimRight(buffer); + + length = strlen(buffer); + if (!length) + { + continue; + } + + if (buffer[0] == '\0' || buffer[0] == ';' || strncmp(buffer, "//", 2) == 0) + { + continue; + } + + file = buffer; + if (buffer[0] == '"') + { + char *cptr = buffer; + file = ++cptr; + + while (*cptr) + { + if (*cptr == '"') + { + *cptr = '\0'; + break; + } + cptr++; + } + } + else + { + char *cptr = buffer; + while (*cptr) + { + if (isspace(*cptr)) + { + char *optr = cptr; + while (*cptr && isspace(*cptr)) + { + cptr++; + } + *optr = '\0'; + UTIL_TrimRight(cptr); + if (*cptr && isalpha(*cptr)) + { + g_PluginMngr.SetAlias(buffer, cptr); + file = cptr; + } + break; + } + cptr++; + } + } + if (!file[0]) + { + continue; + } + /* First find if it's an absolute path or not... */ + if (file[0] == '/' || strncmp(&(file[1]), ":\\", 2) == 0) + { + /* If we're in an absolute path, ignore our normal heuristics */ + id = g_PluginMngr.Load(file, Pl_File, already, error, sizeof(error)); + if (id < Pl_MinId || g_PluginMngr.FindById(id)->m_Status < Pl_Paused) + { + LogMessage("[META] Failed to load plugin %s. %s", buffer, error); + } + else + { + if (already) + { + skipped++; + } + else + { + total++; + } + } + } + else + { + /* Attempt to find a file extension */ + ptr = UTIL_GetExtension(file); + /* Add an extension if there's none there */ + if (!ptr) + { +#if defined WIN32 || defined _WIN32 + ext = ".dll"; +#else + ext = "_i486.so"; +#endif + } + else + { + ext = ""; + } + /* Format the new path */ + g_Metamod.PathFormat(full_path, sizeof(full_path), "%s/%s%s", mod_path.c_str(), file, ext); + id = g_PluginMngr.Load(full_path, Pl_File, already, error, sizeof(error)); + if (id < Pl_MinId || g_PluginMngr.FindById(id)->m_Status < Pl_Paused) + { + LogMessage("[META] Failed to load plugin %s. %s", buffer, error); + } + else + { + if (already) + { + skipped++; + } + else + { + total++; + } + } + } + } + fclose(fp); + + if (skipped) + { + LogMessage("[META] Loaded %d plugins from file (%d already loaded)", total, skipped); + } + else + { + LogMessage("[META] Loaded %d plugins from file.", total); + } + + return total; +} + +void InitializeVSP() +{ + size_t len; + char engine_file[PATH_SIZE]; + char engine_path[PATH_SIZE]; + char rel_path[PATH_SIZE * 2]; + + GetFileOfAddress(engine_factory, engine_file, sizeof(engine_file)); + + /* Chop off the "engine" file part */ + len = strlen(engine_file); + for (size_t i = len - 1; i >= 0 && i < len; i--) + { + if (engine_file[i] == '/' || engine_file[i] == '\\') + { + engine_file[i] = '\0'; + break; + } + } + abspath(engine_path, engine_file); + + const char *usepath = metamod_path.c_str(); + if (UTIL_Relatize(rel_path, sizeof(rel_path), engine_path, metamod_path.c_str())) + { + usepath = rel_path; + } + + char command[PATH_SIZE * 2]; + UTIL_Format(command, sizeof(command), "plugin_load \"%s\"\n", usepath); + provider->ServerCommand(command); +} + +/* Wrapper function. This is called when the GameDLL thinks it's using + * the engine's real engineFactory. + */ +void *EngineFactory(const char *iface, int *ret) +{ + IFACE_MACRO(engine_factory, Engine); +} + +/* Wrapper function. This is called when the GameDLL thinks it's using + * the engine's real physicsFactory. + */ +void *PhysicsFactory(const char *iface, int *ret) +{ + IFACE_MACRO(physics_factory, Physics); +} + +/* Wrapper function. This is called when the GameDLL thinks it's using + * the engine's real fileSystemFactory. + */ +void *FileSystemFactory(const char *iface, int *ret) +{ + IFACE_MACRO(filesystem_factory, FileSystem); +} + +void LogMessage(const char *msg, ...) +{ + va_list ap; + static char buffer[2048]; + + va_start(ap, msg); + size_t len = vsnprintf(buffer, sizeof(buffer) - 2, msg, ap); + va_end(ap); + + buffer[len++] = '\n'; + buffer[len] = '\0'; + + if (!provider->LogMessage(buffer)) + { + fprintf(stdout, "%s", buffer); + } +} + +bool Handler_DLLInit(CreateInterfaceFn engineFactory, CreateInterfaceFn physicsFactory, CreateInterfaceFn filesystemFactory, CGlobalVars *pGlobals) +{ + engine_factory = engineFactory; + filesystem_factory = filesystemFactory; + physics_factory = physicsFactory; + gpGlobals = pGlobals; + + g_GameDllPatch = SH_GET_CALLCLASS(server); + + provider->Notify_DLLInit_Pre(); + + metamod_version = provider->CreateConVar("metamod_version", + SOURCEMM_VERSION, + "Metamod:Source Version", + ConVarFlag_Notify|ConVarFlag_Replicated|ConVarFlag_SpOnly); + + mm_pluginsfile = provider->CreateConVar("mm_pluginsfile", +#if defined WIN32 || defined _WIN32 + "addons\\metamod\\metaplugins.ini", +#else + "addons/metamod/metaplugins.ini", +#endif + "Metamod:Source Plugins File", + ConVarFlag_SpOnly); + + provider->CreateCommand("meta", Command_Meta, "Metamod:Source Menu"); + provider->SetClientCommandHandler(Command_ClientMeta); + + const char *pluginFile = provider->GetCommandLineValue("mm_pluginsfile", NULL); + if (!pluginFile) + { + pluginFile = provider->GetConVarString(mm_pluginsfile); + } + + char full_path[260]; + g_Metamod.PathFormat(full_path, sizeof(full_path), "%s/%s", mod_path.c_str(), pluginFile); + + LoadPluginsFromFile(full_path); + + in_first_level = true; + + RETURN_META_VALUE(MRES_IGNORED, true); +} + +bool Handler_GameInit() +{ + if (is_game_init) + { + return true; + } + + if (vsp_load_requested) + { + InitializeVSP(); + } + + is_game_init = true; + + RETURN_META_VALUE(MRES_IGNORED, true); +} + +bool Handler_DLLInit_Post(CreateInterfaceFn engineFactory, CreateInterfaceFn physicsFactory, CreateInterfaceFn filesystemFactory, CGlobalVars *pGlobals) +{ + g_PluginMngr.SetAllLoaded(); + RETURN_META_VALUE(MRES_IGNORED, true); +} + +void Handler_DLLShutdown() +{ + /* Unload plugins */ + g_PluginMngr.UnloadAll(); + + SH_CALL(g_GameDllPatch, &IServerGameDLL::DLLShutdown)(); + + SH_RELEASE_CALLCLASS(g_GameDllPatch); + g_GameDllPatch = NULL; + + g_SourceHook.CompleteShutdown(); + + if (is_gamedll_loaded && gamedll_info.lib) + { + dlclose(gamedll_info.lib); + is_gamedll_loaded = false; + } + + RETURN_META(MRES_SUPERCEDE); +} + +void Handler_LevelShutdown(void) +{ + if (!in_first_level) + { + char full_path[255]; + g_Metamod.PathFormat(full_path, + sizeof(full_path), + "%s/%s", + mod_path.c_str(), + provider->GetConVarString(mm_pluginsfile)); + + LoadPluginsFromFile(full_path); + } + else + { + in_first_level = false; + } + + ITER_EVENT(OnLevelShutdown, ()); + + RETURN_META(MRES_IGNORED); +} + +bool Handler_LevelInit(char const *pMapName, char const *pMapEntities, char const *pOldLevel, char const *pLandmarkName, bool loadGame, bool background) +{ + ITER_EVENT(OnLevelInit, (pMapName, pMapEntities, pOldLevel, pLandmarkName, loadGame, background)); + + RETURN_META_VALUE(MRES_IGNORED, false); +} + +void MetamodSource::LogMsg(ISmmPlugin *pl, const char *msg, ...) +{ + va_list ap; + char buffer[2048]; + + va_start(ap, msg); + UTIL_FormatArgs(buffer, sizeof(buffer), msg, ap); + va_end(ap); + + LogMessage("[%s] %s", pl->GetLogTag(), buffer); +} + +CreateInterfaceFn MetamodSource::engineFactory(bool syn/* =true */) +{ + if (syn) + { + return EngineFactory; + } + + return engine_factory; +} + +CreateInterfaceFn MetamodSource::physicsFactory(bool syn/* =true */) +{ + if (syn) + { + return PhysicsFactory; + } + + return physics_factory; +} + +CreateInterfaceFn MetamodSource::fileSystemFactory(bool syn/* =true */) +{ + if (syn) + { + return FileSystemFactory; + } + + return filesystem_factory; +} + +CreateInterfaceFn MetamodSource::serverFactory(bool syn/* =true */) +{ + if (syn) + { + return CreateInterface; + } + + return gamedll_info.factory; +} + +CGlobalVars *MetamodSource::pGlobals() +{ + return gpGlobals; +} + +void MetamodSource::SetLastMetaReturn(META_RES res) +{ + last_meta_res = res; +} + +META_RES MetamodSource::GetLastMetaReturn() +{ + return last_meta_res; +} + +void MetamodSource::ConPrint(const char *str) +{ + provider->ConsolePrint(str); +} + +void MetamodSource::ConPrintf(const char *fmt, ...) +{ + va_list ap; + char buffer[2048]; + + va_start(ap, fmt); + UTIL_FormatArgs(buffer, sizeof(buffer), fmt, ap); + va_end(ap); + + provider->ConsolePrint(buffer); +} + +void MetamodSource::GetApiVersions(int &major, int &minor, int &plvers, int &plmin) +{ + major = SM_VERS_API_MAJOR; + minor = SM_VERS_API_MINOR; + plvers = PLAPI_VERSION; + plmin = PLAPI_MIN_VERSION; +} + +void MetamodSource::GetShVersions(int &shvers, int &shimpl) +{ + shvers = SH_IFACE_VERSION; + shimpl = SH_IMPL_VERSION; +} + +int MetamodSource::FormatIface(char iface[], unsigned int maxlength) +{ + int length = (int)strlen(iface); + int i; + int num = 0; + + for (i = length - 1; i >= 0; i--) + { + if (!isdigit(iface[i])) + { + if (i != length - 1) + { + num = 1; + } + break; + } + } + + if ( (num && ((int)maxlength <= length)) || (!num && ((int)maxlength <= length + 3)) ) + { + return -1; + } + + if (i != length - 1) + { + num = atoi(&(iface[++i])); + } + + num++; + + snprintf(&(iface[i]), 4, "%03d", num); + + return num; +} + +void *MetamodSource::InterfaceSearch(CreateInterfaceFn fn, const char *iface, int max, int *ret) +{ + char _if[256]; /* assume no interface goes beyond this */ + size_t len = strlen(iface); + int num = 0; + void *pf = NULL; + + if (max > 999) + { + max = 999; + } + + if (len + 4 > sizeof(_if)) + { + if (ret) + { + *ret = IFACE_FAILED; + } + return NULL; + } + + strcpy(_if, iface); + + do + { + if ((pf = (fn)(_if, ret)) != NULL) + { + break; + } + if (num > max) + { + break; + } + } while ((num = FormatIface(_if, len+1))); + + return pf; +} + +void *MetamodSource::VInterfaceMatch(CreateInterfaceFn fn, const char *iface, int min) +{ + char buffer[256]; /* assume no interface will go beyond this */ + size_t len = strlen(iface); + int ret; /* just in case something doesn't handle NULL properly */ + + if (len > sizeof(buffer) - 4) + { + return NULL; + } + + strcpy(buffer, iface); + + if (min != -1) + { + char *ptr = &buffer[len - 1]; + int digits = 0; + while (isdigit(*ptr) && digits <=3) + { + *ptr = '\0'; + digits++; + ptr--; + } + if (digits != 3) + { + /* for now, assume this is an error */ + strcpy(buffer, iface); + } + else + { + char num[4]; + min = (min == 0) ? 1 : min; + snprintf(num, sizeof(num), "%03d", min); + strcat(buffer, num); + } + } + + return InterfaceSearch(fn, buffer, IFACE_MAXNUM, &ret); +} + +const char *MetamodSource::GetBaseDir() +{ + return mod_path.c_str(); +} + +void MetamodSource::PathFormat(char *buffer, size_t len, const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + size_t mylen = UTIL_FormatArgs(buffer, len, fmt, ap); + va_end(ap); + + for (size_t i = 0; i < mylen; i++) + { + if (buffer[i] == ALT_SEP_CHAR) + { + buffer[i] = PATH_SEP_CHAR; + } + } +} + +void MetamodSource::ClientConPrintf(edict_t *client, const char *fmt, ...) +{ + va_list ap; + char buffer[2048]; + + va_start(ap, fmt); + UTIL_FormatArgs(buffer, sizeof(buffer), fmt, ap); + va_end(ap); + + provider->ClientConsolePrint(client, buffer); +} + +void MetamodSource::EnableVSPListener() +{ + if (is_game_init && !vsp_load_requested && !vsp_loaded) + { + InitializeVSP(); + } + + vsp_load_requested = true; +} + +int MetamodSource::GetVSPVersion() +{ + return vsp_version; +} + +int MetamodSource::GetGameDLLVersion() +{ + return gamedll_version; +} + +bool MetamodSource::RemotePrintingAvailable() +{ + return provider->IsRemotePrintingAvailable(); +} + +void *MetamodSource::MetaFactory(const char *iface, int *ret, PluginId *id) +{ + if (id) + { + *id = 0; + } + + if (!iface) + { + return NULL; + } + + /* First check ours... we get first chance! */ + if (strcmp(iface, MMIFACE_SOURCEHOOK) == 0) + { + if (ret) + { + *ret = IFACE_OK; + } + return static_cast(static_cast(&g_SourceHook)); + } + else if (strcmp(iface, MMIFACE_PLMANAGER) == 0) + { + if (ret) + { + *ret = IFACE_OK; + } + return static_cast(static_cast(&g_PluginMngr)); + } + + CPluginManager::CPlugin *pl; + List::iterator event; + IMetamodListener *api; + void *value; + + int subret = 0; + for (PluginIter iter = g_PluginMngr._begin(); + iter != g_PluginMngr._end(); + iter++) + { + pl = (*iter); + for (event = pl->m_Events.begin(); event != pl->m_Events.end(); event++) + { + api = (*event); + subret = IFACE_FAILED; + if ((value = api->OnMetamodQuery(iface, &subret)) != NULL) + { + if (ret) + { + *ret = subret; + } + if (id) + { + *id = pl->m_Id; + } + return value; + } + } + } + + if (ret) + { + *ret = IFACE_FAILED; + } + + return NULL; +} + +void MetamodSource::AddListener(ISmmPlugin *plugin, IMetamodListener *pListener) +{ + CPluginManager::CPlugin *pl = g_PluginMngr.FindByAPI(plugin); + + pl->m_Events.push_back(pListener); +} + +const char *MetamodSource::GetGameBinaryPath() +{ + return full_bin_path.c_str(); +} + +const char *MetamodSource::GetPluginsFile() +{ + return provider->GetConVarString(mm_pluginsfile); +} + +IConCommandBaseAccessor *MetamodSource::GetCvarBaseAccessor() +{ + return provider->GetConCommandBaseAccessor(); +} + +bool MetamodSource::RegisterConCmdBase(ISmmPlugin *plugin, ConCommandBase *pCommand) +{ + if (provider->IsConCommandBaseACommand(pCommand)) + { + g_PluginMngr.AddPluginCmd(plugin, pCommand); + } + else + { + g_PluginMngr.AddPluginCvar(plugin, pCommand); + } + + return provider->RegisterConCommandBase(pCommand); +} + +void MetamodSource::UnregisterConCmdBase(ISmmPlugin *plugin, ConCommandBase *pCommand) +{ + if (provider->IsConCommandBaseACommand(pCommand)) + { + g_PluginMngr.AddPluginCmd(plugin, pCommand); + } + else + { + g_PluginMngr.AddPluginCvar(plugin, pCommand); + } + + return provider->UnregisterConCommandBase(pCommand); +} + +int MetamodSource::GetUserMessageCount() +{ + return provider->GetUserMessageCount(); +} + +int MetamodSource::FindUserMessage(const char *name, int *size/* =NULL */) +{ + return provider->FindUserMessage(name, size); +} + +const char *MetamodSource::GetUserMessage(int index, int *size/* =NULL */) +{ + return provider->GetUserMessage(index, size); +} + +int MetamodSource::GetSourceEngineBuild() +{ + return engine_build; +} diff --git a/sourcemm/metamod.h b/sourcemm/metamod.h new file mode 100644 index 0000000..5f21669 --- /dev/null +++ b/sourcemm/metamod.h @@ -0,0 +1,88 @@ +/* ======== SourceMM ======== + * Copyright (C) 2004-2007 Metamod:Source Development Team + * No warranties of any kind + * + * License: zlib/libpng + * + * Author(s): David "BAILOPAN" Anderson + * ============================ + */ + +#ifndef _INCLUDE_SOURCEMM_H +#define _INCLUDE_SOURCEMM_H + +/** + * @brief SourceMM main functionality for GameDLL interception + * @file sourcemm.h + */ + +#include +#include +#include +#include +#include +#include "ISmmAPI.h" +#include "metamod_provider.h" +#include "svn_version.h" + +using namespace SourceMM; + +/** + * Versioning + * increase api_major when API breaks + * increase api_minor when new functions are added (non-breaking) + */ +#define SOURCEMM_VERSION SVN_FILE_VERSION_STRING +#define SOURCEMM_DATE __DATE__ +#define SM_VERS_API_MAJOR 1 //increase this on a breaking change +#define SM_VERS_API_MINOR 7 //increase this on a non-breaking API change + +class MetamodSource : public ISmmAPI +{ +public: + void LogMsg(ISmmPlugin *pl, const char *msg, ...); + CreateInterfaceFn engineFactory(bool syn=true); + CreateInterfaceFn physicsFactory(bool syn=true); + CreateInterfaceFn fileSystemFactory(bool syn=true); + CreateInterfaceFn serverFactory(bool syn=true); + CGlobalVars *pGlobals(); + void SetLastMetaReturn(META_RES res); + META_RES GetLastMetaReturn(); + IConCommandBaseAccessor *GetCvarBaseAccessor(); + bool RegisterConCmdBase(ISmmPlugin *plugin, ConCommandBase *pCommand); + void UnregisterConCmdBase(ISmmPlugin *plugin, ConCommandBase *pCommand); + void ConPrint(const char *str); + void ConPrintf(const char *fmt, ...); + bool RemotePrintingAvailable(); + void GetApiVersions(int &major, int &minor, int &plvers, int &plmin); + void GetShVersions(int &shvers, int &shimpl); + void AddListener(ISmmPlugin *plugin, IMetamodListener *pListener); + void *MetaFactory(const char *iface, int *ret, PluginId *id); + int FormatIface(char iface[], unsigned int maxlength); + void *InterfaceSearch(CreateInterfaceFn fn, const char *iface, int max, int *ret); + const char *GetBaseDir(); + void PathFormat(char *buffer, size_t len, const char *fmt, ...); + void ClientConPrintf(edict_t *client, const char *fmt, ...); + void *VInterfaceMatch(CreateInterfaceFn fn, const char *iface, int min=-1); + void EnableVSPListener(); + int GetGameDLLVersion(); + int GetUserMessageCount(); + int FindUserMessage(const char *name, int *size=NULL); + const char *GetUserMessage(int index, int *size=NULL); + int GetVSPVersion(); + int GetSourceEngineBuild(); +public: + const char *GetGameBinaryPath(); + const char *GetPluginsFile(); +}; + +void LogMessage(const char *msg, ...); +int LoadPluginsFromFile(const char *_file); + +extern PluginId g_PLID; +extern SourceHook::ISourceHook *g_SHPtr; +extern SourceHook::CSourceHookImpl g_SourceHook; +extern MetamodSource g_Metamod; +extern IMetamodSourceProvider *provider; + +#endif //_INCLUDE_SOURCEMM_H diff --git a/sourcemm/concommands.cpp b/sourcemm/metamod_console.cpp similarity index 60% rename from sourcemm/concommands.cpp rename to sourcemm/metamod_console.cpp index 0aa0313..1621e62 100644 --- a/sourcemm/concommands.cpp +++ b/sourcemm/metamod_console.cpp @@ -8,12 +8,19 @@ * ============================ */ +#if defined _DEBUG +#define DEBUG2 +#undef _DEBUG +#endif #include -#include "CSmmAPI.h" -#include "concommands.h" -#include "CPlugin.h" -#include "sh_string.h" -#include "sh_list.h" +#include "metamod.h" +#include "metamod_util.h" +#include "metamod_console.h" +#include "metamod_plugins.h" +#if defined DEBUG2 +#undef DEBUG2 +#define _DEBUG +#endif using namespace SourceMM; using namespace SourceHook; @@ -23,143 +30,16 @@ using namespace SourceHook; * @file concommands.cpp */ -CAlwaysRegisterableCommand g_EternalCommand; -SMConVarAccessor g_SMConVarAccessor; +#define CONMSG g_Metamod.ConPrintf +#define CLIENT_CONMSG g_Metamod.ClientConPrintf -bool SMConVarAccessor::RegisterConCommandBase(ConCommandBase *pCommand) +bool Command_Meta(edict_t *pEdict, IMetamodSourceCommandInfo *info) { - // Add the FCVAR_GAMEDLL flag - // => No crash on exit! - // UPDATE: Do _not_ add the FCVAR_GAMEDLL flag here, as it - // causes the command to be unusable on listenservers until you load a map - // We will set the FCVAR_GAMEDLL flag on all commands we have registered once we are being unloaded - //pCommand->AddFlags(FCVAR_GAMEDLL); - m_RegisteredCommands.push_back(pCommand); + unsigned int args = info->GetArgCount(); - pCommand->SetNext( NULL ); - g_Engine.icvar->RegisterConCommandBase(pCommand); - - return true; -} - -bool SMConVarAccessor::Register(ConCommandBase *pCommand) -{ - //simple, don't mark as part of sourcemm! - pCommand->SetNext( NULL ); - g_Engine.icvar->RegisterConCommandBase(pCommand); - - return true; -} - -void SMConVarAccessor::MarkCommandsAsGameDLL() -{ - for (List::iterator iter = m_RegisteredCommands.begin(); - iter != m_RegisteredCommands.end(); ++iter) + if (args >= 1) { - (*iter)->AddFlags(FCVAR_GAMEDLL); - } -} - -void SMConVarAccessor::Unregister(PluginId id, ConCommandBase *pCommand) -{ - /* Notify via IMetamodListener */ - PluginIter iter; - CPluginManager::CPlugin *pPlugin; - List::iterator event; - IMetamodListener *pML; - for (iter=g_PluginMngr._begin(); iter!=g_PluginMngr._end(); iter++) - { - pPlugin = (*iter); - if (pPlugin->m_Status < Pl_Paused) - { - continue; - } - /* Only valid for plugins >= 12 (v1:6, SourceMM 1.5) */ - if (pPlugin->m_API->GetApiVersion() < 12) - { - continue; - } - for (event=pPlugin->m_Events.begin(); - event!=pPlugin->m_Events.end(); - event++) - { - pML = (*event); - pML->OnUnlinkConCommandBase(id, pCommand); - } - } - - ICvar *cv = g_Engine.icvar; - ConCommandBase *ptr = cv->GetCommands(); - - if (ptr == pCommand) - { - //first in list - g_EternalCommand.BringToFront(); - g_EternalCommand.SetNext(const_cast(pCommand->GetNext())); - } else { - //find us and unregister us - ConCommandBase *pPrev = NULL; - while (ptr) - { - if (ptr == pCommand) - break; - pPrev = ptr; - ptr = const_cast(ptr->GetNext()); - } - if (pPrev && ptr == pCommand) - { - pPrev->SetNext(const_cast(pCommand->GetNext())); - } - } -} - -void SMConVarAccessor::UnregisterGameDLLCommands() -{ - ConCommandBase *begin = g_Engine.icvar->GetCommands(); - ConCommandBase *iter = begin; - ConCommandBase *prev = NULL; - while (iter) - { - // watch out for the ETERNAL COMMAND! - if (iter != &g_EternalCommand && iter->IsBitSet(FCVAR_GAMEDLL)) - { - // Remove it! - if (iter == begin) - { - g_EternalCommand.BringToFront(); - iter = const_cast(iter->GetNext()); - g_EternalCommand.SetNext(iter); - prev = &g_EternalCommand; - continue; - } - else - { - iter = const_cast(iter->GetNext()); - prev->SetNext(iter); - continue; - } - } - prev = iter; - iter = const_cast(iter->GetNext()); - } -} - -ConVar metamod_version("metamod_version", SOURCEMM_VERSION, FCVAR_REPLICATED | FCVAR_SPONLY | FCVAR_NOTIFY, "Metamod:Source Version"); -#if defined WIN32 || defined _WIN32 -ConVar mm_pluginsfile("mm_pluginsfile", "addons\\metamod\\metaplugins.ini", FCVAR_SPONLY, "Metamod:Source Plugins File"); -#else -ConVar mm_pluginsfile("mm_pluginsfile", "addons/metamod/metaplugins.ini", FCVAR_SPONLY, "Metamod:Source Plugins File"); -#endif - -CON_COMMAND(meta, "Metamod:Source Menu") -{ - IVEngineServer *e = g_Engine.engine; - - int args = e->Cmd_Argc(); - - if (args >= 2) - { - const char *command = e->Cmd_Argv(1); + const char *command = info->GetArg(1); if (strcmp(command, "credits") == 0) { CONMSG("Metamod:Source was developed by:\n"); @@ -169,57 +49,73 @@ CON_COMMAND(meta, "Metamod:Source Menu") CONMSG("For more information, see the official website\n"); CONMSG("http://www.sourcemm.net/\n"); - return; - } else if (strcmp(command, "version") == 0) { + return true; + } + else if (strcmp(command, "version") == 0) + { CONMSG("Metamod:Source version %s\n", SOURCEMM_VERSION); CONMSG("Compiled on: %s\n", SOURCEMM_DATE); CONMSG("Plugin interface version: %d:%d\n", PLAPI_VERSION, PLAPI_MIN_VERSION); CONMSG("SourceHook version: %d:%d\n", g_SourceHook.GetIfaceVersion(), g_SourceHook.GetImplVersion()); CONMSG("http://www.sourcemm.net/\n"); - return; - } else if (strcmp(command, "game") == 0) { + return true; + } + else if (strcmp(command, "game") == 0) + { CONMSG("GameDLL Information\n"); - CONMSG(" Description: %s\n", g_GameDll.pGameDLL->GetGameDescription()); - CONMSG(" Mod Path: %s\n", g_ModPath.c_str()); - CONMSG(" DLL Path: %s\n", g_BinPath.c_str()); - CONMSG(" Interface: ServerGameDLL%03d, ServerGameClients%03d\n", g_GameDllVersion, g_GameClientsVersion); + CONMSG(" Description: %s\n", provider->GetGameDescription()); + CONMSG(" Mod Path: %s\n", g_Metamod.GetBaseDir()); + CONMSG(" DLL Path: %s\n", g_Metamod.GetGameBinaryPath()); + CONMSG(" Interface: ServerGameDLL%03d\n", g_Metamod.GetGameDLLVersion()); // Display user messages - if (g_SmmAPI.MsgCacheSuccessful()) + int messages = g_Metamod.GetUserMessageCount(); + if (messages == -1) { const char *msgname; int msgsize; - int msgcount = g_SmmAPI.GetUserMessageCount(); - if (msgcount > 0) + if (messages > 0) { CONMSG(" User Messages: %-32.31s %-5s %-5s\n", "Name", "Index", "Size"); - for (int i = 0; i < msgcount; i++) + for (int i = 0; i < messages; i++) { - msgname = g_SmmAPI.GetUserMessage(i, &msgsize); + msgname = g_Metamod.GetUserMessage(i, &msgsize); CONMSG(" %-32.31s %-5d %-5d\n", msgname, i, msgsize); } - CONMSG(" %d user message%s in total\n", msgcount, (msgcount > 1) ? "s" : ""); - } else { + CONMSG(" %d user message%s in total\n", messages, (messages > 1) ? "s" : ""); + } + else + { CONMSG(" User Messages: None\n"); } - } else { + } + else + { CONMSG(" User Messages: Failed to get list of user messages\n"); } - return; - } else if (strcmp(command, "refresh") == 0) { + return true; + } + else if (strcmp(command, "refresh") == 0) + { char full_path[255]; - g_SmmAPI.PathFormat(full_path, sizeof(full_path), "%s/%s", g_ModPath.c_str(), GetPluginsFile()); + g_Metamod.PathFormat(full_path, + sizeof(full_path), + "%s/%s", + g_Metamod.GetBaseDir(), + g_Metamod.GetPluginsFile()); LoadPluginsFromFile(full_path); - return; - } else if (strcmp(command, "list") == 0) { + return true; + } + else if (strcmp(command, "list") == 0) + { CPluginManager::CPlugin *pl; ISmmPlugin *plapi; const char *plname; @@ -231,7 +127,7 @@ CON_COMMAND(meta, "Metamod:Source Menu") if (!plnum) { CONMSG("No plugins loaded.\n"); - return; + return true; } else { CONMSG("Listing %d plugin%s:\n", plnum, (plnum > 1) ? "s" : ""); } @@ -271,23 +167,27 @@ CON_COMMAND(meta, "Metamod:Source Menu") CONMSG("%s\n", buffer); } - return; - } else if (strcmp(command, "cmds") == 0) { - if (args >= 3) + return true; + } + else if (strcmp(command, "cmds") == 0) + { + if (args >= 2) { - int id = atoi(e->Cmd_Argv(2)); + int id = atoi(info->GetArg(2)); CPluginManager::CPlugin *pl = g_PluginMngr.FindById(id); if (!pl) { CONMSG("Plugin %d not found.\n", id); - return; + return true; } if (!pl->m_API) { CONMSG("Plugin %d is not loaded.\n", id); - } else { + } + else + { CONMSG("Console commands for %s:\n", pl->m_API->GetName()); List::iterator ci; size_t count = 0; @@ -298,27 +198,33 @@ CON_COMMAND(meta, "Metamod:Source Menu") CONMSG(" [%5d] %-s\n", count, (*ci)->GetName()); } } - } else { + } + else + { CONMSG("Usage: meta cmds \n"); } - return; - } else if (strcmp(command, "cvars") == 0) { - if (args >= 3) + return true; + } + else if (strcmp(command, "cvars") == 0) + { + if (args >= 2) { - int id = atoi(e->Cmd_Argv(2)); + int id = atoi(info->GetArg(2)); CPluginManager::CPlugin *pl = g_PluginMngr.FindById(id); if (!pl) { CONMSG("Plugin %d not found.\n", id); - return; + return true; } if (!pl->m_API) { CONMSG("Plugin %d is not loaded.\n", id); - } else { + } + else + { CONMSG("Registered cvars for %s:\n", pl->m_API->GetName()); List::iterator ci; size_t count = 0; @@ -329,38 +235,50 @@ CON_COMMAND(meta, "Metamod:Source Menu") CONMSG(" [%5d] %-s\n", count, (*ci)->GetName()); } } - } else { + } + else + { CONMSG("Usage: meta cvars \n"); } - return; - } else if (strcmp(command, "info") == 0) { - if (args >= 3) + return true; + } + else if (strcmp(command, "info") == 0) + { + if (args >= 2) { - int id = atoi(e->Cmd_Argv(2)); + int id = atoi(info->GetArg(2)); CPluginManager::CPlugin *pl = g_PluginMngr.FindById(id); if (!pl) { CONMSG("Plugin %d not found.\n", id); - return; + return true; } if (!pl->m_API) { CONMSG("Plugin %d is not loaded.\n", id); - } else { + } + else + { if (pl->m_Status == Pl_Paused) { CONMSG("Plugin %d is paused.\n", id); - } else if (pl->m_Status == Pl_Running) { + } + else if (pl->m_Status == Pl_Running) + { char run_msg[255]; bool run = false; if (pl->m_API && pl->m_API->QueryRunning(run_msg, sizeof(run_msg)-1)) + { run = true; + } if (run) { CONMSG("Plugin %d is running.\n", id); - } else { + } + else + { CONMSG("Plugin %d is stopped: %s\n", id, run_msg); } } @@ -373,57 +291,69 @@ CON_COMMAND(meta, "Metamod:Source Menu") } CONMSG("File: %s\n\n", pl->m_File.c_str()); - return; - } else { + return true; + } + else + { CONMSG("Usage: meta info \n"); - return; + return true; } - } else if (strcmp(command, "pause") == 0) { - if (args >= 3) + } + else if (strcmp(command, "pause") == 0) + { + if (args >= 2) { - int id = atoi(e->Cmd_Argv(2)); + int id = atoi(info->GetArg(2)); char error[255]; if (!g_PluginMngr.Pause(id, error, sizeof(error))) { CONMSG("Pause failed: %s\n", error); - return; + return true; } CONMSG("Plugin %d has been paused.\n", id); - return; - } else { + return true; + } + else + { CONMSG("Usage: meta pause \n"); - return; + return true; } - } else if (strcmp(command, "unpause") == 0) { - if (args >= 3) + } + else if (strcmp(command, "unpause") == 0) + { + if (args >= 2) { - int id = atoi(e->Cmd_Argv(2)); + int id = atoi(info->GetArg(2)); char error[255]; if (!g_PluginMngr.Unpause(id, error, sizeof(error))) { CONMSG("Unpause failed: %s\n", error); - return; + return true; } CONMSG("Plugin %d has been unpaused.\n", id); - return; - } else { + return true; + } + else + { CONMSG("Usage: meta unpause \n"); - return; + return true; } - } else if (strcmp(command, "load") == 0) { - if (args >= 3) + } + else if (strcmp(command, "load") == 0) + { + if (args >= 2) { - const char *file = e->Cmd_Argv(2); + const char *file = info->GetArg(2); char full_path[255]; const char *alias = g_PluginMngr.LookupAlias(file); @@ -434,15 +364,22 @@ CON_COMMAND(meta, "Metamod:Source Menu") if (file[0] == '/' || strcmp(&(file[1]), ":\\") == 0) { - g_SmmAPI.PathFormat(full_path, sizeof(full_path), "%s", file); - } else { + g_Metamod.PathFormat(full_path, sizeof(full_path), "%s", file); + } + else + { const char *ext = UTIL_GetExtension(file); #if defined WIN32 || defined _WIN32 ext = ext ? "" : ".dll"; #else ext = ext ? "" : "_i486.so"; #endif - g_SmmAPI.PathFormat(full_path, sizeof(full_path), "%s/%s%s", g_ModPath.c_str(), file, ext); + g_Metamod.PathFormat(full_path, + sizeof(full_path), + "%s/%s%s", + g_Metamod.GetBaseDir(), + file, + ext); } char error[255]={0}; @@ -454,7 +391,7 @@ CON_COMMAND(meta, "Metamod:Source Menu") if (!pl || id < Pl_MinId || (pl->m_Status < Pl_Paused)) { CONMSG("Failed to load plugin %s (%s).\n", file, error); - return; + return true; } if (!already) @@ -464,28 +401,34 @@ CON_COMMAND(meta, "Metamod:Source Menu") CONMSG("Plugin \"%s\" is already loaded as %d.\n", pl->m_API->GetName(), pl->m_Id); } - return; - } else { + return true; + } + else + { CONMSG("Usage: meta load \n"); - return; + return true; } - } else if ( (strcmp(command, "alias") == 0) || - (strcmp(command, "aliases") == 0) ) { - if (args >= 4) + } + else if ( (strcmp(command, "alias") == 0) || + (strcmp(command, "aliases") == 0) ) + { + if (args >= 3) { - const char *alias = e->Cmd_Argv(2); - const char *value = e->Cmd_Argv(3); + const char *alias = info->GetArg(2); + const char *value = info->GetArg(3); g_PluginMngr.SetAlias(alias, value); - if (value[0] == '\0') + if (value == NULL || value[0] == '\0') { CONMSG("Deleted alias: %s.\n", alias); } else { CONMSG("Set alias \"%s\" to: %s\n", alias, value); } - } else if (args >= 3) { - const char *alias = e->Cmd_Argv(2); + } + else if (args >= 2) + { + const char *alias = info->GetArg(2); const char *value = g_PluginMngr.LookupAlias(alias); if (value) { @@ -493,7 +436,9 @@ CON_COMMAND(meta, "Metamod:Source Menu") } else { CONMSG("Alias \"%s\" was not found.\n", alias); } - } else { + } + else + { List::iterator iter, end; CNameAlias *p; @@ -512,15 +457,19 @@ CON_COMMAND(meta, "Metamod:Source Menu") } CONMSG(" --- \n"); CONMSG("%d aliases total.\n", total); - } else { + } + else + { CONMSG("No aliases found.\n"); } } - return; - } else if (strcmp(command, "unload") == 0) { - if (args >= 3) + return true; + } + else if (strcmp(command, "unload") == 0) + { + if (args >= 2) { - const char *file = e->Cmd_Argv(2); + const char *file = info->GetArg(2); int id = atoi(file); char error[255]={0}; @@ -537,15 +486,22 @@ CON_COMMAND(meta, "Metamod:Source Menu") /* first check if it's a known filename */ if (file[0] == '/' || strcmp(&(file[1]), ":\\") == 0) { - g_SmmAPI.PathFormat(full_path, sizeof(full_path), "%s", file); - } else { + g_Metamod.PathFormat(full_path, sizeof(full_path), "%s", file); + } + else + { const char *ext = UTIL_GetExtension(file); #if defined WIN32 || defined _WIN32 ext = ext ? "" : ".dll"; #else ext = ext ? "" : "_i486.so"; #endif - g_SmmAPI.PathFormat(full_path, sizeof(full_path), "%s/%s%s", g_ModPath.c_str(), file, ext); + g_Metamod.PathFormat(full_path, + sizeof(full_path), + "%s/%s%s", + g_Metamod.GetBaseDir(), + file, + ext); } List::iterator iter, end; @@ -564,70 +520,82 @@ CON_COMMAND(meta, "Metamod:Source Menu") if (id == 0) { CONMSG("Plugin \"%s\" not found.\n", full_path); - return; + return true; } } if (!g_PluginMngr.Unload(id, false, error, sizeof(error))) { CONMSG("Unload failed: %s\n", error); - return; + return true; } CONMSG("Plugin %d unloaded.\n", id); - } else { + } + else + { CONMSG("Usage: meta unload \n"); } - return; - } else if (strcmp(command, "force_unload") == 0) { - if (args >= 3) + return true; + } + else if (strcmp(command, "force_unload") == 0) + { + if (args >= 2) { - int id = atoi(e->Cmd_Argv(2)); + int id = atoi(info->GetArg(2)); char error[255]={0}; if (!g_PluginMngr.Unload(id, false, error, sizeof(error))) { CONMSG("Force unload failed: %s\n", error); - return; + return true; } CONMSG("Plugin %d force unloaded.\n", id); - return; - } else { + return true; + } + else + { CONMSG("Usage: meta force_unload \n"); - return; + return true; } - } else if (strcmp(command, "clear") == 0) { + } + else if (strcmp(command, "clear") == 0) + { if (!g_PluginMngr.UnloadAll()) { CONMSG("One or more plugins resisted removal (cleaned anyway).\n"); - return; + return true; } CONMSG("All plugins unloaded.\n"); - return; - } else if (strcmp(command, "retry") == 0) { - if (args >= 3) + return true; + } + else if (strcmp(command, "retry") == 0) + { + if (args >= 2) { - int id = atoi(e->Cmd_Argv(2)); + int id = atoi(info->GetArg(2)); char error[255]; if (!g_PluginMngr.Retry(id, error, sizeof(error))) { CONMSG("Error reloading plugin: %s\n", error); - return; + return true; } CONMSG("Plugin %d successfully reloaded.\n", id); - return; - } else { + return true; + } + else + { CONMSG("Usage: meta retry \n"); - return; + return true; } } } @@ -650,66 +618,20 @@ CON_COMMAND(meta, "Metamod:Source Menu") CONMSG(" unload - Unload a loaded plugin\n"); CONMSG(" unpause - Unpause a paused plugin\n"); CONMSG(" version - Version information\n"); + + return true; } -CAlwaysRegisterableCommand::CAlwaysRegisterableCommand() +bool Command_ClientMeta(edict_t *client, IMetamodSourceCommandInfo *info) { - Create("", NULL, FCVAR_UNREGISTERED|FCVAR_GAMEDLL); - m_pICvar = NULL; -} - -bool CAlwaysRegisterableCommand::IsRegistered( void ) const -{ - return false; -} - -void CAlwaysRegisterableCommand::BringToFront() -{ - if (!m_pICvar) - m_pICvar = g_Engine.icvar; - - // First, let's try to find us! - ConCommandBase *pPtr = m_pICvar->GetCommands(); - - if (pPtr == this) - { - // We are already at the beginning; Nothing to do - return; - } - - while (pPtr) - { - if (pPtr == this && pPtr->IsCommand() && stricmp(GetName(), pPtr->GetName()) == 0) - break; - ConCommandBase *pPrev = NULL; - while (pPtr) - { - if (pPtr == this) - break; - pPrev = pPtr; - pPtr = const_cast(pPtr->GetNext()); - } - if (pPrev && pPtr == this) - { - pPrev->SetNext(m_pNext); // Remove us from the list - } - // Now, register us - SetNext(NULL); - m_pICvar->RegisterConCommandBase(this); - } -} - -void ClientCommand_handler(edict_t *client) -{ - IVEngineServer *e = g_Engine.engine; - const char *cmd = e->Cmd_Argv(0); + const char *cmd = info->GetArg(0); if (strcmp(cmd, "meta") == 0) { - int args = e->Cmd_Argc(); - if (args == 2) + unsigned int args = info->GetArgCount(); + if (args == 1) { - const char *subcmd = e->Cmd_Argv(1); + const char *subcmd = info->GetArg(1); if (strcmp(subcmd, "credits") == 0) { @@ -720,16 +642,20 @@ void ClientCommand_handler(edict_t *client) CLIENT_CONMSG(client, "For more information, see the official website\n"); CLIENT_CONMSG(client, "http://www.sourcemm.net/\n"); - RETURN_META(MRES_SUPERCEDE); - } else if(strcmp(subcmd, "version") == 0) { + return true; + } + else if(strcmp(subcmd, "version") == 0) + { CLIENT_CONMSG(client, "Metamod:Source version %s\n", SOURCEMM_VERSION); CLIENT_CONMSG(client, "Compiled on: %s\n", SOURCEMM_DATE); CLIENT_CONMSG(client, "Plugin interface version: %d:%d\n", PLAPI_VERSION, PLAPI_MIN_VERSION); CLIENT_CONMSG(client, "SourceHook version: %d:%d\n", g_SourceHook.GetIfaceVersion(), g_SourceHook.GetImplVersion()); CLIENT_CONMSG(client, "http://www.sourcemm.net/\n"); - RETURN_META(MRES_SUPERCEDE); - } else if(strcmp(subcmd, "list") == 0) { + return true; + } + else if(strcmp(subcmd, "list") == 0) + { CPluginManager::CPlugin *pl; ISmmPlugin *plapi; const char *plname; @@ -773,7 +699,7 @@ void ClientCommand_handler(edict_t *client) CLIENT_CONMSG(client, "No active plugins loaded.\n"); } - RETURN_META(MRES_SUPERCEDE); + return true; } } @@ -783,13 +709,8 @@ void ClientCommand_handler(edict_t *client) CLIENT_CONMSG(client, " list - List plugins\n"); CLIENT_CONMSG(client, " version - Version information\n"); - RETURN_META(MRES_SUPERCEDE); + return true; } - RETURN_META(MRES_IGNORED); -} - -const char *GetPluginsFile() -{ - return mm_pluginsfile.GetString(); + return false; } diff --git a/sourcemm/metamod_console.h b/sourcemm/metamod_console.h new file mode 100644 index 0000000..4410bfd --- /dev/null +++ b/sourcemm/metamod_console.h @@ -0,0 +1,19 @@ +/* ======== SourceMM ======== + * Copyright (C) 2004-2007 Metamod:Source Development Team + * No warranties of any kind + * + * License: zlib/libpng + * + * Author(s): David "BAILOPAN" Anderson + * ============================ + */ + +#ifndef _INCLUDE_CONCOMMANDS_H +#define _INCLUDE_CONCOMMANDS_H + +#include "metamod_provider.h" + +bool Command_Meta(edict_t *pEdict, IMetamodSourceCommandInfo *info); +bool Command_ClientMeta(edict_t *client, IMetamodSourceCommandInfo *info); + +#endif //_INCLUDE_CONCOMMANDS_H diff --git a/sourcemm/CPlugin.h b/sourcemm/metamod_plugins.h similarity index 98% rename from sourcemm/CPlugin.h rename to sourcemm/metamod_plugins.h index b9b0784..aaec549 100644 --- a/sourcemm/CPlugin.h +++ b/sourcemm/metamod_plugins.h @@ -18,11 +18,10 @@ #include #include -#include "convar_smm.h" +#include +#include #include "IPluginManager.h" #include "oslink.h" -#include "sh_list.h" -#include "sh_string.h" /** * History of plugin versions: (M=min, C=current) diff --git a/sourcemm/util.cpp b/sourcemm/metamod_util.cpp similarity index 99% rename from sourcemm/util.cpp rename to sourcemm/metamod_util.cpp index 3e50621..f9ca9ad 100644 --- a/sourcemm/util.cpp +++ b/sourcemm/metamod_util.cpp @@ -11,7 +11,7 @@ #include #include #include -#include "util.h" +#include "metamod_util.h" #include "oslink.h" /** diff --git a/sourcemm/util.h b/sourcemm/metamod_util.h similarity index 100% rename from sourcemm/util.h rename to sourcemm/metamod_util.h diff --git a/sourcemm/msvc8/sourcemm.vcproj b/sourcemm/msvc8/sourcemm.vcproj index 615c8d1..750ab85 100644 --- a/sourcemm/msvc8/sourcemm.vcproj +++ b/sourcemm/msvc8/sourcemm.vcproj @@ -41,6 +41,7 @@ + + - - - - - - - - - + + - - - - - - - - + + &1 | cut -b1) - -CFLAGS += -D_LINUX -DNDEBUG -Dstricmp=strcasecmp -D_stricmp=strcasecmp -D_strnicmp=strncasecmp -Dstrnicmp=strncasecmp -D_snprintf=snprintf -D_vsnprintf=vsnprintf -D_alloca=alloca -Dstrcmpi=strcasecmp -Wall -Wno-non-virtual-dtor -Werror -fPIC -fno-exceptions -fno-rtti -msse - -ifeq "$(GCC_VERSION)" "4" - CFLAGS += $(GCC4_FLAGS) -endif - -OBJ_LINUX := $(OBJECTS:%.cpp=$(BIN_DIR)/%.o) - -$(BIN_DIR)/%.o: %.cpp - $(CPP) $(INCLUDE) $(CFLAGS) -o $@ -c $< - -all: - mkdir -p $(BIN_DIR) - ln -sf $(SRCDS)/bin/vstdlib_i486.so vstdlib_i486.so - ln -sf $(SRCDS)/bin/tier0_i486.so tier0_i486.so - $(MAKE) sourcemm - rm -rf $(BINARY) - ln -sf $(BIN_DIR)/$(BINARY) $(BINARY) - -sourcemm: $(OBJ_LINUX) - $(CPP) $(INCLUDE) $(CFLAGS) $(OBJ_LINUX) $(LINK) -shared -ldl -lm -o$(BIN_DIR)/$(BINARY) - -debug: - $(MAKE) all DEBUG=true - -default: all - -clean: - rm -rf Release/*.o - rm -rf Release/$(BINARY) - rm -rf Debug/*.o - rm -rf Debug/$(BINARY) diff --git a/sourcemm/sample_mm/SamplePlugin.cpp b/sourcemm/sample_mm/SamplePlugin.cpp deleted file mode 100644 index 62c874e..0000000 --- a/sourcemm/sample_mm/SamplePlugin.cpp +++ /dev/null @@ -1,237 +0,0 @@ -/* ======== sample_mm ======== - * Copyright (C) 2004-2007 Metamod:Source Development Team - * No warranties of any kind - * - * License: zlib/libpng - * - * Author(s): David "BAILOPAN" Anderson - * ============================ - */ - -#include -#include "SamplePlugin.h" -#include "cvars.h" - -//Declare the hooks we will be using in this file. Hooking will not compile without these. -//The macro naming scheme is SH_DECL_HOOKn[_void]. -//If you have 5 parameters, it would be HOOK5. If the function is void, add _void. -//It stands for "SourceHook, Declare Hook". -SH_DECL_HOOK6(IServerGameDLL, LevelInit, SH_NOATTRIB, 0, bool, char const *, char const *, char const *, char const *, bool, bool); -SH_DECL_HOOK3_void(IServerGameDLL, ServerActivate, SH_NOATTRIB, 0, edict_t *, int, int); -SH_DECL_HOOK1_void(IServerGameDLL, GameFrame, SH_NOATTRIB, 0, bool); -SH_DECL_HOOK0_void(IServerGameDLL, LevelShutdown, SH_NOATTRIB, 0); -SH_DECL_HOOK2_void(IServerGameClients, ClientActive, SH_NOATTRIB, 0, edict_t *, bool); -SH_DECL_HOOK1_void(IServerGameClients, ClientDisconnect, SH_NOATTRIB, 0, edict_t *); -SH_DECL_HOOK2_void(IServerGameClients, ClientPutInServer, SH_NOATTRIB, 0, edict_t *, char const *); -SH_DECL_HOOK1_void(IServerGameClients, SetCommandClient, SH_NOATTRIB, 0, int); -SH_DECL_HOOK1_void(IServerGameClients, ClientSettingsChanged, SH_NOATTRIB, 0, edict_t *); -SH_DECL_HOOK5(IServerGameClients, ClientConnect, SH_NOATTRIB, 0, bool, edict_t *, const char*, const char *, char *, int); -SH_DECL_HOOK1_void(IServerGameClients, ClientCommand, SH_NOATTRIB, 0, edict_t *); -SH_DECL_HOOK2(IGameEventManager2, FireEvent, SH_NOATTRIB, 0, bool, IGameEvent *, bool); - -SamplePlugin g_SamplePlugin; -MyListener g_Listener; - -PLUGIN_EXPOSE(SamplePlugin, g_SamplePlugin); - -bool SamplePlugin::LevelInit(const char *pMapName, const char *pMapEntities, const char *pOldLevel, const char *pLandmarkName, bool loadGame, bool background) -{ - META_LOG(g_PLAPI, "LevelInit() called: pMapName=%s", pMapName); - RETURN_META_VALUE(MRES_IGNORED, true); -} - -void SamplePlugin::OnLevelShutdown() -{ - META_LOG(g_PLAPI, "OnLevelShutdown() called from listener"); -} - -void SamplePlugin::ServerActivate(edict_t *pEdictList, int edictCount, int clientMax) -{ - META_LOG(g_PLAPI, "ServerActivate() called: edictCount=%d, clientMax=%d", edictCount, clientMax); - RETURN_META(MRES_IGNORED); -} - -void SamplePlugin::GameFrame(bool simulating) -{ - //don't log this, it just pumps stuff to the screen ;] - //META_LOG(g_PLAPI, "GameFrame() called: simulating=%d", simulating); - RETURN_META(MRES_IGNORED); -} - -void SamplePlugin::LevelShutdown( void ) -{ - META_LOG(g_PLAPI, "LevelShutdown() called"); - RETURN_META(MRES_IGNORED); -} - -void SamplePlugin::ClientActive(edict_t *pEntity, bool bLoadGame) -{ - META_LOG(g_PLAPI, "ClientActive called: pEntity=%d", pEntity ? m_Engine->IndexOfEdict(pEntity) : 0); - RETURN_META(MRES_IGNORED); -} - -void SamplePlugin::ClientDisconnect(edict_t *pEntity) -{ - META_LOG(g_PLAPI, "ClientDisconnect called: pEntity=%d", pEntity ? m_Engine->IndexOfEdict(pEntity) : 0); - RETURN_META(MRES_IGNORED); -} - -void SamplePlugin::ClientPutInServer(edict_t *pEntity, char const *playername) -{ - META_LOG(g_PLAPI, "ClientPutInServer called: pEntity=%d, playername=%s", pEntity ? m_Engine->IndexOfEdict(pEntity) : 0, playername); - RETURN_META(MRES_IGNORED); -} - -void SamplePlugin::SetCommandClient(int index) -{ - META_LOG(g_PLAPI, "SetCommandClient() called: index=%d", index); - RETURN_META(MRES_IGNORED); -} - -void SamplePlugin::ClientSettingsChanged(edict_t *pEdict) -{ - META_LOG(g_PLAPI, "ClientSettingsChanged called: pEdict=%d", pEdict ? m_Engine->IndexOfEdict(pEdict) : 0); - RETURN_META(MRES_IGNORED); -} - -bool SamplePlugin::ClientConnect(edict_t *pEntity, const char *pszName, const char *pszAddress, char *reject, int maxrejectlen) -{ - META_LOG(g_PLAPI, "ClientConnect called: pEntity=%d, pszName=%s, pszAddress=%s", pEntity ? m_Engine->IndexOfEdict(pEntity) : 0, pszName, pszAddress); - RETURN_META_VALUE(MRES_IGNORED, true); -} - -void SamplePlugin::ClientCommand(edict_t *pEntity) -{ - META_LOG(g_PLAPI, "ClientCommand called: pEntity=%d (commandString=%s)", pEntity ? m_Engine->IndexOfEdict(pEntity) : 0, m_Engine->Cmd_Args() ? m_Engine->Cmd_Args() : ""); - RETURN_META(MRES_IGNORED); -} - -bool FireEvent_Handler(IGameEvent *event, bool bDontBroadcast) -{ - if (!event || !event->GetName()) - RETURN_META_VALUE(MRES_IGNORED, false); - - /** - * Note that this will only fire on game events that are already being listened to. - * For events that are not firing (such as item_pickup), you must actually - * register an event listener in the event manager. This hook is provided - * as an example for non-eiface hooks only. - */ - - const char *name = event->GetName(); - - META_LOG(g_PLAPI, "FireGameEvent called: name=%s", name); - - RETURN_META_VALUE(MRES_IGNORED, true); -} - -bool SamplePlugin::Load(PluginId id, ISmmAPI *ismm, char *error, size_t maxlen, bool late) -{ - PLUGIN_SAVEVARS(); - - GET_V_IFACE_ANY(serverFactory, m_ServerDll, IServerGameDLL, INTERFACEVERSION_SERVERGAMEDLL); - GET_V_IFACE_CURRENT(engineFactory, m_Engine, IVEngineServer, INTERFACEVERSION_VENGINESERVER); - GET_V_IFACE_ANY(serverFactory, m_ServerClients, IServerGameClients, INTERFACEVERSION_SERVERGAMECLIENTS); - GET_V_IFACE_CURRENT(engineFactory, m_GameEventManager, IGameEventManager2, INTERFACEVERSION_GAMEEVENTSMANAGER2); - - META_LOG(g_PLAPI, "Starting plugin.\n"); - - ismm->AddListener(this, &g_Listener); - - //Init our cvars/concmds - ConCommandBaseMgr::OneTimeInit(&g_Accessor); - - //We're hooking the following things as POST, in order to seem like Server Plugins. - //However, I don't actually know if Valve has done server plugins as POST or not. - //Change the last parameter to 'false' in order to change this to PRE. - //SH_ADD_HOOK_MEMFUNC means "SourceHook, Add Hook, Member Function". - - //Hook LevelInit to our function - SH_ADD_HOOK_MEMFUNC(IServerGameDLL, LevelInit, m_ServerDll, &g_SamplePlugin, &SamplePlugin::LevelInit, true); - //Hook ServerActivate to our function - SH_ADD_HOOK_MEMFUNC(IServerGameDLL, ServerActivate, m_ServerDll, &g_SamplePlugin, &SamplePlugin::ServerActivate, true); - //Hook GameFrame to our function - SH_ADD_HOOK_MEMFUNC(IServerGameDLL, GameFrame, m_ServerDll, &g_SamplePlugin, &SamplePlugin::GameFrame, true); - //Hook LevelShutdown to our function -- this makes more sense as pre I guess - SH_ADD_HOOK_MEMFUNC(IServerGameDLL, LevelShutdown, m_ServerDll, &g_SamplePlugin, &SamplePlugin::LevelShutdown, false); - //Hook ClientActivate to our function - SH_ADD_HOOK_MEMFUNC(IServerGameClients, ClientActive, m_ServerClients, &g_SamplePlugin, &SamplePlugin::ClientActive, true); - //Hook ClientDisconnect to our function - SH_ADD_HOOK_MEMFUNC(IServerGameClients, ClientDisconnect, m_ServerClients, &g_SamplePlugin, &SamplePlugin::ClientDisconnect, true); - //Hook ClientPutInServer to our function - SH_ADD_HOOK_MEMFUNC(IServerGameClients, ClientPutInServer, m_ServerClients, &g_SamplePlugin, &SamplePlugin::ClientPutInServer, true); - //Hook SetCommandClient to our function - SH_ADD_HOOK_MEMFUNC(IServerGameClients, SetCommandClient, m_ServerClients, &g_SamplePlugin, &SamplePlugin::SetCommandClient, true); - //Hook ClientSettingsChanged to our function - SH_ADD_HOOK_MEMFUNC(IServerGameClients, ClientSettingsChanged, m_ServerClients, &g_SamplePlugin, &SamplePlugin::ClientSettingsChanged, true); - - //The following functions are pre handled, because that's how they are in IServerPluginCallbacks - - //Hook ClientConnect to our function - SH_ADD_HOOK_MEMFUNC(IServerGameClients, ClientConnect, m_ServerClients, &g_SamplePlugin, &SamplePlugin::ClientConnect, false); - //Hook ClientCommand to our function - SH_ADD_HOOK_MEMFUNC(IServerGameClients, ClientCommand, m_ServerClients, &g_SamplePlugin, &SamplePlugin::ClientCommand, false); - - //This hook is a static hook, no member function - SH_ADD_HOOK_STATICFUNC(IGameEventManager2, FireEvent, m_GameEventManager, FireEvent_Handler, false); - - //Get the call class for IVServerEngine so we can safely call functions without - // invoking their hooks (when needed). - m_Engine_CC = SH_GET_CALLCLASS(m_Engine); - - SH_CALL(m_Engine_CC, &IVEngineServer::LogPrint)("All hooks started!\n"); - - return true; -} - -bool SamplePlugin::Unload(char *error, size_t maxlen) -{ - //IT IS CRUCIAL THAT YOU REMOVE CVARS. - //As of Metamod:Source 1.00-RC2, it will automatically remove them for you. - //But this is only if you've registered them correctly! - - //Make sure we remove any hooks we did... this may not be necessary since - //SourceHook is capable of unloading plugins' hooks itself, but just to be safe. - - SH_REMOVE_HOOK_STATICFUNC(IGameEventManager2, FireEvent, m_GameEventManager, FireEvent_Handler, false); - SH_REMOVE_HOOK_MEMFUNC(IServerGameDLL, LevelInit, m_ServerDll, &g_SamplePlugin, &SamplePlugin::LevelInit, true); - SH_REMOVE_HOOK_MEMFUNC(IServerGameDLL, ServerActivate, m_ServerDll, &g_SamplePlugin, &SamplePlugin::ServerActivate, true); - SH_REMOVE_HOOK_MEMFUNC(IServerGameDLL, GameFrame, m_ServerDll, &g_SamplePlugin, &SamplePlugin::GameFrame, true); - SH_REMOVE_HOOK_MEMFUNC(IServerGameDLL, LevelShutdown, m_ServerDll, &g_SamplePlugin, &SamplePlugin::LevelShutdown, false); - SH_REMOVE_HOOK_MEMFUNC(IServerGameClients, ClientActive, m_ServerClients, &g_SamplePlugin, &SamplePlugin::ClientActive, true); - SH_REMOVE_HOOK_MEMFUNC(IServerGameClients, ClientDisconnect, m_ServerClients, &g_SamplePlugin, &SamplePlugin::ClientDisconnect, true); - SH_REMOVE_HOOK_MEMFUNC(IServerGameClients, ClientPutInServer, m_ServerClients, &g_SamplePlugin, &SamplePlugin::ClientPutInServer, true); - SH_REMOVE_HOOK_MEMFUNC(IServerGameClients, SetCommandClient, m_ServerClients, &g_SamplePlugin, &SamplePlugin::SetCommandClient, true); - SH_REMOVE_HOOK_MEMFUNC(IServerGameClients, ClientSettingsChanged, m_ServerClients, &g_SamplePlugin, &SamplePlugin::ClientSettingsChanged, true); - SH_REMOVE_HOOK_MEMFUNC(IServerGameClients, ClientConnect, m_ServerClients, &g_SamplePlugin, &SamplePlugin::ClientConnect, false); - SH_REMOVE_HOOK_MEMFUNC(IServerGameClients, ClientCommand, m_ServerClients, &g_SamplePlugin, &SamplePlugin::ClientCommand, false); - - //this, sourcehook does not keep track of. we must do this. - SH_RELEASE_CALLCLASS(m_Engine_CC); - - return true; -} - -void SamplePlugin::AllPluginsLoaded() -{ - //we don't really need this for anything other than interplugin communication - //and that's not used in this plugin. - //If we really wanted, we could override the factories so other plugins can request - // interfaces we make. In this callback, the plugin could be assured that either - // the interfaces it requires were either loaded in another plugin or not. -} - -void *MyListener::OnMetamodQuery(const char *iface, int *ret) -{ - if (strcmp(iface, "SamplePlugin")==0) - { - if (ret) - *ret = IFACE_OK; - return static_cast(&g_SamplePlugin); - } - - if (ret) - *ret = IFACE_FAILED; - - return NULL; -} diff --git a/sourcemm/sample_mm/SamplePlugin.h b/sourcemm/sample_mm/SamplePlugin.h deleted file mode 100644 index 74f5af1..0000000 --- a/sourcemm/sample_mm/SamplePlugin.h +++ /dev/null @@ -1,132 +0,0 @@ -/* ======== sample_mm ======== - * Copyright (C) 2004-2007 Metamod:Source Development Team - * No warranties of any kind - * - * License: zlib/libpng - * - * Author(s): David "BAILOPAN" Anderson - * ============================ - */ - -#ifndef _INCLUDE_SAMPLEPLUGIN_H -#define _INCLUDE_SAMPLEPLUGIN_H - -#include -#include -#include - -#define SAMPLE_VERSION "1.10" - -class SamplePlugin : public ISmmPlugin, public IMetamodListener -{ -public: - bool Load(PluginId id, ISmmAPI *ismm, char *error, size_t maxlen, bool late); - bool Unload(char *error, size_t maxlen); - void AllPluginsLoaded(); - bool Pause(char *error, size_t maxlen) - { - return true; - } - bool Unpause(char *error, size_t maxlen) - { - return true; - } -public: - int GetApiVersion() { return PLAPI_VERSION; } -public: - const char *GetAuthor() - { - return "BAILOPAN"; - } - const char *GetName() - { - return "Sample Plugin"; - } - const char *GetDescription() - { - return "Sample plugin that hooks basic things"; - } - const char *GetURL() - { - return "http://www.sourcemm.net/"; - } - const char *GetLicense() - { - return "zlib/libpng"; - } - const char *GetVersion() - { - return SAMPLE_VERSION; - } - const char *GetDate() - { - return __DATE__; - } - const char *GetLogTag() - { - return "SAMPLE"; - } -public: - //These functions are from IServerPluginCallbacks - //Note, the parameters might be a little different to match the actual calls! - - //Called on LevelInit. Server plugins only have pMapName - bool LevelInit(const char *pMapName, char const *pMapEntities, char const *pOldLevel, char const *pLandmarkName, bool loadGame, bool background); - - //Called on ServerActivate. Same definition as server plugins - void ServerActivate(edict_t *pEdictList, int edictCount, int clientMax); - - //Called on a game tick. Same definition as server plugins - void GameFrame(bool simulating); - - //Called on level shutdown. Same definition as server plugins - void LevelShutdown(void); - - //Client is activate (whatever that means). We get an extra parameter... - // "If bLoadGame is true, don't spawn the player because its state is already setup." - void ClientActive(edict_t *pEntity, bool bLoadGame); - - //Client disconnects - same as server plugins - void ClientDisconnect(edict_t *pEntity); - - //Client is put in server - same as server plugins - void ClientPutInServer(edict_t *pEntity, char const *playername); - - //Sets the client index - same as server plugins - void SetCommandClient(int index); - - //Called on client settings changed (duh) - same as server plugins - void ClientSettingsChanged(edict_t *pEdict); - - //Called on client connect. Unlike server plugins, we return whether the - // connection is allowed rather than set it through a pointer in the first parameter. - // You can still supercede the GameDLL through RETURN_META_VALUE(MRES_SUPERCEDE, true/false) - bool ClientConnect(edict_t *pEntity, const char *pszName, const char *pszAddress, char *reject, int maxrejectlen); - - //Called when a client uses a command. Unlike server plugins, it's void. - // You can still supercede the gamedll through RETURN_META(MRES_SUPERCEDE). - void ClientCommand(edict_t *pEntity); - - //From IMetamodListener - virtual void OnLevelShutdown(); - -private: - IGameEventManager2 *m_GameEventManager; - IVEngineServer *m_Engine; - IServerGameDLL *m_ServerDll; - IServerGameClients *m_ServerClients; - SourceHook::CallClass *m_Engine_CC; -}; - -class MyListener : public IMetamodListener -{ -public: - virtual void *OnMetamodQuery(const char *iface, int *ret); -}; - -extern SamplePlugin g_SamplePlugin; -PLUGIN_GLOBALVARS(); - -bool FireEvent_Handler(IGameEvent *event, bool bDontBroadcast); - -#endif //_INCLUDE_SAMPLEPLUGIN_H diff --git a/sourcemm/sample_mm/cvars.cpp b/sourcemm/sample_mm/cvars.cpp deleted file mode 100644 index 4a6c16a..0000000 --- a/sourcemm/sample_mm/cvars.cpp +++ /dev/null @@ -1,27 +0,0 @@ -/* ======== sample_mm ======== - * Copyright (C) 2004-2007 Metamod:Source Development Team - * No warranties of any kind - * - * License: zlib/libpng - * - * Author(s): David "BAILOPAN" Anderson - * ============================ - */ - -#include "SamplePlugin.h" -#include "cvars.h" - -SampleAccessor g_Accessor; - -ConVar g_MyConVar("sample_version", SAMPLE_VERSION, FCVAR_SPONLY, "Sample Plugin version"); - -bool SampleAccessor::RegisterConCommandBase(ConCommandBase *pVar) -{ - //this will work on any type of concmd! - return META_REGCVAR(pVar); -} - -CON_COMMAND(sample_cmd, "Sample Plugin command") -{ - META_LOG(g_PLAPI, "This sentence is in Spanish when you're not looking."); -} diff --git a/sourcemm/sample_mm/cvars.h b/sourcemm/sample_mm/cvars.h deleted file mode 100644 index 9bc6286..0000000 --- a/sourcemm/sample_mm/cvars.h +++ /dev/null @@ -1,24 +0,0 @@ -/* ======== sample_mm ======== - * Copyright (C) 2004-2007 Metamod:Source Development Team - * No warranties of any kind - * - * License: zlib/libpng - * - * Author(s): David "BAILOPAN" Anderson - * ============================ - */ - -#ifndef _INCLUDE_CVARS_H -#define _INCLUDE_CVARS_H - -#include - -class SampleAccessor : public IConCommandBaseAccessor -{ -public: - virtual bool RegisterConCommandBase(ConCommandBase *pVar); -}; - -extern SampleAccessor g_Accessor; - -#endif //_INCLUDE_CVARS_H diff --git a/sourcemm/sample_mm/msvc8/sample_mm.sln b/sourcemm/sample_mm/msvc8/sample_mm.sln deleted file mode 100644 index df4b2fb..0000000 --- a/sourcemm/sample_mm/msvc8/sample_mm.sln +++ /dev/null @@ -1,20 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 9.00 -# Visual Studio 2005 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sample_mm", "sample_mm.vcproj", "{FAFF34FB-FE14-47B5-81BD-70D237392FB2}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Release|Win32 = Release|Win32 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {FAFF34FB-FE14-47B5-81BD-70D237392FB2}.Debug|Win32.ActiveCfg = Debug|Win32 - {FAFF34FB-FE14-47B5-81BD-70D237392FB2}.Debug|Win32.Build.0 = Debug|Win32 - {FAFF34FB-FE14-47B5-81BD-70D237392FB2}.Release|Win32.ActiveCfg = Release|Win32 - {FAFF34FB-FE14-47B5-81BD-70D237392FB2}.Release|Win32.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/sourcemm/sample_mm/msvc8/sample_mm.vcproj b/sourcemm/sample_mm/msvc8/sample_mm.vcproj deleted file mode 100644 index 9886076..0000000 --- a/sourcemm/sample_mm/msvc8/sample_mm.vcproj +++ /dev/null @@ -1,222 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/sourcemm/sourcemm.cpp b/sourcemm/sourcemm.cpp deleted file mode 100644 index 477ef17..0000000 --- a/sourcemm/sourcemm.cpp +++ /dev/null @@ -1,710 +0,0 @@ -/* ======== SourceMM ======== - * Copyright (C) 2004-2007 Metamod:Source Development Team - * No warranties of any kind - * - * License: zlib/libpng - * - * Author(s): David "BAILOPAN" Anderson - * Contributor(s): Scott "Damaged Soul" Ehlert - * : Pavol "PM OnoTo" Marko - * ============================ - */ - -#include -#include -#include -#include "sourcemm.h" -#include "concommands.h" -#include "CSmmAPI.h" -#include "CPlugin.h" -#include "util.h" -#include "vsp_listener.h" - -using namespace SourceMM; - -/** - * @brief Implementation of main SourceMM GameDLL functionality - * @file sourcemm.cpp - */ - -#undef CommandLine -DLL_IMPORT ICommandLine *CommandLine(); - -SH_DECL_HOOK4(IServerGameDLL, DLLInit, SH_NOATTRIB, false, bool, CreateInterfaceFn, CreateInterfaceFn, CreateInterfaceFn, CGlobalVars *); -SH_DECL_HOOK0_void(IServerGameDLL, DLLShutdown, SH_NOATTRIB, false); -SH_DECL_HOOK0_void(IServerGameDLL, LevelShutdown, SH_NOATTRIB, false); -SH_DECL_HOOK6(IServerGameDLL, LevelInit, SH_NOATTRIB, false, bool, const char *, const char *, const char *, const char *, bool, bool); -SH_DECL_HOOK1_void(IServerGameClients, ClientCommand, SH_NOATTRIB, 0, edict_t *); -SH_DECL_HOOK0(IServerGameDLL, GameInit, SH_NOATTRIB, false, bool); - -bool DLLInit(CreateInterfaceFn engineFactory, CreateInterfaceFn physicsFactory, CreateInterfaceFn filesystemFactory, CGlobalVars *pGlobals); -bool DLLInit_Post(CreateInterfaceFn engineFactory, CreateInterfaceFn physicsFactory, CreateInterfaceFn filesystemFactory, CGlobalVars *pGlobals); -void DLLShutdown_handler(); -void LevelShutdown_handler(); -bool LevelInit_handler(char const *pMapName, char const *pMapEntities, char const *pOldLevel, char const *pLandmarkName, bool loadGame, bool background); -bool GameInit_handler(); - -GameDllInfo g_GameDll = {false, NULL, NULL, NULL, NULL}; -EngineInfo g_Engine; -SourceHook::CSourceHookImpl g_SourceHook; -SourceHook::ISourceHook *g_SHPtr = &g_SourceHook; -SourceHook::String g_ModPath; -SourceHook::String g_BinPath; -SourceHook::String g_SmmPath; -PluginId g_PLID = Pl_Console; /* Technically, SourceMM is the "Console" plugin... :p */ -bool bInFirstLevel = true; -bool gParsedGameInfo = false; -bool bGameInit = false; -SourceHook::List gamedll_list; -SourceHook::CallClass *g_GameDllPatch; -int g_GameDllVersion = 0; -int g_GameClientsVersion = 0; -int g_VspVersion = 0; -int g_SourceEngineVersion = SOURCE_ENGINE_ORIGINAL; -const char VSPIFACE[] = "ISERVERPLUGINCALLBACKS"; -const char GAMEINFO_PATH[] = "|gameinfo_path|"; - -void ClearGamedllList(); - -/* Helper Macro */ -#define IFACE_MACRO(orig,nam) \ - CPluginManager::CPlugin *pl; \ - SourceHook::List::iterator event; \ - IMetamodListener *api; \ - int mret = 0; \ - void *val = NULL; \ - for (PluginIter iter = g_PluginMngr._begin(); iter != g_PluginMngr._end(); iter++) { \ - pl = (*iter); \ - for (event=pl->m_Events.begin(); event!=pl->m_Events.end(); event++) { \ - api = (*event); \ - mret = IFACE_FAILED; \ - if ( (val=api->On##nam##Query(iface, &mret)) != NULL ) { \ - if (ret) *ret = mret; \ - return val; \ - } \ - } \ - } \ - return (orig)(iface, ret); - -#define ITER_EVENT(evn, args) \ - CPluginManager::CPlugin *pl; \ - SourceHook::List::iterator event; \ - IMetamodListener *api; \ - for (PluginIter iter = g_PluginMngr._begin(); iter != g_PluginMngr._end(); iter++) { \ - pl = (*iter); \ - for (event=pl->m_Events.begin(); event!=pl->m_Events.end(); event++) { \ - api = (*event); \ - api->evn args; \ - } \ - } - -/////////////////////////////////// -// Main code for HL2 Interaction // -/////////////////////////////////// - -/* Initialize everything here */ -void InitMainStates() -{ - char full_path[PATH_SIZE] = {0}; - GetFileOfAddress((void *)g_GameDll.factory, full_path, sizeof(full_path)); - g_BinPath.assign(full_path); - - /* Like Metamod, reload plugins at the end of the map. - * This is so plugins can hook everything on load, BUT, new plugins will be reloaded - * if the server is shut down (silly, but rare case). - */ - bInFirstLevel = true; - - SH_ADD_HOOK_STATICFUNC(IServerGameDLL, DLLInit, g_GameDll.pGameDLL, DLLInit, false); - SH_ADD_HOOK_STATICFUNC(IServerGameDLL, DLLInit, g_GameDll.pGameDLL, DLLInit_Post, true); - SH_ADD_HOOK_STATICFUNC(IServerGameDLL, DLLShutdown, g_GameDll.pGameDLL, DLLShutdown_handler, false); - SH_ADD_HOOK_STATICFUNC(IServerGameDLL, LevelShutdown, g_GameDll.pGameDLL, LevelShutdown_handler, true); - SH_ADD_HOOK_STATICFUNC(IServerGameDLL, LevelInit, g_GameDll.pGameDLL, LevelInit_handler, true); - SH_ADD_HOOK_STATICFUNC(IServerGameDLL, GameInit, g_GameDll.pGameDLL, GameInit_handler, false); -} - -bool DLLInit(CreateInterfaceFn engineFactory, CreateInterfaceFn physicsFactory, CreateInterfaceFn filesystemFactory, CGlobalVars *pGlobals) -{ - g_Engine.engineFactory = engineFactory; - g_Engine.fileSystemFactory = filesystemFactory; - g_Engine.physicsFactory = physicsFactory; - g_Engine.pGlobals = pGlobals; - - g_Engine.engine = (IVEngineServer *)((engineFactory)(INTERFACEVERSION_VENGINESERVER, NULL)); - if (!g_Engine.engine) - { - Error("Could not find IVEngineServer! Metamod cannot load."); - return false; - } - g_Engine.icvar = (ICvar *)((engineFactory)(VENGINE_CVAR_INTERFACE_VERSION , NULL)); - if (!g_Engine.icvar) - { - Error("Could not find ICvar! Metamod cannot load."); - return false; - } - - g_Engine.loaded = true; - - /* Initialize our console hooks */ - ConCommandBaseMgr::OneTimeInit(static_cast(&g_SMConVarAccessor)); - - g_GameDllPatch = SH_GET_CALLCLASS(g_GameDll.pGameDLL); - - if (g_GameDll.pGameClients) - { - SH_ADD_HOOK_STATICFUNC(IServerGameClients, ClientCommand, g_GameDll.pGameClients, ClientCommand_handler, false); - } else { - /* If IServerGameClients isn't found, this really isn't a fatal error so... */ - LogMessage("[META] Warning: Could not find IServerGameClients!"); - LogMessage("[META] Warning: The 'meta' command will not be available to clients."); - } - - if (!g_SmmAPI.CacheCmds()) - { - LogMessage("[META] Warning: Failed to initialize Con_Printf. Defaulting to Msg()."); - LogMessage("[META] Warning: Console messages will not be redirected to rcon console."); - } - - if (!g_SmmAPI.CacheUserMessages()) - { - /* Don't know of a mod that has stripped out user messages completely, - * but perhaps should do something different here? - */ - LogMessage("[META] Warning: Failed to get list of user messages."); - LogMessage("[META] Warning: The 'meta game' command will not display user messages."); - } - - const char *pluginFile = g_Engine.icvar->GetCommandLineValue("mm_pluginsfile"); - if (!pluginFile) - { - pluginFile = GetPluginsFile(); - } - - char full_path[260]; - g_SmmAPI.PathFormat(full_path, sizeof(full_path), "%s/%s", g_ModPath.c_str(), pluginFile); - - LoadPluginsFromFile(full_path); - - bInFirstLevel = true; - - RETURN_META_VALUE(MRES_IGNORED, true); -} - -bool GameInit_handler() -{ - if (bGameInit) - { - return true; - } - - if (g_SmmAPI.VSPEnabled()) - { - g_SmmAPI.LoadAsVSP(); - } - - bGameInit = true; - - RETURN_META_VALUE(MRES_IGNORED, true); -} - -bool DLLInit_Post(CreateInterfaceFn engineFactory, CreateInterfaceFn physicsFactory, CreateInterfaceFn filesystemFactory, CGlobalVars *pGlobals) -{ - g_PluginMngr.SetAllLoaded(); - RETURN_META_VALUE(MRES_IGNORED, true); -} - -/* This is where the magic happens */ -SMM_API void *CreateInterface(const char *iface, int *ret) -{ - /* Prevent loading of self as a SourceMM plugin or Valve server plugin :x */ - if (strcmp(iface, PLAPI_NAME) == 0) - { - Warning("Do not try loading Metamod:Source as a plugin.\n"); - - if (ret) - { - *ret = IFACE_FAILED; - } - - return NULL; - } - - if (strncmp(iface, VSPIFACE, 22) == 0) - { - g_VspVersion = atoi(&(iface[22])); - - if (g_VspVersion <= MAX_VSP_VERSION) - { - if (ret) - { - *ret = IFACE_OK; - } - return &g_VspListener; - } - } - - if (!gParsedGameInfo) - { - gParsedGameInfo = true; - const char *gameDir = NULL; - char gamePath[PATH_SIZE]; - char smmPath[PATH_SIZE]; - - /* Get path to SourceMM DLL */ - if (!GetFileOfAddress((void *)CreateInterface, smmPath, sizeof(smmPath))) - { - Error("GetFileOfAddress() failed! Metamod cannot load.\n"); - return NULL; - } - - g_SmmPath.assign(smmPath); - - /* Get value of -game from command line, defaulting to hl2 as engine seems to do */ - gameDir = CommandLine()->ParmValue("-game", "hl2"); - - /* Get absolute path */ - abspath(gamePath, gameDir); - g_ModPath.assign(gamePath); - - char tempPath[PATH_SIZE]; - - /* Path to gameinfo.txt */ - g_SmmAPI.PathFormat(tempPath, PATH_SIZE, "%s/%s", g_ModPath.c_str(), "gameinfo.txt"); - - FILE *fp = fopen(tempPath, "rt"); - - if (!fp) - { - Error("Unable to open gameinfo.txt! Metamod cannot load.\n"); - return NULL; - } - - char buffer[255]; - char key[128], val[128]; - bool search = false; - bool gamebin = false; - char *ptr; - const char *lptr; - char curPath[PATH_SIZE]; - - getcwd(curPath, PATH_SIZE); - - while (!feof(fp)) - { - buffer[0] = '\0'; - fgets(buffer, sizeof(buffer), fp); - UTIL_TrimComments(buffer); - UTIL_TrimLeft(buffer); - UTIL_TrimRight(buffer); - if (stricmp(buffer, "SearchPaths") == 0) - search = true; - if (!search) - continue; - UTIL_KeySplit(buffer, key, sizeof(key) - 1, val, sizeof(val) - 1); - if (stricmp(key, "Game") == 0 || stricmp(key, "GameBin") == 0) - { - if (stricmp(key, "Game") == 0) - gamebin = false; - else - gamebin = true; - - if (strncmp(val, GAMEINFO_PATH, sizeof(GAMEINFO_PATH) - 1) == 0) - { - ptr = &(val[sizeof(GAMEINFO_PATH) - 1]); - if (ptr[0] == '.') - ptr++; - lptr = g_ModPath.c_str(); - } else { - ptr = val; - lptr = curPath; - } - - size_t ptr_len = strlen(ptr); - if (ptr[ptr_len] == '/' || ptr[ptr_len] == '\\') - ptr[--ptr_len] = '\0'; - - /* No need to append "bin" if key is GameBin */ - if (gamebin) - { - g_SmmAPI.PathFormat(tempPath, PATH_SIZE, "%s/%s/%s", lptr, ptr, SERVER_DLL); - } else if (!ptr[0]) { - g_SmmAPI.PathFormat(tempPath, PATH_SIZE, "%s/%s/%s", lptr, "bin", SERVER_DLL); - } else { - g_SmmAPI.PathFormat(tempPath, PATH_SIZE, "%s/%s/%s/%s", lptr, ptr, "bin", SERVER_DLL); - } - - /* If not path to SourceMM... */ - if (!UTIL_PathCmp(smmPath, tempPath)) - { - FILE *fp = fopen(tempPath, "rb"); - if (!fp) - continue; - //:TODO: Optimize this a bit! - SourceHook::List::iterator iter; - GameDllInfo *pCheck; - bool found = false; - for (iter=gamedll_list.begin(); iter!=gamedll_list.end(); iter++) - { - pCheck = (*iter); - if (GetFileOfAddress((void *)pCheck->factory, buffer, sizeof(buffer))) - { - if (UTIL_PathCmp(tempPath, buffer)) - { - found = true; - break; - } - } - } - if (found) - continue; - fclose(fp); - HINSTANCE gamedll = dlmount(tempPath); - if (gamedll == NULL) - continue; - CreateInterfaceFn fn = (CreateInterfaceFn)dlsym(gamedll, "CreateInterface"); - if (fn == NULL) - { - dlclose(gamedll); - continue; - } - GameDllInfo *pInfo = new GameDllInfo; - pInfo->factory = fn; - pInfo->lib = gamedll; - pInfo->loaded = true; - pInfo->pGameDLL = NULL; - gamedll_list.push_back(pInfo); - break; - } - } - } - fclose(fp); - } - - if (!g_GameDll.loaded) - { - const char *str = "ServerGameDLL"; - size_t len = strlen(str); - - if (strncmp(iface, str, len) == 0) - { - /* This is the interface we want! Right now we support versions 3 through 8 */ - g_GameDllVersion = atoi(&(iface[len])); - if (g_GameDllVersion < MIN_GAMEDLL_VERSION) - { - if (ret) - { - *ret = IFACE_FAILED; - } - } - else if (g_GameDllVersion > 3) - { - /* The engine is at least episode 1 */ - g_SourceEngineVersion = SOURCE_ENGINE_EPISODEONE; - } - SourceHook::List::iterator iter; - GameDllInfo *pInfo = NULL; - void *ptr; - for (iter=gamedll_list.begin(); iter!=gamedll_list.end(); iter++) - { - pInfo = (*iter); - ptr = (pInfo->factory)(iface, ret); - if (ptr) - { - /* This is our GameDLL. Unload the others. */ - gamedll_list.erase(iter); - ClearGamedllList(); - pInfo->pGameDLL = static_cast(ptr); - g_GameDll = *pInfo; - delete pInfo; - break; - } - } - if (g_GameDll.loaded) - { - InitMainStates(); - } else { - if (ret) - { - *ret = IFACE_FAILED; - } - return NULL; - } - } else { - /* wtf do we do... */ - /* :TODO: .. something a bit more intelligent? */ - Error("Engine requested unknown interface before GameDLL was known!\n"); - return NULL; - } - } - - /* We use this interface for responding to the meta client command */ - if (strncmp(iface, "ServerGameClients", 17) == 0) - { - void *ptr = (g_GameDll.factory)(iface, ret); - g_GameDll.pGameClients = static_cast(ptr); - g_GameClientsVersion = atoi(&iface[17]); - - return ptr; - } - - /* If we got here, there's definitely a GameDLL */ - IFACE_MACRO(g_GameDll.factory, GameDLL); -} - -void ClearGamedllList() -{ - SourceHook::List::iterator iter; - - GameDllInfo *pInfo; - for (iter=gamedll_list.begin(); iter!=gamedll_list.end(); iter++) - { - pInfo = (*iter); - dlclose(pInfo->lib); - delete pInfo; - } - - gamedll_list.clear(); -} - -void DLLShutdown_handler() -{ - /* Unload plugins */ - g_PluginMngr.UnloadAll(); - - /* Add the FCVAR_GAMEDLL flag to our cvars so the engine removes them properly */ - g_SMConVarAccessor.MarkCommandsAsGameDLL(); - g_SMConVarAccessor.UnregisterGameDLLCommands(); - - SH_CALL(g_GameDllPatch, &IServerGameDLL::DLLShutdown)(); - - SH_RELEASE_CALLCLASS(g_GameDllPatch); - g_GameDllPatch = NULL; - - g_SourceHook.CompleteShutdown(); - - if (g_GameDll.lib && g_GameDll.loaded) - dlclose(g_GameDll.lib); - memset(&g_GameDll, 0, sizeof(GameDllInfo)); - - RETURN_META(MRES_SUPERCEDE); -} - -int LoadPluginsFromFile(const char *_file) -{ - FILE *fp; - int total = 0, skipped=0; - PluginId id; - bool already; - - fp = fopen(_file, "rt"); - if (!fp) - { - LogMessage("[META] Could not open plugins file %s\n", _file); - return -1; - } - - char buffer[255], error[255], full_path[255]; - const char *ptr, *ext, *file; - size_t length; - while (!feof(fp)) - { - buffer[0] = '\0'; - fgets(buffer, sizeof(buffer), fp); - length = strlen(buffer); - if (!length) - continue; - if (buffer[length-1] == '\n') - buffer[--length] = '\0'; - - UTIL_TrimLeft(buffer); - UTIL_TrimRight(buffer); - - if (buffer[0] == '\0' || buffer[0] == ';' || strncmp(buffer, "//", 2) == 0) - continue; - file = buffer; - if (buffer[0] == '"') - { - char *cptr = buffer; - file = ++cptr; - - while (*cptr) - { - if (*cptr == '"') - { - *cptr = '\0'; - break; - } - cptr++; - } - } else { - char *cptr = buffer; - while (*cptr) - { - if (isspace(*cptr)) - { - char *optr = cptr; - while (*cptr && isspace(*cptr)) - cptr++; - *optr = '\0'; - UTIL_TrimRight(cptr); - if (*cptr && isalpha(*cptr)) - { - g_PluginMngr.SetAlias(buffer, cptr); - file = cptr; - } - break; - } - cptr++; - } - } - if (!file[0]) - { - continue; - } - /* First find if it's an absolute path or not... */ - if (file[0] == '/' || strncmp(&(file[1]), ":\\", 2) == 0) - { - /* If we're in an absolute path, ignore our normal heuristics */ - id = g_PluginMngr.Load(file, Pl_File, already, error, sizeof(error)); - if (id < Pl_MinId || g_PluginMngr.FindById(id)->m_Status < Pl_Paused) - { - LogMessage("[META] Failed to load plugin %s. %s", buffer, error); - } else { - if (already) - skipped++; - else - total++; - } - } else { - /* Attempt to find a file extension */ - ptr = UTIL_GetExtension(file); - /* Add an extension if there's none there */ - if (!ptr) - { -#if defined WIN32 || defined _WIN32 - ext = ".dll"; -#else - ext = "_i486.so"; -#endif - } else { - ext = ""; - } - /* Format the new path */ - g_SmmAPI.PathFormat(full_path, sizeof(full_path), "%s/%s%s", g_ModPath.c_str(), file, ext); - id = g_PluginMngr.Load(full_path, Pl_File, already, error, sizeof(error)); - if (id < Pl_MinId || g_PluginMngr.FindById(id)->m_Status < Pl_Paused) - { - LogMessage("[META] Failed to load plugin %s. %s", buffer, error); - } else { - if (already) - skipped++; - else - total++; - } - } - } - fclose(fp); - - if (skipped) - { - LogMessage("[META] Loaded %d plugins from file (%d already loaded)", total, skipped); - } else { - LogMessage("[META] Loaded %d plugins from file.", total); - } - - return total; -} - -/* Wrapper function. This is called when the GameDLL thinks it's using - * the engine's real engineFactory. - */ -void *EngineFactory(const char *iface, int *ret) -{ - IFACE_MACRO(g_Engine.engineFactory, Engine); -} - -/* Wrapper function. This is called when the GameDLL thinks it's using - * the engine's real physicsFactory. - */ -void *PhysicsFactory(const char *iface, int *ret) -{ - IFACE_MACRO(g_Engine.physicsFactory, Physics); -} - -/* Wrapper function. This is called when the GameDLL thinks it's using - * the engine's real fileSystemFactory. - */ -void *FileSystemFactory(const char *iface, int *ret) -{ - IFACE_MACRO(g_Engine.fileSystemFactory, FileSystem); -} - -void LogMessage(const char *msg, ...) -{ - va_list ap; - static char buffer[2048]; - - va_start(ap, msg); - size_t len = vsnprintf(buffer, sizeof(buffer) - 2, msg, ap); - va_end(ap); - - buffer[len++] = '\n'; - buffer[len] = '\0'; - - if (!g_Engine.engine) - { - fprintf(stdout, "%s", buffer); - } else { - g_Engine.engine->LogPrint(buffer); - } -} - -void LevelShutdown_handler(void) -{ - if (!bInFirstLevel) - { - char full_path[255]; - g_SmmAPI.PathFormat(full_path, sizeof(full_path), "%s/%s", g_ModPath.c_str(), GetPluginsFile()); - - LoadPluginsFromFile(full_path); - } else { - bInFirstLevel = false; - } - - ITER_EVENT(OnLevelShutdown, ()); - - RETURN_META(MRES_IGNORED); -} - -bool LevelInit_handler(char const *pMapName, char const *pMapEntities, char const *pOldLevel, char const *pLandmarkName, bool loadGame, bool background) -{ - if (!g_SmmAPI.CmdCacheSuccessful()) - { - LogMessage("[META] Warning: Failed to initialize Con_Printf. Defaulting to Msg()."); - LogMessage("[META] Warning: Console messages will not be redirected to rcon console."); - } - - ITER_EVENT(OnLevelInit, (pMapName, pMapEntities, pOldLevel, pLandmarkName, loadGame, background)); - - RETURN_META_VALUE(MRES_IGNORED, false); -} - -#if defined __GNUC__ && (__GNUC__ == 3 || __GNUC__ == 4) -void * operator new(size_t size) { - return(calloc(1, size)); -} - -void * operator new[](size_t size) { - return(calloc(1, size)); -} - -void operator delete(void * ptr) { - if(ptr) - free(ptr); -} - -void operator delete[](void * ptr) { - if(ptr) - free(ptr); -} -#endif diff --git a/sourcemm/sourcemm.h b/sourcemm/sourcemm.h deleted file mode 100644 index 24bf5fd..0000000 --- a/sourcemm/sourcemm.h +++ /dev/null @@ -1,131 +0,0 @@ -/* ======== SourceMM ======== - * Copyright (C) 2004-2007 Metamod:Source Development Team - * No warranties of any kind - * - * License: zlib/libpng - * - * Author(s): David "BAILOPAN" Anderson - * ============================ - */ - -#ifndef _INCLUDE_SOURCEMM_H -#define _INCLUDE_SOURCEMM_H - -/** - * @brief SourceMM main functionality for GameDLL interception - * @file sourcemm.h - */ - -#include -#include -#include -#include -#include -#include "ISmmAPI.h" -#include "CPlugin.h" -#include "oslink.h" -#include "util.h" -#include "svn_version.h" - -/** - * Versioning - * increase api_major when API breaks - * increase api_minor when new functions are added (non-breaking) - */ -#define SOURCEMM_VERSION SVN_FILE_VERSION_STRING -#define SOURCEMM_DATE __DATE__ -#define SM_VERS_API_MAJOR 1 //increase this on a breaking change -#define SM_VERS_API_MINOR 7 //increase this on a non-breaking API change - -/* We need a good CServerGameDLL version to work properly. We support these inclusively. */ -#define MIN_GAMEDLL_VERSION 3 - -/* Maximum version of IServerPluginCallbacks that SourceMM supports */ -#define MAX_VSP_VERSION 2 - -/** @brief Entry point for HL2 Engine */ -SMM_API void *CreateInterface(const char *name, int *code); - -/** @brief Wrapper to catch GameDLL calls */ -void *EngineFactory(const char *name, int *code); - -/** @brief Wrapper to catch GameDLL calls */ -void *PhysicsFactory(const char *name, int *code); - -/** @brief Wrapper to catch GameDLL calls */ -void *FileSystemFactory(const char *name, int *code); - -/** @brief Loads all plugins found in a file */ -int LoadPluginsFromFile(const char *file); - -/** @brief Logs a message to the standard log file */ -void LogMessage(const char *msg, ...); - -/** @brief Stores information about the GameDLL */ -struct GameDllInfo -{ - bool loaded; - HINSTANCE lib; - CreateInterfaceFn factory; - IServerGameDLL *pGameDLL; - IServerGameClients *pGameClients; -}; - -/** @brief Stores information about the HL2 Engine pointers */ -struct EngineInfo -{ - EngineInfo() : loaded(false), - engineFactory(NULL), physicsFactory(NULL), fileSystemFactory(NULL), - pGlobals(NULL), icvar(NULL), engine(NULL) - { }; - bool loaded; - CreateInterfaceFn engineFactory; - CreateInterfaceFn physicsFactory; - CreateInterfaceFn fileSystemFactory; - CGlobalVars *pGlobals; - ICvar *icvar; - IVEngineServer *engine; -}; - -/** @brief Global variable for GameDLL info */ -extern GameDllInfo g_GameDll; - -/** @brief Global variable for Engine info */ -extern EngineInfo g_Engine; - -/** @brief Global singleton for SourceHook */ -extern SourceHook::CSourceHookImpl g_SourceHook; - -/** @brief Mod path (important!)*/ -extern SourceHook::String g_ModPath; - -/** @brief Path to server binary */ -extern SourceHook::String g_BinPath; - -/** @brief Path to SourceMM binary */ -extern SourceHook::String g_SmmPath; - -/** @brief Global variable for SourceHook macros */ -extern SourceHook::ISourceHook *g_SHPtr; - -/** @brief We have our own internal plugin id... */ -extern PluginId g_PLID; - -/** @brief ServerGameDLL version that is currently loaded */ -extern int g_GameDllVersion; - -/** @brief Highest IServerPluginCallbacks version that is supported by engine */ -extern int g_VspVersion; - -/** @brief IServerGameClients version the mod uses */ -extern int g_GameClientsVersion; - -/** @brief Source Engine version */ -extern int g_SourceEngineVersion; - -extern bool bGameInit; - -/** @brief Global CallClass for IServerGameDLL */ -extern SourceHook::CallClass *g_GameDllPatch; - -#endif //_INCLUDE_SOURCEMM_H diff --git a/sourcemm/stub_mm/LICENSE.txt b/sourcemm/stub_mm/LICENSE.txt deleted file mode 100644 index bf9f1fd..0000000 --- a/sourcemm/stub_mm/LICENSE.txt +++ /dev/null @@ -1,29 +0,0 @@ -The software is Copyright (C) 2004-2007, Metamod:Source Development Team. - -Metamod:Source is distributed under the "zLib/libpng" license, which is reproduced -below: - ------------------------------------------------------------------------------ - -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. - ------------------------------------------------------------------------------ - -The zLib/libpng license has been approved by the "Open Source Initiative" -organization. diff --git a/sourcemm/stub_mm/Makefile b/sourcemm/stub_mm/Makefile deleted file mode 100644 index eec1eb9..0000000 --- a/sourcemm/stub_mm/Makefile +++ /dev/null @@ -1,66 +0,0 @@ -#(C)2004-2007 SourceMM Development Team -# Makefile written by David "BAILOPAN" Anderson - -HL2SDK = ../../../hl2sdk -SMM_ROOT = ../.. -SRCDS = ~/srcds - -### EDIT BELOW FOR OTHER PROJECTS ### - -OPT_FLAGS = -O3 -funroll-loops -s -pipe -GCC4_FLAGS = -fvisibility=hidden -fvisibility-inlines-hidden -DEBUG_FLAGS = -g -ggdb3 -CPP = gcc-4.1 -BINARY = stub_mm_i486.so - -HL2PUB = $(HL2SDK)/public - -OBJECTS = stub_mm.cpp - -LINK = vstdlib_i486.so tier0_i486.so -static-libgcc - -INCLUDE = -I. -I.. -I$(HL2PUB) -I$(HL2PUB)/dlls -I$(HL2PUB)/engine -I$(HL2PUB)/tier0 -I$(HL2PUB)/tier1 \ - -I$(HL2PUB)/vstdlib -I$(HL2SDK)/tier1 -I$(SMM_ROOT) -I$(SMM_ROOT)/sourcehook -I$(SMM_ROOT)/sourcemm - -ifeq "$(DEBUG)" "true" - BIN_DIR = Debug - CFLAGS = $(DEBUG_FLAGS) -else - BIN_DIR = Release - CFLAGS = $(OPT_FLAGS) -endif - -GCC_VERSION := $(shell $(CPP) -dumpversion >&1 | cut -b1) - -CFLAGS += -D_LINUX -DNDEBUG -Dstricmp=strcasecmp -D_stricmp=strcasecmp -D_strnicmp=strncasecmp -Dstrnicmp=strncasecmp -D_snprintf=snprintf -D_vsnprintf=vsnprintf -D_alloca=alloca -Dstrcmpi=strcasecmp -Wall -Wno-non-virtual-dtor -Werror -fPIC -fno-exceptions -fno-rtti -msse - -ifeq "$(GCC_VERSION)" "4" - CFLAGS += $(GCC4_FLAGS) -endif - -OBJ_LINUX := $(OBJECTS:%.cpp=$(BIN_DIR)/%.o) - -$(BIN_DIR)/%.o: %.cpp - $(CPP) $(INCLUDE) $(CFLAGS) -o $@ -c $< - -all: - mkdir -p $(BIN_DIR) - ln -sf $(SRCDS)/bin/vstdlib_i486.so vstdlib_i486.so - ln -sf $(SRCDS)/bin/tier0_i486.so tier0_i486.so - $(MAKE) sourcemm - rm -rf $(BINARY) - ln -sf $(BIN_DIR)/$(BINARY) $(BINARY) - -sourcemm: $(OBJ_LINUX) - $(CPP) $(INCLUDE) $(CFLAGS) $(OBJ_LINUX) $(LINK) -shared -ldl -lm -o$(BIN_DIR)/$(BINARY) - -debug: - $(MAKE) all DEBUG=true - -default: all - -clean: - rm -rf Release/*.o - rm -rf Release/$(BINARY) - rm -rf Debug/*.o - rm -rf Debug/$(BINARY) diff --git a/sourcemm/stub_mm/msvc8/stub_mm.sln b/sourcemm/stub_mm/msvc8/stub_mm.sln deleted file mode 100644 index 4e0655b..0000000 --- a/sourcemm/stub_mm/msvc8/stub_mm.sln +++ /dev/null @@ -1,20 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 9.00 -# Visual Studio 2005 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "stub_mm", "stub_mm.vcproj", "{836E726E-AB80-43AB-9A8F-0E6EE680B0F6}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Release|Win32 = Release|Win32 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {836E726E-AB80-43AB-9A8F-0E6EE680B0F6}.Debug|Win32.ActiveCfg = Debug|Win32 - {836E726E-AB80-43AB-9A8F-0E6EE680B0F6}.Debug|Win32.Build.0 = Debug|Win32 - {836E726E-AB80-43AB-9A8F-0E6EE680B0F6}.Release|Win32.ActiveCfg = Release|Win32 - {836E726E-AB80-43AB-9A8F-0E6EE680B0F6}.Release|Win32.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/sourcemm/stub_mm/msvc8/stub_mm.vcproj b/sourcemm/stub_mm/msvc8/stub_mm.vcproj deleted file mode 100644 index 6490884..0000000 --- a/sourcemm/stub_mm/msvc8/stub_mm.vcproj +++ /dev/null @@ -1,214 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/sourcemm/stub_mm/stub_mm.cpp b/sourcemm/stub_mm/stub_mm.cpp deleted file mode 100644 index f43ed53..0000000 --- a/sourcemm/stub_mm/stub_mm.cpp +++ /dev/null @@ -1,105 +0,0 @@ -/* ======== stub_mm ======== - * Copyright (C) 2004-2007 Metamod:Source Development Team - * No warranties of any kind - * - * License: zlib/libpng - * - * Author(s): David "BAILOPAN" Anderson - * ============================ - */ - -#include -#include "stub_mm.h" - -SH_DECL_HOOK3_void(IServerGameDLL, ServerActivate, SH_NOATTRIB, 0, edict_t *, int, int); - -StubPlugin g_StubPlugin; - -PLUGIN_EXPOSE(SamplePlugin, g_StubPlugin); - -void ServerActivate_handler(edict_t *pEdictList, int edictCount, int clientMax) -{ - META_LOG(g_PLAPI, "ServerActivate() called: edictCount=%d, clientMax=%d", edictCount, clientMax); - RETURN_META(MRES_IGNORED); -} - -bool StubPlugin::Load(PluginId id, ISmmAPI *ismm, char *error, size_t maxlen, bool late) -{ - PLUGIN_SAVEVARS(); - - GET_V_IFACE_ANY(serverFactory, m_ServerDll, IServerGameDLL, INTERFACEVERSION_SERVERGAMEDLL); - - SH_ADD_HOOK_STATICFUNC(IServerGameDLL, ServerActivate, m_ServerDll, ServerActivate_handler, true); - - return true; -} - -bool StubPlugin::Unload(char *error, size_t maxlen) -{ - SH_REMOVE_HOOK_STATICFUNC(IServerGameDLL, ServerActivate, m_ServerDll, ServerActivate_handler, true); - - return true; -} - -bool StubPlugin::Pause(char *error, size_t maxlen) -{ - return true; -} - -bool StubPlugin::Unpause(char *error, size_t maxlen) -{ - return true; -} - -void StubPlugin::AllPluginsLoaded() -{ - //This is an example of inter-plugin communication - PluginId id; - void *ptr = g_SMAPI->MetaFactory("SamplePlugin", NULL, &id); - if (ptr) - { - META_LOG(g_PLAPI, "Found Sample Plugin[%d] at (%p)!", id, ptr); - } else { - META_LOG(g_PLAPI, "Did not find Sample Plugin!"); - } -} - -const char *StubPlugin::GetAuthor() -{ - return "AUTHOR"; -} - -const char *StubPlugin::GetName() -{ - return "Stub Plugin"; -} - -const char *StubPlugin::GetDescription() -{ - return "Stub Plugin"; -} - -const char *StubPlugin::GetURL() -{ - return "http://www.mysite.com/"; -} - -const char *StubPlugin::GetLicense() -{ - return "zlib/libpng"; -} - -const char *StubPlugin::GetVersion() -{ - return "1.00"; -} - -const char *StubPlugin::GetDate() -{ - return __DATE__; -} - -const char *StubPlugin::GetLogTag() -{ - return "STUB"; -} diff --git a/sourcemm/stub_mm/stub_mm.h b/sourcemm/stub_mm/stub_mm.h deleted file mode 100644 index fec6701..0000000 --- a/sourcemm/stub_mm/stub_mm.h +++ /dev/null @@ -1,45 +0,0 @@ -/* ======== stub_mm ======== - * Copyright (C) 2004-2007 Metamod:Source Development Team - * No warranties of any kind - * - * License: zlib/libpng - * - * Author(s): David "BAILOPAN" Anderson - * ============================ - */ - -#ifndef _INCLUDE_SAMPLEPLUGIN_H -#define _INCLUDE_SAMPLEPLUGIN_H - -#include - -class StubPlugin : public ISmmPlugin -{ -public: - bool Load(PluginId id, ISmmAPI *ismm, char *error, size_t maxlen, bool late); - bool Unload(char *error, size_t maxlen); - bool Pause(char *error, size_t maxlen); - bool Unpause(char *error, size_t maxlen); - void AllPluginsLoaded(); -public: - const char *GetAuthor(); - const char *GetName(); - const char *GetDescription(); - const char *GetURL(); - const char *GetLicense(); - const char *GetVersion(); - const char *GetDate(); - const char *GetLogTag(); -private: - IServerGameDLL *m_ServerDll; - IServerGameDLL *m_ServerDll_CC; -}; - -extern StubPlugin g_StubPlugin; - -PLUGIN_GLOBALVARS(); - -//Called on ServerActivate. Same definition as server plugins -void ServerActivate_handler(edict_t *pEdictList, int edictCount, int clientMax); - -#endif //_INCLUDE_SAMPLEPLUGIN_H diff --git a/sourcemm/vsp_listener.cpp b/sourcemm/vsp_listener.cpp deleted file mode 100644 index c02a230..0000000 --- a/sourcemm/vsp_listener.cpp +++ /dev/null @@ -1,152 +0,0 @@ -/* ======== SourceMM ======== - * Copyright (C) 2004-2007 Metamod:Source Development Team - * No warranties of any kind - * - * License: zlib/libpng - * - * Author(s): David "BAILOPAN" Anderson - * ============================ - */ - -#include "vsp_listener.h" -#include "CPlugin.h" - -using namespace SourceMM; - -VSPListener g_VspListener; - -VSPListener::VSPListener() -{ - m_Loaded = false; - m_Loadable = false; -} - -void VSPListener::ClientActive(edict_t *pEntity) -{ -} - -PLUGIN_RESULT VSPListener::ClientCommand(edict_t *pEntity) -{ - return PLUGIN_CONTINUE; -} - -PLUGIN_RESULT VSPListener::ClientConnect(bool *bAllowConnect, edict_t *pEntity, const char *pszName, const char *pszAddress, char *reject, int maxrejectlen) -{ - return PLUGIN_CONTINUE; -} - -void VSPListener::ClientDisconnect(edict_t *pEntity) -{ -} - -void VSPListener::ClientPutInServer(edict_t *pEntity, char const *playername) -{ -} - -void VSPListener::ClientSettingsChanged(edict_t *pEdict) -{ -} - -void VSPListener::SetCommandClient(int index) -{ -} - -void VSPListener::GameFrame(bool simulating) -{ -} - -const char *VSPListener::GetPluginDescription() -{ - return "Metamod:Source Interface v" SOURCEMM_VERSION; -} - -bool VSPListener::IsLoaded() -{ - return m_Loaded; -} - -void VSPListener::LevelInit(char const *pMapName) -{ -} - -void VSPListener::LevelShutdown() -{ -} - -PLUGIN_RESULT VSPListener::NetworkIDValidated(const char *pszUserName, const char *pszNetworkID) -{ - return PLUGIN_CONTINUE; -} - -void VSPListener::Pause() -{ -} - -void VSPListener::UnPause() -{ -} - -void VSPListener::ServerActivate(edict_t *pEdictList, int edictCount, int clientMax) -{ -} - -void VSPListener::Unload() -{ -} - -void VSPListener::SetLoadable(bool set) -{ - m_Loadable = set; -} - -bool VSPListener::Load(CreateInterfaceFn interfaceFactory, CreateInterfaceFn gameServerFactory) -{ - if (!g_GameDll.loaded) - { - Error("Metamod:Source is not a Valve Server Plugin\n"); - - return false; - } - - if (!m_Loadable) - { - Warning("Do not manually load Metamod:Source as a Valve Server Plugin\n"); - - return false; - } - - if (m_Loaded) - { - return false; - } - - m_Loaded = true; - SetLoadable(false); - - PluginIter iter; - CPluginManager::CPlugin *pPlugin; - SourceHook::List::iterator event; - IMetamodListener *pML; - for (iter=g_PluginMngr._begin(); iter!=g_PluginMngr._end(); iter++) - { - pPlugin = (*iter); - if (pPlugin->m_Status < Pl_Paused) - { - continue; - } - /* Only valid for plugins >= 10 (v1:5, SourceMM 1.4) */ - if (pPlugin->m_API->GetApiVersion() < 10) - { - continue; - } - for (event=pPlugin->m_Events.begin(); - event!=pPlugin->m_Events.end(); - event++) - { - pML = (*event); - pML->OnVSPListening(this); - } - } - - return true; -} diff --git a/sourcemm/vsp_listener.h b/sourcemm/vsp_listener.h deleted file mode 100644 index 44b7b60..0000000 --- a/sourcemm/vsp_listener.h +++ /dev/null @@ -1,49 +0,0 @@ -/* ======== SourceMM ======== - * Copyright (C) 2004-2007 Metamod:Source Development Team - * No warranties of any kind - * - * License: zlib/libpng - * - * Author(s): David "BAILOPAN" Anderson - * ============================ - */ - -#ifndef _INCLUDE_SOURCEMM_VSPLISTENER_H_ -#define _INCLUDE_SOURCEMM_VSPLISTENER_H_ - -#include "sourcemm.h" -#include "iserverplugin.h" - -class VSPListener : public IServerPluginCallbacks -{ -public: - VSPListener(); -public: - virtual bool Load(CreateInterfaceFn interfaceFactory, CreateInterfaceFn gameServerFactory); - virtual void Unload(); - virtual void Pause(); - virtual void UnPause(); - virtual const char *GetPluginDescription(); - virtual void LevelInit(char const *pMapName); - virtual void ServerActivate(edict_t *pEdictList, int edictCount, int clientMax); - virtual void GameFrame(bool simulating); - virtual void LevelShutdown(void); - virtual void ClientActive(edict_t *pEntity); - virtual void ClientDisconnect(edict_t *pEntity); - virtual void ClientPutInServer(edict_t *pEntity, char const *playername); - virtual void SetCommandClient(int index); - virtual void ClientSettingsChanged(edict_t *pEdict); - virtual PLUGIN_RESULT ClientConnect(bool *bAllowConnect, edict_t *pEntity, const char *pszName, const char *pszAddress, char *reject, int maxrejectlen); - virtual PLUGIN_RESULT ClientCommand(edict_t *pEntity); - virtual PLUGIN_RESULT NetworkIDValidated(const char *pszUserName, const char *pszNetworkID); -public: - bool IsLoaded(); - void SetLoadable(bool loadable); -private: - bool m_Loaded; - bool m_Loadable; -}; - -extern VSPListener g_VspListener; - -#endif //_INCLUDE_SOURCEMM_VSPLISTENER_H_