JCM:Scripting
Views
Actions
Namespaces
Variants
Tools
Scripting Documentation
JCM Scripting is a feature introduced in JCM v2.0.0-beta.5. It serves as a testbed for scripting in MTR 4, as well as using JavaScript to control PIDS.
The system itself is heavily influenced by the Nemo Transit Expansion and shares much of the similarities. As such, most of the documentation include this page is also referenced from the NTE JS documentation.
Note: This page serves as a documentation for the whole scripting system implemented in JCM, which includes Eyecandy/Decoration Block Scripting and PIDS Scripting.
===== Subpages ====
- Resource Loading Method
- Utilities Method
- Dynamic Textures
- Scripted PIDS Documentation
- Scripted Eyecandy Documentation (Same as NTE)
Introduction
How To Edit JavaScript Files?
A JavaScript file (.js) can be edited in a variety of editors. It is recommended to have a text editor that supports JavaScript Syntax Highlighting like Notepad++ or Sublime text. While a full IDE (like Visual Studio Code or IntelliJ) is not recommended, it can also be used as a basic text editor.
This rest of this article assumes that you have a basic understanding of JavaScript and JavaScript types, so it won't delve into the basic syntax and other aspects of it here. You can learn JavaScript from resources on the web, such as here.
Type Annotation
As you know, values in JS have different types. When calling a function, you must pass parameters of the appropriate type, and the result it returns will also have a type. In this article, all of the functions have their parameter and return types stated. For example:
static Resources.id(idStr: string): Identifier
static
means that you don't need to create an object to use this function, you can callResources.id("aaa:bbb")
directly.idStr: string
means that theidStr
parameter accepts a string.: Identifier
means that a function call will return a value of typeIdentifier
.
Matrices.rotateX(radian: float): void
- The lack of
static
means that an object is required to execute the function. For example, ifa
is an object of Matrices type, then the function can be called asa.rotateX(Math.PI)
. radian: float
means that the parameter takes a numeric argument. Although JS does not distinguish between integers and fractional numbers, this article will specify a specific type -int
,long
,float
ordouble
- to make it clear whether a parameter can accept decimal parts and to what precision.: void
means that the function has no return value.
Using Built-In Java Classes
The Rhino JS engine allows using classes from the standard Java library as java.package.name
. Using classes from MTR is not available yet, most likely due to problems with the class loader.
Errors
If the script is executed incorrectly, an error will be reported in the Minecraft log (Starting with “[Scripting] Error executing script!”). (Please note that at the moment there will not be any in-game indication)
The error message will indicate which line of code in which script file the error occurred. Most launchers have the ability to display logs in a separate window in real time.
The script execution engine will then pause the entire script for 4 seconds before executing the function again.
Tips & Notes
Declaring variables using let or var
Both NTE and JCM uses JavaScript's strict mode, which does not allow variables to be assigned without first declaring them.
To declare a global variable, use syntax like var glb;
or outside a function var glb = 1;
. To use local variables inside a function, use let local;
or let local = 1;
.
[Translator's note: in general, it is better to always try to use let
and resort to using var
as a last resort].
Don't Block Or Infinitely Loop
The function you wrote are called once per frame by JCM, where your function is expected to finish processing and return a value as soon/fast as possible. As such, there's no such concept as “wait for a while before continue executing”.
Instead, what you likely want is to "do a thing later on", in such case you will need to time it and then execute the appropriate action on a call made at the right time.
If you are trying to execute a long-running operation (e.g. Fetching data over the internet), you should submit it to another thread/executor.
If blocks or infinite loops did occur, then the entire script execution will stall as scripts are executed one at a time [in the same thread]. In such situation, you can reset it with F3+T.
Differences When Using Java Classes/Methods
For common function types such as strings, Java and JavaScript have different class implementations, which causes there to be JavaScript strings as well as Java strings.
NTE/MTR functions and fields return Java string classes rather than JavaScript strings, but Rhino does some conversions automatically, so in most cases you can mix and match, but sometimes this can cause problems.
For example, here's an example of a problem caused by using str.length()
from a Java string class and str.length
from a JavaScript string class to get the length of a string:
var stationName = train.getThisRoutePlatforms().get(0).station.name; print(stationName.length); // Error: stationName is a Java string, not a JavaScript string print(stationName.length()); // Java strings get their length from the length() function, not the JavaScript length field print((""+stationName).length) // Use ""+ to turn it into a JavaScript string.
Similarly, there is a List<T>
type in Java. It does the same thing as arrays in JavaScript, but has a different type. Trying to call JavaScript array functions on it won't work, but Rhino adapts it so that you can take values with list[0]
or loop through them with for (a of list)
.
Supported Parts Of The JavaScript Standard
The Rhino engine does not support all of the latest JavaScript features. See Mozilla's documentation for details on what is supported. JCM uses Rhino 1.7.15 with the VERSION_ES6
flag enabled.
Running Other Scripts
By calling the function below, you can include and execute other JavaScript files.
Functions | Description |
---|---|
static include(relPath: String): void
|
Loads and runs another JS file relative to the current JS file. |
static include(path: Identifier): void
|
Loads and runs the JS file by location in the resource pack.
For example, |