summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README12
-rw-r--r--depends.txt2
-rw-r--r--init.lua226
-rw-r--r--textures/invsaw_button.pngbin0 -> 1916 bytes
4 files changed, 240 insertions, 0 deletions
diff --git a/README b/README
new file mode 100644
index 0000000..3a5c52e
--- /dev/null
+++ b/README
@@ -0,0 +1,12 @@
+invsaw
+======
+
+This mod adds a button in unified_inventory that opens a formspec that works exactly like the moreblocks circular saw. It requires that either the server is in creative mode, you have the "creative" priv, or you have one or more circular saws (moreblocks:circular_saw) in your inventory.
+
+Dependencies: moreblocks, unified_inventory
+
+Contains large amounts of code based on Calinou's moreblocks mod, and a texture based on some textures from the same mod.
+
+License:
+Code - zlib
+Textures - CC BY-SA 3.0 Unported
diff --git a/depends.txt b/depends.txt
new file mode 100644
index 0000000..9c40cab
--- /dev/null
+++ b/depends.txt
@@ -0,0 +1,2 @@
+moreblocks
+unified_inventory
diff --git a/init.lua b/init.lua
new file mode 100644
index 0000000..d7f44cd
--- /dev/null
+++ b/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
+
+ circular_saw:reset(pos)
+ 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"
+ })
diff --git a/textures/invsaw_button.png b/textures/invsaw_button.png
new file mode 100644
index 0000000..8ac8093
--- /dev/null
+++ b/textures/invsaw_button.png
Binary files differ