From d674414cf00a9ba01bff7f2470dd56dee5e88619 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Sun, 1 Nov 2015 00:23:33 -0700 Subject: [PATCH] Add a versioned IPluginsListener and deprecate the non-versioned class. --- core/logic/PluginSys.cpp | 88 ++++++++++++++++++++++++++++++++++------ public/IPluginSys.h | 44 +++++++++++++++----- 2 files changed, 108 insertions(+), 24 deletions(-) diff --git a/core/logic/PluginSys.cpp b/core/logic/PluginSys.cpp index db2ed3a5..2e6d0fa9 100644 --- a/core/logic/PluginSys.cpp +++ b/core/logic/PluginSys.cpp @@ -44,7 +44,8 @@ #include "Translator.h" #include "Logger.h" #include "frame_tasks.h" -#include +#include +#include #include #include @@ -2240,7 +2241,42 @@ void CPluginManager::ForEachPlugin(ke::Lambda callback) callback(*iter); } -class OldPluginAPI : public IPluginManager +class PluginsListenerV1Wrapper final + : public IPluginsListener, + public ke::Refcounted +{ +public: + PluginsListenerV1Wrapper(IPluginsListener_V1 *impl) + : impl_(impl) + {} + + // The v2 listener was added with API v7, so we pin these wrappers to v6. + unsigned int GetApiVersion() const override { + return 6; + } + + void OnPluginLoaded(IPlugin *plugin) override { + impl_->OnPluginLoaded(plugin); + } + void OnPluginPauseChange(IPlugin *plugin, bool paused) override { + impl_->OnPluginPauseChange(plugin, paused); + } + void OnPluginUnloaded(IPlugin *plugin) override { + impl_->OnPluginUnloaded(plugin); + } + void OnPluginDestroyed(IPlugin *plugin) override { + impl_->OnPluginDestroyed(plugin); + } + + bool matches(IPluginsListener_V1 *impl) const { + return impl_ == impl; + } + +private: + IPluginsListener_V1 *impl_; +}; + +class OldPluginAPI final : public IPluginManager { public: IPlugin *LoadPlugin(const char *path, @@ -2248,45 +2284,71 @@ public: PluginType type, char error[], size_t maxlength, - bool *wasloaded) + bool *wasloaded) override { return g_PluginSys.LoadPlugin(path, debug, type, error, maxlength, wasloaded); } - bool UnloadPlugin(IPlugin *plugin) + bool UnloadPlugin(IPlugin *plugin) override { return g_PluginSys.UnloadPlugin(plugin); } - IPlugin *FindPluginByContext(const sp_context_t *ctx) + IPlugin *FindPluginByContext(const sp_context_t *ctx) override { return g_PluginSys.FindPluginByContext(ctx); } - unsigned int GetPluginCount() + unsigned int GetPluginCount() override { return g_PluginSys.GetPluginCount(); } - IPluginIterator *GetPluginIterator() + IPluginIterator *GetPluginIterator() override { return g_PluginSys.GetPluginIterator(); } - void AddPluginsListener(IPluginsListener *listener) + void AddPluginsListener_V1(IPluginsListener_V1 *listener) override + { + ke::Ref wrapper = new PluginsListenerV1Wrapper(listener); + + v1_wrappers_.append(wrapper); + g_PluginSys.AddPluginsListener(wrapper); + } + + void RemovePluginsListener_V1(IPluginsListener_V1 *listener) override + { + ke::Ref wrapper; + + // Find which wrapper has this listener. + for (decltype(v1_wrappers_)::iterator iter(v1_wrappers_); !iter.done(); iter.next()) { + if ((*iter)->matches(listener)) { + wrapper = *iter; + iter.remove(); + break; + } + } + g_PluginSys.RemovePluginsListener(wrapper); + } + + IPlugin *PluginFromHandle(Handle_t handle, HandleError *err) override + { + return g_PluginSys.PluginFromHandle(handle, err); + } + + void AddPluginsListener(IPluginsListener *listener) override { g_PluginSys.AddPluginsListener(listener); } - void RemovePluginsListener(IPluginsListener *listener) + void RemovePluginsListener(IPluginsListener *listener) override { g_PluginSys.RemovePluginsListener(listener); } - IPlugin *PluginFromHandle(Handle_t handle, HandleError *err) - { - return g_PluginSys.PluginFromHandle(handle, err); - } +private: + ReentrantList> v1_wrappers_; }; static OldPluginAPI sOldPluginAPI; diff --git a/public/IPluginSys.h b/public/IPluginSys.h index 91a9dda2..85aaea3d 100644 --- a/public/IPluginSys.h +++ b/public/IPluginSys.h @@ -38,7 +38,7 @@ #include #define SMINTERFACE_PLUGINSYSTEM_NAME "IPluginManager" -#define SMINTERFACE_PLUGINSYSTEM_VERSION 6 +#define SMINTERFACE_PLUGINSYSTEM_VERSION 7 /** Context user slot 3 is used Core for holding an IPluginContext pointer. */ #define SM_CONTEXTVAR_USER 3 @@ -278,7 +278,7 @@ namespace SourceMod /** * @brief Listens for plugin-oriented events. */ - class IPluginsListener + class IPluginsListener_V1 { public: // @brief This callback should not be used since plugins may be in @@ -315,6 +315,14 @@ namespace SourceMod } }; + // @brief Listens for plugin-oriented events. Extends the V1 listener class. + class IPluginsListener : public IPluginsListener_V1 + { + public: + virtual unsigned int GetApiVersion() const { + return SMINTERFACE_PLUGINSYSTEM_VERSION; + } + }; /** * @brief Manages the runtime loading and unloading of plugins. @@ -380,6 +388,29 @@ namespace SourceMod */ virtual IPluginIterator *GetPluginIterator() =0; + /** + * @brief Adds a V1 plugin manager listener. + * + * @param listener Pointer to a listener. + */ + virtual void AddPluginsListener_V1(IPluginsListener_V1 *listener) =0; + + /** + * @brief Removes a V1 plugin listener. + * + * @param listener Pointer to a listener. + */ + virtual void RemovePluginsListener_V1(IPluginsListener_V1 *listener) =0; + + /** + * @brief Converts a Handle to an IPlugin if possible. + * + * @param handle Handle. + * @param err Error, set on failure (otherwise undefined). + * @return IPlugin pointer, or NULL on failure. + */ + virtual IPlugin *PluginFromHandle(Handle_t handle, HandleError *err) =0; + /** * @brief Adds a plugin manager listener. * @@ -393,15 +424,6 @@ namespace SourceMod * @param listener Pointer to a listener. */ virtual void RemovePluginsListener(IPluginsListener *listener) =0; - - /** - * @brief Converts a Handle to an IPlugin if possible. - * - * @param handle Handle. - * @param err Error, set on failure (otherwise undefined). - * @return IPlugin pointer, or NULL on failure. - */ - virtual IPlugin *PluginFromHandle(Handle_t handle, HandleError *err) =0; }; }