The District of Joban Difference between revisions of "JCM:Scripting:Documentation:PIDS"

Difference between revisions of "JCM:Scripting:Documentation:PIDS"

From The District of Joban
m (LX86 moved page JCM:Scripted PIDS Preset:Documentation to JCM:Scripting:Documentation:PIDS without leaving a redirect)
m (semicolon;)
 
(11 intermediate revisions by the same user not shown)
Line 1: Line 1:
===Adding a Scripted PIDS Preset===
===Adding a Scripted PIDS Preset===
A preset is automatically considered as a Scripted PIDS Preset by specifying the <code>scripts</code> property in <code>joban_custom_resources.json</code>:
A preset is automatically considered as a Scripted PIDS Preset by specifying either <code>scriptFiles</code> '''or''' <code>scriptTexts</code> property in <code>joban_custom_resources.json</code>:


<pre>
<pre>
Line 8: Line 8:
       "id": "pids_tut",
       "id": "pids_tut",
       "name": "JS Tutorial Preset",
       "name": "JS Tutorial Preset",
       "scripts": ["jsblock:scripts/pids_tut.js"]
       "scriptTexts": ["print('Goodbye World');"],
      "scriptFiles": ["jsblock:scripts/pids_tut.js"]
     }
     }
}
}
</pre>At the moment, mixing Scripted PIDS Preset and JSON PIDS Preset is not possible.
</pre><code>scriptFiles</code> points to the list of script file to load.
 
<code>scriptTexts</code> allows you to directly write JS inside, but should only be used for simple variable declaration.
 
At the moment, mixing Scripted PIDS Preset and JSON PIDS Preset is not possible.


=== Global Environment ===
=== Global Environment ===
Line 19: Line 24:


Code written in top-level space outside of functions will run when a resource package is loaded, and can be used to load resources such as models and textures. It is recommended to store resources (such as models, fonts and textures) in global variables, which do not need to be different for each PIDS block, to avoid excessive memory usage caused by loading a copy of the same content for each PIDS.
Code written in top-level space outside of functions will run when a resource package is loaded, and can be used to load resources such as models and textures. It is recommended to store resources (such as models, fonts and textures) in global variables, which do not need to be different for each PIDS block, to avoid excessive memory usage caused by loading a copy of the same content for each PIDS.
=== Draw Procedure ===
To conserve in-game performance, JCM runs the script in a separate thread from the PIDS rendering logic.
When you command JCM to draw text/texture with <code>Text.draw</code> or <code>Texture.draw</code>, it doesn't actually initiates the rendering, but merely adds the object to a list of things that should be rendered.
When the next frame comes around, JCM will update the list of things that should be drawn, and then it draws the element. Therefore the scripting performance itself should have minimal impact even by drawing a lot of elements. (In-game is another story)
Unless you use [[JCM:Scripting:Documentation:PIDS#Using AWT Graphics/Dynamic Textures|AWT Graphics to render the PIDS]], all text and texture drawn are '''regular polygon drawn to the Minecraft world'''. As such it is possible for elements to overflow beyond the PIDS screen, and it is the developer responsibility to ensure it would not happen.
== Versioning ==
You can obtain JCM version by using <code>Resources.getAddonVersion("jcm")</code>.
This would return a string formatted like: <code>2.0.0-beta.5</code>


== Called Functions ==
== Called Functions ==
Line 44: Line 63:
|-
|-
|First (<code>ctx</code>)
|First (<code>ctx</code>)
|Used to pass train rendering actions to the NTE. Type — PIDSScriptContext.
|Used to pass rendering actions to JCM. Type — PIDSScriptContext.
|-
|-
|Second (<code>state</code>)
|Second (<code>state</code>)
Line 50: Line 69:
The initial value is {}, and its content can be set arbitrarily to store what should be different for each PIDS Block.
The initial value is {}, and its content can be set arbitrarily to store what should be different for each PIDS Block.
|-
|-
|Third (pids)
|Third (<code>pids</code>)
|Used to get the status of pids and arrivals. Type — PIDSWrapper
|Used to get the status of pids and arrivals. Type — [[JCM:Scripting:Documentation:PIDS#PIDSWrapper|PIDSWrapper]]
|}
|}
The following lists all the rendering control operations that can be performed and all the information that can be obtained about PIDS.
The following lists all the rendering control operations that can be performed and all the information that can be obtained about PIDS.


==== PIDSScriptContext ====
== Type Definition ==
 
=== Rendering Related ===
 
==== Text (TextWrapper) ====
{| class="wikitable"
{| class="wikitable"
!Functions And Objects
!Functions And Objects
!Description
!Description
|-
|-
|<code>PIDSScriptContext.cycleString(mtrString: string): string</code>
|<code>Text.create()</code> / <code>Text.create(comment: string)</code>
|<nowiki>This cycles part of a string, separated by the pipe-character (|).</nowiki>
|Create a new text object
|-
|<code>Text.pos(x: number, y: number): TextWrapper</code>
|Set the X and Y position of the element
|-
|<code>Text.size(w: number, h: number): TextWrapper</code>
|Set the width and height of the element
(Used in conjunction with <code>Text.stretchXY()</code> and <code>Text.scaleXY()</code>
|-
|<code>Text.text(str: string): TextWrapper</code>
|Set the text content to str
|-
|<code>Text.scale(i: double): TextWrapper</code>
|Set the text's scale to i
|-
|<code>Text.leftAlign(): TextWrapper</code>
|Align the text to the left (Default)
|-
|<code>Text.centerAlign(): TextWrapper</code>
|Align the text to the center
|-
|<code>Text.rightAlign(): TextWrapper</code>
|Align the text to the right
|-
|<code>Text.shadowed(): TextWrapper</code>
|Add shadow to the drawn text
|-
|<code>Text.italic(): TextWrapper</code>
|Set the text style to Italic
|-
|<code>Text.bold(): TextWrapper</code>
|Set the text style to Bold
|-
|<code>Text.stretchXY(): TextWrapper</code>
|Text Overflow Mechanism:
When text overflowed beyond it's size, stretch the text on the overflowing axis to fit
|-
|<code>Text.scaleXY(): TextWrapper</code>
|Text Overflow Mechanism:
When the text overflowed beyond it's size, stretch the text on both axis to fit
(Keep aspect ratio)
|-
|<code>Text.wrapText(): TextWrapper</code>
|Text Overflow Mechanism:
When the text overflowed beyond it's size, split the text into the next line without any scaling.
|-
|<code>Text.marquee(): TextWrapper</code>
|Text Overflow Mechanism:
When the text overflowed beyond it's size, draw a portion of the text at a time with scrolling animation
|-
|<code>Text.fontMC(): TextWrapper</code>
|Use vanilla Minecraft's font
|-
|<code>Text.font(id: string): TextWrapper</code> / <code>Text.font(id: Identifier): TextWrapper</code>
|Set the font used
|-
|<code>Text.color(color: number): TextWrapper</code>
|Set the text color, in RGB format.
|-
|<code>Text.draw(ctx: PIDSScriptContext): void</code>
|Mark the text as something that should be rendered to the PIDS.
|}
 
=== Texture (TextureWrapper) ===
{| class="wikitable"
!Functions And Objects
!Description
|-
|<code>Texture.create()</code> / <code>Texture.create(comment: string)</code>
|Create a new texture object
|-
|<code>Texture.pos(x: number, y: number): TextureWrapper</code>
|Set the X and Y position of the element
|-
|<code>Texture.size(w: number, h: number): TextureWrapper</code>
|Set the width and height of the element
|-
|<code>Texture.texture(id: string): TextureWrapper</code> / <code>Texture.texture(id: Identifier): TextureWrapper</code>
|Set the texture to draw to id.
|-
|<code>Texture.color(color: number): TextureWrapper</code>
|Set the text color, in RGB format.
|-
|<code>Texture.uv(u2: number, v2: number): TextureWrapper</code> / <code>Texture.uv(u1: number, v1: number, u2: number, v2: number): TextureWrapper</code>
|Set the UV coordinates
|-
|<code>Texture.draw(ctx: PIDSScriptContext): void</code>
|Mark the texture as something that should be rendered to the PIDS.
|}
|}
=== PIDS Object Related ===


==== PIDSWrapper ====
==== PIDSWrapper ====
Line 68: Line 180:
!Functions And Objects
!Functions And Objects
!Description
!Description
|-
|<code>PIDSWrapper.type: string</code>
|Return the type of PIDS used, possible value are:
* rv_pids
* rv_pids_sil_1
* rv_pids_sil_2
* lcd_pids
* pids_projector
*pids_1a
|-
|<code>PIDSWrapper.width: number</code>
|The full width of the available PIDS screen area.
|-
|<code>PIDSWrapper.height: number</code>
|The full height of the available PIDS screen area.
|-
|<code>PIDSWrapper.rows: number</code>
|The number of arrival rows supported by the PIDS Block
|-
|-
|<code>PIDSWrapper.isRowHidden(i: number): boolean</code>
|<code>PIDSWrapper.isRowHidden(i: number): boolean</code>
Line 129: Line 260:
|Returns the departure index[?]
|Returns the departure index[?]
|-
|-
|<code>ArrivalWrapper.isTerminating(): boolean</code>
|<code>ArrivalWrapper.terminating(): boolean</code>
|Returns whether the arrival entry is terminating its service at the current platform.
|Returns whether the arrival entry is terminating its service at the current platform.
|-
|-
Line 167: Line 298:
|}
|}


=== Transport Simulation Core Type ===
=== Transport Simulation Core Related ===


==== Platform ====
==== Platform ====
Line 224: Line 355:
* HIGH_SPEED
* HIGH_SPEED
|}
|}
== Using AWT Graphics/Dynamic Textures ==
While not a regular tested use case for PIDS, you can create a [[JCM:Scripting:Documentation:Dynamic Textures|Dynamic Textures]] and draw it onto a PIDS:<pre>
importPackage(java.awt);
function create(ctx, state, pids) {
    state.tex = new GraphicsTexture(pids.width, pids.height);
}
function render(ctx, state, pids) {
    let g = state.tex.graphics;
    g.setColor(Color.RED);
    g.fillRect(0, 0, pids.width, pids.height);
    g.setColor(Color.GREEN);
    g.fillRect(0, 0, Math.abs(Math.sin(Timing.elapsed())) * pids.width, pids.height);
   
    state.tex.upload();
   
    Texture.create("Dynamic Texture")
    .texture(state.tex.identifier)
    .size(pids.width, pids.height)
    .draw(ctx);
}
function dispose(ctx, state, pids) {
    state.tex.close();
}
</pre>

Latest revision as of 14:00, 11 November 2024

Adding a Scripted PIDS Preset

A preset is automatically considered as a Scripted PIDS Preset by specifying either scriptFiles or scriptTexts property in joban_custom_resources.json:

{
  "pids_images": [
    {
      "id": "pids_tut",
      "name": "JS Tutorial Preset",
      "scriptTexts": ["print('Goodbye World');"],
      "scriptFiles": ["jsblock:scripts/pids_tut.js"]
    }
}

scriptFiles points to the list of script file to load.

scriptTexts allows you to directly write JS inside, but should only be used for simple variable declaration.

At the moment, mixing Scripted PIDS Preset and JSON PIDS Preset is not possible.

Global Environment

A script is evaluated & executed when a PIDS Preset is loaded during the resource-pack loading phase.

Therefore, the same type of PIDS Preset will use the same working environment (global variables and etc).

Code written in top-level space outside of functions will run when a resource package is loaded, and can be used to load resources such as models and textures. It is recommended to store resources (such as models, fonts and textures) in global variables, which do not need to be different for each PIDS block, to avoid excessive memory usage caused by loading a copy of the same content for each PIDS.

Draw Procedure

To conserve in-game performance, JCM runs the script in a separate thread from the PIDS rendering logic.

When you command JCM to draw text/texture with Text.draw or Texture.draw, it doesn't actually initiates the rendering, but merely adds the object to a list of things that should be rendered.

When the next frame comes around, JCM will update the list of things that should be drawn, and then it draws the element. Therefore the scripting performance itself should have minimal impact even by drawing a lot of elements. (In-game is another story)

Unless you use AWT Graphics to render the PIDS, all text and texture drawn are regular polygon drawn to the Minecraft world. As such it is possible for elements to overflow beyond the PIDS screen, and it is the developer responsibility to ensure it would not happen.

Versioning

You can obtain JCM version by using Resources.getAddonVersion("jcm").

This would return a string formatted like: 2.0.0-beta.5

Called Functions

Your script should include the following functions that JCM will call as needed:

function create(ctx, state, pids) { ... }
function render(ctx, state, pids) { ... }
function dispose(ctx, state, pids) { ... }
Functions Description
create It is called when a PIDS is rendered for the first time and can be used to perform some initialization operations, for example, to create dynamic textures.
render This function is called at-most once per frame. It is used to draw contents onto the PIDS. In practice however, the code is executed in a separate thread so as not to slow down FPS. If it takes too long to execute the code, it may be called once every few frames instead of every frame.
dispose Called when a PIDS Block goes out of sight. Can be used for things like releasing the dynamic textures to free up memory.

JCM calls these functions with three parameters, each of which is described below.

Parameter Description
First (ctx) Used to pass rendering actions to JCM. Type — PIDSScriptContext.
Second (state) A JavaScript object associated with a single PIDS Block.

The initial value is {}, and its content can be set arbitrarily to store what should be different for each PIDS Block.

Third (pids) Used to get the status of pids and arrivals. Type — PIDSWrapper

The following lists all the rendering control operations that can be performed and all the information that can be obtained about PIDS.

Type Definition

Rendering Related

Text (TextWrapper)

Functions And Objects Description
Text.create() / Text.create(comment: string) Create a new text object
Text.pos(x: number, y: number): TextWrapper Set the X and Y position of the element
Text.size(w: number, h: number): TextWrapper Set the width and height of the element

(Used in conjunction with Text.stretchXY() and Text.scaleXY()

Text.text(str: string): TextWrapper Set the text content to str
Text.scale(i: double): TextWrapper Set the text's scale to i
Text.leftAlign(): TextWrapper Align the text to the left (Default)
Text.centerAlign(): TextWrapper Align the text to the center
Text.rightAlign(): TextWrapper Align the text to the right
Text.shadowed(): TextWrapper Add shadow to the drawn text
Text.italic(): TextWrapper Set the text style to Italic
Text.bold(): TextWrapper Set the text style to Bold
Text.stretchXY(): TextWrapper Text Overflow Mechanism:

When text overflowed beyond it's size, stretch the text on the overflowing axis to fit

Text.scaleXY(): TextWrapper Text Overflow Mechanism:

When the text overflowed beyond it's size, stretch the text on both axis to fit (Keep aspect ratio)

Text.wrapText(): TextWrapper Text Overflow Mechanism:

When the text overflowed beyond it's size, split the text into the next line without any scaling.

Text.marquee(): TextWrapper Text Overflow Mechanism:

When the text overflowed beyond it's size, draw a portion of the text at a time with scrolling animation

Text.fontMC(): TextWrapper Use vanilla Minecraft's font
Text.font(id: string): TextWrapper / Text.font(id: Identifier): TextWrapper Set the font used
Text.color(color: number): TextWrapper Set the text color, in RGB format.
Text.draw(ctx: PIDSScriptContext): void Mark the text as something that should be rendered to the PIDS.

Texture (TextureWrapper)

Functions And Objects Description
Texture.create() / Texture.create(comment: string) Create a new texture object
Texture.pos(x: number, y: number): TextureWrapper Set the X and Y position of the element
Texture.size(w: number, h: number): TextureWrapper Set the width and height of the element
Texture.texture(id: string): TextureWrapper / Texture.texture(id: Identifier): TextureWrapper Set the texture to draw to id.
Texture.color(color: number): TextureWrapper Set the text color, in RGB format.
Texture.uv(u2: number, v2: number): TextureWrapper / Texture.uv(u1: number, v1: number, u2: number, v2: number): TextureWrapper Set the UV coordinates
Texture.draw(ctx: PIDSScriptContext): void Mark the texture as something that should be rendered to the PIDS.

PIDS Object Related

PIDSWrapper

Functions And Objects Description
PIDSWrapper.type: string Return the type of PIDS used, possible value are:
  • rv_pids
  • rv_pids_sil_1
  • rv_pids_sil_2
  • lcd_pids
  • pids_projector
  • pids_1a
PIDSWrapper.width: number The full width of the available PIDS screen area.
PIDSWrapper.height: number The full height of the available PIDS screen area.
PIDSWrapper.rows: number The number of arrival rows supported by the PIDS Block
PIDSWrapper.isRowHidden(i: number): boolean Returns whether the arrival for that row is hidden. (via PIDS Config)
PIDSWrapper.getCustomMessage(i: number): string Returns the custom message configured for that row via PIDS Config.

Empty string ("") if not set.

PIDSWrapper.isPlatformNumberHidden(): boolean Returns whether the platform number is set to hidden. (via PIDS Config)
PIDSWrapper.station(): Station Returns the station area that this PIDS is in.

null if not in any station.

PIDSWrapper.arrivals(): ArrivalsWrapper Returns the arrivals obtained for the PIDS.

ArrivalsWrapper

Functions And Objects Description
ArrivalsWrapper.get(i: number): ArrivalWrapper? Returns the ith arrival entry.

null if there's no ith arrival entry or no arrival information.

ArrivalsWrapper.mixedCarLength(): boolean Returns whether the list of arrivals have arrival entry with different cars.
ArrivalsWrapper.platforms(): ObjectArrayList<Platform> Returns the platforms that all arrival entry is stopping at.

ArrivalWrapper

Functions And Objects Description
ArrivalWrapper.destination(): string Returns the destination name of the arrival entry.

(Usually the destination's station, or a custom destination string)

ArrivalWrapper.arrivalTime(): number Returns the epoch time (in Millisecond) the train is arriving at.

Use new Date(value: number)to obtain a JS Date object of the arrival time.

ArrivalWrapper.departureTime(): number Returns the epoch time (in Millisecond) the train is departing at.

Use new Date(value: number)to obtain a JS Date object of the departure time.

ArrivalWrapper.deviation(): number Returns the deviation[?]
ArrivalWrapper.realtime(): boolean Returns whether the arrival entry is scheduled (i.e. Train not departed), or a real-time estimation (i.e. Train running)
ArrivalWrapper.departureIndex(): number Returns the departure index[?]
ArrivalWrapper.terminating(): boolean Returns whether the arrival entry is terminating its service at the current platform.
ArrivalWrapper.route(): Route Returns the route object of the route that the train is running on.
ArrivalWrapper.routeId(): number Returns the id of the route that the train is running on.
ArrivalWrapper.routeName(): string Returns the name of the route that the train is running on.
ArrivalWrapper.routeNumber(): string Returns the route number string (Previously called LRT Route Number).

[TODO: What does empty route number returns?]

ArrivalWrapper.routeColor(): number Returns the color of the route that the train is running on.
ArrivalWrapper.circularState(): Route.CircularState Returns the circular state of the route that the train is running on.
ArrivalWrapper.platform(): Platform Returns the platform object that the train is approaching towards.
ArrivalWrapper.platformId(): number Returns the id of the platform that the train is approaching towards.
ArrivalWrapper.platformName(): string Returns the name of the platform that the train is approaching towards.
ArrivalWrapper.carCount(): number The car length of the train in that arrival entry.
ArrivalWrapper.forEachCar(consumer: Consumer<CarDetails>): void Allows you to loop through each car of the train in that arrival entry.

Transport Simulation Core Related

Platform

Functions And Objects Description
Platform.routes: ObjectAVLTreeSet<Route> A list of routes that goes through this platform.
Platform.routeColors: IntAVLTreeSet All colors of route that goes through this platform.
Platform.getName(): string Returns the platform name.
Platform.getId(): number Returns the platform ID.
Platform.getDwellTime(): number The dwell time duration of the platform in millisecond.

Route

Functions And Objects Description
Route.depots: ObjectArrayList<Depot> A list of depot associated with this route[?]
Route.getName(): string Returns the platform name.
Route.getId(): number Returns the route ID.
Route.getColor(): number Returns the color of the route.
Route.getHidden(): boolean Returns whether the route is hidden.
Route.getDestination(index: number): string Returns name of index of the following order:
  • Custom Destination
  • Station Area Name
  • Platform Name
Route.getRouteType(): RouteType Returns the type of route:
  • NORMAL
  • LIGHT_RAIL
  • HIGH_SPEED

Using AWT Graphics/Dynamic Textures

While not a regular tested use case for PIDS, you can create a Dynamic Textures and draw it onto a PIDS:

importPackage(java.awt);

function create(ctx, state, pids) {
    state.tex = new GraphicsTexture(pids.width, pids.height);
}

function render(ctx, state, pids) {
    let g = state.tex.graphics;
    g.setColor(Color.RED);
    g.fillRect(0, 0, pids.width, pids.height);
    g.setColor(Color.GREEN);
    g.fillRect(0, 0, Math.abs(Math.sin(Timing.elapsed())) * pids.width, pids.height);
    
    state.tex.upload();
    
    Texture.create("Dynamic Texture")
    .texture(state.tex.identifier)
    .size(pids.width, pids.height)
    .draw(ctx);
}

function dispose(ctx, state, pids) {
    state.tex.close();
}