* Natural sorting for chests * Fix sorting of separated tools/items containing infotext, reduce overhead of original stack collector Co-authored-by: SX <50966843+S-S-X@users.noreply.github.com>
256 lines
9.4 KiB
Lua
256 lines
9.4 KiB
Lua
|
|
local S = rawget(_G, "intllib") and intllib.Getter() or function(s) return s end
|
|
--local S = minetest.get_translator("technic_chests")
|
|
|
|
local has_pipeworks = minetest.get_modpath("pipeworks")
|
|
|
|
local function get_pipeworks_fs(x, y, meta)
|
|
-- Use a container to reposition the pipeworks button.
|
|
return "container["..x..","..(y - 4.3).."]"..
|
|
pipeworks.fs_helpers.cycling_button(
|
|
meta,
|
|
pipeworks.button_base,
|
|
"splitstacks",
|
|
{
|
|
pipeworks.button_off,
|
|
pipeworks.button_on
|
|
}
|
|
)..pipeworks.button_label.."container_end[]"
|
|
end
|
|
|
|
local function get_color_fs(x, y, meta)
|
|
local fs = ""
|
|
for a = 0, 3 do
|
|
for b = 0, 3 do
|
|
fs = fs.."image_button["..(x + b * 0.73)..","..(y + 0.1 + a * 0.79)..";0.8,0.8;"..
|
|
"technic_colorbutton"..(a * 4 + b)..".png;color_button"..(a * 4 + b + 1)..";]"
|
|
end
|
|
end
|
|
local selected = meta:get_int("color")
|
|
local color
|
|
if technic.chests.colors[selected] then
|
|
color = technic.chests.colors[selected][2]
|
|
else
|
|
color = S("None")
|
|
end
|
|
return fs.."label["..(x + 0.1)..","..(y + 3.4)..";"..S("Selected Color: %s"):format(color).."]"
|
|
end
|
|
|
|
local function get_quickmove_fs(x, y)
|
|
return "button["..x..","..y..";3,1;existing_to_chest;"..S("Move existing to Chest").."]"..
|
|
"label["..(x + 0.1)..","..(y + 1.15)..";"..S("Move specific")..":\n("..S("Drop to move")..")]"..
|
|
"list[context;quickmove;"..(x + 1.8)..","..(y + 1.15)..";1,1]"..
|
|
"button["..x..","..(y + 2.3)..";3,1;all_to_chest;"..S("Move all to Chest").."]"..
|
|
"button["..x..","..(y + 3.2)..";3,1;all_to_inv;"..S("Move all to Inventory").."]"
|
|
end
|
|
|
|
local function get_digilines_fs(x, y, meta)
|
|
local channel = minetest.formspec_escape(meta:get_string("channel"))
|
|
local put = meta:get_int("send_put") == 1 and "true" or "false"
|
|
local take = meta:get_int("send_take") == 1 and "true" or "false"
|
|
local inject = meta:get_int("send_inject") == 1 and "true" or "false"
|
|
local pull = meta:get_int("send_pull") == 1 and "true" or "false"
|
|
local overflow = meta:get_int("send_overflow") == 1 and "true" or "false"
|
|
return "field["..(x + 0.3)..","..(y + 0.5)..";3,1;channel;Digiline Channel:;"..channel.."]"..
|
|
"button["..(x + 0.5)..","..(y + 1.1)..";2,1;save_channel;Save Channel]"..
|
|
"checkbox["..(x + 0.1)..","..(y + 1.8)..";send_put;"..S("Send player put messages")..";"..put.."]"..
|
|
"checkbox["..(x + 0.1)..","..(y + 2.2)..";send_take;"..S("Send player take messages")..";"..take.."]"..
|
|
"checkbox["..(x + 0.1)..","..(y + 2.6)..";send_inject;"..S("Send tube inject messages")..";"..inject.."]"..
|
|
"checkbox["..(x + 0.1)..","..(y + 3.0)..";send_pull;"..S("Send tube pull messages")..";"..pull.."]"..
|
|
"checkbox["..(x + 0.1)..","..(y + 3.4)..";send_overflow;"..S("Send overflow messages")..";"..overflow.."]"
|
|
end
|
|
|
|
local function get_infotext_fs(editing, meta)
|
|
local infotext = minetest.formspec_escape(meta:get_string("infotext"))
|
|
if editing then
|
|
return "image_button[0,0.1;0.8,0.8;technic_checkmark_icon.png;save_infotext;]"..
|
|
"field[1,0.3;4,1;infotext;;"..infotext.."]"
|
|
else
|
|
return "image_button[0,0.1;0.8,0.8;technic_pencil_icon.png;edit_infotext;]"..
|
|
"label[1,0;"..infotext.."]"
|
|
end
|
|
end
|
|
|
|
local function get_autosort_fs(x, meta)
|
|
if meta:get_int("autosort") == 1 then
|
|
return "button["..x..",0;2,1;autosort;"..S("Auto-sort is On").."]"
|
|
else
|
|
return "button["..x..",0;2,1;autosort;"..S("Auto-sort is Off").."]"
|
|
end
|
|
end
|
|
|
|
local function get_sort_fs(x, meta)
|
|
local mode = meta:get_int("sort_mode")
|
|
local fs = "button["..(x + 2)..",0;1,1;sort;"..S("Sort").."]"
|
|
if mode == 1 then
|
|
return fs.."button["..x..",0;2,1;sort_mode;"..S("Sort by Quantity").."]"
|
|
elseif mode == 2 then
|
|
return fs.."button["..x..",0;2,1;sort_mode;"..S("Sort by Type").."]"
|
|
elseif mode == 3 then
|
|
return fs.."button["..x..",0;2,1;sort_mode;"..S("Sort by Wear").."]"
|
|
elseif mode == 4 then
|
|
return fs.."button["..x..",0;2,1;sort_mode;"..S("Natural sort").."]"
|
|
else
|
|
return fs.."button["..x..",0;2,1;sort_mode;"..S("Sort by Item").."]"
|
|
end
|
|
end
|
|
|
|
function technic.chests.get_formspec(data)
|
|
local formspec = {}
|
|
local top_width = (data.infotext and 6 or 0) + (data.autosort and 2 or 0) + (data.sort and 3 or 0)
|
|
local bottom_width = (data.quickmove and 3 or 0) + ((data.color or data.digilines) and 3 or 0) + 8
|
|
local width = math.max(top_width, bottom_width, data.width)
|
|
local padding = (width - bottom_width) / 2
|
|
if data.quickmove and (data.color or data.digilines) then
|
|
padding = (width - bottom_width) / 4
|
|
elseif data.quickmove or data.color or data.digilines then
|
|
padding = (width - bottom_width) / 3
|
|
end
|
|
local player_inv_left = padding
|
|
if data.quickmove then
|
|
player_inv_left = padding + 3 + padding
|
|
end
|
|
local player_inv_top = data.height + (has_pipeworks and 1.6 or 1.3)
|
|
local height = data.height + (has_pipeworks and 5.4 or 5.1)
|
|
local chest_inv_left = (width - data.width) / 2
|
|
formspec.base =
|
|
"size["..width..","..height.."]"..
|
|
"list[context;main;"..chest_inv_left..",1;"..data.width..","..data.height..";]"..
|
|
"list[current_player;main;"..player_inv_left..","..player_inv_top..";8,4;]"..
|
|
"listring[context;main]"..
|
|
"listring[current_player;main]"..
|
|
default.get_hotbar_bg(player_inv_left, player_inv_top)
|
|
if data.quickmove then
|
|
formspec.base = formspec.base..get_quickmove_fs(padding, data.height + 1.2)
|
|
end
|
|
formspec.padding = padding
|
|
formspec.width = width
|
|
return formspec
|
|
end
|
|
|
|
function technic.chests.update_formspec(pos, data, edit_infotext)
|
|
local formspec = data.formspec.base
|
|
local meta = minetest.get_meta(pos)
|
|
if data.infotext then
|
|
formspec = formspec..get_infotext_fs(edit_infotext, meta)
|
|
end
|
|
if data.sort then
|
|
formspec = formspec..get_sort_fs(data.formspec.width - 3, meta)
|
|
if data.autosort then
|
|
formspec = formspec..get_autosort_fs(data.formspec.width - 5, meta)
|
|
end
|
|
end
|
|
if has_pipeworks then
|
|
local offset = data.quickmove and (data.formspec.padding * 2 + 3) or data.formspec.padding
|
|
formspec = formspec..get_pipeworks_fs(offset, data.height + 1, meta)
|
|
end
|
|
if data.color or data.digilines then
|
|
local offset = data.quickmove and (data.formspec.padding * 3 + 11) or (data.formspec.padding * 2 + 8)
|
|
if data.color then
|
|
formspec = formspec..get_color_fs(offset, data.height + 1.2, meta)
|
|
else
|
|
formspec = formspec..get_digilines_fs(offset, data.height + 1.2, meta)
|
|
end
|
|
end
|
|
meta:set_string("formspec", formspec)
|
|
end
|
|
|
|
function technic.chests.get_receive_fields(data)
|
|
return function(pos, formname, fields, player)
|
|
if not fields or not player then
|
|
return
|
|
end
|
|
local meta = minetest.get_meta(pos)
|
|
local chest_inv = meta:get_inventory()
|
|
local player_inv = player:get_inventory()
|
|
if fields.quit then
|
|
if meta:get_int("autosort") == 1 then
|
|
technic.chests.sort_inv(chest_inv, meta:get_int("sort_mode"))
|
|
end
|
|
technic.chests.update_formspec(pos, data)
|
|
return
|
|
end
|
|
if not technic.chests.change_allowed(pos, player, data.locked, data.protected) then
|
|
return
|
|
end
|
|
if data.sort and fields.sort then
|
|
technic.chests.sort_inv(chest_inv, meta:get_int("sort_mode"))
|
|
return
|
|
end
|
|
if data.quickmove then
|
|
if fields.all_to_chest then
|
|
local moved_items = technic.chests.move_inv(player_inv, chest_inv)
|
|
if data.digilines and meta:get_int("send_put") == 1 then
|
|
technic.chests.send_digiline_message(pos, "put", player, moved_items)
|
|
end
|
|
technic.chests.log_inv_change(pos, player:get_player_name(), "put", "stuff")
|
|
return
|
|
elseif fields.all_to_inv then
|
|
local moved_items = technic.chests.move_inv(chest_inv, player_inv)
|
|
if data.digilines and meta:get_int("send_take") == 1 then
|
|
technic.chests.send_digiline_message(pos, "take", player, moved_items)
|
|
end
|
|
technic.chests.log_inv_change(pos, player:get_player_name(), "take", "stuff")
|
|
return
|
|
elseif fields.existing_to_chest then
|
|
local items = technic.chests.get_inv_items(chest_inv)
|
|
local moved_items = technic.chests.move_inv(player_inv, chest_inv, items)
|
|
if data.digilines and meta:get_int("send_put") == 1 then
|
|
technic.chests.send_digiline_message(pos, "put", player, moved_items)
|
|
end
|
|
technic.chests.log_inv_change(pos, player:get_player_name(), "put", "stuff")
|
|
return
|
|
end
|
|
end
|
|
if not technic.chests.change_allowed(pos, player, data.locked, true) then
|
|
return -- Protect settings from being changed, even for open chests
|
|
end
|
|
if has_pipeworks then
|
|
pipeworks.fs_helpers.on_receive_fields(pos, fields)
|
|
end
|
|
if data.sort and fields.sort_mode then
|
|
local value = meta:get_int("sort_mode")
|
|
meta:set_int("sort_mode", (value + 1) % 5)
|
|
end
|
|
if data.autosort and fields.autosort then
|
|
local value = meta:get_int("autosort") == 1 and 0 or 1
|
|
meta:set_int("autosort", value)
|
|
end
|
|
if data.color then
|
|
for i = 1, 16 do
|
|
if fields["color_button"..i] then
|
|
local node = minetest.get_node(pos)
|
|
if technic.chests.colors[i] then
|
|
node.name = data.node_name.."_"..technic.chests.colors[i][1]
|
|
else
|
|
node.name = data.node_name
|
|
end
|
|
minetest.swap_node(pos, node)
|
|
meta:set_int("color", i)
|
|
break
|
|
end
|
|
end
|
|
end
|
|
if data.digilines then
|
|
if fields.save_channel and fields.channel then
|
|
meta:set_string("channel", fields.channel)
|
|
end
|
|
for _,setting in pairs({"send_put", "send_take", "send_inject", "send_pull", "send_overflow"}) do
|
|
if fields[setting] then
|
|
local value = fields[setting] == "true" and 1 or 0
|
|
meta:set_int(setting, value)
|
|
end
|
|
end
|
|
end
|
|
if data.infotext then
|
|
if fields.edit_infotext then
|
|
technic.chests.update_formspec(pos, data, true)
|
|
return
|
|
elseif fields.save_infotext and fields.infotext then
|
|
meta:set_string("infotext", fields.infotext)
|
|
end
|
|
end
|
|
technic.chests.update_formspec(pos, data)
|
|
end
|
|
end
|