Créer un mod
Créer un outil avec une fenêtre et une horloge
Un toolMod autonome, sans signal sélectionné : formulaire, événement, confirmation et changement de date.
Ouvrir un outil indépendant des signaux
package nimby.mod
import nimby.*
fun createMod() = toolMod(modInfo) {
metadata(author = "Your name", description = "Read the game clock.")
window("clock", "Clock", shortcut = "F9") { event ->
showWindow(event, clock().dateTime().toString(),
listOf(ToolButton("refresh", "Refresh")))
}
}Préparez le projet avec le guide d’installation : mod.json génère modInfo. Cet outil ne déclare ni signal ni texture. Une partie doit être chargée et observée. Le raccourci ouvre une fenêtre Windows possédée par la fenêtre du jeu ; ce n’est pas un bouton dans sa barre d’outils. La croix ferme la fenêtre, pas le mod.
| Déclaration | Rôle exact |
|---|---|
| window(id, title, shortcut, handler) | id identifie la fenêtre et reste stable ; title nomme la fenêtre et sa ligne de raccourci, et accepte tr ; shortcut vaut F8 s’il est omis. Jusqu’à 8 fenêtres, identifiants et raccourcis non vides distincts. Le joueur peut modifier chaque raccourci dans Options → NRF Hub, rubrique Raccourcis. |
| Ctrl / Alt / Shift · A–Z · 0–9 · F1–F24 | Modificateurs facultatifs dans cet ordre, puis une touche ; les touches nommées comme Enter et PageUp sont aussi disponibles. Vide désactive le raccourci. Le SDK vérifie les conflits avec le jeu et les autres mods, et ouvre l’outil seulement dans un contexte de jeu actif hors saisie de texte. |
| ToolWindowEvent | window identifie la fenêtre, action vaut open à l’ouverture puis l’id du bouton, values contient tous les champs entiers. sequence, worldId et generation identifient la demande et la partie. |
| showWindow(event, message, buttons, inputs) | message au-dessus, puis les champs et boutons. 8 champs et 12 boutons maximum. id reste technique, label est visible ; enabled active ou désactive le contrôle. Le formulaire UTF-8 complet est borné à 8192 octets. |
Les champs numériques acceptent la saisie, l’effacement et le collage. Au clic, toutes les valeurs doivent respecter leurs bornes ; un événement unique transmet le formulaire complet. Il n’y a pas d’événement par touche. Le callback doit rendre la main rapidement ; une perte de partie masque les fenêtres et invalide les événements.
L’exemple propose F9 à la première utilisation. La valeur déclarée dans le code ne remplace pas une préférence compatible déjà choisie par le joueur, y compris un raccourci désactivé. Ne changez pas l’identifiant "clock" pour renommer la fenêtre ou proposer un autre raccourci par défaut.
Le titre, le message, les libellés de champs et les boutons acceptent tr. Une fenêtre déjà ouverte suit le changement de langue du jeu sans nouvel événement open : la saisie en cours, même vide, la sélection du texte et une demande en attente sont conservées. Seul un nouveau showWindow remplace le formulaire par les valeurs que votre mod fournit.
Lire et modifier le calendrier
| Fonction ou type | Contrat |
|---|---|
| clock(): ToolClock | Observation fraîche de la partie courante : utcSeconds est une date Unix en secondes ; elapsedMillis est le temps simulé écoulé en millisecondes. Cette lecture ne capture pas tout le réseau. |
| GameDateTime · ToolClock.dateTime() | Calendrier grégorien UTC, années 1 à 9999, mois 1 à 12. Les jours impossibles sont refusés. Aucun fuseau Windows ni décalage visuel du jeu n’est ajouté. toUtcSeconds et fromUtcSeconds convertissent sans écrire dans le jeu. |
| changeTime(date: GameDateTime, recalculateTrains = false) | Applique la date choisie. Sans recalcul, conserve les positions et translate les échéances relatives. Cela ne simule pas les journées sautées. Les fractions de seconde sont conservées ; la surcharge en secondes UTC reste disponible. |
| recalculateTrains = true | Demande en plus les interventions natives sur les trains. Elles peuvent déplacer les trains et coûter de l’argent. Ce choix doit être explicite dans votre interface. |
| ToolTimeChange(clock, interventions) | Horloge retournée après application et nombre d’interventions natives. Une erreur ou un délai dépassé n’est pas une preuve qu’aucun effet n’a eu lieu. |
val target = GameDateTime(2026, 9, 28, 12, 0, 0)
// Call only after your own confirmation step.
val result = changeTime(target, recalculateTrains = false)
log("Applied UTC=${result.clock.dateTime()}; interventions=${result.interventions}")BB Timechange propose un seul mode : le changement avec interventions natives sur les trains, qui peuvent les déplacer et entraîner des coûts. Son flux est : lire, saisir six champs, afficher les effets, confirmer une seule fois, relire. Le SDK conserve aussi le mode sans intervention pour les autres outils. Le mod consomme la commande avant l’appel natif pour ne jamais la rejouer après une réponse incertaine. Conservez les données et la session de la confirmation, jamais le ToolContext. Remettez les confirmations à zéro à l’arrêt et au changement de partie.