345 lines
11 KiB
Markdown
345 lines
11 KiB
Markdown
---
|
|
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 <!-- omit in toc -->
|
|
|
|
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", {})
|
|
```
|