Add khooks to source 2 provider

This commit is contained in:
Kenzzer 2025-04-19 18:01:49 +00:00
parent fe9b9ee3be
commit d548c9b3c4
No known key found for this signature in database
GPG Key ID: 64C3FD4332686DC1
5 changed files with 78 additions and 53 deletions

@ -1 +1 @@
Subproject commit cebbfc10f0a74852b79ce90fc918b28e4786632e
Subproject commit dd4ce82cbd9549485615d4c14a74def9b05f641e

View File

@ -121,23 +121,23 @@ void SourceProvider::Notify_DLLInit_Pre(CreateInterfaceFn engineFactory,
if (gameclients)
{
m_ClientCommand.Add(gameclients, false);
m_ClientCommand.Add(gameclients);
}
m_GameInit.Add(server, false);
m_LevelInit.Add(server, true);
m_LevelShutdown.Add(server, true);
m_GameInit.Add(server);
m_LevelInit.Add(server);
m_LevelShutdown.Add(server);
}
void SourceProvider::Notify_DLLShutdown_Pre()
{
m_GameInit.Remove(server, false);
m_LevelInit.Remove(server, true);
m_LevelShutdown.Remove(server, true);
m_GameInit.Remove(server);
m_LevelInit.Remove(server);
m_LevelShutdown.Remove(server);
if (gameclients)
{
m_ClientCommand.Remove(gameclients, false);
m_ClientCommand.Remove(gameclients);
}
m_ConVarAccessor.RemoveMetamodCommands();

View File

@ -45,18 +45,21 @@ static ISource2ServerConfig* serverconfig = NULL;
INetworkServerService* netservice = NULL;
IEngineServiceMgr* enginesvcmgr = NULL;
SH_DECL_HOOK2_void(IServerGameClients, ClientCommand, SH_NOATTRIB, 0, CPlayerSlot, const CCommand&);
SH_DECL_HOOK3_void(IEngineServiceMgr, RegisterLoopMode, SH_NOATTRIB, 0, const char *, ILoopModeFactory *, void **);
SH_DECL_HOOK3_void(IEngineServiceMgr, UnregisterLoopMode, SH_NOATTRIB, 0, const char*, ILoopModeFactory*, void**);
SH_DECL_HOOK0(ILoopModeFactory, CreateLoopMode, SH_NOATTRIB, 0, ILoopMode *);
SH_DECL_HOOK1_void(ILoopModeFactory, DestroyLoopMode, SH_NOATTRIB, 0, ILoopMode *);
SH_DECL_HOOK2(ILoopMode, LoopInit, SH_NOATTRIB, 0, bool, KeyValues*, ILoopModePrerequisiteRegistry *);
SH_DECL_HOOK0_void(ILoopMode, LoopShutdown, SH_NOATTRIB, 0);
#ifdef SHOULD_OVERRIDE_ALLOWDEDICATED_SERVER
SH_DECL_HOOK1(ISource2ServerConfig, AllowDedicatedServers, const, 0, bool, EUniverse);
#endif
Source2Provider::Source2Provider() :
m_RegisterLoopMode(&IEngineServiceMgr::RegisterLoopMode, this, &Source2Provider::Hook_RegisterLoopMode, nullptr),
m_UnregisterLoopMode(&IEngineServiceMgr::UnregisterLoopMode, this, &Source2Provider::Hook_UnregisterLoopMode, nullptr),
m_CreateLoopMode(&ILoopModeFactory::CreateLoopMode, this, nullptr, &Source2Provider::Hook_CreateLoopModePost),
m_DestroyLoopMode(&ILoopModeFactory::DestroyLoopMode, this, nullptr, &Source2Provider::Hook_DestroyLoopMode),
m_LoopInit(&ILoopMode::LoopInit, this, nullptr, &Source2Provider::Hook_LoopInitPost),
m_LoopShutdown(&ILoopMode::LoopShutdown, this, nullptr, &Source2Provider::Hook_LoopShutdownPost),
m_ClientCommand(&IServerGameClients::ClientCommand, this, &Source2Provider::Hook_ClientCommand, nullptr)
{
}
void Source2Provider::Notify_DLLInit_Pre(CreateInterfaceFn engineFactory,
CreateInterfaceFn serverFactory)
{
@ -138,15 +141,15 @@ void Source2Provider::Notify_DLLInit_Pre(CreateInterfaceFn engineFactory,
if (gameclients)
{
SH_ADD_HOOK(IServerGameClients, ClientCommand, gameclients, SH_MEMBER(this, &Source2Provider::Hook_ClientCommand), false);
m_ClientCommand.Add(gameclients);
}
#ifdef SHOULD_OVERRIDE_ALLOWDEDICATED_SERVER
SH_ADD_VPHOOK(ISource2ServerConfig, AllowDedicatedServers, serverconfig, SH_MEMBER(this, &Source2Provider::Hook_AllowDedicatedServers), false);
#endif
SH_ADD_HOOK(IEngineServiceMgr, RegisterLoopMode, enginesvcmgr, SH_MEMBER(this, &Source2Provider::Hook_RegisterLoopMode), false);
SH_ADD_HOOK(IEngineServiceMgr, UnregisterLoopMode, enginesvcmgr, SH_MEMBER(this, &Source2Provider::Hook_UnregisterLoopMode), false);
m_RegisterLoopMode.Add(enginesvcmgr);
m_UnregisterLoopMode.Add(enginesvcmgr);
}
void Source2Provider::Notify_DLLShutdown_Pre()
@ -156,12 +159,12 @@ void Source2Provider::Notify_DLLShutdown_Pre()
ConVar_Unregister();
SH_REMOVE_HOOK(IEngineServiceMgr, RegisterLoopMode, enginesvcmgr, SH_MEMBER(this, &Source2Provider::Hook_RegisterLoopMode), false);
SH_REMOVE_HOOK(IEngineServiceMgr, UnregisterLoopMode, enginesvcmgr, SH_MEMBER(this, &Source2Provider::Hook_UnregisterLoopMode), false);
m_RegisterLoopMode.Remove(enginesvcmgr);
m_UnregisterLoopMode.Remove(enginesvcmgr);
if (gameclients)
{
SH_REMOVE_HOOK(IServerGameClients, ClientCommand, gameclients, SH_MEMBER(this, &Source2Provider::Hook_ClientCommand), false);
m_ClientCommand.Remove(gameclients);
}
}
@ -387,48 +390,52 @@ void LocalCommand_Meta(const CCommandContext &, const CCommand& args)
}
}
void Source2Provider::Hook_RegisterLoopMode(const char *pszLoopModeName, ILoopModeFactory *pLoopModeFactory, void **ppGlobalPointer)
KHook::Return<void> Source2Provider::Hook_RegisterLoopMode(IEngineServiceMgr*, const char *pszLoopModeName, ILoopModeFactory *pLoopModeFactory, void **ppGlobalPointer)
{
if (!strcmp(pszLoopModeName, "game"))
{
SH_ADD_HOOK(ILoopModeFactory, CreateLoopMode, pLoopModeFactory, SH_MEMBER(this, &Source2Provider::Hook_CreateLoopModePost), true);
SH_ADD_HOOK(ILoopModeFactory, DestroyLoopMode, pLoopModeFactory, SH_MEMBER(this, &Source2Provider::Hook_DestroyLoopMode), false);
m_CreateLoopMode.Add(pLoopModeFactory);
m_DestroyLoopMode.Add(pLoopModeFactory);
if (nullptr != m_pCallbacks)
{
m_pCallbacks->OnGameInit();
}
}
return { KHook::Action::Ignore };
}
void Source2Provider::Hook_UnregisterLoopMode(const char* pszLoopModeName, ILoopModeFactory* pLoopModeFactory, void** ppGlobalPointer)
KHook::Return<void> Source2Provider::Hook_UnregisterLoopMode(IEngineServiceMgr*, const char* pszLoopModeName, ILoopModeFactory* pLoopModeFactory, void** ppGlobalPointer)
{
if (!strcmp(pszLoopModeName, "game"))
{
SH_REMOVE_HOOK(ILoopModeFactory, CreateLoopMode, pLoopModeFactory, SH_MEMBER(this, &Source2Provider::Hook_CreateLoopModePost), true);
SH_REMOVE_HOOK(ILoopModeFactory, DestroyLoopMode, pLoopModeFactory, SH_MEMBER(this, &Source2Provider::Hook_DestroyLoopMode), false);
m_CreateLoopMode.Remove(pLoopModeFactory);
m_DestroyLoopMode.Remove(pLoopModeFactory);
}
RETURN_META(MRES_IGNORED);
return { KHook::Action::Ignore };
}
ILoopMode *Source2Provider::Hook_CreateLoopModePost()
KHook::Return<ILoopMode*> Source2Provider::Hook_CreateLoopModePost(ILoopModeFactory*)
{
ILoopMode *pLoopMode = META_RESULT_ORIG_RET(ILoopMode *);
SH_ADD_HOOK(ILoopMode, LoopInit, pLoopMode, SH_MEMBER(this, &Source2Provider::Hook_LoopInitPost), true);
SH_ADD_HOOK(ILoopMode, LoopShutdown, pLoopMode, SH_MEMBER(this, &Source2Provider::Hook_LoopShutdownPost), true);
auto pLoopMode = (ILoopMode*)KHook::GetOriginalValuePtr();
m_LoopInit.Add(pLoopMode);
m_LoopShutdown.Add(pLoopMode);
// Post-hook. Ignored
return nullptr;
return { KHook::Action::Ignore, nullptr };
}
void Source2Provider::Hook_DestroyLoopMode(ILoopMode* pLoopMode)
KHook::Return<void> Source2Provider::Hook_DestroyLoopMode(ILoopModeFactory*, ILoopMode* pLoopMode)
{
SH_REMOVE_HOOK(ILoopMode, LoopInit, pLoopMode, SH_MEMBER(this, &Source2Provider::Hook_LoopInitPost), true);
SH_REMOVE_HOOK(ILoopMode, LoopShutdown, pLoopMode, SH_MEMBER(this, &Source2Provider::Hook_LoopShutdownPost), true);
m_LoopInit.Remove(pLoopMode);
m_LoopShutdown.Remove(pLoopMode);
return { KHook::Action::Ignore };
}
bool Source2Provider::Hook_LoopInitPost(KeyValues* pKeyValues, ILoopModePrerequisiteRegistry *pRegistry)
KHook::Return<bool> Source2Provider::Hook_LoopInitPost(ILoopMode*, KeyValues* pKeyValues, ILoopModePrerequisiteRegistry *pRegistry)
{
if (nullptr != m_pCallbacks)
{
@ -443,18 +450,20 @@ bool Source2Provider::Hook_LoopInitPost(KeyValues* pKeyValues, ILoopModePrerequi
}
// Post-hook. Ignored
return true;
return { KHook::Action::Ignore };
}
void Source2Provider::Hook_LoopShutdownPost()
KHook::Return<void> Source2Provider::Hook_LoopShutdownPost(ILoopMode*)
{
if (nullptr != m_pCallbacks)
{
m_pCallbacks->OnLevelShutdown();
}
return { KHook::Action::Ignore };
}
void Source2Provider::Hook_ClientCommand(CPlayerSlot nSlot, const CCommand& _cmd)
KHook::Return<void> Source2Provider::Hook_ClientCommand(IServerGameClients*, CPlayerSlot nSlot, const CCommand& _cmd)
{
GlobCommand cmd(&_cmd);
@ -465,8 +474,8 @@ void Source2Provider::Hook_ClientCommand(CPlayerSlot nSlot, const CCommand& _cmd
m_pCallbacks->OnCommand_ClientMeta(nSlot, &cmd);
}
RETURN_META(MRES_SUPERCEDE);
return { KHook::Action::Supercede };
}
RETURN_META(MRES_IGNORED);
return { KHook::Action::Ignore };
}

View File

@ -34,6 +34,7 @@
#include "../provider_base.h"
#include "tier1/utlvector.h"
#include "IEngineService.h"
#include "khook.hpp"
// TODO: is this still needed for Dota or CS2 on any platform?
#if SOURCE_ENGINE == SE_DOTA && defined( _WIN32 )
@ -46,6 +47,8 @@ class ISource2WorldSession;
class Source2Provider : public BaseProvider
{
public:
Source2Provider();
virtual void Notify_DLLInit_Pre(CreateInterfaceFn engineFactory, CreateInterfaceFn serverFactory) override;
virtual void Notify_DLLShutdown_Pre() override;
virtual bool ProcessVDF(const char* file, char path[], size_t path_len, char alias[], size_t alias_len) override;
@ -72,13 +75,26 @@ public:
#ifdef SHOULD_OVERRIDE_ALLOWDEDICATED_SERVER
bool Hook_AllowDedicatedServers(EUniverse universe) const;
#endif
void Hook_RegisterLoopMode(const char* pszLoopModeName, ILoopModeFactory *pLoopModeFactory, void **ppGlobalPointer);
void Hook_UnregisterLoopMode(const char* pszLoopModeName, ILoopModeFactory* pLoopModeFactory, void** ppGlobalPointer);
ILoopMode *Hook_CreateLoopModePost();
void Hook_DestroyLoopMode(ILoopMode*);
bool Hook_LoopInitPost(KeyValues* pKeyValues, ILoopModePrerequisiteRegistry *pRegistry);
void Hook_LoopShutdownPost();
void Hook_ClientCommand(CPlayerSlot nSlot, const CCommand& args);
KHook::Virtual<IEngineServiceMgr, void, const char*, ILoopModeFactory*, void **> m_RegisterLoopMode;
KHook::Return<void> Hook_RegisterLoopMode(IEngineServiceMgr*, const char* pszLoopModeName, ILoopModeFactory *pLoopModeFactory, void **ppGlobalPointer);
KHook::Virtual<IEngineServiceMgr, void, const char*, ILoopModeFactory*, void**> m_UnregisterLoopMode;
KHook::Return<void> Hook_UnregisterLoopMode(IEngineServiceMgr*, const char* pszLoopModeName, ILoopModeFactory* pLoopModeFactory, void** ppGlobalPointer);
KHook::Virtual<ILoopModeFactory, ILoopMode*> m_CreateLoopMode;
KHook::Return<ILoopMode*> Hook_CreateLoopModePost(ILoopModeFactory*);
KHook::Virtual<ILoopModeFactory, void, ILoopMode*> m_DestroyLoopMode;
KHook::Return<void> Hook_DestroyLoopMode(ILoopModeFactory*, ILoopMode*);
KHook::Virtual<ILoopMode, bool, KeyValues*, ILoopModePrerequisiteRegistry*> m_LoopInit;
KHook::Return<bool> Hook_LoopInitPost(ILoopMode*, KeyValues* pKeyValues, ILoopModePrerequisiteRegistry *pRegistry);
KHook::Virtual<ILoopMode, void> m_LoopShutdown;
KHook::Return<void> Hook_LoopShutdownPost(ILoopMode*);
KHook::Virtual<IServerGameClients, void, CPlayerSlot, const CCommand&> m_ClientCommand;
KHook::Return<void> Hook_ClientCommand(IServerGameClients*, CPlayerSlot nSlot, const CCommand& args);
private:
IFileSystem* baseFs = nullptr;
std::vector<CConVar<CUtlString> *> m_RegisteredConVars;

View File

@ -149,7 +149,7 @@ public:
if (g_plugin_unload != NULL)
{
CmdDispatch.Add(g_plugin_unload, false);
CmdDispatch.Add(g_plugin_unload);
}
return true;
@ -166,7 +166,7 @@ public:
if (g_plugin_unload != NULL)
{
CmdDispatch.Remove(g_plugin_unload, false);
CmdDispatch.Remove(g_plugin_unload);
g_plugin_unload = NULL;
}
if (!g_Metamod.IsLoadedAsGameDLL())