diff --git a/entry.cpp b/entry.cpp index d51a4324..6babddc3 100644 --- a/entry.cpp +++ b/entry.cpp @@ -3,6 +3,8 @@ #include GEODE_API bool GEODE_CALL geode_implicit_load(geode::Mod* m) { - geode::Interface::get()->init(m); + geode::Mod::setSharedMod(m); + geode::log::releaseSchedules(m); + geode::Loader::get()->releaseScheduledFunctions(m); return true; } diff --git a/loader/include/Geode/Bindings.hpp b/loader/include/Geode/Bindings.hpp index 37dc0116..0a03fbc3 100644 --- a/loader/include/Geode/Bindings.hpp +++ b/loader/include/Geode/Bindings.hpp @@ -11,7 +11,6 @@ #include #include #include -//#include #include #include #include diff --git a/loader/include/Geode/Loader.hpp b/loader/include/Geode/Loader.hpp index fbb5e04f..4188f163 100644 --- a/loader/include/Geode/Loader.hpp +++ b/loader/include/Geode/Loader.hpp @@ -5,6 +5,5 @@ #include "loader/Log.hpp" #include "loader/Mod.hpp" #include "loader/Loader.hpp" -#include "loader/Interface.hpp" #include "loader/Setting.hpp" #include "loader/SettingEvent.hpp" diff --git a/loader/include/Geode/loader/API.hpp b/loader/include/Geode/loader/API.hpp index 6f38928c..2c918bf5 100644 --- a/loader/include/Geode/loader/API.hpp +++ b/loader/include/Geode/loader/API.hpp @@ -1,6 +1,5 @@ #include "Mod.hpp" #include "Loader.hpp" -#include "Interface.hpp" #ifdef API_DECL #undef API_DECL diff --git a/loader/include/Geode/loader/Event.hpp b/loader/include/Geode/loader/Event.hpp index 8e0ec567..8054640b 100644 --- a/loader/include/Geode/loader/Event.hpp +++ b/loader/include/Geode/loader/Event.hpp @@ -3,7 +3,6 @@ #include #include #include "Mod.hpp" -#include "Interface.hpp" #include namespace geode { diff --git a/loader/include/Geode/loader/Interface.hpp b/loader/include/Geode/loader/Interface.hpp deleted file mode 100644 index dc08ae09..00000000 --- a/loader/include/Geode/loader/Interface.hpp +++ /dev/null @@ -1,120 +0,0 @@ -#pragma once - -#include -#include "Types.hpp" -#include -#include -#include "../utils/casts.hpp" -#include "../utils/Result.hpp" -#include "Mod.hpp" - -namespace geode { - class Hook; - - /** - * For developing your own mods, it is - * often convenient to be able to do things - * like create hooks using statically - * initialized global classes. - * - * At that point however, your mod has not - * yet received the Mod* to create hooks - * through. - * - * For situations like that, you can instead - * inherit from Interface to create your own - * mod interface and create hooks through that; - * calling `init` with the Mod* you receive - * from geode will automatically create all - * scheduled hooks, logs, etc. - * - * Interface also provides a handy & - * standardized way to store access to your - * Mod*; you can just define a `get` function - * and a getter for the Mod* stored in the - * Interface. - * - * @class Interface - */ - class Interface { - protected: - static GEODE_DLL Interface* create(); - - - struct ScheduledHook { - std::string m_displayName; - void* m_address; - Result(Mod::*m_addFunction)(std::string const&, void*); - }; - - using ScheduledFunction = std::function; - - Mod* m_mod = nullptr; - std::vector m_scheduledHooks; - std::vector m_scheduledFunctions; - - public: - static inline GEODE_HIDDEN Interface* get() { - static Interface* ret = create(); - return ret; - } - - [[deprecated("Use Mod::get instead")]] - static inline GEODE_HIDDEN Mod* mod() { - return Interface::get()->m_mod; - } - - GEODE_DLL void init(Mod*); - - /** - * Create a hook at an address. This function can - * be used at static initialization time, as it - * doesn't require the Mod* to be set -- it will - * create the hooks later when the Mod* is set. - * - * @param address The absolute address of - * the function to hook, i.e. gd_base + 0xXXXX - * @param detour Pointer to your detour function - * - * @returns Successful result containing the - * Hook handle (or nullptr if Mod* is not loaded - * yet), errorful result with info on error - */ - template class Convention> - Result addHook(void* address) { - return Interface::addHook("", address); - } - - /** - * The same as addHook(void*, void*), but also provides - * a display name to show it in the list of the loader. - * Mostly for internal use but if you don't like your - * hooks showing up like base + 0x123456 it can be useful - */ - template class Convention> - Result addHook(std::string const& displayName, void* address) { - if (this->m_mod) { - return this->m_mod->addHook(displayName, address); - } - this->m_scheduledHooks.push_back({ displayName, address, &Mod::addHook }); - return Ok(nullptr); - } - - GEODE_DLL void scheduleOnLoad(ScheduledFunction function); - - friend Mod* Mod::get(); - }; - - template<> - inline Mod* Mod::get() { - return Interface::get()->m_mod; - } - - inline Mod* getMod() { - return Mod::get(); - } -} - -inline const char* operator"" _spr(const char* str, size_t) { - return geode::Mod::get()->expandSpriteName(str); -} diff --git a/loader/include/Geode/loader/Loader.hpp b/loader/include/Geode/loader/Loader.hpp index 3f5dc43e..87a0f9b3 100644 --- a/loader/include/Geode/loader/Loader.hpp +++ b/loader/include/Geode/loader/Loader.hpp @@ -32,6 +32,14 @@ namespace geode { template class FieldIntermediate; } +} + +/** + * The predeclaration of the implicit entry + */ +GEODE_API bool GEODE_CALL geode_implicit_load(geode::Mod*); + +namespace geode { class GEODE_DLL Loader { public: @@ -47,7 +55,10 @@ namespace geode { }; std::unordered_map m_mods; }; + + using ScheduledFunction = std::function; + std::vector m_scheduledFunctions; std::unordered_map m_mods; std::vector m_logs; std::ofstream m_logStream; @@ -67,15 +78,18 @@ namespace geode { void updateAllDependencies(); + void releaseScheduledFunctions(Mod* mod); + friend class Mod; friend class CustomLoader; friend struct ModInfo; - private: size_t getFieldIndexForClass(size_t hash); template friend class modifier::FieldIntermediate; + + friend bool GEODE_CALL ::geode_implicit_load(Mod*); public: ~Loader(); @@ -233,7 +247,15 @@ namespace geode { * `CCScheduler::update` is called * @param func Function to run */ - void queueInGDThread(std::function func); + void queueInGDThread(ScheduledFunction func); + + /** + * Run a function when the Mod is loaded. Useful if for + * some reason you need to run some function in + * static initialization. + * @param func Function to run + */ + void scheduleOnModLoad(Mod* m, ScheduledFunction func); /** * Open the platform-specific external console (if one exists) diff --git a/loader/include/Geode/loader/Log.hpp b/loader/include/Geode/loader/Log.hpp index c5d1190c..607780e5 100644 --- a/loader/include/Geode/loader/Log.hpp +++ b/loader/include/Geode/loader/Log.hpp @@ -96,15 +96,15 @@ namespace geode { l.pushToLoader(); } - void releaseSchedules(Mod* m); + void GEODE_DLL releaseSchedules(Mod* m); template void schedule(Severity sev, Args... args) { auto m = getMod(); if (m) return log(sev, m, args...); - Log::scheduled().push_back([=](Mod* m){ - log(sev, m, args...); + Log::scheduled().push_back([=](Mod* m2){ + log(sev, m2, args...); }); } diff --git a/loader/include/Geode/loader/Mod.hpp b/loader/include/Geode/loader/Mod.hpp index 4e5bd2c5..13934913 100644 --- a/loader/include/Geode/loader/Mod.hpp +++ b/loader/include/Geode/loader/Mod.hpp @@ -17,8 +17,7 @@ class InternalLoader; class InternalMod; - -namespace geode { +namespace geode { struct PlatformInfo; class Hook; @@ -28,8 +27,16 @@ namespace geode { class Setting; class Unknown; - using unknownmemfn_t = void(Unknown::*)(); - using unknownfn_t = void(*)(); + using unknownmemfn_t = void(Unknown::*)(); + using unknownfn_t = void(*)(); +} + +/** + * The predeclaration of the implicit entry + */ +GEODE_API bool GEODE_CALL geode_implicit_load(geode::Mod*); + +namespace geode { struct Dependency { std::string m_id; @@ -197,9 +204,7 @@ namespace geode { /** * @class Mod - * Represents a Mod ingame. Inherit - * from this class to create your own - * mod interfaces. + * Represents a Mod ingame. * @abstract */ class GEODE_DLL Mod { @@ -316,6 +321,16 @@ namespace geode { friend struct ModInfo; friend class DataStore; + template + static inline GEODE_HIDDEN Mod* sharedMod = nullptr; + + template + static inline GEODE_HIDDEN void setSharedMod(Mod* mod) { + sharedMod<> = mod; + } + + friend bool GEODE_CALL ::geode_implicit_load(Mod*); + public: std::string getID() const; std::string getName() const; @@ -362,7 +377,9 @@ namespace geode { * the mod pointer if it is initialized */ template - static inline Mod* get(); + static inline GEODE_HIDDEN Mod* get() { + return sharedMod<>; + } /** * Get all hooks owned by this Mod @@ -548,5 +565,11 @@ namespace geode { * However, it can be externed, unlike Mod::get() * @returns Same thing Mod::get() returns */ - inline Mod* getMod(); + inline GEODE_HIDDEN Mod* getMod() { + return Mod::get(); + } +} + +inline const char* operator"" _spr(const char* str, size_t) { + return geode::Mod::get()->expandSpriteName(str); } diff --git a/loader/include/Geode/modify/InternalMacros.hpp b/loader/include/Geode/modify/InternalMacros.hpp index 4f601eb5..93a86393 100644 --- a/loader/include/Geode/modify/InternalMacros.hpp +++ b/loader/include/Geode/modify/InternalMacros.hpp @@ -89,8 +89,8 @@ void _##Line_##Function(); \ namespace { \ struct _##Line_##Unique {}; \ } \ -static inline auto _line = (Interface::get()->scheduleOnLoad( \ - &_##Line_##Function<_##Line_##Unique> \ +static inline auto _line = (Loader::get()->scheduleOnModLoad( \ + nullptr, &_##Line_##Function<_##Line_##Unique> \ ), 0); \ template \ void _##Line_##Function() diff --git a/loader/include/Geode/modify/Modify.hpp b/loader/include/Geode/modify/Modify.hpp index 1a194f9f..2c889eca 100644 --- a/loader/include/Geode/modify/Modify.hpp +++ b/loader/include/Geode/modify/Modify.hpp @@ -3,17 +3,14 @@ #include "Types.hpp" #include "Addresses.hpp" #include "../meta/meta.hpp" -#include "../loader/Interface.hpp" +#include #include #define GEODE_APPLY_MODIFY_FOR_FUNCTION(index, convention, className, functionName) \ using base##index = wrap::functionName; \ using derived##index = wrap::functionName; \ if constexpr (derived##index::uuid != nullptr && (void*)base##index::uuid != (void*)derived##index::uuid) { \ - log::debug( \ - "Adding hook at function " #className "::" #functionName \ - ); \ - Interface::get()->addHook( \ + Mod::get()->addHook( \ #className "::" #functionName, \ (void*)addresses::address##index() \ ); \ @@ -30,7 +27,9 @@ namespace geode::modifier { public: // unordered_map idea ModifyBase() { - Derived::apply(); + Loader::get()->scheduleOnModLoad(getMod(), [](){ + Derived::apply(); + }); } template friend class Modify; diff --git a/loader/include/Geode/utils/addresser.hpp b/loader/include/Geode/utils/addresser.hpp index 67e0adee..1873b32e 100644 --- a/loader/include/Geode/utils/addresser.hpp +++ b/loader/include/Geode/utils/addresser.hpp @@ -8,7 +8,6 @@ #include #include #include -#include "../loader/Interface.hpp" #include "../loader/Mod.hpp" #include "../loader/Log.hpp" #include "general.hpp" diff --git a/loader/src/hooks/MenuLayer.cpp b/loader/src/hooks/MenuLayer.cpp index 1776072b..79ebb8dd 100644 --- a/loader/src/hooks/MenuLayer.cpp +++ b/loader/src/hooks/MenuLayer.cpp @@ -210,6 +210,7 @@ class $modify(CustomMenuLayer, MenuLayer) { } auto y = getChild(bottomMenu, 0)->getPositionY(); + std::cout << "test: " << "geode-logo-outline-gold.png"_spr << std::endl; g_geodeButton = SafeCreate() .with(CircleButtonSprite::createWithSpriteFrameName( diff --git a/loader/src/internal/InternalLoader.cpp b/loader/src/internal/InternalLoader.cpp index cb23a943..f8b6518a 100644 --- a/loader/src/internal/InternalLoader.cpp +++ b/loader/src/internal/InternalLoader.cpp @@ -38,7 +38,7 @@ bool InternalLoader::setup() { return true; } -void InternalLoader::queueInGDThread(std::function func) { +void InternalLoader::queueInGDThread(ScheduledFunction func) { std::lock_guard lock(m_gdThreadMutex); this->m_gdThreadQueue.push_back(func); } @@ -113,17 +113,25 @@ void InternalLoader::closePlatformConsole() { } #elif defined(GEODE_IS_MACOS) -#include +#include void InternalLoader::platformMessageBox(const char* title, std::string const& info) { - std::cout << title << ": " << info << std::endl; + CFStringRef cfTitle = CFStringCreateWithCString(NULL, title, kCFStringEncodingUTF8); + CFStringRef cfMessage = CFStringCreateWithCString(NULL, info.c_str(), kCFStringEncodingUTF8); + + CFUserNotificationDisplayNotice(0, kCFUserNotificationNoteAlertLevel, NULL, NULL, NULL, cfTitle, cfMessage, NULL); } void InternalLoader::openPlatformConsole() { m_platformConsoleOpen = true; + + for (auto const& log : Loader::get()->getLogs()) { + std::cout << log->toString(true) << "\n"; + } } void InternalLoader::closePlatformConsole() { + m_platformConsoleOpen = false; } #elif defined(GEODE_IS_IOS) diff --git a/loader/src/internal/InternalLoader.hpp b/loader/src/internal/InternalLoader.hpp index 59715946..eaf14277 100644 --- a/loader/src/internal/InternalLoader.hpp +++ b/loader/src/internal/InternalLoader.hpp @@ -46,7 +46,7 @@ public: */ bool shownInfoAlert(std::string const& key); - void queueInGDThread(std::function func); + void queueInGDThread(ScheduledFunction func); void executeGDThreadQueue(); void logConsoleMessage(std::string const& msg); diff --git a/loader/src/internal/InternalMod.hpp b/loader/src/internal/InternalMod.hpp index a917502f..135f0b4c 100644 --- a/loader/src/internal/InternalMod.hpp +++ b/loader/src/internal/InternalMod.hpp @@ -3,7 +3,6 @@ class InternalMod; #include -#include USE_GEODE_NAMESPACE(); diff --git a/loader/src/load/Hook.cpp b/loader/src/load/Hook.cpp index a0123db3..d6e182cc 100644 --- a/loader/src/load/Hook.cpp +++ b/loader/src/load/Hook.cpp @@ -1,7 +1,6 @@ #include #include #include -#include #include #include #include @@ -31,6 +30,7 @@ Result<> Mod::enableHook(Hook* hook) { if (!hook->isEnabled()) { auto res = std::invoke(hook->m_addFunction, hook->m_address); if (res) { + log::debug("Enabling hook at function ", hook->m_displayName); this->m_hooks.push_back(hook); hook->m_enabled = true; hook->m_handle = res.value(); @@ -48,6 +48,7 @@ Result<> Mod::enableHook(Hook* hook) { Result<> Mod::disableHook(Hook* hook) { if (hook->isEnabled()) { if (geode::core::hook::remove(hook->m_handle)) { + log::debug("Disabling hook at function {}", hook->m_displayName); hook->m_enabled = false; return Ok<>(); } diff --git a/loader/src/load/Interface.cpp b/loader/src/load/Interface.cpp deleted file mode 100644 index 5264afd2..00000000 --- a/loader/src/load/Interface.cpp +++ /dev/null @@ -1,30 +0,0 @@ -#include -#include -#include -#include -#include - -USE_GEODE_NAMESPACE(); - -void Interface::init(Mod* mod) { - if (!m_mod) { - m_mod = mod; - for (auto const& hook : m_scheduledHooks) { - std::invoke(hook.m_addFunction, m_mod, hook.m_displayName, hook.m_address); - } - m_scheduledHooks.clear(); - - for (auto const& fn : m_scheduledFunctions) { - std::invoke(fn); - } - m_scheduledFunctions.clear(); - } -} - -void Interface::scheduleOnLoad(ScheduledFunction function) { - m_scheduledFunctions.push_back(function); -} - -Interface* Interface::create() { - return new Interface; -} diff --git a/loader/src/load/Loader.cpp b/loader/src/load/Loader.cpp index 462bbe46..b92333df 100644 --- a/loader/src/load/Loader.cpp +++ b/loader/src/load/Loader.cpp @@ -1,6 +1,5 @@ #include #include -#include #include #include #include @@ -404,7 +403,7 @@ std::vector Loader::getLogs( return logs; } -void Loader::queueInGDThread(std::function func) { +void Loader::queueInGDThread(ScheduledFunction func) { InternalLoader::get()->queueInGDThread(func); } @@ -462,3 +461,15 @@ void Loader::openPlatformConsole() { void Loader::closePlatfromConsole() { InternalLoader::get()->closePlatformConsole(); } + +void Loader::scheduleOnModLoad(Mod* m, ScheduledFunction func) { + if (m) return func(); + m_scheduledFunctions.push_back(func); +} + +void Loader::releaseScheduledFunctions(Mod* mod) { + for (auto& func : m_scheduledFunctions) { + func(); + } + m_scheduledFunctions.clear(); +} diff --git a/loader/src/load/Log.cpp b/loader/src/load/Log.cpp index ddf4fa3b..e64c61a5 100644 --- a/loader/src/load/Log.cpp +++ b/loader/src/load/Log.cpp @@ -1,7 +1,6 @@ #include #include #include -#include #include #include #include @@ -97,10 +96,10 @@ std::string Log::toString(bool logTime) const { std::string res; if (logTime) { - res += fmt::format("{:%H:%M:%S}", this->m_time); + res += fmt::format("{:%H:%M:%S}", m_time); } - res += fmt::format("[{}]: ", m_sender ? m_sender->getName() : "?"); + res += fmt::format(" [{}]: ", m_sender ? m_sender->getName() : "?"); for (auto& i : m_components) { res += i->_toString(); @@ -114,5 +113,5 @@ void Log::pushToLoader() { } std::string geode::log::generateLogName() { - return fmt::format("Geode_{:%H:%M:%S}.log", log_clock::now()); + return fmt::format("Geode_{:%H.%M.%S}.log", log_clock::now()); } diff --git a/loader/src/load/Mod.cpp b/loader/src/load/Mod.cpp index 821f5bb3..ca2a9c0d 100644 --- a/loader/src/load/Mod.cpp +++ b/loader/src/load/Mod.cpp @@ -3,7 +3,6 @@ #include #include #include -#include #include #include #include @@ -211,7 +210,6 @@ Result<> Mod::load() { if (this->hasUnresolvedDependencies()) { RETURN_LOAD_ERR("Mod has unresolved dependencies"); } - log::releaseSchedules(this); auto err = this->loadPlatformBinary(); if (!err) RETURN_LOAD_ERR(err.error()); if (m_implicitLoadFunc) { diff --git a/loader/src/load/ModInfo.cpp b/loader/src/load/ModInfo.cpp index e7ea4df9..1bd4cbfc 100644 --- a/loader/src/load/ModInfo.cpp +++ b/loader/src/load/ModInfo.cpp @@ -1,7 +1,6 @@ #include #include #include -#include #include #include diff --git a/loader/src/load/Patch.cpp b/loader/src/load/Patch.cpp index 97f5d771..30b652af 100644 --- a/loader/src/load/Patch.cpp +++ b/loader/src/load/Patch.cpp @@ -1,7 +1,6 @@ #include #include #include -#include #include #include #include diff --git a/loader/src/load/cgeode.cpp b/loader/src/load/cgeode.cpp index ab9d9e04..4ad02e89 100644 --- a/loader/src/load/cgeode.cpp +++ b/loader/src/load/cgeode.cpp @@ -1,6 +1,5 @@ #include #include -#include #include USE_GEODE_NAMESPACE(); diff --git a/loader/src/load/load.cpp b/loader/src/load/load.cpp index 987f9061..6fb8bb06 100644 --- a/loader/src/load/load.cpp +++ b/loader/src/load/load.cpp @@ -1,7 +1,6 @@ #include #include #include -#include #undef snprintf USE_GEODE_NAMESPACE(); diff --git a/loader/src/load/mac/Mod.cpp b/loader/src/load/mac/Mod.cpp index f38d0509..4dd8a4f5 100644 --- a/loader/src/load/mac/Mod.cpp +++ b/loader/src/load/mac/Mod.cpp @@ -3,7 +3,6 @@ #ifdef GEODE_IS_MACOS #include -#include #include USE_GEODE_NAMESPACE(); diff --git a/loader/src/main.cpp b/loader/src/main.cpp index 173719c9..028df7ee 100644 --- a/loader/src/main.cpp +++ b/loader/src/main.cpp @@ -1,5 +1,4 @@ #include -#include #include #include #include @@ -124,7 +123,7 @@ int geodeEntry(void* platformData) { ); } - Interface::get()->init(InternalMod::get()); + geode_implicit_load(InternalMod::get()); if (!InternalLoader::get()->setup()) { // if we've made it here, Geode will diff --git a/loader/test/main/main.cpp b/loader/test/main/main.cpp index 6493eaff..fe5218bd 100644 --- a/loader/test/main/main.cpp +++ b/loader/test/main/main.cpp @@ -3,6 +3,11 @@ USE_GEODE_NAMESPACE(); +auto test = [](){ + log::info("Static logged"); + return 0; +}; + // Exported functions GEODE_API bool GEODE_CALL geode_enable() { log::info("Enabled");