NRF Guide

Commencer

Votre premier mod

Un exemple Kotlin complet : un modèle de signal, une case à cocher et deux indications.

Le fichier Entry.kt

Dans le projet que vous venez de créer, ajoutez src/main/kotlin/Entry.kt. Ce premier signal pédagogique s’ouvre lorsque son canton est connu libre et reste fermé lorsque les données manquent.

src/main/kotlin/Entry.kt
package nimby.mod

import nimby.*

// Les noms décrivent vos indications, pas des codes natifs.
enum class Aspect { Closed, Open }
enum class Reason { Unknown, Disabled, Occupied, Clear }

val firstSignal = signalModel(
    id = "monmod.signal",
    title = "Mon premier signal",
    textures = "mon_premier_signal",
    fallback = Indication(Aspect.Closed, Reason.Unknown)
) {
    val active = checkbox("active", "Activer le signal", defaultValue = true)

    rules {
        when {
            settingsStatus == SettingsStatus.Unavailable -> Indication(Aspect.Closed, Reason.Unknown)
            !enabled(active) -> Indication(Aspect.Closed, Reason.Disabled)
            !fresh || !routeKnown || observation.lampFailed || observation.forcedStop ->
                Indication(Aspect.Closed, Reason.Unknown)
            block == Occupancy.Clear -> Indication(Aspect.Open, Reason.Clear)
            block == Occupancy.Occupied -> Indication(Aspect.Closed, Reason.Occupied)
            else -> Indication(Aspect.Closed, Reason.Unknown)
        }
    }

    // Les deux fichiers SVG sont déclarés dans assets/mod.txt.
    images { indication ->
        when (indication.aspect) {
            Aspect.Closed -> "closed.svg"
            Aspect.Open -> "open.svg"
        }
    }
    driving { indication ->
        when (indication.aspect) {
            Aspect.Closed -> AutomaticDriving.stop()
            Aspect.Open -> AutomaticDriving.clear()
        }
    }
}

// Le mod est le paquet ; le modèle ci-dessus garde ses propres types et règles.
fun createMod(): SignallingMod = signalMod("mon-premier-mod", "Mon premier mod") {
    signal(firstSignal)
}

Créer le signal et ses images

Ajoutez ce catalogue dans assets/mod.txt. La valeur mon_premier_signal correspond au troisième argument de signal dans Entry.kt. Chaque image mentionnée dans le catalogue doit exister dans assets.

assets/mod.txt
[ModMeta]
schema=1
name=Mon premier mod
version=0.1.0
author=Votre nom

[SignalTextures]
id=mon_premier_signal
name_en=Mon premier signal
state=closed.svg
state=open.svg

[SignalTemplate]
name_en=Mon premier signal
kind=path
textures=mon_premier_signal
assets/closed.svg
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="64" viewBox="0 0 32 64"><rect x="6" y="2" width="20" height="48" rx="10" fill="#161616"/><circle cx="16" cy="15" r="7" fill="#ef4444"/><path d="M16 50v14" stroke="#888" stroke-width="4"/></svg>
assets/open.svg
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="64" viewBox="0 0 32 64"><rect x="6" y="2" width="20" height="48" rx="10" fill="#161616"/><circle cx="16" cy="37" r="7" fill="#22c55e"/><path d="M16 50v14" stroke="#888" stroke-width="4"/></svg>

Vous pouvez dessiner vos propres SVG ; conservez leurs noms ou modifiez ensemble le catalogue et images.

Construire votre mod

Terminal à la racine de votre projet
.\gradlew.bat assembleReleaseMod verifyNativeMod

assembleReleaseMod produit le paquet dans build/gradle/mod/release. verifyNativeMod vérifie le chargement, l’arrêt et le rechargement des DLL dans un hôte de diagnostic, sans ouvrir le jeu.

Ajoutez ensuite votre projet dans le profil développeur du Hub, renseignez le même kit Kotlin et construisez puis lancez ce profil. Activez les ressources de votre mod dans le jeu et placez votre signal. La validation du comportement en partie reste une étape distincte.

Lire le code

  • signalModel déclare un modèle, ses enums et ses replis pour les données manquantes.
  • signalMod assemble le paquet ; signal ajoute chaque modèle constructible.
  • checkbox crée un réglage et renvoie une référence utilisable avec enabled.
  • rules reçoit les observations du signal et renvoie une Indication.
  • images choisit l’image ; driving choisit la consigne de conduite.

Le code du mod reste du Kotlin ordinaire. Vous pouvez extraire une règle dans une fonction, utiliser des when et écrire des tests sans connaître l’adaptateur natif.

Construire progressivement