Last review by Tuxilio

This commit is contained in:
debiankaios 2022-12-18 11:20:09 +01:00
parent 13eab9451c
commit 3c947c771e
9 changed files with 58 additions and 58 deletions

View File

@ -27,8 +27,8 @@ interessante und abwechslungsreiche Umgebung im Spiel zu schaffen. In diesem Kap
Ein Minetest-Biom ist eine bestimmte Umgebung im Spiel. Wenn Sie Biome registrieren, können Sie können Sie die Arten von Nodes bestimmen, die während der Kartenerstellung darin erscheinen. Einige der gebräuchlichsten Nodetypen, die von Biom zu Biom variieren können, sind:
* Oberer Node: Dies ist der Knoten, der am häufigsten auf der Oberfläche zu finden ist. Ein bekanntes Beispiel wäre "Dirt with Grass", also "Erde mit Gras" aus dem Minetest-Grundspiel (Minetest Game).
* Füllender Node: Dies ist die Schicht unmittelbar unter dem obersten Knoten. In Biomen mit Gras ist dies oft Erde.
* Oberer Node: Dies ist der Node, der am häufigsten auf der Oberfläche zu finden ist. Ein bekanntes Beispiel wäre "Dirt with Grass", also "Erde mit Gras" aus dem Minetest-Grundspiel (Minetest Game).
* Füllender Node: Dies ist die Schicht unmittelbar unter dem obersten Node. In Biomen mit Gras ist dies oft Erde.
* Steinnode: Dies ist der Node, den man am häufigsten unter der Erde sieht.
* Wassernode: Dies ist normalerweise eine Flüssigkeit. Der Node erscheint dort,
wo man Wasserflächen erwarten würde.
@ -120,7 +120,7 @@ minetest.register_biome({
})
```
Dieses Biom hat eine Schicht aus Erde mit Grasknoten an der Oberfläche und drei Schichten von Erde-Knoten darunter. Es wird kein Steinknoten angegeben, so dass der Knoten, der in der Kartenerstellung-Alias-Registrierung (mapgen alias registration) für "mapgen_stone" definiert ist, unter der Erde vorhanden sein wird.
Dieses Biom hat eine Schicht aus Erde mit GrasNode an der Oberfläche und drei Schichten von Erde-Node darunter. Es wird kein SteinNode angegeben, so dass der Node, der in der Kartenerstellung-Alias-Registrierung (mapgen alias registration) für "mapgen_stone" definiert ist, unter der Erde vorhanden sein wird.
Es gibt viele Optionen bei der Registrierung eines Bioms. Diese sind dokumentiert in der [Minetest Lua API Referenz 🇬🇧](https://minetest.gitlab.io/minetest/definition-tables/#biome-definition).
@ -131,11 +131,11 @@ Sie müssen nicht jede Option für jedes Biom, das Sie erstellen, definieren, ab
Dekorationen sind entweder Nodes oder Schematics, die bei der Kartenerstellung (mapgen) auf der Karte platziert werden können.
Einige gängige Beispiele sind Blumen, Sträucher und Bäume. Andere, kreativere Verwendungen sind z. B. hängende Eiszapfen oder Stalagmiten in Höhlen, unterirdische Kristallgebilde oder sogar die Platzierung von kleinen Gebäuden.
Dekorationen können auf bestimmte Biome, auf die Höhe oder auf die Knotenpunkte beschränkt werden. Sie werden oft verwendet, um die Umgebung eines Bioms zu entwickeln,indem sie dafür sorgen, dass es bestimmte Pflanzen, Bäume oder andere Merkmale hat.
Dekorationen können auf bestimmte Biome, auf die Höhe oder auf die Nodepunkte beschränkt werden. Sie werden oft verwendet, um die Umgebung eines Bioms zu entwickeln,indem sie dafür sorgen, dass es bestimmte Pflanzen, Bäume oder andere Merkmale hat.
## Registrierung einer einfachen Dekoration
Einfache Dekorationen werden verwendet, um während der Kartenerstellung einzelne Knotendekorationen auf der Karte zu platzieren.
Einfache Dekorationen werden verwendet, um während der Kartenerstellung einzelne Nodedekorationen auf der Karte zu platzieren.
Sie müssen den Node angeben, der als Dekoration platziert werden soll, Angaben dazu, wo er platziert werden kann und wie häufig er vorkommt.
Zum Beispiel:
@ -199,6 +199,6 @@ Zumindest sollten Sie registrieren:
* mapgen_water_source
* mapgen_river_water_source
Wenn Sie nicht für alle Biome Höhlenflüssigkeitsknoten definieren, sollten Sie diese trotzdem ebenfalls registrieren:
Wenn Sie nicht für alle Biome HöhlenflüssigkeitsNode definieren, sollten Sie diese trotzdem ebenfalls registrieren:
* mapgen_lava_source

View File

@ -45,7 +45,7 @@ Aus Leistungsgründen wird ein LVM fast nie genau den Bereich lesen, den Sie ihm
## Nodes lesen
Um die Typen von Knoten an bestimmten Positionen zu lesen, müssen Sie `get_data()` verwenden. Dies gibt ein flaches Array zurück, in dem jeder Eintrag den Typ eines bestimmten Knotens darstellt.
Um die Typen von Node an bestimmten Positionen zu lesen, müssen Sie `get_data()` verwenden. Dies gibt ein flaches Array zurück, in dem jeder Eintrag den Typ eines bestimmten Nodes darstellt.
```lua
local data = vm:get_data()
@ -53,7 +53,7 @@ local data = vm:get_data()
Sie können param2 und Beleuchtungsdaten mit den Methoden `get_param2_data()` und `get_light_data()` erhalten.
Sie müssen `emin` und `emax` verwenden, um herauszufinden, wo ein Knoten in den flachen Arrays ist, die durch die oben genannten Methoden gegeben sind. Es gibt eine Hilfsklasse namens `VoxelArea`, die die die die Berechnung für Sie übernimmt.
Sie müssen `emin` und `emax` verwenden, um herauszufinden, wo ein Node in den flachen Arrays ist, die durch die oben genannten Methoden gegeben sind. Es gibt eine Hilfsklasse namens `VoxelArea`, die die die die Berechnung für Sie übernimmt.
```lua
local a = VoxelArea:new{
@ -83,9 +83,9 @@ if data[idx] == c_stone then
end
```
Die Inhalts-IDs eines Knotentyps können sich während der Ladezeit ändern, daher wird es nicht empfohlen, diese während dieser Zeit abzurufen.
Die Inhalts-IDs eines Nodetyps können sich während der Ladezeit ändern, daher wird es nicht empfohlen, diese während dieser Zeit abzurufen.
Knoten in einem LVM-Datenarray werden in umgekehrter Koordinatenreihenfolge gespeichert. Deshalb sollten Sie immer in der Reihenfolge `z, y, x` *iterieren* (umdrehen). Zum Beispiel:
Node in einem LVM-Datenarray werden in umgekehrter Koordinatenreihenfolge gespeichert. Deshalb sollten Sie immer in der Reihenfolge `z, y, x` *iterieren* (umdrehen). Zum Beispiel:
```lua
for z = min.z, max.z do
@ -122,7 +122,7 @@ for z = min.z, max.z do
end
```
Wenn Sie die Einstellung der Knoten im LVM abgeschlossen haben, müssen Sie das Daten Array in die Engine hochladen:
Wenn Sie die Einstellung der Node im LVM abgeschlossen haben, müssen Sie das Daten Array in die Engine hochladen:
```lua
vm:set_data(data)
@ -169,6 +169,6 @@ end
## Sie sind dran
* Erstellen Sie `replace_in_area(from, to, pos1, pos2)`, das alle Instanzen von `von` durch `bis` in dem angegebenen Bereich ersetzt, wobei `von` und `bis` Knotennamen sind.
* Programmieren Sie eine Funktion, die alle Brustknoten um 90° dreht.
* Erstellen Sie eine Funktion, die einen LVM benutzt, um zu bewirken, dass sich moosiges Kopfsteinpflaster auf nahegelegene Stein- und Pflastersteinknoten ausbreitet. Verursacht Ihre Implementierung, dass sich das Moospflaster auf mehr als einen Node ausbreitet? Wenn ja, wie können Sie dies verhindern?
* Erstellen Sie `replace_in_area(from, to, pos1, pos2)`, das alle Instanzen von `von` durch `bis` in dem angegebenen Bereich ersetzt, wobei `von` und `bis` Nodenamen sind.
* Programmieren Sie eine Funktion, die alle BrustNode um 90° dreht.
* Erstellen Sie eine Funktion, die einen LVM benutzt, um zu bewirken, dass sich moosiges Kopfsteinpflaster auf nahegelegene Stein- und PflastersteinNode ausbreitet. Verursacht Ihre Implementierung, dass sich das Moospflaster auf mehr als einen Node ausbreitet? Wenn ja, wie können Sie dies verhindern?

View File

@ -78,4 +78,4 @@ Gruppen und Aliase sind beides nützliche Werkzeuge, um die Kompatibilität zwis
## Sie sind dran
* Erstellen Sie ein einfaches Spiel, bei dem der Spieler durch das Abbauen spezieller Blöcke Punkte erhält.
* Erstellen Sie ein einfaches Spiel, bei dem der Spieler durch das Abbauen spezieller Nodes Punkte erhält.

View File

@ -42,8 +42,8 @@ Maß an Präzision und Kontrolle.
### Kacheln
Texturen, die für Blöcke verwendet werden, sollten in der Regel kachelfähig sein. Das bedeutet
wenn Sie mehrere Blöcke mit der gleichen Textur zusammen platzieren, sehen die Kanten
Texturen, die für Nodes verwendet werden, sollten in der Regel kachelfähig sein. Das bedeutet
wenn Sie mehrere Nodes mit der gleichen Textur zusammen platzieren, sehen die Kanten
korrekt aus.
<!-- IMAGE NEEDED - cobblestone that tiles correctly -->
@ -70,7 +70,7 @@ Vorgefertigte Paletten finden Sie unter
### MS Paint
MS Paint ist ein einfacher Editor, der für einfaches Texturendesign nützlich sein kann;
MS Paint ist ein einfacher Editor, der für einfaches Texturendesign nützlich sein kann;
allerdings unterstützt er keine Transparenz.
Dies spielt normalerweise keine Rolle, wenn Sie Texturen für die Seiten von Nodes erstellen,
aber wenn Sie Transparenz in Ihren Texturen benötigen, sollten Sie einen

View File

@ -29,7 +29,7 @@ sind Grundlagen von vielen Mods
Nodes, Craftitems und Tools sind alles Items. Ein Item ist etwas, das im Inventar gefunden werden kann - sogar wenn es im normalen Gameplay nicht möglich ist.
Ein Node ist ein Item, das platziert oder in der Welt gefunden werden kann. Jede Position muss belegt werden mit einem und nur einem Node - scheinbar leere Position sind normalerweise Luftblöcke.
Ein Node ist ein Item, das platziert oder in der Welt gefunden werden kann. Jede Position muss belegt werden mit einem und nur einem Node - scheinbar leere Position sind normalerweise Luftnodes.
Ein Craftitem kann nicht platziert werden. Man kann es nur im Inventar finden oder als gedropptes Item in der Welt.

View File

@ -23,7 +23,7 @@ In diesem Kapitel erfahren Sie, wie Sie grundlegende Aktionen auf der Karte durc
## Karten-Struktur
Die Minetest-Karte ist in Map-Blöcke(nicht zu verwechseln mit Blöcken in deutschen) aufgeteilt, wobei jeder Map-Block ein Würfel der
Die Minetest-Karte ist in Map-Blöcke(nicht zu verwechseln mit Nodes im Deutschen) aufgeteilt, wobei jeder Map-Block ein Würfel der
Kantenlänge 16 ist. Während die Spieler auf der Karte unterwegs sind, werden Map-Blöcke erstellt, geladen,
aktiv und entladen. Bereiche der Karte, die noch nicht geladen sind, sind voll von
*ignore*-Nodes, einem unpassierbaren, nicht auswählbaren Platzhalternode. Leerer Raum ist
@ -31,7 +31,7 @@ voll von *Luft*-Blöcken, einem unsichtbaren Node, durch den man hindurchgehen k
Ein aktiver Map-Block ist ein Node, der geladen ist und für den Aktualisierungen durchgeführt werden.
Geladene Map-Blöcke werden oft als *aktive Blöcke* bezeichnet. Aktive Blöcke können
Geladene Map-Blöcke werden oft als *aktive Nodes* bezeichnet. Aktive Nodes können
von Mods oder Spielern gelesen oder beschrieben werden und haben aktive Entities. Die Engine
führt auch Operationen auf der Karte durch, wie z. B. die Ausführung der Flüssigkeitsphysik.
@ -42,54 +42,54 @@ außerhalb des Generierungslimits aus der Weltdatenbank geladen werden.
## Lesen
### Blöcke lesen
### Nodes lesen
Sobald Sie eine Position haben, können Sie diese auf der Karte ablesen:
```lua
local node = minetest.get_node({ x = 1, y = 3, z = 4 }) --Warnung: Im Englischen ist mit block der Map-Block gemeint. Daher emphielt sich für die Variabelnamen node(Knoten) anstatt block zu nehmen
local node = minetest.get_node({ x = 1, y = 3, z = 4 }) --Warnung: Im Englischen ist mit Node der Map-Block gemeint. Daher emphielt sich für die Variabelnamen node(Node) zu verwenden
print(dump(node)) --> { name=.., param1=.., param2=.. }
```
Handelt es sich bei der Position um eine Dezimalzahl, so wird sie auf den enthaltenen Knoten gerundet.
Die Funktion gibt immer eine Tabelle mit den Blockinformationen zurück:
Handelt es sich bei der Position um eine Dezimalzahl, so wird sie auf den enthaltenen Node gerundet.
Die Funktion gibt immer eine Tabelle mit den Nodeinformationen zurück:
* `name` - Der Knotenname, der beim Entladen des Bereichs *ignoriert* wird.
* `param1` - Siehe Block-Definition. Dieser ist in der Regel light.
* `param2` - Siehe Block-Definition.
* `name` - Der Nodename, der beim Entladen des Bereichs *ignoriert* wird.
* `param1` - Siehe Node-Definition. Dieser ist in der Regel light.
* `param2` - Siehe Node-Definition.
Es ist erwähnenswert, dass die Funktion den enthaltenen Block nicht lädt, wenn der Block
Es ist erwähnenswert, dass die Funktion den enthaltenen Node nicht lädt, wenn der Node
inaktiv ist, sondern stattdessen eine Tabelle zurückgibt, in der `name` `ignore` ist.
Sie können stattdessen `minetest.get_node_or_nil` verwenden, was `nil` zurückgibt
und nicht eine Tabelle mit dem Namen `ignore`. Allerdings wird der Block dann immer noch nicht geladen.
Dies kann immer noch `ignore` zurückgeben, wenn ein Block tatsächlich ignore enthält.
und nicht eine Tabelle mit dem Namen `ignore`. Allerdings wird der Node dann immer noch nicht geladen.
Dies kann immer noch `ignore` zurückgeben, wenn ein Node tatsächlich ignore enthält.
Dies wird in der Nähe des Randes der Karte passieren, wie es durch die Kartengenerierung definiert ist
Grenze (`mapgen_limit`) definiert ist.
### Blöcke finden
### Nodes finden
Minetest bietet eine Reihe von Hilfsfunktionen, um gängige Map-Aktionen zu beschleunigen.
Die am häufigsten verwendeten Funktionen dienen dem Auffinden von Blöcken.
Die am häufigsten verwendeten Funktionen dienen dem Auffinden von Nodesn.
Angenommen, wir wollen eine bestimmte Pflanzenart herstellen, die besser in der Nähe von Mese wächst;
müssten Sie nach allen Mese-Blöcke in der Nähe suchen,
und die Wachstumsrate entsprechend anpassen.
`minetest.find_node_near` liefert den ersten gefundenen Block in einem bestimmten Radius
der mit den angegebenen Knotennamen oder Gruppen übereinstimmt. Im folgenden Beispiel,
suchen wir nach einem Mese-Block innerhalb von 5 Knoten von der Position:
`minetest.find_node_near` liefert den ersten gefundenen Node in einem bestimmten Radius
der mit den angegebenen Nodenamen oder Gruppen übereinstimmt. Im folgenden Beispiel,
suchen wir nach einem Mese-Node innerhalb von 5 Node von der Position:
```lua
local wachstums_geschwindigkeit = 1
local node_pos = minetest.find_node_near(pos, 5, { "default:mese" })
if node_pos then
minetest.chat_send_all("Bei " .. dump(node_pos) .. " Block gefunden")
minetest.chat_send_all("Bei " .. dump(node_pos) .. " Node gefunden")
wachstums_geschwindigkeit = 2
end
```
Nehmen wir zum Beispiel an, dass die Wachstumsrate steigt, je mehr Mese in der Nähe ist.
Dann sollten Sie eine Funktion verwenden, die mehrere Blöcke in dem Gebiet finden kann:
Dann sollten Sie eine Funktion verwenden, die mehrere Nodes in dem Gebiet finden kann:
```lua
local pos1 = vector.subtract(pos, { x = 5, y = 5, z = 5 })
@ -99,7 +99,7 @@ local pos_list =
local wachstums_geschwindigkeit = 1 + #pos_list
```
Der obige Code ermittelt die Anzahl der Knoten in einem *kubischen Volumen*. Dies ist anders
Der obige Code ermittelt die Anzahl der Node in einem *kubischen Volumen*. Dies ist anders
zu `find_node_near`, das den Abstand zur Position (d.h. einer *Kugel*) verwendet.
Um dies zu beheben, müssen wir den Bereich manuell selbst überprüfen:
@ -117,7 +117,7 @@ for i=1, #pos_list do
end
```
Jetzt erhöht der Code korrekt die `wachstums_geschwindigkeit` basierend auf der Anzahl der Knoten in Reichweite.
Jetzt erhöht der Code korrekt die `wachstums_geschwindigkeit` basierend auf der Anzahl der Node in Reichweite.
Beachten Sie, dass wir den quadrierten Abstand von der Position verglichen haben, anstatt
ihn zu quadrierenum die tatsächliche Entfernung zu erhalten. Dies liegt daran, dass Quadratwurzeln
@ -129,11 +129,11 @@ und unter anderen Umständen nützlich sind.
## Schreiben
### Blöcke schreiben
### Nodes schreiben
Sie können `set_node` verwenden, um in die Karte zu schreiben. Jeder Aufruf von set_node wird dazu führen, dass
die Beleuchtung neu berechnet und Block-Callbacks ausgeführt werden, was bedeutet, dass set_node
bei einer großen Anzahl von Blöcken ziemlich langsam ist.
die Beleuchtung neu berechnet und Node-Callbacks ausgeführt werden, was bedeutet, dass set_node
bei einer großen Anzahl von Nodesn ziemlich langsam ist.
```lua
minetest.set_node({ x = 1, y = 3, z = 4 }, { name = "default:mese" })
@ -144,21 +144,21 @@ print(node.name) --> default:mese
set_node entfernt alle zugehörigen Metadaten oder Bestände von dieser Position.
Dies ist nicht unter allen Umständen wünschenswert, insbesondere wenn Sie mehrere
Block-Definitionen verwenden, um einen konzeptionellen Blöcke zu repräsentieren. Ein Beispiel hierfür ist der
Ofenblock - während man ihn konzeptionell als einen Block betrachtet, sind es eigentlich
Node-Definitionen verwenden, um einen konzeptionellen Nodes zu repräsentieren. Ein Beispiel hierfür ist der
Ofennode - während man ihn konzeptionell als einen Node betrachtet, sind es eigentlich
zwei.
Sie können einen Knoten setzen, ohne die Metadaten oder das Inventar zu löschen, wie folgt:
Sie können einen Node setzen, ohne die Metadaten oder das Inventar zu löschen, wie folgt:
```lua
minetest.swap_node({ x = 1, y = 3, z = 4 }, { name = "default:mese" })
```
### Blöcke löschen
### Nodes löschen
Ein Block muss immer vorhanden sein. Um einen Block zu entfernen, setzen Sie die Position auf "Luft".
Ein Node muss immer vorhanden sein. Um einen Node zu entfernen, setzen Sie die Position auf "Luft".
Die folgenden beiden Zeilen entfernen beide einen Block und sind identisch:
Die folgenden beiden Zeilen entfernen beide einen Node und sind identisch:
```lua
minetest.remove_node(pos)
@ -183,7 +183,7 @@ local kontext = {} -- Daten zwischen Callback-Aufrufen aufrechterhalten
minetest.emerge_area(pos1, pos2, emerge_callback, kontext)
```
Minetest ruft `emerge_callback` immer dann auf, wenn er einen Mapblock, mit einigen
Minetest ruft `emerge_callback` immer dann auf, wenn er einen Map-Block, mit einigen
Fortschrittsinformationen, lädt.
```lua
@ -195,7 +195,7 @@ local function emerge_callback(pos, aktion,
kontext.geladene_bloecke = 0
end
-- Erhöhung der Anzahl der geladenen Blöcke
-- Erhöhung der Anzahl der geladenen Nodes
kontext.bloecke_insgesamt = kontext.geladene_bloecke + 1
-- Fortschrittsmeldung senden
@ -203,7 +203,7 @@ local function emerge_callback(pos, aktion,
minetest.chat_send_all("Blöcke laden abgeschlossen!")
end
local perc = 100 * kontext.geladene_bloecke / kontext.bloecke_insgesamt
local msg = string.format("Geladene Blöcke %d/%d (%.2f%%)",
local msg = string.format("Geladene Nodes %d/%d (%.2f%%)",
kontext.geladene_bloecke, kontext.bloecke_insgesamt, perc)
minetest.chat_send_all(msg)
end
@ -214,7 +214,7 @@ Dies ist nicht die einzige Möglichkeit, Mapblöcke zu laden; die Verwendung ein
[Lua Voxel Manipulator (LVM)](../advmap/lvm.html) bewirkt ebenfalls, dass die
umschlossenen Mapblöcke synchron geladen werden.
## Blöcke löschen
## Nodes löschen
Sie können delete_blocks verwenden, um einen Bereich von Map-Blöcken zu löschen:

View File

@ -11,7 +11,7 @@ redirect_from:
## Einleitung <!-- omit in toc -->
Die periodische Ausführung einer Funktion auf bestimmten Knoten ist eine häufige Aufgabe.
Die periodische Ausführung einer Funktion auf bestimmten Node ist eine häufige Aufgabe.
Minetest bietet dafür zwei Methoden: Aktive Map-Block Modifikatoren (ABMs) und Node-Timer(node timers).
ABMs scannen alle geladenen Map-Blöcke auf der Suche nach Blöcken, die einem Kriterium entsprechen.
@ -33,7 +33,7 @@ der ausstehenden Timer benötigen.
## Nodetimer
Nodetimer sind direkt an einen einzelnen Knoten gebunden.
Nodetimer sind direkt an einen einzelnen Node gebunden.
Sie können Nodetimer verwalten, indem Sie ein NodeTimerRef-Objekt erhalten.
```lua
@ -105,5 +105,5 @@ Wenn Sie die Chance nicht angeben, wird der ABM immer ausgeführt, wenn die ande
* Midas Berührung: Verwandelt Wasser alle 5 Sekunden mit einer Wahrscheinlichkeit von 1 zu 100 in Goldblöcke.
* Fäulnis: Verwandelt Holz in Dreck um, wenn Wasser der Nachbar ist.
* Brennen: Bringt jeden Luftknoten in Brand. (Tipp: "air" und "fire:basic_flame").
* Brennen: Bringt jeden LuftNode in Brand. (Tipp: "air" und "fire:basic_flame").
Warnung: Rechnen Sie damit, dass das Spiel abstürzt.

View File

@ -358,7 +358,7 @@ Formulareingaben für meta formspecs zu erhalten, müssen Sie einen
Diese Art von Callback wird ausgelöst, wenn Sie die Eingabetaste
in einem Feld drücken, was mit `minetest.show_formspec` unmöglich ist;
diese Art von Formular kann jedoch nur durch Rechtsklick auf einen Knoten angezeigt werden. Sie kann nicht programmatisch ausgelöst werden.
diese Art von Formular kann jedoch nur durch Rechtsklick auf einen Node angezeigt werden. Sie kann nicht programmatisch ausgelöst werden.
### Spieler Inventar Formspecs

View File

@ -207,7 +207,7 @@ Teile:
`minetest.` geben.
* **View** - Dies war auch die obige Ansicht. Es ist eine gute Idee, dies in separate Dateien für jede Art von Ereignis zu strukturieren.
rubenwardy's [crafting mod](https://github.com/rubenwardy/crafting 🇬🇧) folgt ungefähr diesem Design. Die Datei `api.lua` besteht fast ausschließlich aus reinen Lua-Funktionen, die die Daten Speicherung und Controller-ähnliche Berechnungen handhaben. `gui.lua` ist die Ansicht für Formspecs und Formspec-Übermittlung, und `async_crafter.lua` ist der View und Controller für einen Knoten formspec und Nodezeitgeber.
rubenwardy's [crafting mod](https://github.com/rubenwardy/crafting 🇬🇧) folgt ungefähr diesem Design. Die Datei `api.lua` besteht fast ausschließlich aus reinen Lua-Funktionen, die die Daten Speicherung und Controller-ähnliche Berechnungen handhaben. `gui.lua` ist die Ansicht für Formspecs und Formspec-Übermittlung, und `async_crafter.lua` ist der View und Controller für einen Node formspec und Nodezeitgeber.
Wenn man die Mods auf diese Weise trennt, kann man den API-Teil sehr einfach testen,
da sie keine Minetest-APIs verwendet - wie im [nächstes Kapitel](unit_testing.html) und in der Crafting-Mod zu sehen.