summaryrefslogtreecommitdiff
path: root/autocrafter.lua
blob: 1b899f36ae31716907888475811762948209d620 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
local autocrafterCache = {}

function addCacheEntry(pos, recipe, result, new)
	if autocrafterCache[pos.x] == nil then autocrafterCache[pos.x] = {} end
	if autocrafterCache[pos.x][pos.y] == nil then autocrafterCache[pos.x][pos.y] = {} end
	if autocrafterCache[pos.x][pos.y][pos.z] == nil then autocrafterCache[pos.x][pos.z] = {} end
	autocrafterCache[pos.x][pos.y][pos.z] = {["recipe"] = recipe, ["result"] = result, ["new"] = new}
end

function getCacheEntry(pos)
	if autocrafterCache[pos.x] == nil then return nil, nil, nil end
	if autocrafterCache[pos.x][pos.y] == nil then return nil, nil, nil end
	if autocrafterCache[pos.x][pos.y][pos.z] == nil then return nil, nil, nil end
	return autocrafterCache[pos.x][pos.y][pos.z]["recipe"], autocrafterCache[pos.x][pos.y][pos.z]["result"], autocrafterCache[pos.x][pos.y][pos.z]["new"]
end

function autocraft(inventory, pos)
	local recipe = inventory:get_list("recipe")
		local recipe_last
		local result
		local new

		recipe_last, result, new = getCacheEntry(pos)
		if recipe_last ~= nil then
			local recipeUnchanged = true
			for i = 1, 9 do
				--print ("recipe_base"..i.." ")
				--print (recipe[i]:get_name())
				--print (recipe[i]:get_count())
				--print (recipe_last[i]:get_name())
				--print (recipe_last[i]:get_count())
				if recipe[i]:get_name() ~= recipe_last[i]:get_name() then
					recipeUnchanged = False
					break
				end
				if recipe[i]:get_count() ~= recipe_last[i]:get_count() then
					recipeUnchanged = False
					break
				end
			end
			if recipeUnchanged then
				-- print("autocrafter recipe unchanged")
			else
				print("autocrafter recipe changed at pos("..pos.x..","..pos.y..","..pos.z..")")
				for i = 1, 9 do
						recipe_last[i] = recipe[i]
						recipe[i] = ItemStack({name = recipe[i]:get_name(), count = 1})
				end
				result, new = minetest.get_craft_result({method = "normal", width = 3, items = recipe})
				addCacheEntry(pos, recipe_last, result, new)
			end
		else
			print("first call for this autocrafter at pos("..pos.x..","..pos.y..","..pos.z..")")
			recipe_last = {}
			for i = 1, 9 do
				recipe_last[i] = recipe[i]
				--print (recipe_last[i]:get_name())
				recipe[i] = ItemStack({name = recipe[i]:get_name(), count = 1})
			end
			result, new = minetest.get_craft_result({method = "normal", width = 3, items = recipe})
			addCacheEntry(pos, recipe_last, result, new)
		end

		local input = inventory:get_list("input")
	if result.item:is_empty() then return end
	result = result.item
	if not inventory:room_for_item("dst", result) then return end
	local to_use = {}
	for _, item in ipairs(recipe) do
		if item~= nil and not item:is_empty() then
			if to_use[item:get_name()] == nil then
				to_use[item:get_name()] = 1
			else
				to_use[item:get_name()] = to_use[item:get_name()]+1
			end
		end
	end
	local stack
	for itemname, number in pairs(to_use) do
		stack = ItemStack({name = itemname, count = number})
		if not inventory:contains_item("src", stack) then return end
	end
	for itemname, number in pairs(to_use) do
		stack = ItemStack({name = itemname, count = number})
		inventory:remove_item("src", stack)
	end
	inventory:add_item("dst", result)
	for i = 1, 9 do
		inventory:add_item("dst", new.items[i])
	end
end

minetest.register_node("pipeworks:autocrafter", {
	description = "Autocrafter", 
	drawtype = "normal", 
	tiles = {"pipeworks_autocrafter.png"}, 
	groups = {snappy = 3, tubedevice = 1, tubedevice_receiver = 1}, 
	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, 
		input_inventory = "dst", 
		connect_sides = {left = 1, right = 1, front = 1, back = 1, top = 1, bottom = 1}}, 
	on_construct = function(pos)
		local meta = minetest.get_meta(pos)
		meta:set_string("formspec",
				"size[8,11]"..
				"list[current_name;recipe;0,0;3,3;]"..
				"list[current_name;src;0,3.5;8,3;]"..
				"list[current_name;dst;4,0;4,3;]"..
				"list[current_player;main;0,7;8,4;]")
		meta:set_string("infotext", "Autocrafter")
		local inv = meta:get_inventory()
		inv:set_size("src", 3*8)
		inv:set_size("recipe", 3*3)
		inv:set_size("dst", 4*3)
	end, 
	can_dig = function(pos, player)
		local meta = minetest.get_meta(pos); 
		local inv = meta:get_inventory()
		return (inv:is_empty("src") and inv:is_empty("recipe") and inv:is_empty("dst"))
	end, 
	after_place_node = tube_scanforobjects, 
	after_dig_node = tube_scanforobjects, 
})

minetest.register_abm({nodenames = {"pipeworks:autocrafter"}, interval = 1, chance = 1, 
			action = function(pos, node)
				local meta = minetest.get_meta(pos)
				local inv = meta:get_inventory()
				autocraft(inv, pos)
			end
})