Reference
ToolContext
Read the network, prepare placement, publish buttons and write to the log from a tool.
Usage context
| Module | Package | SDK source |
|---|---|---|
| Kotlin/Native | nimby | kotlin/src/nimby/ToolContext.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 nimby.ToolTrack
import nimby.ToolJunction
import nimby.ToolSignal
import nimby.ToolNetwork
import nimby.SignalPosition
import nimby.ConstructionState
import nimby.ConstructionResult
import nimby.ToolButton
import nimby.ToolNumberInput
import nimby.LogLevel
import nimby.ToolContextContext, units and operations
The context is ready to use in service and onTick. It belongs to the current callback: keep copied values and tickets, never this context. The SDK rejects calls after the callback returns.
| Value | Contract |
|---|---|
| ToolTrack.lengthM | Optional metres; null requires traversal to stop. |
| SignalPosition.fraction | Native fraction strictly between 0 and 1 for placement. |
| SignalPosition.direction | Native direction -1 or 1; separate from some models' visual direction. |
| ConstructionResult.reason | Rejection code from the native bridge; keep it in the log. |
| ToolButton | Identifier, label and enabled state; at most 12 buttons per panel. |
| ToolNumberInput | An integer keyboard input: id, label, value, minimum, maximum, enabled. Selection, deletion and paste are supported. Empty, incomplete or out-of-range text remains a local draft and blocks commands; only a valid integer is sent to the mod. At most four inputs, with IDs distinct from button IDs. |
| SignalActionRequest.value | New integer value for a field edit (action contains its ID); null for a button. Editing blocks buttons until the panel is published again. |
| showPanel | UTF-8 message limited to 256 bytes; replaces the action that opened the tool. |
ToolTrack
data class ToolTrack(val id: Long, val linkA: Long?, val linkB: Long?, val lengthM: Double?)Copied track geometry for a tool. lengthM may be unavailable; use topology for typed connections and stop an unknown traversal.
ToolTrack.id
val id: LongTrack ID in this game world. Retain it with the copy’s worldId and generation; do not treat it as a list index.
ToolTrack.linkA
val linkA: Long?Observed connection identifier at end A, or null when unavailable. Use ToolTopology to check a usable reciprocal connection.
ToolTrack.linkB
val linkB: Long?Observed connection identifier at end B, or null when unavailable. null does not prove the track ends here.
ToolTrack.lengthM
val lengthM: Double?Finite, strictly positive observed length in metres, or null. Do not replace null with an approximate calculated length for construction.
ToolJunction
data class ToolJunction(val branchTrack: Long, val mainTrack: Long, val fraction: Double, val mainDirection: Int, val branchDirection: Int)Copied connection of a branch to a main track, with position and orientations. Does not define a currently permitted branch; ToolTopology avoids implicit route selection.
ToolJunction.branchTrack
val branchTrack: LongBranch-track identifier of this connection, distinct from mainTrack.
ToolJunction.mainTrack
val mainTrack: LongIdentifier of the main track containing the fraction position.
ToolJunction.fraction
val fraction: DoubleConnection position on the main track, from 0 to 1 along A to B. Multiplying by its length gives distance from A.
ToolJunction.mainDirection
val mainDirection: IntObserved main-track orientation at the connection, −1 or +1. This sign does not select a route; use ToolTopology connections.
ToolJunction.branchDirection
val branchDirection: IntObserved branch orientation, −1 or +1. ToolTopology uses it to recognize the junction end; the value authorizes no route.
ToolSignal
data class ToolSignal(val id: Long, val track: Long, val fraction: Double, val direction: Int, val kind: Int)Copied signal with track, position and kind. Use travelDirection for train direction and placementAt to copy orientation correctly.
ToolSignal.id
val id: LongSignal ID in the copy, to revalidate in a fresh read before construction.
ToolSignal.track
val track: LongIdentifier of the track carrying the signal. Look up its length with topology.track(track).
ToolSignal.fraction
val fraction: DoubleSignal position along the track, from 0 to 1 from A to B. A construction position must lie strictly inside the track.
ToolSignal.direction
val direction: IntStored signal orientation, dependent on its kind. Do not use it as train direction; prefer travelDirection.
ToolSignal.kind
val kind: IntObserved signal kind supplied with the copied data. Do not implement direction conversion from this number: placementAt handles it.
ToolSignal.travelDirection
val travelDirection: IntNormalized train direction: +1 from A to B, −1 from B to A. Throws if the copied orientation is invalid.
ToolSignal.placementAt
fun placementAt(trackId: Long, fraction: Double, travelDirection: Int = this.travelDirection): SignalPositionBuilds a position for a copy of the source signal, converting train direction for its kind. Requires a valid track, a finite fraction strictly between 0 and 1, and direction ±1. Use the same value for preview and construction.
ToolNetwork
data class ToolNetwork(val worldId: String, val generation: Long, val tracks: List<ToolTrack>, val junctions: List<ToolJunction>, val signals: List<ToolSignal>)Working copy of tracks, junctions and signals from a session. Lists remain readable after the callback; they do not prove the world is still unchanged.
ToolNetwork.worldId
val worldId: StringIdentity of the world from which all lists in this copy originate.
ToolNetwork.generation
val generation: LongSession generation of the copy. Discard a plan if it no longer matches the active context.
ToolNetwork.tracks
val tracks: List<ToolTrack>Copied tracks; each may have an unknown length. Prepare topology once for repeated lookups.
ToolNetwork.junctions
val junctions: List<ToolJunction>Copied junction connections, including those inside a track. Ignoring them can make a planner cross a junction.
ToolNetwork.signals
val signals: List<ToolSignal>Signals present in the read. A copied list does not authorize construction between them.
SignalPosition
data class SignalPosition(val trackId: Long, val fraction: Double, val direction: Int)Proposed preview or construction position. Prefer source.placementAt(...) to convert direction for the kind; the constructor alone does not validate game state.
SignalPosition.trackId
val trackId: LongTarget track from the refreshed network. It must still exist when the command executes.
SignalPosition.fraction
val fraction: DoubleConstruction target position strictly between 0 and 1 from A to B; neither an endpoint nor a distance in metres.
SignalPosition.direction
val direction: IntOrientation expected by the source kind. Obtain it through placementAt instead of blindly copying travelDirection.
ConstructionState
enum class ConstructionState {
Ready,
Applied,
Undone,
Rejected,
Partial,
Pending
}Stage or result of a ticket-tracked operation. Distinguish preparation, waiting and terminal result; a delay never means nothing was built.
ConstructionState.Ready
ReadyTicket prepared, without creation. Then capture the network and validate the plan before explicit confirmation.
ConstructionState.Applied
AppliedCommand applied. Inspect createdIds and canUndo; a new action must not repeat this construction.
ConstructionState.Undone
UndoneOperation undo completed. Finish tracking it and present this result to the player.
ConstructionState.Rejected
RejectedOperation rejected. Present the reason and invalidate confirmation; do not turn rejection into an automatic retry.
ConstructionState.Partial
PartialIncomplete result with possible effects. Inspect createdIds, reason and canUndo; assume neither complete success nor absence of changes.
ConstructionState.Pending
PendingResult still pending. Retain the original ticket and use pollConstruction; do not submit another command.
ConstructionResult
data class ConstructionResult(val state: ConstructionState, val token: Long, val createdIds: List<Long>, val reason: Int, val canUndo: Boolean)Copied result of preparation, construction, undo or ticket polling. Check state before other fields; an uncertain operation continues to be tracked on its ticket.
ConstructionResult.state
val state: ConstructionStateOperation stage or outcome. Pending requires polling; Partial requires inspection of the resulting effects.
ConstructionResult.token
val token: LongOpaque ticket to retain for createSignals, pollConstruction and undoConstruction. A zero ticket is not a usable preparation.
ConstructionResult.createdIds
val createdIds: List<Long>Created signal IDs reported by the operation. Interpret an empty list with state, never alone as proof of no effects.
ConstructionResult.reason
val reason: IntResult diagnostic code to retain in logs. Do not present it as a domain enum inferred from its value.
ConstructionResult.canUndo
val canUndo: BooleanIndicates that SDK undo was available when the response was produced. History may change afterwards; undoConstruction can still reject.
ToolButton
data class ToolButton(val id: String, val label: String, val enabled: Boolean = true)Temporary button in a panel or window. Its label performs no action; the handler processes the received identifier. Removing it does not alter persistent signal settings.
ToolNumberInput
data class ToolNumberInput(val id: String, val label: String, val value: Int,
val minimum: Int, val maximum: Int, val enabled: Boolean = true)Temporary integer field with explicit value and bounds. A panel sends each valid edit in request.value; a window sends all fields on click. An invalid draft blocks commands.
ToolNumberInput.id
val id: StringField key in action or ToolWindowEvent.values, distinct from other controls in the form.
ToolNumberInput.label
val label: StringInteger-field label shown with the input; accepts tr.
ToolNumberInput.value
val value: IntInteger proposed when publishing the form. Must lie within minimum..maximum; republishing should respect the tool’s validated draft.
ToolNumberInput.minimum
val minimum: IntInclusive lower input bound. Must not exceed maximum.
ToolNumberInput.maximum
val maximum: IntInclusive upper input bound; both the published value and accepted edits must respect it.
ToolNumberInput.enabled
val enabled: Boolean = truefalse makes the input noneditable in this form; does not remove the value from the tool’s local state.
LogLevel
enum class LogLevel {
Info,
Warning,
Error
}Severity of a message written through ToolContext.log. Choose it according to the domain outcome and avoid repeating a message on every tick.
LogLevel.Info
InfoNormal operation event, such as an operation completing or a phase changing.
LogLevel.Warning
WarningUnusual situation that the tool can report without classifying it as a permanent error.
LogLevel.Error
ErrorFailure requiring diagnosis. Keep the message useful and bounded; writing a log can itself be temporarily refused.
ToolContext
class ToolContextGame access supplied only during a tool callback. Retain neither this context nor a closure capturing it. Copied values, session identifiers and tickets may be kept for the next callback.
ToolContext.worldId
val worldId: StringIdentity of the active game world for this call. Compare it with the plan or event before reusing data.
ToolContext.generation
val generation: LongActive session generation for this call. A change invalidates plans and presentations from the old generation.
ToolContext.log
fun log(message: String, level: LogLevel = LogLevel.Info): UnitWrites a persistent message of 1 to 4096 UTF-8 bytes without NUL characters. Do not log secrets or every tick; handle a possible refusal without a diagnostic loop.
ToolContext.clock
fun clock(): ToolClockReads only calendar and simulation time, without capturing the network. Use this lightweight read for clock displays; the copied result does not update itself.
ToolContext.trains
fun trains(query: TrainQuery = TrainQuery()): TrainSnapshotReads the requested train-data groups. Reuses a read from the same callback when it covers the query; additional requirements trigger an expanded read. Copies remain readable after the callback.
ToolContext.linePlan
fun linePlan(trainId: Long): TrainLinePlan?Reads the identified train’s complete line plan, or null if absent/unstable. Timetable values are offsets, not absolute service dates. Reused within the callback; network refreshes the read.
ToolContext.linePlan
fun linePlan(train: TrainId): LinePlan?The same plan read with a typed train identifier. Returns LinePlan or null when absent/unstable; does not infer a service run’s date.
ToolContext.changeTime
fun changeTime(utcSeconds: Long, recalculateTrains: Boolean = false): ToolTimeChangeChanges the UTC calendar within years 1 to 9999, preserving the fractional second. Preserves positions and relative deadlines by default. recalculateTrains may move trains and cost money: require an explicit choice. After an uncertain error, read back instead of replaying.
ToolContext.changeTime
fun changeTime(date: GameDateTime, recalculateTrains: Boolean = false): ToolTimeChangeConverts the validated date to UTC seconds and applies changeTime. The same mutation and read-back requirement after an uncertain outcome apply; calculating the date alone did not change the game.
ToolContext.showWindow
fun showWindow(request: ToolWindowEvent, message: String, buttons: List<ToolButton>, inputs: List<ToolNumberInput> = emptyList()): UnitPublishes the form for the window that produced the event, in the same session: up to 12 buttons and 8 integers, with distinct IDs. Values are sent together on click; 4096 UTF-8 bytes per string without NUL characters, and 8192 in total.
ToolContext.network
fun network(): ToolNetworkCaptures a fresh copy of tracks, junctions and signals; invalidates train reads reused within this context without immediately rereading them. Call after prepareConstruction to compute the plan to confirm, not for every preview renewal.
ToolContext.prepareConstruction
fun prepareConstruction(sourceSignal: Long): ConstructionResultPrepares a ticket to copy the source signal without building a signal. Then take a fresh capture and validate positions. An editor command or session change may invalidate the ticket.
ToolContext.showSignalPreview
fun showSignalPreview(request: SignalActionRequest, positions: List<SignalPosition>): UnitPublishes up to 64 positions with the source kind, without construction. Renew while in use: it expires after two seconds. Visible while editing the source; layers and framing still apply. A Busy refusal does not renew the old preview and must prevent local confirmation.
ToolContext.clearSignalPreview
fun clearSignalPreview(): UnitRequests removal of the tool’s preview without undoing construction. On Busy, immediately revoke local confirmation and retry cleanup in a later callback.
ToolContext.createSignals
fun createSignals(ticket: Long, sourceSignal: Long, positions: List<SignalPosition>): ConstructionResultSubmits 1 to 64 distinct positions once with a prepared ticket and source signal. Validate a fresh capture against the approved plan before calling. Pending or an uncertain error requires tracking that same ticket, never replaying construction.
ToolContext.undoConstruction
fun undoConstruction(ticket: Long): ConstructionResultExplicitly requests undo for the ticket when canUndo allows it. History may have changed, so rejection remains possible. Mark the operation pending before calling and track its result without repeating it.
ToolContext.pollConstruction
fun pollConstruction(ticket: Long): ConstructionResultPolls the original nonzero ticket without resubmitting the command. Continue during Pending, even if the panel is closed. A ticket becoming unavailable does not prove there were no effects.
ToolContext.showPanel
fun showPanel(request: SignalActionRequest, message: String, buttons: List<ToolButton>, inputs: List<ToolNumberInput> = emptyList()): UnitReplaces the originating action with a temporary panel: up to 12 buttons and 4 integers, with distinct IDs. Each string must fit both 256 characters and 256 UTF-8 bytes, without NUL characters. Use the request from the same session. A presentation refusal does not validate old clicks; persistent signal settings remain unchanged.