diff --git a/_en/players/formspecs.md b/_en/players/formspecs.md index a3061d8..0f181b1 100644 --- a/_en/players/formspecs.md +++ b/_en/players/formspecs.md @@ -35,16 +35,16 @@ unexpected windows tend to disrupt gameplay. - [Real or Legacy Coordinates](#real-or-legacy-coordinates) - [Anatomy of a Formspec](#anatomy-of-a-formspec) - - [Elements](#elements) - - [Header](#header) + - [Elements](#elements) + - [Header](#header) - [Guessing Game](#guessing-game) - - [Padding and Spacing](#padding-and-spacing) - - [Receiving Formspec Submissions](#receiving-formspec-submissions) - - [Contexts](#contexts) + - [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) + - [Node Meta Formspecs](#node-meta-formspecs) + - [Player Inventory Formspecs](#player-inventory-formspecs) + - [Your Turn](#your-turn) ## Real or Legacy Coordinates @@ -365,9 +365,9 @@ 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 `""`. -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. +There are a number of different mods which allow multiple mods to customise the +player inventory. Minetest Game uses +[SFINV](https://github.com/rubenwardy/sfinv/blob/master/Tutorial.md). ### Your Turn diff --git a/_en/players/sfinv.md b/_en/players/sfinv.md index 19c908e..6671103 100644 --- a/_en/players/sfinv.md +++ b/_en/players/sfinv.md @@ -1,242 +1,5 @@ --- -title: "SFINV: Inventory Formspec" -layout: default -root: ../.. -idx: 4.7 +sitemap: false redirect_from: /en/chapters/sfinv.html +redirect_to: "https://github.com/rubenwardy/sfinv/blob/master/Tutorial.md" --- - -## Introduction - -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. - -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. - -- [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) - -## Registering a Page - -SFINV provides the aptly named `sfinv.register_page` function to create pages. -Simply call the function with the page's name and its definition: - -```lua -sfinv.register_page("mymod:hello", { - title = "Hello!", - get = function(self, player, context) - return sfinv.make_formspec(player, context, - "label[0.1,0.1;Hello world!]", 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. - -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. - -```lua -sfinv.register_page("myadmin:myadmin", { - title = "Tab", - get = function(self, player, context) - local players = {} - context.myadmin_players = players - - -- Using an array to build a formspec is considerably faster - local formspec = { - "textlist[0.1,0.1;7.8,3;playerlist;" - } - - -- 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 - formspec[#formspec + 1] = "," - end - formspec[#formspec + 1] = - minetest.formspec_escape(player_name) - is_first = 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]" - - -- Wrap the formspec in sfinv's layout - -- (ie: adds the tabs and background) - 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. - -
- Player Admin Page -
- -## Receiving events - -You can receive formspec events by adding a `on_player_receive_fields` function -to a sfinv definition. - -```lua -on_player_receive_fields = function(self, player, context, fields) - -- TODO: implement this -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. - -Now let's implement the `on_player_receive_fields` for our admin 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) - if event.type == "CHG" then - context.myadmin_selected_idx = event.index - end - - -- Kick button was pressed - elseif fields.kick then - local player_name = - context.myadmin_players[context.myadmin_selected_idx] - if player_name then - minetest.chat_send_player(player:get_player_name(), - "Kicked " .. player_name) - minetest.kick_player(player_name) - end - - -- Ban button was pressed - elseif fields.ban then - local player_name = - context.myadmin_players[context.myadmin_selected_idx] - 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") - 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! - -## Conditionally showing to players - -You can add an `is_in_nav` function to your page's definition if you'd like to -control when the page is shown: - -```lua -is_in_nav = function(self, player, context) - local privs = minetest.get_player_privs(player:get_player_name()) - return privs.kick or privs.ban -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`. - -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. - -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: - -```lua -local function on_grant_revoke(grantee, granter, priv) - if priv ~= "kick" and priv ~= "ban" then - return - end - - local player = minetest.get_player_by_name(grantee) - if not player then - return - end - - local context = sfinv.get_or_create_context(player) - if context.page ~= "myadmin:myadmin" then - return - end - - sfinv.set_player_inventory_formspec(player, context) -end - -minetest.register_on_priv_grant(on_grant_revoke) -minetest.register_on_priv_revoke(on_grant_revoke) -``` - -## on_enter and on_leave callbacks - -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. - -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. - -It's not possible to cancel a page change, as that would potentially -confuse the player. - -```lua -on_enter = function(self, player, context) - -end, - -on_leave = function(self, player, context) - -end, -``` - -## Adding to an existing page - -To add content to an existing page, you will need to override the page -and modify the returned formspec. - -```lua -local old_func = sfinv.registered_pages["sfinv:crafting"].get -sfinv.override_page("sfinv:crafting", { - get = function(self, player, context, ...) - local ret = old_func(self, player, context, ...) - - if type(ret) == "table" then - ret.formspec = ret.formspec .. "label[0,0;Hello]" - else - -- Backwards compatibility - ret = ret .. "label[0,0;Hello]" - end - - return ret - end -}) -``` diff --git a/_it/players/formspecs.md b/_it/players/formspecs.md index a8d42dc..46a9201 100644 --- a/_it/players/formspecs.md +++ b/_it/players/formspecs.md @@ -29,16 +29,16 @@ Tieni presente che se non si ha bisogno di ricevere input dal giocatore, per ese - [Coordinate reali o datate](#coordinate-reali-o-datate) - [Anatomia di un formspec](#anatomia-di-un-formspec) - - [Elementi](#elementi) - - [Intestazione](#intestazione) + - [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) + - [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) + - [Formspec nei nodi](#formspec-nei-nodi) + - [Inventario del giocatore](#inventario-del-giocatore) + - [Il tuo turno](#il-tuo-turno) ## Coordinate reali o datate @@ -321,7 +321,7 @@ 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 è `""`. 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. +La mod ufficialmente raccomandata è [SFINV](https://github.com/rubenwardy/sfinv/blob/master/Tutorial.md), ed è inclusa in Minetest Game. ### Il tuo turno diff --git a/_it/players/sfinv.md b/_it/players/sfinv.md index a5dcb3b..1fd6fdd 100644 --- a/_it/players/sfinv.md +++ b/_it/players/sfinv.md @@ -1,223 +1,4 @@ --- -title: "SFINV" -layout: default -root: ../.. -idx: 4.7 -description: una mod per rendere più semplice la creazione di un inventario complesso -redirect_from: /it/chapters/sfinv.html +sitemap: false +redirect_to: "https://github.com/rubenwardy/sfinv/blob/master/Tutorial.md" --- - -## Introduzione - -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. - -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. - -- [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) - -## Registrare una pagina - -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("miamod:ciao", { - title = "Ciao!", - get = function(self, player, context) - return sfinv.make_formspec(player, context, - "label[0.1,0.1;Ciao mondo!]", true) - end -}) -``` - -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. - -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("mioadmin:mioadmin", { - title = "Finestra", - get = function(self, player, context) - local giocatori = {} - context.mioadmin_giocatori = giocatori - - -- Usare un array per costruire un formspec è decisamente più veloce - local formspec = { - "textlist[0.1,0.1;7.8,3;lista_giocatori;" - } - - -- 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(nome_giocatore) - primo = false - end - formspec[#formspec + 1] = "]" - - -- 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]" - - -- 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, -}) -``` - -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. - -
- Pagina per gli amministratori -
- -## Ricevere eventi - -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: implementarlo -end, -``` - -`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. - -Implementiamo ora `on_player_receive_fields` nella mod: - -```lua -on_player_receive_fields = function(self, player, context, fields) - -- 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.mioadmin_sel_id = event.index - end - - -- 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(), - "Cacciato " .. nome_giocatore) - minetest.kick_player(nome_giocatore) - end - - -- 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(nome_giocatore) - minetest.kick_player(nome_giocatore, "Banned") - end - end -end, -``` - -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! - -## Condizioni per la visualizzazione - -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) - local privs = minetest.get_player_privs(player:get_player_name()) - return privs.kick or privs.ban -end, -``` - -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`. - -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. - -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 al_cambio_privilegi(nome_target, nome_garante, priv) - if priv ~= "kick" and priv ~= "ban" then - return - end - - local giocatore = minetest.get_player_by_name(nome_target) - if not giocatore then - return - end - - local contesto = sfinv.get_or_create_context(giocatore) - if contesto.page ~= "mioadmin:mioadmin" then - return - end - - sfinv.set_player_inventory_formspec(giocatore, contesto) -end - -minetest.register_on_priv_grant(al_cambio_privilegi) -minetest.register_on_priv_revoke(al_cambio_privilegi) -``` - -## Callback on_enter e on_leave - -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. - -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. - -Infine, non è possibile annullare il cambio pagina, in quanto potrebbe potenzialmente confondere il giocatore. - -```lua -on_enter = function(self, player, context) - -end, - -on_leave = function(self, player, context) - -end, -``` - -## Aggiungere a una pagina esistente - -Per aggiungere contenuti a una pagina che già esiste, avrai bisogno di sovrascrivere la pagina e modificare il formspec che viene ritornato: - -```lua -local vecchia_funzione = sfinv.registered_pages["sfinv:crafting"].get -sfinv.override_page("sfinv:crafting", { - get = function(self, player, context, ...) - local ret = vecchia_funzione(self, player, context, ...) - - if type(ret) == "table" then - ret.formspec = ret.formspec .. "label[0,0;Ciao]" - else - -- Retrocompatibilità - ret = ret .. "label[0,0;Ciao]" - end - - return ret - end -}) -``` diff --git a/_layouts/default.html b/_layouts/default.html index 5e131e4..f7c609a 100644 --- a/_layouts/default.html +++ b/_layouts/default.html @@ -8,11 +8,12 @@ layout: base {% if language == "_it" %} {% assign language = "it" %} - {% assign links = site.it | sort: "idx" %} + {% assign links = site.it %} {% else %} {% assign language = "en" %} - {% assign links = site.en | sort: "idx" %} + {% assign links = site.en %} {% endif %} +{% assign links = links | where_exp: "item", "item.sitemap != false" | sort: "idx" %} {% assign num = 0 %}