-
Notifications
You must be signed in to change notification settings - Fork 21
/
recycler.lua
254 lines (204 loc) · 8.66 KB
/
recycler.lua
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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
-- rnd 2015:
-- this node works as a reverse of crafting process with a 25% loss of items (aka recycling). You can select which recipe to use when recycling.
-- There is a fuel cost to recycle
-- prevent unrealistic recyclings
local no_recycle_list = {
["default:steel_ingot"]=1,["default:copper_ingot"]=1,["default:bronze_ingot"]=1,["default:gold_ingot"]=1,
["dye:white"]=1,["dye:grey"]=1,["dye:dark_grey"]=1,["dye:black"]=1,
["dye:violet"]=1,["dye:blue"]=1,["dye:cyan"]=1,["dye:dark_green"]=1,
["dye:green"]=1,["dye:yellow"]=1,["dye:brown"]=1,["dye:orange"]=1,
["dye:red"]=1,["dye:magenta"]=1,["dye:pink"]=1,
}
local recycler_process = function(pos)
local node = minetest.get_node({x=pos.x,y=pos.y-1,z=pos.z}).name;
local meta = minetest.get_meta(pos);local inv = meta:get_inventory();
-- FUEL CHECK
local fuel = meta:get_float("fuel");
if fuel-1<0 then -- we need new fuel, check chest below
local fuellist = inv:get_list("fuel")
if not fuellist then return end
local fueladd, afterfuel = minetest.get_craft_result({method = "fuel", width = 1, items = fuellist})
local supply=0;
if fueladd.time == 0 then -- no fuel inserted, try look for outlet
-- No valid fuel in fuel list
supply = basic_machines.check_power({x=pos.x,y=pos.y-1,z=pos.z},1) or 0;
if supply>0 then
fueladd.time = 40*supply -- same as 10 coal
else
meta:set_string("infotext", "Please insert fuel.");
return;
end
else
if supply==0 then -- Take fuel from fuel list if no supply available
inv:set_stack("fuel", 1, afterfuel.items[1])
fueladd.time = fueladd.time*0.1; -- thats 4 for coal
end
end
if fueladd.time>0 then
fuel=fuel + fueladd.time
meta:set_float("fuel",fuel);
meta:set_string("infotext", "added fuel furnace burn time " .. fueladd.time .. ", fuel status " .. fuel);
end
if fuel-1<0 then return end
end
-- RECYCLING: check out inserted items
local stack = inv:get_stack("src",1);
if stack:is_empty() then return end; -- nothing to do
local src_item = stack:to_string();
local p=string.find(src_item," "); if p then src_item = string.sub(src_item,1,p-1) end -- take first word to determine what item was
-- look if we already handled this item
local known_recipe=true;
if src_item~=meta:get_string("node") then-- did we already handle this? if yes read from cache
meta:set_string("node",src_item);
meta:set_string("itemlist","{}");
meta:set_int("reqcount",0);
known_recipe=false;
end
local itemlist, reqcount;
reqcount = 1; -- needed count of materials for recycle to work
if not known_recipe then
if no_recycle_list[src_item] then meta:set_string("node","") return end -- dont allow recycling of forbidden items
local recipe = minetest.get_all_craft_recipes( src_item );
local recipe_id = tonumber(meta:get_int("recipe")) or 1;
if not recipe then
return
else
itemlist = recipe[recipe_id];
if not itemlist then meta:set_string("node","") return end;
itemlist=itemlist.items;
end
local output = recipe[recipe_id].output or "";
if string.find(output," ") then
local par = string.find(output," ");
--if (tonumber(string.sub(output, par)) or 0)>1 then itemlist = {} end
if par then
reqcount = tonumber(string.sub(output, par)) or 1;
end
end
meta:set_string("itemlist",minetest.serialize(itemlist)); -- read cached itemlist
meta:set_int("reqcount",reqcount);
else
itemlist=minetest.deserialize(meta:get_string("itemlist")) or {};
reqcount = meta:get_int("reqcount") or 1;
end
if stack:get_count()<reqcount then
meta:set_string("infotext", "at least " .. reqcount .. " of " .. src_item .. " is needed ");
return
end
--empty dst inventory before proceeding
-- local size = inv:get_size("dst");
-- for i=1,size do
-- inv:set_stack("dst", i, ItemStack(""));
-- end
--take 1 item from src inventory for each activation
stack=stack:take_item(reqcount); inv:remove_item("src", stack)
for _, v in pairs(itemlist) do
if math.random(1, 4)<=3 then -- probability 3/4 = 75%
if not string.find(v,"group") then -- dont add if item described with group
local par = string.find(v,"\"") or 0;
if inv:room_for_item("dst", ItemStack(v)) then -- can item be put in
inv:add_item("dst",ItemStack(v));
else return
end
end
end
end
minetest.sound_play("recycler", {pos=pos,gain=0.5,max_hear_distance = 16,})
fuel = fuel-1; -- burn fuel on succesful operation
meta:set_float("fuel",fuel); meta:set_string("infotext", "fuel status " .. fuel .. ", recycling " .. meta:get_string("node"));
end
local recycler_update_meta = function(pos)
local meta = minetest.get_meta(pos)
local list_name = "nodemeta:"..pos.x..','..pos.y..','..pos.z
local form =
"size[8,8]".. -- width, heightinv:get_stack
--"size[6,10]".. -- width, height
"label[0,0;IN] label[1,0;OUT] label[0,2;FUEL] "..
"list["..list_name..";src;0.,0.5;1,1;]"..
"list["..list_name..";dst;1.,0.5;3,3;]"..
"list["..list_name..";fuel;0.,2.5;1,1;]"..
"list[current_player;main;0,4;8,4;]"..
"field[4.5,0.75;2,1;recipe;select recipe: ;"..(meta:get_int("recipe")).."]"..
"button[6.5,0.5;1,1;OK;OK]"..
"listring["..list_name..";dst]"..
"listring[current_player;main]"..
"listring["..list_name..";src]"..
"listring[current_player;main]"..
"listring["..list_name..";fuel]"..
"listring[current_player;main]"
--"field[0.25,4.5;2,1;mode;mode;"..mode.."]"
meta:set_string("formspec", form)
end
minetest.register_node("basic_machines:recycler", {
description = "Recycler - use to get some ingredients back from crafted things",
tiles = {"recycler.png"},
groups = {cracky=3},
sounds = default.node_sound_wood_defaults(),
after_place_node = function(pos, placer)
local meta = minetest.get_meta(pos);
meta:set_string("infotext", "Recycler: put one item in it (src) and obtain 75% of raw materials (dst). To operate it insert fuel, then insert item to recycle or use keypad to activate it.")
meta:set_string("owner", placer:get_player_name());
meta:set_int("recipe",1);
meta:set_float("fuel",0);
local inv = meta:get_inventory();inv:set_size("src", 1);inv:set_size("dst",9);inv:set_size("fuel",1);
end,
on_rightclick = function(pos, node, player, itemstack, pointed_thing)
local meta = minetest.get_meta(pos);
local privs = minetest.get_player_privs(player:get_player_name());
if minetest.is_protected(pos, player:get_player_name()) and not privs.privs then return end -- only owner can interact with recycler
recycler_update_meta(pos);
end,
allow_metadata_inventory_put = function(pos, listname, index, stack, player)
local meta = minetest.get_meta(pos);
local privs = minetest.get_player_privs(player:get_player_name());
if meta:get_string("owner")~=player:get_player_name() and not privs.privs then return 0 end
return stack:get_count();
end,
allow_metadata_inventory_take = function(pos, listname, index, stack, player)
local meta = minetest.get_meta(pos);
local privs = minetest.get_player_privs(player:get_player_name());
if meta:get_string("owner")~=player:get_player_name() and not privs.privs then return 0 end
return stack:get_count();
end,
on_metadata_inventory_put = function(pos, listname, index, stack, player)
if listname =="dst" then return end
recycler_process(pos);
end,
allow_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)
return 0;
end,
effector = {
action_on = function (pos, node,ttl)
if type(ttl)~="number" then ttl = 1 end
if ttl<0 then return end -- machines_TTL prevents infinite recursion
recycler_process(pos);
end
},
on_receive_fields = function(pos, formname, fields, sender)
if minetest.is_protected(pos, sender:get_player_name()) then return end
if fields.quit then return end
local meta = minetest.get_meta(pos);
local recipe=1;
if fields.recipe then
recipe = tonumber(fields.recipe) or 1;
else return;
end
meta:set_int("recipe",recipe);
meta:set_string("node",""); -- this will force to reread recipe on next use
recycler_update_meta(pos);
end,
can_dig = function(pos)
local meta = minetest.get_meta(pos);
local inv = meta:get_inventory();
if not (inv:is_empty("fuel")) or not (inv:is_empty("src")) or not (inv:is_empty("dst")) then return false end -- all inv must be empty to be dug
return true
end
})
-- minetest.register_craft({
-- output = "basic_machines:recycler",
-- recipe = {
-- {"default:mese_crystal","default:mese_crystal","default:mese_crystal"},
-- {"default:mese_crystal","default:diamondblock","default:mese_crystal"},
-- {"default:mese_crystal","default:mese_crystal","default:mese_crystal"},
-- }
-- })