3f84af947f
Requires unified_inventory 0616d1f76b or newer.
228 lines
7.7 KiB
Lua
228 lines
7.7 KiB
Lua
invsaw = {}
|
|
|
|
invsaw.users = {}
|
|
|
|
invsaw.formspec = "formspec_version[4]"..
|
|
"size[15,15]"..
|
|
"background9[0,0;1,1;ui_formbg_9_sliced.png;true;16]"..
|
|
"label[0.75,1.3;Input\nmaterial]" ..
|
|
"list[detached:invsaw_%s;input;2,1;1,1;]" ..
|
|
"label[0.75,3;Left-over]" ..
|
|
"list[detached:invsaw_%s;micro;2,2.5;1,1;]" ..
|
|
"label[0.75,4.3;Recycle\noutput]" ..
|
|
"list[detached:invsaw_%s;recycle;2,4;1,1;]" ..
|
|
"field[0.75,6;1,1;max_offered;Max:;%s]" ..
|
|
"button[2,6;1,1;Set;Set]" ..
|
|
"list[detached:invsaw_%s;output;4,1;8,6;]" ..
|
|
"list[current_player;main;4,9.5;8,4;]"
|
|
|
|
invsaw.nosawformspec = "size[5,2]"..
|
|
"label[0,0;You don't have a circular saw in your inventory!\nYou need to have one in order to use this function.]"..
|
|
"button_exit[1.5,1;2,1;quit;OK]"
|
|
|
|
function invsaw.reset(inv,name)
|
|
inv:set_list("input", {})
|
|
inv:set_list("micro", {})
|
|
inv:set_list("output", {})
|
|
invsaw.users[name].micros = 0
|
|
end
|
|
|
|
function invsaw.update_inventory(inv, name, amount)
|
|
|
|
amount = invsaw.users[name].micros + amount
|
|
|
|
-- The material is recycled automaticly.
|
|
inv:set_list("recycle", {})
|
|
|
|
if amount < 1 then -- If the last block is taken out.
|
|
invsaw.reset(inv,name)
|
|
return
|
|
end
|
|
|
|
local stack = inv:get_stack("input", 1)
|
|
-- At least one "normal" block is necessary to see what kind of stairs are requested.
|
|
if stack:is_empty() then
|
|
-- Any microblocks not taken out yet are now lost.
|
|
-- (covers material loss in the machine)
|
|
invsaw.reset(inv,name)
|
|
return
|
|
|
|
end
|
|
local node_name = stack:get_name() or ""
|
|
local name_parts = circular_saw.known_nodes[node_name] or ""
|
|
local modname = name_parts[1] or ""
|
|
local material = name_parts[2] or ""
|
|
|
|
inv:set_list("input", { -- Display as many full blocks as possible:
|
|
node_name.. " " .. math.floor(amount / 8)
|
|
})
|
|
|
|
-- The stairnodes made of default nodes use moreblocks namespace, other mods keep own:
|
|
if modname == "default" then
|
|
modname = "moreblocks"
|
|
end
|
|
-- print("circular_saw set to " .. modname .. " : "
|
|
-- .. material .. " with " .. (amount) .. " microblocks.")
|
|
|
|
-- 0-7 microblocks may remain left-over:
|
|
inv:set_list("micro", {
|
|
modname .. ":micro_" .. material .. "_bottom " .. (amount % 8)
|
|
})
|
|
-- Display:
|
|
inv:set_list("output",
|
|
circular_saw:get_output_inv(modname, material, amount,
|
|
invsaw.users[name].max_offered))
|
|
-- Store how many microblocks are available:
|
|
invsaw.users[name].micros = amount
|
|
|
|
end
|
|
|
|
invsaw.allow_put = function(inv, listname, index, stack, player)
|
|
-- The player is not allowed to put something in there:
|
|
if listname == "output" or listname == "micro" then
|
|
return 0
|
|
end
|
|
|
|
local stackname = stack:get_name()
|
|
local count = stack:get_count()
|
|
|
|
-- Only alow those items that are offered in the output inventory to be recycled:
|
|
if listname == "recycle" then
|
|
if not inv:contains_item("output", stackname) then
|
|
return 0
|
|
end
|
|
local stackmax = stack:get_stack_max()
|
|
local instack = inv:get_stack("input", 1)
|
|
local microstack = inv:get_stack("micro", 1)
|
|
local incount = instack:get_count()
|
|
local incost = (incount * 8) + microstack:get_count()
|
|
local maxcost = (stackmax * 8) + 7
|
|
local cost = circular_saw:get_cost(inv, stackname)
|
|
if (incost + cost) > maxcost then
|
|
return math.max((maxcost - incost) / cost, 0)
|
|
end
|
|
return count
|
|
end
|
|
|
|
-- Only accept certain blocks as input which are known to be craftable into stairs:
|
|
if listname == "input" then
|
|
if not inv:is_empty("input") then
|
|
if inv:get_stack("input", index):get_name() ~= stackname then
|
|
return 0
|
|
end
|
|
end
|
|
if not inv:is_empty("micro") then
|
|
local microstackname = inv:get_stack("micro", 1):get_name():gsub("^.+:micro_", "", 1)
|
|
local cutstackname = stackname:gsub("^.+:", "", 1)
|
|
if microstackname ~= cutstackname then
|
|
return 0
|
|
end
|
|
end
|
|
for name, t in pairs(circular_saw.known_nodes) do
|
|
if name == stackname and inv:room_for_item("input", stack) then
|
|
return count
|
|
end
|
|
end
|
|
return 0
|
|
end
|
|
end
|
|
|
|
invsaw.on_take = function(inv, listname, index, stack, player)
|
|
-- Prevent (inbuilt) swapping between inventories with different blocks
|
|
-- corrupting player inventory or Saw with 'unknown' items.
|
|
local input_stack = inv:get_stack(listname, index)
|
|
if not input_stack:is_empty() and input_stack:get_name()~=stack:get_name() then
|
|
local player_inv = player:get_inventory()
|
|
if player_inv:room_for_item("main", input_stack) then
|
|
player_inv:add_item("main", input_stack)
|
|
end
|
|
|
|
invsaw.reset(inv,player:get_player_name())
|
|
return
|
|
end
|
|
|
|
-- If it is one of the offered stairs: find out how many
|
|
-- microblocks have to be substracted:
|
|
if listname == "output" then
|
|
-- We do know how much each block at each position costs:
|
|
local cost = circular_saw.cost_in_microblocks[index]
|
|
* stack:get_count()
|
|
|
|
invsaw.update_inventory(inv, player:get_player_name(), -cost)
|
|
elseif listname == "micro" then
|
|
-- Each microblock costs 1 microblock:
|
|
invsaw.update_inventory(inv, player:get_player_name(), -stack:get_count())
|
|
elseif listname == "input" then
|
|
-- Each normal (= full) block taken costs 8 microblocks:
|
|
invsaw.update_inventory(inv, player:get_player_name(), 8 * -stack:get_count())
|
|
end
|
|
-- The recycle field plays no role here since it is processed immediately.
|
|
end
|
|
|
|
invsaw.on_put = function(inv, listname, index, stack, player)
|
|
-- We need to find out if the circular_saw is already set to a
|
|
-- specific material or not:
|
|
local stackname = stack:get_name()
|
|
local count = stack:get_count()
|
|
|
|
-- Putting something into the input slot is only possible if that had
|
|
-- been empty before or did contain something of the same material:
|
|
if listname == "input" then
|
|
-- Each new block is worth 8 microblocks:
|
|
invsaw.update_inventory(inv, player:get_player_name(), 8 * count)
|
|
elseif listname == "recycle" then
|
|
-- Lets look which shape this represents:
|
|
local cost = circular_saw:get_cost(inv, stackname)
|
|
local input_stack = inv:get_stack("input", 1)
|
|
-- check if this would not exceed input itemstack max_stacks
|
|
if input_stack:get_count() + ((cost * count) / 8) <= input_stack:get_stack_max() then
|
|
invsaw.update_inventory(inv, player:get_player_name(), cost * count)
|
|
end
|
|
end
|
|
end
|
|
|
|
minetest.register_on_joinplayer(function(player)
|
|
local name = player:get_player_name(player)
|
|
invsaw.users[name] = {}
|
|
invsaw.users[name].micros = 0
|
|
invsaw.users[name].max_offered = 99
|
|
local inv = minetest.create_detached_inventory("invsaw_"..name,{
|
|
allow_put = invsaw.allow_put,
|
|
on_put = invsaw.on_put,
|
|
on_take = invsaw.on_take,
|
|
allow_move = function() return 0 end
|
|
}, name)
|
|
inv:set_size("input",1)
|
|
inv:set_size("micro",1)
|
|
inv:set_size("recycle",1)
|
|
inv:set_size("output",48) --6*8
|
|
invsaw.users[name].inv = inv
|
|
end)
|
|
|
|
minetest.register_on_player_receive_fields(function(player,formname,fields)
|
|
local name = player:get_player_name()
|
|
if fields.saw then
|
|
local creative = minetest.setting_getbool("creative_mode") or minetest.check_player_privs(name,{creative=true})
|
|
local havesaw = player:get_inventory():contains_item("main","moreblocks:circular_saw")
|
|
if havesaw or creative then
|
|
minetest.show_formspec(name,"invsaw:saw",string.format(invsaw.formspec,name,name,name,invsaw.users[name].max_offered,name))
|
|
else
|
|
minetest.show_formspec(name,"invsaw:nosaw",invsaw.nosawformspec)
|
|
end
|
|
return true
|
|
elseif formname == "invsaw:saw" and fields.Set then
|
|
invsaw.users[name].max_offered = tonumber(fields.max_offered) or 99
|
|
invsaw.update_inventory(invsaw.users[name].inv,name,0)
|
|
minetest.show_formspec(name,"invsaw:saw",string.format(invsaw.formspec,name,name,name,invsaw.users[name].max_offered,name))
|
|
return true
|
|
else
|
|
return false
|
|
end
|
|
end)
|
|
|
|
unified_inventory.register_button("saw", {
|
|
type = "image",
|
|
image = "invsaw_button.png",
|
|
tooltip = "Circular Saw"
|
|
})
|