mod-listitems/api.lua

311 lines
6.9 KiB
Lua
Raw Normal View History

2017-06-14 23:37:18 -07:00
--[[ LICENSE HEADER
2017-06-14 23:37:18 -07:00
MIT Licensing
2017-06-14 23:37:18 -07:00
Copyright © 2017 Jordan Irwin
2017-06-14 23:37:18 -07:00
See: LICENSE.txt
--]]
2017-08-02 17:36:00 -07:00
--- List Items API
--
2021-07-07 20:00:40 -07:00
-- @topic api
2017-08-02 17:36:00 -07:00
2017-06-14 23:37:18 -07:00
local S = core.get_translator(listitems.modname)
2017-07-23 15:24:27 -07:00
local li = listitems
2021-04-29 05:03:04 -07:00
local sw_verbose = {"-v", S("Display descriptions")}
local sw_shallow = {"-s", S("Don't search descriptions")}
li.options = {
sw_verbose,
sw_shallow,
}
2017-08-02 17:36:00 -07:00
--- Valid option switches.
--
-- @table known_switches
-- @local
local known_switches = {}
for _, o in ipairs(li.options) do
table.insert(known_switches, o[1])
end
--- Valid list types.
--
-- @table known_types
-- @local
li.known_types = {
2021-04-29 05:03:04 -07:00
"items",
"entities",
"nodes",
"ores",
"tools",
}
2021-04-29 05:03:04 -07:00
if core.global_exists("mobs") then
table.insert(li.known_types, "mobs")
end
2017-08-02 17:36:00 -07:00
--- Checks if value is contained in list.
--
-- @function li.listContains
2017-08-02 17:36:00 -07:00
-- @local
-- @tparam table tlist List to be iterated.
-- @tparam string v String to search for in list.
-- @treturn boolean ***true*** if string found within list.
function li.listContains(tlist, v)
for index, value in ipairs(tlist) do
if v == value then
return true
end
end
return false
end
2017-08-02 17:36:00 -07:00
--- Retrieves a simplified table containing string names of registered items or entities.
--
-- @function getRegistered
-- @local
-- @tparam string r_type Must be either "items" or "entities".
2017-08-03 11:09:16 -07:00
-- @treturn table Either a list of registered item or entity names & descriptions.
-- @note Ore names are located in the "ore" field of the registered tables
local function getRegistered(r_type)
2017-08-03 11:09:16 -07:00
-- Default is "items"
2021-04-29 05:03:04 -07:00
r_type = r_type or "items"
local o_names = {}
local objects = {}
local o_temp = {}
2021-04-29 05:03:04 -07:00
if r_type == "entities" then
o_temp = core.registered_entities
2021-04-29 05:03:04 -07:00
elseif r_type == "nodes" then
2017-08-03 21:47:58 -07:00
o_temp = core.registered_nodes
2021-04-29 05:03:04 -07:00
elseif r_type == "ores" then
2017-08-03 11:09:16 -07:00
o_temp = core.registered_ores
2021-04-29 05:03:04 -07:00
elseif r_type == "tools" then
2017-08-04 00:32:12 -07:00
o_temp = core.registered_tools
2021-04-29 05:03:04 -07:00
elseif r_type == "mobs" then
o_temp = mobs.spawning_mobs
2017-08-03 11:09:16 -07:00
else
o_temp = core.registered_items
end
for name, def in pairs(o_temp) do
2021-04-29 05:03:04 -07:00
-- Ore names are located in the "ore" field of the table
if r_type == "ores" then
2017-08-03 11:09:16 -07:00
name = def.ore
2021-04-29 05:03:04 -07:00
elseif r_type == "mobs" then
def = {}
2017-08-03 11:09:16 -07:00
end
table.insert(objects, {name=name, descr=def.description,})
table.insert(o_names, name)
2017-08-01 14:07:57 -07:00
end
-- FIXME: More efficient method to sort output?
table.sort(o_names)
local o_sorted = {}
for i, name in ipairs(o_names) do
for I, entity in ipairs(objects) do
2017-08-01 14:07:57 -07:00
if entity.name == name then
table.insert(o_sorted, entity)
2017-08-01 14:07:57 -07:00
end
end
end
return o_sorted
end
2017-08-02 17:36:00 -07:00
--- Compares a string from a list of substrings.
--
-- @function compareSubstringList
-- @local
2017-08-02 17:36:00 -07:00
-- @tparam table ss_list
-- @tparam string s_value
-- @treturn boolean
2017-06-14 23:37:18 -07:00
local function compareSubstringList(ss_list, s_value)
for index, substring in ipairs(ss_list) do
-- Tests for substring (does not need to match full string)
if string.find(s_value, substring) then
return true
end
end
2017-06-14 23:37:18 -07:00
return false
end
2017-08-02 17:36:00 -07:00
--- Replaces duplicates found in a list.
--
-- @function li.removeListDuplicates
2017-08-02 17:36:00 -07:00
-- @local
-- @tparam table tlist
-- @treturn table
function li.removeListDuplicates(tlist)
2017-06-14 23:37:18 -07:00
local cleaned = {}
if tlist ~= nil then
for index, value in ipairs(tlist) do
if not li.listContains(cleaned, value) then
table.insert(cleaned, value)
end
2017-06-14 23:37:18 -07:00
end
end
2017-06-14 23:37:18 -07:00
return cleaned
end
2017-08-02 17:36:00 -07:00
--- Searches & formats list for matching strings.
--
-- @function formatMatching
-- @local
-- @tparam string player
-- @tparam table nlist
-- @tparam table params
-- @tparam table switches
-- @tparam boolean nocase
2017-08-02 17:36:00 -07:00
-- @treturn table
local function formatMatching(player, nlist, params, switches, nocase)
-- Defaults to case-insensitive
nocase = nocase == nil or nocase == true
local matching = {}
local show_descr = false
local deep_search = true
if switches ~= nil then
show_descr = li.listContains(switches, sw_verbose[1])
deep_search = not li.listContains(switches, sw_shallow[1])
end
if params == nil then
params = {}
end
-- Use entire list if no parameters supplied
if next(params) == nil then
for i, item in ipairs(nlist) do
2017-08-01 13:40:35 -07:00
if show_descr and item.descr ~= nil then
2021-04-29 05:03:04 -07:00
table.insert(matching, item.name .. " (" .. item.descr .. ")")
else
table.insert(matching, item.name)
end
end
else
-- Fill matching list
2017-08-01 13:40:35 -07:00
for i, item in ipairs(nlist) do
local name = item.name
local descr = item.descr
-- Case-insensitive matching
if nocase then
name = string.lower(name)
if descr ~= nil then
descr = string.lower(descr)
end
end
local matches = compareSubstringList(params, name)
if deep_search and not matches and descr ~= nil then
matches = compareSubstringList(params, descr)
end
if matches then
2017-08-01 13:40:35 -07:00
if show_descr and item.descr ~= nil then
2021-04-29 05:03:04 -07:00
table.insert(matching, item.name .. " (" .. item.descr .. ")")
else
2017-08-01 13:40:35 -07:00
table.insert(matching, item.name)
end
end
end
end
return matching
end
2021-04-29 05:03:04 -07:00
local bullet = ""
if listitems.bullet_list then
2021-04-29 05:03:04 -07:00
bullet = S("") .. " "
end
2017-08-02 17:36:00 -07:00
--- Displays list to player.
--
-- @function displayList
-- @local
-- @tparam string player
-- @tparam table dlist
local function displayList(player, dlist)
if dlist ~= nil then
for i, n in ipairs(dlist) do
core.chat_send_player(player, bullet .. n)
end
end
-- Show player number of items listed
2021-04-29 05:03:04 -07:00
core.chat_send_player(player, S("Objects listed:") .. " " .. tostring(#dlist))
end
2017-08-02 17:36:00 -07:00
--- *listitems* base function.
--
-- Lists registered items or entities.
--
-- @function listitems.list
-- @tparam string player Name of player to receive message output.
-- @tparam string l_type Objects to list (e.g. "items", "entities", "ores", etc.).
2017-08-03 16:36:25 -07:00
-- @tparam string switches String list of switch options for manipulating output.
-- @tparam string params String list of parameters.
-- @tparam boolean nocase Case-insensitive matching if ***true***.
2017-08-02 17:36:00 -07:00
-- @treturn boolean
function listitems.list(player, l_type, switches, params, nocase)
2017-08-02 17:03:32 -07:00
-- Default list type is "items"
2021-04-29 05:03:04 -07:00
l_type = l_type or "items"
nocase = nocase == nil or nocase == true
if not li.listContains(li.known_types, l_type) then
2021-04-29 05:03:04 -07:00
listitems.logWarn("listitems.list called with unknown list type: " .. tostring(l_type))
return false
end
2021-04-29 05:03:04 -07:00
if type(params) == "string" then
if nocase then
2017-08-02 17:03:32 -07:00
-- Make parameters case-insensitive
-- FIXME: Switches should not be case-insensitive
params = string.lower(params)
end
2017-08-02 17:03:32 -07:00
-- Split parameters into list & remove duplicates
params = li.removeListDuplicates(string.split(params, " "))
elseif nocase then
2017-08-02 17:03:32 -07:00
for i in pairs(params) do
params[i] = string.lower(params[i])
end
end
2021-04-29 05:03:04 -07:00
if type(switches) == "string" then
switches = string.split(switches, " ")
2017-08-02 17:03:32 -07:00
end
for i, s in ipairs(switches) do
if not li.listContains(known_switches, s) then
2021-04-29 05:03:04 -07:00
core.chat_send_player(player, S("Error: Unknown option:") .. " " .. s)
return false
end
end
2021-04-14 14:57:44 -07:00
local all_objects = getRegistered(l_type)
local matched_items = formatMatching(player, all_objects, params, switches, nocase)
displayList(player, matched_items)
return true
end