Add craft empty and fill buttons.

master
Duane Robertson 2019-07-28 06:06:43 -05:00
parent 67c72c3744
commit fb9246dd69
1 changed files with 212 additions and 15 deletions

227
init.lua
View File

@ -421,13 +421,15 @@ local worn_items = mod.worn_items
-- Formspec definitions are confusing.
mod.form_size = 'size[11.25,7.25]'
mod.main_inventory = 'list[current_player;main;0,3.5;8,4;'
mod.craft_inventory = 'list[current_player;craft;1,0;3,3;]'
mod.craft_preview = 'list[current_player;craftpreview;4,2;1,1;]'
mod.main_inventory_scroll_up = 'image_button[8,3.5;1,1;transparent_button.png;dinv_main_inventory_up;Up]'
mod.main_inventory_scroll_down = 'image_button[8,6.5;1,1;transparent_button.png;dinv_main_inventory_down;Down]'
mod.recipe_button = 'image_button[4,1;1,1;transparent_button.png;dinv_recipe_next;Next]'
mod.worn_items_inv = 'list[current_player;worn;9.25,3.5;2,4;]'
mod.main_inventory = 'list[current_player;main;2.25,3.5;8,4;'
mod.craft_inventory = 'list[current_player;craft;3.25,0;3,3;]'
mod.craft_preview = 'list[current_player;craftpreview;6.25,2;1,1;]'
mod.main_inventory_scroll_up = 'image_button[10.25,3.5;1,1;transparent_button.png;dinv_main_inventory_up;Up]'
mod.main_inventory_scroll_down = 'image_button[10.25,6.5;1,1;transparent_button.png;dinv_main_inventory_down;Down]'
mod.recipe_button = 'image_button[6.25,1;1,1;transparent_button.png;dinv_recipe_next;Next]'
mod.worn_items_inv = 'list[current_player;worn;0,3.5;2,4;]'
mod.empty_button = 'image_button[2.25,2;1,1;transparent_button.png;dinv_empty_craft;Empty]'
mod.fill_button = 'image_button[2.25,1;1,1;transparent_button.png;dinv_fill_craft;Fill]'
-- All this is necessary to add scroll buttons to chests.
@ -538,6 +540,24 @@ function mod.damage_armor(player, damage)
end
function mod.empty_craft(player)
local pinv = player:get_inventory()
local craft_size = pinv:get_size('craft')
for i = 1, craft_size do
local st = pinv:get_stack('craft', i)
if pinv:room_for_item('main', st) then
pinv:add_item('main', st)
pinv:set_stack('craft', i, nil)
else
return
end
end
return true
end
-- Calculate how big the main inventory should be.
function mod.get_main_size_by_bags(player)
local isize = 32
@ -607,13 +627,15 @@ function mod.make_inventory_spec(player)
local inventory = ''
inventory = inventory .. mod.form_size
inventory = inventory .. mod.worn_items_inv
inventory = inventory .. mod.empty_button
inventory = inventory .. mod.fill_button
inventory = inventory .. mod.main_inventory .. scroll_main_to .. ']'
inventory = inventory .. mod.craft_inventory
inventory = inventory .. 'listring[]'
inventory = inventory .. mod.craft_preview
inventory = inventory .. mod.main_inventory_scroll_up
inventory = inventory .. mod.main_inventory_scroll_down
inventory = inventory .. mod.worn_items_inv
inventory = inventory .. mod.recipe_grid(player)
inventory = inventory .. mod.recipe_list(player)
@ -663,6 +685,22 @@ minetest.after(0, function()
end)
function mod.get_all_craft_recipes(craft_item)
local recipes = {}
for k, v in pairs(minetest.get_all_craft_recipes(craft_item) or {}) do
if v.type ~= 'cooking' then
table.insert(recipes, v)
end
end
if #recipes < 1 then
return
end
return recipes
end
-- Return a 3 x 3 grid of images matching the selected recipe.
-- This appears over then actual craft grid, but won't interfere
-- with it.
@ -681,7 +719,7 @@ function mod.recipe_grid(player)
return ''
end
local recipes = minetest.get_all_craft_recipes(craft_item)
local recipes = mod.get_all_craft_recipes(craft_item)
if not recipes then
return ''
end
@ -693,13 +731,13 @@ function mod.recipe_grid(player)
local recipe = recipes[recipe_number]
local inv = ''
inv = inv .. 'container[1,0]'
inv = inv .. 'container[3.25,0]'
do
local tooltip = craft_item
inv = inv .. 'item_image[3,2;1,1;' .. craft_item .. ']'
tooltip = minetest.registered_items[craft_item].description or tooltip
inv = inv .. 'tooltip[3,2;1,1;' .. 'recipe: ' .. tooltip .. ']'
inv = inv .. 'tooltip[3,2;0.8,0.8;' .. 'recipe: ' .. tooltip .. ']'
end
local w = recipe.width or 3
@ -728,7 +766,7 @@ function mod.recipe_grid(player)
end
if item then
inv = inv .. 'item_image[' .. (x - 1) .. ',' .. (y) .. ';1,1;' .. item .. ']'
inv = inv .. 'tooltip[' .. (x - 1) .. ',' .. (y) .. ';1,1;' .. 'recipe: ' .. tooltip .. ']'
inv = inv .. 'tooltip[' .. (x - 1) .. ',' .. (y) .. ';0.8,0.8;' .. 'recipe: ' .. tooltip .. ']'
end
end
end
@ -755,8 +793,8 @@ function mod.recipe_list(player)
if not sorted_items then
sorted_items = {}
for k, v in pairs(minetest.registered_items) do
if k and k ~= '' and minetest.get_all_craft_recipes(k) then
local recs = minetest.get_all_craft_recipes(k)
if k and k ~= '' and mod.get_all_craft_recipes(k) then
local recs = mod.get_all_craft_recipes(k)
for a, b in pairs(recs) do
if b.type ~= 'cooking' then
table.insert(sorted_items, k)
@ -769,7 +807,7 @@ function mod.recipe_list(player)
end
local inv = ''
inv = inv .. 'textlist[5,0;3.75,2.9;dinv_recipe_list;'
inv = inv .. 'textlist[7.25,0;3.75,2.9;dinv_recipe_list;'
local t
for k, v in pairs(sorted_items) do
if t then
@ -1143,6 +1181,8 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
or fields['dinv_main_inventory_down']
or fields['dinv_recipe_list']
or fields['dinv_recipe_next']
or fields['dinv_empty_craft']
or fields['dinv_fill_craft']
) then
return
end
@ -1158,10 +1198,167 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
mod.show_recipe(player, fields['dinv_recipe_list'])
elseif fields and fields['dinv_recipe_next'] then
mod.switch_recipe(player, 1)
elseif fields and fields['dinv_empty_craft'] then
mod.empty_craft(player)
elseif fields and fields['dinv_fill_craft'] then
mod.recipe_fill(player)
end
end)
function mod.recipe_fill(player)
local player_name = player:get_player_name()
local dat = mod.dat[player_name]
local craft_item_number = dat['craft_item_number']
local recipe_number = dat['recipe_number'] or 1
if not craft_item_number then
return
end
local craft_item = sorted_items[craft_item_number]
if not craft_item then
return
end
local recipes = mod.get_all_craft_recipes(craft_item)
if not recipes then
return
end
local pinv = player:get_inventory()
local main_size = pinv:get_size('main')
if recipe_number > #recipes then
recipe_number = 1
dat['recipe_number'] = recipe_number
end
local recipe = recipes[recipe_number]
local w = recipe.width or 3
if w == 0 or w > 3 then
w = 3
end
local items = {}
local totals = {}
local g_s = {}
local i = 0
for y = 0, 2 do
for x = 1, w do
i = i + 1
local item, group
if recipe.type == 'normal' then
item = recipe.items[(y * w) + x]
end
if item then
items[i] = item
totals[item] = (totals[item] or 0) + 1
end
end
end
local avail = {}
local groups = {}
local stack_max = {}
local only_one
local max = 999999
for k, v in pairs(totals) do
if k:find('^group:') then
local group = k:gsub('^group:', '')
for i = 1, main_size do
local st = pinv:get_stack('main', i)
local name = st:get_name()
local it = minetest.registered_items[name]
if not it then
--print(mod_name..': Cannot find item: ' .. name)
return
end
if it.groups and it.groups[group] then
local ct = st:get_count()
avail[k] = (avail[k] or 0) + ct
groups[k] = (groups[k] or {})
groups[k][name] = (groups[k][name] or 0) + ct
stack_max[name] = it.stack_max or 99
end
end
local gmax
for l, w in pairs(groups[k] or {}) do
if not gmax then
gmax = w / v
end
gmax = math.min(math.max(gmax, w / v), stack_max[l])
end
if gmax then
max = math.min(max, gmax)
end
else
for i = 1, main_size do
local st = pinv:get_stack('main', i)
local name = st:get_name()
if k == name then
avail[k] = (avail[k] or 0) + st:get_count()
local it = minetest.registered_items[k]
if not it then
--print(mod_name..': Cannot find item: ' .. name)
return
end
stack_max[name] = it.stack_max or 99
if stack_max[name] < 2 then
only_one = true
end
end
end
if max and avail[k] and stack_max[k] then
max = math.min(math.min(max, avail[k] / v), stack_max[k])
end
end
end
for k, v in pairs(totals) do
if not (avail[k] and avail[k] >= v) then
--print(mod_name..': Cannot find ' .. k .. ' in inventory.')
return
end
end
if only_one then
max = 1
else
max = math.floor(max)
end
if max < 1 then
return
end
if not mod.empty_craft(player) then
--print(mod_name..': Cannot empty craft inventory')
return
end
for k, v in pairs(items) do
if v:find('^group:') then
for l in pairs(groups[v]) do
local w = groups[v][l]
if w >= max then
local st = pinv:remove_item('main', l .. ' ' .. max)
groups[v][l] = groups[v][l] - st:get_count()
pinv:set_stack('craft', k, st)
break
end
end
else
local st = pinv:remove_item('main', v .. ' ' .. max)
pinv:set_stack('craft', k, st)
end
end
end
-- Every time the player gets punched, armor is damaged,
-- even if no damage is done to the player.
minetest.register_on_punchplayer(function(player, hitter, time_from_last_punch, tool_capabilities, dir, damage)