diff --git a/src/Network/Resources.cpp b/src/Network/Resources.cpp index 8dbb2ec..876c6f1 100644 --- a/src/Network/Resources.cpp +++ b/src/Network/Resources.cpp @@ -382,7 +382,7 @@ struct ModInfo { } } catch (const std::exception& e) { debug(std::string("Failed to receive mod list: ") + e.what()); - warn("Failed to receive new mod list format! This server may be outdated, but everything should still work as expected."); + debug("Failed to receive new mod list format! This server may be outdated, but everything should still work as expected."); } return std::make_pair(success, modInfos); } @@ -392,6 +392,52 @@ struct ModInfo { std::string HashAlgorithm; }; +nlohmann::json modUsage = {}; + +void UpdateModUsage(const std::string& fileName) { + try { + fs::path usageFile = fs::path(CachingDirectory) / "mods.json"; + + if (!fs::exists(usageFile)) { + if (std::ofstream file(usageFile); !file.is_open()) { + error("Failed to create mods.json"); + return; + } else { + file.close(); + } + } + + std::fstream file(usageFile, std::ios::in | std::ios::out); + if (!file.is_open()) { + error("Failed to open or create mods.json"); + return; + } + + if (modUsage.empty()) { + auto Size = fs::file_size(fs::path(CachingDirectory) / "mods.json"); + std::string modsJson(Size, 0); + file.read(&modsJson[0], Size); + + if (!modsJson.empty()) { + auto parsedModJson = nlohmann::json::parse(modsJson, nullptr, false); + + if (parsedModJson.is_object()) + modUsage = parsedModJson; + } + } + + modUsage[fileName] = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); + + file.clear(); + file.seekp(0, std::ios::beg); + file << modUsage.dump(); + file.close(); + } catch (std::exception& e) { + error("Failed to update mods.json: " + std::string(e.what())); + } +} + + void NewSyncResources(SOCKET Sock, const std::string& Mods, const std::vector ModInfos) { if (ModInfos.empty()) { CoreSend("L"); @@ -451,6 +497,42 @@ void NewSyncResources(SOCKET Sock, const std::string& Mods, const std::vectorFileName).filename(); + fs::exists(OldCachedPath) && GetSha256HashReallyFast(OldCachedPath.string()) == ModInfoIter->Hash) { + debug("Mod '" + FileName + "' found in old cache, copying it to the new cache"); + std::this_thread::sleep_for(std::chrono::milliseconds(50)); + try { + fs::copy_file(OldCachedPath, PathToSaveTo, fs::copy_options::overwrite_existing); + + if (!fs::exists(GetGamePath() + "mods/multiplayer")) { + fs::create_directories(GetGamePath() + "mods/multiplayer"); + } + + auto modname = ModInfoIter->FileName; + +#if defined(__linux__) + // Linux version of the game doesnt support uppercase letters in mod names + for (char& c : modname) { + c = ::tolower(c); + } +#endif + + debug("Mod name: " + modname); + auto name = std::filesystem::path(GetGamePath()) / "mods/multiplayer" / modname; + std::string tmp_name = name.string(); + tmp_name += ".tmp"; + + fs::copy_file(PathToSaveTo, tmp_name, fs::copy_options::overwrite_existing); + fs::rename(tmp_name, name); + UpdateModUsage(FileName); } catch (std::exception& e) { error("Failed copy to the mods folder! " + std::string(e.what())); Terminate = true; @@ -505,6 +587,7 @@ void NewSyncResources(SOCKET Sock, const std::string& Mods, const std::vectorsubstr(pos)); } WaitForConfirm(); }