Créer un mod
Où apparaissent les textes et les contrôles ?
Cases, titres, boutons, champs et messages : leur emplacement, leur durée de vie et leurs événements.
Panneau du signal sélectionné
Prérequis : un modèle déclaré avec signalModel. Ses réglages apparaissent sous les propriétés du signal sélectionné, dans un groupe défilant. Les commandes d’outils sont séparées des réglages persistants. Les longs libellés peuvent défiler horizontalement et les aides reviennent à la ligne. L’ordre des cases suit leur déclaration Kotlin.
val automatic = checkbox(
name = "automatic",
label = tr("automatic.label"),
description = tr("automatic.help"),
defaultValue = true
)
rules {
if (!enabled(automatic)) Indication(Aspect.Closed, Reason.Disabled)
else /* votre décision à partir des observations */ null
}| Champ | Emplacement et effet |
|---|---|
| SignalType.title | Titre au-dessus des cases de ce modèle. Accepte tr. Ce n’est pas automatiquement le nom du menu de construction : celui-ci vient de construction.name. |
| Checkbox.name | Clé technique enregistrée pour chaque signal posé. Invisible pour le joueur. Ne la renommez pas selon la langue. |
| Checkbox.label | Texte à côté de la case. Accepte tr. |
| Checkbox.description | Texte d’aide sous la case, avec retour à la ligne. Accepte tr. Une chaîne vide ne crée aucune ligne. Il est visible directement, sans survol. |
| Checkbox.defaultValue | Valeur utilisée avant tout réglage enregistré pour ce signal. Elle ne remplace pas une valeur déjà sauvegardée. |
| Checkbox.onlyWhenEnabled | Si true, la case est présentée uniquement tant que sa valeur est vraie. Utile pour un acquittement ; une fois décochée, elle disparaît. Laisser false pour un réglage ordinaire. |
| enabled(option) / settingsStatus | Vos règles consultent la case ; le SDK ne choisit aucune conséquence. Un signal connu sans valeurs enregistrées reçoit ses défauts et peut être Present. Absent désigne une absence dans le catalogue observé ; Unavailable indique que la lecture ne permet pas de décider et rend l’observation non fraîche. |
Valeur persistante ou champ de formulaire ?
| Besoin | API et durée de vie |
|---|---|
| NumberSetting | Option entière enregistrée pour chaque signal, comme une portée de travaux. Déclarez number(option) dans le modèle et utilisez option.read(settings) dans la règle. Le panneau du signal assure la saisie et la persistance. |
| ToolNumberInput | Champ temporaire du formulaire de votre outil, comme un espacement avant pose. L’événement transmet la valeur ; votre outil garde son brouillon. Ce champ ne crée pas de réglage persistant dans les signaux. |
val range = NumberSetting("workBlocks", "Following blocks",
maximum = 64, defaultValue = 0, visibleWhen = "work")
// Declare number(range) inside your signalModel.
// Read range.read(settings) inside its rules.
val proposedSettings = range.withValue(emptyMap(), 2)NumberSetting accepte de 0 à maximum ; maximum va de 1 à 65535 et le défaut doit être dans cette plage. visibleWhen nomme une case du même modèle : le champ apparaît juste sous cette case lorsqu’elle est cochée. Masquer le champ ne supprime pas sa valeur. Une clé vide affiche le champ sans condition. withValue renvoie une nouvelle carte ; ce n’est pas une écriture dans la partie.
Actions et panneaux d’outils
| Déclaration | Comportement visible et événement |
|---|---|
| SignalAction(id, label, whenMod, service) | Bouton sous les réglages du signal, visible si le mod fournisseur et son service sont disponibles dans la même partie. label est affiché ; id, whenMod et service restent techniques. Aucune dépendance obligatoire entre mods. |
| showPanel(request, message, buttons, inputs) | Remplace le bouton d’origine par un panneau temporaire. message apparaît au-dessus des champs et boutons, avec retour à la ligne. Chaque republication remplace ces contrôles, sans modifier les cases persistantes. |
| ToolButton(id, label, enabled) | label est le texte du bouton. enabled=false empêche son activation. Le clic arrive dans le même service, avec request.action=id et request.value=null. Jusqu’à 12 boutons. |
| ToolNumberInput(id, label, value, minimum, maximum, enabled) | label est affiché au-dessus du champ entier. value est la valeur proposée ; minimum et maximum bornent les valeurs acceptées. enabled=false empêche la saisie. Une édition valide arrive avec action=id et value=nouvel entier. Jusqu’à 4 champs. |
| Saisie incomplète | Un champ vide, invalide ou hors bornes conserve le brouillon et bloque les commandes. Le SDK n’invente pas zéro. Après une édition valide, le mod republie le panneau et invalide son ancien aperçu. |
| request.signalId / worldId / generation | Source de l’action et identité de la partie. Ne réutilisez pas un ticket ou un aperçu après changement de génération. panelToken et originAction relient les clics au panneau d’origine : transmettez la requête reçue. |
Un texte déclaré n’est pas une action automatique : écrire « Fermer » ou « Confirmer » ne ferme ni ne construit rien. Le service doit traiter l’identifiant reçu. Pour fermer, retirez l’aperçu et republiez le bouton d’ouverture ; pour construire, utilisez un ticket et suivez son résultat.
showPanel, showSignalPreview et clearSignalPreview peuvent lever ToolOperationException avec isBusy. Conservez la demande de présentation pour un prochain onTick, sans boucle d’attente. Un refus de publication ne confirme ni le nouveau panneau ni l’aperçu : désactivez localement Appliquer et Annuler jusqu’à une présentation à jour. Un clic déjà reçu doit encore passer vos contrôles de session, source, plan et opération en cours.
Reconstruire un mod complet
Pour une signalisation comparable à AB Signalisation lumineuse : assemblez plusieurs signalModel, chacun avec ses enums, règles, construction, images et driving ; ajoutez les cases propres au modèle, observez l’approche si nécessaire et lisez next avec son type. Les couleurs et les vitesses restent des choix du mod. Les extraits AB Signalisation lumineuse du wiki montrent des usages ciblés sans imposer le téléchargement du projet.
Pour un outil comparable à BA Signal Placement : déclarez toolMod et un service facultatif ; lisez network, calculez les positions en respectant les raccordements et aiguilles, affichez toutes les positions avec showSignalPreview, puis préparez un ticket et relisez le réseau avant confirmation. Suivez Pending avec pollConstruction, utilisez undoConstruction uniquement si canUndo, et remettez à zéro votre état lors d’un changement de partie ou de onStop. Le calcul métier appartient à l’outil.