123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209 |
- using SongCore.Data;
- using System;
- using System.Collections.Concurrent;
- using System.Collections.Generic;
- using System.IO;
- using System.Linq;
- using System.Security.Cryptography;
- using System.Text;
- using SongCore.Arcache;
- namespace SongCore.Utilities
- {
- public class Hashing
- {
- internal static ConcurrentDictionary<string, SongHashData> cachedSongHashData = new ConcurrentDictionary<string, SongHashData>();
- internal static ConcurrentDictionary<string, AudioCacheData> cachedAudioData = new ConcurrentDictionary<string, AudioCacheData>();
- public static readonly string cachedHashDataPath = Path.Combine(IPA.Utilities.UnityGame.InstallPath, "UserData", "SongCore", "SongHashData.dat");
- public static readonly string cachedAudioDataPath = Path.Combine(IPA.Utilities.UnityGame.InstallPath, "UserData", "SongCore", "SongDurationCache.dat");
- public static void ReadCachedSongHashes()
- {
- //if (File.Exists(cachedHashDataPath))
- //{
- // cachedSongHashData = Newtonsoft.Json.JsonConvert.DeserializeObject<ConcurrentDictionary<string, SongHashData>>(File.ReadAllText(cachedHashDataPath));
- // if (cachedSongHashData == null) cachedSongHashData = new ConcurrentDictionary<string, SongHashData>();
- // Logging.Log($"Finished reading cached hashes for {cachedSongHashData.Count} songs!");
- //}
- }
- public static void UpdateCachedHashes(HashSet<string> currentSongPaths)
- {
- //UpdateCachedHashesInternal(currentSongPaths);
- }
- /// <summary>
- /// Intended for use in the Loader
- /// </summary>
- /// <param name="currentSongPaths"></param>
- internal static void UpdateCachedHashesInternal(ICollection<string> currentSongPaths)
- {
- foreach (var hashData in cachedSongHashData.ToArray())
- {
- if (!currentSongPaths.Contains(hashData.Key))
- cachedSongHashData.TryRemove(hashData.Key, out _);
- }
- Logging.Log($"Updating cached hashes for {cachedSongHashData.Count} songs!");
- File.WriteAllText(cachedHashDataPath, Newtonsoft.Json.JsonConvert.SerializeObject(cachedSongHashData));
- }
- public static void ReadCachedAudioData()
- {
- //if (File.Exists(cachedAudioDataPath))
- //{
- // cachedAudioData = Newtonsoft.Json.JsonConvert.DeserializeObject<ConcurrentDictionary<string, AudioCacheData>>(File.ReadAllText(cachedAudioDataPath));
- // if (cachedAudioData == null) cachedAudioData = new ConcurrentDictionary<string, AudioCacheData>();
- // Logging.Log($"Finished reading cached Durations for {cachedAudioData.Count} songs!");
- //}
- }
- public static void UpdateCachedAudioData(HashSet<string> currentSongPaths)
- {
- UpdateCachedAudioDataInternal(currentSongPaths);
- }
- /// <summary>
- /// Intended for use in the Loader
- /// </summary>
- /// <param name="currentSongPaths"></param>
- internal static void UpdateCachedAudioDataInternal(ICollection<string> currentSongPaths)
- {
- //foreach (var hashData in cachedAudioData.ToArray())
- //{
- // if (!currentSongPaths.Contains(hashData.Key))
- // cachedAudioData.TryRemove(hashData.Key, out _);
- //}
- //Logging.Log($"Updating cached Map Lengths for {cachedAudioData.Count} songs!");
- //File.WriteAllText(cachedAudioDataPath, Newtonsoft.Json.JsonConvert.SerializeObject(cachedAudioData));
- }
- private static long GetDirectoryHash(string directory)
- {
- long hash = 0;
- var directoryInfo = new DirectoryInfo(directory);
- foreach (var f in directoryInfo.GetFiles())
- {
- hash ^= f.CreationTimeUtc.ToFileTimeUtc();
- hash ^= f.LastWriteTimeUtc.ToFileTimeUtc();
- hash ^= f.Name.GetHashCode();
- hash ^= f.Length;
- }
- return hash;
- }
- private static bool GetCachedSongData(string customLevelPath, out long directoryHash, out string cachedSongHash)
- {
- directoryHash = GetDirectoryHash(customLevelPath);
- cachedSongHash = string.Empty;
- if (cachedSongHashData.TryGetValue(customLevelPath, out var cachedSong))
- {
- if (cachedSong.directoryHash == directoryHash)
- {
- cachedSongHash = cachedSong.songHash;
- return true;
- }
- }
- return false;
- }
- public static string GetCustomLevelHash(CustomPreviewBeatmapLevel level)
- {
- //if (GetCachedSongData(level.customLevelPath, out var directoryHash, out var songHash))
- // return songHash;
- var combinedBytes = new List<byte>();
- combinedBytes.AddRange(ArcacheLoader.ReadAllBytes(level.customLevelPath + '/' + "info.dat"));
- for (var i = 0; i < level.standardLevelInfoSaveData.difficultyBeatmapSets.Length; i++)
- {
- for (var i2 = 0; i2 < level.standardLevelInfoSaveData.difficultyBeatmapSets[i].difficultyBeatmaps.Length; i2++)
- if (ArcacheLoader.ArchiveExists(level.customLevelPath + '/' + level.standardLevelInfoSaveData.difficultyBeatmapSets[i].difficultyBeatmaps[i2].beatmapFilename))
- {
- combinedBytes.AddRange(ArcacheLoader.ReadAllBytes(level.customLevelPath + '/' + level.standardLevelInfoSaveData.difficultyBeatmapSets[i].difficultyBeatmaps[i2].beatmapFilename));
- }
- }
- var hash = CreateSha1FromBytes(combinedBytes.ToArray());
- //cachedSongHashData[level.customLevelPath] = new SongHashData(directoryHash, hash);
- return hash;
- }
- public static string GetCustomLevelHash(StandardLevelInfoSaveData level, string customLevelPath)
- {
- //if (GetCachedSongData(customLevelPath, out var directoryHash, out var songHash))
- // return songHash;
- var combinedBytes = new byte[0];
- combinedBytes = combinedBytes.Concat(ArcacheLoader.ReadAllBytes(customLevelPath + '/' + "info.dat")).ToArray();
- for (var i = 0; i < level.difficultyBeatmapSets.Length; i++)
- {
- for (var i2 = 0; i2 < level.difficultyBeatmapSets[i].difficultyBeatmaps.Length; i2++)
- if (ArcacheLoader.ArchiveExists(customLevelPath + '/' + level.difficultyBeatmapSets[i].difficultyBeatmaps[i2].beatmapFilename))
- combinedBytes = combinedBytes.Concat(ArcacheLoader.ReadAllBytes(customLevelPath + '/' + level.difficultyBeatmapSets[i].difficultyBeatmaps[i2].beatmapFilename)).ToArray();
- }
- var hash = CreateSha1FromBytes(combinedBytes.ToArray());
- //cachedSongHashData[customLevelPath] = new SongHashData(directoryHash, hash);
- return hash;
- }
- public static string GetCustomLevelHash(CustomBeatmapLevel level)
- {
- //if (GetCachedSongData(level.customLevelPath, out var directoryHash, out var songHash))
- // return songHash;
- var combinedBytes = new byte[0];
- combinedBytes = combinedBytes.Concat(ArcacheLoader.ReadAllBytes(level.customLevelPath + '/' + "info.dat")).ToArray();
- for (var i = 0; i < level.standardLevelInfoSaveData.difficultyBeatmapSets.Length; i++)
- {
- for (var i2 = 0; i2 < level.standardLevelInfoSaveData.difficultyBeatmapSets[i].difficultyBeatmaps.Length; i2++)
- if (File.Exists(level.customLevelPath + '/' + level.standardLevelInfoSaveData.difficultyBeatmapSets[i].difficultyBeatmaps[i2].beatmapFilename))
- combinedBytes = combinedBytes.Concat(ArcacheLoader.ReadAllBytes(level.customLevelPath + '/' + level.standardLevelInfoSaveData.difficultyBeatmapSets[i].difficultyBeatmaps[i2].beatmapFilename)).ToArray();
- }
- var hash = CreateSha1FromBytes(combinedBytes.ToArray());
- //cachedSongHashData[level.customLevelPath] = new SongHashData(directoryHash, hash);
- return hash;
- }
- public static string CreateSha1FromString(string input)
- {
- // Use input string to calculate MD5 hash
- using (var sha1 = SHA1.Create())
- {
- var inputBytes = Encoding.ASCII.GetBytes(input);
- var hashBytes = sha1.ComputeHash(inputBytes);
- return BitConverter.ToString(hashBytes).Replace("-", string.Empty);
- }
- }
- public static string CreateSha1FromBytes(byte[] input)
- {
- // Use input string to calculate MD5 hash
- using (var sha1 = SHA1.Create())
- {
- var inputBytes = input;
- var hashBytes = sha1.ComputeHash(inputBytes);
- return BitConverter.ToString(hashBytes).Replace("-", string.Empty);
- }
- }
- public static bool CreateSha1FromFile(string path, out string hash)
- {
- hash = "";
- if (!File.Exists(path)) return false;
- using (var sha1 = SHA1.Create())
- {
- using (var stream = File.OpenRead(path))
- {
- var hashBytes = sha1.ComputeHash(stream);
- hash = BitConverter.ToString(hashBytes).Replace("-", string.Empty);
- return true;
- }
- }
- }
- }
- }
|