I reverted the whole 'players' folder like an idiot. Bless the local copy on the other PC
This commit is contained in:
parent
c0ca655327
commit
50687bc868
150
_it/players/chat.md
Normal file → Executable file
150
_it/players/chat.md
Normal file → Executable 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
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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.
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user