2019-09-19 14:00:26 +02:00
|
|
|
local S = minetest.get_translator("unified_inventory")
|
2018-04-02 13:33:36 +02:00
|
|
|
local F = minetest.formspec_escape
|
2021-03-07 14:18:17 +01:00
|
|
|
local ui = unified_inventory
|
2014-06-21 12:44:31 +02:00
|
|
|
|
2014-06-13 11:40:52 +02:00
|
|
|
-- This pair of encoding functions is used where variable text must go in
|
|
|
|
-- button names, where the text might contain formspec metacharacters.
|
|
|
|
-- We can escape button names for the formspec, to avoid screwing up
|
|
|
|
-- form structure overall, but they then don't get de-escaped, and so
|
|
|
|
-- the input we get back from the button contains the formspec escaping.
|
|
|
|
-- This is a game engine bug, and in the anticipation that it might be
|
|
|
|
-- fixed some day we don't want to rely on it. So for safety we apply
|
|
|
|
-- an encoding that avoids all formspec metacharacters.
|
2021-03-05 16:58:18 +01:00
|
|
|
|
2021-03-07 14:18:17 +01:00
|
|
|
function ui.mangle_for_formspec(str)
|
2014-06-13 11:40:52 +02:00
|
|
|
return string.gsub(str, "([^A-Za-z0-9])", function (c) return string.format("_%d_", string.byte(c)) end)
|
|
|
|
end
|
2021-03-07 14:18:17 +01:00
|
|
|
function ui.demangle_for_formspec(str)
|
2014-06-13 11:40:52 +02:00
|
|
|
return string.gsub(str, "_([0-9]+)_", function (v) return string.char(v) end)
|
|
|
|
end
|
2013-09-29 00:15:37 +02:00
|
|
|
|
2022-02-26 11:41:15 +01:00
|
|
|
-- Get the player-specific unified_inventory style
|
2021-03-07 14:18:17 +01:00
|
|
|
function ui.get_per_player_formspec(player_name)
|
2021-03-08 10:51:54 +01:00
|
|
|
local draw_lite_mode = ui.lite_mode and not minetest.check_player_privs(player_name, {ui_full=true})
|
2015-10-05 10:24:01 +02:00
|
|
|
|
2021-08-14 15:25:55 +02:00
|
|
|
local style = table.copy(draw_lite_mode and ui.style_lite or ui.style_full)
|
|
|
|
style.is_lite_mode = draw_lite_mode
|
|
|
|
return style
|
2015-10-05 10:24:01 +02:00
|
|
|
end
|
|
|
|
|
2022-02-26 11:41:15 +01:00
|
|
|
-- Creates an item image or regular image button with a tooltip
|
2021-04-05 20:07:14 +02:00
|
|
|
local function formspec_button(ui_peruser, name, image, offset, pos, scale, label)
|
|
|
|
local element = 'image_button'
|
|
|
|
if minetest.registered_items[image] then
|
|
|
|
element = 'item_image_button'
|
2021-07-17 10:35:39 +02:00
|
|
|
elseif image:find(":", 1, true) then
|
|
|
|
image = "unknown_item.png"
|
2021-04-05 20:07:14 +02:00
|
|
|
end
|
|
|
|
local spc = (1-scale)*ui_peruser.btn_size/2
|
|
|
|
local size = ui_peruser.btn_size*scale
|
|
|
|
return string.format("%s[%f,%f;%f,%f;%s;%s;]", element,
|
|
|
|
(offset.x or offset[1]) + ( ui_peruser.btn_spc * (pos.x or pos[1]) ) + spc,
|
|
|
|
(offset.y or offset[2]) + ( ui_peruser.btn_spc * (pos.y or pos[2]) ) + spc,
|
|
|
|
size, size, image, name) ..
|
|
|
|
string.format("tooltip[%s;%s]", name, F(label or name))
|
|
|
|
end
|
|
|
|
|
2022-02-26 11:41:15 +01:00
|
|
|
-- Add registered buttons (tabs)
|
|
|
|
local function formspec_tab_buttons(player, formspec, style)
|
2021-08-14 15:25:55 +02:00
|
|
|
local n = #formspec + 1
|
2015-06-28 09:47:03 +02:00
|
|
|
|
2013-09-29 00:15:37 +02:00
|
|
|
-- Main buttons
|
2015-10-05 10:24:01 +02:00
|
|
|
|
|
|
|
local filtered_inv_buttons = {}
|
|
|
|
|
2022-10-26 10:05:03 +02:00
|
|
|
for _, def in pairs(ui.buttons) do
|
2021-08-14 15:25:55 +02:00
|
|
|
if not (style.is_lite_mode and def.hide_lite) then
|
2022-10-26 10:05:03 +02:00
|
|
|
if def.condition == nil or def.condition(player) or not ui.hide_disabled_buttons then
|
|
|
|
table.insert(filtered_inv_buttons, def)
|
|
|
|
end
|
2015-10-05 10:24:01 +02:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2022-02-26 11:41:15 +01:00
|
|
|
local needs_scrollbar = #filtered_inv_buttons > style.main_button_cols * style.main_button_rows
|
|
|
|
|
|
|
|
formspec[n] = ("scroll_container[%g,%g;%g,%g;tabbtnscroll;vertical]"):format(
|
|
|
|
style.main_button_x, style.main_button_y, -- position
|
|
|
|
style.main_button_cols * style.btn_spc, style.main_button_rows -- size
|
|
|
|
)
|
|
|
|
n = n + 1
|
|
|
|
|
2015-10-05 10:24:01 +02:00
|
|
|
for i, def in pairs(filtered_inv_buttons) do
|
2022-02-26 11:41:15 +01:00
|
|
|
local pos_x = ((i - 1) % style.main_button_cols) * style.btn_spc
|
|
|
|
local pos_y = math.floor((i - 1) / style.main_button_cols) * style.btn_spc
|
2015-06-28 09:47:03 +02:00
|
|
|
|
2013-09-29 00:15:37 +02:00
|
|
|
if def.type == "image" then
|
2022-10-26 10:05:03 +02:00
|
|
|
if (def.condition == nil or def.condition(player)) then
|
2022-02-26 11:41:15 +01:00
|
|
|
formspec[n] = string.format("image_button[%g,%g;%g,%g;%s;%s;]",
|
2021-08-14 15:25:55 +02:00
|
|
|
pos_x, pos_y, style.btn_size, style.btn_size,
|
Multiple related changes to string handling
1) Convert most formspec elements to use string.format(), when the
result would be more readable, or less messy, or at least makes the line
shorter, assuming it looked like it really needed it to begin with.
2) Convert all long `foo..","..bar..";"..baz..bleh..` types of excessive
string concatenation into tables that then get concated only once, when
their containing functions return the final formspec string.
3) In some places in the code, such tables were already being used, and
were named "formspec", while others were named "fs". I settled on just
one name, "formspec", as it's more readable, if longer.
4) There was a mix of styles of adding items to those tables:
* Some places used line after line of `t[#t + 1] = foo/bar/baz`.
* Others places used the form `t[1] = foo, t[2] = bar, ...`.
* Still others used the form `t[n] = foo, t[n+1] = bar...`,
with `n` being increased or reset every so often.
Most of them should now be of the third form, with a few of the second.
2021-03-07 16:37:20 +01:00
|
|
|
F(def.image),
|
|
|
|
F(def.name))
|
|
|
|
formspec[n+1] = "tooltip["..F(def.name)..";"..(def.tooltip or "").."]"
|
|
|
|
n = n+2
|
2022-10-26 10:05:03 +02:00
|
|
|
|
2016-11-06 02:28:45 +01:00
|
|
|
else
|
2022-02-26 11:41:15 +01:00
|
|
|
formspec[n] = string.format("image[%g,%g;%g,%g;%s^[colorize:#808080:alpha]",
|
2021-08-14 15:25:55 +02:00
|
|
|
pos_x, pos_y, style.btn_size, style.btn_size,
|
|
|
|
def.image)
|
Multiple related changes to string handling
1) Convert most formspec elements to use string.format(), when the
result would be more readable, or less messy, or at least makes the line
shorter, assuming it looked like it really needed it to begin with.
2) Convert all long `foo..","..bar..";"..baz..bleh..` types of excessive
string concatenation into tables that then get concated only once, when
their containing functions return the final formspec string.
3) In some places in the code, such tables were already being used, and
were named "formspec", while others were named "fs". I settled on just
one name, "formspec", as it's more readable, if longer.
4) There was a mix of styles of adding items to those tables:
* Some places used line after line of `t[#t + 1] = foo/bar/baz`.
* Others places used the form `t[1] = foo, t[2] = bar, ...`.
* Still others used the form `t[n] = foo, t[n+1] = bar...`,
with `n` being increased or reset every so often.
Most of them should now be of the third form, with a few of the second.
2021-03-07 16:37:20 +01:00
|
|
|
n = n+1
|
2016-11-06 02:28:45 +01:00
|
|
|
end
|
2013-09-29 00:15:37 +02:00
|
|
|
end
|
|
|
|
end
|
2022-02-26 11:41:15 +01:00
|
|
|
formspec[n] = "scroll_container_end[]"
|
|
|
|
if needs_scrollbar then
|
2022-12-30 21:43:46 +01:00
|
|
|
local total_rows = math.ceil(#filtered_inv_buttons / style.main_button_cols)
|
2022-02-26 11:41:15 +01:00
|
|
|
formspec[n+1] = ("scrollbaroptions[max=%i;arrows=hide]"):format(
|
|
|
|
-- This calculation is not 100% accurate but "good enough"
|
2022-12-30 21:43:46 +01:00
|
|
|
(total_rows - style.main_button_rows) * style.btn_spc * 10
|
2022-02-26 11:41:15 +01:00
|
|
|
)
|
|
|
|
formspec[n+2] = ("scrollbar[%g,%g;0.4,%g;vertical;tabbtnscroll;0]"):format(
|
|
|
|
style.main_button_x + style.main_button_cols * style.btn_spc - 0.1, -- x pos
|
|
|
|
style.main_button_y, -- y pos
|
|
|
|
style.main_button_rows * style.btn_spc -- height
|
|
|
|
)
|
|
|
|
formspec[n+3] = "scrollbaroptions[max=1000;arrows=default]"
|
|
|
|
end
|
2021-08-14 15:25:55 +02:00
|
|
|
end
|
2013-09-29 00:15:37 +02:00
|
|
|
|
2022-02-26 11:41:15 +01:00
|
|
|
-- Add category GUI elements (top right)
|
2021-08-14 15:25:55 +02:00
|
|
|
local function formspec_add_categories(player, formspec, ui_peruser)
|
|
|
|
local player_name = player:get_player_name()
|
|
|
|
local n = #formspec + 1
|
2021-04-05 20:07:14 +02:00
|
|
|
|
2021-08-14 15:25:55 +02:00
|
|
|
local categories_pos = {
|
|
|
|
ui_peruser.page_x,
|
|
|
|
ui_peruser.page_y-ui_peruser.btn_spc-0.5
|
|
|
|
}
|
|
|
|
local categories_scroll_pos = {
|
|
|
|
ui_peruser.page_x,
|
|
|
|
ui_peruser.form_header_y - (ui_peruser.is_lite_mode and 0 or 0.2)
|
|
|
|
}
|
2021-04-05 20:07:14 +02:00
|
|
|
|
2022-04-03 22:30:21 +02:00
|
|
|
formspec[n] = string.format("background9[%f,%f;%f,%f;%s;false;16]",
|
|
|
|
ui_peruser.page_x-0.15, categories_scroll_pos[2],
|
|
|
|
(ui_peruser.btn_spc * ui_peruser.pagecols) + 0.2, 1.4 + (ui_peruser.is_lite_mode and 0 or 0.2),
|
2021-04-05 20:07:14 +02:00
|
|
|
"ui_smallbg_9_sliced.png")
|
|
|
|
n = n + 1
|
|
|
|
|
2021-08-14 15:25:55 +02:00
|
|
|
formspec[n] = string.format("label[%f,%f;%s]",
|
|
|
|
ui_peruser.page_x,
|
|
|
|
ui_peruser.form_header_y + (ui_peruser.is_lite_mode and 0.3 or 0.2), F(S("Category:")))
|
2021-04-05 20:07:14 +02:00
|
|
|
n = n + 1
|
|
|
|
|
|
|
|
local scroll_offset = 0
|
2021-08-14 15:25:55 +02:00
|
|
|
local category_count = #ui.category_list
|
2021-04-05 20:07:14 +02:00
|
|
|
if category_count > ui_peruser.pagecols then
|
2021-08-14 15:25:55 +02:00
|
|
|
scroll_offset = ui.current_category_scroll[player_name]
|
2021-04-05 20:07:14 +02:00
|
|
|
end
|
|
|
|
|
2021-08-14 15:25:55 +02:00
|
|
|
for index, category in ipairs(ui.category_list) do
|
2021-04-05 20:07:14 +02:00
|
|
|
local column = index - scroll_offset
|
|
|
|
if column > 0 and column <= ui_peruser.pagecols then
|
|
|
|
local scale = 0.8
|
2021-08-14 15:25:55 +02:00
|
|
|
if ui.current_category[player_name] == category.name then
|
2021-04-05 20:07:14 +02:00
|
|
|
scale = 1
|
|
|
|
end
|
|
|
|
formspec[n] = formspec_button(ui_peruser, "category_"..category.name, category.symbol, categories_pos, {column-1, 0}, scale, category.label)
|
|
|
|
n = n + 1
|
|
|
|
end
|
|
|
|
end
|
|
|
|
if category_count > ui_peruser.pagecols and scroll_offset > 0 then
|
|
|
|
-- prev
|
|
|
|
formspec[n] = formspec_button(ui_peruser, "prev_category", "ui_left_icon.png", categories_scroll_pos, {ui_peruser.pagecols - 2, 0}, 0.8, S("Scroll categories left"))
|
|
|
|
n = n + 1
|
|
|
|
end
|
|
|
|
if category_count > ui_peruser.pagecols and category_count - scroll_offset > ui_peruser.pagecols then
|
|
|
|
-- next
|
|
|
|
formspec[n] = formspec_button(ui_peruser, "next_category", "ui_right_icon.png", categories_scroll_pos, {ui_peruser.pagecols - 1, 0}, 0.8, S("Scroll categories right"))
|
|
|
|
end
|
2021-08-14 15:25:55 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
local function formspec_add_search_box(player, formspec, ui_peruser)
|
|
|
|
local player_name = player:get_player_name()
|
|
|
|
local n = #formspec + 1
|
2021-04-05 20:07:14 +02:00
|
|
|
|
2016-11-29 20:45:59 +01:00
|
|
|
formspec[n] = "field_close_on_enter[searchbox;false]"
|
2015-06-28 09:47:03 +02:00
|
|
|
|
Multiple related changes to string handling
1) Convert most formspec elements to use string.format(), when the
result would be more readable, or less messy, or at least makes the line
shorter, assuming it looked like it really needed it to begin with.
2) Convert all long `foo..","..bar..";"..baz..bleh..` types of excessive
string concatenation into tables that then get concated only once, when
their containing functions return the final formspec string.
3) In some places in the code, such tables were already being used, and
were named "formspec", while others were named "fs". I settled on just
one name, "formspec", as it's more readable, if longer.
4) There was a mix of styles of adding items to those tables:
* Some places used line after line of `t[#t + 1] = foo/bar/baz`.
* Others places used the form `t[1] = foo, t[2] = bar, ...`.
* Still others used the form `t[n] = foo, t[n+1] = bar...`,
with `n` being increased or reset every so often.
Most of them should now be of the third form, with a few of the second.
2021-03-07 16:37:20 +01:00
|
|
|
formspec[n+1] = string.format("field[%f,%f;%f,%f;searchbox;;%s]",
|
|
|
|
ui_peruser.page_buttons_x, ui_peruser.page_buttons_y,
|
|
|
|
ui_peruser.searchwidth - 0.1, ui_peruser.btn_size,
|
|
|
|
F(ui.current_searchbox[player_name]))
|
|
|
|
formspec[n+2] = string.format("image_button[%f,%f;%f,%f;ui_search_icon.png;searchbutton;]",
|
|
|
|
ui_peruser.page_buttons_x + ui_peruser.searchwidth, ui_peruser.page_buttons_y,
|
|
|
|
ui_peruser.btn_size,ui_peruser.btn_size)
|
|
|
|
formspec[n+3] = "tooltip[searchbutton;" ..F(S("Search")) .. "]"
|
|
|
|
formspec[n+4] = string.format("image_button[%f,%f;%f,%f;ui_reset_icon.png;searchresetbutton;]",
|
|
|
|
ui_peruser.page_buttons_x + ui_peruser.searchwidth + ui_peruser.btn_spc,
|
|
|
|
ui_peruser.page_buttons_y,
|
|
|
|
ui_peruser.btn_size, ui_peruser.btn_size)
|
|
|
|
formspec[n+5] = "tooltip[searchresetbutton;"..F(S("Reset search and display everything")).."]"
|
|
|
|
|
2021-08-14 15:25:55 +02:00
|
|
|
if ui.activefilter[player_name] ~= "" then
|
|
|
|
formspec[n+6] = string.format("label[%f,%f;%s: %s]",
|
|
|
|
ui_peruser.page_x, ui_peruser.page_y - 0.25,
|
|
|
|
F(S("Filter")), F(ui.activefilter[player_name]))
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
local function formspec_add_item_browser(player, formspec, ui_peruser)
|
|
|
|
local player_name = player:get_player_name()
|
|
|
|
local n = #formspec + 1
|
2021-03-05 16:58:18 +01:00
|
|
|
|
|
|
|
-- Controls to flip items pages
|
|
|
|
|
|
|
|
local btnlist = {
|
2021-03-09 20:26:36 +01:00
|
|
|
{ "ui_skip_backward_icon.png", "start_list", S("First page") },
|
|
|
|
{ "ui_doubleleft_icon.png", "rewind3", S("Back three pages") },
|
|
|
|
{ "ui_left_icon.png", "rewind1", S("Back one page") },
|
|
|
|
{ "ui_right_icon.png", "forward1", S("Forward one page") },
|
|
|
|
{ "ui_doubleright_icon.png", "forward3", S("Forward three pages") },
|
|
|
|
{ "ui_skip_forward_icon.png", "end_list", S("Last page") },
|
2021-03-05 16:58:18 +01:00
|
|
|
}
|
|
|
|
|
2021-08-14 15:25:55 +02:00
|
|
|
if ui_peruser.is_lite_mode then
|
2021-03-05 16:58:18 +01:00
|
|
|
btnlist[2] = nil
|
2021-08-14 15:25:55 +02:00
|
|
|
btnlist[5] = nil
|
2021-03-05 16:58:18 +01:00
|
|
|
end
|
|
|
|
|
|
|
|
local bn = 0
|
|
|
|
for _, b in pairs(btnlist) do
|
Multiple related changes to string handling
1) Convert most formspec elements to use string.format(), when the
result would be more readable, or less messy, or at least makes the line
shorter, assuming it looked like it really needed it to begin with.
2) Convert all long `foo..","..bar..";"..baz..bleh..` types of excessive
string concatenation into tables that then get concated only once, when
their containing functions return the final formspec string.
3) In some places in the code, such tables were already being used, and
were named "formspec", while others were named "fs". I settled on just
one name, "formspec", as it's more readable, if longer.
4) There was a mix of styles of adding items to those tables:
* Some places used line after line of `t[#t + 1] = foo/bar/baz`.
* Others places used the form `t[1] = foo, t[2] = bar, ...`.
* Still others used the form `t[n] = foo, t[n+1] = bar...`,
with `n` being increased or reset every so often.
Most of them should now be of the third form, with a few of the second.
2021-03-07 16:37:20 +01:00
|
|
|
formspec[n] = string.format("image_button[%f,%f;%f,%f;%s;%s;]",
|
|
|
|
ui_peruser.page_buttons_x + ui_peruser.btn_spc*bn,
|
|
|
|
ui_peruser.page_buttons_y + ui_peruser.btn_spc,
|
|
|
|
ui_peruser.btn_size, ui_peruser.btn_size,
|
|
|
|
b[1],b[2])
|
2021-03-09 20:26:36 +01:00
|
|
|
formspec[n+1] = "tooltip["..b[2]..";"..F(b[3]).."]"
|
2021-03-05 16:58:18 +01:00
|
|
|
bn = bn + 1
|
Multiple related changes to string handling
1) Convert most formspec elements to use string.format(), when the
result would be more readable, or less messy, or at least makes the line
shorter, assuming it looked like it really needed it to begin with.
2) Convert all long `foo..","..bar..";"..baz..bleh..` types of excessive
string concatenation into tables that then get concated only once, when
their containing functions return the final formspec string.
3) In some places in the code, such tables were already being used, and
were named "formspec", while others were named "fs". I settled on just
one name, "formspec", as it's more readable, if longer.
4) There was a mix of styles of adding items to those tables:
* Some places used line after line of `t[#t + 1] = foo/bar/baz`.
* Others places used the form `t[1] = foo, t[2] = bar, ...`.
* Still others used the form `t[n] = foo, t[n+1] = bar...`,
with `n` being increased or reset every so often.
Most of them should now be of the third form, with a few of the second.
2021-03-07 16:37:20 +01:00
|
|
|
n = n + 2
|
2015-06-28 09:47:03 +02:00
|
|
|
end
|
|
|
|
|
2013-09-29 00:15:37 +02:00
|
|
|
-- Items list
|
2021-03-07 14:18:17 +01:00
|
|
|
if #ui.filtered_items_list[player_name] == 0 then
|
2021-08-14 15:25:55 +02:00
|
|
|
local no_matches = S("No matching items")
|
|
|
|
if ui_peruser.is_lite_mode then
|
|
|
|
no_matches = S("No matches.")
|
|
|
|
end
|
|
|
|
|
2021-03-05 16:58:18 +01:00
|
|
|
formspec[n] = "label["..ui_peruser.page_x..","..(ui_peruser.page_y+0.15)..";" .. F(no_matches) .. "]"
|
2021-08-14 15:25:55 +02:00
|
|
|
return
|
|
|
|
end
|
2018-12-12 20:18:53 +01:00
|
|
|
|
2021-08-14 15:25:55 +02:00
|
|
|
local dir = ui.active_search_direction[player_name]
|
|
|
|
local list_index = ui.current_index[player_name]
|
|
|
|
local page2 = math.floor(list_index / (ui_peruser.items_per_page) + 1)
|
|
|
|
local pagemax = math.floor(
|
|
|
|
(#ui.filtered_items_list[player_name] - 1)
|
|
|
|
/ (ui_peruser.items_per_page) + 1)
|
|
|
|
for y = 0, ui_peruser.pagerows - 1 do
|
|
|
|
for x = 0, ui_peruser.pagecols - 1 do
|
|
|
|
local name = ui.filtered_items_list[player_name][list_index]
|
|
|
|
local item = minetest.registered_items[name]
|
|
|
|
if item then
|
|
|
|
-- Clicked on current item: Flip crafting direction
|
|
|
|
if name == ui.current_item[player_name] then
|
|
|
|
local cdir = ui.current_craft_direction[player_name]
|
|
|
|
if cdir == "recipe" then
|
|
|
|
dir = "usage"
|
|
|
|
elseif cdir == "usage" then
|
|
|
|
dir = "recipe"
|
|
|
|
end
|
|
|
|
else
|
|
|
|
-- Default: use active search direction by default
|
|
|
|
dir = ui.active_search_direction[player_name]
|
2015-06-28 09:47:03 +02:00
|
|
|
end
|
2021-08-14 15:25:55 +02:00
|
|
|
|
|
|
|
local button_name = "item_button_" .. dir .. "_"
|
|
|
|
.. ui.mangle_for_formspec(name)
|
|
|
|
formspec[n] = ("item_image_button[%f,%f;%f,%f;%s;%s;]"):format(
|
|
|
|
ui_peruser.page_x + x * ui_peruser.btn_spc,
|
|
|
|
ui_peruser.page_y + y * ui_peruser.btn_spc,
|
|
|
|
ui_peruser.btn_size, ui_peruser.btn_size,
|
|
|
|
name, button_name
|
|
|
|
)
|
2022-03-20 13:30:11 +01:00
|
|
|
local tooltip = item.description
|
|
|
|
if item.mod_origin then
|
|
|
|
-- "mod_origin" may not be specified for items that were
|
|
|
|
-- registered in a callback (during or before ServerEnv init)
|
|
|
|
tooltip = tooltip .. " [" .. item.mod_origin .. "]"
|
|
|
|
end
|
2021-12-11 17:15:58 +01:00
|
|
|
formspec[n + 1] = ("tooltip[%s;%s]"):format(
|
2022-03-20 13:30:11 +01:00
|
|
|
button_name, minetest.formspec_escape(tooltip)
|
2021-08-14 15:25:55 +02:00
|
|
|
)
|
|
|
|
n = n + 2
|
2014-04-29 21:08:04 +02:00
|
|
|
end
|
2024-01-06 12:35:54 +01:00
|
|
|
list_index = list_index + 1
|
2014-04-29 21:08:04 +02:00
|
|
|
end
|
2013-09-29 00:15:37 +02:00
|
|
|
end
|
2023-01-04 14:35:46 +01:00
|
|
|
formspec[n] = "style[page_number;content_offset=0]"
|
|
|
|
formspec[n + 1] = string.format("image_button[%f,%f;%f,0.4;;page_number;%s: %s;false;false;]",
|
|
|
|
ui_peruser.page_buttons_x,
|
|
|
|
ui_peruser.page_buttons_y + ui_peruser.btn_spc * 2 - 0.1,
|
|
|
|
ui_peruser.btn_spc * (bn - 1) + ui_peruser.btn_size,
|
2021-08-14 15:25:55 +02:00
|
|
|
F(S("Page")), S("@1 of @2",page2,pagemax))
|
|
|
|
end
|
2015-08-16 16:40:49 +02:00
|
|
|
|
2021-08-14 15:25:55 +02:00
|
|
|
function ui.get_formspec(player, page)
|
|
|
|
|
|
|
|
if not player then
|
|
|
|
return ""
|
|
|
|
end
|
|
|
|
|
|
|
|
local player_name = player:get_player_name()
|
|
|
|
local ui_peruser = ui.get_per_player_formspec(player_name)
|
|
|
|
|
|
|
|
ui.current_page[player_name] = page
|
|
|
|
local pagedef = ui.pages[page]
|
|
|
|
|
|
|
|
if not pagedef then
|
|
|
|
return "" -- Invalid page name
|
2013-09-29 00:15:37 +02:00
|
|
|
end
|
2021-08-14 15:25:55 +02:00
|
|
|
|
2021-08-14 15:30:50 +02:00
|
|
|
local fs = {
|
2021-08-14 15:25:55 +02:00
|
|
|
"formspec_version[4]",
|
|
|
|
"size["..ui_peruser.formw..","..ui_peruser.formh.."]",
|
|
|
|
pagedef.formspec_prepend and "" or "no_prepend[]",
|
|
|
|
ui.standard_background
|
|
|
|
}
|
|
|
|
|
|
|
|
local perplayer_formspec = ui.get_per_player_formspec(player_name)
|
|
|
|
local fsdata = pagedef.get_formspec(player, perplayer_formspec)
|
|
|
|
|
2021-08-14 15:30:50 +02:00
|
|
|
fs[#fs + 1] = fsdata.formspec
|
2021-08-14 15:25:55 +02:00
|
|
|
|
2022-02-26 11:41:15 +01:00
|
|
|
formspec_tab_buttons(player, fs, ui_peruser)
|
2021-08-14 15:25:55 +02:00
|
|
|
|
|
|
|
if fsdata.draw_inventory ~= false then
|
|
|
|
-- Player inventory
|
2021-08-14 15:30:50 +02:00
|
|
|
fs[#fs + 1] = "listcolors[#00000000;#00000000]"
|
|
|
|
fs[#fs + 1] = ui_peruser.standard_inv
|
2021-08-14 15:25:55 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
if fsdata.draw_item_list == false then
|
2021-08-14 15:30:50 +02:00
|
|
|
return table.concat(fs, "")
|
2021-08-14 15:25:55 +02:00
|
|
|
end
|
|
|
|
|
2021-08-14 15:30:50 +02:00
|
|
|
formspec_add_categories(player, fs, ui_peruser)
|
|
|
|
formspec_add_search_box(player, fs, ui_peruser)
|
|
|
|
formspec_add_item_browser(player, fs, ui_peruser)
|
2021-08-14 15:25:55 +02:00
|
|
|
|
2021-08-14 15:30:50 +02:00
|
|
|
return table.concat(fs)
|
2013-09-29 00:15:37 +02:00
|
|
|
end
|
|
|
|
|
2021-03-07 14:18:17 +01:00
|
|
|
function ui.set_inventory_formspec(player, page)
|
2013-09-29 00:15:37 +02:00
|
|
|
if player then
|
2021-03-07 14:18:17 +01:00
|
|
|
player:set_inventory_formspec(ui.get_formspec(player, page))
|
2013-09-29 00:15:37 +02:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2022-10-05 21:07:11 +02:00
|
|
|
function ui.is_itemdef_listable(def)
|
2021-04-05 20:07:14 +02:00
|
|
|
return (not def.groups.not_in_creative_inventory
|
|
|
|
or def.groups.not_in_creative_inventory == 0)
|
|
|
|
and def.description
|
|
|
|
and def.description ~= ""
|
|
|
|
end
|
|
|
|
|
2013-09-29 00:15:37 +02:00
|
|
|
--apply filter to the inventory list (create filtered copy of full one)
|
2021-03-07 14:18:17 +01:00
|
|
|
function ui.apply_filter(player, filter, search_dir)
|
2015-08-16 16:40:49 +02:00
|
|
|
if not player then
|
|
|
|
return false
|
|
|
|
end
|
2014-01-19 19:27:52 +01:00
|
|
|
local player_name = player:get_player_name()
|
2022-10-05 21:07:11 +02:00
|
|
|
|
2024-01-06 12:35:54 +01:00
|
|
|
-- Whether to show uncraftable items
|
|
|
|
local fprefilter = function(_)
|
|
|
|
return true
|
|
|
|
end
|
|
|
|
if ui.hide_uncraftable_items and not ui.is_creative(player_name) then
|
|
|
|
fprefilter = function(name)
|
|
|
|
return ui.get_recipe_list(name)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
local registered_items = minetest.registered_items
|
2013-09-29 00:15:37 +02:00
|
|
|
local lfilter = string.lower(filter)
|
2014-05-01 21:44:16 +02:00
|
|
|
local ffilter
|
2024-01-06 12:35:54 +01:00
|
|
|
|
2014-01-19 17:34:44 +01:00
|
|
|
if lfilter:sub(1, 6) == "group:" then
|
2022-10-05 21:07:11 +02:00
|
|
|
-- Group filter: all groups of the item must match
|
2014-01-19 17:34:44 +01:00
|
|
|
local groups = lfilter:sub(7):split(",")
|
2024-01-06 12:35:54 +01:00
|
|
|
ffilter = function(name)
|
|
|
|
local def = registered_items[name]
|
2024-03-17 16:54:21 +01:00
|
|
|
if not def then
|
|
|
|
return false
|
|
|
|
end
|
|
|
|
|
2014-05-01 21:44:16 +02:00
|
|
|
for _, group in ipairs(groups) do
|
2015-08-16 16:40:49 +02:00
|
|
|
if not def.groups[group]
|
|
|
|
or def.groups[group] <= 0 then
|
2014-05-01 21:44:16 +02:00
|
|
|
return false
|
2014-01-19 17:34:44 +01:00
|
|
|
end
|
|
|
|
end
|
2014-05-01 21:44:16 +02:00
|
|
|
return true
|
2014-01-19 17:34:44 +01:00
|
|
|
end
|
|
|
|
else
|
2022-10-26 10:05:03 +02:00
|
|
|
-- Name filter: fuzzy match item names and descriptions
|
2021-12-25 17:31:18 +01:00
|
|
|
local player_info = minetest.get_player_information(player_name)
|
|
|
|
local lang = player_info and player_info.lang_code or ""
|
|
|
|
|
2024-01-06 12:35:54 +01:00
|
|
|
ffilter = function(name)
|
|
|
|
local def = registered_items[name]
|
2024-03-17 16:54:21 +01:00
|
|
|
if not def then
|
|
|
|
return false
|
|
|
|
end
|
|
|
|
|
2014-05-01 21:44:16 +02:00
|
|
|
local lname = string.lower(name)
|
|
|
|
local ldesc = string.lower(def.description)
|
2020-07-15 20:21:06 +02:00
|
|
|
local llocaldesc = minetest.get_translated_string
|
|
|
|
and string.lower(minetest.get_translated_string(lang, def.description))
|
2014-06-13 09:34:29 +02:00
|
|
|
return string.find(lname, lfilter, 1, true) or string.find(ldesc, lfilter, 1, true)
|
2020-07-15 20:21:06 +02:00
|
|
|
or llocaldesc and string.find(llocaldesc, lfilter, 1, true)
|
2014-05-01 21:44:16 +02:00
|
|
|
end
|
|
|
|
end
|
2022-10-05 21:07:11 +02:00
|
|
|
|
|
|
|
local filtered_items = {}
|
|
|
|
|
2021-04-05 20:07:14 +02:00
|
|
|
local category = ui.current_category[player_name] or 'all'
|
|
|
|
if category == 'all' then
|
2024-01-06 12:35:54 +01:00
|
|
|
for _, name in ipairs(ui.items_list) do
|
|
|
|
if fprefilter(name) and ffilter(name) then
|
2022-10-05 21:07:11 +02:00
|
|
|
table.insert(filtered_items, name)
|
2021-04-05 20:07:14 +02:00
|
|
|
end
|
|
|
|
end
|
|
|
|
elseif category == 'uncategorized' then
|
2024-01-06 12:35:54 +01:00
|
|
|
for _, name in ipairs(ui.items_list) do
|
|
|
|
if not ui.find_category(name)
|
|
|
|
and fprefilter(name)
|
|
|
|
and ffilter(name) then
|
2022-10-05 21:07:11 +02:00
|
|
|
table.insert(filtered_items, name)
|
2021-04-05 20:07:14 +02:00
|
|
|
end
|
|
|
|
end
|
|
|
|
else
|
2022-10-05 21:07:11 +02:00
|
|
|
-- Any other category is selected
|
|
|
|
for name, exists in pairs(ui.registered_category_items[category]) do
|
2024-01-06 12:35:54 +01:00
|
|
|
if exists
|
|
|
|
and fprefilter(name)
|
|
|
|
and ffilter(name) then
|
2022-10-05 21:07:11 +02:00
|
|
|
table.insert(filtered_items, name)
|
2021-04-05 20:07:14 +02:00
|
|
|
end
|
2013-09-29 00:15:37 +02:00
|
|
|
end
|
|
|
|
end
|
2022-10-05 21:07:11 +02:00
|
|
|
table.sort(filtered_items)
|
|
|
|
|
|
|
|
ui.filtered_items_list_size[player_name] = #filtered_items
|
|
|
|
ui.filtered_items_list[player_name] = filtered_items
|
2021-03-07 14:18:17 +01:00
|
|
|
ui.current_index[player_name] = 1
|
|
|
|
ui.activefilter[player_name] = filter
|
|
|
|
ui.active_search_direction[player_name] = search_dir
|
2021-08-29 07:47:32 +02:00
|
|
|
ui.set_inventory_formspec(player, ui.current_page[player_name])
|
2013-09-29 00:15:37 +02:00
|
|
|
end
|
2022-02-26 11:36:56 +01:00
|
|
|
|
|
|
|
-- Inform players about potential visual issues
|
|
|
|
minetest.register_on_joinplayer(function(player)
|
|
|
|
local player_name = player:get_player_name()
|
|
|
|
local info = minetest.get_player_information(player_name)
|
|
|
|
if info and (info.formspec_version or 0) < 4 then
|
|
|
|
minetest.chat_send_player(player_name, S("Unified Inventory: Your game version is too old"
|
|
|
|
.. " and does not support the GUI requirements. You might experience visual issues."))
|
|
|
|
end
|
|
|
|
end)
|