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};
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
m_IgnoreHandle = false;
@ -74,11 +74,15 @@ ConVarManager::~ConVarManager()
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)
#endif
{
SH_ADD_HOOK_MEMFUNC(IServerGameDLL, OnQueryCvarValueFinished, gamedll, this, &ConVarManager::OnQueryCvarValueFinished, false);
m_CanQueryConVars = true;
m_bIsDLLQueryHooked = true;
}
HandleAccess sec;
@ -97,10 +101,15 @@ void ConVarManager::OnSourceModAllInitialized()
void ConVarManager::OnSourceModShutdown()
{
if (m_CanQueryConVars)
if (m_bIsDLLQueryHooked)
{
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;
@ -125,27 +134,35 @@ void ConVarManager::OnSourceModShutdown()
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...
*
* If we haven't been able to hook the IServerGameDLL version at this point,
* then use hook IServerPluginCallbacks version from the engine.
/**
* Don't bother if the DLL is already hooked.
*/
/* The Ship currently only supports ServerPluginCallbacks001, but we need 002 */
if (g_IsOriginalEngine)
if (m_bIsDLLQueryHooked)
{
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;
SH_ADD_HOOK_MEMFUNC(IServerPluginCallbacks, OnQueryCvarValueFinished, iface, this, &ConVarManager::OnQueryCvarValueFinished, false);
m_CanQueryConVars = true;
return;
}
#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
@ -306,7 +323,9 @@ Handle_t ConVarManager::CreateConVar(IPluginContext *pContext, const char *name,
if (sm_trie_retrieve(m_ConVarCache, name, (void **)&pInfo))
{
return pInfo->handle;
} else {
}
else
{
/* If we don't, then create a new handle from the convar */
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;
/* Call StartQueryCvarValue() in either the IVEngineServer or IServerPluginHelpers depending on situation */
if (!m_VSPIface)
if (m_bIsDLLQueryHooked)
{
cookie = engine->StartQueryCvarValue(pPlayer, name);
} else {
}
else if (m_bIsVSPQueryHooked)
{
cookie = serverpluginhelpers->StartQueryCvarValue(pPlayer, name);
}
else
{
return InvalidQueryCvarCookie;
}
ConVarQuery query = {cookie, pCallback, hndl};
m_ConVarQueries.push_back(query);
@ -505,7 +530,9 @@ void ConVarManager::AddConVarToPluginList(IPluginContext *pContext, const ConVar
{
pConVarList = new ConVarList();
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 */
return;
}
@ -568,6 +595,11 @@ void ConVarManager::OnConVarChanged(ConVar *pConVar, const char *oldValue)
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)
{
IPluginFunction *pCallback = NULL;
@ -597,7 +629,9 @@ void ConVarManager::OnQueryCvarValueFinished(QueryCvarCookie_t cookie, edict_t *
if (result == eQueryCvarValueStatus_ValueIntact)
{
pCallback->PushString(cvarValue);
} else {
}
else
{
pCallback->PushString("\0");
}

View File

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

View File

@ -38,7 +38,6 @@
#include <compat_wrappers.h>
CHalfLife2 g_HL2;
bool g_IsOriginalEngine = false;
ConVar *sv_lan = NULL;
namespace SourceHook
@ -90,15 +89,21 @@ CHalfLife2::~CHalfLife2()
}
CSharedEdictChangeInfo *g_pSharedChangeInfo = NULL;
bool is_original_engine = false;
void CHalfLife2::OnSourceModStartup(bool late)
{
/* 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)
#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();
}
}
@ -111,6 +116,13 @@ void CHalfLife2::OnSourceModAllInitialized()
g_ShareSys.AddInterface(NULL, this);
}
#if !defined METAMOD_PLAPI_VERSION
bool CHalfLife2::IsOriginalEngine()
{
return is_original_engine;
}
#endif
IChangeInfoAccessor *CBaseEdict::GetChangeAccessor()
{
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)
{
if (!g_IsOriginalEngine)
if (g_pSharedChangeInfo != NULL)
{
if (offset)
{
@ -262,7 +274,9 @@ void CHalfLife2::SetEdictStateChanged(edict_t *pEdict, unsigned short offset)
} else {
pEdict->StateChanged();
}
} else {
}
else
{
pEdict->m_fStateFlags |= FL_EDICT_CHANGED;
}
}

View File

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

View File

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

View File

@ -143,7 +143,7 @@ public:
/**
* @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;
IPluginFunction *pCallback;
if (g_IsOriginalEngine)
if (!g_ConVarManager.IsQueryingSupported())
{
if (!s_QueryAlreadyWarned)
{

View File

@ -36,17 +36,6 @@
#include "PlayerManager.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)
{
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);
}
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;
}
@ -415,8 +407,6 @@ static cell_t ShowVGUIPanel(IPluginContext *pContext, const cell_t *params)
return 1;
}
static HalfLifeNatives s_HalfLifeNatives;
REGISTER_NATIVES(halflifeNatives)
{
{"CreateFakeClient", CreateFakeClient},

View File

@ -50,6 +50,8 @@ IPlayerInfoManager *playerinfo = NULL;
IBaseFileSystem *basefilesystem = NULL;
IEngineSound *enginesound = NULL;
IServerPluginHelpers *serverpluginhelpers = NULL;
IServerPluginCallbacks *vsp_interface = NULL;
int vsp_version = 0;
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();
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);
}
@ -153,15 +161,44 @@ void SourceMod_Core::OnVSPListening(IServerPluginCallbacks *iface)
/* This shouldn't happen */
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;
}
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! */
SMGlobalClass *pBase = SMGlobalClass::head;
while (pBase)
{
pBase->OnSourceModVSPReceived(iface);
pBase->OnSourceModVSPReceived();
pBase = pBase->m_pGlobalClassNext;
}
}

View File

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

View File

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

View File

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