summaryrefslogtreecommitdiff
path: root/unified_inventory/register.lua
diff options
context:
space:
mode:
Diffstat (limited to 'unified_inventory/register.lua')
-rw-r--r--unified_inventory/register.lua261
1 files changed, 129 insertions, 132 deletions
diff --git a/unified_inventory/register.lua b/unified_inventory/register.lua
index d065e82..6b4454c 100644
--- a/unified_inventory/register.lua
+++ b/unified_inventory/register.lua
@@ -266,64 +266,77 @@ unified_inventory.register_page("craftguide", {
local player_name = player:get_player_name()
local player_privs = minetest.get_player_privs(player_name)
- local formspec = ""
- formspec = formspec.."background[0,"..(formspecy + 3.5)..";8,4;ui_main_inventory.png]"
- formspec = formspec.."label[0,"..formheadery..";" .. F(S("Crafting Guide")) .. "]"
- formspec = formspec.."listcolors[#00000000;#00000000]"
+ local fs = {
+ "background[0,"..(formspecy + 3.5)..";8,4;ui_main_inventory.png]",
+ "label[0,"..formheadery..";" .. F(S("Crafting Guide")) .. "]",
+ "listcolors[#00000000;#00000000]"
+ }
local item_name = unified_inventory.current_item[player_name]
- if not item_name then return {formspec=formspec} end
+ if not item_name then
+ return { formspec = table.concat(fs) }
+ end
+
local item_name_shown
- if minetest.registered_items[item_name] and minetest.registered_items[item_name].description then
- item_name_shown = string.format(S("%s (%s)"), minetest.registered_items[item_name].description, item_name)
+ if minetest.registered_items[item_name]
+ and minetest.registered_items[item_name].description then
+ item_name_shown = string.format(S("%s (%s)"),
+ minetest.registered_items[item_name].description, item_name)
else
item_name_shown = item_name
end
local dir = unified_inventory.current_craft_direction[player_name]
- local rdir
- if dir == "recipe" then rdir = "usage" end
- if dir == "usage" then rdir = "recipe" end
+ local rdir = dir == "recipe" and "usage" or "recipe"
+
local crafts = unified_inventory.crafts_for[dir][item_name]
local alternate = unified_inventory.alternate[player_name]
local alternates, craft
- if crafts ~= nil and #crafts > 0 then
+ if crafts and #crafts > 0 then
alternates = #crafts
craft = crafts[alternate]
end
local has_give = player_privs.give or unified_inventory.is_creative(player_name)
- formspec = formspec.."background[0.5,"..(formspecy + 0.2)..";8,3;ui_craftguide_form.png]"
- formspec = formspec.."textarea["..craftresultx..","..craftresulty
- ..";10,1;;"..F(role_text[dir])..": "..item_name_shown..";]"
- formspec = formspec..stack_image_button(0, formspecy, 1.1, 1.1, "item_button_"
- .. rdir .. "_", ItemStack(item_name))
+ fs[#fs + 1] = "background[0.5,"..(formspecy + 0.2)..";8,3;ui_craftguide_form.png]"
+ fs[#fs + 1] = string.format("textarea[%f,%f;10,1;;%s: %s;]",
+ craftresultx, craftresulty, F(role_text[dir]), item_name_shown)
+ fs[#fs + 1] = stack_image_button(0, formspecy, 1.1, 1.1,
+ "item_button_" .. rdir .. "_", ItemStack(item_name))
if not craft then
- formspec = formspec.."label[5.5,"..(formspecy + 2.35)..";"
- ..F(no_recipe_text[dir]).."]"
+ -- No craft recipes available for this item.
+ fs[#fs + 1] = "label[5.5,"..(formspecy + 2.35)..";"
+ .. F(no_recipe_text[dir]) .. "]"
local no_pos = dir == "recipe" and 4.5 or 6.5
local item_pos = dir == "recipe" and 6.5 or 4.5
- formspec = formspec.."image["..no_pos..","..formspecy..";1.1,1.1;ui_no.png]"
- formspec = formspec..stack_image_button(item_pos, formspecy, 1.1, 1.1, "item_button_"
- ..other_dir[dir].."_", ItemStack(item_name))
+ fs[#fs + 1] = "image["..no_pos..","..formspecy..";1.1,1.1;ui_no.png]"
+ fs[#fs + 1] = stack_image_button(item_pos, formspecy, 1.1, 1.1,
+ "item_button_" .. other_dir[dir] .. "_", ItemStack(item_name))
if has_give then
- formspec = formspec.."label[0,"..(formspecy + 2.10)..";" .. F(S("Give me:")) .. "]"
- .."button[0, "..(formspecy + 2.7)..";0.6,0.5;craftguide_giveme_1;1]"
- .."button[0.6,"..(formspecy + 2.7)..";0.7,0.5;craftguide_giveme_10;10]"
- .."button[1.3,"..(formspecy + 2.7)..";0.8,0.5;craftguide_giveme_99;99]"
+ fs[#fs + 1] = "label[0," .. (formspecy + 2.10) .. ";" .. F(S("Give me:")) .. "]"
+ .. "button[0, " .. (formspecy + 2.7) .. ";0.6,0.5;craftguide_giveme_1;1]"
+ .. "button[0.6," .. (formspecy + 2.7) .. ";0.7,0.5;craftguide_giveme_10;10]"
+ .. "button[1.3," .. (formspecy + 2.7) .. ";0.8,0.5;craftguide_giveme_99;99]"
end
- return {formspec = formspec}
+ return { formspec = table.concat(fs) }
end
local craft_type = unified_inventory.registered_craft_types[craft.type] or
unified_inventory.craft_type_defaults(craft.type, {})
if craft_type.icon then
- formspec = formspec..string.format(" image[%f,%f;%f,%f;%s]",5.7,(formspecy + 0.05),0.5,0.5,craft_type.icon)
+ fs[#fs + 1] = string.format("image[%f,%f;%f,%f;%s]",
+ 5.7, (formspecy + 0.05), 0.5, 0.5, craft_type.icon)
end
- formspec = formspec.."label[5.5,"..(formspecy + 1)..";" .. F(craft_type.description).."]"
- formspec = formspec..stack_image_button(6.5, formspecy, 1.1, 1.1, "item_button_usage_", ItemStack(craft.output))
- local display_size = craft_type.dynamic_display_size and craft_type.dynamic_display_size(craft) or { width = craft_type.width, height = craft_type.height }
- local craft_width = craft_type.get_shaped_craft_width and craft_type.get_shaped_craft_width(craft) or display_size.width
+ fs[#fs + 1] = "label[5.5,"..(formspecy + 1)..";" .. F(craft_type.description).."]"
+ fs[#fs + 1] = stack_image_button(6.5, formspecy, 1.1, 1.1,
+ "item_button_usage_", ItemStack(craft.output))
+
+ local display_size = craft_type.dynamic_display_size
+ and craft_type.dynamic_display_size(craft)
+ or { width = craft_type.width, height = craft_type.height }
+ local craft_width = craft_type.get_shaped_craft_width
+ and craft_type.get_shaped_craft_width(craft)
+ or display_size.width
-- This keeps recipes aligned to the right,
-- so that they're close to the arrow.
@@ -358,47 +371,45 @@ unified_inventory.register_page("craftguide", {
local xof = (fx-1) * of + of
local yof = (y-1) * of + 1
if item then
- formspec = formspec..stack_image_button(
+ fs[#fs + 1] = stack_image_button(
xoffset - xof, formspecy - 1 + yof, bsize_w, bsize_h,
"item_button_recipe_",
ItemStack(item))
else
-- Fake buttons just to make grid
- formspec = formspec.."image_button["
- ..tostring(xoffset - xof)..","..tostring(formspecy - 1 + yof)
- ..";"..bsize_w..","..bsize_h..";ui_blank_image.png;;]"
+ fs[#fs + 1] = string.format("image_button[%f,%f;%f,%f;ui_blank_image.png;;]",
+ xoffset - xof, formspecy - 1 + yof, bsize_w, bsize_h)
end
end
end
else
-- Error
- formspec = formspec.."label["
- ..tostring(2)..","..tostring(formspecy)
- ..";"..F(S("This recipe is too\nlarge to be displayed.")).."]"
+ fs[#fs + 1] = string.format("label[2,%f;%s]",
+ formspecy, F(S("This recipe is too\nlarge to be displayed.")))
end
if craft_type.uses_crafting_grid and display_size.width <= 3 then
- formspec = formspec.."label[0,"..(formspecy + 0.9)..";" .. F(S("To craft grid:")) .. "]"
- .."button[0, "..(formspecy + 1.5)..";0.6,0.5;craftguide_craft_1;1]"
- .."button[0.6,"..(formspecy + 1.5)..";0.7,0.5;craftguide_craft_10;10]"
- .."button[1.3,"..(formspecy + 1.5)..";0.8,0.5;craftguide_craft_max;" .. F(S("All")) .. "]"
+ fs[#fs + 1] = "label[0," .. (formspecy + 0.9) .. ";" .. F(S("To craft grid:")) .. "]"
+ .. "button[0, " .. (formspecy + 1.5) .. ";0.6,0.5;craftguide_craft_1;1]"
+ .. "button[0.6," .. (formspecy + 1.5) .. ";0.7,0.5;craftguide_craft_10;10]"
+ .. "button[1.3," .. (formspecy + 1.5) .. ";0.8,0.5;craftguide_craft_max;" .. F(S("All")) .. "]"
end
if has_give then
- formspec = formspec.."label[0,"..(formspecy + 2.1)..";" .. F(S("Give me:")) .. "]"
- .."button[0, "..(formspecy + 2.7)..";0.6,0.5;craftguide_giveme_1;1]"
- .."button[0.6,"..(formspecy + 2.7)..";0.7,0.5;craftguide_giveme_10;10]"
- .."button[1.3,"..(formspecy + 2.7)..";0.8,0.5;craftguide_giveme_99;99]"
+ fs[#fs + 1] = "label[0," .. (formspecy + 2.1) .. ";" .. F(S("Give me:")) .. "]"
+ .. "button[0, " .. (formspecy + 2.7) .. ";0.6,0.5;craftguide_giveme_1;1]"
+ .. "button[0.6," .. (formspecy + 2.7) .. ";0.7,0.5;craftguide_giveme_10;10]"
+ .. "button[1.3," .. (formspecy + 2.7) .. ";0.8,0.5;craftguide_giveme_99;99]"
end
if alternates and alternates > 1 then
- formspec = formspec.."label[5.5,"..(formspecy + 1.6)..";"
- ..string.format(F(recipe_text[dir]), alternate, alternates).."]"
- .."image_button[5.5,"..(formspecy + 2)..";1,1;ui_left_icon.png;alternate_prev;]"
- .."image_button[6.5,"..(formspecy + 2)..";1,1;ui_right_icon.png;alternate;]"
- .."tooltip[alternate_prev;"..F(prev_alt_text[dir]).."]"
- .."tooltip[alternate;"..F(next_alt_text[dir]).."]"
+ fs[#fs + 1] = "label[5.5," .. (formspecy + 1.6) .. ";"
+ .. string.format(F(recipe_text[dir]), alternate, alternates) .. "]"
+ .. "image_button[5.5," .. (formspecy + 2) .. ";1,1;ui_left_icon.png;alternate_prev;]"
+ .. "image_button[6.5," .. (formspecy + 2) .. ";1,1;ui_right_icon.png;alternate;]"
+ .. "tooltip[alternate_prev;" .. F(prev_alt_text[dir]) .. "]"
+ .. "tooltip[alternate;" .. F(next_alt_text[dir]) .. "]"
end
- return {formspec = formspec}
+ return { formspec = table.concat(fs) }
end,
})
@@ -429,78 +440,63 @@ local function craftguide_giveme(player, formname, fields)
player_inv:add_item("main", {name = output, count = amount})
end
--- tells if an item can be moved and returns an index if so
-local function item_fits(player_inv, craft_item, needed_item)
- local need_group = string.sub(needed_item, 1, 6) == "group:"
- if need_group then
- need_group = string.sub(needed_item, 7)
+-- Takes any stack from "main" where the `amount` of `needed_item` may fit
+-- into the given crafting stack (`craft_item`)
+local function craftguide_move_stacks(inv, craft_item, needed_item, amount)
+ if craft_item:get_count() >= amount then
+ return
end
- if craft_item
- and not craft_item:is_empty() then
- local ciname = craft_item:get_name()
- -- abort if the item there isn't usable
- if ciname ~= needed_item
- and not need_group then
- return
- end
-
- -- abort if no item fits onto it
- if craft_item:get_count() >= craft_item:get_definition().stack_max then
- return
- end
-
- -- use the item there if it's in the right group and a group item is needed
- if need_group then
- if minetest.get_item_group(ciname, need_group) == 0 then
+ local get_item_group = minetest.get_item_group
+ local group = needed_item:match("^group:(.+)")
+ if group then
+ if not craft_item:is_empty() then
+ -- Source item must be the same to fill
+ if get_item_group(craft_item:get_name(), group) ~= 0 then
+ needed_item = craft_item:get_name()
+ else
+ -- TODO: Maybe swap unmatching "craft" items
+ -- !! Would conflict with recursive function call
return
end
- needed_item = ciname
- need_group = false
- end
- end
-
- if need_group then
- -- search an item of the specific group
- for i,item in pairs(player_inv:get_list("main")) do
- if not item:is_empty()
- and minetest.get_item_group(item:get_name(), need_group) > 0 then
- return i
+ else
+ -- Take matching group from the inventory (biggest stack)
+ local main = inv:get_list("main")
+ local max_found = 0
+ for i, stack in ipairs(main) do
+ if stack:get_count() > max_found and
+ get_item_group(stack:get_name(), group) ~= 0 then
+ needed_item = stack:get_name()
+ max_found = stack:get_count()
+ if max_found >= amount then
+ break
+ end
+ end
end
end
-
- -- no index found
- return
- end
-
- -- search an item with a the name needed_item
- for i,item in pairs(player_inv:get_list("main")) do
- if not item:is_empty()
- and item:get_name() == needed_item then
- return i
+ else
+ if not craft_item:is_empty() and
+ craft_item:get_name() ~= needed_item then
+ return -- Item must be identical
end
end
- -- no index found
-end
-
--- modifies the player inventory and returns the changed craft_item if possible
-local function move_item(player_inv, craft_item, needed_item)
- local stackid = item_fits(player_inv, craft_item, needed_item)
- if not stackid then
- return
+ needed_item = ItemStack(needed_item)
+ local to_take = math.min(amount, needed_item:get_stack_max())
+ to_take = to_take - craft_item:get_count()
+ if to_take <= 0 then
+ return -- Nothing to do
end
- local wanted_stack = player_inv:get_stack("main", stackid)
- local taken_item = wanted_stack:take_item()
- player_inv:set_stack("main", stackid, wanted_stack)
-
- if not craft_item
- or craft_item:is_empty() then
- return taken_item
+ needed_item:set_count(to_take)
+
+ local taken = inv:remove_item("main", needed_item)
+ local leftover = taken:add_item(craft_item)
+ if not leftover:is_empty() then
+ -- Somehow failed to add the existing "craft" item. Undo the action.
+ inv:add_item("main", leftover)
+ return taken
end
-
- craft_item:add_item(taken_item)
- return craft_item
+ return taken
end
local function craftguide_craft(player, formname, fields)
@@ -510,15 +506,21 @@ local function craftguide_craft(player, formname, fields)
if amount then break end
end
if not amount then return end
+
+ amount = tonumber(amount) or 99 -- fallback for "all"
+ if amount <= 0 or amount > 99 then return end
+
local player_name = player:get_player_name()
- local output = unified_inventory.current_item[player_name]
- if (not output) or (output == "") then return end
+ local output = unified_inventory.current_item[player_name] or ""
+ if output == "" then return end
local player_inv = player:get_inventory()
+ local craft_list = player_inv:get_list("craft")
- local crafts = unified_inventory.crafts_for[unified_inventory.current_craft_direction[player_name]][output]
- if (not crafts) or (#crafts == 0) then return end
+ local crafts = unified_inventory.crafts_for[
+ unified_inventory.current_craft_direction[player_name]][output] or {}
+ if #crafts == 0 then return end
local alternate = unified_inventory.alternate[player_name]
@@ -526,24 +528,17 @@ local function craftguide_craft(player, formname, fields)
if craft.width > 3 then return end
local needed = craft.items
-
- local craft_list = player_inv:get_list("craft")
-
local width = craft.width
if width == 0 then
-- Shapeless recipe
width = 3
end
- amount = tonumber(amount) or 99
- --[[
- if amount == "max" then
- amount = 99 -- Arbitrary; need better way to do this.
- else
- amount = tonumber(amount)
- end--]]
-
- for iter = 1, amount do
+ -- To spread the items evenly
+ local STEPSIZE = math.ceil(math.sqrt(amount) / 5) * 5
+ local current_count = 0
+ repeat
+ current_count = math.min(current_count + STEPSIZE, amount)
local index = 1
for y = 1, 3 do
for x = 1, width do
@@ -551,7 +546,9 @@ local function craftguide_craft(player, formname, fields)
if needed_item then
local craft_index = ((y - 1) * 3) + x
local craft_item = craft_list[craft_index]
- local newitem = move_item(player_inv, craft_item, needed_item)
+ local newitem = craftguide_move_stacks(player_inv,
+ craft_item, needed_item, current_count)
+
if newitem then
craft_list[craft_index] = newitem
end
@@ -559,7 +556,7 @@ local function craftguide_craft(player, formname, fields)
index = index + 1
end
end
- end
+ until current_count == amount
player_inv:set_list("craft", craft_list)