NRF SDK 0.9

Maintenance

Write a responsive, independent mod

Bound useful work, handle recovery and measure without confusing loading, computation and display.

What the SDK handles

The SDK supervises compatible native mods. It can stop a mod that crashes or whose callback stops responding while other mods keep running. The mod-author contract stays simple: use public functions, bound each calculation and return. After a fault stops a mod, fix the cause and start a new test session; do not assume that the callback will be replayed automatically.

A callback does bounded work, then returns

WhenUseful structure
Mod declarationPrepare models, settings, image descriptions and fixed rules once. Keep identifiers stable.
Signalling observationUse the supplied network and observations. Build useful indexes once per batch; avoid scanning all signals for every signal.
service / onTickTool callbacks are serialized. Calculate on request; reread nothing while idle. During a preview, renew copied positions. During a command, poll its ticket.
onStop / worldId / generationRelease mod data on stop; invalidate plans, indexes and events from another session. Retain no ToolContext beyond its callback.

An observation interval is a target cadence, not a frequency guarantee. If a calculation exceeds that interval, do not launch a catch-up burst. At high speed, simulated time advances faster than callbacks and visible frames: an animation cannot promise to display every phase.

Request the data you need

NeedIn a native toolIn a JVM application
Clock onlyToolContext.clock()Game.clock.read()
Train data familiesToolContext.trains(TrainQuery(...))Game.trains.snapshot(query = TrainQuery(...))
Network geometryToolContext.network()Game.snapshot()

Request passengers, timetables, tags, characteristics or compositions only when your feature uses them. A full map is unnecessary for a date form. Conversely, do not replace a required fresh read with a cache based only on elapsed time: a world, track or source may have changed. Missing data remains unknown, not zero or an invented empty list.

Copied results are useful for calculation and display. Within a native callback, already-covered train requests can reuse that callback’s read; network() and a time change invalidate this reuse. In a JVM application, each capture request makes a fresh read. Explicitly open and close your connection and discard caches when it changes.

Verify behaviour before claiming a gain

Outside the game, test a slow callback, an exception, unknown data and repeated temporary refusals, followed by recovery. Check that other features continue, queues stay bounded and a placement operation is submitted only once. Measure read time, mod computation and actual observed cadence separately. An average alone hides spikes.

For an in-game test, retain package versions and hashes, the reference save, before/after phases and logs from the correct launch. Wait for loading to finish before recording the baseline. Startup counters often include that phase: compare differences between known timestamps. Keep speed and rendering settings consistent between runs. A responding click or isolated snapshot does not measure every frame’s duration.

MeasurementWhat it establishes
Targeted readSuccess rate and duration of useful requests; compare median, 95th percentile and maximum.
Simulation clockRatio of game time to elapsed real time. The selected UI speed does not prove the achieved speed.
Driving and appearanceTest train passages at signals, produced decisions and actually visible frames separately. A fast read does not prove instant display.
RecoveryAfter the fault, check that other features progress and delays return to their usual range without replaying an uncertain mutation.