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`).