Sur cette page

← Toute la documentation

Écrire un mod pour Prism

Démarrage rapide : le dossier d'un mod, main.ts, un premier HUD, l'installation et l'export.

Guide pour les auteurs de mods tiers, lisible par un humain et par un assistant de code (voir llms.txt : un fichier unique à coller dans un LLM). Tout ce qui est écrit ici est tiré du code de crates/modding et des mods livrés ; ce qui ne l'est pas est marqué [À VÉRIFIER]. La référence historique et détaillée reste Mods TypeScript.

Plan

Document Contenu
Ce fichier Démarrage rapide : dossier, main.ts, hello HUD, installation, export
Concepts : comment fonctionne un mod Cycle de vie, threads et budgets, événements, permissions, erreurs, déterminisme, interdits
Référence de l'API des mods (version 2) Référence par espace de noms, vérifiée contre le SDK
Livre de recettes 17 recettes complètes (jugement, vitesse, HUD, hit bar, modificateur, touche, notes/filtre, stage, stockage, skin, script de map, classement, onglet, source de téléchargement, pont, import de skin)
llms.txt Contexte compact pour assistant IA + modèle de prompt
LACUNES.md Ce que l'API ne permet pas (encore), ou qui surprend

Les deux autres genres de scripts : skins (skin.ts, defineSkin) et scripts de map (defineChart).

Démarrage rapide

1. Le dossier

Un mod est un dossier contenant main.ts (ou index.ts) ; il n'y a pas de manifeste JSON, la seule déclaration est l'appel defineMod.

mon-mod/
  main.ts          point d'entrée obligatoire
  lib/format.ts    modules relatifs importés par main.ts (jamais hors du dossier)
  fonts/Title.ttf  polices déclarées dans `fonts` (.ttf/.otf)
  images/star.png  images PNG (hud.image, stage.sprite)

Un dossier sans main.ts (comme mods/sdk) est ignoré ; un nom qui commence par . aussi. Le nom du dossier n'est pas l'id : l'id vient de defineMod.

2. Un hello HUD (moins de 40 lignes)

/// <reference path="../sdk/modding.d.ts" />

export default defineMod({
  id: "hello-hud",          // a-z, 0-9, ., -, _ ; 1 à 64 caractères ; stable
  name: "Hello HUD",
  version: "1.0.0",         // semver
  apiVersion: 2,            // doit valoir la version de l'API du jeu
  author: "Moi",
  description: "Le combo en gros, et la précision dessous.",
  setup() {
    ctx.on("game.songStart", () => {
      hud.group({
        id: "panel",
        flow: { direction: "column", align: "end", gap: 0.004 },
        layout: { x: 0.98, y: 0.5, anchor: "topRight" },
      });
      // `bind` : la surcouche met la valeur à jour toute seule, sans repasser par le script.
      hud.text({ id: "combo", parent: "panel", text: "", bind: { kind: "combo" }, style: { size: 0.06 } });
      hud.text({ id: "acc", parent: "panel", text: "", bind: { kind: "accuracy", decimals: 2 }, style: { size: 0.03 } });
    });
    ctx.on("game.songEnd", () => hud.clear());
    log.info("Hello HUD chargé");
  },
});

Les longueurs (size, width, gap…) sont des fractions de la hauteur de l'écran ; x/y des fractions du parent (l'écran au premier niveau).

3. Où le mettre

Deux racines, lues dans cet ordre (Créer un mod) :

  1. mods\ à côté de prism.exe (en développement : le dossier mods/ du dépôt) ;
  2. le dossier des mods du joueur : %LOCALAPPDATA%\Prism\PrismNG\data\mods (C:\Users\<utilisateur>\AppData\Local\Prism\PrismNG\data\mods). La variable PRISM_MODS_DIR remplace uniquement cette racine de données.
Copy-Item -Recurse mon-mod "$env:LOCALAPPDATA\Prism\PrismNG\data\mods\"

La page Mods (libellés de l’interface en anglais par défaut : Open folder, Reload, Install…, Export, Uninstall) : Open folder ouvre cette racine ; Reload relit tous les mods sans redémarrer le jeu. Le mod apparaît dans la liste, ses messages (log.info/log.warn) et ses erreurs sous lui. Si deux dossiers déclarent le même id, le premier chargé gagne et un message l'indique.

4. Activer, désactiver, désinstaller

  • Chaque mod a un interrupteur (clavier : Espace) sur la page Mods ; le choix est conservé (Settings.disabledMods) sans désinstaller le mod ni effacer son stockage. Un changement fait pendant une partie attend le retour au menu.
  • Désinstaller supprime le dossier (<dossier des mods>/<id>) ; le stockage du mod est conservé pour une réinstallation. Pour un mod de mods\ à côté de l'exe : le dossier est supprimé s'il est accessible en écriture, sinon une erreur nomme le chemin. Retirer un mod, c'est supprimer son dossier.
  • Installer, exporter, désinstaller et recharger sont refusés pendant une partie.

5. Partager : exporter un .pvmod

Page Mods → Export : une archive ZIP <id>-<version>.pvmod. Pour l'installer : bouton Install…, ou glisser-déposer le fichier sur la fenêtre. Règles (Règles d'un paquet) : fichiers .ts, .ttf, .otf, .png, .json (données), .md, .txt ; 64 Mio au plus, 1024 entrées, 256 fichiers ; main.ts ou index.ts à la racine ; entrées cachées et node_modules ignorées ; liens symboliques et entrées chiffrées refusés. Réinstaller un mod de même id le remplace (mise à jour, réinstallation ou retour en arrière).

Vérifier ses types

Le jeu transpile sans vérifier les types : seule l'exécution (budgets, validations Rust) vous reprend. Pour les types, avec le TypeScript de l'interface :

node apps/web/node_modules/typescript/bin/tsc --noEmit --strict --target es2022 --lib es2022 --module esnext --moduleResolution bundler mods/mon-mod/main.ts

Les déclarations sont mods/sdk/modding.d.ts ; la ligne /// <reference path="../sdk/modding.d.ts" /> suffit (elle n'a aucun effet à l'exécution). Hors du dépôt, copiez le fichier et adaptez le chemin. mods/sdk/modding.ts (modèles typés et raccourcis d’écoute comme onJudgement) est optionnel : un mod qui l'utilise le copie dans son dossier.

Vérifier cette documentation

node scripts/check-modding-docs.mjs            # symboles et recettes vérifiés contre le SDK
node scripts/check-modding-docs.mjs --strict   # + échoue si un type du SDK n'est cité nulle part
node scripts/check-modding-docs.mjs --sdk chemin/modding.d.ts   # contre un autre SDK

Le script échoue si un symbole documenté a disparu du SDK, s'il manque une fonction ou un événement dans Référence de l'API des mods (version 2), ou si une recette ts ne passe plus tsc --strict (TypeScript est cherché avec --tsc, $TSC ou apps/web/node_modules). Après un changement d'API : cargo run -p modding --example write_sdk, puis ce script.

Fonctions récentes

  • Classement local (leaderboard.query, leaderboard.best), onglets de sélection (tabs.register, tabs.extend) et import de skins (skinImport.*, permission skinImport) : dans le SDK d'integration, documentés dans Référence de l'API des mods (version 2).
  • Sources et miroirs de téléchargement (downloads.register, downloads.registerBridge, permission network) : documentés ici d'après la branche feature/mod-download-sources ; ils n'existent dans mods/sdk/modding.d.ts qu'une fois cette branche fusionnée dans integration. Avant cela, le script de vérification se lance avec --sdk <d.ts de la branche>.

Ce qui manque encore est dans LACUNES.md.

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