diff --git a/Common/AutoBackupData.cs b/Common/AutoBackupData.cs new file mode 100644 index 0000000..204724e --- /dev/null +++ b/Common/AutoBackupData.cs @@ -0,0 +1,20 @@ +using HarmonyLib; +using Manager; +using MelonLoader; +using Monitor.ModeSelect; +using SinmaiAssist.Utils; + +namespace SinmaiAssist.Common; + +public class AutoBackupData +{ + [HarmonyPostfix] + [HarmonyPatch(typeof(ModeSelectMonitor), "Initialize")] + public static void Initialize(ModeSelectMonitor __instance, int monIndex) + { + UserData userData = User.GetUserData(monIndex); + if (userData.IsGuest()) return; + string fileName = User.ExportBackupData(monIndex, sendMessage:false); + MelonLogger.Msg($"[AutoBackupData] P{monIndex + 1} ID: {userData.Detail.UserID} Data Backup Success: {fileName} "); + } +} \ No newline at end of file diff --git a/Common/BlockCoin.cs b/Common/BlockCoin.cs new file mode 100644 index 0000000..ed706e5 --- /dev/null +++ b/Common/BlockCoin.cs @@ -0,0 +1,72 @@ +using AMDaemon; +using HarmonyLib; +using Credit = Manager.Credit; + +namespace SinmaiAssist.Common; + +public class BlockCoin +{ + [HarmonyPostfix] + [HarmonyPatch(typeof(Credit), "GameCostEnoughFreedom")] + public static void GameCostEnoughFreedom(Credit __instance, ref int __result) + { + __result = 2; + } + + [HarmonyPostfix] + [HarmonyPatch(typeof(Credit), "GameCostEnoughPlay")] + public static void GameCostEnoughPlay(Credit __instance, ref int __result) + { + __result = (int)__instance.NowCoinCost; + } + + [HarmonyPostfix] + [HarmonyPatch(typeof(Credit), "IsGameCostEnough")] + public static void IsGameCostEnough(Credit __instance, ref bool __result) + { + __result = true; + } + + [HarmonyPostfix] + [HarmonyPatch(typeof(Credit), "IsGameCostEnoughFreedom")] + public static void IsGameCostEnoughFreedom(Credit __instance, ref bool __result) + { + __result = true; + } + + [HarmonyPostfix] + [HarmonyPatch(typeof(Credit), "IsZero")] + public static void IsZero(Credit __instance, ref bool __result) + { + __result = false; + } + + [HarmonyPostfix] + [HarmonyPatch(typeof(Credit), "PayGameCostFreedom")] + public static void PayGameCostFreedom(Credit __instance, ref bool __result) + { + __result = true; + } + + [HarmonyPostfix] + [HarmonyPatch(typeof(Credit), "PayItemCost")] + public static void PayItemCost(Credit __instance, ref bool __result) + { + __result = true; + } + + [HarmonyPostfix] + [HarmonyPatch(typeof(Credit), "PayTicketCost")] + public static void PayTicketCost(Credit __instance, ref bool __result) + { + __result = true; + + [HarmonyPrefix] + [HarmonyPatch(typeof(CreditUnit), "get_Credit")] + static bool PreCredit(ref uint __result) + { + __result = 24; + return false; + } + } +} \ No newline at end of file diff --git a/Common/ChangeDefaultOption.cs b/Common/ChangeDefaultOption.cs new file mode 100644 index 0000000..fb059ff --- /dev/null +++ b/Common/ChangeDefaultOption.cs @@ -0,0 +1,92 @@ +using System; +using System.IO; +using System.Linq; +using System.Reflection; +using DB; +using HarmonyLib; +using MAI2.Util; +using Manager; +using Manager.UserDatas; +using MelonLoader; +using SinmaiAssist.Utils; +using YamlDotNet.Serialization; +using YamlDotNet.Serialization.NamingConventions; + +namespace SinmaiAssist.Common; + +public class ChangeDefaultOption +{ + private static string OptionFilePath = $"{BuildInfo.Name}/DefaultOption.yml"; + + [HarmonyPostfix] + [HarmonyPatch(typeof(UserDataManager), "SetDefault")] + public static void DefaultOption(UserDataManager __instance, ref long index) + { + var userData = __instance.GetUserData(index); + if (!userData.IsGuest()) return; + try + { + UserOption option = Singleton.Instance.GetUserData(index).Option; + option.OptionKind = OptionKindID.Custom; + if (!File.Exists(OptionFilePath)) + { + MelonLogger.Warning($"Path: \"{OptionFilePath}\" Not Found, Try to create it."); + SaveOptionFile(index); + } + else + { + var deserializer = new DeserializerBuilder() + .WithNamingConvention(CamelCaseNamingConvention.Instance) + .Build(); + using (var reader = new StreamReader(OptionFilePath)) + { + var newOption = deserializer.Deserialize(reader); + UpdateUserOption(option, newOption); + } + } + } + catch (Exception e) + { + MelonLogger.Error(e); + } + } + + private static void UpdateUserOption(UserOption originalOption, UserOption newOption) + { + if (newOption == null) return; + PropertyInfo[] properties = typeof(UserOption).GetProperties(); + foreach (var property in properties) + { + if (property.CanWrite) + { + var newValue = property.GetValue(newOption); + property.SetValue(originalOption, newValue); + } + } + } + + private static string RemoveUnwantedOption(string yaml) + { + string[] propertiesToRemove = { "getNoteSpeed", "getSlideSpeed", "getTouchSpeed" }; + var lines = yaml.Split('\n'); + var filteredLines = lines.Where(line => !propertiesToRemove.Any(prop => line.TrimStart().StartsWith(prop))); + return string.Join("\n", filteredLines); + } + + public static void SaveOptionFile(long index) + { + UserOption option = Singleton.Instance.GetUserData(index).Option; + option.OptionKind = OptionKindID.Custom; + var serializer = new SerializerBuilder() + .WithNamingConvention(CamelCaseNamingConvention.Instance) + .Build(); + string optionYaml = serializer.Serialize(option); + optionYaml = RemoveUnwantedOption(optionYaml); + if (File.Exists(OptionFilePath)) + { + File.Delete(OptionFilePath); + } + File.WriteAllText(OptionFilePath, optionYaml); + GameMessageManager.SendMessage((int)index,$"User Option File Saved"); + } +} \ No newline at end of file diff --git a/Common/ChangeFadeStyle.cs b/Common/ChangeFadeStyle.cs new file mode 100644 index 0000000..ebe8b06 --- /dev/null +++ b/Common/ChangeFadeStyle.cs @@ -0,0 +1,58 @@ +using HarmonyLib; +using MelonLoader; +using System.Collections.Generic; +using System.Reflection.Emit; +using Process; + +namespace SinmaiAssist.Common; + +public class ChangeFadeStyle +{ + [HarmonyTranspiler] + [HarmonyPatch(typeof(FadeProcess), "OnStart")] + public static IEnumerable TranspilerFade(IEnumerable instructions) + { + var codes = new List(instructions); + bool isFound = false; + + for (int i = 0; i < codes.Count - 1; i++) + { + if (codes[i].opcode == OpCodes.Ldstr && codes[i].operand.ToString().StartsWith("Process/ChangeScreen/Prefabs/ChangeScreen_")) + { + var typeString = "02"; + if (codes[i].operand.ToString().EndsWith("02")) typeString = "01"; + codes[i].operand = $"Process/ChangeScreen/Prefabs/ChangeScreen_{typeString}"; + isFound = true; + break; + } + } + if (!isFound) + MelonLogger.Warning("Failed to patch ChangeFadeStyle, Method Not Found!"); + + return codes; + } + + [HarmonyTranspiler] + [HarmonyPatch(typeof(NextTrackProcess), "OnStart")] + public static IEnumerable TranspilerNextTrack(IEnumerable instructions) + { + var codes = new List(instructions); + bool isFound = false; + + for (int i = 0; i < codes.Count - 1; i++) + { + if (codes[i].opcode == OpCodes.Ldstr && codes[i].operand.ToString().StartsWith("Process/ChangeScreen/Prefabs/ChangeScreen_")) + { + var typeString = "02"; + if (codes[i].operand.ToString().EndsWith("02")) typeString = "01"; + codes[i].operand = $"Process/ChangeScreen/Prefabs/ChangeScreen_{typeString}"; + isFound = true; + break; + } + } + if (!isFound) + MelonLogger.Warning("Failed to patch ChangeFadeStyle, Method Not Found!"); + + return codes; + } +} \ No newline at end of file diff --git a/Common/ChangeGameSettings.cs b/Common/ChangeGameSettings.cs new file mode 100644 index 0000000..fb80069 --- /dev/null +++ b/Common/ChangeGameSettings.cs @@ -0,0 +1,86 @@ +using System; +using System.Collections.Generic; +using DB; +using HarmonyLib; +using Manager; +using MelonLoader; +using Monitor.ModeSelect; +using SinmaiAssist.Utils; +using UnityEngine; + +namespace SinmaiAssist.Common; + +public class ChangeGameSettings +{ + private static readonly List SettingEnable = new List { false,false,false,false }; + private static readonly List UserSettingToggleState = new List { false, false, false, false }; + + [HarmonyPostfix] + [HarmonyPatch(typeof(ModeSelectMonitor), "Initialize")] + public static void SetSettings(ModeSelectMonitor __instance, int monIndex) + { + try + { + UserData userData = User.GetUserData(monIndex); + InitSettings(userData); + SetUserFlag(userData); + AccessTools.Field(typeof(ModeSelectMonitor), "_isSettingEnable").SetValue(__instance, SettingEnable); + AccessTools.Field(typeof(ModeSelectMonitor), "_isSettingToggleState").SetValue(__instance, UserSettingToggleState); + var nullSetting = (List) AccessTools.Field(typeof(ModeSelectMonitor), "_nullSetting").GetValue(__instance); + var animSetting = (List) AccessTools.Field(typeof(ModeSelectMonitor), "_animSetting").GetValue(__instance); + for (int i = 0; i < SettingEnable.Count; i++) + { + nullSetting[i].transform.GetChild(0).GetChild(5).gameObject.SetActive(!SettingEnable[i]); + if (UserSettingToggleState[i]) + { + animSetting[i].Play("On_Loop", 0, 0f); + __instance._settingMiniWindow.transform.GetChild(i).GetChild(0).GetChild(0).gameObject.SetActive(value: true); + __instance._settingMiniWindow.transform.GetChild(i).GetChild(0).GetChild(1).gameObject.SetActive(value: false); + } + else + { + animSetting[i].Play("Off_Loop", 0, 0f); + __instance._settingMiniWindow.transform.GetChild(i).GetChild(0).GetChild(0).gameObject.SetActive(value: false); + __instance._settingMiniWindow.transform.GetChild(i).GetChild(0).GetChild(1).gameObject.SetActive(value: true); + } + nullSetting[i].transform.GetChild(0).GetChild(4).GetChild(2).gameObject.SetActive(value: false); + } + } + catch (Exception e) + { + MelonLogger.Error(e); + } + } + + private static void InitSettings(UserData userData) + { + SettingEnable[0] = SinmaiAssist.MainConfig.Common.ChangeGameSettings.CodeRead; + SettingEnable[1] = SinmaiAssist.MainConfig.Common.ChangeGameSettings.IconPhoto; + SettingEnable[2] = SinmaiAssist.MainConfig.Common.ChangeGameSettings.CharaSelect; + SettingEnable[3] = SinmaiAssist.MainConfig.Common.ChangeGameSettings.UploadPhoto; + UserSettingToggleState[0] = userData.Extend.ExtendContendBit.IsFlagOn(ExtendContentBitID.GotoCodeRead) && SettingEnable[0]; + UserSettingToggleState[1] = userData.Extend.ExtendContendBit.IsFlagOn(ExtendContentBitID.GotoIconPhotoShoot) && SettingEnable[1]; + UserSettingToggleState[2] = userData.Extend.ExtendContendBit.IsFlagOn(ExtendContentBitID.GotoCharaSelect) && SettingEnable[2]; + UserSettingToggleState[3] = userData.Extend.ExtendContendBit.IsFlagOn(ExtendContentBitID.PhotoAgree) && SettingEnable[3]; + } + + private static void SetUserFlag(UserData userData) + { + if (!SettingEnable[0]) + { + userData.Extend.ExtendContendBit.SetFlag(ExtendContentBitID.GotoCodeRead, false); + } + if (!SettingEnable[1]) + { + userData.Extend.ExtendContendBit.SetFlag(ExtendContentBitID.GotoIconPhotoShoot, false); + } + if (!SettingEnable[2]) + { + userData.Extend.ExtendContendBit.SetFlag(ExtendContentBitID.GotoCharaSelect, false); + } + if (!SettingEnable[3]) + { + userData.Extend.ExtendContendBit.SetFlag(ExtendContentBitID.PhotoAgree, false); + } + } +} \ No newline at end of file diff --git a/Common/CustomCameraId.cs b/Common/CustomCameraId.cs new file mode 100644 index 0000000..8c3a47f --- /dev/null +++ b/Common/CustomCameraId.cs @@ -0,0 +1,103 @@ +using System; +using static Manager.CameraManager; +using System.Collections; +using HarmonyLib; +using Manager; +using MelonLoader; +using UnityEngine; + +namespace SinmaiAssist.Common; + +public class CustomCameraId +{ + private static CameraParameter _gameCameraParam; + private static CameraParameter _qrCameraParam; + + [HarmonyPrefix] + [HarmonyPatch(typeof(CameraManager), "CameraInitialize")] + public static bool CameraInitialize(CameraManager __instance, ref IEnumerator __result) + { + __result = CameraInitialize(__instance); + return false; + } + + [HarmonyPostfix] + [HarmonyPatch(typeof(CameraManager), "Initialize")] + public static void SetCameraResolution(CameraManager __instance) + { + if (SinmaiAssist.GameID != "SDEZ") + { + WebCamDevice qrDevice = WebCamTexture.devices[SinmaiAssist.GameID == "SDGB" ? SinmaiAssist.MainConfig.Common.CustomCameraId.ChimeCameraId : SinmaiAssist.MainConfig.Common.CustomCameraId.LeftQrCameraId]; + WebCamTexture qrTexture = new WebCamTexture(qrDevice.name); + qrTexture.Play(); + _qrCameraParam = new CameraParameter(qrTexture.width, qrTexture.height, (int)qrTexture.requestedFPS); + AccessTools.Field(typeof(CameraManager), "QrCameraParam").SetValue(__instance, _qrCameraParam); + qrTexture.Stop(); + } + WebCamDevice gameDevice = WebCamTexture.devices[SinmaiAssist.MainConfig.Common.CustomCameraId.PhotoCameraId]; + WebCamTexture gameTexture = new WebCamTexture(gameDevice.name); + gameTexture.Play(); + _gameCameraParam = new CameraParameter(gameTexture.width, gameTexture.height, (int)gameTexture.requestedFPS); + AccessTools.Field(typeof(CameraManager), "GameCameraParam").SetValue(__instance, _gameCameraParam); + gameTexture.Stop(); + } + + private static IEnumerator CameraInitialize(CameraManager __instance) + { + int webcamtexLength = Math.Max(2, WebCamTexture.devices.Length); + WebCamTexture[] webcamtex = new WebCamTexture[webcamtexLength]; + + int leftQrCameraId = ((SinmaiAssist.MainConfig.Common.CustomCameraId.LeftQrCameraId < WebCamTexture.devices.Length) + ? SinmaiAssist.MainConfig.Common.CustomCameraId.LeftQrCameraId + : 0); + int rightQrCameraId = ((SinmaiAssist.MainConfig.Common.CustomCameraId.RightQrCameraId < WebCamTexture.devices.Length) + ? SinmaiAssist.MainConfig.Common.CustomCameraId.RightQrCameraId + : 0); + int photoCameraId = ((SinmaiAssist.MainConfig.Common.CustomCameraId.PhotoCameraId < WebCamTexture.devices.Length) + ? SinmaiAssist.MainConfig.Common.CustomCameraId.PhotoCameraId + : 0); + int chimeQrCameraId = ((SinmaiAssist.MainConfig.Common.CustomCameraId.ChimeCameraId < WebCamTexture.devices.Length) + ? SinmaiAssist.MainConfig.Common.CustomCameraId.ChimeCameraId + : 0); + + switch (SinmaiAssist.GameID) + { + case "SDGB": + webcamtex[chimeQrCameraId] = new WebCamTexture(WebCamTexture.devices[chimeQrCameraId].name, _qrCameraParam.Width, _qrCameraParam.Height, _qrCameraParam.Fps); + DeviceId[0] = chimeQrCameraId; + DeviceId[1] = photoCameraId; + break; + case "SDEZ": + webcamtex[leftQrCameraId] = new WebCamTexture(WebCamTexture.devices[leftQrCameraId].name, _qrCameraParam.Width, _qrCameraParam.Height, _qrCameraParam.Fps); + webcamtex[rightQrCameraId] = new WebCamTexture(WebCamTexture.devices[rightQrCameraId].name, _qrCameraParam.Width, _qrCameraParam.Height, _qrCameraParam.Fps); + DeviceId[0] = leftQrCameraId; + DeviceId[1] = rightQrCameraId; + DeviceId[2] = photoCameraId; + break; + default: + DeviceId[0] = photoCameraId; + break; + } + webcamtex[photoCameraId] = new WebCamTexture(WebCamTexture.devices[photoCameraId].name, _gameCameraParam.Width, _gameCameraParam.Height, _gameCameraParam.Fps); + + // 判断如果设备只连接了一个摄像头,就将相机0复制到相机1,防止其他代码调用相机1导致读到个Null + if (WebCamTexture.devices.Length == 1) + { + webcamtex[1] = webcamtex[0]; + } + + AccessTools.Field(typeof(CameraManager), "_webcamtex").SetValue(__instance, webcamtex); + + __instance.isAvailableCamera = new bool[webcamtex.Length]; + __instance.cameraProcMode = new CameraProcEnum[webcamtex.Length]; + + for (int i = 0; i < webcamtex.Length; i++) + { + __instance.isAvailableCamera[i] = true; + __instance.cameraProcMode[i] = CameraProcEnum.Good; + } + + IsReady = true; + yield break; + } +} \ No newline at end of file diff --git a/Common/CustomVersionText.cs b/Common/CustomVersionText.cs new file mode 100644 index 0000000..c6e81c9 --- /dev/null +++ b/Common/CustomVersionText.cs @@ -0,0 +1,15 @@ +using HarmonyLib; + +namespace SinmaiAssist.Common; + +public class CustomVersionText +{ + [HarmonyPrefix] + [HarmonyPatch(typeof(MAI2System.Config), "get_displayVersionString")] + public static bool CustomVersionString(ref string __result) + { + if (string.IsNullOrEmpty(SinmaiAssist.MainConfig.Common.CustomVersionText.VersionText)) return true; + __result = SinmaiAssist.MainConfig.Common.CustomVersionText.VersionText; + return false; + } +} \ No newline at end of file diff --git a/Common/DisableBackground.cs b/Common/DisableBackground.cs new file mode 100644 index 0000000..954a911 --- /dev/null +++ b/Common/DisableBackground.cs @@ -0,0 +1,42 @@ +using System; +using HarmonyLib; +using Monitor; +using UnityEngine; + +namespace SinmaiAssist.Common; + +public class DisableBackground +{ + [HarmonyPrefix] + [HarmonyPatch(typeof(MonitorBackgroundTownController), "SetMainDisp")] + public static bool SetMainDisp(MonitorBackgroundTownController __instance, ref bool dispflag) + { + dispflag = false; + DisableSubBackground(); + return true; + } + + private static void DisableSubBackground() + { + try + { + if (SinmaiAssist.MainConfig.Common.SinglePlayer.HideSubMonitor) return; + GameObject leftSubMonitor = GameObject.Find("LeftMonitor") + .transform.Find("CommonProcess(Clone)") + .transform.Find("RearCanvas") + .transform.Find("Sub") + .Find("UI_SubBackground").gameObject; + leftSubMonitor.SetActive(false); + GameObject rightSubMonitor = GameObject.Find("RightMonitor") + .transform.Find("CommonProcess(Clone)") + .transform.Find("RearCanvas") + .transform.Find("Sub") + .Find("UI_SubBackground").gameObject; + rightSubMonitor.SetActive(false); + } + catch (Exception e) + { + // ignored + } + } +} \ No newline at end of file diff --git a/Common/DisableMask.cs b/Common/DisableMask.cs new file mode 100644 index 0000000..de6dfa6 --- /dev/null +++ b/Common/DisableMask.cs @@ -0,0 +1,24 @@ +using System; +using HarmonyLib; +using MelonLoader; +using UnityEngine; + +namespace SinmaiAssist.Common; + +public class DisableMask +{ + [HarmonyPrefix] + [HarmonyPatch(typeof(Main.GameMain), "LateInitialize", new System.Type[] { typeof(MonoBehaviour), typeof(Transform), typeof(Transform) })] + public static bool LateInitialize(MonoBehaviour gameMainObject, ref Transform left, ref Transform right) + { + try + { + GameObject.Find("Mask").SetActive(false); + } + catch (Exception e) + { + MelonLogger.Warning("Maybe the current Sinmai build does not have GameObject \"Mask\"."); + } + return true; + } +} \ No newline at end of file diff --git a/Common/DummyAimeLogin.cs b/Common/DummyAimeLogin.cs new file mode 100644 index 0000000..159b077 --- /dev/null +++ b/Common/DummyAimeLogin.cs @@ -0,0 +1,125 @@ +using System; +using System.IO; +using System.Text.RegularExpressions; +using AMDaemon; +using HarmonyLib; +using Mai2.Mai2Cue; +using Manager; +using SinmaiAssist.GUI; +using SinmaiAssist.Utils; + +namespace SinmaiAssist.Common; + +public class DummyAimeLogin +{ + public static void ReadCard(string accesscode=null, string oldCode=null) + { + accesscode ??= DummyLoginPanel.DummyLoginCode.Trim(); + if (!Directory.Exists("DEVICE")) Directory.CreateDirectory("DEVICE"); + if (accesscode.Length == 20 && Regex.IsMatch(accesscode, @"^\d+$")) + { + File.WriteAllText("DEVICE/aime.txt", accesscode); + Keyboard.LongPressKey(Keys.Enter, 300); + if (oldCode is { Length: 20 } && Regex.IsMatch(oldCode, @"^\d+$")) + File.WriteAllText("DEVICE/aime.txt", oldCode); + } + else + { + GameMessageManager.SendMessage(0,"Failed to read Aime!"); + GameMessageManager.SendMessage(1,"Failed to read Aime!"); + SoundManager.PlaySE(Cue.SE_ENTRY_AIME_ERROR, 1); + } + } + // + // [HarmonyPrefix] + // [HarmonyPatch(typeof(AimeUnit), "HasConfirm")] + // public static bool HasConfirm(ref bool __result) + // { + // if (ModGUI.UserIdLoginFlag) + // { + // __result = ModGUI.UserIdLoginFlag; + // return false; + // } + // return true; + // } + // + // [HarmonyPrefix] + // [HarmonyPatch(typeof(AimeUnit), "HasResult")] + // public static bool HasResult(ref bool __result) + // { + // if (ModGUI.UserIdLoginFlag) + // { + // __result = ModGUI.UserIdLoginFlag; + // return false; + // } + // return true; + // } + // + // [HarmonyPrefix] + // [HarmonyPatch(typeof(AimeUnit), "HasError")] + // public static bool HasError(ref bool __result) + // { + // if (ModGUI.UserIdLoginFlag) + // { + // __result = !ModGUI.UserIdLoginFlag; + // return false; + // } + // return true; + // } + // + // [HarmonyPrefix] + // [HarmonyPatch(typeof(AimeUnit), "ErrorInfo")] + // public static bool GetResult(ref AimeErrorId __result) + // { + // if (ModGUI.UserIdLoginFlag) + // { + // __result = AimeErrorId.None; + // return false; + // } + // return true; + // } + // + // [HarmonyPrefix] + // [HarmonyPatch(typeof(AimeResult), "IsValid")] + // public static bool IsValid(ref bool __result) + // { + // if (ModGUI.UserIdLoginFlag) + // { + // __result = true; + // return false; + // } + // return true; + // } + + // [HarmonyPrefix] + // [HarmonyPatch(typeof(AimeResult), "AccessCode")] + // public static bool GetAccessCode(ref AccessCode __result) + // { + // if (ModGUI.UserIdLoginFlag) + // { + // Random random = new Random(); + // __result = AccessCode.Make((random.NextDouble() * (long)Math.Pow(10, 20)).ToString()); + // return false; + // } + // return true; + // } + + [HarmonyPrefix] + [HarmonyPatch(typeof(AimeId), "Value", MethodType.Getter)] + public static bool GetAimeId(ref uint __result) + { + if (DummyLoginPanel.UserIdLoginFlag) + { + __result = Convert.ToUInt32(DummyLoginPanel.DummyUserId); + return false; + } + return true; + } + + [HarmonyPostfix] + [HarmonyPatch(typeof(Process.Entry.TryAime), "Execute")] + public static void ClearFlag() + { + DummyLoginPanel.UserIdLoginFlag = false; + } +} \ No newline at end of file diff --git a/Common/DummyChimeLogin.cs b/Common/DummyChimeLogin.cs new file mode 100644 index 0000000..d0fe3af --- /dev/null +++ b/Common/DummyChimeLogin.cs @@ -0,0 +1,186 @@ +using ChimeLib.NET; +using HarmonyLib; +using Manager; +using System.Collections; +using System.Reflection; +using SinmaiAssist.GUI; +using UnityEngine; + +namespace SinmaiAssist.Common; + +public class DummyChimeLogin +{ + // CameraManager Patch + [HarmonyPrefix] + [HarmonyPatch(typeof(CameraManager), "get_IsAvailableCamera")] + public static bool IsAvailableCamera(ref bool __result) + { + __result = true; + return false; + } + + [HarmonyPrefix] + [HarmonyPatch(typeof(CameraManager), "get_IsAvailableChimeCamera")] + public static bool IsAvailableChimeCamera(ref bool __result) + { + __result = true; + return false; + } + + [HarmonyPrefix] + [HarmonyPatch(typeof(CameraManager), "get_IsAvailableCameras")] + public static bool IsAvailableCameras(ref bool[] __result) + { + __result = new bool[2] { true, true }; + return false; + } + + [HarmonyPrefix] + [HarmonyPatch(typeof(CameraManager), "GetTexture")] + public static bool GetTexture(ref WebCamTexture __result) + { + __result = null; + return false; + } + + [HarmonyPrefix] + [HarmonyPatch(typeof(CameraManager), "IsPlayingPhotoCamera")] + public static bool IsPlayingPhotoCamera(ref bool __result) + { + __result = false; + return false; + } + + [HarmonyPrefix] + [HarmonyPatch(typeof(CameraManager), "PlayPhotoCamera")] + public static bool PlayPhotoCamera() { return false; } + + [HarmonyPrefix] + [HarmonyPatch(typeof(CameraManager), "PlayPhotoOnly")] + public static bool PlayPhotoOnly() { return false; } + + [HarmonyPrefix] + [HarmonyPatch(typeof(CameraManager), "PausePhoto")] + public static bool PausePhoto() { return false; } + + [HarmonyPrefix] + [HarmonyPatch(typeof(CameraManager), "StopPhoto")] + public static bool StopPhoto() { return false; } + + [HarmonyPrefix] + [HarmonyPatch(typeof(CameraManager), "GetColor32")] + public static bool GetColor32(ref Color32[] __result) + { + __result = null; + return false; + } + + [HarmonyPrefix] + [HarmonyPatch(typeof(CameraManager), "CameraInitialize")] + public static bool CameraInitialize(CameraManager __instance, ref IEnumerator __result) + { + __result = CameraInitialize(__instance); + return false; + } + + public static IEnumerator CameraInitialize(CameraManager __instance) + { + CameraManager.IsReady = true; + yield break; + } + + // ChimeDevice Patch + [HarmonyPrefix] + [HarmonyPatch(typeof(ChimeDevice), MethodType.Constructor, new[] { typeof(WebCamTexture) })] + public static bool ChimeDevice(WebCamTexture texture) { return false; } + + [HarmonyPrefix] + [HarmonyPatch(typeof(ChimeDevice), "HasError")] + public static bool HasError(ref bool __result) + { + __result = false; + return false; + } + + [HarmonyPrefix] + [HarmonyPatch(typeof(ChimeDevice), "IsReady")] + public static bool IsReady(ref bool __result) + { + __result = true; + return false; + } + + [HarmonyPrefix] + [HarmonyPatch(typeof(ChimeDevice), "BeginScan")] + public static bool BeginScan() { return false; } + + [HarmonyPrefix] + [HarmonyPatch(typeof(ChimeDevice), "EndScan")] + public static bool EndScan() { return false; } + + [HarmonyPrefix] + [HarmonyPatch(typeof(ChimeDevice), "GetDecodeStrings")] + public static bool GetDecodeStrings(ref string[] __result) + { + if (DummyLoginPanel.CodeLoginFlag) + { + DummyLoginPanel.CodeLoginFlag = false; + if (DummyLoginPanel.DummyLoginCode == null) + { + __result = null; + return false; + } + else + { + __result = new string[1] { DummyLoginPanel.DummyLoginCode }; + return false; + } + } + __result = null; + return false; + } + + // ChimeReaderManager Patch + [HarmonyPrefix] + [HarmonyPatch(typeof(ChimeReaderManager), "Execute")] + public static bool Execute(ChimeReaderManager __instance) + { + var result = AccessTools.Field(typeof(ChimeReaderManager), "_result"); + var aimeId = AccessTools.Field(typeof(ChimeReaderManager), "_aimeId"); + var currentState = AccessTools.Field(typeof(ChimeReaderManager), "currentState"); + if (DummyLoginPanel.UserIdLoginFlag) + { + ChimeId _aimeId; + System.Type chimeIdType = System.Type.GetType("ChimeLib.NET.ChimeId, ChimeLib.NET"); + MethodInfo makeMethod = chimeIdType.GetMethod("Make", BindingFlags.NonPublic | BindingFlags.Static); + _aimeId = (ChimeId)makeMethod.Invoke(null, new object[] { uint.Parse(DummyLoginPanel.DummyUserId) }); + result.SetValue(__instance, ChimeReaderManager.Result.Done); + aimeId.SetValue(__instance, _aimeId); + currentState.SetValue(__instance, 9); + return false; + } + return true; + } + + [HarmonyPrefix] + [HarmonyPatch(typeof(ChimeReaderManager), "AdvCheck")] + public static bool AdvCheck(ref bool __result) + { + if (DummyLoginPanel.UserIdLoginFlag) + { + __result = true; + return false; + } + else + { + return true; + } + } + + [HarmonyPostfix] + [HarmonyPatch(typeof(Process.Entry.TryAime), "Execute")] + public static void ClearFlag() + { + DummyLoginPanel.UserIdLoginFlag = false; + } +} \ No newline at end of file diff --git a/Common/ForceQuickRetry.cs b/Common/ForceQuickRetry.cs new file mode 100644 index 0000000..c20e6cf --- /dev/null +++ b/Common/ForceQuickRetry.cs @@ -0,0 +1,14 @@ +using HarmonyLib; +using Monitor; + +namespace SinmaiAssist.Common; + +public class ForceQuickRetry +{ + [HarmonyPostfix] + [HarmonyPatch(typeof(QuickRetry), "IsQuickRetryEnable")] + public static void IsQuickRetryEnable(ref bool __result) + { + __result = true; + } +} \ No newline at end of file diff --git a/Common/ForwardATouchRegionToButton.cs b/Common/ForwardATouchRegionToButton.cs new file mode 100644 index 0000000..b0ec1c2 --- /dev/null +++ b/Common/ForwardATouchRegionToButton.cs @@ -0,0 +1,53 @@ +using HarmonyLib; +using Manager; +using Process; +using static Manager.InputManager; + +namespace SinmaiAssist.Common; + +public class ForwardATouchRegionToButton +{ + private static bool IsPlaying = false; + + [HarmonyPostfix] + [HarmonyPatch(typeof(GameProcess),"OnUpdate")] + public static void OnUpdate(GameProcess __instance) + { + NotesManager notesManager = new NotesManager(); + IsPlaying = notesManager.IsPlaying(); + } + + [HarmonyPostfix] + [HarmonyPatch(typeof(Manager.InputManager), "GetButtonDown")] + public static void GetButtonDown(ref bool __result, int monitorId, ButtonSetting button) + { + if (IsPlaying) return; + if (__result) return; + if (button.ToString().StartsWith("Button")) + { + __result = GetTouchPanelAreaDown(monitorId, (TouchPanelArea)button); + } + else if (button.ToString().Equals("Select")) + { + __result = GetTouchPanelAreaLongPush(monitorId, TouchPanelArea.C1, 500L) || GetTouchPanelAreaLongPush(monitorId, TouchPanelArea.C2, 500L); + } + } + + [HarmonyPostfix] + [HarmonyPatch(typeof(Manager.InputManager), "GetButtonPush")] + public static void GetButtonPush(ref bool __result, int monitorId, ButtonSetting button) + { + if (IsPlaying) return; + if (__result) return; + if (button.ToString().StartsWith("Button")) __result = GetTouchPanelAreaPush(monitorId, (TouchPanelArea)button); + } + + [HarmonyPostfix] + [HarmonyPatch(typeof(Manager.InputManager), "GetButtonLongPush")] + public static void GetButtonLongPush(ref bool __result, int monitorId, ButtonSetting button, long msec) + { + if (IsPlaying) return; + if (__result) return; + if (button.ToString().StartsWith("Button")) __result = GetTouchPanelAreaLongPush(monitorId, (TouchPanelArea)button, msec); + } +} \ No newline at end of file diff --git a/Common/Graphic.cs b/Common/Graphic.cs new file mode 100644 index 0000000..ca124e9 --- /dev/null +++ b/Common/Graphic.cs @@ -0,0 +1,36 @@ +using UnityEngine; + +namespace SinmaiAssist.Common; + +public class Graphic +{ + public static void ToggleFullscreen() + { + Screen.fullScreen = !Screen.fullScreen; + } + + public static int GetResolutionWidth() + { + return Screen.width; + } + public static int GetResolutionHeight() + { + return Screen.height; + } + + public static void SetResolution(int width, int height) + { + Screen.SetResolution(width, height, Screen.fullScreen); + } + + public static int GetMaxFrameRate() + { + return Application.targetFrameRate; + } + + public static void SetMaxFrameRate(int fps) + { + Application.targetFrameRate = fps; + QualitySettings.vSyncCount = 0; + } +} \ No newline at end of file diff --git a/Common/IgnoreAnyGameInformation.cs b/Common/IgnoreAnyGameInformation.cs new file mode 100644 index 0000000..fb5a4cd --- /dev/null +++ b/Common/IgnoreAnyGameInformation.cs @@ -0,0 +1,37 @@ +using System; +using System.Reflection; +using HarmonyLib; +using MelonLoader; +using Net.Packet; +using Net.Packet.Mai2; +using Net.VO; +using Net.VO.Mai2; + +namespace SinmaiAssist.Common +{ + public class IgnoreAnyGameInformation + { + [HarmonyPrefix] + [HarmonyPatch(typeof(PacketGetUserData), "SafeNullMember")] + public static bool SafeNullMember(PacketGetUserData __instance, UserDetailResponseVO src) + { + try + { + if (src.userData.eventWatchedDate != null && SinmaiAssist.MainConfig.Common.IgnoreAnyGameInformation) + { + src.userData.eventWatchedDate = "2099-12-31 23:59:59"; + } + else if (src.userData.eventWatchedDate != null && DateTime.Parse(src.userData.eventWatchedDate) > DateTime.Now) + { + src.userData.eventWatchedDate = "2000-01-01 00:00:00"; + } + } + catch (Exception e) + { + MelonLogger.Error($"Failed to patch: {e}"); + MelonLogger.Error(e.StackTrace); + } + return true; + } + } +} \ No newline at end of file diff --git a/Common/InfinityTimer.cs b/Common/InfinityTimer.cs new file mode 100644 index 0000000..d3de04f --- /dev/null +++ b/Common/InfinityTimer.cs @@ -0,0 +1,82 @@ +using HarmonyLib; +using Manager; +using Monitor; +using Process; +using Process.Entry.State; +using Process.ModeSelect; + +namespace SinmaiAssist.Common; + +public class InfinityTimer +{ + // codes from AquaMai [https://github.com/hykilpikonna/AquaDX/blob/v1-dev/AquaMai/UX/ExtendTimer.cs] + [HarmonyPrefix] + [HarmonyPatch(typeof(TimerController), "PrepareTimer")] + public static void PrePrepareTimer(ref int second) + { + second = 65535; + } + + [HarmonyPrefix] + [HarmonyPatch(typeof(CommonTimer), "SetVisible")] + public static void CommonTimerSetVisible(ref bool isVisible) + { + isVisible = false; + } + + [HarmonyPrefix] + [HarmonyPatch(typeof(EntryProcess), "DecrementTimerSecond")] + public static bool EntryProcessDecrementTimerSecond(ContextEntry ____context) + { + SoundManager.PlaySE(Mai2.Mai2Cue.Cue.SE_SYS_SKIP, 0); + ____context.SetState(StateType.DoneEntry); + return false; + } + + [HarmonyPrefix] + [HarmonyPatch(typeof(ModeSelectProcess), "UpdateInput")] + public static bool ModeSelectProcessUpdateInput(ModeSelectProcess __instance) + { + if (!Manager.InputManager.GetButtonDown(0, Manager.InputManager.ButtonSetting.Button05)) return true; + __instance.TimeSkipButtonAnim(Manager.InputManager.ButtonSetting.Button05); + SoundManager.PlaySE(Mai2.Mai2Cue.Cue.SE_SYS_SKIP, 0); + Traverse.Create(__instance).Method("TimeUp").GetValue(); + return false; + } + + [HarmonyPrefix] + [HarmonyPatch(typeof(PhotoEditProcess), "MainMenuUpdate")] + public static void PhotoEditProcess(PhotoEditMonitor[] ____monitors, PhotoEditProcess __instance) + { + if (!Manager.InputManager.GetButtonDown(0, Manager.InputManager.ButtonSetting.Button04)) return; + SoundManager.PlaySE(Mai2.Mai2Cue.Cue.SE_SYS_SKIP, 0); + ____monitors[0].SetButtonPressed(Manager.InputManager.ButtonSetting.Button04); + Traverse.Create(__instance).Method("OnTimeUp").GetValue(); + } + + [HarmonyPrefix] + [HarmonyPatch(typeof(PlInformationMonitor), "IsPlayPlInfoEnd")] + public static bool IWontTapOrSlideVigorously(ref bool __result) + { + __result = true; + return false; + } + + [HarmonyPrefix] + [HarmonyPatch(typeof(GameOverMonitor), "IsPlayEnd")] + public static bool GameOverMonitorPlayEnd(ref bool __result) + { + __result = true; + return false; + } + + [HarmonyPrefix] + [HarmonyPatch(typeof(GameOverProcess), "OnUpdate")] + public static void GameOverProcessOnUpdate(ref GameOverProcess.GameOverSequence ____state) + { + if (____state == GameOverProcess.GameOverSequence.SkyChange) + { + ____state = GameOverProcess.GameOverSequence.Disp; + } + } +} \ No newline at end of file diff --git a/Common/InfinityTimerLegacy.cs b/Common/InfinityTimerLegacy.cs new file mode 100644 index 0000000..791161b --- /dev/null +++ b/Common/InfinityTimerLegacy.cs @@ -0,0 +1,22 @@ +using HarmonyLib; + +namespace SinmaiAssist.Common; + +public class InfinityTimerLegacy +{ + [HarmonyPrefix] + [HarmonyPatch(typeof(TimerController), "UpdateTimer")] + public static bool UpdateTimer(ref float gameMsecAdd) + { + gameMsecAdd = 0; + return true; + } + + [HarmonyPrefix] + [HarmonyPatch(typeof(GenericMonitor), "SetTimerSecond")] + public static bool ForceInfinity(ref bool isInfinity) + { + isInfinity = true; + return true; + } +} \ No newline at end of file diff --git a/Common/InputManager.cs b/Common/InputManager.cs new file mode 100644 index 0000000..e017159 --- /dev/null +++ b/Common/InputManager.cs @@ -0,0 +1,27 @@ +using HarmonyLib; +using System.Reflection; + +namespace SinmaiAssist.Common; + +public class InputManager +{ + public static bool TouchAreaDisplayButton = false; + + [HarmonyPrefix] + [HarmonyPatch(typeof(Manager.InputManager), "UpdateAmInput")] + public static void TouchAreaDisplay() + { + if (TouchAreaDisplayButton) + { + var isMouseTouchPanelVisibleField = typeof(Manager.InputManager).GetField("_isMouseTouchPanelVisible", BindingFlags.NonPublic | BindingFlags.Static); + bool isMouseTouchPanelVisible = !(bool)isMouseTouchPanelVisibleField.GetValue(typeof(Manager.InputManager)); + isMouseTouchPanelVisibleField.SetValue(null, isMouseTouchPanelVisible); + MouseTouchPanel[] mouseTouchPanel = Manager.InputManager.MouseTouchPanel; + for (int i = 0; i < mouseTouchPanel.Length; i++) + { + mouseTouchPanel[i].SetVisible(isMouseTouchPanelVisible); + } + TouchAreaDisplayButton = false; + } + } +} \ No newline at end of file diff --git a/Common/NetworkLogger.cs b/Common/NetworkLogger.cs new file mode 100644 index 0000000..6ae4fc8 --- /dev/null +++ b/Common/NetworkLogger.cs @@ -0,0 +1,102 @@ +using HarmonyLib; +using MAI2.Util; +using Manager; +using MelonLoader; +using Net.Packet; +using Net.VO; +using System; +using System.IO; + +namespace SinmaiAssist.Common; + +public class NetworkLogger +{ + private static readonly object logLock = new object(); + private enum HttpMessageType + { + Request, + Response, + Null + } + private static bool isInsideProcImpl = false; + private static string NowApi = ""; + + [HarmonyPostfix] + [HarmonyPatch(typeof(Packet), "set_State")] + public static void RequestListener(Packet __instance) + { + if (__instance.State == PacketState.Ready) + { + string content = __instance.Query.GetRequest(); + // string baseUrl = (string)AccessTools.Field(typeof(Packet), "BaseUrl").GetValue(__instance); + var baseUrl = Singleton.Instance.GetBaseUri(); + NowApi = baseUrl + __instance.Query.Api; + PrintNetworkLog(HttpMessageType.Request, NowApi, content); + } + } + + [HarmonyPostfix] + [HarmonyPatch(typeof(NetQuery), "SetResponse")] + public static void ResponseListener(ref string str) + { + if (isInsideProcImpl) + { + string ccontent = str; + PrintNetworkLog(HttpMessageType.Response, NowApi, ccontent); + } + } + + /* Not available + [HarmonyPostfix] + [HarmonyPatch(typeof(Encoding), "GetString", new[] { typeof(byte[]) })] + public static void ResponseListener(Packet __instance, ref string __result) + { + if (isInsideProcImpl) + { + string ccontent = __result; + PrintNetworkLog(HttpMessageType.Response, NowApi, ccontent); + } + } + */ + + [HarmonyPrefix] + [HarmonyPatch(typeof(Packet), "ProcImpl")] + public static void ProcImplPrefix() + { + isInsideProcImpl = true; + } + + [HarmonyPostfix] + [HarmonyPatch(typeof(Packet), "ProcImpl")] + public static void ProcImplPostfix() + { + isInsideProcImpl = false; + } + private static void PrintNetworkLog(HttpMessageType httpMessageType, string api, string content) + { + if (httpMessageType == HttpMessageType.Null) return; + try + { + DateTime now = DateTime.Now; + string logText = now.ToString("[HH:mm:ss.fff] "); + logText += $"[{httpMessageType}] [{api}] -> {content}\n"; + + if (SinmaiAssist.MainConfig.Common.NetworkLogger.PrintToConsole) + MelonLogger.Msg($"[NetworkLogger] [{httpMessageType}] [{api}] -> {content}"); + + lock (logLock) + { + string logDir = Path.Combine($"{BuildInfo.Name}/NetworkLogs"); + if (!Directory.Exists(logDir)) + { + Directory.CreateDirectory(logDir); + } + File.AppendAllText(Path.Combine(logDir, now.ToString("yyyy-MM-dd") + ".log"), logText); + } + } + catch (Exception e) + { + MelonLogger.Error(e); + } + } +} \ No newline at end of file diff --git a/Common/PrintUserData.cs b/Common/PrintUserData.cs new file mode 100644 index 0000000..538c822 --- /dev/null +++ b/Common/PrintUserData.cs @@ -0,0 +1,86 @@ +using HarmonyLib; +using MAI2.Util; +using Manager; +using Manager.UserDatas; +using Process; +using System.IO; + + +namespace SinmaiAssist.Common; + +public class PrintUserData +{ + [HarmonyPostfix] + [HarmonyPatch(typeof(MusicSelectProcess), "OnStart")] + public static void Postifx() + { + PrintData(Singleton.Instance.GetUserData(0L).Detail); + PrintData(Singleton.Instance.GetUserData(1L).Detail); + } + + private static void PrintData(UserDetail detail) + { + string userData = string.Empty; + userData += "[General]\n"; + userData = userData + "AccessCode: " + detail.AccessCode + "\n"; + userData = userData + "UserID: " + detail.UserID + "\n"; + userData = userData + "Name: " + detail.UserName + "\n"; + userData = userData + "AuthKey: " + detail.AuthKey + "\n"; + userData = userData + "PlayCount: " + detail.PlayCount + "\n"; + userData = userData + "TotalAwake: " + detail.TotalAwake + "\n"; + userData += "[Rating]\n"; + userData = userData + "Rating: " + detail.Rating + "\n"; + userData = userData + "HighestRating: " + detail.HighestRating + "\n"; + userData = userData + "MusicRating: " + detail.MusicRating + "\n"; + userData = userData + "GradeRating: " + detail.GradeRating + "\n"; + userData = userData + "GradeRank: " + detail.GradeRank + "\n"; + userData += "[Game]\n"; + userData = userData + "TotalAchievement: " + detail.TotalAchievement + "\n"; + userData = userData + "TotalDeluxeScore: " + detail.TotalDeluxscore + "\n"; + userData = userData + "TotalSync: " + detail.TotalSync + "\n"; + userData = userData + "ComboCount: " + detail.ComboCount + "\n"; + userData = userData + "AuthKey: " + detail.AuthKey + "\n"; + userData = userData + "WinCount: " + detail.WinCount + "\n"; + userData = userData + "HelpCount: " + detail.HelpCount + "\n"; + userData = userData + "PlayVsCount: " + detail.PlayVsCount + "\n"; + userData = userData + "PlaySyncCount: " + detail.PlaySyncCount + "\n"; + userData = userData + "EquipIconID: " + detail.EquipIconID + "\n"; + userData = userData + "EquipTitleID: " + detail.EquipTitleID + "\n"; + userData = userData + "EquipPlateID: " + detail.EquipPlateID + "\n"; + userData = userData + "SelectMapID: " + detail.SelectMapID + "\n"; + userData += "[Log]\n"; + userData = userData + "TotalLoginCount: " + detail.TotalLoginCount + "\n"; + userData = userData + "ContinueLoginCount: " + detail.ContinueLoginCount + "\n"; + userData = userData + "LastLoginDate: " + detail.LastLoginDate + "\n"; + userData = userData + "LastPlayDate: " + detail.LastPlayDate + "\n"; + userData = userData + "FirstPlayDate: " + detail.FirstPlayDate + "\n"; + userData = userData + "DailyBounsDate: " + detail.DailyBonusDate + "\n"; + userData = userData + "EventWatchedDate: " + detail.EventWatchedDate + "\n"; + userData += "[System]\n"; + userData = userData + "LastGameID: " + detail.LastGameId + "\n"; + userData = userData + "LastROMVersion: " + detail.LastRomVersion + "\n"; + userData = userData + "LastDataVersion: " + detail.LastDataVersion + "\n"; + userData = userData + "LastRegionID: " + detail.LastRegionId + "\n"; + userData = userData + "LastRegionName: " + detail.LastRegionName + "\n"; + userData = userData + "LastPlaceID: " + detail.LastPlaceId + "\n"; + userData = userData + "LastPlaceName: " + detail.LastPlaceName + "\n"; + userData = userData + "LastAllNetID: " + detail.LastAllNetId + "\n"; + userData = userData + "LastClientID: " + detail.LastClientId + "\n"; + userData = userData + "LastCountryCode: " + detail.LastCountryCode + "\n"; + userData = userData + "FirstGameID: " + detail.FirstGameId + "\n"; + userData = userData + "FirstRomVersion: " + detail.FirstRomVersion + "\n"; + userData = userData + "FirstDataVersion: " + detail.FirstDataVersion + "\n"; + userData = userData + "CompatibleCMVersion: " + detail.CompatibleCmVersion + "\n"; + userData = userData + "IsNetMember: " + detail.IsNetMember + "\n"; + userData += $"Data generated by {BuildInfo.Name}"; + if (!Directory.Exists(Path.Combine($"{BuildInfo.Name}/UserData"))) + { + Directory.CreateDirectory($"{BuildInfo.Name}/UserData"); + } + if (!File.Exists(Path.Combine($"{BuildInfo.Name}/UserData/User" + detail.UserID + ".txt"))) + { + File.Create(Path.Combine($"{BuildInfo.Name}/UserData/User" + detail.UserID + ".txt")).Dispose(); + } + File.WriteAllText(Path.Combine($"{BuildInfo.Name}/UserData/User" + detail.UserID + ".txt"), userData); + } +} \ No newline at end of file diff --git a/Common/QuickBoot.cs b/Common/QuickBoot.cs new file mode 100644 index 0000000..251ba36 --- /dev/null +++ b/Common/QuickBoot.cs @@ -0,0 +1,54 @@ +using HarmonyLib; +using Process; +using System; +using System.Reflection; +using MAI2.Util; +using Manager.Achieve; +using MelonLoader; +using Monitor; +using Util; + +namespace SinmaiAssist.Common; + +public class QuickBoot +{ + [HarmonyPrefix] + [HarmonyPatch(typeof(PowerOnProcess), "OnUpdate")] + public static bool OnPowerOnUpdate(PowerOnProcess __instance) + { + FieldInfo _waitTime = AccessTools.Field(typeof(PowerOnProcess), "_waitTime"); + _waitTime.SetValue(__instance, 0.1f); + FieldInfo _state = AccessTools.Field(typeof(PowerOnProcess), "_state"); + if (Convert.ToInt32(_state.GetValue(__instance)) == 2) + { + _state.SetValue(__instance, Convert.ToByte(3)); + } + return true; + } + + // Research Only + // [HarmonyPrefix] + // [HarmonyPatch(typeof(StartupProcess), "OnUpdate")] + // public static bool OnStartupUpdate(PowerOnProcess __instance) + // { + // FieldInfo _state = AccessTools.Field(typeof(StartupProcess), "_state"); + // if (Convert.ToInt32(_state.GetValue(__instance)) == 3) + // { + // FieldInfo _statusSubMsg = AccessTools.Field(typeof(StartupProcess), "_statusSubMsg"); + // string[] statusSubMsg = (string[])_statusSubMsg.GetValue(__instance); + // + // for (int i = 6; i < statusSubMsg.Length; i++) + // { + // statusSubMsg[i] = "Skip"; + // } + // + // _statusSubMsg.SetValue(__instance, statusSubMsg); + // Singleton.Instance.Configure(); + // Singleton.Instance.Initialize(); + // _state.SetValue(__instance, Convert.ToByte(8)); + // return false; + // } + // return true; + // } + +} \ No newline at end of file diff --git a/Common/ShowFPS.cs b/Common/ShowFPS.cs new file mode 100644 index 0000000..1cfe617 --- /dev/null +++ b/Common/ShowFPS.cs @@ -0,0 +1,28 @@ +using UnityEngine; + +namespace SinmaiAssist.Common; + +public class ShowFPS +{ + private static string fpsText = "FPS: "; + private static float deltaTime = 0.0f; + + public static void OnGUI() + { + Update(); + GUIStyle style = new GUIStyle(); + style.fontSize = 24; + style.normal.textColor = Color.black; + style.alignment = TextAnchor.UpperLeft; + UnityEngine.GUI.Label(new Rect(10 + 2, 10 + 2, 500, 30), fpsText, style); + style.normal.textColor = Color.white; + UnityEngine.GUI.Label(new Rect(10, 10, 500, 30), fpsText, style); + } + + private static void Update() + { + deltaTime += (Time.deltaTime - deltaTime) * 0.1f; + float fps = 1.0f / deltaTime; + fpsText = $"FPS: {Mathf.Ceil(fps)}"; + } +} \ No newline at end of file diff --git a/Common/SinglePlayer.cs b/Common/SinglePlayer.cs new file mode 100644 index 0000000..8645e45 --- /dev/null +++ b/Common/SinglePlayer.cs @@ -0,0 +1,79 @@ +using HarmonyLib; +using Main; +using Manager; +using MelonLoader; +using System; +using System.Reflection; +using UnityEngine; + +namespace SinmaiAssist.Common; + +public class SinglePlayer +{ + [HarmonyPrefix] + [HarmonyPatch(typeof(GameMainObject), "Start")] + public static bool TurnOffRightMonitor(GameMainObject __instance) + { + Camera mainCamera = Camera.main; + + if (mainCamera == null) + { + return false; + } + + var position = mainCamera.gameObject.transform.position; + if (SinmaiAssist.MainConfig.Common.SinglePlayer.HideSubMonitor) + { + mainCamera.gameObject.transform.position = new Vector3(-540f, -420f, position.z); + mainCamera.orthographicSize = 540f; + } + else + { + mainCamera.gameObject.transform.position = new Vector3(-540f, position.y, position.z); + } + var rightMonitorField = typeof(GameMainObject).GetField("rightMonitor", BindingFlags.NonPublic | BindingFlags.Instance); + Transform rightMonitor = (Transform)rightMonitorField.GetValue(__instance); + rightMonitor.transform.localScale = Vector3.zero; + + return false; + } + + [HarmonyPrefix] + [HarmonyPatch(typeof(MeshButton), "Awake")] + public static bool FixDummyTouchPanel(MeshButton __instance) + { + CustomGraphic customGraphic = __instance.targetGraphic as CustomGraphic; + FieldInfo touchAreaField = AccessTools.Field(typeof(MeshButton), "touchArea"); + FieldInfo vertexArrayField = AccessTools.Field(typeof(MeshButton), "vertexArray"); + + touchAreaField.SetValue(__instance, (Manager.InputManager.TouchPanelArea)Enum.Parse(typeof(Manager.InputManager.TouchPanelArea), __instance.name)); + + Vector2[] vertexArray = new Vector2[customGraphic.vertex.Count]; + + for (int i = 0; i < customGraphic.vertex.Count; i++) + { + if (SinmaiAssist.MainConfig.Common.SinglePlayer.HideSubMonitor) + { + vertexArray[i] = RectTransformUtility.WorldToScreenPoint( + Camera.main, + new Vector2( + (__instance.transform.position.x + customGraphic.vertex[i].x + 540f) * Camera.main.orthographicSize / 540f, + (__instance.transform.position.y + customGraphic.vertex[i].y + 420f) * Camera.main.orthographicSize / 540f + ) + ); + } + else + { + vertexArray[i] = RectTransformUtility.WorldToScreenPoint( + Camera.main, + new Vector2( + __instance.transform.position.x + customGraphic.vertex[i].x + 540f, + __instance.transform.position.y + customGraphic.vertex[i].y + ) + ); + } + } + vertexArrayField.SetValue(__instance, vertexArray); + return false; + } +} \ No newline at end of file diff --git a/Common/SkipFade.cs b/Common/SkipFade.cs new file mode 100644 index 0000000..c821616 --- /dev/null +++ b/Common/SkipFade.cs @@ -0,0 +1,22 @@ +using HarmonyLib; + +namespace SinmaiAssist.Common; + +public class SkipFade +{ + [HarmonyPrefix] + [HarmonyPatch(typeof(FadeProcess), "OnStart")] + public static bool OnStart(FadeProcess __instance) + { + __instance.ProcessingProcess(); + return false; + } + + [HarmonyPrefix] + [HarmonyPatch(typeof(FadeProcess), "StartFadeIn")] + public static bool StartFadeIn(FadeProcess __instance) + { + __instance.ProcessingProcess(); + return false; + } +} \ No newline at end of file diff --git a/Common/SkipWarningScreen.cs b/Common/SkipWarningScreen.cs new file mode 100644 index 0000000..65a4192 --- /dev/null +++ b/Common/SkipWarningScreen.cs @@ -0,0 +1,22 @@ +using HarmonyLib; +using Monitor; + +namespace SinmaiAssist.Common; + +public class SkipWarningScreen +{ + [HarmonyPrefix] + [HarmonyPatch(typeof(WarningMonitor), "PlayLogo")] + public static bool PlayLogo() + { + return false; + } + + [HarmonyPrefix] + [HarmonyPatch(typeof(WarningMonitor), "IsLogoAnimationEnd")] + public static bool IsLogoAnimationEnd(ref bool __result) + { + __result = true; + return false; + } +} \ No newline at end of file