13#include <engine/igameeventsystem.h>
17#include <interfaces/interfaces.h>
19#include <networksystem/inetworkmessages.h>
20#include <schemasystem/schemasystem.h>
23#include <tier1/convar.h>
68 return std::unexpected(
Error::NotReady(std::format(
"Could not find interface: {}", version)));
77 auto unsafe = std::make_unique<UnsafeServices>();
98 return std::unexpected(
status.error());
125 std::format(
"this plugin was built against another schema layout (plugin {:016X}, host {:016X}); "
126 "rebuild it against this VoltMod",
131 return std::unexpected(
Error::Invalid(
"the host found schema drift; its log names every field"));
149 return Refuse(std::format(
"SchemaLayout: {}", schema.error().Detail),
error,
errorSize);
157 _unsafe = std::move(*
unsafe);
158 _languages = std::make_unique<HostPlayerLanguages>(host.
Languages());
159 _runtime = std::make_unique<Runtime>(host, *_unsafe, *_languages);
162 _plugin = _factory(*_runtime);
163 if (std::string
reason = _runtime->LoadReport.AbortReason(); !
reason.empty())
168 SubscribeHostEvents();
170 if (!_plugin->Load())
172 std::string
reason = _runtime->LoadReport.AbortReason();
176 Log::Info(
"{}", _runtime->LoadReport.Summary());
184 Log::Info(
"{}", _runtime->LoadReport.Summary());
198void PluginModule::Shutdown()
noexcept
202 _runtime->Commands.RemoveAll();
215 _status = _runtime ? _runtime->Status.BuildJson() : std::string(
"{}");
216 return _status.c_str();
224void PluginModule::SubscribeHostEvents()
229 keep(
events.OnFrame(&HostCallback<&PluginModule::OnFrame>::Call,
this));
230 keep(
events.OnServerStartup(&HostCallback<&PluginModule::OnServerStartup>::Call,
this));
231 keep(
events.OnClientConnecting(&HostCallback<&PluginModule::OnClientConnecting>::Call,
this));
232 keep(
events.OnClientConnected(&HostCallback<&PluginModule::OnClientConnected>::Call,
this));
233 keep(
events.OnClientDisconnected(&HostCallback<&PluginModule::OnClientDisconnected>::Call,
this));
234 keep(
events.OnClientFullyConnected(&HostCallback<&PluginModule::OnClientFullyConnected>::Call,
this));
235 keep(
events.OnClientSettingsChanged(&HostCallback<&PluginModule::OnClientSettingsChanged>::Call,
this));
236 keep(
events.OnConsoleCommand(&HostCallback<&PluginModule::OnConsoleCommand>::Call,
this));
237 keep(
events.OnCheckTransmit(&HostCallback<&PluginModule::OnCheckTransmit>::Call,
this));
238 keep(
events.OnBuildGameSessionManifest(&HostCallback<&PluginModule::OnBuildGameSessionManifest>::Call,
this));
241void PluginModule::OnFrame()
245 _runtime->OnGameFrame();
248void PluginModule::OnServerStartup(std::string_view
mapName)
251 _runtime->Map.SetCurrent(std::string(
mapName));
252 _runtime->Entities.OnServerStartup();
253 _runtime->GameEvents.OnServerStartup();
254 _runtime->ClientConVars.OnServerStartup();
255 _runtime->Map.Started.Raise(
mapName);
261 _runtime->Players.Connecting.Raise(
request);
274void PluginModule::OnClientDisconnected(
int slot)
276 _runtime->Players.Remove(
slot);
279void PluginModule::OnClientFullyConnected(
int slot)
281 _runtime->Players.OnClientFullyConnected(
slot);
284void PluginModule::OnClientSettingsChanged(
int slot)
286 _runtime->Players.OnClientSettingsChanged(
slot);
296 _runtime->Precache.WriteTo(*
manifest);
const char * StatusJson() noexcept
bool Attach(IPluginContext &host, char *error, size_t errorSize) noexcept
static void CopyToBuffer(char *buffer, std::size_t size, std::string_view text) noexcept
void Add(Subscription subscription)
KHook::IKHook * __exported__khook
static Status CheckSchema(const IPluginContext &host)
static Status Resolve(T *&field, const IPluginContext &host, InterfaceLookup lookup, const char *version)
static Result< std::unique_ptr< UnsafeServices > > OpenUnsafe(IPluginContext &host)
Subscription HostSubscription(IPluginEvents &events, uint64_t token)
void *(IPluginContext::*)(const char *version) const InterfaceLookup
void Info(std::format_string< Args... > fmt, Args &&... args)
void SetHandler(Handler handler)
void SetMinimumLevel(LogLevel level)
uint64_t GeneratedLayoutStamp()
A hash of everything GeneratedLayout holds.
void SetBaseDir(const std::filesystem::path &baseDir)
Set the base directory for path resolution (the host's csgo directory). Must be called during initial...
static std::string ReadFile(const std::filesystem::path &path)
std::expected< void, Error > Status
std::expected< T, Error > Result
static Error Invalid(std::string detail)
static Error Engine(std::string detail)
static Error NotReady(std::string detail)
virtual IPluginGameData * GameData() const =0
virtual uint64_t SchemaLayoutStamp() const =0
virtual IPluginEvents & Events()=0
virtual KHook::IKHook * HookDispatcher() const =0
virtual bool SchemaVerified() const =0
virtual void * ServerInterface(const char *version) const =0
virtual void WriteLog(uint8_t level, std::string_view text)=0
virtual std::string_view BaseDir() const =0
virtual uint8_t MinLogLevel() const =0
virtual void * EngineInterface(const char *version) const =0
virtual IPluginLanguages & Languages()=0