255 lines
12 KiB
C++
255 lines
12 KiB
C++
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
|
|
//
|
|
// cmd.h -- Command buffer and command execution
|
|
// Any number of commands can be added in a frame, from several different sources.
|
|
// Most commands come from either keybindings or console line input, but remote
|
|
// servers can also send across commands and entire text files can be execed.
|
|
//
|
|
// The + command line options are also added to the command buffer.
|
|
//
|
|
// The game starts with a Cbuf_AddText ("exec quake.rc\n"); Cbuf_Execute ();
|
|
//
|
|
// $NoKeywords: $
|
|
//
|
|
//===========================================================================//
|
|
|
|
#ifndef CMD_H
|
|
#define CMD_H
|
|
|
|
#ifdef _WIN32
|
|
#pragma once
|
|
#endif
|
|
|
|
#include "tier1/commandbuffer.h" // cmd_source_t
|
|
|
|
// REI 7/18/2016:
|
|
//
|
|
// The main execution point for console commands is in Cmd_ExecuteCommand(). There is also a
|
|
// backdoor via Cmd_Dispatch which skips the access controls and network forwarding in
|
|
// Cmd_ExecuteCommand().
|
|
//
|
|
// In addition, there is some special game/server specific code for executing commands from the
|
|
// client that skips the normal CON_COMMAND parsing / access control / execution path. See
|
|
// section (2) below.
|
|
//
|
|
// There are 4 main paths to executing console commands, and most CON_COMMANDs fit into one
|
|
// or more of these paths based on what flags they have set. ConVars are similar to ConCommands
|
|
// but have some additional access restrictions; in particular, FCVAR_GAMEDLL vars cannot
|
|
// be executed on the server from the client, and FCVAR_REPLICATED variables are transferred from
|
|
// the server to the client automatically, not via networked console commands. (REI FIXME: Should
|
|
// probably unify access controls between console vars and console commands.)
|
|
//
|
|
// 1) No access-control flags set. Generally can be executed locally on either client or server,
|
|
// but see exceptions below.
|
|
//
|
|
// Mostly handled in cmd.cpp
|
|
// Usually created via Cbuf_AddText/CBuf_InsertText in cmd.cpp
|
|
// Executed in a batch via Cbuf_Execute -> Cmd_ExecuteCommand, also in cmd.cpp
|
|
//
|
|
// 2) FCVAR_GAMEDLL / "special" non-CON_COMMAND commands. The client cannot execute these locally,
|
|
// and always forwards these commands to the server which will execute those commands on the client's
|
|
// behalf. The "special" commands are also not executable at the server console AFAICT.
|
|
//
|
|
// Sent by any CNetMsg_StringCommand; the canonical way to send one is
|
|
// via Cmd_ForwardToServer() in cmd.cpp, or via engine->ServerCmd() in cdll_engine_int.cpp
|
|
//
|
|
// Received by CBaseClient::NETMsg_StringCmd in baseclient.cpp and forwarded
|
|
// to CGameClient::ExecuteStringCommand in sv_client.cpp. This either dispatches them to
|
|
// Cmd_Dispatch (direct execution, kind of scary? shouldn't it use Cmd_ExecuteCommand?)
|
|
// for normal CON_COMMANDs, or sends them to ::ClientCommand in server/client.cpp for
|
|
// other commands which are just matched via giant if(strcmp) branches.
|
|
//
|
|
// An example from CS:GO cs_gamerules.cpp:
|
|
// if ( FStrEq( args[0], "tr_map_show_exit_door_msg" ) )
|
|
// {
|
|
// IGameEvent * event = gameeventmanager->CreateEvent( "tr_exit_hint_trigger" );
|
|
// if ( event )
|
|
// gameeventmanager->FireEvent( event );
|
|
// return true;
|
|
// }
|
|
// (Note that this command could be executed by any client at any time by just typing
|
|
// "tr_map_show_exit_door_msg" into the console)
|
|
//
|
|
// There's also a brief excursion to server plugins in case they want to override any commands
|
|
// as well.
|
|
//
|
|
// WARNING: FCVAR_GAMEDLL is automatically set on *every* console var/command defined in the
|
|
// sever DLL. This means that in the absence of further intervention, *every* client
|
|
// can execute those commands, regardless of your intent. The common workaround to
|
|
// this is to include this check in your console commands:
|
|
// if ( !UTIL_IsCommandIssuedByServerAdmin() ) return;
|
|
// Note than convars do not have this vulnerability; FCVAR_GAMEDLL convars are not modifyable
|
|
// by clients by default. I am not sure about the reasoning behind this discrepancy. I
|
|
// believe we should have another flag FCVAR_CLIENT_CAN_EXECUTE as a parallel for
|
|
// FCVAR_SERVER_CAN_EXECUTE, but that would be a pretty drastic change at this moment and
|
|
// certainly would fork CS:GO from other Source games.
|
|
//
|
|
// 3) FCVAR_SERVER_CAN_EXECUTE. Commands which the client will execute on behalf of the server
|
|
// if requested. Note that the server is allowed to call FCVAR_CHEAT commands that the
|
|
// client could not execute themselves (that is, commands with both FCVAR_SERVER_CAN_EXECUTE
|
|
// *and* FCVAR_CHEAT are executable on the client *only* when requested by the server).
|
|
//
|
|
// Sent by any CNETMsg_StringCmd; Two canonical ways to send this message:
|
|
// - SV_ExecuteRemoteCommand in sv_main.cpp
|
|
// - g_pVEngineServer->ClientCommand in vengineserver_impl.cpp (important
|
|
// note: "ClientCommand" here is different from "ClientCmd" below!!)
|
|
//
|
|
// Received by CBaseClientState::NETMsg_StringCmd in baseclientstate.cpp
|
|
// -> CBaseClientState::InternalProcessStringCommand in baseclientstate.cpp
|
|
// -> CBuf_AddText() (the normal way to put things into the console)
|
|
//
|
|
// Note that in the absence of other access controls, these will also be in class (1),
|
|
// executable from the console on both server and client.
|
|
//
|
|
// 4) FCVAR_CLIENTCMD_CAN_EXECUTE. Commands sent from code in the client, to other code in
|
|
// the client. I am not sure of the purpose of this restriction, since the client code
|
|
// has full access to all console commands if it wants.
|
|
//
|
|
// Generally sent via engine->ClientCmd() on the client. Can call *any* command by using
|
|
// engine->ClientCmd_Unrestricted() or the immediate form engine->ExecuteClientCmd() instead.
|
|
//
|
|
// Received via the normal Cmd_ExecuteCommand path in cmd.cpp. In particular this means
|
|
// that calls to these commands will be delated until command processing happens.
|
|
//
|
|
// Note that in the absence of other access controls, these will also be in class (1),
|
|
// executable from the console on both server and client. An interesting combination is
|
|
// FCVAR_CLIENTCMD_CAN_EXECUTE -> FCVAR_GAMEDLL, which will cause calls to
|
|
// engine->ClientCmd() to redirect to the server when those commands are processed.
|
|
//
|
|
// There are a few other access-control mechanisms (most notably FCVAR_CHEAT) which disable
|
|
// access to certain commands on almost all paths unless specific engine states are met. I
|
|
// am not covering those here.
|
|
//
|
|
// Note that despite the name, not all of these commands are executed via the console. Many
|
|
// items in classes (1) and (2) are executed via keybinds on the client, or via automatically
|
|
// executed config files on either client or server. Paths (3) and (4) are really only
|
|
// accessible via code.
|
|
//
|
|
//
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Forward declarations
|
|
//-----------------------------------------------------------------------------
|
|
class CCommand;
|
|
class ConCommandBase;
|
|
|
|
typedef enum
|
|
{
|
|
// These should be single character printable things, like this:
|
|
// eCmdExecutionMarker_Enable_FCVAR_SERVER_CAN_EXECUTE = 'a',
|
|
} ECmdExecutionMarker;
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Initialization, shutdown of the command buffer
|
|
//-----------------------------------------------------------------------------
|
|
void Cbuf_Init (void);
|
|
void Cbuf_Shutdown( void );
|
|
|
|
typedef enum
|
|
{
|
|
CBUF_FIRST_PLAYER = 0,
|
|
CBUF_LAST_PLAYER = MAX_SPLITSCREEN_CLIENTS - 1,
|
|
CBUF_SERVER = CBUF_LAST_PLAYER + 1,
|
|
|
|
CBUF_COUNT,
|
|
} ECommandTarget_t;
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Clears the command buffer
|
|
//-----------------------------------------------------------------------------
|
|
void Cbuf_Clear( ECommandTarget_t eTarget );
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// as new commands are generated from the console or keybindings,
|
|
// the text is added to the end of the command buffer.
|
|
//-----------------------------------------------------------------------------
|
|
void Cbuf_AddText ( ECommandTarget_t eTarget, const char *text, cmd_source_t source = kCommandSrcCode, int nTickDelay = 0 );
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// when a command wants to issue other commands immediately, the text is
|
|
// inserted at the beginning of the buffer, before any remaining unexecuted
|
|
// commands.
|
|
//-----------------------------------------------------------------------------
|
|
void Cbuf_InsertText( ECommandTarget_t eTarget, const char *text, cmd_source_t source = kCommandSrcCode, int nTickDelay = 0 );
|
|
|
|
|
|
// These allow you to create blocks in the command stream where certain rules apply.
|
|
// ONLY use Cbuf_AddText in between execution markers. If you use Cbuf_InsertText,
|
|
// it will put that stuff before the execution marker and the execution marker won't apply.
|
|
//
|
|
// cl_restrict_server_commands uses this. It inserts a marker that says, "don't run
|
|
// anything unless it's marked with FCVAR_SERVER_CAN_EXECUTE", then inserts some commands,
|
|
// then removes the execution marker. That way, ANYTIME Cbuf_Execute() is called,
|
|
// it will apply the cl_restrict_server_commands rules correctly.
|
|
void Cbuf_AddExecutionMarker( ECommandTarget_t eTarget, ECmdExecutionMarker marker );
|
|
|
|
|
|
// Pulls off \n terminated lines of text from the command buffer and sends
|
|
// them through Cmd_ExecuteString. Stops when the buffer is empty.
|
|
// Normally called once per frame, but may be explicitly invoked.
|
|
// Do not call inside a command function!
|
|
//-----------------------------------------------------------------------------
|
|
void Cbuf_Execute();
|
|
|
|
ECommandTarget_t Cbuf_GetCurrentPlayer();
|
|
|
|
//===========================================================================
|
|
|
|
/*
|
|
|
|
Command execution takes a null terminated string, breaks it into tokens,
|
|
then searches for a command or variable that matches the first token.
|
|
|
|
Commands can come from three sources, but the handler functions may choose
|
|
to dissallow the action or forward it to a remote server if the source is
|
|
not apropriate.
|
|
|
|
*/
|
|
|
|
// FIXME: Move these into a field of CCommand?
|
|
extern int cmd_clientslot;
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Initialization, shutdown
|
|
//-----------------------------------------------------------------------------
|
|
void Cmd_Init (void);
|
|
void Cmd_Shutdown( void );
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Executes a command given a CCommand argument structure
|
|
//-----------------------------------------------------------------------------
|
|
const ConCommandBase *Cmd_ExecuteCommand( ECommandTarget_t eTarget, const CCommand &command, int nClientSlot = -1 );
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Dispatches a command with the requested arguments
|
|
//-----------------------------------------------------------------------------
|
|
void Cmd_Dispatch( const ConCommandBase *pCommand, const CCommand &args );
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// adds the current command line as a clc_stringcmd to the client message.
|
|
// things like godmode, noclip, etc, are commands directed to the server,
|
|
// so when they are typed in at the console, they will need to be forwarded.
|
|
// If bReliable is true, it goes into cls.netchan.message.
|
|
// If bReliable is false, it goes into cls.datagram.
|
|
//-----------------------------------------------------------------------------
|
|
void Cmd_ForwardToServer( const CCommand &args, bool bReliable = true );
|
|
|
|
void Cmd_ForwardToServerWithWhitelist( const CCommand &args, bool bReliable = true );
|
|
|
|
|
|
// Used to allow cheats even if cheats aren't theoretically allowed
|
|
void Cmd_SetRptActive( bool bActive );
|
|
bool Cmd_IsRptActive();
|
|
|
|
const char* Cmd_AliasToCommandString( const char* szAliasName );
|
|
|
|
bool Cbuf_IsProcessingCommands( ECommandTarget_t eTarget );
|
|
|
|
#endif // CMD_H
|