1
0
mirror of https://github.com/alliedmodders/metamod-source.git synced 2025-02-20 13:54:14 +01:00
--HG--
extra : convert_revision : svn%3Ac2935e3e-5518-0410-8daf-afa5dab7d4e3/trunk%4015
This commit is contained in:
Pavol Marko 2005-04-17 18:43:21 +00:00
parent 6df8efff3a
commit ba23929c3d
6 changed files with 178 additions and 116 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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<void *>(g_TempGameDLL);
return static_cast<void *>(&g_TempGameDLL);
} else if (strcmp(name, INTERFACEVERSION_SERVERGAMEENTS) == 0) {
if (ret)
*ret = IFACE_OK;
g_TempGameEnts = new CServerGameEnts;
return static_cast<void *>(g_TempGameEnts);
return static_cast<void *>(&g_TempGameEnts);
} else if (strcmp(name, INTERFACEVERSION_SERVERGAMECLIENTS) == 0) {
if (ret)
*ret = IFACE_OK;
g_TempGameClients = new CServerGameClients;
return static_cast<void *>(g_TempGameClients);
return static_cast<void *>(&g_TempGameClients);
} else if (strcmp(name, INTERFACEVERSION_HLTVDIRECTOR) == 0) {
if (ret)
*ret = IFACE_OK;
g_TempDirector = new CHLTVDirector;
return static_cast<void *>(g_TempDirector);
return static_cast<void *>(&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);
}

View File

@ -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 */