Files
ReSkate/Launcher/official_mods.h
T
AyeZeeBB fffd34ca80 Mods: conflicts resolved in MY MODS, official mods live in Mods, and big maps merge faster
MY MODS: a table with an animated drag for the load order, a conflicts bar with Check conflicts, and a Resolve popup whose choices are kept. The check runs at startup and after changes; conflicts no longer show as problems, block Play, or hold mod files during an update.
Conflicts: only game EBX that cannot be combined, or Lua scripts with different versions; colourways and same-name additions are not conflicts.
Official mods: installed in Mods/<Namespace-Name> and turned on or off through mods.json, so they show in MY MODS; the old .reskate-official folder is moved over.
Merge: a scan cache (Mods/.reskate-scan.txt) keeps each unchanged mod's repair, mesh and texture scans, so big maps are not re-read every merge.
Launcher: an announcement from the backend shows under STATUS, with HIDE.
2026-10-18 16:33:53 -05:00

65 lines
3.5 KiB
C++

#pragma once
#include <chrono>
#include <filesystem>
#include <string>
#include <string_view>
#include <vector>
// Official mods: Thunderstore packages made for ReSkate's own features, listed on the launcher's
// OFFICIAL tab, where the player installs, updates and turns them off. The ReSkate backend names
// them (GET /api/v1/official-mods, beside the verified mods), so one is added or dropped without a
// release; the launcher keeps the last list it read, and has one of its own for a first launch with
// no network. Installed, each is a mod like any other in Mods/<Namespace-Name> and mods.json, with a
// stamp naming its version (Engine/Vfs/builtin_packs.h); a new one goes at the bottom of the load order.
//
// As the launcher starts it reads the list and, on a thread of its own, looks up each one's latest
// version: a copy the player installed from Thunderstore counts as the official mod where it is,
// and mods retired with an official one go to the Recycle Bin and out of mods.json.
// Nothing is downloaded until the player asks (install()). Play waits for that and for downloads
// under way.
namespace dingosdk::official_mods {
struct Mod {
std::string full_name; // Namespace-Name
std::string title, description, icon;
std::string version; // the latest the list or Thunderstore gave; empty when not known
std::string download_url;
std::string installed; // the version in place; empty when none is
std::string status; // what the launcher did with it, for the OFFICIAL tab
bool working{}; // being downloaded or put in place now
};
struct State {
std::vector<Mod> mods;
std::string source; // where the list came from: "ReSkate", "the last list read" or "ReSkate's own list"
bool syncing{}, synced{};
};
// Puts the official mods in place under `mods_root`, once a launch (later calls do nothing).
void start(const std::filesystem::path& mods_root);
// Waits for that and any install() under way, at most `timeout`. False while one still runs (or it
// never started).
bool wait(std::chrono::milliseconds timeout);
// Downloads the latest version of the official mod `full_name` and puts it in place under
// `mods_root`, on a thread of its own; snapshot() shows how it goes. Does nothing while the list is
// still being read or the mod is already being downloaded.
void install(const std::filesystem::path& mods_root, const std::string& full_name);
// Takes the installed official mod `full_name` away (its folder, and whether it was turned off), on
// a thread of its own; it can be installed again. Does nothing while it is being downloaded.
void uninstall(const std::filesystem::path& mods_root, const std::string& full_name);
State snapshot();
// Whether the Thunderstore package `full_name` is official (or retired with one): the browser
// neither lists nor installs it.
bool official(std::string_view full_name);
// The pieces, for tests.
// The backend's answer: its mods, or none when it is not that answer.
std::vector<Mod> parse_list(std::string_view json);
// The list ReSkate falls back on when it has never read one: Fourth Studio's Board Break pack and
// Road Rash.
std::vector<Mod> fallback_list();
// Each official mod in the Mods folder without its stamp (installed by the player from Thunderstore)
// is stamped with its manifest's version, as the official mod; retired mods go to the Recycle Bin;
// mods.json forgets what went. Returns what was done, a line each. Never throws.
std::vector<std::string> adopt_and_retire(const std::filesystem::path& mods_root, const std::vector<Mod>& official);
}