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

11 KiB

title layout root idx description redirect_from
ItemStacks und Inventare default ../.. 2.4 Manipulieren von InvRefs und ItemStacks
/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 Nodeinventar oder ein freistehendes Inventar handelt.

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.

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.

print(stack:get_stack_max())

Ein ItemStack kann leer sein, in diesem Fall ist die Anzahl 0.

print(stack:get_count())
stack:set_count(10)

ItemStacks können auf verschiedene Weise mit der Funktion ItemStack konstruiert werden.

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 gespeichert ist.

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:

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.

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.

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:

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:

-- 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.

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:

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:

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:

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:

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:

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:

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:

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.

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.

-- 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:

{
    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:

inv:set_list("main", {})