From 17bf7722c90dbdc52cb8a54a89cb774815eca03a Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Sat, 16 Nov 2024 14:53:21 +0300 Subject: [PATCH] fix before/after priority stuff --- loader/include/Geode/modify/Modify.hpp | 185 +++++++++++++++---------- loader/test/dependency/main.cpp | 32 +++++ loader/test/main/main.cpp | 2 + 3 files changed, 147 insertions(+), 72 deletions(-) diff --git a/loader/include/Geode/modify/Modify.hpp b/loader/include/Geode/modify/Modify.hpp index 650e6fc8..b58d2e73 100644 --- a/loader/include/Geode/modify/Modify.hpp +++ b/loader/include/Geode/modify/Modify.hpp @@ -145,18 +145,19 @@ namespace geode::modifier { /// @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()) { + Result getHook(std::string_view name) { + auto key = std::string(name); + if (m_hooks.find(key) == m_hooks.end()) { return Err("Hook not in this modify"); } - return Ok(m_hooks[name].get()); + return Ok(m_hooks[key].get()); } /// @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) { + Result<> setHookPriority(std::string_view name, int32_t priority = Priority::Normal) { GEODE_UNWRAP_INTO(auto hook, this->getHook(name)); hook->setPriority(priority); return Ok(); @@ -166,7 +167,7 @@ namespace geode::modifier { /// @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) { + Result<> setHookPriorityPre(std::string_view name, int32_t priority = Priority::Normal) { return this->setHookPriority(name, priority); } @@ -174,104 +175,144 @@ namespace geode::modifier { /// @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) { + Result<> setHookPriorityPost(std::string_view 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 + /// @param after The mod 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) { + Result<> setHookPriorityAfter(std::string_view name, Mod* mod) { GEODE_UNWRAP_INTO(auto hook, this->getHook(name)); - ([&](){ - auto mod = Loader::get()->getInstalledMod(after); - if (!mod) return; + auto func = [=](ModStateEvent* event){ auto hooks = mod->getHooks(); - auto func = [=](){ - for (auto modHook : hooks) { - if (modHook->getAddress() != hook->getAddress()) continue; - auto priority = hook->getPriority(); - if (priority < modHook->getPriority()) { - hook->setPriority(modHook->getPriority() + 1); - } + for (auto modHook : hooks) { + if (modHook->getAddress() != hook->getAddress()) continue; + auto priority = modHook->getPriority(); + if (hook->getPriority() <= priority) { + hook->setPriority(priority + 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) { - GEODE_UNWRAP_INTO(auto hook, this->getHook(name)); - ([&](){ - 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 > modHook->getPriority()) { - hook->setPriority(modHook->getPriority() - 1); - } - } - }; - if (Loader::get()->isModLoaded(mod)) { - func(); - } - else { - new EventListener(func, ModStateFilter(mod, ModEventType::Loaded)); - } - } (), ...); + return ListenerResult::Propagate; + }; + if (mod->isEnabled()) { + func(nullptr); + } + 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 + /// @param after The mod id of the mod 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)...); + Result<> setHookPriorityAfter(std::string_view name, std::string_view after) { + auto mod = Loader::get()->getInstalledMod(std::string(after)); + if (!mod) return Err("Mod not found"); + return this->setHookPriorityAfter(name, mod); } /// @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 + /// @param before The mod 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)...); + Result<> setHookPriorityBefore(std::string_view name, Mod* mod) { + GEODE_UNWRAP_INTO(auto hook, this->getHook(name)); + auto func = [=](ModStateEvent* event){ + auto hooks = mod->getHooks(); + for (auto modHook : hooks) { + if (modHook->getAddress() != hook->getAddress()) continue; + auto priority = modHook->getPriority(); + if (hook->getPriority() >= priority) { + hook->setPriority(priority - 1); + } + } + return ListenerResult::Propagate; + }; + if (mod->isEnabled()) { + func(nullptr); + } + 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 id of the mod to set the priority before + /// @returns Ok if the hook was found and the priority was set, Err if the hook was not found + Result<> setHookPriorityBefore(std::string_view name, std::string_view before) { + auto mod = Loader::get()->getInstalledMod(std::string(before)); + if (!mod) return Err("Mod not found"); + return this->setHookPriorityBefore(name, mod); } /// @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 + /// @param after The mod id of the mod 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)...); + Result<> setHookPriorityAfterPre(std::string_view name, std::string_view after) { + return this->setHookPriorityAfter(name, after); + } + + /// @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 before The mod to set the priority after + /// @returns Ok if the hook was found and the priority was set, Err if the hook was not found + Result<> setHookPriorityAfterPre(std::string_view name, Mod* mod) { + return this->setHookPriorityAfter(name, mod); } /// @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 + /// @param before The mod id of the mod 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)...); + Result<> setHookPriorityBeforePre(std::string_view name, std::string_view before) { + return this->setHookPriorityBefore(name, CERT_NOT_BEFORE_FILETIME_PROP_ID); + } + + /// @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 to set the priority before + /// @returns Ok if the hook was found and the priority was set, Err if the hook was not found + Result<> setHookPriorityBeforePre(std::string_view name, Mod* mod) { + return this->setHookPriorityBefore(name, mod); + } + + /// @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 id of the mod to set the priority after + /// @returns Ok if the hook was found and the priority was set, Err if the hook was not found + Result<> setHookPriorityAfterPost(std::string_view name, std::string_view after) { + return this->setHookPriorityBefore(name, after); + } + + /// @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 before The mod to set the priority after + /// @returns Ok if the hook was found and the priority was set, Err if the hook was not found + Result<> setHookPriorityAfterPost(std::string_view name, Mod* mod) { + return this->setHookPriorityBefore(name, mod); + } + + /// @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 id of the mod to set the priority before + /// @returns Ok if the hook was found and the priority was set, Err if the hook was not found + Result<> setHookPriorityBeforePost(std::string_view name, std::string_view before) { + return this->setHookPriorityAfter(name, before); + } + + /// @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 to set the priority before + /// @returns Ok if the hook was found and the priority was set, Err if the hook was not found + Result<> setHookPriorityBeforePost(std::string_view name, Mod* mod) { + return this->setHookPriorityAfter(name, mod); } // unordered_map idea diff --git a/loader/test/dependency/main.cpp b/loader/test/dependency/main.cpp index caafb23a..daf8ddf1 100644 --- a/loader/test/dependency/main.cpp +++ b/loader/test/dependency/main.cpp @@ -160,6 +160,38 @@ struct MyMenuLayer : Modify { } }; +struct AfterMenuLayer : Modify { + static void onModify(auto& self) { + if (self.setHookPriorityAfterPost("MenuLayer::init", "geode.test")) { + log::debug("priority set after test"); + } + } + + bool init() { + if (!MenuLayer::init()) return false; + + log::debug("should run third!"); + + return true; + } +}; + +struct BeforeMenuLayer : Modify { + static void onModify(auto& self) { + if (self.setHookPriorityBeforePost("MenuLayer::init", "geode.test")) { + log::debug("priority set before test"); + } + } + + bool init() { + if (!MenuLayer::init()) return false; + + log::debug("should run first!"); + + return true; + } +}; + $on_mod(Loaded) { // Mod::get()->addCustomSetting("overcast-skies", DEFAULT_ICON); diff --git a/loader/test/main/main.cpp b/loader/test/main/main.cpp index 578bd210..102f720f 100644 --- a/loader/test/main/main.cpp +++ b/loader/test/main/main.cpp @@ -58,6 +58,8 @@ struct $modify(MenuLayer) { log::info("Loader flag 'bool-arg': {}", Loader::get()->getLaunchFlag("bool-arg")); log::info("Loader int 'int-arg': {}", Loader::get()->parseLaunchArgument("int-arg").unwrapOr(0)); + log::debug("should run second!"); + return true; } };