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
root: ../..
idx: 4.2
description: Registering a chatcommand and handling chat messages with register_on_chat_message
redirect_from: /en/chapters/chat.html
description: Come registrare un comando e gestire i messaggi della chat
redirect_from: /it/chapters/chat.html
cmd_online:
level: warning
title: Offline players can run commands
message: <p>A player name is passed instead of a player object because mods
can run commands on behalf of offline players. For example, the IRC
bridge allows players to run commands without joining the game.</p>
title: I giocatori offline possono eseguire comandi
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.
Per esempio, il bridge IRC permette ai giocatori di eseguire comandi senza dover entrare in gioco.</p>
<p>So make sure that you don't assume that the player is online.
You can check by seeing if <pre>minetest.get_player_by_name</pre> returns a player.</p>
<p>Assicurati quindi di non dar per scontato che un giocatore sia connesso.
Puoi controllare ciò tramite <pre>minetest.get_player_by_name</pre>, per vedere se ritorna qualcosa o meno.</p>
cb_cmdsprivs:
level: warning
title: Privileges and Chat Commands
message: The shout privilege isn't needed for a player to trigger this callback.
This is because chat commands are implemented in Lua, and are just
chat messages that begin with a /.
title: Privilegi e comandi
message: Il privilegio shout non è necessario per far sì che un giocatore attivi questo callback.
Questo perché i comandi sono implementati in Lua, e sono semplicemente dei messaggi in chat che iniziano con /.
---
## Introduction <!-- omit in toc -->
## Introduzione <!-- omit in toc -->
Mods can interact with player chat, including
sending messages, intercepting messages, and registering chat commands.
Le mod possono interagire con la chat del giocatore, tra l'inviare messaggi, intercettarli e registrare dei comandi.
- [Sending Messages to All Players](#sending-messages-to-all-players)
- [Sending Messages to Specific Players](#sending-messages-to-specific-players)
- [Chat Commands](#chat-commands)
- [Inviare messaggi a tutti i giocatori](#inviare-messaggi-a-tutti-i-giocatori)
- [Inviare messaggi a giocatori specifici](#inviare-messaggi-a-giocatori-specifici)
- [Comandi](#comandi)
- [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
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
This is a chat message to all players
<player2> What about it?
<Tizio> Guarda qui
Questo è un messaggio visualizzabile da tutti
<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
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
only visible to the named player, in this case, player1.
Questo messaggio viene mostrato esattamente come il precedente, ma solo, in questo caso, a Tizio.
## 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
minetest.register_chatcommand("foo", {
@ -72,93 +68,83 @@ minetest.register_chatcommand("foo", {
interact = true,
},
func = function(name, param)
return true, "You said " .. param .. "!"
return true, "Hai detto " .. param .. "!"
end,
})
```
In the above snippet, `interact` is listed as a required
[privilege](privileges.html) meaning that only players with the `interact` privilege can run the command.
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.
Chat commands can return up to two values,
the first being a Boolean indicating success, and the second being a
message to send to the user.
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.
{% 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>`
* `/team join <teamname>`
* `/team leave <teamname>`
* `/team list`
* `/msg <a> <messaggio>`
* `/team entra <nometeam>`
* `/team esci <nometeam>`
* `/team elenco`
This is usually done using [Lua patterns](https://www.lua.org/pil/20.2.html).
Patterns are a way of extracting stuff from text using rules.
Questo viene solitamente reso possibile dai [pattern di Lua](https://www.lua.org/pil/20.2.html).
I pattern sono un modo di estrapolare "cose" dal testo usando delle regole ben precise.
```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.
* `()` is a matching group - anything that matches stuff in here will be
returned from string.match.
* `[]` means accept characters in this list.
* `%a` means accept any letter and `%d` means accept any digit.
* `[%d%a_-]` means accept any letter or digit or `_` or `-`.
* `+` means match the thing before one or more times.
* `*` means match any character in this context.
* `$` means match the end of the string.
* `^` dice di iniziare a combaciare dall'inizio della stringa;
* `()` è un gruppo - qualsiasi cosa che combaci con ciò che è contenuto al suo interno verrà ritornato da string.match;
* `[]` significa che i caratteri al suo interno sono accettati;
* `%a` significa che accetta ogni lettera e `%d` ogni cifra.
* `[%d%a_-]` significa che accetta ogni lettera, cifra, `_` e `-`.
* `+` dice di combaciare ciò che lo precede una o più volte.
* `*` dice di combaciare qualsiasi tipo di carattere.
* `$` dice di combaciare la fine della stringa.
Put simply, the pattern matches the name (a word with only letters/numbers/-/_),
then a space, then the message (one or more of any character). The name and
message are returned, because they're surrounded by parentheses.
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).
Vengono poi ritornati nome e messaggio, perché sono inseriti nelle parentesi.
That's how most mods implement complex chat commands. A better guide to Lua
Patterns would probably be the
[lua-users.org tutorial](http://lua-users.org/wiki/PatternsTutorial)
or the [PIL documentation](https://www.lua.org/pil/20.2.html).
Questo è come molte mod implementano comandi complessi.
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).
<p class="book_hide">
There is also a library written by the author of this book which can be used
to make complex chat commands without patterns called
<a href="chat_complex.html">Chat Command Builder</a>.
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>.
</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
minetest.register_on_chat_message(function(name, message)
print(name .. " said " .. message)
print(name .. " ha detto " .. message)
return false
end)
```
By returning false, you allow the chat message to be sent by the default
handler. You can actually remove the line `return false` and it would still
work the same, because `nil` is returned implicitly and is treated like false.
Ritornando false, si permette al messaggio di essere inviato.
In verità `return false` può anche essere omesso in quanto `nil` verrebbe ritornato implicitamente, e nil è trattato come false.
{% include notice.html notice=page.cb_cmdsprivs %}
You should make sure you take into account that it may be a chat command,
or the user may not have `shout`.
Dovresti assicurarti, poi, che il messaggio potrebbe essere un comando che invia messaggi in chat,
o che l'utente potrebbere non avere `shout`.
```lua
minetest.register_on_chat_message(function(name, message)
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
print(name .. " said " .. message)
print(name .. " ha detto " .. message)
else
print(name .. " tried to say " .. message ..
" but doesn't have shout")
print(name .. " ha provato a dire " .. message ..
" ma non ha lo shout")
end
return false

View File

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

View File

@ -1,268 +1,224 @@
---
title: Formspecs
title: GUI (Formspec)
layout: default
root: ../..
idx: 4.5
redirect_from: /en/chapters/formspecs.html
minetest510:
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.
description: Tempo di interagire con le finestre
redirect_from: /it/chapters/formspecs.html
submit_vuln:
level: warning
title: Malicious clients can submit anything at anytime
message: You should never trust a formspec submission. A malicious client
can submit anything they like at any time - even if you never showed
them the formspec. This means that you should check privileges
and make sure that they should be allowed to perform the action.
title: Client malevoli possono inviare qualsiasi cosa quando più gli piace
message: Non dovresti mai fidarti di un modulo di compilazione - anche se non hai mai mostrato loro il formspec.
Questo significa che dovresti controllarne i privilegi e assicurarti che dovrebbero effettivamente essere in grado di eseguire quest'azione.
---
## Introduction <!-- omit in toc -->
## Introduzione <!-- omit in toc -->
<figure class="right_image">
<img src="{{ page.root }}//static/formspec_example.png" alt="Furnace Inventory">
<figcaption>
Screenshot of furnace formspec, labelled.
Screenshot del formspec di una fornace e della sua struttura.
</figcaption>
</figure>
In this chapter we will learn how to create a formspec and display it to the user.
A formspec is the specification code for a form.
In Minetest, forms are windows such as the player inventory and can contain a
variety of elements, such as labels, buttons and fields.
In questo capitolo impareremo come creare un formspec e mostrarlo all'utente.
Un formspec è il codice di specifica di un modulo (*form*, da qui *form*-*spec*).
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.
Note that if you do not need to get user input, for example when you only need
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.
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à.
- [Real or Legacy Coordinates](#real-or-legacy-coordinates)
- [Anatomy of a Formspec](#anatomy-of-a-formspec)
- [Elements](#elements)
- [Header](#header)
- [Guessing Game](#guessing-game)
- [Padding and Spacing](#padding-and-spacing)
- [Receiving Formspec Submissions](#receiving-formspec-submissions)
- [Contexts](#contexts)
- [Formspec Sources](#formspec-sources)
- [Node Meta Formspecs](#node-meta-formspecs)
- [Player Inventory Formspecs](#player-inventory-formspecs)
- [Your Turn](#your-turn)
- [Coordinate reali o datate](#coordinate-reali-o-datate)
- [Anatomia di un formspec](#anatomia-di-un-formspec)
- [Elementi](#elementi)
- [Intestazione](#intestazione)
- [Esempio: indovina un numero](#esempio-indovina-un-numero)
- [Imbottitura e spaziatura](#imbottitura-e-spaziatura)
- [Ricevere i moduli di compilazione](#ricevere-i-moduli-di-compilazione)
- [Contesti](#contesti)
- [Ricavare un formspec](#ricavare-un-formspec)
- [Formspec nei nodi](#formspec-nei-nodi)
- [Inventario del giocatore](#inventario-del-giocatore)
- [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
elements were positioned varied in unexpected ways; it was hard to predict the
placement of elements and align them. Minetest 5.1.0 contains a feature
called real coordinates which aims to rectify this by introducing a consistent
coordinate system. The use of real coordinates is highly recommended, and so
this chapter will use them exclusively.
Nelle vecchie versioni di Minetest, i formspec erano incoerenti.
Il modo in cui elementi diversi venivano posizionati nel formspec variava in maniere inaspettate; era difficile predirne la collocazione e allinearli correttamente.
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.
L'uso delle coordinate reali è caldamente consigliato, onde per cui questo capitolo non tratterà di quelle vecchie.
{% 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.
It consists of a number of elements with the following form:
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:
Viene prima dichiarato il tipo dell'elemento, seguito dai parametri nelle parentesi quadre.
Si possono concatenare più elementi, piazzandoli eventualmente su più linee:
foo[param1]bar[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
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.
### Intestazione
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
includes the size of the formspec, the position, the anchor, and whether the
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:
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.
Ecco un formspec di 2x2:
formspec_version[3]
size[2,2]
real_coordinates[true]
Notice how we explicitly need to enable the use of the real coordinate system.
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.
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.
The position and anchor elements are used to place the formspec on the screen.
The position sets where on the screen the formspec will be, and defaults to
the center (`0.5,0.5`). The anchor sets where on the formspec the position is,
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:
La posizione e l'ancoraggio degli elementi sono usati per collocare il formspec nello schermo.
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.
Per esempio, lo si può posizionare ancorato a sinistra in questo modo:
formspec_version[3]
size[2,2]
real_coordinates[true]
position[0,0.5]
anchor[0,0.5]
This sets the anchor to the left middle edge of the formspec box, and then the
position of that anchor to the left of the screen.
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.
## Guessing Game
## Esempio: indovina un numero
<figure class="right_image">
<img src="{{ page.root }}/static/formspec_guessing.png" alt="Guessing Formspec">
<figcaption>
The guessing game formspec.
Il formspec del gioco dell'indovinare un numero
</figcaption>
</figure>
The best way to learn is to make something, so let's make a guessing game.
The principle is simple: the mod decides on a number, then the player makes
guesses on the number. The mod then says if the guess is higher or lower then
the actual number.
Il modo migliore per imparare è sporcarsi le mani, quindi creiamo un gioco.
Il principio è semplice: la mod decide un numero, e il giocatore deve tentare di indovinarlo.
La mod, poi, comunica se si è detto un numero più alto o più basso rispetto a quello corretto.
First, let's make a function to create the formspec code. It's good practice to
do this, as it makes it easier to reuse elsewhere.
Prima di tutto, costruiamo una funzione per creare il formspec.
È buona pratica fare ciò, in quanto rende il riutilizzo più comodo.
<div style="clear: both;"></div>
```lua
guessing = {}
indovina = {}
function guessing.get_formspec(name)
-- TODO: display whether the last guess was higher or lower
local text = "I'm thinking of a number... Make a guess!"
function indovina.prendi_formspec(nome)
-- TODO: comunicare se il numero del tentativo era più alto o più basso
local testo = "Sto pensando a un numero... Prova a indovinare!"
local formspec = {
"size[6,3.476]",
"real_coordinates[true]",
"label[0.375,0.5;", minetest.formspec_escape(text), "]",
"field[0.375,1.25;5.25,0.8;number;Number;]",
"button[1.5,2.3;3,0.8;guess;Guess]"
"label[0.375,0.5;", minetest.formspec_escape(testo), "]",
"field[0.375,1.25;5.25,0.8;numero;Numero;]",
"button[1.5,2.3;3,0.8;indovina;Indovina]"
}
-- table.concat is faster than string concatenation - `..`
-- table.concat è più veloce della concatenazione di stringhe - `..`
return table.concat(formspec, "")
end
```
In the above code, we place a field, a label, and a button. A field allows text
entry, and a button is used to submit the form. You'll notice that the elements
are positioned carefully in order to add padding and spacing, this will be explained
later.
Nel codice qui sopra abbiamo inserito un'etichetta (*label*), un campo (*field*) e un pulante (*button*).
Un campo ci permete di inserire del testo, mentre useremo il pulsante per inviare il modulo.
Noterai che gli elementi sono posizionati attentamente per aggiungere imbottitura e spaziatura (*padding* e *spacing*),
ma ci arriveremo tra poco.
Next, we want to allow the player to show the formspec. The main way to do this
is using `show_formspec`:
Come prossima cosa, vogliamo permettere al giocatore di visualizzare il formspec.
Il metodo principale per farlo è usare `show_formspec`:
```lua
function guessing.show_to(name)
minetest.show_formspec(name, "guessing:game", guessing.get_formspec(name))
function indovina.mostra_a(nome)
minetest.show_formspec(nome, "indovina:gioco", indovina.prendi_formspec(nome))
end
minetest.register_chatcommand("game", {
minetest.register_chatcommand("gioco", {
func = function(name)
guessing.show_to(name)
indovina.mostra_a(name)
end,
})
```
The show_formspec function accepts a player name, the formspec name, and the
formspec itself. The formspec name should be a valid itemname, ie: in the format
`modname:itemname`.
La funzione `show_formspec` prende il nome del giocatore, il nome del formspec e il formspec stesso.
Il nome di quest'ultimo dovrebbe seguire il formato del nome degli oggetti, tipo `nomemod:nomeoggetto`.
### Padding and Spacing
### Imbottitura e spaziatura
<figure class="right_image">
<img src="{{ page.root }}/static/formspec_padding_spacing.png" alt="Padding and spacing">
<figcaption>
The guessing game formspec.
Il formspec del gioco dell'indovinare un numero
</figcaption>
</figure>
Padding is the gap between the edge of the formspec and its contents, or between unrelated
elements, shown in red. Spacing is the gap between related elements, shown in blue.
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.
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>
### Receiving Formspec Submissions
### Ricevere i moduli di compilazione
When `show_formspec` is called, the formspec is sent to the client to be displayed.
For formspecs to be useful, information needs to be returned from the client to server.
The method for this is called formspec field submission, and for `show_formspec`, that
submission is received using a global callback:
Quando `show_formspec` viene chiamato, il formspec viene inviato al client per essere visualizzato.
Per far sì che i formspec siano utili, le informazioni devono essere ritornate dal client al server.
Il metodo per fare ciò è chiamato Campo di Compilazione (*formspec field submission*), e per `show_formspec` quel campo viene ottenuto usando un callback globale:
```lua
minetest.register_on_player_receive_fields(function(player, formname, fields)
if formname ~= "guessing:game" then
if formname ~= "indovina:gioco" then
return
end
if fields.guess then
local pname = player:get_player_name()
minetest.chat_send_all(pname .. " guessed " .. fields.number)
if fields.indovina then
local p_name = player:get_player_name()
minetest.chat_send_all(p_name .. " ha tentato di indovinare con il numero " .. fields.numero)
end
end)
```
The function given in minetest.register_on_player_receive_fields is called
every time a user submits a form. Most callbacks will need to check the formname given
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.
La funzione data in `minetest.register_on_player_receive_fields` è chiamata ogni volta che un utente invia un modulo.
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.
The `fields` parameter to the function is a table of the values submitted by the
user, indexed by strings. Named elements will appear in the field under their own
name, but only if they are relevent for the event that caused the submission.
For example, a button element will only appear in fields if that particular button
was pressed.
Il parametro `fields` è una tabella di tutti i valori inviati dall'utente, indicizzati per stringhe.
I nomi degli elementi appariranno nel campo con il loro nome, ma solo se sono rilevanti per l'evento che ha causato l'invio.
Per esempio, un elemento "pulsante" apparirà nei campi solo se quel particolare pulsante è stato premuto.
{% include notice.html notice=page.submit_vuln %}
So, now the formspec is sent to the client and the client sends information back.
The next step is to somehow generate and remember the target value, and to update
the formspec based on guesses. The way to do this is using a concept called
"contexts".
Quindi, ora il formspec è stato inviato al client e il client ritorna quelle informazioni.
Il prossimo passaggio è generare e ricordare il valore ricevuto, e aggiornare il formspec basandosi sui tentativi.
Il modo per fare ciò è usare un concetto chiamato "contesto".
### Contexts
### Contesti
In many cases you want minetest.show_formspec to give information
to the callback which you don't want to send to the client. This might include
what a chat command was called with, or what the dialog is about. In this case,
the target value that needs to be remembered.
In molti casi si può desiderare che le informazioni passate da `show_formspec` al callback non raggiungano il client.
Ciò potrebbe includere con cosa è stato chiamato un comando via chat, o di cosa tratta la finestra di dialogo.
In questo caso, il valore che si necessita di ricordare.
A context is a per-player table to store information, and the contexts for all
online players are stored in a file-local variable:
Un contesto (*context*) è una tabella assegnata a ogni giocatore per immagazzinare informazioni, e i contesti di tutti i giocatori sono
salvati in una variabile locale di file:
```lua
local _contexts = {}
local function get_context(name)
local context = _contexts[name] or {}
_contexts[name] = context
return context
local _contesti = {}
local function prendi_contesto(nome)
local contesto = _contesto[nome] or {}
_contesti[nome] = contesto
return contesto
end
minetest.register_on_leaveplayer(function(player)
@ -270,83 +226,78 @@ minetest.register_on_leaveplayer(function(player)
end)
```
Next, we need to modify the show code to update the context
before showing the formspec:
Ora abbiamo bisogno di modificare il codice da mostrare, per aggiornare il contesto prima di mostrare il formspec:
```lua
function guessing.show_to(name)
local context = get_context(name)
context.target = context.target or math.random(1, 10)
function indovina.mostra_a(nome)
local contesto = prendi_contesto(nome)
contesto.soluzione = contesto.soluzione or math.random(1, 10)
local fs = guessing.get_formspec(name, context)
minetest.show_formspec(name, "guessing:game", fs)
local formspec = indovina.prendi_formspec(nome, contesto)
minetest.show_formspec(nome, "indovina:gioco", formspec)
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
function guessing.get_formspec(name, context)
local text
if not context.guess then
text = "I'm thinking of a number... Make a guess!"
elseif context.guess == context.target then
text = "Hurray, you got it!"
elseif context.guess > context.target then
text = "To high!"
function indovina.prendi_formspec(nome, contesto)
local testo
if not contesto.tentativo then
testo = "Sto pensando a un numero... Prova a indovinare!"
elseif contesto.tentativo == contesto.soluzione then
testo = "Yeee, hai indovinato!"
elseif contesto.tentativo > contesto.soluzione then
testo = "Troppo alto!"
else
text = "To low!"
testo = "Troppo basso!"
end
```
Note that it's good practice for get_formspec to only read the context, and not
update it at all. This can make the function simpler, and also easier to test.
Tieni a mente che quando si ottiene il formspec è buona norma leggerne il contesto, senza però aggiornalo.
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
if fields.guess then
local name = player:get_player_name()
local context = get_context(name)
context.guess = tonumber(fields.number)
guessing.show_to(name)
if fields.indovina then
local nome = player:get_player_name()
local contesto = prendi_contesto(nome)
contesto.tentativo = tonumber(fields.numero)
indovina.mostra_a(nome)
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.
* [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.
### Formspec nei nodi
### Node Meta Formspecs
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.
`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.
```lua
minetest.register_node("mymod:rightclick", {
description = "Rightclick me!",
tiles = {"mymod_rightclick.png"},
minetest.register_node("miamod:tastodestro", {
description = "Premimi col tasto destro del mouse!",
tiles = {"miamod_tastodestro.png"},
groups = {cracky = 1},
after_place_node = function(pos, placer)
-- This function is run when the chest node is placed.
-- The following code sets the formspec for chest.
-- Meta is a way of storing data onto a node.
-- Questa funzione è eseguita quando viene piazzato il nodo.
-- Il codice che segue imposta il formspec della cassa.
-- I metadati sono un modo per immagazzinare dati nel nodo.
local meta = minetest.get_meta(pos)
meta:set_string("formspec",
"formspec_version[3]" ..
"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;]")
end,
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
receive form input for meta formspecs, you must include an
`on_receive_fields` entry when registering the node.
I formspec impostati in questo modo non innescano lo stesso callback.
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.
This style of callback triggers when you press enter
in a field, which is impossible with `minetest.show_formspec`;
however, this kind of form can only be shown by right-clicking on a
node. It cannot be triggered programmatically.
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
tramite il premere col tasto destro del mouse su un nodo. Non è possibile farlo programmaticamente.
### Player Inventory Formspecs
### Inventario del giocatore
The player inventory formspec is the one shown when the player presses i.
The global callback is used to receive events from this formspec, and the
formname is `""`.
L'inventario del giocatore è un formspec, che viene mostrato al premere "I".
Il callback globale viene usato per ricevere eventi dall'inventario, e il suo nome è `""`.
There are a number of different mods which allow multiple mods to customise
the player inventory. The officially recommended mod is
[Simple Fast Inventory (sfinv)](sfinv.html), and is included in Minetest Game.
Ci sono svariate mod che permettono ad altrettante mod di personalizzare l'inventario del giocatore.
La mod ufficialmente raccomandata è [Simple Fast Inventory (sfinv)](sfinv.html), ed è inclusa in Minetest Game.
### Il tuo turno
### Your Turn
* Extend the Guessing Game to keep track of each player's top score, where the
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.
* 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.
Questo nodo dovrebbe salvare il nome del mittente come `owner` nei metadati, e dovrebbe usare `show_formspec` per mostrare formspec differenti a giocatori differenti.

View File

@ -3,126 +3,116 @@ title: HUD
layout: default
root: ../..
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)
- [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)
## Posizionamento
## Positioning
### Position and Offset
### Posizione e scostamento
<figure class="right_image">
<img
width="300"
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>
Screens come in a variety of different physical sizes and resolutions, and
the HUD needs to work well on all screen types.
Essendoci schermi di tutte le dimensioni e risoluzioni, per funzionare bene le HUD devono sapersi adattare a ognuno di essi.
Minetest's solution to this is to specify the location of an element using both
a percentage position and an offset.
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).
Per ovviare al problema, Minetest specifica il collocamento di un elemento usando sia una posizione in percentuale che uno scostamento (*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 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>
### Alignment
### Allineamento
Alignment is where the result of position and offset is on the element -
for example, `{x = -1.0, y = 0.0}` will make the result of position and offset point
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.
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.
Questo è particolarmente utile quando si vuole allineare del testo a sinistra, a destra o al centro.
<figure>
<img
width="500"
src="{{ page.root }}//static/hud_diagram_alignment.svg"
alt="Diagram showing alignment">
alt="Diagramma che mostra i vari tipi di allineamento">
</figure>
The above diagram shows 3 windows (blue), each with a single HUD element (yellow)
and a different alignment each time. The arrow is the result of the position
and offset calculation.
Il diagramma qui in alto mostra mostra tre finestre (in blu), ognuna contenente un elemento HUD (in giallo) con ogni volta un allineamento diverso.
La freccia è il risultato del calcolo di posizione e scostamento.
### Scoreboard
### Esempio: tabellone segnapunti
For the purposes of this chapter, you will learn how to position and update a
score panel like so:
Per capire meglio il capitolo, vedremo come posizionare e aggiornare un pannello contenente dei punti come questo:
<figure>
<img
src="{{ page.root }}//static/hud_final.png"
alt="screenshot of the HUD we're aiming for">
alt="Screenshot dell'HUD da realizzare">
</figure>
In the above screenshot, all the elements have the same percentage position
(100%, 50%) - but different offsets. This allows the whole thing to be anchored
to the right of the window, but to resize without breaking.
Nello screenshot sovrastante, tutti gli elementi hanno la stessa posizione percentuale (100%, 50%) - ma scostamenti diversi.
Questo permette all'intero pannello di essere ancorato sulla destra della finestra, senza posizioni/scostamenti strani al ridimensionarla.
## 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
local player = minetest.get_player_by_name("username")
local idx = player:hud_add({
local giocatore = minetest.get_player_by_name("tizio")
local idx = giocatore:hud_add({
hud_elem_type = "text",
position = {x = 0.5, y = 0.5},
offset = {x = 0, y = 0},
text = "Hello world!",
alignment = {x = 0, y = 0}, -- center aligned
scale = {x = 100, y = 100}, -- covered later
text = "Ciao mondo!",
alignment = {x = 0, y = 0}, -- allineamento centrato
scale = {x = 100, y = 100}, -- lo vedremo tra poco
})
```
The `hud_add` function returns an element ID - this can be used later to modify
or remove a HUD element.
La funzione `hud_add` ritorna l'ID di un elemento, che è utile per modificarlo o rimuoverlo.
### Parameters
### Parametri
The element's type is given using the `hud_elem_type` property in the definition
table. The meaning of other properties varies based on this type.
Il tipo dell'elemento è ottenuto usando la proprietà `hud_elem_type` nella tabella di definizione.
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
-- Get the dig and place count from storage, or default to 0
local meta = player:get_meta()
local digs_text = "Digs: " .. meta:get_int("score:digs")
local places_text = "Places: " .. meta:get_int("score:places")
-- Ottiene il numero di blocchi scavati e piazzati dallo spazio d'archiviazione; se non esiste è 0
local meta = giocatore:get_meta()
local digs_testo = "Digs: " .. meta:get_int("punteggio:digs")
local places_testo = "Places: " .. meta:get_int("punteggio:places")
player:hud_add({
giocatore:hud_add({
hud_elem_type = "text",
position = {x = 1, y = 0.5},
offset = {x = -120, y = -25},
@ -132,162 +122,160 @@ player:hud_add({
number = 0xFFFFFF,
})
player:hud_add({
giocatore:hud_add({
hud_elem_type = "text",
position = {x = 1, y = 0.5},
offset = {x = -180, y = 0},
text = digs_text,
text = digs_testo,
alignment = -1,
scale = { x = 50, y = 10},
number = 0xFFFFFF,
})
player:hud_add({
giocatore:hud_add({
hud_elem_type = "text",
position = {x = 1, y = 0.5},
offset = {x = -70, y = 0},
text = places_text,
text = places_testo,
alignment = -1,
scale = { x = 50, y = 10},
number = 0xFFFFFF,
})
```
This results in the following:
Il risultato è il seguente:
<figure>
<img
src="{{ page.root }}//static/hud_text.png"
alt="screenshot of the HUD we're aiming for">
alt="Screenshot della HUD finora">
</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
player:hud_add({
hud_elem_type = "image",
position = {x = 1, y = 0.5},
offset = {x = -220, y = 0},
text = "score_background.png",
text = "punteggio_sfondo.png",
scale = { x = 1, y = 1},
alignment = { x = 1, y = 0 },
})
```
You will now have this:
Siamo ora a questo punto:
<figure>
<img
src="{{ page.root }}//static/hud_background_img.png"
alt="screenshot of the HUD so far">
alt="Screenshot della HUD finora">
</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
original image size, 2 being double the size, and so on.
However, if a co-ordinate is negative, it is a percentage of the screen size.
For example, `x=-100` is 100% of the width.
Se una coordinata in `scale` è positiva, allora è un fattore scalare dove 1 è la grandezza originale, 2 è il doppio e così via.
Tuttavia, se una coordinata è negativa, sarà la percentuale della grandezza dello schermo.
Per esempio, `x=-100` equivale al 100% della larghezza di quest'ultimo.
### 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
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",
position = {x = 1, y = 0.5},
offset = {x = -215, y = 23},
text = "score_bar_empty.png",
text = "barra_punteggio_vuota.png",
scale = { x = 1, y = 1},
alignment = { x = 1, y = 0 },
})
player:hud_add({
giocatore:hud_add({
hud_elem_type = "image",
position = {x = 1, y = 0.5},
offset = {x = -215, y = 23},
text = "score_bar_full.png",
scale = { x = percent, y = 1},
text = "barra_punteggio_piena.png",
scale = { x = percentuale, y = 1},
alignment = { x = 1, y = 0 },
})
```
We now have a HUD that looks like the one in the first post!
There is one problem however, it won't update when the stats change.
Abbiamo ora una HUD uguale identica a quella della prima immagine!
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
local idx = player:hud_add({
local idx = giocatore:hud_add({
hud_elem_type = "text",
text = "Hello world!",
-- parameters removed for brevity
text = "Ciao mondo!",
-- parametri rimossi per brevità
})
player:hud_change(idx, "text", "New Text")
player:hud_remove(idx)
giocatore:hud_change(idx, "text", "Nuovo testo")
giocatore:hud_remove(idx)
```
The `hud_change` method takes the element ID, the property to change, and the new
value. The above call changes the `text` property from "Hello World" to "Test".
Il metodo `hud_change` prende l'ID dell'elemento, la proprietà da cambiare e il nuovo valore.
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
functionally equivalent to the following, in a rather inefficient way:
Questo significa che fare `hud_change` subito dopo `hud_add` è funzionalmente equivalente a
fare ciò che segue, in maniera alquanto inefficiente:
```lua
local idx = player:hud_add({
local idx = giocatore:hud_add({
hud_elem_type = "text",
text = "New Text",
text = "Nuovo testo",
})
```
## Storing IDs
## Salvare gli ID
```lua
score = {}
local saved_huds = {}
local hud_salvate = {}
function score.update_hud(player)
local player_name = player:get_player_name()
function punteggio.aggiorna_hud(giocatore)
local nome_giocatore = giocatore:get_player_name()
-- Get the dig and place count from storage, or default to 0
local meta = player:get_meta()
local digs_text = "Digs: " .. meta:get_int("score:digs")
local places_text = "Places: " .. meta:get_int("score:places")
local percent = tonumber(meta:get("score:score") or 0.2)
-- Ottiene il numero di blocchi scavati e piazzati dallo spazio d'archiviazione; se non esiste è 0
local meta = giocatore:get_meta()
local digs_testo = "Digs: " .. meta:get_int("punteggio:digs")
local places_testo = "Places: " .. meta:get_int("punteggio:places")
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
player:hud_change(ids["places"], "text", places_text)
player:hud_change(ids["digs"], "text", digs_text)
player:hud_change(ids["bar_foreground"],
"scale", { x = percent, y = 1 })
giocatore:hud_change(ids["places"], "text", places_testo)
giocatore:hud_change(ids["digs"], "text", digs_testo)
giocatore:hud_change(ids["bar_foreground"],
"scale", { x = percentuale, y = 1 })
else
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
minetest.register_on_joinplayer(score.update_hud)
minetest.register_on_joinplayer(punteggio.aggiorna_hud)
minetest.register_on_leaveplayer(function(player)
saved_huds[player:get_player_name()] = nil
hud_salvate[player:get_player_name()] = nil
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
root: ../..
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.
Physics overrides can set the walking speed, jump speed,
and gravity constants.
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.
La fisica del giocatore può essere modificata usando le sovrascritture apposite (*physics ovverrides*).
Esse sono dei moltiplicatori che servono per impostare la velocità di movimento, del salto, o la gravità del singolo giocatore.
Per esempio, un valore di 2 sulla gravità, renderà la gravità di un utente due volte più forte.
- [Basic Example](#basic-example)
- [Available Overrides](#available-overrides)
- [Old Movement Behaviour](#old-movement-behaviour)
- [Mod Incompatibility](#mod-incompatibility)
- [Your Turn](#your-turn)
- [Esempio base](#esempio-base)
- [Sovrascritture disponibili](#sovrascritture-disponibili)
- [Vecchio sistema di movimento](#vecchio-sistema-di-movimento)
- [Incompatibilità tra mod](#incompatibilita-tra-mod)
- [Il tuo turno](#il-tuo-turno)
## Basic Example
## Esempio base
Here is an example of how to add an antigravity command, which
puts the caller in low G:
Segue l'esempio di un comando di antigravità:
```lua
minetest.register_chatcommand("antigravity", {
minetest.register_chatcommand("antigrav", {
func = function(name, param)
local player = minetest.get_player_by_name(name)
player:set_physics_override({
gravity = 0.1, -- set gravity to 10% of its original value
local giocatore = minetest.get_player_by_name(name)
giocatore:set_physics_override({
gravity = 0.1, -- imposta la gravità al 10% del suo valore originale
-- (0.1 * 9.81)
})
end,
})
```
## Available Overrides
## Sovrascritture disponibili
`player:set_physics_override()` is given a table of overrides.\\
According to [lua_api.txt]({{ page.root }}/lua_api.html#player-only-no-op-for-other-objects),
these can be:
`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:
* speed: multiplier to default walking speed value (default: 1)
* jump: multiplier to default jump value (default: 1)
* gravity: multiplier to default gravity value (default: 1)
* sneak: whether the player can sneak (default: true)
* `speed`: moltiplicatore della velocità di movimento (predefinito: 1)
* `jump`: moltiplicatore del salto (predefinito: 1)
* `gravity`: moltiplicatore della gravità (predefinito: 1)
* `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
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.
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.
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)
* sneak_glitch: whether the player can use 'sneak elevators' (default: false)
* `new_move`: se usare o meno il nuovo sistema di movimento (predefinito: true)
* `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
to be incompatible with each other. When setting an override, it overwrites
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.
Tieni a mente che le mod che sovrascrivono la stessa proprietà fisica di un giocatore tendono a essere incompatibili tra di loro.
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.
## Your Turn
## Il tuo turno
* **Sonic**: Set the speed multiplier to a high value (at least 6) when a player joins the game.
* **Super bounce**: Increase the jump value so that the player can jump 20 metres (1 metre is 1 node).
* **Space**: Make gravity decrease as the player gets higher.
* **Sonic**: Imposta il moltiplicatore di velocità a un valore elevato (almeno 6) quando un giocatore entra in gioco;
* **Super rimbalzo**: Aumenta il valore del salto in modo che il giocatore possa saltare 20 metri (1 cubo = 1 metro);
* **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
root: ../..
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
create the player's inventory [formspec](formspecs.html). SFINV comes with
an API that allows you to add and otherwise manage the pages shown.
Simple Fast Inventory (SFINV) è una mod presente in Minetest Game, usata per creare il [formspec](formspecs.html) del giocatore.
SFINV ha un'API che permette di aggiungere e altresì gestire le pagine mostrate.
Whilst SFINV by default shows pages as tabs, pages are called pages
because it is entirely possible that a mod or game decides to show them in
some other format instead.
For example, multiple pages could be shown in one formspec.
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.
Per esempio, più pagine possono essere mostrate nel medesimo formspec.
- [Registering a Page](#registering-a-page)
- [Receiving events](#receiving-events)
- [Conditionally showing to players](#conditionally-showing-to-players)
- [on_enter and on_leave callbacks](#onenter-and-onleave-callbacks)
- [Adding to an existing page](#adding-to-an-existing-page)
- [Registrare una pagina](#registrare-una-pagina)
- [Ricevere eventi](#ricevere-eventi)
- [Condizioni per la visualizzazione](#condizioni-per-la-visualizzazione)
- [Callback on_enter e on_leave](#callback-onenter-e-onleave)
- [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.
Simply call the function with the page's name and its definition:
SFINV fornisce la funzione chiamata `sfinv.register_page` per creare nuove pagine.
Basta chiamare la funzione con il nome che si vuole assegnare alla pagina e la sua definizione:
```lua
sfinv.register_page("mymod:hello", {
title = "Hello!",
sfinv.register_page("miamod:ciao", {
title = "Ciao!",
get = function(self, 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
})
```
The `make_formspec` function surrounds your formspec with SFINV's formspec code.
The fourth parameter, currently set as `true`, determines whether the
player's inventory is shown.
La funzione `make_formspec` circonda il formspec con il codice di SFINV.
Il quarto parametro, attualmente impostato a `true`, determina se l'inventario del giocatore è mostrato.
Let's make things more exciting; here is the code for the formspec generation
part of a player admin tab. This tab will allow admins to kick or ban players by
selecting them in a list and clicking a button.
Rendiamo le cose più eccitanti; segue il codice della generazione di un formspec per gli admin.
Questa finestra permetterà agli admin di cacciare o bannare i giocatori selezionandoli da una lista e premendo un pulsante.
```lua
sfinv.register_page("myadmin:myadmin", {
title = "Tab",
sfinv.register_page("mioadmin:mioadmin", {
title = "Finestra",
get = function(self, player, context)
local players = {}
context.myadmin_players = players
local giocatori = {}
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 = {
"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
local is_first = true
for _ , player in pairs(minetest.get_connected_players()) do
local player_name = player:get_player_name()
players[#players + 1] = player_name
if not is_first then
-- Aggiunge tutti i giocatori sia alla lista testuale che a quella - appunto - dei giocatori
local primo = true
for _ , giocatore in pairs(minetest.get_connected_players()) do
local nome_giocatore = giocatore:get_player_name()
giocatori[#giocatori + 1] = nome_giocatore
if not primo then
formspec[#formspec + 1] = ","
end
formspec[#formspec + 1] =
minetest.formspec_escape(player_name)
is_first = false
minetest.formspec_escape(nome_giocatore)
primo = false
end
formspec[#formspec + 1] = "]"
-- Add buttons
formspec[#formspec + 1] = "button[0.1,3.3;2,1;kick;Kick]"
formspec[#formspec + 1] = "button[2.1,3.3;2,1;ban;Kick + Ban]"
-- Aggiunge i pulsanti
formspec[#formspec + 1] = "button[0.1,3.3;2,1;caccia;Caccia]"
formspec[#formspec + 1] = "button[2.1,3.3;2,1;banna;Caccia e Banna]"
-- Wrap the formspec in sfinv's layout
-- (ie: adds the tabs and background)
-- Avvolge il formspec nella disposizione di SFINV
-- (es: aggiunge le linguette delle finestre e lo sfondo)
return sfinv.make_formspec(player, context,
table.concat(formspec, ""), false)
end,
})
```
There's nothing new about the above code; all the concepts are
covered above and in previous chapters.
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.
<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>
## Receiving events
## Ricevere eventi
You can receive formspec events by adding a `on_player_receive_fields` function
to a sfinv definition.
Puoi ricevere eventi formspec tramite l'aggiunta della funzione `on_player_receive_fields` nella definizione SFINV.
```lua
on_player_receive_fields = function(self, player, context, fields)
-- TODO: implement this
-- TODO: implementarlo
end,
```
`on_player_receive_fields` works the same as
`minetest.register_on_player_receive_fields`, except that `context` is
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.
`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.
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.
Now let's implement the `on_player_receive_fields` for our admin mod:
Implementiamo ora `on_player_receive_fields` nella mod:
```lua
on_player_receive_fields = function(self, player, context, fields)
-- text list event, check event type and set index if selection changed
if fields.playerlist then
local event = minetest.explode_textlist_event(fields.playerlist)
-- evento della lista testuale: controlla il tipo di evento e imposta il nuovo indice se è cambiata la selezione
if fields.lista_giocatori then
local event = minetest.explode_textlist_event(fields.lista_giocatori)
if event.type == "CHG" then
context.myadmin_selected_idx = event.index
context.mioadmin_sel_id = event.index
end
-- Kick button was pressed
elseif fields.kick then
local player_name =
context.myadmin_players[context.myadmin_selected_idx]
-- Al premere "Caccia"
elseif fields.caccia then
local nome_giocatore =
context.myadmin_players[context.mioadmin_sel_id]
if player_name then
minetest.chat_send_player(player:get_player_name(),
"Kicked " .. player_name)
minetest.kick_player(player_name)
"Cacciato " .. nome_giocatore)
minetest.kick_player(nome_giocatore)
end
-- Ban button was pressed
elseif fields.ban then
local player_name =
context.myadmin_players[context.myadmin_selected_idx]
-- Al premere "Caccia e Banna"
elseif fields.banna then
local nome_giocatore =
context.myadmin_players[context.mioadmin_sel_id]
if player_name then
minetest.chat_send_player(player:get_player_name(),
"Banned " .. player_name)
minetest.ban_player(player_name)
minetest.kick_player(player_name, "Banned")
minetest.ban_player(nome_giocatore)
minetest.kick_player(nome_giocatore, "Banned")
end
end
end,
```
There's a rather large problem with this, however. Anyone can kick or ban players! You
need a way to only show this to players with the kick or ban privileges.
Luckily SFINV allows you to do this!
C'è, tuttavia, un problema abbastanza grande a riguardo: chiunque può cacciare o bannare i giocatori!
C'è bisogno di un modo per mostrare questa finestra solo a chi ha i privilegi `kick` e `ban`.
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
control when the page is shown:
Si può aggiungere una funzione `is_in_nav` nella definizione della pagina se si desidera gestire quando la pagina deve essere mostrata:
```lua
is_in_nav = function(self, player, context)
@ -159,54 +149,46 @@ is_in_nav = function(self, player, context)
end,
```
If you only need to check one priv or want to perform an 'and', you should use
`minetest.check_player_privs()` instead of `get_player_privs`.
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`.
Note that the `is_in_nav` is only called when the player's inventory formspec is
generated. This happens when a player joins the game, switches tabs, or a mod
requests for SFINV to regenerate.
Tieni a mente che `is_in_nav` viene chiamato soltanto alla generazione dell'inventario del giocatore.
Questo succede quando un giocatore entra in gioco, si muove tra le finestre, o una mod richiede a SFINV di rigenerare l'inventario.
This means that you need to manually request that SFINV regenerates the inventory
formspec on any events that may change `is_in_nav`'s result. In our case,
we need to do that whenever kick or ban is granted or revoked to a player:
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`.
Nel nostro caso, abbiamo bisogno di farlo ogni volta che i permessi `kick` o `ban` vengono assegnati/revocati a un giocatore:
```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
return
end
local player = minetest.get_player_by_name(grantee)
if not player then
local giocatore = minetest.get_player_by_name(nome_target)
if not giocatore then
return
end
local context = sfinv.get_or_create_context(player)
if context.page ~= "myadmin:myadmin" then
local contesto = sfinv.get_or_create_context(giocatore)
if contesto.page ~= "mioadmin:mioadmin" then
return
end
sfinv.set_player_inventory_formspec(player, context)
sfinv.set_player_inventory_formspec(giocatore, contesto)
end
minetest.register_on_priv_grant(on_grant_revoke)
minetest.register_on_priv_revoke(on_grant_revoke)
minetest.register_on_priv_grant(al_cambio_privilegi)
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
tab when another tab is about to be selected.
It's possible for multiple pages to be selected if a custom theme is
used.
Un giocatore *entra* in una finestra quando la finestra è selezionata e *esce* dalla finestra quando un'altra finestra è prossima a essere selezionata.
Attenzione che è possibile selezionare più pagine alla volta se viene usata un tema personalizzato.
Note that these events may not be triggered by the player.
The player may not even have the formspec open at that time.
For example, on_enter is called for the home page when a player
joins the game even before they open their inventory.
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.
Per esempio, `on_enter` viene chiamato dalla pagina principale anche quando un giocatore entra in gioco, ancor prima che apri l'inventario.
It's not possible to cancel a page change, as that would potentially
confuse the player.
Infine, non è possibile annullare il cambio pagina, in quanto potrebbe potenzialmente confondere il giocatore.
```lua
on_enter = function(self, player, context)
@ -218,22 +200,21 @@ on_leave = function(self, player, context)
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
and modify the returned formspec.
Per aggiungere contenuti a una pagina che già esiste, avrai bisogno di sovrascrivere la pagina e modificare il formspec che viene ritornato:
```lua
local old_func = sfinv.registered_pages["sfinv:crafting"].get
local vecchia_funzione = sfinv.registered_pages["sfinv:crafting"].get
sfinv.override_page("sfinv:crafting", {
get = function(self, player, context, ...)
local ret = old_func(self, player, context, ...)
local ret = vecchia_funzione(self, player, context, ...)
if type(ret) == "table" then
ret.formspec = ret.formspec .. "label[0,0;Hello]"
ret.formspec = ret.formspec .. "label[0,0;Ciao]"
else
-- Backwards compatibility
ret = ret .. "label[0,0;Hello]"
-- Retrocompatibilità
ret = ret .. "label[0,0;Ciao]"
end
return ret