breeder.lua 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731
  1. -- Functions for the generator nodes.
  2. breeder = breeder or {}
  3. breeder_inactive = breeder_inactive or {}
  4. breeder_active = breeder_active or {}
  5. breeder.siren = breeder.siren or {}
  6. local BUFFER_SIZE = tech.breeder.buffer
  7. local ENERGY_TIME = tech.breeder.time
  8. local TOTAL_COOK_TIME = tech.breeder.totaltime
  9. local ENERGY_AMOUNT = tech.breeder.power
  10. local BREEDER_TIER = "mv"
  11. -- Localize for performance.
  12. local math_floor = math.floor
  13. local math_random = math.random
  14. local fuel = {}
  15. local SS_OFF = 0
  16. local SS_DANGER = 1
  17. local SS_CLEAR = 2
  18. local breeder_siren = breeder.siren
  19. local function siren_set_state(pos, state)
  20. local hpos = minetest.hash_node_position(pos)
  21. local siren = breeder_siren[hpos]
  22. if not siren then
  23. if state == SS_OFF then return end
  24. siren = {state=SS_OFF}
  25. breeder_siren[hpos] = siren
  26. end
  27. if state == SS_DANGER and siren.state ~= SS_DANGER then
  28. if siren.handle then minetest.sound_stop(siren.handle) end
  29. siren.handle = minetest.sound_play("technic_hv_nuclear_reactor_siren_danger_loop",
  30. {pos=pos, gain=1.5, loop=true, max_hear_distance=48})
  31. siren.state = SS_DANGER
  32. elseif state == SS_CLEAR then
  33. if siren.handle then minetest.sound_stop(siren.handle) end
  34. local clear_handle = minetest.sound_play("technic_hv_nuclear_reactor_siren_clear",
  35. {pos=pos, gain=1.5, loop=false, max_hear_distance=48})
  36. siren.handle = clear_handle
  37. siren.state = SS_CLEAR
  38. minetest.after(10, function()
  39. if siren.handle ~= clear_handle then return end
  40. minetest.sound_stop(clear_handle)
  41. if breeder_siren[hpos] == siren then
  42. breeder_siren[hpos] = nil
  43. end
  44. end)
  45. elseif state == SS_OFF and siren.state ~= SS_OFF then
  46. if siren.handle then minetest.sound_stop(siren.handle) end
  47. breeder_siren[hpos] = nil
  48. end
  49. end
  50. local function siren_danger(pos, meta)
  51. meta:set_int("siren", 1)
  52. siren_set_state(pos, SS_DANGER)
  53. end
  54. local function siren_clear(pos, meta)
  55. if meta:get_int("siren") ~= 0 then
  56. siren_set_state(pos, SS_CLEAR)
  57. meta:set_int("siren", 0)
  58. end
  59. end
  60. local function get_breeder_damage(pos)
  61. local meta = minetest.get_meta(pos)
  62. local owner = meta:get_string("owner")
  63. local vm = VoxelManip()
  64. local pos1 = vector.subtract(pos, 3)
  65. local pos2 = vector.add(pos, 3)
  66. local MinEdge, MaxEdge = vm:read_from_map(pos1, pos2)
  67. local data = vm:get_data()
  68. local area = VoxelArea:new({MinEdge=MinEdge, MaxEdge=MaxEdge})
  69. local c_concrete = minetest.get_content_id("concrete:concrete")
  70. local c_steel = minetest.get_content_id("stainless_steel:block")
  71. local c_lava_source = minetest.get_content_id("default:lava_source")
  72. local c_lava_flowing = minetest.get_content_id("default:lava_flowing")
  73. local concrete_layer, steel_layer, lava_layer = 0, 0, 0
  74. for z = pos1.z, pos2.z do
  75. for y = pos1.y, pos2.y do
  76. for x = pos1.x, pos2.x do
  77. local cid = data[area:index(x, y, z)]
  78. if x == pos1.x+0 or x == pos2.x-0 or
  79. y == pos1.y+0 or y == pos2.y-0 or
  80. z == pos1.z+0 or z == pos2.z-0 then
  81. if cid == c_concrete then
  82. concrete_layer = concrete_layer + 1
  83. end
  84. elseif x == pos1.x+1 or x == pos2.x-1 or
  85. y == pos1.y+1 or y == pos2.y-1 or
  86. z == pos1.z+1 or z == pos2.z-1 then
  87. if cid == c_steel then
  88. steel_layer = steel_layer + 1
  89. end
  90. elseif x == pos1.x+2 or x == pos2.x-2 or
  91. y == pos1.y+2 or y == pos2.y-2 or
  92. z == pos1.z+2 or z == pos2.z-2 then
  93. if cid == c_lava_source or cid == c_lava_flowing then
  94. lava_layer = lava_layer + 1
  95. end
  96. end
  97. end
  98. end
  99. end
  100. --minetest.chat_send_player("nhryciw1", "Checking thorium breeder reactor!")
  101. -- Debug!
  102. --if minetest.is_singleplayer() or gdac.player_is_admin(owner) then
  103. -- return 0
  104. --end
  105. if lava_layer > 24 then lava_layer = 24 end
  106. if steel_layer > 96 then steel_layer = 96 end
  107. if concrete_layer > 216 then concrete_layer = 216 end
  108. return (24 - lava_layer) +
  109. (96 - steel_layer) +
  110. (216 - concrete_layer)
  111. end
  112. local function check_environment(pos, meta)
  113. --minetest.chat_send_player("nhryciw1", "Check env!")
  114. local timer = meta:get_int("chktmr")
  115. --local active = meta:get_int("active")
  116. if timer <= 0 then
  117. local result = false
  118. local good = false
  119. local damage = get_breeder_damage(pos)
  120. if damage == 0 then
  121. good = true
  122. end
  123. --minetest.chat_send_player("nhryciw1", "Breeder reactor damage: " .. damage .. "!")
  124. if good then
  125. meta:set_string("error", "DUMMY")
  126. result = false
  127. else
  128. meta:set_string("error", "INSUFFICIENT REACTOR SHIELDING!")
  129. result = true -- Bad
  130. end
  131. -- Randomize time to next nodecheck.
  132. meta:set_int("chktmr", math_random(1*60, 3*60))
  133. return result
  134. end
  135. -- Decrement check timer.
  136. timer = timer - 1
  137. meta:set_int("chktmr", timer)
  138. -- No check performed.
  139. return nil
  140. end
  141. for k, v in ipairs({
  142. {name="inactive"},
  143. {name="active"},
  144. }) do
  145. -- Which function table are we operating on?
  146. local func = _G["breeder_" .. v.name]
  147. func.on_energy_get =
  148. function(pos, energy)
  149. local meta = minetest.get_meta(pos)
  150. local inv = meta:get_inventory()
  151. local have = inv:get_stack("out", 1):get_count()
  152. if have < energy then
  153. inv:set_stack("out", 1, ItemStack(""))
  154. if have > 0 then
  155. func.trigger_update(pos)
  156. end
  157. return have
  158. end
  159. have = have - energy
  160. inv:set_stack("out", 1, ItemStack("atomic:energy " .. have))
  161. if energy > 0 then
  162. func.trigger_update(pos)
  163. end
  164. return energy
  165. end
  166. func.breeder_destroy =
  167. function(pos)
  168. minetest.after(0, function()
  169. tnt.boom(pos, {
  170. radius = 20,
  171. ignore_protection = false,
  172. ignore_on_blast = false,
  173. damage_radius = 30,
  174. disable_drops = true,
  175. })
  176. end)
  177. end
  178. func.trigger_update =
  179. function(pos)
  180. local timer = minetest.get_node_timer(pos)
  181. -- Restart timer even if already running.
  182. timer:start(1.0)
  183. end
  184. func.on_punch =
  185. function(pos, node, puncher, pointed_thing)
  186. --minetest.chat_send_player("nhryciw1", "Punched!")
  187. func.trigger_update(pos)
  188. -- Check breeder integrity.
  189. local meta = minetest.get_meta(pos)
  190. meta:set_int("chktmr", 0)
  191. func.privatize(meta)
  192. end
  193. func.compose_formspec =
  194. function(fuel_percent, item_percent)
  195. local formspec =
  196. "size[8,8.5]" ..
  197. default.formspec.get_form_colors() ..
  198. default.formspec.get_form_image() ..
  199. default.formspec.get_slot_colors() ..
  200. "label[1,0.5;Thorium Rod Compartment]" ..
  201. "list[context;fuel;1,1;3,2;]" ..
  202. "image[4,1.5;1,1;default_furnace_fire_bg.png^[lowpart:" ..
  203. (fuel_percent) .. ":default_furnace_fire_fg.png]" ..
  204. "image[5,1.5;1,1;gui_furnace_arrow_bg.png^[lowpart:"..
  205. (item_percent)..":gui_furnace_arrow_fg.png^[transformR270]"..
  206. "label[6,1.0;Charge Buffer]" ..
  207. "list[context;out;6,1.5;1,1;]" ..
  208. "list[current_player;main;0,4.25;8,1;]" ..
  209. "list[current_player;main;0,5.5;8,3;8]" ..
  210. "listring[context;fuel]" ..
  211. "listring[current_player;main]" ..
  212. default.get_hotbar_bg(0, 4.25)
  213. return formspec
  214. end
  215. func.compose_infotext =
  216. function(pos, keeprunning)
  217. local meta = minetest.get_meta(pos)
  218. local eups = meta:get_int("eups")
  219. local machine_state = "Standby"
  220. if keeprunning then machine_state = "Active" end
  221. local output = math_floor(eups / ENERGY_TIME)
  222. if not keeprunning then
  223. output = 0
  224. end
  225. local infotext = "Breeder Reactor (" .. machine_state .. ")\n" ..
  226. "Output: " .. output .. " EU Per/Sec"
  227. local err = meta:get_string("error") or "DUMMY"
  228. if err ~= "" and err ~= "DUMMY" then
  229. infotext = infotext .. "\n" .. err
  230. end
  231. local damage = meta:get_int("damage")
  232. if damage > 0 then
  233. infotext = infotext .. "\nReactor damage: " .. damage .. "!"
  234. end
  235. return infotext
  236. end
  237. func.can_dig =
  238. function(pos, player)
  239. local meta = minetest.get_meta(pos)
  240. local inv = meta:get_inventory()
  241. -- The energy output inventory does not count.
  242. return inv:is_empty("fuel")
  243. end
  244. func.allow_metadata_inventory_put =
  245. function(pos, listname, index, stack, player)
  246. if minetest.test_protection(pos, player:get_player_name()) then
  247. return 0
  248. end
  249. if listname == "fuel" then
  250. local node = minetest.get_node(pos)
  251. -- Cannot put rods in an active breeder.
  252. if node.name == "breeder:inactive" and stack:get_name() == "thorium:rod" then
  253. return stack:get_count()
  254. end
  255. end
  256. return 0
  257. end
  258. func.allow_metadata_inventory_move =
  259. function(pos, from_list, from_index, to_list, to_index, count, player)
  260. return 0
  261. end
  262. func.allow_metadata_inventory_take =
  263. function(pos, listname, index, stack, player)
  264. if minetest.test_protection(pos, player:get_player_name()) then
  265. return 0
  266. end
  267. if listname == "fuel" then
  268. return stack:get_count()
  269. end
  270. return 0
  271. end
  272. func.on_timer =
  273. function(pos, elapsed)
  274. --minetest.chat_send_player("nhryciw1","# Server: On Timer! " .. minetest.get_gametime())
  275. local keeprunning = false
  276. local meta = minetest.get_meta(pos)
  277. local owner = meta:get_string("owner")
  278. local inv = meta:get_inventory()
  279. local fuellist = inv:get_list("fuel")
  280. local time = meta:get_int("time")
  281. local time2 = meta:get_float("time2")
  282. local maxtime = meta:get_int("maxtime")
  283. local maxtime2 = ENERGY_TIME
  284. local eups = meta:get_int("eups")
  285. local fuel_percent = 0
  286. local item_percent = 0
  287. local need_discharge = false
  288. -- This sets infotext, so must always call this.
  289. local bad = check_environment(pos, meta)
  290. if v.name == "active" then
  291. if bad ~= nil then
  292. if bad then
  293. meta:set_int("bad", 1)
  294. siren_danger(pos, meta)
  295. else
  296. if meta:get_int("bad") == 1 then
  297. siren_clear(pos, meta)
  298. end
  299. meta:set_int("bad", 0)
  300. end
  301. end
  302. -- Damage breeder over time if bad.
  303. if meta:get_int("bad") == 1 then
  304. local damage = meta:get_int("damage")
  305. damage = damage + 1
  306. meta:set_int("damage", damage)
  307. -- Destroy breeder after 10 minutes of continous damage.
  308. if damage > 60*10 then
  309. func.breeder_destroy(pos)
  310. return
  311. end
  312. else
  313. -- Slowly decrease damage if not bad.
  314. local damage = meta:get_int("damage")
  315. if damage > 0 then
  316. damage = damage - 1
  317. meta:set_int("damage", damage)
  318. end
  319. end
  320. else
  321. -- Slowly decrease damage when inactive.
  322. local damage = meta:get_int("damage")
  323. if damage > 0 then
  324. damage = damage - 1
  325. meta:set_int("damage", damage)
  326. end
  327. end
  328. -- Radiation damage to nearby players.
  329. if v.name == "active" then
  330. local entities = minetest.get_objects_inside_radius(pos, 3.5)
  331. for k, v in ipairs(entities) do
  332. if v:is_player() then
  333. v:set_hp(v:get_hp() - 1)
  334. -- Radiation exhausts player.
  335. sprint.set_stamina(v, 0)
  336. end
  337. end
  338. end
  339. do
  340. local stack = inv:get_stack("out", 1)
  341. --minetest.chat_send_player("nhryciw1", "# Server: " .. stack:get_count() .. " charge!")
  342. if stack:get_count() >= BUFFER_SIZE then
  343. need_discharge = true
  344. end
  345. end
  346. -- Manage fuel.
  347. if time > 0 then
  348. -- Keep burning current fuel item.
  349. time = time - 1
  350. -- Restart timer.
  351. keeprunning = true
  352. -- Generate energy.
  353. time2 = time2 + 1
  354. if time2 >= maxtime2 then
  355. if not need_discharge then
  356. local energy = "atomic:energy " .. eups
  357. if inv:room_for_item("out", energy) then
  358. inv:add_item("out", energy)
  359. else
  360. -- No room? Huh. Discharge breeder!
  361. -- Note: this can happen because charge to be added would be
  362. -- greater than stack_max. This bug was actually observed.
  363. -- It is only likely to affect high-output machines.
  364. need_discharge = true
  365. end
  366. end
  367. time2 = 0
  368. end
  369. else
  370. -- Burntime has run out, get new fuel item.
  371. if fuellist[1]:get_count() > 0 and not need_discharge then
  372. local fuel, afterfuel
  373. local is_mese = false
  374. meta:set_int("eups", 0)
  375. -- Check if we have enough fuel.
  376. local rods = 0
  377. for i = 1, 6, 1 do
  378. local stack = inv:get_stack("fuel", i)
  379. if stack:get_name() == "thorium:rod" and stack:get_count() > 0 then
  380. rods = rods + 1
  381. end
  382. end
  383. -- Try to get fuel.
  384. fuel, afterfuel = minetest.get_craft_result({
  385. method="coalfuel", width=1, items=fuellist,
  386. })
  387. if rods == 6 then
  388. -- We got uranium rods, consume them.
  389. for i = 1, 6, 1 do
  390. inv:set_stack("fuel", i, ItemStack(""))
  391. end
  392. time = TOTAL_COOK_TIME
  393. meta:set_int("maxtime", TOTAL_COOK_TIME)
  394. machines.swap_node(pos, "breeder:active")
  395. fuel_percent = 100
  396. keeprunning = true -- Restart timer.
  397. meta:set_int("eups", ENERGY_AMOUNT)
  398. else
  399. -- No valid fuel in fuel slot.
  400. machines.swap_node(pos, "breeder:inactive")
  401. --minetest.get_node_timer(pos):stop()
  402. time2 = 0
  403. end
  404. else
  405. -- No more fuel, shutdown generator.
  406. machines.swap_node(pos, "breeder:inactive")
  407. --minetest.get_node_timer(pos):stop()
  408. meta:set_int("eups", 0)
  409. time2 = 0
  410. end
  411. end
  412. -- Discharge energy into the network.
  413. if need_discharge then
  414. --minetest.chat_send_player("nhryciw1", "# Server: Discharging breeder reactor!")
  415. local timer = meta:get_int("dschgtmr")
  416. -- It's frequently the case that a reactor spends a lot of time trying to
  417. -- send energy to a network where all the batteries are full. We can save
  418. -- the server some work by delaying a little before the next discharge, if
  419. -- the last discharge didn't succeed.
  420. if timer <= 0 then
  421. local energy = inv:get_stack("out", 1)
  422. local old = energy:get_count()
  423. energy:set_count(net2.put_energy(pos, owner, old, BREEDER_TIER))
  424. inv:set_stack("out", 1, energy)
  425. if energy:get_count() < old then
  426. -- If we succeeded in discharging energy, keep doing so.
  427. -- Otherwise, batteries are full.
  428. keeprunning = true
  429. else
  430. meta:set_int("dschgtmr", 60)
  431. end
  432. else
  433. timer = timer - 1
  434. meta:set_int("dschgtmr", timer)
  435. end
  436. end
  437. -- If generator is no longer producing energy,
  438. -- unload the buffered energy.
  439. if not keeprunning then
  440. local energy = inv:get_stack("out", 1)
  441. energy:set_count(net2.put_energy(pos, owner, energy:get_count(), BREEDER_TIER))
  442. inv:set_stack("out", 1, energy)
  443. end
  444. -- Update infotext & formspec.
  445. meta:set_int("time", time)
  446. meta:set_float("time2", time2)
  447. fuel_percent = math_floor(time / maxtime * 100)
  448. item_percent = math_floor(time2 / maxtime2 * 100)
  449. meta:set_string("infotext", func.compose_infotext(pos, keeprunning))
  450. meta:set_string("formspec", func.compose_formspec(fuel_percent, item_percent))
  451. -- Determine mode (active or sleep) and set timer accordingly.
  452. if keeprunning then
  453. minetest.get_node_timer(pos):start(1.0)
  454. else
  455. -- Slow down timer during sleep periods to reduce load.
  456. minetest.get_node_timer(pos):start(math_random(1, 3*60))
  457. end
  458. end
  459. --minetest.chat_send_all("breeder.on_timer registered")
  460. func.on_blast =
  461. function(pos)
  462. local drops = {}
  463. -- Ignore contents of fuel inventory.
  464. minetest.remove_node(pos)
  465. if v.name == "active" then
  466. func.breeder_destroy(pos)
  467. else
  468. -- Only save breeder if it wasn't active.
  469. drops[#drops+1] = "breeder:inactive"
  470. end
  471. return drops
  472. end
  473. --minetest.chat_send_all("breeder.on_blast registered")
  474. func.on_construct =
  475. function(pos)
  476. local meta = minetest.get_meta(pos)
  477. local inv = meta:get_inventory()
  478. meta:set_string("infotext", func.compose_infotext(pos, false))
  479. meta:set_string("formspec", func.compose_formspec(0, 0))
  480. --minetest.chat_send_player("nhryciw1", "Breeder reactor constructed!")
  481. inv:set_size("fuel", 6)
  482. inv:set_size("out", 1)
  483. meta:set_string("owner", "DUMMY")
  484. meta:set_string("error", "DUMMY")
  485. meta:set_string("nodename", "DUMMY")
  486. meta:set_int("siren", 0)
  487. meta:set_int("chktmr", 0)
  488. meta:set_int("eups", 0)
  489. meta:set_int("damage", 0)
  490. meta:set_int("time", 0)
  491. meta:set_int("maxtime", 0)
  492. meta:set_int("bad", 0)
  493. meta:set_float("time2", 0.0)
  494. func.privatize(meta)
  495. end
  496. --minetest.chat_send_all("breeder.on_construct registered")
  497. func.privatize =
  498. function(meta)
  499. meta:mark_as_private({
  500. "nodename", "bad", "time2", "maxtime", "siren", "owner",
  501. "chktmr", "error", "eups", "damage", "time", "dschgtmr",
  502. })
  503. end
  504. func.on_destruct =
  505. function(pos)
  506. local meta = minetest.get_meta(pos)
  507. siren_set_state(pos, SS_OFF)
  508. net2.clear_caches(pos, meta:get_string("owner"), BREEDER_TIER)
  509. nodestore.del_node(pos)
  510. if v.name == "active" then
  511. func.breeder_destroy(pos)
  512. end
  513. end
  514. func.after_place_node =
  515. function(pos, placer, itemstack, pointed_thing)
  516. local meta = minetest.get_meta(pos)
  517. local node = minetest.get_node(pos)
  518. local owner = placer:get_player_name()
  519. meta:set_string("nodename", node.name)
  520. meta:set_string("owner", owner)
  521. net2.clear_caches(pos, owner, BREEDER_TIER)
  522. nodestore.add_node(pos)
  523. end
  524. func.on_metadata_inventory_move =
  525. function(pos)
  526. func.trigger_update(pos)
  527. end
  528. func.on_metadata_inventory_put =
  529. function(pos)
  530. func.trigger_update(pos)
  531. end
  532. func.on_metadata_inventory_take =
  533. function(pos, listname, index, stack, player)
  534. func.trigger_update(pos)
  535. end
  536. end
  537. --i cannot for the life of me figure out why the normal reactor works without this, but it does.
  538. --breeder.run_once = false
  539. --
  540. -- ^^^ This could only break if some code used the wrong table name left over
  541. -- from copy+paste. Anyway it works now. -- MustTest
  542. if not breeder.run_once then
  543. for k, v in ipairs({
  544. {name="inactive", light=0},
  545. {name="active", light=14},
  546. }) do
  547. -- Which function table are we operating on?
  548. local func = _G["breeder_" .. v.name]
  549. minetest.register_node(":breeder:" .. v.name, {
  550. description = "Thorium Breeder Reactor Core\n\nConnects to an MV power-network.\nGenerates a large amount of power.\nExplosion danger, requires shielding!",
  551. tiles = {"reactor_core.png"},
  552. groups = utility.dig_groups("machine", {immovable=1}),
  553. paramtype2 = "facedir",
  554. is_ground_content = false,
  555. sounds = default.node_sound_metal_defaults(),
  556. drop = "breeder:inactive",
  557. light_source = v.light,
  558. on_energy_get = function(...)
  559. return breeder.on_energy_get(...) end,
  560. on_rotate = function(...)
  561. return screwdriver.rotate_simple(...) end,
  562. on_punch = function(...)
  563. return func.on_punch(...) end,
  564. can_dig = function(...)
  565. return func.can_dig(...) end,
  566. on_timer = function(...)
  567. return func.on_timer(...) end,
  568. on_construct = function(...)
  569. return func.on_construct(...) end,
  570. on_destruct = function(...)
  571. return func.on_destruct(...) end,
  572. after_place_node = function(...)
  573. return func.after_place_node(...) end,
  574. on_blast = function(...)
  575. return func.on_blast(...) end,
  576. on_metadata_inventory_move = function(...)
  577. return func.on_metadata_inventory_move(...) end,
  578. on_metadata_inventory_put = function(...)
  579. return func.on_metadata_inventory_put(...) end,
  580. on_metadata_inventory_take = function(...)
  581. return func.on_metadata_inventory_take(...) end,
  582. allow_metadata_inventory_put = function(...)
  583. return func.allow_metadata_inventory_put(...) end,
  584. allow_metadata_inventory_move = function(...)
  585. return func.allow_metadata_inventory_move(...) end,
  586. allow_metadata_inventory_take = function(...)
  587. return func.allow_metadata_inventory_take(...) end,
  588. })
  589. end
  590. --minetest.chat_send_all("node registered")
  591. minetest.register_craft({
  592. output = 'breeder:inactive',
  593. recipe = {
  594. {'techcrafts:carbon_plate', 'default:obsidian_glass', 'techcrafts:carbon_plate'},
  595. {'techcrafts:composite_plate', 'gen2:mv_inactive', 'techcrafts:composite_plate'},
  596. {'stainless_steel:ingot', 'geo2:lv_inactive', 'stainless_steel:ingot'},
  597. }
  598. })
  599. local c = "breeder:core"
  600. local f = machines.modpath .. "/breeder.lua"
  601. reload.register_file(c, f, false)
  602. breeder.run_once = true
  603. end