diff --git a/bridge/include/BridgeAPI.h b/bridge/include/BridgeAPI.h index 80cc0331c..3d03fd9c2 100644 --- a/bridge/include/BridgeAPI.h +++ b/bridge/include/BridgeAPI.h @@ -35,7 +35,7 @@ namespace SourceMod { // Add 1 to the RHS of this expression to bump the intercom file // This is to prevent mismatching core/logic binaries -static const uint32_t SM_LOGIC_MAGIC = 0x0F47C0DE - 50; +static const uint32_t SM_LOGIC_MAGIC = 0x0F47C0DE - 51; } // namespace SourceMod diff --git a/bridge/include/CoreProvider.h b/bridge/include/CoreProvider.h index 887d80a08..1bc93108a 100644 --- a/bridge/include/CoreProvider.h +++ b/bridge/include/CoreProvider.h @@ -30,6 +30,7 @@ #include #include #include +#include namespace SourcePawn { class ISourcePawnEngine; @@ -64,6 +65,9 @@ class IGameHelpers; class IMenuManager; struct DatabaseInfo; class IPlayerInfoBridge; +class ICommandArgs; + +typedef ke::Lambda CommandFunc; class CoreProvider { @@ -92,6 +96,9 @@ public: virtual const char *GetCvarString(ConVar *cvar) = 0; virtual bool GetCvarBool(ConVar* cvar) = 0; + // Command functions. + virtual void DefineCommand(const char *cmd, const char *help, const CommandFunc &callback) = 0; + // Game description functions. virtual bool GetGameName(char *buffer, size_t maxlength) = 0; virtual const char *GetGameDescription() = 0; @@ -105,6 +112,7 @@ public: virtual bool DescribePlayer(int index, const char **namep, const char **authp, int *useridp) = 0; virtual void LogToGame(const char *message) = 0; virtual void ConPrint(const char *message) = 0; + virtual void ConsolePrint(const char *fmt, ...) = 0; virtual void ConsolePrintVa(const char *fmt, va_list ap) = 0; // Game engine helper functions. diff --git a/core/logic_bridge.cpp b/core/logic_bridge.cpp index e4b9076d2..fcfe94993 100644 --- a/core/logic_bridge.cpp +++ b/core/logic_bridge.cpp @@ -564,6 +564,14 @@ void CoreProviderImpl::ConPrint(const char *message) META_CONPRINT(message); } +void CoreProviderImpl::ConsolePrint(const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + UTIL_ConsolePrintVa(fmt, ap); + va_end(ap); +} + void CoreProviderImpl::ConsolePrintVa(const char *message, va_list ap) { UTIL_ConsolePrintVa(message, ap); @@ -754,6 +762,39 @@ CoreProviderImpl::AddPostCommandHook(ConCommand *cmd, const CommandHook::Callbac return hooks_.AddPostCommandHook(cmd, callback); } +CoreProviderImpl::CommandImpl::CommandImpl(ConCommand *cmd, CommandHook *hook) +: cmd_(cmd), + hook_(hook) +{ +} + +CoreProviderImpl::CommandImpl::~CommandImpl() +{ + hook_ = nullptr; + + g_SMAPI->UnregisterConCommandBase(g_PLAPI, cmd_); + delete [] const_cast(cmd_->GetHelpText()); + delete [] const_cast(cmd_->GetName()); + delete cmd_; +} + +void +CoreProviderImpl::DefineCommand(const char *name, const char *help, const CommandFunc &callback) +{ + char *new_name = sm_strdup(name); + char *new_help = sm_strdup(help); + int flags = 0; + + auto ignore_callback = [] (DISPATCH_ARGS) -> void { + }; + + ConCommand *cmd = new ConCommand(new_name, ignore_callback, new_help, flags); + ke::Ref hook = AddCommandHook(cmd, callback); + + ke::Ref impl = new CommandImpl(cmd, hook); + commands_.append(impl); +} + void CoreProviderImpl::InitializeHooks() { hooks_.Start(); @@ -766,6 +807,7 @@ void CoreProviderImpl::OnVSPReceived() void CoreProviderImpl::ShutdownHooks() { + commands_.clear(); hooks_.Shutdown(); } diff --git a/core/provider.h b/core/provider.h index 4f592f902..8199a820d 100644 --- a/core/provider.h +++ b/core/provider.h @@ -59,11 +59,13 @@ public: bool DescribePlayer(int index, const char **namep, const char **authp, int *useridp) override; void LogToGame(const char *message) override; void ConPrint(const char *message) override; + void ConsolePrint(const char *fmt, ...) override; void ConsolePrintVa(const char *fmt, va_list ap) override; int LoadMMSPlugin(const char *file, bool *ok, char *error, size_t maxlength) override; void UnloadMMSPlugin(int id) override; int QueryClientConVar(int client, const char *cvar) override; bool IsClientConVarQueryingSupported() override; + void DefineCommand(const char *cmd, const char *help, const SourceMod::CommandFunc &callback) override; ke::PassRef AddCommandHook(ConCommand *cmd, const CommandHook::Callback &callback); ke::PassRef AddPostCommandHook(ConCommand *cmd, const CommandHook::Callback &callback); @@ -76,6 +78,18 @@ private: ke::Ref logic_; LogicInitFunction logic_init_; GameHooks hooks_; + + struct CommandImpl : public ke::Refcounted + { + public: + CommandImpl(ConCommand *cmd, CommandHook *hook); + ~CommandImpl(); + + private: + ConCommand *cmd_; + ke::Ref hook_; + }; + ke::Vector> commands_; }; extern CoreProviderImpl sCoreProviderImpl;