1
0
mirror of https://github.com/alliedmodders/metamod-source.git synced 2024-12-01 13:24:25 +01:00

initial import of new events system

--HG--
extra : convert_revision : svn%3Ac2935e3e-5518-0410-8daf-afa5dab7d4e3/trunk%40139
This commit is contained in:
David Anderson 2005-10-20 14:37:47 +00:00
parent f3fb7f304d
commit 2cabdcf3da
9 changed files with 159 additions and 73 deletions

View File

@ -39,7 +39,7 @@ CPluginManager::~CPluginManager()
CPluginManager::CPlugin::CPlugin() : m_Lib(NULL), m_API(NULL), m_Id(0), m_Source(0) CPluginManager::CPlugin::CPlugin() : m_Lib(NULL), m_API(NULL), m_Id(0), m_Source(0)
{ {
memset(&fac_list, 0, sizeof(factories));
} }
PluginId CPluginManager::Load(const char *file, PluginId source, bool &already, char *error, size_t maxlen) PluginId CPluginManager::Load(const char *file, PluginId source, bool &already, char *error, size_t maxlen)
@ -260,7 +260,7 @@ CPluginManager::CPlugin *CPluginManager::_Load(const char *file, PluginId source
snprintf(error, maxlen, "Plugin API %d is newer than internal version (%d)", api, PLAPI_VERSION); snprintf(error, maxlen, "Plugin API %d is newer than internal version (%d)", api, PLAPI_VERSION);
pl->m_Status = Pl_Error; pl->m_Status = Pl_Error;
} else { } else {
if (pl->m_API->Load(pl->m_Id, static_cast<ISmmAPI *>(&g_SmmAPI), &(pl->fac_list), error, maxlen, m_AllLoaded)) if (pl->m_API->Load(pl->m_Id, static_cast<ISmmAPI *>(&g_SmmAPI), error, maxlen, m_AllLoaded))
{ {
pl->m_Status = Pl_Running; pl->m_Status = Pl_Running;
if (m_AllLoaded) if (m_AllLoaded)
@ -409,7 +409,7 @@ bool CPluginManager::UnloadAll()
return status; return status;
} }
bool CPluginManager::Query(PluginId id, const char *&file, factories *&list, Pl_Status &status, PluginId &source) bool CPluginManager::Query(PluginId id, const char *&file, Pl_Status &status, PluginId &source)
{ {
CPlugin *pl = FindById(id); CPlugin *pl = FindById(id);
@ -417,7 +417,6 @@ bool CPluginManager::Query(PluginId id, const char *&file, factories *&list, Pl_
return false; return false;
file = pl->m_File.c_str(); file = pl->m_File.c_str();
list = &(pl->fac_list);
status = pl->m_Status; status = pl->m_Status;
source = pl->m_Source; source = pl->m_Source;

View File

@ -61,9 +61,9 @@ namespace SourceMM
PluginId m_Source; PluginId m_Source;
ISmmPlugin *m_API; ISmmPlugin *m_API;
HINSTANCE m_Lib; HINSTANCE m_Lib;
factories fac_list;
SourceHook::List<ConCommandBase *> m_Cvars; SourceHook::List<ConCommandBase *> m_Cvars;
SourceHook::List<ConCommandBase *> m_Cmds; SourceHook::List<ConCommandBase *> m_Cmds;
SourceHook::List<IMetamodListener *> m_Events;
}; };
public: public:
CPluginManager(); CPluginManager();
@ -76,7 +76,7 @@ namespace SourceMM
bool Unpause(PluginId id, char *error, size_t maxlen); bool Unpause(PluginId id, char *error, size_t maxlen);
bool UnloadAll(); bool UnloadAll();
public: public:
bool Query(PluginId id, const char *&file, factories *&list, Pl_Status &status, PluginId &source); bool Query(PluginId id, const char *&file, Pl_Status &status, PluginId &source);
bool QueryRunning(PluginId id, char *error, size_t maxlength); bool QueryRunning(PluginId id, char *error, size_t maxlength);
void AddPluginCvar(ISmmPlugin *api, ConCommandBase *pCvar); void AddPluginCvar(ISmmPlugin *api, ConCommandBase *pCvar);

View File

@ -28,16 +28,6 @@ CSmmAPI::CSmmAPI()
m_Cache = false; m_Cache = false;
} }
ISmmPluginManager *CSmmAPI::PluginManager()
{
return static_cast<ISmmPluginManager *>(&g_PluginMngr);
}
SourceHook::ISourceHook *CSmmAPI::SourceHook()
{
return static_cast<SourceHook::ISourceHook *>(&g_SourceHook);
}
void CSmmAPI::LogMsg(ISmmPlugin *pl, const char *msg, ...) void CSmmAPI::LogMsg(ISmmPlugin *pl, const char *msg, ...)
{ {
va_list ap; va_list ap;
@ -139,6 +129,58 @@ void CSmmAPI::ConPrintf(const char *fmt, ...)
va_end(ap); va_end(ap);
} }
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)
{
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<void *>(static_cast<SourceHook::ISourceHook *>(&g_SourceHook));
} else if (strcmp(iface, MMIFACE_PLMANAGER)==0) {
if (_ret)
*_ret = IFACE_OK;
return static_cast<void *>(static_cast<IConCommandBaseAccessor *>(&g_SMConVarAccessor));
}
CPluginManager::CPlugin *pl;
SourceHook::List<IMetamodListener *>::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;
return val;
}
}
}
if (_ret)
*_ret = IFACE_FAILED;
return NULL;
}
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
//THERE BE HAX HERE!!!! DON'T TELL ALFRED, BUT GABE WANTED IT THAT WAY. // //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 // // (note: you can find the offset by looking for the text //

View File

@ -27,8 +27,6 @@ namespace SourceMM
public: public:
CSmmAPI::CSmmAPI(); CSmmAPI::CSmmAPI();
public: public:
ISmmPluginManager *PluginManager();
SourceHook::ISourceHook *SourceHook();
void LogMsg(ISmmPlugin *pl, const char *msg, ...); void LogMsg(ISmmPlugin *pl, const char *msg, ...);
public: public:
CreateInterfaceFn engineFactory(bool syn=true); CreateInterfaceFn engineFactory(bool syn=true);
@ -50,6 +48,8 @@ namespace SourceMM
} }
virtual void GetApiVersions(int &major, int &minor, int &plvers, int &plmin); virtual void GetApiVersions(int &major, int &minor, int &plvers, int &plmin);
virtual void GetShVersions(int &shvers, int &shimpl); virtual void GetShVersions(int &shvers, int &shimpl);
virtual void AddListener(ISmmPlugin *plugin, IMetamodListener *pListener);
virtual void *MetaFactory(const char *iface, int *ret);
public: public:
bool CacheCmds(); bool CacheCmds();
private: private:

View File

@ -110,7 +110,7 @@ public:
* @param source By reference source of plugin * @param source By reference source of plugin
* @return True on success, false if not found * @return True on success, false if not found
*/ */
virtual bool Query(PluginId id, const char *&file, factories *&list, Pl_Status &status, PluginId &source) =0; virtual bool Query(PluginId id, const char *&file, Pl_Status &status, PluginId &source) =0;
/** /**
* @brief Checks another plugin's QueryRunning() status. * @brief Checks another plugin's QueryRunning() status.

View File

@ -28,14 +28,16 @@
#endif //version check #endif //version check
#endif //__GNUC__ #endif //__GNUC__
class IMetamodListener;
class ISmmPluginManager; class ISmmPluginManager;
class ISmmPlugin; class ISmmPlugin;
#define MMIFACE_SOURCEHOOK "ISourceHook"
#define MMIFACE_PLMANAGER "IPluginManager"
class ISmmAPI class ISmmAPI
{ {
public: public:
virtual ISmmPluginManager *PluginManager() =0;
virtual SourceHook::ISourceHook *SourceHook() =0;
virtual void LogMsg(ISmmPlugin *pl, const char *msg, ...) =0; virtual void LogMsg(ISmmPlugin *pl, const char *msg, ...) =0;
public: public:
virtual CreateInterfaceFn engineFactory(bool syn=true) =0; virtual CreateInterfaceFn engineFactory(bool syn=true) =0;
@ -64,8 +66,13 @@ public: //Added in 1.10 (1:0)
virtual void GetApiVersions(int &major, int &minor, int &plvers, int &plmin) =0; virtual void GetApiVersions(int &major, int &minor, int &plvers, int &plmin) =0;
//Returns sourcehook API version and implementation version //Returns sourcehook API version and implementation version
virtual void GetShVersions(int &shvers, int &shimpl) =0; virtual void GetShVersions(int &shvers, int &shimpl) =0;
//Binds an event listener to your plugin
virtual void AddListener(ISmmPlugin *plugin, IMetamodListener *pListener) =0;
//Queries the metamod factory
virtual void *MetaFactory(const char *iface, int *ret) =0;
}; };
/** Version history /** Version history
* 1.10 bumped API to 1:0. The breaking changes occured in sourcehook and the plugin API. * 1.10 bumped API to 1:0. The breaking changes occured in sourcehook and the plugin API.
*/ */

View File

@ -23,14 +23,6 @@
#define PLAPI_VERSION 7 #define PLAPI_VERSION 7
#define PLAPI_NAME "ISmmPlugin" #define PLAPI_NAME "ISmmPlugin"
struct factories
{
CreateInterfaceFn engine;
CreateInterfaceFn server;
CreateInterfaceFn physics;
CreateInterfaceFn fileSystem;
};
class ISmmAPI; class ISmmAPI;
typedef int PluginId; typedef int PluginId;
@ -57,7 +49,7 @@ public:
* @param maxlen Size of error message buffer * @param maxlen Size of error message buffer
* @return True if successful, return false to reject the load. * @return True if successful, return false to reject the load.
*/ */
virtual bool Load(PluginId id, ISmmAPI *ismm, factories *list, char *error, size_t maxlength, bool late) =0; virtual bool Load(PluginId id, ISmmAPI *ismm, char *error, size_t maxlength, bool late) =0;
/** /**
* @brief Called when your plugin is "queried". This is useful for rejecting a loaded * @brief Called when your plugin is "queried". This is useful for rejecting a loaded
@ -151,6 +143,60 @@ public:
} }
}; };
/**
* @brief Added in 1.2 so plugins could listen to specific events
*/
class IMetamodListener
{
public:
virtual ~IMetamodListener() { }
public:
virtual void OnPluginLoad(PluginId id) { }
virtual void OnPluginUnload(PluginId id) { }
virtual void OnPluginPause(PluginId id) { }
virtual void OnPluginUnpause(PluginId id) { }
virtual void OnLevelInit(char const *pMapName, char const *pMapEntities, char const *pOldLevel, char const *pLandmarkName, bool loadGame, bool background) { }
virtual void *OnEngineQuery(const char *iface, int *ret)
{
if (ret)
*ret = IFACE_FAILED;
return NULL;
}
virtual void *OnPhysicsQuery(const char *iface, int *ret)
{
if (ret)
*ret = IFACE_FAILED;
return NULL;
}
virtual void *OnFileSystemQuery(const char *iface, int *ret)
{
if (ret)
*ret = IFACE_FAILED;
return NULL;
}
virtual void *OnGameDLLQuery(const char *iface, int *ret)
{
if (ret)
*ret = IFACE_FAILED;
return NULL;
}
virtual void *OnMetamodQuery(const char *iface, int *ret)
{
if (ret)
*ret = IFACE_FAILED;
return NULL;
}
};
#define PL_EXPOSURE CreateInterface #define PL_EXPOSURE CreateInterface
#define PL_EXPOSURE_C "CreateInterface" #define PL_EXPOSURE_C "CreateInterface"
@ -174,7 +220,7 @@ public:
#define PLUGIN_SAVEVARS() \ #define PLUGIN_SAVEVARS() \
g_SMAPI = ismm; \ g_SMAPI = ismm; \
g_SHPtr = ismm->SourceHook(); \ g_SHPtr = ismm->MetaQuery(MMIFACE_SOURCEHOOK, NULL); \
g_PLAPI = static_cast<ISmmPlugin *>(this); \ g_PLAPI = static_cast<ISmmPlugin *>(this); \
g_PLID = id; g_PLID = id;

View File

@ -15,8 +15,11 @@
#include "sourcemm.h" #include "sourcemm.h"
#include "concommands.h" #include "concommands.h"
#include "CSmmAPI.h" #include "CSmmAPI.h"
#include "CPlugin.h"
#include "util.h" #include "util.h"
using namespace SourceMM;
/** /**
* @brief Implementation of main SourceMM GameDLL functionality * @brief Implementation of main SourceMM GameDLL functionality
* @file sourcemm.cpp * @file sourcemm.cpp
@ -45,6 +48,26 @@ SourceHook::CallClass<IServerGameDLL> *dllExec;
void ClearGamedllList(); void ClearGamedllList();
//helper macro
#define IFACE_MACRO(orig,nam) \
CPluginManager::CPlugin *pl; \
SourceHook::List<IMetamodListener *>::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);
/////////////////////////////////// ///////////////////////////////////
// Main code for HL2 Interaction // // Main code for HL2 Interaction //
/////////////////////////////////// ///////////////////////////////////
@ -115,7 +138,7 @@ bool DLLInit(CreateInterfaceFn engineFactory, CreateInterfaceFn physicsFactory,
} }
//This is where the magic happens //This is where the magic happens
SMM_API void *CreateInterface(const char *name, int *ret) SMM_API void *CreateInterface(const char *iface, int *ret)
{ {
if (!gParsedGameInfo) if (!gParsedGameInfo)
{ {
@ -317,10 +340,10 @@ SMM_API void *CreateInterface(const char *name, int *ret)
const char *str = "ServerGameDLL"; const char *str = "ServerGameDLL";
size_t len = strlen(str); size_t len = strlen(str);
if (strncmp(name, str, len) == 0) if (strncmp(iface, str, len) == 0)
{ {
//This is the interface we want! Right now we support versions 3 and 4. //This is the interface we want! Right now we support versions 3 and 4.
int version = atoi(&(name[len])); int version = atoi(&(iface[len]));
if (version < MIN_GAMEDLL_VERSION || version > MAX_GAMEDLL_VERSION) if (version < MIN_GAMEDLL_VERSION || version > MAX_GAMEDLL_VERSION)
{ {
Error("GameDLL version %d is not supported by Metamod!", version); Error("GameDLL version %d is not supported by Metamod!", version);
@ -332,7 +355,7 @@ SMM_API void *CreateInterface(const char *name, int *ret)
for (iter=gamedll_list.begin(); iter!=gamedll_list.end(); iter++) for (iter=gamedll_list.begin(); iter!=gamedll_list.end(); iter++)
{ {
pInfo = (*iter); pInfo = (*iter);
ptr = (pInfo->factory)(name, ret); ptr = (pInfo->factory)(iface, ret);
if (ptr) if (ptr)
{ {
//this is our gamedll. unload the others. //this is our gamedll. unload the others.
@ -361,8 +384,7 @@ SMM_API void *CreateInterface(const char *name, int *ret)
} }
//if we got here, there's definitely a gamedll. //if we got here, there's definitely a gamedll.
//META_INTERFACE_MACRO(server, g_GameDll.factory); IFACE_MACRO(g_GameDll.factory, GameDLL);
return (g_GameDll.factory)(name, ret);
} }
void ClearGamedllList() void ClearGamedllList()
@ -491,23 +513,23 @@ int LoadPluginsFromFile(const char *file)
//Wrapper function. This is called when the GameDLL thinks it's using //Wrapper function. This is called when the GameDLL thinks it's using
// the engine's real engineFactory. // the engine's real engineFactory.
void *EngineFactory(const char *name, int *ret) void *EngineFactory(const char *iface, int *ret)
{ {
META_INTERFACE_MACRO(engine, g_Engine.engineFactory); IFACE_MACRO(g_Engine.engineFactory, Engine);
} }
//Wrapper function. This is called when the GameDLL thinks it's using //Wrapper function. This is called when the GameDLL thinks it's using
// the engine's real physicsFactory. // the engine's real physicsFactory.
void *PhysicsFactory(const char *name, int *ret) void *PhysicsFactory(const char *iface, int *ret)
{ {
META_INTERFACE_MACRO(physics, g_Engine.physicsFactory); IFACE_MACRO(g_Engine.physicsFactory, Physics);
} }
//Wrapper function. This is called when the GameDLL thinks it's using //Wrapper function. This is called when the GameDLL thinks it's using
// the engine's real fileSystemFactory. // the engine's real fileSystemFactory.
void *FileSystemFactory(const char *name, int *ret) void *FileSystemFactory(const char *iface, int *ret)
{ {
META_INTERFACE_MACRO(fileSystem, g_Engine.fileSystemFactory); IFACE_MACRO(g_Engine.fileSystemFactory, FileSystem);
} }
void LogMessage(const char *msg, ...) void LogMessage(const char *msg, ...)

View File

@ -24,34 +24,4 @@ void UTIL_KeySplit(const char *str, char *buf1, size_t len1, char *buf2, size_t
void UTIL_PathFmt(char *buffer, size_t len, const char *fmt, ...); void UTIL_PathFmt(char *buffer, size_t len, const char *fmt, ...);
bool UTIL_PathCmp(const char *path1, const char *path2); bool UTIL_PathCmp(const char *path1, const char *path2);
#define META_INTERFACE_MACRO(type, final) \
PluginIter i; \
void *mret=NULL, *d; \
META_RES mres, high=MRES_IGNORED; \
g_SmmAPI.SetLastMetaReturn(MRES_IGNORED); \
for (i=g_PluginMngr._begin(); i!=g_PluginMngr._end(); i++) \
{ \
if ( (*i) && (*i)->fac_list. type ) \
{ \
d = ((*i)->fac_list. type)(name, ret); \
mres = g_SmmAPI.GetLastMetaReturn(); \
if (mres > high) \
high = mres; \
if (mres >= MRES_OVERRIDE) \
mret = d; \
} \
} \
if (high == MRES_OVERRIDE) \
{ \
if (final) \
(final)(name, ret); \
return mret; \
} else if (high == MRES_SUPERCEDE) { \
return mret; \
} else { \
if (final) \
return (final)(name, ret); \
return NULL; \
}
#endif //_INCLUDE_UTIL_H #endif //_INCLUDE_UTIL_H