From 72cdad34ca7139cd3d7a3a0facb1c8d2e05ddcf8 Mon Sep 17 00:00:00 2001 From: HardCPP Date: Wed, 6 Aug 2025 23:43:25 +0200 Subject: [PATCH 1/9] Version 6.4.1 for BS 1.40.8 --- include/git_info.h | 2 +- mod.json | 22 +++++------ mod.template.json | 3 +- qpm.json | 17 +++----- qpm.shared.json | 97 +++++++++++++++++++++++++++------------------- 5 files changed, 77 insertions(+), 64 deletions(-) diff --git a/include/git_info.h b/include/git_info.h index c0e9730..9cb865e 100644 --- a/include/git_info.h +++ b/include/git_info.h @@ -1,5 +1,5 @@ #pragma once #define GIT_USER "HardCPP" #define GIT_BRANCH "dev" -#define GIT_COMMIT 0x136cce8 +#define GIT_COMMIT 0x651e00a #define GIT_MODIFIED 1 diff --git a/mod.json b/mod.json index 89fbd2b..965f5bd 100644 --- a/mod.json +++ b/mod.json @@ -5,37 +5,37 @@ "id": "qbeatsaberplus-notetweaker", "modloader": "Scotland2", "author": "HardCPP", - "version": "6.4.0", + "version": "6.4.1", "packageId": "com.beatgames.beatsaber", "packageVersion": "1.40.4_5283", "description": "Feel good!", "coverImage": "cover.png", "dependencies": [ { - "version": "^6.4.1", + "version": "^6.4.2", "id": "beatsaber-hook", - "downloadIfMissing": "https://github.com/QuestPackageManager/beatsaber-hook/releases/download/v6.4.1/beatsaber-hook.qmod" + "downloadIfMissing": "https://github.com/QuestPackageManager/beatsaber-hook/releases/download/v6.4.2/beatsaber-hook.qmod" }, { - "version": "^0.18.2", + "version": "^0.18.3", "id": "custom-types", - "downloadIfMissing": "https://github.com/QuestPackageManager/Il2CppQuestTypePatching/releases/download/v0.18.2/CustomTypes.qmod" + "downloadIfMissing": "https://github.com/QuestPackageManager/Il2CppQuestTypePatching/releases/download/v0.18.3/CustomTypes.qmod" }, { - "version": "^4.6.1", + "version": "^4.6.4", "id": "paper2_scotland2", - "downloadIfMissing": "https://github.com/Fernthedev/paperlog/releases/download/v4.6.3/paper2_scotland2.qmod" + "downloadIfMissing": "https://github.com/Fernthedev/paperlog/releases/download/v4.6.4/paper2_scotland2.qmod" }, { - "version": "^6.4.0", + "version": "^6.4.1", "id": "chatplex-sdk-bs", - "downloadIfMissing": "https://github.com/hardcpp/QuestChatPlexSDK-BS/releases/download/v6.4.0/ChatPlexSDK-BS.qmod" + "downloadIfMissing": "https://github.com/hardcpp/QuestChatPlexSDK-BS/releases/download/v6.4.1/ChatPlexSDK-BS.qmod" } ], - "modFiles": [ + "modFiles": [], + "lateModFiles": [ "libqbeatsaberplus-notetweaker.so" ], - "lateModFiles": [], "libraryFiles": [], "fileCopies": [], "copyExtensions": [] diff --git a/mod.template.json b/mod.template.json index 5af37ad..e442e71 100644 --- a/mod.template.json +++ b/mod.template.json @@ -11,7 +11,8 @@ "description": "Feel good!", "coverImage": "cover.png", "dependencies": [], - "modFiles": ["${binary}"], + "modFiles": [], + "lateModFiles": ["${binary}"], "libraryFiles": [], "fileCopies": [], "copyExtensions": [] diff --git a/qpm.json b/qpm.json index fb58a24..cdc05f7 100644 --- a/qpm.json +++ b/qpm.json @@ -5,7 +5,7 @@ "info": { "name": "QBeatSaberPlus-NoteTweaker", "id": "qbeatsaberplus-notetweaker", - "version": "6.4.0", + "version": "6.4.1", "url": "https://github.com/hardcpp/QBeatSaberPlus-NoteTweaker", "additionalData": { "overrideSoName": "libqbeatsaberplus-notetweaker.so", @@ -47,17 +47,17 @@ "dependencies": [ { "id": "beatsaber-hook", - "versionRange": "^6.4.1", + "versionRange": "^6.4.2", "additionalData": {} }, { "id": "bs-cordl", - "versionRange": "^4004.0.0", + "versionRange": "^4008.*", "additionalData": {} }, { "id": "custom-types", - "versionRange": "^0.18.2", + "versionRange": "^0.18.3", "additionalData": {} }, { @@ -68,11 +68,6 @@ "private": true } }, - { - "id": "libil2cpp", - "versionRange": "^0.4.0", - "additionalData": {} - }, { "id": "conditional-dependencies", "versionRange": "^0.3.0", @@ -82,7 +77,7 @@ }, { "id": "paper2_scotland2", - "versionRange": "^4.6.1", + "versionRange": "^4.6.4", "additionalData": {} }, { @@ -92,7 +87,7 @@ }, { "id": "chatplex-sdk-bs", - "versionRange": "^6.4.0", + "versionRange": "^6.4.1", "additionalData": { "private": true } diff --git a/qpm.shared.json b/qpm.shared.json index 9f26980..3332b29 100644 --- a/qpm.shared.json +++ b/qpm.shared.json @@ -1,13 +1,13 @@ { "$schema": "https://raw.githubusercontent.com/QuestPackageManager/QPM.Package/refs/heads/main/qpm.shared.schema.json", "config": { - "version": "0.1.0", + "version": "0.4.0", "sharedDir": "shared", "dependenciesDir": "extern", "info": { "name": "QBeatSaberPlus-NoteTweaker", "id": "qbeatsaberplus-notetweaker", - "version": "6.4.0", + "version": "6.4.1", "url": "https://github.com/hardcpp/QBeatSaberPlus-NoteTweaker", "additionalData": { "overrideSoName": "libqbeatsaberplus-notetweaker.so", @@ -38,24 +38,28 @@ "pwsh ./createqmod.ps1 -clean" ] }, - "qmodIncludeDirs": [], + "ndk": "^27.2.12479018", + "qmodIncludeDirs": [ + "build", + "extern/libs" + ], "qmodIncludeFiles": [], - "qmodOutput": null + "qmodOutput": "./QBeatSaberPlus-MenuMusic.qmod" }, "dependencies": [ { "id": "beatsaber-hook", - "versionRange": "^6.4.1", + "versionRange": "^6.4.2", "additionalData": {} }, { "id": "bs-cordl", - "versionRange": "^4004.0.0", + "versionRange": "4008.*", "additionalData": {} }, { "id": "custom-types", - "versionRange": "^0.18.2", + "versionRange": "^0.18.3", "additionalData": {} }, { @@ -66,11 +70,6 @@ "private": true } }, - { - "id": "libil2cpp", - "versionRange": "^0.4.0", - "additionalData": {} - }, { "id": "conditional-dependencies", "versionRange": "^0.3.0", @@ -80,7 +79,7 @@ }, { "id": "paper2_scotland2", - "versionRange": "^4.6.1", + "versionRange": "^4.6.4", "additionalData": {} }, { @@ -90,7 +89,7 @@ }, { "id": "chatplex-sdk-bs", - "versionRange": "^6.4.0", + "versionRange": "^6.4.1", "additionalData": { "private": true } @@ -101,12 +100,12 @@ { "dependency": { "id": "paper2_scotland2", - "versionRange": "=4.6.3", + "versionRange": "=4.6.4", "additionalData": { - "soLink": "https://github.com/Fernthedev/paperlog/releases/download/v4.6.3/libpaper2_scotland2.so", + "soLink": "https://github.com/Fernthedev/paperlog/releases/download/v4.6.4/libpaper2_scotland2.so", "overrideSoName": "libpaper2_scotland2.so", - "modLink": "https://github.com/Fernthedev/paperlog/releases/download/v4.6.3/paper2_scotland2.qmod", - "branchName": "version/v4_6_3", + "modLink": "https://github.com/Fernthedev/paperlog/releases/download/v4.6.4/paper2_scotland2.qmod", + "branchName": "version/v4_6_4", "compileOptions": { "systemIncludes": [ "shared/utfcpp/source" @@ -115,7 +114,7 @@ "cmake": false } }, - "version": "4.6.3" + "version": "4.6.4" }, { "dependency": { @@ -136,28 +135,28 @@ { "dependency": { "id": "chatplex-sdk-bs", - "versionRange": "=6.4.0", + "versionRange": "=6.4.1", "additionalData": { - "soLink": "https://github.com/hardcpp/QuestChatPlexSDK-BS/releases/download/v6.4.0/libchatplex-sdk-bs.so", - "debugSoLink": "https://github.com/hardcpp/QuestChatPlexSDK-BS/releases/download/v6.4.0/debug_libchatplex-sdk-bs.so", + "soLink": "https://github.com/hardcpp/QuestChatPlexSDK-BS/releases/download/v6.4.1/libchatplex-sdk-bs.so", + "debugSoLink": "https://github.com/hardcpp/QuestChatPlexSDK-BS/releases/download/v6.4.1/debug_libchatplex-sdk-bs.so", "overrideSoName": "libchatplex-sdk-bs.so", - "modLink": "https://github.com/hardcpp/QuestChatPlexSDK-BS/releases/download/v6.4.0/ChatPlexSDK-BS.qmod", - "branchName": "version/v6_4_0", + "modLink": "https://github.com/hardcpp/QuestChatPlexSDK-BS/releases/download/v6.4.1/ChatPlexSDK-BS.qmod", + "branchName": "version/v6_4_1", "cmake": true } }, - "version": "6.4.0" + "version": "6.4.1" }, { "dependency": { "id": "custom-types", - "versionRange": "=0.18.2", + "versionRange": "=0.18.3", "additionalData": { - "soLink": "https://github.com/QuestPackageManager/Il2CppQuestTypePatching/releases/download/v0.18.2/libcustom-types.so", - "debugSoLink": "https://github.com/QuestPackageManager/Il2CppQuestTypePatching/releases/download/v0.18.2/debug_libcustom-types.so", + "soLink": "https://github.com/QuestPackageManager/Il2CppQuestTypePatching/releases/download/v0.18.3/libcustom-types.so", + "debugSoLink": "https://github.com/QuestPackageManager/Il2CppQuestTypePatching/releases/download/v0.18.3/debug_libcustom-types.so", "overrideSoName": "libcustom-types.so", - "modLink": "https://github.com/QuestPackageManager/Il2CppQuestTypePatching/releases/download/v0.18.2/CustomTypes.qmod", - "branchName": "version/v0_18_2", + "modLink": "https://github.com/QuestPackageManager/Il2CppQuestTypePatching/releases/download/v0.18.3/CustomTypes.qmod", + "branchName": "version/v0_18_3", "compileOptions": { "cppFlags": [ "-Wno-invalid-offsetof" @@ -166,15 +165,15 @@ "cmake": true } }, - "version": "0.18.2" + "version": "0.18.3" }, { "dependency": { "id": "bs-cordl", - "versionRange": "=4004.0.0", + "versionRange": "=4008.0.0", "additionalData": { "headersOnly": true, - "branchName": "version/v4004_0_0", + "branchName": "version/v4008_0_0", "compileOptions": { "includePaths": [ "include" @@ -190,7 +189,7 @@ } } }, - "version": "4004.0.0" + "version": "4008.0.0" }, { "dependency": { @@ -207,17 +206,35 @@ { "dependency": { "id": "beatsaber-hook", - "versionRange": "=6.4.1", + "versionRange": "=6.4.2", "additionalData": { - "soLink": "https://github.com/QuestPackageManager/beatsaber-hook/releases/download/v6.4.1/libbeatsaber-hook.so", - "debugSoLink": "https://github.com/QuestPackageManager/beatsaber-hook/releases/download/v6.4.1/debug_libbeatsaber-hook.so", + "soLink": "https://github.com/QuestPackageManager/beatsaber-hook/releases/download/v6.4.2/libbeatsaber-hook.so", + "debugSoLink": "https://github.com/QuestPackageManager/beatsaber-hook/releases/download/v6.4.2/debug_libbeatsaber-hook.so", "overrideSoName": "libbeatsaber-hook.so", - "modLink": "https://github.com/QuestPackageManager/beatsaber-hook/releases/download/v6.4.1/beatsaber-hook.qmod", - "branchName": "version/v6_4_1", + "modLink": "https://github.com/QuestPackageManager/beatsaber-hook/releases/download/v6.4.2/beatsaber-hook.qmod", + "branchName": "version/v6_4_2", + "compileOptions": { + "cppFlags": [ + "-Wno-extra-qualification" + ] + }, "cmake": true } }, - "version": "6.4.1" + "version": "6.4.2" + }, + { + "dependency": { + "id": "libcurl", + "versionRange": "=8.5.0", + "additionalData": { + "staticLinking": true, + "soLink": "https://github.com/darknight1050/openssl-curl-android/releases/download/v8.5.0/libcurl.a", + "overrideSoName": "libcurl.a", + "branchName": "version-v8.5.0" + } + }, + "version": "8.5.0" }, { "dependency": { From bc756464af016a14f2e5216e9626f9afbe587f6d Mon Sep 17 00:00:00 2001 From: HardCPP Date: Mon, 10 Aug 2026 00:40:21 +0200 Subject: [PATCH 2/9] Move scripts --- build.ps1 => scripts/build.ps1 | 11 +- scripts/build.sh | 36 ++++++ copy.ps1 => scripts/copy.ps1 | 1 + scripts/copy.sh | 93 ++++++++++++++ createqmod.ps1 => scripts/createqmod.ps1 | 0 scripts/createqmod.sh | 94 ++++++++++++++ ndk-stack.ps1 => scripts/ndk-stack.ps1 | 2 +- scripts/ndk-stack.sh | 54 ++++++++ .../pull-tombstone.ps1 | 4 +- scripts/pull-tombstone.sh | 82 +++++++++++++ .../pullandanalyze.ps1 | 4 +- scripts/pullandanalyze.sh | 32 +++++ restart-game.ps1 => scripts/restart-game.ps1 | 0 scripts/restart-game.sh | 11 ++ .../start-logging.ps1 | 6 +- scripts/start-logging.sh | 115 ++++++++++++++++++ .../validate-modjson.ps1 | 0 scripts/validate-modjson.sh | 75 ++++++++++++ 18 files changed, 608 insertions(+), 12 deletions(-) rename build.ps1 => scripts/build.ps1 (80%) create mode 100755 scripts/build.sh rename copy.ps1 => scripts/copy.ps1 (99%) create mode 100755 scripts/copy.sh rename createqmod.ps1 => scripts/createqmod.ps1 (100%) create mode 100755 scripts/createqmod.sh rename ndk-stack.ps1 => scripts/ndk-stack.ps1 (99%) create mode 100755 scripts/ndk-stack.sh rename pull-tombstone.ps1 => scripts/pull-tombstone.ps1 (99%) create mode 100755 scripts/pull-tombstone.sh rename pullandanalyze.ps1 => scripts/pullandanalyze.ps1 (90%) create mode 100755 scripts/pullandanalyze.sh rename restart-game.ps1 => scripts/restart-game.ps1 (100%) create mode 100755 scripts/restart-game.sh rename start-logging.ps1 => scripts/start-logging.ps1 (93%) create mode 100755 scripts/start-logging.sh rename validate-modjson.ps1 => scripts/validate-modjson.ps1 (100%) create mode 100755 scripts/validate-modjson.sh diff --git a/build.ps1 b/scripts/build.ps1 similarity index 80% rename from build.ps1 rename to scripts/build.ps1 index fe746c3..33f3a7f 100644 --- a/build.ps1 +++ b/scripts/build.ps1 @@ -1,8 +1,8 @@ Param( - [Parameter(Mandatory=$false)] + [Parameter(Mandatory = $false)] [Switch] $clean, - [Parameter(Mandatory=$false)] + [Parameter(Mandatory = $false)] [Switch] $help ) @@ -25,7 +25,10 @@ if ($clean.IsPresent) { if (($clean.IsPresent) -or (-not (Test-Path -Path "build"))) { new-item -Path build -ItemType Directory -} +} & cmake -G "Ninja" -DCMAKE_BUILD_TYPE="RelWithDebInfo" -B build -& cmake --build ./build +& cmake --build ./build --parallel 12 + +$ExitCode = $LastExitCode +exit $ExitCode \ No newline at end of file diff --git a/scripts/build.sh b/scripts/build.sh new file mode 100755 index 0000000..692fd07 --- /dev/null +++ b/scripts/build.sh @@ -0,0 +1,36 @@ +#!/usr/bin/env bash + +set -euo pipefail + +script_dir="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)" +project_root="$(cd -- "$script_dir/.." && pwd -P)" +clean=false + +usage() { + cat <<'EOF' +"Build" - Compiles your mod into a ".so" or ".a" library + +Arguments: + -clean, --clean Delete the build folder before compiling + -help, --help Show this help +EOF +} + +while (($#)); do + case "$1" in + -clean|--clean) clean=true ;; + -help|--help|-h) usage; exit 0 ;; + *) printf 'Unknown argument: %s\n' "$1" >&2; usage >&2; exit 2 ;; + esac + shift +done + +cd -- "$project_root" + +if [[ "$clean" == true && -d "$project_root/build" ]]; then + rm -rf -- "$project_root/build" +fi + +mkdir -p -- "$project_root/build" +cmake -G Ninja -DCMAKE_BUILD_TYPE=RelWithDebInfo -B "$project_root/build" +cmake --build "$project_root/build" --parallel 12 diff --git a/copy.ps1 b/scripts/copy.ps1 similarity index 99% rename from copy.ps1 rename to scripts/copy.ps1 index 92456f1..aeabc97 100644 --- a/copy.ps1 +++ b/scripts/copy.ps1 @@ -71,6 +71,7 @@ foreach ($fileName in $modFiles) { } } + & $PSScriptRoot/restart-game.ps1 if ($log -eq $true) { diff --git a/scripts/copy.sh b/scripts/copy.sh new file mode 100755 index 0000000..fa83112 --- /dev/null +++ b/scripts/copy.sh @@ -0,0 +1,93 @@ +#!/usr/bin/env bash + +set -euo pipefail + +script_dir="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)" +project_root="$(cd -- "$script_dir/.." && pwd -P)" +clean=false +log=false +use_debug=false +self_only=false +all=false +custom="" +log_file="" + +usage() { + cat <<'EOF' +"Copy" - Builds and copies your mod to your Quest, then starts Beat Saber + +Arguments: + -clean, --clean Perform a clean build + -useDebug, --use-debug Copy files from build/debug + -log, --log Start logging after launching Beat Saber + +Logging arguments: + -self, --self Only show this mod and crash logs + -all, --all Show all logs from the Beat Saber process + -custom, --custom REGEX + Add a custom logging pattern + -file, --file FILE Save logging output under the scripts folder + -help, --help Show this help +EOF +} + +require_value() { + if (($# < 2)); then + printf 'Missing value for %s\n' "$1" >&2 + exit 2 + fi +} + +while (($#)); do + case "$1" in + -clean|--clean) clean=true; shift ;; + -log|--log) log=true; shift ;; + -useDebug|--use-debug) use_debug=true; shift ;; + -self|--self) self_only=true; shift ;; + -all|--all) all=true; shift ;; + -custom|--custom) require_value "$@"; custom="$2"; shift 2 ;; + -custom:*|--custom=*) custom="${1#*:}"; [[ "$1" == --custom=* ]] && custom="${1#*=}"; shift ;; + -file|--file) require_value "$@"; log_file="$2"; shift 2 ;; + -file:*|--file=*) log_file="${1#*:}"; [[ "$1" == --file=* ]] && log_file="${1#*=}"; shift ;; + -help|--help|-h) usage; exit 0 ;; + *) printf 'Unknown argument: %s\n' "$1" >&2; usage >&2; exit 2 ;; + esac +done + +cd -- "$project_root" + +build_args=() +[[ "$clean" == true ]] && build_args+=(--clean) +if "$script_dir/build.sh" "${build_args[@]}"; then + : +else + status=$? + printf 'Failed to build, exiting...\n' >&2 + exit "$status" +fi + +"$script_dir/validate-modjson.sh" + +if ! command -v jq >/dev/null 2>&1; then + printf 'Error: jq is required to read mod.json\n' >&2 + exit 1 +fi + +mapfile -t mod_files < <(jq -r '(.modFiles // [])[], (.lateModFiles // [])[]' "$project_root/mod.json") +for file_name in "${mod_files[@]}"; do + source_dir="$project_root/build" + [[ "$use_debug" == true ]] && source_dir="$project_root/build/debug" + adb push "$source_dir/$file_name" "/sdcard/ModData/com.beatgames.beatsaber/Modloader/mods/$file_name" +done + +"$script_dir/restart-game.sh" + +if [[ "$log" == true ]]; then + adb logcat -c + logging_args=() + [[ "$self_only" == true ]] && logging_args+=(--self) + [[ "$all" == true ]] && logging_args+=(--all) + [[ -n "$custom" ]] && logging_args+=(--custom "$custom") + [[ -n "$log_file" ]] && logging_args+=(--file "$log_file") + "$script_dir/start-logging.sh" "${logging_args[@]}" +fi diff --git a/createqmod.ps1 b/scripts/createqmod.ps1 similarity index 100% rename from createqmod.ps1 rename to scripts/createqmod.ps1 diff --git a/scripts/createqmod.sh b/scripts/createqmod.sh new file mode 100755 index 0000000..bdce95d --- /dev/null +++ b/scripts/createqmod.sh @@ -0,0 +1,94 @@ +#!/usr/bin/env bash + +set -euo pipefail + +script_dir="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)" +project_root="$(cd -- "$script_dir/.." && pwd -P)" +qmod_name="" +clean=false + +usage() { + cat <<'EOF' +"CreateQmod" - Packages mod.json and its files into a .qmod archive + +Usage: createqmod.sh [QMOD_NAME] [-clean] + +Arguments: + -qmodname, --qmod-name NAME Set the output name (defaults to mod.json's name) + -clean, --clean Build a fresh archive instead of updating an old one + -help, --help Show this help +EOF +} + +while (($#)); do + case "$1" in + -qmodname|--qmod-name) + (($# >= 2)) || { printf 'Missing qmod name\n' >&2; exit 2; } + qmod_name="$2" + shift 2 + ;; + -qmodname:*|--qmod-name=*) + qmod_name="${1#*:}" + [[ "$1" == --qmod-name=* ]] && qmod_name="${1#*=}" + shift + ;; + -clean|--clean) clean=true; shift ;; + -help|--help|-h) usage; exit 0 ;; + -*) printf 'Unknown argument: %s\n' "$1" >&2; usage >&2; exit 2 ;; + *) + [[ -z "$qmod_name" ]] || { printf 'Unexpected argument: %s\n' "$1" >&2; exit 2; } + qmod_name="$1" + shift + ;; + esac +done + +cd -- "$project_root" + +for tool in jq zip; do + command -v "$tool" >/dev/null 2>&1 || { printf 'Error: %s is required\n' "$tool" >&2; exit 1; } +done + +mod_file="$project_root/mod.json" +[[ -f "$mod_file" ]] || { printf 'Error: mod.json was not found\n' >&2; exit 1; } + +if [[ -z "$qmod_name" ]]; then + qmod_name="$(jq -er '.name' "$mod_file")" +fi + +files=("$mod_file") +cover="$(jq -r '.coverImage // empty' "$mod_file")" +if [[ -n "$cover" && -f "$project_root/$cover" ]]; then + files+=("$project_root/$cover") +fi + +mapfile -t packaged_files < <(jq -r '(.modFiles // [])[], (.lateModFiles // [])[], (.libraryFiles // [])[]' "$mod_file") +for file_name in "${packaged_files[@]}"; do + path="$project_root/build/$file_name" + [[ -f "$path" ]] || path="$project_root/extern/libs/$file_name" + if [[ ! -f "$path" ]]; then + printf 'Error: could not find dependency: %s\n' "$path" >&2 + exit 1 + fi + files+=("$path") +done + +[[ "$clean" == true ]] && printf 'Making clean Qmod\n' + +output="$project_root/${qmod_name}.qmod" +temp_dir="$(mktemp -d)" +trap 'rm -rf -- "$temp_dir"' EXIT +temp_archive="$temp_dir/archive.zip" + +if [[ "$clean" == false && -f "$output" ]]; then + cp -- "$output" "$temp_archive" +fi + +if [[ -f "$temp_archive" ]]; then + zip -j -u "$temp_archive" "${files[@]}" +else + zip -j "$temp_archive" "${files[@]}" +fi + +mv -- "$temp_archive" "$output" +printf 'Created %s\n' "$output" diff --git a/ndk-stack.ps1 b/scripts/ndk-stack.ps1 similarity index 99% rename from ndk-stack.ps1 rename to scripts/ndk-stack.ps1 index b247dbc..ac30cea 100644 --- a/ndk-stack.ps1 +++ b/scripts/ndk-stack.ps1 @@ -9,7 +9,7 @@ Param( if ($help -eq $true) { Write-Output "`"NDK-Stack`" - Processes a tombstone using the debug .so to find file locations" Write-Output "`n-- Arguments --`n" - + Write-Output "LogName `t`t The file name of the tombstone to process" exit diff --git a/scripts/ndk-stack.sh b/scripts/ndk-stack.sh new file mode 100755 index 0000000..faeafa8 --- /dev/null +++ b/scripts/ndk-stack.sh @@ -0,0 +1,54 @@ +#!/usr/bin/env bash + +set -euo pipefail + +script_dir="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)" +project_root="$(cd -- "$script_dir/.." && pwd -P)" +log_name="log.log" + +usage() { + cat <<'EOF' +"NDK-Stack" - Processes a tombstone using the debug .so files + +Usage: ndk-stack.sh [LOG_NAME] + +Arguments: + -logName, --log-name FILE Tombstone to process (default: log.log) + -help, --help Show this help +EOF +} + +while (($#)); do + case "$1" in + -logName|--log-name) + (($# >= 2)) || { printf 'Missing log file name\n' >&2; exit 2; } + log_name="$2" + shift 2 + ;; + -logName:*|--log-name=*) + log_name="${1#*:}" + [[ "$1" == --log-name=* ]] && log_name="${1#*=}" + shift + ;; + -help|--help|-h) usage; exit 0 ;; + -*) printf 'Unknown argument: %s\n' "$1" >&2; usage >&2; exit 2 ;; + *) log_name="$1"; shift ;; + esac +done + +cd -- "$project_root" + +if [[ -f "$project_root/ndkpath.txt" ]]; then + IFS= read -r ndk_path < "$project_root/ndkpath.txt" || true + ndk_path="${ndk_path%$'\r'}" +else + ndk_path="${ANDROID_NDK_HOME:-}" +fi + +[[ -n "$ndk_path" ]] || { printf 'Error: set ANDROID_NDK_HOME or create ndkpath.txt\n' >&2; exit 1; } +stack_script="$ndk_path/ndk-stack" +[[ -x "$stack_script" ]] || { printf 'Error: ndk-stack was not found at %s\n' "$stack_script" >&2; exit 1; } +[[ -f "$log_name" ]] || { printf 'Error: log file was not found: %s\n' "$log_name" >&2; exit 1; } + +"$stack_script" -sym "$project_root/build/debug/" < "$log_name" > "${log_name}_processed.log" +printf 'Created %s\n' "${log_name}_processed.log" diff --git a/pull-tombstone.ps1 b/scripts/pull-tombstone.ps1 similarity index 99% rename from pull-tombstone.ps1 rename to scripts/pull-tombstone.ps1 index 17d3f83..10fbc24 100644 --- a/pull-tombstone.ps1 +++ b/scripts/pull-tombstone.ps1 @@ -1,10 +1,10 @@ Param( [Parameter(Mandatory=$false)] [String] $fileName = "RecentCrash.log", - + [Parameter(Mandatory=$false)] [Switch] $analyze, - + [Parameter(Mandatory=$false)] [Switch] $help ) diff --git a/scripts/pull-tombstone.sh b/scripts/pull-tombstone.sh new file mode 100755 index 0000000..fa339d9 --- /dev/null +++ b/scripts/pull-tombstone.sh @@ -0,0 +1,82 @@ +#!/usr/bin/env bash + +set -euo pipefail + +script_dir="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)" +project_root="$(cd -- "$script_dir/.." && pwd -P)" +file_name="RecentCrash.log" +analyze=false + +usage() { + cat <<'EOF' +"Pull-Tombstone" - Pulls the most recent Beat Saber tombstone from your Quest + +Arguments: + -fileName, --file-name FILE Output file (default: RecentCrash.log) + -analyze, --analyze Process the file with ndk-stack afterward + -help, --help Show this help +EOF +} + +while (($#)); do + case "$1" in + -fileName|--file-name) + (($# >= 2)) || { printf 'Missing output file name\n' >&2; exit 2; } + file_name="$2" + shift 2 + ;; + -fileName:*|--file-name=*) + file_name="${1#*:}" + [[ "$1" == --file-name=* ]] && file_name="${1#*=}" + shift + ;; + -analyze|--analyze) analyze=true; shift ;; + -help|--help|-h) usage; exit 0 ;; + *) printf 'Unknown argument: %s\n' "$1" >&2; usage >&2; exit 2 ;; + esac +done + +cd -- "$project_root" + +current_epoch="$(date +%s)" +recent_epoch="" +recent_tombstone="" + +for index in 0 1 2; do + remote="/sdcard/Android/data/com.beatgames.beatsaber/files/tombstone_0${index}" + if ! stats="$(adb shell stat "$remote" 2>&1)"; then + printf 'Failed to inspect tombstone_0%s: %s\n' "$index" "$stats" >&2 + exit 1 + fi + + modified="$(sed -nE 's/^Modify:[[:space:]]+([0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}).*/\1/p' <<< "$stats" | head -n 1)" + if [[ -z "$modified" ]] || ! modified_epoch="$(date -d "$modified" +%s 2>/dev/null)"; then + printf 'Failed to read the modification time for tombstone_0%s\n' "$index" >&2 + exit 1 + fi + + delta=$((current_epoch - modified_epoch)) + if ((delta >= 0)); then + difference=$(((delta + 30) / 60)) + else + difference=$(((delta - 30) / 60)) + fi + + if ((difference == 1)); then + printf 'Found tombstone_0%s %s minute ago\n' "$index" "$difference" + else + printf 'Found tombstone_0%s %s minutes ago\n' "$index" "$difference" + fi + + if [[ -z "$recent_epoch" ]] || ((modified_epoch > recent_epoch)); then + recent_epoch="$modified_epoch" + recent_tombstone="$index" + fi +done + +printf 'Latest tombstone was tombstone_0%s\n' "$recent_tombstone" +adb pull "/sdcard/Android/data/com.beatgames.beatsaber/files/tombstone_0${recent_tombstone}" "$file_name" + +if [[ "$analyze" == true ]]; then + "$script_dir/ndk-stack.sh" --log-name "$file_name" +fi diff --git a/pullandanalyze.ps1 b/scripts/pullandanalyze.ps1 similarity index 90% rename from pullandanalyze.ps1 rename to scripts/pullandanalyze.ps1 index 813eb55..736f3b4 100644 --- a/pullandanalyze.ps1 +++ b/scripts/pullandanalyze.ps1 @@ -1,4 +1,4 @@ - + $NDKPath = $env:ANDROID_NDK_HOME $stackScript = "$NDKPath/ndk-stack" @@ -8,4 +8,4 @@ if (-not ($PSVersionTable.PSEdition -eq "Core")) { $filename = "tombstone_0" + $args[0] & adb pull /storage/emulated/0/Android/data/com.beatgames.beatsaber/files/$($filename) Get-Content $filename | & $stackScript -sym ./build/debug/ > "$($filename)_unstripped.txt" -& code "$($filename)_unstripped.txt" +& code "$($filename)_unstripped.txt" diff --git a/scripts/pullandanalyze.sh b/scripts/pullandanalyze.sh new file mode 100755 index 0000000..d8c1c4b --- /dev/null +++ b/scripts/pullandanalyze.sh @@ -0,0 +1,32 @@ +#!/usr/bin/env bash + +set -euo pipefail + +script_dir="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)" +project_root="$(cd -- "$script_dir/.." && pwd -P)" + +if [[ "${1:-}" == "-help" || "${1:-}" == "--help" || "${1:-}" == "-h" ]]; then + printf 'Usage: pullandanalyze.sh TOMBSTONE_INDEX\n' + exit 0 +fi + +if (($# != 1)); then + printf 'Usage: pullandanalyze.sh TOMBSTONE_INDEX\n' >&2 + exit 2 +fi + +ndk_path="${ANDROID_NDK_HOME:-}" +[[ -n "$ndk_path" ]] || { printf 'Error: ANDROID_NDK_HOME is not set\n' >&2; exit 1; } +stack_script="$ndk_path/ndk-stack" +[[ -x "$stack_script" ]] || { printf 'Error: ndk-stack was not found at %s\n' "$stack_script" >&2; exit 1; } + +cd -- "$project_root" +filename="tombstone_0${1}" +adb pull "/storage/emulated/0/Android/data/com.beatgames.beatsaber/files/$filename" +"$stack_script" -sym "$project_root/build/debug/" < "$filename" > "${filename}_unstripped.txt" + +if command -v code >/dev/null 2>&1; then + code "${filename}_unstripped.txt" +else + printf 'Created %s (the code command was not found, so it was not opened)\n' "${filename}_unstripped.txt" +fi diff --git a/restart-game.ps1 b/scripts/restart-game.ps1 similarity index 100% rename from restart-game.ps1 rename to scripts/restart-game.ps1 diff --git a/scripts/restart-game.sh b/scripts/restart-game.sh new file mode 100755 index 0000000..9444092 --- /dev/null +++ b/scripts/restart-game.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env bash + +set -euo pipefail + +package="com.beatgames.beatsaber" +activity="$package/com.unity3d.player.UnityPlayerActivity" + +adb shell am force-stop "$package" +adb shell am start "$activity" +sleep 1 +adb shell am start "$activity" diff --git a/start-logging.ps1 b/scripts/start-logging.ps1 similarity index 93% rename from start-logging.ps1 rename to scripts/start-logging.ps1 index 91fdbab..44320c7 100644 --- a/start-logging.ps1 +++ b/scripts/start-logging.ps1 @@ -36,7 +36,7 @@ if ($help -eq $true) { $bspid = adb shell pidof com.beatgames.beatsaber $command = "adb logcat " -if ($all -eq $false) { +if ($all -eq $true) { $loops = 0 while ([string]::IsNullOrEmpty($bspid) -and $loops -lt 3) { Start-Sleep -Milliseconds 100 @@ -55,8 +55,8 @@ if ($all -eq $false) { if ($all -eq $false) { $pattern = "(" if ($self -eq $true) { - $modID = (Get-Content "./mod.json" -Raw | ConvertFrom-Json).id - $pattern += "ChatPlexSDK-BS|$modID|" + $modName = (Get-Content "./mod.json" -Raw | ConvertFrom-Json).name + $pattern += "ChatPlexSDK-BS|$modName|" } if (![string]::IsNullOrEmpty($custom)) { $pattern += "$custom|" diff --git a/scripts/start-logging.sh b/scripts/start-logging.sh new file mode 100755 index 0000000..6bc6b95 --- /dev/null +++ b/scripts/start-logging.sh @@ -0,0 +1,115 @@ +#!/usr/bin/env bash + +set -euo pipefail + +script_dir="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)" +project_root="$(cd -- "$script_dir/.." && pwd -P)" +self_only=false +all=false +custom="" +log_file="" +exclude_header=false +show_help=false + +usage() { + if [[ "$exclude_header" == false ]]; then + cat <<'EOF' +"Start-Logging" - Logs Beat Saber using adb logcat + +Arguments: +EOF + fi + cat <<'EOF' + -self, --self Only show this mod and crash logs + -all, --all Show all logs from the Beat Saber process + -custom, --custom REGEX + Add a custom pattern; AndroidRuntime and CRASH are always included + -file, --file FILE Save output under the scripts folder + -help, --help Show this help +EOF +} + +while (($#)); do + case "$1" in + -self|--self) self_only=true; shift ;; + -all|--all) all=true; shift ;; + -custom|--custom) + (($# >= 2)) || { printf 'Missing custom pattern\n' >&2; exit 2; } + custom="$2" + shift 2 + ;; + -custom:*|--custom=*) + custom="${1#*:}" + [[ "$1" == --custom=* ]] && custom="${1#*=}" + shift + ;; + -file|--file) + (($# >= 2)) || { printf 'Missing output file\n' >&2; exit 2; } + log_file="$2" + shift 2 + ;; + -file:*|--file=*) + log_file="${1#*:}" + [[ "$1" == --file=* ]] && log_file="${1#*=}" + shift + ;; + -excludeHeader|--exclude-header) exclude_header=true; shift ;; + -help|--help|-h) show_help=true; shift ;; + *) printf 'Unknown argument: %s\n' "$1" >&2; usage >&2; exit 2 ;; + esac +done + +if [[ "$show_help" == true ]]; then + usage + exit 0 +fi + +cd -- "$project_root" + +output_file="" +if [[ -n "$log_file" ]]; then + if [[ "$log_file" = /* ]]; then + output_file="$log_file" + else + output_file="$script_dir/$log_file" + fi +fi + +if [[ "$all" == true ]]; then + beat_saber_pid="" + for _ in 0 1 2 3; do + beat_saber_pid="$(adb shell pidof com.beatgames.beatsaber 2>/dev/null | tr -d '\r')" + [[ -n "$beat_saber_pid" ]] && break + sleep 0.1 + done + + if [[ -z "$beat_saber_pid" ]]; then + printf 'Could not connect to adb or find Beat Saber, exiting...\n' >&2 + exit 1 + fi + + printf 'Logging using command: adb logcat --pid %s\n' "$beat_saber_pid" + if [[ -n "$output_file" ]]; then + adb logcat --pid "$beat_saber_pid" > "$output_file" + else + adb logcat --pid "$beat_saber_pid" + fi + exit +fi + +pattern="" +if [[ "$self_only" == true ]]; then + command -v jq >/dev/null 2>&1 || { printf 'Error: jq is required for --self\n' >&2; exit 1; } + mod_name="$(jq -er '.name' "$project_root/mod.json")" + pattern+="ChatPlexSDK-BS|$mod_name|" +fi +[[ -n "$custom" ]] && pattern+="$custom|" +[[ -n "$pattern" ]] || pattern='QuestHook|modloader|scotland2|ChatPlexSDK-BS|' +pattern+='AndroidRuntime|CRASH' + +printf 'Logging using command: adb logcat | grep -E %q\n' "$pattern" +if [[ -n "$output_file" ]]; then + adb logcat | grep --line-buffered -E "$pattern" > "$output_file" +else + adb logcat | grep --line-buffered -E "$pattern" +fi diff --git a/validate-modjson.ps1 b/scripts/validate-modjson.ps1 similarity index 100% rename from validate-modjson.ps1 rename to scripts/validate-modjson.ps1 diff --git a/scripts/validate-modjson.sh b/scripts/validate-modjson.sh new file mode 100755 index 0000000..9b7cf9a --- /dev/null +++ b/scripts/validate-modjson.sh @@ -0,0 +1,75 @@ +#!/usr/bin/env bash +exit +set -euo pipefail + +script_dir="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)" +project_root="$(cd -- "$script_dir/.." && pwd -P)" +mod_file="$project_root/mod.json" +template_file="$project_root/mod.template.json" +schema_url="https://raw.githubusercontent.com/Lauriethefish/QuestPatcher.QMod/refs/heads/main/QuestPatcher.QMod/Resources/qmod.schema.json" + +cd -- "$project_root" + +if [[ ! -f "$mod_file" ]]; then + if [[ -f "$template_file" ]]; then + if command -v qpm-rust >/dev/null 2>&1; then + qpm-rust qmod build + elif command -v qpm >/dev/null 2>&1; then + qpm qmod build + else + printf 'Error: qpm is required to generate mod.json from mod.template.json\n' >&2 + exit 1 + fi + else + printf 'Error: mod.json and mod.template.json were not present\n' >&2 + exit 1 + fi +fi + +printf 'Creating qmod from mod.json\n' +command -v curl >/dev/null 2>&1 || { printf 'Error: curl is required to download the qmod schema\n' >&2; exit 1; } +command -v python3 >/dev/null 2>&1 || { printf 'Error: Python 3 and jsonschema are required to validate mod.json\n' >&2; exit 1; } + +schema_file="$(mktemp)" +trap 'rm -f -- "$schema_file"' EXIT +curl -fsSL "$schema_url" -o "$schema_file" + +printf 'Validating mod.json...\n' +python3 - "$mod_file" "$schema_file" <<'PY' +import json +import sys + +try: + import jsonschema +except ImportError: + print("Error: install the Python 'jsonschema' package to validate mod.json", file=sys.stderr) + raise SystemExit(1) + +mod_path, schema_path = sys.argv[1:] +try: + with open(mod_path, encoding="utf-8") as mod_stream: + instance = json.load(mod_stream) + with open(schema_path, encoding="utf-8") as schema_stream: + schema = json.load(schema_stream) +except (OSError, json.JSONDecodeError) as error: + print(f"Error: {error}", file=sys.stderr) + raise SystemExit(1) + +validator_class = jsonschema.validators.validator_for(schema) +try: + validator_class.check_schema(schema) +except jsonschema.SchemaError as error: + print(f"Error: invalid qmod schema: {error.message}", file=sys.stderr) + raise SystemExit(1) + +validator = validator_class(schema, format_checker=validator_class.FORMAT_CHECKER) +errors = sorted(validator.iter_errors(instance), key=lambda error: list(error.absolute_path)) +if errors: + print("Error: mod.json is not valid", file=sys.stderr) + for error in errors: + location = "$" + for part in error.absolute_path: + location += f"[{part}]" if isinstance(part, int) else f".{part}" + print(f" {location}: {error.message}", file=sys.stderr) + raise SystemExit(1) +PY From 65b362429424193e5418e7ded43877f79c2c02a4 Mon Sep 17 00:00:00 2001 From: HardCPP Date: Mon, 10 Aug 2026 00:40:31 +0200 Subject: [PATCH 3/9] Update CI/CD --- .github/workflows/build-ndk.yml | 2 +- .github/workflows/publish.yml | 3 ++- .gitignore | 3 ++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build-ndk.yml b/.github/workflows/build-ndk.yml index 86e79a0..455616c 100644 --- a/.github/workflows/build-ndk.yml +++ b/.github/workflows/build-ndk.yml @@ -53,7 +53,7 @@ jobs: echo "VERSION=${GITHUB_REF#refs/tags/v}" >> ${GITHUB_OUTPUT} - name: Setup qpm - uses: Fernthedev/qpm-action@main + uses: Fernthedev/qpm-action@v1 with: workflow_token: ${{ secrets.GITHUB_TOKEN }} restore: true diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index ae90cb1..20b256a 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -43,7 +43,7 @@ jobs: echo VERSION="${GITHUB_REF#refs/tags/v}" >> $GITHUB_OUTPUT - name: Setup qpm - uses: Fernthedev/qpm-action@main + uses: Fernthedev/qpm-action@v1 with: workflow_token: ${{ secrets.GITHUB_TOKEN }} restore: true @@ -54,6 +54,7 @@ jobs: qpm_release_bin: true qpm_debug_bin: true qpm_qmod: ${{ env.qmodName }}.qmod + resolve_ndk: true - name: Build & Create Qmod run: | diff --git a/.gitignore b/.gitignore index 9d7352d..b266dea 100644 --- a/.gitignore +++ b/.gitignore @@ -66,4 +66,5 @@ cmake-build-*/ extern.cmake # QMOD Schema -mod.json.schema \ No newline at end of file +mod.json.schema +.env \ No newline at end of file From 049bdb97a3eb9ba494f3c1d8d2d3bd3cac515423 Mon Sep 17 00:00:00 2001 From: HardCPP Date: Mon, 10 Aug 2026 00:41:06 +0200 Subject: [PATCH 4/9] PBombNoteController: Remove useless caching, backport SetBombColorOverride --- shared/Patches/PBombNoteController.hpp | 10 +++ src/Patches/PBombNoteController.cpp | 120 ++++++++++++------------- 2 files changed, 65 insertions(+), 65 deletions(-) diff --git a/shared/Patches/PBombNoteController.hpp b/shared/Patches/PBombNoteController.hpp index fd84cdf..c11c624 100644 --- a/shared/Patches/PBombNoteController.hpp +++ b/shared/Patches/PBombNoteController.hpp @@ -3,9 +3,15 @@ #include #include +#include namespace QBeatSaberPlus_NoteTweaker::Patches { + namespace _v + { + using namespace UnityEngine; + } + /// @brief BombNoteController patch class PBombNoteController { @@ -19,6 +25,10 @@ namespace QBeatSaberPlus_NoteTweaker::Patches { /// @param p_Enabled Is it enabled /// @param p_Scale New scale static void SetTemp(bool p_Enabled, float p_Scale); + /// @brief Set bomb color override + /// @param p_Enabled Is override enabled? + /// @param p_NewColor New color + static void SetBombColorOverride(bool p_Enabled, _v::Color p_NewColor); private: /// @brief Is note scaling enabled diff --git a/src/Patches/PBombNoteController.cpp b/src/Patches/PBombNoteController.cpp index bf7b08b..4f9ac97 100644 --- a/src/Patches/PBombNoteController.cpp +++ b/src/Patches/PBombNoteController.cpp @@ -1,8 +1,5 @@ #include "Patches/PBombNoteController.hpp" #include "NTConfig.hpp" -#include "Logger.hpp" - -#include #include #include @@ -10,23 +7,26 @@ #include #include -#include #include #include #include -#include #include +#include #include #include #include #include #include +#include +#include +#include #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wreturn-type-c-linkage" using namespace GlobalNamespace; using namespace UnityEngine; +using namespace CP_SDK::Utils; namespace QBeatSaberPlus_NoteTweaker::Patches { @@ -38,28 +38,16 @@ namespace QBeatSaberPlus_NoteTweaker::Patches { //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// - struct PBombNoteControllerCache - { - BombNoteController* bombNoteController; - MaterialPropertyBlockController* materialPropertyBlockController; - SphereCollider* sphereCollider; - Transform* transform; - }; - - //////////////////////////////////////////////////////////////////////////// - //////////////////////////////////////////////////////////////////////////// - - static bool PBombNoteController_Enabled = false; - static bool PBombNoteController_TempEnabled = false; - static int32_t PBombNoteController_ColorID = 0; - static Color PBombNoteController_Color; - static Vector3 PBombNoteController_Scale = Vector3(1.0f, 1.0f, 1.0f); - static float PBombNoteController_InvScale = 1.0f; - static Vector3 PBombNoteController_TempScale = Vector3(1.0f, 1.0f, 1.0f); - static float PBombNoteController_TempInvScale = 1.0f; - - static bool PBombNoteController_WasInit = false; - static std::vector PBombNoteController_Cache; + static bool PBombNoteController_Enabled = false; + static bool PBombNoteController_ShouldRecolorize = false; + static bool PBombNoteController_TempEnabled = false; + static int32_t PBombNoteController_ColorID = 0; + static Color PBombNoteController_Color; + static MonoPtr PBombNoteController_SharedMaterial = nullptr; + static Vector3 PBombNoteController_Scale = Vector3(1.0f, 1.0f, 1.0f); + static float PBombNoteController_InvScale = 1.0f; + static Vector3 PBombNoteController_TempScale = Vector3(1.0f, 1.0f, 1.0f); + static float PBombNoteController_TempInvScale = 1.0f; //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// @@ -73,13 +61,22 @@ namespace QBeatSaberPlus_NoteTweaker::Patches { auto& l_Profile = NTConfig::Instance()->GetActiveProfile(); auto l_BombScale = FilterScale(NTConfig::Instance()->Enabled ? l_Profile->BombsScale : 1.0f); - PBombNoteController_Enabled = IsScaleAllowed() ? NTConfig::Instance()->Enabled : false; - PBombNoteController_Color = (PBombNoteController_Enabled && l_Profile->BombsOverrideColor) ? l_Profile->BombsColor : Color(0.251f, 0.251f, 0.251f, 1.000f); - PBombNoteController_Scale = l_BombScale * Vector3::get_one(); - PBombNoteController_InvScale = 1.0f / l_BombScale; + PBombNoteController_Enabled = IsScaleAllowed() ? NTConfig::Instance()->Enabled : false; + PBombNoteController_ShouldRecolorize = true; + PBombNoteController_Color = (PBombNoteController_Enabled && l_Profile->BombsOverrideColor) ? l_Profile->BombsColor : Color(0.251f, 0.251f, 0.251f, 1.000f); + PBombNoteController_Scale = l_BombScale * Vector3::get_one(); + PBombNoteController_InvScale = 1.0f / l_BombScale; if (p_OnSceneSwitch) PBombNoteController_Enabled = false; + + if (PBombNoteController_SharedMaterial) + { + if (CP_SDK_BS::Game::Logic::ActiveScene() == CP_SDK_BS::Game::Logic::ESceneType::Playing) + PBombNoteController_SharedMaterial->SetColor(PBombNoteController_ColorID, PBombNoteController_Color); + else + PBombNoteController_SharedMaterial->SetColor(PBombNoteController_ColorID, Color(0.251f, 0.251f, 0.251f, 1.000f)); + } } /// @brief Set temp config /// @param p_Enabled Is it enabled @@ -97,6 +94,21 @@ namespace QBeatSaberPlus_NoteTweaker::Patches { PBombNoteController_TempScale = p_Scale * Vector3::get_one(); PBombNoteController_TempInvScale = 1.0f / (p_Scale); } + /// @brief Set bomb color override + /// @param p_Enabled Is override enabled? + /// @param p_NewColor New color + void PBombNoteController::SetBombColorOverride(bool p_Enabled, Color p_NewColor) + { + PBombNoteController_ShouldRecolorize = true; + + if (p_Enabled) + PBombNoteController_Color = p_NewColor; + else + { + auto& l_Profile = NTConfig::Instance()->GetActiveProfile(); + PBombNoteController_Color = (PBombNoteController_Enabled && l_Profile->BombsOverrideColor) ? l_Profile->BombsColor : Color(0.251f, 0.251f, 0.251f, 1.000f); + } + } //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// @@ -107,10 +119,10 @@ namespace QBeatSaberPlus_NoteTweaker::Patches { auto& l_LevelData = CP_SDK_BS::Game::Logic::LevelData(); if (l_LevelData) { - auto l_GameplayModifiers = l_LevelData->Data ? l_LevelData->Data->___gameplayModifiers : nullptr; + auto l_GameplayModifiers = l_LevelData->Data ? l_LevelData->Data->gameplayModifiers : nullptr; if (l_GameplayModifiers) { - if (l_GameplayModifiers->____proMode || l_GameplayModifiers->____smallCubes || l_GameplayModifiers->____strictAngles) + if (l_GameplayModifiers->_proMode || l_GameplayModifiers->_smallCubes || l_GameplayModifiers->_strictAngles) return false; } } @@ -130,17 +142,8 @@ namespace QBeatSaberPlus_NoteTweaker::Patches { /// @brief Init specific data and register events void PBombNoteController::Init() { - if (PBombNoteController_Cache.capacity() < 100) - PBombNoteController_Cache.reserve(100); - if (PBombNoteController_ColorID == 0) PBombNoteController_ColorID = Shader::PropertyToID("_SimpleColor"); - - if (!PBombNoteController_WasInit) - { - CP_SDK::ChatPlexSDK::OnGenericSceneChange += [](CP_SDK::EGenericScene x) { if (x == CP_SDK::EGenericScene::Menu) PBombNoteController_Cache.clear(); }; - PBombNoteController_WasInit = true; - } } //////////////////////////////////////////////////////////////////////////// @@ -154,33 +157,20 @@ namespace QBeatSaberPlus_NoteTweaker::Patches { { BombNoteController_Init(__Instance, __a, __b); - auto l_Cache = (PBombNoteControllerCache*)nullptr; - auto l_CacheCount = PBombNoteController_Cache.size(); - for (auto l_I = 0; l_I < l_CacheCount; ++l_I) - { - l_Cache = &PBombNoteController_Cache[l_I]; - if (l_Cache->bombNoteController == __Instance) - break; - } + if (!PBombNoteController_SharedMaterial) + PBombNoteController_SharedMaterial = __Instance->GetComponentInChildren()->get_sharedMaterial(); - if (!l_Cache || l_Cache->bombNoteController != __Instance) + if (PBombNoteController_ShouldRecolorize && PBombNoteController_SharedMaterial) { - PBombNoteController_Cache.push_back({ - __Instance, - __Instance->GetComponentInChildren(), - __Instance->____cuttableBySaber->GetComponent(), - __Instance->get_transform() - }); - l_Cache = &PBombNoteController_Cache.back(); - - if (!l_Cache->materialPropertyBlockController->____materialPropertyBlock) - l_Cache->materialPropertyBlockController->____materialPropertyBlock = MaterialPropertyBlock::New_ctor(); + PBombNoteController_SharedMaterial->SetColor(PBombNoteController_ColorID, PBombNoteController_Color); + PBombNoteController_ShouldRecolorize = false; } - l_Cache->materialPropertyBlockController->____materialPropertyBlock->SetColor(PBombNoteController_ColorID, PBombNoteController_Color); - l_Cache->materialPropertyBlockController->ApplyChanges(); - l_Cache->sphereCollider->set_radius(0.18f * (PBombNoteController_TempEnabled ? PBombNoteController_TempInvScale : PBombNoteController_InvScale)); - l_Cache->transform->set_localScale(PBombNoteController_TempEnabled ? PBombNoteController_TempScale : PBombNoteController_Scale); + if (!PBombNoteController_Enabled && !PBombNoteController_TempEnabled) + return; + + __Instance->transform->set_localScale(PBombNoteController_TempEnabled ? PBombNoteController_TempScale : PBombNoteController_Scale); + __Instance->GetComponent()->set_radius(0.18f * (PBombNoteController_TempEnabled ? PBombNoteController_TempInvScale : PBombNoteController_InvScale)); } } ///< namespace QBeatSaberPlus_NoteTweaker::Patches From bb1cdd1c14528ee74980a89a8bcef8ee7597572f Mon Sep 17 00:00:00 2001 From: HardCPP Date: Mon, 10 Aug 2026 00:41:33 +0200 Subject: [PATCH 5/9] PBurstSliderGameNoteController: Use properties instead of fields, backport from PC --- .../PBurstSliderGameNoteController.cpp | 45 +++++++++++++------ 1 file changed, 32 insertions(+), 13 deletions(-) diff --git a/src/Patches/PBurstSliderGameNoteController.cpp b/src/Patches/PBurstSliderGameNoteController.cpp index 9041327..d5820b0 100644 --- a/src/Patches/PBurstSliderGameNoteController.cpp +++ b/src/Patches/PBurstSliderGameNoteController.cpp @@ -1,6 +1,5 @@ #include "Patches/PBurstSliderGameNoteController.hpp" #include "NTConfig.hpp" -#include "Logger.hpp" #include #include @@ -30,8 +29,9 @@ namespace QBeatSaberPlus_NoteTweaker::Patches { //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// - static bool PBurstSliderGameNoteController_Enabled = false; - static bool PBurstSliderGameNoteController_TempEnabled = false; + static bool PBurstSliderGameNoteController_Enabled = false; + static bool PBurstSliderGameNoteController_TempEnabled = false; + static bool PBurstSliderGameNoteController_WasTempEnabled = false; static Vector3 PBurstSliderGameNoteController_NoteScale; static Vector3 PBurstSliderGameNoteController_NoteInvScale; static Vector3 PBurstSliderGameNoteController_TempNoteScale; @@ -52,7 +52,10 @@ namespace QBeatSaberPlus_NoteTweaker::Patches { PBurstSliderGameNoteController_NoteInvScale = (1.0f / l_NoteScale) * Vector3::get_one(); if (p_OnSceneSwitch) - PBurstSliderGameNoteController_TempEnabled = false; + { + PBurstSliderGameNoteController_TempEnabled = false; + PBurstSliderGameNoteController_WasTempEnabled = false; + } } /// @brief Set temp config /// @param p_Enabled Is it enabled @@ -67,6 +70,9 @@ namespace QBeatSaberPlus_NoteTweaker::Patches { PBurstSliderGameNoteController_TempEnabled = p_Enabled; PBurstSliderGameNoteController_TempNoteScale = ( p_Scale) * Vector3::get_one(); PBurstSliderGameNoteController_TempNoteInvScale = (1.0f / p_Scale) * Vector3::get_one(); + + if (p_Enabled) + PBurstSliderGameNoteController_WasTempEnabled = true; } //////////////////////////////////////////////////////////////////////////// @@ -78,10 +84,10 @@ namespace QBeatSaberPlus_NoteTweaker::Patches { auto& l_LevelData = CP_SDK_BS::Game::Logic::LevelData(); if (l_LevelData) { - auto l_GameplayModifiers = l_LevelData->Data ? l_LevelData->Data->___gameplayModifiers : nullptr; + auto l_GameplayModifiers = l_LevelData->Data ? l_LevelData->Data->gameplayModifiers : nullptr; if (l_GameplayModifiers) { - if (l_GameplayModifiers->____proMode || l_GameplayModifiers->____smallCubes || l_GameplayModifiers->____strictAngles) + if (l_GameplayModifiers->_proMode || l_GameplayModifiers->_smallCubes || l_GameplayModifiers->_strictAngles) return false; } } @@ -106,18 +112,31 @@ namespace QBeatSaberPlus_NoteTweaker::Patches { { BurstSliderGameNoteController_Init(__Instance, __a, __b, __c, __d); - if (!PBurstSliderGameNoteController_Enabled && !PBurstSliderGameNoteController_TempEnabled) + if (!PBurstSliderGameNoteController_Enabled && !PBurstSliderGameNoteController_TempEnabled && !PBurstSliderGameNoteController_WasTempEnabled) return; - __Instance->get_transform()->set_localScale(PBurstSliderGameNoteController_TempEnabled ? PBurstSliderGameNoteController_TempNoteScale : PBurstSliderGameNoteController_NoteScale); - auto l_BoxScale = PBurstSliderGameNoteController_TempEnabled ? PBurstSliderGameNoteController_TempNoteInvScale : PBurstSliderGameNoteController_NoteInvScale; + auto l_NoteScale = PBurstSliderGameNoteController_NoteScale; + auto l_NoteInvScale = PBurstSliderGameNoteController_NoteInvScale; + + if (PBurstSliderGameNoteController_TempEnabled) + { + l_NoteScale = PBurstSliderGameNoteController_TempNoteScale; + l_NoteInvScale = PBurstSliderGameNoteController_TempNoteInvScale; + } + else if (PBurstSliderGameNoteController_WasTempEnabled) + { + l_NoteScale = PBurstSliderGameNoteController_TempNoteScale; + l_NoteInvScale = PBurstSliderGameNoteController_TempNoteInvScale; + } + + __Instance->get_transform()->set_localScale(l_NoteScale); - for (auto l_Current : __Instance->____bigCuttableBySaberList) - l_Current->get_transform()->set_localScale(l_BoxScale); + for (auto l_Current : __Instance->_bigCuttableBySaberList) + l_Current->get_transform()->set_localScale(l_NoteInvScale); - for (auto l_Current : __Instance->____smallCuttableBySaberList) - l_Current->get_transform()->set_localScale(l_BoxScale); + for (auto l_Current : __Instance->_smallCuttableBySaberList) + l_Current->get_transform()->set_localScale(l_NoteInvScale); } } ///< namespace QBeatSaberPlus_NoteTweaker::Patches \ No newline at end of file From 5b55b7b642a29c879fc503ce846b3196566cf9fe Mon Sep 17 00:00:00 2001 From: HardCPP Date: Mon, 10 Aug 2026 00:42:02 +0200 Subject: [PATCH 6/9] PColorNoteVisuals: Redo the whole cache system il2cpp friendly, backport changes from PC --- src/Patches/PColorNoteVisuals.cpp | 287 ++++++++++++++++-------------- 1 file changed, 154 insertions(+), 133 deletions(-) diff --git a/src/Patches/PColorNoteVisuals.cpp b/src/Patches/PColorNoteVisuals.cpp index a2c75d9..22df5fa 100644 --- a/src/Patches/PColorNoteVisuals.cpp +++ b/src/Patches/PColorNoteVisuals.cpp @@ -1,7 +1,6 @@ #include "Patches/PColorNoteVisuals.hpp" #include "CP_SDK/Utils/Il2cpp.hpp" #include "NTConfig.hpp" -#include "Logger.hpp" #include #include @@ -24,12 +23,13 @@ #include #include #include -#include +#include #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wreturn-type-c-linkage" using namespace CP_SDK::Unity::Extensions; +using namespace CP_SDK::Utils; using namespace GlobalNamespace; using namespace System::Collections::Generic; using namespace UnityEngine; @@ -47,13 +47,16 @@ namespace QBeatSaberPlus_NoteTweaker::Patches { constexpr int PColorNoteVisualsCache_MaxSubArray = 10; struct PColorNoteVisualsCache { - ColorNoteVisuals* colorNoteVisuals; - BurstSliderGameNoteController* burstSliderGameNoteController; - MaterialPropertyBlockController* materialPropertyBlockControllers[PColorNoteVisualsCache_MaxSubArray]; - Transform* noteArrows[PColorNoteVisualsCache_MaxSubArray]; - Transform* noteArrowGlows[PColorNoteVisualsCache_MaxSubArray]; - MaterialPropertyBlockController* noteArrowGlowsMaterialPropertyBlockControllers[PColorNoteVisualsCache_MaxSubArray]; - MaterialPropertyBlockController* noteCircleMeshRenderersMaterialPropertyBlockControllers[PColorNoteVisualsCache_MaxSubArray]; + using Ptr = std::shared_ptr; + + bool isBurstNote = false; + + MonoPtr> arrowMeshRenderersTransforms; + MonoPtr> arrowGlowTransforms; + MonoPtr> arrowGlowMaterialPropertyBlockControllers; + + MonoPtr> circleMeshRenderersTransforms; + MonoPtr> circleMaterialPropertyBlockControllers; }; //////////////////////////////////////////////////////////////////////////// @@ -81,8 +84,14 @@ namespace QBeatSaberPlus_NoteTweaker::Patches { static Color PColorNoteVisuals_RightBlockColor; static bool PColorNoteVisuals_WasInit = false; - static std::vector PColorNoteVisuals_Cache; - static CP_SDK::Utils::MonoPtr> PColorNoteVisuals_ComponentsCache; + + static std::map PColorNoteVisuals_Cache; + + static MonoPtr> PColorNoteVisuals_ComponentsCache; + static MonoPtr> PColorNoteVisuals_TransformCacheA; + static MonoPtr> PColorNoteVisuals_TransformCacheB; + static MonoPtr> PColorNoteVisuals_ArrowGlowMaterialPropertyBlockControllers; + static MonoPtr> PColorNoteVisuals_CircleMaterialPropertyBlockControllers; //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// @@ -147,12 +156,21 @@ namespace QBeatSaberPlus_NoteTweaker::Patches { /// @brief Init specific data and register events void PColorNoteVisuals::Init() { - if (PColorNoteVisuals_Cache.capacity() < 100) - PColorNoteVisuals_Cache.reserve(100); - if (!PColorNoteVisuals_ComponentsCache) PColorNoteVisuals_ComponentsCache = List_1::New_ctor(10); + if (!PColorNoteVisuals_TransformCacheA) + PColorNoteVisuals_TransformCacheA = List_1::New_ctor(10); + + if (!PColorNoteVisuals_TransformCacheB) + PColorNoteVisuals_TransformCacheB = List_1::New_ctor(10); + + if (!PColorNoteVisuals_ArrowGlowMaterialPropertyBlockControllers) + PColorNoteVisuals_ArrowGlowMaterialPropertyBlockControllers = List_1::New_ctor(10); + + if (!PColorNoteVisuals_CircleMaterialPropertyBlockControllers) + PColorNoteVisuals_CircleMaterialPropertyBlockControllers = List_1::New_ctor(10); + if (PColorNoteVisuals_ColorID == 0) PColorNoteVisuals_ColorID = Shader::PropertyToID("_Color"); @@ -165,6 +183,12 @@ namespace QBeatSaberPlus_NoteTweaker::Patches { if (!PColorNoteVisuals_Cache.empty()) PColorNoteVisuals_Cache.clear(); + + PColorNoteVisuals_ComponentsCache->Clear(); + PColorNoteVisuals_TransformCacheA->Clear(); + PColorNoteVisuals_TransformCacheB->Clear(); + PColorNoteVisuals_ArrowGlowMaterialPropertyBlockControllers->Clear(); + PColorNoteVisuals_CircleMaterialPropertyBlockControllers->Clear(); }; PColorNoteVisuals_WasInit = true; @@ -182,180 +206,177 @@ namespace QBeatSaberPlus_NoteTweaker::Patches { { ColorNoteVisuals_HandleNoteControllerDidInit(__Instance, __a); - auto l_Cache = (PColorNoteVisualsCache*)nullptr; - auto l_CacheCount = PColorNoteVisuals_Cache.size(); - for (auto l_I = 0; l_I < l_CacheCount; ++l_I) - { - l_Cache = &PColorNoteVisuals_Cache[l_I]; - if (l_Cache->colorNoteVisuals == __Instance) - break; - } - if (!PColorNoteVisuals_WasInit) PColorNoteVisuals::Init(); - if (!l_Cache || l_Cache->colorNoteVisuals != __Instance) - { - PColorNoteVisuals_Cache.push_back({ - __Instance, - __Instance->GetComponent(), - {}, - {}, - {} - }); - l_Cache = &PColorNoteVisuals_Cache.back(); - - auto l_MaterialPropertyBlockControllersIt = 0; - auto l_NoteArrowsIt = 0; - auto l_NoteArrowGlowsIt = 0; - auto l_NoteArrowGlowsMaterialPropertyBlockControllersIt = 0; - auto l_NoteCircleMeshRenderersMaterialPropertyBlockControllersIt= 0; - - for (auto l_CurrentBlock : __Instance->____materialPropertyBlockControllers) - { - if (!l_CurrentBlock->____materialPropertyBlock) - l_CurrentBlock->____materialPropertyBlock = MaterialPropertyBlock::New_ctor(); + auto instanceID = __Instance->GetInstanceID(); + auto cached = std::shared_ptr(); - l_Cache->materialPropertyBlockControllers[l_MaterialPropertyBlockControllersIt++] = l_CurrentBlock; + if (PColorNoteVisuals_Cache.contains(instanceID)) + cached = PColorNoteVisuals_Cache[instanceID]; - if (l_MaterialPropertyBlockControllersIt >= PColorNoteVisualsCache_MaxSubArray) - Logger::Instance->Error(u"[Patches][ColorNoteVisuals_HandleNoteControllerDidInit] Limit reached for l_MaterialPropertyBlockControllersIt"); - } + if (!cached) + { + cached = std::make_shared(); + cached->isBurstNote = __Instance->get_gameObject()->GetComponent() != nullptr; + + auto arrowMeshRenderers = __Instance->_arrowMeshRenderers; + PColorNoteVisuals_TransformCacheA->Clear(); + PColorNoteVisuals_TransformCacheB->Clear(); + PColorNoteVisuals_ArrowGlowMaterialPropertyBlockControllers->Clear(); - for (auto l_CurrentArrow : __Instance->____arrowMeshRenderers) + for (int i = 0; i < arrowMeshRenderers.size(); ++i) { - l_Cache->noteArrows[l_NoteArrowsIt++] = l_CurrentArrow->get_transform(); - if (l_NoteArrowsIt >= PColorNoteVisualsCache_MaxSubArray) - Logger::Instance->Error(u"[Patches][ColorNoteVisuals_HandleNoteControllerDidInit] Limit reached for l_NoteArrowsIt"); + PColorNoteVisuals_TransformCacheA->Add(arrowMeshRenderers[i]->transform); - auto l_Glow = l_CurrentArrow->get_transform()->get_parent()->Find("NoteArrowGlow"); - if (l_Glow) + auto glowTransform = arrowMeshRenderers[i]->transform->get_parent()->Find("NoteArrowGlow"); + if (glowTransform) { - PColorNoteVisuals_ComponentsCache->Clear(); + PColorNoteVisuals_TransformCacheB->Add(glowTransform); - l_Cache->noteArrowGlows[l_NoteArrowGlowsIt++] = l_Glow; - l_Glow->GetComponentsForListInternal(reinterpret_cast(csTypeOf(MaterialPropertyBlockController*).convert()), PColorNoteVisuals_ComponentsCache.Ptr()); - - if (l_NoteArrowGlowsIt >= PColorNoteVisualsCache_MaxSubArray) - Logger::Instance->Error(u"[Patches][ColorNoteVisuals_HandleNoteControllerDidInit] Limit reached for l_NoteArrowGlowsIt"); + PColorNoteVisuals_ComponentsCache->Clear(); + glowTransform->GetComponentsForListInternal(reinterpret_cast(csTypeOf(MaterialPropertyBlockController*).convert()), PColorNoteVisuals_ComponentsCache.Ptr()); - auto l_Count = PColorNoteVisuals_ComponentsCache->get_Count(); - auto l_Items = PColorNoteVisuals_ComponentsCache->____items->_values; - for (auto l_I = 0; l_I < l_Count; ++l_I) + if (PColorNoteVisuals_ComponentsCache->Count > 0) { - auto l_CurrentBlock = reinterpret_cast(l_Items[l_I]); - if (!l_CurrentBlock->____materialPropertyBlock) - l_CurrentBlock->____materialPropertyBlock = MaterialPropertyBlock::New_ctor(); - - l_Cache->noteArrowGlowsMaterialPropertyBlockControllers[l_NoteArrowGlowsMaterialPropertyBlockControllersIt++] = l_CurrentBlock; - - if (l_NoteArrowGlowsMaterialPropertyBlockControllersIt >= PColorNoteVisualsCache_MaxSubArray) - Logger::Instance->Error(u"[Patches][ColorNoteVisuals_HandleNoteControllerDidInit] Limit reached for l_NoteArrowGlowsMaterialPropertyBlockControllersIt"); + auto l_Count = PColorNoteVisuals_ComponentsCache->get_Count(); + auto l_Items = PColorNoteVisuals_ComponentsCache->____items->_values; + for (auto l_I = 0; l_I < l_Count; ++l_I) + { + auto l_CurrentBlock = reinterpret_cast(l_Items[l_I]); + if (!l_CurrentBlock->_materialPropertyBlock) + l_CurrentBlock->_materialPropertyBlock = MaterialPropertyBlock::New_ctor(); + + PColorNoteVisuals_ArrowGlowMaterialPropertyBlockControllers->Add(l_CurrentBlock); + } } } } - for (auto l_CurrentCircle : __Instance->____circleMeshRenderers) + if (PColorNoteVisuals_TransformCacheA->Count > 0) + cached->arrowMeshRenderersTransforms = static_cast*>(PColorNoteVisuals_TransformCacheA->ToArray()); + if (PColorNoteVisuals_TransformCacheB->Count > 0) + cached->arrowGlowTransforms = static_cast*>(PColorNoteVisuals_TransformCacheB->ToArray()); + if (PColorNoteVisuals_ArrowGlowMaterialPropertyBlockControllers->Count > 0) + cached->arrowGlowMaterialPropertyBlockControllers =static_cast*>(PColorNoteVisuals_ArrowGlowMaterialPropertyBlockControllers->ToArray()); + + // ===== + + auto circleMeshRenderers = __Instance->_circleMeshRenderers; + PColorNoteVisuals_TransformCacheA->Clear(); + PColorNoteVisuals_CircleMaterialPropertyBlockControllers->Clear(); + + for (int i = 0; i < circleMeshRenderers.size(); ++i) { + PColorNoteVisuals_TransformCacheA->Add(circleMeshRenderers[i]->transform); + PColorNoteVisuals_ComponentsCache->Clear(); - l_CurrentCircle->GetComponentsForListInternal(reinterpret_cast(csTypeOf(MaterialPropertyBlockController*).convert()), PColorNoteVisuals_ComponentsCache.Ptr()); + circleMeshRenderers[i]->GetComponentsForListInternal(reinterpret_cast(csTypeOf(MaterialPropertyBlockController*).convert()), PColorNoteVisuals_ComponentsCache.Ptr()); - auto l_Count = PColorNoteVisuals_ComponentsCache->get_Count(); - auto l_Items = PColorNoteVisuals_ComponentsCache->____items->_values; - for (auto l_I = 0; l_I < l_Count; ++l_I) + if (PColorNoteVisuals_ComponentsCache->Count > 0) { - auto l_CurrentBlock = reinterpret_cast(l_Items[l_I]); - if (!l_CurrentBlock->____materialPropertyBlock) - l_CurrentBlock->____materialPropertyBlock = MaterialPropertyBlock::New_ctor(); - - l_Cache->noteCircleMeshRenderersMaterialPropertyBlockControllers[l_NoteCircleMeshRenderersMaterialPropertyBlockControllersIt++] = l_CurrentBlock; + auto l_Count = PColorNoteVisuals_ComponentsCache->get_Count(); + auto l_Items = PColorNoteVisuals_ComponentsCache->____items->_values; + for (auto l_I = 0; l_I < l_Count; ++l_I) + { + auto l_CurrentBlock = reinterpret_cast(l_Items[l_I]); + if (!l_CurrentBlock->_materialPropertyBlock) + l_CurrentBlock->_materialPropertyBlock = MaterialPropertyBlock::New_ctor(); - if (l_NoteCircleMeshRenderersMaterialPropertyBlockControllersIt >= PColorNoteVisualsCache_MaxSubArray) - Logger::Instance->Error(u"[Patches][ColorNoteVisuals_HandleNoteControllerDidInit] Limit reached for l_NoteCircleMeshRenderersMaterialPropertyBlockControllersIt"); + PColorNoteVisuals_CircleMaterialPropertyBlockControllers->Add(l_CurrentBlock); + } } } - l_Cache->materialPropertyBlockControllers [l_MaterialPropertyBlockControllersIt++ ] = nullptr; - l_Cache->noteArrows [l_NoteArrowsIt++ ] = nullptr; - l_Cache->noteArrowGlows [l_NoteArrowGlowsIt++ ] = nullptr; - l_Cache->noteArrowGlowsMaterialPropertyBlockControllers [l_NoteArrowGlowsMaterialPropertyBlockControllersIt++ ] = nullptr; - l_Cache->noteCircleMeshRenderersMaterialPropertyBlockControllers[l_NoteCircleMeshRenderersMaterialPropertyBlockControllersIt++] = nullptr; - } + if (PColorNoteVisuals_TransformCacheA->Count > 0) + cached->circleMeshRenderersTransforms = static_cast*>(PColorNoteVisuals_TransformCacheA->ToArray()); + if (PColorNoteVisuals_CircleMaterialPropertyBlockControllers->Count > 0) + cached->circleMaterialPropertyBlockControllers = static_cast*>(PColorNoteVisuals_CircleMaterialPropertyBlockControllers->ToArray()); - //////////////////////////////////////////////////////////////////////////// - //////////////////////////////////////////////////////////////////////////// + // ===== - auto l_NoteData = __Instance->____noteController->get_noteData(); - auto l_ColorType = l_NoteData->get_colorType(); - auto l_CutDirection = l_NoteData->get_cutDirection(); - auto l_OverrideColor = l_ColorType == ColorType::ColorA ? PColorNoteVisuals_LeftBlockColor : PColorNoteVisuals_RightBlockColor; + PColorNoteVisuals_Cache[instanceID] = cached; + } + auto colorType = __Instance->_noteController->get_noteData()->get_colorType(); if (PColorNoteVisuals_BlockColorsEnabled) { - for (auto l_Current : l_Cache->materialPropertyBlockControllers) + auto blockColor = colorType == ColorType::ColorA ? PColorNoteVisuals_LeftBlockColor : PColorNoteVisuals_RightBlockColor; + + for (auto &block : __Instance->_materialPropertyBlockControllers) { - if (!l_Current) break; - l_Current->____materialPropertyBlock->SetColor(PColorNoteVisuals_ColorID, l_OverrideColor); - l_Current->ApplyChanges(); + block->_materialPropertyBlock->SetColor(PColorNoteVisuals_ColorID, blockColor); + block->ApplyChanges(); } - if (!PColorNoteVisuals_Enabled) + + if (!PColorNoteVisuals_Enabled && cached->arrowGlowMaterialPropertyBlockControllers) { - auto l_NoteArrowGlowColor = ColorU::WithAlpha(l_OverrideColor, 0.6f); - for (auto l_Current : l_Cache->noteArrowGlowsMaterialPropertyBlockControllers) + auto newArrowGlowColor = ColorU::WithAlpha(blockColor, 0.6f); + for (auto ¤tBlock : *cached->arrowGlowMaterialPropertyBlockControllers.Ptr()) { - if (!l_Current) break; - l_Current->____materialPropertyBlock->SetColor(PColorNoteVisuals_ColorID, l_NoteArrowGlowColor); - l_Current->ApplyChanges(); + currentBlock->materialPropertyBlock->SetColor(PColorNoteVisuals_ColorID, newArrowGlowColor); + currentBlock->ApplyChanges(); } } } - //////////////////////////////////////////////////////////////////////////// - //////////////////////////////////////////////////////////////////////////// - if (!PColorNoteVisuals_Enabled) return; - auto l_BaseColor = __Instance->____colorManager->ColorForType(l_ColorType); - auto l_ArrowColor = ColorU::WithAlpha(PColorNoteVisuals_OverrideArrowColors ? (l_ColorType == ColorType::ColorB ? PColorNoteVisuals_RightArrowColor : PColorNoteVisuals_LeftArrowColor) : l_BaseColor, PColorNoteVisuals_ArrowAlpha); + auto cutDirection = __Instance->_noteController->get_noteData()->get_cutDirection(); + auto dotEnabled = cutDirection == NoteCutDirection::Any ? PColorNoteVisuals_CircleEnabled : (PColorNoteVisuals_CircleEnabled && PColorNoteVisuals_CircleForceEnabled); + auto baseColor = __Instance->_colorManager->ColorForType(colorType); + auto isRight = colorType == ColorType::ColorB; + + // ===== + + auto arrowColor = ColorU::WithAlpha(PColorNoteVisuals_OverrideArrowColors ? (isRight ? PColorNoteVisuals_RightArrowColor : PColorNoteVisuals_LeftArrowColor) : baseColor, PColorNoteVisuals_ArrowAlpha); if (PColorNoteVisuals_BlockColorsEnabled) - l_ArrowColor = ColorU::WithAlpha(l_OverrideColor, 0.6f); + arrowColor = ColorU::WithAlpha(isRight ? PColorNoteVisuals_RightBlockColor : PColorNoteVisuals_LeftBlockColor, 0.6f); - for (auto l_Current : l_Cache->noteArrows) + if (cached->arrowMeshRenderersTransforms) { - if (!l_Current) break; - l_Current->set_localScale(PColorNoteVisuals_ArrowScale); + for (auto currentMesh: *cached->arrowMeshRenderersTransforms.Ptr()) + currentMesh->localScale = PColorNoteVisuals_ArrowScale; } - for (auto l_Current : l_Cache->noteArrowGlows) + + if (cached->arrowGlowTransforms) { - if (!l_Current) break; - l_Current->set_localScale(PColorNoteVisuals_ArrowGlowScale); + for (auto currentTransform: *cached->arrowGlowTransforms.Ptr()) + currentTransform->localScale = PColorNoteVisuals_ArrowGlowScale; } - for (auto l_Current : l_Cache->noteArrowGlowsMaterialPropertyBlockControllers) + + if (cached->arrowGlowMaterialPropertyBlockControllers) { - if (!l_Current) break; - l_Current->____materialPropertyBlock->SetColor(PColorNoteVisuals_ColorID, l_ArrowColor); - l_Current->ApplyChanges(); + for (auto currentBlock : *cached->arrowGlowMaterialPropertyBlockControllers.Ptr()) + { + currentBlock->materialPropertyBlock->SetColor(PColorNoteVisuals_ColorID, arrowColor); + currentBlock->ApplyChanges(); + } } - auto l_IsBurstNote = l_Cache->burstSliderGameNoteController != nullptr; - auto l_CircleScale = l_IsBurstNote ? PColorNoteVisuals_BurstCircleScale : (l_CutDirection == NoteCutDirection::Any ? PColorNoteVisuals_CircleScale : PColorNoteVisuals_PrecisionCircleScale); - auto l_DotEnabled = l_CutDirection == NoteCutDirection::Any ? PColorNoteVisuals_CircleEnabled : (PColorNoteVisuals_CircleEnabled && PColorNoteVisuals_CircleForceEnabled); - auto l_DotColor = ColorU::WithAlpha(PColorNoteVisuals_OverrideDotColors ? (l_ColorType == ColorType::ColorB ? PColorNoteVisuals_RightCircleColor : PColorNoteVisuals_LeftCircleColor) : l_BaseColor, PColorNoteVisuals_DotAlpha); + // ===== - for (auto l_CurrentRenderer : __Instance->____circleMeshRenderers) - { - l_CurrentRenderer->set_enabled (l_DotEnabled); - l_CurrentRenderer->get_transform()->set_localScale(l_CircleScale); + auto dotColor = ColorU::WithAlpha(PColorNoteVisuals_OverrideDotColors ? (isRight ? PColorNoteVisuals_RightCircleColor : PColorNoteVisuals_LeftCircleColor) : baseColor, PColorNoteVisuals_DotAlpha); + auto circleScale = cached->isBurstNote ? PColorNoteVisuals_BurstCircleScale : (cutDirection == NoteCutDirection::Any ? PColorNoteVisuals_CircleScale : PColorNoteVisuals_PrecisionCircleScale); + + if (cached->circleMeshRenderersTransforms) { + for (auto currentMesh : *cached->circleMeshRenderersTransforms.Ptr()) + currentMesh->localScale = circleScale; } - for (auto l_Current : l_Cache->noteCircleMeshRenderersMaterialPropertyBlockControllers) + for (int i = 0; i < __Instance->_circleMeshRenderers.size(); ++i) + __Instance->_circleMeshRenderers[i]->enabled = dotEnabled; + + if (cached->circleMaterialPropertyBlockControllers) { - if (!l_Current) break; - l_Current->____materialPropertyBlock->SetColor(PColorNoteVisuals_ColorID, l_DotColor); - l_Current->ApplyChanges(); + for (auto currentBlock : *cached->circleMaterialPropertyBlockControllers.Ptr()) + { + currentBlock->materialPropertyBlock->SetColor(PColorNoteVisuals_ColorID, dotColor); + currentBlock->ApplyChanges(); + } } } From b924c8f179ce75cf6ad21d7297c69a877e3b9927 Mon Sep 17 00:00:00 2001 From: HardCPP Date: Mon, 10 Aug 2026 00:42:16 +0200 Subject: [PATCH 7/9] Use properties instead of fields --- src/Patches/PGameNoteController.cpp | 43 ++++++++++++++++------- src/Patches/PSliderController.cpp | 2 +- src/UI/SettingsMainView.cpp | 2 +- src/UI/SettingsRightView.cpp | 54 ++++++++++++++--------------- 4 files changed, 60 insertions(+), 41 deletions(-) diff --git a/src/Patches/PGameNoteController.cpp b/src/Patches/PGameNoteController.cpp index 0f8643d..062c895 100644 --- a/src/Patches/PGameNoteController.cpp +++ b/src/Patches/PGameNoteController.cpp @@ -30,8 +30,9 @@ namespace QBeatSaberPlus_NoteTweaker::Patches { //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// - static bool PGameNoteController_Enabled = false; - static bool PGameNoteController_TempEnabled = false; + static bool PGameNoteController_Enabled = false; + static bool PGameNoteController_TempEnabled = false; + static bool PGameNoteController_WasTempEnabled = false; static Vector3 PGameNoteController_NoteScale; static Vector3 PGameNoteController_NoteInvScale; static Vector3 PGameNoteController_TempNoteScale; @@ -52,7 +53,10 @@ namespace QBeatSaberPlus_NoteTweaker::Patches { PGameNoteController_NoteInvScale = (1.0f / l_NoteScale) * Vector3::get_one(); if (p_OnSceneSwitch) - PGameNoteController_TempEnabled = false; + { + PGameNoteController_TempEnabled = false; + PGameNoteController_WasTempEnabled = false; + } } /// @brief Set temp config /// @param p_Enabled Is it enabled @@ -67,6 +71,9 @@ namespace QBeatSaberPlus_NoteTweaker::Patches { PGameNoteController_TempEnabled = p_Enabled; PGameNoteController_TempNoteScale = ( p_Scale) * Vector3::get_one(); PGameNoteController_TempNoteInvScale = (1.0f / p_Scale) * Vector3::get_one(); + + if (p_Enabled) + PGameNoteController_WasTempEnabled = true; } //////////////////////////////////////////////////////////////////////////// @@ -78,10 +85,10 @@ namespace QBeatSaberPlus_NoteTweaker::Patches { auto& l_LevelData = CP_SDK_BS::Game::Logic::LevelData(); if (l_LevelData) { - auto l_GameplayModifiers = l_LevelData->Data ? l_LevelData->Data->___gameplayModifiers : nullptr; + auto l_GameplayModifiers = l_LevelData->Data ? l_LevelData->Data->gameplayModifiers : nullptr; if (l_GameplayModifiers) { - if (l_GameplayModifiers->____proMode || l_GameplayModifiers->____smallCubes || l_GameplayModifiers->____strictAngles) + if (l_GameplayModifiers->_proMode || l_GameplayModifiers->_smallCubes || l_GameplayModifiers->_strictAngles) return false; } } @@ -106,18 +113,30 @@ namespace QBeatSaberPlus_NoteTweaker::Patches { { GameNoteController_Init(__Instance, __a, __b, __c, __d, __e); - if (!PGameNoteController_Enabled && !PGameNoteController_TempEnabled) + if (!PGameNoteController_Enabled && !PGameNoteController_TempEnabled && !PGameNoteController_WasTempEnabled) return; - __Instance->get_transform()->set_localScale(PGameNoteController_TempEnabled ? PGameNoteController_TempNoteScale : PGameNoteController_NoteScale); + auto l_NoteScale = PGameNoteController_NoteScale; + auto l_NoteInvScale = PGameNoteController_NoteInvScale; + + if (PGameNoteController_TempEnabled) + { + l_NoteScale = PGameNoteController_TempNoteScale; + l_NoteInvScale = PGameNoteController_TempNoteInvScale; + } + else if (PGameNoteController_WasTempEnabled) + { + l_NoteScale = Vector3::get_one(); + l_NoteInvScale = Vector3::get_one(); + } - auto l_BoxScale = PGameNoteController_TempEnabled ? PGameNoteController_TempNoteInvScale : PGameNoteController_NoteInvScale; + __Instance->get_transform()->set_localScale(l_NoteScale); - for (auto l_Current : __Instance->____bigCuttableBySaberList) - l_Current->get_transform()->set_localScale(l_BoxScale); + for (auto l_Current : __Instance->_bigCuttableBySaberList) + l_Current->get_transform()->set_localScale(l_NoteInvScale); - for (auto l_Current : __Instance->____smallCuttableBySaberList) - l_Current->get_transform()->set_localScale(l_BoxScale); + for (auto l_Current : __Instance->_smallCuttableBySaberList) + l_Current->get_transform()->set_localScale(l_NoteInvScale); } } ///< namespace QBeatSaberPlus_NoteTweaker::Patches \ No newline at end of file diff --git a/src/Patches/PSliderController.cpp b/src/Patches/PSliderController.cpp index d0ed32a..74ce2d9 100644 --- a/src/Patches/PSliderController.cpp +++ b/src/Patches/PSliderController.cpp @@ -41,7 +41,7 @@ namespace QBeatSaberPlus_NoteTweaker::Patches { SliderController_Init(__Instance, __a, __b, __c, __d, __e); if (PSliderController_Enabled) - __Instance->____initColor = ColorU::WithAlpha(__Instance->____initColor, PSliderController_Opacity); + __Instance->_initColor = ColorU::WithAlpha(__Instance->_initColor, PSliderController_Opacity); } } ///< namespace QBeatSaberPlus_NoteTweaker::Patches \ No newline at end of file diff --git a/src/UI/SettingsMainView.cpp b/src/UI/SettingsMainView.cpp index 1c0a464..696d861 100644 --- a/src/UI/SettingsMainView.cpp +++ b/src/UI/SettingsMainView.cpp @@ -445,7 +445,7 @@ namespace QBeatSaberPlus_NoteTweaker::UI { /// @param p_ListItem Selected item void SettingsMainView::ProfilesTab_OnListItemSelect(const CP_SDK::UI::Data::IListItem::Ptr& p_ListItem) { - m_SelectedItem = *reinterpret_cast*>(&p_ListItem); + m_SelectedItem = std::static_pointer_cast(p_ListItem); if (m_SelectedItem) { diff --git a/src/UI/SettingsRightView.cpp b/src/UI/SettingsRightView.cpp index c0ff2c2..f26a92f 100644 --- a/src/UI/SettingsRightView.cpp +++ b/src/UI/SettingsRightView.cpp @@ -89,30 +89,30 @@ namespace QBeatSaberPlus_NoteTweaker::UI { GameObject::DontDestroyOnLoad(m_Parent.Ptr()); auto l_MenuTransitionsHelper = Resources::FindObjectsOfTypeAll()->FirstOrDefault(); - auto l_StandardLevelScenesTransitionSetupData = l_MenuTransitionsHelper->____standardLevelScenesTransitionSetupData; - auto l_StandardGameplaySceneInfo = l_StandardLevelScenesTransitionSetupData->____standardGameplaySceneInfo; - auto l_GameCoreSceneInfo = l_StandardLevelScenesTransitionSetupData->____gameCoreSceneInfo; + auto l_StandardLevelScenesTransitionSetupData = l_MenuTransitionsHelper->_standardLevelScenesTransitionSetupData; + auto l_StandardGameplaySceneInfo = l_StandardLevelScenesTransitionSetupData->_standardGameplaySceneInfo; + auto l_GameCoreSceneInfo = l_StandardLevelScenesTransitionSetupData->_gameCoreSceneInfo; using t_Delegate1 = System::Action_1*; - SceneManagement::SceneManager::LoadSceneAsync(l_GameCoreSceneInfo->____sceneName, SceneManagement::LoadSceneMode::Additive)->add_completed(custom_types::MakeDelegate(std::function([=, this](AsyncOperation*) + SceneManagement::SceneManager::LoadSceneAsync(l_GameCoreSceneInfo->_sceneName, SceneManagement::LoadSceneMode::Additive)->add_completed(custom_types::MakeDelegate(std::function([=, this](AsyncOperation*) { - SceneManagement::SceneManager::LoadSceneAsync(l_StandardGameplaySceneInfo->____sceneName, SceneManagement::LoadSceneMode::Additive)->add_completed(custom_types::MakeDelegate(std::function([=, this](AsyncOperation*) + SceneManagement::SceneManager::LoadSceneAsync(l_StandardGameplaySceneInfo->_sceneName, SceneManagement::LoadSceneMode::Additive)->add_completed(custom_types::MakeDelegate(std::function([=, this](AsyncOperation*) { auto l_BeatmapObjectsInstaller = Resources::FindObjectsOfTypeAll()->FirstOrDefault(); - auto l_OriginalNotePrefab = l_BeatmapObjectsInstaller->____normalBasicNotePrefab; + auto l_OriginalNotePrefab = l_BeatmapObjectsInstaller->_normalBasicNotePrefab; m_NoteTemplate = GameObject::Instantiate(l_OriginalNotePrefab->get_transform()->GetChild(0)->get_gameObject()); m_NoteTemplate->get_gameObject()->SetActive(false); GameObject::DontDestroyOnLoad(m_NoteTemplate.Ptr()); - auto l_OriginalBombPrefab = l_BeatmapObjectsInstaller->____bombNotePrefab; + auto l_OriginalBombPrefab = l_BeatmapObjectsInstaller->_bombNotePrefab; m_BombTemplate = GameObject::Instantiate(l_OriginalBombPrefab->get_transform()->GetChild(0)->get_gameObject()); m_BombTemplate->get_gameObject()->SetActive(false); GameObject::DontDestroyOnLoad(m_BombTemplate.Ptr()); - auto l_OriginalBurstSliderPrefab = l_BeatmapObjectsInstaller->____burstSliderNotePrefab; + auto l_OriginalBurstSliderPrefab = l_BeatmapObjectsInstaller->_burstSliderNotePrefab; m_BurstSliderTemplate = GameObject::Instantiate(l_OriginalBurstSliderPrefab->get_transform()->GetChild(0)->get_gameObject()); m_BurstSliderTemplate->get_gameObject()->SetActive(false); @@ -128,8 +128,8 @@ namespace QBeatSaberPlus_NoteTweaker::UI { Logger::Instance->Error(ex); } - SceneManagement::SceneManager::UnloadSceneAsync(SceneManagement::SceneManager::GetSceneByName(l_StandardGameplaySceneInfo->____sceneName)); - SceneManagement::SceneManager::UnloadSceneAsync(SceneManagement::SceneManager::GetSceneByName(l_GameCoreSceneInfo->____sceneName)); + SceneManagement::SceneManager::UnloadSceneAsync(SceneManagement::SceneManager::GetSceneByName(l_StandardGameplaySceneInfo->_sceneName)); + SceneManagement::SceneManager::UnloadSceneAsync(SceneManagement::SceneManager::GetSceneByName(l_GameCoreSceneInfo->_sceneName)); }))); }))); } @@ -207,7 +207,7 @@ namespace QBeatSaberPlus_NoteTweaker::UI { m_CustomPreviewDL->get_transform()->set_localScale(Vector3::get_one() * l_Profile->NotesScale); m_CustomPreviewDR->get_transform()->set_localScale(Vector3::get_one() * l_Profile->NotesScale); - auto l_PlayerData = Resources::FindObjectsOfTypeAll()->First()->____playerData; + auto l_PlayerData = Resources::FindObjectsOfTypeAll()->First()->_playerData; auto l_ColorScheme = l_PlayerData->get_colorSchemesSettings()->overrideDefaultColors ? l_PlayerData->get_colorSchemesSettings()->GetSelectedColorScheme() : nullptr; auto l_LeftColor = l_ColorScheme != nullptr ? l_ColorScheme->saberAColor : Color(0.658823549747467f, 0.125490203499794f, 0.125490203499794f, 1.0f); auto l_RightColor = l_ColorScheme != nullptr ? l_ColorScheme->saberBColor : Color(0.125490203499794f, 0.3921568691730499f, 0.658823549747467f, 1.0f); @@ -246,7 +246,7 @@ namespace QBeatSaberPlus_NoteTweaker::UI { { auto& l_Profile = NTConfig::Instance()->GetActiveProfile(); auto l_PlayerData = Resources::FindObjectsOfTypeAll()->First()->get_playerData(); - auto l_ColorScheme = l_PlayerData->get_colorSchemesSettings()->____overrideDefaultColors ? l_PlayerData->get_colorSchemesSettings()->GetSelectedColorScheme() : nullptr; + auto l_ColorScheme = l_PlayerData->get_colorSchemesSettings()->_overrideDefaultColors ? l_PlayerData->get_colorSchemesSettings()->GetSelectedColorScheme() : nullptr; auto l_LeftColor = l_ColorScheme != nullptr ? l_ColorScheme->get_saberAColor() : Color(0.658823549747467f, 0.125490203499794f, 0.125490203499794f, 1.0f); auto l_RightColor = l_ColorScheme != nullptr ? l_ColorScheme->get_saberBColor() : Color(0.125490203499794f, 0.3921568691730499f, 0.658823549747467f, 1.0f); @@ -433,13 +433,13 @@ namespace QBeatSaberPlus_NoteTweaker::UI { for (auto l_PropertyBlockController : p_Object->GetComponents()) { - if (!l_PropertyBlockController->____materialPropertyBlock) - l_PropertyBlockController->____materialPropertyBlock = MaterialPropertyBlock::New_ctor(); + if (!l_PropertyBlockController->_materialPropertyBlock) + l_PropertyBlockController->_materialPropertyBlock = MaterialPropertyBlock::New_ctor(); - l_PropertyBlockController->____materialPropertyBlock->SetColor(Shader::PropertyToID("_Color"), ColorU::WithAlpha(p_Color, 1.0f)); - l_PropertyBlockController->____materialPropertyBlock->SetFloat(Shader::PropertyToID("_EnableRimDim"), 0.0f); - l_PropertyBlockController->____materialPropertyBlock->SetFloat(Shader::PropertyToID("_EnableFog"), 0.0f); - l_PropertyBlockController->____materialPropertyBlock->SetFloat(Shader::PropertyToID("_RimDarkenning"), 0.0f); + l_PropertyBlockController->_materialPropertyBlock->SetColor(Shader::PropertyToID("_Color"), ColorU::WithAlpha(p_Color, 1.0f)); + l_PropertyBlockController->_materialPropertyBlock->SetFloat(Shader::PropertyToID("_EnableRimDim"), 0.0f); + l_PropertyBlockController->_materialPropertyBlock->SetFloat(Shader::PropertyToID("_EnableFog"), 0.0f); + l_PropertyBlockController->_materialPropertyBlock->SetFloat(Shader::PropertyToID("_RimDarkenning"), 0.0f); l_PropertyBlockController->ApplyChanges(); } @@ -465,10 +465,10 @@ namespace QBeatSaberPlus_NoteTweaker::UI { for (auto l_PropertyBlockController : l_Glow->GetComponents()) { - if (!l_PropertyBlockController->____materialPropertyBlock) - l_PropertyBlockController->____materialPropertyBlock = MaterialPropertyBlock::New_ctor(); + if (!l_PropertyBlockController->_materialPropertyBlock) + l_PropertyBlockController->_materialPropertyBlock = MaterialPropertyBlock::New_ctor(); - l_PropertyBlockController->____materialPropertyBlock->SetColor(Shader::PropertyToID("_Color"), p_Color); + l_PropertyBlockController->_materialPropertyBlock->SetColor(Shader::PropertyToID("_Color"), p_Color); l_PropertyBlockController->ApplyChanges(); } @@ -490,10 +490,10 @@ namespace QBeatSaberPlus_NoteTweaker::UI { for (auto l_PropertyBlockController : l_CircleGlow->GetComponents()) { - if (!l_PropertyBlockController->____materialPropertyBlock) - l_PropertyBlockController->____materialPropertyBlock = MaterialPropertyBlock::New_ctor(); + if (!l_PropertyBlockController->_materialPropertyBlock) + l_PropertyBlockController->_materialPropertyBlock = MaterialPropertyBlock::New_ctor(); - l_PropertyBlockController->____materialPropertyBlock->SetColor(Shader::PropertyToID("_Color"), p_Color); + l_PropertyBlockController->_materialPropertyBlock->SetColor(Shader::PropertyToID("_Color"), p_Color); l_PropertyBlockController->ApplyChanges(); } @@ -505,10 +505,10 @@ namespace QBeatSaberPlus_NoteTweaker::UI { for (auto l_PropertyBlockController : l_Circle->GetComponents()) { - if (!l_PropertyBlockController->____materialPropertyBlock) - l_PropertyBlockController->____materialPropertyBlock = MaterialPropertyBlock::New_ctor(); + if (!l_PropertyBlockController->_materialPropertyBlock) + l_PropertyBlockController->_materialPropertyBlock = MaterialPropertyBlock::New_ctor(); - l_PropertyBlockController->____materialPropertyBlock->SetColor(Shader::PropertyToID("_Color"), p_Color); + l_PropertyBlockController->_materialPropertyBlock->SetColor(Shader::PropertyToID("_Color"), p_Color); l_PropertyBlockController->ApplyChanges(); } From e3008df37186f94cf0520fab73df4cfd2f7532f5 Mon Sep 17 00:00:00 2001 From: HardCPP Date: Mon, 10 Aug 2026 00:42:27 +0200 Subject: [PATCH 8/9] Bump version --- include/git_info.h | 2 +- mod.json | 14 ++-- qpm.json | 10 +-- qpm.shared.json | 178 ++++++++++++++++++++++----------------------- 4 files changed, 102 insertions(+), 102 deletions(-) diff --git a/include/git_info.h b/include/git_info.h index 9cb865e..d6878e8 100644 --- a/include/git_info.h +++ b/include/git_info.h @@ -1,5 +1,5 @@ #pragma once #define GIT_USER "HardCPP" #define GIT_BRANCH "dev" -#define GIT_COMMIT 0x651e00a +#define GIT_COMMIT 0x72cdad3 #define GIT_MODIFIED 1 diff --git a/mod.json b/mod.json index 965f5bd..d9ddbb0 100644 --- a/mod.json +++ b/mod.json @@ -5,7 +5,7 @@ "id": "qbeatsaberplus-notetweaker", "modloader": "Scotland2", "author": "HardCPP", - "version": "6.4.1", + "version": "6.4.5", "packageId": "com.beatgames.beatsaber", "packageVersion": "1.40.4_5283", "description": "Feel good!", @@ -17,19 +17,19 @@ "downloadIfMissing": "https://github.com/QuestPackageManager/beatsaber-hook/releases/download/v6.4.2/beatsaber-hook.qmod" }, { - "version": "^0.18.3", + "version": "^0.18.4", "id": "custom-types", - "downloadIfMissing": "https://github.com/QuestPackageManager/Il2CppQuestTypePatching/releases/download/v0.18.3/CustomTypes.qmod" + "downloadIfMissing": "https://github.com/QuestPackageManager/Il2CppQuestTypePatching/releases/download/v0.18.4/CustomTypes.qmod" }, { - "version": "^4.6.4", + "version": "^4.8.0", "id": "paper2_scotland2", - "downloadIfMissing": "https://github.com/Fernthedev/paperlog/releases/download/v4.6.4/paper2_scotland2.qmod" + "downloadIfMissing": "https://github.com/Fernthedev/paperlog/releases/download/v4.8.0/paper2_scotland2.qmod" }, { - "version": "^6.4.1", + "version": "^6.4.5", "id": "chatplex-sdk-bs", - "downloadIfMissing": "https://github.com/hardcpp/QuestChatPlexSDK-BS/releases/download/v6.4.1/ChatPlexSDK-BS.qmod" + "downloadIfMissing": "https://github.com/hardcpp/QuestChatPlexSDK-BS/releases/download/v6.4.5/ChatPlexSDK-BS.qmod" } ], "modFiles": [], diff --git a/qpm.json b/qpm.json index cdc05f7..a615516 100644 --- a/qpm.json +++ b/qpm.json @@ -5,7 +5,7 @@ "info": { "name": "QBeatSaberPlus-NoteTweaker", "id": "qbeatsaberplus-notetweaker", - "version": "6.4.1", + "version": "6.4.5", "url": "https://github.com/hardcpp/QBeatSaberPlus-NoteTweaker", "additionalData": { "overrideSoName": "libqbeatsaberplus-notetweaker.so", @@ -36,7 +36,7 @@ "pwsh ./createqmod.ps1 -clean" ] }, - "ndk": "^27.2.12479018", + "ndk": "^27.3.13750724", "qmodIncludeDirs": [ "build", "extern/libs" @@ -57,7 +57,7 @@ }, { "id": "custom-types", - "versionRange": "^0.18.3", + "versionRange": "^0.18.4", "additionalData": {} }, { @@ -77,7 +77,7 @@ }, { "id": "paper2_scotland2", - "versionRange": "^4.6.4", + "versionRange": "^4.8.0", "additionalData": {} }, { @@ -87,7 +87,7 @@ }, { "id": "chatplex-sdk-bs", - "versionRange": "^6.4.1", + "versionRange": "^6.4.5", "additionalData": { "private": true } diff --git a/qpm.shared.json b/qpm.shared.json index 3332b29..fdbb4ac 100644 --- a/qpm.shared.json +++ b/qpm.shared.json @@ -7,7 +7,7 @@ "info": { "name": "QBeatSaberPlus-NoteTweaker", "id": "qbeatsaberplus-notetweaker", - "version": "6.4.1", + "version": "6.4.5", "url": "https://github.com/hardcpp/QBeatSaberPlus-NoteTweaker", "additionalData": { "overrideSoName": "libqbeatsaberplus-notetweaker.so", @@ -38,7 +38,7 @@ "pwsh ./createqmod.ps1 -clean" ] }, - "ndk": "^27.2.12479018", + "ndk": "^27.3.13750724", "qmodIncludeDirs": [ "build", "extern/libs" @@ -59,7 +59,7 @@ }, { "id": "custom-types", - "versionRange": "^0.18.3", + "versionRange": "^0.18.4", "additionalData": {} }, { @@ -79,7 +79,7 @@ }, { "id": "paper2_scotland2", - "versionRange": "^4.6.4", + "versionRange": "^4.8.0", "additionalData": {} }, { @@ -89,7 +89,7 @@ }, { "id": "chatplex-sdk-bs", - "versionRange": "^6.4.1", + "versionRange": "^6.4.5", "additionalData": { "private": true } @@ -99,73 +99,40 @@ "restoredDependencies": [ { "dependency": { - "id": "paper2_scotland2", - "versionRange": "=4.6.4", + "id": "custom-types", + "versionRange": "=0.18.4", "additionalData": { - "soLink": "https://github.com/Fernthedev/paperlog/releases/download/v4.6.4/libpaper2_scotland2.so", - "overrideSoName": "libpaper2_scotland2.so", - "modLink": "https://github.com/Fernthedev/paperlog/releases/download/v4.6.4/paper2_scotland2.qmod", - "branchName": "version/v4_6_4", + "soLink": "https://github.com/QuestPackageManager/Il2CppQuestTypePatching/releases/download/v0.18.4/libcustom-types.so", + "debugSoLink": "https://github.com/QuestPackageManager/Il2CppQuestTypePatching/releases/download/v0.18.4/debug_libcustom-types.so", + "overrideSoName": "libcustom-types.so", + "modLink": "https://github.com/QuestPackageManager/Il2CppQuestTypePatching/releases/download/v0.18.4/CustomTypes.qmod", + "branchName": "version/v0_18_4", "compileOptions": { - "systemIncludes": [ - "shared/utfcpp/source" + "cppFlags": [ + "-Wno-invalid-offsetof" ] }, - "cmake": false - } - }, - "version": "4.6.4" - }, - { - "dependency": { - "id": "libil2cpp", - "versionRange": "=0.4.0", - "additionalData": { - "headersOnly": true, - "compileOptions": { - "systemIncludes": [ - "il2cpp/external/baselib/Include", - "il2cpp/external/baselib/Platforms/Android/Include" - ] - } - } - }, - "version": "0.4.0" - }, - { - "dependency": { - "id": "chatplex-sdk-bs", - "versionRange": "=6.4.1", - "additionalData": { - "soLink": "https://github.com/hardcpp/QuestChatPlexSDK-BS/releases/download/v6.4.1/libchatplex-sdk-bs.so", - "debugSoLink": "https://github.com/hardcpp/QuestChatPlexSDK-BS/releases/download/v6.4.1/debug_libchatplex-sdk-bs.so", - "overrideSoName": "libchatplex-sdk-bs.so", - "modLink": "https://github.com/hardcpp/QuestChatPlexSDK-BS/releases/download/v6.4.1/ChatPlexSDK-BS.qmod", - "branchName": "version/v6_4_1", "cmake": true } }, - "version": "6.4.1" + "version": "0.18.4" }, { "dependency": { - "id": "custom-types", - "versionRange": "=0.18.3", + "id": "kaleb", + "versionRange": "=0.1.9", "additionalData": { - "soLink": "https://github.com/QuestPackageManager/Il2CppQuestTypePatching/releases/download/v0.18.3/libcustom-types.so", - "debugSoLink": "https://github.com/QuestPackageManager/Il2CppQuestTypePatching/releases/download/v0.18.3/debug_libcustom-types.so", - "overrideSoName": "libcustom-types.so", - "modLink": "https://github.com/QuestPackageManager/Il2CppQuestTypePatching/releases/download/v0.18.3/CustomTypes.qmod", - "branchName": "version/v0_18_3", + "headersOnly": true, + "branchName": "version/v0_1_9", "compileOptions": { "cppFlags": [ - "-Wno-invalid-offsetof" + "-DKALEB_VERSION=\"0.1.9\"" ] }, - "cmake": true + "cmake": false } }, - "version": "0.18.3" + "version": "0.1.9" }, { "dependency": { @@ -191,6 +158,25 @@ }, "version": "4008.0.0" }, + { + "dependency": { + "id": "paper2_scotland2", + "versionRange": "=4.8.0", + "additionalData": { + "soLink": "https://github.com/Fernthedev/paperlog/releases/download/v4.8.0/libpaper2_scotland2.so", + "overrideSoName": "libpaper2_scotland2.so", + "modLink": "https://github.com/Fernthedev/paperlog/releases/download/v4.8.0/paper2_scotland2.qmod", + "branchName": "version/v4_8_0", + "compileOptions": { + "systemIncludes": [ + "shared/utfcpp/source" + ] + }, + "cmake": false + } + }, + "version": "4.8.0" + }, { "dependency": { "id": "conditional-dependencies", @@ -205,23 +191,16 @@ }, { "dependency": { - "id": "beatsaber-hook", - "versionRange": "=6.4.2", + "id": "scotland2", + "versionRange": "=0.1.7", "additionalData": { - "soLink": "https://github.com/QuestPackageManager/beatsaber-hook/releases/download/v6.4.2/libbeatsaber-hook.so", - "debugSoLink": "https://github.com/QuestPackageManager/beatsaber-hook/releases/download/v6.4.2/debug_libbeatsaber-hook.so", - "overrideSoName": "libbeatsaber-hook.so", - "modLink": "https://github.com/QuestPackageManager/beatsaber-hook/releases/download/v6.4.2/beatsaber-hook.qmod", - "branchName": "version/v6_4_2", - "compileOptions": { - "cppFlags": [ - "-Wno-extra-qualification" - ] - }, - "cmake": true + "soLink": "https://github.com/sc2ad/scotland2/releases/download/v0.1.7/libsl2.so", + "debugSoLink": "https://github.com/sc2ad/scotland2/releases/download/v0.1.7/debug_libsl2.so", + "overrideSoName": "libsl2.so", + "branchName": "version/v0_1_7" } }, - "version": "6.4.2" + "version": "0.1.7" }, { "dependency": { @@ -236,19 +215,6 @@ }, "version": "8.5.0" }, - { - "dependency": { - "id": "scotland2", - "versionRange": "=0.1.6", - "additionalData": { - "soLink": "https://github.com/sc2ad/scotland2/releases/download/v0.1.6/libsl2.so", - "debugSoLink": "https://github.com/sc2ad/scotland2/releases/download/v0.1.6/debug_libsl2.so", - "overrideSoName": "libsl2.so", - "branchName": "version/v0_1_6" - } - }, - "version": "0.1.6" - }, { "dependency": { "id": "fmt", @@ -270,20 +236,54 @@ }, { "dependency": { - "id": "kaleb", - "versionRange": "=0.1.9", + "id": "beatsaber-hook", + "versionRange": "=6.4.2", "additionalData": { - "headersOnly": true, - "branchName": "version/v0_1_9", + "soLink": "https://github.com/QuestPackageManager/beatsaber-hook/releases/download/v6.4.2/libbeatsaber-hook.so", + "debugSoLink": "https://github.com/QuestPackageManager/beatsaber-hook/releases/download/v6.4.2/debug_libbeatsaber-hook.so", + "overrideSoName": "libbeatsaber-hook.so", + "modLink": "https://github.com/QuestPackageManager/beatsaber-hook/releases/download/v6.4.2/beatsaber-hook.qmod", + "branchName": "version/v6_4_2", "compileOptions": { "cppFlags": [ - "-DKALEB_VERSION=\"0.1.9\"" + "-Wno-extra-qualification" ] }, - "cmake": false + "cmake": true } }, - "version": "0.1.9" + "version": "6.4.2" + }, + { + "dependency": { + "id": "chatplex-sdk-bs", + "versionRange": "=6.4.5", + "additionalData": { + "soLink": "https://github.com/hardcpp/QuestChatPlexSDK-BS/releases/download/v6.4.5/libchatplex-sdk-bs.so", + "debugSoLink": "https://github.com/hardcpp/QuestChatPlexSDK-BS/releases/download/v6.4.5/debug_libchatplex-sdk-bs.so", + "overrideSoName": "libchatplex-sdk-bs.so", + "modLink": "https://github.com/hardcpp/QuestChatPlexSDK-BS/releases/download/v6.4.5/ChatPlexSDK-BS.qmod", + "branchName": "version/v6_4_5", + "cmake": true + } + }, + "version": "6.4.5" + }, + { + "dependency": { + "id": "libil2cpp", + "versionRange": "=0.4.0", + "additionalData": { + "headersOnly": true, + "compileOptions": { + "systemIncludes": [ + "il2cpp/external/baselib/Include", + "il2cpp/external/baselib/Platforms/Android/Include" + ] + } + } + }, + "version": "0.4.0" } ] } \ No newline at end of file From e501f005f404b8c3f4bec50841659eb937203494 Mon Sep 17 00:00:00 2001 From: HardCPP Date: Mon, 10 Aug 2026 00:45:23 +0200 Subject: [PATCH 9/9] Update qpm.json --- qpm.json | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/qpm.json b/qpm.json index a615516..681bd64 100644 --- a/qpm.json +++ b/qpm.json @@ -15,25 +15,25 @@ "workspace": { "scripts": { "build": [ - "pwsh ./build.ps1" + "pwsh ./scripts/build.ps1" ], "clean": [ - "pwsh ./build.ps1 -clean" + "pwsh ./scripts/build.ps1 -clean" ], "copy": [ - "pwsh ./copy.ps1" + "pwsh ./scripts/copy.ps1" ], "log": [ - "pwsh ./start-logging.ps1" + "pwsh ./scripts/start-logging.ps1" ], "qmod": [ - "pwsh ./build.ps1 -clean", - "pwsh ./createqmod.ps1 -clean" + "pwsh ./scripts/build.ps1 -clean", + "pwsh ./scripts/createqmod.ps1 -clean" ], "qmod_backup": [ - "pwsh ./build.ps1 -clean", + "pwsh ./scripts/build.ps1 -clean", "qpm qmod build", - "pwsh ./createqmod.ps1 -clean" + "pwsh ./scripts/createqmod.ps1 -clean" ] }, "ndk": "^27.3.13750724", @@ -42,7 +42,7 @@ "extern/libs" ], "qmodIncludeFiles": [], - "qmodOutput": "./QBeatSaberPlus-MenuMusic.qmod" + "qmodOutput": "./QBeatSaberPlus-NoteTweaker.qmod" }, "dependencies": [ {