mirror of
https://github.com/alliedmodders/metamod-source.git
synced 2024-11-29 11:24:19 +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:
parent
f3fb7f304d
commit
2cabdcf3da
@ -39,7 +39,7 @@ CPluginManager::~CPluginManager()
|
||||
|
||||
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)
|
||||
@ -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);
|
||||
pl->m_Status = Pl_Error;
|
||||
} 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;
|
||||
if (m_AllLoaded)
|
||||
@ -409,7 +409,7 @@ bool CPluginManager::UnloadAll()
|
||||
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);
|
||||
|
||||
@ -417,7 +417,6 @@ bool CPluginManager::Query(PluginId id, const char *&file, factories *&list, Pl_
|
||||
return false;
|
||||
|
||||
file = pl->m_File.c_str();
|
||||
list = &(pl->fac_list);
|
||||
status = pl->m_Status;
|
||||
source = pl->m_Source;
|
||||
|
||||
|
@ -61,9 +61,9 @@ namespace SourceMM
|
||||
PluginId m_Source;
|
||||
ISmmPlugin *m_API;
|
||||
HINSTANCE m_Lib;
|
||||
factories fac_list;
|
||||
SourceHook::List<ConCommandBase *> m_Cvars;
|
||||
SourceHook::List<ConCommandBase *> m_Cmds;
|
||||
SourceHook::List<IMetamodListener *> m_Events;
|
||||
};
|
||||
public:
|
||||
CPluginManager();
|
||||
@ -76,7 +76,7 @@ namespace SourceMM
|
||||
bool Unpause(PluginId id, char *error, size_t maxlen);
|
||||
bool UnloadAll();
|
||||
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);
|
||||
|
||||
void AddPluginCvar(ISmmPlugin *api, ConCommandBase *pCvar);
|
||||
|
@ -28,16 +28,6 @@ CSmmAPI::CSmmAPI()
|
||||
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, ...)
|
||||
{
|
||||
va_list ap;
|
||||
@ -139,6 +129,58 @@ void CSmmAPI::ConPrintf(const char *fmt, ...)
|
||||
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. //
|
||||
// (note: you can find the offset by looking for the text //
|
||||
|
@ -27,8 +27,6 @@ namespace SourceMM
|
||||
public:
|
||||
CSmmAPI::CSmmAPI();
|
||||
public:
|
||||
ISmmPluginManager *PluginManager();
|
||||
SourceHook::ISourceHook *SourceHook();
|
||||
void LogMsg(ISmmPlugin *pl, const char *msg, ...);
|
||||
public:
|
||||
CreateInterfaceFn engineFactory(bool syn=true);
|
||||
@ -50,6 +48,8 @@ namespace SourceMM
|
||||
}
|
||||
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);
|
||||
public:
|
||||
bool CacheCmds();
|
||||
private:
|
||||
|
@ -110,7 +110,7 @@ public:
|
||||
* @param source By reference source of plugin
|
||||
* @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.
|
||||
|
@ -28,14 +28,16 @@
|
||||
#endif //version check
|
||||
#endif //__GNUC__
|
||||
|
||||
class IMetamodListener;
|
||||
class ISmmPluginManager;
|
||||
class ISmmPlugin;
|
||||
|
||||
#define MMIFACE_SOURCEHOOK "ISourceHook"
|
||||
#define MMIFACE_PLMANAGER "IPluginManager"
|
||||
|
||||
class ISmmAPI
|
||||
{
|
||||
public:
|
||||
virtual ISmmPluginManager *PluginManager() =0;
|
||||
virtual SourceHook::ISourceHook *SourceHook() =0;
|
||||
virtual void LogMsg(ISmmPlugin *pl, const char *msg, ...) =0;
|
||||
public:
|
||||
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;
|
||||
//Returns sourcehook API version and implementation version
|
||||
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
|
||||
* 1.10 bumped API to 1:0. The breaking changes occured in sourcehook and the plugin API.
|
||||
*/
|
||||
|
@ -23,14 +23,6 @@
|
||||
#define PLAPI_VERSION 7
|
||||
#define PLAPI_NAME "ISmmPlugin"
|
||||
|
||||
struct factories
|
||||
{
|
||||
CreateInterfaceFn engine;
|
||||
CreateInterfaceFn server;
|
||||
CreateInterfaceFn physics;
|
||||
CreateInterfaceFn fileSystem;
|
||||
};
|
||||
|
||||
class ISmmAPI;
|
||||
typedef int PluginId;
|
||||
|
||||
@ -57,7 +49,7 @@ public:
|
||||
* @param maxlen Size of error message buffer
|
||||
* @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
|
||||
@ -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_C "CreateInterface"
|
||||
|
||||
@ -174,7 +220,7 @@ public:
|
||||
|
||||
#define PLUGIN_SAVEVARS() \
|
||||
g_SMAPI = ismm; \
|
||||
g_SHPtr = ismm->SourceHook(); \
|
||||
g_SHPtr = ismm->MetaQuery(MMIFACE_SOURCEHOOK, NULL); \
|
||||
g_PLAPI = static_cast<ISmmPlugin *>(this); \
|
||||
g_PLID = id;
|
||||
|
||||
|
@ -15,8 +15,11 @@
|
||||
#include "sourcemm.h"
|
||||
#include "concommands.h"
|
||||
#include "CSmmAPI.h"
|
||||
#include "CPlugin.h"
|
||||
#include "util.h"
|
||||
|
||||
using namespace SourceMM;
|
||||
|
||||
/**
|
||||
* @brief Implementation of main SourceMM GameDLL functionality
|
||||
* @file sourcemm.cpp
|
||||
@ -45,6 +48,26 @@ SourceHook::CallClass<IServerGameDLL> *dllExec;
|
||||
|
||||
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 //
|
||||
///////////////////////////////////
|
||||
@ -115,7 +138,7 @@ bool DLLInit(CreateInterfaceFn engineFactory, CreateInterfaceFn physicsFactory,
|
||||
}
|
||||
|
||||
//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)
|
||||
{
|
||||
@ -317,10 +340,10 @@ SMM_API void *CreateInterface(const char *name, int *ret)
|
||||
const char *str = "ServerGameDLL";
|
||||
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.
|
||||
int version = atoi(&(name[len]));
|
||||
int version = atoi(&(iface[len]));
|
||||
if (version < MIN_GAMEDLL_VERSION || version > MAX_GAMEDLL_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++)
|
||||
{
|
||||
pInfo = (*iter);
|
||||
ptr = (pInfo->factory)(name, ret);
|
||||
ptr = (pInfo->factory)(iface, ret);
|
||||
if (ptr)
|
||||
{
|
||||
//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.
|
||||
//META_INTERFACE_MACRO(server, g_GameDll.factory);
|
||||
return (g_GameDll.factory)(name, ret);
|
||||
IFACE_MACRO(g_GameDll.factory, GameDLL);
|
||||
}
|
||||
|
||||
void ClearGamedllList()
|
||||
@ -491,23 +513,23 @@ int LoadPluginsFromFile(const char *file)
|
||||
|
||||
//Wrapper function. This is called when the GameDLL thinks it's using
|
||||
// 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
|
||||
// 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
|
||||
// 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, ...)
|
||||
|
@ -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, ...);
|
||||
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
|
||||
|
Loading…
Reference in New Issue
Block a user