Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Templated SourceHook #176

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
22 changes: 17 additions & 5 deletions core/ISmmPlugin.h
Original file line number Diff line number Diff line change
Expand Up @@ -475,12 +475,24 @@ using namespace SourceMM;
/**
* @brief This should be in one of your header files, if you wish
* to use values like g_SHPtr in other files.
* This also creates helpers for accessing the SourceHook templates.
*/
#define PLUGIN_GLOBALVARS() \
extern SourceHook::ISourceHook *g_SHPtr; \
extern ISmmAPI *g_SMAPI; \
extern ISmmPlugin *g_PLAPI; \
extern PluginId g_PLID;
#define PLUGIN_GLOBALVARS() \
extern SourceHook::ISourceHook *g_SHPtr; \
extern ISmmAPI *g_SMAPI; \
extern ISmmPlugin *g_PLAPI; \
extern PluginId g_PLID; \
namespace SourceHook \
{ \
template <typename Interface, auto Method, typename Result, typename... Args> \
struct Hook : public ::SourceHook::HookImpl<&g_SHPtr, &g_PLID, Interface, Method, Result, Args...> \
Mooshua marked this conversation as resolved.
Show resolved Hide resolved
{ \
}; \
template <typename Interface, auto Method, typename Result, typename... Args> \
struct FmtHook : public ::SourceHook::FmtHookImpl<&g_SHPtr, &g_PLID, Interface, Method, Result, Args...> \
{ \
}; \
}

/**
* @brief This should be the first line in your Load callback.
Expand Down
11 changes: 11 additions & 0 deletions core/metamod_provider.h
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,17 @@ extern PluginId g_PLID;
extern SourceHook::ISourceHook *g_SHPtr;
extern SourceMM::IMetamodSourceProvider *provider;
extern SourceMM::ISmmAPI *g_pMetamod;
namespace SourceHook
{
template <typename Interface, auto Method, typename Result, typename... Args>
struct Hook : public ::SourceHook::HookImpl<&g_SHPtr, &g_PLID, Interface, Method, Result, Args...>
{
};
template <typename Interface, auto Method, typename Result, typename... Args>
struct FmtHook : public ::SourceHook::FmtHookImpl<&g_SHPtr, &g_PLID, Interface, Method, Result, Args...>
{
};
}

#endif //_INCLUDE_METAMOD_SOURCE_SUPPORT_H_

49 changes: 22 additions & 27 deletions core/provider/source/provider_source.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,14 +44,14 @@ static SourceProvider g_SourceProvider;

IMetamodSourceProvider* provider = &g_SourceProvider;

SH_DECL_HOOK0(IServerGameDLL, GameInit, SH_NOATTRIB, 0, bool);
SH_DECL_HOOK6(IServerGameDLL, LevelInit, SH_NOATTRIB, 0, bool, const char*, const char*, const char*, const char*, bool, bool);
SH_DECL_HOOK0_void(IServerGameDLL, LevelShutdown, SH_NOATTRIB, 0);
auto OnGameInit = SourceHook::Hook<IServerGameDLL, &IServerGameDLL::GameInit, bool>::Make();
Mooshua marked this conversation as resolved.
Show resolved Hide resolved
auto OnLevelInit = SourceHook::Hook<IServerGameDLL, &IServerGameDLL::LevelInit, bool, const char*, const char*, const char*, const char*, bool, bool>::Make();
auto OnLevelShutdown = SourceHook::Hook<IServerGameDLL, &IServerGameDLL::LevelShutdown, void>::Make();

#if SOURCE_ENGINE >= SE_ORANGEBOX
SH_DECL_HOOK2_void(IServerGameClients, ClientCommand, SH_NOATTRIB, 0, edict_t*, const CCommand&);
auto OnClientCommand = SourceHook::Hook<IServerGameClients, &IServerGameClients::ClientCommand, void, edict_t*, const CCommand&>::Make();
#else
SH_DECL_HOOK1_void(IServerGameClients, ClientCommand, SH_NOATTRIB, 0, edict_t*);
auto OnClientCommand = SourceHook::Hook<IServerGameClients, &IServerGameClients::ClientCommand, void, edict_t*>::Make();
#endif

void SourceProvider::Notify_DLLInit_Pre(CreateInterfaceFn engineFactory,
Expand All @@ -69,34 +69,30 @@ void SourceProvider::Notify_DLLInit_Pre(CreateInterfaceFn engineFactory,
}
}
#else
engine = (IVEngineServer*)((engineFactory)(INTERFACEVERSION_VENGINESERVER, NULL));
engine = (IVEngineServer *) ((engineFactory)(INTERFACEVERSION_VENGINESERVER, NULL));
#endif
if (!engine)
{
if (!engine) {
DisplayError("Could not find IVEngineServer! Metamod cannot load.");
return;
}

#if SOURCE_ENGINE >= SE_ORANGEBOX
icvar = (ICvar*)((engineFactory)(CVAR_INTERFACE_VERSION, NULL));
icvar = (ICvar *) ((engineFactory)(CVAR_INTERFACE_VERSION, NULL));
#else
icvar = (ICvar*)((engineFactory)(VENGINE_CVAR_INTERFACE_VERSION, NULL));
#endif
if (!icvar)
{
if (!icvar) {
DisplayError("Could not find ICvar! Metamod cannot load.");
return;
}

if ((gameclients = (IServerGameClients*)(serverFactory("ServerGameClients003", NULL)))
== NULL)
{
gameclients = (IServerGameClients*)(serverFactory("ServerGameClients004", NULL));
if ((gameclients = (IServerGameClients *) (serverFactory("ServerGameClients003", NULL)))
== NULL) {
gameclients = (IServerGameClients *) (serverFactory("ServerGameClients004", NULL));
}

baseFs = (IFileSystem*)((engineFactory)(FILESYSTEM_INTERFACE_VERSION, NULL));
if (baseFs == NULL)
{
baseFs = (IFileSystem *) ((engineFactory)(FILESYSTEM_INTERFACE_VERSION, NULL));
if (baseFs == NULL) {
mm_LogMessage("Unable to find \"%s\": .vdf files will not be parsed", FILESYSTEM_INTERFACE_VERSION);
}

Expand All @@ -122,21 +118,20 @@ void SourceProvider::Notify_DLLInit_Pre(CreateInterfaceFn engineFactory,
}
#endif

if (gameclients)
{
SH_ADD_HOOK(IServerGameClients, ClientCommand, gameclients, SH_MEMBER(this, &SourceProvider::Hook_ClientCommand), false);
if (gameclients) {
OnClientCommand->Add(gameclients, false, SH_MEMBER(this, &SourceProvider::Hook_ClientCommand));
}

SH_ADD_HOOK(IServerGameDLL, GameInit, server, SH_MEMBER(this, &SourceProvider::Hook_GameInit), false);
SH_ADD_HOOK(IServerGameDLL, LevelInit, server, SH_MEMBER(this, &SourceProvider::Hook_LevelInit), true);
SH_ADD_HOOK(IServerGameDLL, LevelShutdown, server, SH_MEMBER(this, &SourceProvider::Hook_LevelShutdown), true);
OnGameInit->Add(server, false, SH_MEMBER(this, &SourceProvider::Hook_GameInit));
OnLevelInit->Add(server, true, SH_MEMBER(this, &SourceProvider::Hook_LevelInit));
OnLevelShutdown->Add(server, true, SH_MEMBER(this, &SourceProvider::Hook_LevelShutdown));
}

void SourceProvider::Notify_DLLShutdown_Pre()
{
SH_REMOVE_HOOK(IServerGameDLL, GameInit, server, SH_MEMBER(this, &SourceProvider::Hook_GameInit), false);
SH_REMOVE_HOOK(IServerGameDLL, LevelInit, server, SH_MEMBER(this, &SourceProvider::Hook_LevelInit), true);
SH_REMOVE_HOOK(IServerGameDLL, LevelShutdown, server, SH_MEMBER(this, &SourceProvider::Hook_LevelShutdown), true);
OnGameInit->Remove(server, false, SH_MEMBER(this, &SourceProvider::Hook_GameInit));
OnLevelInit->Remove(server, true, SH_MEMBER(this, &SourceProvider::Hook_LevelInit));
OnLevelShutdown->Remove(server, true, SH_MEMBER(this, &SourceProvider::Hook_LevelShutdown));

m_ConVarAccessor.RemoveMetamodCommands();

Expand Down
Loading
Loading