From b492701915d6f0542ba39dabf9dfbfbdf215a6f6 Mon Sep 17 00:00:00 2001 From: Zefram Date: Thu, 1 May 2014 16:08:24 +0100 Subject: [PATCH] Show group ingredients visually in craft guide Where a recipe specifies an ingredient by group, show a typical group item pictorially, with a label flag to indicate that it's a group rather than the single item. This is the inverse of the previous arrangement, which identified the group by label and dipicted groupiness pictorially. The new arrangement is easier to interpret, and if the labels are ignored it actually shows a correct input to the crafting grid. --- api.lua | 4 +++ init.lua | 1 + register.lua | 99 +++++++++++++++++++++++++++++++++++++++++++++------- 3 files changed, 91 insertions(+), 13 deletions(-) diff --git a/api.lua b/api.lua index 18bc875..29af43b 100644 --- a/api.lua +++ b/api.lua @@ -147,6 +147,10 @@ unified_inventory.register_craft_type("digging", { height = 1, }) +function unified_inventory.register_group_representative_item(groupname, itemname) + unified_inventory.registered_group_representative_items[groupname] = itemname +end + function unified_inventory.register_page(name, def) unified_inventory.pages[name] = def end diff --git a/init.lua b/init.lua index ecb22da..058583d 100644 --- a/init.lua +++ b/init.lua @@ -12,6 +12,7 @@ unified_inventory.current_searchbox = {} unified_inventory.current_index = {} unified_inventory.current_item = {} unified_inventory.registered_craft_types = {} +unified_inventory.registered_group_representative_items = {} unified_inventory.crafts_table = {} unified_inventory.crafts_table_count = 0 unified_inventory.players = {} diff --git a/register.lua b/register.lua index cf9c923..82a7834 100644 --- a/register.lua +++ b/register.lua @@ -134,6 +134,74 @@ unified_inventory.register_page("craft", { end, }) +-- group_representative_item(): select representative item for a group +-- +-- This is used when displaying craft recipes, where an ingredient is +-- specified by group rather than as a specific item. A single-item group +-- is represented by that item, with the single-item status signalled +-- so that stack_image_button() can treat it as just the item. If the +-- group contains no items at all, it will be treated as containing a +-- single unknown item. +-- +-- Within a multiple-item group, we prefer to use an item that has the +-- same specific name as the group, and if there are more than one of +-- those items we prefer the one specified by the default mod if there +-- is one. If this produces a bad result, the mod defining a group can +-- register its preference for which item should represent the group, +-- and we'll use that instead if possible. Also, for a handful of groups +-- (predating this registration system) we have built-in preferences +-- that are used like registered preferences. Among equally-preferred +-- items, we just pick the one with the lexicographically earliest name, +-- for determinism. +local builtin_group_representative_items = { + mesecon_conductor_craftable = "mesecons:wire_00000000_off", + stone = "default:cobble", + wool = "wool:white", +} +local function compute_group_representative_item(groupspec) + local groupname = string.sub(groupspec, 7) + local candidate_items = {} + for itemname, itemdef in pairs(minetest.registered_items) do + if itemdef.groups[groupname] and itemdef.groups[groupname] ~= 0 then + table.insert(candidate_items, itemname) + end + end + print("group spec "..groupspec.." has "..#candidate_items.." candidates") + for _, i in ipairs(candidate_items) do + print(" ", i) + end + if #candidate_items == 0 then return { item = "unobtainium!", sole = true } end + if #candidate_items == 1 then return { item = candidate_items[1], sole = true } end + local bestitem = "" + local bestpref = 0 + for _, item in ipairs(candidate_items) do + local pref + if item == unified_inventory.registered_group_representative_items[groupname] then + pref = 5 + elseif item == builtin_group_representative_items[groupname] then + pref = 4 + elseif item == "default:"..groupname then + pref = 3 + elseif item:gsub("^[^:]*:", "") == groupname then + pref = 2 + else + pref = 1 + end + if pref > bestpref or (pref == bestpref and item < bestitem) then + bestitem = item + bestpref = pref + end + end + return { item = bestitem, sole = false } +end +local group_representative_item_cache = {} +local function group_representative_item(groupspec) + if not group_representative_item_cache[groupspec] then + group_representative_item_cache[groupspec] = compute_group_representative_item(groupspec) + end + return group_representative_item_cache[groupspec] +end + -- stack_image_button(): generate a form button displaying a stack of items -- -- Normally a simple item_image_button[] is used. If the stack contains @@ -147,24 +215,29 @@ unified_inventory.register_page("craft", { -- replaced as soon as the engine adds support for a proper item count, -- or at least label placement control, on buttons. -- --- The specified item may be a group. In that case, an image_button[] --- is used, displaying an image that just indicates grouping, with a --- label giving the name of the specific group. It very often happens --- that the group name doesn't fit within the confines of the button and --- gets cropped. Group names are also not brilliantly readable against --- the background of the group image. +-- The specified item may be a group. In that case, the group will be +-- represented by some item in the group, along with a flag indicating +-- that it's a group. If the group contains only one item, it will be +-- treated as if that item had been specified directly. local function stack_image_button(x, y, w, h, buttonname_prefix, stackstring) local st = ItemStack(stackstring) - local n = st:get_name() + local specitem = st:get_name() local c = st:get_count() - local clab = c == 1 and "" or string.format("%9d", c) - local buttonname = buttonname_prefix..n - local xywh = x..","..y..";"..w..","..h - if string.sub(n, 1, 6) == "group:" then - return "image_button["..xywh..";".."ui_group.png;"..minetest.formspec_escape(buttonname)..";"..minetest.formspec_escape(string.sub(n, 7)).."\n\n"..clab.."]" + local clab = c == 1 and " " or string.format("%7d", c) + local gflag, displayitem, selectitem + if string.sub(specitem, 1, 6) == "group:" then + local gri = group_representative_item(specitem) + gflag = not gri.sole + displayitem = gri.item + selectitem = gri.sole and gri.item or specitem else - return "item_image_button["..xywh..";"..minetest.formspec_escape(n)..";"..minetest.formspec_escape(buttonname_prefix..n)..";\n\n"..clab.."]" + gflag = false + displayitem = specitem + selectitem = specitem end + local label = string.format("\n\n%s%7d", gflag and "G" or " ", c):gsub(" 1$", " .") + if label == "\n\n ." then label = "" end + return "item_image_button["..x..","..y..";"..w..","..h..";"..minetest.formspec_escape(displayitem)..";"..minetest.formspec_escape(buttonname_prefix..selectitem)..";"..label.."]" end unified_inventory.register_page("craftguide", {