From 27b8e6bd21fc08a0b005b0495c63f0f63ae8ac94 Mon Sep 17 00:00:00 2001 From: Clansty Date: Sat, 28 Sep 2024 16:30:19 +0800 Subject: [PATCH] [+] PractiseMode Debugging --- AquaMai/AquaMai.csproj | 6 +++ AquaMai/AquaMai.sln | 3 ++ AquaMai/Config.cs | 1 + AquaMai/Fix/DebugFeature.cs | 71 +++++++++++++++++++++---- AquaMai/Helpers/MessageHelper.cs | 2 +- AquaMai/Utils/PractiseMode.cs | 89 ++++++++++++++++++++++++++++++++ 6 files changed, 161 insertions(+), 11 deletions(-) create mode 100644 AquaMai/Utils/PractiseMode.cs diff --git a/AquaMai/AquaMai.csproj b/AquaMai/AquaMai.csproj index 2e833770..c29301a1 100644 --- a/AquaMai/AquaMai.csproj +++ b/AquaMai/AquaMai.csproj @@ -37,6 +37,11 @@ true x64 + + bin\Debug\ + SDGA145 +DEBUG + Libs\0Harmony.dll @@ -314,6 +319,7 @@ + diff --git a/AquaMai/AquaMai.sln b/AquaMai/AquaMai.sln index d350c808..4e5cbf75 100644 --- a/AquaMai/AquaMai.sln +++ b/AquaMai/AquaMai.sln @@ -9,12 +9,15 @@ Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Release|Any CPU = Release|Any CPU SDGA145|Any CPU = SDGA145|Any CPU + Debug|Any CPU = Debug|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {788BC472-59F7-46F6-B760-65C18BA74389}.Release|Any CPU.ActiveCfg = Release|Any CPU {788BC472-59F7-46F6-B760-65C18BA74389}.Release|Any CPU.Build.0 = Release|Any CPU {788BC472-59F7-46F6-B760-65C18BA74389}.SDGA145|Any CPU.ActiveCfg = SDGA145|Any CPU {788BC472-59F7-46F6-B760-65C18BA74389}.SDGA145|Any CPU.Build.0 = SDGA145|Any CPU + {788BC472-59F7-46F6-B760-65C18BA74389}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {788BC472-59F7-46F6-B760-65C18BA74389}.Debug|Any CPU.Build.0 = Debug|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/AquaMai/Config.cs b/AquaMai/Config.cs index 746d7bc8..8b441a81 100644 --- a/AquaMai/Config.cs +++ b/AquaMai/Config.cs @@ -60,6 +60,7 @@ namespace AquaMai public bool Windowed { get; set; } public int Width { get; set; } public int Height { get; set; } + public bool PractiseMode { get; set; } } public class TimeSavingConfig diff --git a/AquaMai/Fix/DebugFeature.cs b/AquaMai/Fix/DebugFeature.cs index 523f2670..783c0661 100644 --- a/AquaMai/Fix/DebugFeature.cs +++ b/AquaMai/Fix/DebugFeature.cs @@ -17,6 +17,7 @@ public class DebugFeature private static MovieController _gameMovie; private static GameMonitor[] _monitors; private static object _debugFeatureOriginal; + private static System.Type _debugFeatureType; [HarmonyPatch(typeof(GameProcess), "OnStart")] [HarmonyPostfix] @@ -39,28 +40,79 @@ public class DebugFeature else { MelonLogger.Msg(" > [DebugFeature] Already included"); + _debugFeatureType = typeof(GameProcess).GetNestedType("DebugFeature", BindingFlags.Instance | BindingFlags.NonPublic); h.PatchAll(typeof(GetOriginal)); } } - public static void SetPause(bool pause) + public static bool Pause { + get + { + if (IsPolyfill) + { + return PolyFill.isPause; + } + + return (bool)_debugFeatureType.GetField("_debugPause", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(_debugFeatureOriginal); + } + + set + { + if (IsPolyfill) + { + PolyFill.isPause = value; + } + else + { + _debugFeatureType.GetField("_debugPause", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(_debugFeatureOriginal, value); + } + + SoundManager.PauseMusic(value); + _gameMovie.Pause(value); + NotesManager.Pause(value); + } + } + + public static void Seek(int msec) + { + Singleton.Instance.Initialize(); if (IsPolyfill) { - PolyFill.isPause = pause; + PolyFill.DebugTimeSkip(msec); } else { - var debugFeatureClass = typeof(GameProcess).GetNestedType("DebugFeature", BindingFlags.Instance | BindingFlags.NonPublic); - debugFeatureClass?.GetField("_debugPause", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(_debugFeatureOriginal, pause); + _debugFeatureType.GetMethod("DebugTimeSkip", BindingFlags.Instance | BindingFlags.NonPublic)?.Invoke(_debugFeatureOriginal, new object[] { msec }); + } + } + + public static double CurrentPlayMsec + { + get + { + if (IsPolyfill) + { + return PolyFill.timer; + } + + return (double)_debugFeatureType.GetField("_debugTimer", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(_debugFeatureOriginal); + } + set + { + if (IsPolyfill) + { + PolyFill.timer = value; + } + else + { + _debugFeatureType.GetField("_debugTimer", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(_debugFeatureOriginal, value); + } + + Seek(0); } - - SoundManager.PauseMusic(pause); - _gameMovie.Pause(pause); - NotesManager.Pause(pause); } - [HarmonyPatch] private static class GetOriginal { [HarmonyPatch(typeof(GameProcess), "OnStart")] @@ -71,7 +123,6 @@ public class DebugFeature } } - [HarmonyPatch] private static class PolyFill { public static bool isPause; diff --git a/AquaMai/Helpers/MessageHelper.cs b/AquaMai/Helpers/MessageHelper.cs index 6dbacfef..0d66c603 100644 --- a/AquaMai/Helpers/MessageHelper.cs +++ b/AquaMai/Helpers/MessageHelper.cs @@ -31,7 +31,7 @@ public class MessageHelper replaceText = true, text = message, changeSize = true, - sizeID = size + sizeID = size, }); } } diff --git a/AquaMai/Utils/PractiseMode.cs b/AquaMai/Utils/PractiseMode.cs new file mode 100644 index 00000000..efc714d4 --- /dev/null +++ b/AquaMai/Utils/PractiseMode.cs @@ -0,0 +1,89 @@ +using AquaMai.Fix; +using AquaMai.Helpers; +using HarmonyLib; +using MelonLoader; +using Monitor; +using Process; +using UnityEngine; +using UrGUI.GUIWindow; + +namespace AquaMai.Utils; + +public class PractiseMode +{ + private static double repeatStart = -1; + private static double repeatEnd = -1; + + private static void SetRepeatEnd(double time) + { + if (repeatStart == -1) + { + MessageHelper.ShowMessage("Please set repeat start time first"); + return; + } + + if (time < repeatStart) + { + MessageHelper.ShowMessage("Repeat end time cannot be less than repeat start time"); + return; + } + + repeatEnd = time; + } + + private static void ClearRepeat() + { + repeatStart = -1; + repeatEnd = -1; + } + + private class DebugWindow : MonoBehaviour + { + private GUIWindow window; + + public void Start() + { + window = GUIWindow.Begin("练习模式 测试"); + window.Button("暂停", () => DebugFeature.Pause = !DebugFeature.Pause); + window.SameLine(); + window.Button("向前", () => DebugFeature.Seek(-1000)); + window.Button("向后", () => DebugFeature.Seek(1000)); + window.SameLine(1, 1, 1); + window.Button("循环开始", () => repeatStart = DebugFeature.CurrentPlayMsec); + window.Button("循环结束", () => SetRepeatEnd(DebugFeature.CurrentPlayMsec)); + window.Button("循环解除", ClearRepeat); + } + + private void OnGUI() + { + window?.Draw(); + } + } + + private static DebugWindow debugWin; + + [HarmonyPatch(typeof(GameProcess), "OnUpdate")] + [HarmonyPostfix] + public static void GameProcessPostUpdate(GameProcess __instance, GameMonitor[] ____monitors) + { + if (Input.GetKeyDown(KeyCode.F12)) + { + if (debugWin is null) + { + debugWin = ____monitors[0].gameObject.AddComponent(); + } + else + { + MelonLogger.Msg("[PractiseMode] 调试窗口作用中"); + } + } + + if (repeatStart >= 0 && repeatEnd >= 0) + { + if (DebugFeature.CurrentPlayMsec >= repeatEnd) + { + DebugFeature.CurrentPlayMsec = repeatStart; + } + } + } +}