Zum Hauptinhalt springen

Skript-API

Skripte sind Rhai-Dateien (.rhai), die das aktuelle Projekt bearbeiten — Terrain erzeugen, Layer malen, Objekte platzieren — mit einem optionalen Parameterformular im Panel Skripte.

Aufbau eines Skripts​

Ein Skript kann vier Funktionen definieren; nur apply ist Pflicht.

// Titel und Beschreibung im Skripte-Panel (optional).
fn meta() {
#{
name: "Mein Skript",
description: "Was dieses Skript macht.",
undo: true, // Undo-Verlauf aufzeichnen (Standard true; false ist schneller)
iterative: false, // bei true zeigt das Panel eine Iterationsanzahl (siehe unten)
}
}

// Eingabeformular (optional). Siehe „Parameter“.
fn params() {
[
#{ id: "radius", label: "Radius", type: "int", min: 1, max: 64, value: 8 },
]
}

// Ausgangsports (optional). Siehe „Ausgaben“.
fn outputs() {
[
#{ id: "cells", label: "Zellen", type: "map2d" },
]
}

// Pflicht. `map` ist die Bearbeitungs-API, `p` enthält die Formularwerte nach id
// (plus `p.iteration`, den 0-basierten Durchlaufindex im iterativen Modus).
fn apply(map, p) {
let r = p.radius;
}

Iterative Skripte​

Mit iterative: true in meta() zeigt das Skripte-Panel eine Iterationsanzahl (1..100000) und apply läuft entsprechend oft. p.iteration ist der aktuelle 0-basierte Durchlaufindex. Zwischen den Durchläufen wird jede map2d-Ausgabe in die map2d-Eingabe mit derselben id zurückgeführt — so kann ein Skript Zustand von einer Iteration zur nächsten mitnehmen.

Parameter​

Jeder Eintrag aus params() ist eine Object-Map. Der Startwert steht in value (default ist in Rhai ein reserviertes Wort).

typeZusätzliche Schlüsselp[id] in apply
intmin, max, valueGanzzahl
floatmin, max, valueGleitkommazahl
boolvalueBoolean
textvalueString
choiceoptions: [...], valueder String der gewählten Option
layerlayer_typeeine Map #{ kind, index, name }
colorvalue ("#rrggbb" oder [r, g, b])eine Map #{ r, g, b } (0–255)
map2d—eine schreibgeschützte 2D-Luminanzkarte (siehe unten)

Lässt man bei int und float min/max weg, erscheint ein freies Zahlenfeld statt eines Schiebereglers.

layer_type ist "material", "cover", "biome", "object", "resource", "feature", "combined", "annotation" oder "any". Übergib p[id].index an die Bearbeitungsfunktionen unten (alle Arten außer Materialien und Biomen sind 1-basiert).

Eine map2d-Eingabe wird über den Skript-Knoten des Knoten-Editors gespeist (verbinde ein beliebiges Skalarfeld mit seinem Port); beim Start aus dem Skripte-Panel enthält sie stattdessen die Werkzeugbedingungen (1, wo die Zelle sie erfüllt, sonst 0).

Ein map2d-Wert bietet:

FunktionBeschreibung
m.width(), m.height()Abmessungen (width() == 0 heißt: keine Karte übergeben)
m.get(x, z)Wert der Zelle (0.0 außerhalb der Grenzen)
m.set(x, z, v)Wert setzen (Float oder Int)
m.neighbor_count(threshold)neue map2d, in der jede Zelle die Anzahl ihrer 8 Nachbarn mit Wert >= threshold enthält
m.neighbor_count_equal(value)neue map2d, die die 8 Nachbarn zählt, deren Wert gleich value ist
m.neighbor_count_equal(value, wrap)ebenso, mit wrap = true für toroidale Ränder (Randzellen laufen herum)
new_map2d(w, h)freie Funktion, die eine mit Nullen gefüllte Karte erzeugt

Ausgaben​

outputs() deklariert Ausgangsports (gleiche Object-Map-Form wie params(), mit type "map2d", "color" oder "material"). Sie werden in apply geschrieben:

FunktionBeschreibung
map.set_output(id, map2d)eine map2d-Ausgabe schreiben
map.set_output_color(id, r, g, b)eine Farbausgabe schreiben (0–255)
map.set_output_material(id, index)eine Ausgabe mit Materialindex schreiben

Die Ausgaben speisen die Ausgangsports des Skript-Knotens im Knoten-Editor und steuern die Rückführung zwischen Iterationen (siehe „Iterative Skripte“).

Skript-Knoten​

Im Knoten-Editor macht der Knoten Skript die Eingaben eines Skripts direkt im Graphen verfügbar: Eingaben vom Typ int, float, color, map2d und Material-layer werden zu benannten Eingangsports (mit einem eingebetteten Widget, solange sie nicht verbunden sind); die übrigen Arten werden im Knoten selbst bearbeitet. Der Knoten wird nie von der Live-Vorschau oder von Auf die Karte anwenden ausgewertet — das Skript läuft nur über den eigenen Button des Knotens.

Die map-API​

Koordinaten sind x (West→Ost) und z (Nord→Süd), Ursprung bei 0,0. Koordinaten außerhalb der Grenzen werden ignoriert.

Abmessungen & Grenzen​

FunktionRückgabe
map.width()Kartenbreite in Zellen
map.height()Kartenhöhe in Zellen
map.water_level()globaler Wasserspiegel
map.min_height()minimal erlaubte Höhe
map.max_height()maximal erlaubte Höhe

Höhen​

Höhen sind f64 (Genauigkeit unterhalb eines Blocks), begrenzt auf [min_height, max_height].

FunktionBeschreibung
map.get_height(x, z)Höhe der Zelle
map.set_height(x, z, h)Höhe setzen
map.add_height(x, z, dh)dh zur Höhe addieren
map.slope(x, z)lokale Neigung in Grad

Oberflächenmaterial​

0-basierter Index in der Materialpalette.

FunktionBeschreibung
map.get_surface(x, z)Materialindex
map.set_surface(x, z, mat)Materialindex setzen
map.set_surface_mask(mask, mat_on)die ganze Oberfläche aus einer map2d malen: Zelle >= 0.5 → mat_on, sonst 0
map.set_surface_mask(mask, mat_on, mat_off)ebenso, mit explizitem Material mat_off für Zellen < 0.5
map.set_surface_mask(mask, mat_on, x0, z0, x1, z1)nur das Rechteck [x0..=x1, z0..=z1] malen

Ein einziger Aufruf von set_surface_mask sperrt die ganze Karte nur einmal, was viel schneller ist als eine Schleife mit set_surface pro Zelle.

Auswahl​

Macht die aktive Werkzeugauswahl verfügbar, damit ein Skript seine Arbeit auf den ausgewählten Bereich beschränken kann, ohne die Kartengröße zu ändern.

FunktionRückgabe
map.has_selection()true, wenn eine nicht leere „Nur“-Auswahl aktiv ist
map.selection_bounds()Begrenzungsrechteck [x0, z0, x1, z1] (inklusive); die ganze Karte, wenn keine nutzbare Auswahl besteht

Kombiniere selection_bounds() mit der Rechteckform von set_surface_mask, um nur den aktiven Bereich zu bearbeiten.

Biom​

0-basierter Index in der Biomliste.

FunktionBeschreibung
map.get_biome(x, z)Biomindex
map.set_biome(x, z, id)Biomindex setzen

Bodendecker​

1-basiert, stapelbar, Alpha 0..=255 (Standard 255).

FunktionBeschreibung
map.add_cover(x, z, id)einen Bodendecker hinzufügen (Alpha 255)
map.add_cover(x, z, id, alpha)einen Bodendecker mit Alpha hinzufügen
map.remove_cover(x, z, id)einen Bodendecker entfernen

Objekt-Layer​

1-basiert, stapelbar; gleiche Signaturen wie bei Bodendeckern.

FunktionBeschreibung
map.add_object(x, z, id)ein Objekt hinzufügen (Alpha 255)
map.add_object(x, z, id, alpha)ein Objekt mit Alpha hinzufügen
map.remove_object(x, z, id)ein Objekt entfernen

Ressourcen-Layer​

1-basiert, stapelbar; gleiche Signaturen wie bei Bodendeckern.

FunktionBeschreibung
map.add_resource(x, z, id)eine Ressource hinzufügen (Alpha 255)
map.add_resource(x, z, id, alpha)eine Ressource mit Alpha hinzufügen
map.remove_resource(x, z, id)eine Ressource entfernen

Feature-Layer​

1-basiert, stapelbar; gleiche Signaturen wie bei Bodendeckern.

FunktionBeschreibung
map.add_feature(x, z, id)ein Feature hinzufügen (Alpha 255)
map.add_feature(x, z, id, alpha)ein Feature mit Alpha hinzufügen
map.remove_feature(x, z, id)ein Feature entfernen

Kombinierte Layer​

1-basiert, stapelbar; gleiche Signaturen wie bei Bodendeckern.

FunktionBeschreibung
map.add_combined(x, z, id)einen kombinierten Layer hinzufügen (Alpha 255)
map.add_combined(x, z, id, alpha)einen kombinierten Layer mit Alpha hinzufügen
map.remove_combined(x, z, id)einen kombinierten Layer entfernen

Anmerkungen​

1-basiert, eine Farbe pro Zelle (id = Index in den 16 festen Anmerkungsfarben).

FunktionBeschreibung
map.add_annotation(x, z, id)die Anmerkungsfarbe malen (ersetzt eine vorhandene)
map.remove_annotation(x, z)die Anmerkung der Zelle löschen
map.set_annotation_mask(mask, on)aus einer map2d malen: Zelle >= 0.5 → on, sonst löschen
map.set_annotation_mask(mask, on, off)ebenso, mit expliziter Farbe off für Zellen < 0.5 (0 löscht)
map.set_annotation_mask(mask, on, off, x0, z0, x1, z1)ebenso, beschränkt auf das Rechteck [x0..=x1, z0..=z1]
map.set_annotation_ids(states, x0, z0)Anmerkungs-IDs pro Zelle stempeln: jede Zelle von states malt die ID round(value) (0 löscht) bei (x0+lx, z0+lz)

Wasser pro Zelle​

FunktionBeschreibung
map.get_water(x, z)lokaler Wasserspiegel (sonst der globale Spiegel)
map.set_water(x, z, level)lokalen Wasserspiegel setzen
map.clear_water(x, z)lokales Wasser entfernen

Suche nach Namen​

Liefern den Index eines Paletteneintrags oder -1, wenn er nicht gefunden wird. Bodendecker- und Objektindizes sind 1-basiert, passend zu add_*/remove_*.

FunktionRückgabe
map.material_index(name)0-basierter Materialindex
map.cover_index(name)1-basierter Bodendecker-Index
map.biome_index(name)0-basierter Biomindex
map.object_index(name)1-basierter Objektindex
map.resource_index(name)1-basierter Ressourcenindex
map.feature_index(name)1-basierter Feature-Index
map.combined_index(name)1-basierter Index des kombinierten Layers
map.annotation_index(name)1-basierter Index der Anmerkungsfarbe

Palettengrößen​

map.material_count(), map.cover_count(), map.biome_count(), map.object_count(), map.resource_count(), map.feature_count(), map.combined_count(), map.annotation_count().

Nächstes Material​

map.nearest_material(r, g, b) liefert den Palettenindex des Materials, das der angegebenen sRGB-Farbe am nächsten ist (CIELAB-Abstand), oder -1, wenn die Palette leer ist. Wie beim Knoten „Nächster Block“ ist die Farbe eines Materials der gewichtete Mittelwert der Texturfarben seiner Blöcke (ersatzweise die Vorschaufarbe, wenn keine Textur auflösbar ist).

map.nearest_block_material(r, g, b) durchsucht stattdessen alle Vanilla-Vollblöcke (wie der Knoten Nächster Block), verwendet den passenden Paletteneintrag wieder oder legt ihn an und liefert seinen Index (-1, wenn die Blockfarbtabelle nicht verfügbar oder die Palette voll ist).

Fortschritt & Abbruch​

FunktionBeschreibung
map.report_progress(current, total, message)die Fortschrittsanzeige aktualisieren
map.is_cancelled()true, wenn der Benutzer abgebrochen hat

print(...) und debug(...) schreiben ins Anwendungsprotokoll.

Beispiel​

Einen Terrainkegel anheben und seine Oberfläche bemalen, mit einer Radius-Eingabe:

fn meta() {
#{ name: "Kegel anheben", description: "Hebt einen Kegel an und malt Stein." }
}

fn params() {
[
#{ id: "radius", label: "Radius", type: "int", min: 1, max: 128, value: 32 },
#{ id: "peak", label: "Gipfelhöhe", type: "float", min: 0.0, max: 256.0, value: 64.0 },
]
}

fn apply(map, p) {
let r = p.radius;
let cx = map.width() / 2;
let cz = map.height() / 2;
let stone = map.material_index("minecraft:stone");

for dz in -r..=r {
if map.is_cancelled() { return; }
map.report_progress(dz + r, 2 * r, "Terrain wird angehoben...");
for dx in -r..=r {
let dist = ((dx * dx + dz * dz) as float).sqrt();
if dist <= r {
map.add_height(cx + dx, cz + dz, p.peak * (1.0 - dist / r));
if stone >= 0 { map.set_surface(cx + dx, cz + dz, stone); }
}
}
}
}