Moduprint/API: Difference between revisions

From Resonite Wiki
→‎Registries: New registry API documentation
Line 78: Line 78:
* If a function receives only one parameter, it is directly given as the impulse data.
* 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 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 (self-driven with write-back) 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>.
* 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/>

Revision as of 15:15, 4 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.

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/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.

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 slots 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 as the tag. 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 where the tag is the registry name. High priority listeners are pulsed first (sorted by priority).

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.