From 1a45ad19d4fa627e147bd385665e37942f6147fb Mon Sep 17 00:00:00 2001
From: Serhiy Zahoriya <serhiy.int@gmail.com>
Date: Sat, 11 Jan 2020 22:06:24 +0100
Subject: [PATCH] Alloy furnace: Accept only unique ItemStacks from tubes (#523)

---
 technic/machines/register/alloy_furnace.lua |   40 ++++++++++++++++++++
 technic/doc/api.md                          |    4 ++
 technic/machines/register/machine_base.lua  |   45 ++++++++++++++--------
 3 files changed, 73 insertions(+), 16 deletions(-)

diff --git a/technic/doc/api.md b/technic/doc/api.md
index 178ab0a..8ae6963 100644
--- a/technic/doc/api.md
+++ b/technic/doc/api.md
@@ -64,6 +64,10 @@
 ### Specific machines
 * `technic.register_solar_array(data)`
 	* data is a table
+* `technic.can_insert_unique_stack(pos, node, stack, direction)`
+* `technic.insert_object_unique_stack(pos, node, stack, direction)`
+	* Functions for the parameters `can_insert` and `insert_object` to avoid
+	  filling multiple inventory slots with same type of item.
 
 Used itemdef fields
 -------------------
diff --git a/technic/machines/register/alloy_furnace.lua b/technic/machines/register/alloy_furnace.lua
index 879e528..1e3796d 100644
--- a/technic/machines/register/alloy_furnace.lua
+++ b/technic/machines/register/alloy_furnace.lua
@@ -1,10 +1,50 @@
 
 local S = technic.getter
 
+function technic.insert_object_unique_stack(pos, node, incoming_stack, direction)
+	local meta = minetest.get_meta(pos)
+	local inv = meta:get_inventory()
+	local incoming_name = incoming_stack:get_name()
+	local stack_index = nil
+	for inv_index, inv_stack in pairs(inv:get_list("src")) do
+		if inv_stack:get_name() == incoming_name then
+			stack_index = inv_index
+			break
+		end
+	end
+	if stack_index == nil then
+		return inv:add_item("src", incoming_stack)
+	end
+	local present_stack = inv:get_stack("src", stack_index)
+	local leftover = present_stack:add_item(incoming_stack)
+	inv:set_stack("src", stack_index, present_stack)
+	return leftover
+end
+
+function technic.can_insert_unique_stack(pos, node, incoming_stack, direction)
+	local meta = minetest.get_meta(pos)
+	local inv = meta:get_inventory()
+	local incoming_name = incoming_stack:get_name()
+	if meta:get_int("splitstacks") == 0 then
+		-- avoid looping second time with inv:contains_item("src", incoming_stack)
+		for _, inv_stack in pairs(inv:get_list("src")) do
+			if inv_stack:get_name() == incoming_name then
+				return inv_stack:item_fits(incoming_stack)
+			end
+		end
+	end
+
+	return technic.default_can_insert(pos, node, incoming_stack, direction)
+end
+
 function technic.register_alloy_furnace(data)
 	data.typename = "alloy"
 	data.machine_name = "alloy_furnace"
 	data.machine_desc = S("%s Alloy Furnace")
+
+	data.insert_object = technic.insert_object_unique_stack
+	data.can_insert = technic.can_insert_unique_stack
+
 	technic.register_base_machine(data)
 end
 
diff --git a/technic/machines/register/machine_base.lua b/technic/machines/register/machine_base.lua
index 15fb8ea..2965ba5 100644
--- a/technic/machines/register/machine_base.lua
+++ b/technic/machines/register/machine_base.lua
@@ -4,22 +4,26 @@
 local fs_helpers = pipeworks.fs_helpers
 local tube_entry = "^pipeworks_tube_connection_metallic.png"
 
-local tube = {
-	insert_object = function(pos, node, stack, direction)
-		local meta = minetest.get_meta(pos)
-		local inv = meta:get_inventory()
-		return inv:add_item("src", stack)
-	end,
-	can_insert = function(pos, node, stack, direction)
-		local meta = minetest.get_meta(pos)
-		local inv = meta:get_inventory()
-		if meta:get_int("splitstacks") == 1 then
-			stack = stack:peek_item(1)
-		end
-		return inv:room_for_item("src", stack)
-	end,
-	connect_sides = {left = 1, right = 1, back = 1, top = 1, bottom = 1},
-}
+function technic.default_can_insert(pos, node, stack, direction)
+	local meta = minetest.get_meta(pos)
+	local inv = meta:get_inventory()
+	if meta:get_int("splitstacks") == 1 then
+		stack = stack:peek_item(1)
+	end
+	return inv:room_for_item("src", stack)
+end
+
+function technic.new_default_tube()
+	return {
+		insert_object = function(pos, node, stack, direction)
+			local meta = minetest.get_meta(pos)
+			local inv = meta:get_inventory()
+			return inv:add_item("src", stack)
+		end,
+		can_insert = technic.default_can_insert,
+		connect_sides = {left = 1, right = 1, back = 1, top = 1, bottom = 1},
+	}
+end
 
 local connect_default = {"bottom", "back", "left", "right"}
 
@@ -62,6 +66,14 @@
 			"listring[current_player;main]"..
 			"listring[current_name;upgrade2]"..
 			"listring[current_player;main]"
+	end
+
+	local tube = technic.new_default_tube()
+	if data.can_insert then
+		tube.can_insert = data.can_insert
+	end
+	if data.insert_object then
+		tube.insert_object = data.insert_object
 	end
 
 	local run = function(pos, node)
@@ -144,6 +156,7 @@
 	if ltier == "lv" then
 		tentry = ""
 	end
+
 	minetest.register_node("technic:"..ltier.."_"..machine_name, {
 		description = machine_desc:format(tier),
 		tiles = {

--
Gitblit v1.8.0