From 80b5b20efba0bdf09b97e0e4a1af1f2eb99a69dd Mon Sep 17 00:00:00 2001
From: altalk23 <45172705+altalk23@users.noreply.github.com>
Date: Mon, 10 Apr 2023 12:49:59 +0300
Subject: [PATCH] fix events, resources, and minor stuff

---
 bindings/GeometryDash.bro                  |  2 --
 loader/include/Geode/loader/Loader.hpp     |  1 +
 loader/include/Geode/loader/ModEvent.hpp   |  1 +
 loader/src/hooks/updateResources.cpp       |  2 +-
 loader/src/loader/Loader.cpp               |  4 ++++
 loader/src/loader/LoaderImpl.cpp           | 12 ++++++++----
 loader/src/loader/LoaderImpl.hpp           |  3 +++
 loader/src/loader/Log.cpp                  |  2 +-
 loader/src/loader/ModEvent.cpp             |  5 ++++-
 loader/src/loader/ModImpl.cpp              | 12 +++++++++---
 loader/src/loader/ModImpl.hpp              |  5 +++++
 loader/src/loader/ModInfo.cpp              |  3 +++
 loader/src/platform/ios/LoaderImpl.cpp     |  6 ++++++
 loader/src/platform/mac/LoaderImpl.cpp     | 18 +++++++++++++++++-
 loader/src/platform/mac/util.mm            |  2 +-
 loader/src/platform/windows/LoaderImpl.cpp |  6 ++++++
 16 files changed, 70 insertions(+), 14 deletions(-)

diff --git a/bindings/GeometryDash.bro b/bindings/GeometryDash.bro
index 258dc122..259de99b 100644
--- a/bindings/GeometryDash.bro
+++ b/bindings/GeometryDash.bro
@@ -4789,8 +4789,6 @@ class PlayerObject : GameObject, AnimatedSpriteDelegate {
     void usingWallLimitedMode() = mac 0x22df00;
     void yStartDown() = mac 0x22e9b0;
     void yStartUp() = mac 0x22e990;
-    void runRotateAction() = win 0x1e9bf0;
-    void runBallRotation() = win 0x1e9d10;
 
     PAD = mac 0x14, win 0x14;
     bool m_unk480;
diff --git a/loader/include/Geode/loader/Loader.hpp b/loader/include/Geode/loader/Loader.hpp
index 4b00ebe2..8e8d1c1c 100644
--- a/loader/include/Geode/loader/Loader.hpp
+++ b/loader/include/Geode/loader/Loader.hpp
@@ -65,6 +65,7 @@ namespace geode {
         std::vector<InvalidGeodeFile> getFailedMods() const;
 
         void updateResources();
+        void updateResources(bool forceReload);
 
         void queueInGDThread(ScheduledFunction func);
         void waitForModsToBeLoaded();
diff --git a/loader/include/Geode/loader/ModEvent.hpp b/loader/include/Geode/loader/ModEvent.hpp
index e8b66f51..9e683820 100644
--- a/loader/include/Geode/loader/ModEvent.hpp
+++ b/loader/include/Geode/loader/ModEvent.hpp
@@ -52,6 +52,7 @@ namespace geode {
          * @param type Type of event to listen to. Ignored if mod is nullptr
          */
         ModStateFilter(Mod* mod, ModEventType type);
+        ModStateFilter(ModStateFilter const&);
     };
 }
 
diff --git a/loader/src/hooks/updateResources.cpp b/loader/src/hooks/updateResources.cpp
index d2ae3e13..85817635 100644
--- a/loader/src/hooks/updateResources.cpp
+++ b/loader/src/hooks/updateResources.cpp
@@ -9,7 +9,7 @@ struct ResourcesUpdate : Modify<ResourcesUpdate, LoadingLayer> {
         LoadingLayer::loadAssets();
         // this is in case the user refreshes texture quality at runtime
         if (m_loadStep == 10) {
-            Loader::get()->updateResources();
+            Loader::get()->updateResources(true);
         }
     }
 };
diff --git a/loader/src/loader/Loader.cpp b/loader/src/loader/Loader.cpp
index 706ca4b9..a539a70a 100644
--- a/loader/src/loader/Loader.cpp
+++ b/loader/src/loader/Loader.cpp
@@ -99,6 +99,10 @@ void Loader::updateResources() {
     return m_impl->updateResources();
 }
 
+void Loader::updateResources(bool forceReload) {
+    return m_impl->updateResources(forceReload);
+}
+
 void Loader::queueInGDThread(ScheduledFunction func) {
     return m_impl->queueInGDThread(func);
 }
diff --git a/loader/src/loader/LoaderImpl.cpp b/loader/src/loader/LoaderImpl.cpp
index 295d011a..e7cef4c2 100644
--- a/loader/src/loader/LoaderImpl.cpp
+++ b/loader/src/loader/LoaderImpl.cpp
@@ -108,14 +108,18 @@ void Loader::Impl::addSearchPaths() {
 }
 
 void Loader::Impl::updateResources() {
-    log::debug("Adding resources");
+    this->updateResources(true);
+}
 
-    // add own spritesheets
-    this->updateModResources(Mod::get());
+void Loader::Impl::updateResources(bool forceReload) {
+    log::debug("Adding resources");
 
     // add mods' spritesheets
     for (auto const& [_, mod] : m_mods) {
-        this->updateModResources(mod);
+        if (forceReload || !ModImpl::getImpl(mod)->m_resourcesLoaded) {
+            this->updateModResources(mod);
+            ModImpl::getImpl(mod)->m_resourcesLoaded = true;
+        }
     }
 }
 
diff --git a/loader/src/loader/LoaderImpl.hpp b/loader/src/loader/LoaderImpl.hpp
index fde4ae6f..4128fbac 100644
--- a/loader/src/loader/LoaderImpl.hpp
+++ b/loader/src/loader/LoaderImpl.hpp
@@ -138,6 +138,7 @@ namespace geode {
         std::vector<InvalidGeodeFile> getFailedMods() const;
 
         void updateResources();
+        void updateResources(bool forceReload);
 
         void waitForModsToBeLoaded();
 
@@ -149,6 +150,8 @@ namespace geode {
         void executeGDThreadQueue();
 
         void logConsoleMessage(std::string const& msg);
+        void logConsoleMessageWithSeverity(std::string const& msg, Severity severity);
+
         bool platformConsoleOpen() const;
         void openPlatformConsole();
         void closePlatformConsole();
diff --git a/loader/src/loader/Log.cpp b/loader/src/loader/Log.cpp
index e17befbd..102e7c73 100644
--- a/loader/src/loader/Log.cpp
+++ b/loader/src/loader/Log.cpp
@@ -209,7 +209,7 @@ void Logger::setup() {
 void Logger::push(Log&& log) {
     std::string logStr = log.toString(true);
 
-    LoaderImpl::get()->logConsoleMessage(logStr);
+    LoaderImpl::get()->logConsoleMessageWithSeverity(logStr, log.getSeverity());
     logStream() << logStr << std::endl;
 
     logs().emplace_back(std::forward<Log>(log));
diff --git a/loader/src/loader/ModEvent.cpp b/loader/src/loader/ModEvent.cpp
index 606cc625..2b32ef21 100644
--- a/loader/src/loader/ModEvent.cpp
+++ b/loader/src/loader/ModEvent.cpp
@@ -13,10 +13,13 @@ Mod* ModStateEvent::getMod() const {
 }
 
 ListenerResult ModStateFilter::handle(utils::MiniFunction<Callback> fn, ModStateEvent* event) {
-    if (!m_mod || (event->getMod() == m_mod && event->getType() == m_type)) {
+    // log::debug("Event mod filter: {}, {}, {}, {}", m_mod, static_cast<int>(m_type), event->getMod(), static_cast<int>(event->getType()));
+    if ((!m_mod || event->getMod() == m_mod) && event->getType() == m_type) {
         fn(event);
     }
     return ListenerResult::Propagate;
 }
 
 ModStateFilter::ModStateFilter(Mod* mod, ModEventType type) : m_mod(mod), m_type(type) {}
+
+ModStateFilter::ModStateFilter(ModStateFilter const& other) : m_mod(other.m_mod), m_type(other.m_type) {}
diff --git a/loader/src/loader/ModImpl.cpp b/loader/src/loader/ModImpl.cpp
index f837116f..18747cfa 100644
--- a/loader/src/loader/ModImpl.cpp
+++ b/loader/src/loader/ModImpl.cpp
@@ -289,6 +289,7 @@ bool Mod::Impl::hasSetting(std::string const& key) const {
 // Loading, Toggling, Installing
 
 Result<> Mod::Impl::loadBinary() {
+    log::debug("Loading binary for mod {}", m_info.id());
     if (m_binaryLoaded) {
         return Ok();
     }
@@ -305,6 +306,7 @@ Result<> Mod::Impl::loadBinary() {
     if (!res) {
         // make sure to free up the next mod mutex
         LoaderImpl::get()->releaseNextMod();
+        log::warn("Failed to load binary for mod {}: {}", m_info.id(), res.unwrapErr());
         return res;
     }
     m_binaryLoaded = true;
@@ -316,8 +318,11 @@ Result<> Mod::Impl::loadBinary() {
     });
 
     Loader::get()->updateAllDependencies();
-    Loader::get()->updateResources();
-
+    if (LoaderImpl::get()->m_isSetup) {
+        Loader::get()->updateResources(false);
+    }
+    
+    log::debug("Enabling mod {}", m_info.id());
     GEODE_UNWRAP(this->enable());
 
     return Ok();
@@ -375,7 +380,8 @@ Result<> Mod::Impl::enable() {
 
     for (auto const& patch : m_patches) {
         if (!patch->apply()) {
-            return Err("Unable to apply patch at " + std::to_string(patch->getAddress()));
+            log::warn("Unable to apply patch at {}", patch->getAddress());
+            continue;
         }
     }
 
diff --git a/loader/src/loader/ModImpl.hpp b/loader/src/loader/ModImpl.hpp
index cfb6f209..ff0ba4d5 100644
--- a/loader/src/loader/ModImpl.hpp
+++ b/loader/src/loader/ModImpl.hpp
@@ -58,6 +58,11 @@ namespace geode {
          */
         json::Value m_savedSettingsData = json::Object();
 
+        /**
+         * Whether the mod resources are loaded or not
+         */
+        bool m_resourcesLoaded = false;
+
         Impl(Mod* self, ModInfo const& info);
         ~Impl();
 
diff --git a/loader/src/loader/ModInfo.cpp b/loader/src/loader/ModInfo.cpp
index 16370f2a..eb64a504 100644
--- a/loader/src/loader/ModInfo.cpp
+++ b/loader/src/loader/ModInfo.cpp
@@ -87,6 +87,9 @@ Result<ModInfo> ModInfo::Impl::createFromSchemaV010(ModJson const& rawJson) {
 
     root.addKnownKey("geode");
 
+    // don't think its used locally yet
+    root.addKnownKey("tags"); 
+
     root.needs("id").validate(MiniFunction<bool(std::string const&)>(&ModInfo::validateID)).into(impl->m_id);
     root.needs("version").into(impl->m_version);
     root.needs("name").into(impl->m_name);
diff --git a/loader/src/platform/ios/LoaderImpl.cpp b/loader/src/platform/ios/LoaderImpl.cpp
index 56852e30..c3a599f2 100644
--- a/loader/src/platform/ios/LoaderImpl.cpp
+++ b/loader/src/platform/ios/LoaderImpl.cpp
@@ -15,6 +15,12 @@ void Loader::Impl::platformMessageBox(char const* title, std::string const& info
     std::cout << title << ": " << info << std::endl;
 }
 
+void Loader::Impl::logConsoleMessageWithSeverity(std::string const& msg, Severity severity) {
+    if (m_platformConsoleOpen) {
+        std::cout << msg << "\n" << std::flush;
+    }
+}
+
 void Loader::Impl::openPlatformConsole() {
     ghc::filesystem::path(getpwuid(getuid())->pw_dir);
     freopen(ghc::filesystem::path(dirs::getGeodeDir() / "geode_log.txt").string().c_str(), "w", stdout);
diff --git a/loader/src/platform/mac/LoaderImpl.cpp b/loader/src/platform/mac/LoaderImpl.cpp
index 3760eb96..1ed684ab 100644
--- a/loader/src/platform/mac/LoaderImpl.cpp
+++ b/loader/src/platform/mac/LoaderImpl.cpp
@@ -19,11 +19,27 @@ void Loader::Impl::platformMessageBox(char const* title, std::string const& info
     );
 }
 
+void Loader::Impl::logConsoleMessageWithSeverity(std::string const& msg, Severity severity) {
+    if (m_platformConsoleOpen) {
+        int colorcode = 0;
+        switch (severity) {
+            case Severity::Debug: colorcode = 36; break;
+            case Severity::Info: colorcode = 34; break;
+            case Severity::Warning: colorcode = 33; break;
+            case Severity::Error: colorcode = 31; break;
+            default: colorcode = 35; break;
+        }
+        auto newMsg = "\033[1;" + std::to_string(colorcode) + "m" + msg.substr(0, 8) + "\033[0m" + msg.substr(8);
+
+        std::cout << newMsg << "\n" << std::flush;
+    }
+}
+
 void Loader::Impl::openPlatformConsole() {
     m_platformConsoleOpen = true;
 
     for (auto const& log : log::Logger::list()) {
-        std::cout << log->toString(true) << "\n";
+        this->logConsoleMessageWithSeverity(log->toString(true), log->getSeverity());
     }
 }
 
diff --git a/loader/src/platform/mac/util.mm b/loader/src/platform/mac/util.mm
index 992149aa..c15a30bb 100644
--- a/loader/src/platform/mac/util.mm
+++ b/loader/src/platform/mac/util.mm
@@ -108,7 +108,7 @@ void utils::web::openLinkInBrowser(std::string const& url) {
 
     int result = [panel runModal];
 
-    if (result == NSFileHandlingPanelOKButton) {
+    if (result == NSModalResponseOK) {
         std::vector<ghc::filesystem::path> fileURLs;
 
         for (NSURL* i in panel.URLs) {
diff --git a/loader/src/platform/windows/LoaderImpl.cpp b/loader/src/platform/windows/LoaderImpl.cpp
index 15bed851..b13160c7 100644
--- a/loader/src/platform/windows/LoaderImpl.cpp
+++ b/loader/src/platform/windows/LoaderImpl.cpp
@@ -17,6 +17,12 @@ void Loader::Impl::platformMessageBox(char const* title, std::string const& info
     MessageBoxA(nullptr, info.c_str(), title, MB_ICONERROR);
 }
 
+void Loader::Impl::logConsoleMessageWithSeverity(std::string const& msg, Severity severity) {
+    if (m_platformConsoleOpen) {
+        std::cout << msg << "\n" << std::flush;
+    }
+}
+
 void Loader::Impl::openPlatformConsole() {
     if (m_platformConsoleOpen) return;
     if (AllocConsole() == 0) return;