// ReSharper disable CheckNamespace // ReSharper disable InconsistentNaming using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; using System.Xml.Serialization; namespace Manager; public class patch_DataManager : DataManager { private const string _cacheDirectory = "dataCache"; [Serializable] [XmlType(TypeName="KeyValuePair")] public class SerializableKeyValuePair { public TK Key; public TV Value; } private static Dictionary LoadCacheFile(string fileName) { if (!File.Exists(fileName)) { return new Dictionary(); } using var fs = File.OpenRead(fileName); var serializer = new XmlSerializer(typeof(List>)); var entries = (List>)serializer.Deserialize(fs); return entries.ToDictionary(e => e.Key, e => e.Value); } private static void SaveCacheFile(string destination, Dictionary collection) { if (collection == null) { return; } using var fs = File.Open(destination, FileMode.Create); var serializer = new XmlSerializer(typeof(List>)); serializer.Serialize( fs, collection .Select(kvp => new SerializableKeyValuePair { Key = kvp.Key, Value = kvp.Value }) .ToList()); } private static void SaveCache() { if (!Directory.Exists(_cacheDirectory)) { Directory.CreateDirectory(_cacheDirectory); } SaveCacheFile(Path.Combine(_cacheDirectory, "RomConfigs.xml"), Cache.RomConfigs); SaveCacheFile(Path.Combine(_cacheDirectory, "DataConfigs.xml"), Cache.DataConfigs); SaveCacheFile(Path.Combine(_cacheDirectory, "Charas.xml"), Cache.Charas); SaveCacheFile(Path.Combine(_cacheDirectory, "CharaAwakes.xml"), Cache.CharaAwakes); SaveCacheFile(Path.Combine(_cacheDirectory, "CharaGenres.xml"), Cache.CharaGenres); SaveCacheFile(Path.Combine(_cacheDirectory, "Events.xml"), Cache.Events); SaveCacheFile(Path.Combine(_cacheDirectory, "Musics.xml"), Cache.Musics); SaveCacheFile(Path.Combine(_cacheDirectory, "MusicGenres.xml"), Cache.MusicGenres); SaveCacheFile(Path.Combine(_cacheDirectory, "MusicGroups.xml"), Cache.MusicGroups); SaveCacheFile(Path.Combine(_cacheDirectory, "MusicVersions.xml"), Cache.MusicVersions); SaveCacheFile(Path.Combine(_cacheDirectory, "MusicNameSorts.xml"), Cache.MusicNameSorts); SaveCacheFile(Path.Combine(_cacheDirectory, "MusicClearRanks.xml"), Cache.MusicClearRanks); SaveCacheFile(Path.Combine(_cacheDirectory, "MusicDifficultys.xml"), Cache.MusicDifficultys); SaveCacheFile(Path.Combine(_cacheDirectory, "MusicLevels.xml"), Cache.MusicLevels); SaveCacheFile(Path.Combine(_cacheDirectory, "TournamentMusics.xml"), Cache.TournamentMusics); SaveCacheFile(Path.Combine(_cacheDirectory, "Courses.xml"), Cache.Courses); SaveCacheFile(Path.Combine(_cacheDirectory, "CourseModes.xml"), Cache.CourseModes); SaveCacheFile(Path.Combine(_cacheDirectory, "LoginBonuses.xml"), Cache.LoginBonuses); SaveCacheFile(Path.Combine(_cacheDirectory, "Maps.xml"), Cache.Maps); SaveCacheFile(Path.Combine(_cacheDirectory, "MapColors.xml"), Cache.MapColors); SaveCacheFile(Path.Combine(_cacheDirectory, "MapTreasures.xml"), Cache.MapTreasures); SaveCacheFile(Path.Combine(_cacheDirectory, "MapBonusMusics.xml"), Cache.MapBonusMusics); SaveCacheFile(Path.Combine(_cacheDirectory, "MapOtomodachis.xml"), Cache.MapOtomodachis); SaveCacheFile(Path.Combine(_cacheDirectory, "MapSilhouettes.xml"), Cache.MapSilhouettes); SaveCacheFile(Path.Combine(_cacheDirectory, "MapTitles.xml"), Cache.MapTitles); SaveCacheFile(Path.Combine(_cacheDirectory, "ItemMusics.xml"), Cache.ItemMusics); SaveCacheFile(Path.Combine(_cacheDirectory, "Icons.xml"), Cache.Icons); SaveCacheFile(Path.Combine(_cacheDirectory, "Plates.xml"), Cache.Plates); SaveCacheFile(Path.Combine(_cacheDirectory, "Titles.xml"), Cache.Titles); SaveCacheFile(Path.Combine(_cacheDirectory, "Partners.xml"), Cache.Partners); SaveCacheFile(Path.Combine(_cacheDirectory, "Frames.xml"), Cache.Frames); SaveCacheFile(Path.Combine(_cacheDirectory, "Tickets.xml"), Cache.Tickets); SaveCacheFile(Path.Combine(_cacheDirectory, "CollectionTypes.xml"), Cache.CollectionTypes); SaveCacheFile(Path.Combine(_cacheDirectory, "CollectionGenres.xml"), Cache.CollectionGenres); SaveCacheFile(Path.Combine(_cacheDirectory, "PhotoFrames.xml"), Cache.PhotoFrames); SaveCacheFile(Path.Combine(_cacheDirectory, "Informations.xml"), Cache.Informations); SaveCacheFile(Path.Combine(_cacheDirectory, "Udemaes.xml"), Cache.Udemaes); SaveCacheFile(Path.Combine(_cacheDirectory, "Classes.xml"), Cache.Classes); SaveCacheFile(Path.Combine(_cacheDirectory, "UdemaeBosses.xml"), Cache.UdemaeBosses); SaveCacheFile(Path.Combine(_cacheDirectory, "UdemaeSeasonEvents.xml"), Cache.UdemaeSeasonEvents); SaveCacheFile(Path.Combine(_cacheDirectory, "UdemaeSeasonRewards.xml"), Cache.UdemaeSeasonRewards); SaveCacheFile(Path.Combine(_cacheDirectory, "Cards.xml"), Cache.Cards); SaveCacheFile(Path.Combine(_cacheDirectory, "CardCharas.xml"), Cache.CardCharas); SaveCacheFile(Path.Combine(_cacheDirectory, "CardTypes.xml"), Cache.CardTypes); SaveCacheFile(Path.Combine(_cacheDirectory, "WeekdayBonuses.xml"), Cache.WeekdayBonuses); SaveCacheFile(Path.Combine(_cacheDirectory, "Challenges.xml"), Cache.Challenges); SaveCacheFile(Path.Combine(_cacheDirectory, "MusicRankings.xml"), Cache.MusicRankings); SaveCacheFile(Path.Combine(_cacheDirectory, "MusicSorts.xml"), Cache.MusicSorts); SaveCacheFile(Path.Combine(_cacheDirectory, "LoginBonusSorts.xml"), Cache.LoginBonusSorts); SaveCacheFile(Path.Combine(_cacheDirectory, "IconSorts.xml"), Cache.IconSorts); SaveCacheFile(Path.Combine(_cacheDirectory, "PlateSorts.xml"), Cache.PlateSorts); SaveCacheFile(Path.Combine(_cacheDirectory, "TitleSorts.xml"), Cache.TitleSorts); SaveCacheFile(Path.Combine(_cacheDirectory, "PartnerSorts.xml"), Cache.PartnerSorts); SaveCacheFile(Path.Combine(_cacheDirectory, "FrameSorts.xml"), Cache.FrameSorts); SaveCacheFile(Path.Combine(_cacheDirectory, "TicketSorts.xml"), Cache.TicketSorts); SaveCacheFile(Path.Combine(_cacheDirectory, "CollectionGenreSorts.xml"), Cache.CollectionGenreSorts); SaveCacheFile(Path.Combine(_cacheDirectory, "CharaSorts.xml"), Cache.CharaSorts); SaveCacheFile(Path.Combine(_cacheDirectory, "CharaGenreSorts.xml"), Cache.CharaGenreSorts); } private static extern bool orig_Deserialize(string filePath, out T dsr) where T : new(); private static bool Deserialize(string filePath, out T dsr) where T : new() { var fileName = Path.GetFileName(filePath); var collectionName = fileName switch { "UdemaeBoss.xml" => "UdemaeBosses", "Class.xml" => "Classes", "LoginBonus.xml" => "LoginBonuses", "ScoreRanking.xml" => "TournamentMusics", "Holiday.xml" => "WeekdayBonuses", _ => fileName.Replace(".xml", "s"), }; var collectionField = typeof(CachedDataManager.SerializationCache).GetField(collectionName, BindingFlags.Public | BindingFlags.Instance); if (collectionField == null) { System.Console.WriteLine("[CachedDataManager] [WARN] Could not find suitable collection for {0} (tried name {1})", fileName, collectionName); return orig_Deserialize(filePath, out dsr); } try { var collection = (Dictionary)collectionField.GetValue(Cache); if (collection == null) { collection = LoadCacheFile(Path.Combine(_cacheDirectory, $"{collectionName}.xml")); collectionField.SetValue(Cache, collection); } if (collection.TryGetValue(filePath, out dsr)) { return true; } if (!orig_Deserialize(filePath, out dsr)) { return false; } collection.Add(filePath, dsr); _cacheBusted = true; return true; } catch (Exception e) { System.Console.WriteLine("[CachedDataManager] [ERROR] Could not load from cache: {0}", e); return orig_Deserialize(filePath, out dsr); } } private extern bool orig_IsLoaded(); public new bool IsLoaded() { var loaded = orig_IsLoaded(); if (!loaded || !_cacheBusted) { return loaded; } try { SaveCache(); } catch (Exception e) { System.Console.WriteLine("[CachedDataManager] [ERROR] Could not save to cache: {0}", e); } _cacheBusted = false; return true; } private static readonly CachedDataManager.SerializationCache Cache = new(); private static bool _cacheBusted; }