VoltMod
C++23 framework for CS2 server plugins
Loading...
Searching...
No Matches
Controller.cpp
Go to the documentation of this file.
7#include <eiface.h>
8#include <icvar.h>
9#include <string>
10#include <string_view>
11#include <tier1/convar.h>
12#include <utility>
13
14namespace VoltMod
15{
16
17// Passed by value across the plugin boundary, so the layout is ABI.
18static_assert(sizeof(Controller) <= 104, "Controller is a frame-local value; keep the field list tight.");
19
21{
22 _pawn = entities.Get(PlayerPawn()).Raw();
23}
24
26{
27 return _sys ? VoltMod::Pawn{*_sys, _pawn} : VoltMod::Pawn{};
28}
29
31{
32 return _sys ? VoltMod::Pawn{*_sys, _sys->Get(PawnRef()).Raw()} : VoltMod::Pawn{};
33}
34
36{
37 // m_pButtonStates[0] holds the buttons down this tick.
38 const Schema::CPlayer_MovementServices services = InputPawn().MovementServices();
39 return services ? services.Buttons().ButtonStates(0) : 0;
40}
41
43{
44 const Schema::CCSPlayerController_InGameMoneyServices money = InGameMoneyServices();
45 return money ? money.Account() : 0;
46}
47
49{
50 const Schema::CCSPlayerController_InGameMoneyServices money = InGameMoneyServices();
51 if (money)
52 {
53 money.SetAccount(amount);
54 }
55}
56
57void Controller::Kick(std::string_view reason) const
58{
59 if (!_e || !_sys || !_sys->Interfaces().Engine)
60 {
61 return;
62 }
63
64 const std::string text(reason);
65 _sys->Interfaces().Engine->DisconnectClient(CPlayerSlot(_slot), NETWORK_DISCONNECT_KICKED, text.c_str());
66}
67
68/** Tokenizes @p command into @p args when it is exactly one non-empty command. */
69static bool TokenizeOneCommand(std::string_view command, CCommand& args)
70{
71 if (command.empty() || command.find_first_of(";\r\n") != std::string_view::npos)
72 {
73 return false;
74 }
75 return args.Tokenize(CUtlString(std::string(command).c_str())) && args.ArgC() > 0;
76}
77
78void Controller::ExecuteCommand(std::string_view command) const
79{
80 if (!_e || !_sys || !IsValidSlot(_slot))
81 {
82 return;
83 }
84 auto* cvar = _sys->Interfaces().CVar;
86 if (!cvar || !clients)
87 {
88 return;
89 }
90
93 {
94 Log::Warn("Controller: refused client command '{}'; it must be one non-empty command.", command);
95 return;
96 }
97
98 ConCommandRef registered = cvar->FindConCommand(args.Arg(0));
99 if (registered.IsValidRef())
100 {
102 }
103 else
104 {
105 clients->ClientCommand(CPlayerSlot(_slot), args);
106 }
107}
108
110{
111 const bool joinable = team == Team::Spectator || IsPlaying(team);
112 if (_e && _sys && joinable && _sys->Bindings().ChangeTeam)
113 {
114 _sys->Bindings().ChangeTeam(_e, std::to_underlying(team));
115 }
116}
117
119{
120 if (!_e || !_sys)
121 {
122 return std::unexpected(Error::NotReady("no controller"));
123 }
124
125 const auto& respawn = _sys->Bindings().Respawn;
126 if (!respawn)
127 {
128 return std::unexpected(Error::Unsupported("gamedata has no 'CCSPlayerController::Respawn' vtable index"));
129 }
130
131 respawn(_e);
132 return {};
133}
134
135} // namespace VoltMod
void SetMoney(int amount) const
VoltMod::Pawn InputPawn() const
void ChangeTeam(VoltMod::Team team) const
uint64_t Buttons() const
void Kick(std::string_view reason) const
VoltMod::Pawn Pawn() const
void ExecuteCommand(std::string_view command) const
Status Respawn() const
runtime.Entities: finds and creates entities. Everything it returns is valid for this frame only; see...
const VoltMod::Bindings & Bindings() const noexcept
Entity Get(EntityRef ref)
const VoltMod::Interfaces & Interfaces() const noexcept
A live entity, valid for this frame only.
Definition Entity.hpp:29
EntitySystem * _sys
Definition Entity.hpp:31
CEntityInstance * _e
Definition Entity.hpp:32
CEntityInstance * Raw() const noexcept
Definition Entity.hpp:47
A player's body: health, armor, movement, aim, weapons. The engine replaces it on every spawn; the Co...
Definition Pawn.hpp:19
void Warn(std::format_string< Args... > fmt, Args &&... args)
Definition Log.hpp:88
constexpr bool IsPlaying(Team team)
Definition Team.hpp:18
static std::string ReadFile(const std::filesystem::path &path)
Definition Loader.cpp:56
static bool TokenizeOneCommand(std::string_view command, CCommand &args)
constexpr bool IsValidSlot(int slot)
Definition Slot.hpp:13
std::expected< void, Error > Status
Definition Result.hpp:67
VirtualFn< void(CEntityInstance *, int)> ChangeTeam
Definition Bindings.hpp:74
VirtualFn< void(CEntityInstance *)> Respawn
Definition Bindings.hpp:75
static Error Unsupported(std::string detail)
Definition Result.hpp:57
static Error NotReady(std::string detail)
Definition Result.hpp:50
IVEngineServer2 * Engine
ISource2GameClients * ServerGameClients