VoltMod
C++23 framework for CS2 server plugins
Loading...
Searching...
No Matches
PluginContext.hpp
Go to the documentation of this file.
1#pragma once
2
8
16#include <cstdint>
17#include <functional>
18#include <optional>
19#include <string>
20#include <string_view>
21#include <vector>
22
23namespace VoltMod
24{
25
26/** A player the host has seen connect and not yet leave. */
28{
30 std::string Name;
31 std::string Address;
32 bool FullyConnected = false;
33};
34
35/** Process-wide host state behind every plugin's view. Owned by @ref PluginRegistry, which outlives every
36 * view. Game thread only; nothing locks. */
38{
41 IPluginAddons* Addons = nullptr; ///< null downloads nothing
42
43 uint64_t SchemaLayoutStamp = 0; ///< zero until the host has checked its own layout
44 bool SchemaVerified = false;
45
46 uint64_t NextToken = 1; ///< unique across every event and the service table, never zero, never reused
47 uint64_t NextOrder = 1; ///< load positions keep rising, so a reloaded plugin dispatches last
48
49 /** Replayed to a plugin loaded mid-map; empty until the first map starts. */
50 std::string CurrentMap;
52
66
70};
71
72/** What a plugin had not released when it was removed. The host drops each and warns about it. */
74{
75 std::vector<std::string_view> Subscriptions; ///< the event each was taken on
76 std::vector<std::string> Services;
77 std::vector<uint64_t> Addons;
78};
79
80/** One plugin's view of the host and the record of what it took, so every call has a known owner.
81 * Owned by @ref PluginRegistry; valid from AddPlugin until RemovePlugin. */
83{
84public:
85 PluginContext(SharedState& state, std::string name, std::string logTag, std::string version, uint64_t order);
86
87 PluginContext(const PluginContext&) = delete;
89
90 void SetMinLogLevel(LogLevel level) { _minLevel = level; }
91
92 /** Remove what the plugin still holds. Command names are the host's to remove, so they are not reported. */
94
95 std::string_view Name() const override;
96 std::string_view Version() const override;
97 void* EngineInterface(const char* version) const override;
98 void* ServerInterface(const char* version) const override;
99 std::string_view BaseDir() const override;
100 KHook::IKHook* HookDispatcher() const override;
101 IPluginEvents& Events() override;
102 IPluginServices& Services() override;
103 IPluginLanguages& Languages() override;
104 IPluginAddons& Addons() override;
105 IPluginGameData* GameData() const override;
106 bool RegisterCommand(std::string_view name) override;
107 bool IsCommandRegistered(std::string_view name) const override;
108 void WriteLog(uint8_t level, std::string_view text) override;
109 uint8_t MinLogLevel() const override;
110 uint64_t SchemaLayoutStamp() const override;
111 bool SchemaVerified() const override;
112
113 uint64_t OnFrame(FrameFn callback, void* context) override;
126
127 void Publish(std::string_view name, void* implementation) override;
128 void Unpublish(std::string_view name) override;
129 void* Find(std::string_view name) override;
130
131 bool Add(uint64_t addonId) override;
132 void Remove(uint64_t addonId) override;
133 bool IsReady(int slot) override;
134
135 /** Raise on this plugin alone what it missed by loading mid-map: OnServerStartup for the running
136 * map, then OnClientConnected and OnClientFullyConnected for each player already in. */
137 void ReplayMissedEvents();
138 /** Raise OnClientDisconnected on this plugin alone for each player still in, before a mid-map unload. */
139 void DisconnectClients();
140
141 /** A token this plugin never took is ignored. */
142 void Unsubscribe(uint64_t token) override;
143
144private:
145 struct Subscribed
146 {
147 uint64_t Token = 0;
148 std::string_view Event; ///< names it in a leak line
149 std::function<void()> Remove; ///< drops the token from the list it went into
150 };
151
152 template <class Fn>
153 uint64_t Subscribe(std::string_view event, CallbackList<Fn>& list, Fn callback, void* context);
154
155 SharedState& _state;
156 std::string _name;
157 std::string _logTag;
158 std::string _version;
159 LogLevel _minLevel = LogLevel::Info;
160 uint64_t _order = 0;
161 std::vector<Subscribed> _subscriptions; ///< in the order the plugin took them
162 std::vector<uint64_t> _addons; ///< one entry per Add
163};
164
165} // namespace VoltMod
A multicast signal with a fixed handler signature: the one way to subscribe in VoltMod.
Definition Event.hpp:54
Per-player-slot value store that never leaks state across occupants.
Definition PerSlot.hpp:25
uint64_t OnButtonPress(ButtonPressFn callback, void *context) override
void * ServerInterface(const char *version) const override
IPluginGameData * GameData() const override
uint64_t OnClientSettingsChanged(ClientSettingsChangedFn callback, void *context) override
std::string_view BaseDir() const override
IPluginAddons & Addons() override
void * EngineInterface(const char *version) const override
uint64_t OnFrame(FrameFn callback, void *context) override
uint64_t OnClientDisconnected(ClientDisconnectedFn callback, void *context) override
void Unsubscribe(uint64_t token) override
uint64_t OnPlayerCommand(PlayerCommandFn callback, void *context) override
std::string_view Name() const override
uint64_t SchemaLayoutStamp() const override
bool SchemaVerified() const override
bool IsReady(int slot) override
PluginContext & operator=(const PluginContext &)=delete
PluginContext(const PluginContext &)=delete
IPluginLanguages & Languages() override
uint64_t OnClientFullyConnected(ClientFullyConnectedFn callback, void *context) override
KHook::IKHook * HookDispatcher() const override
uint64_t OnClientConnected(ClientConnectedFn callback, void *context) override
bool IsCommandRegistered(std::string_view name) const override
bool RegisterCommand(std::string_view name) override
void SetMinLogLevel(LogLevel level)
void * Find(std::string_view name) override
uint64_t OnCheckTransmit(CheckTransmitFn callback, void *context) override
uint8_t MinLogLevel() const override
void Publish(std::string_view name, void *implementation) override
uint64_t OnPlayerCommandDone(PlayerCommandFn callback, void *context) override
void Remove(uint64_t addonId) override
uint64_t OnConsoleCommand(ConsoleCommandFn callback, void *context) override
uint64_t OnClientConnecting(ClientConnectingFn callback, void *context) override
void WriteLog(uint8_t level, std::string_view text) override
IPluginEvents & Events() override
std::string_view Version() const override
uint64_t OnServerStartup(ServerStartupFn callback, void *context) override
bool Add(uint64_t addonId) override
uint64_t OnBuildGameSessionManifest(BuildGameSessionManifestFn callback, void *context) override
void Unpublish(std::string_view name) override
IPluginServices & Services() override
Static utilities for converting between SteamID formats (64-bit, SteamID2, SteamID3).
Definition SteamId.hpp:12
static std::string ReadFile(const std::filesystem::path &path)
Definition Loader.cpp:56
LogLevel
Definition Log.hpp:13
void(*)(void *context, int slot) ClientFullyConnectedFn
void(*)(void *context, int slot) ClientSettingsChangedFn
void(*)(void *context, int slot, std::string_view buttonId) ButtonPressFn
void(*)(void *context, std::string_view mapName) ServerStartupFn
void(*)(void *context, int slot, int64_t steamId, std::string_view name, std::string_view address) ClientConnectedFn
bool(*)(void *context, std::string_view name, std::string_view arguments, int slot) ConsoleCommandFn
void(*)(void *context, CCheckTransmitInfo **infoList, int infoCount) CheckTransmitFn
void(*)(void *context, IEntityResourceManifest *manifest) BuildGameSessionManifestFn
void(*)(void *context) FrameFn
void(*)(void *context, int slot, const PlayerInput &input) PlayerCommandFn
bool(*)(void *context, int slot, int64_t steamId, std::string_view name, char *reason, size_t reasonSize) ClientConnectingFn
void(*)(void *context, int slot) ClientDisconnectedFn
std::vector< std::string_view > Subscriptions
the event each was taken on
std::vector< std::string > Services
std::vector< uint64_t > Addons
CallbackList< IPluginEvents::BuildGameSessionManifestFn > BuildGameSessionManifest
IPluginGameData * GameData
CallbackList< IPluginEvents::PlayerCommandFn > PlayerCommand
CallbackList< IPluginEvents::ClientFullyConnectedFn > ClientFullyConnected
CallbackList< IPluginEvents::ClientSettingsChangedFn > ClientSettingsChanged
CallbackList< IPluginEvents::FrameFn > Frame
PublishedInterfaces Services
PerSlot< std::optional< ConnectedClient > > Clients
CallbackList< IPluginEvents::ClientConnectingFn > ClientConnecting
IPluginAddons * Addons
null downloads nothing
uint64_t NextToken
unique across every event and the service table, never zero, never reused
LanguageTable Languages
CallbackList< IPluginEvents::CheckTransmitFn > CheckTransmit
uint64_t NextOrder
load positions keep rising, so a reloaded plugin dispatches last
CallbackList< IPluginEvents::ButtonPressFn > ButtonPress
CallbackList< IPluginEvents::ConsoleCommandFn > ConsoleCommand
CallbackList< IPluginEvents::PlayerCommandFn > PlayerCommandDone
CallbackList< IPluginEvents::ClientDisconnectedFn > ClientDisconnected
CallbackList< IPluginEvents::ClientConnectedFn > ClientConnected
uint64_t SchemaLayoutStamp
zero until the host has checked its own layout
CallbackList< IPluginEvents::ServerStartupFn > ServerStartup