Sur cette page

← Toute la documentation

Catalogue de mods et de skins (page Télécharger)

Le catalogue de mods et de skins du site : contrat de l'API, installation en un clic, vérification.

La page Télécharger a deux onglets de plus, Mods et Skins, qui listent le catalogue hébergé par le site du projet (https://prism.am) et installent un élément en un clic. Le jeu fait tout lui-même, en natif (crates/downloader/src/repository.rs pour le réseau, apps/desktop/src/app/hosted.rs pour l'orchestration) : jamais le thread des mods, jamais la WebView.

Contrat de l'API (côté site)

GET <catalogBase>/api/catalog?kind=mod|skin répond { "items": [ … ] }. Seuls les éléments approuvés sont listés.

Champ Rôle
id slug : 1 à 64 caractères A-Za-z0-9._-, ni . ni - au début, pas de . à la fin ; c'est l'identifiant du mod ou du skin installé
kind mod ou skin (un élément d'un autre type est ignoré)
name, author, version affichés tels quels (version est libre) ; 80, 80 et 32 caractères au plus
seq entier qui croît à chaque version approuvée ; sert à détecter une mise à jour
description, descriptionFr? 600 caractères au plus ; le français lit descriptionFr, les autres langues description
permissions liste de textes (network, stage, skinImport…), affichée avant l'installation d'un mod
sha256, size 64 chiffres hexadécimaux, octets ; vérifiés après le téléchargement
filename informatif (le jeu nomme lui-même son fichier temporaire)
url absolue ou relative au site, sur l'hôte du catalogue seulement (même schéma, même hôte, même port)
updatedAt, screenshots? updatedAt est lu ; screenshots et tout champ inconnu sont tolérés et ignorés

Un élément invalide (slug, empreinte, taille hors bornes — 64 Mio pour un mod, 256 Mio pour un skin —, URL ailleurs, type différent, doublon) est ignoré sans casser la liste. La liste est lue dans 1 Mio au plus, 500 éléments au plus.

Adresse du catalogue

Par défaut https://prism.am. Dans l'ordre : la variable d'environnement PRISM_CATALOG, puis le réglage catalogUrl (Réglages → Bibliothèque → Téléchargements → Catalogue), puis la valeur par défaut.

  • Le réglage exige https ; http n'y est accepté que pour localhost ou une adresse de boucle locale.
  • La variable seule peut nommer un serveur http (par exemple le serveur de test actuel, sans DNS : PRISM_CATALOG=http://15.235.95.198) ; elle autorise alors http et un port, uniquement pour l'hôte nommé.
  • Le réglage catalogUrl n'est jamais exporté avec les réglages.

Ce que fait le réseau

  • La liste est demandée quand l'onglet s'ouvre, jamais avant. Aucun identifiant n'est envoyé (ni cookie, ni jeton, ni identifiant de machine ou de joueur) : seulement Accept et l'agent utilisateur du jeu.
  • Chaque requête porte une HostPolicy limitée à l'hôte du catalogue : redirections suivies à la main, un seul hôte (une redirection vers un autre hôte est refusée), 3 sauts au plus. Pour un catalogue en https public, une adresse privée ou locale est refusée à la résolution comme pour les sources de mods.
  • Délais et tailles bornés ; un catalogue injoignable donne l'état calme « Catalogue indisponible » avec un bouton Réessayer, sans toucher aux autres onglets.

Installation

  1. L'élément est téléchargé dans un fichier temporaire (<data>/catalog-tmp/<n>/…), avec progression et bouton Annuler. Le flux est borné par la taille annoncée.
  2. La taille exacte et le SHA-256 sont vérifiés ; au moindre écart (fichier trop long, trop court, empreinte différente) le fichier est supprimé et l'erreur « ne correspond pas à ce que le catalogue annonçait » s'affiche.
  3. Le fichier vérifié est confié exactement à l'import existant : ModInstaller::install_package pour un .pvmod (ce que fait la page Mods), skin::Library::import pour un skin .zip (ce que fait la page Skins). Toutes leurs validations s'appliquent (zip-slip, plafonds, identifiants).
  4. Le fichier temporaire est supprimé à la fin ; les dossiers oubliés par une interruption le sont à la prochaine ouverture d'un onglet (au bout d'une heure).

Collisions. Un mod de même identifiant est remplacé par l'import existant (c'est sa mise à jour explicite : la confirmation dit la version remplacée). Un skin n'écrase jamais un skin : l'import lui donne un identifiant libre (neon-2) ; une mise à jour de skin s'ajoute donc à côté de l'actuel.

Un mod installé est actif tout de suite (c'est le comportement de l'import .pvmod, disabledMods est vide par défaut). C'est pourquoi la confirmation précède l'installation. Après coup, l'interface le dit (« il est actif : vérifiez-le, ainsi que ses permissions, dans la page Mods ») avec un bouton qui ouvre la page Mods.

Permissions

Pour un mod, les permissions du catalogue s'affichent en badges avec une explication en clair, sur la carte puis dans la confirmation d'installation. Ce sont les permissions annoncées par le site ; ce qui compte est le manifeste du paquet. Une fois installé, le jeu compare : si le paquet déclare une permission que le catalogue n'annonçait pas, l'interface l'écrit (« le paquet demande des permissions que le catalogue n'annonçait pas : … »). Les retraits existants (networkDenied, stageDenied, page Mods) s'appliquent comme pour tout mod.

Installé / Mise à jour

Le jeu garde <data>/catalog-installed.json : pour chaque élément installé depuis le catalogue, l'identifiant local (celui du manifeste d'un mod, celui que l'import a choisi pour un skin), seq et version.

  • Avec ce lien (et tant que l'élément local existe) : mise à jour si seq du catalogue est plus grand.
  • Sans lien (installé à la main) : comparaison des versions quand les deux sont des nombres séparés par des points (1.2.10, un v initial et une fin -pre ou +build sont ignorés) ; sinon l'élément compte comme installé.
  • Aucun élément local de ce nom : disponible.

Interface

CatalogTab.svelte est un composant générique, sans styles par thème : il lit les jetons --pv-* (les huit thèmes et le classique) et réutilise Button, Badge et IconButton. Textes en en/fr/zh (catalog.*).

Tests

  • crates/downloader/src/repository/tests.rs : serveur HTTP local réel et transport réel — liste (champs inconnus, éléments invalides ignorés, rien d'identifiant envoyé), erreurs de liste (500, pas du JSON, trop gros, injoignable, redirection vers un autre hôte), fichier valide avec progression, mauvaise empreinte, fichier trop court ou trop long, 404, redirection vers un autre hôte, annulation, fichier existant jamais écrasé, règles de l'adresse de base.
  • apps/desktop/src/app/hosted.rs (noms de fichiers sûrs sous Windows, registre) et protocol/tests.rs (contrat).
  • apps/web/src/lib/catalog.test.ts (états, versions, langue, permissions) et tests/catalog-tabs.spec.ts (onglets, confirmation, installation, annulation, échec d'intégrité, indisponible, langue ; classic, cabinet, slant).

Ce qui n'est pas vérifié nativement

Le serveur réel (prism.am ou l'adresse de test), l'installation d'un vrai .pvmod ou skin du catalogue dans le jeu lancé, et le rendu dans la vraie WebView ne sont pas exercés : les tests Rust utilisent un serveur local, l'interface est vue avec le mock.

Source dans le dépôt du jeu : docs/catalogue.md