Move ConCommand hooks into GameHooks and switch callbacks to ICommandArgs.

This commit is contained in:
David Anderson 2015-09-06 12:35:04 -07:00
parent b63bfdc72a
commit b048dc7b10
12 changed files with 169 additions and 66 deletions

View File

@ -36,20 +36,14 @@
#include "ChatTriggers.h" #include "ChatTriggers.h"
#include "logic_bridge.h" #include "logic_bridge.h"
#include "sourcemod.h" #include "sourcemod.h"
#include "provider.h"
#include "command_args.h"
#include <bridge/include/IScriptManager.h> #include <bridge/include/IScriptManager.h>
using namespace ke; using namespace ke;
ConCmdManager g_ConCmds; ConCmdManager g_ConCmds;
#if SOURCE_ENGINE == SE_DOTA
SH_DECL_HOOK2_void(ConCommand, Dispatch, SH_NOATTRIB, false, const CCommandContext &, const CCommand &);
#elif SOURCE_ENGINE >= SE_ORANGEBOX
SH_DECL_HOOK1_void(ConCommand, Dispatch, SH_NOATTRIB, false, const CCommand &);
#else
SH_DECL_HOOK0_void(ConCommand, Dispatch, SH_NOATTRIB, false);
#endif
SH_DECL_HOOK1_void(IServerGameClients, SetCommandClient, SH_NOATTRIB, false, int); SH_DECL_HOOK1_void(IServerGameClients, SetCommandClient, SH_NOATTRIB, false, int);
typedef ke::LinkedList<CmdHook *> PluginHookList; typedef ke::LinkedList<CmdHook *> PluginHookList;
@ -142,23 +136,13 @@ void ConCmdManager::OnPluginDestroyed(IPlugin *plugin)
delete pList; delete pList;
} }
#if SOURCE_ENGINE == SE_DOTA void CommandCallback(DISPATCH_ARGS)
void CommandCallback(const CCommandContext &context, const CCommand &command)
{ {
#elif SOURCE_ENGINE >= SE_ORANGEBOX DISPATCH_PROLOGUE;
void CommandCallback(const CCommand &command) EngineArgs args(command);
{
#else
void CommandCallback()
{
CCommand command;
#endif
g_HL2.PushCommandStack(&command); AutoEnterCommand autoEnterCommand(&args);
g_ConCmds.InternalDispatch(&args);
g_ConCmds.InternalDispatch(command);
g_HL2.PopCommandStack();
} }
void ConCmdManager::SetCommandClient(int client) void ConCmdManager::SetCommandClient(int client)
@ -232,7 +216,7 @@ ResultType ConCmdManager::DispatchClientCommand(int client, const char *cmd, int
return (ResultType)result; return (ResultType)result;
} }
void ConCmdManager::InternalDispatch(const CCommand &command) void ConCmdManager::InternalDispatch(const ICommandArgs *args)
{ {
int client = m_CmdClient; int client = m_CmdClient;
@ -275,7 +259,7 @@ void ConCmdManager::InternalDispatch(const CCommand &command)
return; return;
cell_t result = Pl_Continue; cell_t result = Pl_Continue;
int args = command.ArgC() - 1; int argc = args->ArgC() - 1;
// On a listen server, sometimes the server host's client index can be set // On a listen server, sometimes the server host's client index can be set
// as 0. So index 1 is passed to the command callback to correct this // as 0. So index 1 is passed to the command callback to correct this
@ -311,7 +295,7 @@ void ConCmdManager::InternalDispatch(const CCommand &command)
hook->pf->PushCell(realClient); hook->pf->PushCell(realClient);
} }
hook->pf->PushCell(args); hook->pf->PushCell(argc);
cell_t tempres = result; cell_t tempres = result;
if (hook->pf->Execute(&tempres) == SP_ERROR_NONE) if (hook->pf->Execute(&tempres) == SP_ERROR_NONE)
@ -556,17 +540,14 @@ void ConCmdManager::RemoveConCmd(ConCmdInfo *info, const char *name, bool is_rea
} }
else else
{ {
if (is_read_safe) // If it's not safe to read the pointer, we zap the SourceHook hook so it
{ // doesn't attempt to access the pointer's vtable.
/* Remove the external hook */ if (!is_read_safe)
SH_REMOVE_HOOK(ConCommand, Dispatch, info->pCmd, SH_STATIC(CommandCallback), false); info->sh_hook->Zap();
}
if (untrack) if (untrack)
{
UntrackConCommandBase(info->pCmd, this); UntrackConCommandBase(info->pCmd, this);
} }
} }
}
/* Remove from list */ /* Remove from list */
m_CmdList.remove(info); m_CmdList.remove(info);
@ -623,7 +604,11 @@ ConCmdInfo *ConCmdManager::AddOrFindCommand(const char *name, const char *descri
else else
{ {
TrackConCommandBase(pCmd, this); TrackConCommandBase(pCmd, this);
SH_ADD_HOOK(ConCommand, Dispatch, pCmd, SH_STATIC(CommandCallback), false); CommandHook::Callback callback = [this] (const ICommandArgs *args) {
AutoEnterCommand autoEnterCommand(args);
this->InternalDispatch(args);
};
pInfo->sh_hook = sCoreProviderImpl.AddCommandHook(pCmd, callback);
} }
pInfo->pCmd = pCmd; pInfo->pCmd = pCmd;

View File

@ -40,6 +40,7 @@
#include <IRootConsoleMenu.h> #include <IRootConsoleMenu.h>
#include <IAdminSystem.h> #include <IAdminSystem.h>
#include "concmd_cleaner.h" #include "concmd_cleaner.h"
#include "GameHooks.h"
#include <sm_stringhashmap.h> #include <sm_stringhashmap.h>
#include <am-utility.h> #include <am-utility.h>
#include <am-inlinelist.h> #include <am-inlinelist.h>
@ -105,6 +106,7 @@ struct ConCmdInfo
ConCommand *pCmd; /**< Pointer to the command itself */ ConCommand *pCmd; /**< Pointer to the command itself */
CmdHookList hooks; /**< Hook list */ CmdHookList hooks; /**< Hook list */
FlagBits eflags; /**< Effective admin flags */ FlagBits eflags; /**< Effective admin flags */
ke::Ref<CommandHook> sh_hook; /**< SourceHook hook, if any. */
}; };
typedef List<ConCmdInfo *> ConCmdList; typedef List<ConCmdInfo *> ConCmdList;
@ -115,13 +117,7 @@ class ConCmdManager :
public IPluginsListener, public IPluginsListener,
public IConCommandTracker public IConCommandTracker
{ {
#if SOURCE_ENGINE == SE_DOTA friend void CommandCallback(DISPATCH_ARGS);
friend void CommandCallback(const CCommandContext &context, const CCommand &command);
#elif SOURCE_ENGINE >= SE_ORANGEBOX
friend void CommandCallback(const CCommand &command);
#else
friend void CommandCallback();
#endif
public: public:
ConCmdManager(); ConCmdManager();
~ConCmdManager(); ~ConCmdManager();
@ -147,7 +143,7 @@ public:
bool LookForSourceModCommand(const char *cmd); bool LookForSourceModCommand(const char *cmd);
bool LookForCommandAdminFlags(const char *cmd, FlagBits *pFlags); bool LookForCommandAdminFlags(const char *cmd, FlagBits *pFlags);
private: private:
void InternalDispatch(const CCommand &command); void InternalDispatch(const ICommandArgs *args);
ResultType RunAdminCommand(ConCmdInfo *pInfo, int client, int args); ResultType RunAdminCommand(ConCmdInfo *pInfo, int client, int args);
ConCmdInfo *AddOrFindCommand(const char *name, const char *description, int flags); ConCmdInfo *AddOrFindCommand(const char *name, const char *description, int flags);
void SetCommandClient(int client); void SetCommandClient(int client);

View File

@ -50,6 +50,7 @@
#include "HalfLife2.h" #include "HalfLife2.h"
#include "ConCommandBaseIterator.h" #include "ConCommandBaseIterator.h"
#include "logic_bridge.h" #include "logic_bridge.h"
#include "command_args.h"
#include <am-utility.h> #include <am-utility.h>
#include <bridge/include/ILogger.h> #include <bridge/include/ILogger.h>
@ -653,10 +654,10 @@ bool ConsoleDetours::RemoveListener(IPluginFunction *fun, const char *command)
} }
} }
cell_t ConsoleDetours::InternalDispatch(int client, const CCommand& args) cell_t ConsoleDetours::InternalDispatch(int client, const ICommandArgs *args)
{ {
char name[255]; char name[255];
const char *realname = args.Arg(0); const char *realname = args->Arg(0);
size_t len = strlen(realname); size_t len = strlen(realname);
// Disallow command strings that are too long, for now. // Disallow command strings that are too long, for now.
@ -675,7 +676,7 @@ cell_t ConsoleDetours::InternalDispatch(int client, const CCommand& args)
cell_t result = Pl_Continue; cell_t result = Pl_Continue;
m_pForward->PushCell(client); m_pForward->PushCell(client);
m_pForward->PushString(name); m_pForward->PushString(name);
m_pForward->PushCell(args.ArgC() - 1); m_pForward->PushCell(args->ArgC() - 1);
m_pForward->Execute(&result, NULL); m_pForward->Execute(&result, NULL);
/* Don't let plugins block this. */ /* Don't let plugins block this. */
@ -694,7 +695,7 @@ cell_t ConsoleDetours::InternalDispatch(int client, const CCommand& args)
cell_t result2 = Pl_Continue; cell_t result2 = Pl_Continue;
forward->PushCell(client); forward->PushCell(client);
forward->PushString(name); forward->PushString(name);
forward->PushCell(args.ArgC() - 1); forward->PushCell(args->ArgC() - 1);
forward->Execute(&result2, NULL); forward->Execute(&result2, NULL);
if (result2 > result) if (result2 > result)
@ -714,9 +715,12 @@ cell_t ConsoleDetours::Dispatch(ConCommand *pBase)
{ {
CCommand args; CCommand args;
#endif #endif
g_HL2.PushCommandStack(&args); EngineArgs cargs(args);
cell_t res = g_ConsoleDetours.InternalDispatch(g_ConCmds.GetCommandClient(), args); cell_t res;
g_HL2.PopCommandStack(); {
AutoEnterCommand autoEnterCommand(&cargs);
res = g_ConsoleDetours.InternalDispatch(g_ConCmds.GetCommandClient(), &cargs);
}
#if SH_IMPL_VERSION < 4 #if SH_IMPL_VERSION < 4
if (res >= Pl_Handled) if (res >= Pl_Handled)

View File

@ -36,6 +36,10 @@
#include <IForwardSys.h> #include <IForwardSys.h>
#include <sm_stringhashmap.h> #include <sm_stringhashmap.h>
namespace SourceMod {
class ICommandArgs;
} // namespace SourceMod
class ConsoleDetours : class ConsoleDetours :
public SMGlobalClass, public SMGlobalClass,
public IFeatureProvider public IFeatureProvider
@ -54,7 +58,7 @@ public:
bool AddListener(IPluginFunction *fun, const char *command); bool AddListener(IPluginFunction *fun, const char *command);
bool RemoveListener(IPluginFunction *fun, const char *command); bool RemoveListener(IPluginFunction *fun, const char *command);
private: private:
cell_t InternalDispatch(int client, const CCommand& args); cell_t InternalDispatch(int client, const SourceMod::ICommandArgs *args);
#if SOURCE_ENGINE >= SE_ORANGEBOX #if SOURCE_ENGINE >= SE_ORANGEBOX
static cell_t Dispatch(ConCommand *pBase, const CCommand& args); static cell_t Dispatch(ConCommand *pBase, const CCommand& args);
#else #else

View File

@ -27,6 +27,7 @@
#include "GameHooks.h" #include "GameHooks.h"
#include "sourcemod.h" #include "sourcemod.h"
#include "ConVarManager.h" #include "ConVarManager.h"
#include "command_args.h"
#if SOURCE_ENGINE >= SE_ORANGEBOX #if SOURCE_ENGINE >= SE_ORANGEBOX
SH_DECL_HOOK3_void(ICvar, CallGlobalChangeCallbacks, SH_NOATTRIB, false, ConVar *, const char *, float); SH_DECL_HOOK3_void(ICvar, CallGlobalChangeCallbacks, SH_NOATTRIB, false, ConVar *, const char *, float);
@ -42,6 +43,14 @@ SH_DECL_HOOK5_void(IServerGameDLL, OnQueryCvarValueFinished, SH_NOATTRIB, 0, Que
SH_DECL_HOOK5_void(IServerPluginCallbacks, OnQueryCvarValueFinished, SH_NOATTRIB, 0, QueryCvarCookie_t, edict_t *, EQueryCvarValueStatus, const char *, const char *); SH_DECL_HOOK5_void(IServerPluginCallbacks, OnQueryCvarValueFinished, SH_NOATTRIB, 0, QueryCvarCookie_t, edict_t *, EQueryCvarValueStatus, const char *, const char *);
#endif #endif
#if SOURCE_ENGINE == SE_DOTA
SH_DECL_HOOK2_void(ConCommand, Dispatch, SH_NOATTRIB, false, const CCommandContext &, const CCommand &);
#elif SOURCE_ENGINE >= SE_ORANGEBOX
SH_DECL_HOOK1_void(ConCommand, Dispatch, SH_NOATTRIB, false, const CCommand &);
#else
SH_DECL_HOOK0_void(ConCommand, Dispatch, SH_NOATTRIB, false);
#endif
GameHooks::GameHooks() GameHooks::GameHooks()
: client_cvar_query_mode_(ClientCvarQueryMode::Unavailable) : client_cvar_query_mode_(ClientCvarQueryMode::Unavailable)
{ {
@ -128,3 +137,43 @@ void GameHooks::OnQueryCvarValueFinished(QueryCvarCookie_t cookie, edict_t *pPla
g_ConVarManager.OnClientQueryFinished(cookie, client, result, cvarName, cvarValue); g_ConVarManager.OnClientQueryFinished(cookie, client, result, cvarName, cvarValue);
} }
#endif #endif
ke::PassRef<CommandHook>
GameHooks::AddCommandHook(ConCommand *cmd, const CommandHook::Callback &callback)
{
return new CommandHook(cmd, callback, false);
}
ke::PassRef<CommandHook>
GameHooks::AddPostCommandHook(ConCommand *cmd, const CommandHook::Callback &callback)
{
return new CommandHook(cmd, callback, true);
}
CommandHook::CommandHook(ConCommand *cmd, const Callback &callback, bool post)
: hook_id_(0),
callback_(callback)
{
hook_id_ = SH_ADD_HOOK(ConCommand, Dispatch, cmd, SH_MEMBER(this, &CommandHook::Dispatch), post);
}
CommandHook::~CommandHook()
{
if (hook_id_)
SH_REMOVE_HOOK_ID(hook_id_);
}
void CommandHook::Dispatch(DISPATCH_ARGS)
{
DISPATCH_PROLOGUE;
EngineArgs args(command);
AddRef();
callback_(&args);
Release();
}
void CommandHook::Zap()
{
hook_id_ = 0;
}

View File

@ -32,18 +32,52 @@
#include <stddef.h> #include <stddef.h>
#include <eiface.h> #include <eiface.h>
#include <iserverplugin.h> #include <iserverplugin.h>
#include <amtl/am-refcounting.h>
#include <amtl/am-vector.h> #include <amtl/am-vector.h>
#include <amtl/am-function.h>
class ConVar; class ConVar;
class CCommand;
struct CCommandContext;
#if SOURCE_ENGINE == SE_DOTA
# define DISPATCH_ARGS const CCommandContext &context, const CCommand &command
# define DISPATCH_PROLOGUE
#elif SOURCE_ENGINE >= SE_ORANGEBOX
# define DISPATCH_ARGS const CCommand &command
# define DISPATCH_PROLOGUE
#else
# define DISPATCH_ARGS
# define DISPATCH_PROLOGUE CCommand command
#endif
namespace SourceMod { namespace SourceMod {
// Describes the mechanism in which client cvar queries are implemented.
enum class ClientCvarQueryMode { enum class ClientCvarQueryMode {
Unavailable, Unavailable,
DLL, DLL,
VSP VSP
}; };
class ICommandArgs;
class CommandHook : public ke::Refcounted<CommandHook>
{
public:
typedef ke::Lambda<void(const ICommandArgs *)> Callback;
public:
CommandHook(ConCommand *cmd, const Callback &callback, bool post);
~CommandHook();
void Dispatch(DISPATCH_ARGS);
void Zap();
private:
int hook_id_;
Callback callback_;
};
class GameHooks class GameHooks
{ {
public: public:
@ -57,6 +91,10 @@ public:
return client_cvar_query_mode_; return client_cvar_query_mode_;
} }
public:
ke::PassRef<CommandHook> AddCommandHook(ConCommand *cmd, const CommandHook::Callback &callback);
ke::PassRef<CommandHook> AddPostCommandHook(ConCommand *cmd, const CommandHook::Callback &callback);
private: private:
// Static callback that Valve's ConVar object executes when the convar's value changes. // Static callback that Valve's ConVar object executes when the convar's value changes.
#if SOURCE_ENGINE >= SE_ORANGEBOX #if SOURCE_ENGINE >= SE_ORANGEBOX

View File

@ -825,7 +825,7 @@ bool CHalfLife2::KVLoadFromFile(KeyValues *kv, IBaseFileSystem *filesystem, cons
} }
} }
void CHalfLife2::PushCommandStack(const CCommand *cmd) void CHalfLife2::PushCommandStack(const ICommandArgs *cmd)
{ {
CachedCommandInfo info; CachedCommandInfo info;
@ -837,7 +837,7 @@ void CHalfLife2::PushCommandStack(const CCommand *cmd)
m_CommandStack.push(info); m_CommandStack.push(info);
} }
const CCommand *CHalfLife2::PeekCommandStack() const ICommandArgs *CHalfLife2::PeekCommandStack()
{ {
if (m_CommandStack.empty()) if (m_CommandStack.empty())
{ {

View File

@ -49,7 +49,9 @@
#include <tier0/icommandline.h> #include <tier0/icommandline.h>
#include <string_t.h> #include <string_t.h>
class CCommand; namespace SourceMod {
class ICommandArgs;
} // namespace SourceMod
using namespace SourceHook; using namespace SourceHook;
using namespace SourceMod; using namespace SourceMod;
@ -100,7 +102,7 @@ struct DelayedFakeCliCmd
struct CachedCommandInfo struct CachedCommandInfo
{ {
const CCommand *args; const ICommandArgs *args;
#if SOURCE_ENGINE <= SE_DARKMESSIAH #if SOURCE_ENGINE <= SE_DARKMESSIAH
char cmd[300]; char cmd[300];
#endif #endif
@ -141,6 +143,7 @@ class CHalfLife2 :
public SMGlobalClass, public SMGlobalClass,
public IGameHelpers public IGameHelpers
{ {
friend class AutoEnterCommand;
public: public:
CHalfLife2(); CHalfLife2();
~CHalfLife2(); ~CHalfLife2();
@ -190,9 +193,7 @@ public:
void AddToFakeCliCmdQueue(int client, int userid, const char *cmd); void AddToFakeCliCmdQueue(int client, int userid, const char *cmd);
void ProcessFakeCliCmdQueue(); void ProcessFakeCliCmdQueue();
public: public:
void PushCommandStack(const CCommand *cmd); const ICommandArgs *PeekCommandStack();
void PopCommandStack();
const CCommand *PeekCommandStack();
const char *CurrentCommandName(); const char *CurrentCommandName();
void AddDelayedKick(int client, int userid, const char *msg); void AddDelayedKick(int client, int userid, const char *msg);
void ProcessDelayedKicks(); void ProcessDelayedKicks();
@ -200,6 +201,8 @@ public:
bool IsOriginalEngine(); bool IsOriginalEngine();
#endif #endif
private: private:
void PushCommandStack(const ICommandArgs *cmd);
void PopCommandStack();
DataTableInfo *_FindServerClass(const char *classname); DataTableInfo *_FindServerClass(const char *classname);
private: private:
void InitLogicalEntData(); void InitLogicalEntData();
@ -224,4 +227,15 @@ extern CHalfLife2 g_HL2;
bool IndexToAThings(cell_t, CBaseEntity **pEntData, edict_t **pEdictData); bool IndexToAThings(cell_t, CBaseEntity **pEntData, edict_t **pEdictData);
class AutoEnterCommand
{
public:
AutoEnterCommand(const ICommandArgs *args) {
g_HL2.PushCommandStack(args);
}
~AutoEnterCommand() {
g_HL2.PopCommandStack();
}
};
#endif //_INCLUDE_SOURCEMOD_CHALFLIFE2_H_ #endif //_INCLUDE_SOURCEMOD_CHALFLIFE2_H_

View File

@ -47,6 +47,7 @@
#include "logic_bridge.h" #include "logic_bridge.h"
#include <sourcemod_version.h> #include <sourcemod_version.h>
#include "smn_keyvalues.h" #include "smn_keyvalues.h"
#include "command_args.h"
#include <ITranslator.h> #include <ITranslator.h>
#include <bridge/include/IExtensionBridge.h> #include <bridge/include/IExtensionBridge.h>
#include <bridge/include/IScriptManager.h> #include <bridge/include/IScriptManager.h>
@ -1180,7 +1181,8 @@ void PlayerManager::OnClientCommand(edict_t *pEntity)
RETURN_META(MRES_SUPERCEDE); RETURN_META(MRES_SUPERCEDE);
} }
g_HL2.PushCommandStack(&args); EngineArgs cargs(args);
AutoEnterCommand autoEnterCommand(&cargs);
int argcount = args.ArgC() - 1; int argcount = args.ArgC() - 1;
const char *cmd = g_HL2.CurrentCommandName(); const char *cmd = g_HL2.CurrentCommandName();
@ -1199,10 +1201,9 @@ void PlayerManager::OnClientCommand(edict_t *pEntity)
if (g_ConsoleDetours.IsEnabled()) if (g_ConsoleDetours.IsEnabled())
{ {
cell_t res2 = g_ConsoleDetours.InternalDispatch(client, args); cell_t res2 = g_ConsoleDetours.InternalDispatch(client, &cargs);
if (res2 >= Pl_Stop) if (res2 >= Pl_Stop)
{ {
g_HL2.PopCommandStack();
RETURN_META(MRES_SUPERCEDE); RETURN_META(MRES_SUPERCEDE);
} }
else if (res2 > res) else if (res2 > res)
@ -1226,14 +1227,11 @@ void PlayerManager::OnClientCommand(edict_t *pEntity)
if (res >= Pl_Stop) if (res >= Pl_Stop)
{ {
g_HL2.PopCommandStack();
RETURN_META(MRES_SUPERCEDE); RETURN_META(MRES_SUPERCEDE);
} }
res = g_ConCmds.DispatchClientCommand(client, cmd, argcount, (ResultType)res); res = g_ConCmds.DispatchClientCommand(client, cmd, argcount, (ResultType)res);
g_HL2.PopCommandStack();
if (res >= Pl_Handled) if (res >= Pl_Handled)
{ {
RETURN_META(MRES_SUPERCEDE); RETURN_META(MRES_SUPERCEDE);

View File

@ -742,6 +742,18 @@ bool CoreProviderImpl::LoadBridge(char *error, size_t maxlength)
return true; return true;
} }
ke::PassRef<CommandHook>
CoreProviderImpl::AddCommandHook(ConCommand *cmd, const CommandHook::Callback &callback)
{
return hooks_.AddCommandHook(cmd, callback);
}
ke::PassRef<CommandHook>
CoreProviderImpl::AddPostCommandHook(ConCommand *cmd, const CommandHook::Callback &callback)
{
return hooks_.AddPostCommandHook(cmd, callback);
}
void CoreProviderImpl::InitializeHooks() void CoreProviderImpl::InitializeHooks()
{ {
hooks_.Start(); hooks_.Start();

View File

@ -65,6 +65,9 @@ public:
int QueryClientConVar(int client, const char *cvar) override; int QueryClientConVar(int client, const char *cvar) override;
bool IsClientConVarQueryingSupported() override; bool IsClientConVarQueryingSupported() override;
ke::PassRef<CommandHook> AddCommandHook(ConCommand *cmd, const CommandHook::Callback &callback);
ke::PassRef<CommandHook> AddPostCommandHook(ConCommand *cmd, const CommandHook::Callback &callback);
private: private:
ke::Ref<ke::SharedLib> logic_; ke::Ref<ke::SharedLib> logic_;
LogicInitFunction logic_init_; LogicInitFunction logic_init_;

View File

@ -784,7 +784,7 @@ static cell_t sm_RegAdminCmd(IPluginContext *pContext, const cell_t *params)
static cell_t sm_GetCmdArgs(IPluginContext *pContext, const cell_t *params) static cell_t sm_GetCmdArgs(IPluginContext *pContext, const cell_t *params)
{ {
const CCommand *pCmd = g_HL2.PeekCommandStack(); const ICommandArgs *pCmd = g_HL2.PeekCommandStack();
if (!pCmd) if (!pCmd)
{ {
@ -796,7 +796,7 @@ static cell_t sm_GetCmdArgs(IPluginContext *pContext, const cell_t *params)
static cell_t sm_GetCmdArg(IPluginContext *pContext, const cell_t *params) static cell_t sm_GetCmdArg(IPluginContext *pContext, const cell_t *params)
{ {
const CCommand *pCmd = g_HL2.PeekCommandStack(); const ICommandArgs *pCmd = g_HL2.PeekCommandStack();
if (!pCmd) if (!pCmd)
{ {
@ -814,7 +814,7 @@ static cell_t sm_GetCmdArg(IPluginContext *pContext, const cell_t *params)
static cell_t sm_GetCmdArgString(IPluginContext *pContext, const cell_t *params) static cell_t sm_GetCmdArgString(IPluginContext *pContext, const cell_t *params)
{ {
const CCommand *pCmd = g_HL2.PeekCommandStack(); const ICommandArgs *pCmd = g_HL2.PeekCommandStack();
if (!pCmd) if (!pCmd)
{ {