Implement DeleteDuplicateMods option (#190)

Adds `DeleteDuplicateMods` option to the launcher config which, well,
deletes mods with the same name if their hashes mismatch. Useful for
development where client mod hashes can frequently change.

---

By creating this pull request, I understand that code that is AI
generated or otherwise automatically generated may be rejected without
further discussion.
I declare that I fully understand all code I pushed into this PR, and
wrote all this code myself and own the rights to this code.
This commit is contained in:
Tixx 2025-06-08 12:56:23 +02:00 committed by GitHub
commit 676084f283
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 28 additions and 0 deletions

View File

@ -30,6 +30,7 @@ extern uint64_t UDPSock;
extern uint64_t TCPSock;
extern std::string Branch;
extern std::string CachingDirectory;
extern bool deleteDuplicateMods;
extern bool TCPTerminate;
extern std::string LastIP;
extern std::string MStatus;

View File

@ -15,6 +15,7 @@ namespace fs = std::filesystem;
std::string Branch;
std::string CachingDirectory = "./Resources";
bool deleteDuplicateMods = false;
void ParseConfig(const nlohmann::json& d) {
if (d["Port"].is_number()) {
@ -42,6 +43,11 @@ void ParseConfig(const nlohmann::json& d) {
options.no_launch = dev;
options.no_update = dev;
}
if (d.contains(("DeleteDuplicateMods")) && d["DeleteDuplicateMods"].is_boolean()) {
deleteDuplicateMods = d["DeleteDuplicateMods"].get<bool>();
}
}
void ConfigInit() {

View File

@ -475,10 +475,31 @@ void NewSyncResources(SOCKET Sock, const std::string& Mods, const std::vector<Mo
info("Syncing...");
std::vector<std::pair<std::string, std::filesystem::path>> CachedMods = {};
if (deleteDuplicateMods) {
for (const auto& entry : fs::directory_iterator(CachingDirectory)) {
const std::string filename = entry.path().filename().string();
if (entry.is_regular_file() && entry.path().extension() == ".zip" && filename.length() > 10) {
CachedMods.push_back(std::make_pair(filename.substr(0, filename.length() - 13) + ".zip", entry.path()));
}
}
}
int ModNo = 0;
int TotalMods = ModInfos.size();
for (auto ModInfoIter = ModInfos.begin(), AlsoModInfoIter = ModInfos.begin(); ModInfoIter != ModInfos.end() && !Terminate; ++ModInfoIter, ++AlsoModInfoIter) {
++ModNo;
if (deleteDuplicateMods) {
for (auto& CachedMod : CachedMods) {
const bool cachedModExists = CachedMod.first == ModInfoIter->FileName;
const bool cachedModIsNotNewestVersion = CachedMod.second.stem().string() + ".zip" != std::filesystem::path(ModInfoIter->FileName).stem().string() + "-" + ModInfoIter->Hash.substr(0, 8) + ".zip";
if (cachedModExists && cachedModIsNotNewestVersion) {
debug("Found duplicate mod '" + CachedMod.second.stem().string() + ".zip" + "' in cache, removing it");
std::filesystem::remove(CachedMod.second);
break;
}
}
}
if (ModInfoIter->Hash.length() < 8 || ModInfoIter->HashAlgorithm != "sha256") {
error("Unsupported hash algorithm or invalid hash for '" + ModInfoIter->FileName + "'");
Terminate = true;