fix before/after priority stuff

This commit is contained in:
altalk23 2024-11-16 14:53:21 +03:00
parent 22210956bb
commit 17bf7722c9
3 changed files with 147 additions and 72 deletions

View file

@ -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<Hook*> getHook(std::string const& name) {
if (m_hooks.find(name) == m_hooks.end()) {
Result<Hook*> 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<class... C> requires (std::is_convertible_v<C, std::string> && ...)
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<class... C> requires (std::is_convertible_v<C, std::string> && ...)
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<class... C> requires (std::is_convertible_v<C, std::string> && ...)
Result<> setHookPriorityAfterPre(std::string const& name, C&&... after) {
return this->setHookPriorityAfter(name, Priority::NormalPre, std::forward<C>(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<class... C> requires (std::is_convertible_v<C, std::string> && ...)
Result<> setHookPriorityBeforePre(std::string const& name, C&&... before) {
return this->setHookPriorityBefore(name, Priority::NormalPre, std::forward<C>(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<class... C> requires (std::is_convertible_v<C, std::string> && ...)
Result<> setHookPriorityAfterPost(std::string const& name, C&&... after) {
return this->setHookPriorityBefore(name, Priority::NormalPost, std::forward<C>(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<class... C> requires (std::is_convertible_v<C, std::string> && ...)
Result<> setHookPriorityBeforePost(std::string const& name, C&&... before) {
return this->setHookPriorityAfter(name, Priority::NormalPost, std::forward<C>(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<handles> idea

View file

@ -160,6 +160,38 @@ struct MyMenuLayer : Modify<MyMenuLayer, MenuLayer> {
}
};
struct AfterMenuLayer : Modify<AfterMenuLayer, MenuLayer> {
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<BeforeMenuLayer, MenuLayer> {
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<MySettingValue>("overcast-skies", DEFAULT_ICON);

View file

@ -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>("int-arg").unwrapOr(0));
log::debug("should run second!");
return true;
}
};