diff --git a/MenuDatabaseReplacer/CacheFile.cs b/MenuDatabaseReplacer/CacheFile.cs index f4ca642..e3d8ad2 100644 --- a/MenuDatabaseReplacer/CacheFile.cs +++ b/MenuDatabaseReplacer/CacheFile.cs @@ -1,14 +1,14 @@ -using Newtonsoft.Json; -using Newtonsoft.Json.Converters; -using System; +using System; using System.Collections.Generic; +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; namespace ShortMenuVanillaDatabase { public class CacheFile { public Dictionary CachedLoadedAndDatedArcs { get; set; } - public List MenusList { get; set; } + public List MenusList { get; set; } public CacheFile() { @@ -18,6 +18,15 @@ public CacheFile() public class MenuStub { + public MenuStub() + { + } + + public MenuStub(string fileName) + { + FileName = fileName; + } + public string FileName { get; set; } public string PathInMenu { get; set; } public ulong Hash { get; set; } @@ -30,12 +39,12 @@ public class MenuStub public MPN Category { get; set; } [JsonConverter(typeof(StringEnumConverter))] - public MPN ColorSetMPN { get; set; } + public MPN ColorSetMpn { get; set; } public string ColorSetMenu { get; set; } [JsonConverter(typeof(StringEnumConverter))] - public MaidParts.PARTS_COLOR MultiColorID { get; set; } + public MaidParts.PARTS_COLOR MultiColorId { get; set; } public bool DelMenu { get; set; } public bool ManMenu { get; set; } diff --git a/MenuDatabaseReplacer/JustLogging.cs b/MenuDatabaseReplacer/JustLogging.cs index 232fbd7..a5339f2 100644 --- a/MenuDatabaseReplacer/JustLogging.cs +++ b/MenuDatabaseReplacer/JustLogging.cs @@ -8,28 +8,28 @@ internal class JustLogging [HarmonyPostfix] private static void IsFinished(ref bool __result) { - Main.logger.LogDebug($"A call to check if job was finished was made, returned {__result}"); + Main.PLogger.LogDebug($"A call to check if job was finished was made, returned {__result}"); } [HarmonyPatch(typeof(MenuDataBase), "GetDataSize")] [HarmonyPostfix] private static void GiveDataSize(ref int __result) { - Main.logger.LogDebug($"returning size of {__result}"); + Main.PLogger.LogDebug($"returning size of {__result}"); } [HarmonyPatch(typeof(MenuDataBase), "IsHeaderCheck")] [HarmonyPostfix] private static void header(ref bool __result) { - Main.logger.LogDebug($"returning headercheck of {__result}"); + Main.PLogger.LogDebug($"returning headercheck of {__result}"); } [HarmonyPatch(typeof(MenuDataBase), "GetVersion")] [HarmonyPostfix] private static void getver(ref int __result) { - Main.logger.LogDebug($"returning version of {__result}"); + Main.PLogger.LogDebug($"returning version of {__result}"); } //Unimplemented... @@ -37,14 +37,14 @@ private static void getver(ref int __result) [HarmonyPostfix] private static void givehash(ref ulong __result) { - Main.logger.LogDebug($"returning hash of {__result}"); + Main.PLogger.LogDebug($"returning hash of {__result}"); } [HarmonyPatch(typeof(MenuDataBase), "GetMenuFileName")] [HarmonyPostfix] private static void menufilename(ref string __result) { - Main.logger.LogDebug($"returning menufilename of {__result}"); + Main.PLogger.LogDebug($"returning menufilename of {__result}"); } //Not Implemented... @@ -52,91 +52,91 @@ private static void menufilename(ref string __result) [HarmonyPostfix] private static void parentmenufile(ref string __result) { - Main.logger.LogDebug($"returning parentmenufile of {__result}"); + Main.PLogger.LogDebug($"returning parentmenufile of {__result}"); } [HarmonyPatch(typeof(MenuDataBase), "GetSrcFileName")] [HarmonyPostfix] private static void getsrcfilename(ref string __result) { - Main.logger.LogDebug($"returning srcfilename of {__result}"); + Main.PLogger.LogDebug($"returning srcfilename of {__result}"); } [HarmonyPatch(typeof(MenuDataBase), "GetItemName")] [HarmonyPostfix] private static void getitemanme(ref string __result) { - Main.logger.LogDebug($"returning returning item name of {__result}"); + Main.PLogger.LogDebug($"returning returning item name of {__result}"); } [HarmonyPatch(typeof(MenuDataBase), "GetCategoryName")] [HarmonyPostfix] private static void categoryname(ref string __result) { - Main.logger.LogDebug($"returning category of {__result}"); + Main.PLogger.LogDebug($"returning category of {__result}"); } [HarmonyPatch(typeof(MenuDataBase), "GetInfoText")] [HarmonyPostfix] private static void returninginfotext(ref string __result) { - Main.logger.LogDebug($"returning infotext of {__result}"); + Main.PLogger.LogDebug($"returning infotext of {__result}"); } [HarmonyPatch(typeof(MenuDataBase), "GetMenuName")] [HarmonyPostfix] private static void menuname(ref string __result) { - Main.logger.LogDebug($"returning menuname of {__result}"); + Main.PLogger.LogDebug($"returning menuname of {__result}"); } [HarmonyPatch(typeof(MenuDataBase), "GetItemInfoText")] [HarmonyPostfix] private static void iteminfotext(ref string __result) { - Main.logger.LogDebug($"returning iteminfotext of {__result}"); + Main.PLogger.LogDebug($"returning iteminfotext of {__result}"); } [HarmonyPatch(typeof(MenuDataBase), "GetCategoryMpnText")] [HarmonyPostfix] private static void mpntext(ref string __result) { - Main.logger.LogDebug($"returning mpntext of {__result}"); + Main.PLogger.LogDebug($"returning mpntext of {__result}"); } [HarmonyPatch(typeof(MenuDataBase), "GetCategoryMpn")] [HarmonyPostfix] private static void categorympn(ref int __result) { - Main.logger.LogDebug($"returning category mpn of {__result}"); + Main.PLogger.LogDebug($"returning category mpn of {__result}"); } [HarmonyPatch(typeof(MenuDataBase), "GetColorSetMpn")] [HarmonyPostfix] private static void colorsetmpn(ref int __result) { - Main.logger.LogDebug($"returning colorsetmpn of {__result}"); + Main.PLogger.LogDebug($"returning colorsetmpn of {__result}"); } [HarmonyPatch(typeof(MenuDataBase), "GetMenuNameInColorSet")] [HarmonyPostfix] private static void getmenucolor(ref string __result) { - Main.logger.LogDebug($"returning menu color of {__result}"); + Main.PLogger.LogDebug($"returning menu color of {__result}"); } [HarmonyPatch(typeof(MenuDataBase), "GetMultiColorId")] [HarmonyPostfix] private static void multicolorid(ref int __result) { - Main.logger.LogDebug($"returning multicolorid of {__result}"); + Main.PLogger.LogDebug($"returning multicolorid of {__result}"); } [HarmonyPatch(typeof(MenuDataBase), "GetIconS")] [HarmonyPostfix] private static void geticonstring(ref string __result) { - Main.logger.LogDebug($"returning icon of {__result}"); + Main.PLogger.LogDebug($"returning icon of {__result}"); } //Not Implemented... @@ -144,28 +144,28 @@ private static void geticonstring(ref string __result) [HarmonyPostfix] private static void getsaveitem(ref string __result) { - Main.logger.LogDebug($"returning save item of {__result}"); + Main.PLogger.LogDebug($"returning save item of {__result}"); } [HarmonyPatch(typeof(MenuDataBase), "GetBoDelOnly")] [HarmonyPostfix] private static void bodel(ref bool __result) { - Main.logger.LogDebug($"returning delmenu of {__result}"); + Main.PLogger.LogDebug($"returning delmenu of {__result}"); } [HarmonyPatch(typeof(MenuDataBase), "GetPriority")] [HarmonyPostfix] private static void priority(ref float __result) { - Main.logger.LogDebug($"returning priority of {__result}"); + Main.PLogger.LogDebug($"returning priority of {__result}"); } [HarmonyPatch(typeof(MenuDataBase), "GetIsMan")] [HarmonyPostfix] private static void getisman(ref bool __result) { - Main.logger.LogDebug($"returning is man menu of {__result}"); + Main.PLogger.LogDebug($"returning is man menu of {__result}"); } //Not Implemented... @@ -175,7 +175,7 @@ private static void iscoll(ref bool __result, MenuDataBase __instance) { if (__result == true) { - Main.logger.LogDebug($"returning is collabo of {__result} for {__instance.GetMenuFileName()}"); + Main.PLogger.LogDebug($"returning is collabo of {__result} for {__instance.GetMenuFileName()}"); } } } diff --git a/MenuDatabaseReplacer/Main.cs b/MenuDatabaseReplacer/Main.cs index 961a03c..fda33d3 100644 --- a/MenuDatabaseReplacer/Main.cs +++ b/MenuDatabaseReplacer/Main.cs @@ -3,12 +3,13 @@ using HarmonyLib; using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; using System.Security; using System.Security.Permissions; -//These two lines tell your plugin to not give a flying fuck about accessing private variables/classes whatever. It requires a publicized stubb of the library with those private objects though. +//These two lines tell your plugin to not give a flying fuck about accessing private variables/classes whatever. It requires a publicized stub of the library with those private objects though. [module: UnverifiableCode] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] @@ -16,18 +17,20 @@ namespace ShortMenuVanillaDatabase { //This is the metadata set for your plugin. [BepInPlugin("ShortMenuVanillaDatabase", "ShortMenuVanillaDatabase", "1.2")] + [SuppressMessage("ReSharper", "InconsistentNaming")] + [SuppressMessage("ReSharper", "RedundantAssignment")] public class Main : BaseUnityPlugin { - public static Main @this; + public static Main This; - //Static var for the logger so you can log from other classes. - public static ManualLogSource logger; + //Static var for the PLogger so you can log from other classes. + public static ManualLogSource PLogger; //This is where the magic happens. public static MenuDatabaseReplacement Database; //I'd rather not use an index tbh but whatever, Kiss's implementation is literally retarded. - private static Dictionary IndexToRead = new Dictionary(); + private static readonly Dictionary IndexToRead = new Dictionary(); //Config entry variable. You set your configs to this. //internal static ConfigEntry ExampleConfig; @@ -36,40 +39,41 @@ public class Main : BaseUnityPlugin private void Awake() { - //Useful for engaging coroutines or accessing variables non-static variables. Completely optional though. - @this = this; + //Useful for engaging co-routines or accessing variables non-static variables. Completely optional though. + This = this; - //pushes the logger to a public static var so you can use the bepinex logger from other classes. - logger = Logger; + //pushes the PLogger to a public static var so you can use the bepInEx PLogger from other classes. + PLogger = Logger; //Binds the configuration. In other words it sets your ConfigEntry var to your config setup. //ExampleConfig = Config.Bind("Section", "Name", false, "Description"); //Installs the patches in the Main class. - var Plugs = Directory.GetFiles(BepInEx.Paths.PluginPath, "*", SearchOption.AllDirectories) - .Select(t => Path.GetFileName(t).ToLower()); + var plugs = Directory.GetFiles(Paths.PluginPath, "*", SearchOption.AllDirectories) + .Select(t => Path.GetFileName(t).ToLower()) + .ToArray(); - var HasDependencies = Plugs.Contains("system.threading.dll") && Plugs.Contains("cm3d2.toolkit.guest4168branch.dll"); + var hasDependencies = plugs.Contains("system.threading.dll") && plugs.Contains("cm3d2.toolkit.guest4168branch.dll"); - if (!HasDependencies) + if (!hasDependencies) { - Main.logger.LogFatal("SMVD is missing some dependencies! SMVD will not operate correctly and neither will your game!"); + PLogger.LogFatal("SMVD is missing some dependencies! SMVD will not operate correctly and neither will your game!"); } #if !OnlyCompare harmony = Harmony.CreateAndPatchAll(typeof(Main)); #else - //Harmony.CreateAndPatchAll(typeof(JustLogging)); + Harmony.CreateAndPatchAll(typeof(JustLogging)); #endif } //Basic harmony patch format. You specify the class to be patched and the method within that class to be patched. This patcher prefixes the method, meaning it runs before the patched method does. You can also postfix, run after the method patches and do lots of things like change parameters and results with harmony patching. Very powerful. - [HarmonyPatch(typeof(MenuDataBase), MethodType.Constructor, new Type[] { typeof(IntPtr), typeof(EnumData), typeof(EnumData) })] + [HarmonyPatch(typeof(MenuDataBase), MethodType.Constructor, typeof(IntPtr), typeof(EnumData), typeof(EnumData))] [HarmonyPrefix] private static void BuildingDatabase() { - logger.LogDebug("Created the database..."); + PLogger.LogDebug("Created the database..."); Database = new MenuDatabaseReplacement(); } @@ -91,9 +95,9 @@ private static bool IsFinished(ref bool __result) [HarmonyPrefix] private static bool StartLoad() { - logger.LogInfo("Starting Vanilla Menu Files Analysis..."); + PLogger.LogInfo("Starting Vanilla Menu Files Analysis..."); - @this.StartCoroutine(Database.StartLoading()); + This.StartCoroutine(Database.StartLoading()); #if !OnlyCompare return false; #else @@ -101,7 +105,7 @@ private static bool StartLoad() #endif } - [HarmonyPatch(typeof(MenuDataBase), "Dispose", new Type[] { typeof(bool) })] + [HarmonyPatch(typeof(MenuDataBase), "Dispose", typeof(bool))] [HarmonyPrefix] private static bool DisposeVar(MenuDataBase __instance) { @@ -328,7 +332,7 @@ private static bool GetCategoryMpn(ref int __result, ref MenuDataBase __instance private static bool GetColorSetMpn(ref int __result, ref MenuDataBase __instance) { #if !OnlyCompare - __result = (int)Database.MenusList[IndexToRead[__instance]].ColorSetMPN; + __result = (int)Database.MenusList[IndexToRead[__instance]].ColorSetMpn; return false; #else @@ -354,7 +358,7 @@ private static bool GetMenuNameInColorSet(ref string __result, ref MenuDataBase private static bool GetMultiColorId(ref int __result, ref MenuDataBase __instance) { #if !OnlyCompare - __result = (int)Database.MenusList[IndexToRead[__instance]].MultiColorID; + __result = (int)Database.MenusList[IndexToRead[__instance]].MultiColorId; return false; #else diff --git a/MenuDatabaseReplacer/MenuDatabaseReplacement.cs b/MenuDatabaseReplacer/MenuDatabaseReplacement.cs index c5241d1..7d9cfef 100644 --- a/MenuDatabaseReplacer/MenuDatabaseReplacement.cs +++ b/MenuDatabaseReplacer/MenuDatabaseReplacement.cs @@ -1,6 +1,4 @@ -using CM3D2.Toolkit.Guest4168Branch.MultiArcLoader; -using Newtonsoft.Json; -using System; +using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; @@ -9,6 +7,11 @@ using System.Text; using System.Threading; using System.Threading.Tasks; +using BepInEx; +using CM3D2.Toolkit.Guest4168Branch.Arc.Entry; +using CM3D2.Toolkit.Guest4168Branch.Logging; +using CM3D2.Toolkit.Guest4168Branch.MultiArcLoader; +using Newtonsoft.Json; namespace ShortMenuVanillaDatabase { @@ -18,14 +21,43 @@ public class MenuDatabaseReplacement public bool Done { get; private set; } - private ArcCompare Compare = new ArcCompare(); + private readonly ArcCompare _compare = new ArcCompare(); - /* - public MenuDatabaseReplacement() + private class LogToolkit : ILogger { - //MenusList = new List(); + public string Name => throw new NotImplementedException(); + + public void Debug(string message, params object[] args) + { + //Main.PLogger.LogDebug(message); + } + + public void Error(string message, params object[] args) + { + //Main.PLogger.LogError(message); + } + + public void Fatal(string message, params object[] args) + { + //Main.PLogger.LogFatal(message); + } + + public void Info(string message, params object[] args) + { + //Main.PLogger.LogInfo(message); + } + + public void Trace(string message, params object[] args) + { + //Main.PLogger.LogError(message); + } + + public void Warn(string message, params object[] args) + { + //Main.PLogger.LogWarning(message); + } } - */ + public IEnumerator StartLoading() { @@ -34,143 +66,155 @@ public IEnumerator StartLoading() yield break; } - Stopwatch stopwatch = new Stopwatch(); + var stopwatch = new Stopwatch(); stopwatch.Start(); - HashSet tempList = new HashSet(); + var tempList = new HashSet(); - var cachePath = BepInEx.Paths.CachePath + "\\ShortMenuVanillaDatabase.json"; - CacheFile cachedFile = null; - Dictionary CurrentlyLoadedAndDatedArcs = new Dictionary(); + var cachePath = Paths.CachePath + "\\ShortMenuVanillaDatabase.json"; + CacheFile cachedFile; + var currentlyLoadedAndDatedArcs = new Dictionary(); //Cancel token is setup in case I need it in the future but the error handling we currently have should be more than enough. var cts = new CancellationTokenSource(); - Task LoaderTask = Task.Factory.StartNew(new Action(() => + var loaderTask = Task.Factory.StartNew(() => { //The following simply decides what is to be loaded. - List PathsToLoad = new List() - { - $"{BepInEx.Paths.GameRootPath}\\GameData" - }; - if (!String.IsNullOrEmpty(GameMain.Instance.CMSystem.CM3D2Path)) + var pathsToLoad = new List + { + $"{Paths.GameRootPath}\\GameData" + }; + if (!string.IsNullOrEmpty(GameMain.Instance.CMSystem.CM3D2Path)) { - PathsToLoad.Add(GameMain.Instance.CMSystem.CM3D2Path + "\\GameData"); + pathsToLoad.Add(GameMain.Instance.CMSystem.CM3D2Path + "\\GameData"); } - if (Directory.Exists($"{BepInEx.Paths.GameRootPath}\\GameData_20")) + if (Directory.Exists($"{Paths.GameRootPath}\\GameData_20")) { - PathsToLoad.Add($"{BepInEx.Paths.GameRootPath}\\GameData_20"); + pathsToLoad.Add($"{Paths.GameRootPath}\\GameData_20"); } //This loop handles the listing of arcs within the above directories. - foreach (string s in PathsToLoad) + foreach (var s in pathsToLoad) { //Gets all arc files in the directories that match our filters.. - var ArcFilesLoaded = Directory.GetFiles(s) - .Where(t => - ( - Path.GetFileName(t).StartsWith("menu", StringComparison.OrdinalIgnoreCase) - || Path.GetFileName(t).StartsWith("parts", StringComparison.OrdinalIgnoreCase) + var arcFilesLoaded = Directory.GetFiles(s) + .Where(t => + ( + Path.GetFileName(t).StartsWith("menu", StringComparison.OrdinalIgnoreCase) + || Path.GetFileName(t).StartsWith("parts", StringComparison.OrdinalIgnoreCase) + ) + && t.EndsWith(".arc", StringComparison.OrdinalIgnoreCase) ) - && t.EndsWith(".arc", StringComparison.OrdinalIgnoreCase) - ) - .ToList(); + .ToArray(); //Gets the write time for each arc file to track any modifications. - foreach (string arc in ArcFilesLoaded) + foreach (var arc in arcFilesLoaded) { - CurrentlyLoadedAndDatedArcs[arc] = File.GetLastWriteTimeUtc(arc); + currentlyLoadedAndDatedArcs[arc] = File.GetLastWriteTimeUtc(arc); } } - Main.logger.LogDebug($"We found {CurrentlyLoadedAndDatedArcs.Count} that fit our specifications @ {stopwatch.Elapsed}"); + Main.PLogger.LogDebug($"We found {currentlyLoadedAndDatedArcs.Count} that fit our specifications @ {stopwatch.Elapsed}"); + + //PLogger for logging. + var logger = new LogToolkit(); //Loads all our arc files that we've observed are currently available. - MultiArcLoader arcFileExplorer = new MultiArcLoader(CurrentlyLoadedAndDatedArcs.Keys.ToArray(), Environment.ProcessorCount, MultiArcLoader.LoadMethod.Single, true, true, MultiArcLoader.Exclude.Voice | MultiArcLoader.Exclude.BG | MultiArcLoader.Exclude.CSV | MultiArcLoader.Exclude.Motion | MultiArcLoader.Exclude.Sound); + var arcFileExplorer = new MultiArcLoader(currentlyLoadedAndDatedArcs.Keys.ToArray(), Environment.ProcessorCount, MultiArcLoader.LoadMethod.Single, true, true, MultiArcLoader.Exclude.Voice | MultiArcLoader.Exclude.BG | MultiArcLoader.Exclude.CSV | MultiArcLoader.Exclude.Motion | MultiArcLoader.Exclude.Sound, logger); //Loads our cache file. if (File.Exists(cachePath)) { try { - string mconfig = (File.ReadAllText(cachePath)); - cachedFile = JsonConvert.DeserializeObject(mconfig); + var mConfig = (File.ReadAllText(cachePath)); + cachedFile = JsonConvert.DeserializeObject(mConfig) ?? new CacheFile(); + + Main.PLogger.LogDebug($"Cache loaded @ {stopwatch.Elapsed}" + + $"\nIt contains {cachedFile.MenusList.Count} entries." + + $"\nWe extrapolated {cachedFile.CachedLoadedAndDatedArcs.Count} arcs were loaded from cache..."); } catch (Exception e) { - Main.logger.LogError("Ran into a catastrophic error while trying to read the MenuDatabaseCache. We will attempt to delete the cache and rebuild it..."); - Main.logger.LogError($"{e.Message}\n\n{e.StackTrace}"); + Main.PLogger.LogError("Ran into a catastrophic error while trying to read the MenuDatabaseCache. We will attempt to delete the cache and rebuild it..."); + Main.PLogger.LogError($"{e.Message}\n\n{e.StackTrace}"); File.Delete(cachePath); cachedFile = null; - throw e; + throw; } - Main.logger.LogDebug($"Cache loaded @ {stopwatch.Elapsed}" - + $"\nIt contains {cachedFile.MenusList.Count()} entries." - + $"\nWe extrapolated {cachedFile.CachedLoadedAndDatedArcs.Count} arcs were loaded from cache..."); - - List ArcsToReload = new List(); + var arcsToReload = new List(); //These are what's currently loaded in this run and compares it to what's not been loaded or what menu files have been loaded from - var ArcsToCheck = CurrentlyLoadedAndDatedArcs - .Keys - .Where(k => cachedFile.MenusList.Select(m => m.SourceArc).Contains(k) || !cachedFile.CachedLoadedAndDatedArcs.ContainsKey(k)); + var arcsToCheck = currentlyLoadedAndDatedArcs + .Keys + .Where(k => cachedFile.MenusList.Select(m => m.SourceArc).Contains(k) || !cachedFile.CachedLoadedAndDatedArcs.ContainsKey(k)); //This checks each currently loaded arc against what's been loaded in previous runs and checks to see if anything has changed. - foreach (string Arc in ArcsToCheck) + foreach (var arc in arcsToCheck) { //Has this arc not been cached? Has this arc been modified? - if (!cachedFile.CachedLoadedAndDatedArcs.ContainsKey(Arc) || CurrentlyLoadedAndDatedArcs[Arc] != cachedFile.CachedLoadedAndDatedArcs[Arc]) + if (cachedFile.CachedLoadedAndDatedArcs.ContainsKey(arc) && currentlyLoadedAndDatedArcs[arc] == cachedFile.CachedLoadedAndDatedArcs[arc]) { - //Was arc modified? - if (cachedFile.CachedLoadedAndDatedArcs.ContainsKey(Arc) && CurrentlyLoadedAndDatedArcs.ContainsKey(Arc)) - { - //Arc modified! - Main.logger.LogDebug($"{Arc} was modified and requires reloading! Entries from this arc will be removed and remade!\nTime In Cache:{cachedFile.CachedLoadedAndDatedArcs[Arc]}\nTime In Folder{CurrentlyLoadedAndDatedArcs[Arc]}"); - } - - //Regardless of modified or new, it needs to be re/loaded and re/cached. - ArcsToReload.Add(Arc); + continue; + } - //If it was modified, it will just remove any menu cached from it, allowing for a clean recache. - cachedFile.MenusList.RemoveAll(menu => menu.SourceArc.Equals(Arc, StringComparison.OrdinalIgnoreCase)); + //Was arc modified? + if (cachedFile.CachedLoadedAndDatedArcs.ContainsKey(arc) && currentlyLoadedAndDatedArcs.ContainsKey(arc)) + { + //Arc modified! + Main.PLogger.LogDebug($"{arc} was modified and requires reloading! Entries from this arc will be removed and remade!\nTime In Cache:{cachedFile.CachedLoadedAndDatedArcs[arc]}\nTime In Folder{currentlyLoadedAndDatedArcs[arc]}"); } + + //Regardless of modified or new, it needs to be re/loaded and re/cached. + arcsToReload.Add(arc); + + //If it was modified, it will just remove any menu cached from it, allowing for a clean recache. + cachedFile.MenusList.RemoveAll(menu => menu.SourceArc.Equals(arc, StringComparison.OrdinalIgnoreCase)); } //This loop checks if the arcs in cache are still valid and cleans the cache if not. foreach (var arc in cachedFile.CachedLoadedAndDatedArcs.ToList()) { //Is the cached arc not part of the current paths? - if ((!arc.Key.Contains(BepInEx.Paths.GameRootPath) && !arc.Key.Contains(GameMain.Instance.CMSystem.CM3D2Path)) || !File.Exists(arc.Key)) + if ((arc.Key.Contains(Paths.GameRootPath) || arc.Key.Contains(GameMain.Instance.CMSystem.CM3D2Path)) && File.Exists(arc.Key)) { - //Remove the arc from our cached list. - cachedFile.CachedLoadedAndDatedArcs.Remove(arc.Key); - //Remove all menus loaded from this arc. - cachedFile.MenusList.RemoveAll(menu => menu.SourceArc.Equals(arc.Key, StringComparison.OrdinalIgnoreCase)); + continue; } + + //Remove the arc from our cached list. + cachedFile.CachedLoadedAndDatedArcs.Remove(arc.Key); + //Remove all menus loaded from this arc. + cachedFile.MenusList.RemoveAll(menu => menu.SourceArc.Equals(arc.Key, StringComparison.OrdinalIgnoreCase)); } - Main.logger.LogDebug($"Done cleaning cache and amending @ {stopwatch.Elapsed}..."); + Main.PLogger.LogDebug($"Done cleaning cache and amending @ {stopwatch.Elapsed}..."); foreach (var menu in cachedFile.MenusList) { tempList.Add(menu); } - if (ArcsToReload.Count > 0) + if (arcsToReload.Count > 0) { - arcFileExplorer = new MultiArcLoader(ArcsToReload.ToArray(), Environment.ProcessorCount, MultiArcLoader.LoadMethod.Single, true, true, MultiArcLoader.Exclude.Voice | MultiArcLoader.Exclude.BG | MultiArcLoader.Exclude.CSV | MultiArcLoader.Exclude.Motion | MultiArcLoader.Exclude.Sound); + + Main.PLogger.LogDebug("Building Arc Loader."); + + arcFileExplorer = new MultiArcLoader(arcsToReload.ToArray(), Environment.ProcessorCount, MultiArcLoader.LoadMethod.Single, true, true, MultiArcLoader.Exclude.Voice | MultiArcLoader.Exclude.BG | MultiArcLoader.Exclude.CSV | MultiArcLoader.Exclude.Motion | MultiArcLoader.Exclude.Sound, logger); + + Main.PLogger.LogDebug("Loading Arcs..."); arcFileExplorer.LoadArcs(); - Main.logger.LogDebug($"Done, loading refreshed files..."); + Main.PLogger.LogDebug("Done, loading refreshed files..."); } else { arcFileExplorer = null; - Main.logger.LogDebug($"No arc files needed updating..."); + Main.PLogger.LogDebug("No arc files needed updating..."); } } else//No cache file is found. Load all. @@ -180,42 +224,48 @@ public IEnumerator StartLoading() if (arcFileExplorer != null && arcFileExplorer.arc.Files.Count > 0) { - Main.logger.LogInfo($"Arcs read @ {stopwatch.Elapsed}"); + Main.PLogger.LogInfo($"Arcs read @ {stopwatch.Elapsed}"); - var filesInArc = new HashSet(arcFileExplorer.arc.Files.Values.Where(val => val.Name.ToLower().EndsWith(".menu") && !val.Name.ToLower().Contains("_mekure_") && !val.Name.ToLower().Contains("_zurashi_"))); + var filesInArc = new HashSet(arcFileExplorer.arc.Files.Values.Where(val => + val.Name.ToLower() + .EndsWith(".menu") && + !val.Name.ToLower() + .Contains("_mekure_") && + !val.Name.ToLower() + .Contains("_zurashi_"))); - foreach (CM3D2.Toolkit.Guest4168Branch.Arc.Entry.ArcFileEntry fileInArc in filesInArc.OrderBy(f => arcFileExplorer.GetContentsArcFilePath(f))) + foreach (var fileInArc in filesInArc.OrderBy(f => arcFileExplorer.GetContentsArcFilePath(f))) { var arcFile = arcFileExplorer.GetContentsArcFilePath(fileInArc); var data = fileInArc.Pointer.Decompress(); if (!ReadInternalMenuFile(fileInArc.Name, arcFile, data.Data, ref tempList)) { - Main.logger.LogError($"Failed to load {fileInArc.Name} from {arcFile}."); + Main.PLogger.LogError($"Failed to load {fileInArc.Name} from {arcFile}."); } } - Main.logger.LogInfo($"Processed all menus @ {stopwatch.Elapsed}"); + Main.PLogger.LogInfo($"Processed all menus @ {stopwatch.Elapsed}"); } //Completely done. - Main.logger.LogInfo($"SMVD thread is done @ {stopwatch.Elapsed}"); + Main.PLogger.LogInfo($"SMVD thread is done @ {stopwatch.Elapsed}"); stopwatch = null; arcFileExplorer = null; - }), cts.Token); + }, cts.Token); - while (!LoaderTask.IsCompleted) + while (!loaderTask.IsCompleted) { yield return null; } - if (LoaderTask.IsFaulted) + if (loaderTask.IsFaulted) { - Main.logger.LogError(LoaderTask.Exception + "\n\nGonna try running the method again..."); + Main.PLogger.LogError(loaderTask.Exception?.InnerException + "\n\nGonna try running the method again..."); - Main.@this.StartCoroutine(StartLoading()); + Main.This.StartCoroutine(StartLoading()); yield break; } @@ -223,62 +273,48 @@ public IEnumerator StartLoading() MenusList = tempList.ToArray(); Done = true; - LoaderTask.Dispose(); + loaderTask.Dispose(); - CacheFile cache = new CacheFile() + var cache = new CacheFile { MenusList = tempList.ToList(), - CachedLoadedAndDatedArcs = CurrentlyLoadedAndDatedArcs + CachedLoadedAndDatedArcs = currentlyLoadedAndDatedArcs }; File.WriteAllText(cachePath, JsonConvert.SerializeObject(cache, Formatting.Indented)); } - private bool ReadInternalMenuFile(string f_strMenuFileName, string sourceArc, byte[] data, ref HashSet currentCollection) + private bool ReadInternalMenuFile(string fStrMenuFileName, string sourceArc, byte[] data, ref HashSet currentCollection) { - MemoryStream DataStream; + MemoryStream dataStream; try { - DataStream = new MemoryStream(data); + dataStream = new MemoryStream(data); } catch (Exception ex) { - Main.logger.LogError(string.Concat(new string[] - { - "The following menu file could not be read! (メニューファイルがが読み込めませんでした。): ", - f_strMenuFileName, - "\n\n", - ex.Message, - "\n", - ex.StackTrace - })); + Main.PLogger.LogError(string.Concat("The following menu file could not be read! (メニューファイルがが読み込めませんでした。): ", fStrMenuFileName, "\n\n", ex.Message, "\n", ex.StackTrace)); return false; } - string text6 = string.Empty; - string text7 = string.Empty; - string path = ""; - - CacheFile.MenuStub cacheEntry = new CacheFile.MenuStub(); - - cacheEntry.FileName = f_strMenuFileName; + var cacheEntry = new CacheFile.MenuStub(fStrMenuFileName); try { - BinaryReader binaryReader = new BinaryReader(DataStream, Encoding.UTF8); - string text = binaryReader.ReadString(); + var binaryReader = new BinaryReader(dataStream, Encoding.UTF8); + var text = binaryReader.ReadString(); if (!text.Equals("CM3D2_MENU")) { - Main.logger.LogError("ProcScriptBin (例外 : ヘッダーファイルが不正です。) The header indicates a file type that is not a menu file!" + text + " @ " + f_strMenuFileName); + Main.PLogger.LogError("ProcScriptBin (例外 : ヘッダーファイルが不正です。) The header indicates a file type that is not a menu file!" + text + " @ " + fStrMenuFileName); return false; } cacheEntry.Version = binaryReader.ReadInt32(); - path = binaryReader.ReadString(); + var path = binaryReader.ReadString(); cacheEntry.SourceArc = sourceArc; cacheEntry.PathInMenu = path; @@ -291,28 +327,26 @@ private bool ReadInternalMenuFile(string f_strMenuFileName, string sourceArc, by while (true) { int num4 = binaryReader.ReadByte(); - text7 = text6; - text6 = string.Empty; + var text6 = string.Empty; if (num4 == 0) { break; } - for (int i = 0; i < num4; i++) + for (var i = 0; i < num4; i++) { text6 = text6 + "\"" + binaryReader.ReadString() + "\" "; } - if (!(text6 == string.Empty)) + if (text6 != string.Empty) { - string stringCom = UTY.GetStringCom(text6); - string[] stringList = UTY.GetStringList(text6); - if (stringCom.Equals("name")) + var stringCom = UTY.GetStringCom(text6); + var stringList = UTY.GetStringList(text6); + switch (stringCom) { - if (stringList.Length > 1) + case "name" when stringList.Length > 1: { - string text8 = stringList[1]; - string text9 = string.Empty; - string arg = string.Empty; - int j = 0; + var text8 = stringList[1]; + var text9 = string.Empty; + var j = 0; while (j < text8.Length && text8[j] != '\u3000' && text8[j] != ' ') { text9 += text8[j]; @@ -320,63 +354,51 @@ private bool ReadInternalMenuFile(string f_strMenuFileName, string sourceArc, by } while (j < text8.Length) { - arg += text8[j]; j++; } cacheEntry.Name = text9; + break; } - else - { - Main.logger.LogWarning("Menu file has no name and an empty name will be used instead." + " @ " + f_strMenuFileName); + case "name": + Main.PLogger.LogWarning("Menu file has no name and an empty name will be used instead." + " @ " + fStrMenuFileName); cacheEntry.Name = ""; - } - } - else if (stringCom.Equals("setumei")) - { - if (stringList.Length > 1) - { + break; + case "setumei" when stringList.Length > 1: cacheEntry.Description = stringList[1]; cacheEntry.Description = cacheEntry.Description.Replace("《改行》", "\n"); - } - else - { - Main.logger.LogWarning("Menu file has no description (setumei) and an empty description will be used instead." + " @ " + f_strMenuFileName); + break; + case "setumei": + Main.PLogger.LogWarning("Menu file has no description (setumei) and an empty description will be used instead." + " @ " + fStrMenuFileName); cacheEntry.Description = ""; - } - } - else if (stringCom.Equals("category")) - { - if (stringList.Length > 1) + break; + case "category" when stringList.Length > 1: { - string strCateName = stringList[1].ToLower(); + var strCatName = stringList[1].ToLower(); try { - cacheEntry.Category = (MPN)Enum.Parse(typeof(MPN), strCateName); + cacheEntry.Category = (MPN)Enum.Parse(typeof(MPN), strCatName); } catch { cacheEntry.Category = MPN.null_mpn; } + + break; } - else - { - Main.logger.LogWarning("The following menu file has a category parent with no category: " + f_strMenuFileName); + case "category": + Main.PLogger.LogWarning("The following menu file has a category parent with no category: " + fStrMenuFileName); return false; - } - } - else if (stringCom.Equals("color_set")) - { - if (stringList.Length > 1) + case "color_set" when stringList.Length > 1: { try { - cacheEntry.ColorSetMPN = (MPN)Enum.Parse(typeof(MPN), stringList[1].ToLower()); + cacheEntry.ColorSetMpn = (MPN)Enum.Parse(typeof(MPN), stringList[1].ToLower()); } catch { - Main.logger.LogWarning("There is no category called(カテゴリがありません。): " + stringList[1].ToLower() + " @ " + f_strMenuFileName); + Main.PLogger.LogWarning("There is no category called(カテゴリがありません。): " + stringList[1].ToLower() + " @ " + fStrMenuFileName); return false; } @@ -384,111 +406,109 @@ private bool ReadInternalMenuFile(string f_strMenuFileName, string sourceArc, by { cacheEntry.ColorSetMenu = stringList[2].ToLower(); } + + break; } - else + case "color_set": + Main.PLogger.LogWarning("A color_set entry exists but is otherwise empty" + " @ " + fStrMenuFileName); + break; + case "tex": + case "テクスチャ変更": { - Main.logger.LogWarning("A color_set entry exists but is otherwise empty" + " @ " + f_strMenuFileName); + if (stringList.Length == 6) + { + var text10 = stringList[5]; + MaidParts.PARTS_COLOR pcMultiColorId; + try + { + pcMultiColorId = (MaidParts.PARTS_COLOR)Enum.Parse(typeof(MaidParts.PARTS_COLOR), text10.ToUpper()); + } + catch + { + Main.PLogger.LogError("無限色IDがありません。(The following free color ID does not exist: )" + text10 + " @ " + fStrMenuFileName); + + return false; + } + cacheEntry.MultiColorId = pcMultiColorId; + } + + break; } - } - else if (stringCom.Equals("tex") || stringCom.Equals("テクスチャ変更")) - { - MaidParts.PARTS_COLOR pcMultiColorID = MaidParts.PARTS_COLOR.NONE; - if (stringList.Length == 6) + case "icon": + case "icons": { - string text10 = stringList[5]; - try + if (stringList.Length > 1) { - pcMultiColorID = (MaidParts.PARTS_COLOR)Enum.Parse(typeof(MaidParts.PARTS_COLOR), text10.ToUpper()); + cacheEntry.Icon = stringList[1]; } - catch + else { - Main.logger.LogError("無限色IDがありません。(The following free color ID does not exist: )" + text10 + " @ " + f_strMenuFileName); + Main.PLogger.LogError("The following menu file has an icon entry but no field set: " + fStrMenuFileName); return false; } - cacheEntry.MultiColorID = pcMultiColorID; - } - } - else if (stringCom.Equals("icon") || stringCom.Equals("icons")) - { - if (stringList.Length > 1) - { - cacheEntry.Icon = stringList[1]; - } - else - { - Main.logger.LogError("The following menu file has an icon entry but no field set: " + f_strMenuFileName); - return false; + break; } - } - else if (stringCom.Equals("saveitem")) - { - if (stringList.Length > 1) + case "saveitem" when stringList.Length > 1: { - string text11 = stringList[1]; - if (String.IsNullOrEmpty(text11)) + var text11 = stringList[1]; + if (string.IsNullOrEmpty(text11)) { - Main.logger.LogWarning("SaveItem is either null or empty." + " @ " + f_strMenuFileName); + Main.PLogger.LogWarning("SaveItem is either null or empty." + " @ " + fStrMenuFileName); } + + break; } - else - { - Main.logger.LogWarning("A saveitem entry exists with nothing set in the field @ " + f_strMenuFileName); - } - } - else if (stringCom.Equals("unsetitem")) - { - cacheEntry.DelMenu = true; - } - else if (stringCom.Equals("priority")) - { - if (stringList.Length > 1) - { + case "saveitem": + Main.PLogger.LogWarning("A saveitem entry exists with nothing set in the field @ " + fStrMenuFileName); + break; + case "unsetitem": + cacheEntry.DelMenu = true; + break; + case "priority" when stringList.Length > 1: cacheEntry.Priority = float.Parse(stringList[1]); - } - else - { - Main.logger.LogError("The following menu file has a priority entry but no field set. A default value of 10000 will be used: " + f_strMenuFileName); + break; + case "priority": + Main.PLogger.LogError("The following menu file has a priority entry but no field set. A default value of 10000 will be used: " + fStrMenuFileName); cacheEntry.Priority = 10000f; - } - } - else if (stringCom.Equals("メニューフォルダ")) - { - if (stringList.Length > 1) + break; + case "メニューフォルダ" when stringList.Length > 1: { if (stringList[1].ToLower().Equals("man")) { cacheEntry.ManMenu = true; } + + break; } - else - { - Main.logger.LogError("A menu with a menu folder setting (メニューフォルダ) has an entry but no field set: " + f_strMenuFileName); + case "メニューフォルダ": + Main.PLogger.LogError("A menu with a menu folder setting (メニューフォルダ) has an entry but no field set: " + fStrMenuFileName); return false; - } } } } - var currEnumerable = currentCollection.ToArray(); + var curEnumerable = currentCollection.ToArray(); - int leftoverCount = 0; + var leftoverCount = 0; - foreach (var currElement in currEnumerable) + foreach (var curElement in curEnumerable) { - if (String.Equals(currElement.FileName, cacheEntry.FileName, StringComparison.OrdinalIgnoreCase)) + if (!string.Equals(curElement.FileName, cacheEntry.FileName, StringComparison.OrdinalIgnoreCase)) { - if (Compare.Compare(sourceArc, currElement.SourceArc) != -1) - { - currentCollection.Remove(currElement); - } - else - { - leftoverCount++; - } + continue; + } + + if (_compare.Compare(sourceArc, curElement.SourceArc) != -1) + { + currentCollection.Remove(curElement); + } + else + { + leftoverCount++; } } @@ -499,7 +519,7 @@ private bool ReadInternalMenuFile(string f_strMenuFileName, string sourceArc, by } catch { - Main.logger.LogError("Encountered some error while reading a vanilla menu file..."); + Main.PLogger.LogError("Encountered some error while reading a vanilla menu file..."); return false; } @@ -511,43 +531,46 @@ public class ArcCompare : IComparer { public int Compare(string path1, string path2) { - if (path1.Contains(BepInEx.Paths.GameRootPath + "\\GameData\\") ^ path2.Contains(BepInEx.Paths.GameRootPath + "\\GameData\\")) + if (path1 is null) { - if (path1.Contains(BepInEx.Paths.GameRootPath + "\\GameData\\")) + throw new ArgumentNullException(nameof(path1)); + } + if (path2 is null) + { + throw new ArgumentNullException(nameof(path2)); + } + + if (path1.Contains(Paths.GameRootPath + "\\GameData\\") ^ path2.Contains(Paths.GameRootPath + "\\GameData\\")) + { + if (path1.Contains(Paths.GameRootPath + "\\GameData\\")) { return 1; } - else - { - return -1; - } + + return -1; } - else if (path1.Contains(BepInEx.Paths.GameRootPath + "\\GameData_20\\") ^ path2.Contains(BepInEx.Paths.GameRootPath + "\\GameData_20\\")) + + if (path1.Contains(Paths.GameRootPath + "\\GameData_20\\") ^ path2.Contains(Paths.GameRootPath + "\\GameData_20\\")) { - if (path1.Contains(BepInEx.Paths.GameRootPath + "\\GameData_20\\")) + if (path1.Contains(Paths.GameRootPath + "\\GameData_20\\")) { return 1; } - else - { - return -1; - } + + return -1; } - else if (path1.Contains(GameMain.Instance.CMSystem.CM3D2Path + "\\GameData\\") ^ path2.Contains(GameMain.Instance.CMSystem.CM3D2Path + "\\GameData\\")) + + if (path1.Contains(GameMain.Instance.CMSystem.CM3D2Path + "\\GameData\\") ^ path2.Contains(GameMain.Instance.CMSystem.CM3D2Path + "\\GameData\\")) { if (path1.Contains(GameMain.Instance.CMSystem.CM3D2Path + "\\GameData\\")) { return 1; } - else - { - return -1; - } - } - else - { - return String.Compare(path1, path2); + + return -1; } + + return string.CompareOrdinal(path1, path2); } } }