Source de vérité : mods/sdk/modding.d.ts (généré depuis les contrats Rust par
cargo run -p modding --example write_sdk). Cette page est vérifiée contre ce
fichier par node scripts/check-modding-docs.mjs : chaque symbole en titre
(###) doit exister dans le SDK, et chaque fonction ou événement du SDK doit
apparaître ici. Pour les champs exacts d'un type, le .d.ts fait foi ; pour les
règles détaillées et les limites, voir aussi Mods TypeScript.
Conventions : les temps de chanson sont en microsecondes (timeUs), sauf
Hit.offsetMs (millisecondes réelles). Les longueurs de mise en page et de style
sont des fractions de la hauteur de l'écran. Toute valeur hors bornes lève une
exception dans le script (voir concepts).
Disponibilité par genre de script
Trois genres de scripts partagent la même API : un mod (defineMod, main.ts),
un skin (defineSkin, skin.ts) et un script de map (defineChart,
script.ts). Phases : chargement (premier niveau du fichier), setup, événement.
| Fonction | mod | skin | script de map | Phase |
|---|---|---|---|---|
defineMod / defineSkin / defineChart |
defineMod |
defineSkin |
defineChart |
chargement, une seule fois |
ctx.on |
oui | oui | oui | chargement, setup ; ensuite |
ctx.has, ctx.element |
oui | oui | [À VÉRIFIER] | setup, événement |
game.* (lectures) |
oui | oui | oui | setup, événement |
hud.*, storage.* |
oui | oui | non | setup, événement |
stage.* |
permission stage |
permission stage |
permission stage |
setup, événement |
playfield.*, lanes.set |
non | oui | oui | setup, événement pendant une partie |
judgements.register, scrollSpeed.register, ratings.register, tables.register, library.filters.register, controls.register, gameplay.register |
oui | non | non | setup seulement |
ratings.backfill, metron.performance, ui.popup, ui.dismiss |
oui | non | non | setup, événement |
leaderboard.query, leaderboard.best |
oui | non | non | setup, événement (réponse : leaderboard.result) |
tabs.register, tabs.extend |
oui | non | non | setup seulement |
downloads.register, downloads.registerBridge |
permission network |
non | non | setup seulement |
skinImport.register |
permission skinImport |
non | non | setup seulement |
skinImport.stage, skinImport.create, skinImport.panel, skinImport.close |
permission skinImport |
non | non | setup, événement |
metron.catalog, metron.difficulty |
oui | oui | oui | setup, événement |
log.info, log.warn |
oui | oui | oui | toujours (même au chargement) |
Sources : crates/modding/src/api.rs (for_running, for_mods_and_skins,
playfield_call, fonctions *Register).
Déclaration
defineMod
defineMod(input: ModDefinition): ModManifest. Appelée une fois, au premier
niveau de main.ts, avec export default. Champs : id, name, version,
apiVersion (doit valoir 2), et facultatifs author, description,
homepage, fonts, uses, provides, permissions, images, loadOrder,
setup(mod). Tout champ inconnu est refusé. Règles de chaque champ :
Déclarer le mod : defineMod.
defineSkin
defineSkin(input: SkinDefinition): SkinManifest, dans skin.ts. Mêmes champs
qu'un mod sauf loadOrder ; setup(play: PlayContext). Voir
Skins.
defineChart
defineChart(input: ChartDefinition): ChartManifest, dans script.ts à côté
d'un chart. Champs : apiVersion, permissions?, images?, setup(play). Pas
d'id. Voir Scripts de map.
ctx
Global typé ctx (pas un paramètre : nommez le paramètre de setup play ou
mod, jamais ctx).
ctx.on(event, handler): abonne un gestionnaire à un événement de la liste ci-dessous ; autorisé au premier niveau et danssetup.ctx.has(id): vrai si le paquetid, déclaré dansuses, est présent, compatible et en marche.ctx.element("<paquet>/<élément>").configure(options): configure un élément qu'un autre paquet fournit (provides.elements). Le paquet doit être dansuses, sinon exceptionadd `<paquet>` to `uses` to configure its elements.
Événements
Abonnement : ctx.on("<nom>", handler). Les événements game.* ne sont livrés
qu'aux scripts en marche pendant la partie ; les files sont bornées (1024) et un
événement peut être abandonné si le thread des mods est en retard.
game.songStart
SongStartEvent : song, judgements (JudgementConfig), timeUs (négatif
pendant un pré-roll). Le chart et le playfield deviennent lisibles.
game.judgement
JudgementEvent : column, timeUs, offsetUs (entrée − note ; 0 pour un
miss), tier (TierRef), combo, counts (par palier), accuracy. Les
totaux sont ceux du moteur après cette note.
game.pause
SongTime : { timeUs }.
game.resume
SongTime : { timeUs }.
game.tick
TickEvent : timeUs, hitCount (frappes non-Miss natives, remis à zéro à
chaque partie). 30 Hz, seulement pendant qu'un chart joue sans pause.
game.beat
Beat : index, timeUs, bpm, meterBeat (0 sur le premier temps de la
mesure). Livré à l'heure de chaque battement du chart ; en retard, seulement le
dernier.
game.songEnd
SongEndEvent : counts, maxCombo, accuracy, aborted.
game.playfieldChange
Payload : Playfield (redimensionnement).
game.settingsChange
Payload : ModSettings.
elements.configure
ElementConfigure : element, from ("player" ou l'id du paquet appelant),
options (toutes les options, défauts complétés). Reçu par le fournisseur.
controls.action
ModActionEvent : id (id local déclaré), pressed, timeUs.
library.ready
LibraryReady ({}) : la bibliothèque est chargée (après l'interface et les mods).
library.chartAdd
ChartAdded : { chartId }, un par chart ajouté par un scan.
library.chartsAdded
ChartsAdded : { chartIds, truncated } (8192 au plus) : les mêmes ids en un
seul événement.
ratings.progress
RatingProgress (au mod demandeur seulement) : requestId, id, done,
total, failed, finished, error?, ahead.
metron.performanceResult
PerformanceResult (au mod demandeur seulement) : requestId, calculator,
value?, unit (pp ou SSR), error?.
ui.action
PopupActionEvent : { id } d'une action du popup, ou "dismiss".
leaderboard.result
LeaderboardResult (au mod demandeur seulement) : requestId, chartId,
offset, total, entries (LeaderboardEntry[]), judgement,
performance? (LeaderboardPerformance), unavailableReplays, error?.
skinImport.opened
SkinImportOpened (permission skinImport) : importerId, locale
(en, fr ou zh), source? (SkinSource), error?.
skinImport.staged
SkinImportStaged : requestId, stageId?, report? (Report), error?.
skinImport.created
SkinImportCreated : requestId, id? (id du skin écrit), error?.
skinImport.action
SkinImportAction : { id } d'une action de la carte (skinImport.panel) ou
"dismiss".
Lectures : game.*
Lecture à la demande depuis setup ou un gestionnaire. Jamais au chargement
(is not available while the mod loads).
game.song
game.song(): Song | null : dernière chanson lancée (title, artist,
creator, difficulty, mode, layout, keys, durationUs, noteCount,
holdCount, bpm, timing, ratings indexés par id de calculateur).
game.notes
game.notes(query: NoteQuery): NotePage. fromUs, toUs (tête dans
[fromUs, toUs)), column?, cursor?, limit? (défaut 64, 1 à 256). Pagination
par next. endUs est null pour une note simple ; les mines ne sont pas des notes.
game.hits
game.hits(query: HitQuery): Hit[] : derniers impacts natifs non-Miss, du plus
ancien au plus récent (limit 1 à 256, défaut 50). Hit = { offsetMs, tier }
(offsetMs négatif en avance).
game.playfield
game.playfield(): Playfield | null : keys, lanes ({ column, x, width }),
hitY, spawnY, scrollTimeUs.
game.player
game.player(): PlayerState : playing, paused, timeUs, combo,
maxCombo, counts, judged, accuracy.
game.judgements
game.judgements(): JudgementConfig | null : preset et tiers (TierInfo).
game.settings
game.settings(): ModSettings | null : volume, showFps, scrollTimeMs,
audioOffsetMs, ratingSystem.
HUD : hud.*
Un arbre de nœuds retenu par mod ; un nœud reste jusqu'à hud.remove,
hud.clear ou la désactivation du mod. Limites par mod : 256 nœuds, 256
caractères par texte, id de 1 à 64 caractères, 8 niveaux de groupes.
Réutiliser un id remplace le nœud (même parent). Champs communs de tout
nœud : id, parent?, visible?, layout?, style?, showWhen?, animate?,
element?.
hud.text
hud.text(node: TextNode): string. Champs propres : text, bind?
(TextBinding). Liaisons : combo, maxCombo, hits, misses, judged,
remaining, accuracy (decimals?), ghostAccuracy, ghostDelta, ghostCombo,
ghostName, tierCount (tier), tierName (tier), lastJudgement
(colors?), elapsed, total, timer, fps, label (label: HudLabel),
action (action: "skipIntro"). La surcouche les met à jour sans repasser
par le script.
hud.box
hud.box(node: BoxNode): string. Champ propre : fill? (Fill :
songProgress, accuracy, tierShare + tier) qui rogne la boîte
horizontalement depuis la gauche.
hud.image
hud.image(node: ImageNode): string. src : PNG du dossier du mod (8 Mio au
plus, vérifié à l'appel) ; fit? : contain (défaut), cover, fill.
hud.group
hud.group(node: GroupNode): string. flow? (Flow : direction row |
column, gap?, align?, justify?) dispose les enfants ; sans flow, ils se
placent en fractions du groupe (donnez-lui alors width et height).
hud.update
hud.update(patch: NodePatch): void : modifie un nœud existant ; les champs
donnés de layout et style remplacent ceux du nœud, les autres restent.
text/bind, src/fit, flow, fill ne valent que pour le type de nœud
correspondant.
hud.remove
hud.remove(id: string): void : retire le nœud et ses descendants.
hud.clear
hud.clear(): void : retire tous les nœuds du mod.
Mise en page (Layout) : x, y (fractions du parent, [-10, 10]), width,
height ([0, 4], hauteurs d'écran), anchor (Anchor). Style (Style) :
color, background, gradient, border, radius, padding, opacity,
font, size, weight, italic, align, shadow, transform,
transitionMs. Détail des bornes : HUD.
Couleurs : #rgb, #rgba, #rrggbb, #rrggbbaa.
Rendu natif : stage.*
Exige permissions: ["stage"] (Permission vaut "stage", "skinImport" ou "network") ; le joueur peut la retirer par mod.
Budgets par script : 128 éléments, 16 émetteurs, 1024 particules, 64
déclencheurs. Les éléments sont déclaratifs : animations et déclencheurs sont
évalués par le rendu à chaque image, jamais par le script.
stage.sprite
stage.sprite(input: StageSprite): string : image PNG déclarée dans images.
stage.rect
stage.rect(input: StageRect): string : rectangle plein, radius en hauteurs d'écran.
stage.text
stage.text(input: StageText): string : une ligne (128 caractères) dans la
police du jeu.
stage.emitter
stage.emitter(input: StageEmitter): string : émetteur de particules (burst,
rate, maxParticles, lifetimeMs…).
stage.trigger
stage.trigger(input: StageTrigger): string : on (StageEvent : judgement,
press, release, holdStart, holdEnd), target, play? ou stop?.
stage.play
stage.play(input: StageCue): void : lance une animation depuis un gestionnaire.
stage.stop
stage.stop(input: StageCue): void : l'arrête.
stage.remove
stage.remove(id: string): boolean : retire un élément ou un déclencheur.
stage.clear
stage.clear(): void : retire tout.
Position at (StagePoint) : space (screen défaut, playfield, lane,
receptor), column?, x?, y?. Calques (StageLayer) : below, lanes,
above.
Playfield : playfield.* et lanes.set (skins et scripts de map)
playfield.set
playfield.set(spec: PlayfieldSpec): void : fusionne spec dans le playfield
(au setup). Les champs sont listés dans PlayfieldSpec du SDK ; voir
Référence du playfield.
playfield.update
playfield.update(update: PlayfieldUpdate): void : patch (PlayfieldSpec),
transitionMs? (0 à 10000), easing? (Easing). Animé champ par champ par le
rendu ; aucun appel par image.
lanes.set
lanes.set(update: LaneUpdate): void : column (à partir de 0), lane
(LaneSpec), transitionMs?, easing?.
Jugement : judgements.register
judgements.register
judgements.register(definition: JudgementSetDefinition): void, setup
seulement, 8 jeux par mod. Champs : id (a-z, 0-9, -, 32 au plus), name,
params? (JudgementParam : label, min, max, step, default,
short?), accuracy (SetAccuracy), holds (SetHolds), tiers(params)
(JudgementTiers, synchrone, résolu une fois par combinaison de paramètres juste
après setup). Un palier (JudgementTier) : id, name, color, gradient?,
windowMs? ou earlyMs + lateMs, weight?, breaksCombo?. Du plus serré
au plus large, le Miss en dernier. Règles :
Jeux de jugement,
docs/judgement.md.
Vitesse de défilement : scrollSpeed.register
scrollSpeed.register
scrollSpeed.register(definition: ScrollSpeedDefinition): void, setup
seulement, 8 systèmes par mod. id, name, param (ScrollSpeedParam, comme
JudgementParam), toMs(value, context) (ScrollSpeedToMs) qui renvoie le temps
de défilement en millisecondes ; context.travel (ScrollSpeedContext) est la
distance de référence en hauteurs d'écran. Règles :
Vitesse de défilement.
Modificateurs de jeu : gameplay.register
gameplay.register
gameplay.register(input: GameplayModifierDeclaration): void, setup seulement,
8 par mod. id, name (32), description (200), kind
(GameplayModifierKind : auto, ghost, mirror, random, noLn, fullLn),
group?, icon?, conflictsWith? (8 clés <modId>/<id>). Le comportement est
natif : le script ne fait que déclarer.
Touches : controls.register
controls.register
controls.register(input: ModActionDeclaration): void, setup seulement, 32 par
mod. id, name (64), defaultKey : code physique accepté par le jeu
(KeyH, Digit1, Backquote…, liste : crates/core/src/mode/key-codes.json).
Reçu par controls.action. Échap et F2 restent réservées.
Bibliothèque, tables et notes de difficulté
tables.register
tables.register(input: TableDefinition): void, setup seulement. id,
columns (ColumnDefinition : name, kind number | text, indexed?).
16 tables par mod, isolées par mod ; leurs lignes disparaissent avec leur chart.
ratings.register
ratings.register(input: RatingDeclaration): void, setup seulement, 16 vues
par mod. id, name, calculator, unit, table, column, version,
panels? (RatingPanel : metrics, bars, radar, timeline, au plus 4).
La table doit avoir été déclarée par ce mod, la colonne être numérique,
version égale à celle de metron.catalog().
ratings.backfill
ratings.backfill(input: BackfillRequest): number | null : demande le calcul des
charts manquants ou périmés (charts? restreint à des ids). Renvoie un id de
demande (null quand le mod a déjà 2 demandes en cours) ; la progression arrive par ratings.progress.
library.filters.register
library.filters.register(input: LibraryFilterDeclaration): void, setup
seulement, 32 par mod. id, name, table, column, version, unit?. Table
déjà déclarée par ce mod.
metron.catalog
metron.catalog(): MetronCatalog : calculators (MetronCalculator : id,
performance, version).
metron.difficulty
metron.difficulty(input: CalculatorRequest): number | null : valeur native
préchargée du chart courant, null si absente.
metron.performance
metron.performance(input: PerformanceRequest): number | null : calculator,
accuracy (fraction [0, 1]). Renvoie un id de demande (null si le service
est occupé) ; le résultat arrive par metron.performanceResult. Seuls osu-2018
(pp) et etterna-515 (SSR) ont une performance.
ui.popup
ui.popup(input: PopupDefinition): void : fenêtre de progression du menu
(title, detail, done, total, actions? jusqu'à 4 PopupAction { id, label }).
Un popup ouvert par mod, 8 au total ; le texte n'est jamais du HTML.
ui.dismiss
ui.dismiss(): void : ferme le popup du mod.
Classement local : leaderboard.*
Lecture seule du classement local d'un chart, sans permission : typée, bornée,
asynchrone (sources : Classement local : leaderboard.*,
crates/modding/src/leaderboard.rs, api.rs). chartId est l'identifiant de
chart de la bibliothèque (library.chartAdd, library.chartsAdded). Réservé aux
mods ; jamais de chemin, de fichier ni d'entrée de replay.
leaderboard.query
leaderboard.query(input: LeaderboardQuery): number | null : chartId, limit?
(1 à 100, 20 par défaut), offset? (0 à 100 000). Renvoie un numéro de demande,
ou null quand elles s'accumulent (2 en attente par mod, 16 en tout) ; la
réponse arrive par l'événement leaderboard.result. Chaque demande rejuge le
chart : lisez une page à la fois.
leaderboard.best
leaderboard.best(input: LeaderboardBestQuery): number | null : { chartId }.
Équivaut à query avec limit: 1 : le rang 1 du classement entier (replays
importés compris, received).
Une LeaderboardEntry : rank (à partir de 1), replayId, playerName? (null
pour un ancien replay sans nom), received, accuracy (pourcent),
performance? (null si non calculable), performanceNonstandard, maxCombo,
misses, tiers (TierCount[] : { name, count }), rate, modified,
playedAtMs. Le classement est celui de l'interface : replays rejugés avec le
jugement courant du joueur, classés par performance.
Onglets de la sélection : tabs.*
Déclaratif : un mod ajoute un onglet au panneau du chart choisi, ou des
sections aux onglets existants ; Rust valide tout, l'interface rend de façon
générique (aucun balisage du mod). setup seulement, mods seulement (sources :
Onglets dans la sélection : tabs.*, tabs.rs).
tabs.register
tabs.register(input: TabDeclaration): void : id, title (1 à 24 caractères),
icon? (liste fermée de 16 icônes lucide : layers, info, trophy, star,
gauge, activity, chart-bar, list, flame, music, clock, target,
sparkles, bookmark, heart, users), order? (0 à 1000), panels
(1 à 8 TabPanel). 4 onglets par mod, 12 en tout.
tabs.extend
tabs.extend(input: TabExtensionDeclaration): void : tab (ExtendableTab :
info, leaderboard, mods), slot (TabSlot : top | bottom), order?,
panels (1 à 4). Ajoute avant ou après le contenu de l'hôte, sans jamais le
retirer. 4 extensions par mod, 24 en tout.
Panneaux (TabPanel) : metrics, bars (max?), radar (max?) avec des
TabField (label, source, unit?, decimals?), timeline (comme les
notes), leaderboard (title, limit 1 à 10 : le classement déjà évalué de
l'onglet Leaderboard) et text (title?, text 1 à 280 caractères, sans
balisage). Sources d'un champ (TabFieldSource) : { kind: "column", rating, column } (colonne numérique de la table d'une vue de difficulté déclarée
par le même mod avec ratings.register, avant), { kind: "chart", metric }
(ChartMetric), { kind: "leaderboard", stat } (LeaderboardStat : plays,
bestPerformance, bestAccuracy). Les onglets suivent le mod en direct.
Téléchargements : downloads.*
Permission network. Exige permissions: ["network"] ; setup seulement ; le joueur peut retirer la
permission mod par mod et voit les hôtes déclarés. Le script ne fait jamais
de réseau : l'hôte (crates/downloader) envoie toutes les requêtes, HTTPS et
hôtes déclarés seulement, et garde le jeton du joueur hors de portée du script.
Sources : Téléchargements : downloads.register et
Mods et téléchargements de la branche feature/mod-download-sources,
crates/modding/src/downloads.rs (4 déclarations par mod, 64 en tout).
downloads.register
downloads.register(input: DownloadDeclaration): void : source déclarative
(données seulement). Champs : id, name, description?, site?, kind
(DownloadKind : mirror = un miroir de plus pour les beatmapsets osu!,
target: "osu" ; source = un onglet de plus dans Télécharger), hosts (1 à 8
noms DNS exacts en minuscules), rateLimit? (requêtes par minute, 1 à 120, 30 par
défaut), auth? (DownloadAuth : kind none | token, header?, scheme?,
scope? download | all ; le jeton est saisi par le joueur), search?
(SearchSpec : url, params, sorts, statuses, paging, response) et
download (DownloadSpec : url avec {id}, ou urlField = chemin JSON de
l'URL). Modèles d'URL : variables fermées {query}, {status}, {sort},
{offset}, {page}, {limit}, {cursor}, {keysMin}, {keysMax}, {starsMin},
{starsMax}, {bpmMin}, {bpmMax}, {lengthMin}, {lengthMax}, {genre},
{language} ; un groupe [ …] n'est écrit que si toutes ses variables ont une
valeur. Réponses : chemins JSON simples (ItemSpec, DifficultySpec, OnlySpec,
ResponseSpec avec format osu | mapped, PagingSpec offset | page |
cursor).
downloads.registerBridge
downloads.registerBridge(input: BridgeDefinition): void : pour une API que les
données ne décrivent pas (POST, XML/HTML, enchaînement recherche → détail →
fichier). Des fonctions pures et synchrones calculent la prochaine étape
(BridgeStep), l'hôte fait la requête puis rappelle le mod :
search(query, page, state)(BridgeSearch) : première page,pagevaut 1 ;onResponse(response, state)(BridgeOnResponse) :responseest unBridgeResponse(status,headers,text) ;action?(result, actionId, state)(BridgeAction) : clic sur un bouton d'un résultat (BridgeActionResult).
Une étape (BridgeStep) contient une de : request (BridgeRequest : url,
method GET | POST, headers?, body?, form?, json?, expect? json |
text | xml | html), results (BridgeResult[] : id, title, artist,
creator?, coverUrl?, tags?, size?, keyCount?, details?
(ResultDetail), actions? (ResultAction), data?), download
(BridgeDownload : url, method?, headers?, body?, form?, json?,
filename?, format BridgeFormat : zip | osz | qp) ou error ; plus
nextPage? et state? (JSON rendu tel quel à l'appel suivant). Bornes : 6
requêtes par recherche ou action, 60 s, 2 Mio de texte par réponse. Une
exception, un résultat non JSON ou un dépassement de budget désactive le pont.
BridgeDeclaration est la forme sans les fonctions.
Import de skins : skinImport.*
Permission skinImport. Un mod avec permissions: ["skinImport"] propose de convertir un skin osu!
(dossier ou .osk) en skin de Prism. Il ne touche ni fichier ni pixel : l'hôte lit,
transforme les images, écrit le dossier ; le mod ne donne que des valeurs.
Mods seulement ; register en setup, le reste en gestionnaire. Sans la
permission : `skinImport` needs the `skinImport` permission. Exemple complet :
mods/skin-converter (pvng.skin-converter). Source : Convertir un skin osu! : la permission skinImport,
docs/convertisseur-skin-osu.md, crates/modding/src/importers.rs.
skinImport.register
skinImport.register(input: ImporterDeclaration): void : id, name,
description?, localized? (ImporterText par langue), sources
(SourceKind[] : folder, archive). Ajoute une carte sur la page Skins ; 4
importeurs par mod. Le bouton ouvre le dialogue de fichier du jeu.
skinImport.stage
skinImport.stage(input: StageRequest): number | null : sourceId, skin
(SkinDescription : id, name, version?, author?, description?,
playfield?, layouts (SkinLayout : keys, playfield?, lanes), hud?
(SkinHud)), images (ImageOp[] : source, dest, animation?, frame?,
padTop?, padBottom?, fit? (ImageBox), stretch? (ImageSize)). L'hôte
valide, transforme et répond par skinImport.staged (Report : fichiers
StagedFile, totalBytes, budgetBytes, overBudget, problems).
skinImport.create
skinImport.create(input: SkinImportCreate): number | null : { stageId } ;
l'hôte écrit un skin.ts lisible dans <données>/skins/ (jamais en remplaçant un
skin existant) et répond par skinImport.created.
skinImport.panel
skinImport.panel(input: ImportPanelDefinition): void : carte déclarative (texte
seulement) : title, status (PanelStatus : working, ready, done,
error), detail?, sections? (PanelSection : heading, rows de
PanelRow { label, value }), notes? (PanelNote : level NoteLevel
info | warning | error, text), actions? (PanelAction : id, label,
primary?, editSkin? = id d'un skin créé par ce mod, ouvre l'éditeur). Bornes :
6 sections de 24 lignes, 48 notes, 4 actions.
skinImport.close
skinImport.close(): void : retire la carte.
La source lue (SkinSource) : sourceId, label, kind, ini? (SkinIni :
general IniGeneral, mania ManiaSection[] de ManiaColumn, fontsUsed,
problems), images (SourceImage : nom normalisé, frames, hasStill,
scale, dimensions, bytes, blank?, peakColor?, peakWidth?),
truncated, totalBytes, problems.
Stockage : storage.*
Fichier JSON propre au mod ; 256 Kio, 256 clés de 1 à 128 caractères ; écrit au plus une fois par seconde.
storage.get
storage.get(key: string): unknown | null.
storage.set
storage.set(entry: StorageEntry): void : { key, value }, valeur JSON.
storage.remove
storage.remove(key: string): void.
storage.keys
storage.keys(): string[] : clés triées.
storage.clear
storage.clear(): void.
Journal : log.*
log.info
log.info(text: string): void : message affiché sous le mod dans la page Mods
(1024 caractères au plus, 256 messages en file).
log.warn
log.warn(text: string): void : idem, niveau avertissement.
Types secondaires
Types du SDK que les sections ci-dessus citent sans les détailler (le .d.ts
donne chaque champ) :
| Type | Sens |
|---|---|
Animate |
{ on: AnimateOn, kind: AnimateKind, durationMs } : animation de nœud HUD ; AnimateOn = judgement | miss | hit, AnimateKind = pop | popFade | flash ; durée 1 à 5000 ms |
Border |
{ width, color } (bordure pleine d'un nœud) |
Gradient, GradientStop |
{ angle, stops } (2 à 8 arrêts { color, at }, at dans [0, 1]) |
Shadow |
{ x, y, blur, color } |
Transform |
{ x?, y?, scale?, rotate? } appliqué après le placement |
TextAlign |
start | center | end |
ShowWhen |
paused | running | showFps | judged | ghost |
HudElement |
nom d'élément standard dont le joueur change la police : fps, accuracy, hits, misses, combo, timer, remaining, status, judgement, judgementCounts |
HudAction |
skipIntro (liaison action) |
ImageFit |
contain | cover | fill |
FlowDirection, FlowAlign, FlowJustify |
champs de Flow : row | column ; start | center | end | stretch ; start | center | end | spaceBetween |
Lane |
{ column, x, width } d'un Playfield |
Note |
{ index, column, timeUs, endUs? } d'une NotePage |
TimingPoint, BpmRange |
{ timeUs, bpm, beatUs, meter } ; { min, max, main } (dans Song) |
HitList |
Hit[] |
HostEvents |
table nom d'événement → payload qui type ctx.on |
Dependency, DependencySpec |
valeur de uses : intervalle semver, ou { version, required?, feature? } |
Provides, ElementDeclaration, OptionKind |
provides.elements ; { root?, options? } ; number | integer | boolean | string | color | enum | colors |
ModSetup, SkinSetup, ChartSetup |
signatures de setup (ModManifest / PlayContext) |
SetDeclaration, ScrollSpeedDeclaration |
formes de déclaration sans la fonction (tiers, toMs) |
ColumnKind |
number | text (colonne de table) |
ChartMetric |
notes, holds, holdPercent, averageNps, peakNps, bpmMin, bpmMax, duration |
RatingField, RatingFieldSource, RatingSeries, RatingSeriesSource |
champs et séries d'un RatingPanel : { label, source, unit?, decimals? }, { kind: "column" } ou { kind: "chart" }, density | bpm |
SpriteSize |
{ width, height } (hauteurs d'écran) |
PlayfieldAnchor, ScrollDirection, HitLightOn, TextureFilter, JudgementLineAt, MeasureLineLength, HoldMissedStyle |
énumérations de PlayfieldSpec et LaneSpec |
StageAlign, StageSpace, StageSize, StageProps, StageAnimation, StageJudgementFilter, StageColumn |
pièces de stage.* : alignement, repère, taille, propriétés animées (x, y, scale, rotation, opacity, color), animation { durationMs, easing?, repeat?, from?, to? }, filtres de déclencheur |
AuthKind, AuthScope |
DownloadAuth.kind : none | token ; scope : download | all |
DownloadTarget, PagingKind, ResponseFormat |
osu (seule cible de miroir) ; offset | page | cursor ; osu | mapped |
BridgeMethod, BridgeExpect |
GET | POST ; json | text | xml | html |