minetest_modding_book/_de/items/inventories.md
2022-09-01 15:53:13 +00:00

344 lines
11 KiB
Markdown

---
title: ItemStacks und Inventare
layout: default
root: ../..
idx: 2.4
description: Manipulieren von InvRefs und ItemStacks
redirect_from:
- /de/chapters/inventories.html
- /de/chapters/itemstacks.html
- /de/inventories/inventories.html
- /de/inventories/itemstacks.html
---
## Einleitung <!-- omit in toc -->
In diesem Kapitel werden Sie lernen, wie man Inventare verwendet und manipuliert, egal
ob es sich um ein Spielerinventar, ein Nodeinventar oder ein freistehendes Inventar handelt.
- [Was sind ItemStacks und Inventare?](#was-sind-itemstacks-und-inventare)
- [ItemStacks](#itemstacks)
- [Inventarstandorte](#inventarstandorte)
- [Listen](#listen)
- [Größe und Breite](#größe-und-breite)
- [Inhalt überprüfen](#inhalt-überprüfen)
- [Ändern von Inventaren und ItemStacks](#ändern-von-inventaren-und-itemstacks)
- [Zu einer Liste hinzufügen](#zu-einer-liste-hinzufügen)
- [Items nehmen](#items-nehmen)
- [Stacks manipulieren](#stacks-manipulieren)
- [Abnutzung](#abnutzung)
- [Lua Tabellen](#lua-tabellen)
## Was sind ItemStacks und Inventare?
Ein ItemStack sind die Daten hinter einer einzelnen Zelle in einem Inventar.
Ein *Inventar* ist eine Sammlung von *Inventarlisten*, von denen jede
ein 2D-Gitter aus ItemStacks ist.
Inventarlisten werden im Kontext von Inventaren einfach *Listen* genannt.
Der Sinn eines Inventars ist es, mehrere Raster zu ermöglichen, wenn Spieler
und Nodes nur maximal ein Inventar haben.
## ItemStacks
ItemStacks haben vier Komponenten: name, count, wear und metadata.
Der Itemname kann der Itemname eines registrierten Items, ein Alias oder ein
unbekannter Itemname sein.
Unbekannte Items treten häufig auf, wenn Benutzer Mods deinstallieren oder wenn Mods
Items ohne Vorsichtsmaßnahmen, z. B. durch die Registrierung von Aliasen, entfernen.
```lua
print(stack:get_name())
stack:set_name("default:dirt")
if not stack:is_known() then
print("Ist ein unbekanntes Item!")
end
```
Die Anzahl wird immer 0 oder größer sein.
Bei normalem Spielverlauf sollte die Anzahl nicht größer sein als die maximale
Stackgröße des Gegenstands - `stack_max`.
Allerdings können Admin-Befehle und fehlerhafte Mods dazu führen, dass Stacks die maximale Größe überschreiten.
```lua
print(stack:get_stack_max())
```
Ein ItemStack kann leer sein, in diesem Fall ist die Anzahl 0.
```lua
print(stack:get_count())
stack:set_count(10)
```
ItemStacks können auf verschiedene Weise mit der Funktion ItemStack konstruiert werden.
```lua
ItemStack() -- name="", count=0
ItemStack("default:pick_stone") -- count=1
ItemStack("default:stone 30")
ItemStack({ name = "default:wood", count = 10 })
```
Item-Metadaten sind ein unbegrenzter Schlüssel-Wert-Speicher für Daten über das Item.
Schlüssel-Wert bedeutet, dass Sie einen Namen (den sogenannten key) verwenden, um auf die Daten (den sogenannten value) zuzugreifen.
Einige Keys haben eine besondere Bedeutung, wie z. B. `description`, welches für eine per-Item-Beschreibung verwendet wird.
Dies wird im Kapitel über Metadaten und Speicherung ausführlicher behandelt.
## Inventarstandorte
Ein Inventarstandort ist der Ort und die Art und Weise, wie das Inventar gespeichert wird.
Es gibt drei Arten von Inventarstandorten: Spieler, Nodes und freistehend.
Ein Inventar ist direkt an einen und nur einen Ort gebunden - eine Aktualisierung des
Inventars wird es sofort aktualisieren.
Nodeinventare beziehen sich auf die Position eines bestimmten Nodes, z. B. einer Truhe.
Der Node muss geladen werden, da er in den [Node-Metadaten](../map/storage.html#metadata) gespeichert ist.
```lua
local inv = minetest.get_inventory({ type="node", pos={x=1, y=2, z=3} })
```
Auf diese Weise erhält man eine *Inventar-Referenz*, auch als *InvRef* bekannt.
Inventar-Referenzen werden verwendet, um ein Inventar zu manipulieren.
*Referenz* bedeutet, dass die Daten nicht tatsächlich in diesem Objekt gespeichert sind,
sondern das Objekt aktualisiert die Daten direkt an Ort und Stelle.
Der Standort eines Inventar-Referenz kann wie folgt ermittelt werden:
```lua
local location = inv:get_location()
```
Spielerinventare können auf ähnliche Weise oder über eine Spielerreferenz abgerufen werden.
Der Spieler muss online sein, um auf sein Inventar zugreifen zu können.
```lua
local inv = minetest.get_inventory({ type="player", name="spieler1" })
-- oder
local inv = player:get_inventory()
```
Ein freistehendes Inventar ist ein Inventar, das unabhängig von Spielern oder Nodes ist.
Freistehende Inventare werden auch nicht bei einem Neustart gespeichert.
```lua
local inv = minetest.get_inventory({
type="detached", name="inventar_name" })
```
Im Gegensatz zu den anderen Inventararten müssen Sie zunächst ein freistehendes Inventar erstellen
erstellen, bevor Sie darauf zugreifen:
```lua
minetest.create_detached_inventory("inventar_name")
```
Die Funktion create_detached_inventory akzeptiert 3 Argumente, wobei nur das erste -
der Inventarname - erforderlich ist.
Das zweite Argument nimmt eine Tabelle von Callbacks entgegen, die verwendet werden können,
um zu steuern, wie Spieler mit dem Inventar interagieren:
```lua
-- Nur-Eingabefähiges freistehendes Inventar
minetest.create_detached_inventory("inventory_name", {
allow_move = function(inv, from_list, from_index, to_list, to_index, count, player)
return count -- erlaubt bewegen
end,
allow_put = function(inv, listname, index, stack, player)
return stack:get_count() -- erlaubt ablegen
end,
allow_take = function(inv, listname, index, stack, player)
return 0 -- erlaubt Nehmen nicht
end,
on_put = function(inv, listname, index, stack, player)
minetest.chat_send_all(player:get_player_name() ..
" gab " .. stack:to_string() ..
" In die Spendenkiste von " .. minetest.pos_to_string(player:get_pos()))
end,
})
```
Berechtigungsaufrufe - d.h. diejenigen, die mit `allow_` beginnen - geben die Anzahl
der zu übertragenden Items zurück, wobei 0 verwendet wird, um die Übertragung vollständig zu verhindern.
Im Gegensatz dazu haben Aktionsrückrufe - beginnend mit `on_` - keinen Rückgabewert.
## Listen
Inventarlisten sind ein Konzept, das es ermöglicht, mehrere Raster an einem einzigen Ort zu speichern.
Dies ist besonders nützlich für den Spieler, da es eine Reihe von allgemeinen Listen
gibt, die alle Spiele haben, wie das *Hauptinventar* und die *Craftingplätze*.
### Größe und Breite
Listen haben eine Größe, die die Gesamtzahl der Zellen im Raster angibt, und eine
Breite, die nur innerhalb der Engine verwendet wird.
Die Breite der Liste wird beim Zeichnen des Inventars in einem Fenster nicht verwendet, denn der Code hinter dem Fenster bestimmt die zu verwendende Breite.
```lua
if inv:set_size("main", 32) then
inv:set_width("main", 8)
print("Größe: " .. inv:get_size("main"))
print("Breite: " .. inv:get_width("main"))
else
print("Fehler! Ungültiger itemname oder ungültige Größe für set_size()")
end
```
`set_size` wird fehlschlagen und false zurückgeben, wenn der Listenname oder die Größe ungültig ist.
Zum Beispiel kann die neue Größe zu klein sein, damit alle aktuellen Gegenstände
im Inventar zu passen.
### Inhalt überprüfen
`is_empty` kann benutzt werden, um zu sehen, ob eine Liste Items enthält:
```lua
if inv:is_empty("main") then
print("Die Liste ist leer!")
end
```
`contains_item` kann verwendet werden, um festzustellen, ob eine Liste ein bestimmtes Item enthält:
```lua
if inv:contains_item("main", "default:stone") then
print("Ich habe ein paar Steine gefunden!")
end
```
## Ändern von Inventaren und ItemStacks
### Zu einer Liste hinzufügen
`add_item` fügt Items zu einer Liste hinzu (in diesem Fall `"main"`). Im folgenden
Beispiel wird auch die maximale Stackgröße beachtet:
```lua
local stack = ItemStack("default:stone 99")
local reste = inv:add_item("main", stack)
if reste:get_count() > 0 then
print("Inventar ist voll! " ..
reste:get_count() .. " Items wurden nicht hinzugefügt")
end
```
### Items nehmen
Um Items von einer Liste zu löschen:
```lua
local genommen = inv:remove_item("main", stack)
print("Nahm " .. genommen:get_count())
```
### Stacks manipulieren
Sie können einzelne Stacks ändern, indem Sie sie zuerst auswählen:
```lua
local stack = inv:get_stack(listenname, 0)
```
Dann ändern Sie sie durch das Setzen von Eigenschaften oder durch die Verwendung von
Methoden, welche die `stack_size` respektieren:
```lua
local stack = ItemStack("default:stone 50")
local zum_hinzufuegen = ItemStack("default:stone 100")
local reste = stack:add_item(to_add)
local genommen = stack:take_item(19)
print("Konnte nicht" .. reste:get_count() .. " der items hinzufügen.")
-- ^ wird 51 seind
print("Habe " .. stack:get_count() .. " items")
-- ^ wird 80 sein
-- min(50+100, stack_max) - 19 = 80
-- wobei stack_max = 99
```
`add_item` fügt Items zu einem ItemStack hinzu und gibt alle zurück, die nicht hinzugefügt werden konnten.
`take_item` nimmt bis zu der Anzahl der Items, kann aber auch weniger nehmen, und gibt den genommenen Stack zurück.
Legen Sie schließlich den ItemStack fest:
```lua
inv:set_stack(listenname, 0, stack)
```
## Abnutzung
Werkzeuge können abgenutzt sein; die Abnutzung wird in einem Fortschrittsbalken angezeigt und führt zum Abbruch des Werkzeugs, wenn es vollständig abgenutzt ist.
Die Abnutzung ist eine Zahl bis 65535; je höher sie ist, desto mehr ist das Werkzeug abgenutzt.
Die Abnutzung kann mit `add_wear()`, `get_wear()` und `set_wear(wear)` beeinflusst werden.
```lua
local stack = ItemStack("default:pick_mese")
local max_nutzungen = 10
-- Dies geschieht automatisch, wenn Sie ein Werkzeug verwenden, das Dinge abbaut
-- Sie erhöht die Abnutzung eines Gegenstandes um einen Einsatz.
stack:add_wear(65535 / (max_nutzungen - 1))
```
Beim abbauen eines Nodes kann die Abnutzung des Werkzeugs von dem Node abhängen,
der abgebaut wird. Daher variiert max_nutzungen je nachdem, was abgebaut wird.
## Lua Tabellen
ItemStacks und Inventare können in und aus Tabellen konvertiert werden.
Dies ist nützlich für Kopier- und Bulk-Operationen.
```lua
-- Gesamtes Inventar
local daten = inv1:get_lists()
inv2:set_lists(daten)
-- Eine Liste
local listendaten = inv1:get_list("main")
inv2:set_list("main", listendaten)
```
Die Tabelle der Listen, die von `get_lists()` zurückgegeben wird, wird in dieser Form vorliegen:
```lua
{
liste_eins = {
ItemStack,
ItemStack,
ItemStack,
ItemStack,
-- inv:get_size("liste_eins") Elemente
},
liste_zwei = {
ItemStack,
ItemStack,
ItemStack,
ItemStack,
-- inv:get_size("liste_zwei") Elemente
}
}
```
`get_list()` gibt eine einzelne Liste zurück, die lediglich eine Liste von ItemStacks ist.
Ein wichtiger Punkt ist, dass die obigen Set-Methoden die Größe der Listen nicht verändern.
Das bedeutet, dass Sie eine Liste löschen können, indem Sie sie auf eine leere Tabelle setzen, ohne dass sie verkleinert wird:
```lua
inv:set_list("main", {})
```