using SongCore.Utilities; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; namespace SongCore.Arcache { public static class ArcacheLoader { private static readonly Lz4ArchiveReader JsonArchive; private static readonly Dictionary OggLengthDictionary = new(); static ArcacheLoader() { var basePath = CustomLevelPathHelper.customLevelsDirectoryPath; var jsonArcBase = Path.Combine(basePath, "bsa"); var lengthCache = Path.Combine(basePath, "bslp"); Logging.logger.Info("ArcacheLoader: Loading jsonArc"); JsonArchive = new Lz4ArchiveReader(jsonArcBase, true); Logging.logger.Info("ArcacheLoader: Loading oggLengthCache"); OggLengthDictionary = LengthPack.Read(lengthCache); Logging.logger.Info($"ArcacheLoader: Load finished. Json Archive:{JsonArchive.Entries.Count}, ogg Length:{OggLengthDictionary.Count}"); } public static void InitFastLoad() { //Just fire static ctor } private static string ConvertFullPathToArchivePath(string fullPath) { // assume full path is "...\ffde (Country Rounds - EpicTroller)\Info.dat" // ^ ^ var parts = fullPath.Split(new[] { '\\', '/' }, StringSplitOptions.RemoveEmptyEntries); var vPath = $"{parts[parts.Length - 2]}/{parts[parts.Length - 1]}"; return vPath.ToLower(); } public static string ReadJson(string fullPath) { var vPath = ConvertFullPathToArchivePath(fullPath); if (JsonArchive.Entries.TryGetValue(vPath, out var entry)) return JsonArchive.ReadText(entry, Encoding.UTF8); Logging.Log($"Archive[Json] Cache miss:{fullPath} -- {vPath}"); return File.ReadAllText(fullPath); } public static byte[] ReadAllBytes(string fullPath) { var vPath = ConvertFullPathToArchivePath(fullPath); if (JsonArchive.Entries.TryGetValue(vPath, out var entry)) return JsonArchive.ReadData(entry); Logging.Log($"Archive[Data] Cache miss:{fullPath} -- {vPath}"); return File.ReadAllBytes(fullPath); } public static bool GetCachedOggLength(string fullPath, out float len) { var vPath = ConvertFullPathToArchivePath(fullPath); if (OggLengthDictionary.TryGetValue(vPath, out var data)) { len = data; return true; } Logging.Log($"Archive[OggLen] Cache miss:{fullPath} -- {vPath}"); len = -1; return false; } public static string[] ExtractCustomLevelFoldersFromArchive() { return JsonArchive.Entries.Keys .Select(p => Path.Combine(CustomLevelPathHelper.customLevelsDirectoryPath, p.Split('/')[0]).ToLower()) .Distinct().ToArray(); } public static bool ArchiveExists(string fullPath) { var vPath = ConvertFullPathToArchivePath(fullPath); var archiveExists = JsonArchive.Entries.ContainsKey(vPath); if (archiveExists == false) { if (File.Exists(fullPath)) { Logging.logger.Info($"Arcache: Provide by real FS {fullPath}"); return true; } Logging.logger.Warn($"Arcache: file not exist? {fullPath} -> {vPath}"); } return archiveExists; } public static string ExtractParentDirectoryName(string fullPath) { return Path.GetFileName(Path.GetDirectoryName(fullPath))?.ToLower(); } } }