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

Add source2 convar/concommand support (#203)

Co-authored-by: Nicholas Hastings <nshastings@gmail.com>
This commit is contained in:
GAMMACASE 2025-02-15 22:00:01 +03:00 committed by GitHub
parent 4fe356b724
commit a0ef30603f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
20 changed files with 402 additions and 107 deletions

View File

@ -121,6 +121,7 @@ class MMSConfig(object):
'-Wall',
'-Werror',
'-Wno-uninitialized',
'-Wno-sign-compare',
'-Wno-unused',
'-Wno-switch',
'-msse',

View File

@ -28,17 +28,15 @@ for sdk_target in MMS.sdk_targets:
binary.sources += [
'provider/source2/provider_source2.cpp',
]
binary.custom = [builder.tools.Protoc(protoc = sdk_target.protoc, sources = [
os.path.join(sdk['path'], 'common', 'network_connection.proto'),
])]
else:
binary.sources += [
'provider/source/provider_source.cpp',
'provider/source/provider_source_console.cpp',
'vsp_bridge.cpp'
]
if sdk['name'] == 'cs2':
binary.custom = [builder.tools.Protoc(protoc = sdk_target.protoc, sources = [
os.path.join(sdk['path'], 'common', 'network_connection.proto'),
])]
if cxx.target.arch == 'x86':
binary.sources += ['sourcehook/sourcehook_hookmangen_x86.cpp']

View File

@ -41,8 +41,19 @@
class CGlobalVars;
struct edict_t;
class ConCommandBase;
typedef ConCommandBase ProviderConVar;
typedef ConCommandBase ProviderConCommand;
#else
#include <eiface.h>
#if defined META_IS_SOURCE2
typedef ConVarRefAbstract ProviderConVar;
typedef ConCommandRef ProviderConCommand;
class ConCommandBase;
#else
typedef ConCommandBase ProviderConVar;
typedef ConCommandBase ProviderConCommand;
#endif
#endif
#include <ISmmPlugin.h>
@ -130,6 +141,8 @@ namespace SourceMM
/**
* @brief Registers a ConCommandBase.
*
* @deprecated since 2.1
*
* @param plugin Parent plugin API pointer.
* @param pCommand ConCommandBase to register.
@ -139,6 +152,8 @@ namespace SourceMM
/**
* @brief Unregisters a ConCommandBase.
*
* @deprecated since 2.1
*
* @param plugin Parent plugin API pointer.
* @param pCommand ConCommandBase to unlink.
@ -400,6 +415,40 @@ namespace SourceMM
size_t maxlength,
const char *format,
va_list ap) =0;
/**
* @brief Registers a ConCommand.
*
* @param plugin Parent plugin API pointer.
* @param pCommand ConCommand to register.
* @return True if successful, false otherwise.
*/
virtual bool RegisterConCommand(ISmmPlugin *plugin, ProviderConCommand *pCommand) =0;
/**
* @brief Registers a ConVar.
*
* @param plugin Parent plugin API pointer.
* @param pCvar ConVar to register.
* @return True if successful, false otherwise.
*/
virtual bool RegisterConVar(ISmmPlugin *plugin, ProviderConVar *pCvar) =0;
/**
* @brief Unregisters a ConCommand.
*
* @param plugin Parent plugin API pointer.
* @param pCommand ConCommand to unlink.
*/
virtual void UnregisterConCommand(ISmmPlugin *plugin, ProviderConCommand *pCommand) =0;
/**
* @brief Unregisters a ConVar.
*
* @param plugin Parent plugin API pointer.
* @param pCvar ConVar to unlink.
*/
virtual void UnregisterConVar(ISmmPlugin *plugin, ProviderConVar *pCvar) =0;
};
}

View File

@ -419,6 +419,8 @@ namespace SourceMM
* @brief Called when Metamod:Source is about to remove a concommand or
* convar. This can also be called if ISmmAPI::UnregisterConCmdBase is
* used by a plugin.
*
* @deprecated since PLAPI 17
*
* @param id Id of the plugin that created the concommand or
* convar.
@ -428,6 +430,30 @@ namespace SourceMM
virtual void OnUnlinkConCommandBase(PluginId id, ConCommandBase *pCommand)
{
}
/**
* @brief Called when Metamod:Source is about to remove a concommand.
* This can also be called if ISmmAPI::UnregisterConCommand is
* used by a plugin.
*
* @param id Id of the plugin that created the concommand.
* @param pCommand Pointer to concommand that is being removed.
*/
virtual void OnUnlinkConCommand(PluginId id, ProviderConCommand *pCommand)
{
}
/**
* @brief Called when Metamod:Source is about to remove a convar.
* This can also be called if ISmmAPI::UnregisterConVar is
* used by a plugin.
*
* @param id Id of the plugin that created the convar.
* @param pVar Pointer to convar that is being removed.
*/
virtual void OnUnlinkConVar(PluginId id, ProviderConVar *pVar)
{
}
};
}
@ -492,13 +518,31 @@ using namespace SourceMM;
g_PLID = id;
#define META_LOG g_SMAPI->LogMsg
#define META_REGCMD(name) g_SMAPI->RegisterConCommandBase(g_PLAPI, name##_command)
#define META_REGCVAR(var) g_SMAPI->RegisterConCommandBase(g_PLAPI, var)
#define META_UNREGCMD(name) g_SMAPI->UnregisterConCommandBase(g_PLAPI, name##_command)
#define META_UNREGCVAR(var) g_SMAPI->UnregisterConCommandBase(g_PLAPI, var)
#define META_CONPRINT g_SMAPI->ConPrint
#define META_CONPRINTF g_SMAPI->ConPrintf
#if defined META_IS_SOURCE2
#define META_UNREGCMD(name) g_SMAPI->UnregisterConCommand( g_PLAPI, name##_command )
#define META_UNREGCVAR(var) g_SMAPI->UnregisterConVar( g_PLAPI, var )
#define META_CONVAR_REGISTER(flags) ConVar_Register( flags, \
[]( ConVarRefAbstract *ref ) { g_SMAPI->RegisterConVar( g_PLAPI, ref ); }, \
[]( ConCommandRef *ref ) { g_SMAPI->RegisterConCommand( g_PLAPI, ref ); } \
)
#else
// @deprecated since 2.1
#define META_REGCMD(name) g_SMAPI->RegisterConCommandBase(g_PLAPI, name##_command)
// @deprecated since 2.1
#define META_REGCVAR(var) g_SMAPI->RegisterConCommandBase(g_PLAPI, var)
// @deprecated since 2.1
#define META_UNREGCMD(name) g_SMAPI->UnregisterConCommandBase(g_PLAPI, name##_command)
// @deprecated since 2.1
#define META_UNREGCVAR(var) g_SMAPI->UnregisterConCommandBase(g_PLAPI, var)
#define META_REGBASECMD(var) (var->IsCommand() ? g_SMAPI->RegisterConCommand(g_PLAPI, var) : g_SMAPI->RegisterConVar(g_PLAPI, var))
#define META_UNREGBASECMD(var) (var->IsCommand() ? g_SMAPI->UnregisterConCommand(g_PLAPI, var) : g_SMAPI->UnregisterConVar(g_PLAPI, var))
#endif
/* Probably should use this up above someday */
#define CONCMD_VARNAME(name) name##_command

View File

@ -65,7 +65,7 @@
#define SOURCE_ENGINE_MCV 27 /**< Military Conflict: Vietnam */
#define SOURCE_ENGINE_CS2 28 /**< Counter-Strike 2 */
#define METAMOD_PLAPI_VERSION 16 /**< Version of this header file */
#define METAMOD_PLAPI_VERSION 17 /**< Version of this header file */
#define METAMOD_PLAPI_NAME "ISmmPlugin" /**< Name of the plugin interface */
namespace SourceMM

View File

@ -919,33 +919,48 @@ const char *MetamodSource::GetVDFDir()
bool MetamodSource::RegisterConCommandBase(ISmmPlugin *plugin, ConCommandBase *pCommand)
{
if (provider->IsConCommandBaseACommand(pCommand))
{
g_PluginMngr.AddPluginCmd(plugin, pCommand);
}
return RegisterConCommand(plugin, (ProviderConCommand *)pCommand);
else
{
g_PluginMngr.AddPluginCvar(plugin, pCommand);
}
return provider->RegisterConCommandBase(pCommand);
return RegisterConVar(plugin, (ProviderConVar *)pCommand);
}
void MetamodSource::UnregisterConCommandBase(ISmmPlugin *plugin, ConCommandBase *pCommand)
{
if (provider->IsConCommandBaseACommand(pCommand))
{
g_PluginMngr.RemovePluginCmd(plugin, pCommand);
}
UnregisterConCommand(plugin, (ProviderConCommand *)pCommand);
else
{
g_PluginMngr.RemovePluginCvar(plugin, pCommand);
}
CPluginManager::CPlugin *pOrig = g_PluginMngr.FindByAPI(plugin);
UnregisterConCommandBase(pOrig ? pOrig->m_Id : 0, pCommand);
UnregisterConVar(plugin, (ProviderConVar *)pCommand);
}
void MetamodSource::UnregisterConCommandBase(PluginId id, ConCommandBase *pCommand)
bool MetamodSource::RegisterConCommand(ISmmPlugin *plugin, ProviderConCommand *pCommand)
{
g_PluginMngr.AddPluginCmd(plugin, pCommand);
return provider->RegisterConCommand(pCommand);
}
bool MetamodSource::RegisterConVar(ISmmPlugin *plugin, ProviderConVar *pVar)
{
g_PluginMngr.AddPluginCvar(plugin, pVar);
return provider->RegisterConVar(pVar);
}
void MetamodSource::UnregisterConCommand(ISmmPlugin *plugin, ProviderConCommand *pCommand)
{
CPluginManager::CPlugin *pOrig = g_PluginMngr.FindByAPI(plugin);
g_PluginMngr.RemovePluginCmd(plugin, pCommand);
UnregisterConCommand(pOrig ? pOrig->m_Id : 0, pCommand);
}
void MetamodSource::UnregisterConVar(ISmmPlugin *plugin, ProviderConVar *pVar)
{
CPluginManager::CPlugin *pOrig = g_PluginMngr.FindByAPI(plugin);
g_PluginMngr.RemovePluginCvar(plugin, pVar);
UnregisterConVar(pOrig ? pOrig->m_Id : 0, pVar);
}
void MetamodSource::UnregisterConCommand(PluginId id, ProviderConCommand *pCommand)
{
PluginIter iter;
CPluginManager::CPlugin *pPlugin;
@ -963,16 +978,74 @@ void MetamodSource::UnregisterConCommandBase(PluginId id, ConCommandBase *pComma
{
continue;
}
for (event=pPlugin->m_Events.begin();
event!=pPlugin->m_Events.end();
event++)
if(pPlugin->m_API->GetApiVersion() < 17)
{
pML = (*event);
pML->OnUnlinkConCommandBase(id, pCommand);
for(event=pPlugin->m_Events.begin();
event != pPlugin->m_Events.end();
event++)
{
pML = (*event);
pML->OnUnlinkConCommandBase(id, (ConCommandBase *)pCommand);
}
}
else
{
for(event=pPlugin->m_Events.begin();
event != pPlugin->m_Events.end();
event++)
{
pML = (*event);
pML->OnUnlinkConCommand(id, pCommand);
}
}
}
return provider->UnregisterConCommandBase(pCommand);
return provider->UnregisterConCommand(pCommand);
}
void MetamodSource::UnregisterConVar(PluginId id, ProviderConVar *pVar)
{
PluginIter iter;
CPluginManager::CPlugin *pPlugin;
List<IMetamodListener *>::iterator event;
IMetamodListener *pML;
for(iter=g_PluginMngr._begin(); iter != g_PluginMngr._end(); iter++)
{
pPlugin = (*iter);
if(pPlugin->m_Status < Pl_Paused)
{
continue;
}
/* Only valid for plugins >= 12 (v1:6, SourceMM 1.5) */
if(pPlugin->m_API->GetApiVersion() < 12)
{
continue;
}
if(pPlugin->m_API->GetApiVersion() < 17)
{
for(event=pPlugin->m_Events.begin();
event != pPlugin->m_Events.end();
event++)
{
pML = (*event);
pML->OnUnlinkConCommandBase(id, (ConCommandBase *)pVar);
}
}
else
{
for(event=pPlugin->m_Events.begin();
event != pPlugin->m_Events.end();
event++)
{
pML = (*event);
pML->OnUnlinkConVar(id, pVar);
}
}
}
return provider->UnregisterConVar(pVar);
}
int MetamodSource::GetUserMessageCount()

View File

@ -49,7 +49,7 @@ using namespace SourceMM;
#define SOURCEMM_VERSION SVN_FILE_VERSION_STRING
#define SOURCEMM_DATE __DATE__
#define METAMOD_API_MAJOR 2 /* increase this on a breaking change */
#define METAMOD_API_MINOR 0 /* increase this on a non-breaking API change */
#define METAMOD_API_MINOR 1 /* increase this on a non-breaking API change */
class MetamodSource : public ISmmAPI
{
@ -62,6 +62,10 @@ public: // ISmmAPI
CGlobalVars *GetCGlobals() override;
bool RegisterConCommandBase(ISmmPlugin *plugin, ConCommandBase *pCommand) override;
void UnregisterConCommandBase(ISmmPlugin *plugin, ConCommandBase *pCommand) override;
bool RegisterConCommand(ISmmPlugin *plugin, ProviderConCommand *pCommand) override;
bool RegisterConVar(ISmmPlugin *plugin, ProviderConVar *pCvar) override;
void UnregisterConCommand(ISmmPlugin *plugin, ProviderConCommand *pCommand) override;
void UnregisterConVar(ISmmPlugin *plugin, ProviderConVar *pCvar) override;
void ConPrint(const char *str) override;
void ConPrintf(const char *fmt, ...) override;
void GetApiVersions(int &major, int &minor, int &plvers, int &plmin) override;
@ -91,7 +95,8 @@ public:
const char *GetGameBinaryPath();
const char *GetPluginsFile();
const char *GetVDFDir();
void UnregisterConCommandBase(PluginId id, ConCommandBase *pCommand);
void UnregisterConCommand(PluginId id, ProviderConCommand *pCommand);
void UnregisterConVar(PluginId id, ProviderConVar *pVar);
void NotifyVSPListening(IServerPluginCallbacks *callbacks, int version);
const char* GetGameDLLInterfaceName() const;
void SetGameDLLInfo(CreateInterfaceFn serverFactory, const char *pGameDllIfaceName, int version, bool loaded);

View File

@ -240,7 +240,7 @@ bool Command_Meta(IMetamodSourceCommandInfo *info)
else
{
CONMSG("Console commands for %s:\n", pl->m_API->GetName());
List<ConCommandBase *>::iterator ci;
List<ProviderConCommand *>::iterator ci;
size_t count = 0;
for (ci=pl->m_Cmds.begin(); ci!=pl->m_Cmds.end(); ci++)
@ -277,7 +277,7 @@ bool Command_Meta(IMetamodSourceCommandInfo *info)
else
{
CONMSG("Registered cvars for %s:\n", pl->m_API->GetName());
List<ConCommandBase *>::iterator ci;
List<ProviderConVar *>::iterator ci;
size_t count = 0;
for (ci=pl->m_Cvars.begin(); ci!=pl->m_Cvars.end(); ci++)

View File

@ -802,7 +802,7 @@ PluginIter CPluginManager::_end()
return m_Plugins.end();
}
void CPluginManager::AddPluginCvar(ISmmPlugin *api, ConCommandBase *pCvar)
void CPluginManager::AddPluginCvar(ISmmPlugin *api, ProviderConVar *pCvar)
{
CPlugin *pl = FindByAPI(api);
@ -814,7 +814,7 @@ void CPluginManager::AddPluginCvar(ISmmPlugin *api, ConCommandBase *pCvar)
pl->m_Cvars.push_back(pCvar);
}
void CPluginManager::AddPluginCmd(ISmmPlugin *api, ConCommandBase *pCmd)
void CPluginManager::AddPluginCmd(ISmmPlugin *api, ProviderConCommand *pCmd)
{
CPlugin *pl = FindByAPI(api);
@ -826,7 +826,7 @@ void CPluginManager::AddPluginCmd(ISmmPlugin *api, ConCommandBase *pCmd)
pl->m_Cmds.push_back(pCmd);
}
void CPluginManager::RemovePluginCvar(ISmmPlugin *api, ConCommandBase *pCvar)
void CPluginManager::RemovePluginCvar(ISmmPlugin *api, ProviderConVar *pCvar)
{
CPlugin *pl = FindByAPI(api);
@ -838,7 +838,7 @@ void CPluginManager::RemovePluginCvar(ISmmPlugin *api, ConCommandBase *pCvar)
pl->m_Cvars.remove(pCvar);
}
void CPluginManager::RemovePluginCmd(ISmmPlugin *api, ConCommandBase *pCmd)
void CPluginManager::RemovePluginCmd(ISmmPlugin *api, ProviderConCommand *pCmd)
{
CPlugin *pl = FindByAPI(api);
@ -852,18 +852,16 @@ void CPluginManager::RemovePluginCmd(ISmmPlugin *api, ConCommandBase *pCmd)
void CPluginManager::UnregAllConCmds(CPlugin *pl)
{
SourceHook::List<ConCommandBase *>::iterator i;
/* :TODO: */
for (i=pl->m_Cvars.begin(); i!=pl->m_Cvars.end(); i++)
for (auto i=pl->m_Cvars.begin(); i!=pl->m_Cvars.end(); i++)
{
g_Metamod.UnregisterConCommandBase(pl->m_Id, (*i) );
g_Metamod.UnregisterConVar(pl->m_Id, (*i) );
}
pl->m_Cvars.clear();
for (i=pl->m_Cmds.begin(); i!=pl->m_Cmds.end(); i++)
for (auto i=pl->m_Cmds.begin(); i!=pl->m_Cmds.end(); i++)
{
g_Metamod.UnregisterConCommandBase(pl->m_Id, (*i) );
g_Metamod.UnregisterConCommand(pl->m_Id, (*i) );
}
pl->m_Cmds.clear();
}

View File

@ -90,8 +90,8 @@ public:
PluginId m_Source;
ISmmPlugin *m_API;
HINSTANCE m_Lib;
SourceHook::List<ConCommandBase *> m_Cvars;
SourceHook::List<ConCommandBase *> m_Cmds;
SourceHook::List<ProviderConVar *> m_Cvars;
SourceHook::List<ProviderConCommand *> m_Cmds;
SourceHook::List<IMetamodListener *> m_Events;
METAMOD_FN_UNLOAD m_UnloadFn;
};
@ -111,10 +111,10 @@ public:
bool QueryRunning(PluginId id, char *error, size_t maxlength);
bool QueryHandle(PluginId id, void **handle);
void AddPluginCvar(ISmmPlugin *api, ConCommandBase *pCvar);
void AddPluginCmd(ISmmPlugin *api, ConCommandBase *pCmd);
void RemovePluginCvar(ISmmPlugin *api, ConCommandBase *pCvar);
void RemovePluginCmd(ISmmPlugin *api, ConCommandBase *pCmd);
void AddPluginCvar(ISmmPlugin *api, ProviderConVar *pCvar);
void AddPluginCmd(ISmmPlugin *api, ProviderConCommand *pCmd);
void RemovePluginCvar(ISmmPlugin *api, ProviderConVar *pCvar);
void RemovePluginCmd(ISmmPlugin *api, ProviderConCommand *pCmd);
/**
* @brief Finds a plugin by Id

View File

@ -254,19 +254,34 @@ namespace SourceMM
virtual const char *GetGameDescription() =0;
/**
* @brief Registers a ConCommandBase.
* @brief Registers a ConCommand.
*
* @param pCommand ConCommandBase to register.
* @param pCommand ConCommand to register.
* @return True if successful, false otherwise.
*/
virtual bool RegisterConCommandBase(ConCommandBase *pCommand) =0;
virtual bool RegisterConCommand(ProviderConCommand *pCommand) =0;
/**
* @brief Unregisters a ConCommandBase.
* @brief Registers a ConVar.
*
* @param pCommand ConCommandBase to unlink.
* @param pVar ConVar to register.
* @return True if successful, false otherwise.
*/
virtual void UnregisterConCommandBase(ConCommandBase *pCommand) =0;
virtual bool RegisterConVar(ProviderConVar *pVar) =0;
/**
* @brief Unregisters a ConCommand.
*
* @param pCommand ConCommand to unlink.
*/
virtual void UnregisterConCommand(ProviderConCommand *pCommand) =0;
/**
* @brief Unregisters a ConVar.
*
* @param pVar ConVar to unlink.
*/
virtual void UnregisterConVar(ProviderConVar *pVar) =0;
/**
* @brief Returns whether a ConCommandBase is a command or not.

View File

@ -68,8 +68,10 @@ public: // Must implement
int flags) override = 0;
virtual const char* GetConVarString(MetamodSourceConVar *convar) override = 0;
virtual void SetConVarString(MetamodSourceConVar *convar, const char* str) override = 0;
virtual bool RegisterConCommandBase(ConCommandBase* pCommand) override = 0;
virtual void UnregisterConCommandBase(ConCommandBase* pCommand) override = 0;
virtual bool RegisterConCommand(ProviderConCommand *pCommand) override = 0;
virtual bool RegisterConVar(ProviderConVar *pVar) override = 0;
virtual void UnregisterConCommand(ProviderConCommand *pCommand) override = 0;
virtual void UnregisterConVar(ProviderConVar *pVar) override = 0;
virtual bool IsConCommandBaseACommand(ConCommandBase* pCommand) override = 0;
public: // May implement/override (stubbed)
virtual int GetUserMessageCount() override { return -1; }

View File

@ -385,14 +385,24 @@ bool SourceProvider::IsConCommandBaseACommand(ConCommandBase* pCommand)
return pCommand->IsCommand();
}
bool SourceProvider::RegisterConCommandBase(ConCommandBase* pCommand)
bool SourceProvider::RegisterConCommand(ProviderConCommand* pCommand)
{
return m_ConVarAccessor.Register(pCommand);
}
void SourceProvider::UnregisterConCommandBase(ConCommandBase* pCommand)
bool SourceProvider::RegisterConVar(ProviderConVar* pVar)
{
return m_ConVarAccessor.Unregister(pCommand);
return m_ConVarAccessor.Register(pVar);
}
void SourceProvider::UnregisterConCommand(ProviderConCommand* pCommand)
{
m_ConVarAccessor.Unregister(pCommand);
}
void SourceProvider::UnregisterConVar(ProviderConVar* pVar)
{
m_ConVarAccessor.Unregister(pVar);
}
MetamodSourceConVar* SourceProvider::CreateConVar(const char* name,

View File

@ -55,8 +55,10 @@ public: // BaseProvider
int flags) override;
virtual const char* GetConVarString(MetamodSourceConVar *convar) override;
virtual void SetConVarString(MetamodSourceConVar *convar, const char* str) override;
virtual bool RegisterConCommandBase(ConCommandBase* pCommand) override;
virtual void UnregisterConCommandBase(ConCommandBase* pCommand) override;
virtual bool RegisterConCommand(ProviderConCommand *pCommand) override;
virtual bool RegisterConVar(ProviderConVar *pVar) override;
virtual void UnregisterConCommand(ProviderConCommand *pCommand) override;
virtual void UnregisterConVar(ProviderConVar *pVar) override;
virtual bool IsConCommandBaseACommand(ConCommandBase* pCommand) override;
virtual int GetUserMessageCount() override;
virtual int FindUserMessage(const char* name, int* size = nullptr) override;

View File

@ -151,6 +151,9 @@ void Source2Provider::Notify_DLLInit_Pre(CreateInterfaceFn engineFactory,
void Source2Provider::Notify_DLLShutdown_Pre()
{
for(auto cvar : m_RegisteredConVars)
delete cvar;
ConVar_Unregister();
SH_REMOVE_HOOK(IEngineServiceMgr, RegisterLoopMode, enginesvcmgr, SH_MEMBER(this, &Source2Provider::Hook_RegisterLoopMode), false);
@ -267,48 +270,61 @@ void Source2Provider::ServerCommand(const char* cmd)
const char* Source2Provider::GetConVarString(MetamodSourceConVar *convar)
{
#ifdef S2_CONVAR_UNFINISHED
if (convar == NULL)
{
return NULL;
}
return convar->GetString();
#else
return nullptr;
#endif
auto &value = reinterpret_cast<CConVar<CUtlString> *>(convar)->Get();
return !value.IsEmpty() ? value.Get() : nullptr;
}
void Source2Provider::SetConVarString(MetamodSourceConVar *convar, const char* str)
{
#ifdef S2_CONVAR_UNFINISHED
convar->SetValue(str);
#endif
reinterpret_cast<CConVar<CUtlString> *>(convar)->Set( str );
}
bool Source2Provider::IsConCommandBaseACommand(ConCommandBase* pCommand)
{
#ifdef S2_CONVAR_UNFINISHED
return pCommand->IsCommand();
#else
// This method shouldn't ever be called on s2 titles
return false;
#endif
}
bool Source2Provider::RegisterConCommandBase(ConCommandBase* pCommand)
bool Source2Provider::RegisterConCommand(ProviderConCommand* pCommand)
{
#ifdef S2_CONVAR_UNFINISHED
return g_SMConVarAccessor.Register(pCommand);
#else
// Registration is handled by the plugins
// If command has FCVAR_DEVELOPMENTONLY and is registered through our system
// assume that it's previously plugin registered command that was hidden (on plugin reloads for example),
// so remove that flag to make it available again
if(pCommand->IsFlagSet( FCVAR_DEVELOPMENTONLY ))
pCommand->RemoveFlags( FCVAR_DEVELOPMENTONLY );
return true;
#endif
}
void Source2Provider::UnregisterConCommandBase(ConCommandBase* pCommand)
bool Source2Provider::RegisterConVar(ProviderConVar *pVar)
{
#ifdef S2_CONVAR_UNFINISHED
return g_SMConVarAccessor.Unregister(pCommand);
#endif
// Registration is handled by the plugins
return true;
}
void Source2Provider::UnregisterConCommand(ProviderConCommand *pCommand)
{
icvar->UnregisterConCommandCallbacks(*pCommand);
// Hide command from the search, as it would still be available otherwise
pCommand->AddFlags( FCVAR_DEVELOPMENTONLY );
}
void Source2Provider::UnregisterConVar(ProviderConVar *pVar)
{
icvar->UnregisterConVarCallbacks(*pVar);
// Invalidate cvar for future use
// This makes it hidden from the search and lets future convar registrations of that
// name to take over its setup
pVar->GetConVarData()->Invalidate();
}
MetamodSourceConVar* Source2Provider::CreateConVar(const char* name,
@ -316,8 +332,7 @@ MetamodSourceConVar* Source2Provider::CreateConVar(const char* name,
const char* help,
int flags)
{
#ifdef S2_CONVAR_UNFINISHED
int newflags = 0;
uint64 newflags = 0ll;
if (flags & ConVarFlag_Notify)
{
newflags |= FCVAR_NOTIFY;
@ -327,14 +342,11 @@ MetamodSourceConVar* Source2Provider::CreateConVar(const char* name,
newflags |= FCVAR_SPONLY;
}
ConVar* pVar = new ConVar(name, defval, newflags, help);
CConVar<CUtlString> *pVar = new CConVar<CUtlString>( name, newflags, help, defval );
m_RegisteredConVars.push_back( pVar );
g_SMConVarAccessor.RegisterConCommandBase(pVar);
return pVar;
#else
return nullptr;
#endif
return reinterpret_cast<MetamodSourceConVar *>(pVar);
}
class GlobCommand : public IMetamodSourceCommandInfo

View File

@ -32,6 +32,7 @@
#include <tier1/utlvector.h>
#include <IEngineService.h>
#include <string>
#include <vector>
// TODO: is this still needed for Dota or CS2 on any platform?
#if SOURCE_ENGINE == SE_DOTA && defined( _WIN32 )
@ -61,8 +62,10 @@ public:
int flags) override;
virtual const char* GetConVarString(MetamodSourceConVar *convar) override;
virtual void SetConVarString(MetamodSourceConVar *convar, const char* str) override;
virtual bool RegisterConCommandBase(ConCommandBase* pCommand) override;
virtual void UnregisterConCommandBase(ConCommandBase* pCommand) override;
virtual bool RegisterConCommand(ProviderConCommand *pCommand) override;
virtual bool RegisterConVar(ProviderConVar *pVar) override;
virtual void UnregisterConCommand(ProviderConCommand *pCommand) override;
virtual void UnregisterConVar(ProviderConVar *pVar) override;
virtual bool IsConCommandBaseACommand(ConCommandBase* pCommand) override;
public:
#ifdef SHOULD_OVERRIDE_ALLOWDEDICATED_SERVER
@ -77,6 +80,7 @@ public:
void Hook_ClientCommand(CPlayerSlot nSlot, const CCommand& args);
private:
IFileSystem* baseFs = nullptr;
std::vector<CConVar<CUtlString> *> m_RegisteredConVars;
friend void LocalCommand_Meta(const CCommandContext& context, const CCommand& args);
};

@ -1 +1 @@
Subproject commit 2ae4644db6459ae16da7e3900260bbd6aa7ba03d
Subproject commit 37da720ae7ff42fbda3be88c7465860c9e2421fc

View File

@ -54,8 +54,8 @@ class BaseAccessor : public IConCommandBaseAccessor
public:
bool RegisterConCommandBase(ConCommandBase *pCommandBase)
{
/* Always call META_REGCVAR instead of going through the engine. */
return META_REGCVAR(pCommandBase);
/* Always call META_REGBASECMD instead of going through the engine. */
return META_REGBASECMD(pCommandBase);
}
} s_BaseAccessor;

View File

@ -154,6 +154,7 @@ class MMSPluginConfig(object):
'-fno-strict-aliasing',
'-Wall',
'-Werror',
'-Wno-sign-compare',
'-Wno-uninitialized',
'-Wno-unused',
'-Wno-switch',

View File

@ -46,10 +46,17 @@ CGlobalVars *GetGameGlobals()
return g_pNetworkServerService->GetIGameServer()->GetGlobals();
}
#if 0
// Currently unavailable, requires hl2sdk work!
ConVar sample_cvar("sample_cvar", "42", 0);
#endif
void SampleCvarFChangeCB( CConVar<float> *cvar, CSplitScreenSlot slot, const float *new_val, const float *old_val )
{
META_CONPRINTF( "Sample convar \"%s\" was changed from %f to %f [%s]\n",
cvar->GetName(), *old_val, *new_val,
// When convar is first initialised with a default value, it would have FCVAR_INITIAL_SETVALUE
// flag set, so you can check for it if needed.
cvar->IsFlagSet( FCVAR_INITIAL_SETVALUE ) ? "initialised" : "change" );
}
CConVar<int> sample_cvari("sample_cvari", FCVAR_NONE, "help string", 42);
CConVar<float> sample_cvarf("sample_cvarf", FCVAR_NONE, "help string", 69.69f, true, 10.0f, true, 100.0f, SampleCvarFChangeCB );
CON_COMMAND_F(sample_command, "Sample command", FCVAR_NONE)
{
@ -87,7 +94,81 @@ bool SamplePlugin::Load(PluginId id, ISmmAPI *ismm, char *error, size_t maxlen,
META_CONPRINTF( "All hooks started!\n" );
g_pCVar = icvar;
ConVar_Register( FCVAR_RELEASE | FCVAR_CLIENT_CAN_EXECUTE | FCVAR_GAMEDLL );
META_CONVAR_REGISTER( FCVAR_RELEASE | FCVAR_CLIENT_CAN_EXECUTE | FCVAR_GAMEDLL );
// You can get a convar reference to an already existing cvar via CConVarRef.
// This will pre-register it if it's not yet registered and would use default data until
// the actual cvar is registered. You can assert data existance via IsConVarDataAvailable().
// Make sure the type is correct here otherwise it might prevent actual convar being registered,
// since you pre-registered it with a different type or if convar already exists you'd be left with
// an invalid ref, so a check for IsValidRef() is also nice to have.
// Generally with these you should just know the type of a cvar you are referencing beforehand
// and if not, refer to ConVarRefAbstract usage
//
// Side Note: Always make sure you are working with a valid ref (IsValidRef()) before reading/writing to it
// as otherwise you'd be reading/writing off of default convar data which is shared across
// all the invalid convar refs.
CConVarRef<int> ccvar_ref_example( "mp_limitteams" );
if(ccvar_ref_example.IsValidRef() && ccvar_ref_example.IsConVarDataAvailable())
{
META_CONPRINTF( "CConVarRef \"%s\" got value pre = %d [float = %f, bool = %d, string = \"%s\"]\n",
ccvar_ref_example.GetName(), ccvar_ref_example.Get(),
ccvar_ref_example.GetFloat(), ccvar_ref_example.GetBool(),
ccvar_ref_example.GetString() );
// By default if you are using CConVar or CConVarRef you should be using Get()/Set()
// methods to read/write values, as these are templated for the particular type the cvar is of.
// It also is usually faster since it skips all the type conversion logic of non templated methods
ccvar_ref_example.Set( 5 );
// As noted above there are methods that support value conversion between certain types
// so stuff like this is possible on an int typed cvar for example,
// refer to ConVarRefAbstract declaration for more info on these methods
ccvar_ref_example.SetFloat( 8.5f );
META_CONPRINTF( "CConVarRef \"%s\" got value after = %d [float = %f, bool = %d, string = \"%s\"]\n",
ccvar_ref_example.GetName(), ccvar_ref_example.Get(),
ccvar_ref_example.GetFloat(), ccvar_ref_example.GetBool(),
ccvar_ref_example.GetString() );
}
// You can also use ConVarRefAbstract class if you don't want typisation support
// or don't know the actual type used, since you are responsible for picking the correct type there!
// And ConVarRefAbstract won't pre-register the convar in the system, as it acts as a plain ref,
// so make sure to check the ref for validity before usage via IsValidRef()
ConVarRefAbstract cvar_ref_example( "mp_limitteams" );
if(cvar_ref_example.IsValidRef())
{
META_CONPRINTF( "ConVarRefAbstract \"%s\" got value pre [float = %f, bool = %d, string = \"%s\"]\n",
cvar_ref_example.GetName(), cvar_ref_example.GetFloat(), cvar_ref_example.GetBool(), cvar_ref_example.GetString() );
// Since the ref is not typed, you can't use direct Get() and Set() methods,
// instead you need to use methods with type conversion support.
cvar_ref_example.SetFloat( 10.0f );
// If you work with convars of non primitive types, you can also use SetAs() methods
// to try to set the value as a specific type, if type mismatches it would try to do
// conversion if possible and if not it would do nothing.
// There's also an equvialent methods for reading the value, GetAs()
cvar_ref_example.SetAs<Vector>( Vector( 1.0f, 2.0f, 3.0f ) );
// Alternatively you can "promote" plain ref to a typed variant by passing plain ref to a constructor
// but be careful, as there's a type checker in place that would invalidate convar ref
// if cast to a wrong type was attempted, you can check for that either via IsValidRef()
// or IsConVarDataValid() (usually IsValidRef() is enough) afterwards, but generally you should
// just know the correct type of the cvar you are casting to beforehand.
CConVarRef<int> promoted_ref( cvar_ref_example );
if(promoted_ref.IsValidRef() && promoted_ref.IsConVarDataValid())
{
// If the promoted ref is valid, you can use its templated methods like with CConVarRef/CConVar
promoted_ref.Set( 5 );
}
META_CONPRINTF( "ConVarRefAbstract \"%s\" got value after [float = %f, bool = %d, string = \"%s\"]\n",
cvar_ref_example.GetName(), cvar_ref_example.GetFloat(), cvar_ref_example.GetBool(), cvar_ref_example.GetString() );
}
return true;
}