From aa8af0c8715a4492f43da3834e4f324c72b90b71 Mon Sep 17 00:00:00 2001
From: Novatux <nathanael.courant@laposte.net>
Date: Wed, 02 Jul 2014 22:24:38 +0200
Subject: [PATCH] Refactor a lot of code: make only one registration function for grinder, extractor and electric furnace (compressor will follow soon)

---
 technic/machines/register/grinder_recipes.lua   |   47 --
 technic/machines/register/electric_furnace.lua  |  171 -----------
 technic/machines/register/init.lua              |    2 
 technic/machines/register/machine_base.lua      |  169 ++++++++++++
 technic/machines/register/recipes.lua           |   63 ++++
 technic/machines/register/extractor.lua         |  155 ----------
 technic/machines/register/extractor_recipes.lua |   46 ---
 technic/machines/register/grinder.lua           |  160 -----------
 8 files changed, 260 insertions(+), 553 deletions(-)

diff --git a/technic/machines/register/electric_furnace.lua b/technic/machines/register/electric_furnace.lua
index a2df6f8..44de16c 100644
--- a/technic/machines/register/electric_furnace.lua
+++ b/technic/machines/register/electric_furnace.lua
@@ -1,170 +1,9 @@
 
 local S = technic.getter
 
-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()
-		return inv:room_for_item("src", stack)
-	end,
-	connect_sides = {left=1, right=1, back=1, top=1, bottom=1},
-}
-
 function technic.register_electric_furnace(data)
-	local tier = data.tier
-	local ltier = string.lower(tier)
-
-	local tube_side_texture = data.tube and "technic_"..ltier.."_electric_furnace_side_tube.png"
-			or "technic_"..ltier.."_electric_furnace_side.png"
-
-	local groups = {cracky=2}
-	local active_groups = {cracky=2, not_in_creative_inventory=1}
-	if data.tube then
-		groups.tubedevice = 1
-		groups.tubedevice_receiver = 1
-		active_groups.tubedevice = 1
-		active_groups.tubedevice_receiver = 1
-	end
-
-	local formspec =
-		"invsize[8,10;]"..
-		"list[current_name;src;3,1;1,1;]"..
-		"list[current_name;dst;5,1;2,2;]"..
-		"list[current_player;main;0,6;8,4;]"..
-		"label[0,0;"..S("%s Furnace"):format(tier).."]"
-	if data.upgrade then
-		formspec = formspec..
-			"list[current_name;upgrade1;1,4;1,1;]"..
-			"list[current_name;upgrade2;2,4;1,1;]"..
-			"label[1,5;"..S("Upgrade Slots").."]"
-	end
-
-	minetest.register_node("technic:"..ltier.."_electric_furnace", {
-		description = S("%s Furnace"):format(tier),
-		tiles = {"technic_"..ltier.."_electric_furnace_top.png",
-		         "technic_"..ltier.."_electric_furnace_bottom.png",
-		         tube_side_texture,
-			 tube_side_texture,
-			 "technic_"..ltier.."_electric_furnace_side.png",
-		         "technic_"..ltier.."_electric_furnace_front.png"},
-		paramtype2 = "facedir",
-		groups = groups,
-		legacy_facedir_simple = true,
-		sounds = default.node_sound_stone_defaults(),
-		tube = data.tube and tube or nil,
-		on_construct = function(pos)
-			local meta = minetest.get_meta(pos)
-			local name = minetest.get_node(pos).name
-			meta:set_string("infotext", S("%s Furnace"):format(tier))
-			meta:set_int("tube_time",  0)
-			meta:set_string("formspec", formspec)
-			local inv = meta:get_inventory()
-			inv:set_size("src", 1)
-			inv:set_size("dst", 4)
-			inv:set_size("upgrade1", 1)
-			inv:set_size("upgrade2", 1)
-		end,
-		can_dig = technic.machine_can_dig,
-		allow_metadata_inventory_put = technic.machine_inventory_put,
-		allow_metadata_inventory_take = technic.machine_inventory_take,
-		allow_metadata_inventory_move = technic.machine_inventory_move,
-	})
-
-	minetest.register_node("technic:"..ltier.."_electric_furnace_active", {
-		description = ("%s Furnace"):format(tier),
-		tiles = {"technic_"..ltier.."_electric_furnace_top.png",
-		         "technic_"..ltier.."_electric_furnace_bottom.png",
-		         tube_side_texture,
-		         tube_side_texture,
-		         "technic_"..ltier.."_electric_furnace_side.png",
-		         "technic_"..ltier.."_electric_furnace_front_active.png"},
-		paramtype2 = "facedir",
-		drop = "technic:"..ltier.."_electric_furnace",
-		groups = active_groups,
-		light_source = 8,
-		legacy_facedir_simple = true,
-		sounds = default.node_sound_stone_defaults(),
-		tube = data.tube and tube or nil,
-		on_construct = function(pos)
-			local meta = minetest.get_meta(pos)
-			local name = minetest.get_node(pos).name
-			local data = minetest.registered_nodes[name].technic
-			meta:set_string("infotext", S("%s Furnace"):format(tier))
-			meta:set_int("tube_time",  0)
-			meta:set_string("formspec", formspec)
-			local inv = meta:get_inventory()
-			inv:set_size("src", 1)
-			inv:set_size("dst", 4)
-			inv:set_size("upgrade1", 1)
-			inv:set_size("upgrade2", 1)
-		end,
-		can_dig = technic.machine_can_dig,
-		allow_metadata_inventory_put = technic.machine_inventory_put,
-		allow_metadata_inventory_take = technic.machine_inventory_take,
-		allow_metadata_inventory_move = technic.machine_inventory_move,
-	})
-
-	minetest.register_abm({
-		nodenames = {"technic:"..ltier.."_electric_furnace",
-		             "technic:"..ltier.."_electric_furnace_active"},
-		interval = 1,
-		chance   = 1,
-		action = function(pos, node, active_object_count, active_object_count_wider)
-			local meta     = minetest.get_meta(pos)
-			local inv      = meta:get_inventory()
-			local eu_input = meta:get_int(tier.."_EU_input")
-
-			-- Machine information
-			local machine_name   = S("%s Furnace"):format(tier)
-			local machine_node   = "technic:"..ltier.."_electric_furnace"
-			local machine_demand = data.demand
-
-			-- Power off automatically if no longer connected to a switching station
-			technic.switching_station_timeout_count(pos, tier)
-
-			-- Check upgrade slots
-			local EU_upgrade, tube_upgrade = 0, 0
-			if data.upgrade then
-				EU_upgrade, tube_upgrade = technic.handle_machine_upgrades(meta)
-			end
-			if data.tube then
-				technic.handle_machine_pipeworks(pos, tube_upgrade)
-			end
-
-			local result = minetest.get_craft_result({
-					method = "cooking",
-					width = 1,
-					items = inv:get_list("src")})
-			if not result or result.time == 0 or
-			   not inv:room_for_item("dst", result.item) then
-				meta:set_int(tier.."_EU_demand", 0)
-				technic.swap_node(pos, machine_node)
-				meta:set_string("infotext", S("%s Idle"):format(machine_name))
-				return
-			end
-
-			if eu_input < machine_demand[EU_upgrade+1] then
-				-- Unpowered - go idle
-				technic.swap_node(pos, machine_node)
-				meta:set_string("infotext", S("%s Unpowered"):format(machine_name))
-			elseif eu_input >= machine_demand[EU_upgrade+1] then
-				-- Powered
-				technic.swap_node(pos, machine_node.."_active")
-				meta:set_string("infotext", S("%s Active"):format(machine_name))
-				technic.smelt_item(meta, result, data.speed)
-
-			end
-			meta:set_int(tier.."_EU_demand", machine_demand[EU_upgrade+1])
-		end,
-	})
-
-	technic.register_machine(tier, "technic:"..ltier.."_electric_furnace",        technic.receiver)
-	technic.register_machine(tier, "technic:"..ltier.."_electric_furnace_active", technic.receiver)
-
-end -- End registration
-
+	data.typename = "cooking"
+	data.machine_name = "electric_furnace"
+	data.machine_desc = S("%s Furnace")
+	technic.register_base_machine(data)
+end
diff --git a/technic/machines/register/extractor.lua b/technic/machines/register/extractor.lua
index e79d32c..eeef9ff 100644
--- a/technic/machines/register/extractor.lua
+++ b/technic/machines/register/extractor.lua
@@ -1,154 +1,9 @@
 
 local S = technic.getter
 
-local extractor_formspec =
-   "invsize[8,9;]"..
-   "label[0,0;"..S("%s Extractor"):format("LV").."]"..
-   "list[current_name;src;3,1;1,1;]"..
-   "list[current_name;dst;5,1;2,2;]"..
-   "list[current_player;main;0,5;8,4;]"
-
 function technic.register_extractor(data)
-	local tier = data.tier
-	local ltier = string.lower(tier)
-
-	local groups = {cracky = 2}
-	local active_groups = {cracky = 2, not_in_creative_inventory = 1}
-	if data.tube then
-		groups.tubedevice = 1
-		groups.tubedevice_receiver = 1
-		active_groups.tubedevice = 1
-		active_groups.tubedevice_receiver = 1
-	end
-
-
-	local formspec =
-		"invsize[8,9;]"..
-		"list[current_name;src;3,1;1,1;]"..
-		"list[current_name;dst;5,1;2,2;]"..
-		"list[current_player;main;0,5;8,4;]"..
-		"label[0,0;"..S("%s Extractor"):format(tier).."]"
-	
-	if data.upgrade then
-		formspec = formspec..
-			"list[current_name;upgrade1;1,4;1,1;]"..
-			"list[current_name;upgrade2;2,4;1,1;]"..
-			"label[1,5;"..S("Upgrade Slots").."]"
-	end
-
-	minetest.register_node("technic:"..ltier.."_extractor", {
-		description = S("%s Extractor"):format(tier),
-		tiles = {"technic_"..ltier.."_extractor_top.png",  "technic_"..ltier.."_extractor_bottom.png",
-			 "technic_"..ltier.."_extractor_side.png", "technic_"..ltier.."_extractor_side.png",
-			 "technic_"..ltier.."_extractor_side.png", "technic_"..ltier.."_extractor_front.png"},
-		paramtype2 = "facedir",
-		groups = groups,
-		tube = data.tube and tube or nil,
-		legacy_facedir_simple = true,
-		sounds = default.node_sound_wood_defaults(),
-		on_construct = function(pos)
-			local node = minetest.get_node(pos)
-			local meta = minetest.get_meta(pos)
-			meta:set_string("infotext", S("%s Extractor"):format(tier))
-			meta:set_int("tube_time",  0)
-			meta:set_string("formspec", formspec)
-			local inv = meta:get_inventory()
-			inv:set_size("src", 1)
-			inv:set_size("dst", 4)
-			inv:set_size("upgrade1", 1)
-			inv:set_size("upgrade2", 1)
-		end,
-		can_dig = technic.machine_can_dig,
-		allow_metadata_inventory_put = technic.machine_inventory_put,
-		allow_metadata_inventory_take = technic.machine_inventory_take,
-		allow_metadata_inventory_move = technic.machine_inventory_move,
-	})
-
-	minetest.register_node("technic:"..ltier.."_extractor_active",{
-		description = S("%s Grinder"):format(tier),
-		tiles = {"technic_"..ltier.."_extractor_top.png",  "technic_"..ltier.."_extractor_bottom.png",
-			 "technic_"..ltier.."_extractor_side.png", "technic_"..ltier.."_extractor_side.png",
-			 "technic_"..ltier.."_extractor_side.png", "technic_"..ltier.."_extractor_front_active.png"},
-		paramtype2 = "facedir",
-		drop = "technic:"..ltier.."_extractor",
-		groups = active_groups,
-		legacy_facedir_simple = true,
-		sounds = default.node_sound_wood_defaults(),
-		tube = data.tube and tube or nil,
-		can_dig = technic.machine_can_dig,
-		allow_metadata_inventory_put = technic.machine_inventory_put,
-		allow_metadata_inventory_take = technic.machine_inventory_take,
-		allow_metadata_inventory_move = technic.machine_inventory_move,
-	})
-
-	minetest.register_abm({
-		nodenames = {"technic:"..ltier.."_extractor","technic:"..ltier.."_extractor_active"},
-		interval = 1,
-		chance   = 1,
-		action = function(pos, node, active_object_count, active_object_count_wider)
-			local meta     = minetest.get_meta(pos)
-			local inv      = meta:get_inventory()
-			local eu_input = meta:get_int(tier.."_EU_input")
-
-			local machine_name   = S("%s Extractor"):format(tier)
-			local machine_node   = "technic:"..ltier.."_extractor"
-			local machine_demand = data.demand
-
-			-- Setup meta data if it does not exist.
-			if not eu_input then
-				meta:set_int(tier.."_EU_demand", machine_demand[1])
-				meta:set_int(tier.."_EU_input", 0)
-				return
-			end
-		
-			-- Power off automatically if no longer connected to a switching station
-			technic.switching_station_timeout_count(pos, tier)
-
-			local EU_upgrade, tube_upgrade = 0, 0
-			if data.upgrade then
-				EU_upgrade, tube_upgrade = technic.handle_machine_upgrades(meta)
-			end
-			if data.tube then
-				technic.handle_machine_pipeworks(pos, tube_upgrade)
-			end
-
-			local srcstack = inv:get_stack("src", 1)
-			local result = technic.get_extractor_recipe(inv:get_stack("src", 1))
-
-			if not result then
-				technic.swap_node(pos, machine_node)
-				meta:set_string("infotext", S("%s Idle"):format(machine_name))
-				meta:set_int(tier.."_EU_demand", 0)
-				return
-			end
-		
-			if eu_input < machine_demand[EU_upgrade+1] then
-				-- Unpowered - go idle
-				technic.swap_node(pos, machine_node)
-				meta:set_string("infotext", S("%s Unpowered"):format(machine_name))
-			elseif eu_input >= machine_demand[EU_upgrade+1] then
-				-- Powered	
-				technic.swap_node(pos, machine_node.."_active")
-				meta:set_string("infotext", S("%s Active"):format(machine_name))
-
-				meta:set_int("src_time", meta:get_int("src_time") + 1)
-				if meta:get_int("src_time") >= result.time / data.speed then
-					meta:set_int("src_time", 0)
-					local result_stack = ItemStack(result.output)
-					if inv:room_for_item("dst", result_stack) then
-						srcstack = inv:get_stack("src", 1)
-						srcstack:take_item(ItemStack(result.input):get_count())
-						inv:set_stack("src", 1, srcstack)
-						inv:add_item("dst", result_stack)
-					end
-				end
-			end
-			meta:set_int(tier.."_EU_demand", machine_demand[EU_upgrade+1])
-		end
-	})
-
-	technic.register_machine(tier, "technic:"..ltier.."_extractor",        technic.receiver)
-	technic.register_machine(tier, "technic:"..ltier.."_extractor_active", technic.receiver)
-
-end -- End registration
-
+	data.typename = "extracting"
+	data.machine_name = "extractor"
+	data.machine_desc = S("%s Extractor")
+	technic.register_base_machine(data)
+end
diff --git a/technic/machines/register/extractor_recipes.lua b/technic/machines/register/extractor_recipes.lua
index 2d19130..ff09bdf 100644
--- a/technic/machines/register/extractor_recipes.lua
+++ b/technic/machines/register/extractor_recipes.lua
@@ -1,53 +1,11 @@
 
 local S = technic.getter
 
-if unified_inventory and unified_inventory.register_craft_type then
-	unified_inventory.register_craft_type("extracting", {
-		description = S("Extracting"),
-		height = 1,
-		width = 1,
-	})
-end
-
-technic.extractor_recipes = {}
+technic.register_recipe_type("extracting", S("Extracting"))
 
 function technic.register_extractor_recipe(data)
 	data.time = data.time or 4
-	local src = ItemStack(data.input):get_name()
-	technic.extractor_recipes[src] = data
-	if unified_inventory then
-		unified_inventory.register_craft({
-			type = "extracting",
-			output = data.output,
-			items = {data.input},
-			width = 0,
-		})
-	end
-end
-
--- Receive an ItemStack of result by an ItemStack input
-function technic.get_extractor_recipe(item)
-	if technic.extractor_recipes[item:get_name()] and
-	   item:get_count() >= ItemStack(technic.extractor_recipes[item:get_name()].input):get_count() then
-		return technic.extractor_recipes[item:get_name()]
-	else
-		return nil
-	end
-end
-
-minetest.after(0.01, function ()
-	for ingredient, recipe in pairs(technic.extractor_recipes) do
-		ingredient = minetest.registered_aliases[ingredient]
-		while ingredient do
-			technic.grinder_recipes[ingredient] = recipe
-			ingredient = minetest.registered_aliases[ingredient]
-		end
-	end
-end)
-
--- Receive an ItemStack of result by an ItemStack input
-function technic.get_grinder_recipe(itemstack)
-	return technic.grinder_recipes[itemstack:get_name()]
+	technic.register_recipe("extracting", data)
 end
 
 local recipes = {
diff --git a/technic/machines/register/grinder.lua b/technic/machines/register/grinder.lua
index 02a79c3..19ea094 100644
--- a/technic/machines/register/grinder.lua
+++ b/technic/machines/register/grinder.lua
@@ -1,159 +1,9 @@
 
 local S = technic.getter
 
-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()
-		return inv:room_for_item("src", stack)
-	end,
-	connect_sides = {left=1, right=1, back=1, top=1, bottom=1},
-}
-
 function technic.register_grinder(data)
-	local tier = data.tier
-	local ltier = string.lower(tier)
-
-	local groups = {cracky=2}
-	local active_groups = {cracky=2, not_in_creative_inventory=1}
-	if data.tube then
-		groups.tubedevice = 1
-		groups.tubedevice_receiver = 1
-		active_groups.tubedevice = 1
-		active_groups.tubedevice_receiver = 1
-	end
-
-
-	local formspec =
-		"invsize[8,10;]"..
-		"list[current_name;src;3,1;1,1;]"..
-		"list[current_name;dst;5,1;2,2;]"..
-		"list[current_player;main;0,6;8,4;]"..
-		"label[0,0;"..S("%s Grinder"):format(tier).."]"
-	if data.upgrade then
-		formspec = formspec..
-			"list[current_name;upgrade1;1,4;1,1;]"..
-			"list[current_name;upgrade2;2,4;1,1;]"..
-			"label[1,5;"..S("Upgrade Slots").."]"
-	end
-
-	minetest.register_node("technic:"..ltier.."_grinder", {
-		description = S("%s Grinder"):format(tier),
-		tiles = {"technic_"..ltier.."_grinder_top.png",  "technic_"..ltier.."_grinder_bottom.png",
-			 "technic_"..ltier.."_grinder_side.png", "technic_"..ltier.."_grinder_side.png",
-			 "technic_"..ltier.."_grinder_side.png", "technic_"..ltier.."_grinder_front.png"},
-		paramtype2 = "facedir",
-		groups = groups,
-		tube = data.tube and tube or nil,
-		legacy_facedir_simple = true,
-		sounds = default.node_sound_wood_defaults(),
-		on_construct = function(pos)
-			local node = minetest.get_node(pos)
-			local meta = minetest.get_meta(pos)
-			meta:set_string("infotext", S("%s Grinder"):format(tier))
-			meta:set_int("tube_time",  0)
-			meta:set_string("formspec", formspec)
-			local inv = meta:get_inventory()
-			inv:set_size("src", 1)
-			inv:set_size("dst", 4)
-			inv:set_size("upgrade1", 1)
-			inv:set_size("upgrade2", 1)
-		end,
-		can_dig = technic.machine_can_dig,
-		allow_metadata_inventory_put = technic.machine_inventory_put,
-		allow_metadata_inventory_take = technic.machine_inventory_take,
-		allow_metadata_inventory_move = technic.machine_inventory_move,
-	})
-
-	minetest.register_node("technic:"..ltier.."_grinder_active",{
-		description = S("%s Grinder"):format(tier),
-		tiles = {"technic_"..ltier.."_grinder_top.png",  "technic_"..ltier.."_grinder_bottom.png",
-			 "technic_"..ltier.."_grinder_side.png", "technic_"..ltier.."_grinder_side.png",
-			 "technic_"..ltier.."_grinder_side.png", "technic_"..ltier.."_grinder_front_active.png"},
-		paramtype2 = "facedir",
-		drop = "technic:"..ltier.."_grinder",
-		groups = active_groups,
-		legacy_facedir_simple = true,
-		sounds = default.node_sound_wood_defaults(),
-		tube = data.tube and tube or nil,
-		can_dig = technic.machine_can_dig,
-		allow_metadata_inventory_put = technic.machine_inventory_put,
-		allow_metadata_inventory_take = technic.machine_inventory_take,
-		allow_metadata_inventory_move = technic.machine_inventory_move,
-	})
-
-	minetest.register_abm({
-		nodenames = {"technic:"..ltier.."_grinder","technic:"..ltier.."_grinder_active"},
-		interval = 1,
-		chance   = 1,
-		action = function(pos, node, active_object_count, active_object_count_wider)
-			local meta     = minetest.get_meta(pos)
-			local inv      = meta:get_inventory()
-			local eu_input = meta:get_int(tier.."_EU_input")
-
-			local machine_name   = S("%s Grinder"):format(tier)
-			local machine_node   = "technic:"..ltier.."_grinder"
-			local machine_demand = data.demand
-
-			-- Setup meta data if it does not exist.
-			if not eu_input then
-				meta:set_int(tier.."_EU_demand", machine_demand[1])
-				meta:set_int(tier.."_EU_input", 0)
-				return
-			end
-		
-			-- Power off automatically if no longer connected to a switching station
-			technic.switching_station_timeout_count(pos, tier)
-
-			local EU_upgrade, tube_upgrade = 0, 0
-			if data.upgrade then
-				EU_upgrade, tube_upgrade = technic.handle_machine_upgrades(meta)
-			end
-			if data.tube then
-				technic.handle_machine_pipeworks(pos, tube_upgrade)
-			end
-
-			local result = technic.get_grinder_recipe(inv:get_stack("src", 1))
-
-			if not result then
-				technic.swap_node(pos, machine_node)
-				meta:set_string("infotext", S("%s Idle"):format(machine_name))
-				meta:set_int(tier.."_EU_demand", 0)
-				return
-			end
-		
-			if eu_input < machine_demand[EU_upgrade+1] then
-				-- Unpowered - go idle
-				technic.swap_node(pos, machine_node)
-				meta:set_string("infotext", S("%s Unpowered"):format(machine_name))
-			elseif eu_input >= machine_demand[EU_upgrade+1] then
-				-- Powered	
-				technic.swap_node(pos, machine_node.."_active")
-				meta:set_string("infotext", S("%s Active"):format(machine_name))
-
-				meta:set_int("src_time", meta:get_int("src_time") + 1)
-				if meta:get_int("src_time") >= result.time / data.speed then
-					meta:set_int("src_time", 0)
-					local result_stack = ItemStack(result.output)
-					if inv:room_for_item("dst", result_stack) then
-						srcstack = inv:get_stack("src", 1)
-						srcstack:take_item()
-						inv:set_stack("src", 1, srcstack)
-						inv:add_item("dst", result_stack)
-					end
-				end
-			end
-			meta:set_int(tier.."_EU_demand", machine_demand[EU_upgrade+1])
-		end
-	})
-
-	technic.register_machine(tier, "technic:"..ltier.."_grinder",        technic.receiver)
-	technic.register_machine(tier, "technic:"..ltier.."_grinder_active", technic.receiver)
-
-end -- End registration
-
+	data.typename = "grinding"
+	data.machine_name = "grinder"
+	data.machine_desc = S("%s Grinder")
+	technic.register_base_machine(data)
+end
diff --git a/technic/machines/register/grinder_recipes.lua b/technic/machines/register/grinder_recipes.lua
index cde68b6..4453ea8 100644
--- a/technic/machines/register/grinder_recipes.lua
+++ b/technic/machines/register/grinder_recipes.lua
@@ -1,59 +1,30 @@
 
 local S = technic.getter
 
-if unified_inventory and unified_inventory.register_craft_type then
-	unified_inventory.register_craft_type("grinding", {
-		description = S("Grinding"),
-		height = 1,
-		width = 1,
-	})
-end
-
-technic.grinder_recipes = {}
+technic.register_recipe_type("grinding", S("Grinding"))
 
 function technic.register_grinder_recipe(data)
 	data.time = data.time or 3
-	technic.grinder_recipes[data.input] = data
-	if unified_inventory then
-		unified_inventory.register_craft({
-			type = "grinding",
-			output = data.output,
-			items = {data.input},
-			width = 0,
-		})
-	end
+	technic.register_recipe("grinding", data)
 end
 
-minetest.after(0.01, function ()
-	for ingredient, recipe in pairs(technic.grinder_recipes) do
-		ingredient = minetest.registered_aliases[ingredient]
-		while ingredient do
-			technic.grinder_recipes[ingredient] = recipe
-			ingredient = minetest.registered_aliases[ingredient]
-		end
-	end
-end)
-
--- Receive an ItemStack of result by an ItemStack input
-function technic.get_grinder_recipe(itemstack)
-	return technic.grinder_recipes[itemstack:get_name()]
-end
-
--- Sorted alphebeticaly
 local recipes = {
+	-- Dusts
 	{"default:coal_lump",       "technic:coal_dust 2"},
-	{"default:cobble",          "default:gravel"},
 	{"default:copper_lump",     "technic:copper_dust 2"},
 	{"default:desert_stone",    "default:desert_sand"},
 	{"default:gold_lump",       "technic:gold_dust 2"},
-	{"default:gravel",          "default:dirt"},
 	{"default:iron_lump",       "technic:wrought_iron_dust 2"},
-	{"default:stone",           "default:sand"},
 	{"moreores:mithril_lump",   "technic:mithril_dust 2"},
 	{"moreores:silver_lump",    "technic:silver_dust 2"},
 	{"moreores:tin_lump",       "technic:tin_dust 2"},
 	{"technic:chromium_lump",   "technic:chromium_dust 2"},
 	{"technic:zinc_lump",       "technic:zinc_dust 2"},
+	
+	-- Other
+	{"default:cobble",          "default:gravel"},
+	{"default:gravel",          "default:dirt"},
+	{"default:stone",           "default:sand"},
 }
 
 if minetest.get_modpath("gloopores") or minetest.get_modpath("glooptest") then
@@ -69,7 +40,7 @@
 end
 
 for _, data in pairs(recipes) do
-	technic.register_grinder_recipe({input=data[1], output=data[2]})
+	technic.register_grinder_recipe({input = data[1], output = data[2]})
 end
 
 local function register_dust(name, ingot)
diff --git a/technic/machines/register/init.lua b/technic/machines/register/init.lua
index a4435c2..f1518fe 100644
--- a/technic/machines/register/init.lua
+++ b/technic/machines/register/init.lua
@@ -1,5 +1,7 @@
 local path = technic.modpath.."/machines/register"
 
+dofile(path.."/recipes.lua")
+dofile(path.."/machine_base.lua")
 dofile(path.."/alloy_furnace.lua")
 dofile(path.."/battery_box.lua")
 dofile(path.."/cables.lua")
diff --git a/technic/machines/register/machine_base.lua b/technic/machines/register/machine_base.lua
new file mode 100644
index 0000000..4cc3c71
--- /dev/null
+++ b/technic/machines/register/machine_base.lua
@@ -0,0 +1,169 @@
+
+local S = technic.getter
+
+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()
+		return inv:room_for_item("src", stack)
+	end,
+	connect_sides = {left = 1, right = 1, back = 1, top = 1, bottom = 1},
+}
+
+function technic.register_base_machine(data)
+	local typename = data.typename
+	local machine_name = data.machine_name
+	local machine_desc = data.machine_desc
+	local tier = data.tier
+	local ltier = string.lower(tier)
+
+	local groups = {cracky = 2}
+	local active_groups = {cracky = 2, not_in_creative_inventory = 1}
+	if data.tube then
+		groups.tubedevice = 1
+		groups.tubedevice_receiver = 1
+		active_groups.tubedevice = 1
+		active_groups.tubedevice_receiver = 1
+	end
+
+
+	local formspec =
+		"invsize[8,9;]"..
+		"list[current_name;src;3,1;1,1;]"..
+		"list[current_name;dst;5,1;2,2;]"..
+		"list[current_player;main;0,5;8,4;]"..
+		"label[0,0;"..S("%s Grinder"):format(tier).."]"
+	if data.upgrade then
+		formspec = formspec..
+			"list[current_name;upgrade1;1,3;1,1;]"..
+			"list[current_name;upgrade2;2,3;1,1;]"..
+			"label[1,4;"..S("Upgrade Slots").."]"
+	end
+
+	minetest.register_node("technic:"..ltier.."_"..machine_name, {
+		description = machine_desc:format(tier),
+		tiles = {"technic_"..ltier.."_"..machine_name.."_top.png", 
+	                 "technic_"..ltier.."_"..machine_name.."_bottom.png",
+		         "technic_"..ltier.."_"..machine_name.."_side.png",
+		         "technic_"..ltier.."_"..machine_name.."_side.png",
+		         "technic_"..ltier.."_"..machine_name.."_side.png",
+		         "technic_"..ltier.."_"..machine_name.."_front.png"},
+		paramtype2 = "facedir",
+		groups = groups,
+		tube = data.tube and tube or nil,
+		legacy_facedir_simple = true,
+		sounds = default.node_sound_wood_defaults(),
+		on_construct = function(pos)
+			local node = minetest.get_node(pos)
+			local meta = minetest.get_meta(pos)
+			meta:set_string("infotext", machine_desc:format(tier))
+			meta:set_int("tube_time",  0)
+			meta:set_string("formspec", formspec)
+			local inv = meta:get_inventory()
+			inv:set_size("src", 1)
+			inv:set_size("dst", 4)
+			inv:set_size("upgrade1", 1)
+			inv:set_size("upgrade2", 1)
+		end,
+		can_dig = technic.machine_can_dig,
+		allow_metadata_inventory_put = technic.machine_inventory_put,
+		allow_metadata_inventory_take = technic.machine_inventory_take,
+		allow_metadata_inventory_move = technic.machine_inventory_move,
+	})
+
+	minetest.register_node("technic:"..ltier.."_"..machine_name.."_active",{
+		description = machine_desc:format(tier),
+		tiles = {"technic_"..ltier.."_"..machine_name.."_top.png",
+		         "technic_"..ltier.."_"..machine_name.."_bottom.png",
+		         "technic_"..ltier.."_"..machine_name.."_side.png",
+		         "technic_"..ltier.."_"..machine_name.."_side.png",
+		         "technic_"..ltier.."_"..machine_name.."_side.png",
+		         "technic_"..ltier.."_"..machine_name.."_front_active.png"},
+		paramtype2 = "facedir",
+		drop = "technic:"..ltier.."_"..machine_name,
+		groups = active_groups,
+		legacy_facedir_simple = true,
+		sounds = default.node_sound_wood_defaults(),
+		tube = data.tube and tube or nil,
+		can_dig = technic.machine_can_dig,
+		allow_metadata_inventory_put = technic.machine_inventory_put,
+		allow_metadata_inventory_take = technic.machine_inventory_take,
+		allow_metadata_inventory_move = technic.machine_inventory_move,
+	})
+
+	minetest.register_abm({
+		nodenames = {"technic:"..ltier.."_"..machine_name,
+		             "technic:"..ltier.."_"..machine_name.."_active"},
+		interval = 1,
+		chance   = 1,
+		action = function(pos, node, active_object_count, active_object_count_wider)
+			local meta     = minetest.get_meta(pos)
+			local inv      = meta:get_inventory()
+			local eu_input = meta:get_int(tier.."_EU_input")
+
+			local machine_desc_tier = machine_desc:format(tier)
+			local machine_node      = "technic:"..ltier.."_"..machine_name
+			local machine_demand    = data.demand
+
+			-- Setup meta data if it does not exist.
+			if not eu_input then
+				meta:set_int(tier.."_EU_demand", machine_demand[1])
+				meta:set_int(tier.."_EU_input", 0)
+				return
+			end
+		
+			-- Power off automatically if no longer connected to a switching station
+			technic.switching_station_timeout_count(pos, tier)
+
+			local EU_upgrade, tube_upgrade = 0, 0
+			if data.upgrade then
+				EU_upgrade, tube_upgrade = technic.handle_machine_upgrades(meta)
+			end
+			if data.tube then
+				technic.handle_machine_pipeworks(pos, tube_upgrade)
+			end
+
+			local result = technic.get_recipe(typename, inv:get_stack("src", 1))
+
+			if not result then
+				technic.swap_node(pos, machine_node)
+				meta:set_string("infotext", S("%s Idle"):format(machine_desc_tier))
+				meta:set_int(tier.."_EU_demand", 0)
+				return
+			end
+		
+			if eu_input < machine_demand[EU_upgrade+1] then
+				-- Unpowered - go idle
+				technic.swap_node(pos, machine_node)
+				meta:set_string("infotext", S("%s Unpowered"):format(machine_desc_tier))
+			elseif eu_input >= machine_demand[EU_upgrade+1] then
+				-- Powered	
+				technic.swap_node(pos, machine_node.."_active")
+				meta:set_string("infotext", S("%s Active"):format(machine_desc_tier))
+
+				meta:set_int("src_time", meta:get_int("src_time") + 1)
+				if meta:get_int("src_time") >= result.time / data.speed then
+					meta:set_int("src_time", 0)
+					local result_stack = ItemStack(result.output)
+					if inv:room_for_item("dst", result_stack) then
+						srcstack = inv:get_stack("src", 1)
+						srcstack:take_item(ItemStack(result.input):get_count())
+						inv:set_stack("src", 1, srcstack)
+						inv:add_item("dst", result_stack)
+					end
+				end
+			end
+			meta:set_int(tier.."_EU_demand", machine_demand[EU_upgrade+1])
+		end
+	})
+
+	technic.register_machine(tier, "technic:"..ltier.."_"..machine_name,            technic.receiver)
+	technic.register_machine(tier, "technic:"..ltier.."_"..machine_name.."_active", technic.receiver)
+
+end -- End registration
+
diff --git a/technic/machines/register/recipes.lua b/technic/machines/register/recipes.lua
new file mode 100644
index 0000000..fb5c09e
--- /dev/null
+++ b/technic/machines/register/recipes.lua
@@ -0,0 +1,63 @@
+
+technic.recipes = {}
+function technic.register_recipe_type(typename, desc)
+	if unified_inventory and unified_inventory.register_craft_type then
+		unified_inventory.register_craft_type(typename, {
+			description = desc,
+			height = 1,
+			width = 1,
+		})
+	end
+	technic.recipes[typename] = {}
+end
+
+function technic.register_recipe(typename, data)
+	local src = ItemStack(data.input):get_name()
+	technic.recipes[typename][src] = data
+	if unified_inventory then
+		unified_inventory.register_craft({
+			type = typename,
+			output = data.output,
+			items = {data.input},
+			width = 0,
+		})
+	end
+end
+
+function technic.get_recipe(typename, item)
+	if typename == "cooking" then -- Already builtin in Minetest, so use that
+		local result = minetest.get_craft_result({
+			method = "cooking",
+			width = 1,
+			items = {item}})
+		-- Compatibility layer
+		if not result or result.time == 0 then
+			return nil
+		else
+			return {time = result.time,
+			        input = item:get_name(),
+			        output = result.item:to_string()}
+		end
+	end
+	local recipe = technic.recipes[typename][item:get_name()]
+	if recipe and item:get_count() >= ItemStack(recipe.input):get_count() then
+		return recipe
+	else
+		return nil
+	end
+end
+
+-- Handle aliases
+minetest.after(0.01, function ()
+	for _, recipes_list in pairs(technic.recipes) do
+		for ingredient, recipe in pairs(recipes_list) do
+			ingredient = minetest.registered_aliases[ingredient]
+			while ingredient do
+				recipes_list[ingredient] = recipe
+				ingredient = minetest.registered_aliases[ingredient]
+			end
+		end
+	end
+end)
+
+

--
Gitblit v1.8.0