techage/basis/submenu.lua

319 lines
10 KiB
Lua
Raw Permalink Normal View History

2021-06-09 23:09:59 +03:00
--[[
TechAge
=======
2021-12-30 17:05:20 +03:00
Copyright (C) 2019-2022 Joachim Stolberg
2021-06-09 23:09:59 +03:00
AGPL v3
See LICENSE.txt for more information
2022-01-03 23:40:31 +03:00
2021-06-09 23:09:59 +03:00
A formspec control to generate formspec strings for machine settings and monitoring
]]--
local S = techage.S
2021-12-30 17:05:20 +03:00
techage.menu = {}
2021-06-09 23:09:59 +03:00
local function index(list, x)
2022-09-18 12:53:51 +03:00
for idx, v in ipairs(list or {}) do
if tostring(v) == x then return idx end
2021-06-09 23:09:59 +03:00
end
return nil
end
2021-09-19 21:02:24 +03:00
local function allow_put(inv, listname, index, stack, player)
local list = inv:get_list(listname)
stack:set_count(1)
inv:set_stack(listname, index, stack)
return 0
end
local function allow_take(inv, listname, index, stack, player)
local list = inv:get_list(listname)
stack:set_count(0)
inv:set_stack(listname, index, stack)
return 0
end
2021-06-09 23:09:59 +03:00
-- generate the formspec string to be placed into a container frame
2021-09-19 21:02:24 +03:00
local function generate_formspec_substring(pos, meta, form_def, player_name)
2021-06-09 23:09:59 +03:00
local tbl = {}
2021-09-19 21:02:24 +03:00
local player_inv_needed = false
2021-06-09 23:09:59 +03:00
if meta and form_def then
local nvm = techage.get_nvm(pos)
2022-01-03 23:40:31 +03:00
2021-06-09 23:09:59 +03:00
for i,elem in ipairs(form_def) do
local offs = (i - 1) * 0.9 - 0.2
tbl[#tbl+1] = "label[0," .. offs .. ";" .. minetest.formspec_escape(elem.label) .. ":]"
tbl[#tbl+1] = "tooltip[0," .. offs .. ";4,1;" .. elem.tooltip .. "]"
if elem.type == "label" then
-- none
elseif elem.type == "number" then
2021-06-27 19:29:46 +03:00
local val = elem.default
if meta:contains(elem.name) then
val = meta:get_int(elem.name)
end
if nvm.running or techage.is_running(nvm) then
2021-06-09 23:09:59 +03:00
tbl[#tbl+1] = "label[4.75," .. offs .. ";" .. val .. "]"
else
tbl[#tbl+1] = "field[5," .. (offs+0.2) .. ";5.3,1;" .. elem.name .. ";;" .. val .. "]"
end
elseif elem.type == "numbers" then
2021-06-27 19:29:46 +03:00
local val = elem.default
if meta:contains(elem.name) then
val = meta:get_string(elem.name)
end
if nvm.running or techage.is_running(nvm) then
2021-06-09 23:09:59 +03:00
tbl[#tbl+1] = "label[4.75," .. offs .. ";" .. val .. "]"
else
tbl[#tbl+1] = "field[5," .. (offs+0.2) .. ";5.3,1;" .. elem.name .. ";;" .. val .. "]"
end
elseif elem.type == "float" then
2021-06-27 19:29:46 +03:00
local val = elem.default
if meta:contains(elem.name) then
val = tonumber(meta:get_string(elem.name)) or 0
end
if nvm.running or techage.is_running(nvm) then
2021-06-09 23:09:59 +03:00
tbl[#tbl+1] = "label[4.75," .. offs .. ";" .. val .. "]"
else
tbl[#tbl+1] = "field[5," .. (offs+0.2) .. ";5.3,1;" .. elem.name .. ";;" .. val .. "]"
end
elseif elem.type == "ascii" then
2021-06-27 19:29:46 +03:00
local val = elem.default
if meta:contains(elem.name) then
val = meta:get_string(elem.name)
end
if nvm.running or techage.is_running(nvm) then
2021-06-09 23:09:59 +03:00
tbl[#tbl+1] = "label[4.75," .. offs .. ";" .. minetest.formspec_escape(val) .. "]"
else
tbl[#tbl+1] = "field[5," .. (offs+0.2) .. ";5.3,1;" .. elem.name .. ";;" .. minetest.formspec_escape(val) .. "]"
end
elseif elem.type == "const" then
tbl[#tbl+1] = "label[4.75," .. offs .. ";" .. elem.value .. "]"
elseif elem.type == "output" then
2021-12-30 17:05:20 +03:00
local val = nvm[elem.name] or meta:get_string(elem.name) or ""
2021-06-09 23:09:59 +03:00
if tonumber(val) then
val = techage.round(val)
end
tbl[#tbl+1] = "label[4.75," .. offs .. ";" .. val .. "]"
elseif elem.type == "dropdown" then
2021-06-27 19:29:46 +03:00
if nvm.running or techage.is_running(nvm) then
2022-02-26 01:00:17 +03:00
local val = elem.default or ""
2021-06-27 19:29:46 +03:00
if meta:contains(elem.name) then
val = meta:get_string(elem.name) or ""
end
2021-06-09 23:09:59 +03:00
tbl[#tbl+1] = "label[4.75," .. offs .. ";" .. val .. "]"
elseif elem.on_dropdown then -- block provides a specific list of choice elements
local val = elem.default
if meta:contains(elem.name) then
val = meta:get_string(elem.name) or ""
end
local choices = elem.on_dropdown(pos)
local l = choices:split(",")
local idx = index(l, val) or 1
tbl[#tbl+1] = "dropdown[4.72," .. (offs) .. ";5.5,1.4;" .. elem.name .. ";" .. choices .. ";" .. idx .. "]"
2021-06-09 23:09:59 +03:00
else
2021-06-27 19:29:46 +03:00
local val = elem.default
if meta:contains(elem.name) then
val = meta:get_string(elem.name) or ""
end
2022-09-18 12:53:51 +03:00
local idx
if elem.values then
idx = index(elem.values, val) or 1
else
local l = elem.choices:split(",")
idx = index(l, val) or 1
end
2021-06-09 23:09:59 +03:00
tbl[#tbl+1] = "dropdown[4.72," .. (offs) .. ";5.5,1.4;" .. elem.name .. ";" .. elem.choices .. ";" .. idx .. "]"
end
elseif elem.type == "items" then -- inventory
2024-07-14 23:26:54 +03:00
if elem.size then
tbl[#tbl+1] = "list[detached:" .. minetest.formspec_escape(player_name) .. "_techage_wrench_menu;cfg;4.75," .. offs .. ";" .. elem.size .. ",1;]"
else
tbl[#tbl+1] = "list[detached:" .. minetest.formspec_escape(player_name) .. "_techage_wrench_menu;cfg;4.75," .. offs .. ";" .. elem.width .. "," .. elem.height .. ";]"
end
2021-09-19 21:02:24 +03:00
player_inv_needed = true
2021-06-09 23:09:59 +03:00
end
end
2021-07-12 22:55:40 +03:00
if nvm.running or techage.is_running(nvm) then
local offs = #form_def * 0.9 - 0.2
tbl[#tbl+1] = "label[0," .. offs .. ";" .. S("Note: You can't change any values while the block is running!") .. "]"
end
2021-06-09 23:09:59 +03:00
end
2022-01-03 23:40:31 +03:00
2021-09-19 21:02:24 +03:00
return player_inv_needed, table.concat(tbl, "")
2021-06-09 23:09:59 +03:00
end
2022-09-16 20:30:49 +03:00
local function value_check(elem, value, player_name)
2021-06-09 23:09:59 +03:00
if elem.check then
2022-09-16 20:30:49 +03:00
return elem.check(value, player_name)
2021-06-09 23:09:59 +03:00
end
return value ~= nil
2021-06-09 23:09:59 +03:00
end
2022-01-03 23:40:31 +03:00
2021-09-19 21:02:24 +03:00
local function evaluate_data(pos, meta, form_def, fields, player_name)
2021-06-09 23:09:59 +03:00
local res = true
2022-01-03 23:40:31 +03:00
2021-06-09 23:09:59 +03:00
if meta and form_def then
local nvm = techage.get_nvm(pos)
2021-06-27 19:29:46 +03:00
if nvm.running or techage.is_running(nvm) then
return res
end
for idx,elem in ipairs(form_def) do
2022-01-03 23:40:31 +03:00
if elem.type == "number" then
2021-06-27 19:29:46 +03:00
if fields[elem.name] then
2022-01-03 23:40:31 +03:00
if fields[elem.name] == "" then
meta:set_string(elem.name, "")
elseif fields[elem.name]:find("^[%d ]+$") then
2021-06-09 23:09:59 +03:00
local val = tonumber(fields[elem.name])
2022-09-16 20:30:49 +03:00
if value_check(elem, val, player_name) then
2021-06-27 19:29:46 +03:00
meta:set_int(elem.name, val)
--print("set_int", elem.name, val)
2021-06-09 23:09:59 +03:00
else
res = false
end
2021-06-27 19:29:46 +03:00
else
res = false
2021-06-09 23:09:59 +03:00
end
2021-06-27 19:29:46 +03:00
end
2022-01-03 23:40:31 +03:00
elseif elem.type == "numbers" then
2021-06-27 19:29:46 +03:00
if fields[elem.name] then
2022-01-03 23:40:31 +03:00
if fields[elem.name] == "" then
meta:set_string(elem.name, "")
2022-09-16 20:30:49 +03:00
elseif fields[elem.name]:find("^[%d ]+$") and
value_check(elem, fields[elem.name], player_name) then
2021-06-27 19:29:46 +03:00
meta:set_string(elem.name, fields[elem.name])
else
res = false
end
end
elseif elem.type == "float" then
if fields[elem.name] == ""then
meta:set_string(elem.name, "")
elseif fields[elem.name] then
2021-06-27 19:29:46 +03:00
local val = tonumber(fields[elem.name])
2022-09-16 20:30:49 +03:00
if val and value_check(elem, val, player_name) then
2021-06-27 19:29:46 +03:00
meta:set_string(elem.name, val)
else
res = false
2021-06-09 23:09:59 +03:00
end
2021-06-27 19:29:46 +03:00
end
2022-01-03 23:40:31 +03:00
elseif elem.type == "ascii" then
if fields[elem.name] == ""then
meta:set_string(elem.name, "")
elseif fields[elem.name] then
2022-09-16 20:30:49 +03:00
if value_check(elem, fields[elem.name], player_name) then
2021-06-09 23:09:59 +03:00
meta:set_string(elem.name, fields[elem.name])
2021-06-27 19:29:46 +03:00
else
res = false
2021-06-09 23:09:59 +03:00
end
end
2022-01-03 23:40:31 +03:00
elseif elem.type == "dropdown" then
2021-06-27 19:29:46 +03:00
if fields[elem.name] ~= nil then
2022-09-18 12:53:51 +03:00
if elem.values then
local l = elem.choices:split(",")
local idx = index(l, fields[elem.name]) or 1
local text = elem.values[idx]
meta:set_string(elem.name, text)
else
meta:set_string(elem.name, fields[elem.name])
end
2021-06-27 19:29:46 +03:00
end
2022-01-03 23:40:31 +03:00
elseif elem.type == "items" and player_name then
2021-09-19 21:02:24 +03:00
local inv_name = minetest.formspec_escape(player_name) .. "_techage_wrench_menu"
local dinv = minetest.get_inventory({type = "detached", name = inv_name})
local ninv = minetest.get_inventory({type = "node", pos = pos})
if dinv and ninv then
for i = 1, ninv:get_size("cfg") do
ninv:set_stack("cfg", i, dinv:get_stack("cfg", i))
end
end
2021-06-09 23:09:59 +03:00
end
end
end
return res
end
2021-12-30 17:05:20 +03:00
function techage.menu.generate_formspec(pos, ndef, form_def, player_name)
2021-06-09 23:09:59 +03:00
local meta = minetest.get_meta(pos)
2022-01-18 23:38:57 +03:00
local number = techage.get_node_number(pos) or "-"
2021-06-09 23:09:59 +03:00
local mem = techage.get_mem(pos)
mem.star = ((mem.star or 0) + 1) % 2
local star = mem.star == 1 and "*" or ""
2021-12-30 17:05:20 +03:00
if player_name then
local inv_name = minetest.formspec_escape(player_name) .. "_techage_wrench_menu"
minetest.create_detached_inventory(inv_name, {
allow_put = allow_put,
allow_take = allow_take})
local dinv = minetest.get_inventory({type = "detached", name = inv_name})
local ninv = minetest.get_inventory({type = "node", pos = pos})
2022-01-03 23:40:31 +03:00
if dinv and ninv then
2021-12-30 17:05:20 +03:00
dinv:set_size('cfg', ninv:get_size("cfg"))
for i = 1, ninv:get_size("cfg") do
dinv:set_stack("cfg", i, ninv:get_stack("cfg", i))
end
2021-09-19 21:02:24 +03:00
end
end
2021-06-09 23:09:59 +03:00
if meta and number and ndef and form_def then
local title = ndef.description .. " (" .. number .. ")"
2021-09-19 21:02:24 +03:00
local player_inv_needed, text = generate_formspec_substring(pos, meta, form_def, player_name)
local buttons
2022-01-03 23:40:31 +03:00
2021-09-19 21:02:24 +03:00
if player_inv_needed then
buttons = "button[0.5,6.2;3,1;refresh;" .. S("Refresh") .. "]" ..
"button_exit[3.5,6.2;3,1;cancel;" .. S("Cancel") .. "]" ..
"button[6.5,6.2;3,1;save;" .. S("Save") .. "]" ..
"list[current_player;main;1,7.2;8,2;]"
else
buttons = "button[0.5,8.4;3,1;refresh;" .. S("Refresh") .. "]" ..
"button_exit[3.5,8.4;3,1;cancel;" .. S("Cancel") .. "]" ..
"button[6.5,8.4;3,1;save;" .. S("Save") .. "]"
end
2022-01-03 23:40:31 +03:00
2021-09-24 23:19:36 +03:00
if #form_def > 8 then
local size = (#form_def * 10) - 60
return "size[10,9]" ..
default.gui_bg ..
default.gui_bg_img ..
default.gui_slots ..
"box[0,-0.1;9.8,0.5;#c6e8ff]" ..
"label[0.2,-0.1;" .. minetest.colorize( "#000000", title) .. "]" ..
"label[9.5,-0.1;" .. minetest.colorize( "#000000", star) .. "]" ..
"scrollbaroptions[max=" .. size .. "]" ..
"scrollbar[9.4,0.6;0.4,7.7;vertical;wrenchmenu;]" ..
"scroll_container[0,1;12,9;wrenchmenu;vertical;]" ..
text ..
"scroll_container_end[]" ..
buttons
else
return "size[10,9]" ..
default.gui_bg ..
default.gui_bg_img ..
default.gui_slots ..
"box[0,-0.1;9.8,0.5;#c6e8ff]" ..
"label[0.2,-0.1;" .. minetest.colorize( "#000000", title) .. "]" ..
"label[9.5,-0.1;" .. minetest.colorize( "#000000", star) .. "]" ..
"container[0,1]" ..
text ..
"container_end[]" ..
buttons
end
2021-06-09 23:09:59 +03:00
end
return ""
end
2022-01-03 23:40:31 +03:00
function techage.menu.eval_input(pos, form_def, fields, player_name)
2022-01-02 23:00:46 +03:00
if fields.save or fields.key_enter_field then
2021-06-09 23:09:59 +03:00
local meta = minetest.get_meta(pos)
2021-09-19 21:02:24 +03:00
evaluate_data(pos, meta, form_def, fields, player_name)
2021-06-09 23:09:59 +03:00
end
2022-01-03 23:40:31 +03:00
return fields.refresh or fields.save or fields.key_enter_field
end
function techage.dropdown_index(sChoices, selected_value)
local l = sChoices:split(",")
return index(l, selected_value) or 1
2023-06-09 17:31:22 +03:00
end