---
title: Storage und Metadaten
layout: default
root: ../..
idx: 3.3
description: Mod Storage, NodeMetaRef (get_meta).
redirect_from:
  - /de/chapters/node_metadata.html
  - /de/map/node_metadata.html
---

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

In diesem Kapitel erfahren Sie, wie Sie Daten speichern können.

- [Metadaten](#metadaten)
	- [Was sind Metadaten?](#was-sind-metadaten)
	- [Abrufen eines Metadatenobjekts](#abrufen-eines-metadatenobjekts)
	- [Lesen und Schreiben](#lesen-und-schreiben)
	- [Besondere Schlüssel](#besondere-schlüssel)
	- [Speichern von Tabellen](#speichern-von-tabellen)
	- [Private Metadaten](#private-metadaten)
	- [Lua Tabellen](#lua-tabellen)
- [Mod Storage](#mod-storage)
- [Datenbanken](#datenbanken)
- [Entscheidung, was man benutzt](#entscheidung-was-man-benutzt)
- [Sie sind dran](#sie-sind-dran)

## Metadaten

### Was sind Metadaten?

In Minetest sind Metadaten ein Key-Value-Speicher, der verwendet wird, um benutzerdefinierte Daten an etwas anzuhängen.
Sie können Metadaten verwenden, um Informationen zu einem Node, Spieler oder ItemStack zu speichern.

Jede Art von Metadaten verwendet genau dieselbe API.
Metadaten speichern Werte als Strings, aber es gibt eine Reihe von Methoden um
andere primitive Typen zu konvertieren und zu speichern.

Einige Schlüssel in Metadaten können eine besondere Bedeutung haben.
Zum Beispiel wird `infotext` in den Node-Metadaten verwendet, um den Tooltip zu speichern,
der angezeigt wird, wenn man mit dem Fadenkreuz über den Node fährt.
Um Konflikte mit anderen Mods zu vermeiden, sollten Sie die Standard-Namensraum
Konvention für Schlüssel verwenden: `Modname:Schlüsselname`.
Die Ausnahme sind konventionelle Daten wie der Name des Besitzers, der als
`owner` abgespeichert wird.

Metadaten sind Daten über Daten.
Die Daten selbst, wie der Typ eines Nodes oder die Anzahl eines Stapels, sind keine Metadaten.

### Abrufen eines Metadatenobjekts

Wenn Sie die Position eines Nodes kennen, können Sie seine Metadaten abrufen:

```lua
local meta = minetest.get_meta({ x = 1, y = 2, z = 3 })
```

Spieler- und ItemStack-Metadaten werden mit `get_meta()` ermittelt.:

```lua
local pmeta = player:get_meta()
local imeta = stack:get_meta()
```

### Lesen und Schreiben

In den meisten Fällen werden die Methoden `get_<type>()` und `set_<type>()` zum Lesen
und zum schreiben in Metadaten verwendet .
Metadaten speichern Strings, so dass die String-Methoden direkt den Wert setzen und holen.

```lua
print(meta:get_string("foo")) --> ""
meta:set_string("foo", "bar")
print(meta:get_string("foo")) --> "bar"
```

Alle typisierten Getter geben einen neutralen Standardwert zurück, wenn der Schlüssel nicht
nicht existiert, wie zum Beispiel `""` oder `0`.
Sie können `get()` verwenden, um einen String oder nil zurückzugeben.

Da es sich bei Metadaten um eine Referenz handelt, werden alle Änderungen automatisch in der Quelle aktualisiert.
ItemStacks sind jedoch keine Referenzen, daher müssen Sie den Itemstack im
Inventar aktualisieren.

Die nicht typisierten Getter und Setter werden in und aus Strings konvertiert:

```lua
print(meta:get_int("count"))    --> 0
meta:set_int("count", 3)
print(meta:get_int("count"))    --> 3
print(meta:get_string("count")) --> "3"
```

### Besondere Schlüssel

`infotext` wird in Node-Metadaten verwendet, um einen Tooltip anzuzeigen, wenn das Fadenkreuz über einem Node schwebt.
Dies ist nützlich, um die Eigentümerschaft oder den Status eines Nodes anzuzeigen.

`description` wird in ItemStack-Metadaten verwendet, um die Beschreibung zu überschreiben,
wenn der Mauszeiger über den Stack in einem Inventar bewegt wird.
Sie können Farben verwenden, indem Sie sie mit `minetest.colorize()` kodieren.

`owner` ist ein allgemeiner Schlüssel, der verwendet wird, um den Benutzernamen des Spielers zu speichern,
der Eigentümer des Elements oder Node ist.

### Speichern von Tabellen

Tabellen müssen in Strings umgewandelt werden, bevor sie gespeichert werden können.
Minetest bietet dafür zwei Formate an: Lua und JSON.

Die Lua-Methode ist in der Regel viel schneller und entspricht dem Format, das Lua
für Tabellen verwendet, während JSON ein standardisierteres Format ist, das besser
strukturiert und sich gut für den Austausch von Informationen mit
einem anderen Programm eignet.

```lua
local daten = { benutzername = "spieler1", punktestand = 1234 }
meta:set_string("foo", minetest.serialize(daten))

daten = minetest.deserialize(minetest:get_string("foo"))
```

### Private Metadaten

Standardmäßig werden alle Node-Metadaten an den Client gesendet.
Sie können Schlüssel als privat markieren, um dies zu verhindern.

```lua
meta:set_string("geheim", "asd34dn")
meta:mark_as_private("geheim")
```

### Lua Tabellen

Sie können mit `to_table` und `from_table` in und aus Lua-Tabellen konvertieren:

```lua
local tmp = meta:to_table()
tmp.foo = "bar"
meta:from_table(tmp)
```

## Mod Storage

Mod-Storage verwendet genau dieselbe API wie Metadaten, obwohl sie technisch gesehen keine
Metadaten sind.
Mod-Speicher ist pro Mod und kann nur während der Ladezeit abgefragt werden, um zu wissen,
welche Mod sie anfordert.

```lua
local storage = minetest.get_mod_storage()
```

Sie können den Speicher nun genau wie Metadaten manipulieren:

```lua
storage:set_string("foo", "bar")
```

## Datenbanken

Wenn der Mod wahrscheinlich auf einem Server verwendet wird und viele Daten speichert,
ist es eine gute Idee, eine Datenbank-Speichermethode anzubieten.
Sie sollten dies optional machen, indem Sie trennen, wie die Daten gespeichert werden und wo
sie verwendet werden.

```lua
local backend
if verwende_datenbank then
    backend =
        dofile(minetest.get_modpath("meinemod") .. "/backend_sqlite.lua")
else
    backend =
        dofile(minetest.get_modpath("meinemod") .. "/backend_storage.lua")
end

backend.get_foo("a")
backend.set_foo("a", { score = 3 })
```

Die Datei backend_storage.lua sollte eine Mod-Storage-Implementierung enthalten:

```lua
local storage = minetest.get_mod_storage()
local backend = {}

function backend.set_foo(schluessel, wert)
    storage:set_string(schluessel, minetest.serialize(wert))
end

function backend.get_foo(schluessel)
    return minetest.deserialize(storage:get_string(schluessel))
end

return backend
```

Backend_sqlite würde eine ähnliche Funktion erfüllen, aber Sie sollten die Lua-Bibliothek *lsqlite3* verwenden
anstelle des Mod-Speichers.

Die Verwendung einer Datenbank wie SQLite erfordert die Verwendung einer unsicheren Umgebung.
Eine unsichere Umgebung ist eine Tabelle, die nur für Mods verfügbar ist,
die vom Benutzer explizit auf eine Whitelist gesetzt wurden, und sie enthält eine weniger eingeschränkte
Kopie der Lua-API, die missbraucht werden könnte, wenn sie böswilligen Mods zur Verfügung stünde.
Unsichere Umgebungen werden im Detail in dem
Kapitel [Sicherheit](../quality/security.html) behandelt.

```lua
local uu = minetest.request_insecure_environment()
assert(uu, "Bitte fügen Sie meinemod zu secure.trusted_mods in den Einstellungen hinzu")

local _sql = uu.require("lsqlite3")
-- Andere Mods daran hindern, die globale sqlite3-Bibliothek zu verwenden
if sqlite3 then
    sqlite3 = nil
end
```

Die Vermittlung von Wissen über SQL oder die Verwendung der lsqlite3-Bibliothek ist nicht Gegenstand dieses Buches.

## Entscheidung, was man benutzt

Welche Methode Sie verwenden, hängt davon ab, worum es sich bei den Daten handelt,
wie sie formatiert sind und wie groß sie sind.
Als Richtlinie gilt, dass kleine Daten bis zu 10K, mittlere Daten bis zu 10MB und große
Daten jede Größe darüber sind.

Node-Metadaten sind eine gute Wahl, wenn Sie nodebezogene Daten speichern müssen.
Die Speicherung mittlerer Daten ist recht effizient, wenn Sie sie privat machen.

Item-Metadaten sollten nur zum Speichern kleiner Datenmengen verwendet werden, da es nicht möglich ist,
sie an den Client zu senden.
Die Daten werden auch jedes Mal kopiert, wenn der Stack verschoben oder von Lua aus aufgerufen wird.

Mod-Storage ist gut für mittlere Daten, aber das Schreiben großer Daten kann ineffizient sein.
Es ist besser, eine Datenbank für große Daten zu verwenden, um zu vermeiden,
dass alle Daten bei jedem Speichern geschrieben werden müssen.

Datenbanken kommen nur für Server in Frage, da
der Mod auf eine Whitelist gesetzt werden muss, um auf eine unsichere Umgebung zugreifen zu können.
Sie sind gut geeignet für große Datenmengen.

## Sie sind dran

* Erstellen Sie einen Node, der verschwindet, nachdem er fünfmal geschlagen wurde.
(Verwenden Sie `on_punch` in der Definition des Nodes und `minetest.set_node`.)
