diff --git a/Convoy/Convoy.csproj b/Convoy/Convoy.csproj index 4f00e22..d434c5c 100644 --- a/Convoy/Convoy.csproj +++ b/Convoy/Convoy.csproj @@ -36,6 +36,10 @@ + + + + @@ -59,6 +63,8 @@ + diff --git a/Convoy/SyncEngine.cs b/Convoy/SyncEngine.cs index 873cc99..4bb6949 100644 --- a/Convoy/SyncEngine.cs +++ b/Convoy/SyncEngine.cs @@ -2,9 +2,9 @@ using System.Collections.Generic; using System.IO; using System.IO.Compression; +using System.IO.Hashing; using System.Linq; using System.Net; -using System.Security.Cryptography; using System.Text; using BepInEx; using BepInEx.Logging; @@ -563,22 +563,18 @@ private List ExtractZip(byte[] zipBytes, string targetDir) private bool VerifyHashes(List extractedPaths, Dictionary expected, string baseDir) { - using (var sha = SHA256.Create()) + foreach (var relPath in extractedPaths) { - foreach (var relPath in extractedPaths) + if (!expected.TryGetValue(relPath, out var want)) continue; + var fullPath = Path.Combine(baseDir, relPath.Replace('/', Path.DirectorySeparatorChar)); + var hasher = new XxHash3(); + using (var stream = File.OpenRead(fullPath)) + hasher.Append(stream); + var got = hasher.GetCurrentHashAsUInt64().ToString("x16"); + if (got != want.ToLowerInvariant()) { - if (!expected.TryGetValue(relPath, out var want)) continue; - var fullPath = Path.Combine(baseDir, relPath.Replace('/', Path.DirectorySeparatorChar)); - using (var stream = File.OpenRead(fullPath)) - { - var got = BitConverter.ToString(sha.ComputeHash(stream)) - .Replace("-", "").ToLowerInvariant(); - if (got != want.ToLowerInvariant()) - { - _log.LogError($"Hash mismatch: {relPath} (expected {want}, got {got})"); - return false; - } - } + _log.LogError($"Hash mismatch: {relPath} (expected {want}, got {got})"); + return false; } } return true; diff --git a/README.md b/README.md index df8205b..69b66d4 100644 --- a/README.md +++ b/README.md @@ -6,14 +6,14 @@ BepInEx 5 plugin for [SPT](https://www.sp-tarkov.com/) that syncs client-side mo 1. Fetches the mod catalog from your Quartermaster server (with ETag caching) 2. Diffs against local state to determine what needs to be installed, updated, or removed -3. Downloads changed mods as a batch ZIP, extracts, and verifies SHA-256 hashes +3. Downloads changed mods as a batch ZIP, extracts, and verifies xxHash3 hashes 4. Prompts for a restart if any BepInEx plugin files changed (they're already loaded by the time Convoy runs) Optional mod groups are toggled via BepInEx Configuration Manager (F12 in-game). ## Installation -Copy `Convoy.dll` to `BepInEx/plugins/Convoy/` in your SPT install directory. +Copy the contents of `Build/BepInEx/plugins/Convoy/` (includes `Convoy.dll` and `System.IO.Hashing.dll`) to `BepInEx/plugins/Convoy/` in your SPT install directory. On first run, Convoy creates its config at `BepInEx/config/io.cebarks.convoy.cfg` — set `ServerUrl` to your Quartermaster instance (e.g. `http://192.168.1.50:9190`).