From 98f82ff00e320971daa4166ae2016fd99e0627b3 Mon Sep 17 00:00:00 2001 From: HJfod <60038575+HJfod@users.noreply.github.com> Date: Tue, 16 Jul 2024 13:21:58 +0300 Subject: [PATCH 01/64] fix platform-specific dependencies through Cli 3.2.0 --- cmake/GeodeFile.cmake | 11 ++++++++++- cmake/Platform.cmake | 5 +++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/cmake/GeodeFile.cmake b/cmake/GeodeFile.cmake index 9c21103c..143b8f93 100644 --- a/cmake/GeodeFile.cmake +++ b/cmake/GeodeFile.cmake @@ -119,7 +119,16 @@ function(setup_geode_mod proname) endif() # Check dependencies using CLI - if (${GEODE_CLI_VERSION} VERSION_GREATER_EQUAL "2.0.0") + if (${GEODE_CLI_VERSION} VERSION_GREATER_EQUAL "3.2.0") + execute_process( + COMMAND ${GEODE_CLI} project check ${CMAKE_CURRENT_BINARY_DIR} + --externals ${GEODE_MODS_BEING_BUILT} ${DONT_UPDATE_INDEX_ARG} + --platform ${GEODE_TARGET_PLATFORM_SHORT} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + COMMAND_ERROR_IS_FATAL ANY + ) + elseif (${GEODE_CLI_VERSION} VERSION_GREATER_EQUAL "2.0.0") + message(WARNING "If you use platform-specific dependencies, upgrade Geode CLI to version 3.2.0 or greater!") execute_process( COMMAND ${GEODE_CLI} project check ${CMAKE_CURRENT_BINARY_DIR} --externals ${GEODE_MODS_BEING_BUILT} ${DONT_UPDATE_INDEX_ARG} diff --git a/cmake/Platform.cmake b/cmake/Platform.cmake index a1fd167a..36fbce4f 100644 --- a/cmake/Platform.cmake +++ b/cmake/Platform.cmake @@ -14,6 +14,7 @@ if (GEODE_TARGET_PLATFORM STREQUAL "iOS") set(GEODE_OUTPUT_NAME "Geode.ios") set(GEODE_PLATFORM_BINARY "Geode.ios.dylib") set(GEODE_MOD_BINARY_SUFFIX ".ios.dylib" CACHE STRING "" FORCE) + set(GEODE_TARGET_PLATFORM_SHORT "ios" PARENT_SCOPE) elseif (GEODE_TARGET_PLATFORM STREQUAL "MacOS") set_target_properties(${PROJECT_NAME} PROPERTIES SYSTEM_NAME MacOS @@ -49,6 +50,7 @@ elseif (GEODE_TARGET_PLATFORM STREQUAL "MacOS") set(GEODE_OUTPUT_NAME "Geode") set(GEODE_PLATFORM_BINARY "Geode.dylib") set(GEODE_MOD_BINARY_SUFFIX ".dylib" CACHE STRING "" FORCE) + set(GEODE_TARGET_PLATFORM_SHORT "mac" PARENT_SCOPE) elseif (GEODE_TARGET_PLATFORM STREQUAL "Win64") set_target_properties(${PROJECT_NAME} PROPERTIES SYSTEM_NAME Win64 @@ -77,6 +79,7 @@ elseif (GEODE_TARGET_PLATFORM STREQUAL "Win64") set(GEODE_OUTPUT_NAME "Geode") set(GEODE_PLATFORM_BINARY "Geode.lib") set(GEODE_MOD_BINARY_SUFFIX ".dll" CACHE STRING "" FORCE) + set(GEODE_TARGET_PLATFORM_SHORT "win" PARENT_SCOPE) elseif (GEODE_TARGET_PLATFORM STREQUAL "Android32") set_target_properties(${PROJECT_NAME} PROPERTIES SYSTEM_NAME Android @@ -101,6 +104,7 @@ elseif (GEODE_TARGET_PLATFORM STREQUAL "Android32") set(GEODE_OUTPUT_NAME "Geode.android32") set(GEODE_PLATFORM_BINARY "Geode.android32.so") set(GEODE_MOD_BINARY_SUFFIX ".android32.so" CACHE STRING "" FORCE) + set(GEODE_TARGET_PLATFORM_SHORT "android32" PARENT_SCOPE) elseif (GEODE_TARGET_PLATFORM STREQUAL "Android64") set_target_properties(${PROJECT_NAME} PROPERTIES SYSTEM_NAME Android @@ -130,6 +134,7 @@ elseif (GEODE_TARGET_PLATFORM STREQUAL "Android64") set(GEODE_OUTPUT_NAME "Geode.android64") set(GEODE_PLATFORM_BINARY "Geode.android64.so") set(GEODE_MOD_BINARY_SUFFIX ".android64.so" CACHE STRING "" FORCE) + set(GEODE_TARGET_PLATFORM_SHORT "android64" PARENT_SCOPE) else() message(FATAL_ERROR "Unknown platform ${GEODE_TARGET_PLATFORM}") endif() From b5484acc602abd12d5f396953130caf459d02c5b Mon Sep 17 00:00:00 2001 From: HJfod <60038575+HJfod@users.noreply.github.com> Date: Tue, 16 Jul 2024 13:25:08 +0300 Subject: [PATCH 02/64] i goofed up --- cmake/Platform.cmake | 35 ++++++++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/cmake/Platform.cmake b/cmake/Platform.cmake index 36fbce4f..e8ea0d55 100644 --- a/cmake/Platform.cmake +++ b/cmake/Platform.cmake @@ -14,7 +14,12 @@ if (GEODE_TARGET_PLATFORM STREQUAL "iOS") set(GEODE_OUTPUT_NAME "Geode.ios") set(GEODE_PLATFORM_BINARY "Geode.ios.dylib") set(GEODE_MOD_BINARY_SUFFIX ".ios.dylib" CACHE STRING "" FORCE) - set(GEODE_TARGET_PLATFORM_SHORT "ios" PARENT_SCOPE) + + if (NOT ${PROJECT_NAME} STREQUAL ${CMAKE_PROJECT_NAME}) + set(GEODE_TARGET_PLATFORM_SHORT "ios" PARENT_SCOPE) + else() + set(GEODE_TARGET_PLATFORM_SHORT "ios") + endif() elseif (GEODE_TARGET_PLATFORM STREQUAL "MacOS") set_target_properties(${PROJECT_NAME} PROPERTIES SYSTEM_NAME MacOS @@ -50,7 +55,12 @@ elseif (GEODE_TARGET_PLATFORM STREQUAL "MacOS") set(GEODE_OUTPUT_NAME "Geode") set(GEODE_PLATFORM_BINARY "Geode.dylib") set(GEODE_MOD_BINARY_SUFFIX ".dylib" CACHE STRING "" FORCE) - set(GEODE_TARGET_PLATFORM_SHORT "mac" PARENT_SCOPE) + + if (NOT ${PROJECT_NAME} STREQUAL ${CMAKE_PROJECT_NAME}) + set(GEODE_TARGET_PLATFORM_SHORT "mac" PARENT_SCOPE) + else() + set(GEODE_TARGET_PLATFORM_SHORT "mac") + endif() elseif (GEODE_TARGET_PLATFORM STREQUAL "Win64") set_target_properties(${PROJECT_NAME} PROPERTIES SYSTEM_NAME Win64 @@ -79,7 +89,12 @@ elseif (GEODE_TARGET_PLATFORM STREQUAL "Win64") set(GEODE_OUTPUT_NAME "Geode") set(GEODE_PLATFORM_BINARY "Geode.lib") set(GEODE_MOD_BINARY_SUFFIX ".dll" CACHE STRING "" FORCE) - set(GEODE_TARGET_PLATFORM_SHORT "win" PARENT_SCOPE) + + if (NOT ${PROJECT_NAME} STREQUAL ${CMAKE_PROJECT_NAME}) + set(GEODE_TARGET_PLATFORM_SHORT "win" PARENT_SCOPE) + else() + set(GEODE_TARGET_PLATFORM_SHORT "win") + endif() elseif (GEODE_TARGET_PLATFORM STREQUAL "Android32") set_target_properties(${PROJECT_NAME} PROPERTIES SYSTEM_NAME Android @@ -104,7 +119,12 @@ elseif (GEODE_TARGET_PLATFORM STREQUAL "Android32") set(GEODE_OUTPUT_NAME "Geode.android32") set(GEODE_PLATFORM_BINARY "Geode.android32.so") set(GEODE_MOD_BINARY_SUFFIX ".android32.so" CACHE STRING "" FORCE) - set(GEODE_TARGET_PLATFORM_SHORT "android32" PARENT_SCOPE) + + if (NOT ${PROJECT_NAME} STREQUAL ${CMAKE_PROJECT_NAME}) + set(GEODE_TARGET_PLATFORM_SHORT "android32" PARENT_SCOPE) + else() + set(GEODE_TARGET_PLATFORM_SHORT "android32") + endif() elseif (GEODE_TARGET_PLATFORM STREQUAL "Android64") set_target_properties(${PROJECT_NAME} PROPERTIES SYSTEM_NAME Android @@ -134,7 +154,12 @@ elseif (GEODE_TARGET_PLATFORM STREQUAL "Android64") set(GEODE_OUTPUT_NAME "Geode.android64") set(GEODE_PLATFORM_BINARY "Geode.android64.so") set(GEODE_MOD_BINARY_SUFFIX ".android64.so" CACHE STRING "" FORCE) - set(GEODE_TARGET_PLATFORM_SHORT "android64" PARENT_SCOPE) + + if (NOT ${PROJECT_NAME} STREQUAL ${CMAKE_PROJECT_NAME}) + set(GEODE_TARGET_PLATFORM_SHORT "android64" PARENT_SCOPE) + else() + set(GEODE_TARGET_PLATFORM_SHORT "android64") + endif() else() message(FATAL_ERROR "Unknown platform ${GEODE_TARGET_PLATFORM}") endif() From 2edfb71bacd957e30f60124cbf92ddbc8966cf9c Mon Sep 17 00:00:00 2001 From: HJfod <60038575+HJfod@users.noreply.github.com> Date: Tue, 16 Jul 2024 13:53:33 +0300 Subject: [PATCH 03/64] add GEODE_DONT_USE_CCACHE --- CMakeLists.txt | 66 ++++++++++++++++++++++++++------------------------ 1 file changed, 35 insertions(+), 31 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1eb8a5ac..8fbfc08e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -88,42 +88,46 @@ endif() project(geode-sdk VERSION ${GEODE_VERSION} LANGUAGES CXX C) -message(STATUS "Looking for ccache/sccache") -if (DEFINED CMAKE_C_COMPILER_LAUNCHER OR DEFINED CMAKE_CXX_COMPILER_LAUNCHER) - message(STATUS "Looking for ccache/sccache - detecting variant") - if (DEFINED CMAKE_C_COMPILER_LAUNCHER AND DEFINED CMAKE_CXX_COMPILER_LAUNCHER AND - CMAKE_C_COMPILER_LAUNCHER STREQUAL CMAKE_CXX_COMPILER_LAUNCHER) - if (CMAKE_CXX_COMPILER_LAUNCHER MATCHES "sccache(|.exe)$") - message(STATUS "Looking for ccache/sccache - detected sccache") - set(GEODE_CCACHE_VARIANT "sccache") - elseif(CMAKE_CXX_COMPILER_LAUNCHER MATCHES "ccache(|.exe)$") - message(STATUS "Looking for ccache/sccache - detected ccache") - set(GEODE_CCACHE_VARIANT "ccache") +if (NOT GEODE_DONT_USE_CCACHE) + message(STATUS "Looking for ccache/sccache") + if (DEFINED CMAKE_C_COMPILER_LAUNCHER OR DEFINED CMAKE_CXX_COMPILER_LAUNCHER) + message(STATUS "Looking for ccache/sccache - detecting variant") + if (DEFINED CMAKE_C_COMPILER_LAUNCHER AND DEFINED CMAKE_CXX_COMPILER_LAUNCHER AND + CMAKE_C_COMPILER_LAUNCHER STREQUAL CMAKE_CXX_COMPILER_LAUNCHER) + if (CMAKE_CXX_COMPILER_LAUNCHER MATCHES "sccache(|.exe)$") + message(STATUS "Looking for ccache/sccache - detected sccache") + set(GEODE_CCACHE_VARIANT "sccache") + elseif(CMAKE_CXX_COMPILER_LAUNCHER MATCHES "ccache(|.exe)$") + message(STATUS "Looking for ccache/sccache - detected ccache") + set(GEODE_CCACHE_VARIANT "ccache") + else() + message(STATUS "Looking for ccache/sccache - none (custom compiler launcher: {CMAKE_C_COMPILER_LAUNCHER}, {CMAKE_CXX_COMPILER_LAUNCHER})") + endif() else() - message(STATUS "Looking for ccache/sccache - none (custom compiler launcher: {CMAKE_C_COMPILER_LAUNCHER}, {CMAKE_CXX_COMPILER_LAUNCHER})") + message(STATUS "Looking for ccache/sccache - skipped (custom compiler launcher: {CMAKE_C_COMPILER_LAUNCHER}, {CMAKE_CXX_COMPILER_LAUNCHER})") endif() + elseif (CMAKE_GENERATOR MATCHES "Visual Studio") + message(STATUS "Looking for ccache/sccache - skipped (Visual Studio generator)") else() - message(STATUS "Looking for ccache/sccache - skipped (custom compiler launcher: {CMAKE_C_COMPILER_LAUNCHER}, {CMAKE_CXX_COMPILER_LAUNCHER})") + find_program(GEODE_CCACHE NAMES sccache ccache) + if (GEODE_CCACHE) + if (${GEODE_CCACHE} MATCHES "sccache(|.exe)$") + set(GEODE_CCACHE_VARIANT "sccache") + else() + set(GEODE_CCACHE_VARIANT "ccache") + endif() + message(STATUS "Looking for ccache/sccache - found ${GEODE_CCACHE_VARIANT}") + message(NOTICE "Compiler launcher not set but ccache/sccache was found. " + "Setting compiler launcher to that") + set(CMAKE_C_COMPILER_LAUNCHER ${GEODE_CCACHE}) + set(CMAKE_CXX_COMPILER_LAUNCHER ${GEODE_CCACHE}) + else() + message(STATUS "Looking for ccache/sccache - not found") + endif() + unset(GEODE_CCACHE) endif() -elseif (CMAKE_GENERATOR MATCHES "Visual Studio") - message(STATUS "Looking for ccache/sccache - skipped (Visual Studio generator)") else() - find_program(GEODE_CCACHE NAMES sccache ccache) - if (GEODE_CCACHE) - if (${GEODE_CCACHE} MATCHES "sccache(|.exe)$") - set(GEODE_CCACHE_VARIANT "sccache") - else() - set(GEODE_CCACHE_VARIANT "ccache") - endif() - message(STATUS "Looking for ccache/sccache - found ${GEODE_CCACHE_VARIANT}") - message(NOTICE "Compiler launcher not set but ccache/sccache was found. " - "Setting compiler launcher to that") - set(CMAKE_C_COMPILER_LAUNCHER ${GEODE_CCACHE}) - set(CMAKE_CXX_COMPILER_LAUNCHER ${GEODE_CCACHE}) - else() - message(STATUS "Looking for ccache/sccache - not found") - endif() - unset(GEODE_CCACHE) + message(STATUS "Not looking for ccache because GEODE_DONT_USE_CCACHE was ON") endif() if (DEFINED GEODE_CCACHE_VARIANT) From 2b35e0e833fd31d91db245760beb7bc8b6ae8b6a Mon Sep 17 00:00:00 2001 From: Chloe <25387744+qimiko@users.noreply.github.com> Date: Thu, 18 Jul 2024 18:45:20 -0700 Subject: [PATCH 04/64] remove useless fs hash block ndk r27 implements this, so it won't build --- loader/include/Geode/utils/general.hpp | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/loader/include/Geode/utils/general.hpp b/loader/include/Geode/utils/general.hpp index e231cb1a..d23b3c63 100644 --- a/loader/include/Geode/utils/general.hpp +++ b/loader/include/Geode/utils/general.hpp @@ -14,16 +14,6 @@ #include #include -// only windows seems to properly implement std::hash on std::filesystem::path -#ifdef GEODE_IS_ANDROID -template <> -struct std::hash { - std::size_t operator()(std::filesystem::path const& path) const noexcept { - return std::filesystem::hash_value(path); - } -}; -#endif - namespace geode { using ByteVector = std::vector; From f86d4db20fe905d0050025177264e8106800fb32 Mon Sep 17 00:00:00 2001 From: matcool <26722564+matcool@users.noreply.github.com> Date: Sat, 20 Jul 2024 16:27:24 -0300 Subject: [PATCH 05/64] update docs version --- .gitignore | 1 + flash.toml | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 979b5d0f..7dccd325 100644 --- a/.gitignore +++ b/.gitignore @@ -50,6 +50,7 @@ bin # Ignore docs folders docs/** docs +docs-dist/ # Ignore codegenned files loader/src/internal/about.cpp diff --git a/flash.toml b/flash.toml index a966930f..84c671b0 100644 --- a/flash.toml +++ b/flash.toml @@ -1,10 +1,10 @@ # Configuration file for the Flash C++ documentation generator. -# https://github.com/hjfod/flash +# https://github.com/geode-sdk/flash [project] name = "Geode" -version = "v1.0.0" +version = "v3.0.0" repository = "https://github.com/geode-sdk/geode" tree = "https://github.com/geode-sdk/geode/tree/main" icon = "loader/resources/logos/geode-circle.png" From 4f321973ac0e6140a4d48d62691c8aa41a575e41 Mon Sep 17 00:00:00 2001 From: matcool <26722564+matcool@users.noreply.github.com> Date: Sat, 20 Jul 2024 16:28:03 -0300 Subject: [PATCH 06/64] implement custom window for showing crashlog instead of messagebox very cool :-) --- loader/CMakeLists.txt | 4 +- loader/src/internal/crashlog.cpp | 8 +- loader/src/internal/crashlog.hpp | 2 + loader/src/platform/windows/crashlog.cpp | 12 +- .../src/platform/windows/crashlogWindow.cpp | 208 ++++++++++++++++++ 5 files changed, 230 insertions(+), 4 deletions(-) create mode 100644 loader/src/platform/windows/crashlogWindow.cpp diff --git a/loader/CMakeLists.txt b/loader/CMakeLists.txt index 69e99005..9595bbc6 100644 --- a/loader/CMakeLists.txt +++ b/loader/CMakeLists.txt @@ -335,7 +335,9 @@ if (APPLE) elseif (WIN32) add_subdirectory(launcher/windows) - target_link_libraries(${PROJECT_NAME} dbghelp) + target_link_libraries(${PROJECT_NAME} dbghelp comctl32 uxtheme Winmm) + + target_compile_definitions(${PROJECT_NAME} PUBLIC ISOLATION_AWARE_ENABLED=1) if (MSVC) # disable warnings about CCNode::setID diff --git a/loader/src/internal/crashlog.cpp b/loader/src/internal/crashlog.cpp index 279a73d8..359fa926 100644 --- a/loader/src/internal/crashlog.cpp +++ b/loader/src/internal/crashlog.cpp @@ -53,6 +53,11 @@ void crashlog::printMods(std::stringstream& stream) { } std::string crashlog::writeCrashlog(geode::Mod* faultyMod, std::string const& info, std::string const& stacktrace, std::string const& registers) { + std::filesystem::path outPath; + return writeCrashlog(faultyMod, info, stacktrace, registers, outPath); +} + +std::string crashlog::writeCrashlog(geode::Mod* faultyMod, std::string const& info, std::string const& stacktrace, std::string const& registers, std::filesystem::path& outPath) { // make sure crashlog directory exists (void)utils::file::createDirectoryAll(crashlog::getCrashLogDirectory()); @@ -94,9 +99,10 @@ std::string crashlog::writeCrashlog(geode::Mod* faultyMod, std::string const& in printMods(file); // save actual file + outPath = crashlog::getCrashLogDirectory() / (getDateString(true) + ".log"); std::ofstream actualFile; actualFile.open( - crashlog::getCrashLogDirectory() / (getDateString(true) + ".log"), std::ios::app + outPath, std::ios::app ); actualFile << file.rdbuf() << std::flush; actualFile.close(); diff --git a/loader/src/internal/crashlog.hpp b/loader/src/internal/crashlog.hpp index 7f1c9d72..eb907b78 100644 --- a/loader/src/internal/crashlog.hpp +++ b/loader/src/internal/crashlog.hpp @@ -33,6 +33,8 @@ namespace crashlog { std::string GEODE_DLL writeCrashlog(geode::Mod* faultyMod, std::string const& info, std::string const& stacktrace, std::string const& registers); + std::string writeCrashlog(geode::Mod* faultyMod, std::string const& info, std::string const& stacktrace, std::string const& registers, std::filesystem::path& outCrashlogPath); + std::string getDateString(bool filesafe); void GEODE_DLL printGeodeInfo(std::stringstream& stream); diff --git a/loader/src/platform/windows/crashlog.cpp b/loader/src/platform/windows/crashlog.cpp index 53006c54..d2cd97ff 100644 --- a/loader/src/platform/windows/crashlog.cpp +++ b/loader/src/platform/windows/crashlog.cpp @@ -464,6 +464,7 @@ static std::string getInfo(LPEXCEPTION_POINTERS info, Mod* faultyMod, Mod* suspe static void handleException(LPEXCEPTION_POINTERS info) { std::string text; + std::filesystem::path crashlogPath; // calling SymInitialize from multiple threads can have unexpected behavior, so synchronize this part static std::mutex symMutex; @@ -492,7 +493,8 @@ static void handleException(LPEXCEPTION_POINTERS info) { faultyMod, crashInfo, stacktrace, - getRegisters(info->ContextRecord) + getRegisters(info->ContextRecord), + crashlogPath ); if (g_symbolsInitialized) { @@ -500,7 +502,13 @@ static void handleException(LPEXCEPTION_POINTERS info) { } } - MessageBoxA(nullptr, text.c_str(), "Geometry Dash Crashed", MB_ICONERROR); + // defined in crashlogWindow.cpp + extern bool showCustomCrashlogWindow(std::string text, std::filesystem::path const& crashlogPath); + + if (!showCustomCrashlogWindow(text, crashlogPath)) { + // if the window fails to show, we show a message box instead + MessageBoxA(nullptr, text.c_str(), "Geometry Dash Crashed", MB_ICONERROR); + } } static LONG WINAPI exceptionHandler(LPEXCEPTION_POINTERS info) { diff --git a/loader/src/platform/windows/crashlogWindow.cpp b/loader/src/platform/windows/crashlogWindow.cpp new file mode 100644 index 00000000..34049348 --- /dev/null +++ b/loader/src/platform/windows/crashlogWindow.cpp @@ -0,0 +1,208 @@ +#define ISOLATION_AWARE_ENABLED 1 + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +// comctl32 v6 +#pragma comment(linker, "\"/manifestdependency:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"") + +enum { + ID_CRASHLOG_TEXT = 101, + ID_BUTTON_CLOSE = 102, + ID_BUTTON_OPEN_FOLDER = 103, + ID_BUTTON_COPY_CLIPBOARD = 104, +}; +#define TO_HMENU(x) reinterpret_cast(static_cast(x)) + +namespace layout { + static constexpr int CRASHLOG_FONT_SIZE = 16; + static constexpr int BUTTON_HEIGHT = 30; + static constexpr int BUTTON_WIDTH = 120; + static constexpr int BUTTON_SPACING = 10; + + static constexpr int PADDING = 10; +} + +// dont judge +std::filesystem::path g_crashlogPath; +std::string g_crashlogText; + +LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { + switch (msg) { + case WM_CLOSE: + DestroyWindow(hwnd); + break; + case WM_DESTROY: + PostQuitMessage(0); + break; + + case WM_CREATE: { + { + // center the window + RECT desktopRect; + GetClientRect(GetDesktopWindow(), &desktopRect); + + RECT windowRect; + GetWindowRect(hwnd, &windowRect); + + auto x = desktopRect.right / 2 - (windowRect.right - windowRect.left) / 2; + auto y = desktopRect.bottom / 2 - (windowRect.bottom - windowRect.top) / 2; + + SetWindowPos(hwnd, NULL, x, y, 0, 0, SWP_NOZORDER | SWP_NOSIZE); + } + + auto monoFont = CreateFontA(layout::CRASHLOG_FONT_SIZE, 0, 0, 0, FW_DONTCARE, FALSE, FALSE, FALSE, ANSI_CHARSET, + OUT_TT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, + DEFAULT_PITCH | FF_DONTCARE, TEXT("Consolas")); + auto guiFont = static_cast(GetStockObject(DEFAULT_GUI_FONT)); + + auto handleText = CreateWindowA( + "EDIT", "Crashlog text goes here", WS_CHILD | WS_VISIBLE | WS_VSCROLL | ES_LEFT | ES_MULTILINE | ES_READONLY | ES_AUTOVSCROLL | WS_BORDER, + 0, 0, 100, 100, + hwnd, TO_HMENU(ID_CRASHLOG_TEXT), NULL, NULL + ); + SendMessage(handleText, WM_SETFONT, WPARAM(monoFont), TRUE); + // does nothing :( + Edit_SetEndOfLine(handleText, EC_ENDOFLINE_LF); + + auto button = CreateWindowA( + "BUTTON", "Close", + WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, + 0, 0, layout::BUTTON_WIDTH, layout::BUTTON_HEIGHT, + hwnd, TO_HMENU(ID_BUTTON_CLOSE), NULL, NULL + ); + SendMessage(button, WM_SETFONT, WPARAM(guiFont), TRUE); + + button = CreateWindowA( + "BUTTON", "Open crashlog folder", + WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, + 0, 0, layout::BUTTON_WIDTH, layout::BUTTON_HEIGHT, + hwnd, TO_HMENU(ID_BUTTON_OPEN_FOLDER), NULL, NULL + ); + SendMessage(button, WM_SETFONT, WPARAM(guiFont), TRUE); + + button = CreateWindowA( + "BUTTON", "Copy to clipboard", + WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, + 0, 0, layout::BUTTON_WIDTH, layout::BUTTON_HEIGHT, + hwnd, TO_HMENU(ID_BUTTON_COPY_CLIPBOARD), NULL, NULL + ); + SendMessage(button, WM_SETFONT, WPARAM(guiFont), TRUE); + } break; + + case WM_SIZE: { + RECT clientRect; + GetClientRect(hwnd, &clientRect); + + SetWindowPos( + GetDlgItem(hwnd, ID_CRASHLOG_TEXT), NULL, + layout::PADDING, layout::PADDING, + clientRect.right - layout::PADDING * 2, clientRect.bottom - layout::BUTTON_HEIGHT - layout::PADDING * 3, + SWP_NOZORDER + ); + + auto buttonY = clientRect.bottom - layout::BUTTON_HEIGHT - layout::PADDING; + SetWindowPos( + GetDlgItem(hwnd, ID_BUTTON_COPY_CLIPBOARD), NULL, + layout::PADDING, buttonY, + 0, 0, + SWP_NOZORDER | SWP_NOSIZE + ); + SetWindowPos( + GetDlgItem(hwnd, ID_BUTTON_CLOSE), NULL, + clientRect.right - layout::BUTTON_WIDTH - layout::PADDING, buttonY, + 0, 0, + SWP_NOZORDER | SWP_NOSIZE + ); + SetWindowPos( + GetDlgItem(hwnd, ID_BUTTON_OPEN_FOLDER), NULL, + clientRect.right - layout::BUTTON_WIDTH * 2 - layout::BUTTON_SPACING - layout::PADDING, buttonY, + 0, 0, + SWP_NOZORDER | SWP_NOSIZE + ); + } break; + + case WM_CTLCOLORSTATIC: { + return (LRESULT)(COLOR_WINDOWFRAME); + } break; + + case WM_COMMAND: { + auto id = LOWORD(wParam); + if (id == ID_BUTTON_CLOSE) { + DestroyWindow(hwnd); + } else if (id == ID_BUTTON_OPEN_FOLDER) { + geode::utils::file::openFolder(g_crashlogPath); + } else if (id == ID_BUTTON_COPY_CLIPBOARD) { + geode::utils::clipboard::write(g_crashlogText); + } + } break; + + default: + return DefWindowProc(hwnd, msg, wParam, lParam); + } + return 0; +} + +bool showCustomCrashlogWindow(std::string text, std::filesystem::path const& crashlogPath) { + static constexpr auto WINDOW_CLASS_NAME = "GeodeCrashHandlerWindow"; + + g_crashlogPath = crashlogPath; + g_crashlogText = text; + + // i cant get the edit control to use LF, so just replace them myself :-) + for (int i = 0; i < text.size(); ++i) { + auto c = text[i]; + if (c == '\n') { + text.insert(text.begin() + i, '\r'); + ++i; + } + } + + WNDCLASS wc = {0}; + wc.lpfnWndProc = &WndProc; + wc.hInstance = GetModuleHandleA(NULL); + wc.lpszClassName = WINDOW_CLASS_NAME; + + wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); + wc.hCursor = LoadCursor(NULL, IDC_ARROW); + wc.hbrBackground = (HBRUSH)COLOR_WINDOW; + + if (!RegisterClass(&wc)) { + return false; + } + + auto hwnd = CreateWindowExA( + 0, + WINDOW_CLASS_NAME, + "Geode Crash Handler", + WS_OVERLAPPEDWINDOW, + CW_USEDEFAULT, CW_USEDEFAULT, 800, 600, + NULL, NULL, wc.hInstance, NULL + ); + + if (hwnd == NULL) { + return false; + } + + SetWindowTextA(GetDlgItem(hwnd, ID_CRASHLOG_TEXT), text.c_str()); + + ShowWindow(hwnd, SW_SHOWNORMAL); + PlaySound((LPCTSTR)SND_ALIAS_SYSTEMDEFAULT, NULL, SND_ASYNC | SND_ALIAS_ID); + UpdateWindow(hwnd); + + MSG message; + while (GetMessage(&message, NULL, 0, 0) > 0) { + TranslateMessage(&message); + DispatchMessage(&message); + } + return true; +} From dfdb7107ddebbcc239242bc61fbc9f96bf390e86 Mon Sep 17 00:00:00 2001 From: matcool <26722564+matcool@users.noreply.github.com> Date: Sat, 20 Jul 2024 17:04:35 -0300 Subject: [PATCH 07/64] fix build --- loader/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/loader/CMakeLists.txt b/loader/CMakeLists.txt index 9595bbc6..aa886425 100644 --- a/loader/CMakeLists.txt +++ b/loader/CMakeLists.txt @@ -335,7 +335,7 @@ if (APPLE) elseif (WIN32) add_subdirectory(launcher/windows) - target_link_libraries(${PROJECT_NAME} dbghelp comctl32 uxtheme Winmm) + target_link_libraries(${PROJECT_NAME} dbghelp comctl32 uxtheme winmm) target_compile_definitions(${PROJECT_NAME} PUBLIC ISOLATION_AWARE_ENABLED=1) From 1e6d6fbcb695db4a656973956d2c985fde5ac214 Mon Sep 17 00:00:00 2001 From: matcool <26722564+matcool@users.noreply.github.com> Date: Sat, 20 Jul 2024 17:12:28 -0300 Subject: [PATCH 08/64] these arent used anymore --- loader/CMakeLists.txt | 2 +- loader/src/platform/windows/crashlogWindow.cpp | 5 +---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/loader/CMakeLists.txt b/loader/CMakeLists.txt index aa886425..51b56ae8 100644 --- a/loader/CMakeLists.txt +++ b/loader/CMakeLists.txt @@ -335,7 +335,7 @@ if (APPLE) elseif (WIN32) add_subdirectory(launcher/windows) - target_link_libraries(${PROJECT_NAME} dbghelp comctl32 uxtheme winmm) + target_link_libraries(${PROJECT_NAME} dbghelp winmm) target_compile_definitions(${PROJECT_NAME} PUBLIC ISOLATION_AWARE_ENABLED=1) diff --git a/loader/src/platform/windows/crashlogWindow.cpp b/loader/src/platform/windows/crashlogWindow.cpp index 34049348..ff076832 100644 --- a/loader/src/platform/windows/crashlogWindow.cpp +++ b/loader/src/platform/windows/crashlogWindow.cpp @@ -1,9 +1,6 @@ #define ISOLATION_AWARE_ENABLED 1 #include -#include -#include -#include #include #include @@ -72,7 +69,7 @@ LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { ); SendMessage(handleText, WM_SETFONT, WPARAM(monoFont), TRUE); // does nothing :( - Edit_SetEndOfLine(handleText, EC_ENDOFLINE_LF); + // Edit_SetEndOfLine(handleText, EC_ENDOFLINE_LF); auto button = CreateWindowA( "BUTTON", "Close", From 9924892407e1bcf13777d4f3b5203a47188f9e93 Mon Sep 17 00:00:00 2001 From: Erymanthus | RayDeeUx <51521765+RayDeeUx@users.noreply.github.com> Date: Sat, 20 Jul 2024 16:46:10 -0400 Subject: [PATCH 09/64] revise chinese translations (#997) --- installer/windows/Language Files/SimpChineseExtra.nsh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/installer/windows/Language Files/SimpChineseExtra.nsh b/installer/windows/Language Files/SimpChineseExtra.nsh index 39416bc4..5d5bea8c 100644 --- a/installer/windows/Language Files/SimpChineseExtra.nsh +++ b/installer/windows/Language Files/SimpChineseExtra.nsh @@ -8,7 +8,7 @@ ${LangFileString} MUI_UNTEXT_WELCOME_INFO_TEXT "Setup会帮您卸载$(^NameDA) ; installer ${LangFileString} GEODE_TEXT_GD_MISSING "$\r$\n$\r$\nGeometry Dash不在这文件夹,请再试一遍!" -${LangFileString} GEODE_TEXT_GD_OLD "$\r$\n$\r$\n您的Geometry Dash版本太旧了,不適合Geode的版本!" +${LangFileString} GEODE_TEXT_GD_OLD "$\r$\n$\r$\n您的Geometry Dash版本太旧了,不适合Geode的版本!" ${LangFileString} GEODE_TEXT_MOD_LOADER_ALREADY_INSTALLED "这文件夹已经安装了不同的游戏修改器加载器!$\r$\nGeode会改写那些游戏修改器加载器。 (the dll trademark)" ; uninstaller From c84be42afaa3b4c6c03ed73952dbdf27f7c9cc41 Mon Sep 17 00:00:00 2001 From: xparadoxical <43796685+xparadoxical@users.noreply.github.com> Date: Sat, 20 Jul 2024 22:50:50 +0200 Subject: [PATCH 10/64] Update Polish installer translation (#998) --- installer/windows/Language Files/PolishExtra.nsh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/installer/windows/Language Files/PolishExtra.nsh b/installer/windows/Language Files/PolishExtra.nsh index 1974e153..c3644a6d 100644 --- a/installer/windows/Language Files/PolishExtra.nsh +++ b/installer/windows/Language Files/PolishExtra.nsh @@ -8,7 +8,7 @@ ${LangFileString} MUI_UNTEXT_WELCOME_INFO_TEXT "Instalator przeprowadzi Cię prz ; installer ${LangFileString} GEODE_TEXT_GD_MISSING "$\r$\n$\r$\nGeometry Dash nie jest zainstalowane w tym folderze!" -${LangFileString} GEODE_TEXT_GD_OLD "$\r$\n$\r$\nYour version of Geometry Dash is too old for this version of Geode!" +${LangFileString} GEODE_TEXT_GD_OLD "$\r$\n$\r$\nTwoja wersja Geometry Dash jest zbyt stara dla tej wersji Geode!" ${LangFileString} GEODE_TEXT_MOD_LOADER_ALREADY_INSTALLED "W tym folderze zainstalowane są inne modyfikacje!$\r$\nZostaną one zastąpione przez Geode. (the dll trademark)" ; uninstaller From af17213798283b097cae4bac218de883ac928cd6 Mon Sep 17 00:00:00 2001 From: matcool <26722564+matcool@users.noreply.github.com> Date: Sat, 20 Jul 2024 17:56:54 -0300 Subject: [PATCH 11/64] update version and changelog --- CHANGELOG.md | 11 +++++++++++ VERSION | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 61d43dcf..7ff3966a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,16 @@ # Geode Changelog +## v3.3.0 + * Update network libraries, fixing problems with old Wine versions (e26fe95) + * Fix scale on mod logos for low quality (ba7b0fa) + * Fix platform-specific dependencies by using CLI 3.2.0 (98f82ff) + * Add `GEODE_DONT_USE_CCACHE` CMake option (2edfb71) + * Remove now useless `std::hash` impl for `std::filesystem::path` on android (2b35e0e) + * Implement custom window for showing crashlog on windows (4f32197) + * Update docs version to show v3.0.0 (f86d4db) + * Update chinese installer translation (#995, #997) + * Update polish installer translation (#998) + ## v3.2.0 * Fix auto-updater on MacOS (d752bc2) * Use tasks for `FileSettingNode` (f94e95e) diff --git a/VERSION b/VERSION index a4f52a5d..0fa4ae48 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -3.2.0 \ No newline at end of file +3.3.0 \ No newline at end of file From 61e000daa0292477ceba1ffd171a049954d77678 Mon Sep 17 00:00:00 2001 From: matcool <26722564+matcool@users.noreply.github.com> Date: Sat, 20 Jul 2024 18:16:06 -0300 Subject: [PATCH 12/64] check hash for downloaded mods --- loader/hash/hash.cpp | 6 ++++-- loader/hash/hash.hpp | 7 ++++++- loader/src/server/DownloadManager.cpp | 11 ++++++++++- 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/loader/hash/hash.cpp b/loader/hash/hash.cpp index 2b60276e..5757b778 100644 --- a/loader/hash/hash.cpp +++ b/loader/hash/hash.cpp @@ -52,6 +52,8 @@ std::string calculateSHA256Text(std::filesystem::path const& path) { return picosha2::bytes_to_hex_string(hash.begin(), hash.end()); } -std::string calculateHash(std::filesystem::path const& path) { - return calculateSHA3_256(path); +std::string calculateHash(std::span data) { + std::vector hash(picosha2::k_digest_size); + picosha2::hash256(data.begin(), data.end(), hash); + return picosha2::bytes_to_hex_string(hash.begin(), hash.end()); } \ No newline at end of file diff --git a/loader/hash/hash.hpp b/loader/hash/hash.hpp index 06d7adec..5b517c48 100644 --- a/loader/hash/hash.hpp +++ b/loader/hash/hash.hpp @@ -2,6 +2,7 @@ #include #include +#include std::string calculateSHA3_256(std::filesystem::path const& path); @@ -9,4 +10,8 @@ std::string calculateSHA256(std::filesystem::path const& path); std::string calculateSHA256Text(std::filesystem::path const& path); -std::string calculateHash(std::filesystem::path const& path); +/** + * Calculates the SHA256 hash of the given data, + * used for verifying mods. + */ +std::string calculateHash(std::span data); diff --git a/loader/src/server/DownloadManager.cpp b/loader/src/server/DownloadManager.cpp index 5d89316d..ee16fe2d 100644 --- a/loader/src/server/DownloadManager.cpp +++ b/loader/src/server/DownloadManager.cpp @@ -3,6 +3,7 @@ #include #include #include +#include using namespace server; @@ -103,8 +104,16 @@ public: m_downloadListener.bind([this, hash = version.hash](web::WebTask::Event* event) { if (auto value = event->getValue()) { if (value->ok()) { + if (auto actualHash = ::calculateHash(value->data()); actualHash != hash) { + log::error("Failed to download {}, hash mismatch ({} != {})", m_id, actualHash, hash); + m_status = DownloadStatusError { + .details = "Hash mismatch, downloaded file did not match what was expected", + }; + ModDownloadEvent(m_id).post(); + return; + } + bool removingInstalledWasError = false; - bool disablingReplacedWasError = false; std::string id = m_replacesMod.has_value() ? m_replacesMod.value() : m_id; if (auto mod = Loader::get()->getInstalledMod(id)) { std::error_code ec; From ecc83ca3596edb1c5e152a7a510b742ff7108cbf Mon Sep 17 00:00:00 2001 From: matcool <26722564+matcool@users.noreply.github.com> Date: Sat, 20 Jul 2024 18:18:03 -0300 Subject: [PATCH 13/64] update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7ff3966a..2aaaf52c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ * Remove now useless `std::hash` impl for `std::filesystem::path` on android (2b35e0e) * Implement custom window for showing crashlog on windows (4f32197) * Update docs version to show v3.0.0 (f86d4db) + * Check hash for downloaded mods (61e000d) * Update chinese installer translation (#995, #997) * Update polish installer translation (#998) From fc544f9144780a29921a59eb2b3551a684ebcbe6 Mon Sep 17 00:00:00 2001 From: dankmeme01 <42031238+dankmeme01@users.noreply.github.com> Date: Sun, 21 Jul 2024 20:25:01 +0200 Subject: [PATCH 14/64] fix ccparticlesystem virtuals --- .../include/Geode/cocos/particle_nodes/CCParticleSystem.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/loader/include/Geode/cocos/particle_nodes/CCParticleSystem.h b/loader/include/Geode/cocos/particle_nodes/CCParticleSystem.h index f31ccdce..fe60d137 100644 --- a/loader/include/Geode/cocos/particle_nodes/CCParticleSystem.h +++ b/loader/include/Geode/cocos/particle_nodes/CCParticleSystem.h @@ -265,6 +265,9 @@ protected: ////////////////////////////////////////////////////////////////////////// public: + // @note RobTop Addition + virtual void updateEmissionRate(); + // mode A virtual const CCPoint& getGravity(); virtual void setGravity(const CCPoint& g); @@ -630,9 +633,6 @@ public: void toggleUniformColorMode(bool); // @note RobTop Addition void updateVisible(); - - // @note RobTop Addition - virtual void updateEmissionRate(); }; // end of particle_nodes group From 95f9eeb187ce25c8f1304e063b5f4990a6aad473 Mon Sep 17 00:00:00 2001 From: Cvolton Date: Wed, 24 Jul 2024 05:00:54 -0700 Subject: [PATCH 15/64] add objectdecoder (#1012) --- loader/include/Geode/cocos/include/cocos2d.h | 1 + .../Geode/cocos/robtop/xml/ObjectDecoder.h | 20 +++++++++++++++++++ 2 files changed, 21 insertions(+) create mode 100644 loader/include/Geode/cocos/robtop/xml/ObjectDecoder.h diff --git a/loader/include/Geode/cocos/include/cocos2d.h b/loader/include/Geode/cocos/include/cocos2d.h index 215aa4ae..f2426f06 100644 --- a/loader/include/Geode/cocos/include/cocos2d.h +++ b/loader/include/Geode/cocos/include/cocos2d.h @@ -326,6 +326,7 @@ THE SOFTWARE. #include "../robtop/scene_nodes/CCSceneTransitionDelegate.h" #include "../robtop/xml/DS_Dictionary.h" +#include "../robtop/xml/ObjectDecoder.h" // #include "../robtop/glfw/glfw3.h" diff --git a/loader/include/Geode/cocos/robtop/xml/ObjectDecoder.h b/loader/include/Geode/cocos/robtop/xml/ObjectDecoder.h new file mode 100644 index 00000000..782ac30e --- /dev/null +++ b/loader/include/Geode/cocos/robtop/xml/ObjectDecoder.h @@ -0,0 +1,20 @@ +#ifndef __OBJECTDECODER_H__ +#define __OBJECTDECODER_H__ + +#include "../../include/cocos2d.h" + +// @note RobTop Addition +class CC_DLL ObjectDecoder { +public: + ObjectDecoder(); + ~ObjectDecoder() {} + GEODE_CUSTOM_CONSTRUCTOR_BEGIN(ObjectDecoder) + + static ObjectDecoder* sharedDecoder(); + + cocos2d::CCObject* getDecodedObject(int, DS_Dictionary*); + + virtual bool init(); +}; + +#endif From 49c8d386a9c77bb0364b54c9ac16138b67d56aba Mon Sep 17 00:00:00 2001 From: Cvolton Date: Wed, 24 Jul 2024 15:48:33 +0200 Subject: [PATCH 16/64] fix objectdecoder inheritance --- loader/include/Geode/cocos/robtop/xml/ObjectDecoder.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/loader/include/Geode/cocos/robtop/xml/ObjectDecoder.h b/loader/include/Geode/cocos/robtop/xml/ObjectDecoder.h index 782ac30e..9162d1fa 100644 --- a/loader/include/Geode/cocos/robtop/xml/ObjectDecoder.h +++ b/loader/include/Geode/cocos/robtop/xml/ObjectDecoder.h @@ -4,7 +4,7 @@ #include "../../include/cocos2d.h" // @note RobTop Addition -class CC_DLL ObjectDecoder { +class CC_DLL ObjectDecoder : public cocos2d::CCNode { public: ObjectDecoder(); ~ObjectDecoder() {} From 4272b8b549b070048c6ff552d7cb955f41fb33b0 Mon Sep 17 00:00:00 2001 From: Cvolton Date: Wed, 24 Jul 2024 19:41:52 +0200 Subject: [PATCH 17/64] fix missing include in terminate header --- loader/include/Geode/utils/terminate.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/loader/include/Geode/utils/terminate.hpp b/loader/include/Geode/utils/terminate.hpp index ceed11d7..b9f44d0d 100644 --- a/loader/include/Geode/utils/terminate.hpp +++ b/loader/include/Geode/utils/terminate.hpp @@ -1,6 +1,7 @@ #pragma once #include "../DefaultInclude.hpp" +#include namespace geode { class Mod; From 2cd1a9ee265c6ecfbe882ab5432b1efd6f8a93a0 Mon Sep 17 00:00:00 2001 From: matcool <26722564+matcool@users.noreply.github.com> Date: Wed, 24 Jul 2024 19:21:35 -0300 Subject: [PATCH 18/64] use C locale instead of en_us.utf8 TODO: replace these with numFromString instead :P --- loader/src/loader/ModMetadataImpl.cpp | 2 +- loader/src/ui/mods/settings/GeodeSettingNode.cpp | 2 +- loader/src/ui/nodes/ColorPickPopup.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/loader/src/loader/ModMetadataImpl.cpp b/loader/src/loader/ModMetadataImpl.cpp index c689bc26..f9f7cbc8 100644 --- a/loader/src/loader/ModMetadataImpl.cpp +++ b/loader/src/loader/ModMetadataImpl.cpp @@ -151,7 +151,7 @@ Result ModMetadata::Impl::createFromSchemaV010(ModJson const& rawJs if (ver != "*") { double val = 0.0; errno = 0; - if (std::setlocale(LC_NUMERIC, "en_US.utf8")) { + if (std::setlocale(LC_NUMERIC, "C")) { val = std::strtod(ver.c_str(), nullptr); if (errno == ERANGE) { return Err("[mod.json] has invalid target GD version"); diff --git a/loader/src/ui/mods/settings/GeodeSettingNode.cpp b/loader/src/ui/mods/settings/GeodeSettingNode.cpp index 90ad665e..e07dbfd1 100644 --- a/loader/src/ui/mods/settings/GeodeSettingNode.cpp +++ b/loader/src/ui/mods/settings/GeodeSettingNode.cpp @@ -27,7 +27,7 @@ Num parseNumForInput(std::string const& str) { else if constexpr (std::is_same_v) { double val = 0.0; errno = 0; - if (std::setlocale(LC_NUMERIC, "en_US.utf8")) { + if (std::setlocale(LC_NUMERIC, "C")) { val = std::strtod(str.c_str(), nullptr); if (errno == 0) { return val; diff --git a/loader/src/ui/nodes/ColorPickPopup.cpp b/loader/src/ui/nodes/ColorPickPopup.cpp index 49f5d1bf..da8cde82 100644 --- a/loader/src/ui/nodes/ColorPickPopup.cpp +++ b/loader/src/ui/nodes/ColorPickPopup.cpp @@ -22,7 +22,7 @@ static GLubyte parseInt(char const* str) { static GLubyte parseFloat(char const* str) { float val = 0.0f; errno = 0; - if (std::setlocale(LC_NUMERIC, "en_US.utf8")) { + if (std::setlocale(LC_NUMERIC, "C")) { val = std::strtof(str, nullptr); if (errno == 0) { return val; From 006ede8f34cd8f9b530d8f12f75b6a775999f5a7 Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Thu, 25 Jul 2024 15:17:35 +0300 Subject: [PATCH 19/64] replace all c number parsing with numFromString --- loader/src/loader/ModMetadataImpl.cpp | 17 ++++--- loader/src/platform/android/crashlog.cpp | 6 ++- .../src/ui/mods/settings/GeodeSettingNode.cpp | 34 +++---------- loader/src/ui/nodes/ColorPickPopup.cpp | 50 ++++++++----------- loader/src/ui/nodes/MDTextArea.cpp | 27 ++++------ loader/src/utils/cocos.cpp | 12 ++--- loader/src/utils/web.cpp | 8 ++- 7 files changed, 65 insertions(+), 89 deletions(-) diff --git a/loader/src/loader/ModMetadataImpl.cpp b/loader/src/loader/ModMetadataImpl.cpp index f9f7cbc8..cacc4aa6 100644 --- a/loader/src/loader/ModMetadataImpl.cpp +++ b/loader/src/loader/ModMetadataImpl.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -149,13 +150,9 @@ Result ModMetadata::Impl::createFromSchemaV010(ModJson const& rawJs ver = "0.000"; } if (ver != "*") { - double val = 0.0; - errno = 0; - if (std::setlocale(LC_NUMERIC, "C")) { - val = std::strtod(ver.c_str(), nullptr); - if (errno == ERANGE) { - return Err("[mod.json] has invalid target GD version"); - } + auto res = numFromString(ver); + if (res.isErr()) { + return Err("[mod.json] has invalid target GD version"); } impl->m_gdVersion = ver; } @@ -567,7 +564,11 @@ Result<> ModMetadata::checkGameVersion() const { if (!m_impl->m_gdVersion.empty()) { auto const ver = m_impl->m_gdVersion; - double modTargetVer = std::stod(ver); + auto res = numFromString(ver); + if (res.isErr()) { + return Err("Invalid target GD version"); + } + double modTargetVer = res.unwrap(); if (modTargetVer == 0.0) { // O.o return Err(fmt::format("This mod doesn't support the current platform.")); diff --git a/loader/src/platform/android/crashlog.cpp b/loader/src/platform/android/crashlog.cpp index 27aad0b3..392b23e0 100644 --- a/loader/src/platform/android/crashlog.cpp +++ b/loader/src/platform/android/crashlog.cpp @@ -264,7 +264,11 @@ int writeAndGetPid() { log::warn("Failed to read last-pid file: {}", res.error()); } else { - lastPid = std::stoi(res.unwrap()); + auto res = numFromString(res.unwrap()); + if (!res) { + log::warn("Failed to parse last-pid file: {}", res.error()); + } + else lastPid = res.unwrap(); } std::error_code ec; diff --git a/loader/src/ui/mods/settings/GeodeSettingNode.cpp b/loader/src/ui/mods/settings/GeodeSettingNode.cpp index e07dbfd1..ef6cb388 100644 --- a/loader/src/ui/mods/settings/GeodeSettingNode.cpp +++ b/loader/src/ui/mods/settings/GeodeSettingNode.cpp @@ -9,37 +9,13 @@ #include #include #include +#include #include #include #include // Helpers -template -Num parseNumForInput(std::string const& str) { - if constexpr (std::is_same_v) { - int64_t i = 0; - auto res = std::from_chars(str.data(), str.data() + str.size(), i); - if (res.ec == std::errc()) { - return i; - } - } - else if constexpr (std::is_same_v) { - double val = 0.0; - errno = 0; - if (std::setlocale(LC_NUMERIC, "C")) { - val = std::strtod(str.c_str(), nullptr); - if (errno == 0) { - return val; - } - } - } - else { - static_assert(!std::is_same_v, "Impl Num for parseNumForInput"); - } - return 0; -} - template static float valueToSlider(T const& setting, typename T::ValueType value) { auto min = setting.min ? setting.min.value() : -100; @@ -193,7 +169,9 @@ void IntSettingNode::onArrow(CCObject* sender) { } void IntSettingNode::textChanged(CCTextInputNode* input) { - m_uncommittedValue = parseNumForInput(input->getString()); + auto res = numFromString(input->getString()); + if (!res) return; + m_uncommittedValue = res.unwrap(); this->valueChanged(false); } @@ -275,7 +253,9 @@ void FloatSettingNode::onArrow(CCObject* sender) { } void FloatSettingNode::textChanged(CCTextInputNode* input) { - m_uncommittedValue = parseNumForInput(input->getString()); + auto res = numFromString(input->getString()); + if (!res) return; + m_uncommittedValue = res.unwrap(); this->valueChanged(false); } diff --git a/loader/src/ui/nodes/ColorPickPopup.cpp b/loader/src/ui/nodes/ColorPickPopup.cpp index da8cde82..01083a6f 100644 --- a/loader/src/ui/nodes/ColorPickPopup.cpp +++ b/loader/src/ui/nodes/ColorPickPopup.cpp @@ -10,27 +10,6 @@ using namespace geode::prelude; -static GLubyte parseInt(char const* str) { - int i = 0; - auto res = std::from_chars(str, str + strlen(str), i); - if (res.ec == std::errc()) { - return static_cast(i); - } - return 255; -} - -static GLubyte parseFloat(char const* str) { - float val = 0.0f; - errno = 0; - if (std::setlocale(LC_NUMERIC, "C")) { - val = std::strtof(str, nullptr); - if (errno == 0) { - return val; - } - } - return 255.f; -} - bool ColorPickPopup::setup(ccColor4B const& color, bool isRGBA) { m_noElasticity = true; m_color = color; @@ -307,8 +286,7 @@ bool ColorPickPopup::setup(ccColor4B const& color, bool isRGBA) { sliderWrapper->addChildAtPosition(m_opacitySlider, Anchor::Center, ccp(0, 0)); sliderColumn->addChild(sliderWrapper); - m_opacityInput = TextInput::create(60.f, "0.00"); - m_opacityInput->setPosition(85.f, -95.f); + m_opacityInput = TextInput::create(60.f, "Opacity"); m_opacityInput->setScale(.7f); m_opacityInput->setDelegate(this, TAG_OPACITY_INPUT); m_opacityInput->setID("opacity-input"); @@ -382,15 +360,27 @@ void ColorPickPopup::textChanged(CCTextInputNode* input) { } break; - case TAG_OPACITY_INPUT: - { - m_color.a = parseFloat(input->getString().c_str()); - } + case TAG_OPACITY_INPUT: { + auto res = numFromString(input->getString().c_str()); + if (res) m_color.a = std::clamp(static_cast(res.unwrap() * 255.f), 0, 255); break; + } - case TAG_R_INPUT: m_color.r = parseInt(input->getString().c_str()); break; - case TAG_G_INPUT: m_color.g = parseInt(input->getString().c_str()); break; - case TAG_B_INPUT: m_color.b = parseInt(input->getString().c_str()); break; + case TAG_R_INPUT: { + auto res = numFromString(input->getString().c_str()); + if (res) m_color.r = std::clamp(res.unwrap(), 0u, 255u); + break; + } + case TAG_G_INPUT: { + auto res = numFromString(input->getString().c_str()); + if (res) m_color.g = std::clamp(res.unwrap(), 0u, 255u); + break; + } + case TAG_B_INPUT: { + auto res = numFromString(input->getString().c_str()); + if (res) m_color.b = std::clamp(res.unwrap(), 0u, 255u); + break; + } default: break; } diff --git a/loader/src/ui/nodes/MDTextArea.cpp b/loader/src/ui/nodes/MDTextArea.cpp index 3f09f771..2023f00f 100644 --- a/loader/src/ui/nodes/MDTextArea.cpp +++ b/loader/src/ui/nodes/MDTextArea.cpp @@ -79,12 +79,11 @@ public: Result colorForIdentifier(std::string const& tag) { if (utils::string::contains(tag, ' ')) { auto hexStr = utils::string::split(utils::string::normalize(tag), " ").at(1); - int hex = 0; - auto res = std::from_chars(hexStr.data(), hexStr.data() + hexStr.size(), hex, 16); - if (res.ec != std::errc()) { + auto res = numFromString(hexStr, 16); + if (res.isErr()) { return Err("Invalid hex"); } - return Ok(cc3x(hex)); + return Ok(cc3x(res.unwrap())); } else { auto colorText = tag.substr(1); @@ -190,40 +189,36 @@ void MDTextArea::onGDProfile(CCObject* pSender) { auto href = as(as(pSender)->getUserObject()); auto profile = std::string(href->getCString()); profile = profile.substr(profile.find(":") + 1); - int id = 0; - auto res = std::from_chars(profile.data(), profile.data() + profile.size(), id); - if (res.ec != std::errc()) { + auto res = numFromString(profile); + if (res.isErr()) { FLAlertLayer::create( "Error", "Invalid profile ID: " + profile + ". This is " "probably the mod developer's fault, report the bug to them.", "OK" - ) - ->show(); + )->show(); return; } - ProfilePage::create(id, false)->show(); + ProfilePage::create(res.unwrap(), false)->show(); } void MDTextArea::onGDLevel(CCObject* pSender) { auto href = as(as(pSender)->getUserObject()); auto level = std::string(href->getCString()); level = level.substr(level.find(":") + 1); - int id = 0; - auto res = std::from_chars(level.data(), level.data() + level.size(), id); - if (res.ec != std::errc()) { + auto res = numFromString(level); + if (res.isErr()) { FLAlertLayer::create( "Error", "Invalid level ID: " + level + ". This is " "probably the mod developers's fault, report the bug to them.", "OK" - ) - ->show(); + )->show(); return; } - auto searchObject = GJSearchObject::create(SearchType::Type19, fmt::format("{}&gameVersion=22", id)); + auto searchObject = GJSearchObject::create(SearchType::Type19, fmt::format("{}&gameVersion=22", res.unwrap())); auto scene = LevelBrowserLayer::scene(searchObject); CCDirector::sharedDirector()->replaceScene(CCTransitionFade::create(0.5f, scene)); } diff --git a/loader/src/utils/cocos.cpp b/loader/src/utils/cocos.cpp index b1018f42..f1400e7a 100644 --- a/loader/src/utils/cocos.cpp +++ b/loader/src/utils/cocos.cpp @@ -131,11 +131,11 @@ Result geode::cocos::cc3bFromHexString(std::string const& rawHexValue if (hexValue.size() > 6) { return Err("Hex value too large"); } - size_t numValue; - auto res = std::from_chars(hexValue.data(), hexValue.data() + hexValue.size(), numValue, 16); - if (res.ec != std::errc()) { + auto res = numFromString(hexValue, 16); + if (!res) { return Err("Invalid hex value '{}'", hexValue); } + auto numValue = res.unwrap(); switch (hexValue.size()) { case 6: { auto r = static_cast((numValue & 0xFF0000) >> 16); @@ -189,11 +189,11 @@ Result geode::cocos::cc4bFromHexString(std::string const& rawHexValue if (hexValue.size() > 8) { return Err("Hex value too large"); } - size_t numValue; - auto res = std::from_chars(hexValue.data(), hexValue.data() + hexValue.size(), numValue, 16); - if (res.ec != std::errc()) { + auto res = numFromString(hexValue, 16); + if (!res) { return Err("Invalid hex value '{}'", hexValue); } + auto numValue = res.unwrap(); switch (hexValue.size()) { case 8: { auto r = static_cast((numValue & 0xFF000000) >> 24); diff --git a/loader/src/utils/web.cpp b/loader/src/utils/web.cpp index 66405463..bc789c39 100644 --- a/loader/src/utils/web.cpp +++ b/loader/src/utils/web.cpp @@ -488,7 +488,13 @@ WebRequest& WebRequest::header(std::string_view name, std::string_view value) { const size_t comma = value.find(',', numStart); const size_t numLength = (comma == std::string::npos ? value.size() : comma) - numStart; - timeout(std::chrono::seconds(std::stol(std::string(value.substr(numStart, numLength))))); + int timeoutValue = 5; + auto res = numFromString(value.substr(numStart, numLength)); + if (res) { + timeoutValue = res.value(); + } + + timeout(std::chrono::seconds(timeoutValue)); return *this; } From 82bfe290b0b5a3c43528b50c2feeaa6bbc4fed19 Mon Sep 17 00:00:00 2001 From: Chloe <25387744+qimiko@users.noreply.github.com> Date: Thu, 25 Jul 2024 05:24:27 -0700 Subject: [PATCH 20/64] update dump_syms --- .github/actions/setup-dump-sym/action.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/setup-dump-sym/action.yml b/.github/actions/setup-dump-sym/action.yml index edf9d700..5f408550 100644 --- a/.github/actions/setup-dump-sym/action.yml +++ b/.github/actions/setup-dump-sym/action.yml @@ -5,7 +5,7 @@ inputs: dump_syms_version: description: "Revision of mozilla/dump_syms repository to fetch" required: true - default: "v2.2.2" + default: "v2.3.3" outputs: binary-path: description: "Path of the dump_syms utility, including the executable." From fc14b302626d0c899d89f1fc43cb446f7c971133 Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Thu, 25 Jul 2024 15:26:16 +0300 Subject: [PATCH 21/64] update changelog and version --- CHANGELOG.md | 5 +++++ VERSION | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2aaaf52c..f8d62ba1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Geode Changelog +## v3.3.1 + * Move ObjectDecoder to Cocos headers (95f9eeb) + * Fix weird behavior with textures, objects and more by changing en-US.utf8 locale to C (2cd1a9e) + * Change all C number parsing to use `numFromString` to further remove the risk of this happening again (006ede8) + ## v3.3.0 * Update network libraries, fixing problems with old Wine versions (e26fe95) * Fix scale on mod logos for low quality (ba7b0fa) diff --git a/VERSION b/VERSION index 0fa4ae48..712bd5a6 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -3.3.0 \ No newline at end of file +3.3.1 \ No newline at end of file From 4266a82a56791b122e3373002c88d44d1f6e7376 Mon Sep 17 00:00:00 2001 From: Chloe <25387744+qimiko@users.noreply.github.com> Date: Thu, 25 Jul 2024 05:43:38 -0700 Subject: [PATCH 22/64] update minizip-ng to latest commit this fixes an issue in which some compilers may complain about gz_intmax not being defined - this is intentional to match rob's version of zlib on windows --- loader/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/loader/CMakeLists.txt b/loader/CMakeLists.txt index 51b56ae8..33376e25 100644 --- a/loader/CMakeLists.txt +++ b/loader/CMakeLists.txt @@ -249,7 +249,7 @@ if (NOT GEODE_BUILDING_DOCS) set(MZ_FETCH_LIBS ON CACHE INTERNAL "" FORCE) set(MZ_FORCE_FETCH_LIBS ${WIN32} CACHE INTERNAL "") set(SKIP_INSTALL_ALL ON CACHE INTERNAL "") - CPMAddPackage("gh:geode-sdk/minizip-ng#7548419") + CPMAddPackage("gh:geode-sdk/minizip-ng#43d9254") if (WIN32) set_target_properties(zlib PROPERTIES SUFFIX "1.dll") endif() From 509c5e7e93a8bc1159f078daf8be2e49ca0a47e9 Mon Sep 17 00:00:00 2001 From: Chloe <25387744+qimiko@users.noreply.github.com> Date: Thu, 25 Jul 2024 06:58:44 -0700 Subject: [PATCH 23/64] add objectdecoderdelegate for objectdecoder --- loader/include/Geode/cocos/robtop/xml/ObjectDecoder.h | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/loader/include/Geode/cocos/robtop/xml/ObjectDecoder.h b/loader/include/Geode/cocos/robtop/xml/ObjectDecoder.h index 9162d1fa..c2833216 100644 --- a/loader/include/Geode/cocos/robtop/xml/ObjectDecoder.h +++ b/loader/include/Geode/cocos/robtop/xml/ObjectDecoder.h @@ -3,18 +3,26 @@ #include "../../include/cocos2d.h" +// @note RobTop Addition +class CC_DLL ObjectDecoderDelegate { + virtual cocos2d::CCObject* getDecodedObject(int, DS_Dictionary*) { return nullptr; } +}; + // @note RobTop Addition class CC_DLL ObjectDecoder : public cocos2d::CCNode { public: ObjectDecoder(); ~ObjectDecoder() {} - GEODE_CUSTOM_CONSTRUCTOR_BEGIN(ObjectDecoder) + GEODE_CUSTOM_CONSTRUCTOR_BEGIN(ObjectDecoder) static ObjectDecoder* sharedDecoder(); cocos2d::CCObject* getDecodedObject(int, DS_Dictionary*); virtual bool init(); + +public: + ObjectDecoderDelegate* m_delegate; }; #endif From 057bb7a44d1e58776b3a0ae3a3640e680c3bce85 Mon Sep 17 00:00:00 2001 From: Chloe <25387744+qimiko@users.noreply.github.com> Date: Thu, 25 Jul 2024 07:13:26 -0700 Subject: [PATCH 24/64] undo everything part 2 --- loader/include/Geode/cocos/robtop/xml/ObjectDecoder.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/loader/include/Geode/cocos/robtop/xml/ObjectDecoder.h b/loader/include/Geode/cocos/robtop/xml/ObjectDecoder.h index c2833216..f0a09ca5 100644 --- a/loader/include/Geode/cocos/robtop/xml/ObjectDecoder.h +++ b/loader/include/Geode/cocos/robtop/xml/ObjectDecoder.h @@ -4,9 +4,13 @@ #include "../../include/cocos2d.h" // @note RobTop Addition +/* +// TODO: uncomment just before 3.3.1 releases, it requires a change in bindings/codegen as well class CC_DLL ObjectDecoderDelegate { +public: virtual cocos2d::CCObject* getDecodedObject(int, DS_Dictionary*) { return nullptr; } }; +*/ // @note RobTop Addition class CC_DLL ObjectDecoder : public cocos2d::CCNode { From d13b1dc2697a134d7e2a054e48a855e8e190932e Mon Sep 17 00:00:00 2001 From: Chloe <25387744+qimiko@users.noreply.github.com> Date: Thu, 25 Jul 2024 07:14:01 -0700 Subject: [PATCH 25/64] =?UTF-8?q?actually=20no=20i=20forgot=20one=20thing?= =?UTF-8?q?=20=F0=9F=98=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- loader/include/Geode/cocos/robtop/xml/ObjectDecoder.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/loader/include/Geode/cocos/robtop/xml/ObjectDecoder.h b/loader/include/Geode/cocos/robtop/xml/ObjectDecoder.h index f0a09ca5..5a14d9b5 100644 --- a/loader/include/Geode/cocos/robtop/xml/ObjectDecoder.h +++ b/loader/include/Geode/cocos/robtop/xml/ObjectDecoder.h @@ -25,8 +25,10 @@ public: virtual bool init(); +/* public: ObjectDecoderDelegate* m_delegate; +*/ }; #endif From dceb91e181e408793c60bc3b69d38334e789cfa9 Mon Sep 17 00:00:00 2001 From: Chloe <25387744+qimiko@users.noreply.github.com> Date: Thu, 25 Jul 2024 17:11:37 -0700 Subject: [PATCH 26/64] he can go back now :D --- loader/include/Geode/cocos/robtop/xml/ObjectDecoder.h | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/loader/include/Geode/cocos/robtop/xml/ObjectDecoder.h b/loader/include/Geode/cocos/robtop/xml/ObjectDecoder.h index 5a14d9b5..c9c33c92 100644 --- a/loader/include/Geode/cocos/robtop/xml/ObjectDecoder.h +++ b/loader/include/Geode/cocos/robtop/xml/ObjectDecoder.h @@ -4,13 +4,10 @@ #include "../../include/cocos2d.h" // @note RobTop Addition -/* -// TODO: uncomment just before 3.3.1 releases, it requires a change in bindings/codegen as well class CC_DLL ObjectDecoderDelegate { public: - virtual cocos2d::CCObject* getDecodedObject(int, DS_Dictionary*) { return nullptr; } + virtual cocos2d::CCObject* getDecodedObject(int objectType, DS_Dictionary* data) { return nullptr; } }; -*/ // @note RobTop Addition class CC_DLL ObjectDecoder : public cocos2d::CCNode { @@ -25,10 +22,8 @@ public: virtual bool init(); -/* public: ObjectDecoderDelegate* m_delegate; -*/ }; #endif From 29dba46f1e56603c7ca135617729f83d21a75cf5 Mon Sep 17 00:00:00 2001 From: Chloe <25387744+qimiko@users.noreply.github.com> Date: Thu, 25 Jul 2024 17:47:14 -0700 Subject: [PATCH 27/64] add the delegate to changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f8d62ba1..7425986c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ # Geode Changelog ## v3.3.1 - * Move ObjectDecoder to Cocos headers (95f9eeb) + * Move ObjectDecoder and its delegate to Cocos headers (95f9eeb, dceb91e) * Fix weird behavior with textures, objects and more by changing en-US.utf8 locale to C (2cd1a9e) * Change all C number parsing to use `numFromString` to further remove the risk of this happening again (006ede8) From 72586f780dc47a98dd58ffd2ce5bd5c29c7726d7 Mon Sep 17 00:00:00 2001 From: SMJSGaming Date: Sat, 27 Jul 2024 19:53:07 +0200 Subject: [PATCH 28/64] Added remove methods to the web API --- loader/include/Geode/utils/web.hpp | 2 ++ loader/src/utils/web.cpp | 10 ++++++++++ 2 files changed, 12 insertions(+) diff --git a/loader/include/Geode/utils/web.hpp b/loader/include/Geode/utils/web.hpp index de85e720..0ad58d45 100644 --- a/loader/include/Geode/utils/web.hpp +++ b/loader/include/Geode/utils/web.hpp @@ -125,11 +125,13 @@ namespace geode::utils::web { WebTask patch(std::string_view url); WebRequest& header(std::string_view name, std::string_view value); + WebRequest& removeHeader(std::string_view name); WebRequest& param(std::string_view name, std::string_view value); template WebRequest& param(std::string_view name, T value) { return this->param(name, std::to_string(value)); } + WebRequest& removeParam(std::string_view name); /** * Sets the request's user agent. diff --git a/loader/src/utils/web.cpp b/loader/src/utils/web.cpp index bc789c39..3a352edb 100644 --- a/loader/src/utils/web.cpp +++ b/loader/src/utils/web.cpp @@ -505,11 +505,21 @@ WebRequest& WebRequest::header(std::string_view name, std::string_view value) { return *this; } +WebRequest& WebRequest::removeHeader(std::string_view name) { + m_impl->m_headers.erase(std::string(name)); + return *this; +} + WebRequest& WebRequest::param(std::string_view name, std::string_view value) { m_impl->m_urlParameters.insert_or_assign(std::string(name), std::string(value)); return *this; } +WebRequest& WebRequest::removeParam(std::string_view name) { + m_impl->m_urlParameters.erase(std::string(name)); + return *this; +} + WebRequest& WebRequest::userAgent(std::string_view name) { m_impl->m_userAgent = name; return *this; From caeef8f4a48343d076ac352d562235ac387841d0 Mon Sep 17 00:00:00 2001 From: SMJSGaming Date: Sun, 28 Jul 2024 16:16:41 +0200 Subject: [PATCH 29/64] Changed the operator overloads of CCPoint to be more inline with other engines --- loader/include/Geode/utils/cocos.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/loader/include/Geode/utils/cocos.hpp b/loader/include/Geode/utils/cocos.hpp index 851e1451..3e9d7445 100644 --- a/loader/include/Geode/utils/cocos.hpp +++ b/loader/include/Geode/utils/cocos.hpp @@ -149,16 +149,16 @@ namespace cocos2d { return s1.width != s2.width || s1.height != s2.height; } static bool operator<(cocos2d::CCSize const& s1, cocos2d::CCSize const& s2) { - return s1.width < s2.width || s1.height < s2.height; + return s1.width < s2.width && s1.height < s2.height; } static bool operator<=(cocos2d::CCSize const& s1, cocos2d::CCSize const& s2) { - return s1.width <= s2.width || s1.height <= s2.height; + return s1.width <= s2.width && s1.height <= s2.height; } static bool operator>(cocos2d::CCSize const& s1, cocos2d::CCSize const& s2) { - return s1.width > s2.width || s1.height > s2.height; + return s1.width > s2.width && s1.height > s2.height; } static bool operator>=(cocos2d::CCSize const& s1, cocos2d::CCSize const& s2) { - return s1.width >= s2.width || s1.height >= s2.height; + return s1.width >= s2.width && s1.height >= s2.height; } static bool operator==(cocos2d::CCRect const& r1, cocos2d::CCRect const& r2) { return r1.origin == r2.origin && r1.size == r2.size; From 0ef7d6e07500030b058914580c8255c09a0f507f Mon Sep 17 00:00:00 2001 From: MarioMastr <84964352+MarioMastr@users.noreply.github.com> Date: Sun, 28 Jul 2024 22:19:00 +0100 Subject: [PATCH 30/64] add custom_constructor to ccglprogram (#1009) --- loader/include/Geode/cocos/shaders/CCGLProgram.h | 1 + 1 file changed, 1 insertion(+) diff --git a/loader/include/Geode/cocos/shaders/CCGLProgram.h b/loader/include/Geode/cocos/shaders/CCGLProgram.h index 7ca4b01e..8aa8f66c 100644 --- a/loader/include/Geode/cocos/shaders/CCGLProgram.h +++ b/loader/include/Geode/cocos/shaders/CCGLProgram.h @@ -107,6 +107,7 @@ public: * @lua NA */ CCGLProgram(); + GEODE_CUSTOM_CONSTRUCTOR_COCOS(CCGLProgram, CCObject); /** * @js NA * @lua NA From f4898789527f201d95ec0ec8419f7f1e673f4614 Mon Sep 17 00:00:00 2001 From: alk <45172705+altalk23@users.noreply.github.com> Date: Mon, 29 Jul 2024 00:56:35 +0300 Subject: [PATCH 31/64] Update JapaneseExtra.nsh --- installer/windows/Language Files/JapaneseExtra.nsh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/installer/windows/Language Files/JapaneseExtra.nsh b/installer/windows/Language Files/JapaneseExtra.nsh index 164df676..4cdb9435 100644 --- a/installer/windows/Language Files/JapaneseExtra.nsh +++ b/installer/windows/Language Files/JapaneseExtra.nsh @@ -8,7 +8,7 @@ ${LangFileString} MUI_UNTEXT_WELCOME_INFO_TEXT "このセットアップは$(^Na ; installer ${LangFileString} GEODE_TEXT_GD_MISSING "$\r$\n$\r$\nこのパスにはGeometry Dashがインストールされていません!" -${LangFileString} GEODE_TEXT_GD_OLD "$\r$\n$\r$\nYour version of Geometry Dash is too old for this version of Geode!" +${LangFileString} GEODE_TEXT_GD_OLD "$\r$\n$\r$\nGeometry DashのバージョンはこのGeodeのバージョンには古すぎます!" ${LangFileString} GEODE_TEXT_MOD_LOADER_ALREADY_INSTALLED "このパスには他のモッドがインストールされています!$\r$\nそれらはGeodeによって上書きされます。(the dll trademark)" ; uninstaller From 5c840127fa6a8e9629d0a5287f931a169a4c427b Mon Sep 17 00:00:00 2001 From: HJfod <60038575+HJfod@users.noreply.github.com> Date: Mon, 29 Jul 2024 12:50:22 +0300 Subject: [PATCH 32/64] expose LoadingSpinner for mods to use --- loader/include/Geode/ui/LoadingSpinner.hpp | 29 ++++++++++++++ loader/src/ui/mods/GeodeStyle.cpp | 46 +--------------------- loader/src/ui/nodes/LoadingSpinner.cpp | 42 ++++++++++++++++++++ 3 files changed, 72 insertions(+), 45 deletions(-) create mode 100644 loader/include/Geode/ui/LoadingSpinner.hpp create mode 100644 loader/src/ui/nodes/LoadingSpinner.cpp diff --git a/loader/include/Geode/ui/LoadingSpinner.hpp b/loader/include/Geode/ui/LoadingSpinner.hpp new file mode 100644 index 00000000..ef2c7e70 --- /dev/null +++ b/loader/include/Geode/ui/LoadingSpinner.hpp @@ -0,0 +1,29 @@ +#pragma once + +#include + +namespace geode { + /** + * An eternally spinning loading circle. Essentially just a more convenient + * alternative to RobTop's `LoadingCircle` class, as this one respects its + * content size and is a lot more stripped down (not requiring a `show` + * method or anything - it just works!) + */ + class LoadingSpinner : public cocos2d::CCNode { + protected: + cocos2d::CCSprite* m_spinner; + + bool init(float size); + + void spin(); + + public: + /** + * Create a loading circle + * @param size The diameter of the circle in Cocos units + */ + static LoadingSpinner* create(float size); + + void setVisible(bool visible) override; + }; +} diff --git a/loader/src/ui/mods/GeodeStyle.cpp b/loader/src/ui/mods/GeodeStyle.cpp index 497002a5..920244c9 100644 --- a/loader/src/ui/mods/GeodeStyle.cpp +++ b/loader/src/ui/mods/GeodeStyle.cpp @@ -3,6 +3,7 @@ #include #include #include +#include $on_mod(Loaded) { // todo: these names should probably be shorter so they fit in SSO... @@ -134,51 +135,6 @@ void GeodeSquareSprite::setState(bool state) { } } -class LoadingSpinner : public CCNode { -protected: - CCSprite* m_spinner; - - bool init(float sideLength) { - if (!CCNode::init()) - return false; - - this->setID("loading-spinner"); - this->setContentSize({ sideLength, sideLength }); - this->setAnchorPoint({ .5f, .5f }); - - m_spinner = CCSprite::create("loadingCircle.png"); - m_spinner->setBlendFunc({ GL_ONE, GL_ONE }); - limitNodeSize(m_spinner, m_obContentSize, 1.f, .1f); - this->addChildAtPosition(m_spinner, Anchor::Center); - - this->spin(); - - return true; - } - - void spin() { - m_spinner->runAction(CCRepeatForever::create(CCRotateBy::create(1.f, 360.f))); - } - -public: - static LoadingSpinner* create(float sideLength) { - auto ret = new LoadingSpinner(); - if (ret->init(sideLength)) { - ret->autorelease(); - return ret; - } - delete ret; - return nullptr; - } - - void setVisible(bool visible) override { - CCNode::setVisible(visible); - if (visible) { - this->spin(); - } - } -}; - CCNode* createLoadingCircle(float sideLength, const char* id) { auto spinner = LoadingSpinner::create(sideLength); spinner->setID(id); diff --git a/loader/src/ui/nodes/LoadingSpinner.cpp b/loader/src/ui/nodes/LoadingSpinner.cpp new file mode 100644 index 00000000..8ca51f6e --- /dev/null +++ b/loader/src/ui/nodes/LoadingSpinner.cpp @@ -0,0 +1,42 @@ +#include + +using namespace geode::prelude; + +bool LoadingSpinner::init(float sideLength) { + if (!CCNode::init()) + return false; + + this->setID("loading-spinner"); + this->setContentSize({ sideLength, sideLength }); + this->setAnchorPoint({ .5f, .5f }); + + m_spinner = CCSprite::create("loadingCircle.png"); + m_spinner->setBlendFunc({ GL_ONE, GL_ONE }); + limitNodeSize(m_spinner, m_obContentSize, 1.f, .1f); + this->addChildAtPosition(m_spinner, Anchor::Center); + + this->spin(); + + return true; +} + +void LoadingSpinner::spin() { + m_spinner->runAction(CCRepeatForever::create(CCRotateBy::create(1.f, 360.f))); +} + +LoadingSpinner* LoadingSpinner::create(float sideLength) { + auto ret = new LoadingSpinner(); + if (ret->init(sideLength)) { + ret->autorelease(); + return ret; + } + delete ret; + return nullptr; +} + +void LoadingSpinner::setVisible(bool visible) { + CCNode::setVisible(visible); + if (visible) { + this->spin(); + } +} From 6080fdbfde98443b51746adfb56881553dee8b22 Mon Sep 17 00:00:00 2001 From: HJfod <60038575+HJfod@users.noreply.github.com> Date: Mon, 29 Jul 2024 12:50:37 +0300 Subject: [PATCH 33/64] deprecate cc3x --- loader/include/Geode/utils/cocos.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/loader/include/Geode/utils/cocos.hpp b/loader/include/Geode/utils/cocos.hpp index 3e9d7445..8c731489 100644 --- a/loader/include/Geode/utils/cocos.hpp +++ b/loader/include/Geode/utils/cocos.hpp @@ -861,6 +861,7 @@ namespace geode::cocos { return {color.r / 255.f, color.g / 255.f, color.b / 255.f, color.a / 255.f}; } + [[deprecated("This function sucks, use cc3bFromHexString instead")]] constexpr cocos2d::ccColor3B cc3x(int hexValue) { if (hexValue <= 0xf) return cocos2d::ccColor3B{ From 028bbf9a8b5b89d3fa527ed287fb146af47f5576 Mon Sep 17 00:00:00 2001 From: HJfod <60038575+HJfod@users.noreply.github.com> Date: Mon, 29 Jul 2024 12:50:56 +0300 Subject: [PATCH 34/64] add support for hex colors + 2.2 color tags + fix mod links --- loader/include/Geode/ui/GeodeUI.hpp | 6 +++ loader/src/ui/GeodeUI.cpp | 67 ++++++++++++++++++++++++++ loader/src/ui/nodes/MDTextArea.cpp | 75 ++++++++--------------------- 3 files changed, 94 insertions(+), 54 deletions(-) diff --git a/loader/include/Geode/ui/GeodeUI.hpp b/loader/include/Geode/ui/GeodeUI.hpp index d37ab69e..ba775e20 100644 --- a/loader/include/Geode/ui/GeodeUI.hpp +++ b/loader/include/Geode/ui/GeodeUI.hpp @@ -11,6 +11,12 @@ namespace geode { * Open the info popup for a mod */ GEODE_DLL void openInfoPopup(Mod* mod); + /** + * Open the info popup for a mod based on an ID. If the mod is installed, + * its installed popup is opened. Otherwise will check if the servers + * have this mod, or if not, show an error popup + */ + GEODE_DLL void openInfoPopup(std::string const& modID); /** * Open the info popup for a mod on the changelog page */ diff --git a/loader/src/ui/GeodeUI.cpp b/loader/src/ui/GeodeUI.cpp index 8ad2ca03..dd5af876 100644 --- a/loader/src/ui/GeodeUI.cpp +++ b/loader/src/ui/GeodeUI.cpp @@ -2,12 +2,71 @@ #include #include #include +#include #include #include #include "mods/GeodeStyle.hpp" #include "mods/settings/ModSettingsPopup.hpp" #include "mods/popups/ModPopup.hpp" +class LoadServerModLayer : public Popup { +protected: + std::string m_id; + EventListener> m_listener; + + bool setup(std::string const& id) override { + m_closeBtn->setVisible(false); + + this->setTitle("Loading mod..."); + + auto spinner = LoadingSpinner::create(40); + m_mainLayer->addChildAtPosition(spinner, Anchor::Center, ccp(0, -10)); + + m_id = id; + m_listener.bind(this, &LoadServerModLayer::onRequest); + m_listener.setFilter(server::getMod(id)); + + return true; + } + + void onRequest(server::ServerRequest::Event* event) { + if (auto res = event->getValue()) { + if (res->isOk()) { + // Copy info first as onClose may free the listener which will free the event + auto info = **res; + this->onClose(nullptr); + // Run this on next frame because otherwise the popup is unable to call server::getMod for some reason + Loader::get()->queueInMainThread([info = std::move(info)]() mutable { + ModPopup::create(ModSource(std::move(info)))->show(); + }); + } + else { + auto id = m_id; + this->onClose(nullptr); + FLAlertLayer::create( + "Error Loading Mod", + fmt::format("Unable to find mod with the ID {}!", id), + "OK" + )->show(); + } + } + else if (event->isCancelled()) { + this->onClose(nullptr); + } + } + +public: + static LoadServerModLayer* create(std::string const& id) { + auto ret = new LoadServerModLayer(); + if (ret && ret->initAnchored(180, 100, id, "square01_001.png", CCRectZero)) { + ret->autorelease(); + return ret; + } + CC_SAFE_RELEASE(ret); + return nullptr; + } +}; + void geode::openModsList() { ModsLayer::scene(); } @@ -68,6 +127,14 @@ void geode::openSupportPopup(ModMetadata const& metadata) { void geode::openInfoPopup(Mod* mod) { ModPopup::create(mod)->show(); } +void geode::openInfoPopup(std::string const& modID) { + if (auto mod = Loader::get()->getInstalledMod(modID)) { + openInfoPopup(mod); + } + else { + LoadServerModLayer::create(modID)->show(); + } +} void geode::openIndexPopup(Mod* mod) { // deprecated func openInfoPopup(mod); diff --git a/loader/src/ui/nodes/MDTextArea.cpp b/loader/src/ui/nodes/MDTextArea.cpp index 2023f00f..be6f5f62 100644 --- a/loader/src/ui/nodes/MDTextArea.cpp +++ b/loader/src/ui/nodes/MDTextArea.cpp @@ -15,6 +15,8 @@ #include #include #include +#include +#include using namespace geode::prelude; @@ -77,13 +79,8 @@ public: }; Result colorForIdentifier(std::string const& tag) { - if (utils::string::contains(tag, ' ')) { - auto hexStr = utils::string::split(utils::string::normalize(tag), " ").at(1); - auto res = numFromString(hexStr, 16); - if (res.isErr()) { - return Err("Invalid hex"); - } - return Ok(cc3x(res.unwrap())); + if (tag.length() > 2 && tag[1] == '-') { + return cc3bFromHexString(tag.substr(2)); } else { auto colorText = tag.substr(1); @@ -95,15 +92,19 @@ Result colorForIdentifier(std::string const& tag) { } else { switch (colorText.front()) { - case 'a': return Ok(cc3x(0x9632ff)); break; - case 'b': return Ok(cc3x(0x4a52e1)); break; - case 'g': return Ok(cc3x(0x40e348)); break; - case 'l': return Ok(cc3x(0x60abef)); break; - case 'j': return Ok(cc3x(0x32c8ff)); break; - case 'y': return Ok(cc3x(0xffff00)); break; - case 'o': return Ok(cc3x(0xffa54b)); break; - case 'r': return Ok(cc3x(0xff5a5a)); break; - case 'p': return Ok(cc3x(0xff00ff)); break; + case 'a': return Ok(ccc3(150, 50, 255)); break; + case 'b': return Ok(ccc3(74, 82, 225)); break; + case 'c': return Ok(ccc3(255, 255, 150)); break; + case 'd': return Ok(ccc3(255, 150, 255)); break; + case 'f': return Ok(ccc3(150, 255, 255)); break; + case 'g': return Ok(ccc3(64, 227, 72)); break; + case 'j': return Ok(ccc3(50, 200, 255)); break; + case 'l': return Ok(ccc3(96, 171, 239)); break; + case 'o': return Ok(ccc3(255, 165, 75)); break; + case 'p': return Ok(ccc3(255, 0, 255)); break; + case 'r': return Ok(ccc3(255, 90, 90)); break; + case 's': return Ok(ccc3(255, 220, 65)); break; + case 'y': return Ok(ccc3(255, 255, 0)); break; default: return Err("Unknown color " + colorText); } } @@ -223,44 +224,10 @@ void MDTextArea::onGDLevel(CCObject* pSender) { CCDirector::sharedDirector()->replaceScene(CCTransitionFade::create(0.5f, scene)); } -void MDTextArea::onGeodeMod(CCObject* pSender) { - // TODO - // auto href = as(as(pSender)->getUserObject()); - // auto modString = std::string(href->getCString()); - // modString = modString.substr(modString.find(":") + 1); - // auto loader = Loader::get(); - // auto index = Index::get(); - // Mod* mod; - // bool success = false; - // IndexItemHandle indexItem; - // bool isIndexMod = !loader->isModInstalled(modString); - - // if (isIndexMod) { - // auto indexSearch = index->getItemsByModID(modString); - // if (indexSearch.size() != 0) { - // indexItem = indexSearch.back(); - // Mod mod2 = Mod(indexItem->getMetadata()); - // mod = &mod2; - // auto item = Index::get()->getItem(mod); - // IndexItemInfoPopup::create(item, nullptr)->show(); - // success = true; - // } - // } else { - // mod = loader->getLoadedMod(modString); - // LocalModInfoPopup::create(mod, nullptr)->show(); - // success = true; - // } - - // if (!success) { - // FLAlertLayer::create( - // "Error", - // "Invalid mod ID: " + modString + - // ". This is " - // "probably the mod developers's fault, report the bug to them.", - // "OK" - // ) - // ->show(); - // } +void MDTextArea::onGeodeMod(CCObject* sender) { + auto href = as(as(sender)->getUserObject()); + auto modID = std::string(href->getCString()); + openInfoPopup(modID.substr(modID.find(":") + 1)); } void MDTextArea::FLAlert_Clicked(FLAlertLayer* layer, bool btn) { From c4fe40b03715e346828cb7e4074786d24469a449 Mon Sep 17 00:00:00 2001 From: HJfod <60038575+HJfod@users.noreply.github.com> Date: Mon, 29 Jul 2024 12:51:12 +0300 Subject: [PATCH 35/64] teehee totally forgot GEODE_DLL on this one --- loader/include/Geode/ui/LoadingSpinner.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/loader/include/Geode/ui/LoadingSpinner.hpp b/loader/include/Geode/ui/LoadingSpinner.hpp index ef2c7e70..c959ea9d 100644 --- a/loader/include/Geode/ui/LoadingSpinner.hpp +++ b/loader/include/Geode/ui/LoadingSpinner.hpp @@ -9,7 +9,7 @@ namespace geode { * content size and is a lot more stripped down (not requiring a `show` * method or anything - it just works!) */ - class LoadingSpinner : public cocos2d::CCNode { + class GEODE_DLL LoadingSpinner : public cocos2d::CCNode { protected: cocos2d::CCSprite* m_spinner; From c323faee27bcb599f757218a8907e2db6c36b2ec Mon Sep 17 00:00:00 2001 From: HJfod <60038575+HJfod@users.noreply.github.com> Date: Mon, 29 Jul 2024 13:10:42 +0300 Subject: [PATCH 36/64] make openInfoPopup return a Task --- loader/include/Geode/ui/GeodeUI.hpp | 5 ++++- loader/src/ui/GeodeUI.cpp | 15 +++++++++++++-- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/loader/include/Geode/ui/GeodeUI.hpp b/loader/include/Geode/ui/GeodeUI.hpp index ba775e20..303b85d8 100644 --- a/loader/include/Geode/ui/GeodeUI.hpp +++ b/loader/include/Geode/ui/GeodeUI.hpp @@ -15,8 +15,11 @@ namespace geode { * Open the info popup for a mod based on an ID. If the mod is installed, * its installed popup is opened. Otherwise will check if the servers * have this mod, or if not, show an error popup + * @returns A Task that completes to `true` if the mod was found and a + * popup was opened, and `false` otherwise. If you wish to modify the + * created popup, listen for the Geode UI events listed in `GeodeUI.hpp` */ - GEODE_DLL void openInfoPopup(std::string const& modID); + GEODE_DLL Task openInfoPopup(std::string const& modID); /** * Open the info popup for a mod on the changelog page */ diff --git a/loader/src/ui/GeodeUI.cpp b/loader/src/ui/GeodeUI.cpp index dd5af876..de21ca50 100644 --- a/loader/src/ui/GeodeUI.cpp +++ b/loader/src/ui/GeodeUI.cpp @@ -56,6 +56,13 @@ protected: } public: + Task listen() const { + return m_listener.getFilter().map( + [](auto* result) -> bool { return result->isOk(); }, + [](auto) -> std::monostate { return std::monostate(); } + ); + } + static LoadServerModLayer* create(std::string const& id) { auto ret = new LoadServerModLayer(); if (ret && ret->initAnchored(180, 100, id, "square01_001.png", CCRectZero)) { @@ -127,12 +134,16 @@ void geode::openSupportPopup(ModMetadata const& metadata) { void geode::openInfoPopup(Mod* mod) { ModPopup::create(mod)->show(); } -void geode::openInfoPopup(std::string const& modID) { +Task geode::openInfoPopup(std::string const& modID) { if (auto mod = Loader::get()->getInstalledMod(modID)) { openInfoPopup(mod); + return Task::immediate(true); } else { - LoadServerModLayer::create(modID)->show(); + auto popup = LoadServerModLayer::create(modID); + auto task = popup->listen(); + popup->show(); + return task; } } void geode::openIndexPopup(Mod* mod) { From 2a3c35f5848db6ea4d171ac874b7a9341ccdbaa1 Mon Sep 17 00:00:00 2001 From: HJfod <60038575+HJfod@users.noreply.github.com> Date: Mon, 29 Jul 2024 15:14:49 +0300 Subject: [PATCH 37/64] allow modifying Geode UI via events --- loader/include/Geode/ui/GeodeUI.hpp | 97 ++++++++++++++++++++++++++ loader/src/ui/GeodeUI.cpp | 24 +++++-- loader/src/ui/GeodeUIEvent.cpp | 68 ++++++++++++++++++ loader/src/ui/GeodeUIEvent.hpp | 32 +++++++++ loader/src/ui/mods/list/ModItem.cpp | 7 ++ loader/src/ui/mods/list/ModItem.hpp | 2 + loader/src/ui/mods/popups/ModPopup.cpp | 64 ++++++++++++----- loader/src/ui/mods/popups/ModPopup.hpp | 2 + 8 files changed, 273 insertions(+), 23 deletions(-) create mode 100644 loader/src/ui/GeodeUIEvent.cpp create mode 100644 loader/src/ui/GeodeUIEvent.hpp diff --git a/loader/include/Geode/ui/GeodeUI.hpp b/loader/include/Geode/ui/GeodeUI.hpp index 303b85d8..3b22f60b 100644 --- a/loader/include/Geode/ui/GeodeUI.hpp +++ b/loader/include/Geode/ui/GeodeUI.hpp @@ -2,7 +2,104 @@ #include "../loader/Mod.hpp" +class ModPopup; +class ModItem; +class ModLogoSprite; + namespace geode { + /** + * Event posted whenever a popup is opened for a mod. Allows mods to modify + * the Geode UI. See the [tutorial on Geode UI modification](https://docs.geode-sdk.org/tutorials/modify-geode) + * for **very important notes on these events**! + */ + class GEODE_DLL ModPopupUIEvent final : public Event { + private: + class Impl; + std::unique_ptr m_impl; + + friend class ::ModPopup; + + ModPopupUIEvent(std::unique_ptr&& impl); + + public: + virtual ~ModPopupUIEvent(); + + /** + * Get the popup itself + */ + FLAlertLayer* getPopup() const; + /** + * Get the ID of the mod this popup is for + */ + std::string getModID() const; + /** + * If this popup is of an installed mod, get it + */ + std::optional getMod() const; + }; + + /** + * Event posted whenever a logo sprite is created for a mod. Allows mods to modify + * the Geode UI. See the [tutorial on Geode UI modification](https://docs.geode-sdk.org/tutorials/modify-geode) + * for **very important notes on these events**! + */ + class GEODE_DLL ModItemUIEvent final : public Event { + private: + class Impl; + std::unique_ptr m_impl; + + friend class ::ModItem; + + ModItemUIEvent(std::unique_ptr&& impl); + + public: + virtual ~ModItemUIEvent(); + + /** + * Get the item itself + */ + cocos2d::CCNode* getItem() const; + /** + * Get the ID of the mod this logo is for + */ + std::string getModID() const; + /** + * If this logo is of an installed mod, get it + */ + std::optional getMod() const; + }; + + /** + * Event posted whenever a logo sprite is created for a mod. Allows mods to modify + * the Geode UI. See the [tutorial on Geode UI modification](https://docs.geode-sdk.org/tutorials/modify-geode) + * for **very important notes on these events**! + */ + class GEODE_DLL ModLogoUIEvent final : public Event { + private: + class Impl; + std::unique_ptr m_impl; + + friend class ::ModLogoSprite; + + ModLogoUIEvent(std::unique_ptr&& impl); + + public: + virtual ~ModLogoUIEvent(); + + /** + * Get the sprite itself + */ + cocos2d::CCNode* getSprite() const; + /** + * Get the ID of the mod this logo is for + */ + std::string getModID() const; + /** + * If this logo is of an installed mod, get it + */ + std::optional getMod() const; + }; + /** * Open the Geode mods list */ diff --git a/loader/src/ui/GeodeUI.cpp b/loader/src/ui/GeodeUI.cpp index de21ca50..bedfa20d 100644 --- a/loader/src/ui/GeodeUI.cpp +++ b/loader/src/ui/GeodeUI.cpp @@ -8,6 +8,7 @@ #include "mods/GeodeStyle.hpp" #include "mods/settings/ModSettingsPopup.hpp" #include "mods/popups/ModPopup.hpp" +#include "GeodeUIEvent.hpp" class LoadServerModLayer : public Popup { protected: @@ -176,6 +177,9 @@ protected: this->setAnchorPoint({ .5f, .5f }); this->setContentSize({ 50, 50 }); + // This is a default ID, nothing should ever rely on the ID of any ModLogoSprite being this + this->setID(std::string(Mod::get()->expandSpriteName(fmt::format("sprite-{}", id)))); + m_modID = id; m_listener.bind(this, &ModLogoSprite::onFetch); @@ -183,19 +187,22 @@ protected: if (!fetch) { this->setSprite(id == "geode.loader" ? CCSprite::createWithSpriteFrameName("geode-logo.png"_spr) : - CCSprite::create(fmt::format("{}/logo.png", id).c_str()) + CCSprite::create(fmt::format("{}/logo.png", id).c_str()), + false ); } // Asynchronously fetch from server else { - this->setSprite(createLoadingCircle(25)); + this->setSprite(createLoadingCircle(25), false); m_listener.setFilter(server::getModLogo(id)); } + ModLogoUIEvent(std::make_unique(this, id)).post(); + return true; } - void setSprite(CCNode* sprite) { + void setSprite(CCNode* sprite, bool postEvent) { // Remove any existing sprite if (m_sprite) { m_sprite->removeFromParent(); @@ -207,15 +214,20 @@ protected: } // Set sprite and scale it to node size m_sprite = sprite; + m_sprite->setID("sprite"); limitNodeSize(m_sprite, m_obContentSize, 99.f, 0.f); this->addChildAtPosition(m_sprite, Anchor::Center); + + if (postEvent) { + ModLogoUIEvent(std::make_unique(this, m_modID)).post(); + } } void onFetch(server::ServerRequest::Event* event) { if (auto result = event->getValue()) { // Set default sprite on error if (result->isErr()) { - this->setSprite(nullptr); + this->setSprite(nullptr, true); } // Otherwise load downloaded sprite to memory else { @@ -224,11 +236,11 @@ protected: image->initWithImageData(const_cast(data.data()), data.size()); auto texture = CCTextureCache::get()->addUIImage(image, m_modID.c_str()); - this->setSprite(CCSprite::createWithTexture(texture)); + this->setSprite(CCSprite::createWithTexture(texture), true); } } else if (event->isCancelled()) { - this->setSprite(nullptr); + this->setSprite(nullptr, true); } } diff --git a/loader/src/ui/GeodeUIEvent.cpp b/loader/src/ui/GeodeUIEvent.cpp new file mode 100644 index 00000000..3b29d036 --- /dev/null +++ b/loader/src/ui/GeodeUIEvent.cpp @@ -0,0 +1,68 @@ +#include "GeodeUIEvent.hpp" + +ModPopupUIEvent::ModPopupUIEvent(std::unique_ptr&& impl) : m_impl(std::move(impl)) {} +ModPopupUIEvent::~ModPopupUIEvent() = default; + +FLAlertLayer* ModPopupUIEvent::getPopup() const { + return m_impl->popup; +} +std::string ModPopupUIEvent::getModID() const { + return m_impl->popup->getSource().getID(); +} +std::optional ModPopupUIEvent::getMod() const { + auto mod = m_impl->popup->getSource().asMod(); + return mod ? std::optional(mod) : std::nullopt; +} + +ModItemUIEvent::ModItemUIEvent(std::unique_ptr&& impl) : m_impl(std::move(impl)) {} +ModItemUIEvent::~ModItemUIEvent() = default; + +CCNode* ModItemUIEvent::getItem() const { + return m_impl->item; +} +std::string ModItemUIEvent::getModID() const { + return m_impl->item->getSource().getID(); +} +std::optional ModItemUIEvent::getMod() const { + auto mod = m_impl->item->getSource().asMod(); + return mod ? std::optional(mod) : std::nullopt; +} + +ModLogoUIEvent::ModLogoUIEvent(std::unique_ptr&& impl) : m_impl(std::move(impl)) {} +ModLogoUIEvent::~ModLogoUIEvent() = default; + +CCNode* ModLogoUIEvent::getSprite() const { + return m_impl->sprite; +} +std::string ModLogoUIEvent::getModID() const { + return m_impl->modID; +} +std::optional ModLogoUIEvent::getMod() const { + if (auto mod = Loader::get()->getInstalledMod(m_impl->modID)) { + return mod; + } + return std::nullopt; +} + +// $execute { +// new EventListener>(+[](ModLogoUIEvent* event) { +// if (event->getModID() == "geode.loader") { +// auto fart = CCSprite::createWithSpriteFrameName("GJ_demonIcon_001.png"); +// fart->setScaleX(5); +// fart->setScaleY(3); +// event->getSprite()->addChildAtPosition(fart, Anchor::Center); +// } +// return ListenerResult::Propagate; +// }); +// new EventListener>(+[](ModItemUIEvent* event) { +// if (event->getModID() == "geode.loader") { +// auto fart = CCSprite::createWithSpriteFrameName("GJ_demonIcon_001.png"); +// fart->setScaleX(4); +// fart->setScaleY(2); +// if (auto dev = event->getItem()->querySelector("developers-button")) { +// dev->addChildAtPosition(fart, Anchor::Center, ccp(-15, 0)); +// } +// } +// return ListenerResult::Propagate; +// }); +// } diff --git a/loader/src/ui/GeodeUIEvent.hpp b/loader/src/ui/GeodeUIEvent.hpp new file mode 100644 index 00000000..668651b5 --- /dev/null +++ b/loader/src/ui/GeodeUIEvent.hpp @@ -0,0 +1,32 @@ +#pragma once + +#include +#include "mods/popups/ModPopup.hpp" +#include "mods/list/ModItem.hpp" + +using namespace geode::prelude; + +class ModPopupUIEvent::Impl { +public: + ModPopup* popup; + + Impl(ModPopup* popup) + : popup(popup) {} +}; + +class ModItemUIEvent::Impl { +public: + ModItem* item; + + Impl(ModItem* item) + : item(item) {} +}; + +class ModLogoUIEvent::Impl { +public: + CCNode* sprite; + std::string modID; + + Impl(CCNode* sprite, std::string const& modID) + : sprite(sprite), modID(modID) {} +}; diff --git a/loader/src/ui/mods/list/ModItem.cpp b/loader/src/ui/mods/list/ModItem.cpp index 08a27fa0..ee85ab85 100644 --- a/loader/src/ui/mods/list/ModItem.cpp +++ b/loader/src/ui/mods/list/ModItem.cpp @@ -9,6 +9,7 @@ #include "../popups/DevPopup.hpp" #include "ui/mods/popups/ModErrorPopup.hpp" #include "ui/mods/sources/ModSource.hpp" +#include "../../GeodeUIEvent.hpp" bool ModItem::init(ModSource&& source) { if (!CCNode::init()) @@ -407,6 +408,8 @@ void ModItem::updateState() { on->setOpacity(105); } } + + ModItemUIEvent(std::make_unique(this)).post(); } void ModItem::updateSize(float width, bool big) { @@ -521,3 +524,7 @@ ModItem* ModItem::create(ModSource&& source) { delete ret; return nullptr; } + +ModSource& ModItem::getSource() & { + return m_source; +} diff --git a/loader/src/ui/mods/list/ModItem.hpp b/loader/src/ui/mods/list/ModItem.hpp index 91d4008a..717c030c 100644 --- a/loader/src/ui/mods/list/ModItem.hpp +++ b/loader/src/ui/mods/list/ModItem.hpp @@ -56,4 +56,6 @@ public: static ModItem* create(ModSource&& source); void updateSize(float width, bool big); + + ModSource& getSource() &; }; diff --git a/loader/src/ui/mods/popups/ModPopup.cpp b/loader/src/ui/mods/popups/ModPopup.cpp index f81cb7d5..82006b0b 100644 --- a/loader/src/ui/mods/popups/ModPopup.cpp +++ b/loader/src/ui/mods/popups/ModPopup.cpp @@ -8,6 +8,7 @@ #include "ConfirmUninstallPopup.hpp" #include "../settings/ModSettingsPopup.hpp" #include "../../../internal/about.hpp" +#include "../../GeodeUIEvent.hpp" class FetchTextArea : public CCNode { public: @@ -29,6 +30,7 @@ protected: m_noneText = noneText; m_textarea = MDTextArea::create("", size); + m_textarea->setID("textarea"); this->addChildAtPosition(m_textarea, Anchor::Center); m_loading = createLoadingCircle(30); @@ -67,6 +69,8 @@ bool ModPopup::setup(ModSource&& src) { m_source = std::move(src); m_noElasticity = true; + this->setID(std::string(Mod::get()->expandSpriteName(fmt::format("popup-{}", src.getID())))); + if (src.asMod() == Mod::get()) { // Display commit hashes auto loaderHash = about::getLoaderCommitHash(); @@ -97,6 +101,7 @@ bool ModPopup::setup(ModSource&& src) { titleContainer->setAnchorPoint({ .5f, .5f }); auto logo = m_source.createModLogo(); + logo->setID("mod-logo"); limitNodeSize( logo, ccp(titleContainer->getContentHeight(), titleContainer->getContentHeight()), @@ -112,12 +117,14 @@ bool ModPopup::setup(ModSource&& src) { auto title = CCLabelBMFont::create(m_source.getMetadata().getName().c_str(), "bigFont.fnt"); title->limitLabelWidth(titleContainer->getContentWidth() - devAndTitlePos, .45f, .1f); title->setAnchorPoint({ .0f, .5f }); + title->setID("mod-name-label"); titleContainer->addChildAtPosition(title, Anchor::TopLeft, ccp(devAndTitlePos, -titleContainer->getContentHeight() * .25f)); auto by = "By " + m_source.formatDevelopers(); auto dev = CCLabelBMFont::create(by.c_str(), "goldFont.fnt"); dev->limitLabelWidth(titleContainer->getContentWidth() - devAndTitlePos, .35f, .05f); dev->setAnchorPoint({ .0f, .5f }); + dev->setID("mod-developer-label"); titleContainer->addChildAtPosition(dev, Anchor::BottomLeft, ccp(devAndTitlePos, titleContainer->getContentHeight() * .25f)); // Suggestions @@ -170,6 +177,7 @@ bool ModPopup::setup(ModSource&& src) { idLabel->limitLabelWidth(leftColumn->getContentWidth(), .25f, .05f); idLabel->setColor({ 150, 150, 150 }); idLabel->setOpacity(140); + idLabel->setID("mod-id-label"); leftColumn->addChild(idLabel); auto statsContainer = CCNode::create(); @@ -186,6 +194,7 @@ bool ModPopup::setup(ModSource&& src) { m_stats = CCNode::create(); m_stats->setContentSize(statsContainer->getContentSize() - ccp(10, 10)); m_stats->setAnchorPoint({ .5f, .5f }); + m_stats->setID("mod-stats-container"); for (auto stat : std::initializer_list, const char* @@ -264,6 +273,7 @@ bool ModPopup::setup(ModSource&& src) { m_tags->ignoreAnchorPointForPosition(false); m_tags->setContentSize(tagsContainer->getContentSize() - ccp(10, 10)); m_tags->setAnchorPoint({ .5f, .5f }); + m_tags->setID("tags-container"); m_tags->addChild(createLoadingCircle(50)); @@ -438,6 +448,7 @@ bool ModPopup::setup(ModSource&& src) { linksMenu->ignoreAnchorPointForPosition(false); linksMenu->setContentSize(linksContainer->getContentSize() - ccp(10, 10)); linksMenu->setAnchorPoint({ .5f, .5f }); + linksMenu->setID("links-container"); // auto linksLabel = CCLabelBMFont::create("Links", "bigFont.fnt"); // linksLabel->setLayoutOptions( @@ -447,28 +458,29 @@ bool ModPopup::setup(ModSource&& src) { // linksMenu->addChild(linksLabel); for (auto stat : std::initializer_list, SEL_MenuHandler + const char*, const char*, std::optional, SEL_MenuHandler >> { - { "homepage.png"_spr, m_source.getMetadata().getLinks().getHomepageURL(), nullptr }, - { "github.png"_spr, m_source.getMetadata().getLinks().getSourceURL(), nullptr }, - { "gj_discordIcon_001.png", m_source.getMetadata().getLinks().getCommunityURL(), nullptr }, - { "gift.png"_spr, m_source.getMetadata().getSupportInfo(), menu_selector(ModPopup::onSupport) }, + { "homepage", "homepage.png"_spr, m_source.getMetadata().getLinks().getHomepageURL(), nullptr }, + { "github", "github.png"_spr, m_source.getMetadata().getLinks().getSourceURL(), nullptr }, + { "discord", "gj_discordIcon_001.png", m_source.getMetadata().getLinks().getCommunityURL(), nullptr }, + { "support", "gift.png"_spr, m_source.getMetadata().getSupportInfo(), menu_selector(ModPopup::onSupport) }, }) { - auto spr = CCSprite::createWithSpriteFrameName(std::get<0>(stat)); + auto spr = CCSprite::createWithSpriteFrameName(std::get<1>(stat)); spr->setScale(.75f); - if (!std::get<1>(stat).has_value()) { + if (!std::get<2>(stat).has_value()) { spr->setColor({ 155, 155, 155 }); spr->setOpacity(155); } auto btn = CCMenuItemSpriteExtra::create( spr, this, ( - std::get<1>(stat).has_value() ? - (std::get<2>(stat) ? std::get<2>(stat) : menu_selector(ModPopup::onLink)) : + std::get<2>(stat).has_value() ? + (std::get<3>(stat) ? std::get<3>(stat) : menu_selector(ModPopup::onLink)) : nullptr ) ); - if (!std::get<2>(stat) && std::get<1>(stat)) { - btn->setUserObject("url", CCString::create(*std::get<1>(stat))); + btn->setID(std::get<0>(stat)); + if (!std::get<3>(stat) && std::get<2>(stat)) { + btn->setUserObject("url", CCString::create(*std::get<2>(stat))); } linksMenu->addChild(btn); } @@ -510,17 +522,19 @@ bool ModPopup::setup(ModSource&& src) { tabsMenu->setScale(.65f); tabsMenu->setContentWidth(m_rightColumn->getContentWidth() / tabsMenu->getScale()); tabsMenu->setAnchorPoint({ .5f, 1.f }); + tabsMenu->setID("tabs-menu"); - for (auto mdTab : std::initializer_list> { - { "message.png"_spr, "Description", Tab::Details }, - { "changelog.png"_spr, "Changelog", Tab::Changelog } + for (auto mdTab : std::initializer_list> { + { "message.png"_spr, "Description", "description", Tab::Details }, + { "changelog.png"_spr, "Changelog", "changelog", Tab::Changelog } // { "version.png"_spr, "Versions", Tab::Versions }, }) { auto spr = GeodeTabSprite::create(std::get<0>(mdTab), std::get<1>(mdTab), 140, m_source.asServer()); auto btn = CCMenuItemSpriteExtra::create(spr, this, menu_selector(ModPopup::onTab)); - btn->setTag(static_cast(std::get<2>(mdTab))); + btn->setTag(static_cast(std::get<3>(mdTab))); + btn->setID(std::get<2>(mdTab)); tabsMenu->addChild(btn); - m_tabs.insert({ std::get<2>(mdTab), { spr, nullptr } }); + m_tabs.insert({ std::get<3>(mdTab), { spr, nullptr } }); } // placeholder external link until versions tab is implemented @@ -532,7 +546,7 @@ bool ModPopup::setup(ModSource&& src) { auto externalLinkBtn = CCMenuItemSpriteExtra::create(externalLinkSpr, this, menu_selector(ModPopup::onLink)); externalLinkBtn->setUserObject("url", CCString::create(modUrl)); - + externalLinkBtn->setID("mod-online-page-button"); m_buttonMenu->addChildAtPosition(externalLinkBtn, Anchor::TopRight, ccp(-14, -16)); tabsMenu->setLayout(RowLayout::create()->setAxisAlignment(AxisAlignment::Start)); @@ -548,6 +562,7 @@ bool ModPopup::setup(ModSource&& src) { auto settingsBtn = CCMenuItemSpriteExtra::create( settingsSpr, this, menu_selector(ModPopup::onSettings) ); + settingsBtn->setID("settings-button"); m_buttonMenu->addChildAtPosition(settingsBtn, Anchor::BottomLeft, ccp(28, 25)); if (!m_source.asMod() || !m_source.asMod()->hasSettings()) { @@ -707,6 +722,8 @@ void ModPopup::updateState() { } m_installMenu->updateLayout(); + + ModPopupUIEvent(std::make_unique(this)).post(); } void ModPopup::setStatIcon(CCNode* stat, const char* spr) { @@ -794,6 +811,7 @@ void ModPopup::onLoadServerInfo(typename server::ServerRequestsetStatValue(stat, id.second); } } + ModPopupUIEvent(std::make_unique(this)).post(); } else if (event->isCancelled() || (event->getValue() && event->getValue()->isErr())) { for (auto child : CCArrayExt(m_stats->getChildren())) { @@ -801,6 +819,7 @@ void ModPopup::onLoadServerInfo(typename server::ServerRequestsetStatValue(child, "N/A"); } } + ModPopupUIEvent(std::make_unique(this)).post(); } } @@ -851,6 +870,8 @@ void ModPopup::onLoadTags(typename server::ServerRequestupdateLayout(); + + ModPopupUIEvent(std::make_unique(this)).post(); } else if (event->isCancelled() || (event->getValue() && event->getValue()->isErr())) { m_tags->removeAllChildren(); @@ -860,6 +881,8 @@ void ModPopup::onLoadTags(typename server::ServerRequestaddChild(label); m_tags->updateLayout(); + + ModPopupUIEvent(std::make_unique(this)).post(); } } @@ -888,6 +911,7 @@ void ModPopup::loadTab(ModPopup::Tab tab) { "No description provided", size / mdScale ); + m_currentTabPage->setID("description-container"); m_currentTabPage->setScale(mdScale); } break; @@ -897,12 +921,14 @@ void ModPopup::loadTab(ModPopup::Tab tab) { "No changelog provided", size / mdScale ); + m_currentTabPage->setID("changelog-container"); m_currentTabPage->setScale(mdScale); } break; case Tab::Versions: { m_currentTabPage = CCNode::create(); m_currentTabPage->setContentSize(size); + m_currentTabPage->setID("versions-container"); } break; } m_currentTabPage->setAnchorPoint({ .5f, .0f }); @@ -995,3 +1021,7 @@ ModPopup* ModPopup::create(ModSource&& src) { delete ret; return nullptr; } + +ModSource& ModPopup::getSource() & { + return m_source; +} diff --git a/loader/src/ui/mods/popups/ModPopup.hpp b/loader/src/ui/mods/popups/ModPopup.hpp index a7873083..b91c5092 100644 --- a/loader/src/ui/mods/popups/ModPopup.hpp +++ b/loader/src/ui/mods/popups/ModPopup.hpp @@ -65,4 +65,6 @@ protected: public: void loadTab(Tab tab); static ModPopup* create(ModSource&& src); + + ModSource& getSource() &; }; From 4b4bc0eb9b9f8b260a5c0b76b331f0d74b8e3020 Mon Sep 17 00:00:00 2001 From: HJfod <60038575+HJfod@users.noreply.github.com> Date: Mon, 29 Jul 2024 15:15:00 +0300 Subject: [PATCH 38/64] don't cancel subtasks on task destructor --- loader/include/Geode/utils/Task.hpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/loader/include/Geode/utils/Task.hpp b/loader/include/Geode/utils/Task.hpp index 8fe407e8..38868bf1 100644 --- a/loader/include/Geode/utils/Task.hpp +++ b/loader/include/Geode/utils/Task.hpp @@ -163,9 +163,12 @@ namespace geode { m_status = Status::Cancelled; // If this task carries extra data, call the extra data's // handling method - if (m_extraData) { - m_extraData->cancel(); - } + // Actually: don't do this! This will cancel tasks even if + // they have other listeners! The extra data's destructor + // will handle cancellation if it has no other listeners! + // if (m_extraData) { + // m_extraData->cancel(); + // } // No need to actually post an event because this Task is // unlisteanable m_finalEventPosted = true; From 69f2934768c01fc301b859a501bb5c767790ee9b Mon Sep 17 00:00:00 2001 From: HJfod <60038575+HJfod@users.noreply.github.com> Date: Mon, 29 Jul 2024 15:15:08 +0300 Subject: [PATCH 39/64] silence a warning --- loader/src/ui/nodes/MDTextArea.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/loader/src/ui/nodes/MDTextArea.cpp b/loader/src/ui/nodes/MDTextArea.cpp index be6f5f62..1db036e5 100644 --- a/loader/src/ui/nodes/MDTextArea.cpp +++ b/loader/src/ui/nodes/MDTextArea.cpp @@ -227,7 +227,7 @@ void MDTextArea::onGDLevel(CCObject* pSender) { void MDTextArea::onGeodeMod(CCObject* sender) { auto href = as(as(sender)->getUserObject()); auto modID = std::string(href->getCString()); - openInfoPopup(modID.substr(modID.find(":") + 1)); + (void)openInfoPopup(modID.substr(modID.find(":") + 1)); } void MDTextArea::FLAlert_Clicked(FLAlertLayer* layer, bool btn) { From 96e2f5b63a72fb9ce15f052a5deb34d612e71cfc Mon Sep 17 00:00:00 2001 From: HJfod <60038575+HJfod@users.noreply.github.com> Date: Mon, 29 Jul 2024 15:17:25 +0300 Subject: [PATCH 40/64] update theme button name and id --- loader/src/ui/mods/ModsLayer.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/loader/src/ui/mods/ModsLayer.cpp b/loader/src/ui/mods/ModsLayer.cpp index 05a3fcef..1b83dbcd 100644 --- a/loader/src/ui/mods/ModsLayer.cpp +++ b/loader/src/ui/mods/ModsLayer.cpp @@ -350,17 +350,17 @@ bool ModsLayer::init() { reloadBtn->setID("reload-button"); actionsMenu->addChild(reloadBtn); - auto themeSpr = createGeodeCircleButton( + auto settingsSpr = createGeodeCircleButton( CCSprite::createWithSpriteFrameName("settings.png"_spr), 1.f, CircleBaseSize::Medium ); - themeSpr->setScale(.8f); - themeSpr->setTopOffset(ccp(.5f, 0)); - auto themeBtn = CCMenuItemSpriteExtra::create( - themeSpr, this, menu_selector(ModsLayer::onSettings) + settingsSpr->setScale(.8f); + settingsSpr->setTopOffset(ccp(.5f, 0)); + auto settingsBtn = CCMenuItemSpriteExtra::create( + settingsSpr, this, menu_selector(ModsLayer::onSettings) ); - themeBtn->setID("theme-button"); - actionsMenu->addChild(themeBtn); + settingsBtn->setID("settings-button"); + actionsMenu->addChild(settingsBtn); auto folderSpr = createGeodeCircleButton( CCSprite::createWithSpriteFrameName("gj_folderBtn_001.png"), 1.f, From d95b879b4dc06dc10fd8309bcb49fd22e230750b Mon Sep 17 00:00:00 2001 From: HJfod <60038575+HJfod@users.noreply.github.com> Date: Mon, 29 Jul 2024 15:58:02 +0300 Subject: [PATCH 41/64] update changelog --- CHANGELOG.md | 8 ++++++++ loader/include/Geode/ui/GeodeUI.hpp | 1 + 2 files changed, 9 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7425986c..d56ea235 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Geode Changelog +## v3.4.0 + * Add an API for modifying the Geode UI via events; see [the corresponding docs page](https://docs.geode-sdk.org/tutorials/modify-geode) (2a3c35f) + * Add `openInfoPopup` overload that accepts a mod ID and can open both an installed mod page or a server page (028bbf9) + * Add `LoadingSpinner` for creating loading circles easily (5c84012) + * MDTextArea changes: hex colors are now formatted as ``; added support for ``, ``, ``, and ``; fixed `mod:` links (028bbf9) + * Deprecate `cc3x` (6080fdb) + * Don't cancel subtasks on `Task` destructor (4b4bc0e) + ## v3.3.1 * Move ObjectDecoder and its delegate to Cocos headers (95f9eeb, dceb91e) * Fix weird behavior with textures, objects and more by changing en-US.utf8 locale to C (2cd1a9e) diff --git a/loader/include/Geode/ui/GeodeUI.hpp b/loader/include/Geode/ui/GeodeUI.hpp index 3b22f60b..955c1fb1 100644 --- a/loader/include/Geode/ui/GeodeUI.hpp +++ b/loader/include/Geode/ui/GeodeUI.hpp @@ -1,6 +1,7 @@ #pragma once #include "../loader/Mod.hpp" +#include class ModPopup; class ModItem; From b6250cd2781a0853c6eb7cca1c020ac9150f63e9 Mon Sep 17 00:00:00 2001 From: Chloe <25387744+qimiko@users.noreply.github.com> Date: Mon, 29 Jul 2024 05:58:47 -0700 Subject: [PATCH 42/64] fix mac build --- loader/include/Geode/ui/GeodeUI.hpp | 1 + loader/src/ui/nodes/LoadingSpinner.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/loader/include/Geode/ui/GeodeUI.hpp b/loader/include/Geode/ui/GeodeUI.hpp index 955c1fb1..02417318 100644 --- a/loader/include/Geode/ui/GeodeUI.hpp +++ b/loader/include/Geode/ui/GeodeUI.hpp @@ -6,6 +6,7 @@ class ModPopup; class ModItem; class ModLogoSprite; +class FLAlertLayer; // for macos :3 namespace geode { /** diff --git a/loader/src/ui/nodes/LoadingSpinner.cpp b/loader/src/ui/nodes/LoadingSpinner.cpp index 8ca51f6e..5fabc773 100644 --- a/loader/src/ui/nodes/LoadingSpinner.cpp +++ b/loader/src/ui/nodes/LoadingSpinner.cpp @@ -1,4 +1,5 @@ #include +#include using namespace geode::prelude; From 7599321fa8afe03fc6404d9047f1d7aa99a2fc42 Mon Sep 17 00:00:00 2001 From: HJfod <60038575+HJfod@users.noreply.github.com> Date: Mon, 29 Jul 2024 16:13:25 +0300 Subject: [PATCH 43/64] increment VERSION --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 712bd5a6..fbcbf738 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -3.3.1 \ No newline at end of file +3.4.0 \ No newline at end of file From 22bcbe1b5e75025f44d9e59b10b20dee708bac8e Mon Sep 17 00:00:00 2001 From: Chloe <25387744+qimiko@users.noreply.github.com> Date: Mon, 29 Jul 2024 06:18:17 -0700 Subject: [PATCH 44/64] remove usages of cc3x --- loader/include/Geode/utils/cocos.hpp | 2 +- loader/src/ui/mods/settings/GeodeSettingNode.hpp | 4 ++-- loader/src/ui/mods/settings/ModSettingsPopup.cpp | 8 ++++---- loader/src/ui/nodes/MDTextArea.cpp | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/loader/include/Geode/utils/cocos.hpp b/loader/include/Geode/utils/cocos.hpp index 8c731489..8500c157 100644 --- a/loader/include/Geode/utils/cocos.hpp +++ b/loader/include/Geode/utils/cocos.hpp @@ -861,7 +861,7 @@ namespace geode::cocos { return {color.r / 255.f, color.g / 255.f, color.b / 255.f, color.a / 255.f}; } - [[deprecated("This function sucks, use cc3bFromHexString instead")]] + [[deprecated("This function may have unintended behavior, use cc3bFromHexString or manually expand the color instead")]] constexpr cocos2d::ccColor3B cc3x(int hexValue) { if (hexValue <= 0xf) return cocos2d::ccColor3B{ diff --git a/loader/src/ui/mods/settings/GeodeSettingNode.hpp b/loader/src/ui/mods/settings/GeodeSettingNode.hpp index 56c435d6..d9b44d6a 100644 --- a/loader/src/ui/mods/settings/GeodeSettingNode.hpp +++ b/loader/src/ui/mods/settings/GeodeSettingNode.hpp @@ -150,10 +150,10 @@ protected: virtual void valueChanged(bool updateText = true) { if (this->hasUncommittedChanges()) { - m_nameLabel->setColor(cc3x(0x1d0)); + m_nameLabel->setColor({0x11, 0xdd, 0x00}); } else { - m_nameLabel->setColor(cc3x(0xfff)); + m_nameLabel->setColor({0xff, 0xff, 0xff}); } if (m_resetBtn) m_resetBtn->setVisible(this->hasNonDefaultValue()); auto isValid = setting()->validate(m_uncommittedValue); diff --git a/loader/src/ui/mods/settings/ModSettingsPopup.cpp b/loader/src/ui/mods/settings/ModSettingsPopup.cpp index c92f7ddf..573218dc 100644 --- a/loader/src/ui/mods/settings/ModSettingsPopup.cpp +++ b/loader/src/ui/mods/settings/ModSettingsPopup.cpp @@ -145,22 +145,22 @@ void ModSettingsPopup::onResetAll(CCObject*) { void ModSettingsPopup::settingValueCommitted(SettingNode*) { if (this->hasUncommitted()) { - m_applyBtnSpr->setColor(cc3x(0xf)); + m_applyBtnSpr->setColor({0xff, 0xff, 0xff}); m_applyBtn->setEnabled(true); } else { - m_applyBtnSpr->setColor(cc3x(0x4)); + m_applyBtnSpr->setColor({0x44, 0x44, 0x44}); m_applyBtn->setEnabled(false); } } void ModSettingsPopup::settingValueChanged(SettingNode*) { if (this->hasUncommitted()) { - m_applyBtnSpr->setColor(cc3x(0xf)); + m_applyBtnSpr->setColor({0xff, 0xff, 0xff}); m_applyBtn->setEnabled(true); } else { - m_applyBtnSpr->setColor(cc3x(0x4)); + m_applyBtnSpr->setColor({0x44, 0x44, 0x44}); m_applyBtn->setEnabled(false); } } diff --git a/loader/src/ui/nodes/MDTextArea.cpp b/loader/src/ui/nodes/MDTextArea.cpp index 1db036e5..107e512d 100644 --- a/loader/src/ui/nodes/MDTextArea.cpp +++ b/loader/src/ui/nodes/MDTextArea.cpp @@ -24,7 +24,7 @@ static constexpr float g_fontScale = .5f; static constexpr float g_paragraphPadding = 7.f; static constexpr float g_indent = 7.f; static constexpr float g_codeBlockIndent = 8.f; -static constexpr ccColor3B g_linkColor = cc3x(0x7ff4f4); +static constexpr ccColor3B g_linkColor = {0x7f, 0xf4, 0xf4}; TextRenderer::Font g_mdFont = [](int style) -> TextRenderer::Label { if ((style & TextStyleBold) && (style & TextStyleItalic)) { From 749fdf1ad376950e71a851a3051d4e6dd28c3fdf Mon Sep 17 00:00:00 2001 From: HJfod <60038575+HJfod@users.noreply.github.com> Date: Mon, 29 Jul 2024 20:58:58 +0300 Subject: [PATCH 45/64] add TextInput::focus and unfocus --- loader/include/Geode/ui/TextInput.hpp | 9 +++++++++ loader/src/ui/nodes/TextInput.cpp | 7 +++++++ 2 files changed, 16 insertions(+) diff --git a/loader/include/Geode/ui/TextInput.hpp b/loader/include/Geode/ui/TextInput.hpp index 1d65b30d..f771c675 100644 --- a/loader/include/Geode/ui/TextInput.hpp +++ b/loader/include/Geode/ui/TextInput.hpp @@ -138,6 +138,15 @@ namespace geode { */ std::string getString() const; + /** + * Focus this input (activate the cursor) + */ + void focus(); + /** + * Defocus this input (deactivate the cursor) + */ + void defocus(); + CCTextInputNode* getInputNode() const; cocos2d::extension::CCScale9Sprite* getBGSprite() const; }; diff --git a/loader/src/ui/nodes/TextInput.cpp b/loader/src/ui/nodes/TextInput.cpp index fb47ad5b..5c80d308 100644 --- a/loader/src/ui/nodes/TextInput.cpp +++ b/loader/src/ui/nodes/TextInput.cpp @@ -191,6 +191,13 @@ std::string TextInput::getString() const { return m_input->getString(); } +void TextInput::focus() { + m_input->onClickTrackNode(true); +} +void TextInput::defocus() { + m_input->detachWithIME(); +} + CCTextInputNode* TextInput::getInputNode() const { return m_input; } From 7e87d675bc4914d85a477767cb43a4b94ef16cd0 Mon Sep 17 00:00:00 2001 From: HJfod <60038575+HJfod@users.noreply.github.com> Date: Mon, 29 Jul 2024 21:00:46 +0300 Subject: [PATCH 46/64] update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d56ea235..5118ed95 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ * Add an API for modifying the Geode UI via events; see [the corresponding docs page](https://docs.geode-sdk.org/tutorials/modify-geode) (2a3c35f) * Add `openInfoPopup` overload that accepts a mod ID and can open both an installed mod page or a server page (028bbf9) * Add `LoadingSpinner` for creating loading circles easily (5c84012) + * Add `TextInput::focus` and `TextInput::unfocus` (749fdf1) * MDTextArea changes: hex colors are now formatted as ``; added support for ``, ``, ``, and ``; fixed `mod:` links (028bbf9) * Deprecate `cc3x` (6080fdb) * Don't cancel subtasks on `Task` destructor (4b4bc0e) From 8de28d1e2a26bd8191efe0df36d9e7b1c88a11a1 Mon Sep 17 00:00:00 2001 From: HJfod <60038575+HJfod@users.noreply.github.com> Date: Mon, 29 Jul 2024 22:05:37 +0300 Subject: [PATCH 47/64] support old `` syntax too for backwards compatability --- loader/src/ui/nodes/MDTextArea.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/loader/src/ui/nodes/MDTextArea.cpp b/loader/src/ui/nodes/MDTextArea.cpp index 107e512d..6c245535 100644 --- a/loader/src/ui/nodes/MDTextArea.cpp +++ b/loader/src/ui/nodes/MDTextArea.cpp @@ -82,6 +82,10 @@ Result colorForIdentifier(std::string const& tag) { if (tag.length() > 2 && tag[1] == '-') { return cc3bFromHexString(tag.substr(2)); } + // Support the old form of + else if (tag.find(' ') != std::string::npos) { + return cc3bFromHexString(tag.substr(tag.find(' ') + 1)); + } else { auto colorText = tag.substr(1); if (!colorText.size()) { From a533b5f51af03929f642bc530691b34475d0a9c0 Mon Sep 17 00:00:00 2001 From: HJfod <60038575+HJfod@users.noreply.github.com> Date: Mon, 29 Jul 2024 22:06:14 +0300 Subject: [PATCH 48/64] actually technically that last one didn't match og behaviour even --- loader/src/ui/nodes/MDTextArea.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/loader/src/ui/nodes/MDTextArea.cpp b/loader/src/ui/nodes/MDTextArea.cpp index 6c245535..da766a4f 100644 --- a/loader/src/ui/nodes/MDTextArea.cpp +++ b/loader/src/ui/nodes/MDTextArea.cpp @@ -84,7 +84,7 @@ Result colorForIdentifier(std::string const& tag) { } // Support the old form of else if (tag.find(' ') != std::string::npos) { - return cc3bFromHexString(tag.substr(tag.find(' ') + 1)); + return cc3bFromHexString(string::trim(tag.substr(tag.find(' ') + 1))); } else { auto colorText = tag.substr(1); From bae22b4e340eca831ecef48b9e07a6b3203644af Mon Sep 17 00:00:00 2001 From: dankmeme01 <42031238+dankmeme01@users.noreply.github.com> Date: Tue, 30 Jul 2024 17:19:33 +0200 Subject: [PATCH 49/64] add new gd::string constructor --- loader/include/Geode/c++stl/string.hpp | 1 + loader/src/c++stl/string.cpp | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/loader/include/Geode/c++stl/string.hpp b/loader/include/Geode/c++stl/string.hpp index 8f520cfc..1e0a1ac5 100644 --- a/loader/include/Geode/c++stl/string.hpp +++ b/loader/include/Geode/c++stl/string.hpp @@ -66,6 +66,7 @@ namespace gd { string(string const&); // string(string&&); string(char const*); + string(char const*, size_t); string(std::string const&); // tried to add a string_view ctor, but got overload errors :( ~string(); diff --git a/loader/src/c++stl/string.cpp b/loader/src/c++stl/string.cpp index e5a1f2db..eaab2453 100644 --- a/loader/src/c++stl/string.cpp +++ b/loader/src/c++stl/string.cpp @@ -34,6 +34,10 @@ namespace gd { impl.setStorage(str); } + string::string(char const* str, size_t size) { + impl.setStorage(std::string_view(str, size)); + } + string::string(std::string const& str) { impl.setStorage(str); } From fe730ed78ba94cb181e9734caf455c413559fa01 Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Thu, 1 Aug 2024 12:31:16 +0300 Subject: [PATCH 50/64] use virtual getChildren for getChildByID --- loader/src/hooks/GeodeNodeMetadata.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/loader/src/hooks/GeodeNodeMetadata.cpp b/loader/src/hooks/GeodeNodeMetadata.cpp index 0eb01a3d..49896d78 100644 --- a/loader/src/hooks/GeodeNodeMetadata.cpp +++ b/loader/src/hooks/GeodeNodeMetadata.cpp @@ -122,7 +122,7 @@ void CCNode::setID(std::string const& id) { } CCNode* CCNode::getChildByID(std::string const& id) { - for (auto child : CCArrayExt(m_pChildren)) { + for (auto child : CCArrayExt(this->getChildren())) { if (child->getID() == id) { return child; } From d729a12bf3fae2db888039f5f67a1d34539b4b1f Mon Sep 17 00:00:00 2001 From: dankmeme01 <42031238+dankmeme01@users.noreply.github.com> Date: Thu, 1 Aug 2024 14:05:33 +0200 Subject: [PATCH 51/64] fix order of buttons in CCMenuItemExt::createToggler --- loader/include/Geode/utils/cocos.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/loader/include/Geode/utils/cocos.hpp b/loader/include/Geode/utils/cocos.hpp index 8500c157..73eb1c32 100644 --- a/loader/include/Geode/utils/cocos.hpp +++ b/loader/include/Geode/utils/cocos.hpp @@ -1301,7 +1301,7 @@ namespace geode::cocos { cocos2d::CCNode* offSprite, utils::MiniFunction&& callback ) { - auto item = CCMenuItemToggler::create(onSprite, offSprite, nullptr, nullptr); + auto item = CCMenuItemToggler::create(offSprite, onSprite, nullptr, nullptr); assignCallback(item, std::forward>(callback)); return item; } From 59a0ade533e8d97222aeb1fb961985ed8475c032 Mon Sep 17 00:00:00 2001 From: dankmeme01 <42031238+dankmeme01@users.noreply.github.com> Date: Thu, 1 Aug 2024 14:14:50 +0200 Subject: [PATCH 52/64] actually fix it --- loader/include/Geode/utils/cocos.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/loader/include/Geode/utils/cocos.hpp b/loader/include/Geode/utils/cocos.hpp index 73eb1c32..02eba1a0 100644 --- a/loader/include/Geode/utils/cocos.hpp +++ b/loader/include/Geode/utils/cocos.hpp @@ -1316,7 +1316,7 @@ namespace geode::cocos { offSprite->setScale(scale); onSprite->setScale(scale); - return createToggler(offSprite, onSprite, std::forward>(callback)); + return createToggler(onSprite, offSprite, std::forward>(callback)); } static CCMenuItemToggler* createTogglerWithFilename( @@ -1331,7 +1331,7 @@ namespace geode::cocos { offSprite->setScale(scale); onSprite->setScale(scale); - return createToggler(offSprite, onSprite, std::forward>(callback)); + return createToggler(onSprite, offSprite, std::forward>(callback)); } static CCMenuItemToggler* createTogglerWithFrameName( @@ -1346,7 +1346,7 @@ namespace geode::cocos { offSprite->setScale(scale); onSprite->setScale(scale); - return createToggler(offSprite, onSprite, std::forward>(callback)); + return createToggler(onSprite, offSprite, std::forward>(callback)); } template From 677e7debd5b54380084092e7c3631a82d94ffd31 Mon Sep 17 00:00:00 2001 From: Oleksandr Nemesh Date: Fri, 2 Aug 2024 02:45:28 +0300 Subject: [PATCH 53/64] add restart button --- loader/src/platform/windows/crashlogWindow.cpp | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/loader/src/platform/windows/crashlogWindow.cpp b/loader/src/platform/windows/crashlogWindow.cpp index ff076832..85e21948 100644 --- a/loader/src/platform/windows/crashlogWindow.cpp +++ b/loader/src/platform/windows/crashlogWindow.cpp @@ -17,6 +17,7 @@ enum { ID_BUTTON_CLOSE = 102, ID_BUTTON_OPEN_FOLDER = 103, ID_BUTTON_COPY_CLIPBOARD = 104, + ID_BUTTON_RESTART_GAME = 105, }; #define TO_HMENU(x) reinterpret_cast(static_cast(x)) @@ -94,6 +95,14 @@ LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { hwnd, TO_HMENU(ID_BUTTON_COPY_CLIPBOARD), NULL, NULL ); SendMessage(button, WM_SETFONT, WPARAM(guiFont), TRUE); + + button = CreateWindowA( + "BUTTON", "Restart game", + WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, + 0, 0, layout::BUTTON_WIDTH, layout::BUTTON_HEIGHT, + hwnd, TO_HMENU(ID_BUTTON_RESTART_GAME), NULL, NULL + ); + SendMessage(button, WM_SETFONT, WPARAM(guiFont), TRUE); } break; case WM_SIZE: { @@ -126,6 +135,12 @@ LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { 0, 0, SWP_NOZORDER | SWP_NOSIZE ); + SetWindowPos( + GetDlgItem(hwnd, ID_BUTTON_RESTART_GAME), NULL, + clientRect.right - layout::BUTTON_WIDTH * 3 - layout::BUTTON_SPACING * 2 - layout::PADDING, buttonY, + 0, 0, + SWP_NOZORDER | SWP_NOSIZE + ); } break; case WM_CTLCOLORSTATIC: { @@ -140,6 +155,8 @@ LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { geode::utils::file::openFolder(g_crashlogPath); } else if (id == ID_BUTTON_COPY_CLIPBOARD) { geode::utils::clipboard::write(g_crashlogText); + } else if (id == ID_BUTTON_RESTART_GAME) { + geode::utils::game::restart(); } } break; From bf6879113f848db4a46ea829ced55d271e190e62 Mon Sep 17 00:00:00 2001 From: Oleksandr Nemesh Date: Fri, 2 Aug 2024 02:45:39 +0300 Subject: [PATCH 54/64] fix buttons glitches --- loader/src/platform/windows/crashlogWindow.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/loader/src/platform/windows/crashlogWindow.cpp b/loader/src/platform/windows/crashlogWindow.cpp index 85e21948..501a81f4 100644 --- a/loader/src/platform/windows/crashlogWindow.cpp +++ b/loader/src/platform/windows/crashlogWindow.cpp @@ -141,6 +141,12 @@ LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { 0, 0, SWP_NOZORDER | SWP_NOSIZE ); + + // force redraw buttons to fix weird artifacts + RedrawWindow(GetDlgItem(hwnd, ID_BUTTON_CLOSE), NULL, NULL, RDW_ERASE | RDW_INVALIDATE | RDW_FRAME); + RedrawWindow(GetDlgItem(hwnd, ID_BUTTON_OPEN_FOLDER), NULL, NULL, RDW_ERASE | RDW_INVALIDATE | RDW_FRAME); + RedrawWindow(GetDlgItem(hwnd, ID_BUTTON_COPY_CLIPBOARD), NULL, NULL, RDW_ERASE | RDW_INVALIDATE | RDW_FRAME); + RedrawWindow(GetDlgItem(hwnd, ID_BUTTON_RESTART_GAME), NULL, NULL, RDW_ERASE | RDW_INVALIDATE | RDW_FRAME); } break; case WM_CTLCOLORSTATIC: { From b595d98cd75da6c1b63ee8160ffd5b54ccdc98ab Mon Sep 17 00:00:00 2001 From: Cvolton Date: Sun, 4 Aug 2024 19:40:49 +0200 Subject: [PATCH 55/64] fix missing includes --- loader/include/Geode/loader/Event.hpp | 1 + loader/include/Geode/platform/android.hpp | 1 + 2 files changed, 2 insertions(+) diff --git a/loader/include/Geode/loader/Event.hpp b/loader/include/Geode/loader/Event.hpp index 9a5a9ab9..55a12e8a 100644 --- a/loader/include/Geode/loader/Event.hpp +++ b/loader/include/Geode/loader/Event.hpp @@ -8,6 +8,7 @@ #include #include #include +#include namespace geode { class Mod; diff --git a/loader/include/Geode/platform/android.hpp b/loader/include/Geode/platform/android.hpp index 31c7edeb..3faf3ad5 100644 --- a/loader/include/Geode/platform/android.hpp +++ b/loader/include/Geode/platform/android.hpp @@ -1,6 +1,7 @@ #pragma once #include +#include #include "ItaniumCast.hpp" namespace geode { From 63b82f9fb2b1969aee25122a8fcf82fb804b8d6b Mon Sep 17 00:00:00 2001 From: dankmeme01 <42031238+dankmeme01@users.noreply.github.com> Date: Sun, 4 Aug 2024 20:23:48 +0200 Subject: [PATCH 56/64] bump FMOD headers to 2.02.23 --- loader/include/Geode/fmod/fmod.h | 11 +- loader/include/Geode/fmod/fmod.hpp | 11 +- loader/include/Geode/fmod/fmod_android.h | 7 + loader/include/Geode/fmod/fmod_codec.h | 71 ++++++-- loader/include/Geode/fmod/fmod_common.h | 171 +++++++++++++++++-- loader/include/Geode/fmod/fmod_dsp.h | 13 +- loader/include/Geode/fmod/fmod_dsp_effects.h | 48 +++++- loader/include/Geode/fmod/fmod_errors.h | 110 ++++++++++++ loader/include/Geode/fmod/fmod_output.h | 23 +-- 9 files changed, 410 insertions(+), 55 deletions(-) create mode 100644 loader/include/Geode/fmod/fmod_android.h create mode 100644 loader/include/Geode/fmod/fmod_errors.h diff --git a/loader/include/Geode/fmod/fmod.h b/loader/include/Geode/fmod/fmod.h index 43f26439..7ce3a622 100644 --- a/loader/include/Geode/fmod/fmod.h +++ b/loader/include/Geode/fmod/fmod.h @@ -1,12 +1,12 @@ /* ======================================================================================== */ /* FMOD Core API - C header file. */ -/* Copyright (c), Firelight Technologies Pty, Ltd. 2004-2020. */ +/* Copyright (c), Firelight Technologies Pty, Ltd. 2004-2024. */ /* */ /* Use this header in conjunction with fmod_common.h (which contains all the constants / */ /* callbacks) to develop using the C interface */ /* */ /* For more detail visit: */ -/* https://fmod.com/resources/documentation-api?version=2.0&page=core-api.html */ +/* https://fmod.com/docs/2.02/api/core-api.html */ /* ======================================================================================== */ #ifndef _FMOD_H @@ -27,11 +27,12 @@ FMOD_RESULT F_API FMOD_Memory_GetStats (int *currentalloced, int *ma FMOD_RESULT F_API FMOD_Debug_Initialize (FMOD_DEBUG_FLAGS flags, FMOD_DEBUG_MODE mode, FMOD_DEBUG_CALLBACK callback, const char *filename); FMOD_RESULT F_API FMOD_File_SetDiskBusy (int busy); FMOD_RESULT F_API FMOD_File_GetDiskBusy (int *busy); +FMOD_RESULT F_API FMOD_Thread_SetAttributes (FMOD_THREAD_TYPE type, FMOD_THREAD_AFFINITY affinity, FMOD_THREAD_PRIORITY priority, FMOD_THREAD_STACK_SIZE stacksize); /* FMOD System factory functions. Use this to create an FMOD System Instance. below you will see FMOD_System_Init/Close to get started. */ -FMOD_RESULT /*F_API*/ FMOD_System_Create (FMOD_SYSTEM **system); +FMOD_RESULT F_API FMOD_System_Create (FMOD_SYSTEM **system, unsigned int headerversion); FMOD_RESULT F_API FMOD_System_Release (FMOD_SYSTEM *system); /* @@ -100,7 +101,7 @@ FMOD_RESULT F_API FMOD_System_GetSpeakerModeChannels (FMOD_SYSTEM *system, FM FMOD_RESULT F_API FMOD_System_GetVersion (FMOD_SYSTEM *system, unsigned int *version); FMOD_RESULT F_API FMOD_System_GetOutputHandle (FMOD_SYSTEM *system, void **handle); FMOD_RESULT F_API FMOD_System_GetChannelsPlaying (FMOD_SYSTEM *system, int *channels, int *realchannels); -FMOD_RESULT F_API FMOD_System_GetCPUUsage (FMOD_SYSTEM *system, float *dsp, float *stream, float *geometry, float *update, float *total); +FMOD_RESULT F_API FMOD_System_GetCPUUsage (FMOD_SYSTEM *system, FMOD_CPU_USAGE *usage); FMOD_RESULT F_API FMOD_System_GetFileUsage (FMOD_SYSTEM *system, long long *sampleBytesRead, long long *streamBytesRead, long long *otherBytesRead); /* Sound/DSP/Channel/FX creation and retrieval. */ @@ -114,6 +115,7 @@ FMOD_RESULT F_API FMOD_System_CreateReverb3D (FMOD_SYSTEM *system, FM FMOD_RESULT F_API FMOD_System_PlaySound (FMOD_SYSTEM *system, FMOD_SOUND *sound, FMOD_CHANNELGROUP *channelgroup, FMOD_BOOL paused, FMOD_CHANNEL **channel); FMOD_RESULT F_API FMOD_System_PlayDSP (FMOD_SYSTEM *system, FMOD_DSP *dsp, FMOD_CHANNELGROUP *channelgroup, FMOD_BOOL paused, FMOD_CHANNEL **channel); FMOD_RESULT F_API FMOD_System_GetChannel (FMOD_SYSTEM *system, int channelid, FMOD_CHANNEL **channel); +FMOD_RESULT F_API FMOD_System_GetDSPInfoByType (FMOD_SYSTEM *system, FMOD_DSP_TYPE type, const FMOD_DSP_DESCRIPTION **description); FMOD_RESULT F_API FMOD_System_GetMasterChannelGroup (FMOD_SYSTEM *system, FMOD_CHANNELGROUP **channelgroup); FMOD_RESULT F_API FMOD_System_GetMasterSoundGroup (FMOD_SYSTEM *system, FMOD_SOUNDGROUP **soundgroup); @@ -533,6 +535,7 @@ FMOD_RESULT F_API FMOD_DSP_SetChannelFormat (FMOD_DSP *dsp, FMOD_CHA FMOD_RESULT F_API FMOD_DSP_GetChannelFormat (FMOD_DSP *dsp, FMOD_CHANNELMASK *channelmask, int *numchannels, FMOD_SPEAKERMODE *source_speakermode); FMOD_RESULT F_API FMOD_DSP_GetOutputChannelFormat (FMOD_DSP *dsp, FMOD_CHANNELMASK inmask, int inchannels, FMOD_SPEAKERMODE inspeakermode, FMOD_CHANNELMASK *outmask, int *outchannels, FMOD_SPEAKERMODE *outspeakermode); FMOD_RESULT F_API FMOD_DSP_Reset (FMOD_DSP *dsp); +FMOD_RESULT F_API FMOD_DSP_SetCallback (FMOD_DSP *dsp, FMOD_DSP_CALLBACK callback); /* DSP parameter control. diff --git a/loader/include/Geode/fmod/fmod.hpp b/loader/include/Geode/fmod/fmod.hpp index a77122c8..8def4e09 100644 --- a/loader/include/Geode/fmod/fmod.hpp +++ b/loader/include/Geode/fmod/fmod.hpp @@ -1,12 +1,12 @@ /* ======================================================================================== */ /* FMOD Core API - C++ header file. */ -/* Copyright (c), Firelight Technologies Pty, Ltd. 2004-2020. */ +/* Copyright (c), Firelight Technologies Pty, Ltd. 2004-2024. */ /* */ /* Use this header in conjunction with fmod_common.h (which contains all the constants / */ /* callbacks) to develop using the C++ language. */ /* */ /* For more detail visit: */ -/* https://fmod.com/resources/documentation-api?version=2.0&page=core-api.html */ +/* https://fmod.com/docs/2.02/api/core-api.html */ /* ======================================================================================== */ #ifndef _FMOD_HPP #define _FMOD_HPP @@ -38,11 +38,12 @@ namespace FMOD inline FMOD_RESULT Debug_Initialize (FMOD_DEBUG_FLAGS flags, FMOD_DEBUG_MODE mode = FMOD_DEBUG_MODE_TTY, FMOD_DEBUG_CALLBACK callback = 0, const char *filename = 0) { return FMOD_Debug_Initialize(flags, mode, callback, filename); } inline FMOD_RESULT File_SetDiskBusy (int busy) { return FMOD_File_SetDiskBusy(busy); } inline FMOD_RESULT File_GetDiskBusy (int *busy) { return FMOD_File_GetDiskBusy(busy); } + inline FMOD_RESULT Thread_SetAttributes (FMOD_THREAD_TYPE type, FMOD_THREAD_AFFINITY affinity = FMOD_THREAD_AFFINITY_GROUP_DEFAULT, FMOD_THREAD_PRIORITY priority = FMOD_THREAD_PRIORITY_DEFAULT, FMOD_THREAD_STACK_SIZE stacksize = FMOD_THREAD_STACK_SIZE_DEFAULT) { return FMOD_Thread_SetAttributes(type, affinity, priority, stacksize); } /* FMOD System factory functions. */ - inline FMOD_RESULT System_Create (System **system) { return FMOD_System_Create((FMOD_SYSTEM **)system); } + inline FMOD_RESULT System_Create (System **system, unsigned int headerversion = FMOD_VERSION) { return FMOD_System_Create((FMOD_SYSTEM **)system, headerversion); } /* 'System' API @@ -122,7 +123,7 @@ namespace FMOD FMOD_RESULT F_API getVersion (unsigned int *version); FMOD_RESULT F_API getOutputHandle (void **handle); FMOD_RESULT F_API getChannelsPlaying (int *channels, int *realchannels = 0); - FMOD_RESULT F_API getCPUUsage (float *dsp, float *stream, float *geometry, float *update, float *total); + FMOD_RESULT F_API getCPUUsage (FMOD_CPU_USAGE *usage); FMOD_RESULT F_API getFileUsage (long long *sampleBytesRead, long long *streamBytesRead, long long *otherBytesRead); // Sound/DSP/Channel/FX creation and retrieval. @@ -137,6 +138,7 @@ namespace FMOD FMOD_RESULT F_API playSound (Sound *sound, ChannelGroup *channelgroup, bool paused, Channel **channel); FMOD_RESULT F_API playDSP (DSP *dsp, ChannelGroup *channelgroup, bool paused, Channel **channel); FMOD_RESULT F_API getChannel (int channelid, Channel **channel); + FMOD_RESULT F_API getDSPInfoByType (FMOD_DSP_TYPE type, const FMOD_DSP_DESCRIPTION **description); FMOD_RESULT F_API getMasterChannelGroup (ChannelGroup **channelgroup); FMOD_RESULT F_API getMasterSoundGroup (SoundGroup **soundgroup); @@ -471,6 +473,7 @@ namespace FMOD FMOD_RESULT F_API getChannelFormat (FMOD_CHANNELMASK *channelmask, int *numchannels, FMOD_SPEAKERMODE *source_speakermode); FMOD_RESULT F_API getOutputChannelFormat (FMOD_CHANNELMASK inmask, int inchannels, FMOD_SPEAKERMODE inspeakermode, FMOD_CHANNELMASK *outmask, int *outchannels, FMOD_SPEAKERMODE *outspeakermode); FMOD_RESULT F_API reset (); + FMOD_RESULT F_API setCallback (FMOD_DSP_CALLBACK callback); // DSP parameter control. FMOD_RESULT F_API setParameterFloat (int index, float value); diff --git a/loader/include/Geode/fmod/fmod_android.h b/loader/include/Geode/fmod/fmod_android.h new file mode 100644 index 00000000..5ae7cb6d --- /dev/null +++ b/loader/include/Geode/fmod/fmod_android.h @@ -0,0 +1,7 @@ +#pragma once + +#include "fmod_common.h" +#include + +extern "C" FMOD_RESULT F_API FMOD_Android_JNI_Init(JavaVM *vm, jobject javaActivity); +extern "C" FMOD_RESULT F_API FMOD_Android_JNI_Close(); \ No newline at end of file diff --git a/loader/include/Geode/fmod/fmod_codec.h b/loader/include/Geode/fmod/fmod_codec.h index 59a26f37..3c31c7cf 100644 --- a/loader/include/Geode/fmod/fmod_codec.h +++ b/loader/include/Geode/fmod/fmod_codec.h @@ -1,6 +1,6 @@ /* ======================================================================================== */ /* FMOD Core API - Codec development header file. */ -/* Copyright (c), Firelight Technologies Pty, Ltd. 2004-2020. */ +/* Copyright (c), Firelight Technologies Pty, Ltd. 2004-2024. */ /* */ /* Use this header if you are wanting to develop your own file format plugin to use with */ /* FMOD's codec system. With this header you can make your own fileformat plugin that FMOD */ @@ -8,7 +8,7 @@ /* plugin. */ /* */ /* For more detail visit: */ -/* https://fmod.com/resources/documentation-api?version=2.0&page=core-api.html */ +/* https://fmod.com/docs/2.02/api/core-api.html */ /* ======================================================================================== */ #ifndef _FMOD_CODEC_H #define _FMOD_CODEC_H @@ -22,7 +22,12 @@ typedef struct FMOD_CODEC_WAVEFORMAT FMOD_CODEC_WAVEFORMAT; /* Codec constants */ -#define FMOD_CODEC_WAVEFORMAT_VERSION 3 +#define FMOD_CODEC_PLUGIN_VERSION 1 + +typedef int FMOD_CODEC_SEEK_METHOD; +#define FMOD_CODEC_SEEK_METHOD_SET 0 +#define FMOD_CODEC_SEEK_METHOD_CURRENT 1 +#define FMOD_CODEC_SEEK_METHOD_END 2 /* Codec callbacks @@ -34,14 +39,27 @@ typedef FMOD_RESULT (F_CALLBACK *FMOD_CODEC_GETLENGTH_CALLBACK) (FMOD_CODEC_S typedef FMOD_RESULT (F_CALLBACK *FMOD_CODEC_SETPOSITION_CALLBACK) (FMOD_CODEC_STATE *codec_state, int subsound, unsigned int position, FMOD_TIMEUNIT postype); typedef FMOD_RESULT (F_CALLBACK *FMOD_CODEC_GETPOSITION_CALLBACK) (FMOD_CODEC_STATE *codec_state, unsigned int *position, FMOD_TIMEUNIT postype); typedef FMOD_RESULT (F_CALLBACK *FMOD_CODEC_SOUNDCREATE_CALLBACK) (FMOD_CODEC_STATE *codec_state, int subsound, FMOD_SOUND *sound); -typedef FMOD_RESULT (F_CALLBACK *FMOD_CODEC_METADATA_CALLBACK) (FMOD_CODEC_STATE *codec_state, FMOD_TAGTYPE tagtype, char *name, void *data, unsigned int datalen, FMOD_TAGDATATYPE datatype, int unique); typedef FMOD_RESULT (F_CALLBACK *FMOD_CODEC_GETWAVEFORMAT_CALLBACK)(FMOD_CODEC_STATE *codec_state, int index, FMOD_CODEC_WAVEFORMAT *waveformat); +/* + Codec functions +*/ +typedef FMOD_RESULT (F_CALLBACK *FMOD_CODEC_METADATA_FUNC) (FMOD_CODEC_STATE *codec_state, FMOD_TAGTYPE tagtype, char *name, void *data, unsigned int datalen, FMOD_TAGDATATYPE datatype, int unique); +typedef void * (F_CALLBACK *FMOD_CODEC_ALLOC_FUNC) (unsigned int size, unsigned int align, const char *file, int line); +typedef void (F_CALLBACK *FMOD_CODEC_FREE_FUNC) (void *ptr, const char *file, int line); +typedef void (F_CALLBACK *FMOD_CODEC_LOG_FUNC) (FMOD_DEBUG_FLAGS level, const char *file, int line, const char *function, const char *string, ...); + +typedef FMOD_RESULT (F_CALLBACK *FMOD_CODEC_FILE_READ_FUNC) (FMOD_CODEC_STATE *codec_state, void *buffer, unsigned int sizebytes, unsigned int *bytesread); +typedef FMOD_RESULT (F_CALLBACK *FMOD_CODEC_FILE_SEEK_FUNC) (FMOD_CODEC_STATE *codec_state, unsigned int pos, FMOD_CODEC_SEEK_METHOD method); +typedef FMOD_RESULT (F_CALLBACK *FMOD_CODEC_FILE_TELL_FUNC) (FMOD_CODEC_STATE *codec_state, unsigned int *pos); +typedef FMOD_RESULT (F_CALLBACK *FMOD_CODEC_FILE_SIZE_FUNC) (FMOD_CODEC_STATE *codec_state, unsigned int *size); + /* Codec structures */ typedef struct FMOD_CODEC_DESCRIPTION { + unsigned int apiversion; const char *name; unsigned int version; int defaultasstream; @@ -73,21 +91,46 @@ struct FMOD_CODEC_WAVEFORMAT float peakvolume; }; +typedef struct FMOD_CODEC_STATE_FUNCTIONS +{ + FMOD_CODEC_METADATA_FUNC metadata; + FMOD_CODEC_ALLOC_FUNC alloc; + FMOD_CODEC_FREE_FUNC free; + FMOD_CODEC_LOG_FUNC log; + FMOD_CODEC_FILE_READ_FUNC read; + FMOD_CODEC_FILE_SEEK_FUNC seek; + FMOD_CODEC_FILE_TELL_FUNC tell; + FMOD_CODEC_FILE_SIZE_FUNC size; +} FMOD_CODEC_STATE_FUNCTIONS; + struct FMOD_CODEC_STATE { - int numsubsounds; - FMOD_CODEC_WAVEFORMAT *waveformat; void *plugindata; - - void *filehandle; - unsigned int filesize; - FMOD_FILE_READ_CALLBACK fileread; - FMOD_FILE_SEEK_CALLBACK fileseek; - FMOD_CODEC_METADATA_CALLBACK metadata; - - int waveformatversion; + FMOD_CODEC_WAVEFORMAT *waveformat; + FMOD_CODEC_STATE_FUNCTIONS *functions; + int numsubsounds; }; +/* + Codec macros +*/ +#define FMOD_CODEC_METADATA(_state, _tagtype, _name, _data, _datalen, _datatype, _unique) \ + (_state)->functions->metadata(_state, _tagtype, _name, _data, _datalen, _datatype, _unique) +#define FMOD_CODEC_ALLOC(_state, _size, _align) \ + (_state)->functions->alloc(_size, _align, __FILE__, __LINE__) +#define FMOD_CODEC_FREE(_state, _ptr) \ + (_state)->functions->free(_ptr, __FILE__, __LINE__) +#define FMOD_CODEC_LOG(_state, _level, _location, _format, ...) \ + (_state)->functions->log(_level, __FILE__, __LINE__, _location, _format, __VA_ARGS__) +#define FMOD_CODEC_FILE_READ(_state, _buffer, _sizebytes, _bytesread) \ + (_state)->functions->read(_state, _buffer, _sizebytes, _bytesread) +#define FMOD_CODEC_FILE_SEEK(_state, _pos, _method) \ + (_state)->functions->seek(_state, _pos, _method) +#define FMOD_CODEC_FILE_TELL(_state, _pos) \ + (_state)->functions->tell(_state, _pos) +#define FMOD_CODEC_FILE_SIZE(_state, _size) \ + (_state)->functions->size(_state, _size) + #endif diff --git a/loader/include/Geode/fmod/fmod_common.h b/loader/include/Geode/fmod/fmod_common.h index 99cb99d9..e03cbd05 100644 --- a/loader/include/Geode/fmod/fmod_common.h +++ b/loader/include/Geode/fmod/fmod_common.h @@ -1,11 +1,11 @@ /* ======================================================================================== */ /* FMOD Core API - Common C/C++ header file. */ -/* Copyright (c), Firelight Technologies Pty, Ltd. 2004-2020. */ +/* Copyright (c), Firelight Technologies Pty, Ltd. 2004-2024. */ /* */ /* This header is included by fmod.hpp (C++ interface) and fmod.h (C interface) */ /* */ /* For more detail visit: */ -/* https://fmod.com/resources/documentation-api?version=2.0&page=core-api-common.html */ +/* https://fmod.com/docs/2.02/api/core-api-common.html */ /* ======================================================================================== */ #ifndef _FMOD_COMMON_H #define _FMOD_COMMON_H @@ -52,13 +52,11 @@ typedef struct FMOD_POLYGON FMOD_POLYGON; typedef struct FMOD_GEOMETRY FMOD_GEOMETRY; typedef struct FMOD_SYNCPOINT FMOD_SYNCPOINT; typedef struct FMOD_ASYNCREADINFO FMOD_ASYNCREADINFO; -typedef unsigned int FMOD_PORT_TYPE; -typedef unsigned long long FMOD_PORT_INDEX; /* FMOD constants */ -#define FMOD_VERSION 0x00020010 /* 0xaaaabbcc -> aaaa = product version, bb = major version, cc = minor version.*/ +#define FMOD_VERSION 0x00020223 /* 0xaaaabbcc -> aaaa = product version, bb = major version, cc = minor version.*/ typedef unsigned int FMOD_DEBUG_FLAGS; #define FMOD_DEBUG_LEVEL_NONE 0x00000000 @@ -88,6 +86,7 @@ typedef unsigned int FMOD_INITFLAGS; #define FMOD_INIT_STREAM_FROM_UPDATE 0x00000001 #define FMOD_INIT_MIX_FROM_UPDATE 0x00000002 #define FMOD_INIT_3D_RIGHTHANDED 0x00000004 +#define FMOD_INIT_CLIP_OUTPUT 0x00000008 #define FMOD_INIT_CHANNEL_LOWPASS 0x00000100 #define FMOD_INIT_CHANNEL_DISTANCEFILTER 0x00000200 #define FMOD_INIT_PROFILE_ENABLE 0x00010000 @@ -126,6 +125,10 @@ typedef unsigned int FMOD_SYSTEM_CALLBACK_TYPE; #define FMOD_SYSTEM_CALLBACK_PREUPDATE 0x00000400 #define FMOD_SYSTEM_CALLBACK_POSTUPDATE 0x00000800 #define FMOD_SYSTEM_CALLBACK_RECORDLISTCHANGED 0x00001000 +#define FMOD_SYSTEM_CALLBACK_BUFFEREDNOMIX 0x00002000 +#define FMOD_SYSTEM_CALLBACK_DEVICEREINITIALIZE 0x00004000 +#define FMOD_SYSTEM_CALLBACK_OUTPUTUNDERRUN 0x00008000 +#define FMOD_SYSTEM_CALLBACK_RECORDPOSITIONCHANGED 0x00010000 #define FMOD_SYSTEM_CALLBACK_ALL 0xFFFFFFFF typedef unsigned int FMOD_MODE; @@ -169,7 +172,6 @@ typedef unsigned int FMOD_CHANNELMASK; #define FMOD_CHANNELMASK_BACK_LEFT 0x00000040 #define FMOD_CHANNELMASK_BACK_RIGHT 0x00000080 #define FMOD_CHANNELMASK_BACK_CENTER 0x00000100 - #define FMOD_CHANNELMASK_MONO (FMOD_CHANNELMASK_FRONT_LEFT) #define FMOD_CHANNELMASK_STEREO (FMOD_CHANNELMASK_FRONT_LEFT | FMOD_CHANNELMASK_FRONT_RIGHT) #define FMOD_CHANNELMASK_LRC (FMOD_CHANNELMASK_FRONT_LEFT | FMOD_CHANNELMASK_FRONT_RIGHT | FMOD_CHANNELMASK_FRONT_CENTER) @@ -180,6 +182,92 @@ typedef unsigned int FMOD_CHANNELMASK; #define FMOD_CHANNELMASK_7POINT0 (FMOD_CHANNELMASK_FRONT_LEFT | FMOD_CHANNELMASK_FRONT_RIGHT | FMOD_CHANNELMASK_FRONT_CENTER | FMOD_CHANNELMASK_SURROUND_LEFT | FMOD_CHANNELMASK_SURROUND_RIGHT | FMOD_CHANNELMASK_BACK_LEFT | FMOD_CHANNELMASK_BACK_RIGHT) #define FMOD_CHANNELMASK_7POINT1 (FMOD_CHANNELMASK_FRONT_LEFT | FMOD_CHANNELMASK_FRONT_RIGHT | FMOD_CHANNELMASK_FRONT_CENTER | FMOD_CHANNELMASK_LOW_FREQUENCY | FMOD_CHANNELMASK_SURROUND_LEFT | FMOD_CHANNELMASK_SURROUND_RIGHT | FMOD_CHANNELMASK_BACK_LEFT | FMOD_CHANNELMASK_BACK_RIGHT) +typedef unsigned long long FMOD_PORT_INDEX; +#define FMOD_PORT_INDEX_NONE 0xFFFFFFFFFFFFFFFF +#define FMOD_PORT_INDEX_FLAG_VR_CONTROLLER 0x1000000000000000 + +typedef int FMOD_THREAD_PRIORITY; +/* Platform specific priority range */ +#define FMOD_THREAD_PRIORITY_PLATFORM_MIN (-32 * 1024) +#define FMOD_THREAD_PRIORITY_PLATFORM_MAX ( 32 * 1024) +/* Platform agnostic priorities, maps internally to platform specific value */ +#define FMOD_THREAD_PRIORITY_DEFAULT (FMOD_THREAD_PRIORITY_PLATFORM_MIN - 1) +#define FMOD_THREAD_PRIORITY_LOW (FMOD_THREAD_PRIORITY_PLATFORM_MIN - 2) +#define FMOD_THREAD_PRIORITY_MEDIUM (FMOD_THREAD_PRIORITY_PLATFORM_MIN - 3) +#define FMOD_THREAD_PRIORITY_HIGH (FMOD_THREAD_PRIORITY_PLATFORM_MIN - 4) +#define FMOD_THREAD_PRIORITY_VERY_HIGH (FMOD_THREAD_PRIORITY_PLATFORM_MIN - 5) +#define FMOD_THREAD_PRIORITY_EXTREME (FMOD_THREAD_PRIORITY_PLATFORM_MIN - 6) +#define FMOD_THREAD_PRIORITY_CRITICAL (FMOD_THREAD_PRIORITY_PLATFORM_MIN - 7) +/* Thread defaults */ +#define FMOD_THREAD_PRIORITY_MIXER FMOD_THREAD_PRIORITY_EXTREME +#define FMOD_THREAD_PRIORITY_FEEDER FMOD_THREAD_PRIORITY_CRITICAL +#define FMOD_THREAD_PRIORITY_STREAM FMOD_THREAD_PRIORITY_VERY_HIGH +#define FMOD_THREAD_PRIORITY_FILE FMOD_THREAD_PRIORITY_HIGH +#define FMOD_THREAD_PRIORITY_NONBLOCKING FMOD_THREAD_PRIORITY_HIGH +#define FMOD_THREAD_PRIORITY_RECORD FMOD_THREAD_PRIORITY_HIGH +#define FMOD_THREAD_PRIORITY_GEOMETRY FMOD_THREAD_PRIORITY_LOW +#define FMOD_THREAD_PRIORITY_PROFILER FMOD_THREAD_PRIORITY_MEDIUM +#define FMOD_THREAD_PRIORITY_STUDIO_UPDATE FMOD_THREAD_PRIORITY_MEDIUM +#define FMOD_THREAD_PRIORITY_STUDIO_LOAD_BANK FMOD_THREAD_PRIORITY_MEDIUM +#define FMOD_THREAD_PRIORITY_STUDIO_LOAD_SAMPLE FMOD_THREAD_PRIORITY_MEDIUM +#define FMOD_THREAD_PRIORITY_CONVOLUTION1 FMOD_THREAD_PRIORITY_VERY_HIGH +#define FMOD_THREAD_PRIORITY_CONVOLUTION2 FMOD_THREAD_PRIORITY_VERY_HIGH + +typedef unsigned int FMOD_THREAD_STACK_SIZE; +#define FMOD_THREAD_STACK_SIZE_DEFAULT 0 +#define FMOD_THREAD_STACK_SIZE_MIXER (80 * 1024) +#define FMOD_THREAD_STACK_SIZE_FEEDER (16 * 1024) +#define FMOD_THREAD_STACK_SIZE_STREAM (96 * 1024) +#define FMOD_THREAD_STACK_SIZE_FILE (64 * 1024) +#define FMOD_THREAD_STACK_SIZE_NONBLOCKING (112 * 1024) +#define FMOD_THREAD_STACK_SIZE_RECORD (16 * 1024) +#define FMOD_THREAD_STACK_SIZE_GEOMETRY (48 * 1024) +#define FMOD_THREAD_STACK_SIZE_PROFILER (128 * 1024) +#define FMOD_THREAD_STACK_SIZE_STUDIO_UPDATE (96 * 1024) +#define FMOD_THREAD_STACK_SIZE_STUDIO_LOAD_BANK (96 * 1024) +#define FMOD_THREAD_STACK_SIZE_STUDIO_LOAD_SAMPLE (96 * 1024) +#define FMOD_THREAD_STACK_SIZE_CONVOLUTION1 (16 * 1024) +#define FMOD_THREAD_STACK_SIZE_CONVOLUTION2 (16 * 1024) + +typedef long long FMOD_THREAD_AFFINITY; +/* Platform agnostic thread groupings */ +#define FMOD_THREAD_AFFINITY_GROUP_DEFAULT 0x4000000000000000 +#define FMOD_THREAD_AFFINITY_GROUP_A 0x4000000000000001 +#define FMOD_THREAD_AFFINITY_GROUP_B 0x4000000000000002 +#define FMOD_THREAD_AFFINITY_GROUP_C 0x4000000000000003 +/* Thread defaults */ +#define FMOD_THREAD_AFFINITY_MIXER FMOD_THREAD_AFFINITY_GROUP_A +#define FMOD_THREAD_AFFINITY_FEEDER FMOD_THREAD_AFFINITY_GROUP_C +#define FMOD_THREAD_AFFINITY_STREAM FMOD_THREAD_AFFINITY_GROUP_C +#define FMOD_THREAD_AFFINITY_FILE FMOD_THREAD_AFFINITY_GROUP_C +#define FMOD_THREAD_AFFINITY_NONBLOCKING FMOD_THREAD_AFFINITY_GROUP_C +#define FMOD_THREAD_AFFINITY_RECORD FMOD_THREAD_AFFINITY_GROUP_C +#define FMOD_THREAD_AFFINITY_GEOMETRY FMOD_THREAD_AFFINITY_GROUP_C +#define FMOD_THREAD_AFFINITY_PROFILER FMOD_THREAD_AFFINITY_GROUP_C +#define FMOD_THREAD_AFFINITY_STUDIO_UPDATE FMOD_THREAD_AFFINITY_GROUP_B +#define FMOD_THREAD_AFFINITY_STUDIO_LOAD_BANK FMOD_THREAD_AFFINITY_GROUP_C +#define FMOD_THREAD_AFFINITY_STUDIO_LOAD_SAMPLE FMOD_THREAD_AFFINITY_GROUP_C +#define FMOD_THREAD_AFFINITY_CONVOLUTION1 FMOD_THREAD_AFFINITY_GROUP_C +#define FMOD_THREAD_AFFINITY_CONVOLUTION2 FMOD_THREAD_AFFINITY_GROUP_C +/* Core mask, valid up to 1 << 62 */ +#define FMOD_THREAD_AFFINITY_CORE_ALL 0 +#define FMOD_THREAD_AFFINITY_CORE_0 (1 << 0) +#define FMOD_THREAD_AFFINITY_CORE_1 (1 << 1) +#define FMOD_THREAD_AFFINITY_CORE_2 (1 << 2) +#define FMOD_THREAD_AFFINITY_CORE_3 (1 << 3) +#define FMOD_THREAD_AFFINITY_CORE_4 (1 << 4) +#define FMOD_THREAD_AFFINITY_CORE_5 (1 << 5) +#define FMOD_THREAD_AFFINITY_CORE_6 (1 << 6) +#define FMOD_THREAD_AFFINITY_CORE_7 (1 << 7) +#define FMOD_THREAD_AFFINITY_CORE_8 (1 << 8) +#define FMOD_THREAD_AFFINITY_CORE_9 (1 << 9) +#define FMOD_THREAD_AFFINITY_CORE_10 (1 << 10) +#define FMOD_THREAD_AFFINITY_CORE_11 (1 << 11) +#define FMOD_THREAD_AFFINITY_CORE_12 (1 << 12) +#define FMOD_THREAD_AFFINITY_CORE_13 (1 << 13) +#define FMOD_THREAD_AFFINITY_CORE_14 (1 << 14) +#define FMOD_THREAD_AFFINITY_CORE_15 (1 << 15) + /* Preset for FMOD_REVERB_PROPERTIES */ #define FMOD_PRESET_OFF { 1000, 7, 11, 5000, 100, 100, 100, 250, 0, 20, 96, -80.0f } #define FMOD_PRESET_GENERIC { 1500, 7, 11, 5000, 83, 100, 100, 250, 0, 14500, 96, -8.0f } @@ -210,7 +298,26 @@ typedef unsigned int FMOD_CHANNELMASK; #define FMOD_MAX_SYSTEMS 8 #define FMOD_MAX_LISTENERS 8 #define FMOD_REVERB_MAXINSTANCES 4 -#define FMOD_PORT_INDEX_NONE 0xFFFFFFFFFFFFFFFF + +typedef enum FMOD_THREAD_TYPE +{ + FMOD_THREAD_TYPE_MIXER, + FMOD_THREAD_TYPE_FEEDER, + FMOD_THREAD_TYPE_STREAM, + FMOD_THREAD_TYPE_FILE, + FMOD_THREAD_TYPE_NONBLOCKING, + FMOD_THREAD_TYPE_RECORD, + FMOD_THREAD_TYPE_GEOMETRY, + FMOD_THREAD_TYPE_PROFILER, + FMOD_THREAD_TYPE_STUDIO_UPDATE, + FMOD_THREAD_TYPE_STUDIO_LOAD_BANK, + FMOD_THREAD_TYPE_STUDIO_LOAD_SAMPLE, + FMOD_THREAD_TYPE_CONVOLUTION1, + FMOD_THREAD_TYPE_CONVOLUTION2, + + FMOD_THREAD_TYPE_MAX, + FMOD_THREAD_TYPE_FORCEINT = 65536 +} FMOD_THREAD_TYPE; typedef enum FMOD_RESULT { @@ -330,6 +437,9 @@ typedef enum FMOD_OUTPUTTYPE FMOD_OUTPUTTYPE_NNAUDIO, FMOD_OUTPUTTYPE_WINSONIC, FMOD_OUTPUTTYPE_AAUDIO, + FMOD_OUTPUTTYPE_AUDIOWORKLET, + FMOD_OUTPUTTYPE_PHASE, + FMOD_OUTPUTTYPE_OHAUDIO, FMOD_OUTPUTTYPE_MAX, FMOD_OUTPUTTYPE_FORCEINT = 65536 @@ -531,6 +641,14 @@ typedef enum FMOD_DSP_RESAMPLER FMOD_DSP_RESAMPLER_FORCEINT = 65536 } FMOD_DSP_RESAMPLER; +typedef enum FMOD_DSP_CALLBACK_TYPE +{ + FMOD_DSP_CALLBACK_DATAPARAMETERRELEASE, + + FMOD_DSP_CALLBACK_MAX, + FMOD_DSP_CALLBACK_FORCEINT = 65536 +} FMOD_DSP_CALLBACK_TYPE; + typedef enum FMOD_DSPCONNECTION_TYPE { FMOD_DSPCONNECTION_TYPE_STANDARD, @@ -574,12 +692,27 @@ typedef enum FMOD_TAGDATATYPE FMOD_TAGDATATYPE_FORCEINT = 65536 } FMOD_TAGDATATYPE; +typedef enum FMOD_PORT_TYPE +{ + FMOD_PORT_TYPE_MUSIC, + FMOD_PORT_TYPE_COPYRIGHT_MUSIC, + FMOD_PORT_TYPE_VOICE, + FMOD_PORT_TYPE_CONTROLLER, + FMOD_PORT_TYPE_PERSONAL, + FMOD_PORT_TYPE_VIBRATION, + FMOD_PORT_TYPE_AUX, + + FMOD_PORT_TYPE_MAX, + FMOD_PORT_TYPE_FORCEINT = 65536 +} FMOD_PORT_TYPE; + /* FMOD callbacks */ typedef FMOD_RESULT (F_CALL *FMOD_DEBUG_CALLBACK) (FMOD_DEBUG_FLAGS flags, const char *file, int line, const char* func, const char* message); typedef FMOD_RESULT (F_CALL *FMOD_SYSTEM_CALLBACK) (FMOD_SYSTEM *system, FMOD_SYSTEM_CALLBACK_TYPE type, void *commanddata1, void* commanddata2, void *userdata); typedef FMOD_RESULT (F_CALL *FMOD_CHANNELCONTROL_CALLBACK) (FMOD_CHANNELCONTROL *channelcontrol, FMOD_CHANNELCONTROL_TYPE controltype, FMOD_CHANNELCONTROL_CALLBACK_TYPE callbacktype, void *commanddata1, void *commanddata2); +typedef FMOD_RESULT (F_CALL *FMOD_DSP_CALLBACK) (FMOD_DSP *dsp, FMOD_DSP_CALLBACK_TYPE type, void *data); typedef FMOD_RESULT (F_CALL *FMOD_SOUND_NONBLOCK_CALLBACK) (FMOD_SOUND *sound, FMOD_RESULT result); typedef FMOD_RESULT (F_CALL *FMOD_SOUND_PCMREAD_CALLBACK) (FMOD_SOUND *sound, void *data, unsigned int datalen); typedef FMOD_RESULT (F_CALL *FMOD_SOUND_PCMSETPOS_CALLBACK) (FMOD_SOUND *sound, int subsound, unsigned int position, FMOD_TIMEUNIT postype); @@ -659,12 +792,11 @@ typedef struct FMOD_ADVANCEDSETTINGS float distanceFilterCenterFreq; int reverb3Dinstance; int DSPBufferPoolSize; - unsigned int stackSizeStream; - unsigned int stackSizeNonBlocking; - unsigned int stackSizeMixer; FMOD_DSP_RESAMPLER resamplerMethod; - unsigned int commandQueueSize; unsigned int randomSeed; + int maxConvolutionThreads; + int maxOpusCodecs; + int maxSpatialObjects; } FMOD_ADVANCEDSETTINGS; typedef struct FMOD_TAG @@ -742,6 +874,23 @@ typedef struct FMOD_ERRORCALLBACK_INFO const char *functionparams; } FMOD_ERRORCALLBACK_INFO; +typedef struct FMOD_CPU_USAGE +{ + float dsp; + float stream; + float geometry; + float update; + float convolution1; + float convolution2; +} FMOD_CPU_USAGE; + +typedef struct FMOD_DSP_DATA_PARAMETER_INFO +{ + void *data; + unsigned int length; + int index; +} FMOD_DSP_DATA_PARAMETER_INFO; + /* FMOD optional headers for plugin development */ diff --git a/loader/include/Geode/fmod/fmod_dsp.h b/loader/include/Geode/fmod/fmod_dsp.h index dbfcad26..4719699c 100644 --- a/loader/include/Geode/fmod/fmod_dsp.h +++ b/loader/include/Geode/fmod/fmod_dsp.h @@ -1,13 +1,13 @@ /* ======================================================================================== */ /* FMOD Core API - DSP header file. */ -/* Copyright (c), Firelight Technologies Pty, Ltd. 2004-2020. */ +/* Copyright (c), Firelight Technologies Pty, Ltd. 2004-2024. */ /* */ /* Use this header if you are wanting to develop your own DSP plugin to use with FMODs */ /* dsp system. With this header you can make your own DSP plugin that FMOD can */ /* register and use. See the documentation and examples on how to make a working plugin. */ /* */ /* For more detail visit: */ -/* https://fmod.com/resources/documentation-api?version=2.0&page=plugin-api-dsp.html */ +/* https://fmod.com/docs/2.02/api/plugin-api-dsp.html */ /* =========================================================================================*/ #ifndef _FMOD_DSP_H #define _FMOD_DSP_H @@ -66,6 +66,7 @@ typedef enum FMOD_DSP_PARAMETER_DATA_TYPE_SIDECHAIN = -3, FMOD_DSP_PARAMETER_DATA_TYPE_FFT = -4, FMOD_DSP_PARAMETER_DATA_TYPE_3DATTRIBUTES_MULTI = -5, + FMOD_DSP_PARAMETER_DATA_TYPE_ATTENUATION_RANGE = -6, } FMOD_DSP_PARAMETER_DATA_TYPE; /* @@ -96,7 +97,7 @@ typedef FMOD_RESULT (F_CALL *FMOD_DSP_SYSTEM_MIX_CALLBACK) (FMOD_ typedef void * (F_CALL *FMOD_DSP_ALLOC_FUNC) (unsigned int size, FMOD_MEMORY_TYPE type, const char *sourcestr); typedef void * (F_CALL *FMOD_DSP_REALLOC_FUNC) (void *ptr, unsigned int size, FMOD_MEMORY_TYPE type, const char *sourcestr); typedef void (F_CALL *FMOD_DSP_FREE_FUNC) (void *ptr, FMOD_MEMORY_TYPE type, const char *sourcestr); -typedef void (F_CALL *FMOD_DSP_LOG_FUNC) (FMOD_DEBUG_FLAGS level, const char *file, int line, const char *function, const char *string); +typedef void (F_CALL *FMOD_DSP_LOG_FUNC) (FMOD_DEBUG_FLAGS level, const char *file, int line, const char *function, const char *str, ...); typedef FMOD_RESULT (F_CALL *FMOD_DSP_GETSAMPLERATE_FUNC) (FMOD_DSP_STATE *dsp_state, int *rate); typedef FMOD_RESULT (F_CALL *FMOD_DSP_GETBLOCKSIZE_FUNC) (FMOD_DSP_STATE *dsp_state, unsigned int *blocksize); typedef FMOD_RESULT (F_CALL *FMOD_DSP_GETSPEAKERMODE_FUNC) (FMOD_DSP_STATE *dsp_state, FMOD_SPEAKERMODE *speakermode_mixer, FMOD_SPEAKERMODE *speakermode_output); @@ -207,6 +208,12 @@ typedef struct FMOD_DSP_PARAMETER_3DATTRIBUTES_MULTI FMOD_3D_ATTRIBUTES absolute; } FMOD_DSP_PARAMETER_3DATTRIBUTES_MULTI; +typedef struct FMOD_DSP_PARAMETER_ATTENUATION_RANGE +{ + float min; + float max; +} FMOD_DSP_PARAMETER_ATTENUATION_RANGE; + typedef struct FMOD_DSP_PARAMETER_SIDECHAIN { FMOD_BOOL sidechainenable; diff --git a/loader/include/Geode/fmod/fmod_dsp_effects.h b/loader/include/Geode/fmod/fmod_dsp_effects.h index af1a0d65..2374a1aa 100644 --- a/loader/include/Geode/fmod/fmod_dsp_effects.h +++ b/loader/include/Geode/fmod/fmod_dsp_effects.h @@ -1,12 +1,12 @@ /* ============================================================================================================= */ /* FMOD Core API - Built-in effects header file. */ -/* Copyright (c), Firelight Technologies Pty, Ltd. 2004-2020. */ +/* Copyright (c), Firelight Technologies Pty, Ltd. 2004-2024. */ /* */ /* In this header you can find parameter structures for FMOD system registered DSP effects */ /* and generators. */ /* */ /* For more detail visit: */ -/* https://fmod.com/resources/documentation-api?version=2.0&page=core-api-common-dsp-effects.html#fmod_dsp_type */ +/* https://fmod.com/docs/2.02/api/core-api-common-dsp-effects.html#fmod_dsp_type */ /* ============================================================================================================= */ #ifndef _FMOD_DSP_EFFECTS_H @@ -126,7 +126,7 @@ typedef enum typedef enum { FMOD_DSP_NORMALIZE_FADETIME, - FMOD_DSP_NORMALIZE_THRESHHOLD, + FMOD_DSP_NORMALIZE_THRESHOLD, FMOD_DSP_NORMALIZE_MAXAMP } FMOD_DSP_NORMALIZE; @@ -363,6 +363,8 @@ typedef enum FMOD_DSP_PAN_OVERALL_GAIN, FMOD_DSP_PAN_SURROUND_SPEAKER_MODE, FMOD_DSP_PAN_2D_HEIGHT_BLEND, + FMOD_DSP_PAN_ATTENUATION_RANGE, + FMOD_DSP_PAN_OVERRIDE_RANGE } FMOD_DSP_PAN; @@ -404,6 +406,42 @@ typedef enum FMOD_DSP_FFT_DOMINANT_FREQ } FMOD_DSP_FFT; +#define FMOD_DSP_LOUDNESS_METER_HISTOGRAM_SAMPLES 66 + +typedef enum +{ + FMOD_DSP_LOUDNESS_METER_STATE, + FMOD_DSP_LOUDNESS_METER_WEIGHTING, + FMOD_DSP_LOUDNESS_METER_INFO +} FMOD_DSP_LOUDNESS_METER; + + +typedef enum +{ + FMOD_DSP_LOUDNESS_METER_STATE_RESET_INTEGRATED = -3, + FMOD_DSP_LOUDNESS_METER_STATE_RESET_MAXPEAK = -2, + FMOD_DSP_LOUDNESS_METER_STATE_RESET_ALL = -1, + FMOD_DSP_LOUDNESS_METER_STATE_PAUSED = 0, + FMOD_DSP_LOUDNESS_METER_STATE_ANALYZING = 1 +} FMOD_DSP_LOUDNESS_METER_STATE_TYPE; + +typedef struct FMOD_DSP_LOUDNESS_METER_INFO_TYPE +{ + float momentaryloudness; + float shorttermloudness; + float integratedloudness; + float loudness10thpercentile; + float loudness95thpercentile; + float loudnesshistogram[FMOD_DSP_LOUDNESS_METER_HISTOGRAM_SAMPLES]; + float maxtruepeak; + float maxmomentaryloudness; +} FMOD_DSP_LOUDNESS_METER_INFO_TYPE; + +typedef struct FMOD_DSP_LOUDNESS_METER_WEIGHTING_TYPE +{ + float channelweight[32]; +} FMOD_DSP_LOUDNESS_METER_WEIGHTING_TYPE; + typedef enum { @@ -530,7 +568,9 @@ typedef enum FMOD_DSP_OBJECTPAN_3D_SOUND_SIZE, FMOD_DSP_OBJECTPAN_3D_MIN_EXTENT, FMOD_DSP_OBJECTPAN_OVERALL_GAIN, - FMOD_DSP_OBJECTPAN_OUTPUTGAIN + FMOD_DSP_OBJECTPAN_OUTPUTGAIN, + FMOD_DSP_OBJECTPAN_ATTENUATION_RANGE, + FMOD_DSP_OBJECTPAN_OVERRIDE_RANGE } FMOD_DSP_OBJECTPAN; #endif diff --git a/loader/include/Geode/fmod/fmod_errors.h b/loader/include/Geode/fmod/fmod_errors.h new file mode 100644 index 00000000..2c158bfc --- /dev/null +++ b/loader/include/Geode/fmod/fmod_errors.h @@ -0,0 +1,110 @@ +/* ============================================================================================== */ +/* FMOD Core / Studio API - Error string header file. */ +/* Copyright (c), Firelight Technologies Pty, Ltd. 2004-2024. */ +/* */ +/* Use this header if you want to store or display a string version / english explanation */ +/* of the FMOD error codes. */ +/* */ +/* For more detail visit: */ +/* https://fmod.com/docs/2.02/api/core-api-common.html#fmod_result */ +/* =============================================================================================== */ +#ifndef _FMOD_ERRORS_H +#define _FMOD_ERRORS_H + +#include "fmod.h" + +#ifdef __GNUC__ +static const char *FMOD_ErrorString(FMOD_RESULT errcode) __attribute__((unused)); +#endif + +static const char *FMOD_ErrorString(FMOD_RESULT errcode) +{ + switch (errcode) + { + case FMOD_OK: return "No errors."; + case FMOD_ERR_BADCOMMAND: return "Tried to call a function on a data type that does not allow this type of functionality (ie calling Sound::lock on a streaming sound)."; + case FMOD_ERR_CHANNEL_ALLOC: return "Error trying to allocate a channel."; + case FMOD_ERR_CHANNEL_STOLEN: return "The specified channel has been reused to play another sound."; + case FMOD_ERR_DMA: return "DMA Failure. See debug output for more information."; + case FMOD_ERR_DSP_CONNECTION: return "DSP connection error. Connection possibly caused a cyclic dependency or connected dsps with incompatible buffer counts."; + case FMOD_ERR_DSP_DONTPROCESS: return "DSP return code from a DSP process query callback. Tells mixer not to call the process callback and therefore not consume CPU. Use this to optimize the DSP graph."; + case FMOD_ERR_DSP_FORMAT: return "DSP Format error. A DSP unit may have attempted to connect to this network with the wrong format, or a matrix may have been set with the wrong size if the target unit has a specified channel map."; + case FMOD_ERR_DSP_INUSE: return "DSP is already in the mixer's DSP network. It must be removed before being reinserted or released."; + case FMOD_ERR_DSP_NOTFOUND: return "DSP connection error. Couldn't find the DSP unit specified."; + case FMOD_ERR_DSP_RESERVED: return "DSP operation error. Cannot perform operation on this DSP as it is reserved by the system."; + case FMOD_ERR_DSP_SILENCE: return "DSP return code from a DSP process query callback. Tells mixer silence would be produced from read, so go idle and not consume CPU. Use this to optimize the DSP graph."; + case FMOD_ERR_DSP_TYPE: return "DSP operation cannot be performed on a DSP of this type."; + case FMOD_ERR_FILE_BAD: return "Error loading file."; + case FMOD_ERR_FILE_COULDNOTSEEK: return "Couldn't perform seek operation. This is a limitation of the medium (ie netstreams) or the file format."; + case FMOD_ERR_FILE_DISKEJECTED: return "Media was ejected while reading."; + case FMOD_ERR_FILE_EOF: return "End of file unexpectedly reached while trying to read essential data (truncated?)."; + case FMOD_ERR_FILE_ENDOFDATA: return "End of current chunk reached while trying to read data."; + case FMOD_ERR_FILE_NOTFOUND: return "File not found."; + case FMOD_ERR_FORMAT: return "Unsupported file or audio format."; + case FMOD_ERR_HEADER_MISMATCH: return "There is a version mismatch between the FMOD header and either the FMOD Studio library or the FMOD Low Level library."; + case FMOD_ERR_HTTP: return "A HTTP error occurred. This is a catch-all for HTTP errors not listed elsewhere."; + case FMOD_ERR_HTTP_ACCESS: return "The specified resource requires authentication or is forbidden."; + case FMOD_ERR_HTTP_PROXY_AUTH: return "Proxy authentication is required to access the specified resource."; + case FMOD_ERR_HTTP_SERVER_ERROR: return "A HTTP server error occurred."; + case FMOD_ERR_HTTP_TIMEOUT: return "The HTTP request timed out."; + case FMOD_ERR_INITIALIZATION: return "FMOD was not initialized correctly to support this function."; + case FMOD_ERR_INITIALIZED: return "Cannot call this command after System::init."; + case FMOD_ERR_INTERNAL: return "An error occured in the FMOD system. Use the logging version of FMOD for more information."; + case FMOD_ERR_INVALID_FLOAT: return "Value passed in was a NaN, Inf or denormalized float."; + case FMOD_ERR_INVALID_HANDLE: return "An invalid object handle was used."; + case FMOD_ERR_INVALID_PARAM: return "An invalid parameter was passed to this function."; + case FMOD_ERR_INVALID_POSITION: return "An invalid seek position was passed to this function."; + case FMOD_ERR_INVALID_SPEAKER: return "An invalid speaker was passed to this function based on the current speaker mode."; + case FMOD_ERR_INVALID_SYNCPOINT: return "The syncpoint did not come from this sound handle."; + case FMOD_ERR_INVALID_THREAD: return "Tried to call a function on a thread that is not supported."; + case FMOD_ERR_INVALID_VECTOR: return "The vectors passed in are not unit length, or perpendicular."; + case FMOD_ERR_MAXAUDIBLE: return "Reached maximum audible playback count for this sound's soundgroup."; + case FMOD_ERR_MEMORY: return "Not enough memory or resources."; + case FMOD_ERR_MEMORY_CANTPOINT: return "Can't use FMOD_OPENMEMORY_POINT on non PCM source data, or non mp3/xma/adpcm data if FMOD_CREATECOMPRESSEDSAMPLE was used."; + case FMOD_ERR_NEEDS3D: return "Tried to call a command on a 2d sound when the command was meant for 3d sound."; + case FMOD_ERR_NEEDSHARDWARE: return "Tried to use a feature that requires hardware support."; + case FMOD_ERR_NET_CONNECT: return "Couldn't connect to the specified host."; + case FMOD_ERR_NET_SOCKET_ERROR: return "A socket error occurred. This is a catch-all for socket-related errors not listed elsewhere."; + case FMOD_ERR_NET_URL: return "The specified URL couldn't be resolved."; + case FMOD_ERR_NET_WOULD_BLOCK: return "Operation on a non-blocking socket could not complete immediately."; + case FMOD_ERR_NOTREADY: return "Operation could not be performed because specified sound/DSP connection is not ready."; + case FMOD_ERR_OUTPUT_ALLOCATED: return "Error initializing output device, but more specifically, the output device is already in use and cannot be reused."; + case FMOD_ERR_OUTPUT_CREATEBUFFER: return "Error creating hardware sound buffer."; + case FMOD_ERR_OUTPUT_DRIVERCALL: return "A call to a standard soundcard driver failed, which could possibly mean a bug in the driver or resources were missing or exhausted."; + case FMOD_ERR_OUTPUT_FORMAT: return "Soundcard does not support the specified format."; + case FMOD_ERR_OUTPUT_INIT: return "Error initializing output device."; + case FMOD_ERR_OUTPUT_NODRIVERS: return "The output device has no drivers installed. If pre-init, FMOD_OUTPUT_NOSOUND is selected as the output mode. If post-init, the function just fails."; + case FMOD_ERR_PLUGIN: return "An unspecified error has been returned from a plugin."; + case FMOD_ERR_PLUGIN_MISSING: return "A requested output, dsp unit type or codec was not available."; + case FMOD_ERR_PLUGIN_RESOURCE: return "A resource that the plugin requires cannot be allocated or found. (ie the DLS file for MIDI playback)"; + case FMOD_ERR_PLUGIN_VERSION: return "A plugin was built with an unsupported SDK version."; + case FMOD_ERR_RECORD: return "An error occurred trying to initialize the recording device."; + case FMOD_ERR_REVERB_CHANNELGROUP: return "Reverb properties cannot be set on this channel because a parent channelgroup owns the reverb connection."; + case FMOD_ERR_REVERB_INSTANCE: return "Specified instance in FMOD_REVERB_PROPERTIES couldn't be set. Most likely because it is an invalid instance number or the reverb doesn't exist."; + case FMOD_ERR_SUBSOUNDS: return "The error occurred because the sound referenced contains subsounds when it shouldn't have, or it doesn't contain subsounds when it should have. The operation may also not be able to be performed on a parent sound."; + case FMOD_ERR_SUBSOUND_ALLOCATED: return "This subsound is already being used by another sound, you cannot have more than one parent to a sound. Null out the other parent's entry first."; + case FMOD_ERR_SUBSOUND_CANTMOVE: return "Shared subsounds cannot be replaced or moved from their parent stream, such as when the parent stream is an FSB file."; + case FMOD_ERR_TAGNOTFOUND: return "The specified tag could not be found or there are no tags."; + case FMOD_ERR_TOOMANYCHANNELS: return "The sound created exceeds the allowable input channel count. This can be increased using the 'maxinputchannels' parameter in System::setSoftwareFormat."; + case FMOD_ERR_TRUNCATED: return "The retrieved string is too long to fit in the supplied buffer and has been truncated."; + case FMOD_ERR_UNIMPLEMENTED: return "Something in FMOD hasn't been implemented when it should be. Contact support."; + case FMOD_ERR_UNINITIALIZED: return "This command failed because System::init or System::setDriver was not called."; + case FMOD_ERR_UNSUPPORTED: return "A command issued was not supported by this object. Possibly a plugin without certain callbacks specified."; + case FMOD_ERR_VERSION: return "The version number of this file format is not supported."; + case FMOD_ERR_EVENT_ALREADY_LOADED: return "The specified bank has already been loaded."; + case FMOD_ERR_EVENT_LIVEUPDATE_BUSY: return "The live update connection failed due to the game already being connected."; + case FMOD_ERR_EVENT_LIVEUPDATE_MISMATCH: return "The live update connection failed due to the game data being out of sync with the tool."; + case FMOD_ERR_EVENT_LIVEUPDATE_TIMEOUT: return "The live update connection timed out."; + case FMOD_ERR_EVENT_NOTFOUND: return "The requested event, parameter, bus or vca could not be found."; + case FMOD_ERR_STUDIO_UNINITIALIZED: return "The Studio::System object is not yet initialized."; + case FMOD_ERR_STUDIO_NOT_LOADED: return "The specified resource is not loaded, so it can't be unloaded."; + case FMOD_ERR_INVALID_STRING: return "An invalid string was passed to this function."; + case FMOD_ERR_ALREADY_LOCKED: return "The specified resource is already locked."; + case FMOD_ERR_NOT_LOCKED: return "The specified resource is not locked, so it can't be unlocked."; + case FMOD_ERR_RECORD_DISCONNECTED: return "The specified recording driver has been disconnected."; + case FMOD_ERR_TOOMANYSAMPLES: return "The length provided exceeds the allowable limit."; + default : return "Unknown error."; + }; +} + +#endif diff --git a/loader/include/Geode/fmod/fmod_output.h b/loader/include/Geode/fmod/fmod_output.h index a92b550b..61e1d8e6 100644 --- a/loader/include/Geode/fmod/fmod_output.h +++ b/loader/include/Geode/fmod/fmod_output.h @@ -1,6 +1,6 @@ /* ======================================================================================== */ /* FMOD Core API - output development header file. */ -/* Copyright (c), Firelight Technologies Pty, Ltd. 2004-2020. */ +/* Copyright (c), Firelight Technologies Pty, Ltd. 2004-2024. */ /* */ /* Use this header if you are wanting to develop your own output plugin to use with */ /* FMOD's output system. With this header you can make your own output plugin that FMOD */ @@ -8,7 +8,7 @@ /* plugin. */ /* */ /* For more detail visit: */ -/* https://fmod.com/resources/documentation-api?version=2.0&page=plugin-api-output.html */ +/* https://fmod.com/docs/2.02/api/plugin-api-output.html */ /* ======================================================================================== */ #ifndef _FMOD_OUTPUT_H #define _FMOD_OUTPUT_H @@ -19,27 +19,23 @@ typedef struct FMOD_OUTPUT_OBJECT3DINFO FMOD_OUTPUT_OBJECT3DINFO; /* Output constants */ -#define FMOD_OUTPUT_PLUGIN_VERSION 4 +#define FMOD_OUTPUT_PLUGIN_VERSION 5 typedef unsigned int FMOD_OUTPUT_METHOD; #define FMOD_OUTPUT_METHOD_MIX_DIRECT 0 -#define FMOD_OUTPUT_METHOD_POLLING 1 -#define FMOD_OUTPUT_METHOD_MIX_BUFFERED 2 +#define FMOD_OUTPUT_METHOD_MIX_BUFFERED 1 /* Output callbacks */ typedef FMOD_RESULT (F_CALL *FMOD_OUTPUT_GETNUMDRIVERS_CALLBACK) (FMOD_OUTPUT_STATE *output_state, int *numdrivers); typedef FMOD_RESULT (F_CALL *FMOD_OUTPUT_GETDRIVERINFO_CALLBACK) (FMOD_OUTPUT_STATE *output_state, int id, char *name, int namelen, FMOD_GUID *guid, int *systemrate, FMOD_SPEAKERMODE *speakermode, int *speakermodechannels); -typedef FMOD_RESULT (F_CALL *FMOD_OUTPUT_INIT_CALLBACK) (FMOD_OUTPUT_STATE *output_state, int selecteddriver, FMOD_INITFLAGS flags, int *outputrate, FMOD_SPEAKERMODE *speakermode, int *speakermodechannels, FMOD_SOUND_FORMAT *outputformat, int dspbufferlength, int dspnumbuffers, void *extradriverdata); +typedef FMOD_RESULT (F_CALL *FMOD_OUTPUT_INIT_CALLBACK) (FMOD_OUTPUT_STATE *output_state, int selecteddriver, FMOD_INITFLAGS flags, int *outputrate, FMOD_SPEAKERMODE *speakermode, int *speakermodechannels, FMOD_SOUND_FORMAT *outputformat, int dspbufferlength, int *dspnumbuffers, int *dspnumadditionalbuffers, void *extradriverdata); typedef FMOD_RESULT (F_CALL *FMOD_OUTPUT_START_CALLBACK) (FMOD_OUTPUT_STATE *output_state); typedef FMOD_RESULT (F_CALL *FMOD_OUTPUT_STOP_CALLBACK) (FMOD_OUTPUT_STATE *output_state); typedef FMOD_RESULT (F_CALL *FMOD_OUTPUT_CLOSE_CALLBACK) (FMOD_OUTPUT_STATE *output_state); typedef FMOD_RESULT (F_CALL *FMOD_OUTPUT_UPDATE_CALLBACK) (FMOD_OUTPUT_STATE *output_state); typedef FMOD_RESULT (F_CALL *FMOD_OUTPUT_GETHANDLE_CALLBACK) (FMOD_OUTPUT_STATE *output_state, void **handle); -typedef FMOD_RESULT (F_CALL *FMOD_OUTPUT_GETPOSITION_CALLBACK) (FMOD_OUTPUT_STATE *output_state, unsigned int *pcm); -typedef FMOD_RESULT (F_CALL *FMOD_OUTPUT_LOCK_CALLBACK) (FMOD_OUTPUT_STATE *output_state, unsigned int offset, unsigned int length, void **ptr1, void **ptr2, unsigned int *len1, unsigned int *len2); -typedef FMOD_RESULT (F_CALL *FMOD_OUTPUT_UNLOCK_CALLBACK) (FMOD_OUTPUT_STATE *output_state, void *ptr1, void *ptr2, unsigned int len1, unsigned int len2); typedef FMOD_RESULT (F_CALL *FMOD_OUTPUT_MIXER_CALLBACK) (FMOD_OUTPUT_STATE *output_state); typedef FMOD_RESULT (F_CALL *FMOD_OUTPUT_OBJECT3DGETINFO_CALLBACK) (FMOD_OUTPUT_STATE *output_state, int *maxhardwareobjects); typedef FMOD_RESULT (F_CALL *FMOD_OUTPUT_OBJECT3DALLOC_CALLBACK) (FMOD_OUTPUT_STATE *output_state, void **object3d); @@ -57,7 +53,7 @@ typedef FMOD_RESULT (F_CALL *FMOD_OUTPUT_COPYPORT_FUNC) (FMOD_OUTPUT typedef FMOD_RESULT (F_CALL *FMOD_OUTPUT_REQUESTRESET_FUNC) (FMOD_OUTPUT_STATE *output_state); typedef void * (F_CALL *FMOD_OUTPUT_ALLOC_FUNC) (unsigned int size, unsigned int align, const char *file, int line); typedef void (F_CALL *FMOD_OUTPUT_FREE_FUNC) (void *ptr, const char *file, int line); -typedef void (F_CALL *FMOD_OUTPUT_LOG_FUNC) (FMOD_DEBUG_FLAGS level, const char *file, int line, const char *function, const char *string); +typedef void (F_CALL *FMOD_OUTPUT_LOG_FUNC) (FMOD_DEBUG_FLAGS level, const char *file, int line, const char *function, const char *string, ...); /* Output structures @@ -67,7 +63,7 @@ typedef struct FMOD_OUTPUT_DESCRIPTION unsigned int apiversion; const char *name; unsigned int version; - FMOD_OUTPUT_METHOD polling; /* This will become "method" on the next major version */ + FMOD_OUTPUT_METHOD method; FMOD_OUTPUT_GETNUMDRIVERS_CALLBACK getnumdrivers; FMOD_OUTPUT_GETDRIVERINFO_CALLBACK getdriverinfo; FMOD_OUTPUT_INIT_CALLBACK init; @@ -76,9 +72,6 @@ typedef struct FMOD_OUTPUT_DESCRIPTION FMOD_OUTPUT_CLOSE_CALLBACK close; FMOD_OUTPUT_UPDATE_CALLBACK update; FMOD_OUTPUT_GETHANDLE_CALLBACK gethandle; - FMOD_OUTPUT_GETPOSITION_CALLBACK getposition; - FMOD_OUTPUT_LOCK_CALLBACK lock; - FMOD_OUTPUT_UNLOCK_CALLBACK unlock; FMOD_OUTPUT_MIXER_CALLBACK mixer; FMOD_OUTPUT_OBJECT3DGETINFO_CALLBACK object3dgetinfo; FMOD_OUTPUT_OBJECT3DALLOC_CALLBACK object3dalloc; @@ -120,7 +113,7 @@ struct FMOD_OUTPUT_OBJECT3DINFO #define FMOD_OUTPUT_FREE(_state, _ptr) \ (_state)->free(_ptr, __FILE__, __LINE__) #define FMOD_OUTPUT_LOG(_state, _level, _location, _format, ...) \ - (_state)->log(_level, __FILE__, __LINE__, _location, _format, __VA_ARGS__) + (_state)->log(_level, __FILE__, __LINE__, _location, _format, ##__VA_ARGS__) #define FMOD_OUTPUT_COPYPORT(_state, _id, _buffer, _length) \ (_state)->copyport(_state, _id, _buffer, _length) #define FMOD_OUTPUT_REQUESTRESET(_state) \ From f63bd44ad20ef94fc3b1fef453428c7d1e6f9fdf Mon Sep 17 00:00:00 2001 From: dankmeme01 <42031238+dankmeme01@users.noreply.github.com> Date: Mon, 5 Aug 2024 09:46:51 +0200 Subject: [PATCH 57/64] add custom constructor for ccfileutilsandroid --- .../cocos/platform/android/CCFileUtilsAndroid.h | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/loader/include/Geode/cocos/platform/android/CCFileUtilsAndroid.h b/loader/include/Geode/cocos/platform/android/CCFileUtilsAndroid.h index fc0321cc..01bd4034 100644 --- a/loader/include/Geode/cocos/platform/android/CCFileUtilsAndroid.h +++ b/loader/include/Geode/cocos/platform/android/CCFileUtilsAndroid.h @@ -1,18 +1,18 @@ /**************************************************************************** Copyright (c) 2010 cocos2d-x.org - + http://www.cocos2d-x.org - + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - + The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -42,6 +42,8 @@ NS_CC_BEGIN class CC_DLL CCFileUtilsAndroid : public CCFileUtils { GEODE_FRIEND_MODIFY + GEODE_CUSTOM_CONSTRUCTOR_COCOS(CCFileUtilsAndroid, CCFileUtils) + friend class CCFileUtils; CCFileUtilsAndroid(); public: @@ -53,12 +55,12 @@ public: virtual gd::string getWritablePath(); virtual bool isFileExist(const gd::string& strFilePath); virtual bool isAbsolutePath(const gd::string& strPath); - - /** This function is android specific. It is used for CCTextureCache::addImageAsync(). + + /** This function is android specific. It is used for CCTextureCache::addImageAsync(). Don't use it in your codes. */ unsigned char* getFileDataForAsync(const char* pszFileName, const char* pszMode, unsigned long * pSize); - + private: unsigned char* doGetFileData(const char* pszFileName, const char* pszMode, unsigned long * pSize, bool forAsync); }; From 81f8573cc523a8361674f4152d735b6979c63d24 Mon Sep 17 00:00:00 2001 From: Chloe <25387744+qimiko@users.noreply.github.com> Date: Mon, 5 Aug 2024 02:26:38 -0700 Subject: [PATCH 58/64] stl fix for member tests --- loader/include/Geode/c++stl/string.hpp | 2 +- loader/src/c++stl/string.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/loader/include/Geode/c++stl/string.hpp b/loader/include/Geode/c++stl/string.hpp index 1e0a1ac5..6b8ca914 100644 --- a/loader/include/Geode/c++stl/string.hpp +++ b/loader/include/Geode/c++stl/string.hpp @@ -52,7 +52,7 @@ namespace geode::stl { } namespace gd { -#if defined(GEODE_IS_MACOS) || defined(GEODE_IS_WINDOWS) +#if defined(GEODE_IS_MACOS) || defined(GEODE_IS_WINDOWS) || defined(GEODE_IS_IOS) // rob uses libc++ now! this will prob work fine using string = std::string; diff --git a/loader/src/c++stl/string.cpp b/loader/src/c++stl/string.cpp index eaab2453..7c7f18d9 100644 --- a/loader/src/c++stl/string.cpp +++ b/loader/src/c++stl/string.cpp @@ -14,7 +14,7 @@ using geode::stl::StringImpl; #define impl implFor((*this)) namespace gd { -#if !defined(GEODE_IS_MACOS) && !defined(GEODE_IS_WINDOWS) +#if !defined(GEODE_IS_MACOS) && !defined(GEODE_IS_IOS) && !defined(GEODE_IS_WINDOWS) string::string() { impl.setEmpty(); } From c11462af1d23832f39563bc16bf1ed4c941e6bc6 Mon Sep 17 00:00:00 2001 From: Cvolton Date: Mon, 5 Aug 2024 14:18:36 +0200 Subject: [PATCH 59/64] add arg name for fullPathForFilename --- loader/include/Geode/cocos/platform/CCFileUtils.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/loader/include/Geode/cocos/platform/CCFileUtils.h b/loader/include/Geode/cocos/platform/CCFileUtils.h index ac95e838..8ad4c192 100644 --- a/loader/include/Geode/cocos/platform/CCFileUtils.h +++ b/loader/include/Geode/cocos/platform/CCFileUtils.h @@ -165,7 +165,7 @@ public: @since v2.1 @note Robtop Addition: added a bool parameter */ - virtual gd::string fullPathForFilename(const char* pszFileName, bool); + virtual gd::string fullPathForFilename(const char* pszFileName, bool skipSuffix); // @note RobTop Addition virtual void removeFullPath(const char* path); From 677bd762dee47d9cdc1f69773e7603f225a38b13 Mon Sep 17 00:00:00 2001 From: TheSillyDoggo <95105680+TheSillyDoggo@users.noreply.github.com> Date: Tue, 6 Aug 2024 00:29:32 +1000 Subject: [PATCH 60/64] Change SwelvyBG sprites to be 2048x512 (#1029) Since these textures use GL_REPEAT, the resolution should be powers of two otherwise it might not work on some devices (such as iOS) Source: https://registry.khronos.org/OpenGL-Refpages/es2.0/xhtml/glTexParameter.xml --- loader/resources/swelve/swelve-layer0.png | Bin 2074 -> 6343 bytes loader/resources/swelve/swelve-layer1.png | Bin 3078 -> 7428 bytes loader/resources/swelve/swelve-layer2.png | Bin 2186 -> 6422 bytes loader/resources/swelve/swelve-layer3.png | Bin 267 -> 5422 bytes 4 files changed, 0 insertions(+), 0 deletions(-) diff --git a/loader/resources/swelve/swelve-layer0.png b/loader/resources/swelve/swelve-layer0.png index cbd6dc3f95becbbc966d9232d4f08b5414ff4d1d..8fbbecd927859971f8e8eace269071198a7c8e64 100644 GIT binary patch literal 6343 zcmeHLi&Ilq8vkx`2?3FW$71A_AP*~p7>ti}#U(J{qjaR;icnn|$P{c%YcRHk1=+Jj z5Q=uKs}?jBMyKqqW!WgZN@uBaZEdLK)sE|xE#k45wch9A}|3fF=Op^P( ze&>6f^PMDh&uv&c*EiG`0Oqb=m!1P4$43dsW%v_*mBETLI<-2`>hY*;N3l zvi0eyzqQ%#-}y3kV`i`+o1d9!oZ{E{Z9aC;-tzKQ`#<7eIx~5>VBp(1h=61{{RrvQ zj){jzcW<$i!^cBK&2LJbITxNWL)Z8LVNn1>&3k+PWP=Bz$Gs>|qVh*3wiGeBqhXW> zawmU87kUOVzWR?SNbV_WivJ_%TrHvp|5=*)LA27C{?%d8V2vid zj|%-ig2|D&;+k4*_ny2eJy~qS3cF-$D z>zfTrmPkYaS&~04)dhLAcFpmpl7!wv>b$zAntSWTA`Iobq!k;KpAUS(QhiIwMTH|G zo9pbfP@W4;_>t+0_HC$|=R*amn%ERBoMlX|laz;jXNSD+2C(}t){DHk?~vN~${WPm z`R*QXQ3Pc4Z;AAg>~n9PhTGj)tiER9d@6Du_DX^B0Cw!-KMO6#hPDrR^X4LQ-?o6J zX=Fm4Ku?--T%Q$A4bt;m(&wUO?ue`q%0KHosV19zBo{_6QwNfo|AUmfehFq=d#M3e zhe_~dMIPRhlV|g7Enm z#^<^9OpZeAPh=sw1Q(HeYO2SqPO71!t2K!`yjujlP;^-V=9gMj#$&6*+|DB?IdvdX z>bGZ93=Mr$U(_aXmfgZG2eKSvhxX7|nQCAIwQ%^?S3>hxkIFz<;1UIlBku-Cr~`oQ z&5RV_9=-J@BeoD8e|ks_#;|fH9vVt*=mBs2>qVtT!%?MTX1m<_{%oebG$f)B`bNdrl)m3*7T>ECf6o_do61ML6G-EY@($vUUUGu%n z-DT)9s80a5OS4&yM&e|T^H3?#6U+C2FxdqY!VR2lpHEkF;9oux=0XkRu&Y2xL&gJF+I)>1;fb% zh?%7&6e2tm97&jtBd|S&dgxhL6@aSP;xz(KzV`ut4W8oS!WCEt?AtrQ8;dX{w%8!> zB$DCk5RnV$DHnLyt^~g{KU}hVE3Khp1;ZKlqCr;A4r)-b2DDmSvbEPvrvtY`4slU3 zAc+&=X5FHMXP?2=SeKS#F)+4yjDeuaX>!t-`E3%SLV)o8WO`w6auy0Pq#H*+ph=Rq zeIR6k9Lv%8HeIpd02s5;!2NLo&B0I&fc|A8w55=%0bYuHyN#fCfaGe85(#02YzLbIN=R^&{sFfLA%gOHwWy`1nwSI)wDF4`g2=Z@LQ_{OF}#4VVN9M zCp0*^`YNbkTM%d?QgOD~?^E6p$H0{!7T(`kBO;z>A*N13d`Fj2y=4glnHXTSHAK{7 z(H$|VV3C!G*N4n64rVF6y8 z-Cjivget!t<4deh4^o~S!2-n$fbGO=S$T}XZ;cAnPydA)z=LQYb+yu`N~cBMjMWVo zfHebVv1s}e_^oC^AfMkS_Jx%C08yk%wwKb41h5O6zOT;9Ir!Z!amm-vU}LTKwCj;p zgv2yw$-v$Ea`(@S4UuO_Lbr&(C^fSpAhW|9c~%%Blr)Cf2LMJa5%Ti?MS z;-vI!BG2go@Qe-5y!2cY!rf>f!aF6;4e7ZdJvXFq6g=NAJvSt71J5rC&rhje;0^iM YJ25`z_2DD)>EF@oGd85Rr5WG&FXY_fGXMYp literal 2074 zcmeH{`BRfu6o${25CVZvSyB<%sz9k&iDeNGfgt-5+1DV!iYWvvN&=AzL^hYvK&u2S zghf<91VRO+X2b}JqZCX60hFMjSPd`{ZNUwde*HH(-kCe+p68x<&wI}g_jnl9pGYtv z001#Cz$XF#F9AT7w6G|N(D4gL1Ckx#?+qOzrgLbb!Jvdv0J_R`KBVB#Tr(^r%6D~j z6+K4xj~1W-!-}9ruEJl}$U$hPofQzD4WKvh-$w5K*s>RGQ6A_+iQ?>5%M%YOoQ)tn zb+v{UoZf7dxN*4n3$Dxaf#fYjZQA346+Ap!dM)_$;5!X7ZWl?VUdpxilOV={(j8%* z?%OGN<=#>@?2w#6uV+b;1Ix9B`Yhl@Y-Y$#@A8r$lhLWQG-3BrkQOblN1AfP&F7cx@?x8I>UM@bH{uG%08(wq44PdkA$9%UAln+wK{ z2vEh|_K;Tq#3IQRCy0dt4Hp-_)Vt;{uXqe3I@wLkn?tO184>YS6;qHp`P2S03^ju(YTd zI&FH)S;I`3ehKHG8gaH%!9=)Kb?~(}8z}hRBANL7^}$#zH?d+9=E{Ocy^RV^U&7M- zx2>2`@YU3Xdb@d^#n&n@Oqy62XOg=s#0)+%UbG6yn;?`Ib2Wu4Zua%=0tk zu5|B6aUZsYCuxj+u}KW{$vR539lPPM>_kbcV;|VMW;1!nxZI=Uo|6RH(scUSj#J{R z@B2rj4lgT5w6?T-g*TUPa}<~tZoT17OPJMDj87cQzp_0izVZa;1A=^p+}c<35v`oVKRU}6e>qjhB#j%3hnDNq=rlM@bT6p^5ZwF0!j?RD0yIiN)h)des7hV*vxJz~equ)?yd zp0ToNjF7)cjALDZ%a_c_o%;>AayjneC=TOA(72*{49Z=VMN)P$WJTVihfEv5hs!x+ z{(d~Xh}~)IU4?-MEjG0+ZNRNML!wGZAa-X-A-FJ0rBDZ#V&+v ze`Y9Uxf;Yt1eIl;Ehq!6mpLCjK-eB6YAVnImmp#RrBDm~&OWct6Zl_EU{W?UbyKtQ V>4cZnuZ;g*7U)a$>F}l({R^p$LInT- diff --git a/loader/resources/swelve/swelve-layer1.png b/loader/resources/swelve/swelve-layer1.png index 8ae3edc32522a6966ac9fe7a4f163b54ead667c7..0c4f7dbd5b19472c430e447b391c3927eddcbf1f 100644 GIT binary patch literal 7428 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 Zp9c9XyLq}nr;GjHh%?IFfoVs)^Dkw{hI{}3 diff --git a/loader/resources/swelve/swelve-layer3.png b/loader/resources/swelve/swelve-layer3.png index f1f6aac82503621e4551c77821d6d70160592ea1..c10606e8fb5baf20fa20c419b825d0612c67bc58 100644 GIT binary patch literal 5422 zcmeAS@N?(olHy`uVBq!ia0y~y-~ck27&zE~l-Tv2Iv~Ya;1OBOz`!jG!i)^F=14Fw zh&=FgaSW-L^Y)gbAcLa7fenxURL8k|NO+;brL`bC?HMyr9|+9*cApQzVqiEY31cZ7 zfUy`DK^B1lhXIV`(7*^|GV#Dz0tqly0|U%-1{R=GAYjx;hS9JDrryy+G@5&W1=wh@ zF7)F~0qfG-~P8e+(j5ZB`$zZheJlZq>CWFxt nn9-&I!)Vh0m=lmj4K^^QonZgNwbMTwD9+&N>gTe~DWM4fHjv-7 literal 267 zcmeAS@N?(olHy`uVBq!ia0y~yV86h?!1#rc87LAjt)c*=7>k44ofy`glX(f`u%tWs zIx;Y9?C1WI$O_~$2l#}z{{R1f`4Q<8KrUy2M`SSr1K(i~W;~w1A_XWo(bL5-q~g}w rgNBSi-k}9w{d2kX6@biv0XtSPzVc>ZJn+n8F316%u6{1-oD!M Date: Wed, 7 Aug 2024 19:18:36 +0200 Subject: [PATCH 61/64] fix missing GEODE_DLL in ccarray funcs --- loader/include/Geode/cocos/cocoa/CCArray.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/loader/include/Geode/cocos/cocoa/CCArray.h b/loader/include/Geode/cocos/cocoa/CCArray.h index 3fa0afa5..38978d7a 100644 --- a/loader/include/Geode/cocos/cocoa/CCArray.h +++ b/loader/include/Geode/cocos/cocoa/CCArray.h @@ -186,7 +186,7 @@ public: * Returns first element, or null if empty * @note Geode addition */ - CCObject* firstObject(); + GEODE_DLL CCObject* firstObject(); /** Returns last element */ CCObject* lastObject(); /** Returns a random element */ @@ -215,7 +215,7 @@ public: * Remove first object, or do nothing if array is empty * @note Geode addition */ - void removeFirstObject(bool bReleaseObj = true); + GEODE_DLL void removeFirstObject(bool bReleaseObj = true); /** Remove last object */ void removeLastObject(bool bReleaseObj = true); /** Remove a certain object */ From 80693c1db17aa79d9408845d7b6085cefae22776 Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Fri, 9 Aug 2024 18:38:59 +0300 Subject: [PATCH 62/64] Add code of conduct --- CODE_OF_CONDUCT.md | 94 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 CODE_OF_CONDUCT.md diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 00000000..a3088399 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,94 @@ + +# Code of Conduct + +## Notes + +As an open source project, our policies are based on a Code of Conduct. Please +make sure you read it before using our services. We expect everyone to follow +the guidelines presented in this document. + +## Our Pledge + +We as members, contributors, and leaders pledge to make participation in our +community a harassment-free experience for everyone, regardless of age, body +size, visible or invisible disability, ethnicity, sex characteristics, gender +identity and expression, level of experience, education, socio-economic status, +nationality, personal appearance, race, caste, color, religion, or sexual +identity and orientation. + +We pledge to act and interact in ways that contribute to an open, welcoming, +diverse, inclusive, and healthy community. + +## Our Standards + +Examples of behavior that contributes to a positive environment for our +community include: + +* Demonstrating empathy and kindness toward other people +* Being respectful of differing opinions, viewpoints, and experiences +* Giving and gracefully accepting constructive feedback +* Accepting responsibility and apologizing to those affected by our mistakes, + and learning from the experience +* Focusing on what is best not just for us as individuals, but for the overall + community + +Examples of unacceptable behavior include: + +* The use of sexualized language or imagery, and sexual attention or advances of + any kind +* Trolling (antagonistic, inflammatory, insincere behaviour), insulting or + derogatory comments, and personal or political attacks +* Threats of violence or violent acts towards others +* Public or private harassment +* Intentionally dead-naming or misgendering others +* Publishing others' private information, such as a physical or email address, + without their explicit permission +* Gatekeeping others' access to mental health or accessibility tools +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Enforcement Responsibilities + +Community leaders are responsible for clarifying and enforcing our standards of +acceptable behavior and will take appropriate and fair corrective action in +response to any behavior that they deem inappropriate, threatening, offensive, +or harmful. Actions may range from a warning to permanent removal from the +community. + +Community leaders have the right and responsibility to remove, edit, or reject +comments, commits, code, wiki edits, issues, and other contributions that are +not aligned to this Code of Conduct, and will communicate reasons for moderation +decisions when appropriate. + +## Scope + +This Code of Conduct applies within all community spaces, and also applies when +an individual is officially representing the community in public spaces. +Examples of representing our community include using an official email address, +posting via an official social media account, or acting as an appointed +representative at an online or offline event. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported to the community leaders directly on Discord, or via a private message +to the official Geode X account (@GeodeSDK). If your report concerns a specific +community team member or group of community team members, please send your +report to a team member that is not part of the report, or a member of the +administrative board. + +All complaints will be reviewed and investigated promptly and fairly. All +community leaders are obligated to respect the privacy and security of the +reporter of any incident. + +## Changes & Feedback + +Since the world is a dynamic place, this Code of Conduct may need changes. We +reserve the right to update this Code of Conduct at any time. + +We welcome feedback and suggestions. Feel free to open an issue on our +[GitHub](https://github.com/geode-sdk/geode). + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant version 2.1](https://www.contributor-covenant.org/version/2/1/code_of_conduct.html), with inspirations taken from [Prism Code of Conduct](https://prismlauncher.org/wiki/overview/code-of-conduct/) and [Quilt Code of Conduct](https://quiltmc.org/en/community/code-of-conduct/). From ab8ace055ade225097a7a0a85946ce5aa5031c9a Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Fri, 9 Aug 2024 18:41:24 +0300 Subject: [PATCH 63/64] Clarify code of conduct inspirations --- CODE_OF_CONDUCT.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index a3088399..a1ed7b88 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -91,4 +91,4 @@ We welcome feedback and suggestions. Feel free to open an issue on our ## Attribution -This Code of Conduct is adapted from the [Contributor Covenant version 2.1](https://www.contributor-covenant.org/version/2/1/code_of_conduct.html), with inspirations taken from [Prism Code of Conduct](https://prismlauncher.org/wiki/overview/code-of-conduct/) and [Quilt Code of Conduct](https://quiltmc.org/en/community/code-of-conduct/). +This Code of Conduct is adapted from the [Contributor Covenant version 2.1](https://www.contributor-covenant.org/version/2/1/code_of_conduct.html), with inspirations taken from [Prism Launcher Code of Conduct](https://prismlauncher.org/wiki/overview/code-of-conduct/) and [QuiltMC Code of Conduct](https://quiltmc.org/en/community/code-of-conduct/). From ca3a2a378af2182ed510ac7274987df26b3199da Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Fri, 9 Aug 2024 18:42:39 +0300 Subject: [PATCH 64/64] link geode sdk account in code of conduct --- CODE_OF_CONDUCT.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index a1ed7b88..18e59108 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -72,7 +72,7 @@ representative at an online or offline event. Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the community leaders directly on Discord, or via a private message -to the official Geode X account (@GeodeSDK). If your report concerns a specific +to the official Geode X account ([@GeodeSDK](https://x.com/GeodeSDK)). If your report concerns a specific community team member or group of community team members, please send your report to a team member that is not part of the report, or a member of the administrative board.