Files
AyeZeeBB a2d6daffbc Official mods: Board Break and Road Rash downloaded from Thunderstore and kept at their latest, with an Official tab
The launcher reads the official list from the ReSkate backend (or the last one it read, or its own)
and keeps each mod in Mods/.reskate-official at its latest version; a copy the player installed is
moved in, the deprecated Board Break retired. The game loads them always on and leaves out Mods
folder copies; the browser no longer lists them. The built-in zips are gone (FPV drone too), and
built-in folders no longer carried are removed.
2026-10-16 18:59:41 -05:00

55 lines
2.7 KiB
C++

#pragma once
#include <chrono>
#include <filesystem>
#include <string>
#include <string_view>
#include <vector>
// Official mods: Thunderstore packages every player has, always on, at their latest version. 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. They live in Mods/.reskate-official/<Namespace-Name>
// (Engine/Vfs/builtin_packs.h), which the game merges after every installed mod.
//
// As the launcher starts it reads the list and, on a thread of its own, puts each mod in place: a
// copy the player installed from Thunderstore is moved over rather than downloaded again, a newer
// version is downloaded, and copies left in the Mods folder (and mods retired with an official
// one) go to the Recycle Bin and out of mods.json. Play waits for it.
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, at most `timeout`. False while it still runs (or never started).
bool wait(std::chrono::milliseconds timeout);
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();
// For each official mod not in place yet, a copy in the Mods folder is moved in (stamped with its
// manifest's version); the copies left in the Mods folder and 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);
}