mirror of
https://github.com/Dingo-Shenanigans/ReSkate.git
synced 2026-10-29 03:46:50 +01:00
A server lists Thunderstore packages in plugins.required ("Owner-Name", or "Owner-Name-1.2.3"
for at least that version, at most 16). It checks each on Thunderstore as it starts and leaves
out one not listed as a plugin, and sends the rest with its map offer (protocol 55).
A joining player's game checks them before the server's map loads. Those missing, switched off
or too old go on one card with the map when that is missing too, so the player is asked once.
GET ALL downloads and installs each, switches on any that were off, runs one live merge when
any brings game data, and joins; CANCEL leaves. The game fetches a package only when
Thunderstore lists it as a plugin and it installs as one (a reskate-plugin.json naming Luau
code), whatever a server asks; anything else is taken out again, so a cosmetic can never be
required.
map_download handles a list of packages instead of one map, and the Thunderstore chooser takes
the category it needs. A map alone keeps its card as it was.
47 lines
2.2 KiB
C++
47 lines
2.2 KiB
C++
#pragma once
|
|
|
|
#include <optional>
|
|
#include <string>
|
|
#include <string_view>
|
|
|
|
// One Thunderstore package looked up by name, for the game: the map a multiplayer host is on
|
|
// and this player does not have, and the plugins a dedicated server needs
|
|
// (Extension/Assets/map_download.h). No network here; the caller
|
|
// fetches details_url() and hands the answer to choose().
|
|
namespace dingosdk::thunderstore_package {
|
|
|
|
struct Name {
|
|
std::string owner, name;
|
|
std::string version; // "1.2.3", or empty for the newest
|
|
// The Mods folder the package installs as, and how its files name it.
|
|
[[nodiscard]] std::string folder() const { return owner + '-' + name; }
|
|
bool operator==(const Name&) const = default;
|
|
};
|
|
// "Owner-Name" or "Owner-Name-1.2.3", as a host names a map's package
|
|
// (Extension/Multiplayer/Net/protocol.h: valid_map_package). Nothing for anything else.
|
|
std::optional<Name> parse_name(std::string_view package);
|
|
|
|
// /api/experimental/package/<owner>/<name>/: what Thunderstore says of the package.
|
|
std::wstring details_url(const Name& name);
|
|
// Where a version of it downloads from. Always thunderstore.io, whatever an answer says.
|
|
std::wstring download_url(const Name& name, std::string_view version);
|
|
|
|
struct Choice {
|
|
bool ok{};
|
|
std::string version; // the one to download: the one asked for, else the newest
|
|
std::string newest; // the newest, to fall back on when the one asked for is gone
|
|
// What its page says of it, for the player: one line of plain text, cut to a few lines' worth.
|
|
std::string description;
|
|
// Its picture, a PNG on Thunderstore's own hosts; empty when the answer names anything else.
|
|
std::string icon;
|
|
std::string reason; // why not, for the player
|
|
};
|
|
// What the package has to be listed as: a map (the "Maps" category) or a plugin ("Plugins").
|
|
enum class Kind { map, plugin };
|
|
// Reads that answer. The package is taken only when it is the one asked for, is listed in
|
|
// `community` as `kind`, is not deprecated or marked NSFW there and was not rejected by the
|
|
// community's moderators.
|
|
Choice choose(std::string_view json, const Name& wanted, std::string_view community, Kind kind = Kind::map);
|
|
|
|
} // namespace dingosdk::thunderstore_package
|