Reference
Observation
Observed trains, tracks, signals, services, clock and collections.
Usage context
| Module | Package | SDK source |
|---|---|---|
| Kotlin/JVM | fr.nimby.sdk | kotlin-client/src/main/kotlin/fr/nimby/sdk/Observation.kt |
Public API for SDK 0.9.0-alpha.2. Each entry provides the Kotlin signature and its contract: what the value means, conditions of use and effects to understand. Choose imports from the module shown above.
import fr.nimby.sdk.Train
import fr.nimby.sdk.Position
import fr.nimby.sdk.Track
import fr.nimby.sdk.Station
import fr.nimby.sdk.TrackNode
import fr.nimby.sdk.TrackJunction
import fr.nimby.sdk.TrackUsage
import fr.nimby.sdk.Signal
import fr.nimby.sdk.Service
import fr.nimby.sdk.TrainDetails
import fr.nimby.sdk.Platform
import fr.nimby.sdk.LineStop
import fr.nimby.sdk.SimulationClock
import fr.nimby.sdk.SimulationTimeChange
import fr.nimby.sdk.Observation
import fr.nimby.sdk.ObservationClient
import fr.nimby.sdk.GameProcess
import fr.nimby.sdk.GameProcesses
import fr.nimby.sdk.SdkExceptionChoose a read and interpret its results
In a mod, use ToolContext.trains(query). In a JVM application, use game.trains.snapshot(query = query); selecting a train also requests its line plan. One query batches all trains: do not create a snapshot per train. Clock reads and targeted single-train reads are separate.
| TrainQuery option | Default | Requested data |
|---|---|---|
| includeService | true | Observed state, service and assignment. |
| includeLocations | true | Positions and required location references. |
| includeCharacteristics | false | Configured and current material profiles. |
| includeTimetables | false | Available timetable information; implies includeService. |
| includeTags | false | Declared tags and inheritance references; implies includeLines. |
| includePassengers | false | Observed occupants, distinct from capacity. |
| includeLines | false | Line catalog, including lines with no assigned train. |
| includeComposition | false | Ordered vehicles of configured and current compositions and referenced models. |
| Value | Unit and contract |
|---|---|
| Train.speedMps / Train.speedKmh | Current speed. Native: an unavailable measurement remains null. JVM: also check speedDefaulted before treating a fallback value as a measurement. |
| maximumSpeedMps / maximumSpeedKmh | Material maximum speed, in m/s or km/h; distinct from current speed and the track speed limit. |
| lengthM / emptyMassKg / maximumAccelerationMps2 | Metres, kilograms, metres per second squared. |
| powerW / tractiveForceN | Watts and newtons. |
| passengers / passengerCapacity / carCount | Occupants, capacity and vehicle count: three distinct quantities. |
| configured / current / composition | Independent profiles, without filling missing values from one another. Null composition: unknown or unrequested; empty list: observed empty composition. |
| predictedArrivalDelayUs / predictedArrivalDelaySeconds | Signed estimate in microseconds or seconds; negative for predicted early arrival. Neither deadline age nor priority. |
| arrivalOffsetSeconds / departureOffsetSeconds | Validated offsets in seconds from the line-plan origin. Do not convert them into a train’s absolute date. |
| arrivalTimeUs / departureTimeUs / dispatchRetryTimeUs | Microseconds from the simulation origin, not 1970. Use calendar helpers; dates remain null when the origin is unknown. |
| capturedAtMillis / ageMillis | Computer UTC time / monotonic age when copying; distinct from the game calendar. |
Typed identifiers are opaque. TimetableShiftId is unique only together with its TimetableId. LineType distinguishes only Depot and Other; no passenger/freight category is inferred. An unavailable timetable name remains null. Tags are labels without automatic priority; incomplete or cyclic inheritance remains unknown. VehicleModel.nameEnglish retains the English catalog name.
TrainVehicle describes a vehicle within a composition. The nimby.Vehicle type used in driving calculations is a different contract. Do not mix identically named classes from nimby and fr.nimby.sdk.
Train
data class Train(val id: Long, val name: String, val position: Position?, val speedKmh: Double?, val speedDefaulted: Boolean)Basic train observation in a JVM snapshot. Use snapshot.train(trainId) to join service, locations and metadata from that same snapshot.
Train.id
val id: LongOpaque value to compare and pass unchanged; do not decode it or reuse it in another game.
Train.name
val name: StringObserved train name; renames do not change its identity.
Train.position
val position: Position?Observable position; null when unavailable.
Train.speedKmh
val speedKmh: Double?Measured speed in km/h; null for unavailable or fallback measurements.
Train.speedDefaulted
val speedDefaulted: BooleanIndicates a fallback game speed. Measured speed remains unknown in this case; it does not prove a stop.
Train.trainId
val trainId: TrainIdThe same identity as a TrainId.
Position
data class Position(val trackId: Long, val fraction: Double, val direction: Int)Position on a track: longitudinal fraction and direction. For construction, use observed identities and a fraction strictly inside the track.
Position.trackId
val trackId: LongOpaque value to compare and pass unchanged; do not decode it or reuse it in another game.
Position.fraction
val fraction: DoubleLongitudinal fraction: 0 at track origin, 1 at its end. Direction does not change this origin.
Position.direction
val direction: IntObserved direction; -1 or 1 required for construction. Do not infer a geographic orientation from this value.
Position.track
val track: TrackIdThe same identity as a TrackId.
Track
data class Track(val id: Long, val stationId: Long?, val speedLimitKmh: Double)Observed track with its possible station and speed limit. Its length belongs to TrackMetric.
Track.id
val id: LongOpaque value to compare and pass unchanged; do not decode it or reuse it in another game.
Track.stationId
val stationId: Long?Observed associated station, when available.
Track.speedLimitKmh
val speedLimitKmh: DoubleTrack speed limit in km/h, distinct from the material limit.
Track.trackId
val trackId: TrackIdThe same identity as a TrackId.
Track.station
val station: StationId?stationId in typed form; null if no identity is available.
Station
data class Station(val id: Long, val name: String)Station from the copied catalogue. Use its identity for joins and its name for display.
Station.id
val id: LongOpaque value to compare and pass unchanged; do not decode it or reuse it in another game.
Station.name
val name: StringStation name copied during capture.
Station.stationId
val stationId: StationIdThe same identity as a StationId.
TrackNode
data class TrackNode(val id: Long, val linkA: Long?, val linkB: Long?, val x: Double, val y: Double)Element of the observed track graph. Links may be incomplete or non-reciprocal; they prove neither switch state nor a reserved route.
TrackNode.id
val id: LongOpaque value to compare and pass unchanged; do not decode it or reuse it in another game.
TrackNode.linkA
val linkA: Long?Observed link on side A; null means unknown/absent, not a proven buffer stop.
TrackNode.linkB
val linkB: Long?Observed link on side B; null means unknown/absent, not a proven buffer stop.
TrackNode.x
val x: DoubleProjected game coordinate; not longitude or track length.
TrackNode.y
val y: DoubleProjected game coordinate; not latitude or track length.
TrackJunction
data class TrackJunction(val branchTrackId: Long, val mainTrackId: Long, val fraction: Double, val mainDirection: Int, val branchDirection: Int)Observed branch attachment to a main track. Describes connection geometry without guaranteeing passage permission.
TrackJunction.branchTrackId
val branchTrackId: LongBranch-track identity.
TrackJunction.mainTrackId
val mainTrackId: LongMain-track identity.
TrackJunction.fraction
val fraction: DoubleAttachment fraction on the main track.
TrackJunction.mainDirection
val mainDirection: IntDirection approaching the attachment on the main track.
TrackJunction.branchDirection
val branchDirection: IntDirection leaving the attachment onto the branch, without reversal.
TrackUsage
data class TrackUsage(val trainId: Long, val trackId: Long, val from: Double, val to: Double)Observed reservation or occupation interval, according to its source table. Intervals may overlap; this is neither a permission nor an ordered route.
TrackUsage.trainId
val trainId: LongTrain associated with this interval.
TrackUsage.trackId
val trackId: LongTrack carrying this interval.
TrackUsage.from
val from: DoubleLower track-fraction bound; less than or equal to to.
TrackUsage.to
val to: DoubleUpper track-fraction bound; does not indicate travel direction.
Signal
data class Signal(val id: Long, val position: Position, val kind: Int, val textureState: Int?, val specificState: String?, val texturePath: String?)Copied signal with its position and available display information. An image is not proof of movement permission.
Signal.id
val id: LongOpaque value to compare and pass unchanged; do not decode it or reuse it in another game.
Signal.position
val position: PositionObserved signal position.
Signal.kind
val kind: IntKind code reported by the game; do not confuse it with aspect or priority.
Signal.textureState
val textureState: Int?Observed image index, when available; belongs to the signal catalogue.
Signal.specificState
val specificState: String?Observed specific state in system:state form; null when unavailable.
Signal.texturePath
val texturePath: String?Observed image path; null when unavailable. Does not describe a driving rule.
Service
data class Service(
val trainId: Long, val lineName: String?, val status: Int?, val stationId: Long?, val flags: Int,
val lineId: Long? = null, val stopStationId: Long? = null, val stopIndex: Int? = null,
val gameEpochSeconds: Long? = null, val gameTimeUs: Long? = null,
val arrivalTimeUs: Long? = null, val departureTimeUs: Long? = null, val dispatchTimeUs: Long? = null,
val motionFlags: Int? = null, val alert: Int? = null, val locationTrackId: Long? = null,
val stopTrackId: Long? = null, val lineKind: Int? = null,
val arrivalRemainingSeconds: Double? = null, val departureRemainingSeconds: Double? = null,
val dispatchRemainingSeconds: Double? = null,
)Copied service data. Use state, alertState, hidden, onNetwork and converted dates to interpret results; raw values remain available for diagnostics.
Service.trainId
val trainId: LongOpaque value to compare and pass unchanged; do not decode it or reuse it in another game.
Service.lineName
val lineName: String?Optional observed line name.
Service.status
val status: Int?Observed state code; prefer the typed state property.
Service.stationId
val stationId: Long?Service-location station identity when available; distinct from stopStationId.
Service.flags
val flags: IntAvailability indicators for this record. Prefer optional and typed properties in application logic.
Service.lineId
val lineId: Long? = nullOptional service-line identity.
Service.stopStationId
val stopStationId: Long? = nullOptional target-stop station identity.
Service.stopIndex
val stopIndex: Int? = nullZero-based current stop index; null when unknown.
Service.gameEpochSeconds
val gameEpochSeconds: Long? = nullUTC simulation-calendar origin in seconds since 1970; null when unknown.
Service.gameTimeUs
val gameTimeUs: Long? = nullObserved counter in microseconds from the simulation origin; not a Unix date.
Service.arrivalTimeUs
val arrivalTimeUs: Long? = nullOptional active arrival deadline in microseconds from the simulation origin.
Service.departureTimeUs
val departureTimeUs: Long? = nullOptional active departure deadline in microseconds from the simulation origin.
Service.dispatchTimeUs
val dispatchTimeUs: Long? = nullDispatch-retry deadline in microseconds from the simulation origin.
Service.motionFlags
val motionFlags: Int? = nullObserved presence indicators; prefer hidden and onNetwork.
Service.alert
val alert: Int? = nullObserved alert code; prefer alertState.
Service.locationTrackId
val locationTrackId: Long? = nullOptional service-location track; distinct from the train’s geometric position.
Service.stopTrackId
val stopTrackId: Long? = nullOptional target-stop track.
Service.lineKind
val lineKind: Int? = nullRaw line classification; prefer isDepotLine or Line.type.
Service.arrivalRemainingSeconds
val arrivalRemainingSeconds: Double? = nullSeconds remaining to the arrival deadline; may be negative. Not predicted commercial delay.
Service.departureRemainingSeconds
val departureRemainingSeconds: Double? = nullSeconds remaining to the departure deadline, clamped to zero; null when unknown.
Service.dispatchRemainingSeconds
val dispatchRemainingSeconds: Double? = nullSeconds remaining before a dispatch retry, clamped to zero; null when unknown.
Service.train
val train: TrainIdTyped identity of this service’s train.
Service.line
val line: LineId?lineId in typed form, without another read.
Service.state
val state: TrainState?Typed state derived from the observed code; null remains unavailable, an unrecognised code becomes Other.
Service.alertState
val alertState: TrainAlert?Typed alert derived from the observed code; null remains unavailable.
Service.onNetwork
val onNetwork: Boolean?Optional reported network presence; does not prove permission.
Service.isDepotLine
val isDepotLine: Boolean?true for a depot line, false for another known classification; null when unknown.
Service.observedAt
val observedAt: java.time.Instant?Observed counter converted to the game UTC calendar; null if origin/counter is missing or conversion is out of range.
Service.arrival
val arrival: java.time.Instant?UTC date of the active arrival deadline. null if conversion is impossible; not necessarily the commercial timetable.
Service.departure
val departure: java.time.Instant?UTC date of the active departure deadline. null if conversion is impossible; not necessarily the commercial timetable.
Service.dispatchRetry
val dispatchRetry: java.time.Instant?UTC dispatch-retry date; not a commercial departure time. null when not convertible.
TrainDetails
data class TrainDetails(val trainId: Long, val passengers: Int?, val scheduleId: Long?, val shiftId: Long?,
val orderIndex: Int? = null, val orderMode: Int? = null)Assignment and occupants copied according to requested groups. Typed properties do not calculate a next scheduled time.
TrainDetails.trainId
val trainId: LongOpaque value to compare and pass unchanged; do not decode it or reuse it in another game.
TrainDetails.passengers
val passengers: Int?Observed occupants; null when unknown or unrequested. Not capacity.
TrainDetails.scheduleId
val scheduleId: Long?Opaque assigned timetable identity; null when unavailable.
TrainDetails.shiftId
val shiftId: Long?Shift key within scheduleId; do not compare it alone across timetables.
TrainDetails.orderIndex
val orderIndex: Int? = nullObserved zero-based order index; null when unavailable.
TrainDetails.orderMode
val orderMode: Int? = nullObserved order mode; prefer isMothballed for mothballing.
TrainDetails.train
val train: TrainIdTyped train identity.
TrainDetails.timetable
val timetable: Timetable?Timetable built from scheduleId, with identity only; null if scheduleId is missing.
TrainDetails.shift
val shift: TimetableShiftId?Composite identity available only when timetable and shift key are known.
TrainDetails.isMothballed
val isMothballed: Boolean?Indicates mothballing from a known order mode; null when uninterpretable.
Platform
data class Platform(val trackId: Long, val stationId: Long?, val name: String?)Platform information associated with a track. A missing name does not imply an absent platform.
Platform.trackId
val trackId: LongObserved track associated with the platform.
Platform.stationId
val stationId: Long?Associated station, when known.
Platform.name
val name: String?Optional observed platform name.
LineStop
data class LineStop(val lineId: Long, val trackId: Long, val stationId: Long?, val index: Int, val arrivalOffsetSeconds: Int?, val departureOffsetSeconds: Int?)Stop or waypoint in a line plan; times are offsets relative to the plan, not absolute dates for the selected train.
LineStop.lineId
val lineId: LongOpaque value to compare and pass unchanged; do not decode it or reuse it in another game.
LineStop.trackId
val trackId: LongStop-track identity.
LineStop.stationId
val stationId: Long?Stop station; null for a waypoint outside stations or unknown data.
LineStop.index
val index: IntZero-based stop index in the line plan.
LineStop.arrivalOffsetSeconds
val arrivalOffsetSeconds: Int?Arrival offset in seconds from the plan origin; null when unknown. Not an absolute train date.
LineStop.departureOffsetSeconds
val departureOffsetSeconds: Int?Departure offset in seconds from the plan origin; null when unknown.
LineStop.line
val line: LineIdTyped line identity.
LineStop.track
val track: TrackIdTyped track identity.
LineStop.station
val station: StationId?Typed station identity when known.
LineStop.plannedDwellSeconds
val plannedDwellSeconds: Long?departureOffsetSeconds minus arrivalOffsetSeconds, in seconds; null if either offset is missing.
SimulationClock
data class SimulationClock(val epochSeconds: Long, val ticks: Long)Copied simulation-calendar clock. Combine origin and counter with toInstant; do not confuse it with computer time.
SimulationClock.epochSeconds
val epochSeconds: LongGame-calendar origin in UTC seconds since 1970; may precede 1970.
SimulationClock.ticks
val ticks: LongSimulation counter in hundredths of a second from the origin; must be nonnegative for toInstant.
SimulationClock.toInstant
fun toInstant(): java.time.InstantAdds origin and ticks while preserving hundredths. Rejects negative ticks and out-of-range dates; no game read.
SimulationTimeChange
data class SimulationTimeChange(val clock: SimulationClock, val interventions: Long)Result of an explicit date change. Contains the returned clock and intervention count for the requested recalculation.
SimulationTimeChange.clock
val clock: SimulationClockClock returned after the command; read again later for new state.
SimulationTimeChange.interventions
val interventions: LongRecalculation intervention count; zero when no recalculation was requested.
Observation
data class Observation(
val capturedAtMillis: Long,
val processId: Int,
val gameHash: String,
val trains: List<Train>,
val tracks: List<Track>,
val stations: List<Station>,
val nodes: List<TrackNode>,
val junctions: List<TrackJunction>,
val signals: List<Signal>,
val services: List<Service>,
val details: List<TrainDetails>,
val platforms: List<Platform>,
val reservations: List<TrackUsage>?,
val occupations: List<TrackUsage>?,
val selectedPath: List<Long>?,
val lineStops: List<LineStop>?,
val clock: SimulationClock?,
val trackMetrics: List<TrackMetric>? = null,
val lines: List<Line>? = null, val tags: List<Tag>? = null, val trainMetadata: List<TrainMetadata>? = null,
val vehicleModels: List<VehicleModel>? = null,
)Set of copied values, retainable after closing. Contents depend on capture mode and requested groups. Local joins refresh nothing; a snapshot does not guarantee an atomic tick.
Observation.capturedAtMillis
val capturedAtMillis: LongComputer UTC timestamp in milliseconds since 1970. It does not measure simulation time.
Observation.processId
val processId: IntPID of the game supplying this snapshot; explicitly choose the game when connecting.
Observation.gameHash
val gameHash: StringObserved game-binary fingerprint, useful for compatibility diagnostics; not a save identity.
Observation.trains
val trains: List<Train>Basic observations of trains in the batch; selectedTrain does not filter this list.
Observation.tracks
val tracks: List<Track>Tracks requested by capture mode. A specialised query without locations can leave this list empty.
Observation.stations
val stations: List<Station>Stations requested by capture mode; an empty list does not prove a station-free world.
Observation.nodes
val nodes: List<TrackNode>Observed full-capture graph; empty in specialised train captures and possibly when unavailable.
Observation.junctions
val junctions: List<TrackJunction>Observed full-capture attachments; empty in specialised captures without proving there are no junctions.
Observation.signals
val signals: List<Signal>Observed full-capture signals; specialised train captures do not request them.
Observation.services
val services: List<Service>Requested, observable services; an empty list can also result from an unrequested or unavailable group.
Observation.details
val details: List<TrainDetails>Assignments/occupants according to read options; interpret each optional property separately.
Observation.platforms
val platforms: List<Platform>Full-capture platforms when observable; not requested in specialised captures.
Observation.reservations
val reservations: List<TrackUsage>?Reservation intervals when observable; null in a specialised capture. A reservation is not an occupation.
Observation.occupations
val occupations: List<TrackUsage>?Occupation intervals when observable; null in a specialised capture. An unknown table does not prove a clear track.
Observation.selectedPath
val selectedPath: List<Long>?Selected train path in a full capture; null when unrequested or unavailable. Not a passage permission.
Observation.lineStops
val lineStops: List<LineStop>?Line plan requested for selectedTrain; null when unrequested or unavailable. May extend beyond its partial run.
Observation.clock
val clock: SimulationClock?Simulation clock copied with the snapshot, when available.
Observation.trackMetrics
val trackMetrics: List<TrackMetric>? = nullObserved full-capture track lengths; null when unavailable or unrequested. A missing row remains unknown.
Observation.lines
val lines: List<Line>? = nullExplicitly requested line catalogue; null when unrequested or unavailable.
Observation.trainMetadata
val trainMetadata: List<TrainMetadata>? = nullRich train metadata according to TrainQuery; null outside this capture or when unavailable.
Observation.vehicleModels
val vehicleModels: List<VehicleModel>? = nullModels referenced by requested compositions; null when unrequested or unavailable.
Observation.train
fun train(id: Long): TrainRecord?Indexed lookup of joined train record in this snapshot only. null if no matching data exists; no new game read.
Observation.service
fun service(trainId: Long): Service?Indexed lookup of train service in this snapshot only. null if no matching data exists; no new game read.
Observation.train
fun train(id: TrainId): TrainRecord?Indexed lookup of joined train record in this snapshot only. null if no matching data exists; no new game read.
Observation.service
fun service(id: TrainId): Service?Indexed lookup of train service in this snapshot only. null if no matching data exists; no new game read.
Observation.details
fun details(trainId: Long): TrainDetails?Indexed lookup of train assignment/occupant details in this snapshot only. null if no matching data exists; no new game read.
Observation.details
fun details(id: TrainId): TrainDetails?Indexed lookup of train assignment/occupant details in this snapshot only. null if no matching data exists; no new game read.
Observation.station
fun station(id: Long): Station?Indexed lookup of station in this snapshot only. null if no matching data exists; no new game read.
Observation.station
fun station(id: StationId): Station?Indexed lookup of station in this snapshot only. null if no matching data exists; no new game read.
Observation.track
fun track(id: Long): Track?Indexed lookup of track in this snapshot only. null if no matching data exists; no new game read.
Observation.track
fun track(id: TrackId): Track?Indexed lookup of track in this snapshot only. null if no matching data exists; no new game read.
Observation.platform
fun platform(trackId: Long): Platform?Indexed lookup of platform information for this track in this snapshot only. null if no matching data exists; no new game read.
Observation.platform
fun platform(trackId: TrackId): Platform?Indexed lookup of platform information for this track in this snapshot only. null if no matching data exists; no new game read.
Observation.line
fun line(id: LineId): Line?Indexed lookup of catalogue line in this snapshot only. null if no matching data exists; no new game read.
Observation.tag
fun tag(id: TagId): Tag?Indexed lookup of catalogue tag in this snapshot only. null if no matching data exists; no new game read.
Observation.metadata
fun metadata(id: TrainId): TrainMetadata?Indexed lookup of rich train metadata in this snapshot only. null if no matching data exists; no new game read.
ObservationClient
interface ObservationClient : AutoCloseableCloseable observation-source contract. Useful for injecting a controlled source into application tests; NimbyClient is the game-connected implementation.
ObservationClient.capture
fun capture(selectedTrainId: Long? = null): ObservationCaptures network tables and ordinary observations. A selected train adds its path and line plan; it does not filter the train list. Tables are copied without guaranteeing an atomic tick.
GameProcess
data class GameProcess(val pid: Int, val executable: String)Discovered game process. Discovery proves neither a loaded game nor SDK compatibility.
GameProcess.pid
val pid: IntProcess identity to pass explicitly to connect.
GameProcess.executable
val executable: StringExecutable path reported by the system.
GameProcesses
object GameProcessesDiscovery of visible NIMBY Rails processes. Prefer Nimby.runningGames at the application entry point.
GameProcesses.discover
fun discover(): List<GameProcess>Lists recognised game executables among visible processes. Returns an empty list when none is visible; neither selects nor opens a connection.
SdkException
class SdkException(val status: Int, operation: String) : IllegalStateExceptionSDK operation failure. Retain message and status for diagnostics; distinguish it from an optional null result. Do not automatically repeat a write after an exception.
SdkException.status
val status: IntFailure code: notably 2 inaccessible process/file, 7 unsupported game, 8 unavailable data, 11 closed game. Retain other codes without inventing their meaning.