2020-04-27 16:11:54 +03:00
---
2020-08-18 23:57:46 +03:00
title: "Mappa: operazioni base"
2020-04-27 16:11:54 +03:00
layout: default
root: ../..
idx: 3.1
2020-06-15 02:24:44 +03:00
description: Operazioni base come set_node e get_node
redirect_from: /it/chapters/environment.html
2020-04-27 16:11:54 +03:00
---
2020-10-14 21:18:55 +03:00
## Introduzione <!-- omit in toc -->
2020-04-27 16:11:54 +03:00
2020-06-15 02:24:44 +03:00
In questo capitolo imparerai come eseguire semplici azioni sulla mappa.
2020-04-27 16:11:54 +03:00
2020-06-15 02:24:44 +03:00
- [Struttura della mappa ](#struttura-della-mappa )
- [Lettura ](#lettura )
2020-12-24 21:40:59 +03:00
- [Lettura dei nodi ](#lettura-dei-nodi )
- [Ricerca dei nodi ](#ricerca-dei-nodi )
2020-06-15 02:24:44 +03:00
- [Scrittura ](#scrittura )
2020-12-24 21:40:59 +03:00
- [Scrittura dei nodi ](#scrittura-dei-nodi )
- [Rimozione dei nodi ](#rimozione-dei-nodi )
2020-06-15 02:24:44 +03:00
- [Caricamento blocchi ](#caricamento-blocchi )
- [Cancellazione blocchi ](#cancellazione-blocchi )
2020-04-27 16:11:54 +03:00
2020-06-15 02:24:44 +03:00
## Struttura della mappa
2020-04-27 16:11:54 +03:00
2020-06-15 02:24:44 +03:00
La mappa di Minetest è suddivisa in Blocchi Mappa (*MapBlocks*), cubi di 16x16x16 nodi.
Man mano che i giocatori si addentrano per la mappa, i Blocchi Mappa vengono creati, caricati e rimossi dalla memoria.
Le aree della mappa che non sono ancora caricate sono piene di nodi *ignora* , dei nodi segnaposto che non possono
essere né attraversati né selezionati. Gli spazi vuoti delle aree già caricate, invece, sono nodi *d'aria* , dei
nodi invisibili e attraversabili.
2020-04-27 16:11:54 +03:00
2020-06-15 02:24:44 +03:00
Spesso, ci si rifà ai blocchi caricati (attenzione! Blocco non vuol dire nodo, come detto qui sopra!) chiamandoli *blocchi attivi* .
2020-08-18 23:57:46 +03:00
I blocchi attivi possono essere letti e sovrascritti dalle mod o dai giocatori, e contenere entità attive.
2020-06-15 02:24:44 +03:00
Anche il motore di gioco esegue operazioni sulla mappa, come il calcolare la fisica dei liquidi.
2020-04-27 16:11:54 +03:00
2020-06-15 02:24:44 +03:00
I Blocchi Mappa possono essere sia caricati dal database del mondo che generati.
Essi vengono generati fino al limite di generazione della mappa (`mapgen_limit`), che è impostato di base al suo valore massimo, 31000.
I Blocchi Mappa esistenti, tuttavia, ignorano questo limite quando caricati dal database del mondo.
2020-04-27 16:11:54 +03:00
2020-06-15 02:24:44 +03:00
## Lettura
2020-04-27 16:11:54 +03:00
2020-06-15 02:24:44 +03:00
### Lettura dei nodi
2020-04-27 16:11:54 +03:00
2020-06-15 02:24:44 +03:00
Un nodo può essere letto da un mondo fornendone la posizione:
2020-04-27 16:11:54 +03:00
```lua
2024-10-23 02:39:22 +03:00
local nodo = core.get_node({ x = 1, y = 3, z = 4 })
2020-06-15 02:24:44 +03:00
print(dump(nodo)) --> { name=.., param1=.., param2=.. }
2020-04-27 16:11:54 +03:00
```
2020-06-15 02:24:44 +03:00
Se la posizione è un decimale, verrà arrotondata alle coordinate del nodo.
`get_node` ritornerà sempre una tabella contenente le informazioni del nodo:
2020-04-27 16:11:54 +03:00
2020-06-15 02:24:44 +03:00
* `name` - Il nome del nodo, che sarà `ignore` quando l'area non è caricata.
* `param1` - Guarda la definizione dei nodi. È solitamente associato alla luce.
* `param2` - Guarda la definizione dei nodi.
2020-04-27 16:11:54 +03:00
2024-10-23 02:39:22 +03:00
Per vedere se un nodo è caricato si può utilizzare `core.get_node_or_nil` , che ritornerà `nil` se il nome del nodo risulta `ignore`
2020-06-15 02:24:44 +03:00
(la funzione non caricherà comunque il nodo).
Potrebbe comunque ritornare `ignore` se un blocco contiene effettivamente `ignore` : questo succede ai limiti della mappa.
2020-04-27 16:11:54 +03:00
2020-06-15 02:24:44 +03:00
### Ricerca dei nodi
2020-04-27 16:11:54 +03:00
2020-06-15 02:24:44 +03:00
Minetest offre un numero di funzioni d'aiuto per accelerare le azioni più comuni legate alla mappa.
Le più frequenti sono quelle per trovare i nodi.
2020-04-27 16:11:54 +03:00
2020-06-15 02:24:44 +03:00
Per esempio, mettiamo che si voglia creare un certo tipo di pianta che cresce più velocemente vicino alla pietra;
si dovrebbe controllare che ogni nodo nei pressi della pianta sia pietra, e modificarne il suo indice di crescita di conseguenza.
2020-04-27 16:11:54 +03:00
2024-10-23 02:39:22 +03:00
`core.find_node_near` ritornerà il primo nodo trovato in un dato raggio, combaciante con le informazioni passategli (nomi di nodi o gruppi).
2021-01-28 03:13:08 +03:00
Nell'esempio che segue, andiamo alla ricerca di un nodo di mese nel raggio di 5 nodi:
2020-04-27 16:11:54 +03:00
```lua
2020-06-15 02:24:44 +03:00
local vel_crescita = 1
2024-10-23 02:39:22 +03:00
local pos_nodo = core.find_node_near(pos, 5, { "default:stone" })
2020-06-15 02:24:44 +03:00
if pos_nodo then
2024-10-23 02:39:22 +03:00
core.chat_send_all("Nodo trovato a: " .. dump(pos_nodo))
2020-06-15 02:24:44 +03:00
vel_crescita = 2
2020-04-27 16:11:54 +03:00
end
```
2020-06-15 02:24:44 +03:00
Mettiamo ora che l'indice di crescita debba incrementare per ogni nodo di pietra nei dintorni.
Si dovrebbe quindi usare una funzione in grado di trovare più nodi in un'area:
2020-04-27 16:11:54 +03:00
```lua
local pos1 = vector.subtract(pos, { x = 5, y = 5, z = 5 })
local pos2 = vector.add(pos, { x = 5, y = 5, z = 5 })
2020-06-15 02:24:44 +03:00
local lista_pos =
2024-10-23 02:39:22 +03:00
core.find_nodes_in_area(pos1, pos2, { "default:stone" })
2020-06-15 02:24:44 +03:00
local vel_crescita = 1 + #lista_pos
2020-04-27 16:11:54 +03:00
```
2021-01-28 03:13:08 +03:00
Il codice qui in alto ritorna il numero di nodi in un *volume cuboidale* .
Il che è diverso da usare `find_node_near` , il quale usa la distanza dalla posizione data (cioé una *sfera* ).
Per ovviare a ciò, bisogna controllare l'intervallo manualmente.
2020-04-27 16:11:54 +03:00
```lua
local pos1 = vector.subtract(pos, { x = 5, y = 5, z = 5 })
local pos2 = vector.add(pos, { x = 5, y = 5, z = 5 })
2020-06-15 02:24:44 +03:00
local lista_pos =
2024-10-23 02:39:22 +03:00
core.find_nodes_in_area(pos1, pos2, { "default:stone" })
2020-06-15 02:24:44 +03:00
local vel_crescita = 1
for i=1, #lista_pos do
local delta = vector.subtract(lista_pos[i], pos)
2020-12-24 22:44:51 +03:00
if delta.x*delta.x + delta.y*delta.y + delta.z*delta.z < = 5*5 then
2020-06-15 02:24:44 +03:00
vel_crescita = vel_crescita + 1
2020-04-27 16:11:54 +03:00
end
end
```
2020-06-15 02:24:44 +03:00
Ora il codice aumenterà correttamente `vel_crescita` basandosi su quanti nodi di pietra ci sono in un intervallo.
2020-12-24 22:44:51 +03:00
2020-06-15 02:24:44 +03:00
Notare come si sia comparata la distanza al quadrato dalla posizione, invece che calcolarne la radice quadrata per ottenerne la distanza vera e propria.
2021-01-28 03:13:08 +03:00
Questo perché i computer trovano le radici quadrate computazionalmente pesanti, quindi dovrebbero essere evitate il più possibile.
2020-04-27 16:11:54 +03:00
2020-06-15 02:24:44 +03:00
Ci sono altre variazioni delle due funzioni sopracitate, come `find_nodes_with_meta` e `find_nodes_in_area_under_air` , che si comportano in modo simile e sono utili in altre circostanze.
2020-04-27 16:11:54 +03:00
2020-06-15 02:24:44 +03:00
## Scrittura
2020-04-27 16:11:54 +03:00
2020-06-15 02:24:44 +03:00
### Scrittura dei nodi
2020-04-27 16:11:54 +03:00
2020-06-15 02:24:44 +03:00
Puoi usare `set_node` per sovrascrivere nodi nella mappa.
2021-01-28 03:13:08 +03:00
Ogni chiamata a `set_node` ricalcolerà la luce e richiamerà i suoi callback, il che significa che `set_node` è alquanto lento quando usato su un elevato numero di nodi.
2020-04-27 16:11:54 +03:00
```lua
2024-10-23 02:39:22 +03:00
core.set_node({ x = 1, y = 3, z = 4 }, { name = "default:stone" })
2020-04-27 16:11:54 +03:00
2024-10-23 02:39:22 +03:00
local nodo = core.get_node({ x = 1, y = 3, z = 4 })
2020-06-15 02:24:44 +03:00
print(nodo.name) --> default:stone
2020-04-27 16:11:54 +03:00
```
2021-01-28 03:13:08 +03:00
`set_node` rimuoverà ogni metadato e inventario associato a quel nodo: ciò non è sempre desiderabile, specialmente se si stanno usando
2020-06-15 02:24:44 +03:00
più definizioni di nodi per rappresentarne concettualmente uno. Un esempio è il nodo fornace: per quanto lo si immagini come un nodo unico,
sono in verità due.
2020-04-27 16:11:54 +03:00
2020-06-15 02:24:44 +03:00
Si può impostare un nuovo nodo senza rimuoverne metadati e inventario con `swap_node` :
2020-04-27 16:11:54 +03:00
```lua
2024-10-23 02:39:22 +03:00
core.swap_node({ x = 1, y = 3, z = 4 }, { name = "default:stone" })
2020-04-27 16:11:54 +03:00
```
2020-06-15 02:24:44 +03:00
### Rimozione dei nodi
2020-04-27 16:11:54 +03:00
2020-06-15 02:24:44 +03:00
Un nodo deve sempre essere presente. Per rimuoverlo, basta impostarlo uguale a `air` .
2020-04-27 16:11:54 +03:00
2020-06-15 02:24:44 +03:00
Le seguenti due linee di codice sono equivalenti, rimuovendo in entrambi i casi il nodo:
2020-04-27 16:11:54 +03:00
```lua
2024-10-23 02:39:22 +03:00
core.remove_node(pos)
core.set_node(pos, { name = "air" })
2020-04-27 16:11:54 +03:00
```
2020-06-15 02:24:44 +03:00
Infatti, `remove_node` non fa altro che richiamare `set_node` con nome `air` .
2020-04-27 16:11:54 +03:00
2020-06-15 02:24:44 +03:00
## Caricamento blocchi
2020-04-27 16:11:54 +03:00
2024-10-23 02:39:22 +03:00
Puoi usare `core.emerge_area` per caricare i blocchi mappa.
2020-06-15 02:24:44 +03:00
Questo comando è asincrono, ovvero i blocchi non saranno caricati istantaneamente; al contrario, verranno caricati man mano e il callback associato sarà richiamato a ogni passaggio.
2020-04-27 16:11:54 +03:00
```lua
2020-06-15 02:24:44 +03:00
-- Carica un'area 20x20x20
local mezza_dimensione = { x = 10, y = 10, z = 10 }
local pos1 = vector.subtract(pos, mezza_dimensione)
local pos2 = vector.add (pos, mezza_dimensione)
2020-04-27 16:11:54 +03:00
2020-06-15 02:24:44 +03:00
local param = {} -- dati persistenti tra un callback e l'altro
2024-10-23 02:39:22 +03:00
core.emerge_area(pos1, pos2, mio_callback, param)
2020-04-27 16:11:54 +03:00
```
2020-06-15 02:24:44 +03:00
Minetest chiamerà la funzione locale definita qua sotto `mio_callback` ogni volta che carica un blocco, con delle informazioni sul progresso.
2020-04-27 16:11:54 +03:00
```lua
2020-06-15 02:24:44 +03:00
local function mio_callback(pos, action,
calls_remaining, param)
-- alla prima chiamata, registra il numero di blocchi
if not param.blocchi_totali then
param.blocchi_totali = calls_remaining + 1
param.blocchi_caricati = 0
2020-04-27 16:11:54 +03:00
end
2020-06-15 02:24:44 +03:00
-- Incrementa il numero di blocchi caricati
param.loaded_blocks = param.blocchi_caricati + 1
2020-04-27 16:11:54 +03:00
2020-06-15 02:24:44 +03:00
-- Invia messaggio indicante il progresso
if param.blocchi_totali == param.blocchi_caricati then
2024-10-23 02:39:22 +03:00
core.chat_send_all("Ho finito di caricare blocchi!")
2021-06-27 01:15:26 +03:00
else
2020-06-15 02:24:44 +03:00
local percentuale = 100 * param.blocchi_caricati / param.blocchi_totali
local msg = string.format("Caricamento blocchi %d/%d (%.2f%%)",
param.blocchi_caricati, param.blocchi_totali, percentuale)
2024-10-23 02:39:22 +03:00
core.chat_send_all(msg)
2020-04-27 16:11:54 +03:00
end
end
```
2020-06-15 02:24:44 +03:00
Questo non è l'unico modo per caricare blocchi; utilizzando un LVM (nel dettaglio nel capitolo 19) si potranno infatti caricare i blocchi selezionati in maniera sincrona.
2020-04-27 16:11:54 +03:00
2020-06-15 02:24:44 +03:00
## Cancellazione blocchi
2020-04-27 16:11:54 +03:00
2020-06-15 02:24:44 +03:00
Puoi usare `delete_area` per cancellare una serie di blocchi mappa:
2020-04-27 16:11:54 +03:00
```lua
2020-06-15 02:24:44 +03:00
-- Cancella un'area 20x20x20
local mezza_dimensione = { x = 10, y = 10, z = 10 }
local pos1 = vector.subtract(pos, mezza_dimensione)
local pos2 = vector.add (pos, mezza_dimensione)
2020-04-27 16:11:54 +03:00
2024-10-23 02:39:22 +03:00
core.delete_area(pos1, pos2)
2020-04-27 16:11:54 +03:00
```
2020-06-15 02:24:44 +03:00
Questo cancellerà tutti i blocchi mappa in quell'area, anche quelli solo parzialmente selezionati.