Formspecs: created
This commit is contained in:
parent
0b0c52865c
commit
fe3d75da53
@ -11,6 +11,7 @@
|
||||
<li><a href="{{ page.root }}index.html" class="title">Minetest Tutorials</a></li>
|
||||
<li><a href="{{ page.root }}chapters/folders.html">1 - Folder Structure</a></li>
|
||||
<li><a href="{{ page.root }}chapters/nodes_items_crafting.html">2 - Nodes, Items and Crafting</a></li>
|
||||
<li><a href="{{ page.root }}chapters/formspecs.html">3 - Formspecs</a></li>
|
||||
<li><hr></li>
|
||||
<li><a href="{{ page.root }}book_index.html">Index</a></li>
|
||||
</ul>
|
||||
|
@ -7,10 +7,14 @@ layout: default
|
||||
## C
|
||||
* Craft item
|
||||
* [Registering Nodes and Items]({{ page.root }}chapters/nodes_items_crafting.html#registering-a-craftitem)
|
||||
* Context
|
||||
* [Formspecs]({{ page.root }}chapters/formspecs.html)
|
||||
|
||||
## F
|
||||
* Food
|
||||
* [Registering Nodes and Items]({{ page.root }}chapters/nodes_items_crafting.html#foods)
|
||||
* Formspec
|
||||
* [Formspecs]({{ page.root }}chapters/formspecs.html)
|
||||
|
||||
## I
|
||||
* Item String
|
||||
@ -21,5 +25,3 @@ layout: default
|
||||
* [Registering Nodes and Items]({{ page.root }}chapters/nodes_items_crafting.html#item-strings)
|
||||
* Nodes
|
||||
* [Registering Nodes and Items]({{ page.root }}chapters/nodes_items_crafting.html#registering-a-basic-node)
|
||||
* Node boxes
|
||||
* [Registering Nodes and Items]({{ page.root }}chapters/nodes_items_crafting.html#node-boxes)
|
||||
|
181
chapters/formspecs.md
Normal file
181
chapters/formspecs.md
Normal file
@ -0,0 +1,181 @@
|
||||
---
|
||||
title: Formspecs
|
||||
layout: default
|
||||
root: ../
|
||||
---
|
||||
|
||||
Introduction
|
||||
------------
|
||||
|
||||
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 like the Inventory which allow you to move your mouse
|
||||
and enter information.
|
||||
You should consider using Heads Up Display (HUD) elements if you do
|
||||
not need to get user input - notifications, for example - as unexpected windows
|
||||
tend to disrupt game play.
|
||||
|
||||
* Formspec syntax
|
||||
* Displaying Forms
|
||||
* Callbacks
|
||||
* Contexts
|
||||
|
||||
|
||||
Formspec Syntax
|
||||
---------------
|
||||
|
||||
Formspecs have a rather weird syntax.
|
||||
They consist of a series of tags which are in the following form:
|
||||
|
||||
element[param1;param2;...]
|
||||
|
||||
Firstly the element type is declared, and then the attributes are given in square brackets.
|
||||
|
||||
### Size[w, h]
|
||||
|
||||
Nearly all forms have a size tag. They are used to declare the size of the window required.
|
||||
**Forms don't use pixels as co-ordinates, they use a grid**, based on inventories.
|
||||
A size of (1, 1) means the form is big enough to host a 1x1 inventory.
|
||||
The reason this is used is because it is independent on screen resolution -
|
||||
The form should work just as well on large screens as small screens.
|
||||
You can use decimals in sizes and co-ordinates.
|
||||
|
||||
size[5,2]
|
||||
|
||||
Co-ordinates and sizes only use one attribute.
|
||||
The x and y values are separated by a comma, as you can see above.
|
||||
|
||||
### Field[x, y; w, h; name; label; default]
|
||||
|
||||
Most elements follow a similar form to this. The name attribute is used in callbacks
|
||||
to get the submitted information. The others are pretty self-explaintary.
|
||||
|
||||
field[1,1;3,1;firstname;Firstname;]
|
||||
|
||||
It is perfectly valid to not define an attribute, like above.
|
||||
|
||||
### Other Elements
|
||||
|
||||
You should look in [lua_api.txt](https://github.com/minetest/minetest/blob/master/doc/lua_api.txt#L1019)
|
||||
for a list of all possible elements, just search for "Formspec".
|
||||
It is near line 1019, at time of writing.
|
||||
|
||||
Displaying Formspecs
|
||||
--------------------
|
||||
|
||||
Here is a generalized way to show a formspec
|
||||
|
||||
minetest.show_formspec(playername, formname, formspec)
|
||||
|
||||
Formnames should be itemnames, however that is not enforced.
|
||||
There is no need to override a formspec here, formspecs are not registered like
|
||||
nodes and items are, instead the formspec code is sent to the player's client for them
|
||||
to see, along with the formname.
|
||||
Formnames are used in callbacks to identify which form has been submitted,
|
||||
and see if the callback is relevant.
|
||||
|
||||
Callbacks
|
||||
---------
|
||||
|
||||
{% highlight lua %}
|
||||
-- Show form when the /formspec command is used.
|
||||
minetest.register_chatcommand("formspec", {
|
||||
func = function(name, param)
|
||||
minetest.show_formspec(name, "mymod:form",
|
||||
"size[4,3]" ..
|
||||
"label[0,0;Hello, " .. name .. "]" ..
|
||||
"field[1,1.5;3,1;name;Name;]" ..
|
||||
"button_exit[1,2;2,1;exit;Save]")
|
||||
end
|
||||
})
|
||||
|
||||
-- Register callback
|
||||
minetest.register_on_player_receive_fields(function(player, formname, fields)
|
||||
if formname ~= "mymod:form" then
|
||||
-- Formname is not mymod:form,
|
||||
-- exit callback.
|
||||
return false
|
||||
end
|
||||
|
||||
-- Send message to player.
|
||||
minetest.chat_send_player(player:get_player_name(), "You said: " .. fields.name .. "!")
|
||||
|
||||
-- Return true to stop other minetest.register_on_player_receive_fields
|
||||
-- from receiving this submission.
|
||||
return true
|
||||
end)
|
||||
{% endhighlight %}
|
||||
|
||||
The function given in minetest.register_on_player_receive_fields is called
|
||||
everytime a user submits a form. Most callbacks will 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 all forms - it depends on what you
|
||||
want to do.
|
||||
|
||||
### Fields
|
||||
|
||||
The fields parameter to the function is a table, index by string, of the values
|
||||
submitted by the user. You can access values in the table by doing fields.name,
|
||||
where 'name' is the name of the element.
|
||||
|
||||
As well as having the values of each element, you can also get which button
|
||||
was clicked. In this case, the button called 'exit' was clicked, so fields.exit
|
||||
will be true.
|
||||
|
||||
Some elements can submit the form without the user having to click a button,
|
||||
such as a check box. You can detect for these cases by looking
|
||||
for a clicked button.
|
||||
|
||||
Contexts
|
||||
--------
|
||||
|
||||
In quite a lot of cases you want your minetest.show_formspec to give information
|
||||
to the callback which you don't want to have to send to the client. Information
|
||||
such as what a chat command was called with, or what the dialog is about.
|
||||
|
||||
Let's say you are making a form to handle land protection information. Here is
|
||||
how you would do it:
|
||||
|
||||
{% highlight lua %}
|
||||
local land_formspec_context = {}
|
||||
|
||||
minetest.register_chatcommand("land", {
|
||||
func = function(name, param)
|
||||
if param == "" then
|
||||
minetest.chat_send_player(name, "Incorrect parameters - supply a land ID")
|
||||
return
|
||||
end
|
||||
|
||||
-- Save information
|
||||
land_formspec_context[name] = {id = param}
|
||||
|
||||
minetest.show_formspec(name, "mylandowner:edit",
|
||||
"size[4,4]" ..
|
||||
"field[1,1;3,1;plot;Plot Name;]" ..
|
||||
"field[1,2;3,1;owner;Owner;]" ..
|
||||
"button_exit[1,3;2,1;exit;Save]")
|
||||
end
|
||||
})
|
||||
|
||||
minetest.register_on_player_receive_fields(function(player, formname, fields)
|
||||
if formname ~= "mylandowner:edit" then
|
||||
return false
|
||||
end
|
||||
|
||||
-- Load information
|
||||
local context = land_formspec_context[player:get_player_name()]
|
||||
|
||||
if context then
|
||||
minetest.chat_send_player(player:get_player_name(), "Id " .. context.id .. " is now called " ..
|
||||
fields.plot .. " and owned by " .. fields.owner)
|
||||
|
||||
-- Delete context if it is no longer going to be used
|
||||
land_formspec_context[player:get_player_name()] = nil
|
||||
|
||||
return true
|
||||
else
|
||||
-- Fail gracefully if the context does not exist.
|
||||
minetest.chat_send_player(player:get_player_name(), "Something went wrong, try again.")
|
||||
end
|
||||
end)
|
||||
{% endhighlight %}
|
Loading…
Reference in New Issue
Block a user