Initial commit

master
luk3yx 2021-03-24 08:30:33 +13:00
commit c9fffbf642
7 changed files with 879 additions and 0 deletions

11
.luacheckrc Normal file
View File

@ -0,0 +1,11 @@
max_line_length = 80
globals = {
'formspec_ast',
'minetest',
}
read_globals = {
string = {fields = {'split', 'trim'}},
table = {fields = {'copy'}}
}

22
LICENSE.md Normal file
View File

@ -0,0 +1,22 @@
# The MIT License (MIT)
Copyright © 2021 by luk3yx
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

108
README.md Normal file
View File

@ -0,0 +1,108 @@
# hud_fs
A Minetest mod library to make handling formspec-like HUDs easier. Depends on
[formspec_ast](https://content.minetest.net/packages/luk3yx/formspec_ast/).
## API
- `hud_fs.show_hud(player, formname, formspec)`: Displays or updates a HUD
with the specified formname and formspec.
- `formspec` can also be a formspec_ast tree for more advanced usage.
- `hud_fs.close_hud(player, formname)`: Closes `formname`. Equivalent to
`hud_fs.show_hud(player, formname, "")`.
The player parameter in the above function can either be a player object or a
player name.
*If you just want to manage HUDs, that's all you need to know!* Don't worry
about trying to get incremental updates or tracking HUD IDs, `hud_fs` does that
for you behind-the-scenes.
### Supported formspec features
All formspecs are assumed to be version 3 and the `formspec_version` element
(if any) is ignored.
The following elements are supported:
- `size`
- While there is no background for the HUD, this does change where the
co-ordinates start from.
- `position`, `anchor`
- **You need to use these to set the position of the HUD!**
- See [the Minetest API documentation](https://minetest.gitlab.io/minetest/formspec/#positionxy) for more info.
- You probably want `anchor` to have the same value as `position`.
- `container`
- `label`
- Because of HUD limitations, `minetest.colorize()` only works at the start
of the label.
- `image`
- `box`
- `textarea`
- If the name is non-empty a background is drawn behind the text.
- Text will overflow vertically outside the specified height.
- `item_image`
- Only works with some nodes, should work with all craftitems.
- `button`, `button_exit`, `image_button`, `image_button_exit`,
`item_image_button`
- Buttons become a grey box with a label in the middle.
- The label has the same limitations as the `label` element.
- The `noclip` option is ignored.
- Item image buttons have the same limitations as `item_image`.
All valid formspec elements not listed above are ignored.
### Advanced API
- `hud_fs.set_scale(formname, scale)`: Sets the scale of the HUD.
- All future HUDs shown with `formname` will use this scale instead of the
default (64, subject to change).
- The scale is the amount of pixels per co-ordinate. For example, a 1x1
image will have a size of 10x10 pixels if the scale is set to 10.
- `hud_fs.set_z_index(formname, z_index)`: Sets the base Z-Index of the HUD.
- All future HUDs shown with `formname` will use this z-index instead of
the default (0).
- The HUD will use z-index values from `z_index` to
`z_index + amount_of_hud_elements`.
- This won't work properly with Minetest clients older than 5.2.0.
## FAQ(?)
#### Why not implement this mod in the Minetest engine?
This mod (or anything similar) won't be implemented, a proposal to do so was
rejected in https://github.com/minetest/minetest/issues/10135.
#### Why formspecs?
- There isn't a complicated new API to learn, if you write MT mods you
probably know how to use formspecs already.
- I have a [web-based formspec editor] which can now be used to design HUDs
for use with this mod.
- You don't need any knowledge of Minetest's HUD API to use this mod.
- As this mod parses formspecs server-side, the lack of differential updates
is for the most part a non-issue.
[web-based formspec editor]: https://git.minetest.land/luk3yx/formspec-editor
#### But I hate formspecs and don't want to touch them
Then don't use this mod. There are plenty of other HUD library mods around such
as [hudlib](https://github.com/octacian/hudlib) and
[panel_lib](https://gitlab.com/zughy-friends-minetest/panel_lib).
## Performance
If this mod becomes a performance bottleneck you can try the following things:
- Move any formspec elements that are added or removed frequently to the end
of the formspec. This will allow them to be removed without touching other
elements internally.
- This mod is currently inefficient at updating HUDs when elements are
added or removed when they aren't at the end of the formspec.
- Using a formspec_ast tree instead of a formspec in show_hud. `formspec_ast`
is relatively slow at parsing formspecs at the time of writing.
- Don't call show_hud when you already know that nothing has changed. Doing so
will waste time parsing the formspec, converting it to HUD elements, then
figuring out what has changed.

173
colorstring_to_number.lua Normal file
View File

@ -0,0 +1,173 @@
--
-- hud_fs: Render formspecs into HUDs
--
-- This is the fallback parser for ColorStrings when
-- minetest.colorspec_to_colorstring doesn't exist.
--
-- From https://www.w3.org/TR/css-color-3/#svg-color
local lookup_table = {
aliceblue = 0xf0f8ff,
antiquewhite = 0xfaebd7,
aqua = 0x00ffff,
aquamarine = 0x7fffd4,
azure = 0xf0ffff,
beige = 0xf5f5dc,
bisque = 0xffe4c4,
black = 0x000000,
blanchedalmond = 0xffebcd,
blue = 0x0000ff,
blueviolet = 0x8a2be2,
brown = 0xa52a2a,
burlywood = 0xdeb887,
cadetblue = 0x5f9ea0,
chartreuse = 0x7fff00,
chocolate = 0xd2691e,
coral = 0xff7f50,
cornflowerblue = 0x6495ed,
cornsilk = 0xfff8dc,
crimson = 0xdc143c,
cyan = 0x00ffff,
darkblue = 0x00008b,
darkcyan = 0x008b8b,
darkgoldenrod = 0xb8860b,
darkgray = 0xa9a9a9,
darkgreen = 0x006400,
darkgrey = 0xa9a9a9,
darkkhaki = 0xbdb76b,
darkmagenta = 0x8b008b,
darkolivegreen = 0x556b2f,
darkorange = 0xff8c00,
darkorchid = 0x9932cc,
darkred = 0x8b0000,
darksalmon = 0xe9967a,
darkseagreen = 0x8fbc8f,
darkslateblue = 0x483d8b,
darkslategray = 0x2f4f4f,
darkslategrey = 0x2f4f4f,
darkturquoise = 0x00ced1,
darkviolet = 0x9400d3,
deeppink = 0xff1493,
deepskyblue = 0x00bfff,
dimgray = 0x696969,
dimgrey = 0x696969,
dodgerblue = 0x1e90ff,
firebrick = 0xb22222,
floralwhite = 0xfffaf0,
forestgreen = 0x228b22,
fuchsia = 0xff00ff,
gainsboro = 0xdcdcdc,
ghostwhite = 0xf8f8ff,
gold = 0xffd700,
goldenrod = 0xdaa520,
gray = 0x808080,
green = 0x008000,
greenyellow = 0xadff2f,
grey = 0x808080,
honeydew = 0xf0fff0,
hotpink = 0xff69b4,
indianred = 0xcd5c5c,
indigo = 0x4b0082,
ivory = 0xfffff0,
khaki = 0xf0e68c,
lavender = 0xe6e6fa,
lavenderblush = 0xfff0f5,
lawngreen = 0x7cfc00,
lemonchiffon = 0xfffacd,
lightblue = 0xadd8e6,
lightcoral = 0xf08080,
lightcyan = 0xe0ffff,
lightgoldenrodyellow = 0xfafad2,
lightgray = 0xd3d3d3,
lightgreen = 0x90ee90,
lightgrey = 0xd3d3d3,
lightpink = 0xffb6c1,
lightsalmon = 0xffa07a,
lightseagreen = 0x20b2aa,
lightskyblue = 0x87cefa,
lightslategray = 0x778899,
lightslategrey = 0x778899,
lightsteelblue = 0xb0c4de,
lightyellow = 0xffffe0,
lime = 0x00ff00,
limegreen = 0x32cd32,
linen = 0xfaf0e6,
magenta = 0xff00ff,
maroon = 0x800000,
mediumaquamarine = 0x66cdaa,
mediumblue = 0x0000cd,
mediumorchid = 0xba55d3,
mediumpurple = 0x9370db,
mediumseagreen = 0x3cb371,
mediumslateblue = 0x7b68ee,
mediumspringgreen = 0x00fa9a,
mediumturquoise = 0x48d1cc,
mediumvioletred = 0xc71585,
midnightblue = 0x191970,
mintcream = 0xf5fffa,
mistyrose = 0xffe4e1,
moccasin = 0xffe4b5,
navajowhite = 0xffdead,
navy = 0x000080,
oldlace = 0xfdf5e6,
olive = 0x808000,
olivedrab = 0x6b8e23,
orange = 0xffa500,
orangered = 0xff4500,
orchid = 0xda70d6,
palegoldenrod = 0xeee8aa,
palegreen = 0x98fb98,
paleturquoise = 0xafeeee,
palevioletred = 0xdb7093,
papayawhip = 0xffefd5,
peachpuff = 0xffdab9,
peru = 0xcd853f,
pink = 0xffc0cb,
plum = 0xdda0dd,
powderblue = 0xb0e0e6,
purple = 0x800080,
rebeccapurple = 0x663399,
red = 0xff0000,
rosybrown = 0xbc8f8f,
royalblue = 0x4169e1,
saddlebrown = 0x8b4513,
salmon = 0xfa8072,
sandybrown = 0xf4a460,
seagreen = 0x2e8b57,
seashell = 0xfff5ee,
sienna = 0xa0522d,
silver = 0xc0c0c0,
skyblue = 0x87ceeb,
slateblue = 0x6a5acd,
slategray = 0x708090,
slategrey = 0x708090,
snow = 0xfffafa,
springgreen = 0x00ff7f,
steelblue = 0x4682b4,
tan = 0xd2b48c,
teal = 0x008080,
thistle = 0xd8bfd8,
tomato = 0xff6347,
turquoise = 0x40e0d0,
violet = 0xee82ee,
wheat = 0xf5deb3,
white = 0xffffff,
whitesmoke = 0xf5f5f5,
yellow = 0xffff00,
yellowgreen = 0x9acd32,
}
return function(col)
if col:byte(1) == 35 then
-- Convert #123 to #112233
if #col < 7 then
col = col:gsub("[^#]", "%1%1")
end
-- Remove the alpha channel and convert to a number
return tonumber(col:sub(2, 7), 16)
end
-- Try the lookup table
return lookup_table[col:lower():match('^[^#]+')]
end

563
init.lua Normal file
View File

@ -0,0 +1,563 @@
--
-- hud_fs: Render formspecs into HUDs
--
-- Copyright © 2021 by luk3yx
--
local hud_fs = {}
local modname = minetest.get_current_modname()
_G[modname] = hud_fs
local DEBUG = false
local DEFAULT_SCALE = 64
local DEFAULT_Z_INDEX = 0
local floor, type, pairs, max = math.floor, type, pairs, math.max
local colorstring_to_number
local function colorstring_to_number_fallback(col)
colorstring_to_number_fallback = dofile(minetest.get_modpath(modname) ..
"/colorstring_to_number.lua")
return colorstring_to_number_fallback(col)
end
if minetest.colorspec_to_colorstring then
function colorstring_to_number(col)
local res = minetest.colorspec_to_colorstring(col)
if res and (res:byte(1) ~= 35 or #res < 7) then
-- Unexpected return value, go back to using the fallback parser.
minetest.log("warning", ("[hud_fs] Unexpected value returned by" ..
" minetest.colorspec_to_colorstring(%q): %q"):format(col,
res))
colorstring_to_number = colorstring_to_number_fallback
return colorstring_to_number_fallback(col)
end
return res and tonumber(res:sub(2, 7), 16)
end
else
colorstring_to_number = colorstring_to_number_fallback
end
-- Hacks to allow colorize() to work to some extent on labels
local function get_label_number(label)
local number, text = label:match("^\027%(c@([^%)]+)%)(.*)$")
-- Remove trailing escape sequence added by minetest.colorize().
if text then
text = text:gsub("\027%(c@[^%)]+%)$", "")
end
return text or label, number and colorstring_to_number(number) or 0xFFFFFF
end
local nodes = {}
function nodes.label(node, scale)
local text, number = get_label_number(node.label)
local elem = {
hud_elem_type = "text",
text = text,
alignment = {x = 1, y = 0},
number = number
}
-- Hack for newlines. This will unfortunately break if the font size is
-- changed from the default.
if elem.text:find('[\r\n]') then
elem.alignment.y = 1
node.y = node.y - 10 / scale
end
return elem
end
function nodes.image(node, scale, _, proto_ver)
local w = floor(node.w * scale)
local h = floor(node.h * scale)
local elem_scale = {x = 1, y = 1}
-- Hacks to support MultiCraft
-- This is horrible and unfortunately is applied to MT clients as well
if proto_ver == 32 then
local true_w, true_h = w, h
w, h = 2 ^ math.ceil(math.log(w, 2)), 2 ^ math.ceil(math.log(h, 2))
elem_scale.x, elem_scale.y = true_w / max(w, 1), true_h / max(h, 1)
end
local texture = node.texture_name
if w > 0 and h > 0 and texture ~= "" then
texture = "(" .. texture .. ")^[resize:" .. w .. "x" .. h
else
-- Minetest throws an error with zero-width HUD images, use blank.png
-- to keep the image around (for future HUD update calls) while
-- silencing the error.
texture = "blank.png"
end
return {
hud_elem_type = "image",
text = texture,
alignment = {x = 1, y = 1},
scale = elem_scale,
}
end
-- Hack box[] into image[]
function nodes.box(node, scale, add_node, proto_ver)
local col = node.color
-- Add default transparency
if col:byte(1) == 35 then
if #col == 4 then
col = col:gsub("[^#]", "%1%1") .. "8C"
elseif #col == 7 then
col = col .. "8C"
end
end
node.texture_name = 'hud_fs_box.png^[colorize:' .. col
return nodes.image(node, scale, add_node, proto_ver)
end
function nodes.textarea(node, scale, add_node)
-- Add in separate nodes for the label and background
if node.label ~= "" then
add_node("label", {
x = node.x,
y = node.y - 10 / scale,
label = node.label
})
end
if node.name ~= "" then
add_node("box", {
x = node.x,
y = node.y,
w = node.w,
h = node.h,
color = "#757575FF"
})
end
node.x = node.x + 5 / scale
node.y = node.y + 3 / scale
local lines = (node.default or ""):split("\n", true)
local max_line_length = node.w * scale / 8
for i, line in ipairs(lines) do
lines[i] = minetest.wrap_text(line, max_line_length)
end
return {
hud_elem_type = "text",
text = table.concat(lines, "\n"),
alignment = {x = 1, y = 1},
number = 0xFFFFFF,
scale = {x = node.w * scale, y = node.h * scale}
}
end
local function get_tile_image(tiles, preferred_texture)
local tile
for i = preferred_texture, 1, -1 do
tile = tiles[i]
if tile then break end
end
if type(tile) == "table" then tile = tile.name end
if type(tile) ~= "string" then tile = "unknown_item.png" end
return tile
end
function nodes.item_image(node, scale, add_node, proto_ver)
local def = minetest.registered_items[node.item_name]
if not def then
node.texture_name = "unknown_item.png"
elseif def.inventory_image and def.inventory_image ~= "" then
node.texture_name = def.inventory_image
elseif def.wield_image and def.wield_image ~= "" then
node.texture_name = def.wield_image
elseif def.tiles then
node.texture_name = minetest.inventorycube(
get_tile_image(def.tiles, 1),
get_tile_image(def.tiles, 6),
get_tile_image(def.tiles, 3)
)
else
node.texture_name = "unknown_node.png"
end
return nodes.image(node, scale, add_node, proto_ver)
end
function nodes.button(node, _, add_node)
-- This function is used by image_button and item_image_button as well
if node.drawborder == nil or node.drawborder then
add_node("box", {
x = node.x,
y = node.y,
w = node.w,
h = node.h,
color = "#515151FF"
})
end
if node.texture_name and node.texture_name ~= "" then
add_node("image", node)
elseif node.item_name and node.item_name ~= "" then
add_node("item_image", node)
end
node.x = node.x + node.w / 2
node.y = node.y + node.h / 2
local text, number = get_label_number(node.label)
return {
hud_elem_type = "text",
text = text,
alignment = {x = 0, y = 0},
number = number
}
end
nodes.button_exit = nodes.button
nodes.image_button = nodes.button
nodes.image_button_exit = nodes.button
nodes.item_image_button = nodes.button
local render_error
local function render(tree, proto_ver, scale, z_index)
if type(tree) == "string" then
local err
tree, err = formspec_ast.parse(tree)
if not tree then
return render_error(err)
end
end
tree = formspec_ast.flatten(tree)
-- if (tree.formspec_version or 1) < 2 then
-- return render_error("Formspec version 1 is not supported!")
-- end
local hud_elems = {}
local size_w, size_h = 0, 0
local pos = {x = 0.5, y = 0.5}
local offset_x, offset_y = 0, 0
scale = scale or DEFAULT_SCALE
z_index = z_index or DEFAULT_Z_INDEX
local function add_node(node_type, node)
local elem = nodes[node_type](node, scale, add_node, proto_ver)
elem.position = pos
elem.name = node_type
elem.z_index = z_index
elem.offset = {
x = (node.x + offset_x) * scale,
y = (node.y + offset_y) * scale
}
hud_elems[#hud_elems + 1] = elem
z_index = z_index + 1
end
for _, node in ipairs(tree) do
local node_type = node.type
if node_type == "size" then
size_w, size_h = node.w, node.h
offset_x, offset_y = -size_w / 2, -size_h / 2
elseif node_type == "position" then
pos = {x = node.x, y = node.y}
elseif node_type == "anchor" then
if size_w == 0 or size_h == 0 then
return render_error("anchor[] without size[]")
end
offset_x = -node.x * size_w
offset_y = -node.y * size_h
-- return render_error('anchor[] not implemented')
elseif nodes[node_type] then
add_node(node_type, node)
end
end
return hud_elems
end
-- Defined as a local before render()
function render_error(err)
return render("formspec_version[3]size[8,1]label[0,0.5;" ..
minetest.formspec_escape(tostring(err)) .. "]")
end
local hud_elems = {}
--[[
hud_elems[player_name][formname] = {
{List of HUD IDs},
{List of HUD definitions}
}
]]
-- Returns needs_replacing, differences
local function compare_elems(old_elem, new_elem)
local differences = {}
for k, v in pairs(old_elem) do
local v2 = new_elem[k]
if type(v) == "table" and type(v2) == "table" then
-- Tables are guaranteed to be 2-dimensional vectors at the moment,
-- don't bother checking anything else to improve performance.
if v.x ~= v2.x or v.y ~= v2.y then
differences[#differences + 1] = k
end
elseif v ~= v2 then
-- Sometimes the HUD element will need to be deleted/re-added.
if k == "hud_elem_type" or v2 == nil then return true, nil end
differences[#differences + 1] = k
end
end
-- Check for missing keys in old_elem
for k in pairs(new_elem) do
if old_elem[k] == nil then
differences[#differences + 1] = k
end
end
return false, differences
end
local scales = {}
local z_indexes = {}
function hud_fs.show_hud(player, formname, formspec)
if type(player) == "string" then
player = minetest.get_player_by_name(player)
end
local name = player:get_player_name()
if not hud_elems[name] then
hud_elems[name] = {}
end
-- Work around Minetest bug (should be fixed in 5.4)
local info = minetest.get_player_information(name)
if not info then return end
local data = hud_elems[name][formname]
if not data then
data = {{}, {}}
hud_elems[name][formname] = data
end
local ids, elems = data[1], data[2]
local proto_ver = info.protocol_version
local new_elems = render(formspec, proto_ver, scales[formname],
z_indexes[formname])
-- Z-index was added to MT 5.2.0 (protocol version 39) and is ignored by
-- older clients. Because of the way HUDs work, sometimes it's safest to
-- just delete and re-add every single element for these older clients.
if proto_ver < 39 then
-- Maybe we can get away with just doing hud_change() and not resending
local diff_cache = {}
local can_update = true
local update_packets = max(#elems - #new_elems, 0)
for i, new_elem in ipairs(new_elems) do
local old_elem = elems[i]
if old_elem then
local needs_replacing, diff = compare_elems(old_elem, new_elem)
if needs_replacing then
can_update = false
break
end
if #diff > 0 then
diff_cache[i] = diff
update_packets = update_packets + 1
end
else
-- If elements are added the whole HUD needs to be resent.
can_update = false
break
end
end
local resend_packets = #elems + #new_elems
if can_update and resend_packets >= update_packets then
-- Send lots of hud_change packets
for i, new_elem in ipairs(new_elems) do
local diff = diff_cache[i]
if diff then
for _, stat in ipairs(diff) do
player:hud_change(ids[i], stat, new_elem[stat])
end
elems[i] = new_elem
end
end
-- Remove any extra elements
for i = #new_elems + 1, #ids do
player:hud_remove(ids[i])
ids[i] = nil
elems[i] = nil
end
if DEBUG then
minetest.chat_send_player(name, "[DEBUG] Sent " ..
update_packets .. " packet(s) using hud_change() and " ..
"hud_remove() to update HUD")
end
else
-- Or resend every single HUD element
for i = 1, #ids do
player:hud_remove(ids[i])
ids[i] = nil
elems[i] = nil
end
for i, elem in ipairs(new_elems) do
ids[i] = player:hud_add(elem)
elems[i] = elem
end
if DEBUG then
minetest.chat_send_player(name, "[DEBUG] Sent " ..
resend_packets .. " packet(s) resending entire HUD")
end
end
return
end
-- As MT 5.2.0+ clients support z_index, the HUD IDs don't need to be
-- sequential and the update packets can therefore be more efficient.
local replaced, modified, modify_packets, added = 0, 0, 0, 0
for i, new_elem in ipairs(new_elems) do
local old_elem = elems[i]
if old_elem then
local needs_replacing, diff = compare_elems(old_elem, new_elem)
if needs_replacing or #diff > 2 then
-- Resend the entire element if there are more than two
-- differences as this only sends two packets to the client.
player:hud_remove(ids[i])
ids[i] = player:hud_add(new_elem)
replaced = replaced + 1
else
-- Otherwise it's more efficient to use multiple hud_change()
-- calls (this is a no-op if #diff == 0).
for _, stat in ipairs(diff) do
player:hud_change(ids[i], stat, new_elem[stat])
modify_packets = modify_packets + 1
end
if #diff > 0 then modified = modified + 1 end
end
else
ids[i] = player:hud_add(new_elem)
added = added + 1
end
elems[i] = new_elem
end
-- Remove any extra elements
local removed = 0
for i = #new_elems + 1, #ids do
player:hud_remove(ids[i])
ids[i] = nil
elems[i] = nil
removed = removed + 1
end
if DEBUG then
local packets = modify_packets + replaced * 2 + added + removed
minetest.chat_send_player(name, "[DEBUG] Sent " .. packets ..
" network packet(s): Modified " .. modified ..
" elements in-place (for " .. modify_packets ..
" packet(s)), replaced " .. replaced .. ", added " .. added ..
" and removed " .. removed .. " element(s).")
end
end
function hud_fs.close_hud(player, formname)
hud_fs.show_hud(player, formname, {})
end
minetest.register_on_leaveplayer(function(player)
hud_elems[player:get_player_name()] = nil
end)
-- Sets the base z-index for formname. Should not be done when the formspec is
-- open. Note that this is not used for all elements, if the formspec contains
-- 10 HUD elements it will use a z-index ranging from z_index to z_index + 9.
-- This has no effect for clients older than 5.2.0.
function hud_fs.set_z_index(formname, z_index)
if z_index == DEFAULT_Z_INDEX then z_index = nil end
z_indexes[formname] = z_index
end
-- Sets the scale for formname. This can be done when the HUD is open, however
-- the scale won't be changed for existing formspecs.
function hud_fs.set_scale(formname, scale)
if scale == DEFAULT_SCALE then scale = nil end
scales[formname] = scale
end
-- Testing
--[=[
if not DEBUG then return end
local using_fs = {}
local function poll()
for _, player in ipairs(minetest.get_connected_players()) do
local name = player:get_player_name()
local fs = "formspec_version[3]" ..
"size[4,4.5] position[1,0] anchor[1,0] no_prepend[]" ..
"bgcolor[#00000022;true]" ..
"box[0,0;5,2;#380C2AFF]" ..
"label[0.25,0.5;This is a test HUD]" ..
"label[0.25,1;" .. minetest.colorize("#00ffff", "Server uptime: " ..
floor(minetest.get_server_uptime()) .. " seconds") ..
"]" ..
"label[0.25,1.5;Run /hud to interact!]"
if math.random(0, 1) == 0 then
fs = fs .. "image[3,1.5;1,1;default_dirt.png]"
end
-- if math.random(1, 5) > 1 then
-- fs = fs .. "label[0,1.5;Second label (test)\nNewline test\rabc]"
-- end
fs = fs ..
"box[0,2;5,2;#380C2ABF]" ..
"container[0,2.5]" ..
"item_image[0,0;1,1;carts:rail]" ..
"item_image[1,0;1,1;default:dirt_with_grass]" ..
"container[2,-0.5]" ..
"item_image[0,0.5;1,1;default:cactus]" ..
"item_image[1,0.5;1,1;default:tree]" ..
"container_end[]" ..
"container_end[]" ..
"button[0,4;2,0.5;mrkr;Waypoints]" ..
"button[2,4;2,0.5;close;Close]"
if using_fs[name] then
minetest.show_formspec(name, "hud_fs:uptime", fs)
hud_fs.close_hud(name, "hud_fs:uptime")
else
hud_fs.show_hud(name, "hud_fs:uptime", fs)
end
end
end
local function poll_outer()
poll()
minetest.after(1, poll_outer)
end
minetest.register_on_mods_loaded(poll_outer)
minetest.register_chatcommand("hud", {
func = function(name, _)
using_fs[name] = true
poll()
end,
})
minetest.register_chatcommand("hud2", {
func = function(name, _)
minetest.show_formspec(name, "hud_fs:uptime", "formspec_version[3]" ..
"size[4,4.5] position[1,0] anchor[1,0] no_prepend[]" ..
"bgcolor[#ff000000;neither;#00ff0000]" ..
"button[0,4;2,0.5;mrkr;Waypoints]" ..
"button[2,4;2,0.5;close;Close]")
end,
})
minetest.register_on_player_receive_fields(function(player, formname, fields)
if formname ~= "hud_fs:uptime" then return end
local name = player:get_player_name()
if fields.mrkr then
minetest.registered_chatcommands["mrkr"].func(name, "")
elseif fields.close then
minetest.close_formspec(name, "hud_fs:uptime")
elseif not fields.quit then
return
end
using_fs[name] = nil
poll()
end)
]=]

2
mod.conf Normal file
View File

@ -0,0 +1,2 @@
name = hud_fs
depends = formspec_ast

BIN
textures/hud_fs_box.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 565 B