1
0
mirror of https://github.com/alliedmodders/metamod-source.git synced 2025-02-17 10:54:14 +01:00

Initial version of GameInit, LevelInit, LevelShutdown hookup; removed cmds to manually trigger them.

This commit is contained in:
Nicholas Hastings 2015-07-11 13:59:51 -04:00
parent 1c7fb146ff
commit a73b63cb51
4 changed files with 240 additions and 60 deletions

View File

@ -37,6 +37,9 @@
#if defined __linux__
#include <sys/stat.h>
#endif
#if SOURCE_ENGINE == SE_SOURCE2
#include <iserver.h>
#endif
using namespace SourceMM;
using namespace SourceHook;
@ -47,6 +50,35 @@ using namespace SourceHook::Impl;
* @file sourcemm.cpp
*/
#if SOURCE_ENGINE == SE_SOURCE2
// Hack to make hook decl compile when only having forward decl in header.
// (we have class structure but it requires protobuf which we don't want to include here)
class GameSessionConfiguration_t { };
SH_DECL_MANUALHOOK4_void(SGD_StartupServer, 0, 0, 0, const GameSessionConfiguration_t &, INetworkGameServerFactory *, ISource2WorldSession *, const char *);
SH_DECL_MANUALHOOK2_void(SGD_Init, 0, 0, 0, GameSessionConfiguration_t *, const char *);
SH_DECL_MANUALHOOK0(SGD_StartChangeLevel, 0, 0, 0, CUtlVector<INetworkGameClient *> *);
SH_DECL_MANUALHOOK5_void(SGD_SwitchToLoop, 0, 0, 0, const char *, KeyValues *, uint32, const char *, bool);
SH_DECL_MANUALHOOK3(SGD_AllocateServer, 0, 0, 0, INetworkGameServer *, int, INetworkServerService *, ISource2WorldSession *);
static INetworkGameServer *
Handler_AllocateServer(int, INetworkServerService *, ISource2WorldSession *);
static void
Handler_SwitchToLoop(const char *, KeyValues *, uint32, const char *, bool);
static void
Handler_StartupServer(const GameSessionConfiguration_t &, INetworkGameServerFactory *, ISource2WorldSession *, const char *);
static void
Handler_StartupServer_Post(const GameSessionConfiguration_t &, INetworkGameServerFactory *, ISource2WorldSession *, const char *);
static void
Handler_Init(GameSessionConfiguration_t *, const char *);
static CUtlVector<INetworkGameClient *> *
Handler_StartChangeLevel();
#else
SH_DECL_MANUALHOOK0(SGD_GameInit, 0, 0, 0, bool);
SH_DECL_MANUALHOOK6(SGD_LevelInit, 0, 0, 0, bool, const char *, const char *, const char *, const char *, bool, bool);
SH_DECL_MANUALHOOK0_void(SGD_LevelShutdown, 0, 0, 0);
@ -64,6 +96,7 @@ Handler_LevelInit(char const *pMapName,
static bool
Handler_GameInit();
#endif
static void
InitializeVSP();
@ -142,21 +175,6 @@ SourceMM::ISmmAPI *g_pMetamod = &g_Metamod;
} \
}
#if SOURCE_ENGINE == SE_SOURCE2
void meta_game_init(const CCommand &args)
{
Handler_GameInit();
}
void meta_level_init(const CCommand &args)
{
Handler_LevelInit("dummy_level", "", "", "", false, false);
}
void meta_level_shutdown(const CCommand &args)
{
Handler_LevelShutdown();
}
#endif
/* Initialize everything here */
void
mm_InitializeForLoad()
@ -171,7 +189,24 @@ mm_InitializeForLoad()
*/
in_first_level = true;
#if SOURCE_ENGINE != SE_SOURCE2
#if SOURCE_ENGINE == SE_SOURCE2
SourceHook::MemFuncInfo info;
if (!provider->GetHookInfo(ProvidedHook_StartupServer, &info))
{
provider->DisplayError("Metamod:Source could not find a valid hook for INetworkServerService::StartupServer");
}
SH_MANUALHOOK_RECONFIGURE(SGD_StartupServer, info.vtblindex, info.vtbloffs, info.thisptroffs);
SH_ADD_MANUALHOOK(SGD_StartupServer, netservice, SH_STATIC(Handler_StartupServer), false);
SH_ADD_MANUALHOOK(SGD_StartupServer, netservice, SH_STATIC(Handler_StartupServer_Post), true);
if (!provider->GetHookInfo(ProvidedHook_SwitchToLoop, &info))
{
provider->DisplayError("Metamod:Source could not find a valid hook for IEngineServiceMgr::SwitchToLoop");
}
SH_MANUALHOOK_RECONFIGURE(SGD_SwitchToLoop, info.vtblindex, info.vtbloffs, info.thisptroffs);
SH_ADD_MANUALHOOK(SGD_SwitchToLoop, enginesvcmgr, SH_STATIC(Handler_SwitchToLoop), false);
#else
SourceHook::MemFuncInfo info;
if (!provider->GetHookInfo(ProvidedHook_GameInit, &info))
@ -485,30 +520,6 @@ mm_InitializeGlobals(CreateInterfaceFn engineFactory,
provider->Notify_DLLInit_Pre(engineFactory, gamedll_info.factory);
}
static bool
Handler_GameInit()
{
if (is_game_init)
return true;
if (vsp_load_requested)
InitializeVSP();
if (g_bIsVspBridged && !were_plugins_loaded)
{
DoInitialPluginLoads();
g_PluginMngr.SetAllLoaded();
were_plugins_loaded = true;
}
is_game_init = true;
#if SOURCE_ENGINE == SE_SOURCE2
return true;
#else
RETURN_META_VALUE(MRES_IGNORED, true);
#endif
}
void
mm_UnloadMetamod()
{
@ -521,8 +532,35 @@ mm_UnloadMetamod()
}
static void
Handler_LevelShutdown(void)
mm_HandleGameInit()
{
if (is_game_init)
return;
#if SOURCE_ENGINE == SE_SOURCE2
Msg("MMS: GameInit\n");
#endif
if (vsp_load_requested)
InitializeVSP();
if (g_bIsVspBridged && !were_plugins_loaded)
{
DoInitialPluginLoads();
g_PluginMngr.SetAllLoaded();
were_plugins_loaded = true;
}
is_game_init = true;
}
static void
mm_HandleLevelShutdown()
{
#if SOURCE_ENGINE == SE_SOURCE2
Msg("MMS: LevelShutdown\n");
#endif
if (g_bIsVspBridged && !were_plugins_loaded)
{
DoInitialPluginLoads();
@ -553,11 +591,120 @@ Handler_LevelShutdown(void)
}
ITER_EVENT(OnLevelShutdown, ());
}
static void
mm_HandleLevelInit(char const *pMapName,
char const *pMapEntities,
char const *pOldLevel,
char const *pLandmarkName,
bool loadGame,
bool background)
{
#if SOURCE_ENGINE == SE_SOURCE2
#else
RETURN_META(MRES_IGNORED);
Msg("MMS: LevelInit\n");
#endif
ITER_EVENT(OnLevelInit, (pMapName, pMapEntities, pOldLevel, pLandmarkName, loadGame, background));
}
#include <utlbuffer.h>
#if SOURCE_ENGINE == SE_SOURCE2
static void
Handler_SwitchToLoop(const char *pszLoopName, KeyValues *pKV, uint32 nId, const char *pszUnk, bool bUnk)
{
if (strcmp(pszLoopName, "levelload") == 0)
{
mm_HandleGameInit();
}
RETURN_META(MRES_IGNORED);
}
static void
Handler_StartupServer(const GameSessionConfiguration_t &config, INetworkGameServerFactory *pFactory, ISource2WorldSession *, const char *)
{
SourceHook::MemFuncInfo info;
if (!provider->GetHookInfo(ProvidedHook_AllocateServer, &info))
{
provider->DisplayError("Metamod:Source could not find a valid hook for INetworkGameServerFactory::Allocate");
}
SH_MANUALHOOK_RECONFIGURE(SGD_AllocateServer, info.vtblindex, info.vtbloffs, info.thisptroffs);
SH_ADD_MANUALHOOK(SGD_AllocateServer, pFactory, SH_STATIC(Handler_AllocateServer), true);
RETURN_META(MRES_IGNORED);
}
static void
Handler_StartupServer_Post(const GameSessionConfiguration_t &config, INetworkGameServerFactory *pFactory, ISource2WorldSession *, const char *)
{
SH_REMOVE_MANUALHOOK(SGD_AllocateServer, pFactory, SH_STATIC(Handler_AllocateServer), true);
RETURN_META(MRES_IGNORED);
}
static INetworkGameServer *
Handler_AllocateServer(int, INetworkServerService *, ISource2WorldSession *)
{
static bool bGameServerHooked = false;
if (!bGameServerHooked)
{
INetworkGameServer *netserver = META_RESULT_ORIG_RET(INetworkGameServer *);
SourceHook::MemFuncInfo info;
if (!provider->GetHookInfo(ProvidedHook_Init, &info))
{
provider->DisplayError("Metamod:Source could not find a valid hook for INetworkGameServer::Init");
}
SH_MANUALHOOK_RECONFIGURE(SGD_Init, info.vtblindex, info.vtbloffs, info.thisptroffs);
SH_ADD_MANUALVPHOOK(SGD_Init, netserver, SH_STATIC(Handler_Init), false);
if (!provider->GetHookInfo(ProvidedHook_StartChangeLevel, &info))
{
provider->DisplayError("Metamod:Source could not find a valid hook for INetworkGameServer::StartChangeLevel");
}
SH_MANUALHOOK_RECONFIGURE(SGD_StartChangeLevel, info.vtblindex, info.vtbloffs, info.thisptroffs);
SH_ADD_MANUALVPHOOK(SGD_StartChangeLevel, netserver, SH_STATIC(Handler_StartChangeLevel), false);
bGameServerHooked = true;
}
RETURN_META_VALUE(MRES_IGNORED, nullptr);
}
static void
Handler_Init(GameSessionConfiguration_t *pConfig, const char *pszMapName)
{
static char szLastMap[260] = "";
mm_HandleLevelInit(pszMapName, "", szLastMap, "", false, false);
UTIL_Format(szLastMap, sizeof(szLastMap), "%s", pszMapName);
RETURN_META(MRES_IGNORED);
}
static CUtlVector<INetworkGameClient *> *
Handler_StartChangeLevel()
{
mm_HandleLevelShutdown();
RETURN_META_VALUE(MRES_IGNORED, nullptr);
}
#else
static bool
Handler_GameInit()
{
mm_HandleGameInit();
RETURN_META_VALUE(MRES_IGNORED, true);
}
static void
Handler_LevelShutdown(void)
{
mm_HandleLevelShutdown();
RETURN_META(MRES_IGNORED);
}
static bool
@ -570,12 +717,9 @@ Handler_LevelInit(char const *pMapName,
{
ITER_EVENT(OnLevelInit, (pMapName, pMapEntities, pOldLevel, pLandmarkName, loadGame, background));
#if SOURCE_ENGINE == SE_SOURCE2
return false;
#else
RETURN_META_VALUE(MRES_IGNORED, false);
#endif
}
#endif
void MetamodSource::LogMsg(ISmmPlugin *pl, const char *msg, ...)
{

View File

@ -37,9 +37,17 @@ namespace SourceMM
enum ProvidedHooks
{
#if SOURCE_ENGINE == SE_SOURCE2
ProvidedHook_StartChangeLevel = 0,
ProvidedHook_Init = 1,
ProvidedHook_StartupServer = 2,
ProvidedHook_SwitchToLoop = 3,
ProvidedHook_AllocateServer = 4,
#else
ProvidedHook_LevelInit = 0, /**< IServerGameDLL::LevelInit */
ProvidedHook_LevelShutdown = 1, /**< IServerGameDLL::LevelShutdown */
ProvidedHook_GameInit = 4, /**< IServerGameDLL::GameInit */
#endif
};
/**

View File

@ -39,6 +39,9 @@
#include <filesystem.h>
#include "metamod.h"
#include <tier1/KeyValues.h>
#if SOURCE_ENGINE == SE_SOURCE2
#include <iserver.h>
#endif
#if SOURCE_ENGINE == SE_SOURCE2
SH_DECL_HOOK1(ISource2ServerConfig, AllowDedicatedServers, const, 0, bool, EUniverse);
@ -103,17 +106,14 @@ IFileSystem *baseFs = NULL;
IServerGameDLL *server = NULL;
#if SOURCE_ENGINE == SE_SOURCE2
static ISource2ServerConfig *serverconfig = NULL;
INetworkServerService *netservice = NULL;
IEngineServiceMgr *enginesvcmgr = NULL;
#endif
IVEngineServer *engine = NULL;
IServerGameClients *gameclients = NULL;
CGlobalVars *gpGlobals = NULL;
IMetamodSourceProvider *provider = &g_Ep1Provider;
ConCommand meta_local_cmd("meta", LocalCommand_Meta, "Metamod:Source control options");
#if SOURCE_ENGINE == SE_SOURCE2
ConCommand _meta_game_init("meta_game_init", meta_game_init);
ConCommand _meta_level_init("meta_level_init", meta_level_init);
ConCommand _meta_level_shutdown("meta_level_shutdown", meta_level_shutdown);
#endif
#if SOURCE_ENGINE == SE_DOTA || SOURCE_ENGINE == SE_SOURCE2
SH_DECL_HOOK2_void(IServerGameClients, ClientCommand, SH_NOATTRIB, 0, CEntityIndex, const CCommand &);
@ -144,6 +144,8 @@ void BaseProvider::Notify_DLLInit_Pre(CreateInterfaceFn engineFactory,
#if SOURCE_ENGINE == SE_SOURCE2
gpGlobals = engine->GetServerGlobals();
serverconfig = (ISource2ServerConfig *) ((serverFactory) (INTERFACEVERSION_SERVERCONFIG, NULL));
netservice = (INetworkServerService *) ((engineFactory) (NETWORKSERVERSERVICE_INTERFACE_VERSION, NULL));
enginesvcmgr = (IEngineServiceMgr *) ((engineFactory) (ENGINESERVICEMGR_INTERFACE_VERSION, NULL));
#endif
#if SOURCE_ENGINE >= SE_ORANGEBOX
icvar = (ICvar *)((engineFactory)(CVAR_INTERFACE_VERSION, NULL));
@ -177,11 +179,6 @@ void BaseProvider::Notify_DLLInit_Pre(CreateInterfaceFn engineFactory,
#endif
g_SMConVarAccessor.RegisterConCommandBase(&meta_local_cmd);
#if SOURCE_ENGINE == SE_SOURCE2
g_SMConVarAccessor.RegisterConCommandBase(&_meta_game_init);
g_SMConVarAccessor.RegisterConCommandBase(&_meta_level_init);
g_SMConVarAccessor.RegisterConCommandBase(&_meta_level_shutdown);
#endif
CacheUserMessages();
@ -308,7 +305,34 @@ bool BaseProvider::LogMessage(const char *buffer)
bool BaseProvider::GetHookInfo(ProvidedHooks hook, SourceHook::MemFuncInfo *pInfo)
{
#if SOURCE_ENGINE != SE_SOURCE2
#if SOURCE_ENGINE == SE_SOURCE2
SourceHook::MemFuncInfo mfi = {true, -1, 0, 0};
switch (hook)
{
case ProvidedHook_StartupServer:
SourceHook::GetFuncInfo(&INetworkServerService::StartupServer, mfi);
break;
case ProvidedHook_StartChangeLevel:
SourceHook::GetFuncInfo(&INetworkGameServer::StartChangeLevel, mfi);
break;
case ProvidedHook_Init:
SourceHook::GetFuncInfo(&INetworkGameServer::Init, mfi);
break;
case ProvidedHook_SwitchToLoop:
SourceHook::GetFuncInfo(&IEngineServiceMgr::SwitchToLoop, mfi);
break;
case ProvidedHook_AllocateServer:
SourceHook::GetFuncInfo(&INetworkGameServerFactory::Allocate, mfi);
break;
default:
return false;
}
*pInfo = mfi;
return (mfi.thisptroffs >= 0);
#else
SourceHook::MemFuncInfo mfi = {true, -1, 0, 0};
if (hook == ProvidedHook_LevelInit)
@ -327,8 +351,6 @@ bool BaseProvider::GetHookInfo(ProvidedHooks hook, SourceHook::MemFuncInfo *pInf
*pInfo = mfi;
return (mfi.thisptroffs >= 0);
#else
return false;
#endif
}

View File

@ -46,6 +46,8 @@
using namespace SourceMM;
using namespace SourceHook;
class INetworkGameServer;
class BaseProvider : public IMetamodSourceProvider
{
public:
@ -89,6 +91,10 @@ extern IServerGameDLL *server;
extern IServerGameClients *gameclients;
extern ICvar *icvar;
extern CGlobalVars *gpGlobals;
#if SOURCE_ENGINE == SE_SOURCE2
extern INetworkServerService *netservice;
extern IEngineServiceMgr *enginesvcmgr;
#endif
#endif //_INCLUDE_METAMOD_SOURCE_BASE_PROVIDER_H_