overhaul of the vsp listening code

--HG--
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%401587
This commit is contained in:
David Anderson 2007-10-15 22:15:22 +00:00
parent 0600be8c3a
commit 60d8e4f248
12 changed files with 144 additions and 52 deletions

View File

@ -46,7 +46,7 @@ SH_DECL_HOOK5_void(IServerPluginCallbacks, OnQueryCvarValueFinished, SH_NOATTRIB
const ParamType CONVARCHANGE_PARAMS[] = {Param_Cell, Param_String, Param_String}; const ParamType CONVARCHANGE_PARAMS[] = {Param_Cell, Param_String, Param_String};
typedef List<const ConVar *> ConVarList; typedef List<const ConVar *> ConVarList;
ConVarManager::ConVarManager() : m_ConVarType(0), m_VSPIface(NULL), m_CanQueryConVars(false) ConVarManager::ConVarManager() : m_ConVarType(0), m_bIsDLLQueryHooked(false), m_bIsVSPQueryHooked(false)
{ {
#if PLAPI_VERSION < 12 #if PLAPI_VERSION < 12
m_IgnoreHandle = false; m_IgnoreHandle = false;
@ -74,11 +74,15 @@ ConVarManager::~ConVarManager()
void ConVarManager::OnSourceModAllInitialized() void ConVarManager::OnSourceModAllInitialized()
{ {
/* Only valid with ServerGameDLL006 or greater */ /**
* Episode 2 has this function by default, but the older versions do not.
*/
#if !defined ORANGEBOX_BUILD
if (g_SMAPI->GetGameDLLVersion() >= 6) if (g_SMAPI->GetGameDLLVersion() >= 6)
#endif
{ {
SH_ADD_HOOK_MEMFUNC(IServerGameDLL, OnQueryCvarValueFinished, gamedll, this, &ConVarManager::OnQueryCvarValueFinished, false); SH_ADD_HOOK_MEMFUNC(IServerGameDLL, OnQueryCvarValueFinished, gamedll, this, &ConVarManager::OnQueryCvarValueFinished, false);
m_CanQueryConVars = true; m_bIsDLLQueryHooked = true;
} }
HandleAccess sec; HandleAccess sec;
@ -97,10 +101,15 @@ void ConVarManager::OnSourceModAllInitialized()
void ConVarManager::OnSourceModShutdown() void ConVarManager::OnSourceModShutdown()
{ {
if (m_CanQueryConVars) if (m_bIsDLLQueryHooked)
{ {
SH_REMOVE_HOOK_MEMFUNC(IServerGameDLL, OnQueryCvarValueFinished, gamedll, this, &ConVarManager::OnQueryCvarValueFinished, false); SH_REMOVE_HOOK_MEMFUNC(IServerGameDLL, OnQueryCvarValueFinished, gamedll, this, &ConVarManager::OnQueryCvarValueFinished, false);
SH_REMOVE_HOOK_MEMFUNC(IServerPluginCallbacks, OnQueryCvarValueFinished, m_VSPIface, this, &ConVarManager::OnQueryCvarValueFinished, false); m_bIsDLLQueryHooked = false;
}
else if (m_bIsVSPQueryHooked)
{
SH_REMOVE_HOOK_MEMFUNC(IServerPluginCallbacks, OnQueryCvarValueFinished, vsp_interface, this, &ConVarManager::OnQueryCvarValueFinished, false);
m_bIsVSPQueryHooked = false;
} }
IChangeableForward *fwd; IChangeableForward *fwd;
@ -125,27 +134,35 @@ void ConVarManager::OnSourceModShutdown()
g_HandleSys.RemoveType(m_ConVarType, g_pCoreIdent); g_HandleSys.RemoveType(m_ConVarType, g_pCoreIdent);
} }
void ConVarManager::OnSourceModVSPReceived(IServerPluginCallbacks *iface) /**
* Orange Box will never use this.
*/
void ConVarManager::OnSourceModVSPReceived()
{ {
/* This will be called after OnSourceModAllInitialized(), so... /**
* * Don't bother if the DLL is already hooked.
* If we haven't been able to hook the IServerGameDLL version at this point,
* then use hook IServerPluginCallbacks version from the engine.
*/ */
if (m_bIsDLLQueryHooked)
/* The Ship currently only supports ServerPluginCallbacks001, but we need 002 */
if (g_IsOriginalEngine)
{ {
return; return;
} }
if (!m_CanQueryConVars) /* For later MM:S versions, use the updated API, since it's cleaner. */
#if defined METAMOD_PLAPI_VERSION
int engine = g_SMAPI->GetSourceEngineBuild();
if (engine == SOURCE_ENGINE_ORIGINAL || vsp_version < 2)
{ {
m_VSPIface = iface; return;
SH_ADD_HOOK_MEMFUNC(IServerPluginCallbacks, OnQueryCvarValueFinished, iface, this, &ConVarManager::OnQueryCvarValueFinished, false);
m_CanQueryConVars = true;
} }
#else
if (g_HL2.IsOriginalEngine() || vsp_version < 2)
{
return;
}
#endif
SH_ADD_HOOK_MEMFUNC(IServerPluginCallbacks, OnQueryCvarValueFinished, vsp_interface, this, &ConVarManager::OnQueryCvarValueFinished, false);
m_bIsVSPQueryHooked = true;
} }
#if PLAPI_VERSION >= 12 #if PLAPI_VERSION >= 12
@ -306,7 +323,9 @@ Handle_t ConVarManager::CreateConVar(IPluginContext *pContext, const char *name,
if (sm_trie_retrieve(m_ConVarCache, name, (void **)&pInfo)) if (sm_trie_retrieve(m_ConVarCache, name, (void **)&pInfo))
{ {
return pInfo->handle; return pInfo->handle;
} else { }
else
{
/* If we don't, then create a new handle from the convar */ /* If we don't, then create a new handle from the convar */
hndl = g_HandleSys.CreateHandle(m_ConVarType, pConVar, NULL, g_pCoreIdent, NULL); hndl = g_HandleSys.CreateHandle(m_ConVarType, pConVar, NULL, g_pCoreIdent, NULL);
@ -478,12 +497,18 @@ QueryCvarCookie_t ConVarManager::QueryClientConVar(edict_t *pPlayer, const char
QueryCvarCookie_t cookie; QueryCvarCookie_t cookie;
/* Call StartQueryCvarValue() in either the IVEngineServer or IServerPluginHelpers depending on situation */ /* Call StartQueryCvarValue() in either the IVEngineServer or IServerPluginHelpers depending on situation */
if (!m_VSPIface) if (m_bIsDLLQueryHooked)
{ {
cookie = engine->StartQueryCvarValue(pPlayer, name); cookie = engine->StartQueryCvarValue(pPlayer, name);
} else { }
else if (m_bIsVSPQueryHooked)
{
cookie = serverpluginhelpers->StartQueryCvarValue(pPlayer, name); cookie = serverpluginhelpers->StartQueryCvarValue(pPlayer, name);
} }
else
{
return InvalidQueryCvarCookie;
}
ConVarQuery query = {cookie, pCallback, hndl}; ConVarQuery query = {cookie, pCallback, hndl};
m_ConVarQueries.push_back(query); m_ConVarQueries.push_back(query);
@ -505,7 +530,9 @@ void ConVarManager::AddConVarToPluginList(IPluginContext *pContext, const ConVar
{ {
pConVarList = new ConVarList(); pConVarList = new ConVarList();
plugin->SetProperty("ConVarList", pConVarList); plugin->SetProperty("ConVarList", pConVarList);
} else if (pConVarList->find(pConVar) != pConVarList->end()) { }
else if (pConVarList->find(pConVar) != pConVarList->end())
{
/* If convar is already in list, then don't add it */ /* If convar is already in list, then don't add it */
return; return;
} }
@ -568,6 +595,11 @@ void ConVarManager::OnConVarChanged(ConVar *pConVar, const char *oldValue)
pForward->Execute(NULL); pForward->Execute(NULL);
} }
bool ConVarManager::IsQueryingSupported()
{
return (m_bIsDLLQueryHooked || m_bIsVSPQueryHooked);
}
void ConVarManager::OnQueryCvarValueFinished(QueryCvarCookie_t cookie, edict_t *pPlayer, EQueryCvarValueStatus result, const char *cvarName, const char *cvarValue) void ConVarManager::OnQueryCvarValueFinished(QueryCvarCookie_t cookie, edict_t *pPlayer, EQueryCvarValueStatus result, const char *cvarName, const char *cvarValue)
{ {
IPluginFunction *pCallback = NULL; IPluginFunction *pCallback = NULL;
@ -597,7 +629,9 @@ void ConVarManager::OnQueryCvarValueFinished(QueryCvarCookie_t cookie, edict_t *
if (result == eQueryCvarValueStatus_ValueIntact) if (result == eQueryCvarValueStatus_ValueIntact)
{ {
pCallback->PushString(cvarValue); pCallback->PushString(cvarValue);
} else { }
else
{
pCallback->PushString("\0"); pCallback->PushString("\0");
} }

View File

@ -80,7 +80,7 @@ public:
public: // SMGlobalClass public: // SMGlobalClass
void OnSourceModAllInitialized(); void OnSourceModAllInitialized();
void OnSourceModShutdown(); void OnSourceModShutdown();
void OnSourceModVSPReceived(IServerPluginCallbacks *iface); void OnSourceModVSPReceived();
public: // IHandleTypeDispatch public: // IHandleTypeDispatch
void OnHandleDestroy(HandleType_t type, void *object); void OnHandleDestroy(HandleType_t type, void *object);
public: // IPluginsListener public: // IPluginsListener
@ -131,6 +131,8 @@ public:
QueryCvarCookie_t QueryClientConVar(edict_t *pPlayer, const char *name, IPluginFunction *pCallback, QueryCvarCookie_t QueryClientConVar(edict_t *pPlayer, const char *name, IPluginFunction *pCallback,
Handle_t hndl); Handle_t hndl);
bool IsQueryingSupported();
#if PLAPI_VERSION >= 12 #if PLAPI_VERSION >= 12
/** /**
* Called when Metamod:Source is about to remove convar * Called when Metamod:Source is about to remove convar
@ -167,8 +169,8 @@ private:
List<ConVarInfo *> m_ConVars; List<ConVarInfo *> m_ConVars;
List<ConVarQuery> m_ConVarQueries; List<ConVarQuery> m_ConVarQueries;
Trie *m_ConVarCache; Trie *m_ConVarCache;
IServerPluginCallbacks *m_VSPIface; bool m_bIsDLLQueryHooked;
bool m_CanQueryConVars; bool m_bIsVSPQueryHooked;
#if PLAPI_VERSION < 12 #if PLAPI_VERSION < 12
bool m_IgnoreHandle; bool m_IgnoreHandle;
#endif #endif

View File

@ -38,7 +38,6 @@
#include <compat_wrappers.h> #include <compat_wrappers.h>
CHalfLife2 g_HL2; CHalfLife2 g_HL2;
bool g_IsOriginalEngine = false;
ConVar *sv_lan = NULL; ConVar *sv_lan = NULL;
namespace SourceHook namespace SourceHook
@ -90,15 +89,21 @@ CHalfLife2::~CHalfLife2()
} }
CSharedEdictChangeInfo *g_pSharedChangeInfo = NULL; CSharedEdictChangeInfo *g_pSharedChangeInfo = NULL;
bool is_original_engine = false;
void CHalfLife2::OnSourceModStartup(bool late) void CHalfLife2::OnSourceModStartup(bool late)
{ {
/* The Ship currently is the only known game to use an older version of the engine */ /* The Ship currently is the only known game to use an older version of the engine */
#if defined METAMOD_PLAPI_VERSION
if (g_SMAPI->GetSourceEngineBuild() == SOURCE_ENGINE_ORIGINAL)
#else
if (strcasecmp(g_SourceMod.GetGameFolderName(), "ship") == 0) if (strcasecmp(g_SourceMod.GetGameFolderName(), "ship") == 0)
#endif
{
is_original_engine = true;
}
else if (g_pSharedChangeInfo == NULL)
{ {
/* :TODO: Better engine versioning - perhaps something added to SourceMM? */
g_IsOriginalEngine = true;
} else if (!g_pSharedChangeInfo) {
g_pSharedChangeInfo = engine->GetSharedEdictChangeInfo(); g_pSharedChangeInfo = engine->GetSharedEdictChangeInfo();
} }
} }
@ -111,6 +116,13 @@ void CHalfLife2::OnSourceModAllInitialized()
g_ShareSys.AddInterface(NULL, this); g_ShareSys.AddInterface(NULL, this);
} }
#if !defined METAMOD_PLAPI_VERSION
bool CHalfLife2::IsOriginalEngine()
{
return is_original_engine;
}
#endif
IChangeInfoAccessor *CBaseEdict::GetChangeAccessor() IChangeInfoAccessor *CBaseEdict::GetChangeAccessor()
{ {
return engine->GetChangeAccessor( (const edict_t *)this ); return engine->GetChangeAccessor( (const edict_t *)this );
@ -254,7 +266,7 @@ typedescription_t *CHalfLife2::FindInDataMap(datamap_t *pMap, const char *offset
void CHalfLife2::SetEdictStateChanged(edict_t *pEdict, unsigned short offset) void CHalfLife2::SetEdictStateChanged(edict_t *pEdict, unsigned short offset)
{ {
if (!g_IsOriginalEngine) if (g_pSharedChangeInfo != NULL)
{ {
if (offset) if (offset)
{ {
@ -262,7 +274,9 @@ void CHalfLife2::SetEdictStateChanged(edict_t *pEdict, unsigned short offset)
} else { } else {
pEdict->StateChanged(); pEdict->StateChanged();
} }
} else { }
else
{
pEdict->m_fStateFlags |= FL_EDICT_CHANGED; pEdict->m_fStateFlags |= FL_EDICT_CHANGED;
} }
} }

View File

@ -105,6 +105,9 @@ public:
void PopCommandStack(); void PopCommandStack();
const CCommand *PeekCommandStack(); const CCommand *PeekCommandStack();
const char *CurrentCommandName(); const char *CurrentCommandName();
#if !defined METAMOD_PLAPI_VERSION
bool IsOriginalEngine();
#endif
private: private:
DataTableInfo *_FindServerClass(const char *classname); DataTableInfo *_FindServerClass(const char *classname);
private: private:
@ -120,6 +123,5 @@ private:
}; };
extern CHalfLife2 g_HL2; extern CHalfLife2 g_HL2;
extern bool g_IsOriginalEngine;
#endif //_INCLUDE_SOURCEMOD_CHALFLIFE2_H_ #endif //_INCLUDE_SOURCEMOD_CHALFLIFE2_H_

View File

@ -799,6 +799,10 @@
RelativePath="..\ChatTriggers.h" RelativePath="..\ChatTriggers.h"
> >
</File> </File>
<File
RelativePath="..\..\public\compat_wrappers.h"
>
</File>
<File <File
RelativePath="..\ConCmdManager.h" RelativePath="..\ConCmdManager.h"
> >

View File

@ -143,7 +143,7 @@ public:
/** /**
* @brief Called when SourceMod receives a pointer to IServerPluginCallbacks from SourceMM * @brief Called when SourceMod receives a pointer to IServerPluginCallbacks from SourceMM
*/ */
virtual void OnSourceModVSPReceived(IServerPluginCallbacks *iface) virtual void OnSourceModVSPReceived()
{ {
} }

View File

@ -507,7 +507,7 @@ static cell_t sm_QueryClientConVar(IPluginContext *pContext, const cell_t *param
char *name; char *name;
IPluginFunction *pCallback; IPluginFunction *pCallback;
if (g_IsOriginalEngine) if (!g_ConVarManager.IsQueryingSupported())
{ {
if (!s_QueryAlreadyWarned) if (!s_QueryAlreadyWarned)
{ {

View File

@ -36,17 +36,6 @@
#include "PlayerManager.h" #include "PlayerManager.h"
#include "HalfLife2.h" #include "HalfLife2.h"
IServerPluginCallbacks *g_VSP = NULL;
class HalfLifeNatives : public SMGlobalClass
{
public: //SMGlobalClass
void OnSourceModVSPReceived(IServerPluginCallbacks *iface)
{
g_VSP = iface;
}
};
static cell_t SetRandomSeed(IPluginContext *pContext, const cell_t *params) static cell_t SetRandomSeed(IPluginContext *pContext, const cell_t *params)
{ {
engrandom->SetSeed(params[1]); engrandom->SetSeed(params[1]);
@ -270,7 +259,10 @@ static cell_t smn_CreateDialog(IPluginContext *pContext, const cell_t *params)
return pContext->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr); return pContext->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
} }
serverpluginhelpers->CreateMessage(pPlayer->GetEdict(), static_cast<DIALOG_TYPE>(params[3]), pKV, g_VSP); serverpluginhelpers->CreateMessage(pPlayer->GetEdict(),
static_cast<DIALOG_TYPE>(params[3]),
pKV,
vsp_interface);
return 1; return 1;
} }
@ -415,8 +407,6 @@ static cell_t ShowVGUIPanel(IPluginContext *pContext, const cell_t *params)
return 1; return 1;
} }
static HalfLifeNatives s_HalfLifeNatives;
REGISTER_NATIVES(halflifeNatives) REGISTER_NATIVES(halflifeNatives)
{ {
{"CreateFakeClient", CreateFakeClient}, {"CreateFakeClient", CreateFakeClient},

View File

@ -50,6 +50,8 @@ IPlayerInfoManager *playerinfo = NULL;
IBaseFileSystem *basefilesystem = NULL; IBaseFileSystem *basefilesystem = NULL;
IEngineSound *enginesound = NULL; IEngineSound *enginesound = NULL;
IServerPluginHelpers *serverpluginhelpers = NULL; IServerPluginHelpers *serverpluginhelpers = NULL;
IServerPluginCallbacks *vsp_interface = NULL;
int vsp_version = 0;
PLUGIN_EXPOSE(SourceMod, g_SourceMod_Core); PLUGIN_EXPOSE(SourceMod, g_SourceMod_Core);
@ -82,7 +84,13 @@ bool SourceMod_Core::Load(PluginId id, ISmmAPI *ismm, char *error, size_t maxlen
gpGlobals = ismm->GetCGlobals(); gpGlobals = ismm->GetCGlobals();
ismm->AddListener(this, this); ismm->AddListener(this, this);
ismm->EnableVSPListener();
#if defined METAMOD_PLAPI_VERSION
if ((vsp_interface = g_SMAPI->GetVSPInfo(&vsp_version)) == NULL)
#endif
{
g_SMAPI->EnableVSPListener();
}
return g_SourceMod.InitializeSourceMod(error, maxlen, late); return g_SourceMod.InitializeSourceMod(error, maxlen, late);
} }
@ -153,15 +161,44 @@ void SourceMod_Core::OnVSPListening(IServerPluginCallbacks *iface)
/* This shouldn't happen */ /* This shouldn't happen */
if (!iface) if (!iface)
{ {
g_Logger.LogFatal("Metamod:Source version is out of date. SourceMod requires 1.4 or greater."); g_Logger.LogFatal("Metamod:Source version is out of date. SourceMod requires 1.4.2 or greater.");
return; return;
} }
if (vsp_interface == NULL)
{
vsp_interface = iface;
}
if (!g_Loaded)
{
return;
}
#if defined METAMOD_PLAPI_VERSION
if (vsp_version == 0)
{
g_SMAPI->GetVSPInfo(&vsp_version);
}
#else
if (vsp_version == 0)
{
if (strcmp(g_SourceMod.GetGameFolderName(), "ship") == 0)
{
vsp_version = 1;
}
else
{
vsp_version = 2;
}
}
#endif
/* Notify! */ /* Notify! */
SMGlobalClass *pBase = SMGlobalClass::head; SMGlobalClass *pBase = SMGlobalClass::head;
while (pBase) while (pBase)
{ {
pBase->OnSourceModVSPReceived(iface); pBase->OnSourceModVSPReceived();
pBase = pBase->m_pGlobalClassNext; pBase = pBase->m_pGlobalClassNext;
} }
} }

View File

@ -96,6 +96,8 @@ extern IPlayerInfoManager *playerinfo;
extern IBaseFileSystem *basefilesystem; extern IBaseFileSystem *basefilesystem;
extern IEngineSound *enginesound; extern IEngineSound *enginesound;
extern IServerPluginHelpers *serverpluginhelpers; extern IServerPluginHelpers *serverpluginhelpers;
extern IServerPluginCallbacks *vsp_interface;
extern int vsp_version;
#define ENGINE_CALL(func) SH_CALL(enginePatch, &IVEngineServer::func) #define ENGINE_CALL(func) SH_CALL(enginePatch, &IVEngineServer::func)
#define SERVER_CALL(func) SH_CALL(gamedllPatch, &IServerGameDLL::func) #define SERVER_CALL(func) SH_CALL(gamedllPatch, &IServerGameDLL::func)

View File

@ -306,6 +306,12 @@ void SourceModBase::StartSourceMod(bool late)
/* We're loaded! */ /* We're loaded! */
g_Loaded = true; g_Loaded = true;
/* Initialize VSP stuff */
if (vsp_interface != NULL)
{
g_SourceMod_Core.OnVSPListening(vsp_interface);
}
} }
static bool g_LevelEndBarrier = false; static bool g_LevelEndBarrier = false;

View File

@ -128,6 +128,7 @@ private:
bool m_GotBasePath; bool m_GotBasePath;
}; };
extern bool g_Loaded;
extern SourceModBase g_SourceMod; extern SourceModBase g_SourceMod;
extern HandleType_t g_WrBitBufType; //:TODO: find a better place for this extern HandleType_t g_WrBitBufType; //:TODO: find a better place for this
extern HandleType_t g_RdBitBufType; //:TODO: find a better place for this extern HandleType_t g_RdBitBufType; //:TODO: find a better place for this