forked from your-land-mirror/minetest-flow
Luanti rename, add ButtonURL support
This commit is contained in:
parent
136f2b1637
commit
f306f01f57
@ -5,11 +5,11 @@ globals = {
|
||||
}
|
||||
|
||||
read_globals = {
|
||||
'core',
|
||||
'dump',
|
||||
'formspec_ast',
|
||||
'fs51',
|
||||
'hud_fs',
|
||||
'minetest',
|
||||
string = {fields = {'split', 'trim'}},
|
||||
table = {fields = {'copy', 'indexof'}}
|
||||
}
|
||||
|
20
README.md
20
README.md
@ -1,8 +1,8 @@
|
||||
# flow
|
||||
|
||||
[](https://content.minetest.net/packages/luk3yx/flow/)
|
||||
[](https://content.luanti.org/packages/luk3yx/flow/)
|
||||
|
||||
An experimental layout manager and formspec API replacement for Minetest.
|
||||
An experimental layout manager and formspec API replacement for Luanti (formerly Minetest).
|
||||
Vaguely inspired by Flutter and GTK.
|
||||
|
||||
[Online tutorial/demo](https://luk3yx.gitlab.io/minetest-flow-playground/)
|
||||
@ -28,14 +28,14 @@ Vaguely inspired by Flutter and GTK.
|
||||
- No having to worry about state.
|
||||
- Values of fields, scrollbars, checkboxes, etc are remembered when
|
||||
redrawing a form and are automatically applied.
|
||||
- Has an [inspector mod](https://content.minetest.net/packages/luk3yx/flow_inspector/)
|
||||
- Has an [inspector mod](https://content.luanti.org/packages/luk3yx/flow_inspector/)
|
||||
to help with developing and debugging forms.
|
||||
- Some common security issues with formspec input handling are mitigated.
|
||||
|
||||
## Limitations
|
||||
|
||||
- This mod doesn't support all of the features that regular formspecs do.
|
||||
- [FS51](https://content.minetest.net/packages/luk3yx/fs51/) is required if
|
||||
- [FS51](https://content.luanti.org/packages/luk3yx/fs51/) is required if
|
||||
you want to have full support for Minetest 5.3 and below.
|
||||
- Make sure you're using the latest version of flow if you are on MT 5.10-dev
|
||||
or later, older versions used a hack which no longer works.
|
||||
@ -74,7 +74,7 @@ local my_gui = flow.make_gui(function(player, ctx)
|
||||
on_event = function(player, ctx)
|
||||
-- flow should guarantee that `ctx.form.my_dropdown` exists, even if the client doesn't send my_dropdown to the server.
|
||||
local selected_idx = ctx.form.my_dropdown
|
||||
minetest.chat_send_player(player:get_player_name(), "You have selected item #" .. selected_idx .. "!")
|
||||
core.chat_send_player(player:get_player_name(), "You have selected item #" .. selected_idx .. "!")
|
||||
end,
|
||||
}
|
||||
}
|
||||
@ -118,7 +118,7 @@ end)
|
||||
|
||||
-- Re-shows the form for all players with the "server" privilege
|
||||
my_gui:update_where(function(player, ctx)
|
||||
return minetest.check_player_privs(player, "server")
|
||||
return core.check_player_privs(player, "server")
|
||||
end)
|
||||
|
||||
-- Re-shows the form for all players with the form open
|
||||
@ -148,12 +148,12 @@ a newline without pasting it in).
|
||||
These utilities likely aren't compatible with flow.
|
||||
|
||||
- [fs_layout](https://github.com/fluxionary/minetest-fs_layout/) is another mod library that does automatic formspec element positioning.
|
||||
- [fslib](https://content.minetest.net/packages/LMD/fslib/) is a small mod library that lets you build formspec strings.
|
||||
- [Just_Visiting's formspec editor](https://content.minetest.net/packages/Just_Visiting/formspec_editor) is a Minetest (sub)game that lets you edit formspecs and preview them as you go
|
||||
- [fslib](https://content.luanti.org/packages/LMD/fslib/) is a small mod library that lets you build formspec strings.
|
||||
- [Just_Visiting's formspec editor](https://content.luanti.org/packages/Just_Visiting/formspec_editor) is a Minetest (sub)game that lets you edit formspecs and preview them as you go
|
||||
- [kuto](https://github.com/TerraQuest-Studios/kuto/) is a formspec library that has some extra widgets/components and has a callback API. Some automatic sizing can be done for buttons.
|
||||
- It may be possible to use kuto's components with flow somehow as they both use formspec_ast internally.
|
||||
- kuto was the the source of the "on_event" function idea.
|
||||
- [My web-based formspec editor](https://forum.minetest.net/viewtopic.php?f=14&t=24130) lets you add elements and drag+drop them, however it doesn't support all formspec features.
|
||||
- [My web-based formspec editor](https://forum.luanti.org/viewtopic.php?f=14&t=24130) lets you add elements and drag+drop them, however it doesn't support all formspec features.
|
||||
|
||||
## Elements
|
||||
|
||||
@ -469,7 +469,7 @@ player. Elements hidden this way will still take up space like with
|
||||
<summary><b>Using a form as an inventory</b></summary>
|
||||
|
||||
> [!TIP]
|
||||
> Consider using [Sway](https://content.minetest.net/packages/lazerbeak12345/sway/)
|
||||
> Consider using [Sway](https://content.luanti.org/packages/lazerbeak12345/sway/)
|
||||
> instead if you want to use flow as an inventory replacement while still
|
||||
> having some way for other mods to extend the inventory.
|
||||
|
||||
|
128
elements.md
128
elements.md
@ -4,11 +4,11 @@ This is probably broken.
|
||||
|
||||
### `gui.AnimatedImage`
|
||||
|
||||
Equivalent to Minetest's `animated_image[]` element.
|
||||
Equivalent to Luanti's `animated_image[]` element.
|
||||
|
||||
**Example**
|
||||
```lua
|
||||
gui.AnimatedImage {
|
||||
gui.AnimatedImage{
|
||||
w = 1,
|
||||
h = 2,
|
||||
name = "my_animated_image", -- Optional
|
||||
@ -33,11 +33,11 @@ gui.AnimatedImage {
|
||||
|
||||
### `gui.Box`
|
||||
|
||||
Equivalent to Minetest's `box[]` element.
|
||||
Equivalent to Luanti's `box[]` element.
|
||||
|
||||
**Example**
|
||||
```lua
|
||||
gui.Box {
|
||||
gui.Box{
|
||||
w = 1, -- Optional
|
||||
h = 2, -- Optional
|
||||
color = "#FF0000",
|
||||
@ -46,11 +46,11 @@ gui.Box {
|
||||
|
||||
### `gui.Button`
|
||||
|
||||
Equivalent to Minetest's `button[]` element.
|
||||
Equivalent to Luanti's `button[]` element.
|
||||
|
||||
**Example**
|
||||
```lua
|
||||
gui.Button {
|
||||
gui.Button{
|
||||
w = 1, -- Optional
|
||||
h = 2, -- Optional
|
||||
name = "my_button", -- Optional
|
||||
@ -60,11 +60,11 @@ gui.Button {
|
||||
|
||||
### `gui.ButtonExit`
|
||||
|
||||
Equivalent to Minetest's `button_exit[]` element.
|
||||
Equivalent to Luanti's `button_exit[]` element.
|
||||
|
||||
**Example**
|
||||
```lua
|
||||
gui.ButtonExit {
|
||||
gui.ButtonExit{
|
||||
w = 1, -- Optional
|
||||
h = 2, -- Optional
|
||||
name = "my_button_exit", -- Optional
|
||||
@ -72,13 +72,43 @@ gui.ButtonExit {
|
||||
}
|
||||
```
|
||||
|
||||
### `gui.Checkbox`
|
||||
### `gui.ButtonURL`
|
||||
|
||||
Equivalent to Minetest's `checkbox[]` element.
|
||||
Equivalent to Luanti's `button_url[]` element.
|
||||
|
||||
**Example**
|
||||
```lua
|
||||
gui.Checkbox {
|
||||
gui.ButtonURL{
|
||||
w = 1, -- Optional
|
||||
h = 2, -- Optional
|
||||
name = "my_button_url", -- Optional
|
||||
label = "Hello world!",
|
||||
url = "Hello world!",
|
||||
}
|
||||
```
|
||||
|
||||
### `gui.ButtonUrlExit`
|
||||
|
||||
Equivalent to Luanti's `button_url_exit[]` element.
|
||||
|
||||
**Example**
|
||||
```lua
|
||||
gui.ButtonUrlExit{
|
||||
w = 1, -- Optional
|
||||
h = 2, -- Optional
|
||||
name = "my_button_url_exit", -- Optional
|
||||
label = "Hello world!",
|
||||
url = "Hello world!",
|
||||
}
|
||||
```
|
||||
|
||||
### `gui.Checkbox`
|
||||
|
||||
Equivalent to Luanti's `checkbox[]` element.
|
||||
|
||||
**Example**
|
||||
```lua
|
||||
gui.Checkbox{
|
||||
name = "my_checkbox", -- Optional
|
||||
label = "Hello world!",
|
||||
selected = false, -- Optional
|
||||
@ -87,11 +117,11 @@ gui.Checkbox {
|
||||
|
||||
### `gui.Dropdown`
|
||||
|
||||
Equivalent to Minetest's `dropdown[]` element.
|
||||
Equivalent to Luanti's `dropdown[]` element.
|
||||
|
||||
**Example**
|
||||
```lua
|
||||
gui.Dropdown {
|
||||
gui.Dropdown{
|
||||
w = 1, -- Optional
|
||||
h = 2, -- Optional
|
||||
name = "my_dropdown", -- Optional
|
||||
@ -103,11 +133,11 @@ gui.Dropdown {
|
||||
|
||||
### `gui.Field`
|
||||
|
||||
Equivalent to Minetest's `field[]` element.
|
||||
Equivalent to Luanti's `field[]` element.
|
||||
|
||||
**Example**
|
||||
```lua
|
||||
gui.Field {
|
||||
gui.Field{
|
||||
w = 1, -- Optional
|
||||
h = 2, -- Optional
|
||||
name = "my_field", -- Optional
|
||||
@ -122,11 +152,11 @@ gui.Field {
|
||||
|
||||
### `gui.Hypertext`
|
||||
|
||||
Equivalent to Minetest's `hypertext[]` element.
|
||||
Equivalent to Luanti's `hypertext[]` element.
|
||||
|
||||
**Example**
|
||||
```lua
|
||||
gui.Hypertext {
|
||||
gui.Hypertext{
|
||||
w = 1,
|
||||
h = 2,
|
||||
name = "my_hypertext", -- Optional
|
||||
@ -136,11 +166,11 @@ gui.Hypertext {
|
||||
|
||||
### `gui.Image`
|
||||
|
||||
Equivalent to Minetest's `image[]` element.
|
||||
Equivalent to Luanti's `image[]` element.
|
||||
|
||||
**Example**
|
||||
```lua
|
||||
gui.Image {
|
||||
gui.Image{
|
||||
w = 1,
|
||||
h = 2,
|
||||
texture_name = "texture.png",
|
||||
@ -153,11 +183,11 @@ gui.Image {
|
||||
|
||||
### `gui.ImageButton`
|
||||
|
||||
Equivalent to Minetest's `image_button[]` element.
|
||||
Equivalent to Luanti's `image_button[]` element.
|
||||
|
||||
**Example**
|
||||
```lua
|
||||
gui.ImageButton {
|
||||
gui.ImageButton{
|
||||
w = 1,
|
||||
h = 2,
|
||||
texture_name = "texture.png",
|
||||
@ -171,11 +201,11 @@ gui.ImageButton {
|
||||
|
||||
### `gui.ImageButtonExit`
|
||||
|
||||
Equivalent to Minetest's `image_button_exit[]` element.
|
||||
Equivalent to Luanti's `image_button_exit[]` element.
|
||||
|
||||
**Example**
|
||||
```lua
|
||||
gui.ImageButtonExit {
|
||||
gui.ImageButtonExit{
|
||||
w = 1,
|
||||
h = 2,
|
||||
texture_name = "texture.png",
|
||||
@ -189,11 +219,11 @@ gui.ImageButtonExit {
|
||||
|
||||
### `gui.ItemImage`
|
||||
|
||||
Equivalent to Minetest's `item_image[]` element.
|
||||
Equivalent to Luanti's `item_image[]` element.
|
||||
|
||||
**Example**
|
||||
```lua
|
||||
gui.ItemImage {
|
||||
gui.ItemImage{
|
||||
w = 1,
|
||||
h = 2,
|
||||
item_name = "Hello world!",
|
||||
@ -202,11 +232,11 @@ gui.ItemImage {
|
||||
|
||||
### `gui.ItemImageButton`
|
||||
|
||||
Equivalent to Minetest's `item_image_button[]` element.
|
||||
Equivalent to Luanti's `item_image_button[]` element.
|
||||
|
||||
**Example**
|
||||
```lua
|
||||
gui.ItemImageButton {
|
||||
gui.ItemImageButton{
|
||||
w = 1,
|
||||
h = 2,
|
||||
item_name = "Hello world!",
|
||||
@ -217,22 +247,22 @@ gui.ItemImageButton {
|
||||
|
||||
### `gui.Label`
|
||||
|
||||
Equivalent to Minetest's `label[]` element.
|
||||
Equivalent to Luanti's `label[]` element.
|
||||
|
||||
**Example**
|
||||
```lua
|
||||
gui.Label {
|
||||
gui.Label{
|
||||
label = "Hello world!",
|
||||
}
|
||||
```
|
||||
|
||||
### `gui.List`
|
||||
|
||||
Equivalent to Minetest's `list[]` element.
|
||||
Equivalent to Luanti's `list[]` element.
|
||||
|
||||
**Example**
|
||||
```lua
|
||||
gui.List {
|
||||
gui.List{
|
||||
inventory_location = "Hello world!",
|
||||
list_name = "Hello world!",
|
||||
w = 1,
|
||||
@ -246,11 +276,11 @@ gui.List {
|
||||
|
||||
### `gui.Model`
|
||||
|
||||
Equivalent to Minetest's `model[]` element.
|
||||
Equivalent to Luanti's `model[]` element.
|
||||
|
||||
**Example**
|
||||
```lua
|
||||
gui.Model {
|
||||
gui.Model{
|
||||
w = 1,
|
||||
h = 2,
|
||||
name = "my_model", -- Optional
|
||||
@ -278,11 +308,11 @@ gui.Model {
|
||||
|
||||
### `gui.Pwdfield`
|
||||
|
||||
Equivalent to Minetest's `pwdfield[]` element.
|
||||
Equivalent to Luanti's `pwdfield[]` element.
|
||||
|
||||
**Example**
|
||||
```lua
|
||||
gui.Pwdfield {
|
||||
gui.Pwdfield{
|
||||
w = 1, -- Optional
|
||||
h = 2, -- Optional
|
||||
name = "my_pwdfield", -- Optional
|
||||
@ -292,11 +322,11 @@ gui.Pwdfield {
|
||||
|
||||
### `gui.Table`
|
||||
|
||||
Equivalent to Minetest's `table[]` element.
|
||||
Equivalent to Luanti's `table[]` element.
|
||||
|
||||
**Example**
|
||||
```lua
|
||||
gui.Table {
|
||||
gui.Table{
|
||||
w = 1, -- Optional
|
||||
h = 2, -- Optional
|
||||
name = "my_table", -- Optional
|
||||
@ -309,11 +339,11 @@ gui.Table {
|
||||
|
||||
### `gui.TableColumns`
|
||||
|
||||
Equivalent to Minetest's `tablecolumns[]` element.
|
||||
Equivalent to Luanti's `tablecolumns[]` element.
|
||||
|
||||
**Example**
|
||||
```lua
|
||||
gui.TableColumns {
|
||||
gui.TableColumns{
|
||||
tablecolumns = {
|
||||
{
|
||||
type = "text",
|
||||
@ -326,22 +356,22 @@ gui.TableColumns {
|
||||
|
||||
### `gui.TableOptions`
|
||||
|
||||
Equivalent to Minetest's `tableoptions[]` element.
|
||||
Equivalent to Luanti's `tableoptions[]` element.
|
||||
|
||||
**Example**
|
||||
```lua
|
||||
gui.TableOptions {
|
||||
gui.TableOptions{
|
||||
opts = {field = "value"},
|
||||
}
|
||||
```
|
||||
|
||||
### `gui.Textarea`
|
||||
|
||||
Equivalent to Minetest's `textarea[]` element.
|
||||
Equivalent to Luanti's `textarea[]` element.
|
||||
|
||||
**Example**
|
||||
```lua
|
||||
gui.Textarea {
|
||||
gui.Textarea{
|
||||
w = 1, -- Optional
|
||||
h = 2, -- Optional
|
||||
name = "my_textarea", -- Optional
|
||||
@ -352,11 +382,11 @@ gui.Textarea {
|
||||
|
||||
### `gui.Textlist`
|
||||
|
||||
Equivalent to Minetest's `textlist[]` element.
|
||||
Equivalent to Luanti's `textlist[]` element.
|
||||
|
||||
**Example**
|
||||
```lua
|
||||
gui.Textlist {
|
||||
gui.Textlist{
|
||||
w = 1, -- Optional
|
||||
h = 2, -- Optional
|
||||
name = "my_textlist", -- Optional
|
||||
@ -368,11 +398,11 @@ gui.Textlist {
|
||||
|
||||
### `gui.Tooltip`
|
||||
|
||||
Equivalent to Minetest's `tooltip[]` element.
|
||||
Equivalent to Luanti's `tooltip[]` element.
|
||||
|
||||
**Example**
|
||||
```lua
|
||||
gui.Tooltip {
|
||||
gui.Tooltip{
|
||||
tooltip_text = "Hello world!",
|
||||
bgcolor = "#FF0000", -- Optional
|
||||
fontcolor = "#FF0000", -- Optional
|
||||
@ -382,11 +412,11 @@ gui.Tooltip {
|
||||
|
||||
### `gui.Vertlabel`
|
||||
|
||||
Equivalent to Minetest's `vertlabel[]` element.
|
||||
Equivalent to Luanti's `vertlabel[]` element.
|
||||
|
||||
**Example**
|
||||
```lua
|
||||
gui.Vertlabel {
|
||||
gui.Vertlabel{
|
||||
label = "Hello world!",
|
||||
}
|
||||
```
|
@ -1,5 +1,5 @@
|
||||
--
|
||||
-- Minetest formspec layout engine
|
||||
-- Luanti formspec layout engine
|
||||
--
|
||||
-- Copyright © 2022 by luk3yx
|
||||
--
|
||||
|
@ -1,5 +1,5 @@
|
||||
--
|
||||
-- Minetest formspec layout engine
|
||||
-- Luanti formspec layout engine
|
||||
--
|
||||
-- Copyright © 2022 by luk3yx
|
||||
--
|
||||
@ -19,7 +19,7 @@
|
||||
|
||||
-- You can run /flow-example in singleplayer to open this form
|
||||
local gui = flow.widgets
|
||||
local S = minetest.get_translator("flow")
|
||||
local S = core.get_translator("flow")
|
||||
|
||||
local elements = {"box", "label", "image", "field", "checkbox", "list"}
|
||||
local alignments = {"auto", "start", "end", "centre", "fill"}
|
||||
@ -99,7 +99,7 @@ local my_gui = flow.make_gui(function(player, ctx)
|
||||
ctx.form.checkbox = not ctx.form.checkbox
|
||||
|
||||
-- Send a chat message
|
||||
minetest.chat_send_player(player:get_player_name(), S"Toggled!")
|
||||
core.chat_send_player(player:get_player_name(), S"Toggled!")
|
||||
|
||||
-- Return true to tell flow to redraw the formspec
|
||||
return true
|
||||
|
@ -7,7 +7,8 @@ hide_elements = {
|
||||
'background', 'background9', 'scroll_container', 'scrollbar', 'tabheader'
|
||||
}
|
||||
hide_comments = {'x', 'y', 'w', 'h', 'name', 'selected'}
|
||||
special_case_names = {'tablecolumns': 'TableColumns',
|
||||
special_case_names = {'button_url': 'ButtonURL',
|
||||
'tablecolumns': 'TableColumns',
|
||||
'tableoptions': 'TableOptions'}
|
||||
|
||||
|
||||
@ -94,10 +95,10 @@ def element_to_docs(element_name, variants):
|
||||
|
||||
lines = [
|
||||
f'### `gui.{flow_name}`\n',
|
||||
f"Equivalent to Minetest's `{element_name}[]` element.\n",
|
||||
f"Equivalent to Luanti's `{element_name}[]` element.\n",
|
||||
'**Example**',
|
||||
'```lua',
|
||||
f'gui.{flow_name} {{'
|
||||
f'gui.{flow_name}{{'
|
||||
]
|
||||
|
||||
num = 1
|
||||
|
79
init.lua
79
init.lua
@ -1,5 +1,5 @@
|
||||
--
|
||||
-- Minetest formspec layout engine
|
||||
-- Luanti formspec layout engine
|
||||
--
|
||||
-- Copyright © 2022 by luk3yx
|
||||
--
|
||||
@ -19,8 +19,8 @@
|
||||
|
||||
local DEBUG_MODE = false
|
||||
flow = {}
|
||||
local S = minetest.get_translator("flow")
|
||||
local modpath = minetest.get_modpath("flow")
|
||||
local S = core.get_translator("flow")
|
||||
local modpath = core.get_modpath("flow")
|
||||
|
||||
local Form = {}
|
||||
|
||||
@ -83,7 +83,7 @@ local CHAR_WIDTH = 0.21
|
||||
local current_lang
|
||||
|
||||
-- get_translated_string doesn't exist in MT 5.2.0 and older
|
||||
local get_translated_string = minetest.get_translated_string or function(_, s)
|
||||
local get_translated_string = core.get_translated_string or function(_, s)
|
||||
return s
|
||||
end
|
||||
|
||||
@ -156,6 +156,7 @@ size_getters.button_exit = size_getters.button
|
||||
size_getters.image_button = size_getters.button
|
||||
size_getters.image_button_exit = size_getters.button
|
||||
size_getters.item_image_button = size_getters.button
|
||||
size_getters.button_url = size_getters.button
|
||||
|
||||
function size_getters.field(node)
|
||||
local label_w, label_h = get_label_size(node.label)
|
||||
@ -289,7 +290,7 @@ function size_getters.stack(stack)
|
||||
end
|
||||
|
||||
function size_getters.padding(node)
|
||||
minetest.log("warning", "[flow] The gui.Padding element is deprecated")
|
||||
core.log("warning", "[flow] The gui.Padding element is deprecated")
|
||||
assert(#node == 1, "Padding can only have one element inside.")
|
||||
local n = node[1]
|
||||
local x, y = apply_padding(n, 0, 0)
|
||||
@ -365,7 +366,7 @@ function align_types.fill(node, x, w, extra_space)
|
||||
if node[w] then
|
||||
node[w] = node[w] + extra_space
|
||||
else
|
||||
minetest.log("warning", "[flow] Unknown element: \"" ..
|
||||
core.log("warning", "[flow] Unknown element: \"" ..
|
||||
tostring(node.type) .. "\". Please make sure that flow is " ..
|
||||
"up-to-date and the element has a size set (if required).")
|
||||
node[w] = extra_space
|
||||
@ -541,12 +542,12 @@ end
|
||||
-- Renders the GUI into hopefully valid AST
|
||||
-- This won't fill in names
|
||||
local function render_ast(node, embedded)
|
||||
local t1 = DEBUG_MODE and minetest.get_us_time()
|
||||
local t1 = DEBUG_MODE and core.get_us_time()
|
||||
node.padding = node.padding or 0.3
|
||||
local w, h = apply_padding(node, 0, 0)
|
||||
local t2 = DEBUG_MODE and minetest.get_us_time()
|
||||
local t2 = DEBUG_MODE and core.get_us_time()
|
||||
expand(node)
|
||||
local t3 = DEBUG_MODE and minetest.get_us_time()
|
||||
local t3 = DEBUG_MODE and core.get_us_time()
|
||||
local res = {
|
||||
formspec_version = 7,
|
||||
{type = "size", w = w, h = h},
|
||||
@ -589,7 +590,7 @@ local function render_ast(node, embedded)
|
||||
res[#res + 1] = node
|
||||
|
||||
if DEBUG_MODE then
|
||||
local t4 = minetest.get_us_time()
|
||||
local t4 = core.get_us_time()
|
||||
print('apply_padding', t2 - t1)
|
||||
print('expand', t3 - t2)
|
||||
print('field_close_on_enter', t4 - t3)
|
||||
@ -627,12 +628,12 @@ local field_value_transformers = {
|
||||
-- Remove control characters and newlines
|
||||
return value:gsub("[%z\1-\8\10-\31\127]", ""):gsub(C1_CHARS, "")
|
||||
end),
|
||||
checkbox = simple_transformer(minetest.is_yes),
|
||||
checkbox = simple_transformer(core.is_yes),
|
||||
|
||||
-- Scrollbars do have min/max values but scrollbars are only really used by
|
||||
-- ScrollableVBox which doesn't need the extra checks
|
||||
scrollbar = simple_transformer(function(value)
|
||||
return minetest.explode_scrollbar_event(value).value
|
||||
return core.explode_scrollbar_event(value).value
|
||||
end),
|
||||
}
|
||||
|
||||
@ -653,7 +654,7 @@ function field_value_transformers.dropdown(node, _, formspec_version)
|
||||
-- value of the dropdown is anyway, we can just enable index_event for new
|
||||
-- clients and keep the same behaviour
|
||||
if (formspec_version and formspec_version >= 4) or
|
||||
(minetest.global_exists("fs51") and
|
||||
(core.global_exists("fs51") and
|
||||
fs51.monkey_patching_enabled) then
|
||||
node.index_event = true
|
||||
|
||||
@ -682,7 +683,7 @@ function field_value_transformers.table(node, tablecolumn_count)
|
||||
local rows = ceil(cells / tablecolumn_count)
|
||||
|
||||
return function(value)
|
||||
local row = floor(minetest.explode_table_event(value).row)
|
||||
local row = floor(core.explode_table_event(value).row)
|
||||
-- Tables and textlists can have values of 0 (nothing selected) but I
|
||||
-- don't think the client can un-select a row so it should be safe to
|
||||
-- ignore any 0 sent by the client to guarantee that the row will be
|
||||
@ -696,7 +697,7 @@ end
|
||||
function field_value_transformers.textlist(node)
|
||||
local rows = node.listelems and #node.listelems or 0
|
||||
return function(value)
|
||||
local index = floor(minetest.explode_textlist_event(value).index)
|
||||
local index = floor(core.explode_textlist_event(value).index)
|
||||
if index >= 1 and index <= rows then
|
||||
return index
|
||||
end
|
||||
@ -847,7 +848,7 @@ local function parse_callbacks(tree, ctx_form, auto_name_id,
|
||||
elseif btn_callbacks[node_name] or
|
||||
(is_btn and saved_fields[node_name]) or
|
||||
(callbacks and callbacks[node_name]) then
|
||||
minetest.log("warning", ("[flow] Multiple callbacks have " ..
|
||||
core.log("warning", ("[flow] Multiple callbacks have " ..
|
||||
"been registered for elements with the same name (%q), " ..
|
||||
"this will not work properly."):format(node_name))
|
||||
|
||||
@ -899,7 +900,7 @@ local gui_mt = {
|
||||
}
|
||||
local gui = setmetatable({
|
||||
embed = function(fs, w, h)
|
||||
minetest.log("warning", "[flow] gui.embed() is deprecated")
|
||||
core.log("warning", "[flow] gui.embed() is deprecated")
|
||||
if type(fs) ~= "table" then
|
||||
fs = formspec_ast.parse(fs)
|
||||
end
|
||||
@ -929,7 +930,7 @@ local function insert_style_elem(tree, idx, node, props, sels)
|
||||
if suffix then
|
||||
selectors[i] = base_selector .. ":" .. suffix
|
||||
else
|
||||
minetest.log("warning", "[flow] Invalid style selector: " ..
|
||||
core.log("warning", "[flow] Invalid style selector: " ..
|
||||
tostring(sel))
|
||||
end
|
||||
end
|
||||
@ -1097,15 +1098,15 @@ end
|
||||
|
||||
local function prepare_form(self, player, formname, ctx, auto_name_id)
|
||||
local name = player:get_player_name()
|
||||
-- local t = DEBUG_MODE and minetest.get_us_time()
|
||||
local info = minetest.get_player_information(name)
|
||||
-- local t = DEBUG_MODE and core.get_us_time()
|
||||
local info = core.get_player_information(name)
|
||||
local tree, form_info = self:_render(player, ctx,
|
||||
info and info.formspec_version, auto_name_id, false,
|
||||
info and info.lang_code)
|
||||
|
||||
-- local t2 = DEBUG_MODE and minetest.get_us_time()
|
||||
-- local t2 = DEBUG_MODE and core.get_us_time()
|
||||
local fs = assert(formspec_ast.unparse(tree))
|
||||
-- local t3 = DEBUG_MODE and minetest.get_us_time()
|
||||
-- local t3 = DEBUG_MODE and core.get_us_time()
|
||||
|
||||
form_info.formname = formname
|
||||
-- if DEBUG_MODE then
|
||||
@ -1121,15 +1122,15 @@ local function show_form(self, player, formname, ctx, auto_name_id)
|
||||
auto_name_id)
|
||||
|
||||
open_formspecs[name] = form_info
|
||||
minetest.show_formspec(name, formname, fs)
|
||||
core.show_formspec(name, formname, fs)
|
||||
end
|
||||
|
||||
local next_formname = 0
|
||||
function Form:show(player, ctx)
|
||||
if type(player) == "string" then
|
||||
minetest.log("warning",
|
||||
core.log("warning",
|
||||
"[flow] Calling form:show() with a player name is deprecated")
|
||||
player = minetest.get_player_by_name(player)
|
||||
player = core.get_player_by_name(player)
|
||||
if not player then return end
|
||||
end
|
||||
|
||||
@ -1142,7 +1143,7 @@ function Form:show(player, ctx)
|
||||
end
|
||||
|
||||
function Form:show_hud(player, ctx)
|
||||
local info = minetest.get_player_information(player:get_player_name())
|
||||
local info = core.get_player_information(player:get_player_name())
|
||||
local tree = self:_render(player, ctx or {}, nil, nil, nil,
|
||||
info and info.lang_code)
|
||||
hud_fs.show_hud(player, self, tree)
|
||||
@ -1177,7 +1178,7 @@ local render_to_formspec_auto_name_ids = {}
|
||||
-- target formspec version
|
||||
function Form:render_to_formspec_string(player, ctx, standalone)
|
||||
local name = player:get_player_name()
|
||||
local info = minetest.get_player_information(name)
|
||||
local info = core.get_player_information(name)
|
||||
local tree, form_info = self:_render(player, ctx or {},
|
||||
info and info.formspec_version, render_to_formspec_auto_name_ids[name],
|
||||
not standalone, info and info.lang_code)
|
||||
@ -1194,9 +1195,9 @@ function Form:render_to_formspec_string(player, ctx, standalone)
|
||||
-- Just in case the player goes offline, we should not keep the player
|
||||
-- reference. Nothing prevents the user from calling this function when
|
||||
-- the player is offline, unlike the _real_ formspec submission.
|
||||
local player = minetest.get_player_by_name(name)
|
||||
local player = core.get_player_by_name(name)
|
||||
if not player then
|
||||
minetest.log("warning", "[flow] Player " .. name ..
|
||||
core.log("warning", "[flow] Player " .. name ..
|
||||
" was offline when render_to_formspec_string event was" ..
|
||||
" triggered. Events were not passed through.")
|
||||
return nil
|
||||
@ -1211,7 +1212,7 @@ function Form:close(player)
|
||||
local form_info = open_formspecs[name]
|
||||
if form_info and form_info.self == self then
|
||||
open_formspecs[name] = nil
|
||||
minetest.close_formspec(name, form_info.formname)
|
||||
core.close_formspec(name, form_info.formname)
|
||||
end
|
||||
end
|
||||
|
||||
@ -1228,7 +1229,7 @@ function Form:unset_as_inventory_for(player)
|
||||
end
|
||||
end
|
||||
|
||||
-- This function may eventually call minetest.update_formspec if/when it gets
|
||||
-- This function may eventually call core.update_formspec if/when it gets
|
||||
-- added (https://github.com/minetest/minetest/issues/13142)
|
||||
local function update_form(self, player, form_info)
|
||||
show_form(self, player, form_info.formname, form_info.ctx,
|
||||
@ -1245,7 +1246,7 @@ end
|
||||
function Form:update_where(func)
|
||||
for name, form_info in pairs(open_formspecs) do
|
||||
if form_info.self == self then
|
||||
local player = minetest.get_player_by_name(name)
|
||||
local player = core.get_player_by_name(name)
|
||||
if player and func(player, form_info.ctx) then
|
||||
update_form(self, player, form_info)
|
||||
end
|
||||
@ -1281,7 +1282,7 @@ function fs_process_events(player, form_info, fields)
|
||||
-- potential to break things. Please open an issue if you
|
||||
-- (somehow) need to use longer text in fields.
|
||||
local name = player:get_player_name()
|
||||
minetest.log("warning", "[flow] Player " .. name .. " tried" ..
|
||||
core.log("warning", "[flow] Player " .. name .. " tried" ..
|
||||
" submitting a large field value (>60 kB), ignoring.")
|
||||
else
|
||||
local new_value = transformer(raw_value)
|
||||
@ -1327,7 +1328,7 @@ function fs_process_events(player, form_info, fields)
|
||||
return redraw_fs
|
||||
end
|
||||
|
||||
minetest.register_on_player_receive_fields(function(player, formname, fields)
|
||||
core.register_on_player_receive_fields(function(player, formname, fields)
|
||||
local name = player:get_player_name()
|
||||
local form_infos = formname == "" and open_inv_formspecs or open_formspecs
|
||||
local form_info = form_infos[name]
|
||||
@ -1350,7 +1351,7 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
|
||||
return true
|
||||
end)
|
||||
|
||||
minetest.register_on_leaveplayer(function(player)
|
||||
core.register_on_leaveplayer(function(player)
|
||||
local name = player:get_player_name()
|
||||
open_formspecs[name] = nil
|
||||
open_inv_formspecs[name] = nil
|
||||
@ -1537,9 +1538,9 @@ function gui_mt.__newindex()
|
||||
error("Cannot modifiy gui table")
|
||||
end
|
||||
|
||||
if minetest.is_singleplayer() then
|
||||
if core.is_singleplayer() then
|
||||
local example_form
|
||||
minetest.register_chatcommand("flow-example", {
|
||||
core.register_chatcommand("flow-example", {
|
||||
privs = {server = true},
|
||||
help = S"Shows an example form",
|
||||
func = function(name)
|
||||
@ -1547,7 +1548,7 @@ if minetest.is_singleplayer() then
|
||||
if not example_form then
|
||||
example_form = dofile(modpath .. "/example.lua")
|
||||
end
|
||||
example_form:show(minetest.get_player_by_name(name))
|
||||
example_form:show(core.get_player_by_name(name))
|
||||
end,
|
||||
})
|
||||
end
|
||||
@ -1557,5 +1558,5 @@ if DEBUG_MODE then
|
||||
if f then
|
||||
return f()
|
||||
end
|
||||
minetest.log("error", "[flow] " .. tostring(err))
|
||||
core.log("error", "[flow] " .. tostring(err))
|
||||
end
|
||||
|
32
test.lua
32
test.lua
@ -1,5 +1,5 @@
|
||||
--
|
||||
-- Minetest formspec layout engine
|
||||
-- Luanti formspec layout engine
|
||||
--
|
||||
-- Copyright © 2022 by luk3yx
|
||||
--
|
||||
@ -24,26 +24,26 @@ _G.FORMSPEC_AST_PATH = '../formspec_ast'
|
||||
dofile(FORMSPEC_AST_PATH .. '/init.lua')
|
||||
|
||||
-- Stub Minetest API
|
||||
_G.minetest = {}
|
||||
_G.core = {}
|
||||
|
||||
function minetest.is_yes(str)
|
||||
function core.is_yes(str)
|
||||
str = str:lower()
|
||||
return str == "true" or str == "yes"
|
||||
end
|
||||
|
||||
local callback
|
||||
function minetest.register_on_player_receive_fields(func)
|
||||
function core.register_on_player_receive_fields(func)
|
||||
assert(callback == nil)
|
||||
callback = func
|
||||
end
|
||||
|
||||
local function dummy() end
|
||||
minetest.register_on_leaveplayer = dummy
|
||||
minetest.is_singleplayer = dummy
|
||||
minetest.get_player_information = dummy
|
||||
minetest.show_formspec = dummy
|
||||
core.register_on_leaveplayer = dummy
|
||||
core.is_singleplayer = dummy
|
||||
core.get_player_information = dummy
|
||||
core.show_formspec = dummy
|
||||
|
||||
function minetest.get_modpath(modname)
|
||||
function core.get_modpath(modname)
|
||||
if modname == "flow" then
|
||||
return "."
|
||||
elseif modname == "formspec_ast" then
|
||||
@ -51,7 +51,7 @@ function minetest.get_modpath(modname)
|
||||
end
|
||||
end
|
||||
|
||||
function minetest.get_translator(modname)
|
||||
function core.get_translator(modname)
|
||||
assert(modname == "flow")
|
||||
return function(str) return str end
|
||||
end
|
||||
@ -72,7 +72,7 @@ local function stub_player(name)
|
||||
return formspec
|
||||
end
|
||||
end
|
||||
function minetest.get_player_by_name(passed_in_name)
|
||||
function core.get_player_by_name(passed_in_name)
|
||||
assert(name == passed_in_name)
|
||||
return self
|
||||
end
|
||||
@ -99,21 +99,21 @@ string.split = string.split or function(str, chr)
|
||||
return r
|
||||
end
|
||||
|
||||
function minetest.explode_textlist_event(event)
|
||||
function core.explode_textlist_event(event)
|
||||
local event_type, number = event:match("^([A-Z]+):(%d+)$")
|
||||
return {type = event_type, index = tonumber(number) or 0}
|
||||
end
|
||||
|
||||
function minetest.explode_table_event(event)
|
||||
function core.explode_table_event(event)
|
||||
local event_type, row, column = event:match("^([A-Z]+):(%d+):(%d+)$")
|
||||
return {type = event_type, row = tonumber(row) or 0, column = tonumber(column) or 0}
|
||||
end
|
||||
|
||||
function minetest.global_exists(var)
|
||||
function core.global_exists(var)
|
||||
return rawget(_G, var) ~= nil
|
||||
end
|
||||
|
||||
function minetest.get_player_information(name)
|
||||
function core.get_player_information(name)
|
||||
return name == "fs6" and {formspec_version = 6} or nil
|
||||
end
|
||||
|
||||
@ -519,7 +519,7 @@ describe("Flow", function()
|
||||
assert.equals(manual_spy[1], player, "player was first arg")
|
||||
assert.equals(manual_spy[2], ctx, "context was next")
|
||||
|
||||
minetest.get_player_by_name = nil
|
||||
core.get_player_by_name = nil
|
||||
end)
|
||||
end)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user