Skip to content

Developing for the project

Please use the project's homepage on GitHub to file issues and submit pull requests.

All code for the Open NEC project is currently written in Lua, plus some Python to automate the building process.

Train Simulator uses Lua 5.0. It will compile .lua files, but if an .out file is present with the same filename, the bytecode will be prioritized over the source file. Therefore, unless we want to require our users to unpack their .ap files, we must replace the target .out file with our own compiled bytecode.

Repository structure

  • Src\Mod\ maps to Train Simulator's Assets\ folder on a 1:1 basis. Replacement Lua code goes here.
  • Src\Lib\ contains any common Lua code. The build system automatically includes these files when linting or compiling files in Src\Mod\.
  • Docs contains the Markdown text of this manual.
  • wscript contains build instructions, which are written for WAF.

Building the project

To compile the mod, you will need the following tools in your %PATH%:

  • python.exe: a recent copy of Python 3 is required. Our build system uses WAF, which runs on Python.
  • luacheck.exe: the Luacheck linter. Its static analysis capabilities are much appreciated for an untyped language like Lua. Although it was designed for Lua 5.1+, it works well enough on 5.0—with the exception of variable length arguments, which it misinterprets as "unused variables." The static Windows executable will work just fine.
  • lua-format.exe: the LuaFormatter code formatter. You can obtain a Windows executable from the repository for the official Visual Studio Code extension.
  • compressonatorcli.exe: The CLI version of AMD's Compressonator, a tool we use to generate DDS textures.

In the root directory of the project, run python waf configure to confirm that your system has met all of these requirements.

The build process also needs to be informed of the location of Train Simulator—the game comes with several essential command-line utilities. The WAF script attempts to infer its location using the Steam uninstallation path in the Registry. If this autodetection fails, you should set the %RAILWORKS% environment variable to the path to your copy of Train Simulator.

If all looks good after the configure step, run python waf build to compile the project. The compiled files will output to the Mod\ folder, from which they can be copied into Train Simulator's Assets\ folder. (You can copy all artifacts into the Assets folder by running python waf build install.) The build process will also run LuaFormatter on the code to enforce a consistent style.

Other useful WAF commands include:

  • python waf clean: delete compiled files in the Mod\ folder.
  • python waf distclean: delete the Mod\ folder entirely.
  • python waf release: build a redistributable Zip archive for a release.

Programming resources

The following tools are not needed to compile project, but they may assist you in development work:

  • unluac can be used to decompile and study (to varying degrees of success) Dovetail's Lua bytecode.
  • My Rail Sim Remote program exposes Train Simulator's RailDriver interface via a REST API. You can use this in conjunction with cURL or a browser developer console to experiment with a locomotive's controls.
  • Build the website with MkDocs using the included Visual Studio Code development container. Or, install MkDocs directly.
  • If you have Discord, join the Train Sim Community server for modding tips, street cred, and comradery.

Reference material

Coding style

  • Please follow the standard Lua style. That means 2-space indents.
  • Dovetail's programmers don't take full advantage of the language's features, so don't use their source files as a reference.
  • Write packages using PiL's suggested "privacy" style, and classes using PiL's suggested "basic" style.
  • Lua places heavy emphasis on tables and their pairs() and ipairs() iterators. I've created the Iterator package to introduce useful transformations and compositions for such key-value iterators.