VoltMod
C++23 framework for CS2 server plugins
Loading...
Searching...
No Matches
ArgBinding.hpp
Go to the documentation of this file.
1#pragma once
2
4
10#include <expected>
11#include <span>
12#include <string>
13#include <string_view>
14#include <vector>
15
16namespace VoltMod
17{
18
19/**
20 * @brief The one thing command dispatch needs a running server for.
21 *
22 * Everything else - prefixes, quoting, aliases, arity, parsing, usage lines, error keys - is plain
23 * logic over strings, so the whole dispatch path is unit-tested against a stub implementation of
24 * this interface and no engine at all.
25 */
27{
28public:
29 virtual ~ArgBinder() = default;
30
31 /** The connected players @p token names, honoring @p rules; a null @p caller is the server console,
32 * which may target anyone and never matches `@me`. */
33 virtual std::expected<std::vector<Player*>, TargetFailure> Resolve(std::string_view token, Player* caller,
34 const TargetRules& rules) = 0;
35};
36
37/** @ref ArgBinder over the connected players. Defined in TargetResolver.cpp, so the binding translation
38 * unit stays SDK-free. */
40{
41public:
43 : _players(players), _policy(policy), _entities(entities)
44 {}
45
46 std::expected<std::vector<Player*>, TargetFailure> Resolve(std::string_view token, Player* caller,
47 const TargetRules& rules) override;
48
49private:
50 PlayerManager& _players;
51 const Policy& _policy;
52 EntitySystem& _entities;
53};
54
55/**
56 * @brief A binding failure, as the key and tokens the reply is built from.
57 *
58 * Kept as key plus tokens rather than a finished string so the localization happens once, at reply
59 * time, in the language of whoever is being answered - and so a test can assert on the key without
60 * a translation table.
61 */
63{
64 std::string Key;
66};
67
68/**
69 * Bind @p tokens against @p def's argument descriptor.
70 *
71 * Arity is the caller's job: this assumes @p tokens already satisfies @p def's required count, so
72 * a short list can only mean a trailing optional argument. Takes nothing from the router, which is
73 * why it is a free function - the descriptor and the binder are the whole input.
74 */
75std::expected<std::vector<BoundArg>, ArgError> BindArgs(const CommandDefinition& def,
76 std::span<const std::string> tokens, Player* caller,
78
79} // namespace VoltMod
The one thing command dispatch needs a running server for.
virtual ~ArgBinder()=default
virtual std::expected< std::vector< Player * >, TargetFailure > Resolve(std::string_view token, Player *caller, const TargetRules &rules)=0
std::expected< std::vector< Player * >, TargetFailure > Resolve(std::string_view token, Player *caller, const TargetRules &rules) override
EngineArgBinder(PlayerManager &players, const Policy &policy, EntitySystem &entities)
runtime.Entities: finds and creates entities. Everything it returns is valid for this frame only; see...
The roster: every connected player, and the signals for the connection lifecycle.
One connected player, owned by PlayerManager for the length of the connection.
Definition Player.hpp:23
The one permission and targeting gate, plus the plugin's reply callback.
Definition Policy.hpp:41
std::expected< std::vector< BoundArg >, ArgError > BindArgs(const CommandDefinition &def, std::span< const std::string > tokens, Player *caller, ArgBinder &binder)
static std::string ReadFile(const std::filesystem::path &path)
Definition Loader.cpp:56
std::map< std::string, std::string > Tokens
Definition Strings.hpp:14
A binding failure, as the key and tokens the reply is built from.
std::string Key
One command as the builder assembled it.