Skip to content
perpetualKid edited this page Oct 25, 2026 · 7 revisions

Traffic files (.trf)

An MSTS traffic file defines a collection of AI service entries that can be scheduled as traffic in an activity. Traffic files normally reside in ROUTES/<route>/TRAFFIC/ and are selected from an activity's traffic definition. They reference path and service-related data but do not replace the player service or the activity event model.

This page compares the derived FTS/Open Rails lineage, independent TSRE5 editor code, published Open Rails guidance, and read-only SCE community content. Original MSTS documentation has not yet established a complete .trf grammar or every scheduling rule. In particular, identically named Service_Definition blocks in .srv, .act, and .trf are not interchangeable.

On this page

Serialization and outline

A traffic file uses Kuju/SIMISA structured serialization. A simplified outline is:

SIMISA...traffic-signature...

Traffic_Definition ( "traffic-stem"
    Serial ( serial-value )
    Service_Definition ( "service-stem" start-time
        ArrivalTime ( clock-seconds )
        DepartTime ( clock-seconds )
        SkipCount ( path-stop-index )
        DistanceDownPath ( distance )
        PlatformStartID ( track-item-id )
        ... repeated flat stop fields ...
    )
    ...
)

The actual signature, encoding, and optional records must be read from bytes and preserved as serialized. The outline uses placeholders and is not a complete valid file. There is no leading service count or nested stop wrapper in the examined writer/sample.

TSRE5 writes UTF-16 with a BOM and SIMISA@@@@@@@@@@JINX0f0t______; the inspected SCE traffic file has that signature and a UTF-16LE BOM. Preserve alternatives rather than imposing this writer's encoding on all content.

Traffic and service records

Record Working interpretation Evidence status
Positional traffic name First value after Traffic_Definition ( Not a nested Name record in the examined grammar.
Serial Traffic-level serialized revision/serial value FTS expects it immediately after the name; TSRE5 reads it among children. Do not equate it with a required format version.
Positional service stem and start time First two values after Service_Definition ( Reference to .srv plus scheduled instance start; not nested Name / Time records.
ArrivalTime / DepartTime Scheduled stop clock times Flat repeated fields, corroborated by TSRE5 and SCE content.
SkipCount Path-stop selection/index value TSRE5's service template uses path-object ordinals; retain gaps rather than renumbering.
DistanceDownPath Distance along the selected path FTS reads a distance (unsuffixed metres); original unit/suffix acceptance is not independently specified here.
PlatformStartID Rail TDB platform track-item reference See the platform contract; not a stop-list index or world UID.

A traffic definition commonly contains multiple Service_Definition records. It should be represented as an ordered collection rather than a map because order, repeated service names, and duplicate service/start pairs must be preserved.

UiD and per-stop Efficiency belong to the corresponding activity instance records below, not the examined external .trf schedule grammar.

Activity versus traffic records

The activity's AI block is distinct from the external schedule:

Traffic_Definition ( "traffic-stem"
    Service_Definition ( "service-stem" start-time
        UiD ( activity-service-id )
        Efficiency ( factor )
        SkipCount ( path-stop-index )
        DistanceDownPath ( distance )
        PlatformStartID ( track-item-id )
        ... repeated flat performance/path fields ...
    )
)

This lives inside .act Tr_Activity_File. Its positional traffic name selects a .trf; its AI entries supply service stems, start times, UIDs, and section performance. The external .trf supplies the paired timed stop records. The .srv selected by each service stem supplies consist/path/default performance and the separate nested stop template.

FTS AI.CreateAITrain joins the activity instance to the first external schedule matching service stem (case-insensitively) and start time. It loads .srv using the stem, not the service's display Name. TSRE5 also distinguishes scheduled instances by name/time, while its internal nameTime string concatenation is not an on-disk key format.

The SCE sample contains two instances of one service with starts 33780 and 35690, and activity UIDs 3 and 4. This directly demonstrates why service name alone is insufficient. UID and (service, start) are different identity domains; duplicate pairs and inconsistent companion files must be reported, not silently merged. First-match behavior is an implementation observation, not a uniqueness rule proved for MSTS.

The player's schedule is embedded rather than a .trf entry:

Player_Service_Definition ( "player-service-stem"
    Player_Traffic_Definition ( start-time
        ArrivalTime ( clock-seconds )
        DepartTime ( clock-seconds )
        SkipCount ( path-stop-index )
        DistanceDownPath ( distance )
        PlatformStartID ( track-item-id )
        ... repeated flat stop fields ...
    )
    ... optional/preserved player instance metadata ...
)

TSRE5 and the sample retain player UiD and flat performance/path fields outside Player_Traffic_Definition. The examined FTS PlayerServices reader only models the service stem and nested player schedule. Preserve these extra fields even when the consuming simulator ignores them. Do not apply the AI requirement for a positional start time directly after the service stem to this player wrapper.

Schedule fields and time domains

Context Time domain and evidence
.act header StartTime ( hour minute second ) Clock components, not a scalar duration.
AI Service_Definition ( service start ) in .act / .trf Scalar scheduled clock time in seconds from midnight in the examined implementations/content; the Open Rails AI-event manual explicitly describes this service start as time of day in seconds.
Player_Traffic_Definition ( start ) Scalar player schedule start. The observed value 34140 equals 09:29:00, matching the header's 9 29 0. Preserve both if they disagree.
ArrivalTime / DepartTime Scheduled clock seconds, not elapsed time since activity start. Sample player arrival 33420 (09:17:00) precedes its 09:29 start, while departure 34200 is 09:30:00; do not clamp all stop times to activity start.
Activity time-event Time Elapsed-seconds threshold in the examined derived runtime; a different domain from timetable clock times.

The external .trf service start is read as a plain integer by FTS; arrival/departure fields use its time-unit reader then cast to integers. Activity instance/player start readers use the time-unit reader and integer conversion. TSRE5 stores schedule values through its generic number reader. These differences do not establish uniform suffix, fractional-time, or rollover acceptance.

Midnight crossing, values above 86400, negative/sentinel values, fractional truncation, and conflicting header/schedule starts need original-content or runtime confirmation. Preserve raw values and report anomalies instead of wrapping modulo one day or converting all fields to elapsed seconds.

A 2015 Elvas Tower community thread reports an Open Rails 3190 workaround for an AI service that should start after midnight: add 86400 seconds to the positional start value in the activity's AI Service_Definition. The thread author reports that changing 480 (00:08) to 86880 made the train appear; the advice explicitly says MSTS acceptance was not tested. This is evidence for one Open Rails activity-AI case, not a universal rollover rule for .act player schedules, .trf stop times, or original MSTS.

Scheduled times are not necessarily actual departure times. The Open Rails manual's Stop Time at Stations describes passenger loading and states explicitly that honoring scheduled AI departure time is an improvement over MSTS. Do not transfer that behavior to the original simulator merely because the same records exist.

Grouping and preservation

The repeated stop fields are flat siblings, not a count-prefixed table or StationStop blocks:

  • FTS creates a schedule item when it encounters PlatformStartID, using the current arrival, departure, skip, and distance values. Those accumulators are initialized once per service, not cleared after each item; omitted fields can carry prior values.
  • FTS activity AI performance groups similarly commit on PlatformStartID, using the current efficiency, skip, and distance values.
  • TSRE5 loads separate vectors for each field and writes aligned groups in arrival/departure/skip/distance/platform order (or efficiency/skip/distance/platform for activity metadata). This corroborates ordinary output order, not acceptance of arbitrary incomplete/reordered groups.
  • The external schedule constructor in FTS corrects any negative parsed integer arrival/departure value using the service start and companion time, with diagnostics: a negative arrival becomes the earlier of a nonnegative departure and service start (or service start when departure is also negative); a negative departure becomes the later of arrival and service start. Its player-schedule constructor does not use that same correction path. The reader first converts its time value to an integer, so this behavior is about the resulting model value, not necessarily every negative fractional token. A negative value is not preserved as an opaque sentinel by this FTS path, but that does not establish the original MSTS meaning of -1 or other negative values. Corrections are runtime model behavior, not source values to overwrite during preservation.

Keep source order, duplicates, missing fields, raw values, and group boundaries. Validate vector lengths and paired stop identities before deriving rows; a parser's successful load is not a lossless round trip or proof of original-editor acceptance. Do not deduplicate platform visits or replace schedules from the .srv template.

Cross-file relationships

flowchart LR
    ACT[activity.act] -->|traffic definition| TRF[traffic.trf]
    TRF -->|AI service entries| AI[AI services]
    AI -->|path/service data| SRV[service.srv]
    SRV -->|PathID| PAT[path.pat]
    PAT -->|network resolution| TDB[route.tdb]
    SRV -->|Train_Config| CON[consist.con]
Loading

An activity can select traffic separately from its player service. Do not merge AI entries into the player service model: their timing, UID, path, and timetable data can use different structures and defaults. Detailed service and consist relationships are documented in [[service files (.srv)|MSTS-Service-Files]]. Preserve unresolved timing, distance, scale, and default states according to MSTS units and numeric values.

Implementation differences and open questions

FTS/Open Rails provide the derived parser lineage and can convert some player-timetable data into AI traffic service definitions. TSRE5 independently edits traffic and activity data. Agreement supports the collection structure, but not original MSTS runtime behavior.

Observed signatures, instance pairing, the scalar clock-time convention, and TDB platform ownership are now documented with scoped evidence. Original requiredness, UID allocation rules, duplicate-pair resolution, midnight behavior, original unit/suffix acceptance, missing-file behavior, and malformed-group tolerance remain unresolved. Open Rails conversion behavior must not be treated as proof of an original MSTS export operation.

Validation checklist

  • Detect and retain the actual SIMISA envelope and encoding.
  • Validate the traffic root, serial value, and all declared counts.
  • Preserve the ordered service list, repeated names, duplicate service/start pairs, and unknown records.
  • Check service times, path distances, platform IDs, and skip lists without normalizing uncertain units.
  • Resolve referenced paths and consists in the selected route context.
  • Keep traffic-list data separate from activity events, player service data, and Open Rails extensions.
  • Pair activity AI entries with external schedules by service stem and start time without discarding UIDs or duplicate pairs.
  • Check flat group completeness/order separately from the .srv nested stop template; keep clock times distinct from elapsed-event time.

Sources

  • Open Rails TrafficFile.cs: derived traffic parser and service definitions.
  • FTS traffic format code in the Orts.Formats.Msts source tree: derived format implementation.
  • TSRE5 Activity.h and Activity.cpp: independent traffic/activity structure evidence.
  • TSRE5 Traffic.cpp, load / save, and ActivityTimetable.cpp, load / save: positional names/start values, flat schedule groups, encoding; ActivityServiceDefinition::load / save in Activity.cpp: distinct activity performance records and preserved player metadata. Inspected 25 October 2026.
  • FTS Traffic.cs, ServiceTraffic, ServiceTraffics, Services, PlayerTraffics, and PlayerServices: owner-specific grammar, group commit, numeric readers, and corrections; AI.cs, CreateAITrain: service/start join and service-file loading.
  • Open Rails Train Operation manual, Activity location events for other trains, Default Performance and Performance Parameters, and Stop Time at Stations: service clock-time qualifier, performance scale, and explicit original/derived departure-behavior boundary.
  • Read-only SCE companion sample identities and hashes are recorded under Service and traffic schedule evidence. These are community files, not authenticated original MSTS distribution samples.
  • [[Activity files (.act)|MSTS-Activity-Files]] and [[service files (.srv)|MSTS-Service-Files]]: consuming activity and service contracts.

Navigation

User documentation

Development and architecture

MSTS domain knowledge

News archive

Clone this wiki locally