Native C++ scripting
Gives resource pack authors for Minecraft Transit Railway 4 the ability to write the five script kinds—vehicle, PIDS, lift, eyecandy and platform screen doors—in C++, with the same lifecycle and API surface as JavaScript scripts and zero JVM crossings on the hot path. Full documentation of JavaScript scripting (the upstream JCM scripting system) is in the JavaScript scripting section below.
What is this?
The original Joban Client Mod (JCM) lets resource packs write dynamic display scripts in JavaScript. The Yanyang fork adds C++ native scripting on top: scripts are compiled into native shared libraries (.dll / .so / .dylib) which the mod loads in game and drives frame by frame.
C++ and JS scripts can be mixed within the same declaration entry and rendered at the same time. The mod detects the language automatically from file characteristics—.js is JavaScript, everything else is parsed as a C++ module. Each side captures its own draw commands and replays them independently, without interference.
The same script model
The create / render / dispose lifecycle and per-instance persistent state are exactly the same as in JS; the snapshot wrappers align with the JS wrappers field for field.
Zero-JNI transport
Java ↔ C++ communicates over the shared-memory polling plane (any JDK ≥ 16) or the Panama FFM plane (JDK 22+); JNI is never involved, and there is only one host crossing per frame per instance.
Native bridge for 8 platforms
windows-x64 / windows-arm64 / linux-x64 / linux-arm64 / android-arm64 / macos-x64 / macos-arm64 / ios-arm64 are all bundled inside the jar and matched automatically by system architecture.
Crash isolation
A script crash disables only the offending module itself and leaves a single log line behind; the game process is unaffected. C++ exceptions thrown inside a module are caught by the guard in the same way.
The journey of a frame
natives/<platform>/ library files
Serialises a compact snapshot every frame
Reads the snapshot · writes draw records
Same render path as JS scripts
A fifteen-line PIDS script
#include <mtr/script.hpp>
struct ArrivalState {};
struct ArrivalDisplay : mtr::PidsScript<ArrivalState> {
static constexpr auto ID = "example:arrivals";
void render(mtr::PidsContext& ctx, ArrivalState&, const mtr::Pids& pids) override {
for (int row = 0; row < pids.rows(); row++) {
if (pids.is_row_hidden(row)) continue;
std::string text = pids.get_custom_message(row).str();
if (text.empty() && row < pids.arrivals().size())
text = pids.arrivals().at(row).destination().str();
if (!text.empty())
mtr::Text::create().text(text.c_str())
.pos(2, row * 10.0 + 2).size(pids.width() - 4, 9).draw(ctx);
}
}
};
MTR_REGISTER_PIDS_SCRIPT(ArrivalDisplay)
No JNI, no reflection, no per-call boxing—pids.rows() and arrivals().at(i).destination() are plain memory reads on a compact snapshot.
When to choose C++
| Scenario | Recommendation |
|---|---|
| High-resolution LCD / dot-matrix screens that repaint large numbers of pixels every frame | C++ Gfx2D software rasteriser + dirty-rectangle upload; pixels never cross the JVM |
| Complex string processing / per-frame sorting / mathematical computation | C++ native computation with zero allocation |
| Needs to call many Java APIs (networking, files, the sound manager) | Either both sides reach the same set of public objects through Api |
| Simple one-off display logic | JS no compiler toolchain needed; faster iteration |
Compatibility
| Item | Requirement |
|---|---|
| Minecraft | 1.17.1 – 1.20.4 (Fabric / Forge) |
| Prerequisites | Minecraft Transit Railway 4.0.5+ (required); the Fabric build also needs Fabric API |
| Java | 16 or later; 22+ automatically enables the fully zero-JNI FFM plane |
| ABI | The host accepts ABI 6–13 modules; the current SDK compiles to ABI 13 |
| Toolchain | C++17; MSVC / GCC / Clang; CMake ≥ 3.16 (recommended) |