508 lines
14 KiB
Lua
508 lines
14 KiB
Lua
|
|
local S = core.get_translator(equip_exam.name)
|
|
|
|
|
|
-- wielded_light support
|
|
local function get_light_def(id) end
|
|
if core.global_exists("wielded_light") and wielded_light.get_light_def then
|
|
get_light_def = wielded_light.get_light_def
|
|
end
|
|
|
|
-- 3d_armor_light support
|
|
local function is_lighted_armor(id) end
|
|
if core.global_exists("armor_light") and armor_light.is_lighted then
|
|
is_lighted_armor = armor_light.is_lighted
|
|
end
|
|
|
|
-- workbench support
|
|
local workbench_repairable
|
|
if core.global_exists("workbench") and workbench.repairable then
|
|
workbench_repairable = function(iname)
|
|
return workbench:repairable(iname) or false
|
|
end
|
|
elseif core.global_exists("xdecor") and xdecor.is_repairable then
|
|
workbench_repairable = function(iname)
|
|
return xdecor:is_repairable(iname) or false
|
|
end
|
|
end
|
|
|
|
|
|
local general_types = {
|
|
["description"] = "Description",
|
|
["short_description"] = "Short Description",
|
|
["uses"] = "durability",
|
|
}
|
|
|
|
local tool_node_types = {
|
|
["cracky"] = "mine level",
|
|
["choppy"] = "chop level",
|
|
["crumbly"] = "dig level",
|
|
["snappy"] = "snap level",
|
|
["explody"] = "explosive level",
|
|
}
|
|
|
|
local tool_types = {
|
|
["max_drop_level"] = "node drop level",
|
|
["disable_repair"] = "repair disabled",
|
|
["not_repaired_by_anvil"] = "anvil repair disabled",
|
|
["_airtanks_uses"] = "uses",
|
|
["_airtanks_empty"] = "replace empty with",
|
|
}
|
|
for k, v in pairs(tool_node_types) do
|
|
tool_types[k] = v
|
|
end
|
|
|
|
local node_types = {
|
|
["attached_node"] = "attached",
|
|
["dig_immediate"] = "dig immediate",
|
|
["fall_damage_add_percent"] = "added fall damage",
|
|
["oddly_breakable_by_hand"] = "hand breakable",
|
|
["bouncy"] = true,
|
|
["ud_param2_colorable"] = "colorable",
|
|
["connect_to_raillike"] = "rail-like",
|
|
["disable_jump"] = "jump disabled",
|
|
["falling_node"] = "fall",
|
|
["float"] = "liquid boyancy",
|
|
["level"] = true,
|
|
["slippery"] = true,
|
|
["drop"] = "drops",
|
|
["is_ground_content"] = "ground content",
|
|
["buildable_to"] = "replaced on build",
|
|
["sunlight_propagates"] = true,
|
|
["walkable"] = true,
|
|
["pointable"] = true,
|
|
["diggable"] = true,
|
|
["climable"] = true,
|
|
["floodable"] = true,
|
|
["liquidtype"] = "liquid type",
|
|
["drawtype"] = true,
|
|
["light_source"] = "light level",
|
|
}
|
|
for k, v in pairs(tool_node_types) do
|
|
node_types[k] = v
|
|
end
|
|
|
|
local weapon_types = {
|
|
["fleshy"] = "attack",
|
|
["punch_attack_uses"] = "durability",
|
|
}
|
|
|
|
local armor_types = {
|
|
["fleshy"] = "defense",
|
|
["armor_head"] = "head def.",
|
|
["armor_torso"] = "torso def.",
|
|
["armor_legs"] = "legs def.",
|
|
["armor_feet"] = "feet def.",
|
|
["armor_shield"] = "shield def.",
|
|
["armor_use"] = "durability",
|
|
["armor_heal"] = "healing",
|
|
["armor_radiation"] = "radiation",
|
|
}
|
|
|
|
local entity_types = {
|
|
["punch_operable"] = true,
|
|
}
|
|
|
|
local other_types = {
|
|
["full_punch_interval"] = "speed interval",
|
|
["use_texture_alpha"] = "texture alpha mode",
|
|
["bagslots"] = "slots",
|
|
}
|
|
|
|
-- excluded from automatic parsing
|
|
local excluded_types = {
|
|
"name",
|
|
"description",
|
|
"short_description",
|
|
"type",
|
|
"punch_attack_uses",
|
|
"armor_use",
|
|
"stack_max",
|
|
"mod_origin",
|
|
"light_source",
|
|
"ud_param2_colorable",
|
|
}
|
|
|
|
local function is_excluded(spec)
|
|
for _, ex in ipairs(excluded_types) do
|
|
if spec == ex then return true end
|
|
end
|
|
|
|
return false
|
|
end
|
|
|
|
local function format_spec(grp, name, value, technical)
|
|
local v_type = type(value)
|
|
|
|
if v_type == "boolean" then
|
|
if value then
|
|
value = S("yes")
|
|
else
|
|
value = S("no")
|
|
end
|
|
end
|
|
|
|
if v_type == "string" then
|
|
value = value:gsub("\n", " ")
|
|
end
|
|
|
|
if technical then return name .. ": " .. value end
|
|
|
|
local nname = grp[name]
|
|
if not nname or nname == true then
|
|
nname = name:gsub("_", " "):trim()
|
|
end
|
|
|
|
return S(nname .. ": @1", value)
|
|
end
|
|
|
|
local function get_durability(value)
|
|
-- FIXME: not sure if `nil` means unlimited
|
|
if not value or value == 0 then return "∞" end
|
|
|
|
return value
|
|
end
|
|
|
|
local function get_item_specs(item, technical)
|
|
if not item then return nil end
|
|
|
|
local specs = {}
|
|
local name = item.short_description
|
|
if not name then name = item.description end
|
|
local id = item.name
|
|
|
|
-- remove multi-lines
|
|
if name:find("\n") then name = name:split("\n")[1]:trim() end
|
|
|
|
local groups = item.groups or {}
|
|
local tool_capabilities = item.tool_capabilities or {}
|
|
tool_capabilities.damage_groups = tool_capabilities.damage_groups or {}
|
|
tool_capabilities.groupcaps = tool_capabilities.groupcaps or {}
|
|
local armor_groups = item.armor_groups or {}
|
|
|
|
local specs_tool = {}
|
|
local specs_weapon = {}
|
|
local specs_armor = {}
|
|
local specs_node = {}
|
|
local specs_entity = {}
|
|
local specs_other = {}
|
|
|
|
local item_types = {}
|
|
item_types.tool = core.registered_tools[item.name] ~= nil
|
|
item_types.node = core.registered_nodes[item.name] ~= nil
|
|
item_types.entity = core.registered_entities[item.name] ~= nil
|
|
|
|
for k, v in pairs(tool_capabilities) do
|
|
if not is_excluded(k) then
|
|
if type(v) ~= "table" then
|
|
if tool_types[k] then
|
|
table.insert(specs_tool, format_spec(tool_types, k, v, technical))
|
|
item_types.tool = true
|
|
elseif weapon_types[k] then
|
|
table.insert(specs_weapon, format_spec(weapon_types, k, v, technical))
|
|
item_types.weapon = true
|
|
elseif armor_types[k] then
|
|
table.insert(specs_armor, format_spec(armor_types, k, v, technical))
|
|
item_types.armor = true
|
|
else
|
|
table.insert(specs_other, format_spec(other_types, k, v, technical))
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
for k, v in pairs(tool_capabilities.groupcaps) do
|
|
if type(v) ~= "table" then
|
|
table.insert(specs_other, k .. ": " .. v)
|
|
else
|
|
if v.maxlevel then
|
|
if tool_types[k] then
|
|
table.insert(specs_tool, format_spec(tool_types, k, v.maxlevel, technical))
|
|
table.insert(specs_tool, format_spec(general_types, "uses", get_durability(v.uses), technical))
|
|
item_types.tool = true
|
|
else
|
|
table.insert(specs_other, format_spec(other_types, k, v.maxlevel, technical))
|
|
table.insert(specs_other, format_spec(general_types, "uses", get_durability(v.uses), technical))
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
for k, v in pairs(tool_capabilities.damage_groups) do
|
|
if weapon_types[k] then
|
|
table.insert(specs_weapon, format_spec(weapon_types, k, v, technical))
|
|
item_types.weapon = true
|
|
else
|
|
table.insert(specs_other, format_spec(other_types, k, v, technical))
|
|
end
|
|
end
|
|
|
|
for k, v in pairs(armor_groups) do
|
|
if not is_excluded(k) then
|
|
if armor_types[k] then
|
|
if v ~= 0 then
|
|
table.insert(specs_armor, format_spec(armor_types, k, v, technical))
|
|
item_types.armor = true
|
|
end
|
|
else
|
|
table.insert(specs_other, format_spec(other_types, k, v, technical))
|
|
end
|
|
end
|
|
end
|
|
|
|
local type_group = tool_types
|
|
local spec_group = specs_tool
|
|
if item_types.node then
|
|
type_group = node_types
|
|
spec_group = specs_node
|
|
end
|
|
|
|
for k, v in pairs(groups) do
|
|
if not is_excluded(k) then
|
|
if type_group[k] then
|
|
table.insert(spec_group, format_spec(type_group, k, v, technical))
|
|
if not item_types.node then
|
|
item_types.tool = true
|
|
end
|
|
elseif weapon_types[k] then
|
|
table.insert(specs_weapon, format_spec(weapon_types, k, v, technical))
|
|
item_types.weapon = true
|
|
elseif armor_types[k] then
|
|
if v ~= 0 then
|
|
table.insert(specs_armor, format_spec(armor_types, k, v, technical))
|
|
item_types.armor = true
|
|
end
|
|
elseif entity_types[k] then
|
|
table.insert(specs_entity, format_spec(entity_types, k, v, technical))
|
|
item_types.entity = true
|
|
else
|
|
table.insert(specs_other, format_spec(other_types, k, v, technical))
|
|
end
|
|
end
|
|
end
|
|
|
|
local is_ranged = false
|
|
|
|
for k, v in pairs(table.copy(item)) do
|
|
local v_type = type(v)
|
|
if v_type == "table" or v_type == "function" or v_type == "userdata" then
|
|
v = nil
|
|
end
|
|
|
|
if v ~= nil and not is_excluded(k) then
|
|
if tool_types[k] then
|
|
table.insert(specs_tool, format_spec(tool_types, k, v, technical))
|
|
item_types.tool = true
|
|
elseif weapon_types[k] then
|
|
table.insert(specs_weapon, format_spec(weapon_types, k, v, technical))
|
|
item_types.weapon = true
|
|
elseif armor_types[k] then
|
|
table.insert(specs_armor, format_spec(armor_types, k, v, technical))
|
|
item_types.armor = true
|
|
elseif node_types[k] then
|
|
table.insert(specs_node, format_spec(node_types, k, v, technical))
|
|
item_types.node = true
|
|
elseif entity_types[k] then
|
|
table.insert(specs_entity, format_spec(entity_types, k, v, technical))
|
|
item_types.entity = true
|
|
else
|
|
local specs_group = specs_other
|
|
-- hack for slingshot
|
|
if k == "range" and id:find("^slingshot:") then
|
|
specs_group = specs_weapon
|
|
item_types.weapon = true
|
|
is_ranged = true
|
|
end
|
|
|
|
table.insert(specs_group, format_spec(other_types, k, v, technical))
|
|
end
|
|
end
|
|
end
|
|
|
|
local stackable = item.stack_max ~= 1
|
|
if not technical then
|
|
table.insert(specs_other, format_spec(other_types, "stackable", stackable, false))
|
|
end
|
|
if item.stack_max and (technical or stackable) then
|
|
table.insert(specs_other, format_spec(other_types, "stack_max", item.stack_max, technical))
|
|
end
|
|
|
|
if item_types.weapon and not is_ranged then
|
|
table.insert(specs_weapon, format_spec(weapon_types, "punch_attack_uses",
|
|
get_durability(tool_capabilities.punch_attack_uses), technical))
|
|
end
|
|
|
|
if item_types.armor then
|
|
local armor_use = groups.armor_use or armor_groups.armor_use
|
|
table.insert(specs_armor, format_spec(armor_types, "armor_use",
|
|
get_durability(armor_use), technical))
|
|
end
|
|
|
|
if item.light_source then
|
|
item_types.node = true
|
|
if not technical then
|
|
table.insert(specs_node, S("emits light: @1", S("yes")))
|
|
end
|
|
|
|
table.insert(specs_node, format_spec(node_types, "light_source", item.light_source, technical))
|
|
end
|
|
|
|
local light_level = get_light_def(id)
|
|
if light_level and light_level > 0 then
|
|
local spec_list, type_list = specs_tool, tool_types
|
|
if is_lighted_armor(id) then
|
|
item_types.armor = true
|
|
spec_list, type_list = specs_armor, armor_types
|
|
else
|
|
item_types.tool = true
|
|
end
|
|
|
|
if not technical then
|
|
table.insert(spec_list, S("emits light: @1", S("yes")))
|
|
end
|
|
|
|
table.insert(spec_list, format_spec(type_list, "light level", light_level, technical))
|
|
end
|
|
|
|
local colorable = groups.ud_param2_colorable ~= nil
|
|
if colorable then
|
|
item_types.node = true
|
|
table.insert(specs_node, format_spec(node_types, "ud_param2_colorable", groups.ud_param2_colorable,
|
|
technical))
|
|
|
|
local p_idx = tonumber(item.meta:get_string("palette_index"))
|
|
|
|
-- FIXME: perhaps store this in local variable to reduce load (will need to add unifieddyes as opt depends)
|
|
if not technical and p_idx and core.global_exists("unifieddyes") then
|
|
local color = unifieddyes.color_to_name(p_idx, item)
|
|
if color then
|
|
table.insert(specs_node, S("color: @1", color))
|
|
end
|
|
end
|
|
end
|
|
|
|
if not technical and workbench_repairable then
|
|
table.insert(specs_other, format_spec(other_types, "workbench repairable",
|
|
workbench_repairable(id), false))
|
|
end
|
|
|
|
if name then
|
|
table.insert(specs, S("Name: @1", name))
|
|
end
|
|
table.insert(specs, S("ID: @1", id))
|
|
|
|
if item.mod_origin then
|
|
table.insert(specs, S("Mod: @1", item.mod_origin))
|
|
end
|
|
|
|
for _, desc in ipairs({"description", "short_description"}) do
|
|
if item[desc] and item[desc] ~= name then
|
|
table.insert(specs, format_spec(general_types, desc, item[desc], false))
|
|
end
|
|
end
|
|
|
|
local it = {}
|
|
for k, v in pairs(item_types) do
|
|
if v then table.insert(it, k) end
|
|
end
|
|
|
|
if #it > 0 then
|
|
table.insert(specs, S("Type: @1", table.concat(it, ", ")))
|
|
end
|
|
|
|
if #specs_tool > 0 then
|
|
table.insert(specs, S("Tool:"))
|
|
for _, sp in ipairs(specs_tool) do
|
|
table.insert(specs, " " .. sp)
|
|
end
|
|
end
|
|
if #specs_weapon > 0 then
|
|
table.insert(specs, S("Weapon:"))
|
|
for _, sp in ipairs(specs_weapon) do
|
|
table.insert(specs, " " .. sp)
|
|
end
|
|
end
|
|
if #specs_armor > 0 then
|
|
table.insert(specs, S("Armor:"))
|
|
for _, sp in ipairs(specs_armor) do
|
|
table.insert(specs, " " .. sp)
|
|
end
|
|
end
|
|
if #specs_node > 0 then
|
|
table.insert(specs, S("Node:"))
|
|
for _, sp in ipairs(specs_node) do
|
|
table.insert(specs, " " .. sp)
|
|
end
|
|
end
|
|
if #specs_other > 0 then
|
|
table.insert(specs, S("Other:"))
|
|
for _, sp in ipairs(specs_other) do
|
|
table.insert(specs, " " .. sp)
|
|
end
|
|
end
|
|
|
|
local has_meta = false
|
|
local meta_table = item.meta:to_table().fields
|
|
|
|
-- clean excluded types
|
|
for _, ex in ipairs(excluded_types) do
|
|
meta_table[ex] = nil
|
|
end
|
|
|
|
-- check that meta is not empty
|
|
for k in pairs(meta_table) do
|
|
has_meta = true
|
|
break
|
|
end
|
|
|
|
if has_meta then
|
|
table.insert(specs, S("Meta:"))
|
|
for k, v in pairs(meta_table) do
|
|
table.insert(specs, " " .. format_spec(other_types, k, v, technical))
|
|
end
|
|
end
|
|
|
|
if not specs then return end
|
|
|
|
return core.formspec_escape(table.concat(specs, "|")):gsub("|", ",")
|
|
end
|
|
|
|
|
|
--- Retrieves formspec string.
|
|
--
|
|
-- @function equip_exam:get_formspec
|
|
-- @param item The item name string.
|
|
-- @param empty If *true*, no stats information will be printed.
|
|
function equip_exam:get_formspec(item, empty, nmeta)
|
|
local specs
|
|
local show_technical = nmeta:get_string("show_technical") == "true"
|
|
if not empty then
|
|
local item_table = core.registered_items[item:get_name()]
|
|
-- make sure we're using a recognized item before copying
|
|
if item_table then
|
|
item_table = table.copy(item_table)
|
|
item_table.meta = item:get_meta()
|
|
end
|
|
|
|
specs = get_item_specs(item_table, show_technical)
|
|
else
|
|
specs = "" -- empty
|
|
end
|
|
|
|
if not specs then
|
|
specs = S("ID: @1", item:get_name()) .. "," .. S("specs unavailable")
|
|
end
|
|
|
|
local formspec = "formspec_version[4]"
|
|
.. "size[13,9]"
|
|
.. "list[context;input;1,1;1,1;0]"
|
|
.. "checkbox[0.25,2.55;techname;" .. core.formspec_escape(S("Technical Names"):gsub(" ", "\n"))
|
|
.. ";" .. tostring(show_technical) .. "]"
|
|
.. "button_exit[0.25,3.1;2.5,0.8;close;" .. core.formspec_escape(S("Close")) .. "]"
|
|
.. "label[3,0.7;" .. core.formspec_escape(S("Specs:")) .. "]"
|
|
.. "textlist[3.5,1;8,3;speclist;" .. specs .. ";1;false]"
|
|
.. "list[current_player;main;1.65,4.1;8,4;0]"
|
|
|
|
return formspec
|
|
end
|