Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/twhl-community/halflife-unified-sdk/llms.txt

Use this file to discover all available pages before exploring further.

The Half-Life Unified SDK provides a structured registry for client commands — commands that players send from their client to the server. In the original SDK, incoming client commands were matched using a chain of if statements. The Unified SDK replaces this with a proper registry that supports dynamic registration and removal of commands at any time during the game’s lifetime.

Command Structure

Commands take a std::function object for a function signature void(CBasePlayer* player, const CCommandArgs& args). Typical use involves using a capturing lambda to forward command execution to a member function, as shown below. The player entity is that of the player who issued the command. Commands also have a name and flags. The name must include only lowercase alphabetical and underscore characters.

Flags

FlagDescription
ClientCommandFlag::NoneConstant to use when no flags are set
ClientCommandFlag::CheatIndicates that this command is a cheat command, only allowed when sv_cheats is non-zero

Registering Commands

There are two ways to register commands, depending on how you want to manage the lifetime of the command. If a command exists for the lifetime of another object like a gamerules class then you should use a scoped command:
//In the class declaration:
CScopedClientCommand m_SpectateCommand;

//In the constructor:
CGameRules::CGameRules()
{
	m_SpectateCommand = g_ClientCommands.CreateScoped("spectate", [this](CBasePlayer* player, const CCommandArgs& args)
		{
			// clients wants to become a spectator
			BecomeSpectator(player, args);
		});
}
The command will be removed automatically when the gamerules object is destroyed. When the command lifetime does not matter or if you need to manage its lifetime manually you should use the Create function:
g_ClientCommands.Create("say", [](CBasePlayer* player, const CCommandArgs& args)
	{
		Host_Say(player->edict(), false);
	});
The pointer returned by this function can be used to remove the command at any time by calling Remove:
g_ClientCommands.Remove(myCommand);
myCommand = nullptr;
To set flags on the command, pass the flags as an additional argument:
g_ClientCommands.Create("give", [](CBasePlayer* player, const CCommandArgs& args)
	{
		int iszItem = ALLOC_STRING(args.Argument(1)); // Make a copy of the classname
		player->GiveNamedItem(STRING(iszItem));
	},
	{.Flags = ClientCommandFlag::Cheat});
This feature relies on Designated initializers.

Build docs developers (and LLMs) love