---
title: Grundlegende Kartenoperationen
layout: default
root: ../..
idx: 3.1
description: Grundlegende Operationen wie set_node und get_node
redirect_from: /de/chapters/environment.html
---

## Einleitung <!-- omit in toc -->

In diesem Kapitel erfahren Sie, wie Sie grundlegende Aktionen auf der Karte durchführen können.

- [Karten-Struktur](#karten-struktur)
- [Lesen](#lesen)
    - [Blöcke lesen](#blöcke-lesen)
    - [Blöcke finden](#blöcke-finden)
- [Schreiben](#schreiben)
    - [Blöcke schreiben](#blöcke-schreiben)
    - [Blöcke löschen](#blöcke-löschen)
- [Mapblöcke laden](#mapblöcke-laden)
- [Blöcke löschen](#blöcke-löschen)

## 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
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
voll von *Luft*-Blöcken, einem unsichtbaren Node, durch den man hindurchgehen kann.

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

Map-Blöcke können entweder aus der Weltdatenbank geladen oder generiert werden. Map-Blöcke
werden bis zum Limit der Kartengenerierung (`mapgen_limit`) generiert, das
standardmäßig auf den Maximalwert von 31000 gesetzt ist. Vorhandene Map-Blöcke können jedoch
außerhalb des Generierungslimits aus der Weltdatenbank geladen werden.

## Lesen

### Blöcke 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
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:

* `name` - Der Knotenname, der beim Entladen des Bereichs *ignoriert* wird.
* `param1` - Siehe Block-Definition. Dieser ist in der Regel light.
* `param2` - Siehe Block-Definition.

Es ist erwähnenswert, dass die Funktion den enthaltenen Block nicht lädt, wenn der Block
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.
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

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.

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:
```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")
    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:

```lua
local pos1       = vector.subtract(pos, { x = 5, y = 5, z = 5 })
local pos2       = vector.add(pos, { x = 5, y = 5, z = 5 })
local pos_list   =
        minetest.find_nodes_in_area(pos1, pos2, { "default:mese" })
local wachstums_geschwindigkeit = 1 + #pos_list
```

Der obige Code ermittelt die Anzahl der Knoten 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:

```lua
local pos1       = vector.subtract(pos, { x = 5, y = 5, z = 5 })
local pos2       = vector.add(pos, { x = 5, y = 5, z = 5 })
local pos_list   =
        minetest.find_nodes_in_area(pos1, pos2, { "default:mese" })
local grow_speed = 1
for i=1, #pos_list do
    local delta = vector.subtract(pos_list[i], pos)
    if delta.x*delta.x + delta.y*delta.y + delta.z*delta.z <= 5*5 then
        wachstums_geschwindigkeit = wachstums_geschwindigkeit + 1
    end
end
```

Jetzt erhöht der Code korrekt die `wachstums_geschwindigkeit` basierend auf der Anzahl der Knoten 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
für den Computer sehr rechenintensiv sind und daher möglichst vermieden werden sollten.

Es gibt weitere Variationen der beiden oben genannten Funktionen, wie z.B.
`find_nodes_with_meta` und `find_nodes_in_area_under_air`, die ähnlich funktionieren
und unter anderen Umständen nützlich sind.

## Schreiben

### Blöcke 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.

```lua
minetest.set_node({ x = 1, y = 3, z = 4 }, { name = "default:mese" })

local node = minetest.get_node({ x = 1, y = 3, z = 4 })
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
zwei.

Sie können einen Knoten 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

Ein Block muss immer vorhanden sein. Um einen Block zu entfernen, setzen Sie die Position auf "Luft".

Die folgenden beiden Zeilen entfernen beide einen Block und sind identisch:

```lua
minetest.remove_node(pos)
minetest.set_node(pos, { name = "air" })
```

Tatsächlich ist remove_node nur eine Hilfsfunktion, die set_node mit `"air"` aufruft.

## Mapblöcke laden

Sie können `minetest.emerge_area` verwenden, um Map-Blöcke zu laden. Emerge area ist asynchron,
das heißt, die Mapblöcke werden nicht sofort geladen. Stattdessen werden sie
in der Zukunft geladen und der Callback wird jedes Mal aufgerufen.

```lua
-- Lädt einen 20x20x20-Bereich
local halbegroesse = { x = 10, y = 10, z = 10 } --ss = ß
local pos1 = vector.subtract(pos, halbegroesse)
local pos2 = vector.add     (pos, halbegroesse)

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
Fortschrittsinformationen, lädt.

```lua
local function emerge_callback(pos, aktion,
        verbleibende_calls, kontext)
    -- Beim ersten Aufruf, Anzahl der Mapblöcke erfassen
    if not kontext.bloecke_insgesamt then
        kontext.bloecke_insgesamt  = verbleibende_calls + 1
        kontext.geladene_bloecke = 0
    end

    -- Erhöhung der Anzahl der geladenen Blöcke
    kontext.bloecke_insgesamt = kontext.geladene_bloecke + 1

    -- Fortschrittsmeldung senden
    if kontext.bloecke_insgesamt == kontext.geladene_bloecke then
        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%%)",
                kontext.geladene_bloecke, kontext.bloecke_insgesamt, perc)
        minetest.chat_send_all(msg)
    end
end
```

Dies ist nicht die einzige Möglichkeit, Mapblöcke zu laden; die Verwendung eines
[Lua Voxel Manipulator (LVM)](../advmap/lvm.html) bewirkt ebenfalls, dass die
umschlossenen Mapblöcke synchron geladen werden.

## Blöcke löschen

Sie können delete_blocks verwenden, um einen Bereich von Map-Blöcken zu löschen:

```lua
-- Löscht einen 20x20x20-Bereich
local halbegroesse = { x = 10, y = 10, z = 10 }
local pos1 = vector.subtract(pos, halbegroesse)
local pos2 = vector.add     (pos, halbegroesse)

minetest.delete_area(pos1, pos2)
```

Dadurch werden alle Map-Blöcke in diesem Bereich *inklusive* gelöscht. Das bedeutet, dass einige
Blöcke außerhalb des Bereichs gelöscht werden, da sie sich auf einem Map-Block befinden, der sich mit den
die Bereichsgrenzen überlappen.
