Difference between revisions of "Train Plugin API (IRuntime)"
(Created page with "<font size="small"><font face="sans-serif"> <font size="+2" color="#0080ff">Train plugin API (IRuntime)</font><br /> {| style="border: 0px currentColor; margin-right: 10pt;...") |
(No difference)
|
Latest revision as of 19:07, 6 February 2015
Train plugin API (IRuntime)
This is the documentation for train plugins. In order to create a train plugin, implement the IRuntime interface from the OpenBveApi.Runtime namespace. In the following, you will find a description of how this interface works.
■ Overview
The following functions are called in this order when the plugin is loaded:
● | Load |
● | SetVehicleSpecs |
● | Initialize |
● | SetPower |
● | SetBrake |
● | SetReverser |
● | SetSignal |
The following functions can be called at any time:
● | SetPower |
● | SetBrake |
● | SetReverser |
● | KeyDown |
● | KeyUp |
● | HornBlow |
● | DoorChange |
● | SetSignal |
● | SetBeacon |
● | PerformAI |
The following function is called when the plugin is unloaded:
● | Unload |
● Function calls
The following is a list of all function calls along with explanations on their behavior.
bool Load(LoadProperties properties)
This function is the first to be called after the plugin has been loaded. When this function triggers inside the plugin, a matching call to Unload will be made when the plugin is unloaded.
Arguments:
LoadProperties | properties | The properties supplied to the plugin on loading. |
LoadProperties (class):
string | PluginFolder | Gets the absolute path to the plugin folder. |
string | TrainFolder | Gets the absolute path to the train folder. |
int[] | Panel | Gets or sets the array of panel variables. |
PlaySoundDelegate | PlaySound | Gets the callback function for playing sounds. |
AISupport | AISupport | The extent to which the plugin supports the AI. |
string | FailureReason | Gets or sets the reason why the plugin failed loading. |
PlaySound (function):
See the section on playing sounds.
AISupport (enumeration):
AISupport.None | 0 | The plugin does not support the AI. Calls to PerformAI will not be made. Non-player trains will not use the plugin. |
AISupport.Basic | 1 | The plugin complements the built-in AI by performing only functions specific to the plugin. |
Return value:
bool | Whether the plugin was loaded successfully. |
If your plugin uses external configuration files, open files relative to the properties.PluginFolder or properties.TrainFolder. The difference between the two can be best visualized when the plugin is in a shared folder: Files relative to the plugin folder are common for all trains that use the plugin, while files relative to the train folder are specific to each train. The plugin folder is simply the folder in which the plugin is stored.
Initialize the properties.Panel array to any size and with any startup values you need. The array is processed after every call to Elapse by the host application in order to update custom panel indicators. Developers of the panel2.cfg file can query these values with the atsi variable, while developers of the panel.animated file can query these values with the pluginState[i] variable.
The properties.PlaySound function can be used at any time to play sounds. This callback function returns a handle that you can use to track if the sound is still playing, to change its volume and pitch, or to stop it. Please also see the section on playing sounds.
Set properties.AISupport to a value other than AISupport.None if you want your plugin to support the AI. Please also see the section on supporting the AI.
You should return true as the return value when loading succeeded. If, on the other hand, you want to abort loading the plugin, for example because an external configuration file could not be found, return false and set properties.FailureReason to a human-readible string that explains why loading failed.
void Unload()
This function is the last to be called before the plugin is unloaded.
void SetVehicleSpecs(VehicleSpecs specs)
This function is called after Load to inform the plugin about the specifications of the train.
Arguments:
VehicleSpecs | specs | The specifications of the train. |
VehicleSpecs (class):
int | PowerNotches | Gets the number of power notches the train has. |
BrakeTypes | BrakeType | Gets the type of brake the train uses. |
int | BrakeNotches | Gets the number of brake notches the train has, including the hold brake, but excluding the emergency brake. |
bool | HasHoldBrake | Gets whether the train has a hold brake. |
int | AtsNotch | Gets the index of the brake notch that corresponds to B1 or LAP. |
int | B67Notch | Gets the index of the brake notch that corresponds to 70% of the available brake notches. |
int | Cars | Gets the number of cars the train has. |
BrakeTypes (enumeration):
BrakeTypes.ElectromagneticStraightAirBrake | 0 | The train uses the electromagnetic straight air brake. |
BrakeTypes.ElectricCommandBrake | 1 | The train uses the analog/digital electro-pneumatic air brake without a brake pipe (electric command brake). |
BrakeTypes.AutomaticAirBrake | 2 | The train uses the automatic air brake with partial release. |
For more information about the meanings of the notches, see the sections on SetReverser, SetPower and SetBrake.
void Initialize(InitializationModes mode)
This function is called after SetVehicleSpecs and informs the plugin about the mode the safety system should start in. If the safety system in your plugin can be activated or deactivated, you should initialize the state of the plugin accordingly. When the user selects a Jump to station target, this function is also called prior to moving the train to its new location.
Arguments:
InitializationModes | mode | The mode of initialization. |
InitializationModes (enumeration):
InitializationModes.OnService | -1 | The safety system should be enabled. The train has its service brakes applied. |
InitializationModes.OnEmergency | 0 | The safety system should be enabled. The train has its emergency brakes applied. |
InitializationModes.OffEmergency | 1 | The safety system should be disabled. The train has its emergency brakes applied. |
The initialization mode is set in CSV/RW routes via the Route.Change command. Please note that any value between -2147483648 and 2147483647 can be conveyed to the plugin - the enumeration members are simply meant to standardize the meanings of the initialization modes.
void Elapse(ElapseData data)
This function is called every frame. It informs the plugin about the current state of the train and allows to set the virtual handles.
Arguments:
ElapseData | data | The data passed to the plugin. |
ElapseData (class):
VehicleState | Vehicle | Gets the state of the train. |
PrecedingVehicleState | PrecedingVehicle | Gets the state of the preceding train, or a null reference if there is no preceding train. |
Handles | Handles | Gets or sets the virtual handles. |
Time | TotalTime | Gets the absolute in-game time. |
Time | ElapsedTime | Gets the time that elapsed since the last call to Elapse. |
string | DebugMessage | Gets or sets the debug message the plugin wants the host application to display. |
VehicleState (class):
double | Location | Gets the location of the front of the train, in meters. |
Speed | Speed | Gets the speed of the train. |
double | BcPressure | Gets the pressure in the brake cylinder, in pascal. |
double | MrPressure | Gets the pressure in the main reservoir, in pascal. |
double | ErPressure | Gets the pressure in the equilizing reservoir, in pascal. |
double | BpPressure | Gets the pressure in the brake pipe, in pascal. |
double | SapPressure | Gets the pressure in the straight air pipe, in pascal. |
PrecedingVehicleState (class):
double | Location | Gets the location of the back of the preceding train, in meters. |
double | Distance | Gets the distance from the front of the current train to the back of the preceding train, in meters. |
Speed | Speed | Gets the speed of the preceding train. |
Speed (structure):
double | MetersPerSecond | Gets the speed in meters per second. |
double | KilometersPerHour | Gets the speed in kilometers per hour. |
double | MilesPerHour | Gets the speed in miles per hour. |
Time (structure):
double | Seconds | Gets the time in seconds. |
double | Milliseconds | Gets the time in milliseconds. |
Handles (class):
int | Reverser | Gets or sets the reverser position. |
int | PowerNotch | Gets or sets the power notch. |
int | BrakeNotch | Gets or sets the brake notch. |
bool | ConstSpeed | Gets or sets whether the const speed system is enabled. |
The meanings of the notches are explained in the sections on SetReverser, SetPower and SetBrake.
void SetReverser(int reverser)
This function is called when the driver changes the reverser position.
Arguments:
int | reverser | The new reverser position. |
For reverser, the value of -1 corresponds to backward, 0 to neutral and 1 to forward.
void SetPower(int powerNotch)
This function is called when the driver changes the power notch.
Arguments:
int | powerNotch | The new power notch. |
For powerNotch, the value passed can range from 0 to specs.PowerNotches.
void SetBrake(int brakeNotch)
This function is called when the driver changes the brake notch.
Arguments:
int | brakeNotch | The new brake notch. |
For trains with the automatic air brake, 0 is RELEASE, 1 is LAP, 2 is SERVICE and 3 is EMERGENCY.
For all other trains without a hold brake, 0 is released brakes, 1 is brake notch B1, 2 is brake notch B2, etc., specs.BrakeNotches is the maximum brake notch, and specs.BrakeNotches+1 is the emergency brake.
For all other trains with a hold brake, 0 is released brakes, 1 is the hold brake, 2 is brake notch B1, 3 is brake notch B2, etc., specs.BrakeNotches is the maximum brake notch, and specs.BrakeNotches+1 is the emergency brake.
Generally speaking, for trains without the automatic air brake, specs.AtsNotch is brake notch B1 and specs.BrakeNotches is the maximum service brake notch. For all types of trains, specs.BrakeNotches+1 is the emergency brake.
void KeyDown(VirtualKeys key)
This function is called when a plugin-specific key is pressed.
Arguments:
VirtualKeys | key | The virtual key that was pressed. |
VirtualKeys (enumeration):
VirtualKeys.S | 0 | The virtual S key. The default assignment is Space. |
VirtualKeys.A1 | 1 | The virtual A1 key. The default assignment is Insert. |
VirtualKeys.A2 | 2 | The virtual A2 key. The default assignment is Delete. |
VirtualKeys.B1 | 3 | The virtual B1 key. The default assignment is Home. |
VirtualKeys.B2 | 4 | The virtual B2 key. The default assignment is End. |
VirtualKeys.C1 | 5 | The virtual C1 key. The default assignment is Page Up. |
VirtualKeys.C2 | 6 | The virtual C2 key. The default assignment is Page Down. |
VirtualKeys.D | 7 | The virtual D key. The default assignment is 2. |
VirtualKeys.E | 8 | The virtual E key. The default assignment is 3. |
VirtualKeys.F | 9 | The virtual F key. The default assignment is 4. |
VirtualKeys.G | 10 | The virtual G key. The default assignment is 5. |
VirtualKeys.H | 11 | The virtual H key. The default assignment is 6. |
VirtualKeys.I | 12 | The virtual I key. The default assignment is 7. |
VirtualKeys.J | 13 | The virtual J key. The default assignment is 8. |
VirtualKeys.K | 14 | The virtual K key. The default assignment is 9. |
VirtualKeys.L | 15 | The virtual L key. The default assignment is 0. |
When making use of plugin-specific keys in your plugin, be sure to release a documentation that includes the virtual names of the keys along with their plugin-specific meanings.
void KeyUp(VirtualKeys key)
This function is called when a plugin-specific key is released.
Arguments:
VirtualKeys | key | The virtual key that was released. |
VirtualKeys (enumeration):
VirtualKeys.S | 0 | The virtual S key. The default assignment is Space. |
VirtualKeys.A1 | 1 | The virtual A1 key. The default assignment is Insert. |
VirtualKeys.A2 | 2 | The virtual A2 key. The default assignment is Delete. |
VirtualKeys.B1 | 3 | The virtual B1 key. The default assignment is Home. |
VirtualKeys.B2 | 4 | The virtual B2 key. The default assignment is End. |
VirtualKeys.C1 | 5 | The virtual C1 key. The default assignment is Page Up. |
VirtualKeys.C2 | 6 | The virtual C2 key. The default assignment is Page Down. |
VirtualKeys.D | 7 | The virtual D key. The default assignment is 2. |
VirtualKeys.E | 8 | The virtual E key. The default assignment is 3. |
VirtualKeys.F | 9 | The virtual F key. The default assignment is 4. |
VirtualKeys.G | 10 | The virtual G key. The default assignment is 5. |
VirtualKeys.H | 11 | The virtual H key. The default assignment is 6. |
VirtualKeys.I | 12 | The virtual I key. The default assignment is 7. |
VirtualKeys.J | 13 | The virtual J key. The default assignment is 8. |
VirtualKeys.K | 14 | The virtual K key. The default assignment is 9. |
VirtualKeys.L | 15 | The virtual L key. The default assignment is 0. |
When making use of plugin-specific keys in your plugin, be sure to release a documentation that includes the virtual names of the keys along with their plugin-specific meanings.
void HornBlow(HornTypes type)
This function is called when a horn starts playing. In case of the musical horn, this function is also called when the horn stops playing.
Arguments:
HornTypes | type | The type of horn. |
HornTypes (enumeration):
HornTypes.Primary | 0 | The primary horn. |
HornTypes.Secondary | 1 | The secondary horn. |
HornTypes.Music | 2 | The musical horn. |
void DoorChange(DoorStates oldState, DoorStates newState)
This function is called when the state of the doors change.
Arguments:
DoorStates | oldState | The old state of the doors. |
DoorStates | newState | The new state of the doors. |
DoorStates (enumeration):
DoorStates.None | 0 | No door is open. |
DoorStates.Left | 1 | The left doors are open. |
DoorStates.Right | 2 | The right doors are open. |
DoorStates.Both | 3 | All doors are open. |
void SetSignal(SignalData[] data)
This function is called when the aspect in the current or in any of the upcoming section changes, or when passing section boundaries. For the current section, it is assumed that no train is currently inside. Only sections until the first red section are reported.
Arguments:
SignalData[] | data | The signal data per section. |
SignalData (class):
int | Aspect | Gets the aspect of the section. |
double | Distance | Gets the distance to the section. |
The data array contains one entry per section, where data[0] is the current section, data[1] the upcoming section, and so on. You can inspect the aspect and the distance to each section reported.
Please note that the length of the data array is dynamic. Only sections until the first red section are reported. This means that you need to check the size of the array before querying a particular section.
Please also note that the last section in the data array does not have to be red necessarily. For example at the end of the track, the last section might be green.
In CSV/RW routes, the Track.Section (CSV) or @Section (RW) command is used to create signalling sections. The data.Aspect member corresponds to any of the aspects defined by this command.
void SetBeacon(BeaconData data)
This function is called when a beacon is passed by the front of the train.
Arguments:
BeaconData | data | The beacon data. |
BeaconData (class):
int | Type | Gets the type of beacon. |
int | Optional | Gets optional data the beacon transmits. |
SignalData | Signal | Gets the section the beacon is attached to. |
SignalData (class):
int | Aspect | Gets the aspect of the section. |
double | Distance | Gets the distance to the section. |
In CSV/RW routes, the Track.Beacon (CSV) or @Beacon (RW) command is used to install beacons on the route. Both the beacon type and the optional data set by this command is transmitted to the train plugin along with the distance to the attached section.
Please note that plugins may receive beacon types less than 0. These beacon types are reserved for future use and must be ignored by current plugins.
void PerformAI(AIData data)
This function is called when the AI is performed.
Arguments:
AIData | data | The AI data. |
AIData (class):
Handles | Handles | Gets or sets the driver handles. |
AIResponse | Response | Gets or sets the AI response. |
Whenever you let the AI perform something, set data.Response to a value other than AIResponse.None. Please also see the section on supporting the AI.
■ Playing sounds
You can play custom sounds from within your plugin. Custom sounds need to be configured inside the sound.cfg file before they can be used by the plugin. In order to play such sounds, keep a reference to the PlaySound function that is passed in the Load call. You can then start playing sounds at any time by calling this function:
SoundHandle PlaySound(int index, double volume, double pitch, bool looped)
Arguments:
int | index | The index to the sound to be played. |
double | volume | The initial volume of the sound. A value of 1.0 represents nominal volume. |
double | pitch | The initial pitch of the sound. A value of 1.0 represents nominal pitch. |
bool | looped | Whether the sound should be played in an indefinate loop. |
Return value:
SoundHandle | The handle to the sound, or a null reference if the sound could not be played. |
When you call the PlaySound function, a handle will be returned that you can use to later check if the sound is still playing, in order to change the volume or pitch, or to stop playing the sound. If you play a sound in a loop, you must keep the handle in order to subsequently stop the sound - otherwise it would play indefinately. The handle returned by PlaySound is of the following form:
SoundHandle (class):
bool | Playing | Gets whether the sound is still playing. Once this returns false, the sound handle is invalid. |
bool | Stopped | Gets whether the sound has stopped. Once this returns true, the sound handle is invalid. |
double | Volume | Gets or sets the volume. A value of 1.0 represents nominal volume. |
double | Pitch | Gets or sets the pitch. A value of 1.0 represents nominal pitch. |
void | Stop() | Stops the sound and invalidates the handle. |
Please note that depending on the implementation by the host application, sounds that are not in audible range may not be played at all.
Please also note that the handle returned might be a null reference in the case the host application could not play the sound, for example because the file could not be found.
■ Supporting the AI
Usually, the host application performs the AI. However, your plugin might require special operation precedures which the built-in AI cannot know of. For this reason, you can complement the built-in AI by performing operation procedures specific to your plugin. Before considering to support the AI, however, you should understand what the AI is intended to represent: a human being standing or sitting in the cab, operating levers and pressing buttons, just like the player. This means that the AI must not operate 6 levers and 12 buttons simultaneously, but only do one thing at a time.
If you want to support the AI, first set data.AISupport inside the Load call to AISupport.Basic. Whenever the host application performs an AI round, a call to PerformAI will then be made inside the plugin. The plugin can then decide to let the AI perform an action, or to pass and let the host application perform an action. Different kinds of actions can take different amounts of time, so whenever the plugin lets the AI perform an action, it will also set the time it takes before the next action can be performed.
It is important to understand that unless your plugin also simulates a full ATO with automatic stopping at stations, you must let the host application perform the AI for most of the time and only intervene if absolutely necessary, for example in order to start the engine, to acknowledge a vigilance device, etc. Whenever this is the case, react to the PerformAI call appropriately:
void PerformAI(AIData data)
Arguments:
AIData | data | The AI data. |
AIData (class):
Handles | Handles | Gets or sets the driver handles. |
AIResponse | Response | Gets or sets the AI response. |
Handles (class):
int | Reverser | Gets or sets the reverser position. |
int | PowerNotch | Gets or sets the power notch. |
int | BrakeNotch | Gets or sets the brake notch. |
bool | ConstSpeed | Gets or sets whether the const speed system is enabled. |
The meanings of the notches are explained in the sections on SetReverser, SetPower and SetBrake.
AIResponse (enumeration):
AIResponse.None | No action was performed by the plugin. |
AIResponse.Short | The action performed took a short time. |
AIResponse.Medium | The action performed took an average amount of time. |
AIResponse.Long | The action performed took a long time. |
You can directly control the driver handles with the data.Handles member, for example if you want to cut power or apply a certain brake notch. For plugin-specific actions, you should only simulate key presses, for example by calling KeyDown or KeyUp. This will prevent you from letting the AI cheat in any way. If you let the AI operate the handles, you should only change by one notch at a time with a short response time.
If you decide to let the AI do something, you must set the data.Response member to a meaningful value. For operating the handles, best use a short response time, while for other actions like turning a switch not directly accessible, use a long response time. Note that the actual timings are at the whim of the host application.
Example:
' | |
▶ | if (AtsAlarm) { /* The driver needs to cut power and apply the brakes, * then press the virtual S key.*/ if (data.Handles.PowerNotch > 0) { /* We change only by one notch at a time. */ data.Handles.PowerNotch -= 1; data.Response = AIResponse.Short; } else if (data.Handles.BrakeNotch < 2) { /* We change only by one notch at a time. */ data.Handles.BrakeNotch += 1; data.Response = AIResponse.Short; } else { /* We simulate a key press here. */ KeyDown(VirtualKeys.S); data.Response = AIResponse.Medium; } } else if (AtoActive) { /* Our ATO does not require driver interaction, so * let's prevent the built-in AI from doing anything. */ data.Response = AIResponse.Long; } else { /* Let the host application perform a default action * such as braking for signals or stations. */ data.Response = AIResponse.None; } |