128 lines
4.4 KiB
Lua
128 lines
4.4 KiB
Lua
-- Organize items in the craft inventory following a pattern:
|
|
local ui = unified_inventory
|
|
|
|
-- Backup to inject code
|
|
unified_inventory_plus.craft_organize = unified_inventory.pages["craft"].get_formspec
|
|
|
|
local function onload()
|
|
unified_inventory.pages["craft"] = {
|
|
get_formspec = function(player, perplayer_formspec)
|
|
local formspec = unified_inventory_plus.craft_organize(player, perplayer_formspec).formspec
|
|
local btnsz = ui.imgscale/3
|
|
local btnspc = ui.imgscale/2
|
|
|
|
if perplayer_formspec.pagecols == 4 then -- UI is in lite mode.
|
|
for i,v in ipairs(unified_inventory_plus.craft_patterns) do
|
|
formspec = formspec..string.format("image_button[%f,%f;%f,%f;%s;craft_organize_%i;]",
|
|
perplayer_formspec.craft_x + btnspc * (i-1),
|
|
perplayer_formspec.craft_y + 0.1 - btnspc,
|
|
btnsz, btnsz, v.ico, i)
|
|
end
|
|
else
|
|
for i,v in ipairs(unified_inventory_plus.craft_patterns) do
|
|
formspec = formspec..string.format("image_button[%f,%f;%f,%f;%s;craft_organize_%i;]",
|
|
perplayer_formspec.craft_x + btnspc * ((i-1)%6) + 0.1,
|
|
perplayer_formspec.craft_y + 0.22 - (math.ceil(i/6)) * btnspc,
|
|
btnsz, btnsz, v.ico, i)
|
|
end
|
|
end
|
|
return {formspec=formspec}
|
|
end,
|
|
}
|
|
end
|
|
|
|
onload()
|
|
|
|
|
|
|
|
-- Return if there is only one type and the item type name in the StackItems list (nil if none)
|
|
local function get_type_infos(craft_list)
|
|
local item = nil
|
|
for j=0,2 do
|
|
for i=1,3 do
|
|
if not craft_list[3*j+i]:is_empty() then
|
|
if item == nil then item = craft_list[3*j+i]
|
|
elseif item:get_name() ~= craft_list[3*j+i]:get_name() then return false, ""
|
|
end
|
|
end
|
|
end
|
|
end
|
|
return true, (item ~= nil) and item:get_name() or nil
|
|
end
|
|
|
|
-- Sum the craft_list items
|
|
local function get_total_amount(craft_list)
|
|
local nb = 0
|
|
for j=0,2 do
|
|
for i=1,3 do
|
|
nb = nb + craft_list[3*j+i]:get_count()
|
|
end
|
|
end
|
|
return nb
|
|
end
|
|
|
|
|
|
-- Organize items in the craft inventory following a pattern
|
|
local function craft_organize(player, formname, fields)
|
|
local pattern_id
|
|
for k, v in pairs(fields) do
|
|
pattern_id = k:match("craft_organize_(.*)")
|
|
if pattern_id then break end
|
|
end
|
|
if not pattern_id then return end
|
|
|
|
local player_inv = player:get_inventory()
|
|
assert(player_inv)
|
|
local player_name = player:get_player_name()
|
|
local craft_list = player_inv:get_list("craft")
|
|
local is_creative = minetest.get_player_privs(player_name).creative
|
|
|
|
-- Organize only on 1 type of item
|
|
local only_one_type, type_name = get_type_infos(craft_list)
|
|
if not type_name then return end -- craft is empty
|
|
if not only_one_type then minetest.chat_send_player(player_name, "You can only organize one type of item.") return end
|
|
|
|
local itemdef = minetest.registered_items[type_name]
|
|
if itemdef and itemdef.stack_max == 1 then
|
|
-- disallow non-stackable items
|
|
-- most of them have assiciated metadata which gets cleared in the reordering
|
|
minetest.chat_send_player(player_name, "You can only organize stackable items.")
|
|
return
|
|
end
|
|
|
|
|
|
-- Don't exceed 9*99 for non creative players. It shouldn't happen but avoids potential losses then
|
|
local total_amount = get_total_amount(craft_list)
|
|
if not is_creative and total_amount > 891 then minetest.chat_send_player(player_name, "There are too many items to organize ! Have less than 9 x 99 items.") return end
|
|
|
|
local res = {ItemStack(type_name),ItemStack(type_name),ItemStack(type_name),ItemStack(type_name),ItemStack(type_name),ItemStack(type_name),ItemStack(type_name),ItemStack(type_name),ItemStack(type_name)}
|
|
for i=1,9 do res[i]:set_count(0) end -- Doing this because using empty ItemStack in list constructor crashes the game :S
|
|
|
|
local pattern = unified_inventory_plus.craft_patterns[tonumber(pattern_id)].pattern
|
|
local nb_stacks = 0
|
|
for i in pairs(pattern) do nb_stacks = nb_stacks + 1 end
|
|
local stack_size = math.floor(total_amount / nb_stacks)
|
|
if not is_creative then stack_size = math.min(stack_size, ItemStack(type_name):get_stack_max()) end -- limit stacks to get_stack_max() for non creatives
|
|
local remaining = total_amount - nb_stacks * stack_size -- no % nb_stacks if limit: remaining could be greater than a stack
|
|
|
|
for i=1,nb_stacks do
|
|
res[pattern[i]]:add_item(type_name.." "..stack_size)
|
|
end
|
|
|
|
player_inv:set_list("craft", res)
|
|
place_item_in_stacks(player, "craft", type_name, remaining)
|
|
end
|
|
|
|
|
|
|
|
|
|
minetest.register_on_player_receive_fields(function(player, formname, fields)
|
|
--if not formname:match("craft") then return end
|
|
for k, v in pairs(fields) do
|
|
if k:match("craft_organize_") then
|
|
craft_organize(player, formname, fields)
|
|
return
|
|
end
|
|
end
|
|
end)
|