TNI TrainzScript Interface
From TrainzOnline
The TNI TrainzScript Interface is a protocol and associated functions which allows communication between TrainzScript and a third-party TNI plugin.
All TNI plugin DLLs must adhere to the TNI Core Interface.
This page is a work in progress, and reflects technologies which are not present in the retail version of Trainz.
Creating a TNI Library Asset
In order to access a TrainzNativeInterface plugin from TrainzScript, the following steps are taken:
- The TNI plugin DLL is created in the normal fashion. (eg. "ScriptedPlugin.dll")
- A single KIND Library asset is created to represent the TNI plugin. (eg. "ScriptedPluginLibrary")
- The "tni-library-name" tag is added to the library asset, with the value being the name of the TNI plugin DLL. (eg. "tni-library-name ScriptedPlugin")
Accessing a TNI Library from TrainzScript
Accessing a TNI Library from TrainzScript is fairly straightforward:
- The library ("ScriptedPluginLibrary") is loaded by script in the normal fashion, using TrainzScriptBase.GetLibrary(). This causes the native TNI plugin DLL ("ScriptedPlugin.dll") to be loaded, and an instance of the plugin's TNILibrary to be created for the current script context.
- Any calls to Library.LibraryCall() on the library object which are not intercepted by script are forwarded to the native TNILibrary dispatch function. The 'function' and 'stringParam' arguments to the LibraryCall() function are passed as the 'functionName' and 'params' arguments, respectively. The 'objectParam' parameter is reserved for future expansion and should be left null or empty.
- LibraryCalls made from TrainzScript threads will cause the thread to sleep while the TNI plugin responds to the function call. This will take a minimum of one render frame, and so rapid dispatch of many functions in this manner is not practical.
- LibraryCalls made from non-threaded code will cause the TNI plugin to respond to the function call in the background, and will immediately return an empty string to the calling script.
- Regardless of which approach is used, all calls are placed in a queue and are executed in-order on a single native thread. If the script context is shut down while function calls are outstanding, those function calls may be cancelled.