From ba23929c3d152ec013af635b2f6ba3e8abd86fad Mon Sep 17 00:00:00 2001 From: Pavol Marko Date: Sun, 17 Apr 2005 18:43:21 +0000 Subject: [PATCH] YAMS --HG-- extra : convert_revision : svn%3Ac2935e3e-5518-0410-8daf-afa5dab7d4e3/trunk%4015 --- sourcemm/CHLTVDirector.h | 22 +++++--- sourcemm/CServerGameClients.h | 66 ++++++++++++++++++------ sourcemm/CServerGameDLL.h | 97 +++++++++++++++++++++++++---------- sourcemm/CServerGameEnts.h | 25 ++++++--- sourcemm/sourcemm.cpp | 82 +++++++++-------------------- sourcemm/sourcemm.h | 2 +- 6 files changed, 178 insertions(+), 116 deletions(-) diff --git a/sourcemm/CHLTVDirector.h b/sourcemm/CHLTVDirector.h index 087ea03..59383c1 100644 --- a/sourcemm/CHLTVDirector.h +++ b/sourcemm/CHLTVDirector.h @@ -21,15 +21,21 @@ class CHLTVDirector : IHLTVDirector { + IHLTVDirector *m_pOrig; public: - virtual bool IsActive() { return false; } - virtual void SetHLTVServer(IHLTVServer *hltv) { } - virtual IHLTVServer *GetHLTVServer() { return NULL; } - virtual int GetDirectorTick() { return 0; } - virtual int GetPVSEntity() { return 0; } - virtual Vector GetPVSOrigin() { return Vector(0, 0, 0); } - virtual float GetDelay() { return 0.0f; } - virtual const char**GetModEvents() { return NULL; } + CHLTVDirector() : m_pOrig(0) {} + void SetOrig(IHLTVDirector *pOrig) + { + m_pOrig = pOrig; + } + virtual bool IsActive() { return m_pOrig->IsActive(); } + virtual void SetHLTVServer(IHLTVServer *hltv) { m_pOrig->SetHLTVServer(hltv); } + virtual IHLTVServer *GetHLTVServer() { return m_pOrig->GetHLTVServer(); } + virtual int GetDirectorTick() { return m_pOrig->GetDirectorTick(); } + virtual int GetPVSEntity() { return m_pOrig->GetPVSEntity(); } + virtual Vector GetPVSOrigin() { return m_pOrig->GetPVSOrigin(); } + virtual float GetDelay() { return m_pOrig->GetDelay(); } + virtual const char**GetModEvents() { return m_pOrig->GetModEvents(); } }; #endif //_INCLUDE_HLTVDIRECTOR_H diff --git a/sourcemm/CServerGameClients.h b/sourcemm/CServerGameClients.h index 92548ab..5bb1424 100644 --- a/sourcemm/CServerGameClients.h +++ b/sourcemm/CServerGameClients.h @@ -20,22 +20,58 @@ class CServerGameClients : public IServerGameClients { + IServerGameClients *m_pOrig; public: - virtual void GetPlayerLimits(int& minplayers, int& maxplayers, int &defaultMaxPlayers) const { } - virtual bool ClientConnect(edict_t *pEntity, const char *pszName, const char *pszAddress, char *reject, int maxrejectlen) { return false; } - virtual void ClientActive(edict_t *pEntity, bool bLoadGame) { } - virtual void ClientDisconnect(edict_t *pEntity) { } - virtual void ClientPutInServer(edict_t *pEntity, char const *playername) { } - virtual void ClientCommand(edict_t *pEntity) { } - virtual void SetCommandClient(int index) { } - virtual void ClientSettingsChanged(edict_t *pEdict) { } - virtual void ClientSetupVisibility(edict_t *pViewEntity, edict_t *pClient, unsigned char *pvs, int pvssize) { } - virtual float ProcessUsercmds(edict_t *player, bf_read *buf, int numcmds, int totalcmds, int dropped_packets, bool ignore, bool paused) { return 0.0f; } - virtual void PostClientMessagesSent() { } - virtual CPlayerState *GetPlayerState(edict_t *player) { return NULL; } - virtual void ClientEarPosition(edict_t *pEntity, Vector *pEarOrigin) { } - virtual int GetReplayDelay(edict_t *player) { return 0; } - virtual void GetBugReportInfo(char *buf, int buflen) { } + CServerGameClients() : m_pOrig(0) {} + void SetOrig(IServerGameClients *pOrig) + { + m_pOrig = pOrig; + } + + virtual void GetPlayerLimits(int& minplayers, int& maxplayers, int &defaultMaxPlayers) const + { m_pOrig->GetPlayerLimits(minplayers, maxplayers, defaultMaxPlayers); } + + virtual bool ClientConnect(edict_t *pEntity, const char *pszName, const char *pszAddress, char *reject, int maxrejectlen) + { return m_pOrig->ClientConnect(pEntity, pszName, pszAddress, reject, maxrejectlen); } + + virtual void ClientActive(edict_t *pEntity, bool bLoadGame) + { m_pOrig->ClientActive(pEntity, bLoadGame); } + + virtual void ClientDisconnect(edict_t *pEntity) + { m_pOrig->ClientDisconnect(pEntity); } + + virtual void ClientPutInServer(edict_t *pEntity, char const *playername) + { m_pOrig->ClientPutInServer(pEntity, playername); } + + virtual void ClientCommand(edict_t *pEntity) + { m_pOrig->ClientCommand(pEntity); } + + virtual void SetCommandClient(int index) + { m_pOrig->SetCommandClient(index); } + + virtual void ClientSettingsChanged(edict_t *pEdict) + { m_pOrig->ClientSettingsChanged(pEdict); } + + virtual void ClientSetupVisibility(edict_t *pViewEntity, edict_t *pClient, unsigned char *pvs, int pvssize) + { m_pOrig->ClientSetupVisibility(pViewEntity, pClient, pvs, pvssize); } + + virtual float ProcessUsercmds(edict_t *player, bf_read *buf, int numcmds, int totalcmds, int dropped_packets, bool ignore, bool paused) + { return m_pOrig->ProcessUsercmds(player, buf, numcmds, totalcmds, dropped_packets, ignore, paused); } + + virtual void PostClientMessagesSent() + { m_pOrig->PostClientMessagesSent(); } + + virtual CPlayerState *GetPlayerState(edict_t *player) + { return m_pOrig->GetPlayerState(player); } + + virtual void ClientEarPosition(edict_t *pEntity, Vector *pEarOrigin) + { m_pOrig->ClientEarPosition(pEntity, pEarOrigin); } + + virtual int GetReplayDelay(edict_t *player) + { return m_pOrig->GetReplayDelay(player); } + + virtual void GetBugReportInfo(char *buf, int buflen) + { m_pOrig->GetBugReportInfo(buf, buflen); } }; #endif //_INCLUDE_CSERVERGAMECLIENTS_H diff --git a/sourcemm/CServerGameDLL.h b/sourcemm/CServerGameDLL.h index 7b0a400..1e4ed24 100644 --- a/sourcemm/CServerGameDLL.h +++ b/sourcemm/CServerGameDLL.h @@ -23,36 +23,77 @@ */ class CServerGameDLL : public IServerGameDLL { + IServerGameDLL *m_pOrig; + char m_GameDescBuffer[256]; public: + CServerGameDLL() : m_pOrig(0) + { + m_GameDescBuffer[0] = 0; + } + void SetOrig(IServerGameDLL *pOrig) + { + m_pOrig = pOrig; + strncpy(m_GameDescBuffer, pOrig->GetGameDescription(), 254); + m_GameDescBuffer[255] = 0; + } + virtual bool DLLInit( CreateInterfaceFn engineFactory, CreateInterfaceFn physicsFactory, CreateInterfaceFn fileSystemFactory, CGlobalVars *pGlobals); - virtual bool GameInit( void ) { return false; } - virtual bool LevelInit( char const *pMapName, char const *pMapEntities, char const *pOldLevel, char const *pLandmarkName, bool loadGame, bool background ) { return false; } - virtual void ServerActivate( edict_t *pEdictList, int edictCount, int clientMax ) { } - virtual void GameFrame( bool simulating ) { } - virtual void PreClientUpdate( bool simulating ) { } - virtual void LevelShutdown( void ) { } - virtual void GameShutdown( void ) { } - virtual void DLLShutdown( void ) { } - virtual float GetTickInterval( void ) const { return 0.0f; } - virtual ServerClass *GetAllServerClasses( void ) { return NULL; } - virtual const char *GetGameDescription( void ) { return NULL; } - virtual void CreateNetworkStringTables( void ) { } - virtual CSaveRestoreData *SaveInit( int size ) { return NULL; } - virtual void SaveWriteFields( CSaveRestoreData *, const char *, void *, datamap_t *, typedescription_t *, int ) { } - virtual void SaveReadFields( CSaveRestoreData *, const char *, void *, datamap_t *, typedescription_t *, int ) { } - virtual void SaveGlobalState( CSaveRestoreData * ) { } - virtual void RestoreGlobalState( CSaveRestoreData * ) { } - virtual void PreSave( CSaveRestoreData * ) { } - virtual void Save( CSaveRestoreData * ) { } - virtual void GetSaveComment( char *comment, int maxlength ) { } - virtual void WriteSaveHeaders( CSaveRestoreData * ) { } - virtual void ReadRestoreHeaders( CSaveRestoreData * ) { } - virtual void Restore( CSaveRestoreData *, bool ) { } - virtual bool IsRestoring() { return false; } - virtual int CreateEntityTransitionList( CSaveRestoreData *, int ) { return 0; } - virtual void BuildAdjacentMapList( void ) { } - virtual bool GetUserMessageInfo( int msg_type, char *name, int maxnamelength, int& size ) { return false; } - virtual CStandardSendProxies* GetStandardSendProxies() { return NULL; } + virtual bool GameInit( void ) + { return m_pOrig->GameInit(); } + virtual bool LevelInit( char const *pMapName, char const *pMapEntities, char const *pOldLevel, char const *pLandmarkName, bool loadGame, bool background ) + { return m_pOrig->LevelInit(pMapName, pMapEntities, pOldLevel, pLandmarkName, loadGame, background); } + virtual void ServerActivate( edict_t *pEdictList, int edictCount, int clientMax ) + { m_pOrig->ServerActivate(pEdictList, edictCount, clientMax); } + virtual void GameFrame( bool simulating ) + { m_pOrig->GameFrame(simulating); } + virtual void PreClientUpdate( bool simulating ) + { m_pOrig->PreClientUpdate(simulating); } + virtual void LevelShutdown( void ) + { m_pOrig->LevelShutdown(); } + virtual void GameShutdown( void ) + { m_pOrig->GameShutdown(); } + virtual void DLLShutdown( void ) + { m_pOrig->DLLShutdown(); } + virtual float GetTickInterval( void ) const + { return m_pOrig->GetTickInterval(); } + virtual ServerClass *GetAllServerClasses( void ) + { return m_pOrig->GetAllServerClasses(); } + virtual const char *GetGameDescription( void ) + { return m_GameDescBuffer; } + virtual void CreateNetworkStringTables( void ) + { m_pOrig->CreateNetworkStringTables(); } + virtual CSaveRestoreData *SaveInit( int size ) + { return m_pOrig->SaveInit(size); } + virtual void SaveWriteFields( CSaveRestoreData *a1, const char *a2, void *a3, datamap_t *a4, typedescription_t *a5, int a6) + { m_pOrig->SaveWriteFields(a1, a2, a3, a4, a5, a6); } + virtual void SaveReadFields( CSaveRestoreData *a1, const char *a2, void *a3, datamap_t *a4, typedescription_t *a5, int a6) + { m_pOrig->SaveReadFields(a1, a2, a3, a4, a5, a6); } + virtual void SaveGlobalState( CSaveRestoreData *a1) + { m_pOrig->SaveGlobalState(a1); } + virtual void RestoreGlobalState( CSaveRestoreData *a1) + { m_pOrig->RestoreGlobalState(a1); } + virtual void PreSave( CSaveRestoreData *a1) + { m_pOrig->PreSave(a1); } + virtual void Save( CSaveRestoreData *a1) + { m_pOrig->Save(a1); } + virtual void GetSaveComment( char *comment, int maxlength ) + { m_pOrig->GetSaveComment(comment, maxlength); } + virtual void WriteSaveHeaders( CSaveRestoreData *a1) + { m_pOrig->WriteSaveHeaders(a1); } + virtual void ReadRestoreHeaders( CSaveRestoreData *a1) + { m_pOrig->ReadRestoreHeaders(a1); } + virtual void Restore( CSaveRestoreData *a1, bool a2) + { m_pOrig->Restore(a1, a2); } + virtual bool IsRestoring() + { return m_pOrig->IsRestoring(); } + virtual int CreateEntityTransitionList( CSaveRestoreData *a1, int a2) + { return m_pOrig->CreateEntityTransitionList(a1, a2); } + virtual void BuildAdjacentMapList( void ) + { m_pOrig->BuildAdjacentMapList(); } + virtual bool GetUserMessageInfo( int msg_type, char *name, int maxnamelength, int& size ) + { return m_pOrig->GetUserMessageInfo(msg_type, name, maxnamelength, size); } + virtual CStandardSendProxies* GetStandardSendProxies() + { return m_pOrig->GetStandardSendProxies(); } }; #endif //_INCLUDE_CSERVER_GAMEDLL_H diff --git a/sourcemm/CServerGameEnts.h b/sourcemm/CServerGameEnts.h index 958cef4..adfe3f4 100644 --- a/sourcemm/CServerGameEnts.h +++ b/sourcemm/CServerGameEnts.h @@ -20,13 +20,26 @@ class CServerGameEnts : public IServerGameEnts { + IServerGameEnts *m_pOrig; public: - virtual void SetDebugEdictBase(edict_t *base) { } - virtual void MarkEntitiesAsTouching(edict_t *e1, edict_t *e2) { } - virtual void FreeContainingEntity(edict_t *e) { } - virtual edict_t *BaseEntityToEdict(CBaseEntity *pEnt) { return NULL; } - virtual CBaseEntity *EdictToBaseEntity(edict_t *pEdict) { return NULL; } - virtual void CheckTransmit(CCheckTransmitInfo *pInfo, const unsigned short *pEdictIndices, int nEdicts) { } + CServerGameEnts() : m_pOrig(0) {} + void SetOrig(IServerGameEnts *pOrig) + { + m_pOrig = pOrig; + } + + virtual void SetDebugEdictBase(edict_t *base) + { m_pOrig->SetDebugEdictBase(base); } + virtual void MarkEntitiesAsTouching(edict_t *e1, edict_t *e2) + { m_pOrig->MarkEntitiesAsTouching(e1, e2); } + virtual void FreeContainingEntity(edict_t *e) + { m_pOrig->FreeContainingEntity(e); } + virtual edict_t *BaseEntityToEdict(CBaseEntity *pEnt) + { return m_pOrig->BaseEntityToEdict(pEnt); } + virtual CBaseEntity *EdictToBaseEntity(edict_t *pEdict) + { return m_pOrig->EdictToBaseEntity(pEdict); } + virtual void CheckTransmit(CCheckTransmitInfo *pInfo, const unsigned short *pEdictIndices, int nEdicts) + { m_pOrig->CheckTransmit(pInfo, pEdictIndices, nEdicts); } }; #endif //_INCLUDE_CSERVER_GAMEENTS_H diff --git a/sourcemm/sourcemm.cpp b/sourcemm/sourcemm.cpp index a71e4a8..d5856b3 100644 --- a/sourcemm/sourcemm.cpp +++ b/sourcemm/sourcemm.cpp @@ -24,10 +24,10 @@ * @file sourcemm.cpp */ -CServerGameDLL *g_TempGameDLL = NULL; -CServerGameEnts *g_TempGameEnts = NULL; -CServerGameClients *g_TempGameClients = NULL; -CHLTVDirector *g_TempDirector = NULL; +CServerGameDLL g_TempGameDLL; +CServerGameEnts g_TempGameEnts; +CServerGameClients g_TempGameClients; +CHLTVDirector g_TempDirector; GameDllInfo g_GameDll = {false, NULL, NULL}; EngineInfo g_Engine = {NULL, NULL, NULL, NULL}; SourceHook::CSourceHookImpl g_SourceHook; @@ -52,38 +52,29 @@ SMM_API void *CreateInterface(const char *name, int *ret) // Currently, HL2 Engine has loaded Metamod:Source // It is now asking it to get an interface. We don't have one, // so we're gonna try to give it a fake one to get the information we need. - // Then we'll swap the vtables with the real one from the real gamedll. + // Then, the the interface will forward the calls to the original interface if (strcmp(name, INTERFACEVERSION_SERVERGAMEDLL) == 0) { //We're in. Give the server our fake class as bait. if (ret) *ret = IFACE_OK; - - g_TempGameDLL = new CServerGameDLL; - - return static_cast(g_TempGameDLL); + return static_cast(&g_TempGameDLL); } else if (strcmp(name, INTERFACEVERSION_SERVERGAMEENTS) == 0) { if (ret) *ret = IFACE_OK; - g_TempGameEnts = new CServerGameEnts; - - return static_cast(g_TempGameEnts); + return static_cast(&g_TempGameEnts); } else if (strcmp(name, INTERFACEVERSION_SERVERGAMECLIENTS) == 0) { if (ret) *ret = IFACE_OK; - g_TempGameClients = new CServerGameClients; - - return static_cast(g_TempGameClients); + return static_cast(&g_TempGameClients); } else if (strcmp(name, INTERFACEVERSION_HLTVDIRECTOR) == 0) { if (ret) *ret = IFACE_OK; - g_TempDirector = new CHLTVDirector; - - return static_cast(g_TempDirector); + return static_cast(&g_TempDirector); } else { if (ret) *ret = IFACE_FAILED; @@ -97,6 +88,9 @@ SMM_API void *CreateInterface(const char *name, int *ret) bool CServerGameDLL::DLLInit(CreateInterfaceFn engineFactory, CreateInterfaceFn physicsFactory, CreateInterfaceFn fileSystemFactory, CGlobalVars *pGlobals) { + if (m_pOrig) + return m_pOrig->DLLInit(engineFactory, physicsFactory, fileSystemFactory, pGlobals); + if (!g_GameDll.loaded) { //Initialize SourceHook @@ -159,7 +153,7 @@ bool CServerGameDLL::DLLInit(CreateInterfaceFn engineFactory, CreateInterfaceFn return false; } - g_GameDll.serverGameDLL = serverDll; + g_GameDll.serverGameDLL_CC = SH_GET_CALLCLASS(IServerGameDLL, serverDll); //Set this information early in case our wrappers are called somehow g_Engine.engineFactory = engineFactory; @@ -217,35 +211,12 @@ bool CServerGameDLL::DLLInit(CreateInterfaceFn engineFactory, CreateInterfaceFn dlclose(g_GameDll.lib); return false; } - - //The GameDLL has given the go - now we'll swap the vtables ( eww! ) - //This ugly hack will patch the pointer we've given the engine - // so it will just be calling the real GameDLL instead. - // Unlike Metamod:HL1, this is the effect we want, rather than duplicating - // the entire class (because SourceHook doesn't do that). - void *vtableDst = ((void *)(g_TempGameDLL)); - void *vtableSrc = ((void *)(serverDll)); - - SourceHook::SetMemAccess(vtableDst, sizeof(IServerGameDLL), SH_MEM_READ|SH_MEM_WRITE); - memcpy(vtableDst, vtableSrc, sizeof(IServerGameDLL)); - - //Now patch IServerGameEnts - vtableDst = ((void *)(g_TempGameEnts)); - vtableSrc = ((void *)(serverEnts)); - SourceHook::SetMemAccess(vtableDst, sizeof(IServerGameEnts), SH_MEM_READ|SH_MEM_WRITE); - memcpy(vtableDst, vtableSrc, sizeof(IServerGameEnts)); - - //Now patch IServerGameClients - vtableDst = ((void *)(g_TempGameClients)); - vtableSrc = ((void *)(serverClients)); - SourceHook::SetMemAccess(vtableDst, sizeof(IServerGameClients), SH_MEM_READ|SH_MEM_WRITE); - memcpy(vtableDst, vtableSrc, sizeof(IServerGameClients)); - - //Now patch IHLTVDirector - vtableDst = ((void *)(g_TempDirector)); - vtableSrc = ((void *)(serverHLTV)); - SourceHook::SetMemAccess(vtableDst, sizeof(IHLTVDirector), SH_MEM_READ|SH_MEM_WRITE); - memcpy(vtableDst, vtableSrc, sizeof(IHLTVDirector)); + + // Now tell the global temp classes that they can call the original functions + g_TempDirector.SetOrig(serverHLTV); + g_TempGameClients.SetOrig(serverClients); + g_TempGameEnts.SetOrig(serverEnts); + g_TempGameDLL.SetOrig(serverDll); //Everything's done. g_GameDll.loaded = true; @@ -269,8 +240,7 @@ bool CServerGameDLL::DLLInit(CreateInterfaceFn engineFactory, CreateInterfaceFn } } - //Somehow, the function got here. This should be impossible, as not only is it - // only called once, but the vtables should be overridden. + //Somehow, the function got here. This should be impossible. Error("Metamod:Source fatal error - IServerGameDLL::DLLInit() called inappropriately"); return false; @@ -282,19 +252,15 @@ void DLLShutdown_handler(void) g_PluginMngr.UnloadAll(); //Call the DLL... - g_GameDll.serverGameDLL->DLLShutdown(); + g_GameDll.serverGameDLL_CC->DLLShutdown(); + + // Shutdown sourcehook now + g_SourceHook.CompleteShutdown(); //Unload the DLL forcefully dlclose(g_GameDll.lib); memset(&g_GameDll, 0, sizeof(GameDllInfo)); - //For now, I'm not gonna bother freeing the memory allocated above. - //Why? - // 1. We're exiting the application (I should hope!) - // 2. If we're not exiting, we just deallocated the gamedll, so we're about to crash out ANYWAY - // 3. We never saved the original vtable pointers, and we'd have to copy them back to get our destructors. - //Soooo... we'll just accept our fate here. - //DON'T CALL THE GAMEDLL! IT'S GONE! pinin' for the fjords RETURN_META(MRES_SUPERCEDE); } diff --git a/sourcemm/sourcemm.h b/sourcemm/sourcemm.h index c90b8ec..6a0de11 100644 --- a/sourcemm/sourcemm.h +++ b/sourcemm/sourcemm.h @@ -55,7 +55,7 @@ struct GameDllInfo bool loaded; HINSTANCE lib; CreateInterfaceFn factory; - IServerGameDLL *serverGameDLL; + IServerGameDLL *serverGameDLL_CC; }; /** @brief Stores information about the HL2 Engine pointers */