Moduprint/API: Difference between revisions

From Resonite Wiki
No edit summary
→‎Structure of a Module: snapper and parent value link
 
(12 intermediate revisions by the same user not shown)
Line 1: Line 1:
[https://en.wikipedia.org/wiki/API Application Programming Interfaces] are commonly used in computer software for communicating between programs. Moduprint is defining an API for interacting with the manager, other modules, and any other part of the print system. This API is based on [[Dynamic_impulses|Dynamic Impulses]] and [[Dynamic_variables|Dynamic Variables]].
[https://en.wikipedia.org/wiki/API Application Programming Interfaces] are commonly used in computer software for communicating between programs. Moduprint is defining an API for interacting with the manager, other modules, and any other part of the print system. This API is based on [[Dynamic_impulses|Dynamic Impulses]] and [[Dynamic_variables|Dynamic Variables]].
* [[Moduprint/API/Methods|All methods]]
* [[Moduprint/API/Registries|All registries]]
=== Methods ===
All methods that can be called on a manager are defined as Dynamic Reference Variables of a dynamic impulse receiver. For the calling convention, see below. All methods are documented under [[Moduprint/API/Methods]].


=== Structure of a Module ===
=== Structure of a Module ===
Line 20: Line 27:
|-
|-
| <code>Module/ManifestOwner</code>    || {{Template:TypeColorCard|String}} || Optional || Reserved for future use
| <code>Module/ManifestOwner</code>    || {{Template:TypeColorCard|String}} || Optional || Reserved for future use
|-
| <code>Module/Requirements</code> || {{Template:TypeColorCard|Slot}} || Optional || List of requirements of the module, such as dependencies or the manager version
|-
|-
| <code>Module/Lifecycle.Register</code> || {{Template:TypeColorCard|Slot}} || Optional || List of registry entries to create
| <code>Module/Lifecycle.Register</code> || {{Template:TypeColorCard|Slot}} || Optional || List of registry entries to create
Line 29: Line 38:


The module ID is of the format <code>Namespace.Module</code> where <code>Namespace</code> is anything uniquely identifying the creator such as the user or group name and <code>Module</code> is the identifier of the module. Only one module with the same ID can be installed on the same manager at any point in time. The ID must only contain letters which are valid for a [[Dynamic_variables|Dynamic Variable]].
The module ID is of the format <code>Namespace.Module</code> where <code>Namespace</code> is anything uniquely identifying the creator such as the user or group name and <code>Module</code> is the identifier of the module. Only one module with the same ID can be installed on the same manager at any point in time. The ID must only contain letters which are valid for a [[Dynamic_variables|Dynamic Variable]].
The registries are given as Slot children which each have a (not directly binding) [[Component:DynamicVariableSpace|Dynamic Variable Space]] on them as well as a dynamic [[Slot]] variable <code>Target</code> pointing to the registry entry.
Each module should have a [[Component:Snapper|Snapper]] with the tags <code>Moduprint.Module</code> and <code>Moduprint.Module/<i>ID</i></code> and a radius of 0.01.
To hide the module visual when it is installed, add a [[Component:ParentValueLink|Parent Value Link]] of type <code>bool</code> matching the tag "Moduprint.ModuleVisual" and set it to be true by default.
=== Requirements ===
Requirements are conditions which must be fulfilled before a module can be installed. They are defined as slots under the slot which the Dynamic Variable <code>Module/Requirements</code> is pointing to. Those slots have a [[Component:DynamicVariableSpace|Dynamic Variable Space]] which contains the following variables. The tag of the slot is the type of the requirement. If the type is not known or supported by the manager, the module is rejected.
{| class="wikitable"
|+Dynamic Variables
|-
! Name !! Type !! !! Purpose
|-
| <code>MinVersion</code> || {{Template:TypeColorCard|uint3}} || Optional || Minimum version of module or manager.
|-
| <code>MaxVersion</code> || {{Template:TypeColorCard|uint3}} || Optional || Inclusive maximum version of module or manager. The maximum version number is <code>4294967295</code>.
|-
| <code>Optional</code> || {{Template:TypeColorCard|bool}} || Optional || If the dependency is optional.
|}
==== Manager ====
The <code>Manager</code> requirement only allows installation of the module if the manager version is within the given range.
==== Dependency ====
The <code>Dependency</code> requirement only allows installing a module if a module identified by the slot's name is already installed. This module will have a Dynamic Reference variable with the name <code>Module/Dependency.<i>ID</i></code> defined which will hold the slot of the module depended upon.
Slot children with the name of slot reference variables that are defined on the dependency module will be defined on this module with the prefix <code>Module/Dependency.<i>ID</i>.<i>Variable</i></code>.
For example, adding a slot with the name <code>Method.Raycast</code> under the dependency requirement slot with the name <code>ColinTheCat.PrintRaycasting</code> will lead to the variable <code>Module/Dependency.ColinTheCat.PrintRaycasting.Method.Raycast</code> being defined on this module.
==== Unique ====
Only one module can be installed on the print with the same unique requirement at the same time. This is useful to prevent incompatible modules from being installed. For example, the <code>ColinTheCat.Colors</code> module has the unique requirement "Print.Tint" because it sets up a driver to the field <code>Print/Tint</code>, making it incompatible with any module that attempts to drive the same field.


=== Registries ===
=== Registries ===


Registries are the core system of Moduprint for communication between modules. A registry has a unique name and contains a list of entries. Every module can create an arbitrary amount of registry entries. Registry entries are just [[Slot|Slots]] with the name of the registry and a tag for priority.
All registries are documented under [[Moduprint/API/Registries]].
 
Registries are the core system of Moduprint for communication between modules. A registry has a unique name and contains a list of [[Slot]] entries. Every module can create an arbitrary amount of registry entries. Entries are defined as children under the slot which the Dynamic Variable <code>Module/Lifecycle.Register</code> is pointing to. Those slots have a [[Component:DynamicVariableSpace|Dynamic Variable Space]] which contains the following variables.
{| class="wikitable"
|+Dynamic Variables
|-
! Name !! Type !! !! Purpose
|-
| <code>Entry</code>      || {{Template:TypeColorCard|Slot}} || Required || Slot that should be registered.
|-
| <code>Registry</code> || {{Template:TypeColorCard|String}}  || Required || Name of the registry this entry belongs to.
|-
| <code>Priority</code>    || {{Template:TypeColorCard|String}} || Optional || Entry priority in the registry, see below.
|}


{| class="wikitable"
{| class="wikitable"
Line 53: Line 113:
|}
|}


Instead of a priority name, a number can also be used directly as the tag.
Instead of a priority name, a number can also be used directly.
The monitor priority should only used for event listeners which only check for the final data of the event without modifying it.
The monitor priority should only be used for event listeners which only check for the final data of the event without modifying it.
 
Registries are both used as a kind of dynamic list (for example for selection modes or packing handlers) and for registering event listeners. In the latter case, the registry entry should be a [[ProtoFlux:Dynamic_Impulse_Receiver|Dynamic Impulse Receiver]]. High priority listeners are pulsed first (sorted by priority).
 
==== Events ====
 
Events are a special type of registry where each entry is a [[ProtoFlux:Dynamic_Impulse_Receiver_With_Data|Dynamic Impulse Receiver]] of a slot. The slot has a [[Component:DynamicVariableSpace|Dynamic Variable Space]] holding the event data. All variables are local (not networked). Some of the variables are meant to be modified by listeners, for example to change the result of an operation. Use [[Moduprint/API/Methods#DispatchEvent|DispatchEvent]] and [[Moduprint/API/Methods#DispatchAsyncEvent|DispatchAsyncEvent]] to dispatch an event.
 
All events on a manager are defined as Dynamic Reference Variables of the data slot following the naming scheme <code>Manager/EventData.<i>EventName</i></code>.
 
=== Calling Convention ===
 
A [https://en.wikipedia.org/wiki/Calling_convention calling convention] is commonly used by low level computer code such that functions can receive parameters and return results. The same is applicable to [[Dynamic_impulses|Dynamic Impulses]]. Moduprint uses the following convention for both sync and async dynamic impulses:


Registries are both used as a kind of dynamic list (for example for selection modes or packing handlers) and for registering event listeners. In the latter case, the registry entry should be a [[ProtoFlux:Dynamic_Impulse_Receiver|Dynamic Impulse Receiver] with the Impulse tag and Slot name of the registry. High priority listeners are pulsed first (sorted by priority).
* If a function has no parameters, a regular impulse is used.
* If a function receives only one parameter, it is directly given as the impulse data.
* If a function receives more than one parameter, it receives a [[Slot]] as impulse data that has a [[Component:DynamicVariableSpace|Dynamic Variable Space]] defined on itself (not directly binding) with the parameters given as variables, which is referred to as the function's context.
* If a function returns data, it should write it into the localized<ref>Fields are localized by creating a [[Component:ValueCopy|driver]] where both source and target are set to the field and "write back" being enabled. Localized fields are not networked to other players, which makes them more efficient.</ref> dynamic variables <code>Manager/Local.Result</code>. If no variable of the correct type exists, the module needs to have one on itself as <code>Module/Local.Result</code>.
* An async function must write its results only immediately after the impulse ends without any delays afterwards.


=== Notes ===
=== Notes ===
<references/>
<references/>

Latest revision as of 17:54, 5 August 2025

Application Programming Interfaces are commonly used in computer software for communicating between programs. Moduprint is defining an API for interacting with the manager, other modules, and any other part of the print system. This API is based on Dynamic Impulses and Dynamic Variables.

Methods

All methods that can be called on a manager are defined as Dynamic Reference Variables of a dynamic impulse receiver. For the calling convention, see below. All methods are documented under Moduprint/API/Methods.

Structure of a Module

A module is a Slot with the direct-binding Dynamic Variable Space "Module" defined on itself.


Dynamic Variables
Name Type Purpose
Module/ID String Required Unique module identifier
Module/Version uint3 Optional Semantic Version (major.minor.patch)
Module/Name String Optional Human-Readable name of the module
Module/ShortDescription String Optional Human-Readable short description of the module
Module/ManifestOwner String Optional Reserved for future use
Module/Requirements Slot Optional List of requirements of the module, such as dependencies or the manager version
Module/Lifecycle.Register Slot Optional List of registry entries to create
Module/Lifecycle.Install Slot Optional Dynamic Impulse on install
Module/Lifecycle.Uninstall Slot Optional Dynamic Impulse on uninstall

The module ID is of the format Namespace.Module where Namespace is anything uniquely identifying the creator such as the user or group name and Module is the identifier of the module. Only one module with the same ID can be installed on the same manager at any point in time. The ID must only contain letters which are valid for a Dynamic Variable.

The registries are given as Slot children which each have a (not directly binding) Dynamic Variable Space on them as well as a dynamic Slot variable Target pointing to the registry entry.

Each module should have a Snapper with the tags Moduprint.Module and Moduprint.Module/ID and a radius of 0.01.

To hide the module visual when it is installed, add a Parent Value Link of type bool matching the tag "Moduprint.ModuleVisual" and set it to be true by default.

Requirements

Requirements are conditions which must be fulfilled before a module can be installed. They are defined as slots under the slot which the Dynamic Variable Module/Requirements is pointing to. Those slots have a Dynamic Variable Space which contains the following variables. The tag of the slot is the type of the requirement. If the type is not known or supported by the manager, the module is rejected.

Dynamic Variables
Name Type Purpose
MinVersion uint3 Optional Minimum version of module or manager.
MaxVersion uint3 Optional Inclusive maximum version of module or manager. The maximum version number is 4294967295.
Optional bool Optional If the dependency is optional.

Manager

The Manager requirement only allows installation of the module if the manager version is within the given range.

Dependency

The Dependency requirement only allows installing a module if a module identified by the slot's name is already installed. This module will have a Dynamic Reference variable with the name Module/Dependency.ID defined which will hold the slot of the module depended upon.

Slot children with the name of slot reference variables that are defined on the dependency module will be defined on this module with the prefix Module/Dependency.ID.Variable.

For example, adding a slot with the name Method.Raycast under the dependency requirement slot with the name ColinTheCat.PrintRaycasting will lead to the variable Module/Dependency.ColinTheCat.PrintRaycasting.Method.Raycast being defined on this module.

Unique

Only one module can be installed on the print with the same unique requirement at the same time. This is useful to prevent incompatible modules from being installed. For example, the ColinTheCat.Colors module has the unique requirement "Print.Tint" because it sets up a driver to the field Print/Tint, making it incompatible with any module that attempts to drive the same field.

Registries

All registries are documented under Moduprint/API/Registries.

Registries are the core system of Moduprint for communication between modules. A registry has a unique name and contains a list of Slot entries. Every module can create an arbitrary amount of registry entries. Entries are defined as children under the slot which the Dynamic Variable Module/Lifecycle.Register is pointing to. Those slots have a Dynamic Variable Space which contains the following variables.

Dynamic Variables
Name Type Purpose
Entry Slot Required Slot that should be registered.
Registry String Required Name of the registry this entry belongs to.
Priority String Optional Entry priority in the registry, see below.
Priorities [1]
Name Priority
Highest -2.000.000
High -1.000.000
Normal 0
Low 1.000.000
Lowest 2.000.000
Monitor 3.000.000

Instead of a priority name, a number can also be used directly. The monitor priority should only be used for event listeners which only check for the final data of the event without modifying it.

Registries are both used as a kind of dynamic list (for example for selection modes or packing handlers) and for registering event listeners. In the latter case, the registry entry should be a Dynamic Impulse Receiver. High priority listeners are pulsed first (sorted by priority).

Events

Events are a special type of registry where each entry is a Dynamic Impulse Receiver of a slot. The slot has a Dynamic Variable Space holding the event data. All variables are local (not networked). Some of the variables are meant to be modified by listeners, for example to change the result of an operation. Use DispatchEvent and DispatchAsyncEvent to dispatch an event.

All events on a manager are defined as Dynamic Reference Variables of the data slot following the naming scheme Manager/EventData.EventName.

Calling Convention

A calling convention is commonly used by low level computer code such that functions can receive parameters and return results. The same is applicable to Dynamic Impulses. Moduprint uses the following convention for both sync and async dynamic impulses:

  • If a function has no parameters, a regular impulse is used.
  • If a function receives only one parameter, it is directly given as the impulse data.
  • If a function receives more than one parameter, it receives a Slot as impulse data that has a Dynamic Variable Space defined on itself (not directly binding) with the parameters given as variables, which is referred to as the function's context.
  • If a function returns data, it should write it into the localized[2] dynamic variables Manager/Local.Result. If no variable of the correct type exists, the module needs to have one on itself as Module/Local.Result.
  • An async function must write its results only immediately after the impulse ends without any delays afterwards.

Notes

  1. This system is inspired by the Event Priority enum of Bukkit
  2. Fields are localized by creating a driver where both source and target are set to the field and "write back" being enabled. Localized fields are not networked to other players, which makes them more efficient.