summaryrefslogtreecommitdiff
path: root/invsaw/init.lua
diff options
context:
space:
mode:
Diffstat (limited to 'invsaw/init.lua')
-rw-r--r--invsaw/init.lua226
1 files changed, 226 insertions, 0 deletions
diff --git a/invsaw/init.lua b/invsaw/init.lua
new file mode 100644
index 0000000..0dda0b5
--- /dev/null
+++ b/invsaw/init.lua
@@ -0,0 +1,226 @@
+invsaw = {}
+
+invsaw.users = {}
+
+local fancy_inv = default.gui_bg..default.gui_bg_img..default.gui_slots
+invsaw.formspec = "size[11,10]"..fancy_inv..
+ "label[0,0;Input\nmaterial]" ..
+ "list[detached:invsaw_%s;input;1.5,0;1,1;]" ..
+ "label[0,1;Left-over]" ..
+ "list[detached:invsaw_%s;micro;1.5,1;1,1;]" ..
+ "label[0,2;Recycle\noutput]" ..
+ "list[detached:invsaw_%s;recycle;1.5,2;1,1;]" ..
+ "field[0.3,3.5;1,1;max_offered;Max:;%s]" ..
+ "button[1,3.2;1,1;Set;Set]" ..
+ "list[detached:invsaw_%s;output;2.8,0;8,6;]" ..
+ "list[current_player;main;1.5,6.25;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
+ })
+ 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"
+ })