From 7f449b996e3cb735bbf8c1bb02d53e7be613f80f Mon Sep 17 00:00:00 2001
From: ConfiG <cgytrus@cgyt.ru>
Date: Tue, 8 Aug 2023 21:59:13 +0300
Subject: [PATCH] add utils::game::restart, reset => forceReset

---
 loader/include/Geode/utils/general.hpp |  4 ++++
 loader/launcher/windows/Updater.cpp    |  5 +++++
 loader/src/load.cpp                    |  4 ++--
 loader/src/loader/LoaderImpl.cpp       |  5 ++---
 loader/src/loader/LoaderImpl.hpp       |  2 +-
 loader/src/platform/mac/util.mm        | 14 +++++++++++++-
 loader/src/platform/windows/main.cpp   | 11 +----------
 loader/src/platform/windows/util.cpp   | 26 ++++++++++++++++++++++++++
 8 files changed, 54 insertions(+), 17 deletions(-)

diff --git a/loader/include/Geode/utils/general.hpp b/loader/include/Geode/utils/general.hpp
index ec736efb..c4f5015f 100644
--- a/loader/include/Geode/utils/general.hpp
+++ b/loader/include/Geode/utils/general.hpp
@@ -127,3 +127,7 @@ namespace geode::utils::clipboard {
     GEODE_DLL bool write(std::string const& data);
     GEODE_DLL std::string read();
 }
+
+namespace geode::utils::game {
+    GEODE_DLL void restart();
+}
diff --git a/loader/launcher/windows/Updater.cpp b/loader/launcher/windows/Updater.cpp
index ef5b3cfc..3a1506ef 100644
--- a/loader/launcher/windows/Updater.cpp
+++ b/loader/launcher/windows/Updater.cpp
@@ -107,6 +107,11 @@ int main(int argc, char* argv[]) {
     if (argc < 2)
         return 0;
 
+    if (!waitForFile(workingDir / argv[1])) {
+        showError("There was an error restarting GD. Please, restart the game manually.");
+        return 0;
+    }
+
     // restart gd using the provided path
     ShellExecuteA(NULL, "open", (workingDir / argv[1]).string().c_str(), "", workingDir.string().c_str(), TRUE);
     return 0;
diff --git a/loader/src/load.cpp b/loader/src/load.cpp
index a60259fa..85e05d42 100644
--- a/loader/src/load.cpp
+++ b/loader/src/load.cpp
@@ -66,7 +66,7 @@ int geodeEntry(void* platformData) {
             "There was a fatal error setting up "
             "the internal mod and Geode can not be loaded: " + internalSetupRes.unwrapErr()
         );
-        LoaderImpl::get()->reset();
+        LoaderImpl::get()->forceReset();
         return 1;
     }
 
@@ -84,7 +84,7 @@ int geodeEntry(void* platformData) {
             "the loader and Geode can not be loaded. " 
             "(" + setupRes.unwrapErr() + ")"
         );
-        LoaderImpl::get()->reset();
+        LoaderImpl::get()->forceReset();
         return 1;
     }
 
diff --git a/loader/src/loader/LoaderImpl.cpp b/loader/src/loader/LoaderImpl.cpp
index caca7b4d..99d12cb6 100644
--- a/loader/src/loader/LoaderImpl.cpp
+++ b/loader/src/loader/LoaderImpl.cpp
@@ -430,9 +430,8 @@ bool Loader::Impl::didLastLaunchCrash() const {
     return crashlog::didLastLaunchCrash();
 }
 
-void Loader::Impl::reset() {
+void Loader::Impl::forceReset() {
     this->closePlatformConsole();
-
     for (auto& [_, mod] : m_mods) {
         delete mod;
     }
@@ -447,7 +446,7 @@ bool Loader::Impl::isReadyToHook() const {
 }
 
 void Loader::Impl::addInternalHook(Hook* hook, Mod* mod) {
-    m_internalHooks.push_back({hook, mod});
+    m_internalHooks.emplace_back(hook, mod);
 }
 
 bool Loader::Impl::loadHooks() {
diff --git a/loader/src/loader/LoaderImpl.hpp b/loader/src/loader/LoaderImpl.hpp
index 2869ac2c..7b4fd48e 100644
--- a/loader/src/loader/LoaderImpl.hpp
+++ b/loader/src/loader/LoaderImpl.hpp
@@ -116,7 +116,7 @@ namespace geode {
         Result<Mod*> loadModFromInfo(ModInfo const& info);
 
         Result<> setup();
-        void reset();
+        void forceReset();
 
         Result<> saveData();
         Result<> loadData();
diff --git a/loader/src/platform/mac/util.mm b/loader/src/platform/mac/util.mm
index 80838c56..250e0047 100644
--- a/loader/src/platform/mac/util.mm
+++ b/loader/src/platform/mac/util.mm
@@ -10,6 +10,7 @@ using namespace geode::prelude;
 #include <Geode/utils/web.hpp>
 #include <Geode/utils/file.hpp>
 #include <Geode/utils/cocos.hpp>
+#include <Geode/binding/GameManager.hpp>
 
 bool utils::clipboard::write(std::string const& data) {
     [[NSPasteboard generalPasteboard] clearContents];
@@ -180,7 +181,7 @@ ghc::filesystem::path dirs::getGameDir() {
         _NSGetExecutablePath(gddir.data(), &out);
 
         ghc::filesystem::path gdpath = gddir.data();
-        auto currentPath = gdpath.parent_path().parent_path();    
+        auto currentPath = gdpath.parent_path().parent_path();
         return currentPath;
     }();
 
@@ -200,4 +201,15 @@ ghc::filesystem::path dirs::getSaveDir() {
     return path;
 }
 
+void geode::utils::game::restart() {
+    if (CCApplication::sharedApplication() &&
+        (GameManager::get()->m_playLayer || GameManager::get()->m_levelEditorLayer)) {
+        log::error("Cannot restart in PlayLayer or LevelEditorLayer!");
+        return;
+    }
+
+    // TODO: implement restarting on mac
+    log::warn("Restarting is not yet implemented on macOS!");
+}
+
 #endif
diff --git a/loader/src/platform/windows/main.cpp b/loader/src/platform/windows/main.cpp
index 99376181..28f9979d 100644
--- a/loader/src/platform/windows/main.cpp
+++ b/loader/src/platform/windows/main.cpp
@@ -24,16 +24,7 @@ void updateGeode() {
         ghc::filesystem::exists(updatesDir / "GeodeUpdater.exe"))
         ghc::filesystem::rename(updatesDir / "GeodeUpdater.exe", workingDir / "GeodeUpdater.exe");
 
-    wchar_t buffer[MAX_PATH];
-    GetModuleFileNameW(nullptr, buffer, MAX_PATH);
-    const auto gdName = ghc::filesystem::path(buffer).filename().string();
-
-    // launch updater
-    const auto updaterPath = (workingDir / "GeodeUpdater.exe").string();
-    ShellExecuteA(nullptr, "open", updaterPath.c_str(), gdName.c_str(), workingDir.string().c_str(), false);
-
-    // quit gd before it can even start
-    exit(0);
+    utils::game::restart();
 }
 
 int WINAPI gdMainHook(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow) {
diff --git a/loader/src/platform/windows/util.cpp b/loader/src/platform/windows/util.cpp
index 062d0b19..7ecb7322 100644
--- a/loader/src/platform/windows/util.cpp
+++ b/loader/src/platform/windows/util.cpp
@@ -158,4 +158,30 @@ ghc::filesystem::path dirs::getSaveDir() {
     return path;
 }
 
+void geode::utils::game::restart() {
+    if (CCApplication::sharedApplication() &&
+        (GameManager::get()->m_playLayer || GameManager::get()->m_levelEditorLayer)) {
+        log::error("Cannot restart in PlayLayer or LevelEditorLayer!");
+        return;
+    }
+
+    const auto workingDir = dirs::getGameDir();
+
+    wchar_t buffer[MAX_PATH];
+    GetModuleFileNameW(nullptr, buffer, MAX_PATH);
+    const auto gdName = ghc::filesystem::path(buffer).filename().string();
+
+    // launch updater
+    const auto updaterPath = (workingDir / "GeodeUpdater.exe").string();
+    ShellExecuteA(nullptr, "open", updaterPath.c_str(), gdName.c_str(), workingDir.string().c_str(), false);
+
+    if (CCApplication::sharedApplication())
+        // please forgive me..
+        // manually set the closed flag
+        // TODO: actually call glfwSetWindowShouldClose
+        *reinterpret_cast<bool*>(reinterpret_cast<uintptr_t>(CCEGLView::sharedOpenGLView()->getWindow()) + 0xa) = true;
+    else
+        exit(0);
+}
+
 #endif