From 4309e27827d89b98f6efbef7da56d4ea63bcbd50 Mon Sep 17 00:00:00 2001 From: Karol Szuster Date: Fri, 23 Oct 2020 16:02:37 +0200 Subject: [PATCH] Rework dynamic natives Add support for new SP api [SPExt] Signed-off-by: Karol Szuster --- include/public/Common.hpp | 8 +- include/public/IMessageSystem.hpp | 40 +++- include/public/INativeProxy.hpp | 77 +++++--- include/public/IPluginSystem.hpp | 64 ------- include/public/ISPGlobal.hpp | 15 +- include/public/engine/Common.hpp | 17 -- include/public/engine/IFuncs.hpp | 7 +- src/CMakeLists.txt | 1 + src/MessageSystem.cpp | 79 ++++---- src/MessageSystem.hpp | 44 +++-- src/NativeProxy.cpp | 42 +---- src/NativeProxy.hpp | 30 +-- src/PlayerSystem.cpp | 2 +- src/SPGlobal.cpp | 14 +- src/SPGlobal.hpp | 4 +- src/engine/Edict.cpp | 11 +- src/engine/Edict.hpp | 4 +- src/engine/Engine.cpp | 18 ++ src/engine/Engine.hpp | 1 + src/engine/Funcs.cpp | 2 +- src/engine/Funcs.hpp | 2 +- subprojects/sourcepawn/CMakeLists.txt | 2 +- subprojects/sourcepawn/CoreNatives.cpp | 119 +++++++----- subprojects/sourcepawn/ExtMain.cpp | 7 + subprojects/sourcepawn/ExtMain.hpp | 2 + subprojects/sourcepawn/MessageNatives.cpp | 150 ++++++++------- subprojects/sourcepawn/NativeCallback.cpp | 212 +++++++++++++++++++++- subprojects/sourcepawn/NativeCallback.hpp | 58 +++++- subprojects/sourcepawn/PluginSystem.cpp | 186 +++---------------- subprojects/sourcepawn/PluginSystem.hpp | 22 +-- 30 files changed, 666 insertions(+), 574 deletions(-) diff --git a/include/public/Common.hpp b/include/public/Common.hpp index 7adf8afd..c3779446 100644 --- a/include/public/Common.hpp +++ b/include/public/Common.hpp @@ -30,7 +30,7 @@ namespace SPMod Configs }; - enum class ModName : std::uint8_t + enum class ModType : std::uint8_t { Valve = 0, Cstrike, @@ -55,6 +55,12 @@ namespace SPMod Error }; + enum class HookType : std::uint8_t + { + Pre = 0, + Post + }; + /** * @brief Maximum number of supported players. */ diff --git a/include/public/IMessageSystem.hpp b/include/public/IMessageSystem.hpp index 636eb295..4f54075d 100644 --- a/include/public/IMessageSystem.hpp +++ b/include/public/IMessageSystem.hpp @@ -23,7 +23,7 @@ namespace SPMod { constexpr std::size_t MAX_USER_MESSAGES = 256U; - enum class MsgParamType + enum class MsgParamType : std::uint8_t { Byte, Char, @@ -35,18 +35,40 @@ namespace SPMod Entity, }; - enum class BlockType + enum class MsgBlockType : std::uint8_t { Not, Once, Set }; - class IEdict; + /** + * Message destination. + */ + enum class MsgDest : std::uint8_t + { + BROADCAST = 0, /**< Unreliable to all */ + ONE = 1, /**< Reliable to one (msg_entity) */ + ALL = 2, /**< Reliable to all */ + INIT = 3, /**< Write to the init string */ + PVS = 4, /**< Ents in PVS of org */ + PAS = 5, /**< Ents in PAS of org */ + PVS_R = 6, /**< Reliable to PVS */ + PAS_R = 7, /**< Reliable to PAS */ + ONE_UNRELIABLE = 8, /**< Send to one client, but don't put in reliable stream, put in unreliable datagram */ + SPEC = 9, /**< Sends to all spectator proxies */ + }; + + namespace Engine + { + class IEdict; + } class IMessage { public: + using Handler = std::function; + virtual ~IMessage() = default; virtual std::size_t getParams() const = 0; @@ -61,14 +83,12 @@ namespace SPMod virtual void setParamFloat(std::size_t index, float value) = 0; virtual void setParamString(std::size_t index, std::string_view string) = 0; - virtual int getDest() const = 0; + virtual MsgDest getDest() const = 0; virtual int getType() const = 0; virtual const float *getOrigin() const = 0; - virtual IEdict *getEdict() const = 0; + virtual Engine::IEdict *getEdict() const = 0; }; - using MessageHandler = std::function; - class IMessageHook { public: @@ -111,11 +131,11 @@ namespace SPMod return VERSION; } - virtual IMessageHook *registerHook(int msgType, MessageHandler handler, std::any cbData, bool post) = 0; + virtual IMessageHook *registerHook(int msgType, IMessage::Handler handler, HookType hookType) = 0; virtual void unregisterHook(IMessageHook *hook) = 0; - virtual BlockType getMessageBlock(int msgType) const = 0; - virtual void setMessageBlock(int msgType, BlockType blockType) = 0; + virtual MsgBlockType getMessageBlock(int msgType) const = 0; + virtual void setMessageBlock(int msgType, MsgBlockType blockType) = 0; virtual IMessage *getMessage() const = 0; virtual bool inHook() const = 0; diff --git a/include/public/INativeProxy.hpp b/include/public/INativeProxy.hpp index e4b3fefd..2bd46e15 100644 --- a/include/public/INativeProxy.hpp +++ b/include/public/INativeProxy.hpp @@ -36,27 +36,65 @@ namespace SPMod virtual std::string_view getName() const = 0; /** - * @brief Gets native data. + * @brief Gets passed param as int. * - * @return Native's data. + * @param index Param number. + * + * @return Param as int. */ - virtual std::any getData() const = 0; + virtual std::int32_t getParamAsInt(std::size_t index) const = 0; /** - * @brief Gets native plugin. + * @brief Gets passed param as pointer to int. + * + * @param index Param number. + * + * @return Param as pointer to int. + */ + virtual std::int32_t *getParamAsIntAddr(std::size_t index) const = 0; + + /** + * @brief Gets passed param as float. + * + * @param index Param number. * - * @return Native's plugin. + * @return Param as float. */ - virtual IPlugin *getPlugin() const = 0; + virtual float getParamAsFloat(std::size_t index) const = 0; /** - * @brief Notifies adapter about executed native. + * @brief Gets passed param as pointer to float. * - * @param plugin Plugin which has executed the native. + * @param index Param number. * - * @return Native result. + * @return Param as pointer to float. */ - virtual std::int32_t exec(IPlugin *plugin) = 0; + virtual float *getParamAsFloatAddr(std::size_t index) const = 0; + + /** + * @brief Gets passed param as string. + * + * @param index Param number. + * + * @return Param as string. + */ + virtual char *getParamAsString(std::size_t index) const = 0; + + /** + * @brief Gets passed param as array. + * + * @param index Param number. + * + * @return Param as pointer to float. + */ + virtual void *getParamAsArray(std::size_t index) const = 0; + + /** + * @brief Executes the native. + * + * @return Param as pointer to float. + */ + virtual std::int32_t InvokeSPModNative() = 0; }; class INativeProxy : public ISPModInterface @@ -95,26 +133,17 @@ namespace SPMod * @brief Registers proxied native. * * @param name Native name. - * @param data Native data. - * @param plugin Plugin which native belongs to. + * @param callback Callback to be executed. * * @return True if registration succeed, false otherwise. */ - virtual bool registerNative(std::string_view name, std::any data, IPlugin *plugin) = 0; + virtual bool registerNative(IProxiedNative *native) = 0; /** - * @brief Gets list of proxied natives. - * - * @param native Native's id. + * @brief Returns list of already registered proxied natives. * - * @return Proxied native or nullptr if invalid id. + * @return Map of registered proxied natives (first element - name of the native, second - implementation) */ - std::vector getProxiedNatives() const - { - return getProxiedNativesImpl(); - } - - protected: - virtual std::vector getProxiedNativesImpl() const = 0; + virtual const std::unordered_map &getProxiedNatives() const = 0; }; } // namespace SPMod \ No newline at end of file diff --git a/include/public/IPluginSystem.hpp b/include/public/IPluginSystem.hpp index d000e24d..5d94cacb 100644 --- a/include/public/IPluginSystem.hpp +++ b/include/public/IPluginSystem.hpp @@ -79,60 +79,6 @@ namespace SPMod * @return Plugin manager. */ virtual IPluginMngr *getPluginMngr() const = 0; - - /** - * @brief Gets proxied param as int. - * - * @param index Param number. - * - * @return Param as int. - */ - virtual std::int32_t getProxiedParamAsInt(std::size_t index) const = 0; - - /** - * @brief Gets proxied param as pointer to int. - * - * @param index Param number. - * - * @return Param as pointer to int. - */ - virtual std::int32_t *getProxiedParamAsIntAddr(std::size_t index) const = 0; - - /** - * @brief Gets proxied param as float. - * - * @param index Param number. - * - * @return Param as float. - */ - virtual float getProxiedParamAsFloat(std::size_t index) const = 0; - - /** - * @brief Gets proxied param as pointer to float. - * - * @param index Param number. - * - * @return Param as pointer to float. - */ - virtual float *getProxiedParamAsFloatAddr(std::size_t index) const = 0; - - /** - * @brief Gets proxied param as string. - * - * @param index Param number. - * - * @return Param as string. - */ - virtual char *getProxiedParamAsString(std::size_t index) const = 0; - - /** - * @brief Gets proxied param as array. - * - * @param index Param number. - * - * @return Param as pointer to float. - */ - virtual void *getProxiedParamAsArray(std::size_t index) const = 0; }; class IPluginMngr @@ -167,16 +113,6 @@ namespace SPMod */ virtual void unloadPlugins() = 0; - /** - * @brief Called on proxied native. - * - * @param native Proxied native. - * @param plugin Plugin which executed the native. - * - * @return Native result. - */ - virtual std::int32_t proxyNativeCallback(IProxiedNative *native, IPlugin *plugin) = 0; - /** * @brief Returns numbers of loaded plugins. * diff --git a/include/public/ISPGlobal.hpp b/include/public/ISPGlobal.hpp index f28e01b2..2f72d2d7 100644 --- a/include/public/ISPGlobal.hpp +++ b/include/public/ISPGlobal.hpp @@ -30,6 +30,7 @@ #include #include #include +#include #include @@ -84,6 +85,7 @@ namespace fs = std::experimental::filesystem; #include #include #include +#include namespace SPMod { @@ -127,11 +129,11 @@ namespace SPMod virtual const fs::path &getPath(DirType type) const = 0; /** - * @brief Returns name of the mod. + * @brief Returns type of the mod. * - * @return Mod name. + * @return Mod type. */ - virtual ModName getModName() const = 0; + virtual ModType getModType() const = 0; /** * @brief Checks if plugins can precache resources. @@ -177,6 +179,13 @@ namespace SPMod */ virtual IMenuMngr *getMenuManager() const = 0; + /** + * @brief Returns SPMod message manager. + * + * @return Message manager. + */ + virtual IMessageMngr *getMessageManager() const = 0; + /** * @brief Returns SPMod logger manager. * diff --git a/include/public/engine/Common.hpp b/include/public/engine/Common.hpp index 5efc5544..f723a5a3 100644 --- a/include/public/engine/Common.hpp +++ b/include/public/engine/Common.hpp @@ -35,23 +35,6 @@ namespace SPMod::Engine RightLeg = 7 /**< Right leg */ }; - /** - * Message destination. - */ - enum class MessageDest : std::uint8_t - { - BROADCAST = 0, /**< Unreliable to all */ - ONE = 1, /**< Reliable to one (msg_entity) */ - ALL = 2, /**< Reliable to all */ - INIT = 3, /**< Write to the init string */ - PVS = 4, /**< Ents in PVS of org */ - PAS = 5, /**< Ents in PAS of org */ - PVS_R = 6, /**< Reliable to PVS */ - PAS_R = 7, /**< Reliable to PAS */ - ONE_UNRELIABLE = 8, /**< Send to one client, but don't put in reliable stream, put in unreliable datagram */ - SPEC = 9, /**< Sends to all spectator proxies */ - }; - /** * Server command callback. */ diff --git a/include/public/engine/IFuncs.hpp b/include/public/engine/IFuncs.hpp index d364db19..20412aee 100644 --- a/include/public/engine/IFuncs.hpp +++ b/include/public/engine/IFuncs.hpp @@ -19,6 +19,11 @@ #pragma once +namespace SPMod +{ + enum class MsgDest : std::uint8_t; +} + namespace SPMod::Engine { class IFuncs @@ -121,7 +126,7 @@ namespace SPMod::Engine virtual void registerSrvCommand(std::string_view cmd, ServerCmdCallback callback) const = 0; // TODO: Describe funcs - virtual void messageBegin(MessageDest msgDest, + virtual void messageBegin(MsgDest msgDest, std::uint32_t msgType, const float *pOrigin = nullptr, IEdict *pEdict = nullptr) const = 0; diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 05d0e8f5..68a92541 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -29,6 +29,7 @@ set(SRC_FILES h_export.cpp ValveInterface.cpp UtilsSystem.cpp NativeProxy.cpp + MessageSystem.cpp engine/Funcs.cpp metamod/Funcs.cpp metamod/Metamod.cpp diff --git a/src/MessageSystem.cpp b/src/MessageSystem.cpp index 6d607344..b07c0751 100644 --- a/src/MessageSystem.cpp +++ b/src/MessageSystem.cpp @@ -19,17 +19,30 @@ #include "spmod.hpp" -void Message::init(int dest, int type, const float *origin, edict_t *edict) +namespace +{ + inline std::int32_t msgDestToInt(MsgDest destType) + { + return static_cast(destType); + } + + inline MsgDest intToMsgDest(std::int32_t destType) + { + return static_cast(destType); + } +} + +void Message::init(MsgDest dest, int type, const float *origin, Engine::Edict *edict) { m_dest = dest; m_type = type; m_origin = Vector(origin[0], origin[1], origin[2]); - m_edict = std::make_unique(edict); + m_edict = edict; } void Message::exec() const { - MESSAGE_BEGIN(m_dest, m_type, m_origin, m_edict->getInternalEdict()); + MESSAGE_BEGIN(msgDestToInt(m_dest), m_type, m_origin, *m_edict); for (auto param : m_params) { @@ -98,7 +111,7 @@ void Message::setParamString(std::size_t index, std::string_view string) void Message::addParam(MsgParamType type, std::variant &&data) { - MessageParam param; + Param param; param.type = type; param.data = data; @@ -120,7 +133,7 @@ MsgParamType Message::getParamType(std::size_t index) const return m_params[index].type; } -int Message::getDest() const +MsgDest Message::getDest() const { return m_dest; } @@ -135,13 +148,13 @@ const float *Message::getOrigin() const return m_origin; } -IEdict *Message::getEdict() const +Engine::IEdict *Message::getEdict() const { - return m_edict.get(); + return m_edict; } -MessageHook::MessageHook(int msgType, MessageHandler handler, std::any cbData, bool post) - : m_msgType(msgType), m_handler(handler), m_cbData(cbData), m_post(post), m_active(true) +MessageHook::MessageHook(int msgType, Message::Handler handler, HookType hookType) + : m_msgType(msgType), m_handler(handler), m_hookType(hookType), m_active(true) { } @@ -165,26 +178,24 @@ int MessageHook::getMsgType() const } // MessageHook -bool MessageHook::getPost() const +HookType MessageHook::getHookType() const { - return m_post; + return m_hookType; } -MessageHandler MessageHook::getHandler() const + +Message::Handler MessageHook::getHandler() const { return m_handler; } -std::any MessageHook::getCbData() const -{ - return m_cbData; -} + bool MessageHook::getActive() const { return m_active; } -MessageHook *MessageHooks::addHook(int msgType, MessageHandler handler, std::any cbData, bool post) +MessageHook *MessageHooks::addHook(int msgType, Message::Handler handler, HookType hookType) { - return m_handlers.emplace_back(std::make_unique(msgType, handler, cbData, post)).get(); + return m_handlers.emplace_back(std::make_unique(msgType, handler, hookType)).get(); } void MessageHooks::removeHook(IMessageHook *hook) { @@ -199,20 +210,20 @@ void MessageHooks::removeHook(IMessageHook *hook) ++iter; } } -IForward::ReturnValue MessageHooks::exec(const std::unique_ptr &message, bool post) const +IForward::ReturnValue MessageHooks::exec(const std::unique_ptr &message, HookType hookType) const { IForward::ReturnValue result = IForward::ReturnValue::Ignored; for (const auto &hook : m_handlers) { - if (!hook->getActive() || hook->getPost() != post) + if (!hook->getActive() || hook->getHookType() != hookType) { continue; } auto func = hook->getHandler(); - IForward::ReturnValue ret = func(message.get(), hook->getCbData()); + IForward::ReturnValue ret = func(message.get()); if (ret == IForward::ReturnValue::Stop) { @@ -243,13 +254,13 @@ MessageMngr::MessageMngr() : m_message(std::make_unique()) for (std::size_t i = 0; i < MAX_USER_MESSAGES; i++) { - m_blocks[i] = BlockType::Not; + m_blocks[i] = MsgBlockType::Not; } } -MessageHook *MessageMngr::registerHook(int msgType, MessageHandler handler, std::any cbData, bool post) +MessageHook *MessageMngr::registerHook(int msgType, Message::Handler handler, HookType hookType) { - return m_hooks[msgType].addHook(msgType, handler, cbData, post); + return m_hooks[msgType].addHook(msgType, handler, hookType); } void MessageMngr::unregisterHook(IMessageHook *hook) @@ -258,19 +269,19 @@ void MessageMngr::unregisterHook(IMessageHook *hook) m_hooks[msgType].removeHook(hook); } -BlockType MessageMngr::getMessageBlock(int msgType) const +MsgBlockType MessageMngr::getMessageBlock(int msgType) const { return m_blocks[msgType]; } -void MessageMngr::setMessageBlock(int msgType, BlockType blockType) +void MessageMngr::setMessageBlock(int msgType, MsgBlockType blockType) { m_blocks[msgType] = blockType; } -IForward::ReturnValue MessageMngr::execHandlers(bool post) +IForward::ReturnValue MessageMngr::execHandlers(HookType hookType) { - return m_hooks[m_message->getType()].exec(m_message, post); + return m_hooks[m_message->getType()].exec(m_message, hookType); } bool MessageMngr::inHook() const @@ -288,7 +299,7 @@ void MessageMngr::clearMessages() META_RES MessageMngr::MessageBegin(int msg_dest, int msg_type, const float *pOrigin, edict_t *ed) { - if (m_blocks[msg_type] != BlockType::Not) + if (m_blocks[msg_type] != MsgBlockType::Not) { m_inblock = true; m_msgType = msg_type; @@ -299,7 +310,7 @@ META_RES MessageMngr::MessageBegin(int msg_dest, int msg_type, const float *pOri if (m_inhook) { - m_message->init(msg_dest, msg_type, pOrigin, ed); + m_message->init(intToMsgDest(msg_dest), msg_type, pOrigin, gSPGlobal->getEngine()->getEdict(ed)); return MRES_SUPERCEDE; } @@ -311,9 +322,9 @@ META_RES MessageMngr::MessageEnd() if (m_inblock) { m_inblock = false; - if (m_blocks[m_msgType] == BlockType::Once) + if (m_blocks[m_msgType] == MsgBlockType::Once) { - m_blocks[m_msgType] = BlockType::Not; + m_blocks[m_msgType] = MsgBlockType::Not; } return MRES_SUPERCEDE; } @@ -326,7 +337,7 @@ META_RES MessageMngr::MessageEnd() // exec pre hooks // add contidions for hooks like in amxx events - IForward::ReturnValue ret = execHandlers(false); + IForward::ReturnValue ret = execHandlers(HookType::Pre); // hooks can change params // then exec message @@ -335,7 +346,7 @@ META_RES MessageMngr::MessageEnd() m_message->exec(); // exec post hooks? - execHandlers(true); + execHandlers(HookType::Post); } m_inhook = false; diff --git a/src/MessageSystem.hpp b/src/MessageSystem.hpp index bd7c0e6e..7991ce42 100644 --- a/src/MessageSystem.hpp +++ b/src/MessageSystem.hpp @@ -24,7 +24,7 @@ class Message : public IMessage { public: - struct MessageParam + struct Param { MsgParamType type; std::variant data; @@ -45,13 +45,13 @@ class Message : public IMessage void setParamFloat(std::size_t index, float value) override; void setParamString(std::size_t index, std::string_view string) override; - int getDest() const override; + MsgDest getDest() const override; int getType() const override; const float *getOrigin() const override; - IEdict *getEdict() const override; + Engine::IEdict *getEdict() const override; // Message - void init(int dest, int type, const float *origin, edict_t *edict); + void init(MsgDest dest, int type, const float *origin, Engine::Edict *edict); void exec() const; @@ -76,18 +76,18 @@ class Message : public IMessage } private: - int m_dest; + MsgDest m_dest; int m_type; Vector m_origin; - std::unique_ptr m_edict; + Engine::Edict *m_edict; - std::vector m_params; + std::vector m_params; }; -class MessageHook : public IMessageHook +class MessageHook final : public IMessageHook { public: - MessageHook(int msgType, MessageHandler handler, std::any cbData, bool post); + MessageHook(int msgType, Message::Handler handler, HookType hookType); ~MessageHook() = default; // IMessageHook @@ -97,16 +97,14 @@ class MessageHook : public IMessageHook int getMsgType() const override; // MessageHook - bool getPost() const; - MessageHandler getHandler() const; - std::any getCbData() const; + HookType getHookType() const; + Message::Handler getHandler() const; bool getActive() const; private: int m_msgType; - MessageHandler m_handler; - std::any m_cbData; - bool m_post; + Message::Handler m_handler; + HookType m_hookType; bool m_active; }; @@ -114,13 +112,13 @@ class MessageHooks { public: MessageHooks() = default; - ~MessageHooks() {} + ~MessageHooks() = default; - MessageHook *addHook(int msgType, MessageHandler handler, std::any cbData, bool post); + MessageHook *addHook(int msgType, Message::Handler handler, HookType hookType); void removeHook(IMessageHook *hook); - IForward::ReturnValue exec(const std::unique_ptr &message, bool post) const; + IForward::ReturnValue exec(const std::unique_ptr &message, HookType hookType) const; bool hasHooks() const; @@ -137,13 +135,13 @@ class MessageMngr : public IMessageMngr ~MessageMngr() = default; // IMessageMngr - MessageHook *registerHook(int msgType, MessageHandler handler, std::any cbData, bool post) override; + MessageHook *registerHook(int msgType, Message::Handler handler, HookType hookType) override; void unregisterHook(IMessageHook *) override; - BlockType getMessageBlock(int msgType) const override; - void setMessageBlock(int msgType, BlockType blockType) override; + MsgBlockType getMessageBlock(int msgType) const override; + void setMessageBlock(int msgType, MsgBlockType blockType) override; - IForward::ReturnValue execHandlers(bool post); + IForward::ReturnValue execHandlers(HookType hookType); IMessage *getMessage() const override { @@ -176,7 +174,7 @@ class MessageMngr : public IMessageMngr private: std::unique_ptr m_message; std::array m_hooks; - std::array m_blocks; + std::array m_blocks; bool m_inhook; bool m_inblock; diff --git a/src/NativeProxy.cpp b/src/NativeProxy.cpp index 01f7d25b..f44b7e74 100644 --- a/src/NativeProxy.cpp +++ b/src/NativeProxy.cpp @@ -19,37 +19,12 @@ #include "spmod.hpp" -ProxiedNative::ProxiedNative(std::string_view name, std::any data, IPlugin *plugin) - : m_plugin(plugin), m_name(name), m_data(data) +bool NativeProxy::registerNative(IProxiedNative *native) { + return m_proxiedNatives.try_emplace(std::string(native->getName()), native).second; } -std::string_view ProxiedNative::getName() const -{ - return m_name; -} - -std::any ProxiedNative::getData() const -{ - return m_data; -} - -IPlugin *ProxiedNative::getPlugin() const -{ - return m_plugin; -} - -std::int32_t ProxiedNative::exec(IPlugin *plugin) -{ - return getPlugin()->getPluginMngr()->proxyNativeCallback(this, plugin); -} - -bool NativeProxy::registerNative(std::string_view name, std::any data, IPlugin *plugin) -{ - return m_proxiedNatives.try_emplace(name.data(), std::make_unique(name, data, plugin)).second; -} - -const std::unordered_map> &NativeProxy::getProxiedNatives() const +const std::unordered_map &NativeProxy::getProxiedNatives() const { return m_proxiedNatives; } @@ -58,14 +33,3 @@ void NativeProxy::clearNatives() { m_proxiedNatives.clear(); } - -std::vector NativeProxy::getProxiedNativesImpl() const -{ - std::vector proxiedNatives; - for (const auto &[name, native] : getProxiedNatives()) - { - proxiedNatives.emplace_back(native.get()); - } - - return proxiedNatives; -} diff --git a/src/NativeProxy.hpp b/src/NativeProxy.hpp index a507eb27..f7bd632a 100644 --- a/src/NativeProxy.hpp +++ b/src/NativeProxy.hpp @@ -21,27 +21,6 @@ #include "spmod.hpp" -class ProxiedNative final : public IProxiedNative -{ -public: - ProxiedNative() = delete; - ProxiedNative(const ProxiedNative &other) = delete; - ProxiedNative(ProxiedNative &&other) = default; - ~ProxiedNative() = default; - - ProxiedNative(std::string_view name, std::any data, IPlugin *plugin); - - std::string_view getName() const override; - std::any getData() const override; - IPlugin *getPlugin() const override; - std::int32_t exec(IPlugin *plugin) override; - -private: - IPlugin *m_plugin; - std::string m_name; - std::any m_data; -}; - class NativeProxy final : public INativeProxy { public: @@ -50,14 +29,11 @@ class NativeProxy final : public INativeProxy NativeProxy(NativeProxy &&other) = default; ~NativeProxy() = default; - bool registerNative(std::string_view name, std::any data, IPlugin *plugin) override; + bool registerNative(IProxiedNative *native) override; - const std::unordered_map> &getProxiedNatives() const; + const std::unordered_map &getProxiedNatives() const override; void clearNatives(); -protected: - std::vector getProxiedNativesImpl() const override; - private: - std::unordered_map> m_proxiedNatives; + std::unordered_map m_proxiedNatives; }; \ No newline at end of file diff --git a/src/PlayerSystem.cpp b/src/PlayerSystem.cpp index 06f47289..86f89916 100644 --- a/src/PlayerSystem.cpp +++ b/src/PlayerSystem.cpp @@ -144,7 +144,7 @@ bool Player::isInGame() const IBasePlayer *Player::basePlayer() const { - if (gSPGlobal->getModName() == ModName::Valve) + if (gSPGlobal->getModName() == ModType::Valve) { return m_basePlayer; } diff --git a/src/SPGlobal.cpp b/src/SPGlobal.cpp index 93d9fdf4..8c83493e 100644 --- a/src/SPGlobal.cpp +++ b/src/SPGlobal.cpp @@ -42,23 +42,23 @@ SPGlobal::SPGlobal(fs::path &&dllDir) std::string_view modName(GET_GAME_INFO(PLID, GINFO_NAME)); if (modName == "valve") { - m_modName = ModName::Valve; + m_modType = ModType::Valve; } else if (modName == "cstrike") { - m_modName = ModName::Cstrike; + m_modType = ModType::Cstrike; } else if (modName == "czero") { - m_modName = ModName::CZero; + m_modType = ModType::CZero; } else if (modName == "dod") { - m_modName = ModName::DoD; + m_modType = ModType::DoD; } else if (modName == "tfc") { - m_modName = ModName::TFC; + m_modType = ModType::TFC; } } @@ -224,9 +224,9 @@ void SPGlobal::setPath(DirType type, std::string_view path) } } -ModName SPGlobal::getModName() const +ModType SPGlobal::getModType() const { - return m_modName; + return m_modType; } ForwardMngr *SPGlobal::getForwardManager() const diff --git a/src/SPGlobal.hpp b/src/SPGlobal.hpp index fc43245e..b95fdefa 100644 --- a/src/SPGlobal.hpp +++ b/src/SPGlobal.hpp @@ -33,7 +33,7 @@ class SPGlobal final : public ISPGlobal // ISPGlobal const fs::path &getPath(DirType type) const override; - ModName getModName() const override; + ModType getModType() const override; bool canPluginsPrecache() const override; IPlugin *getPlugin(std::string_view pluginname) const override; @@ -94,7 +94,7 @@ class SPGlobal final : public ISPGlobal std::unique_ptr m_utils; std::unique_ptr m_vTableHookManager; - ModName m_modName; + ModType m_modType; std::unordered_map m_modulesInterfaces; std::unordered_map m_adaptersInterfaces; std::vector> m_extHandles; diff --git a/src/engine/Edict.cpp b/src/engine/Edict.cpp index 04b22ab7..ad665100 100644 --- a/src/engine/Edict.cpp +++ b/src/engine/Edict.cpp @@ -39,14 +39,14 @@ namespace SPMod::Engine bool Edict::isValid() const { - return !FNullEnt(m_edict) && !m_edict->free; + return _isValid() && m_serialNumber == static_cast(m_edict->serialnumber); } IBaseEntity *Edict::getBaseEntity() { switch (gSPGlobal->getModName()) { - case ModName::Valve: + case ModType::Valve: return getEntity(); default: return nullptr; @@ -57,7 +57,7 @@ namespace SPMod::Engine { switch (gSPGlobal->getModName()) { - case ModName::Valve: + case ModType::Valve: return getEntity(); default: return nullptr; @@ -73,4 +73,9 @@ namespace SPMod::Engine { return m_edict; } + + bool Edict::_isValid() const + { + return !FNullEnt(m_edict) && !m_edict->free; + } } // namespace SPMod::Engine \ No newline at end of file diff --git a/src/engine/Edict.hpp b/src/engine/Edict.hpp index e1354c26..8cec7e9b 100644 --- a/src/engine/Edict.hpp +++ b/src/engine/Edict.hpp @@ -43,10 +43,12 @@ namespace SPMod::Engine operator edict_t *() const; private: + bool _isValid() const; + template>> T *getEntity() { - if (!isValid()) + if (!_isValid()) { return nullptr; } diff --git a/src/engine/Engine.cpp b/src/engine/Engine.cpp index 84f5070f..749b9fab 100644 --- a/src/engine/Engine.cpp +++ b/src/engine/Engine.cpp @@ -46,6 +46,24 @@ namespace SPMod::Engine } } + Edict *Engine::getEdict(edict_t *edict) + { + try + { + return m_edicts.at(ENTINDEX(edict)).get(); + } + catch (const std::out_of_range &e [[maybe_unused]]) + { + // check if edict is valid and register it + if (!FNullEnt(edict) || !ENTINDEX(edict)) + { + auto resultIter = m_edicts.emplace(ENTINDEX(edict), std::make_unique(edict)).first; + return (*resultIter).second.get(); + } + return nullptr; + } + } + Globals *Engine::getGlobals() const { return m_globals.get(); diff --git a/src/engine/Engine.hpp b/src/engine/Engine.hpp index 8bc17354..cc13e0cb 100644 --- a/src/engine/Engine.hpp +++ b/src/engine/Engine.hpp @@ -39,6 +39,7 @@ namespace SPMod::Engine void freeTraceResult(ITraceResult *tr) override; // Engine + Edict *getEdict(edict_t *edict); EntVars *getEntVars(entvars_t *vars); TraceResult *createTraceResult(::TraceResult *tr); void clear(); diff --git a/src/engine/Funcs.cpp b/src/engine/Funcs.cpp index fe995b69..8dd9f2f8 100644 --- a/src/engine/Funcs.cpp +++ b/src/engine/Funcs.cpp @@ -78,7 +78,7 @@ namespace SPMod::Engine (m_hook) ? gpEngineFuncs->pfnAddServerCommand(cmd.data(), callback) : REG_SVR_COMMAND(cmd.data(), callback); } - void Funcs::messageBegin(MessageDest msgDest, std::uint32_t msgType, const float *pOrigin, IEdict *pEdict) const + void Funcs::messageBegin(MsgDest msgDest, std::uint32_t msgType, const float *pOrigin, IEdict *pEdict) const { (m_hook) ? gpEngineFuncs->pfnMessageBegin(static_cast(msgDest), msgType, pOrigin, INDEXENT(pEdict->getIndex())) diff --git a/src/engine/Funcs.hpp b/src/engine/Funcs.hpp index 76757d7e..b404f8a1 100644 --- a/src/engine/Funcs.hpp +++ b/src/engine/Funcs.hpp @@ -44,7 +44,7 @@ namespace SPMod::Engine void serverCommand(std::string_view cmd) const override; void serverExecute() const override; void registerSrvCommand(std::string_view cmd, ServerCmdCallback callback) const override; - void messageBegin(MessageDest msgDest, + void messageBegin(MsgDest msgDest, std::uint32_t msgType, const float *pOrigin, IEdict *pEdict) const override; diff --git a/subprojects/sourcepawn/CMakeLists.txt b/subprojects/sourcepawn/CMakeLists.txt index e9005d2c..ccda1124 100644 --- a/subprojects/sourcepawn/CMakeLists.txt +++ b/subprojects/sourcepawn/CMakeLists.txt @@ -20,7 +20,7 @@ set(SRC_FILES AdapterInterface.cpp SourcePawnAPI.cpp StringNatives.cpp TimerNatives.cpp - VTableNatives.cpp) + VTableNatives.cpp NativeCallback.hpp NativeCallback.cpp) add_library(${PROJECT_NAME} MODULE ${SRC_FILES}) diff --git a/subprojects/sourcepawn/CoreNatives.cpp b/subprojects/sourcepawn/CoreNatives.cpp index 261b0cff..9ddc33c9 100644 --- a/subprojects/sourcepawn/CoreNatives.cpp +++ b/subprojects/sourcepawn/CoreNatives.cpp @@ -19,6 +19,8 @@ #include "ExtMain.hpp" +std::vector> gSourcePawnPluginsNatives; + // native void PrintToServer(const char[] text, any ...) static cell_t PrintToServer(SourcePawn::IPluginContext *ctx, const cell_t *params) { @@ -86,22 +88,28 @@ static cell_t NativeRegister(SourcePawn::IPluginContext *ctx, const cell_t *para { char *nativeName; ctx->LocalToString(params[1], &nativeName); - SPExt::Plugin *plugin = gAdapterInterface->getPluginMngr()->getPlugin(ctx); - return gSPNativeProxy->registerNative(nativeName, ctx->GetFunctionById(params[2]), plugin); + if (!gAdapterInterface->getPluginMngr()->registerNative(nativeName, ctx->GetFunctionById(params[2]))) + { + ctx->ReportError("Native with the same name already registered"); + return 0; + } + + return 1; } // native int NativeGetInt(int param) static cell_t NativeGetInt(SourcePawn::IPluginContext *ctx, const cell_t *params) { - if (!SPExt::PluginMngr::m_callerPlugin) + if (SPExt::NativeCallback::currentPluginNative.empty()) { - ctx->ReportError("No caller plugin"); + ctx->ReportError("No native executed"); return 0; } cell_t param = params[1]; - int paramsNum = SPExt::PluginMngr::m_callerPlugin->getProxiedParamAsInt(0); + SPExt::NativeCallback *nativeCallback = SPExt::NativeCallback::currentPluginNative.top(); + std::int32_t paramsNum = nativeCallback->getParamAsInt(0); if (param > paramsNum || param < 0) { @@ -109,40 +117,42 @@ static cell_t NativeGetInt(SourcePawn::IPluginContext *ctx, const cell_t *params return 0; } - return SPExt::PluginMngr::m_callerPlugin->getProxiedParamAsInt(param); + return nativeCallback->getParamAsInt(param); } // native int NativeGetIntRef(int param) static cell_t NativeGetIntRef(SourcePawn::IPluginContext *ctx, const cell_t *params) { - if (!SPExt::PluginMngr::m_callerPlugin) + if (SPExt::NativeCallback::currentPluginNative.empty()) { - ctx->ReportError("No caller plugin"); + ctx->ReportError("No native executed"); return 0; } cell_t param = params[1]; - int paramsNum = SPExt::PluginMngr::m_callerPlugin->getProxiedParamAsInt(0); + SPExt::NativeCallback *nativeCallback = SPExt::NativeCallback::currentPluginNative.top(); + std::int32_t paramsNum = nativeCallback->getParamAsInt(0); if (param > paramsNum || param < 0) { ctx->ReportError("Incorrect parameter %d (range: 0 - %d)", param, paramsNum); return 0; } - return *SPExt::PluginMngr::m_callerPlugin->getProxiedParamAsIntAddr(param); + return *nativeCallback->getParamAsIntAddr(param); } // native float NativeGetFloat(int param) static cell_t NativeGetFloat(SourcePawn::IPluginContext *ctx, const cell_t *params) { - if (!SPExt::PluginMngr::m_callerPlugin) + if (SPExt::NativeCallback::currentPluginNative.empty()) { ctx->ReportError("No caller plugin"); return 0; } cell_t param = params[1]; - int paramsNum = SPExt::PluginMngr::m_callerPlugin->getProxiedParamAsInt(0); + SPExt::NativeCallback *nativeCallback = SPExt::NativeCallback::currentPluginNative.top(); + std::int32_t paramsNum = nativeCallback->getParamAsInt(0); if (param > paramsNum || param < 0) { @@ -150,47 +160,49 @@ static cell_t NativeGetFloat(SourcePawn::IPluginContext *ctx, const cell_t *para return 0; } - return sp_ftoc(SPExt::PluginMngr::m_callerPlugin->getProxiedParamAsFloat(param)); + return sp_ftoc(nativeCallback->getParamAsFloat(param)); } // native float NativeGetFloatRef(int param) static cell_t NativeGetFloatRef(SourcePawn::IPluginContext *ctx, const cell_t *params) { - if (!SPExt::PluginMngr::m_callerPlugin) + if (SPExt::NativeCallback::currentPluginNative.empty()) { - ctx->ReportError("No caller plugin"); + ctx->ReportError("No native executed"); return 0; } cell_t param = params[1]; - int paramsNum = SPExt::PluginMngr::m_callerPlugin->getProxiedParamAsInt(0); + SPExt::NativeCallback *nativeCallback = SPExt::NativeCallback::currentPluginNative.top(); + std::int32_t paramsNum = nativeCallback->getParamAsInt(0); if (param > paramsNum || param < 0) { ctx->ReportError("Incorrect parameter %d (range: 0 - %d)", param, paramsNum); return 0; } - return sp_ftoc(*SPExt::PluginMngr::m_callerPlugin->getProxiedParamAsFloatAddr(param)); + return sp_ftoc(*nativeCallback->getParamAsFloatAddr(param)); } // native int NativeGetString(int param, char[] buffer, int size) static cell_t NativeGetString(SourcePawn::IPluginContext *ctx, const cell_t *params) { - if (!SPExt::PluginMngr::m_callerPlugin) + if (SPExt::NativeCallback::currentPluginNative.empty()) { - ctx->ReportError("No caller plugin"); + ctx->ReportError("No native executed"); return 0; } cell_t param = params[1]; - int paramsNum = SPExt::PluginMngr::m_callerPlugin->getProxiedParamAsInt(0); + SPExt::NativeCallback *nativeCallback = SPExt::NativeCallback::currentPluginNative.top(); + std::int32_t paramsNum = nativeCallback->getParamAsInt(0); if (param > paramsNum || param < 0) { ctx->ReportError("Incorrect parameter %d (range: 0 - %d)", param, paramsNum); return 0; } - const char *stringToCopy = SPExt::PluginMngr::m_callerPlugin->getProxiedParamAsString(param); + const char *stringToCopy = nativeCallback->getParamAsString(param); std::size_t writtenBytes; ctx->StringToLocalUTF8(params[2], params[3], stringToCopy, &writtenBytes); @@ -201,14 +213,15 @@ static cell_t NativeGetString(SourcePawn::IPluginContext *ctx, const cell_t *par // native bool NativeGetArrayInt(int param, int[] buffer, int size) static cell_t NativeGetArrayInt(SourcePawn::IPluginContext *ctx, const cell_t *params) { - if (!SPExt::PluginMngr::m_callerPlugin) + if (SPExt::NativeCallback::currentPluginNative.empty()) { - ctx->ReportError("No caller plugin"); + ctx->ReportError("No native executed"); return 0; } cell_t param = params[1]; - int paramsNum = SPExt::PluginMngr::m_callerPlugin->getProxiedParamAsInt(0); + SPExt::NativeCallback *nativeCallback = SPExt::NativeCallback::currentPluginNative.top(); + std::int32_t paramsNum = nativeCallback->getParamAsInt(0); if (param > paramsNum || param < 0) { ctx->ReportError("Incorrect parameter %d (range: 0 - %d)", param, paramsNum); @@ -217,7 +230,7 @@ static cell_t NativeGetArrayInt(SourcePawn::IPluginContext *ctx, const cell_t *p cell_t *destArray; ctx->LocalToPhysAddr(params[2], &destArray); - auto srcArray = reinterpret_cast(SPExt::PluginMngr::m_callerPlugin->getProxiedParamAsArray(param)); + auto srcArray = reinterpret_cast(nativeCallback->getParamAsArray(param)); std::copy_n(srcArray, params[3], destArray); @@ -227,14 +240,15 @@ static cell_t NativeGetArrayInt(SourcePawn::IPluginContext *ctx, const cell_t *p // native bool NativeGetArrayFloat(int param, float[] buffer, int size) static cell_t NativeGetArrayFloat(SourcePawn::IPluginContext *ctx, const cell_t *params) { - if (!SPExt::PluginMngr::m_callerPlugin) + if (SPExt::NativeCallback::currentPluginNative.empty()) { - ctx->ReportError("No caller plugin"); + ctx->ReportError("No native executed"); return 0; } cell_t param = params[1]; - int paramsNum = SPExt::PluginMngr::m_callerPlugin->getProxiedParamAsInt(0); + SPExt::NativeCallback *nativeCallback = SPExt::NativeCallback::currentPluginNative.top(); + std::int32_t paramsNum = nativeCallback->getParamAsInt(0); if (param > paramsNum || param < 0) { ctx->ReportError("Incorrect parameter %d (range: 0 - %d)", param, paramsNum); @@ -243,7 +257,7 @@ static cell_t NativeGetArrayFloat(SourcePawn::IPluginContext *ctx, const cell_t cell_t *destArray; ctx->LocalToPhysAddr(params[2], &destArray); - auto srcArray = reinterpret_cast(SPExt::PluginMngr::m_callerPlugin->getProxiedParamAsArray(param)); + auto srcArray = reinterpret_cast(nativeCallback->getParamAsArray(param)); for (std::size_t i = 0; i < static_cast(params[3]); i++) { @@ -256,56 +270,59 @@ static cell_t NativeGetArrayFloat(SourcePawn::IPluginContext *ctx, const cell_t // native bool NativeSetIntRef(int param, int value) static cell_t NativeSetIntRef(SourcePawn::IPluginContext *ctx, const cell_t *params) { - if (!SPExt::PluginMngr::m_callerPlugin) + if (SPExt::NativeCallback::currentPluginNative.empty()) { - ctx->ReportError("No caller plugin"); + ctx->ReportError("No native executed"); return 0; } cell_t param = params[1]; - int paramsNum = SPExt::PluginMngr::m_callerPlugin->getProxiedParamAsInt(0); + SPExt::NativeCallback *nativeCallback = SPExt::NativeCallback::currentPluginNative.top(); + std::int32_t paramsNum = nativeCallback->getParamAsInt(0); if (param > paramsNum || param < 0) { ctx->ReportError("Incorrect parameter %d (range: 0 - %d)", param, paramsNum); return 0; } - *SPExt::PluginMngr::m_callerPlugin->getProxiedParamAsIntAddr(param) = params[2]; + *nativeCallback->getParamAsIntAddr(param) = params[2]; return 1; } // native bool NativeSetFloatRef(int param, float value) static cell_t NativeSetFloatRef(SourcePawn::IPluginContext *ctx, const cell_t *params) { - if (!SPExt::PluginMngr::m_callerPlugin) + if (SPExt::NativeCallback::currentPluginNative.empty()) { - ctx->ReportError("No caller plugin"); + ctx->ReportError("No native executed"); return 0; } cell_t param = params[1]; - int paramsNum = SPExt::PluginMngr::m_callerPlugin->getProxiedParamAsInt(0); + SPExt::NativeCallback *nativeCallback = SPExt::NativeCallback::currentPluginNative.top(); + std::int32_t paramsNum = nativeCallback->getParamAsInt(0); if (param > paramsNum || param < 0) { ctx->ReportError("Incorrect parameter %d (range: 0 - %d)", param, paramsNum); return 0; } - *SPExt::PluginMngr::m_callerPlugin->getProxiedParamAsFloatAddr(param) = sp_ctof(params[2]); + *nativeCallback->getParamAsFloatAddr(param) = sp_ctof(params[2]); return 1; } // native int NativeSetString(int param, const char[] string, int size) static cell_t NativeSetString(SourcePawn::IPluginContext *ctx, const cell_t *params) { - if (!SPExt::PluginMngr::m_callerPlugin) + if (SPExt::NativeCallback::currentPluginNative.empty()) { - ctx->ReportError("No caller plugin"); + ctx->ReportError("No native executed"); return 0; } cell_t param = params[1]; - int paramsNum = SPExt::PluginMngr::m_callerPlugin->getProxiedParamAsInt(0); + SPExt::NativeCallback *nativeCallback = SPExt::NativeCallback::currentPluginNative.top(); + std::int32_t paramsNum = nativeCallback->getParamAsInt(0); if (param > paramsNum || param < 0) { ctx->ReportError("Incorrect parameter %d (range: 0 - %d)", param, paramsNum); @@ -315,7 +332,7 @@ static cell_t NativeSetString(SourcePawn::IPluginContext *ctx, const cell_t *par char *stringToCopy; ctx->LocalToString(params[2], &stringToCopy); - char *destString = SPExt::PluginMngr::m_callerPlugin->getProxiedParamAsString(param); + char *destString = nativeCallback->getParamAsString(param); std::copy_n(stringToCopy, params[3], destString); return params[3]; @@ -324,14 +341,15 @@ static cell_t NativeSetString(SourcePawn::IPluginContext *ctx, const cell_t *par // native bool NativeSetArrayInt(int param, const int[] buffer, int size) static cell_t NativeSetArrayInt(SourcePawn::IPluginContext *ctx, const cell_t *params) { - if (!SPExt::PluginMngr::m_callerPlugin) + if (SPExt::NativeCallback::currentPluginNative.empty()) { - ctx->ReportError("No caller plugin"); + ctx->ReportError("No native executed"); return 0; } cell_t param = params[1]; - int paramsNum = SPExt::PluginMngr::m_callerPlugin->getProxiedParamAsInt(0); + SPExt::NativeCallback *nativeCallback = SPExt::NativeCallback::currentPluginNative.top(); + std::int32_t paramsNum = nativeCallback->getParamAsInt(0); if (param > paramsNum || param < 0) { ctx->ReportError("Incorrect parameter %d (range: 0 - %d)", param, paramsNum); @@ -340,7 +358,7 @@ static cell_t NativeSetArrayInt(SourcePawn::IPluginContext *ctx, const cell_t *p cell_t *arrayToCopy; ctx->LocalToPhysAddr(params[2], &arrayToCopy); - auto destArray = reinterpret_cast(SPExt::PluginMngr::m_callerPlugin->getProxiedParamAsArray(param)); + auto destArray = reinterpret_cast(nativeCallback->getParamAsArray(param)); std::copy_n(arrayToCopy, params[3], destArray); @@ -350,14 +368,15 @@ static cell_t NativeSetArrayInt(SourcePawn::IPluginContext *ctx, const cell_t *p // native bool NativeSetArrayFloat(int param, const float[] buffer, int size) static cell_t NativeSetArrayFloat(SourcePawn::IPluginContext *ctx, const cell_t *params) { - if (!SPExt::PluginMngr::m_callerPlugin) + if (SPExt::NativeCallback::currentPluginNative.empty()) { - ctx->ReportError("No caller plugin"); + ctx->ReportError("No native executed"); return 0; } cell_t param = params[1]; - int paramsNum = SPExt::PluginMngr::m_callerPlugin->getProxiedParamAsInt(0); + SPExt::NativeCallback *nativeCallback = SPExt::NativeCallback::currentPluginNative.top(); + std::int32_t paramsNum = nativeCallback->getParamAsInt(0); if (param > paramsNum || param < 0) { ctx->ReportError("Incorrect parameter %d (range: 0 - %d)", param, paramsNum); @@ -366,7 +385,7 @@ static cell_t NativeSetArrayFloat(SourcePawn::IPluginContext *ctx, const cell_t cell_t *arrayToCopy; ctx->LocalToPhysAddr(params[2], &arrayToCopy); - auto destArray = reinterpret_cast(SPExt::PluginMngr::m_callerPlugin->getProxiedParamAsArray(param)); + auto destArray = reinterpret_cast(nativeCallback->getParamAsArray(param)); for (std::size_t i = 0; i < static_cast(params[3]); i++) { @@ -441,7 +460,7 @@ static cell_t GetMapName(SourcePawn::IPluginContext *ctx, const cell_t *params) std::string_view mapName = gSPEngGlobals->getMapName(); - return static_cast(gSPGlobal->getUtils()->strCopy(plOutput, params[arg_size], mapName)); + return static_cast(gSPUtils->strCopy(plOutput, params[arg_size], mapName)); } sp_nativeinfo_t gCoreNatives[] = {{"PrintToServer", PrintToServer}, diff --git a/subprojects/sourcepawn/ExtMain.cpp b/subprojects/sourcepawn/ExtMain.cpp index c297f28f..d24ea081 100644 --- a/subprojects/sourcepawn/ExtMain.cpp +++ b/subprojects/sourcepawn/ExtMain.cpp @@ -30,6 +30,7 @@ SPMod::ICvarMngr *gSPCvarMngr; SPMod::IForwardMngr *gSPFwdMngr; SPMod::ILoggerMngr *gSPLoggerMngr; SPMod::IMenuMngr *gSPMenuMngr; +SPMod::IMessageMngr *gSPMsgMngr; SPMod::IPlayerMngr *gSPPlrMngr; SPMod::ITimerMngr *gSPTimerMngr; SPMod::IUtils *gSPUtils; @@ -78,6 +79,12 @@ namespace return false; } + gSPMsgMngr = gSPGlobal->getMessageManager(); + if (!gSPMsgMngr->isVersionCompatible(SPMod::IMessageMngr::VERSION)) + { + return false; + } + gSPPlrMngr = gSPGlobal->getPlayerManager(); if (!gSPPlrMngr->isVersionCompatible(SPMod::IPlayerMngr::VERSION)) { diff --git a/subprojects/sourcepawn/ExtMain.hpp b/subprojects/sourcepawn/ExtMain.hpp index a00a5794..26b29868 100644 --- a/subprojects/sourcepawn/ExtMain.hpp +++ b/subprojects/sourcepawn/ExtMain.hpp @@ -36,6 +36,7 @@ #endif #include "SourcePawnAPI.hpp" +#include "NativeCallback.hpp" #include "DebugListener.hpp" #include "PluginSystem.hpp" #include "AdapterInterface.hpp" @@ -49,6 +50,7 @@ extern SPMod::ICvarMngr *gSPCvarMngr; extern SPMod::IForwardMngr *gSPFwdMngr; extern SPMod::ILoggerMngr *gSPLoggerMngr; extern SPMod::IMenuMngr *gSPMenuMngr; +extern SPMod::IMessageMngr *gSPMsgMngr; extern SPMod::IPlayerMngr *gSPPlrMngr; extern SPMod::ITimerMngr *gSPTimerMngr; extern SPMod::IUtils *gSPUtils; diff --git a/subprojects/sourcepawn/MessageNatives.cpp b/subprojects/sourcepawn/MessageNatives.cpp index 74898720..46f7f767 100644 --- a/subprojects/sourcepawn/MessageNatives.cpp +++ b/subprojects/sourcepawn/MessageNatives.cpp @@ -33,7 +33,7 @@ static cell_t GetUserMsgId(SourcePawn::IPluginContext *ctx, const cell_t *params char *string; ctx->LocalToString(params[arg_msgname], &string); - return gSPGlobal->getMetaFuncs()->getUsrMsgId(string); + return gSPMetamodFuncs->getUsrMsgId(string); } // int GetUserMsgName(int msgid, char[] str, int len) = 3 params @@ -46,7 +46,7 @@ static cell_t GetUserMsgName(SourcePawn::IPluginContext *ctx, const cell_t *para arg_len }; - std::string_view string = gSPGlobal->getMetaFuncs()->getUsrMsgName(params[arg_msg]); + std::string_view string = gSPMetamodFuncs->getUsrMsgName(params[arg_msg]); if (!string.empty()) { ctx->StringToLocal(params[arg_str], params[arg_len], string.data()); @@ -75,8 +75,22 @@ static cell_t HookMessage(SourcePawn::IPluginContext *ctx, const cell_t *params) } // TODO: natives for enable/disable hook - SPMod::IMessageHook *hook = gSPGlobal->getMessageManager()->registerHook( - params[arg_msg_type], SPExt::Listener::MessageHookCallback, func, params[arg_post]); + SPMod::IMessageHook *hook = gSPMsgMngr->registerHook( + params[arg_msg_type], + [func](SPMod::IMessage *const message) { + if (func && func->IsRunnable()) + { + // typedef MessageHandler = function PluginReturn (MessageDest dest, int type, int receiver); + cell_t retValue = 0; + func->PushCell(static_cast(message->getDest())); + func->PushCell(message->getType()); + func->PushCell(message->getEdict()->getIndex()); + func->Execute(&retValue); + + return static_cast(retValue); + } + return SPMod::IForward::ReturnValue::Ignored; + },params[arg_post] == 1 ? SPMod::HookType::Post : SPMod::HookType::Pre); return gMessageHooks.create(hook); } @@ -97,7 +111,7 @@ static cell_t UnhookMessage(SourcePawn::IPluginContext *ctx, const cell_t *param return 0; } - gSPGlobal->getMessageManager()->unregisterHook(hook); + gSPMsgMngr->unregisterHook(hook); return 1; } @@ -116,7 +130,7 @@ static cell_t GetMsgBlock(SourcePawn::IPluginContext *ctx, const cell_t *params) return 0; } - return static_cast(gSPGlobal->getMessageManager()->getMessageBlock(params[arg_msg_type])); + return static_cast(gSPMsgMngr->getMessageBlock(params[arg_msg_type])); } // native void SetMsgBlock(int msgtype, BlockType type); @@ -134,8 +148,8 @@ static cell_t SetMsgBlock(SourcePawn::IPluginContext *ctx, const cell_t *params) return 0; } - gSPGlobal->getMessageManager()->setMessageBlock(params[arg_msg_type], - static_cast(params[arg_block_type])); + gSPMsgMngr->setMessageBlock(params[arg_msg_type], + static_cast(params[arg_block_type])); return 1; } @@ -143,15 +157,13 @@ static cell_t SetMsgBlock(SourcePawn::IPluginContext *ctx, const cell_t *params) // native int GetMsgArgs(); static cell_t GetMsgArgs(SourcePawn::IPluginContext *ctx [[maybe_unused]], const cell_t *params [[maybe_unused]]) { - SPMod::IMessageMngr *messageMngr = gSPGlobal->getMessageManager(); - - if (!messageMngr->inHook()) + if (!gSPMsgMngr->inHook()) { ctx->ReportError("Invalid function call. Use this native in message hook handler."); return 0; } - SPMod::IMessage *message = messageMngr->getMessage(); + SPMod::IMessage *message = gSPMsgMngr->getMessage(); return message->getParams(); } @@ -164,15 +176,13 @@ static cell_t GetMsgArgType(SourcePawn::IPluginContext *ctx [[maybe_unused]], co arg_index = 1 }; - SPMod::IMessageMngr *messageMngr = gSPGlobal->getMessageManager(); - - if (!messageMngr->inHook()) + if (!gSPMsgMngr->inHook()) { ctx->ReportError("Invalid function call. Use this native in message hook handler."); return 0; } - SPMod::IMessage *message = messageMngr->getMessage(); + SPMod::IMessage *message = gSPMsgMngr->getMessage(); if (params[arg_index] < 0 || static_cast(params[arg_index]) >= message->getParams()) { @@ -191,15 +201,13 @@ static cell_t GetMsgArgInt(SourcePawn::IPluginContext *ctx [[maybe_unused]], con arg_index = 1 }; - SPMod::IMessageMngr *messageMngr = gSPGlobal->getMessageManager(); - - if (!messageMngr->inHook()) + if (!gSPMsgMngr->inHook()) { ctx->ReportError("Invalid function call. Use this native in message hook handler."); return 0; } - SPMod::IMessage *message = messageMngr->getMessage(); + SPMod::IMessage *message = gSPMsgMngr->getMessage(); if (params[arg_index] < 0 || static_cast(params[arg_index]) >= message->getParams()) { @@ -218,15 +226,13 @@ static cell_t GetMsgArgFloat(SourcePawn::IPluginContext *ctx [[maybe_unused]], c arg_index = 1 }; - SPMod::IMessageMngr *messageMngr = gSPGlobal->getMessageManager(); - - if (!messageMngr->inHook()) + if (!gSPMsgMngr->inHook()) { ctx->ReportError("Invalid function call. Use this native in message hook handler."); return 0; } - SPMod::IMessage *message = messageMngr->getMessage(); + SPMod::IMessage *message = gSPMsgMngr->getMessage(); if (params[arg_index] < 0 || static_cast(params[arg_index]) >= message->getParams()) { @@ -247,15 +253,13 @@ static cell_t GetMsgArgString(SourcePawn::IPluginContext *ctx, const cell_t *par arg_size }; - SPMod::IMessageMngr *messageMngr = gSPGlobal->getMessageManager(); - - if (!messageMngr->inHook()) + if (!gSPMsgMngr->inHook()) { ctx->ReportError("Invalid function call. Use this native in message hook handler."); return 0; } - SPMod::IMessage *message = messageMngr->getMessage(); + SPMod::IMessage *message = gSPMsgMngr->getMessage(); if (params[arg_index] < 0 || static_cast(params[arg_index]) >= message->getParams()) { @@ -278,15 +282,13 @@ static cell_t SetMsgArgInt(SourcePawn::IPluginContext *ctx [[maybe_unused]], con arg_value }; - SPMod::IMessageMngr *messageMngr = gSPGlobal->getMessageManager(); - - if (!messageMngr->inHook()) + if (!gSPMsgMngr->inHook()) { ctx->ReportError("Invalid function call. Use this native in message hook handler."); return 0; } - SPMod::IMessage *message = messageMngr->getMessage(); + SPMod::IMessage *message = gSPMsgMngr->getMessage(); if (params[arg_index] < 0 || static_cast(params[arg_index]) >= message->getParams()) { @@ -308,15 +310,13 @@ static cell_t SetMsgArgFloat(SourcePawn::IPluginContext *ctx [[maybe_unused]], c arg_value }; - SPMod::IMessageMngr *messageMngr = gSPGlobal->getMessageManager(); - - if (!messageMngr->inHook()) + if (!gSPMsgMngr->inHook()) { ctx->ReportError("Invalid function call. Use this native in message hook handler."); return 0; } - SPMod::IMessage *message = messageMngr->getMessage(); + SPMod::IMessage *message = gSPMsgMngr->getMessage(); if (params[arg_index] < 0 || static_cast(params[arg_index]) >= message->getParams()) { @@ -338,15 +338,13 @@ static cell_t SetMsgArgString(SourcePawn::IPluginContext *ctx [[maybe_unused]], arg_string }; - SPMod::IMessageMngr *messageMngr = gSPGlobal->getMessageManager(); - - if (!messageMngr->inHook()) + if (!gSPMsgMngr->inHook()) { ctx->ReportError("Invalid function call. Use this native in message hook handler."); return 0; } - SPMod::IMessage *message = messageMngr->getMessage(); + SPMod::IMessage *message = gSPMsgMngr->getMessage(); if (params[arg_index] < 0 || static_cast(params[arg_index]) >= message->getParams()) { @@ -380,30 +378,30 @@ static cell_t MessageBegin(SourcePawn::IPluginContext *ctx, const cell_t *params cell_t *cpOrigin; if (params[arg_msg_type] < 1 || ((params[arg_msg_type] > 63) // maximal number of engine messages - && gSPGlobal->getMetaFuncs()->getUsrMsgName(params[2]).empty())) + && gSPMetamodFuncs->getUsrMsgName(params[2]).empty())) { ctx->ReportError("Plugin called MessageBegin with an invalid message id (%d).", params[arg_msg_type]); return 0; } ignoreHooks = static_cast(params[arg_ignore_hooks]); - auto messageDest = static_cast(params[arg_dest]); + auto messageDest = static_cast(params[arg_dest]); switch (messageDest) { - case SPMod::MessageDest::BROADCAST: - case SPMod::MessageDest::ALL: - case SPMod::MessageDest::SPEC: - case SPMod::MessageDest::INIT: + case SPMod::MsgDest::BROADCAST: + case SPMod::MsgDest::ALL: + case SPMod::MsgDest::SPEC: + case SPMod::MsgDest::INIT: if (ignoreHooks) - gSPGlobal->getEngineFuncs()->messageBegin(messageDest, params[arg_msg_type], nullptr); + gSPEngFuncs->messageBegin(messageDest, params[arg_msg_type], nullptr); else - gSPGlobal->getEngineHookedFuncs()->messageBegin(messageDest, params[arg_msg_type], nullptr); + gSPEngFuncsHooked->messageBegin(messageDest, params[arg_msg_type], nullptr); break; - case SPMod::MessageDest::PVS: - case SPMod::MessageDest::PAS: - case SPMod::MessageDest::PVS_R: - case SPMod::MessageDest::PAS_R: + case SPMod::MsgDest::PVS: + case SPMod::MsgDest::PAS: + case SPMod::MsgDest::PVS_R: + case SPMod::MsgDest::PAS_R: if (numparam < 3) { ctx->ReportError("Invalid number of parameters passed"); @@ -417,13 +415,13 @@ static cell_t MessageBegin(SourcePawn::IPluginContext *ctx, const cell_t *params vecOrigin[2] = sp_ctof(*(cpOrigin + 2)); if (ignoreHooks) - gSPGlobal->getEngineFuncs()->messageBegin(messageDest, params[arg_msg_type], vecOrigin); + gSPEngFuncs->messageBegin(messageDest, params[arg_msg_type], vecOrigin); else - gSPGlobal->getEngineHookedFuncs()->messageBegin(messageDest, params[arg_msg_type], vecOrigin); + gSPEngFuncsHooked->messageBegin(messageDest, params[arg_msg_type], vecOrigin); break; - case SPMod::MessageDest::ONE_UNRELIABLE: - case SPMod::MessageDest::ONE: + case SPMod::MsgDest::ONE_UNRELIABLE: + case SPMod::MsgDest::ONE: if (numparam < 4) { ctx->ReportError("Invalid number of parameters passed"); @@ -433,9 +431,9 @@ static cell_t MessageBegin(SourcePawn::IPluginContext *ctx, const cell_t *params SPMod::IPlayer *player = gSPGlobal->getPlayerManager()->getPlayer(params[arg_player]); if (ignoreHooks) - gSPGlobal->getEngineFuncs()->messageBegin(messageDest, params[arg_msg_type], nullptr, player); + gSPEngFuncs->messageBegin(messageDest, params[arg_msg_type], nullptr, player->edict()); else - gSPGlobal->getEngineHookedFuncs()->messageBegin(messageDest, params[arg_msg_type], nullptr, player); + gSPEngFuncsHooked->messageBegin(messageDest, params[arg_msg_type], nullptr, player->edict()); break; } @@ -447,9 +445,9 @@ static cell_t MessageBegin(SourcePawn::IPluginContext *ctx, const cell_t *params static cell_t MessageEnd(SourcePawn::IPluginContext *ctx [[maybe_unused]], const cell_t *params [[maybe_unused]]) { if (ignoreHooks) - gSPGlobal->getEngineFuncs()->messageEnd(); + gSPEngFuncs->messageEnd(); else - gSPGlobal->getEngineHookedFuncs()->messageEnd(); + gSPEngFuncsHooked->messageEnd(); return 1; } @@ -462,9 +460,9 @@ static cell_t WriteByte(SourcePawn::IPluginContext *ctx [[maybe_unused]], const arg_value = 1 }; if (ignoreHooks) - gSPGlobal->getEngineFuncs()->writeByte(params[arg_value]); + gSPEngFuncs->writeByte(params[arg_value]); else - gSPGlobal->getEngineHookedFuncs()->writeByte(params[arg_value]); + gSPEngFuncsHooked->writeByte(params[arg_value]); return 1; } @@ -476,9 +474,9 @@ static cell_t WriteChar(SourcePawn::IPluginContext *ctx [[maybe_unused]], const arg_value = 1 }; if (ignoreHooks) - gSPGlobal->getEngineFuncs()->writeChar(params[arg_value]); + gSPEngFuncs->writeChar(params[arg_value]); else - gSPGlobal->getEngineHookedFuncs()->writeChar(params[arg_value]); + gSPEngFuncsHooked->writeChar(params[arg_value]); return 1; } @@ -490,9 +488,9 @@ static cell_t WriteShort(SourcePawn::IPluginContext *ctx [[maybe_unused]], const arg_value = 1 }; if (ignoreHooks) - gSPGlobal->getEngineFuncs()->writeShort(params[arg_value]); + gSPEngFuncs->writeShort(params[arg_value]); else - gSPGlobal->getEngineHookedFuncs()->writeShort(params[arg_value]); + gSPEngFuncsHooked->writeShort(params[arg_value]); return 1; } @@ -504,9 +502,9 @@ static cell_t WriteLong(SourcePawn::IPluginContext *ctx [[maybe_unused]], const arg_value = 1 }; if (ignoreHooks) - gSPGlobal->getEngineFuncs()->writeLong(params[arg_value]); + gSPEngFuncs->writeLong(params[arg_value]); else - gSPGlobal->getEngineHookedFuncs()->writeLong(params[arg_value]); + gSPEngFuncsHooked->writeLong(params[arg_value]); return 1; } @@ -518,9 +516,9 @@ static cell_t WriteEntity(SourcePawn::IPluginContext *ctx [[maybe_unused]], cons arg_value = 1 }; if (ignoreHooks) - gSPGlobal->getEngineFuncs()->writeEntity(params[arg_value]); + gSPEngFuncs->writeEntity(params[arg_value]); else - gSPGlobal->getEngineHookedFuncs()->writeEntity(params[arg_value]); + gSPEngFuncsHooked->writeEntity(params[arg_value]); return 1; } // native void WriteAngle(float value); @@ -531,9 +529,9 @@ static cell_t WriteAngle(SourcePawn::IPluginContext *ctx [[maybe_unused]], const arg_value = 1 }; if (ignoreHooks) - gSPGlobal->getEngineFuncs()->writeAngle(sp_ctof(params[arg_value])); + gSPEngFuncs->writeAngle(sp_ctof(params[arg_value])); else - gSPGlobal->getEngineHookedFuncs()->writeAngle(sp_ctof(params[arg_value])); + gSPEngFuncsHooked->writeAngle(sp_ctof(params[arg_value])); return 1; } // native void WriteCoord(float value); @@ -544,9 +542,9 @@ static cell_t WriteCoord(SourcePawn::IPluginContext *ctx [[maybe_unused]], const arg_value = 1 }; if (ignoreHooks) - gSPGlobal->getEngineFuncs()->writeCoord(sp_ctof(params[arg_value])); + gSPEngFuncs->writeCoord(sp_ctof(params[arg_value])); else - gSPGlobal->getEngineHookedFuncs()->writeCoord(sp_ctof(params[arg_value])); + gSPEngFuncsHooked->writeCoord(sp_ctof(params[arg_value])); return 1; } @@ -561,9 +559,9 @@ static cell_t WriteString(SourcePawn::IPluginContext *ctx, const cell_t *params) ctx->LocalToString(params[arg_value], &string); if (ignoreHooks) - gSPGlobal->getEngineFuncs()->writeString(string); + gSPEngFuncs->writeString(string); else - gSPGlobal->getEngineHookedFuncs()->writeString(string); + gSPEngFuncsHooked->writeString(string); return 1; } diff --git a/subprojects/sourcepawn/NativeCallback.cpp b/subprojects/sourcepawn/NativeCallback.cpp index 479db198..0618c5f2 100644 --- a/subprojects/sourcepawn/NativeCallback.cpp +++ b/subprojects/sourcepawn/NativeCallback.cpp @@ -1,3 +1,209 @@ -// -// Created by karol on 9/30/20. -// +/* + * Copyright (C) 2020 SPMod Development Team + * + * This file is part of SPMod. + * + * SPMod is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * SPMod is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with SPMod. If not, see . + */ + +#include "ExtMain.hpp" +#include "NativeCallback.hpp" + +namespace SPExt +{ + NativeCallback::NativeCallback(std::string_view name, SourcePawn::IPluginFunction *pluginFunction) + : m_name(name), m_pluginFunction(pluginFunction) + { + } + + NativeCallback::NativeCallback(SPMod::IProxiedNative *native) : m_name(native->getName()), m_proxiedNative(native) {} + + void NativeCallback::AddRef() + { + m_refCount++; + } + + void NativeCallback::Release() + { + if (--m_refCount <= 0) + { + delete this; + } + } + + cell_t NativeCallback::Invoke(SourcePawn::IPluginContext *ctx, const cell_t *params) + { + if (params[0] > SP_MAX_CALL_ARGUMENTS) + { + ctx->ReportError("Too many parameters passed to native %d (max: %d)", params[0], SP_MAX_CALL_ARGUMENTS); + return 0; + } + + m_ctx.emplace(ctx); + m_params.emplace(params); + NativeCallback::currentPluginNative.emplace(this); + + cell_t result = 0; + if (m_pluginFunction && m_pluginFunction->IsRunnable()) + { + SPExt::Plugin *executor; + ctx->GetKey(2, reinterpret_cast(&executor)); + m_pluginFunction->PushCell(executor->getId()); + m_pluginFunction->Execute(&result); + } + else + { + result = m_proxiedNative->InvokeSPModNative(); + } + + NativeCallback::currentPluginNative.pop(); + m_ctx.pop(); + m_params.pop(); + + return result; + } + + std::int32_t NativeCallback::getParamAsInt(std::size_t index) const + { + try + { + if (m_proxiedNative) + { + return m_proxiedNative->getParamAsInt(index); + } + return m_params.top()[index]; + } + catch (const std::out_of_range &e [[maybe_unused]]) + { + return 0; + } + } + + std::int32_t *NativeCallback::getParamAsIntAddr(std::size_t index) const + { + try + { + if (m_proxiedNative) + { + return m_proxiedNative->getParamAsIntAddr(index); + } + + cell_t *result; + cell_t address = m_params.top()[index]; + m_ctx.top()->LocalToPhysAddr(address, &result); + return result; + } + catch (const std::out_of_range &e [[maybe_unused]]) + { + return nullptr; + } + } + + float NativeCallback::getParamAsFloat(std::size_t index) const + { + try + { + if (m_proxiedNative) + { + return m_proxiedNative->getParamAsFloat(index); + } + return sp_ctof(m_params.top()[index]); + } + catch (const std::out_of_range &e [[maybe_unused]]) + { + return 0; + } + } + + float *NativeCallback::getParamAsFloatAddr(std::size_t index) const + { + try + { + if (m_proxiedNative) + { + return m_proxiedNative->getParamAsFloatAddr(index); + } + + cell_t *result; + cell_t address = m_params.top()[index]; + m_ctx.top()->LocalToPhysAddr(address, &result); + + return reinterpret_cast(result); + } + catch (const std::out_of_range &e [[maybe_unused]]) + { + return nullptr; + } + } + + char *NativeCallback::getParamAsString(std::size_t index) const + { + try + { + if (m_proxiedNative) + { + return m_proxiedNative->getParamAsString(index); + } + + char *result; + cell_t address = m_params.top()[index]; + m_ctx.top()->LocalToString(address, &result); + + return result; + } + catch (const std::out_of_range &e [[maybe_unused]]) + { + return nullptr; + } + } + + void *NativeCallback::getParamAsArray(std::size_t index) const + { + try + { + if (m_proxiedNative) + { + m_proxiedNative->getParamAsArray(index); + } + + cell_t *result; + cell_t address = m_params.top()[index]; + m_ctx.top()->LocalToPhysAddr(address, &result); + + return result; + } + catch (const std::out_of_range &e [[maybe_unused]]) + { + return nullptr; + } + } + + std::string_view NativeCallback::getName() const + { + return m_name; + } + + std::int32_t NativeCallback::InvokeSPModNative() + { + cell_t result = 0; + if (m_pluginFunction && m_pluginFunction->IsRunnable()) + { + NativeCallback::currentPluginNative.emplace(this); + m_pluginFunction->PushCell(-1); // TODO: Make valid ids for external adapters plugins + m_pluginFunction->Execute(&result); + NativeCallback::currentPluginNative.pop(); + } + return result; + } +} \ No newline at end of file diff --git a/subprojects/sourcepawn/NativeCallback.hpp b/subprojects/sourcepawn/NativeCallback.hpp index d8a90e67..5a7ebffd 100644 --- a/subprojects/sourcepawn/NativeCallback.hpp +++ b/subprojects/sourcepawn/NativeCallback.hpp @@ -1,8 +1,54 @@ -// -// Created by karol on 9/30/20. -// +/* + * Copyright (C) 2020 SPMod Development Team + * + * This file is part of SPMod. + * + * SPMod is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * SPMod is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with SPMod. If not, see . + */ -#ifndef SPMOD_NATIVECALLBACK_HPP -#define SPMOD_NATIVECALLBACK_HPP +#pragma once -#endif //SPMOD_NATIVECALLBACK_HPP +#include "ExtMain.hpp" + +namespace SPExt +{ + class NativeCallback : public SourcePawn::INativeCallback, public SPMod::IProxiedNative + { + public: + explicit NativeCallback(std::string_view name, SourcePawn::IPluginFunction *pluginFunction); + explicit NativeCallback(SPMod::IProxiedNative *native); + void AddRef() override; + void Release() override; + cell_t Invoke(SourcePawn::IPluginContext *ctx, const cell_t *params) override; + std::int32_t InvokeSPModNative() override; + + std::string_view getName() const override; + std::int32_t getParamAsInt(std::size_t index) const override; + std::int32_t *getParamAsIntAddr(std::size_t index) const override; + float getParamAsFloat(std::size_t index) const override; + float *getParamAsFloatAddr(std::size_t index) const override; + char *getParamAsString(std::size_t index) const override; + void *getParamAsArray(std::size_t index) const override; + + static inline std::stack currentPluginNative = {}; + + private: + std::string m_name; + SourcePawn::IPluginFunction *m_pluginFunction = nullptr; + SPMod::IProxiedNative *m_proxiedNative = nullptr; + std::stack m_ctx; + std::stack m_params; + std::uint32_t m_refCount = 0; + }; +} \ No newline at end of file diff --git a/subprojects/sourcepawn/PluginSystem.cpp b/subprojects/sourcepawn/PluginSystem.cpp index 41b535eb..8a53b84e 100644 --- a/subprojects/sourcepawn/PluginSystem.cpp +++ b/subprojects/sourcepawn/PluginSystem.cpp @@ -51,7 +51,8 @@ namespace SPExt m_url = gatherInfo(Plugin::FIELD_URL); m_runtime = plugin; - m_runtime->GetDefaultContext()->SetKey(1, const_cast(m_identity.c_str())); + m_runtime->GetDefaultContext()->SetKey(1, reinterpret_cast(m_identity.data())); + m_runtime->GetDefaultContext()->SetKey(2, this); std::uint32_t nativesNum = plugin->GetNativesNum(); for (std::uint32_t index = 0; index < nativesNum; ++index) @@ -113,106 +114,7 @@ namespace SPExt return m_pluginMngr; } - int Plugin::getProxiedParamAsInt(std::size_t index) const - { - try - { - return m_proxiedParams.at(index); - } - catch (const std::out_of_range &e) - { - (void)e; - return 0; - } - } - - int *Plugin::getProxiedParamAsIntAddr(std::size_t index) const - { - try - { - cell_t *result; - cell_t address = m_proxiedParams.at(index); - m_proxyContext->LocalToPhysAddr(address, &result); - - return result; - } - catch (const std::out_of_range &e) - { - (void)e; - return nullptr; - } - } - - float Plugin::getProxiedParamAsFloat(std::size_t index) const - { - try - { - return sp_ctof(m_proxiedParams.at(index)); - } - catch (const std::out_of_range &e) - { - (void)e; - return 0; - } - } - - float *Plugin::getProxiedParamAsFloatAddr(std::size_t index) const - { - try - { - cell_t *result; - cell_t address = m_proxiedParams.at(index); - m_proxyContext->LocalToPhysAddr(address, &result); - - return reinterpret_cast(result); - } - catch (const std::out_of_range &e) - { - (void)e; - return nullptr; - } - } - - char *Plugin::getProxiedParamAsString(std::size_t index) const - { - try - { - char *result; - cell_t address = m_proxiedParams.at(index); - m_proxyContext->LocalToString(address, &result); - - return result; - } - catch (const std::out_of_range &e) - { - (void)e; - return nullptr; - } - } - - void *Plugin::getProxiedParamAsArray(std::size_t index) const - { - try - { - cell_t *result; - cell_t address = m_proxiedParams.at(index); - m_proxyContext->LocalToPhysAddr(address, &result); - - return result; - } - catch (const std::out_of_range &e) - { - (void)e; - return nullptr; - } - } - // Plugin - void Plugin::setProxyContext(SourcePawn::IPluginContext *ctx) - { - m_proxyContext = ctx; - } - std::size_t Plugin::getId() const { return m_id; @@ -223,12 +125,6 @@ namespace SPExt return m_runtime; } - void Plugin::setProxyParams(const cell_t *params) - { - for (std::size_t i = 0; i <= static_cast(params[0]); i++) - m_proxiedParams[i] = params[i]; - } - Plugin *PluginMngr::getPlugin(std::string_view name) const { auto result = m_plugins.find(name.data()); @@ -312,7 +208,7 @@ namespace SPExt std::string errorMsg; for (const auto &entry : directoryIter) { - fs::path filePath = entry.path(); + const fs::path& filePath = entry.path(); if (!_loadPlugin(filePath, errorMsg) && !errorMsg.empty()) { gSPLogger->logToConsole(SPMod::LogLevel::Error, errorMsg); @@ -323,9 +219,9 @@ namespace SPExt void PluginMngr::bindPluginsNatives() { - for (const auto &proxiedNative : gSPNativeProxy->getProxiedNatives()) + for (const auto &[name, proxiedNative] : gSPNativeProxy->getProxiedNatives()) { - addProxiedNative(proxiedNative->getName(), proxiedNative); + addNative(proxiedNative); } for (const auto &entry : m_plugins) @@ -340,14 +236,14 @@ namespace SPExt if (pluginNative->status == SP_NATIVE_BOUND) continue; - SPVM_NATIVE_FUNC router = findNative(pluginNative->name); - if (!router) + NativeCallback *nativeCallback = findPluginNative(pluginNative->name); + if (!nativeCallback) { // TODO: At this point if native cannot be found mark plugin as not working break; } - runtime->UpdateNativeBinding(index, router, 0, nullptr); + runtime->UpdateNativeBindingObject(index, nativeCallback, 0, nullptr); } } } @@ -375,6 +271,14 @@ namespace SPExt return nullptr; } + NativeCallback *PluginMngr::findPluginNative(std::string_view name) + { + if (auto iter = m_pluginNatives.find(name.data()); iter != m_pluginNatives.end()) + return iter->second; + + return nullptr; + } + bool PluginMngr::addNatives(const sp_nativeinfo_t *natives) { while (natives->name && natives->func) @@ -388,67 +292,27 @@ namespace SPExt return true; } - bool PluginMngr::addProxiedNative(std::string_view name, SPMod::IProxiedNative *native) + void PluginMngr::addNative(SPMod::IProxiedNative *native) { - SourcePawn::ISourcePawnEngine2 *spAPIv2 = gSPAPI->getSPEnvironment()->APIv2(); - SPVM_NATIVE_FUNC router = spAPIv2->CreateFakeNative(PluginMngr::proxyNativeRouter, native); - - if (!m_natives.try_emplace(name.data(), router).second) - { - spAPIv2->DestroyFakeNative(router); - return false; - } - - m_routers.push_back(router); - return true; + m_pluginNatives.emplace(native->getName(), new NativeCallback(native)); } - cell_t PluginMngr::proxyNativeRouter(SourcePawn::IPluginContext *ctx, const cell_t *params, void *data) + bool PluginMngr::registerNative(std::string_view nativeName, SourcePawn::IPluginFunction *pluginFunc) { - if (params[0] > SP_MAX_CALL_ARGUMENTS) + auto nativeCallback = new NativeCallback(nativeName, pluginFunc); + if (!gSPNativeProxy->registerNative(nativeCallback)) { - ctx->ReportError("Too many parameters passed to native %d (max: %d)", params[0], SP_MAX_CALL_ARGUMENTS); - return 0; - } - - // TODO: Support later? - if (PluginMngr::m_callerPlugin) - { - ctx->ReportError("Cannot call another plugin native in native callback"); - return 0; + return false; } - Plugin *caller = gAdapterInterface->getPluginMngr()->getPlugin(ctx); - caller->setProxyContext(ctx); - caller->setProxyParams(params); - - cell_t result = reinterpret_cast(data)->exec(caller); - - return result; - } - - int PluginMngr::proxyNativeCallback(SPMod::IProxiedNative *native, SPMod::IPlugin *plugin) - { - PluginMngr::m_callerPlugin = plugin; - - cell_t result; - auto pluginHandler = std::any_cast(native->getData()); - pluginHandler->Execute(&result); - - PluginMngr::m_callerPlugin = nullptr; - - return result; + m_pluginNatives.emplace(nativeName, nativeCallback); + return true; } void PluginMngr::clearNatives() { - SourcePawn::ISourcePawnEngine2 *spAPIv2 = gSPAPI->getSPEnvironment()->APIv2(); - - for (auto router : m_routers) - { - spAPIv2->DestroyFakeNative(router); - } m_natives.clear(); + m_pluginNatives.clear(); } void PluginMngr::addDefaultNatives() diff --git a/subprojects/sourcepawn/PluginSystem.hpp b/subprojects/sourcepawn/PluginSystem.hpp index 19ad9da1..b91e048d 100644 --- a/subprojects/sourcepawn/PluginSystem.hpp +++ b/subprojects/sourcepawn/PluginSystem.hpp @@ -46,18 +46,10 @@ namespace SPExt std::string_view getIdentity() const override; std::string_view getFilename() const override; SPMod::IPluginMngr *getPluginMngr() const override; - int getProxiedParamAsInt(std::size_t index) const override; - int *getProxiedParamAsIntAddr(std::size_t index) const override; - float getProxiedParamAsFloat(std::size_t index) const override; - float *getProxiedParamAsFloatAddr(std::size_t index) const override; - char *getProxiedParamAsString(std::size_t index) const override; - void *getProxiedParamAsArray(std::size_t index) const override; // Plugin SourcePawn::IPluginRuntime *getRuntime() const; std::size_t getId() const; - void setProxyContext(SourcePawn::IPluginContext *ctx); - void setProxyParams(const cell_t *params); private: std::size_t m_id; @@ -69,8 +61,6 @@ namespace SPExt std::string m_version; std::string m_author; std::string m_url; - std::array m_proxiedParams; - SourcePawn::IPluginContext *m_proxyContext; }; class PluginMngr final : public SPMod::IPluginMngr @@ -105,13 +95,11 @@ namespace SPExt void clearNatives(); void addDefaultNatives(); SPVM_NATIVE_FUNC findNative(std::string_view name); + NativeCallback *findPluginNative(std::string_view name); // Proxied natives - int proxyNativeCallback(SPMod::IProxiedNative *native, SPMod::IPlugin *plugin) override; - bool addProxiedNative(std::string_view name, SPMod::IProxiedNative *native); - static cell_t proxyNativeRouter(SourcePawn::IPluginContext *ctx, const cell_t *params, void *data); - - static inline SPMod::IPlugin *m_callerPlugin; + void addNative(SPMod::IProxiedNative *native); + bool registerNative(std::string_view nativeName, SourcePawn::IPluginFunction *pluginFunc); private: Plugin *_loadPlugin(const fs::path &path, std::string &error); @@ -121,8 +109,6 @@ namespace SPExt std::unordered_map> m_plugins; std::vector m_exportedPlugins; std::unordered_map m_natives; - - // Routers to be freed on the map change - std::vector m_routers; + std::unordered_map m_pluginNatives; }; } // namespace SPExt