2020-04-27 16:11:54 +03:00
---
2020-07-02 15:34:49 +03:00
title: Storaggio e metadati
2020-04-27 16:11:54 +03:00
layout: default
root: ../..
idx: 3.3
2020-07-02 15:34:49 +03:00
description: Scopri come funziona lo spazio d'archiviazione delle mod e come usare i metadati per passare informazioni.
2020-04-27 16:11:54 +03:00
redirect_from:
2020-07-02 15:34:49 +03:00
- /it/chapters/node_metadata.html
- /it/map/node_metadata.html
2020-04-27 16:11:54 +03:00
---
2020-08-20 01:49:39 +03:00
## Introduzione <!-- omit in toc -->
2020-04-27 16:11:54 +03:00
2020-07-02 15:34:49 +03:00
In questo capitolo imparerai i vari modi per immagazzinare dati.
2020-04-27 16:11:54 +03:00
2020-07-02 15:34:49 +03:00
- [Metadati ](#metadati )
2024-08-06 20:23:52 +03:00
- [Cos'è un metadato? ](#cosè-un-metadato )
- [Ottenere i metadati di un oggetto ](#ottenere-i-metadati-di-un-oggetto )
- [Lettura e scrittura ](#lettura-e-scrittura )
- [Chiavi speciali ](#chiavi-speciali )
- [Immagazzinare tabelle ](#immagazzinare-tabelle )
- [Metadati privati ](#metadati-privati )
- [Tabelle Lua ](#tabelle-lua )
- [Storaggio Mod ](#storaggio-mod )
2020-07-02 15:34:49 +03:00
- [Database ](#database )
- [Decidere quale usare ](#decidere-quale-usare )
- [Il tuo turno ](#il-tuo-turno )
2020-04-27 16:11:54 +03:00
2020-07-02 15:34:49 +03:00
## Metadati
2020-04-27 16:11:54 +03:00
2020-07-02 15:34:49 +03:00
### Cos'è un metadato?
2020-04-27 16:11:54 +03:00
2020-07-02 15:34:49 +03:00
In Minetest, un metadato è una coppia chiave-valore usata per collegare dei dati a qualcosa.
Puoi usare i metadati per salvare informazioni nei nodi, nei giocatori o negli ItemStack.
2020-04-27 16:11:54 +03:00
2020-07-02 15:34:49 +03:00
Ogni tipo di metadato usa la stessa identica API.
Ognuno di essi salva i valori come stringhe, ma ci sono comunque dei metodi per convertire e salvare altri tipi di primitivi.
2020-04-27 16:11:54 +03:00
2020-07-02 15:34:49 +03:00
Per evitare conflitti con altre mod, dovresti usare la nomenclatura convenzionale per le chiavi: `nomemod:nomechiave` .
Alcune chiavi hanno invece un significato speciale, come vedremo più in basso.
2020-04-27 16:11:54 +03:00
2020-07-02 15:34:49 +03:00
Ricorda che i metadati sono dati riguardo altri dati.
Il dato in sé, come il tipo di un nodo o la quantità di un ItemStack, non rientra perciò nella definizione.
2020-04-27 16:11:54 +03:00
2020-07-02 15:34:49 +03:00
### Ottenere i metadati di un oggetto
2020-04-27 16:11:54 +03:00
2020-07-02 15:34:49 +03:00
Se si conosce la posizione di un nodo, si possono ottenere i suoi metadati:
2020-04-27 16:11:54 +03:00
```lua
2024-10-23 02:39:22 +03:00
local meta = core.get_meta({ x = 1, y = 2, z = 3 })
2020-04-27 16:11:54 +03:00
```
2020-07-02 15:34:49 +03:00
Quelli dei giocatori e degli ItemStack invece sono ottenuti tramite `get_meta()` :
2020-04-27 16:11:54 +03:00
```lua
2020-07-02 15:34:49 +03:00
local p_meta = player:get_meta()
local i_meta = pila:get_meta()
2020-04-27 16:11:54 +03:00
```
2020-07-02 15:34:49 +03:00
### Lettura e scrittura
2020-04-27 16:11:54 +03:00
2020-07-02 15:34:49 +03:00
Nella maggior parte dei casi, per leggere e scrivere metadati saranno usati i metodi `get_<type>()` e `set_<type>()` .
2020-04-27 16:11:54 +03:00
```lua
print(meta:get_string("foo")) --> ""
meta:set_string("foo", "bar")
print(meta:get_string("foo")) --> "bar"
```
2020-07-02 15:34:49 +03:00
Tutti i getter ritorneranno un valore di default se la chiave non esiste, rispettivamente `""` per le stringhe e `0` per gli interi.
Si può inoltre usare `get()` per ritornare o una stringa o nil.
2020-04-27 16:11:54 +03:00
2020-07-02 15:34:49 +03:00
Come gli inventari, anche i metadati sono riferimenti: ogni cambiamento applicato ad essi, cambierà la fonte originale.
2020-04-27 16:11:54 +03:00
2020-07-02 15:34:49 +03:00
Inoltre, se è possibile convertire un intero in stringa e viceversa, basterà cambiare `get_int` /`get_string` per ottenerne la versione corrispondente:
2020-04-27 16:11:54 +03:00
```lua
print(meta:get_int("count")) --> 0
meta:set_int("count", 3)
print(meta:get_int("count")) --> 3
print(meta:get_string("count")) --> "3"
```
2020-07-02 15:34:49 +03:00
### Chiavi speciali
2020-04-27 16:11:54 +03:00
2020-07-02 15:34:49 +03:00
`infotext` è usato nei nodi per mostrare una porzione di testo al passare il mirino sopra il nodo.
Questo è utile, per esempio, per mostrare lo stato o il proprietario di un nodo.
2020-04-27 16:11:54 +03:00
2020-07-02 15:34:49 +03:00
`description` è usato negli ItemStack per sovrascrivere la descrizione al passare il mouse sopra l'oggetto in un formspec (come l'inventario, li vedremo più avanti).
2024-10-23 02:39:22 +03:00
È possibile utilizzare `core.colorize()` per cambiarne il colore.
2020-04-27 16:11:54 +03:00
2020-07-02 15:34:49 +03:00
`owner` è una chiave comune, usata per immagazzinare il nome del giocatore a cui appartiene l'oggetto o il nodo.
2020-04-27 16:11:54 +03:00
2020-07-02 15:34:49 +03:00
### Immagazzinare tabelle
2020-04-27 16:11:54 +03:00
2020-07-02 15:34:49 +03:00
Le tabelle devono essere convertite in stringhe prima di essere immagazzinate.
Minetest offre due formati per fare ciò: Lua e JSON.
2020-04-27 16:11:54 +03:00
2020-07-02 15:34:49 +03:00
Quello in Lua tende a essere molto più veloce e corrisponde al formato usato da Lua per le tabelle, mentre JSON è un formato più standard, con una miglior struttura, e che ben si presta per scambiare informazioni con un altro programma.
2020-04-27 16:11:54 +03:00
```lua
2020-07-02 15:34:49 +03:00
local data = { username = "utente1", score = 1234 }
2024-10-23 02:39:22 +03:00
meta:set_string("foo", core.serialize(data))
2020-04-27 16:11:54 +03:00
2024-10-23 02:39:22 +03:00
data = core.deserialize(meta:get_string("foo"))
2020-04-27 16:11:54 +03:00
```
2020-07-02 15:34:49 +03:00
### Metadati privati
2020-04-27 16:11:54 +03:00
2020-12-24 21:40:59 +03:00
Di base, tutti i metadati dei nodi sono inviati al client. Rendendo le loro chiavi private, questo invece non succede.
2020-04-27 16:11:54 +03:00
```lua
2020-07-02 15:34:49 +03:00
meta:set_string("segreto", "asd34dn")
meta:mark_as_private("segreto")
2020-04-27 16:11:54 +03:00
```
2020-07-02 15:34:49 +03:00
### Tabelle Lua
2020-04-27 16:11:54 +03:00
2020-07-02 15:34:49 +03:00
Le tabelle possono essere convertite da/a stringhe nei metadati tramite `to_table` e `from_table` :
2020-04-27 16:11:54 +03:00
```lua
local tmp = meta:to_table()
tmp.foo = "bar"
meta:from_table(tmp)
```
2020-07-02 15:34:49 +03:00
## Storaggio Mod
2020-04-27 16:11:54 +03:00
2020-07-02 15:34:49 +03:00
Lo spazio d'archiviazione della mod (*storage*) usa la stessa identica API dei metadati, anche se non sono tecnicamente la stessa cosa.
Il primo infatti è per mod, e può essere ottenuto solo durante l'inizializzazione - appunto - della mod.
2020-04-27 16:11:54 +03:00
```lua
2024-10-23 02:39:22 +03:00
local memoria = core.get_mod_storage()
2020-04-27 16:11:54 +03:00
```
2020-07-02 15:34:49 +03:00
Nell'esempio è ora possibile manipolare lo spazio d'archiviazione come se fosse un metadato:
2020-04-27 16:11:54 +03:00
```lua
2020-07-02 15:34:49 +03:00
memoria:set_string("foo", "bar")
2020-04-27 16:11:54 +03:00
```
2020-07-02 15:34:49 +03:00
## Database
2020-04-27 16:11:54 +03:00
2020-07-02 15:34:49 +03:00
Se la mod ha buone probabilità di essere usata su un server e tenere traccia di un sacco di dati, è buona norma offrire un database come metodo di storaggio.
Dovresti rendere ciò opzionale, separando il come i dati vengono salvati e il dove vengono usati.
2020-04-27 16:11:54 +03:00
```lua
local backend
if use_database then
backend =
2024-10-23 02:39:22 +03:00
dofile(core.get_modpath("miamod") .. "/backend_sqlite.lua")
2020-04-27 16:11:54 +03:00
else
backend =
2024-10-23 02:39:22 +03:00
dofile(core.get_modpath("miamod") .. "/backend_storage.lua")
2020-04-27 16:11:54 +03:00
end
backend.get_foo("a")
backend.set_foo("a", { score = 3 })
```
2020-07-02 15:34:49 +03:00
Il file `backend_storage.lua` dell'esempio (puoi nominarlo come vuoi) dovrebbe includere l'implementazione del metodo di storaggio:
2020-04-27 16:11:54 +03:00
```lua
2024-10-23 02:39:22 +03:00
local memoria = core.get_mod_storage()
2020-04-27 16:11:54 +03:00
local backend = {}
function backend.set_foo(key, value)
2024-10-23 02:39:22 +03:00
memoria:set_string(key, core.serialize(value))
2020-04-27 16:11:54 +03:00
end
2021-02-21 07:26:49 +03:00
function backend.get_foo(key)
2024-10-23 02:39:22 +03:00
return core.deserialize(memoria:get_string(key))
2020-04-27 16:11:54 +03:00
end
return backend
```
2020-07-02 15:34:49 +03:00
Il file `backend_sqlite.lua` dovrebbe fare una cosa simile, ma utilizzando la libreria Lua *lsqlite3* al posto della memoria d'archiviazione interna.
2020-04-27 16:11:54 +03:00
2020-07-02 15:34:49 +03:00
Usare un database come SQLite richiede l'utilizzo di un ambiente non sicuro (*insecure environment*).
Un ambiente non sicuro è una tabella disponibile solamente alle mod con accesso esplicito dato dall'utente, e contiene una copia meno limitata della API Lua, che potrebbe essere abusata da mod con intenzioni malevole.
Gli ambienti non sicuri saranno trattati più nel dettaglio nel capitolo sulla [Sicurezza ](../quality/security.html ).
2020-04-27 16:11:54 +03:00
```lua
2024-10-23 02:39:22 +03:00
local amb_nonsicuro = core.request_insecure_environment()
2020-07-02 15:34:49 +03:00
assert(amb_nonsicuro, "Per favore aggiungi miamod a secure.trusted_mods nelle impostazioni")
2020-04-27 16:11:54 +03:00
2020-07-02 15:34:49 +03:00
local _sql = amb_nonsicuro.require("lsqlite3")
-- Previene che altre mod usino la libreria globale sqlite3
2020-04-27 16:11:54 +03:00
if sqlite3 then
sqlite3 = nil
end
```
2020-07-02 15:34:49 +03:00
Spiegare il funzionamento di SQL o della libreria lsqlite non rientra nell'obiettivo di questo libro.
2020-04-27 16:11:54 +03:00
2020-07-02 15:34:49 +03:00
## Decidere quale usare
2020-04-27 16:11:54 +03:00
2020-07-02 15:34:49 +03:00
Il tipo di metodo che si sceglie di utilizzare dipende dal tipo di dati trattati, come sono formattati e quanto sono grandi.
In linea di massima, i dati piccoli vanno fino ai 10KB, quelli medi 10MB, e quelli grandi oltre i 10MB.
2020-04-27 16:11:54 +03:00
2020-07-02 15:34:49 +03:00
I metadati dei nodi sono un'ottima scelta quando si vogliono immagazzinare dati relativi al nodo.
Inserirne di medi (quindi massimo 10MB) è abbastanza efficiente se si rendono privati.
2020-04-27 16:11:54 +03:00
2020-07-02 15:34:49 +03:00
Quelli degli oggetti invece dovrebbero essere usati solo per piccole quantità di dati e non è possibile evitare di inviarli al client.
I dati, poi, saranno anche copiati ogni volta che la pila viene spostata o ne viene fatto accesso tramite Lua.
2020-04-27 16:11:54 +03:00
2020-07-02 15:34:49 +03:00
La memoria interna della mod va bene per i dati di medie dimensioni, tuttavia provare a salvarne di grandi potrebbe rivelarsi inefficiente.
È meglio usare un database per le grandi porzioni di dati, onde evitare di dover sovrascrivere tutti i dati a ogni salvataggio.
2020-04-27 16:11:54 +03:00
2020-07-02 15:34:49 +03:00
I database sono fattibili solo per i server a causa della necessità di lasciar passare la mod nell'ambiente non sicuro.
Si prestano bene per i grandi ammontare di dati.
2020-04-27 16:11:54 +03:00
2020-07-02 15:34:49 +03:00
## Il tuo turno
2020-04-27 16:11:54 +03:00
2020-07-02 15:34:49 +03:00
* Crea un nodo che sparisce dopo essere stato colpito cinque volte.
2024-10-23 02:39:22 +03:00
(Usa `on_punch` nella definizione del nodo e `core.set_node` )