VoltMod
C++23 framework for CS2 server plugins
Loading...
Searching...
No Matches
PluginLoader.hpp
Go to the documentation of this file.
1#pragma once
2
7
11#include <functional>
12#include <map>
13#include <string>
14#include <string_view>
15#include <vector>
16
17namespace VoltMod
18{
19
20/** One plugin whose library is open and whose Load returned true. */
22{
24 const PluginDescriptor* Descriptor = nullptr;
25 SharedLibrary Library; ///< last member: freed only after Unload has returned
26};
27
28/**
29 * @brief Finds the installed plugins and loads the ones their dependencies allow.
30 *
31 * Console load and unload requests wait for @ref RunPending on the next frame: freeing a library
32 * inside the command dispatch would pull the code out from under the call in flight.
33 */
35{
36public:
37 enum class ActionKind
38 {
39 Load,
40 Unload,
41 Reload
42 };
43
46
47 PluginLoader(const PluginLoader&) = delete;
49
50 /** Load every installed plugin whose required dependencies are there. */
51 void LoadAll();
52
53 /** Unload every loaded plugin, newest first. */
54 void UnloadAll();
55
56 /** Take @p kind on @p name at the start of the next frame. */
57 void Defer(ActionKind kind, std::string_view name);
58
59 /** Act on what was deferred. The frame hook calls this before the frame reaches plugins. */
60 void RunPending();
61
62 /** In load order; unload runs it backwards. */
63 const std::vector<LoadedPlugin>& LoadedPlugins() const { return _loaded; }
64
65 /** The loaded plugin @p name, or nullptr after logging that it is not loaded. */
66 LoadedPlugin* RequireLoaded(std::string_view name);
67
68 /** Each plugin the last load attempt refused, by name, with the reason; a later load clears it. */
69 const std::map<std::string, std::string>& Refused() const { return _refused; }
70
71private:
72 struct PendingAction
73 {
75 std::string Name;
76 };
77
78 /** Open the library, check its descriptor and give it a view of the host. */
79 Status LoadOne(const PluginManifest& manifest);
80 /** Players are disconnected from a plugin only mid-map: at shutdown the engine may be past
81 * running handlers. */
82 enum class UnloadTime
83 {
84 MidMap,
85 Shutdown,
86 };
87
88 /** Unload @p name, report whatever it left behind, then free its library. */
89 void UnloadOne(std::string_view name, UnloadTime when);
90
91 /** Plan @p installed, log what it refuses, and load whatever @p wanted accepts. */
92 void LoadGroup(const InstalledScan& installed, const std::function<bool(std::string_view)>& wanted);
93 /** Log that @p name was refused and remember why, for `volt list`. */
94 void Refuse(std::string_view name, std::string reason);
95
96 LoadedPlugin* FindLoaded(std::string_view name);
97 std::vector<PluginManifest> LoadedManifests() const;
98
99 void RunLoad(std::string_view name);
100 void RunUnload(std::string_view name);
101 void RunReload(std::string_view name);
102
103 PluginRegistry& _registry;
104 ServerAssets& _assets;
105 std::vector<LoadedPlugin> _loaded;
106 std::vector<PendingAction> _pending;
107 std::map<std::string, std::string> _refused;
108};
109
110} // namespace VoltMod
Finds the installed plugins and loads the ones their dependencies allow.
PluginLoader(const PluginLoader &)=delete
LoadedPlugin * RequireLoaded(std::string_view name)
const std::map< std::string, std::string > & Refused() const
PluginLoader & operator=(const PluginLoader &)=delete
const std::vector< LoadedPlugin > & LoadedPlugins() const
void Defer(ActionKind kind, std::string_view name)
The loaded plugins and the engine events raised on them, one per process.
constexpr std::string_view Name(E value) noexcept
Definition EnumNames.hpp:33
static std::string ReadFile(const std::filesystem::path &path)
Definition Loader.cpp:56
std::expected< void, Error > Status
Definition Result.hpp:67
PluginManifest Manifest
SharedLibrary Library
last member: freed only after Unload has returned
const PluginDescriptor * Descriptor