I reverted the whole 'players' folder like an idiot. Bless the local copy on the other PC

This commit is contained in:
Marco 2020-07-11 10:30:46 +02:00 committed by rubenwardy
parent c0ca655327
commit 50687bc868
6 changed files with 563 additions and 687 deletions

150
_it/players/chat.md Normal file → Executable file
View File

@ -1,70 +1,66 @@
--- ---
title: Chat and Commands title: Chat e comandi
layout: default layout: default
root: ../.. root: ../..
idx: 4.2 idx: 4.2
description: Registering a chatcommand and handling chat messages with register_on_chat_message description: Come registrare un comando e gestire i messaggi della chat
redirect_from: /en/chapters/chat.html redirect_from: /it/chapters/chat.html
cmd_online: cmd_online:
level: warning level: warning
title: Offline players can run commands title: I giocatori offline possono eseguire comandi
message: <p>A player name is passed instead of a player object because mods message: <p>Viene passato il nome del giocatore al posto del giocatore in sé perché le mod possono eseguire comandi in vece di un giocatore offline.
can run commands on behalf of offline players. For example, the IRC Per esempio, il bridge IRC permette ai giocatori di eseguire comandi senza dover entrare in gioco.</p>
bridge allows players to run commands without joining the game.</p>
<p>So make sure that you don't assume that the player is online. <p>Assicurati quindi di non dar per scontato che un giocatore sia connesso.
You can check by seeing if <pre>minetest.get_player_by_name</pre> returns a player.</p> Puoi controllare ciò tramite <pre>minetest.get_player_by_name</pre>, per vedere se ritorna qualcosa o meno.</p>
cb_cmdsprivs: cb_cmdsprivs:
level: warning level: warning
title: Privileges and Chat Commands title: Privilegi e comandi
message: The shout privilege isn't needed for a player to trigger this callback. message: Il privilegio shout non è necessario per far sì che un giocatore attivi questo callback.
This is because chat commands are implemented in Lua, and are just Questo perché i comandi sono implementati in Lua, e sono semplicemente dei messaggi in chat che iniziano con /.
chat messages that begin with a /.
--- ---
## Introduction <!-- omit in toc --> ## Introduzione <!-- omit in toc -->
Mods can interact with player chat, including Le mod possono interagire con la chat del giocatore, tra l'inviare messaggi, intercettarli e registrare dei comandi.
sending messages, intercepting messages, and registering chat commands.
- [Sending Messages to All Players](#sending-messages-to-all-players) - [Inviare messaggi a tutti i giocatori](#inviare-messaggi-a-tutti-i-giocatori)
- [Sending Messages to Specific Players](#sending-messages-to-specific-players) - [Inviare messaggi a giocatori specifici](#inviare-messaggi-a-giocatori-specifici)
- [Chat Commands](#chat-commands) - [Comandi](#comandi)
- [Complex Subcommands](#complex-subcommands) - [Complex Subcommands](#complex-subcommands)
- [Intercepting Messages](#intercepting-messages) - [Intercettare i messaggi](#interecettare-i-messaggi)
## Sending Messages to All Players ## Inviare messaggi a tutti i giocatori
To send a message to every player in the game, call the chat_send_all function. Per inviare un messaggio a tutti i giocatori connessi in gioco, si usa la funzione `chat_send_all`:
```lua ```lua
minetest.chat_send_all("This is a chat message to all players") minetest.chat_send_all("Questo è un messaggio visualizzabile da tutti")
``` ```
Here is an example of how this appears in-game: Segue un esempio di come apparirerebbe in gioco:
<player1> Look at this entrance <Tizio> Guarda qui
This is a chat message to all players Questo è un messaggio visualizzabile da tutti
<player2> What about it? <Caio> Eh, cosa?
The message appears on a separate line to distinguish it from in-game player chat. Il messaggio appare su una nuova riga, per distinguerlo dai messaggi dei giocatori.
## Sending Messages to Specific Players ## Inviare messaggi a giocatori specifici
To send a message to a specific player, call the chat_send_player function: Per inviare un messaggio a un giocatore in particolare, si usa invece la funzione `chat_send_player`:
```lua ```lua
minetest.chat_send_player("player1", "This is a chat message for player1") minetest.chat_send_player("Tizio", "Questo è un messaggio per Tizio")
``` ```
This message displays in the same manner as messages to all players, but is Questo messaggio viene mostrato esattamente come il precedente, ma solo, in questo caso, a Tizio.
only visible to the named player, in this case, player1.
## Chat Commands ## Comandi
To register a chat command, for example `/foo`, use `register_chatcommand`: Per registrare un comando, per esempio `/foo`, si usa `register_chatcommand`:
```lua ```lua
minetest.register_chatcommand("foo", { minetest.register_chatcommand("foo", {
@ -72,93 +68,83 @@ minetest.register_chatcommand("foo", {
interact = true, interact = true,
}, },
func = function(name, param) func = function(name, param)
return true, "You said " .. param .. "!" return true, "Hai detto " .. param .. "!"
end, end,
}) })
``` ```
In the above snippet, `interact` is listed as a required Nel codice qui in alto, `interact` è elencato come [privilegio](privileges.html) necessario; in altre parole, solo i giocatori che hanno quel privilegio possono usare il comando.
[privilege](privileges.html) meaning that only players with the `interact` privilege can run the command.
Chat commands can return up to two values, I comandi ritornano un massimo di due valori, dove il primo è un booleano che indica l'eventuale successo, mentre il secondo è un messaggio da inviare all'utente.
the first being a Boolean indicating success, and the second being a
message to send to the user.
{% include notice.html notice=page.cmd_online %} {% include notice.html notice=page.cmd_online %}
## Complex Subcommands ## Sottocomandi complessi
It is often required to make complex chat commands, such as: È spesso necessario creare dei comandi complessi, come per esempio:
* `/msg <to> <message>` * `/msg <a> <messaggio>`
* `/team join <teamname>` * `/team entra <nometeam>`
* `/team leave <teamname>` * `/team esci <nometeam>`
* `/team list` * `/team elenco`
This is usually done using [Lua patterns](https://www.lua.org/pil/20.2.html). Questo viene solitamente reso possibile dai [pattern di Lua](https://www.lua.org/pil/20.2.html).
Patterns are a way of extracting stuff from text using rules. I pattern sono un modo di estrapolare "cose" dal testo usando delle regole ben precise.
```lua ```lua
local to, msg = string.match(param, "^([%a%d_-]+) (*+)$") local a, msg = string.match(param, "^([%a%d_-]+) (*+)$")
``` ```
The above code implements `/msg <to> <message>`. Let's go through left to right: Il codice sovrastante implementa `/msg <a> <messaggio>`. Vediamo cos'è successo partendo da sinistra:
* `^` means match the start of the string. * `^` dice di iniziare a combaciare dall'inizio della stringa;
* `()` is a matching group - anything that matches stuff in here will be * `()` è un gruppo - qualsiasi cosa che combaci con ciò che è contenuto al suo interno verrà ritornato da string.match;
returned from string.match. * `[]` significa che i caratteri al suo interno sono accettati;
* `[]` means accept characters in this list. * `%a` significa che accetta ogni lettera e `%d` ogni cifra.
* `%a` means accept any letter and `%d` means accept any digit. * `[%d%a_-]` significa che accetta ogni lettera, cifra, `_` e `-`.
* `[%d%a_-]` means accept any letter or digit or `_` or `-`. * `+` dice di combaciare ciò che lo precede una o più volte.
* `+` means match the thing before one or more times. * `*` dice di combaciare qualsiasi tipo di carattere.
* `*` means match any character in this context. * `$` dice di combaciare la fine della stringa.
* `$` means match the end of the string.
Put simply, the pattern matches the name (a word with only letters/numbers/-/_), Detto semplicemente, il pattern cerca un nome (una parola fatta di lettere, numeri, trattini o trattini bassi), poi uno spazio e poi il messaggio (uno o più caratteri, qualsiasi essi siano).
then a space, then the message (one or more of any character). The name and Vengono poi ritornati nome e messaggio, perché sono inseriti nelle parentesi.
message are returned, because they're surrounded by parentheses.
That's how most mods implement complex chat commands. A better guide to Lua Questo è come molte mod implementano comandi complessi.
Patterns would probably be the Una guida più completa ai pattern è probabilmente quella su [lua-users.org](http://lua-users.org/wiki/PatternsTutorial) o la [documentazione PIL](https://www.lua.org/pil/20.2.html).
[lua-users.org tutorial](http://lua-users.org/wiki/PatternsTutorial)
or the [PIL documentation](https://www.lua.org/pil/20.2.html).
<p class="book_hide"> <p class="book_hide">
There is also a library written by the author of this book which can be used C'è anche una libreria scritta dall'autore di questo libro che può essere usata per creare comandi complessi senza l'utilizzo di pattern: <a href="chat_complex.html">Chat Command Builder</a>.
to make complex chat commands without patterns called
<a href="chat_complex.html">Chat Command Builder</a>.
</p> </p>
## Intercepting Messages ## Intercettare i messaggi
To intercept a message, use register_on_chat_message: Per intercettare un messaggio, si usa `register_on_chat_message`:
```lua ```lua
minetest.register_on_chat_message(function(name, message) minetest.register_on_chat_message(function(name, message)
print(name .. " said " .. message) print(name .. " ha detto " .. message)
return false return false
end) end)
``` ```
By returning false, you allow the chat message to be sent by the default Ritornando false, si permette al messaggio di essere inviato.
handler. You can actually remove the line `return false` and it would still In verità `return false` può anche essere omesso in quanto `nil` verrebbe ritornato implicitamente, e nil è trattato come false.
work the same, because `nil` is returned implicitly and is treated like false.
{% include notice.html notice=page.cb_cmdsprivs %} {% include notice.html notice=page.cb_cmdsprivs %}
You should make sure you take into account that it may be a chat command, Dovresti assicurarti, poi, che il messaggio potrebbe essere un comando che invia messaggi in chat,
or the user may not have `shout`. o che l'utente potrebbere non avere `shout`.
```lua ```lua
minetest.register_on_chat_message(function(name, message) minetest.register_on_chat_message(function(name, message)
if message:sub(1, 1) == "/" then if message:sub(1, 1) == "/" then
print(name .. " ran chat command") print(name .. " ha eseguito un comando")
elseif minetest.check_player_privs(name, { shout = true }) then elseif minetest.check_player_privs(name, { shout = true }) then
print(name .. " said " .. message) print(name .. " ha detto " .. message)
else else
print(name .. " tried to say " .. message .. print(name .. " ha provato a dire " .. message ..
" but doesn't have shout") " ma non ha lo shout")
end end
return false return false

View File

@ -3,178 +3,168 @@ title: Chat Command Builder
layout: default layout: default
root: ../.. root: ../..
idx: 4.3 idx: 4.3
description: Use ChatCmdBuilder to make a complex chat command description: Creazione di comandi complessi semplificandosi la vita
redirect_from: /en/chapters/chat_complex.html redirect_from: /it/chapters/chat_complex.html
--- ---
## Introduction <!-- omit in toc --> ## Introduzione <!-- omit in toc -->
This chapter will show you how to make complex chat commands with ChatCmdBuilder, Questo capitolo ti mostrerà come creare comandi complessi con ChatCmdBuilder, come `/msg <nome> <messaggio>`, `/team entra <nometeam>` or `/team esci <nometeam>`.
such as `/msg <name> <message>`, `/team join <teamname>` or `/team leave <teamname>`.
Note that ChatCmdBuilder is a library created by the author of this book, and most Tieni conto che ChatCmdBuilder è una libreria creata dall'autore di questo libro, e che molti modder tendono a usare il metodo illustrato nel capitolo [Chat e comandi](chat.html#complex-subcommands).
modders tend to use the method outlined in the
[Chat and Commands](chat.html#complex-subcommands) chapter.
- [Why ChatCmdBuilder?](#why-chatcmdbuilder) - [Perché ChatCmdBuilder?](#perche-chatcmdbuilder)
- [Routes](#routes) - [Tratte](#tratte)
- [Subcommand functions](#subcommand-functions) - [Funzioni nei sottocomandi](#funzioni-nei-sottocomandi)
- [Installing ChatCmdBuilder](#installing-chatcmdbuilder) - [Installare ChatCmdBuilder](#installare-chatcmdbuilder)
- [Admin complex command](#admin-complex-command) - [Esempio: comando complesso /admin](#esempio-comando-complesso-admin)
## Why ChatCmdBuilder? ## Perché ChatCmdBuilder?
Traditionally mods implemented these complex commands using Lua patterns. Le mod tradizionali implementano questi comandi complessi usando i pattern Lua.
```lua ```lua
local name = string.match(param, "^join ([%a%d_-]+)") local nome = string.match(param, "^join ([%a%d_-]+)")
``` ```
I, however, find Lua patterns annoying to write and unreadable. Io, tuttavia, trovo i pattern Lua illeggibili e scomodi.
Because of this, I created a library to do this for you. Per via di ciò, ho creato una libreria che ti semplifichi la vita.
```lua ```lua
ChatCmdBuilder.new("sethp", function(cmd) ChatCmdBuilder.new("sethp", function(cmd)
cmd:sub(":target :hp:int", function(name, target, hp) cmd:sub(":target :hp:int", function(name, target, hp)
local player = minetest.get_player_by_name(target) local giocatore = minetest.get_player_by_name(target)
if player then if giocatore then
player:set_hp(hp) giocatore:set_hp(hp)
return true, "Killed " .. target return true, "Gli hp di " .. target .. " sono ora " .. hp
else else
return false, "Unable to find " .. target return false, "Giocatore " .. target .. " non trovato"
end end
end) end)
end, { end, {
description = "Set hp of player", description = "Imposta gli hp del giocatore",
privs = { privs = {
kick = true kick = true
-- ^ probably better to register a custom priv -- ^ è probabilmente meglio impostare un nuovo privilegio
} }
}) })
``` ```
`ChatCmdBuilder.new(name, setup_func, def)` creates a new chat command called `ChatCmdBuilder.new(name, setup_func, def)` crea un nuovo comando chiamato `name`.
`name`. It then calls the function passed to it (`setup_func`), which then creates Poi, chiama la funzione passatagli (`setup_func`), che crea a sua volta i sottocomandi.
subcommands. Each `cmd:sub(route, func)` is a subcommand. Ogni `cmd:sub(route, func)` è un sottocomando.
A subcommand is a particular response to an input param. When a player runs Un sottocomando è una particolare risposta a un parametro di input.
the chat command, the first subcommand that matches their input will be run, Quando un giocatore esegue il comando, il primo sottocomando che combacia con l'input verrà eseguito.
and no others. If no subcommands match, then the user will be told of the invalid Se non ne viene trovato nessuno, il giocatore verrà avvisato della sintassi non valida.
syntax. For example, in the above code snippet if a player Nel codice qui in alto, per esempio, se qualcuno scrive qualcosa come `/sethp nickname 12`, la funzione corrispondente verrà chiamata.
types something of the form `/sethp username 12` then the function passed Tuttavia, qualcosa come `/sethp 12 bleh` genererà un messaggio d'errore.
to cmd:sub will be called. If they type `/sethp 12 bleh`, then a wrong
input message will appear.
`:name :hp:int` is a route. It describes the format of the param passed to /teleport. `:name :hp:int` è una tratta.
Descrive il formato del parametro passato a /teleport.
## Routes ## Tratte
A route is made up of terminals and variables. Terminals must always be there. Una tratta è composta di fermate e variabili, dove le prime sono obbligatorie.
For example, `join` in `/team join :username :teamname`. The spaces also count Una fermata è per esempio `crea` in `/team crea :nometeam :giocatorimassimi:int`, ma anche gli spazi contano come tali.
as terminals.
Variables can change value depending on what the user types. For example, `:username` Le variabili possono cambiare valore a seconda di cosa scrive l'utente. Per esempio `:nometeam` e `:giocatorimassimi:int`.
and `:teamname`.
Variables are defined as `:name:type`. The `name` is used in the help documentation. Le variabili sono definite con `:nome:tipo`: il nome è usato nella documentazione, mentre il tipo è usato per far combaciare l'input.
The `type` is used to match the input. If the type is not given, then the type is Se il tipo non è specificato, allora sarà di base `word`.
`word`.
Valid types are: I tipi consentiti sono:
* `word` - default. Any string without spaces. * `word` - Predefinito. Qualsiasi stringa senza spazi;
* `int` - Any integer/whole number, no decimals. * `int` - Qualsiasi numero intero;
* `number` - Any number, including ints and decimals. * `number` - Qualsiasi numero, decimali inclusi;
* `pos` - 1,2,3 or 1.1,2,3.4567 or (1,2,3) or 1.2, 2 ,3.2 * `pos` - Coordinate. Il formato può essere 1,2,3, o 1.1,2,3.4567, o (1,2,3), o ancora 1.2, 2 ,3.2;
* `text` - Any string. There can only ever be one text variable, * `text` - Qualsiasi stringa, spazi inclusi. Può esserci solo un `text` e non può essere seguito da nient'altro.
no variables or terminals can come afterwards.
In `:name :hp:int`, there are two variables: In `:nome :hp:int`, ci sono due variabili:
* `name` - type of `word` as no type is specified. Accepts any string without spaces. * `name` - di tipo `word` in quanto non è stato specificato
* `hp` - type of `int` * `hp` - di tipo `int`, quindi un numero intero
## Subcommand functions ## Funzioni nei sottocomandi
The first argument is the caller's name. The variables are then passed to the Il primo parametro è il nome di chi invia il comando. Le variabili sono poi passate alla funzione nell'ordine in cui sono state dichiarate.
function in order.
```lua ```lua
cmd:sub(":target :hp:int", function(name, target, hp) cmd:sub(":target :hp:int", function(name, target, hp)
-- subcommand function -- funzione del sottocomando
end) end)
``` ```
## Installing ChatCmdBuilder ## Installare ChatCmdBuilder
The source code can be found and downloaded on Il codice sorgente può essere trovato e scaricato su
[Github](https://github.com/rubenwardy/ChatCmdBuilder/). [Github](https://github.com/rubenwardy/ChatCmdBuilder/).
There are two ways to install: Ci sono due modi per installarlo:
1. Install ChatCmdBuilder as a mod and depend on it. 1. Installarlo come una mod a sé stante;
2. Include the init.lua file in ChatCmdBuilder as chatcmdbuilder.lua in your mod, 2. Includere nella tua mod l'init.lua di ChatCmdBuilder rinominandolo chatcmdbuilder.lua, e integrarlo tramite `dofile`.
and dofile it.
## Admin complex command ## Esempio: comando complesso /admin
Here is an example that creates a chat command that allows us to do this: Segue un esempio che crea un comando che aggiunge le seguenti funzioni per chi ha il permesso `kick` e `ban` (quindi, in teoria, un admin):
* `/admin kill <username>` - kill user * `/admin uccidi <nome>` - uccide un utente;
* `/admin move <username> to <pos>` - teleport user * `/admin sposta <nome> a <pos>` - teletrasporta un utente;
* `/admin log <username>` - show report log * `/admin log <nome>` - mostra il log di un utente;
* `/admin log <username> <message>` - log to report log * `/admin log <nome> <messaggio>` - aggiunge un messaggio al log di un utente.
```lua ```lua
local admin_log local admin_log
local function load() local function carica()
admin_log = {} admin_log = {}
end end
local function save() local function salva()
-- todo -- todo
end end
load() carica()
ChatCmdBuilder.new("admin", function(cmd) ChatCmdBuilder.new("admin", function(cmd)
cmd:sub("kill :name", function(name, target) cmd:sub("uccidi :nome", function(name, target)
local player = minetest.get_player_by_name(target) local giocatore = minetest.get_player_by_name(target)
if player then if giocatore then
player:set_hp(0) giocatore:set_hp(0)
return true, "Killed " .. target return true, "Hai ucciso " .. target
else else
return false, "Unable to find " .. target return false, "Unable to find " .. target
end end
end) end)
cmd:sub("move :name to :pos:pos", function(name, target, pos) cmd:sub("sposta :nome to :pos:pos", function(nome, target, pos)
local player = minetest.get_player_by_name(target) local giocatore = minetest.get_player_by_name(target)
if player then if giocatore then
player:setpos(pos) giocatore:setpos(pos)
return true, "Moved " .. target .. " to " .. return true, "Giocatore " .. target .. " teletrasportato a " ..
minetest.pos_to_string(pos) minetest.pos_to_string(pos)
else else
return false, "Unable to find " .. target return false, "Giocatore " .. target .. " non trovato"
end end
end) end)
cmd:sub("log :username", function(name, target) cmd:sub("log :nome", function(name, target)
local log = admin_log[target] local log = admin_log[target]
if log then if log then
return true, table.concat(log, "\n") return true, table.concat(log, "\n")
else else
return false, "No entries for " .. target return false, "Nessuna voce per " .. target
end end
end) end)
cmd:sub("log :username :message", function(name, target, message) cmd:sub("log :nome :messaggio", function(name, target, messaggio)
local log = admin_log[target] or {} local log = admin_log[target] or {}
table.insert(log, message) table.insert(log, messaggio)
admin_log[target] = log admin_log[target] = log
save() salva()
return true, "Logged" return true, "Aggiunto"
end) end)
end, { end, {
description = "Admin tools", description = "Strumenti per gli admin",
privs = { privs = {
kick = true, kick = true,
ban = true ban = true

View File

@ -1,268 +1,224 @@
--- ---
title: Formspecs title: GUI (Formspec)
layout: default layout: default
root: ../.. root: ../..
idx: 4.5 idx: 4.5
redirect_from: /en/chapters/formspecs.html description: Tempo di interagire con le finestre
minetest510: redirect_from: /it/chapters/formspecs.html
level: warning
title: Real coordinates will be in 5.1.0
classes: web-only
message: This chapter describes the use of a feature that hasn't been released yet.
You can still use this chapter and the code in Minetest 5.0, but elements will
be positioned differently to what is shown.
submit_vuln: submit_vuln:
level: warning level: warning
title: Malicious clients can submit anything at anytime title: Client malevoli possono inviare qualsiasi cosa quando più gli piace
message: You should never trust a formspec submission. A malicious client message: Non dovresti mai fidarti di un modulo di compilazione - anche se non hai mai mostrato loro il formspec.
can submit anything they like at any time - even if you never showed Questo significa che dovresti controllarne i privilegi e assicurarti che dovrebbero effettivamente essere in grado di eseguire quest'azione.
them the formspec. This means that you should check privileges
and make sure that they should be allowed to perform the action.
--- ---
## Introduction <!-- omit in toc --> ## Introduzione <!-- omit in toc -->
<figure class="right_image"> <figure class="right_image">
<img src="{{ page.root }}//static/formspec_example.png" alt="Furnace Inventory"> <img src="{{ page.root }}//static/formspec_example.png" alt="Furnace Inventory">
<figcaption> <figcaption>
Screenshot of furnace formspec, labelled. Screenshot del formspec di una fornace e della sua struttura.
</figcaption> </figcaption>
</figure> </figure>
In this chapter we will learn how to create a formspec and display it to the user. In questo capitolo impareremo come creare un formspec e mostrarlo all'utente.
A formspec is the specification code for a form. Un formspec è il codice di specifica di un modulo (*form*, da qui *form*-*spec*).
In Minetest, forms are windows such as the player inventory and can contain a In Minetest, i moduli sono delle finestre come l'inventario del giocatore e possono contenere un'ampia gamma di elementi, come le etichette, i pulsanti e i campi.
variety of elements, such as labels, buttons and fields.
Note that if you do not need to get user input, for example when you only need Tieni presente che se non si ha bisogno di ricevere input dal giocatore, per esempio quando si vogliono far apparire semplicemente delle istruzioni a schermo, si dovrebbe considerare l'utilizzo di una [HUD (Heads Up Display)](hud.html) piuttosto che quello di un formspec, in quanto le finestre inaspettate (con tanto di mouse che appare) tendono a impattare negativamente sulla giocabilità.
to provide information to the player, you should consider using
[Heads Up Display (HUD)](hud.html) elements instead of forms, because
unexpected windows tend to disrupt gameplay.
- [Real or Legacy Coordinates](#real-or-legacy-coordinates) - [Coordinate reali o datate](#coordinate-reali-o-datate)
- [Anatomy of a Formspec](#anatomy-of-a-formspec) - [Anatomia di un formspec](#anatomia-di-un-formspec)
- [Elements](#elements) - [Elementi](#elementi)
- [Header](#header) - [Intestazione](#intestazione)
- [Guessing Game](#guessing-game) - [Esempio: indovina un numero](#esempio-indovina-un-numero)
- [Padding and Spacing](#padding-and-spacing) - [Imbottitura e spaziatura](#imbottitura-e-spaziatura)
- [Receiving Formspec Submissions](#receiving-formspec-submissions) - [Ricevere i moduli di compilazione](#ricevere-i-moduli-di-compilazione)
- [Contexts](#contexts) - [Contesti](#contesti)
- [Formspec Sources](#formspec-sources) - [Ricavare un formspec](#ricavare-un-formspec)
- [Node Meta Formspecs](#node-meta-formspecs) - [Formspec nei nodi](#formspec-nei-nodi)
- [Player Inventory Formspecs](#player-inventory-formspecs) - [Inventario del giocatore](#inventario-del-giocatore)
- [Your Turn](#your-turn) - [Il tuo turno](#il-tuo-turno)
## Real or Legacy Coordinates ## Coordinate reali o datate
In older versions of Minetest, formspecs were inconsistent. The way that different Nelle vecchie versioni di Minetest, i formspec erano incoerenti.
elements were positioned varied in unexpected ways; it was hard to predict the Il modo in cui elementi diversi venivano posizionati nel formspec variava in maniere inaspettate; era difficile predirne la collocazione e allinearli correttamente.
placement of elements and align them. Minetest 5.1.0 contains a feature Da Minetest 5.1.0, tuttavia, è stata introdotta una funzione chiamata Coordinate Reali (*real coordinates*), la quale punta a correggere questo comportamento tramite l'introduzione di un sistema di coordinate coerente.
called real coordinates which aims to rectify this by introducing a consistent L'uso delle coordinate reali è caldamente consigliato, onde per cui questo capitolo non tratterà di quelle vecchie.
coordinate system. The use of real coordinates is highly recommended, and so
this chapter will use them exclusively.
{% include notice.html notice=page.minetest510 %} ## Anatomia di un formspec
### Elementi
## Anatomy of a Formspec Il formspec è un linguaggio di dominio specifico con un formato insolito.
Consiste in un numero di elementi che seguono il seguente schema:
### Elements tipo[param1;param2]
Formspec is a domain-specific language with an unusual format. Viene prima dichiarato il tipo dell'elemento, seguito dai parametri nelle parentesi quadre.
It consists of a number of elements with the following form: Si possono concatenare più elementi, piazzandoli eventualmente su più linee:
type[param1;param2]
The element type is declared and then any parameters are given
in square brackets. Multiple elements can be joined together, or placed
on multiple lines, like so:
foo[param1]bar[param1] foo[param1]bar[param1]
bo[param1] bo[param1]
Gli elementi sono o oggetti come i campi di testo e i pulsanti, o dei metadati come la grandezza e lo sfondo.
Per una lista esaustiva di tutti i possibili elementi, si rimanda a [lua_api.txt](../../lua_api.html#elements).
Elements are items such as text boxes or buttons, or can be metadata such ### Intestazione
as size or background. You should refer to
[lua_api.txt](https://github.com/minetest/minetest/blob/master/doc/lua_api.txt#L1019)
for a list of all possible elements. Search for "Formspec" to locate the correct
part of the document.
L'intestazione di un formspec contiene informazioni che devono apparire prima di tutto il resto.
Questo include la grandezza del formspec, la posizione, l'ancoraggio, e se il tema specifico del gioco debba venir applicato.
### Header Gli elementi nell'intestazione devono essere definiti in un ordine preciso, altrimenti ritorneranno un errore.
L'ordine è dato nel paragrafo qui in alto e, come sempre, documentato in [lua_api.txt](../../lua_api.html#sizewhfixed_size).
The header of a formspec contains information which must appear first. This La grandezza è in caselle formspec - un'unità di misura che è circa 64 pixel, ma varia a seconda della densità dello schermo e delle impostazioni del client.
includes the size of the formspec, the position, the anchor, and whether the Ecco un formspec di 2x2:
game-wide theme should be applied.
The elements in the header must be defined in a specific order, otherwise you
will see an error. This order is given in the above paragraph, and, as always,
documented in [lua_api.txt](../../lua_api.html#sizewhfixed_size)
The size is in formspec slots - a unit of measurement which is roughly
around 64 pixels, but varies based on the screen density and scaling
settings of the client. Here's a formspec which is `2,2` in size:
formspec_version[3]
size[2,2] size[2,2]
real_coordinates[true]
Notice how we explicitly need to enable the use of the real coordinate system. Notare come è stata esplicitamente definita la versione del linguaggio: senza di essa, il sistema datato sarebbe stato usato di base - che avrebbe impossibilitato il posizionamento coerente degli elementi e altre nuove funzioni.
Without this, the legacy system will instead be used to size the formspec, which will
result in a larger size. This element is a special case, as it is the only element
which may appear both in the header and the body of a formspec. When in the header,
it must appear immediately after the size.
The position and anchor elements are used to place the formspec on the screen. La posizione e l'ancoraggio degli elementi sono usati per collocare il formspec nello schermo.
The position sets where on the screen the formspec will be, and defaults to La posizione imposta dove si troverà (con valore predefinito al centro, `0.5,0.5`), mentre l'ancoraggio da dove partire, permettendo di allineare il formspec con i bordi dello schermo.
the center (`0.5,0.5`). The anchor sets where on the formspec the position is, Per esempio, lo si può posizionare ancorato a sinistra in questo modo:
allowing you to line the formspec up with the edge of the screen. The formspec
can be placed to the left of the screen like so:
formspec_version[3]
size[2,2] size[2,2]
real_coordinates[true] real_coordinates[true]
position[0,0.5] position[0,0.5]
anchor[0,0.5] anchor[0,0.5]
This sets the anchor to the left middle edge of the formspec box, and then the Per l'esattezza è stato messo il centro del formspec sul bordo sinistro dello schermo (`position[0, 0.5]`) e poi ne è stato spostato l'ancoraggio in modo da allineare il lato sinistro del formspec con quello dello schermo.
position of that anchor to the left of the screen.
## Esempio: indovina un numero
## Guessing Game
<figure class="right_image"> <figure class="right_image">
<img src="{{ page.root }}/static/formspec_guessing.png" alt="Guessing Formspec"> <img src="{{ page.root }}/static/formspec_guessing.png" alt="Guessing Formspec">
<figcaption> <figcaption>
The guessing game formspec. Il formspec del gioco dell'indovinare un numero
</figcaption> </figcaption>
</figure> </figure>
The best way to learn is to make something, so let's make a guessing game. Il modo migliore per imparare è sporcarsi le mani, quindi creiamo un gioco.
The principle is simple: the mod decides on a number, then the player makes Il principio è semplice: la mod decide un numero, e il giocatore deve tentare di indovinarlo.
guesses on the number. The mod then says if the guess is higher or lower then La mod, poi, comunica se si è detto un numero più alto o più basso rispetto a quello corretto.
the actual number.
First, let's make a function to create the formspec code. It's good practice to Prima di tutto, costruiamo una funzione per creare il formspec.
do this, as it makes it easier to reuse elsewhere. È buona pratica fare ciò, in quanto rende il riutilizzo più comodo.
<div style="clear: both;"></div> <div style="clear: both;"></div>
```lua ```lua
guessing = {} indovina = {}
function guessing.get_formspec(name) function indovina.prendi_formspec(nome)
-- TODO: display whether the last guess was higher or lower -- TODO: comunicare se il numero del tentativo era più alto o più basso
local text = "I'm thinking of a number... Make a guess!" local testo = "Sto pensando a un numero... Prova a indovinare!"
local formspec = { local formspec = {
"size[6,3.476]", "size[6,3.476]",
"real_coordinates[true]", "label[0.375,0.5;", minetest.formspec_escape(testo), "]",
"label[0.375,0.5;", minetest.formspec_escape(text), "]", "field[0.375,1.25;5.25,0.8;numero;Numero;]",
"field[0.375,1.25;5.25,0.8;number;Number;]", "button[1.5,2.3;3,0.8;indovina;Indovina]"
"button[1.5,2.3;3,0.8;guess;Guess]"
} }
-- table.concat is faster than string concatenation - `..` -- table.concat è più veloce della concatenazione di stringhe - `..`
return table.concat(formspec, "") return table.concat(formspec, "")
end end
``` ```
In the above code, we place a field, a label, and a button. A field allows text Nel codice qui sopra abbiamo inserito un'etichetta (*label*), un campo (*field*) e un pulante (*button*).
entry, and a button is used to submit the form. You'll notice that the elements Un campo ci permete di inserire del testo, mentre useremo il pulsante per inviare il modulo.
are positioned carefully in order to add padding and spacing, this will be explained Noterai che gli elementi sono posizionati attentamente per aggiungere imbottitura e spaziatura (*padding* e *spacing*),
later. ma ci arriveremo tra poco.
Next, we want to allow the player to show the formspec. The main way to do this Come prossima cosa, vogliamo permettere al giocatore di visualizzare il formspec.
is using `show_formspec`: Il metodo principale per farlo è usare `show_formspec`:
```lua ```lua
function guessing.show_to(name) function indovina.mostra_a(nome)
minetest.show_formspec(name, "guessing:game", guessing.get_formspec(name)) minetest.show_formspec(nome, "indovina:gioco", indovina.prendi_formspec(nome))
end end
minetest.register_chatcommand("game", { minetest.register_chatcommand("gioco", {
func = function(name) func = function(name)
guessing.show_to(name) indovina.mostra_a(name)
end, end,
}) })
``` ```
The show_formspec function accepts a player name, the formspec name, and the La funzione `show_formspec` prende il nome del giocatore, il nome del formspec e il formspec stesso.
formspec itself. The formspec name should be a valid itemname, ie: in the format Il nome di quest'ultimo dovrebbe seguire il formato del nome degli oggetti, tipo `nomemod:nomeoggetto`.
`modname:itemname`.
### Imbottitura e spaziatura
### Padding and Spacing
<figure class="right_image"> <figure class="right_image">
<img src="{{ page.root }}/static/formspec_padding_spacing.png" alt="Padding and spacing"> <img src="{{ page.root }}/static/formspec_padding_spacing.png" alt="Padding and spacing">
<figcaption> <figcaption>
The guessing game formspec. Il formspec del gioco dell'indovinare un numero
</figcaption> </figcaption>
</figure> </figure>
Padding is the gap between the edge of the formspec and its contents, or between unrelated L'imbottitura (*padding*) è lo spazio che intercorre tra il bordo del formspec e i suoi contenuti, o tra elementi non in relazione fra loro - mostrato in rosso.
elements, shown in red. Spacing is the gap between related elements, shown in blue. La spaziatura (*spacing*) è invece lo spazio tra elementi in comune - mostrata in blu.
It is fairly standard to have a padding of `0.375` and a spacing of `0.25`. È abbastanza uno standard avere un'imbottitura di `0.375` e una spaziatura di `0.25`.
<div style="clear: both;"></div> <div style="clear: both;"></div>
### Receiving Formspec Submissions ### Ricevere i moduli di compilazione
When `show_formspec` is called, the formspec is sent to the client to be displayed. Quando `show_formspec` viene chiamato, il formspec viene inviato al client per essere visualizzato.
For formspecs to be useful, information needs to be returned from the client to server. Per far sì che i formspec siano utili, le informazioni devono essere ritornate dal client al server.
The method for this is called formspec field submission, and for `show_formspec`, that Il metodo per fare ciò è chiamato Campo di Compilazione (*formspec field submission*), e per `show_formspec` quel campo viene ottenuto usando un callback globale:
submission is received using a global callback:
```lua ```lua
minetest.register_on_player_receive_fields(function(player, formname, fields) minetest.register_on_player_receive_fields(function(player, formname, fields)
if formname ~= "guessing:game" then if formname ~= "indovina:gioco" then
return return
end end
if fields.guess then if fields.indovina then
local pname = player:get_player_name() local p_name = player:get_player_name()
minetest.chat_send_all(pname .. " guessed " .. fields.number) minetest.chat_send_all(p_name .. " ha tentato di indovinare con il numero " .. fields.numero)
end end
end) end)
``` ```
The function given in minetest.register_on_player_receive_fields is called La funzione data in `minetest.register_on_player_receive_fields` è chiamata ogni volta che un utente invia un modulo.
every time a user submits a form. Most callbacks will need to check the formname given La maggior parte dei callback necessiteranno di controllare il nome fornito alla funzione, e uscire se non è quello esatto; tuttavia, alcuni potrebbero necessitare di operare su più moduli, se non addirittura su tutti.
to the function, and exit if it is not the right form; however, some callbacks
may need to work on multiple forms, or on all forms.
The `fields` parameter to the function is a table of the values submitted by the Il parametro `fields` è una tabella di tutti i valori inviati dall'utente, indicizzati per stringhe.
user, indexed by strings. Named elements will appear in the field under their own I nomi degli elementi appariranno nel campo con il loro nome, ma solo se sono rilevanti per l'evento che ha causato l'invio.
name, but only if they are relevent for the event that caused the submission. Per esempio, un elemento "pulsante" apparirà nei campi solo se quel particolare pulsante è stato premuto.
For example, a button element will only appear in fields if that particular button
was pressed.
{% include notice.html notice=page.submit_vuln %} {% include notice.html notice=page.submit_vuln %}
So, now the formspec is sent to the client and the client sends information back. Quindi, ora il formspec è stato inviato al client e il client ritorna quelle informazioni.
The next step is to somehow generate and remember the target value, and to update Il prossimo passaggio è generare e ricordare il valore ricevuto, e aggiornare il formspec basandosi sui tentativi.
the formspec based on guesses. The way to do this is using a concept called Il modo per fare ciò è usare un concetto chiamato "contesto".
"contexts".
### Contexts ### Contesti
In many cases you want minetest.show_formspec to give information In molti casi si può desiderare che le informazioni passate da `show_formspec` al callback non raggiungano il client.
to the callback which you don't want to send to the client. This might include Ciò potrebbe includere con cosa è stato chiamato un comando via chat, o di cosa tratta la finestra di dialogo.
what a chat command was called with, or what the dialog is about. In this case, In questo caso, il valore che si necessita di ricordare.
the target value that needs to be remembered.
A context is a per-player table to store information, and the contexts for all Un contesto (*context*) è una tabella assegnata a ogni giocatore per immagazzinare informazioni, e i contesti di tutti i giocatori sono
online players are stored in a file-local variable: salvati in una variabile locale di file:
```lua ```lua
local _contexts = {} local _contesti = {}
local function get_context(name) local function prendi_contesto(nome)
local context = _contexts[name] or {} local contesto = _contesto[nome] or {}
_contexts[name] = context _contesti[nome] = contesto
return context return contesto
end end
minetest.register_on_leaveplayer(function(player) minetest.register_on_leaveplayer(function(player)
@ -270,83 +226,78 @@ minetest.register_on_leaveplayer(function(player)
end) end)
``` ```
Next, we need to modify the show code to update the context Ora abbiamo bisogno di modificare il codice da mostrare, per aggiornare il contesto prima di mostrare il formspec:
before showing the formspec:
```lua ```lua
function guessing.show_to(name) function indovina.mostra_a(nome)
local context = get_context(name) local contesto = prendi_contesto(nome)
context.target = context.target or math.random(1, 10) contesto.soluzione = contesto.soluzione or math.random(1, 10)
local fs = guessing.get_formspec(name, context) local formspec = indovina.prendi_formspec(nome, contesto)
minetest.show_formspec(name, "guessing:game", fs) minetest.show_formspec(nome, "indovina:gioco", formspec)
end end
``` ```
We also need to modify the formspec generation code to use the context: Abbiamo anche bisogno di modificare la generazione del formspec per usare il contesto:
```lua ```lua
function guessing.get_formspec(name, context) function indovina.prendi_formspec(nome, contesto)
local text local testo
if not context.guess then if not contesto.tentativo then
text = "I'm thinking of a number... Make a guess!" testo = "Sto pensando a un numero... Prova a indovinare!"
elseif context.guess == context.target then elseif contesto.tentativo == contesto.soluzione then
text = "Hurray, you got it!" testo = "Yeee, hai indovinato!"
elseif context.guess > context.target then elseif contesto.tentativo > contesto.soluzione then
text = "To high!" testo = "Troppo alto!"
else else
text = "To low!" testo = "Troppo basso!"
end end
``` ```
Note that it's good practice for get_formspec to only read the context, and not Tieni a mente che quando si ottiene il formspec è buona norma leggerne il contesto, senza però aggiornalo.
update it at all. This can make the function simpler, and also easier to test. Questo può rendere la funzione più semplice, e anche più facile da testare.
And finally, we need to update the handler to update the context with the guess: E in ultimo, abbiamo bisogno di aggiornare il contesto con il tentativo del giocatore:
```lua ```lua
if fields.guess then if fields.indovina then
local name = player:get_player_name() local nome = player:get_player_name()
local context = get_context(name) local contesto = prendi_contesto(nome)
context.guess = tonumber(fields.number) contesto.tentativo = tonumber(fields.numero)
guessing.show_to(name) indovina.mostra_a(nome)
end end
``` ```
## Ricavare un formspec
## Formspec Sources Ci sono tre diversi modi per far sì che un formspec sia consegnato al client:
There are three different ways that a formspec can be delivered to the client: * [show_formspec](#esempio-indovina-un-numero): il metodo usato qui sopra. I campi sono ottenuti tramite `register_on_player_receive_fields`;
* [Metadati di un nodo](#formspec-nei-nodi): si aggiunge il formspec nel nodo tramite metadati, che viene mostrato *immediatamente* al giocatore che preme il nodo col tasto destro.
I campi vengono ricevuti attraverso un metodo nella definizione del nodo chiamato `on_receive_fields`.
* [Inventario del giocatore](#inventario-del-giocatore): il formspec viene inviato al client in un certo momento, e mostrato immediatamente quando il giocatore preme "I".
I campi vengono ricevuti tramite `register_on_player_receive_fields`.
* [show_formspec](#guessing-game): the method used above, fields are received by register_on_player_receive_fields. ### Formspec nei nodi
* [Node Meta Formspecs](#node-meta-formspecs): the node contains a formspec in its meta data, and the client
shows it *immediately* when the player rightclicks. Fields are received by a
method in the node definition called `on_receive_fields`.
* [Player Inventory Formspecs](#player-inventory-formspecs): the formspec is sent to the client at some point, and then
shown immediately when the player presses `i`. Fields are received by
register_on_player_receive_fields.
### Node Meta Formspecs `minetest.show_formspec` non è l'unico modo per mostrare un formspec; essi possono infatti essere aggiunti anche ai [metadati di un nodo](node_metadata.html).
Per esempio, questo è usato con le casse per permettere tempi più veloci d'apertura - non si ha bisogno di aspettare che il server invii il formspec della cassa al giocatore.
minetest.show_formspec is not the only way to show a formspec; you can also
add formspecs to a [node's metadata](node_metadata.html). For example,
this is used with chests to allow for faster opening times -
you don't need to wait for the server to send the player the chest formspec.
```lua ```lua
minetest.register_node("mymod:rightclick", { minetest.register_node("miamod:tastodestro", {
description = "Rightclick me!", description = "Premimi col tasto destro del mouse!",
tiles = {"mymod_rightclick.png"}, tiles = {"miamod_tastodestro.png"},
groups = {cracky = 1}, groups = {cracky = 1},
after_place_node = function(pos, placer) after_place_node = function(pos, placer)
-- This function is run when the chest node is placed. -- Questa funzione è eseguita quando viene piazzato il nodo.
-- The following code sets the formspec for chest. -- Il codice che segue imposta il formspec della cassa.
-- Meta is a way of storing data onto a node. -- I metadati sono un modo per immagazzinare dati nel nodo.
local meta = minetest.get_meta(pos) local meta = minetest.get_meta(pos)
meta:set_string("formspec", meta:set_string("formspec",
"formspec_version[3]" ..
"size[5,5]".. "size[5,5]"..
"label[1,1;This is shown on right click]".. "label[1,1;Questo è mostrato al premere col destro]"..
"field[1,2;2,1;x;x;]") "field[1,2;2,1;x;x;]")
end, end,
on_receive_fields = function(pos, formname, fields, player) on_receive_fields = function(pos, formname, fields, player)
@ -356,30 +307,22 @@ minetest.register_node("mymod:rightclick", {
}) })
``` ```
Formspecs set this way do not trigger the same callback. In order to I formspec impostati in questo modo non innescano lo stesso callback.
receive form input for meta formspecs, you must include an Per far in modo di ricevere il modulo di input per i formspec nei nodi, bisogna includere una voce `on_receive_fields` al registrare il nodo.
`on_receive_fields` entry when registering the node.
This style of callback triggers when you press enter Questo stile di callback viene innescato al premere invio in un campo, che è possibile grazie a `minetest.show_formspec`; tuttavia, questi tipi di moduli possono essere mostrati solo
in a field, which is impossible with `minetest.show_formspec`; tramite il premere col tasto destro del mouse su un nodo. Non è possibile farlo programmaticamente.
however, this kind of form can only be shown by right-clicking on a
node. It cannot be triggered programmatically.
### Player Inventory Formspecs ### Inventario del giocatore
The player inventory formspec is the one shown when the player presses i. L'inventario del giocatore è un formspec, che viene mostrato al premere "I".
The global callback is used to receive events from this formspec, and the Il callback globale viene usato per ricevere eventi dall'inventario, e il suo nome è `""`.
formname is `""`.
There are a number of different mods which allow multiple mods to customise Ci sono svariate mod che permettono ad altrettante mod di personalizzare l'inventario del giocatore.
the player inventory. The officially recommended mod is La mod ufficialmente raccomandata è [Simple Fast Inventory (sfinv)](sfinv.html), ed è inclusa in Minetest Game.
[Simple Fast Inventory (sfinv)](sfinv.html), and is included in Minetest Game.
### Il tuo turno
### Your Turn * Estendi l'indovina il numero per far in modo che tenga traccia del risultato migliore di ogni giocatore, dove con "risultato migliore" si intende il minor numero di tentativi per indovinare.
* Crea un nodo chiamato "Casella delle lettere" dove gli utenti possono aprire un formspec e lasciare messaggi.
* Extend the Guessing Game to keep track of each player's top score, where the Questo nodo dovrebbe salvare il nome del mittente come `owner` nei metadati, e dovrebbe usare `show_formspec` per mostrare formspec differenti a giocatori differenti.
top score is how many guesses it took.
* Make a node called "Inbox" where users can open up a formspec and leave messages.
This node should store the placers' name as `owner` in the meta, and should use
`show_formspec` to show different formspecs to different players.

View File

@ -3,126 +3,116 @@ title: HUD
layout: default layout: default
root: ../.. root: ../..
idx: 4.6 idx: 4.6
redirect_from: /en/chapters/hud.html description: come creare elementi a schermo
redirect_from: /it/chapters/hud.html
--- ---
## Introduction <!-- omit in toc --> ## Introduzione <!-- omit in toc -->
Heads Up Display (HUD) elements allow you to show text, images, and other graphical elements. Le HUD (Heads Up Display) ti permettono di mostrare testi, immagini e altri elementi grafici senza interrompere il giocatore.
Le HUD, infatti, non accettano input dall'utente, lasciando quel ruolo ai [formspec](formspecs.html).
The HUD doesn't accept user input; for that, you should use a [formspec](formspecs.html). - [Posizionamento](#posizionamento)
- [Posizione e scostamento](#posizione-e-scostamento)
- [Allineamento](#allineamento)
- [Esempio: tabellone segnapunti](#esempio-tabellone-segnapunti)
- [Elementi di testo](#elementi-di-testo)
- [Parametri](#parametri)
- [Tornando all'esempio](#tornando-all-esempio)
- [Elementi immagine](#elementi-immagine)
- [Parametri](#parametri-1)
- [Tornando all'esempio](#tornando-all-esempio-1)
- [Cambiare un elemento](#cambiare-un-elemento)
- [Salvare gli ID](#salvare-gli-id)
- [Altri elementi](#altri-elementi)
- [Positioning](#positioning) ## Posizionamento
- [Position and Offset](#position-and-offset)
- [Alignment](#alignment)
- [Scoreboard](#scoreboard)
- [Text Elements](#text-elements)
- [Parameters](#parameters)
- [Our Example](#our-example)
- [Image Elements](#image-elements)
- [Parameters](#parameters-1)
- [Scale](#scale)
- [Changing an Element](#changing-an-element)
- [Storing IDs](#storing-ids)
- [Other Elements](#other-elements)
## Positioning ### Posizione e scostamento
### Position and Offset
<figure class="right_image"> <figure class="right_image">
<img <img
width="300" width="300"
src="{{ page.root }}//static/hud_diagram_center.svg" src="{{ page.root }}//static/hud_diagram_center.svg"
alt="Diagram showing a centered text element"> alt="Diagramma che mostra un elemento di testo centrato">
</figure> </figure>
Screens come in a variety of different physical sizes and resolutions, and Essendoci schermi di tutte le dimensioni e risoluzioni, per funzionare bene le HUD devono sapersi adattare a ognuno di essi.
the HUD needs to work well on all screen types.
Minetest's solution to this is to specify the location of an element using both Per ovviare al problema, Minetest specifica il collocamento di un elemento usando sia una posizione in percentuale che uno scostamento (*offset*).
a percentage position and an offset. La posizione percentuale è relativa alla grandezza dello schermo, dacché per posizionarne un elemento al centro, bisogna fornire un valore di 0.5 (cioè il 50%).
The percentage position is relative to the screen size, so to place an element
in the centre of the screen, you would need to provide a percentage position of half
the screen, e.g. (50%, 50%), and an offset of (0, 0).
The offset is then used to move an element relative to the percentage position. Lo scostamento è poi usato per - appunto - scostare un elemento in relazione alla sua posizione.
<div style="clear:both;"></div> <div style="clear:both;"></div>
### Alignment ### Allineamento
Alignment is where the result of position and offset is on the element - L'allineamento (*alignment*) è dove il risultato della posizione e dello scostamento viene applicato sull'elemento - per esempio, `{x = -1.0, y = 0.0}` allineerà i valori degli altri due parametri sulla sinistra dell'elemento.
for example, `{x = -1.0, y = 0.0}` will make the result of position and offset point Questo è particolarmente utile quando si vuole allineare del testo a sinistra, a destra o al centro.
to the left of the element's bounds. This is particularly useful when you want to
make a text element aligned to the left, centre, or right.
<figure> <figure>
<img <img
width="500" width="500"
src="{{ page.root }}//static/hud_diagram_alignment.svg" src="{{ page.root }}//static/hud_diagram_alignment.svg"
alt="Diagram showing alignment"> alt="Diagramma che mostra i vari tipi di allineamento">
</figure> </figure>
The above diagram shows 3 windows (blue), each with a single HUD element (yellow) Il diagramma qui in alto mostra mostra tre finestre (in blu), ognuna contenente un elemento HUD (in giallo) con ogni volta un allineamento diverso.
and a different alignment each time. The arrow is the result of the position La freccia è il risultato del calcolo di posizione e scostamento.
and offset calculation.
### Scoreboard ### Esempio: tabellone segnapunti
For the purposes of this chapter, you will learn how to position and update a Per capire meglio il capitolo, vedremo come posizionare e aggiornare un pannello contenente dei punti come questo:
score panel like so:
<figure> <figure>
<img <img
src="{{ page.root }}//static/hud_final.png" src="{{ page.root }}//static/hud_final.png"
alt="screenshot of the HUD we're aiming for"> alt="Screenshot dell'HUD da realizzare">
</figure> </figure>
In the above screenshot, all the elements have the same percentage position Nello screenshot sovrastante, tutti gli elementi hanno la stessa posizione percentuale (100%, 50%) - ma scostamenti diversi.
(100%, 50%) - but different offsets. This allows the whole thing to be anchored Questo permette all'intero pannello di essere ancorato sulla destra della finestra, senza posizioni/scostamenti strani al ridimensionarla.
to the right of the window, but to resize without breaking.
## Text Elements ## Elementi di testo
You can create a HUD element once you have a copy of the player object: Puoi creare un elemento HUD una volta ottenuto il riferimento al giocatore al quale assegnarla:
```lua ```lua
local player = minetest.get_player_by_name("username") local giocatore = minetest.get_player_by_name("tizio")
local idx = player:hud_add({ local idx = giocatore:hud_add({
hud_elem_type = "text", hud_elem_type = "text",
position = {x = 0.5, y = 0.5}, position = {x = 0.5, y = 0.5},
offset = {x = 0, y = 0}, offset = {x = 0, y = 0},
text = "Hello world!", text = "Ciao mondo!",
alignment = {x = 0, y = 0}, -- center aligned alignment = {x = 0, y = 0}, -- allineamento centrato
scale = {x = 100, y = 100}, -- covered later scale = {x = 100, y = 100}, -- lo vedremo tra poco
}) })
``` ```
The `hud_add` function returns an element ID - this can be used later to modify La funzione `hud_add` ritorna l'ID di un elemento, che è utile per modificarlo o rimuoverlo.
or remove a HUD element.
### Parameters ### Parametri
The element's type is given using the `hud_elem_type` property in the definition Il tipo dell'elemento è ottenuto usando la proprietà `hud_elem_type` nella tabella di definizione.
table. The meaning of other properties varies based on this type. Cambiando il tipo, cambia il significato di alcune delle proprietà che seguono.
`scale` is the maximum bounds of text; text outside these bounds is cropped, e.g.: `{x=100, y=100}`. `scale` sono i limiti del testo; se esce da questo spazio, viene tagliato - nell'esempio `{x=100, y=100}`.
`number` is the text's colour, and is in [hexadecimal form](http://www.colorpicker.com/), e.g.: `0xFF0000`. `number` è il colore del testo, ed è in [formato esadecimale](http://www.colorpicker.com/) - nell'esempio `0xFF0000`.
### Our Example ### Tornando all'esempio
Let's go ahead and place all the text in our score panel: Andiamo avanti e piazziamo tutto il testo nel nostro pannello (si son tenute le stringhe in inglese per non confondere con l'immagine, NdT):
```lua ```lua
-- Get the dig and place count from storage, or default to 0 -- Ottiene il numero di blocchi scavati e piazzati dallo spazio d'archiviazione; se non esiste è 0
local meta = player:get_meta() local meta = giocatore:get_meta()
local digs_text = "Digs: " .. meta:get_int("score:digs") local digs_testo = "Digs: " .. meta:get_int("punteggio:digs")
local places_text = "Places: " .. meta:get_int("score:places") local places_testo = "Places: " .. meta:get_int("punteggio:places")
player:hud_add({ giocatore:hud_add({
hud_elem_type = "text", hud_elem_type = "text",
position = {x = 1, y = 0.5}, position = {x = 1, y = 0.5},
offset = {x = -120, y = -25}, offset = {x = -120, y = -25},
@ -132,162 +122,160 @@ player:hud_add({
number = 0xFFFFFF, number = 0xFFFFFF,
}) })
player:hud_add({ giocatore:hud_add({
hud_elem_type = "text", hud_elem_type = "text",
position = {x = 1, y = 0.5}, position = {x = 1, y = 0.5},
offset = {x = -180, y = 0}, offset = {x = -180, y = 0},
text = digs_text, text = digs_testo,
alignment = -1, alignment = -1,
scale = { x = 50, y = 10}, scale = { x = 50, y = 10},
number = 0xFFFFFF, number = 0xFFFFFF,
}) })
player:hud_add({ giocatore:hud_add({
hud_elem_type = "text", hud_elem_type = "text",
position = {x = 1, y = 0.5}, position = {x = 1, y = 0.5},
offset = {x = -70, y = 0}, offset = {x = -70, y = 0},
text = places_text, text = places_testo,
alignment = -1, alignment = -1,
scale = { x = 50, y = 10}, scale = { x = 50, y = 10},
number = 0xFFFFFF, number = 0xFFFFFF,
}) })
``` ```
This results in the following: Il risultato è il seguente:
<figure> <figure>
<img <img
src="{{ page.root }}//static/hud_text.png" src="{{ page.root }}//static/hud_text.png"
alt="screenshot of the HUD we're aiming for"> alt="Screenshot della HUD finora">
</figure> </figure>
## Image Elements ## Elementi immagine
Image elements are created in a very similar way to text elements: Le immagini sono create in un modo molto simile a quelli del testo:
```lua ```lua
player:hud_add({ player:hud_add({
hud_elem_type = "image", hud_elem_type = "image",
position = {x = 1, y = 0.5}, position = {x = 1, y = 0.5},
offset = {x = -220, y = 0}, offset = {x = -220, y = 0},
text = "score_background.png", text = "punteggio_sfondo.png",
scale = { x = 1, y = 1}, scale = { x = 1, y = 1},
alignment = { x = 1, y = 0 }, alignment = { x = 1, y = 0 },
}) })
``` ```
You will now have this: Siamo ora a questo punto:
<figure> <figure>
<img <img
src="{{ page.root }}//static/hud_background_img.png" src="{{ page.root }}//static/hud_background_img.png"
alt="screenshot of the HUD so far"> alt="Screenshot della HUD finora">
</figure> </figure>
### Parameters ### Parametri
The `text` field is used to provide the image name. Il campo `text` in questo caso viene usato per fornire il nome dell'immagine.
If a co-ordinate is positive, then it is a scale factor with 1 being the Se una coordinata in `scale` è positiva, allora è un fattore scalare dove 1 è la grandezza originale, 2 è il doppio e così via.
original image size, 2 being double the size, and so on. Tuttavia, se una coordinata è negativa, sarà la percentuale della grandezza dello schermo.
However, if a co-ordinate is negative, it is a percentage of the screen size. Per esempio, `x=-100` equivale al 100% della larghezza di quest'ultimo.
For example, `x=-100` is 100% of the width.
### Scale ### Tornando all'esempio
Let's make the progress bar for our score panel as an example of scale: Creiamo la barra di progresso per il nostro tabellone usando `scale`:
```lua ```lua
local percent = tonumber(meta:get("score:score") or 0.2) local percentuale = tonumber(meta:get("punteggio:score") or 0.2)
player:hud_add({ giocatore:hud_add({
hud_elem_type = "image", hud_elem_type = "image",
position = {x = 1, y = 0.5}, position = {x = 1, y = 0.5},
offset = {x = -215, y = 23}, offset = {x = -215, y = 23},
text = "score_bar_empty.png", text = "barra_punteggio_vuota.png",
scale = { x = 1, y = 1}, scale = { x = 1, y = 1},
alignment = { x = 1, y = 0 }, alignment = { x = 1, y = 0 },
}) })
player:hud_add({ giocatore:hud_add({
hud_elem_type = "image", hud_elem_type = "image",
position = {x = 1, y = 0.5}, position = {x = 1, y = 0.5},
offset = {x = -215, y = 23}, offset = {x = -215, y = 23},
text = "score_bar_full.png", text = "barra_punteggio_piena.png",
scale = { x = percent, y = 1}, scale = { x = percentuale, y = 1},
alignment = { x = 1, y = 0 }, alignment = { x = 1, y = 0 },
}) })
``` ```
We now have a HUD that looks like the one in the first post! Abbiamo ora una HUD uguale identica a quella della prima immagine!
There is one problem however, it won't update when the stats change. C'è un problema, tuttavia: non si aggiornerà al cambiare delle statistiche.
## Changing an Element ## Cambiare un elemento
You can use the ID returned by the hud_add method to update it or remove it later. Per cambiare un elemento si usa l'ID ritornato dal metodo `hud_add`.
```lua ```lua
local idx = player:hud_add({ local idx = giocatore:hud_add({
hud_elem_type = "text", hud_elem_type = "text",
text = "Hello world!", text = "Ciao mondo!",
-- parameters removed for brevity -- parametri rimossi per brevità
}) })
player:hud_change(idx, "text", "New Text") giocatore:hud_change(idx, "text", "Nuovo testo")
player:hud_remove(idx) giocatore:hud_remove(idx)
``` ```
The `hud_change` method takes the element ID, the property to change, and the new Il metodo `hud_change` prende l'ID dell'elemento, la proprietà da cambiare e il nuovo valore.
value. The above call changes the `text` property from "Hello World" to "Test". La chiamata qui sopra cambia la proprietà `text` da "Ciao mondo!" a "Nuovo test".
This means that doing the `hud_change` immediately after the `hud_add` is Questo significa che fare `hud_change` subito dopo `hud_add` è funzionalmente equivalente a
functionally equivalent to the following, in a rather inefficient way: fare ciò che segue, in maniera alquanto inefficiente:
```lua ```lua
local idx = player:hud_add({ local idx = giocatore:hud_add({
hud_elem_type = "text", hud_elem_type = "text",
text = "New Text", text = "Nuovo testo",
}) })
``` ```
## Storing IDs ## Salvare gli ID
```lua ```lua
score = {} local hud_salvate = {}
local saved_huds = {}
function score.update_hud(player) function punteggio.aggiorna_hud(giocatore)
local player_name = player:get_player_name() local nome_giocatore = giocatore:get_player_name()
-- Get the dig and place count from storage, or default to 0 -- Ottiene il numero di blocchi scavati e piazzati dallo spazio d'archiviazione; se non esiste è 0
local meta = player:get_meta() local meta = giocatore:get_meta()
local digs_text = "Digs: " .. meta:get_int("score:digs") local digs_testo = "Digs: " .. meta:get_int("punteggio:digs")
local places_text = "Places: " .. meta:get_int("score:places") local places_testo = "Places: " .. meta:get_int("punteggio:places")
local percent = tonumber(meta:get("score:score") or 0.2) local percentuale = tonumber(meta:get("punteggio:score") or 0.2)
local ids = saved_huds[player_name] local ids = hud_salvate[nome_giocatore]
if ids then if ids then
player:hud_change(ids["places"], "text", places_text) giocatore:hud_change(ids["places"], "text", places_testo)
player:hud_change(ids["digs"], "text", digs_text) giocatore:hud_change(ids["digs"], "text", digs_testo)
player:hud_change(ids["bar_foreground"], giocatore:hud_change(ids["bar_foreground"],
"scale", { x = percent, y = 1 }) "scale", { x = percentuale, y = 1 })
else else
ids = {} ids = {}
saved_huds[player_name] = ids hud_salvate[player_name] = ids
-- create HUD elements and set ids into `ids` -- crea gli elementi HUD e imposta gli ID in `ids`
end end
end end
minetest.register_on_joinplayer(score.update_hud) minetest.register_on_joinplayer(punteggio.aggiorna_hud)
minetest.register_on_leaveplayer(function(player) minetest.register_on_leaveplayer(function(player)
saved_huds[player:get_player_name()] = nil hud_salvate[player:get_player_name()] = nil
end) end)
``` ```
## Other Elements ## Altri elementi
Read [lua_api.txt]({{ page.root }}/lua_api.html#hud-element-types) for a complete list of HUD elements. Dai un occhio a [lua_api.txt]({{ page.root }}/lua_api.html#hud-element-types) per una lista completa degli elementi HUD.

View File

@ -1,76 +1,64 @@
--- ---
title: Player Physics title: Fisica del giocatore
layout: default layout: default
root: ../.. root: ../..
idx: 4.4 idx: 4.4
redirect_from: /en/chapters/player_physics.html redirect_from: /it/chapters/player_physics.html
--- ---
## Introduction <!-- omit in toc --> ## Introduzione <!-- omit in toc -->
Player physics can be modified using physics overrides. La fisica del giocatore può essere modificata usando le sovrascritture apposite (*physics ovverrides*).
Physics overrides can set the walking speed, jump speed, Esse sono dei moltiplicatori che servono per impostare la velocità di movimento, del salto, o la gravità del singolo giocatore.
and gravity constants. Per esempio, un valore di 2 sulla gravità, renderà la gravità di un utente due volte più forte.
Physics overrides are set on a player-by-player basis
and are multipliers.
For example, a value of 2 for gravity would make gravity twice as strong.
- [Basic Example](#basic-example) - [Esempio base](#esempio-base)
- [Available Overrides](#available-overrides) - [Sovrascritture disponibili](#sovrascritture-disponibili)
- [Old Movement Behaviour](#old-movement-behaviour) - [Vecchio sistema di movimento](#vecchio-sistema-di-movimento)
- [Mod Incompatibility](#mod-incompatibility) - [Incompatibilità tra mod](#incompatibilita-tra-mod)
- [Your Turn](#your-turn) - [Il tuo turno](#il-tuo-turno)
## Basic Example ## Esempio base
Here is an example of how to add an antigravity command, which Segue l'esempio di un comando di antigravità:
puts the caller in low G:
```lua ```lua
minetest.register_chatcommand("antigravity", { minetest.register_chatcommand("antigrav", {
func = function(name, param) func = function(name, param)
local player = minetest.get_player_by_name(name) local giocatore = minetest.get_player_by_name(name)
player:set_physics_override({ giocatore:set_physics_override({
gravity = 0.1, -- set gravity to 10% of its original value gravity = 0.1, -- imposta la gravità al 10% del suo valore originale
-- (0.1 * 9.81) -- (0.1 * 9.81)
}) })
end, end,
}) })
``` ```
## Available Overrides ## Sovrascritture disponibili
`player:set_physics_override()` is given a table of overrides.\\ `set_physics_override()` è una tabella. Stando a [lua_api.txt]({{ page.root }}/lua_api.html#player-only-no-op-for-other-objects), le chiavi possono essere:
According to [lua_api.txt]({{ page.root }}/lua_api.html#player-only-no-op-for-other-objects),
these can be:
* speed: multiplier to default walking speed value (default: 1) * `speed`: moltiplicatore della velocità di movimento (predefinito: 1)
* jump: multiplier to default jump value (default: 1) * `jump`: moltiplicatore del salto (predefinito: 1)
* gravity: multiplier to default gravity value (default: 1) * `gravity`: moltiplicatore della gravità (predefinito: 1)
* sneak: whether the player can sneak (default: true) * `sneak`: se il giocatore può camminare di soppiatto o meno (predefinito: true)
### Old Movement Behaviour ### Vecchio sistema di movimento
Player movement prior to the 0.4.16 release included the sneak glitch, which Il movimento dei giocatori prima della versione 0.4.16 includeva il cosiddetto *sneak glitch*, il quale permetteva vari glitch di movimento come l'abilità di scalare un "ascensore" fatta di certi blocchi premendo shift (la camminata di soppiatto) e salto. Nonostante non fosse una funzionalità voluta, è stata mantenuta nelle sovrascritture dato il suo uso in molti server.
allows various movement glitches, including the ability
to climb an 'elevator' made from a certain placement of nodes by sneaking
(pressing shift) and pressing space to ascend. Though the behaviour was
unintended, it has been preserved in overrides due to its use on many servers.
Two overrides are needed to fully restore old movement behaviour: Per ripristinare del tutto questo comportamento servono due chiavi:
* new_move: whether the player uses new movement (default: true) * `new_move`: se usare o meno il nuovo sistema di movimento (predefinito: true)
* sneak_glitch: whether the player can use 'sneak elevators' (default: false) * `sneak_glitch`: se il giocatore può usare o meno il glitch dell'ascensore (default: false)
## Mod Incompatibility ## Incompatibilità tra mod
Please be warned that mods which override the same physics value of a player tend Tieni a mente che le mod che sovrascrivono la stessa proprietà fisica di un giocatore tendono a essere incompatibili tra di loro.
to be incompatible with each other. When setting an override, it overwrites Quando si imposta una sovrascrittura, sovrascriverà qualsiasi altro suo simile impostato in precedenza: ciò significa che se la velocità di movimento di un giocatore viene cambiata più volte, solo l'ultimo valore verrà preso in considerazione.
any overrides that have been set before. This means that if multiple overrides set a
player's speed, only the last one to run will be in effect.
## Your Turn ## Il tuo turno
* **Sonic**: Set the speed multiplier to a high value (at least 6) when a player joins the game. * **Sonic**: Imposta il moltiplicatore di velocità a un valore elevato (almeno 6) quando un giocatore entra in gioco;
* **Super bounce**: Increase the jump value so that the player can jump 20 metres (1 metre is 1 node). * **Super rimbalzo**: Aumenta il valore del salto in modo che il giocatore possa saltare 20 metri (1 cubo = 1 metro);
* **Space**: Make gravity decrease as the player gets higher. * **Space**: Fai in modo che la gravità diminuisca man mano che si sale di altitudine.

View File

@ -1,156 +1,146 @@
--- ---
title: "SFINV: Inventory Formspec" title: "SFINV"
layout: default layout: default
root: ../.. root: ../..
idx: 4.7 idx: 4.7
redirect_from: /en/chapters/sfinv.html description: una mod per rendere più semplice la creazione di un inventario complesso
redirect_from: /it/chapters/sfinv.html
--- ---
## Introduction <!-- omit in toc --> ## Introduzione <!-- omit in toc -->
Simple Fast Inventory (SFINV) is a mod found in Minetest Game that is used to Simple Fast Inventory (SFINV) è una mod presente in Minetest Game, usata per creare il [formspec](formspecs.html) del giocatore.
create the player's inventory [formspec](formspecs.html). SFINV comes with SFINV ha un'API che permette di aggiungere e altresì gestire le pagine mostrate.
an API that allows you to add and otherwise manage the pages shown.
Whilst SFINV by default shows pages as tabs, pages are called pages Mentre SFINV di base mostra le pagine come finestre, le pagine sono chiamate tali in quanto è assolutamente possibile che una mod o un gioco decidano di mostrarle in un altro formato.
because it is entirely possible that a mod or game decides to show them in Per esempio, più pagine possono essere mostrate nel medesimo formspec.
some other format instead.
For example, multiple pages could be shown in one formspec.
- [Registering a Page](#registering-a-page) - [Registrare una pagina](#registrare-una-pagina)
- [Receiving events](#receiving-events) - [Ricevere eventi](#ricevere-eventi)
- [Conditionally showing to players](#conditionally-showing-to-players) - [Condizioni per la visualizzazione](#condizioni-per-la-visualizzazione)
- [on_enter and on_leave callbacks](#onenter-and-onleave-callbacks) - [Callback on_enter e on_leave](#callback-onenter-e-onleave)
- [Adding to an existing page](#adding-to-an-existing-page) - [Aggiungere a una pagina esistente](#aggiungere-a-una-pagina-esistente)
## Registering a Page ## Registrare una pagina
SFINV provides the aptly named `sfinv.register_page` function to create pages. SFINV fornisce la funzione chiamata `sfinv.register_page` per creare nuove pagine.
Simply call the function with the page's name and its definition: Basta chiamare la funzione con il nome che si vuole assegnare alla pagina e la sua definizione:
```lua ```lua
sfinv.register_page("mymod:hello", { sfinv.register_page("miamod:ciao", {
title = "Hello!", title = "Ciao!",
get = function(self, player, context) get = function(self, player, context)
return sfinv.make_formspec(player, context, return sfinv.make_formspec(player, context,
"label[0.1,0.1;Hello world!]", true) "label[0.1,0.1;Ciao mondo!]", true)
end end
}) })
``` ```
The `make_formspec` function surrounds your formspec with SFINV's formspec code. La funzione `make_formspec` circonda il formspec con il codice di SFINV.
The fourth parameter, currently set as `true`, determines whether the Il quarto parametro, attualmente impostato a `true`, determina se l'inventario del giocatore è mostrato.
player's inventory is shown.
Let's make things more exciting; here is the code for the formspec generation Rendiamo le cose più eccitanti; segue il codice della generazione di un formspec per gli admin.
part of a player admin tab. This tab will allow admins to kick or ban players by Questa finestra permetterà agli admin di cacciare o bannare i giocatori selezionandoli da una lista e premendo un pulsante.
selecting them in a list and clicking a button.
```lua ```lua
sfinv.register_page("myadmin:myadmin", { sfinv.register_page("mioadmin:mioadmin", {
title = "Tab", title = "Finestra",
get = function(self, player, context) get = function(self, player, context)
local players = {} local giocatori = {}
context.myadmin_players = players context.mioadmin_giocatori = giocatori
-- Using an array to build a formspec is considerably faster -- Usare un array per costruire un formspec è decisamente più veloce
local formspec = { local formspec = {
"textlist[0.1,0.1;7.8,3;playerlist;" "textlist[0.1,0.1;7.8,3;lista_giocatori;"
} }
-- Add all players to the text list, and to the players list -- Aggiunge tutti i giocatori sia alla lista testuale che a quella - appunto - dei giocatori
local is_first = true local primo = true
for _ , player in pairs(minetest.get_connected_players()) do for _ , giocatore in pairs(minetest.get_connected_players()) do
local player_name = player:get_player_name() local nome_giocatore = giocatore:get_player_name()
players[#players + 1] = player_name giocatori[#giocatori + 1] = nome_giocatore
if not is_first then if not primo then
formspec[#formspec + 1] = "," formspec[#formspec + 1] = ","
end end
formspec[#formspec + 1] = formspec[#formspec + 1] =
minetest.formspec_escape(player_name) minetest.formspec_escape(nome_giocatore)
is_first = false primo = false
end end
formspec[#formspec + 1] = "]" formspec[#formspec + 1] = "]"
-- Add buttons -- Aggiunge i pulsanti
formspec[#formspec + 1] = "button[0.1,3.3;2,1;kick;Kick]" formspec[#formspec + 1] = "button[0.1,3.3;2,1;caccia;Caccia]"
formspec[#formspec + 1] = "button[2.1,3.3;2,1;ban;Kick + Ban]" formspec[#formspec + 1] = "button[2.1,3.3;2,1;banna;Caccia e Banna]"
-- Wrap the formspec in sfinv's layout -- Avvolge il formspec nella disposizione di SFINV
-- (ie: adds the tabs and background) -- (es: aggiunge le linguette delle finestre e lo sfondo)
return sfinv.make_formspec(player, context, return sfinv.make_formspec(player, context,
table.concat(formspec, ""), false) table.concat(formspec, ""), false)
end, end,
}) })
``` ```
There's nothing new about the above code; all the concepts are Non c'è niente di nuovo in questa parte di codice; tutti i concetti sono già stati trattati o qui in alto o nei precedenti capitoli.
covered above and in previous chapters.
<figure> <figure>
<img src="{{ page.root }}//static/sfinv_admin_fs.png" alt="Player Admin Page"> <img src="{{ page.root }}//static/sfinv_admin_fs.png" alt="Pagina per gli amministratori">
</figure> </figure>
## Receiving events ## Ricevere eventi
You can receive formspec events by adding a `on_player_receive_fields` function Puoi ricevere eventi formspec tramite l'aggiunta della funzione `on_player_receive_fields` nella definizione SFINV.
to a sfinv definition.
```lua ```lua
on_player_receive_fields = function(self, player, context, fields) on_player_receive_fields = function(self, player, context, fields)
-- TODO: implement this -- TODO: implementarlo
end, end,
``` ```
`on_player_receive_fields` works the same as `on_player_receive_fields` funziona alla stessa maniera di `minetest.register_on_player_receive_fields`, con la differenza che viene richiesto il contesto al posto del nome del form.
`minetest.register_on_player_receive_fields`, except that `context` is Tieni a mente che gli eventi interni di SFINV, come la navigazione tra le varie finestre, vengono gestiti dentro la mod stessa, e che quindi non verranno ricevuti in questo callback.
given instead of `formname`.
Please note that SFINV will consume events relevant to itself, such as
navigation tab events, so you won't receive them in this callback.
Now let's implement the `on_player_receive_fields` for our admin mod: Implementiamo ora `on_player_receive_fields` nella mod:
```lua ```lua
on_player_receive_fields = function(self, player, context, fields) on_player_receive_fields = function(self, player, context, fields)
-- text list event, check event type and set index if selection changed -- evento della lista testuale: controlla il tipo di evento e imposta il nuovo indice se è cambiata la selezione
if fields.playerlist then if fields.lista_giocatori then
local event = minetest.explode_textlist_event(fields.playerlist) local event = minetest.explode_textlist_event(fields.lista_giocatori)
if event.type == "CHG" then if event.type == "CHG" then
context.myadmin_selected_idx = event.index context.mioadmin_sel_id = event.index
end end
-- Kick button was pressed -- Al premere "Caccia"
elseif fields.kick then elseif fields.caccia then
local player_name = local nome_giocatore =
context.myadmin_players[context.myadmin_selected_idx] context.myadmin_players[context.mioadmin_sel_id]
if player_name then if player_name then
minetest.chat_send_player(player:get_player_name(), minetest.chat_send_player(player:get_player_name(),
"Kicked " .. player_name) "Cacciato " .. nome_giocatore)
minetest.kick_player(player_name) minetest.kick_player(nome_giocatore)
end end
-- Ban button was pressed -- Al premere "Caccia e Banna"
elseif fields.ban then elseif fields.banna then
local player_name = local nome_giocatore =
context.myadmin_players[context.myadmin_selected_idx] context.myadmin_players[context.mioadmin_sel_id]
if player_name then if player_name then
minetest.chat_send_player(player:get_player_name(), minetest.chat_send_player(player:get_player_name(),
"Banned " .. player_name) "Banned " .. player_name)
minetest.ban_player(player_name) minetest.ban_player(nome_giocatore)
minetest.kick_player(player_name, "Banned") minetest.kick_player(nome_giocatore, "Banned")
end end
end end
end, end,
``` ```
There's a rather large problem with this, however. Anyone can kick or ban players! You C'è, tuttavia, un problema abbastanza grande a riguardo: chiunque può cacciare o bannare i giocatori!
need a way to only show this to players with the kick or ban privileges. C'è bisogno di un modo per mostrare questa finestra solo a chi ha i privilegi `kick` e `ban`.
Luckily SFINV allows you to do this! Fortunatamente, SFINV ci permette di farlo!
## Conditionally showing to players ## Condizioni per la visualizzazione
You can add an `is_in_nav` function to your page's definition if you'd like to Si può aggiungere una funzione `is_in_nav` nella definizione della pagina se si desidera gestire quando la pagina deve essere mostrata:
control when the page is shown:
```lua ```lua
is_in_nav = function(self, player, context) is_in_nav = function(self, player, context)
@ -159,54 +149,46 @@ is_in_nav = function(self, player, context)
end, end,
``` ```
If you only need to check one priv or want to perform an 'and', you should use Se si ha bisogno di controllare un solo privilegio o si vuole eseguire un `and`, si bisognerebbe usare `minetest.check_player_privs()` al posto di `get_player_privs`.
`minetest.check_player_privs()` instead of `get_player_privs`.
Note that the `is_in_nav` is only called when the player's inventory formspec is Tieni a mente che `is_in_nav` viene chiamato soltanto alla generazione dell'inventario del giocatore.
generated. This happens when a player joins the game, switches tabs, or a mod Questo succede quando un giocatore entra in gioco, si muove tra le finestre, o una mod richiede a SFINV di rigenerare l'inventario.
requests for SFINV to regenerate.
This means that you need to manually request that SFINV regenerates the inventory Ciò significa che hai bisogno di richiedere manualmente la rigenerazione del formspec dell'inventario per ogni evento che potrebbe cambiare il risultato ti `is_in_nav`.
formspec on any events that may change `is_in_nav`'s result. In our case, Nel nostro caso, abbiamo bisogno di farlo ogni volta che i permessi `kick` o `ban` vengono assegnati/revocati a un giocatore:
we need to do that whenever kick or ban is granted or revoked to a player:
```lua ```lua
local function on_grant_revoke(grantee, granter, priv) local function al_cambio_privilegi(nome_target, nome_garante, priv)
if priv ~= "kick" and priv ~= "ban" then if priv ~= "kick" and priv ~= "ban" then
return return
end end
local player = minetest.get_player_by_name(grantee) local giocatore = minetest.get_player_by_name(nome_target)
if not player then if not giocatore then
return return
end end
local context = sfinv.get_or_create_context(player) local contesto = sfinv.get_or_create_context(giocatore)
if context.page ~= "myadmin:myadmin" then if contesto.page ~= "mioadmin:mioadmin" then
return return
end end
sfinv.set_player_inventory_formspec(player, context) sfinv.set_player_inventory_formspec(giocatore, contesto)
end end
minetest.register_on_priv_grant(on_grant_revoke) minetest.register_on_priv_grant(al_cambio_privilegi)
minetest.register_on_priv_revoke(on_grant_revoke) minetest.register_on_priv_revoke(al_cambio_privilegi)
``` ```
## on_enter and on_leave callbacks ## Callback on_enter e on_leave
A player *enters* a tab when the tab is selected and *leaves* a Un giocatore *entra* in una finestra quando la finestra è selezionata e *esce* dalla finestra quando un'altra finestra è prossima a essere selezionata.
tab when another tab is about to be selected. Attenzione che è possibile selezionare più pagine alla volta se viene usata un tema personalizzato.
It's possible for multiple pages to be selected if a custom theme is
used.
Note that these events may not be triggered by the player. Si tenga conto, poi, che questi eventi potrebbero non essere innescati dal giocatore, in quanto potrebbe addirittura non avere un formspec aperto in quel momento.
The player may not even have the formspec open at that time. Per esempio, `on_enter` viene chiamato dalla pagina principale anche quando un giocatore entra in gioco, ancor prima che apri l'inventario.
For example, on_enter is called for the home page when a player
joins the game even before they open their inventory.
It's not possible to cancel a page change, as that would potentially Infine, non è possibile annullare il cambio pagina, in quanto potrebbe potenzialmente confondere il giocatore.
confuse the player.
```lua ```lua
on_enter = function(self, player, context) on_enter = function(self, player, context)
@ -218,22 +200,21 @@ on_leave = function(self, player, context)
end, end,
``` ```
## Adding to an existing page ## Aggiungere a una pagina esistente
To add content to an existing page, you will need to override the page Per aggiungere contenuti a una pagina che già esiste, avrai bisogno di sovrascrivere la pagina e modificare il formspec che viene ritornato:
and modify the returned formspec.
```lua ```lua
local old_func = sfinv.registered_pages["sfinv:crafting"].get local vecchia_funzione = sfinv.registered_pages["sfinv:crafting"].get
sfinv.override_page("sfinv:crafting", { sfinv.override_page("sfinv:crafting", {
get = function(self, player, context, ...) get = function(self, player, context, ...)
local ret = old_func(self, player, context, ...) local ret = vecchia_funzione(self, player, context, ...)
if type(ret) == "table" then if type(ret) == "table" then
ret.formspec = ret.formspec .. "label[0,0;Hello]" ret.formspec = ret.formspec .. "label[0,0;Ciao]"
else else
-- Backwards compatibility -- Retrocompatibilità
ret = ret .. "label[0,0;Hello]" ret = ret .. "label[0,0;Ciao]"
end end
return ret return ret