Added generic inv sorting func and Tool Box item sorting that uses it

This commit is contained in:
Zenon Seth 2023-11-10 18:26:41 +00:00
parent 1cbafa7e92
commit 34a09c60b2
6 changed files with 125 additions and 4 deletions

View File

@ -4,12 +4,12 @@ Missing Features:
- Crafting recipes
High Priority:
- Item Storage Sorting
- Mesecons compat
- Machine Upgrades
- Wirelss Network Extender
- Mesecons compat
Medium Priority
- Wirelss Network Extender
- inv_plus compatibility
- Remote Storage Access Point
- Crafting Supplier
- Rework all node models and textures; make new textures 32x32

View File

@ -2,18 +2,25 @@
local FORMSPEC_NAME = "logistica_itemstor"
local ON_OFF_BUTTON = "on_off_btn"
local ITEM_STORAGE_SIZE_PER_PAGE = 128
local SORT_PICKER = "sortby"
local SORT_BUTTON = "sortBtn"
local itemStorageForms = {}
local function get_item_storage_formspec(pos)
local meta = minetest.get_meta(pos)
local posForm = "nodemeta:"..pos.x..","..pos.y..","..pos.z
local isOn = logistica.is_machine_on(pos)
local sortValues = logistica.get_item_storage_sort_list_str()
local selectedSortIdx = logistica.get_item_storage_selected_sort_index(meta)
return "formspec_version[4]" ..
"size[20.5,16]" ..
logistica.ui.background..
logistica.ui.on_off_btn(isOn, 16.0, 11.0, ON_OFF_BUTTON, "Allow Network to take")..
"label[5.3,10.6;Tool Box: Accepts only tools, no stackable items]"..
logistica.ui.on_off_btn(isOn, 16.0, 11.0, ON_OFF_BUTTON, "Allow Network to take")..
"dropdown[16,12;2,0.8;"..SORT_PICKER..";"..sortValues..";"..selectedSortIdx..";false]"..
"button[18.5,12;1,0.8;"..SORT_BUTTON..";Sort]"..
"list["..posForm..";main;0.4,0.5;16,8;0]"..
"list[current_player;main;5.35,11.0;8,4;0]"..
"listring[]"
@ -33,12 +40,17 @@ local function on_player_receive_fields(player, formname, fields)
if not itemStorageForms[playerName] then return false end
local pos = itemStorageForms[playerName].position
if minetest.is_protected(pos, playerName) then return true end
local meta = minetest.get_meta(pos)
if fields.quit then
itemStorageForms[playerName] = nil
elseif fields[SORT_BUTTON] then
logistica.sort_item_storage_list(meta)
elseif fields[ON_OFF_BUTTON] then
logistica.toggle_machine_on_off(pos)
show_item_storage_formspec(player:get_player_name(), pos)
elseif fields[SORT_PICKER] then
logistica.set_item_storage_selected_sort_value(meta, fields[SORT_PICKER])
end
return true
end

40
logic/item_storage.lua Normal file
View File

@ -0,0 +1,40 @@
local ITEM_STORAGE_LIST = "main"
local META_STORED_ORDER = "logitemsort"
local sortFunctions = {
[1] = function(list) return logistica.sort_list_by(list, LOG_SORT_NAME_AZ) end,
[2] = function(list) return logistica.sort_list_by(list, LOG_SORT_MOD_AZ) end,
[3] = function(list) return logistica.sort_list_by(list, LOG_SORT_DURABILITY_FWD) end,
}
-- the order should match above lookup
local sortListOrder = {"Name", "Mod", "Durability"}
local sortListStr = table.concat(sortListOrder, ",")
--------------------------------
-- public functions
--------------------------------
function logistica.get_item_storage_sort_list_str()
return sortListStr
end
function logistica.get_item_storage_selected_sort_index(meta)
local index = meta:get_int(META_STORED_ORDER)
if index <= 0 then return 1 else return index end
end
function logistica.set_item_storage_selected_sort_value(meta, value)
meta:set_int(META_STORED_ORDER, table.indexof(sortListOrder, value))
end
function logistica.sort_item_storage_list(meta)
local sortFunc = sortFunctions[logistica.get_item_storage_selected_sort_index(meta)]
if not sortFunc then return end
local inv = meta:get_inventory()
local list = inv:get_list(ITEM_STORAGE_LIST)
local sortedList = sortFunc(list)
if not sortedList then return end
inv:set_list(ITEM_STORAGE_LIST, sortedList)
end

View File

@ -11,3 +11,4 @@ dofile(path .. "/mass_storage.lua")
dofile(path .. "/supplier.lua")
dofile(path .. "/requester.lua")
dofile(path .. "/injector.lua")
dofile(path .. "/item_storage.lua")

67
util/inv_list_sorting.lua Normal file
View File

@ -0,0 +1,67 @@
--------------------------------
-- private funcs
--------------------------------
local function get_description(st) return st:get_short_description() end
local function get_name(st) return st:get_name() end
local function get_stack_size(st) return st:get_count() end
local function get_wear(st) return st:get_wear() end
local compareSmallestFirst = function(s1,s2) return s1 < s2 end
local compareLargestFirst = function(s1,s2) return s1 > s2 end
local function create_sorter(valOf, compare)
return {
areEq = function(stack1, stack2) return valOf(stack1) == valOf(stack2) end,
compare = function (stack1, stack2) return compare(valOf(stack1), valOf(stack2)) end
}
end
local function do_sort(list, crit1, crit2)
if crit2 then
table.sort(list, function(s1, s2)
if crit1.areEq(s1, s2) then return crit2.compare(s1, s2) end
return crit1.compare(s1, s2)
end)
else
table.sort(list, crit1.compare)
end
end
--------------------------------
-- sorting criteria
--------------------------------
LOG_SORT_NAME_AZ = create_sorter(get_description, compareSmallestFirst)
LOG_SORT_NAME_ZA = create_sorter(get_description, compareLargestFirst)
LOG_SORT_MOD_AZ = create_sorter(get_name, compareSmallestFirst)
LOG_SORT_MOD_AZ = create_sorter(get_name, compareLargestFirst)
LOG_SORT_DURABILITY_FWD = create_sorter(get_wear, compareSmallestFirst)
LOG_SORT_DURABILITY_REV = create_sorter(get_wear, compareLargestFirst)
LOG_SORT_STACK_SIZE_FWD = create_sorter(get_stack_size, compareSmallestFirst)
LOG_SORT_STACK_SIZE_REV = create_sorter(get_stack_size, compareLargestFirst)
--------------------------------
-- public functions
--------------------------------
-- sorts the given list, returning a new, sorted copy
-- `criteria` must be one of:<br>
-- `LOG_SORT_NAME_AZ`, `LOG_SORT_MOD_AZ`, `LOG_SORT_DURABILITY`, `LOG_SORT_STACK_SIZE`<br>
-- `secondaryCriteria` is optional; takes a function just like `criteria` and will be used
-- if two items are equal by the primary `criteria`.<br>
-- `emptyFirst` is optional, default `nil`; `true` = put all empty slots at top; `false`/`nil` = put all empty slots at bottom
function logistica.sort_list_by(list, criteria, secondaryCriteria, emptyFirst)
if not list then return end
local filledList = {}
local emptyList = {}
for _, v in ipairs(list) do
if v:is_empty() then table.insert(emptyList, v)
else table.insert(filledList, v) end
end
do_sort(filledList, criteria, secondaryCriteria)
local first = filledList; local second = emptyList
if emptyFirst then first = emptyList ; second = filledList end
return table.insert_all(first, second)
end

View File

@ -6,6 +6,7 @@ dofile(path.."/hud.lua")
dofile(path.."/ui_logic.lua")
dofile(path.."/ui.lua")
dofile(path.."/sound.lua")
dofile(path.."/inv_list_sorting.lua")
-- bad debug
d = {}