breeder.lua 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728
  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. utility.progress_image(4, 1.5, "default_furnace_fire_bg.png", "default_furnace_fire_fg.png", fuel_percent) ..
  203. utility.progress_image(5, 1.5, "gui_furnace_arrow_bg.png", "gui_furnace_arrow_fg.png", item_percent, "^[transformR270") ..
  204. "label[6,1.0;Charge Buffer]" ..
  205. "list[context;out;6,1.5;1,1;]" ..
  206. "list[current_player;main;0,4.25;8,1;]" ..
  207. "list[current_player;main;0,5.5;8,3;8]" ..
  208. "listring[context;fuel]" ..
  209. "listring[current_player;main]" ..
  210. default.get_hotbar_bg(0, 4.25)
  211. return formspec
  212. end
  213. func.compose_infotext =
  214. function(pos, keeprunning)
  215. local meta = minetest.get_meta(pos)
  216. local eups = meta:get_int("eups")
  217. local machine_state = "Standby"
  218. if keeprunning then machine_state = "Active" end
  219. local output = math_floor(eups / ENERGY_TIME)
  220. if not keeprunning then
  221. output = 0
  222. end
  223. local infotext = "Breeder Reactor (" .. machine_state .. ")\n" ..
  224. "Output: " .. output .. " EU Per/Sec"
  225. local err = meta:get_string("error") or "DUMMY"
  226. if err ~= "" and err ~= "DUMMY" then
  227. infotext = infotext .. "\n" .. err
  228. end
  229. local damage = meta:get_int("damage")
  230. if damage > 0 then
  231. infotext = infotext .. "\nReactor damage: " .. damage .. "!"
  232. end
  233. return infotext
  234. end
  235. func.can_dig =
  236. function(pos, player)
  237. local meta = minetest.get_meta(pos)
  238. local inv = meta:get_inventory()
  239. -- The energy output inventory does not count.
  240. return inv:is_empty("fuel")
  241. end
  242. func.allow_metadata_inventory_put =
  243. function(pos, listname, index, stack, player)
  244. if minetest.test_protection(pos, player:get_player_name()) then
  245. return 0
  246. end
  247. if listname == "fuel" then
  248. local node = minetest.get_node(pos)
  249. -- Cannot put rods in an active breeder.
  250. if node.name == "breeder:inactive" and stack:get_name() == "thorium:rod" then
  251. return stack:get_count()
  252. end
  253. end
  254. return 0
  255. end
  256. func.allow_metadata_inventory_move =
  257. function(pos, from_list, from_index, to_list, to_index, count, player)
  258. return 0
  259. end
  260. func.allow_metadata_inventory_take =
  261. function(pos, listname, index, stack, player)
  262. if minetest.test_protection(pos, player:get_player_name()) then
  263. return 0
  264. end
  265. if listname == "fuel" then
  266. return stack:get_count()
  267. end
  268. return 0
  269. end
  270. func.on_timer =
  271. function(pos, elapsed)
  272. --minetest.chat_send_player("nhryciw1","# Server: On Timer! " .. minetest.get_gametime())
  273. local keeprunning = false
  274. local meta = minetest.get_meta(pos)
  275. local owner = meta:get_string("owner")
  276. local inv = meta:get_inventory()
  277. local fuellist = inv:get_list("fuel")
  278. local time = meta:get_int("time")
  279. local time2 = meta:get_float("time2")
  280. local maxtime = meta:get_int("maxtime")
  281. local maxtime2 = ENERGY_TIME
  282. local eups = meta:get_int("eups")
  283. local fuel_percent = 0
  284. local item_percent = 0
  285. local need_discharge = false
  286. -- This sets infotext, so must always call this.
  287. local bad = check_environment(pos, meta)
  288. if v.name == "active" then
  289. if bad ~= nil then
  290. if bad then
  291. meta:set_int("bad", 1)
  292. siren_danger(pos, meta)
  293. else
  294. if meta:get_int("bad") == 1 then
  295. siren_clear(pos, meta)
  296. end
  297. meta:set_int("bad", 0)
  298. end
  299. end
  300. -- Damage breeder over time if bad.
  301. if meta:get_int("bad") == 1 then
  302. local damage = meta:get_int("damage")
  303. damage = damage + 1
  304. meta:set_int("damage", damage)
  305. -- Destroy breeder after 10 minutes of continous damage.
  306. if damage > 60*10 then
  307. func.breeder_destroy(pos)
  308. return
  309. end
  310. else
  311. -- Slowly decrease damage if not bad.
  312. local damage = meta:get_int("damage")
  313. if damage > 0 then
  314. damage = damage - 1
  315. meta:set_int("damage", damage)
  316. end
  317. end
  318. else
  319. -- Slowly decrease damage when inactive.
  320. local damage = meta:get_int("damage")
  321. if damage > 0 then
  322. damage = damage - 1
  323. meta:set_int("damage", damage)
  324. end
  325. end
  326. -- Radiation damage to nearby players.
  327. if v.name == "active" then
  328. local entities = minetest.get_objects_inside_radius(pos, 3.5)
  329. for k, v in ipairs(entities) do
  330. if v:is_player() then
  331. v:set_hp(v:get_hp() - 1)
  332. -- Radiation exhausts player.
  333. sprint.set_stamina(v, 0)
  334. end
  335. end
  336. end
  337. do
  338. local stack = inv:get_stack("out", 1)
  339. --minetest.chat_send_player("nhryciw1", "# Server: " .. stack:get_count() .. " charge!")
  340. if stack:get_count() >= BUFFER_SIZE then
  341. need_discharge = true
  342. end
  343. end
  344. -- Manage fuel.
  345. if time > 0 then
  346. -- Keep burning current fuel item.
  347. time = time - 1
  348. -- Restart timer.
  349. keeprunning = true
  350. -- Generate energy.
  351. time2 = time2 + 1
  352. if time2 >= maxtime2 then
  353. if not need_discharge then
  354. local energy = "atomic:energy " .. eups
  355. if inv:room_for_item("out", energy) then
  356. inv:add_item("out", energy)
  357. else
  358. -- No room? Huh. Discharge breeder!
  359. -- Note: this can happen because charge to be added would be
  360. -- greater than stack_max. This bug was actually observed.
  361. -- It is only likely to affect high-output machines.
  362. need_discharge = true
  363. end
  364. end
  365. time2 = 0
  366. end
  367. else
  368. -- Burntime has run out, get new fuel item.
  369. if fuellist[1]:get_count() > 0 and not need_discharge then
  370. local fuel, afterfuel
  371. local is_mese = false
  372. meta:set_int("eups", 0)
  373. -- Check if we have enough fuel.
  374. local rods = 0
  375. for i = 1, 6, 1 do
  376. local stack = inv:get_stack("fuel", i)
  377. if stack:get_name() == "thorium:rod" and stack:get_count() > 0 then
  378. rods = rods + 1
  379. end
  380. end
  381. -- Try to get fuel.
  382. fuel, afterfuel = minetest.get_craft_result({
  383. method="coalfuel", width=1, items=fuellist,
  384. })
  385. if rods == 6 then
  386. -- We got uranium rods, consume them.
  387. for i = 1, 6, 1 do
  388. inv:set_stack("fuel", i, ItemStack(""))
  389. end
  390. time = TOTAL_COOK_TIME
  391. meta:set_int("maxtime", TOTAL_COOK_TIME)
  392. machines.swap_node(pos, "breeder:active")
  393. fuel_percent = 100
  394. keeprunning = true -- Restart timer.
  395. meta:set_int("eups", ENERGY_AMOUNT)
  396. else
  397. -- No valid fuel in fuel slot.
  398. machines.swap_node(pos, "breeder:inactive")
  399. --minetest.get_node_timer(pos):stop()
  400. time2 = 0
  401. end
  402. else
  403. -- No more fuel, shutdown generator.
  404. machines.swap_node(pos, "breeder:inactive")
  405. --minetest.get_node_timer(pos):stop()
  406. meta:set_int("eups", 0)
  407. time2 = 0
  408. end
  409. end
  410. -- Discharge energy into the network.
  411. if need_discharge then
  412. --minetest.chat_send_player("nhryciw1", "# Server: Discharging breeder reactor!")
  413. local timer = meta:get_int("dschgtmr")
  414. -- It's frequently the case that a reactor spends a lot of time trying to
  415. -- send energy to a network where all the batteries are full. We can save
  416. -- the server some work by delaying a little before the next discharge, if
  417. -- the last discharge didn't succeed.
  418. if timer <= 0 then
  419. local energy = inv:get_stack("out", 1)
  420. local old = energy:get_count()
  421. energy:set_count(net2.put_energy(pos, owner, old, BREEDER_TIER))
  422. inv:set_stack("out", 1, energy)
  423. if energy:get_count() < old then
  424. -- If we succeeded in discharging energy, keep doing so.
  425. -- Otherwise, batteries are full.
  426. keeprunning = true
  427. else
  428. meta:set_int("dschgtmr", 60)
  429. end
  430. else
  431. timer = timer - 1
  432. meta:set_int("dschgtmr", timer)
  433. end
  434. end
  435. -- If generator is no longer producing energy,
  436. -- unload the buffered energy.
  437. if not keeprunning then
  438. local energy = inv:get_stack("out", 1)
  439. energy:set_count(net2.put_energy(pos, owner, energy:get_count(), BREEDER_TIER))
  440. inv:set_stack("out", 1, energy)
  441. end
  442. -- Update infotext & formspec.
  443. meta:set_int("time", time)
  444. meta:set_float("time2", time2)
  445. fuel_percent = math_floor(time / maxtime * 100)
  446. item_percent = math_floor(time2 / maxtime2 * 100)
  447. meta:set_string("infotext", func.compose_infotext(pos, keeprunning))
  448. meta:set_string("formspec", func.compose_formspec(fuel_percent, item_percent))
  449. -- Determine mode (active or sleep) and set timer accordingly.
  450. if keeprunning then
  451. minetest.get_node_timer(pos):start(1.0)
  452. else
  453. -- Slow down timer during sleep periods to reduce load.
  454. minetest.get_node_timer(pos):start(math_random(1, 3*60))
  455. end
  456. end
  457. --minetest.chat_send_all("breeder.on_timer registered")
  458. func.on_blast =
  459. function(pos)
  460. local drops = {}
  461. -- Ignore contents of fuel inventory.
  462. minetest.remove_node(pos)
  463. if v.name == "active" then
  464. func.breeder_destroy(pos)
  465. else
  466. -- Only save breeder if it wasn't active.
  467. drops[#drops+1] = "breeder:inactive"
  468. end
  469. return drops
  470. end
  471. --minetest.chat_send_all("breeder.on_blast registered")
  472. func.on_construct =
  473. function(pos)
  474. local meta = minetest.get_meta(pos)
  475. local inv = meta:get_inventory()
  476. meta:set_string("infotext", func.compose_infotext(pos, false))
  477. meta:set_string("formspec", func.compose_formspec(0, 0))
  478. --minetest.chat_send_player("nhryciw1", "Breeder reactor constructed!")
  479. inv:set_size("fuel", 6)
  480. inv:set_size("out", 1)
  481. meta:set_string("owner", "DUMMY")
  482. meta:set_string("error", "DUMMY")
  483. meta:set_string("nodename", "DUMMY")
  484. meta:set_int("siren", 0)
  485. meta:set_int("chktmr", 0)
  486. meta:set_int("eups", 0)
  487. meta:set_int("damage", 0)
  488. meta:set_int("time", 0)
  489. meta:set_int("maxtime", 0)
  490. meta:set_int("bad", 0)
  491. meta:set_float("time2", 0.0)
  492. func.privatize(meta)
  493. end
  494. --minetest.chat_send_all("breeder.on_construct registered")
  495. func.privatize =
  496. function(meta)
  497. meta:mark_as_private({
  498. "nodename", "bad", "time2", "maxtime", "siren", "owner",
  499. "chktmr", "error", "eups", "damage", "time", "dschgtmr",
  500. })
  501. end
  502. func.on_destruct =
  503. function(pos)
  504. local meta = minetest.get_meta(pos)
  505. siren_set_state(pos, SS_OFF)
  506. net2.clear_caches(pos, meta:get_string("owner"), BREEDER_TIER)
  507. nodestore.del_node(pos)
  508. if v.name == "active" then
  509. func.breeder_destroy(pos)
  510. end
  511. end
  512. func.after_place_node =
  513. function(pos, placer, itemstack, pointed_thing)
  514. local meta = minetest.get_meta(pos)
  515. local node = minetest.get_node(pos)
  516. local owner = placer:get_player_name()
  517. meta:set_string("nodename", node.name)
  518. meta:set_string("owner", owner)
  519. net2.clear_caches(pos, owner, BREEDER_TIER)
  520. nodestore.add_node(pos)
  521. end
  522. func.on_metadata_inventory_move =
  523. function(pos)
  524. func.trigger_update(pos)
  525. end
  526. func.on_metadata_inventory_put =
  527. function(pos)
  528. func.trigger_update(pos)
  529. end
  530. func.on_metadata_inventory_take =
  531. function(pos, listname, index, stack, player)
  532. func.trigger_update(pos)
  533. end
  534. end
  535. --i cannot for the life of me figure out why the normal reactor works without this, but it does.
  536. --breeder.run_once = false
  537. --
  538. -- ^^^ This could only break if some code used the wrong table name left over
  539. -- from copy+paste. Anyway it works now. -- MustTest
  540. if not breeder.run_once then
  541. for k, v in ipairs({
  542. {name="inactive", light=0},
  543. {name="active", light=14},
  544. }) do
  545. -- Which function table are we operating on?
  546. local func = _G["breeder_" .. v.name]
  547. minetest.register_node(":breeder:" .. v.name, {
  548. description = "Thorium Breeder Reactor Core\n\nConnects to an MV power-network.\nGenerates a large amount of power.\nExplosion danger, requires shielding!",
  549. tiles = {"reactor_core.png"},
  550. groups = utility.dig_groups("machine", {immovable=1}),
  551. paramtype2 = "facedir",
  552. is_ground_content = false,
  553. sounds = default.node_sound_metal_defaults(),
  554. drop = "breeder:inactive",
  555. light_source = v.light,
  556. on_energy_get = function(...)
  557. return breeder.on_energy_get(...) end,
  558. on_rotate = function(...)
  559. return screwdriver.rotate_simple(...) end,
  560. on_punch = function(...)
  561. return func.on_punch(...) end,
  562. can_dig = function(...)
  563. return func.can_dig(...) end,
  564. on_timer = function(...)
  565. return func.on_timer(...) end,
  566. on_construct = function(...)
  567. return func.on_construct(...) end,
  568. on_destruct = function(...)
  569. return func.on_destruct(...) end,
  570. after_place_node = function(...)
  571. return func.after_place_node(...) end,
  572. on_blast = function(...)
  573. return func.on_blast(...) end,
  574. on_metadata_inventory_move = function(...)
  575. return func.on_metadata_inventory_move(...) end,
  576. on_metadata_inventory_put = function(...)
  577. return func.on_metadata_inventory_put(...) end,
  578. on_metadata_inventory_take = function(...)
  579. return func.on_metadata_inventory_take(...) end,
  580. allow_metadata_inventory_put = function(...)
  581. return func.allow_metadata_inventory_put(...) end,
  582. allow_metadata_inventory_move = function(...)
  583. return func.allow_metadata_inventory_move(...) end,
  584. allow_metadata_inventory_take = function(...)
  585. return func.allow_metadata_inventory_take(...) end,
  586. })
  587. end
  588. --minetest.chat_send_all("node registered")
  589. minetest.register_craft({
  590. output = 'breeder:inactive',
  591. recipe = {
  592. {'techcrafts:carbon_plate', 'default:obsidian_glass', 'techcrafts:carbon_plate'},
  593. {'techcrafts:composite_plate', 'gen2:mv_inactive', 'techcrafts:composite_plate'},
  594. {'stainless_steel:ingot', 'geo2:lv_inactive', 'stainless_steel:ingot'},
  595. }
  596. })
  597. local c = "breeder:core"
  598. local f = machines.modpath .. "/breeder.lua"
  599. reload.register_file(c, f, false)
  600. breeder.run_once = true
  601. end