--- 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 ob es sich um ein Spielerinventar, ein Knoteninventar oder ein freistehendes Inventar handelt. - [Was sind ItemStacks und Inventare?](#was-sind-itemstacks-und-inventare) - [ItemStacks](#itemstacks) - [Inventarstandorte](#inventarstandorte) - [Lists](#lists) - [Size and Width](#size-and-width) - [Checking Contents](#checking-contents) - [Modifying Inventories and ItemStacks](#modifying-inventories-and-itemstacks) - [Adding to a List](#adding-to-a-list) - [Taking Items](#taking-items) - [Manipulating Stacks](#manipulating-stacks) - [Wear](#wear) - [Lua Tables](#lua-tables) ## 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. ## Lists Inventory Lists are a concept used to allow multiple grids to be stored inside a single location. This is especially useful for the player as there are a number of common lists which all games have, such as the *main* inventory and *craft* slots. ### Size and Width Lists have a size, which is the total number of cells in the grid, and a width, which is only used within the engine. The width of the list is not used when drawing the inventory in a window, because the code behind the window determines the width to use. ```lua if inv:set_size("main", 32) then inv:set_width("main", 8) print("size: " .. inv:get_size("main")) print("width: " .. inv:get_width("main")) else print("Error! Invalid itemname or size to set_size()") end ``` `set_size` will fail and return false if the listname or size is invalid. For example, the new size may be too small to fit all the current items in the inventory. ### Checking Contents `is_empty` can be used to see if a list contains any items: ```lua if inv:is_empty("main") then print("The list is empty!") end ``` `contains_item` can be used to see if a list contains a specific item: ```lua if inv:contains_item("main", "default:stone") then print("I've found some stone!") end ``` ## Modifying Inventories and ItemStacks ### Adding to a List `add_item` adds items to a list (in this case `"main"`). In the example below, the maximum stack size is also respected: ```lua local stack = ItemStack("default:stone 99") local leftover = inv:add_item("main", stack) if leftover:get_count() > 0 then print("Inventory is full! " .. leftover:get_count() .. " items weren't added") end ``` ### Taking Items To remove items from a list: ```lua local taken = inv:remove_item("main", stack) print("Took " .. taken:get_count()) ``` ### Manipulating Stacks You can modify individual stacks by first getting them: ```lua local stack = inv:get_stack(listname, 0) ``` Then modifying them by setting properties or by using the methods which respect `stack_size`: ```lua local stack = ItemStack("default:stone 50") local to_add = ItemStack("default:stone 100") local leftover = stack:add_item(to_add) local taken = stack:take_item(19) print("Could not add" .. leftover:get_count() .. " of the items.") -- ^ will be 51 print("Have " .. stack:get_count() .. " items") -- ^ will be 80 -- min(50+100, stack_max) - 19 = 80 -- where stack_max = 99 ``` `add_item` will add items to an ItemStack and return any that could not be added. `take_item` will take up to the number of items but may take less, and returns the stack taken. Finally, set the item stack: ```lua inv:set_stack(listname, 0, stack) ``` ## Wear Tools can have wear; wear shows a progress bar and makes the tool break when completely worn. Wear is a number out of 65535; the higher it is, the more worn the tool is. Wear can be manipulated using `add_wear()`, `get_wear()`, and `set_wear(wear)`. ```lua local stack = ItemStack("default:pick_mese") local max_uses = 10 -- This is done automatically when you use a tool that digs things -- It increases the wear of an item by one use. stack:add_wear(65535 / (max_uses - 1)) ``` When digging a node, the amount of wear a tool gets may depend on the node being dug. So max_uses varies depending on what is being dug. ## Lua Tables ItemStacks and Inventories can be converted to and from tables. This is useful for copying and bulk operations. ```lua -- Entire inventory local data = inv1:get_lists() inv2:set_lists(data) -- One list local listdata = inv1:get_list("main") inv2:set_list("main", listdata) ``` The table of lists returned by `get_lists()` will be in this form: ```lua { list_one = { ItemStack, ItemStack, ItemStack, ItemStack, -- inv:get_size("list_one") elements }, list_two = { ItemStack, ItemStack, ItemStack, ItemStack, -- inv:get_size("list_two") elements } } ``` `get_list()` will return a single list as just a list of ItemStacks. One important thing to note is that the set methods above don't change the size of the lists. This means that you can clear a list by setting it to an empty table and it won't decrease in size: ```lua inv:set_list("main", {}) ```