diff --git a/Libraries/Core/Core.csproj b/Libraries/Core/Core.csproj index af618654..1462d2b5 100644 --- a/Libraries/Core/Core.csproj +++ b/Libraries/Core/Core.csproj @@ -11,4 +11,8 @@ + + + + diff --git a/Libraries/Core/Loaders/BundleLoader.cs b/Libraries/Core/Loaders/BundleLoader.cs index 96ca7a27..01bb98c2 100644 --- a/Libraries/Core/Loaders/BundleLoader.cs +++ b/Libraries/Core/Loaders/BundleLoader.cs @@ -9,7 +9,12 @@ namespace Core.Loaders { public class BundleInfo { - public string ModPath + public string? ModPath + { + get; + } + + public string FileName { get; } @@ -19,7 +24,7 @@ namespace Core.Loaders get; } - public string Crc + public uint Crc { get; } @@ -32,9 +37,10 @@ namespace Core.Loaders public BundleInfo( string modPath, BundleManifestEntry bundle, - string bundleHash) + uint bundleHash) { ModPath = modPath; + FileName = bundle.Key; Bundle = bundle; Crc = bundleHash; Dependencies = bundle?.DependencyKeys ?? []; @@ -51,7 +57,7 @@ namespace Core.Loaders private readonly BundleHashCacheService _bundleHashCacheService; private readonly InMemoryCacheService _inMemoryCacheService; private readonly ICloner _cloner; - private readonly Dictionary _bundles; + private readonly Dictionary _bundles = new Dictionary(); public BundleLoader( ISptLogger logger, @@ -84,27 +90,22 @@ namespace Core.Loaders public BundleInfo? GetBundle(string bundleKey) { - return _bundles.GetValueOrDefault(bundleKey); + return _cloner.Clone(_bundles.GetValueOrDefault(bundleKey)); } public void AddBundles(string modPath) { - // TODO: Implement + // modPath should be relative to the server exe - /user/mods/Mod3/ - var modBundlesJson = _fileUtil.ReadFile(Path.Combine(modPath, "bundles.json")); + var modBundlesJson = _fileUtil.ReadFile(Path.Join(Directory.GetCurrentDirectory(), modPath, "bundles.json")); var modBundles = _jsonUtil.Deserialize(modBundlesJson); var bundleManifestArr = modBundles?.Manifest; foreach (var bundleManifest in bundleManifestArr) { - // TODO: complete - // we currently get D:\HomeRepos\SPT-CS-Server\Server\bin\Debug\net9.0/user/mods/Mod3 - // we want /user/mods/Mod3 - var relativeModPath = modPath.Substring(0, modPath.Length - 1); // /\\/g, "/" - replaces all instances of \\ with / + var relativeModPath = modPath.Replace('\\', '/'); // /\\/g, "/" - replaces all instances of \\ with / - // we currently get D:\HomeRepos\SPT-CS-Server\Server\bin\Debug\net9.0/user/mods/Mod3/bundles\assets/content/weapons/usable_items/item_bottle/textures/client_assets.bundle - // we want /user/mods/Mod3/bundles\assets/content/weapons/usable_items/item_bottle/textures/client_assets.bundle - var bundleLocalPath = Path.Combine(modPath, "bundles", bundleManifest.Key); // /\\/g, "/" - replaces all instances of \\ with / + var bundleLocalPath = Path.Join(relativeModPath, "bundles", bundleManifest.Key); if (!_bundleHashCacheService.CalculateAndMatchHash(bundleLocalPath)) { diff --git a/Libraries/Core/Services/BundleHashCacheService.cs b/Libraries/Core/Services/BundleHashCacheService.cs index 35df5224..b87201ff 100644 --- a/Libraries/Core/Services/BundleHashCacheService.cs +++ b/Libraries/Core/Services/BundleHashCacheService.cs @@ -11,8 +11,10 @@ namespace Core.Services private readonly JsonUtil _jsonUtil; private readonly HashUtil _hashUtil; private readonly FileUtil _fileUtil; - protected readonly Dictionary _bundleHashes = new Dictionary(); - protected const string _bundleHashCachePath = "./user/cache/bundleHashCache.json"; + protected readonly Dictionary _bundleHashes = new Dictionary(); + protected const string _bundleHashCachePath = "./user/cache/"; + protected const string _cacheName = "bundleHashCache.json"; + private readonly string _currentDirectory = Directory.GetCurrentDirectory(); public BundleHashCacheService( ISptLogger logger, @@ -25,44 +27,52 @@ namespace Core.Services _hashUtil = hashUtil; _fileUtil = fileUtil; } - public string GetStoredValue(string key) + + public uint GetStoredValue(string key) { if (!_bundleHashes.TryGetValue(key, out var value)) { - return string.Empty; + return 0; } return value; } - public void StoreValue(string bundlePath, string hash) + public void StoreValue(string bundlePath, uint hash) { _bundleHashes.Add(bundlePath, hash); - _fileUtil.WriteFile(_bundleHashCachePath, _jsonUtil.Serialize(_bundleHashes)); + if (!Directory.Exists(_bundleHashCachePath)) + { + Directory.CreateDirectory(_bundleHashCachePath); + } + + _fileUtil.WriteFile(Path.Join(_bundleHashCachePath, _cacheName), _jsonUtil.Serialize(_bundleHashes)); _logger.Debug($"Bundle: {bundlePath} hash stored in: ${_bundleHashCachePath}"); } - public bool CalculateAndMatchHash(string bundlePath) + public bool CalculateAndMatchHash(string relativeBundlePath) { - return MatchWithStoredHash(bundlePath, CalculateHash(bundlePath)); + var absolutePath = Path.Join(_currentDirectory, relativeBundlePath); + return MatchWithStoredHash(relativeBundlePath, CalculateHash(absolutePath)); } - public void CalculateAndStoreHash(string bundlePath) + public void CalculateAndStoreHash(string relativeBundlePath) { - StoreValue(bundlePath, CalculateHash(bundlePath)); + var absolutePath = Path.Join(_currentDirectory, relativeBundlePath); + StoreValue(relativeBundlePath, CalculateHash(absolutePath)); } - public string CalculateHash(string bundlePath) + public uint CalculateHash(string absoluteBundlePath) { - var fileData = _fileUtil.ReadFile(bundlePath); - return _hashUtil.GenerateMd5ForData(fileData); + var fileData = _fileUtil.ReadFile(absoluteBundlePath); + return _hashUtil.GenerateCrc32ForData(fileData); } - public bool MatchWithStoredHash(string bundlePath, string hash) + public bool MatchWithStoredHash(string relativeBundlePath, uint hash) { - return GetStoredValue(bundlePath) == hash; + return GetStoredValue(relativeBundlePath) == hash; } } } diff --git a/Libraries/Core/Utils/HashUtil.cs b/Libraries/Core/Utils/HashUtil.cs index adfed2f8..b6687f28 100644 --- a/Libraries/Core/Utils/HashUtil.cs +++ b/Libraries/Core/Utils/HashUtil.cs @@ -1,3 +1,4 @@ +using System.IO.Hashing; using System.Security.Cryptography; using System.Text; using System.Text.RegularExpressions; @@ -64,12 +65,9 @@ public class HashUtil return GenerateHashForData(HashingAlgorithm.SHA1, data); } - [Obsolete("Use GenerateMd5ForData instead")] - public string GenerateCrc32ForData(string data) + public uint GenerateCrc32ForData(string data) { - // TODO: Could not find a ms way of doing this. - // May need a custom impl to avoid an external lib. - CJ - throw new NotImplementedException(); + return Crc32.HashToUInt32(new ArraySegment(Encoding.UTF8.GetBytes(data))); } /// diff --git a/ModExamples/12Bundle/Bundle.cs b/ModExamples/12Bundle/Bundle.cs index b027292e..c221e554 100644 --- a/ModExamples/12Bundle/Bundle.cs +++ b/ModExamples/12Bundle/Bundle.cs @@ -19,8 +19,6 @@ public class Bundle : IPostDBLoadMod public void PostDBLoad() { - var modFolder = Directory.GetCurrentDirectory(); - var test = Assembly.GetExecutingAssembly().Location; - _bundleLoader.AddBundles(Path.Join(modFolder, "/user/mods/Mod3/")); + _bundleLoader.AddBundles("/user/mods/Mod3"); } }