--- title: ItemStacks und Inventare layout: default root: ../.. idx: 2.4 description: Manipuliere InvRefs und ItemStacks redirect_from: - /de/chapters/inventories.html - /de/chapters/itemstacks.html - /de/inventories/inventories.html - /de/inventories/itemstacks.html --- ## Einleitung In diesem Kapitel werden Sie lernen, wie man Inventare verwendet und manipuliert, egal ob es sich um ein Spielerinventar, ein Blockinventar 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 Blöcke 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 entfernen, z. B. durch die Registrierung von Aliasen. ```lua print(stack:get_name()) stack:set_name("default:dirt") if not stack:is_known() then print("Ist ein unbekanntes Item!") end ``` Der 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 Schlüssel haben eine besondere Bedeutung, wie z. B. `Beschreibung`, die verwendet wird, um eine pro Stack Beschreibung. 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, Blöcke und freistehend. Ein Inventar ist direkt an einen und nur einen Ort gebunden - eine Aktualisierung des Inventars wird es sofort aktualisieren. Blockinventare beziehen sich auf die Position eines bestimmten Blockes, z. B. einer Truhe. Der Block muss geladen werden, da er in den [Block-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*, allgemein als *InvRef* bezeichnet. 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 Inventarverweises 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 Blöcken 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 -- Eingabe nur freistehendes Inventar minetest.create_detached_inventory("inventar_name", { allow_move = function(inv, von_liste, von_index, zu_liste, zu_index, anzahl, player) return anzahl -- erlaubt bewegen end, allow_put = function(inv, listenname, index, stack, spieler) return stack:get_count() -- erlaubt setzen end, allow_take = function(inv, listenname, index, stack, spieler) return 0 -- erlaubt es nicht zu nehmen end, on_put = function(inv, listenname, index, stack, spieler) minetest.chat_send_all(spieler:get_player_name() .. " gab " .. stack:to_string() .. " zu der Spendenkiste von " .. minetest.pos_to_string(spieler: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 *Handwerksplä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 Stapelgröß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 erhalten: ```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 Blockes kann die Abnutzung des Werkzeugs von dem Block abhängen der gegraben wird. Daher variiert max_nutzungen je nachdem, was gegraben 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, und sie wird nicht verkleinert: ```lua inv:set_list("main", {}) ```