From 221e49cbc64fc6e1ce372bb59fcd67e6709024ca Mon Sep 17 00:00:00 2001 From: David Anderson Date: Tue, 6 Dec 2005 07:59:18 +0000 Subject: [PATCH] Added API call for guessing iface names Added interface query overriding+sharing examples to stub+sample --HG-- extra : convert_revision : svn%3Ac2935e3e-5518-0410-8daf-afa5dab7d4e3/trunk%40153 --- sourcemm/CSmmAPI.cpp | 28 ++++++++++++ sourcemm/CSmmAPI.h | 1 + sourcemm/ISmmAPI.h | 11 ++++- sourcemm/sample_mm/SamplePlugin.cpp | 68 +++++++++++++++++++---------- sourcemm/sample_mm/SamplePlugin.h | 6 +++ sourcemm/sourcemm.h | 4 +- sourcemm/stub_mm/stub_mm.cpp | 36 ++++++++++++--- 7 files changed, 119 insertions(+), 35 deletions(-) diff --git a/sourcemm/CSmmAPI.cpp b/sourcemm/CSmmAPI.cpp index 35a3bc1..913d923 100644 --- a/sourcemm/CSmmAPI.cpp +++ b/sourcemm/CSmmAPI.cpp @@ -288,3 +288,31 @@ 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])) + break; + } + + if ( (num && (maxlength <= length)) || (!num && (maxlength <= length+3)) ) + { + return -1; + } + + if (i != length-1) + num = atoi(&(iface[++i])); + + num++; + + snprintf(&(iface[i]), 4, "%03d", num); + + return num; +} + diff --git a/sourcemm/CSmmAPI.h b/sourcemm/CSmmAPI.h index a1a63b2..978a3b2 100644 --- a/sourcemm/CSmmAPI.h +++ b/sourcemm/CSmmAPI.h @@ -50,6 +50,7 @@ namespace SourceMM 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); public: bool CacheCmds(); private: diff --git a/sourcemm/ISmmAPI.h b/sourcemm/ISmmAPI.h index d3b6a8e..b7d5e2e 100644 --- a/sourcemm/ISmmAPI.h +++ b/sourcemm/ISmmAPI.h @@ -56,7 +56,7 @@ public: //Added in 1.00-RC2 (0:0) //these do not add newlines virtual void ConPrint(const char *fmt) =0; virtual void ConPrintf(const char *fmt, ...) =0; -public: //Added in 1.10 (1:0) +public: //Added in 1.1.0 (1:0) //added by request. Checks if ConPrint/ConPrintf will mirror to rcon. virtual bool RemotePrintingAvailable() =0; //Returns the Metamod Version numbers as major version and minor (API) version. @@ -77,11 +77,18 @@ public: //Added in 1.10 (1:0) * @return Returned pointer */ virtual void *MetaFactory(const char *iface, int *ret, PluginId *id) =0; +public: //Added in 1.1.2 (1:1) + /** + * @brief Given a base interface name, such as ServerGameDLL or ServerGameDLL003, + * reformats the string to increase the number, then returns the new number. + */ + virtual int FormatIface(char iface[], unsigned int maxlength) =0; }; /** Version history - * 1.10 bumped API to 1:0. The breaking changes occured in sourcehook and the plugin API. + * 1.1.0 bumped API to 1:0. The breaking changes occured in sourcehook and the plugin API. + * 1.1.2 added API call for generating iface names. */ #endif //_INCLUDE_ISMM_API_H diff --git a/sourcemm/sample_mm/SamplePlugin.cpp b/sourcemm/sample_mm/SamplePlugin.cpp index e20d843..8dc9157 100644 --- a/sourcemm/sample_mm/SamplePlugin.cpp +++ b/sourcemm/sample_mm/SamplePlugin.cpp @@ -13,12 +13,28 @@ #include "cvars.h" SamplePlugin g_SamplePlugin; +MyListener g_Listener; PLUGIN_EXPOSE(SamplePlugin, g_SamplePlugin); //This has all of the necessary hook declarations. Read it! #include "meta_hooks.h" +#define FIND_IFACE(func, assn_var, num_var, name, type) \ + do { \ + if ( (assn_var=(type)((ismm->func())(name, NULL))) != NULL ) { \ + num = 0; \ + break; \ + } \ + if (num >= 999) \ + break; \ + } while ( num_var=ismm->FormatIface(name, sizeof(name)-1) ); \ + if (!assn_var) { \ + if (error) \ + snprintf(error, maxlen, "Could not find interface %s", name); \ + return false; \ + } + 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); @@ -107,34 +123,22 @@ bool SamplePlugin::Load(PluginId id, ISmmAPI *ismm, char *error, size_t maxlen, { PLUGIN_SAVEVARS(); - m_ServerDll = (IServerGameDLL *)((ismm->serverFactory())(INTERFACEVERSION_SERVERGAMEDLL, NULL)); - m_Engine = (IVEngineServer *)((ismm->engineFactory())(INTERFACEVERSION_VENGINESERVER, NULL)); - m_ServerClients = (IServerGameClients *)((ismm->serverFactory())(INTERFACEVERSION_SERVERGAMECLIENTS, NULL)); - m_GameEventManager = (IGameEventManager2 *)((ismm->engineFactory())(INTERFACEVERSION_GAMEEVENTSMANAGER2, NULL)); + char iface_buffer[255]; + int num; - if (!m_ServerDll) - { - snprintf(error, maxlen, "Could not find interface %s", INTERFACEVERSION_SERVERGAMEDLL); - return false; - } - if (!m_Engine) - { - snprintf(error, maxlen, "Could not find interface %s", INTERFACEVERSION_VENGINESERVER); - return false; - } - if (!m_ServerClients) - { - snprintf(error, maxlen, "Could not find interface %s", INTERFACEVERSION_SERVERGAMECLIENTS); - return false; - } - if (!m_GameEventManager) - { - snprintf(error, maxlen, "Could not find interface %s", INTERFACEVERSION_GAMEEVENTSMANAGER2); - return false; - } + strcpy(iface_buffer, INTERFACEVERSION_SERVERGAMEDLL); + FIND_IFACE(serverFactory, m_ServerDll, num, iface_buffer, IServerGameDLL *) + strcpy(iface_buffer, INTERFACEVERSION_VENGINESERVER); + FIND_IFACE(engineFactory, m_Engine, num, iface_buffer, IVEngineServer *) + strcpy(iface_buffer, INTERFACEVERSION_SERVERGAMECLIENTS); + FIND_IFACE(serverFactory, m_ServerClients, num, iface_buffer, IServerGameClients *) + strcpy(iface_buffer, INTERFACEVERSION_GAMEEVENTSMANAGER2); + FIND_IFACE(engineFactory, m_GameEventManager, num, iface_buffer, IGameEventManager2 *); META_LOG(g_PLAPI, "Starting plugin.\n"); + ismm->AddListener(this, &g_Listener); + //Init our cvars/concmds ConCommandBaseMgr::OneTimeInit(&g_Accessor); @@ -219,3 +223,19 @@ void SamplePlugin::AllPluginsLoaded() // 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 index 5aca42e..9060bc1 100644 --- a/sourcemm/sample_mm/SamplePlugin.h +++ b/sourcemm/sample_mm/SamplePlugin.h @@ -118,6 +118,12 @@ private: SourceHook::CallClass *m_Engine_CC; }; +class MyListener : public IMetamodListener +{ +public: + virtual void *OnMetamodQuery(const char *iface, int *ret); +}; + extern SamplePlugin g_SamplePlugin; PLUGIN_GLOBALVARS(); diff --git a/sourcemm/sourcemm.h b/sourcemm/sourcemm.h index ea94a63..60f4e74 100644 --- a/sourcemm/sourcemm.h +++ b/sourcemm/sourcemm.h @@ -39,11 +39,11 @@ * minor changes can also roll over, but a big change should ALWAYS roll over. * Increasing one grouping should make the lesser ones reset back to zero. */ -#define SOURCEMM_VERSION "1.1.1" +#define SOURCEMM_VERSION "1.1.2" #define SOURCEMM_DATE __DATE__ #define SM_MAJOR_VERSION 1 //never need to increase this #define SM_VERS_API_MAJOR 1 //increase this on a breaking change -#define SM_VERS_API_MINOR 0 //increase this on a non-breaking API change +#define SM_VERS_API_MINOR 1 //increase this on a non-breaking API change #define SM_VERS_RELEASE 0 //increase this on a bug-fix release. //We need a good CServerGameDLL version to work properly. We support these inclusively. diff --git a/sourcemm/stub_mm/stub_mm.cpp b/sourcemm/stub_mm/stub_mm.cpp index e245288..2876cde 100644 --- a/sourcemm/stub_mm/stub_mm.cpp +++ b/sourcemm/stub_mm/stub_mm.cpp @@ -18,6 +18,21 @@ PLUGIN_EXPOSE(SamplePlugin, g_StubPlugin); //This has all of the necessary hook declarations. Read it! #include "meta_hooks.h" +#define FIND_IFACE(func, assn_var, num_var, name, type) \ + do { \ + if ( (assn_var=(type)((ismm->func())(name, NULL))) != NULL ) { \ + num = 0; \ + break; \ + } \ + if (num >= 999) \ + break; \ + } while ( num_var=ismm->FormatIface(name, sizeof(name)-1) ); \ + if (!assn_var) { \ + if (error) \ + snprintf(error, maxlen, "Could not find interface %s", name); \ + return false; \ + } + void ServerActivate_handler(edict_t *pEdictList, int edictCount, int clientMax) { META_LOG(g_PLAPI, "ServerActivate() called: edictCount=%d, clientMax=%d", edictCount, clientMax); @@ -28,13 +43,11 @@ bool StubPlugin::Load(PluginId id, ISmmAPI *ismm, char *error, size_t maxlen, bo { PLUGIN_SAVEVARS(); - m_ServerDll = (IServerGameDLL *)((ismm->serverFactory())(INTERFACEVERSION_SERVERGAMEDLL, NULL)); + char iface_buffer[255]; + int num; - if (!m_ServerDll) - { - snprintf(error, maxlen, "Could not find interface %s", INTERFACEVERSION_SERVERGAMEDLL); - return false; - } + strcpy(iface_buffer, INTERFACEVERSION_SERVERGAMEDLL); + FIND_IFACE(serverFactory, m_ServerDll, num, iface_buffer, IServerGameDLL *) SH_ADD_HOOK_STATICFUNC(IServerGameDLL, ServerActivate, m_ServerDll, ServerActivate_handler, true); @@ -60,7 +73,15 @@ bool StubPlugin::Unpause(char *error, size_t maxlen) 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() @@ -102,3 +123,4 @@ const char *StubPlugin::GetLogTag() { return "STUB"; } +