diff --git a/core/ConCmdManager.cpp b/core/ConCmdManager.cpp index b64b78d6..e44c5d90 100644 --- a/core/ConCmdManager.cpp +++ b/core/ConCmdManager.cpp @@ -157,7 +157,12 @@ void CommandCallback() { CCommand command; #endif + + g_HL2.PushCommandStack(&command); + g_ConCmds.InternalDispatch(command); + + g_HL2.PopCommandStack(); } void ConCmdManager::SetCommandClient(int client) @@ -230,8 +235,7 @@ void ConCmdManager::InternalDispatch(const CCommand &command) * -- * Whether or not it goes through the callback is determined by FCVAR_GAMEDLL */ - char cmd[300]; - strncopy(cmd, command.Arg(0), sizeof(cmd)); + const char *cmd = g_HL2.CurrentCommandName(); ConCmdInfo *pInfo; if (!sm_trie_retrieve(m_pCmds, cmd, (void **)&pInfo)) diff --git a/core/ConVarManager.cpp b/core/ConVarManager.cpp index f9831058..01e8e178 100644 --- a/core/ConVarManager.cpp +++ b/core/ConVarManager.cpp @@ -527,13 +527,16 @@ void ConVarManager::AddConVarToPluginList(IPluginContext *pContext, const ConVar } #if defined ORANGEBOX_BUILD -void ConVarManager::OnConVarChanged(IConVar *pConVar, const char *oldValue, float flOldValue) +void ConVarManager::OnConVarChanged(IConVar *pIConVar, const char *oldValue, float flOldValue) #else void ConVarManager::OnConVarChanged(ConVar *pConVar, const char *oldValue) #endif { /* If the values are the same, exit early in order to not trigger callbacks */ - if (strcmp(reinterpret_cast(pConVar)->GetString(), oldValue) == 0) +#if defined ORANGEBOX_BUILD + ConVar *pConVar = (ConVar *)pIConVar; +#endif + if (strcmp(pConVar->GetString(), oldValue) == 0) { return; } diff --git a/core/HalfLife2.cpp b/core/HalfLife2.cpp index 3deeb771..18c2bebc 100644 --- a/core/HalfLife2.cpp +++ b/core/HalfLife2.cpp @@ -382,3 +382,39 @@ bool CHalfLife2::IsLANServer() return (sv_lan->GetInt() != 0); } + +void CHalfLife2::PushCommandStack(const CCommand *cmd) +{ + CachedCommandInfo info; + + info.args = cmd; +#if !defined ORANGEBOX_BUILD + strncopy(info.cmd, cmd->Arg(0), sizeof(info.cmd)); +#endif + + m_CommandStack.push(info); +} + +const CCommand *CHalfLife2::PeekCommandStack() +{ + if (m_CommandStack.empty()) + { + return NULL; + } + + return m_CommandStack.front().args; +} + +void CHalfLife2::PopCommandStack() +{ + m_CommandStack.pop(); +} + +const char *CHalfLife2::CurrentCommandName() +{ +#if defined ORANGEBOX_BUILD + return m_CommandStack.front().args->Arg(0); +#else + return m_CommandStack.front().cmd; +#endif +} diff --git a/core/HalfLife2.h b/core/HalfLife2.h index 23664fc3..221e010a 100644 --- a/core/HalfLife2.h +++ b/core/HalfLife2.h @@ -41,6 +41,8 @@ #include #include +class CCommand; + using namespace SourceHook; using namespace SourceMod; @@ -66,6 +68,14 @@ struct DelayedFakeCliCmd int userid; }; +struct CachedCommandInfo +{ + const CCommand *args; +#if !defined ORANGEBOX_BUILD + char cmd[300]; +#endif +}; + class CHalfLife2 : public SMGlobalClass, public IGameHelpers @@ -90,6 +100,11 @@ public: //IGameHelpers public: void AddToFakeCliCmdQueue(int client, int userid, const char *cmd); void ProcessFakeCliCmdQueue(); +public: + void PushCommandStack(const CCommand *cmd); + void PopCommandStack(); + const CCommand *PeekCommandStack(); + const char *CurrentCommandName(); private: DataTableInfo *_FindServerClass(const char *classname); private: @@ -101,6 +116,7 @@ private: int m_VGUIMenu; Queue m_CmdQueue; CStack m_FreeCmds; + CStack m_CommandStack; }; extern CHalfLife2 g_HL2; diff --git a/core/PlayerManager.cpp b/core/PlayerManager.cpp index 99fff178..d9528ee2 100644 --- a/core/PlayerManager.cpp +++ b/core/PlayerManager.cpp @@ -44,6 +44,7 @@ #include "Translator.h" #include "Logger.h" #include "ChatTriggers.h" +#include "HalfLife2.h" PlayerManager g_Players; bool g_OnMapStarted = false; @@ -586,12 +587,10 @@ void PlayerManager::OnClientCommand(edict_t *pEntity) return; } - /** - * We cache this because the engine is not re-entrant. - */ - char cmd[300]; + g_HL2.PushCommandStack(&args); + int argcount = args.ArgC() - 1; - strncopy(cmd, args.Arg(0), sizeof(cmd)); + const char *cmd = g_HL2.CurrentCommandName(); bool result = g_ValveMenuStyle.OnClientCommand(client, cmd, args); if (result) @@ -617,11 +616,14 @@ void PlayerManager::OnClientCommand(edict_t *pEntity) if (res >= Pl_Stop) { + g_HL2.PopCommandStack(); RETURN_META(MRES_SUPERCEDE); } res = g_ConCmds.DispatchClientCommand(client, cmd, argcount, (ResultType)res); + g_HL2.PopCommandStack(); + if (res >= Pl_Handled) { RETURN_META(MRES_SUPERCEDE); diff --git a/core/smn_console.cpp b/core/smn_console.cpp index b556ecb0..d88ccd2a 100644 --- a/core/smn_console.cpp +++ b/core/smn_console.cpp @@ -623,28 +623,50 @@ static cell_t sm_RegAdminCmd(IPluginContext *pContext, const cell_t *params) return 1; } -BUILD INTENTIONALLY BROKEN BY BAIL -HAHA -I DOUBT YOU CAN COMPILE THIS, GCC +LOL BUILD IS STILL BROKEN +LOL +Seriously. Don't compile it. static cell_t sm_GetCmdArgs(IPluginContext *pContext, const cell_t *params) { - return 4; //:O;//engine->Cmd_Argc() - 1; + const CCommand *pCmd = g_HL2.PeekCommandStack(); + + if (!pCmd) + { + return pContext->ThrowNativeError("No command callback available"); + } + + return pCmd->ArgC() - 1; } static cell_t sm_GetCmdArg(IPluginContext *pContext, const cell_t *params) { - //const char *arg = //engine->Cmd_Argv(params[1]); + const CCommand *pCmd = g_HL2.PeekCommandStack(); + + if (!pCmd) + { + return pContext->ThrowNativeError("No command callback available"); + } + size_t length; + + const char *arg = pCmd->Arg(params[1]); - //pContext->StringToLocalUTF8(params[2], params[3], arg, &length); + pContext->StringToLocalUTF8(params[2], params[3], arg ? arg : "", &length); return (cell_t)length; } static cell_t sm_GetCmdArgString(IPluginContext *pContext, const cell_t *params) { - const char *args = NULL;//engine->Cmd_Args(); + const CCommand *pCmd = g_HL2.PeekCommandStack(); + + if (!pCmd) + { + return pContext->ThrowNativeError("No command callback available"); + } + + const char *args = pCmd->ArgS(); size_t length; if (!args)