335 lines
12 KiB
Lua
335 lines
12 KiB
Lua
local S = logistica.TRANSLATOR
|
|
|
|
local META_CURR_PAGE = "ap_curr_p"
|
|
local META_SORT_TYPE = "ap_sort"
|
|
local META_FILTER_TYPE = "ap_fltr"
|
|
local META_CURR_SEARCH = "ap_curr_s"
|
|
local META_IGNORE_METADATA = "ap_usemd"
|
|
local META_CURR_LIQUID_INDEX = "ap_curr_l"
|
|
|
|
local STR_NO_LIQUID = S("No Liquid Storage")
|
|
local STR_EMPTY_RESERVOIRS = S("Free Capacity:")
|
|
|
|
local fakeInvMap = {}
|
|
local liquidsMap = {}
|
|
|
|
local LIQUID_NONE = -1
|
|
|
|
local SORT_NAME = 1
|
|
local SORT_MOD = 2
|
|
local SORT_COUNT = 3
|
|
local SORT_WEAR = 4
|
|
local sortMethodMap = {
|
|
[SORT_NAME] = function(list) return logistica.sort_list_by(list, LOG_SORT_NAME_AZ) end,
|
|
[SORT_MOD] = function(list) return logistica.sort_list_by(list, LOG_SORT_MOD_AZ) end,
|
|
[SORT_COUNT] = function(list) return logistica.sort_list_by(list, LOG_SORT_STACK_SIZE_REV) end,
|
|
[SORT_WEAR] = function(list) return logistica.sort_list_by(list, LOG_SORT_DURABILITY_FWD) end,
|
|
}
|
|
|
|
local FILTER_ALL = 1
|
|
local FILTER_NODES = 2
|
|
local FILTER_ITEMS = 3
|
|
local FILTER_TOOLS = 4
|
|
local FILTER_LIGHTS = 5
|
|
|
|
local filterMethodMap = {
|
|
[FILTER_ALL] = function(list,s) return list, s end,
|
|
[FILTER_NODES] = function(list,_) return logistica.filter_list_by(list, LOG_FILTER_NODE) end,
|
|
[FILTER_ITEMS] = function(list,_) return logistica.filter_list_by(list, LOG_FILTER_CRAFTITEM) end,
|
|
[FILTER_TOOLS] = function(list,_) return logistica.filter_list_by(list, LOG_FILTER_TOOL) end,
|
|
[FILTER_LIGHTS] = function(list,_) return logistica.filter_list_by(list, LOG_FILTER_LIGHT) end,
|
|
}
|
|
|
|
local h2p = minetest.get_position_from_hash
|
|
local get_meta = minetest.get_meta
|
|
|
|
local function do_search_for(stackList, term, stackListSize)
|
|
if not stackList or not term or term:gsub("%s+","") == "" then return stackList, stackListSize end
|
|
term = string.lower(term)
|
|
local match = function(stack) return string.find(string.lower(stack:get_description()), term, nil, true) ~= nil end
|
|
local grpS, grpE = term:find("group:", nil, true)
|
|
if grpS and grpS == 1 then
|
|
local groupName = string.sub(term, grpE + 1)
|
|
match = function(stack) return minetest.get_item_group(string.lower(stack:get_name()), groupName) > 0 end
|
|
end
|
|
local res = {}
|
|
local idx = 0
|
|
for _, stack in ipairs(stackList) do
|
|
if match(stack) then
|
|
idx = idx + 1
|
|
res[idx] = stack
|
|
end
|
|
end
|
|
return res, idx
|
|
end
|
|
|
|
local function get_curr_sort_method_int(meta)
|
|
local curr = meta:get_int(META_SORT_TYPE)
|
|
if curr <= 0 or curr >= 5 then return 1 else return curr end
|
|
end
|
|
|
|
local function set_curr_sort_method_int(meta, methodIndex)
|
|
meta:set_int(META_SORT_TYPE, methodIndex)
|
|
end
|
|
|
|
local function get_curr_filter_method_int(meta)
|
|
local curr = meta:get_int(META_FILTER_TYPE)
|
|
if curr <= 0 or curr >= 6 then return 1 else return curr end
|
|
end
|
|
|
|
local function set_curr_filter_method_int(meta, methodIndex)
|
|
meta:set_int(META_FILTER_TYPE, methodIndex)
|
|
end
|
|
|
|
local function add_list_to_itemmap(itemMap, list, useMetadata)
|
|
for _, stack in ipairs(list) do
|
|
if not stack:is_empty() then
|
|
local stackName = stack:get_name()
|
|
if useMetadata and stack:get_stack_max() == 1 then stackName = stack:to_string() end
|
|
if itemMap[stackName] == nil then itemMap[stackName] = 0 end
|
|
itemMap[stackName] = itemMap[stackName] + stack:get_count()
|
|
end
|
|
end
|
|
end
|
|
|
|
local function build_stack_list(pos)
|
|
local network = logistica.get_network_or_nil(pos)
|
|
if not network then return {stackList = {}, stackListSize = 0} end
|
|
local useMetadata = logistica.access_point_is_set_to_use_metadata(pos)
|
|
local meta = get_meta(pos)
|
|
|
|
local itemMap = {}
|
|
-- we scan all supply chests and mass storage and item storage
|
|
for hash, _ in pairs(network.suppliers) do
|
|
local mPos = logistica.load_position(h2p(hash))
|
|
local list = logistica.get_cache_list_for(mPos, get_meta(mPos), "main")
|
|
add_list_to_itemmap(itemMap, list, useMetadata)
|
|
end
|
|
for hash, _ in pairs(network.mass_storage) do
|
|
local mPos = logistica.load_position(h2p(hash))
|
|
local list = logistica.get_cache_list_for(mPos, get_meta(mPos), "storage")
|
|
add_list_to_itemmap(itemMap, list, useMetadata)
|
|
end
|
|
for hash, _ in pairs(network.item_storage) do
|
|
local mPos = logistica.load_position(h2p(hash))
|
|
local list = logistica.get_cache_list_for(mPos, get_meta(mPos), "main")
|
|
add_list_to_itemmap(itemMap, list, useMetadata)
|
|
end
|
|
local itemList = {}
|
|
local listSize = 0
|
|
for item, count in pairs(itemMap) do
|
|
local stack = ItemStack(item)
|
|
stack:set_count(count)
|
|
if count > 1 and stack:get_stack_max() == 1 then
|
|
stack:get_meta():set_string("count_meta", tostring(count))
|
|
end
|
|
listSize = listSize + 1
|
|
itemList[listSize] = stack
|
|
end
|
|
local searchList, searchSize =
|
|
do_search_for(itemList, logistica.access_point_get_current_search_term(meta), listSize)
|
|
local filtered, filtSize = filterMethodMap[get_curr_filter_method_int(meta)](searchList, searchSize)
|
|
local sorted = sortMethodMap[get_curr_sort_method_int(meta)](filtered)
|
|
return {
|
|
stackList = sorted,
|
|
stackListSize = filtSize,
|
|
}
|
|
end
|
|
|
|
-- { description = "description here", capacity = "3/32", texture = "texture_name.png"}
|
|
local function make_display_info(name, currBuckets, maxBuckets)
|
|
if not currBuckets or not maxBuckets then return { description = name, capacity = "", texture = ""} end
|
|
|
|
local desc, cap
|
|
if name == "" then
|
|
desc = STR_EMPTY_RESERVOIRS
|
|
cap = tostring(maxBuckets)
|
|
else
|
|
desc = logistica.reservoir_get_description_of_liquid(name)
|
|
cap = tostring(currBuckets).." / "..tostring(maxBuckets)
|
|
end
|
|
|
|
local texture = logistica.reservoir_get_texture_of_liquid(name)
|
|
return {
|
|
description = desc,
|
|
capacity = cap,
|
|
texture = texture,
|
|
}
|
|
end
|
|
|
|
--------------------------------
|
|
-- public functions
|
|
--------------------------------
|
|
|
|
function logistica.access_point_on_player_close(playerName)
|
|
fakeInvMap[playerName] = nil
|
|
liquidsMap[playerName] = nil
|
|
end
|
|
|
|
function logistica.update_fake_inv(pos, invName, listName, listSize, playerName)
|
|
local meta = get_meta(pos)
|
|
local inv = minetest.get_inventory({type = "detached", name = invName})
|
|
local pageInfo = logistica.access_point_get_current_page_info(pos, playerName, listSize, meta)
|
|
if pageInfo.max == 0 then inv:set_list(listName, {}) ; return end
|
|
local startingPos = (pageInfo.curr - 1) * listSize + 1
|
|
local fullList = fakeInvMap[playerName].stackList
|
|
if not fullList then return end
|
|
local fakeInvList = {}
|
|
for i = startingPos, startingPos + listSize do
|
|
fakeInvList[i - startingPos + 1] = fullList[i] or ItemStack("")
|
|
end
|
|
inv:set_list(listName, fakeInvList)
|
|
end
|
|
|
|
-- returns a table representing pages: {curr = #, max = #}
|
|
function logistica.access_point_get_current_page_info(pos, playerName, listSize, optMeta)
|
|
if not fakeInvMap[playerName] then return {curr = 0, max = 0} end
|
|
local meta = optMeta or get_meta(pos)
|
|
local storedPage = meta:get_int(META_CURR_PAGE)
|
|
if storedPage <= 0 then storedPage = 1 end
|
|
local fakeInv = fakeInvMap[playerName]
|
|
local maxPages = math.ceil(fakeInv.stackListSize / listSize)
|
|
if storedPage > maxPages then
|
|
storedPage = maxPages
|
|
meta:set_int(META_CURR_PAGE, storedPage)
|
|
end
|
|
return {curr = storedPage, max = maxPages}
|
|
end
|
|
|
|
function logistica.access_point_is_set_to_use_metadata(pos)
|
|
local meta = get_meta(pos)
|
|
return meta:get_int(META_IGNORE_METADATA) == 0
|
|
end
|
|
|
|
-- toggles whether to use metadata and returns the new state
|
|
function logistica.access_point_toggle_use_metadata(pos)
|
|
local meta = get_meta(pos)
|
|
local curr = meta:get_int(META_IGNORE_METADATA)
|
|
local new = (curr + 1) % 2
|
|
meta:set_int(META_IGNORE_METADATA, new)
|
|
return new == 0
|
|
end
|
|
|
|
-- returns true if page was changed, false if it wasn't
|
|
function logistica.access_point_change_page(pos, op, playerName, listSize)
|
|
local meta = get_meta(pos)
|
|
local currInfo = logistica.access_point_get_current_page_info(pos, playerName, listSize, meta)
|
|
if currInfo.max == 0 then return false end
|
|
local newPage = currInfo.curr
|
|
if op == 1 then newPage = newPage + 1
|
|
elseif op > 1 then newPage = currInfo.max
|
|
elseif op == -1 then newPage = newPage - 1
|
|
elseif op < -1 then newPage = 1 end
|
|
newPage = logistica.clamp(newPage, 1, currInfo.max)
|
|
if currInfo.curr == newPage then return false end
|
|
meta:set_int(META_CURR_PAGE, newPage)
|
|
return true
|
|
end
|
|
|
|
function logistica.access_point_get_filter_highlight_images(meta, highlightImg, blankImg)
|
|
local method = get_curr_filter_method_int(meta)
|
|
return {
|
|
all = (method == FILTER_ALL and highlightImg) or blankImg,
|
|
node = (method == FILTER_NODES and highlightImg) or blankImg,
|
|
craftitem = (method == FILTER_ITEMS and highlightImg) or blankImg,
|
|
tools = (method == FILTER_TOOLS and highlightImg) or blankImg,
|
|
lights = (method == FILTER_LIGHTS and highlightImg) or blankImg,
|
|
}
|
|
end
|
|
|
|
function logistica.access_point_get_sort_highlight_images(meta, highlightImg, blankImg)
|
|
local method = get_curr_sort_method_int(meta)
|
|
return {
|
|
name = (method == SORT_NAME and highlightImg) or blankImg,
|
|
mod = (method == SORT_MOD and highlightImg) or blankImg,
|
|
count = (method == SORT_COUNT and highlightImg) or blankImg,
|
|
wear = (method == SORT_WEAR and highlightImg) or blankImg,
|
|
}
|
|
end
|
|
|
|
function logistica.access_point_refresh_fake_inv(pos, invName, listName, listSize, playerName)
|
|
local listInfo = build_stack_list(pos)
|
|
fakeInvMap[playerName] = listInfo
|
|
logistica.update_fake_inv(pos, invName, listName, listSize, playerName)
|
|
end
|
|
|
|
function logistica.access_point_set_filter_method(pos, playerName, method)
|
|
set_curr_filter_method_int(get_meta(pos), method)
|
|
end
|
|
|
|
function logistica.access_point_set_sort_method(pos, playerName, method)
|
|
set_curr_sort_method_int(get_meta(pos), method)
|
|
end
|
|
|
|
function logistica.access_point_on_search_clear(pos)
|
|
local meta = get_meta(pos)
|
|
meta:set_string(META_CURR_SEARCH, "")
|
|
end
|
|
|
|
function logistica.access_point_on_search_change(pos, searchTerm)
|
|
local meta = get_meta(pos)
|
|
meta:set_string(META_CURR_SEARCH, searchTerm)
|
|
end
|
|
|
|
function logistica.access_point_get_current_search_term(meta)
|
|
return meta:get_string(META_CURR_SEARCH)
|
|
end
|
|
|
|
function logistica.access_point_change_liquid(meta, dir, playerName)
|
|
local liquidsInfo = liquidsMap[playerName]
|
|
if not liquidsInfo then return end
|
|
local currLiquidIndex = meta:get_int(META_CURR_LIQUID_INDEX)
|
|
if currLiquidIndex == LIQUID_NONE then return end
|
|
local numLiquids = #liquidsInfo
|
|
if numLiquids <= 0 then return end
|
|
local next = currLiquidIndex + dir
|
|
|
|
if next > numLiquids then next = 1 end
|
|
if next < 1 then next = numLiquids end
|
|
|
|
meta:set_int(META_CURR_LIQUID_INDEX, next)
|
|
return true
|
|
end
|
|
|
|
function logistica.access_point_refresh_liquids(pos, playerName)
|
|
local liquidsInfo = logistica.get_available_liquids_in_network(pos)
|
|
liquidsMap[playerName] = liquidsInfo
|
|
|
|
local meta = minetest.get_meta(pos)
|
|
if #liquidsInfo <= 0 then
|
|
meta:set_int(META_CURR_LIQUID_INDEX, LIQUID_NONE)
|
|
return
|
|
end
|
|
|
|
local currLiquid = meta:get_int(META_CURR_LIQUID_INDEX)
|
|
local validSelected = currLiquid >= 1 and currLiquid <= #liquidsInfo
|
|
if not validSelected then
|
|
meta:set_int(META_CURR_LIQUID_INDEX, 1)
|
|
end
|
|
end
|
|
|
|
-- returns a table: { description = "description here", capacity = "3/32", texture = "texture_name.png"}
|
|
function logistica.access_point_get_current_liquid_display_info(meta, playerName)
|
|
local liquidsInfo = liquidsMap[playerName]
|
|
if not liquidsInfo then return make_display_info(STR_NO_LIQUID, nil, nil) end
|
|
local currLiquid = meta:get_int(META_CURR_LIQUID_INDEX)
|
|
local liquidInfo = liquidsInfo[currLiquid]
|
|
|
|
if currLiquid == LIQUID_NONE or not liquidInfo then return make_display_info(STR_NO_LIQUID, nil, nil) end
|
|
|
|
return make_display_info(liquidInfo.name, liquidInfo.curr, liquidInfo.max)
|
|
end
|
|
|
|
-- returns the current liquid name (which may be "" for the empty reservoirs) or nil if invalid/no reservoirs
|
|
function logistica.access_point_get_current_liquid_name(meta, playerName)
|
|
local liquidsInfo = liquidsMap[playerName]
|
|
if not liquidsInfo then return nil end
|
|
|
|
local currLiquid = meta:get_int(META_CURR_LIQUID_INDEX)
|
|
if currLiquid == LIQUID_NONE then return "" end
|
|
|
|
local liquidInfo = liquidsInfo[currLiquid]
|
|
if not liquidInfo then return nil
|
|
else return liquidInfo.name end
|
|
end
|