summaryrefslogtreecommitdiff
path: root/autocrafter.lua
blob: 663b14ce783576f40c70b429bf533f9dd6fa0e59 (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
})