The District of Joban Difference between revisions of "JCM:Building a Scripted PIDS Preset"

Difference between revisions of "JCM:Building a Scripted PIDS Preset"

From The District of Joban
(Fix alignment)
Line 167: Line 167:
[[File:JCM JS PIDS Tutorial v0.4.png|thumb|287x287px|''<small>(The reason the bottom line appears to be more "left" than the top line is due to Minecraft's imperfection when rendering TTF font, it will work fine if you switch to Minecraft font or with most other text combination)</small>''|none]]
[[File:JCM JS PIDS Tutorial v0.4.png|thumb|287x287px|''<small>(The reason the bottom line appears to be more "left" than the top line is due to Minecraft's imperfection when rendering TTF font, it will work fine if you switch to Minecraft font or with most other text combination)</small>''|none]]


[TODO v0, actually code]
==== Rendering Arrivals ====
During the tutorial, you might have noticed the pids object in the create/render/dispose function. This represents our pids object, where we can obtain arrivals and more from there.
 
[TODO v0]


=== v1: Light Rail, Light Rail Everywhere! ===
=== v1: Light Rail, Light Rail Everywhere! ===

Revision as of 14:47, 3 November 2024

This is a step-by-step tutorial on building a Scripted PIDS Preset using JavaScript.

By the end of the tutorial, you would have built a Fictional LRT (Light Rail) version of the MTR Railway Vision PIDS, which can adapt to Custom PIDS Messages and handling long string.

Top: Default RV PIDS Preset, Bottom: Custom JS-based PIDS Preset

Getting started

To get started, [download](link here) the tutorial resource pack here and apply it to Minecraft. This resource pack specifically set-up for this tutorial, and therefore the JS scripts inside are (mostly) empty. However we can still take a look at how a Scripted PIDS Preset is set-up.

joban_custom_resources.json

The file will look like this:

{
  "pids_images": [
    {
      "id": "pids_tut",
      "name": "DIY JS Preset",
      "scripts": ["jsblock:scripts/pids_tut.js"]
    }
  ]
}

This is mostly the same from a JSON PIDS Preset, except the scripts which is a JSON array that points to the actual JS script to load for this preset. Multiple JS files can be loaded for the same preset, however to keep things simple, we are simply going to use 1 single JS file, scripts/pids_tut.js.

scripts/pids_tut.js

By opening up pids_tut.js in the scripts folder in a text editor (Notepad etc.), we can see the following script:

function create(ctx, state, pids) {
  // Your custom logic here...
}

function render(ctx, state, pids) {
  // Your custom logic here...
}

function dispose(ctx, state, pids) {
  // Your custom logic here...
}

Our custom logic can be placed between each curly brackets on each of the function. As seen, there are a total of 3 functions: create, render, dispose.

The create function is called when our PIDS enters the player's view. So this means that when a player switches the PIDS preset to our preset, or if a player is approaching a station with our PIDS in sight, everything within the curly bracket of the create function will be run.

The render function is called every frame (So 60fps = 60 times per second)*. Notice the asterisk? Because running scripts simply takes time, even if a short amount of time. JCM will try to, whenever possible, call your function every frame. However if there are too many scripts or your script is slow, then it may not be called every frame.

The dispose function is called when a PIDS Preset is switched away from, or the PIDS is no longer in sight for the player. This can be used to do clean-up work in complex PIDS that stores texture etc.


In this tutorial, the most useful one is going to be the render function, since this is where we can obtain up-to-date information and dynamically render our PIDS. But let's not get ahead of ourselves, and instead start from something very simple: A hello world scripts.

Hello, World!

First, let's insert print("Hello World ^^"); to the brackets within the create function

And now, let's insert print("Goodbye World ^^;"); within the brackets of the dispose function.

Now F3+T and look at your game console!

You should the following message:

[JCM] [Scripting] Hello World ^^

[JCM] [Scripting] Hello World ^^

As PIDS in JCM (as well as MTR) are constructed in a way where each "side" is drawn separately, a normally placed PIDS will would call the function 2 times. This is normal behavior, you didn't do anything wrong!

Now, you can try going very far away from the PIDS, to the point where you can visually no longer sees them. (More technically, when the PIDS chunk is no longer loaded). You will notice the following 2 also pops up:

[JCM] [Scripting] Goodbye World ^^;

[JCM] [Scripting] Goodbye World ^^;

There you have it, a simply Hello World script for the Scripted PIDS Preset.

(In case you got lost, run /tp 0 -60 0).

So this concludes the Scripted PIDS tutorial, I hope that...

No where are you going!

ok I am sorry :<

Now let's actually draw the "Hello World" text onto the PIDS, because printing to console isn't considered exciting for most players apparently!

We can insert the following code to the render method to draw a text with "Hello World":

Text.create().text("Hello World").draw(ctx);

If this looks confusing, we can also split it line by line in the code:

Text.create()
.text("Hello World")
.draw(ctx);

This creates a text, setting the text content to "Hello World", and then drawing it to the ctx (Which is a provided parameter in the render function, more on that later).

A statement is only considered finish by ending with a semicolon (;), so our code will still work after breaking down to different lines. For readability purposes, opening new line is generally preferred.

So now your render function code should look something like this:

function render(ctx, state, pids) {
    Text.create()
    .text("Hello World")
    .draw(ctx);
}

Now let's save the file, reload with F3+T and see what happens!

*checks date* It's not April Fools yet is it?

Ok our text do actually get rendered, the only problem is that the default text color is black, and as you might have realized, black text on black background is not necessarily a very visible color combination.

Let's change our text to be rendered with the white color so we can see!

The hex color code for a solid white color is "FFFFFF", so we can add the following line to our text, before .draw():

.color(0xFFFFFF)

(0x is used to depict that the number is a hexadecimal number)

So our text code should look something like this:

Text.create()
.text("Hello World")
.color(0xFFFFFF)
.draw(ctx);

Note that .draw is the final command and you cannot append anything afterwards, so any setting must be appended before .draw.

Now reload our resource pack again and we now see our text!

A white text in our PIDS saying "Hello World"

With this logic, we can append a second Text block to render 2 text as well!

function render(ctx, state, pids) {
    Text.create()
    .text("Hello World")
    .color(0xFFFFFF)
    .draw(ctx);
    
    Text.create()
    .text("Joban Client Mod v2!")
    .color(0xFFFFFF)
    .draw(ctx);
}
I mean it technically did render twice...

But it's hard to see, let's move each of them apart!

We can use the .pos(x, y) command to set the position of an element.

By default, a text have a height of 9, so we can append .pos(0, 9) to set the text position to 9 unit downwards:

function render(ctx, state, pids) {
    Text.create()
    .text("Joban Client Mod v2!")
    .color(0xFFFFFF)
    .pos(0, 9)
    .draw(ctx);
}
(The reason the bottom line appears to be more "left" than the top line is due to Minecraft's imperfection when rendering TTF font, it will work fine if you switch to Minecraft font or with most other text combination)

Rendering Arrivals

During the tutorial, you might have noticed the pids object in the create/render/dispose function. This represents our pids object, where we can obtain arrivals and more from there.

[TODO v0]

v1: Light Rail, Light Rail Everywhere!

[TODO v1]

v2: Something is missing

[TODO v2 plat number]

v3: It's still missing

[TODO v3 header bar]

v4: Go ham!

[TODO v4 overflow adjustment]

v5: It's coming together