diff --git a/loader/include/Geode/loader/Hook.hpp b/loader/include/Geode/loader/Hook.hpp index da6e42e6..1f79e9c6 100644 --- a/loader/include/Geode/loader/Hook.hpp +++ b/loader/include/Geode/loader/Hook.hpp @@ -16,13 +16,14 @@ namespace geode { private: class Impl; std::shared_ptr<Impl> m_impl; - explicit Hook(std::shared_ptr<Impl>&& impl); ~Hook(); friend class Mod; friend class Loader; public: + explicit Hook(std::shared_ptr<Impl>&& impl); + /** * Create a hook at an address. The hook is enabled immediately. By * default, the hook is placed at the end of the detour list; however, @@ -37,7 +38,7 @@ namespace geode { * @returns The created hook, or an error. Make sure to add the created * hook to the mod that owns it using mod->claimHook! */ - static Hook* create( + static std::shared_ptr<Hook> create( void* address, void* detour, std::string const& displayName, @@ -46,7 +47,7 @@ namespace geode { ); template<class DetourType> - static Hook* create( + static std::shared_ptr<Hook> create( void* address, DetourType detour, std::string const& displayName, @@ -144,14 +145,15 @@ namespace geode { private: class Impl; std::shared_ptr<Impl> m_impl; - explicit Patch(std::shared_ptr<Impl>&& impl); ~Patch(); friend class Mod; friend class Loader; public: - static Patch* create(void* address, const ByteVector& patch); + explicit Patch(std::shared_ptr<Impl>&& impl); + + static std::shared_ptr<Patch> create(void* address, const ByteVector& patch); Patch(Patch const&) = delete; Patch operator=(Patch const&) = delete; diff --git a/loader/include/Geode/loader/Mod.hpp b/loader/include/Geode/loader/Mod.hpp index 82320363..14aa1959 100644 --- a/loader/include/Geode/loader/Mod.hpp +++ b/loader/include/Geode/loader/Mod.hpp @@ -251,8 +251,8 @@ namespace geode { tulip::hook::HookMetadata const& hookMetadata = tulip::hook::HookMetadata() ) { auto hook = Hook::create(address, detour, displayName, convention, hookMetadata); - GEODE_UNWRAP(this->claimHook(hook)); - return Ok(hook); + GEODE_UNWRAP_INTO(auto ptr, this->claimHook(std::move(hook))); + return Ok(ptr); } Result<Hook*> hook( @@ -261,11 +261,11 @@ namespace geode { tulip::hook::HookMetadata const& hookMetadata ) { auto hook = Hook::create(address, detour, displayName, handlerMetadata, hookMetadata); - GEODE_UNWRAP(this->claimHook(hook)); - return Ok(hook); + GEODE_UNWRAP_INTO(auto ptr, this->claimHook(std::move(hook))); + return Ok(ptr); } - Result<> claimHook(Hook* hook); + Result<Hook*> claimHook(std::shared_ptr<Hook>&& hook); Result<> disownHook(Hook* hook); @@ -284,11 +284,11 @@ namespace geode { */ Result<Patch*> patch(void* address, ByteVector const& data) { auto patch = Patch::create(address, data); - GEODE_UNWRAP(this->claimPatch(patch)); - return Ok(patch); + GEODE_UNWRAP_INTO(auto ptr, this->claimPatch(std::move(patch))); + return Ok(ptr); } - Result<> claimPatch(Patch* patch); + Result<Patch*> claimPatch(std::shared_ptr<Patch>&& patch); Result<> disownPatch(Patch* patch); diff --git a/loader/include/Geode/modify/Modify.hpp b/loader/include/Geode/modify/Modify.hpp index 504d2988..32e27459 100644 --- a/loader/include/Geode/modify/Modify.hpp +++ b/loader/include/Geode/modify/Modify.hpp @@ -70,13 +70,13 @@ namespace geode::modifier { template <class ModifyDerived> class ModifyBase { public: - std::map<std::string, Hook*> m_hooks; + std::map<std::string, std::shared_ptr<Hook>> m_hooks; Result<Hook*> getHook(std::string const& name) { if (m_hooks.find(name) == m_hooks.end()) { return Err("Hook not in this modify"); } - return Ok(m_hooks[name]); + return Ok(m_hooks[name].get()); } Result<> setHookPriority(std::string const& name, int32_t priority) { @@ -94,11 +94,18 @@ namespace geode::modifier { auto test = static_cast<ModifyDerived*>(this); test->ModifyDerived::apply(); ModifyDerived::Derived::onModify(*this); + std::vector<std::string> added; for (auto& [uuid, hook] : m_hooks) { - auto res = Mod::get()->claimHook(hook); + auto res = Mod::get()->claimHook(std::move(hook)); if (!res) { log::error("Failed to claim hook {}: {}", hook->getDisplayName(), res.error()); } + else { + added.push_back(uuid); + } + } + for (auto& uuid : added) { + m_hooks.erase(uuid); } } diff --git a/loader/include/Geode/utils/ObjcHook.hpp b/loader/include/Geode/utils/ObjcHook.hpp index 7e156777..ec52ae4f 100644 --- a/loader/include/Geode/utils/ObjcHook.hpp +++ b/loader/include/Geode/utils/ObjcHook.hpp @@ -35,7 +35,7 @@ namespace geode { * @returns The created hook, or an error. */ template <class Func> - static Result<Hook*> create(std::string const& className, std::string const& selectorName, Func function, tulip::hook::HookMetadata const& metadata = tulip::hook::HookMetadata()) { + static Result<std::shared_ptr<Hook>> create(std::string const& className, std::string const& selectorName, Func function, tulip::hook::HookMetadata const& metadata = tulip::hook::HookMetadata()) { GEODE_UNWRAP_INTO(auto imp, geode::hook::getObjcMethodImp(className, selectorName)); return Ok(Hook::create( @@ -59,7 +59,7 @@ namespace geode { * @returns The created hook, or an error. */ template <class Func> - static Result<Hook*> create(std::string const& className, std::string const& selectorName, Func function, void(*empty)(), tulip::hook::HookMetadata const& metadata = tulip::hook::HookMetadata()) { + static Result<std::shared_ptr<Hook>> create(std::string const& className, std::string const& selectorName, Func function, void(*empty)(), tulip::hook::HookMetadata const& metadata = tulip::hook::HookMetadata()) { GEODE_UNWRAP(geode::hook::addObjcMethod(className, selectorName, (void*)empty)); return ObjcHook::create(className, selectorName, function, metadata); diff --git a/loader/src/loader/Hook.cpp b/loader/src/loader/Hook.cpp index 376b231f..ae0d6239 100644 --- a/loader/src/loader/Hook.cpp +++ b/loader/src/loader/Hook.cpp @@ -6,7 +6,7 @@ using namespace geode::prelude; Hook::Hook(std::shared_ptr<Impl>&& impl) : m_impl(std::move(impl)) { m_impl->m_self = this; } Hook::~Hook() = default; -Hook* Hook::create( +std::shared_ptr<Hook> Hook::create( void* address, void* detour, std::string const& displayName, diff --git a/loader/src/loader/HookImpl.cpp b/loader/src/loader/HookImpl.cpp index 2fab7464..558a1756 100644 --- a/loader/src/loader/HookImpl.cpp +++ b/loader/src/loader/HookImpl.cpp @@ -29,7 +29,7 @@ Hook::Impl::~Impl() { } } -Hook* Hook::Impl::create( +std::shared_ptr<Hook> Hook::Impl::create( void* address, void* detour, std::string const& displayName, @@ -39,7 +39,9 @@ Hook* Hook::Impl::create( auto impl = std::make_shared<Impl>( address, detour, displayName, handlerMetadata, hookMetadata ); - return new Hook(std::move(impl)); + return std::shared_ptr<Hook>(new Hook(std::move(impl)), [](Hook* hook) { + delete hook; + }); } Result<> Hook::Impl::enable() { diff --git a/loader/src/loader/HookImpl.hpp b/loader/src/loader/HookImpl.hpp index e9258ac0..3dbf8cdd 100644 --- a/loader/src/loader/HookImpl.hpp +++ b/loader/src/loader/HookImpl.hpp @@ -22,7 +22,7 @@ public: ); ~Impl(); - static Hook* create( + static std::shared_ptr<Hook> create( void* address, void* detour, std::string const& displayName, @@ -31,7 +31,7 @@ public: ); template<class DetourType> - static Hook* create( + static std::shared_ptr<Hook> create( void* address, DetourType detour, std::string const& displayName, diff --git a/loader/src/loader/Mod.cpp b/loader/src/loader/Mod.cpp index 1617d537..0e93d85b 100644 --- a/loader/src/loader/Mod.cpp +++ b/loader/src/loader/Mod.cpp @@ -121,8 +121,8 @@ void Mod::registerCustomSetting(std::string_view const key, std::unique_ptr<Sett return m_impl->registerCustomSetting(key, std::move(value)); } -Result<> Mod::claimHook(Hook* hook) { - return m_impl->claimHook(hook); +Result<Hook*> Mod::claimHook(std::shared_ptr<Hook>&& hook) { + return m_impl->claimHook(std::move(hook)); } Result<> Mod::disownHook(Hook* hook) { @@ -133,8 +133,8 @@ std::vector<Hook*> Mod::getHooks() const { return m_impl->getHooks(); } -Result<> Mod::claimPatch(Patch* patch) { - return m_impl->claimPatch(patch); +Result<Patch*> Mod::claimPatch(std::shared_ptr<Patch>&& patch) { + return m_impl->claimPatch(std::move(patch)); } Result<> Mod::disownPatch(Patch* patch) { diff --git a/loader/src/loader/ModImpl.cpp b/loader/src/loader/ModImpl.cpp index 6b87660d..363e2438 100644 --- a/loader/src/loader/ModImpl.cpp +++ b/loader/src/loader/ModImpl.cpp @@ -132,11 +132,19 @@ bool Mod::Impl::needsEarlyLoad() const { } std::vector<Hook*> Mod::Impl::getHooks() const { - return m_hooks; + std::vector<Hook*> ret; + for (auto& hook : m_hooks) { + ret.push_back(hook.get()); + } + return ret; } std::vector<Patch*> Mod::Impl::getPatches() const { - return m_patches; + std::vector<Patch*> ret; + for (auto& patch : m_patches) { + ret.push_back(patch.get()); + } + return ret; } // Settings and saved values @@ -441,27 +449,30 @@ bool Mod::Impl::depends(std::string_view const id) const { // Hooks -Result<> Mod::Impl::claimHook(Hook* hook) { +Result<Hook*> Mod::Impl::claimHook(std::shared_ptr<Hook>&& hook) { auto res1 = hook->m_impl->setOwner(m_self); if (!res1) { return Err("Cannot claim hook: {}", res1.unwrapErr()); } - m_hooks.push_back(hook); + auto ptr = hook.get(); + m_hooks.push_back(std::move(hook)); if (!this->isEnabled() || !hook->getAutoEnable()) - return Ok(); + return Ok(ptr); if (!LoaderImpl::get()->isReadyToHook()) { - LoaderImpl::get()->addUninitializedHook(hook, m_self); - return Ok(); + LoaderImpl::get()->addUninitializedHook(ptr, m_self); + return Ok(ptr); } - auto res2 = hook->enable(); + auto res2 = ptr->enable(); if (!res2) { return Err("Cannot enable hook: {}", res2.unwrapErr()); } - return Ok(); + + + return Ok(ptr); } Result<> Mod::Impl::disownHook(Hook* hook) { @@ -473,7 +484,9 @@ Result<> Mod::Impl::disownHook(Hook* hook) { if (!res1) { return Err("Cannot disown hook: {}", res1.unwrapErr()); } - m_hooks.erase(std::find(m_hooks.begin(), m_hooks.end(), hook)); + m_hooks.erase(std::find_if(m_hooks.begin(), m_hooks.end(), [&](auto& a) { + return a.get() == hook; + })); if (!this->isEnabled() || !hook->getAutoEnable()) return Ok(); @@ -488,22 +501,23 @@ Result<> Mod::Impl::disownHook(Hook* hook) { // Patches -Result<> Mod::Impl::claimPatch(Patch* patch) { +Result<Patch*> Mod::Impl::claimPatch(std::shared_ptr<Patch>&& patch) { auto res1 = patch->m_impl->setOwner(m_self); if (!res1) { return Err("Cannot claim patch: {}", res1.unwrapErr()); } - m_patches.push_back(patch); + auto ptr = patch.get(); + m_patches.push_back(std::move(patch)); if (!this->isEnabled() || !patch->getAutoEnable()) - return Ok(); + return Ok(ptr); - auto res2 = patch->enable(); + auto res2 = ptr->enable(); if (!res2) { return Err("Cannot enable patch: {}", res2.unwrapErr()); } - return Ok(); + return Ok(ptr); } Result<> Mod::Impl::disownPatch(Patch* patch) { @@ -515,7 +529,9 @@ Result<> Mod::Impl::disownPatch(Patch* patch) { if (!res1) { return Err("Cannot disown patch: {}", res1.unwrapErr()); } - m_patches.erase(std::find(m_patches.begin(), m_patches.end(), patch)); + m_patches.erase(std::find_if(m_patches.begin(), m_patches.end(), [&](auto& a) { + return a.get() == patch; + })); if (!this->isEnabled() || !patch->getAutoEnable()) return Ok(); diff --git a/loader/src/loader/ModImpl.hpp b/loader/src/loader/ModImpl.hpp index 4378aea5..335b054f 100644 --- a/loader/src/loader/ModImpl.hpp +++ b/loader/src/loader/ModImpl.hpp @@ -18,11 +18,11 @@ namespace geode { /** * Hooks owned by this mod */ - std::vector<Hook*> m_hooks; + std::vector<std::shared_ptr<Hook>> m_hooks; /** * Patches owned by this mod */ - std::vector<Patch*> m_patches; + std::vector<std::shared_ptr<Patch>> m_patches; /** * Whether the mod is enabled or not */ @@ -113,11 +113,11 @@ namespace geode { SettingValue* getSetting(std::string_view const key) const; void registerCustomSetting(std::string_view const key, std::unique_ptr<SettingValue> value); - Result<> claimHook(Hook* hook); + Result<Hook*> claimHook(std::shared_ptr<Hook>&& hook); Result<> disownHook(Hook* hook); [[nodiscard]] std::vector<Hook*> getHooks() const; - Result<> claimPatch(Patch* patch); + Result<Patch*> claimPatch(std::shared_ptr<Patch>&& patch); Result<> disownPatch(Patch* patch); [[nodiscard]] std::vector<Patch*> getPatches() const; diff --git a/loader/src/loader/Patch.cpp b/loader/src/loader/Patch.cpp index 180d7368..15471c95 100644 --- a/loader/src/loader/Patch.cpp +++ b/loader/src/loader/Patch.cpp @@ -6,7 +6,7 @@ using namespace geode::prelude; Patch::Patch(std::shared_ptr<Impl>&& impl) : m_impl(std::move(impl)) { m_impl->m_self = this; } Patch::~Patch() = default; -Patch* Patch::create(void* address, const ByteVector& patch) { +std::shared_ptr<Patch> Patch::create(void* address, const ByteVector& patch) { return Impl::create(address, patch); } diff --git a/loader/src/loader/PatchImpl.cpp b/loader/src/loader/PatchImpl.cpp index db571b98..d38defda 100644 --- a/loader/src/loader/PatchImpl.cpp +++ b/loader/src/loader/PatchImpl.cpp @@ -31,11 +31,13 @@ static ByteVector readMemory(void* address, size_t amount) { return ret; } -Patch* Patch::Impl::create(void* address, const geode::ByteVector& patch) { +std::shared_ptr<Patch> Patch::Impl::create(void* address, const geode::ByteVector& patch) { auto impl = std::make_shared<Impl>( address, readMemory(address, patch.size()), patch ); - return new Patch(std::move(impl)); + return std::shared_ptr<Patch>(new Patch(std::move(impl)), [](Patch* patch) { + delete patch; + }); } Result<> Patch::Impl::enable() { diff --git a/loader/src/loader/PatchImpl.hpp b/loader/src/loader/PatchImpl.hpp index 522284f6..67ce4207 100644 --- a/loader/src/loader/PatchImpl.hpp +++ b/loader/src/loader/PatchImpl.hpp @@ -13,7 +13,7 @@ public: Impl(void* address, ByteVector original, ByteVector patch); ~Impl(); - static Patch* create(void* address, const ByteVector& patch); + static std::shared_ptr<Patch> create(void* address, const ByteVector& patch); Patch* m_self = nullptr; void* m_address;