From 673317d3cb1fd5ee85b5a7bb1fe476f3f48b5f11 Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Mon, 11 Nov 2024 22:38:03 +0300 Subject: [PATCH] hook priority changes with pre/post and Priority class for static priority values --- loader/include/Geode/modify/Modify.hpp | 161 ++++++++++++++++++++++++- loader/include/Geode/utils/NodeIDs.hpp | 4 +- 2 files changed, 161 insertions(+), 4 deletions(-) diff --git a/loader/include/Geode/modify/Modify.hpp b/loader/include/Geode/modify/Modify.hpp index a81ec8c4..392ea11f 100644 --- a/loader/include/Geode/modify/Modify.hpp +++ b/loader/include/Geode/modify/Modify.hpp @@ -104,8 +104,36 @@ } \ } while (0); -namespace geode::modifier { +namespace geode { + class Priority { + public: + static inline constexpr int32_t First = -3000; + static inline constexpr int32_t VeryEarly = -2000; + static inline constexpr int32_t Early = -1000; + static inline constexpr int32_t Normal = 0; + static inline constexpr int32_t Late = 1000; + static inline constexpr int32_t VeryLate = 2000; + static inline constexpr int32_t Last = 3000; + static inline constexpr int32_t FirstPre = First; + static inline constexpr int32_t VeryEarlyPre = VeryEarly; + static inline constexpr int32_t EarlyPre = Early; + static inline constexpr int32_t NormalPre = Normal; + static inline constexpr int32_t LatePre = Late; + static inline constexpr int32_t VeryLatePre = VeryLate; + static inline constexpr int32_t LastPre = Last; + + static inline constexpr int32_t FirstPost = Last; + static inline constexpr int32_t VeryEarlyPost = VeryLate; + static inline constexpr int32_t EarlyPost = Late; + static inline constexpr int32_t NormalPost = Normal; + static inline constexpr int32_t LatePost = Early; + static inline constexpr int32_t VeryLatePost = VeryEarly; + static inline constexpr int32_t LastPost = First; + }; +} + +namespace geode::modifier { template class ModifyDerive; @@ -114,6 +142,9 @@ namespace geode::modifier { public: std::map> m_hooks; + /// @brief Get a hook by name + /// @param name The name of the hook to get + /// @returns Ok if the hook was found, Err if the hook was not found Result getHook(std::string const& name) { if (m_hooks.find(name) == m_hooks.end()) { return Err("Hook not in this modify"); @@ -121,15 +152,139 @@ namespace geode::modifier { return Ok(m_hooks[name].get()); } - Result<> setHookPriority(std::string const& name, int32_t priority) { + /// @brief Set the priority of a hook + /// @param name The name of the hook to set the priority of + /// @param priority The priority to set the hook to + /// @returns Ok if the hook was found and the priority was set, Err if the hook was not found + Result<> setHookPriority(std::string const& name, int32_t priority = Priority::Normal) { auto res = this->getHook(name); if (!res) { - return Err(res.unwrapErr()); + return Err(std::move(res).unwrapErr()); } res.unwrap()->setPriority(priority); return Ok(); } + /// @brief Set the priority of a hook + /// @param name The name of the hook to set the priority of + /// @param priority The priority to set the hook to + /// @returns Ok if the hook was found and the priority was set, Err if the hook was not found + Result<> setHookPriorityPre(std::string const& name, int32_t priority = Priority::Normal) { + return this->setHookPriority(name, priority); + } + + /// @brief Set the priority of a hook + /// @param name The name of the hook to set the priority of + /// @param priority The priority to set the hook to + /// @returns Ok if the hook was found and the priority was set, Err if the hook was not found + Result<> setHookPriorityPost(std::string const& name, int32_t priority = Priority::Normal) { + return this->setHookPriority(name, -priority); + } + + /// @brief Set the priority of a hook to be after another hook in different mods + /// @param name The name of the hook to set the priority of + /// @param after The mod ids of the mods to set the priority after + /// @returns Ok if the hook was found and the priority was set, Err if the hook was not found + template requires (std::is_convertible_v && ...) + Result<> setHookPriorityAfter(std::string const& name, C&&... after) { + auto res = this->getHook(name); + if (!res) { + return Err(std::move(res).unwrapErr()); + } + auto hook = std::move(res).unwrap(); + ([&](){ + auto mod = Loader::get()->getInstalledMod(after); + if (!mod) return; + auto hooks = mod->getHooks(); + auto func = [=](){ + for (auto modHook : hooks) { + if (modHook->getAddress() != hook->getAddress()) continue; + auto priority = hook->getPriority(); + if (priority < mod->getPriority()) { + hook->setPriority(mod->getPriority() + 1); + } + } + }; + if (Loader::get()->isModLoaded(mod)) { + func(); + } + else { + new EventListener(func, ModStateFilter(mod, ModEventType::Loaded)); + } + } (), ...); + return Ok(); + } + + /// @brief Set the priority of a hook to be before another hook in different mods + /// @param name The name of the hook to set the priority of + /// @param before The mod ids of the mods to set the priority before + /// @returns Ok if the hook was found and the priority was set, Err if the hook was not found + template requires (std::is_convertible_v && ...) + Result<> setHookPriorityBefore(std::string const& name, C&&... before) { + auto res = this->getHook(name); + if (!res) { + return Err(std::move(res).unwrapErr()); + } + auto hook = std::move(res).unwrap(); + ([&](){ + auto mod = Loader::get()->getInstalledMod(before); + if (!mod) return; + auto hooks = mod->getHooks(); + auto func = [=](){ + for (auto modHook : hooks) { + if (modHook->getAddress() != hook->getAddress()) continue; + auto priority = hook->getPriority(); + if (priority > mod->getPriority()) { + hook->setPriority(mod->getPriority() - 1); + } + } + }; + if (Loader::get()->isModLoaded(mod)) { + func(); + } + else { + new EventListener(func, ModStateFilter(mod, ModEventType::Loaded)); + } + } (), ...); + return Ok(); + } + + /// @brief Set the priority of a hook to be after another hook in different mods + /// @param name The name of the hook to set the priority of + /// @param after The mod ids of the mods to set the priority after + /// @returns Ok if the hook was found and the priority was set, Err if the hook was not found + template requires (std::is_convertible_v && ...) + Result<> setHookPriorityAfterPre(std::string const& name, C&&... after) { + return this->setHookPriorityAfter(name, Priority::NormalPre, std::forward(after)...); + } + + /// @brief Set the priority of a hook to be before another hook in different mods + /// @param name The name of the hook to set the priority of + /// @param before The mod ids of the mods to set the priority before + /// @returns Ok if the hook was found and the priority was set, Err if the hook was not found + template requires (std::is_convertible_v && ...) + Result<> setHookPriorityBeforePre(std::string const& name, C&&... before) { + return this->setHookPriorityBefore(name, Priority::NormalPre, std::forward(before)...); + } + + /// @brief Set the priority of a hook to be after another hook in different mods + /// @param name The name of the hook to set the priority of + /// @param after The mod ids of the mods to set the priority after + /// @returns Ok if the hook was found and the priority was set, Err if the hook was not found + template requires (std::is_convertible_v && ...) + Result<> setHookPriorityAfterPost(std::string const& name, C&&... after) { + return this->setHookPriorityBefore(name, Priority::NormalPost, std::forward(after)...); + } + + /// @brief Set the priority of a hook to be before another hook in different mods + /// @param name The name of the hook to set the priority of + /// @param before The mod ids of the mods to set the priority before + /// @returns Ok if the hook was found and the priority was set, Err if the hook was not found + template requires (std::is_convertible_v && ...) + Result<> setHookPriorityBeforePost(std::string const& name, C&&... before) { + return this->setHookPriorityAfter(name, Priority::NormalPost, std::forward(before)...); + } + // unordered_map idea ModifyBase() { struct EboCheck : ModifyDerived::Base { diff --git a/loader/include/Geode/utils/NodeIDs.hpp b/loader/include/Geode/utils/NodeIDs.hpp index b2fad89f..8b22d8a2 100644 --- a/loader/include/Geode/utils/NodeIDs.hpp +++ b/loader/include/Geode/utils/NodeIDs.hpp @@ -1,9 +1,11 @@ +#pragma once +#include #include "cocos.hpp" namespace geode::node_ids { using namespace cocos2d; - static constexpr int32_t GEODE_ID_PRIORITY = 0x100000; + static constexpr int32_t GEODE_ID_PRIORITY = Priority::VeryEarlyPost; template requires std::is_base_of_v