generator.lua 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549
  1. -- Functions for the generator nodes.
  2. if not minetest.global_exists("gen2") then gen2 = {} end
  3. if not minetest.global_exists("gen2_lv") then gen2_lv = {} end
  4. if not minetest.global_exists("gen2_mv") then gen2_mv = {} end
  5. if not minetest.global_exists("gen2_hv") then gen2_hv = {} end
  6. -- Localize for performance.
  7. local math_floor = math.floor
  8. local math_random = math.random
  9. for k, v in ipairs({
  10. {tier="lv", up="LV", eups=tech.generator_lv.power, bt=tech.generator_lv.time, buf=tech.generator_lv.buffer, mese=tech.generator_lv.mesepower},
  11. {tier="mv", up="MV", eups=tech.generator_mv.power, bt=tech.generator_mv.time, buf=tech.generator_mv.buffer, mese=tech.generator_mv.mesepower},
  12. {tier="hv", up="HV", eups=tech.generator_hv.power, bt=tech.generator_hv.time, buf=tech.generator_hv.buffer, mese=tech.generator_hv.mesepower},
  13. }) do
  14. -- Which function table are we operating on?
  15. local func = _G["gen2_" .. v.tier]
  16. func.trigger_update =
  17. function(pos)
  18. local timer = minetest.get_node_timer(pos)
  19. -- Restart timer even if already running.
  20. timer:start(1.0)
  21. end
  22. func.on_energy_get =
  23. function(pos, energy)
  24. local meta = minetest.get_meta(pos)
  25. local inv = meta:get_inventory()
  26. local have = inv:get_stack("out", 1):get_count()
  27. if have < energy then
  28. inv:set_stack("out", 1, ItemStack(""))
  29. func.trigger_update(pos)
  30. return have
  31. end
  32. have = have - energy
  33. inv:set_stack("out", 1, ItemStack("atomic:energy " .. have))
  34. func.trigger_update(pos)
  35. return energy
  36. end
  37. func.on_punch =
  38. function(pos, node, puncher, pointed_thing)
  39. func.trigger_update(pos)
  40. -- Upgrade old machines.
  41. if v.tier == "mv" or v.tier == "hv" then
  42. local meta = minetest.get_meta(pos)
  43. local inv = meta:get_inventory()
  44. inv:set_size("upg", 2)
  45. end
  46. end
  47. func.compose_formspec =
  48. function(fuel_percent, item_percent)
  49. local formspec
  50. if v.tier == "lv" then
  51. -- Formspec without upgrade slots.
  52. formspec =
  53. "size[8,8.5]" ..
  54. default.formspec.get_form_colors() ..
  55. default.formspec.get_form_image() ..
  56. default.formspec.get_slot_colors() ..
  57. "label[2,0.5;Fuel Supply]" ..
  58. "list[context;fuel;2,1;1,1;]" ..
  59. utility.progress_image(3, 1, "default_furnace_fire_bg.png", "default_furnace_fire_fg.png", fuel_percent) ..
  60. utility.progress_image(4, 1, "gui_furnace_arrow_bg.png", "gui_furnace_arrow_fg.png", item_percent, "^[transformR270") ..
  61. "label[5,0.5;Charge Buffer]" ..
  62. "list[context;out;5,1;1,1;]" ..
  63. "list[current_player;main;0,4.25;8,1;]" ..
  64. "list[current_player;main;0,5.5;8,3;8]" ..
  65. "listring[context;fuel]" ..
  66. "listring[current_player;main]" ..
  67. default.get_hotbar_bg(0, 4.25)
  68. else
  69. -- Formspec *with* upgrade slots.
  70. formspec =
  71. "size[8,8.5]" ..
  72. default.formspec.get_form_colors() ..
  73. default.formspec.get_form_image() ..
  74. default.formspec.get_slot_colors() ..
  75. "label[1,0.5;Upgrades]" ..
  76. "list[context;upg;1,1;1,2;]" ..
  77. "label[3,0.5;Fuel Supply]" ..
  78. "list[context;fuel;3,1;1,1;]" ..
  79. utility.progress_image(4, 1, "default_furnace_fire_bg.png", "default_furnace_fire_fg.png", fuel_percent) ..
  80. utility.progress_image(5, 1, "gui_furnace_arrow_bg.png", "gui_furnace_arrow_fg.png", item_percent, "^[transformR270") ..
  81. "label[6,0.5;Charge Buffer]" ..
  82. "list[context;out;6,1;1,1;]" ..
  83. "list[current_player;main;0,4.25;8,1;]" ..
  84. "list[current_player;main;0,5.5;8,3;8]" ..
  85. "listring[context;fuel]" ..
  86. "listring[current_player;main]" ..
  87. default.get_hotbar_bg(0, 4.25)
  88. end
  89. return formspec
  90. end
  91. func.compose_infotext =
  92. function(pos, keeprunning)
  93. local meta = minetest.get_meta(pos)
  94. local eups = meta:get_int("eups")
  95. local machine_state = "Standby"
  96. if keeprunning then machine_state = "Active" end
  97. local output = math_floor(eups / v.bt)
  98. if not keeprunning then
  99. output = 0
  100. end
  101. local infotext = v.up .. " Fuel Generator (" .. machine_state .. ")\n" ..
  102. "Output: " .. output .. " EU Per/Sec"
  103. return infotext
  104. end
  105. func.can_dig =
  106. function(pos, player)
  107. local meta = minetest.get_meta(pos)
  108. local inv = meta:get_inventory()
  109. -- The energy output inventory does not count.
  110. return inv:is_empty("fuel") and inv:is_empty("upg")
  111. end
  112. func.has_public_access =
  113. function(pos)
  114. if v.tier == "lv" then
  115. return
  116. end
  117. local meta = minetest.get_meta(pos)
  118. local inv = meta:get_inventory()
  119. local s1 = inv:get_stack("upg", 1)
  120. if s1 and s1:get_count() > 0 then
  121. if minetest.get_item_group(s1:get_name(), "chest") > 0 then
  122. return true
  123. end
  124. end
  125. local s2 = inv:get_stack("upg", 2)
  126. if s2 and s2:get_count() > 0 then
  127. if minetest.get_item_group(s2:get_name(), "chest") > 0 then
  128. return true
  129. end
  130. end
  131. end
  132. func.allow_metadata_inventory_put =
  133. function(pos, listname, index, stack, player)
  134. local pname = player:get_player_name()
  135. local public = func.has_public_access(pos)
  136. local protected = false
  137. if minetest.test_protection(pos, pname) then
  138. protected = true
  139. end
  140. if listname == "fuel" and (not protected or public) then
  141. if minetest.get_craft_result({method="coalfuel", width=1, items={stack}}).time ~= 0 then
  142. func.trigger_update(pos)
  143. return stack:get_count()
  144. end
  145. if minetest.get_craft_result({method="mesefuel", width=1, items={stack}}).time ~= 0 then
  146. func.trigger_update(pos)
  147. return stack:get_count()
  148. end
  149. elseif listname == "upg" and not protected and (v.tier == "mv" or v.tier == "hv") then
  150. if minetest.get_item_group(stack:get_name(), "chest") > 0 then
  151. return stack:get_count()
  152. elseif stack:get_name() == "battery:battery" then
  153. return stack:get_count()
  154. elseif stack:get_name() == "techcrafts:control_logic_unit" then
  155. return stack:get_count()
  156. end
  157. end
  158. return 0
  159. end
  160. func.allow_metadata_inventory_move =
  161. function(pos, from_list, from_index, to_list, to_index, count, player)
  162. local pname = player:get_player_name()
  163. local public = func.has_public_access(pos)
  164. local protected = false
  165. if minetest.test_protection(pos, pname) then
  166. protected = true
  167. end
  168. if (from_list == "upg" or to_list == "upg") and protected and (v.tier == "mv" or v.tier == "hv") then
  169. -- Don't permit public users to mess with the upgrades.
  170. return 0
  171. end
  172. if not protected or public then
  173. -- Can't touch the output energy buffer.
  174. if from_list == "out" or to_list == "out" then
  175. return 0
  176. end
  177. if from_list == to_list then
  178. return count
  179. end
  180. end
  181. return 0
  182. end
  183. func.allow_metadata_inventory_take =
  184. function(pos, listname, index, stack, player)
  185. local pname = player:get_player_name()
  186. local public = func.has_public_access(pos)
  187. local protected = false
  188. if minetest.test_protection(pos, pname) then
  189. protected = true
  190. end
  191. if listname == "fuel" and (not protected or public) then
  192. func.trigger_update(pos)
  193. return stack:get_count()
  194. elseif listname == "upg" and not protected and (v.tier == "mv" or v.tier == "hv") then
  195. func.trigger_update(pos)
  196. return stack:get_count()
  197. end
  198. return 0
  199. end
  200. func.on_timer =
  201. function(pos, elapsed)
  202. --minetest.chat_send_all("# Server: On Timer! " .. minetest.get_gametime())
  203. local keeprunning = false
  204. local meta = minetest.get_meta(pos)
  205. local owner = meta:get_string("owner")
  206. local inv = meta:get_inventory()
  207. local fuellist = inv:get_list("fuel")
  208. local time = meta:get_float("time")
  209. local time2 = meta:get_float("time2")
  210. local maxtime = meta:get_float("maxtime")
  211. local maxtime2 = v.bt
  212. local eups = meta:get_int("eups")
  213. local fuel_percent = 0
  214. local item_percent = 0
  215. local need_discharge = false
  216. do
  217. local stack = inv:get_stack("out", 1)
  218. if stack:get_count() >= v.buf then
  219. need_discharge = true
  220. end
  221. end
  222. -- Manage fuel.
  223. if time > 0 then
  224. -- Keep burning current fuel item.
  225. time = time - 1
  226. -- Restart timer.
  227. keeprunning = true
  228. -- Generate energy.
  229. time2 = time2 + 1
  230. if time2 >= maxtime2 then
  231. if not need_discharge then
  232. local energy = "atomic:energy " .. eups
  233. if inv:room_for_item("out", energy) then
  234. inv:add_item("out", energy)
  235. end
  236. end
  237. time2 = 0
  238. end
  239. else
  240. -- Burntime has run out, get new fuel item.
  241. if fuellist[1]:get_count() > 0 and not need_discharge then
  242. local fuel, afterfuel
  243. local is_mese = false
  244. meta:set_int("eups", 0)
  245. -- Try to get fuel.
  246. fuel, afterfuel = minetest.get_craft_result({
  247. method="coalfuel", width=1, items=fuellist,
  248. })
  249. if fuel.time == 0 then
  250. fuel, afterfuel = minetest.get_craft_result({
  251. method="mesefuel", width=1, items=fuellist,
  252. })
  253. is_mese = true
  254. end
  255. if fuel.time > 0 then
  256. -- We got a valid fuel item, consume it.
  257. inv:set_stack("fuel", 1, afterfuel.items[1])
  258. time = fuel.time
  259. meta:set_float("maxtime", fuel.time)
  260. local swapped = machines.swap_node(pos, "gen2:" .. v.tier .. "_active")
  261. fuel_percent = 100
  262. keeprunning = true -- Restart timer.
  263. if swapped then
  264. ambiance.spawn_sound_beacon("ambiance:furnace_active", pos)
  265. end
  266. if is_mese then
  267. meta:set_int("eups", math_floor(v.mese))
  268. else
  269. meta:set_int("eups", v.eups)
  270. end
  271. else
  272. -- No valid fuel in fuel slot.
  273. machines.swap_node(pos, "gen2:" .. v.tier .. "_inactive")
  274. --minetest.get_node_timer(pos):stop()
  275. time2 = 0
  276. end
  277. else
  278. -- No more fuel, shutdown generator.
  279. machines.swap_node(pos, "gen2:" .. v.tier .. "_inactive")
  280. --minetest.get_node_timer(pos):stop()
  281. meta:set_int("eups", 0)
  282. time2 = 0
  283. end
  284. end
  285. -- Discharge energy into the network.
  286. if need_discharge then
  287. local energy = inv:get_stack("out", 1)
  288. local old = energy:get_count()
  289. energy:set_count(net2.put_energy(pos, owner, old, v.tier))
  290. inv:set_stack("out", 1, energy)
  291. if energy:get_count() < old then
  292. -- If we succeeded in discharging energy, keep doing so.
  293. -- Otherwise, batteries are full.
  294. keeprunning = true
  295. end
  296. end
  297. -- If generator is no longer producing energy,
  298. -- unload the buffered energy.
  299. if not keeprunning then
  300. local energy = inv:get_stack("out", 1)
  301. energy:set_count(net2.put_energy(pos, owner, energy:get_count(), v.tier))
  302. inv:set_stack("out", 1, energy)
  303. end
  304. -- Update infotext & formspec.
  305. meta:set_float("time", time)
  306. meta:set_float("time2", time2)
  307. fuel_percent = math_floor(time / maxtime * 100)
  308. item_percent = math_floor(time2 / maxtime2 * 100)
  309. meta:set_string("infotext", func.compose_infotext(pos, keeprunning))
  310. meta:set_string("formspec", func.compose_formspec(fuel_percent, item_percent))
  311. -- Determine mode (active or sleep) and set timer accordingly.
  312. if keeprunning then
  313. minetest.get_node_timer(pos):start(1.0)
  314. else
  315. -- Slow down timer during sleep periods to reduce load.
  316. minetest.get_node_timer(pos):start(math_random(1, 3*60))
  317. end
  318. end
  319. func.on_blast =
  320. function(pos)
  321. local drops = {}
  322. default.get_inventory_drops(pos, "fuel", drops)
  323. drops[#drops+1] = "gen2:" .. v.tier .. "_inactive"
  324. minetest.remove_node(pos)
  325. return drops
  326. end
  327. func.on_construct =
  328. function(pos)
  329. local meta = minetest.get_meta(pos)
  330. local inv = meta:get_inventory()
  331. meta:set_string("infotext", func.compose_infotext(pos, false))
  332. meta:set_string("formspec", func.compose_formspec(0, 0))
  333. inv:set_size("fuel", 1)
  334. inv:set_size("out", 1)
  335. -- MV and HV generators have upgrade slots.
  336. if v.tier == "mv" or v.tier == "hv" then
  337. inv:set_size("upg", 2)
  338. end
  339. end
  340. func.on_destruct =
  341. function(pos)
  342. local meta = minetest.get_meta(pos)
  343. net2.clear_caches(pos, meta:get_string("owner"), v.tier)
  344. nodestore.del_node(pos)
  345. end
  346. func.after_place_node =
  347. function(pos, placer, itemstack, pointed_thing)
  348. local meta = minetest.get_meta(pos)
  349. local node = minetest.get_node(pos)
  350. local owner = placer:get_player_name()
  351. meta:set_string("nodename", node.name)
  352. meta:set_string("owner", owner)
  353. net2.clear_caches(pos, owner, v.tier)
  354. nodestore.add_node(pos)
  355. end
  356. func.on_metadata_inventory_move =
  357. function(pos)
  358. end
  359. func.on_metadata_inventory_put =
  360. function(pos)
  361. end
  362. func.on_metadata_inventory_take =
  363. function(pos, listname, index, stack, player)
  364. end
  365. func.burn_feet = function(pos, player)
  366. if not heatdamage.is_immune(player:get_player_name()) then
  367. utility.damage_player(player, "heat", 1*500)
  368. end
  369. end
  370. end
  371. if not generator.gen2_loaded then
  372. -- Register active & inactive generator nodes.
  373. -- Generates atomic energy from coal.
  374. for m, n in ipairs({
  375. {tier="lv", up="LV"},
  376. {tier="mv", up="MV"},
  377. {tier="hv", up="HV"},
  378. }) do
  379. for k, v in ipairs({
  380. {name="inactive", tile="generator_" .. n.tier .. "_front.png", light=0},
  381. {name="active", tile="generator_" .. n.tier .. "_front_active.png", light=8},
  382. }) do
  383. -- Which function table are we operating on?
  384. local func = _G["gen2_" .. n.tier]
  385. local feet_burning_func = nil
  386. if v.name == "active" then
  387. feet_burning_func = function(...)
  388. return func.burn_feet(...)
  389. end
  390. end
  391. minetest.register_node(":gen2:" .. n.tier .. "_" .. v.name, {
  392. description = n.up .. " Fuel-Activated Generator\n\nCan burn coal, kalite or mese and convert it to energy.",
  393. tiles = {
  394. "generator_" .. n.tier .. "_top.png", "generator_" .. n.tier .. "_bottom.png",
  395. "generator_" .. n.tier .. "_side.png", "generator_" .. n.tier .. "_side.png",
  396. "generator_" .. n.tier .. "_side.png", v.tile,
  397. },
  398. groups = utility.dig_groups("machine"),
  399. paramtype2 = "facedir",
  400. is_ground_content = false,
  401. sounds = default.node_sound_metal_defaults(),
  402. drop = "gen2:" .. n.tier .. "_inactive",
  403. light_source = v.light,
  404. on_energy_get = function(...)
  405. return func.on_energy_get(...) end,
  406. on_rotate = function(...)
  407. return screwdriver.rotate_simple(...) end,
  408. on_punch = function(...)
  409. return func.on_punch(...) end,
  410. can_dig = function(...)
  411. return func.can_dig(...) end,
  412. on_timer = function(...)
  413. return func.on_timer(...) end,
  414. on_construct = function(...)
  415. return func.on_construct(...) end,
  416. on_destruct = function(...)
  417. return func.on_destruct(...) end,
  418. after_place_node = function(...)
  419. return func.after_place_node(...) end,
  420. on_blast = function(...)
  421. return func.on_blast(...) end,
  422. on_metadata_inventory_move = function(...)
  423. return func.on_metadata_inventory_move(...) end,
  424. on_metadata_inventory_put = function(...)
  425. return func.on_metadata_inventory_put(...) end,
  426. on_metadata_inventory_take = function(...)
  427. return func.on_metadata_inventory_take(...) end,
  428. allow_metadata_inventory_put = function(...)
  429. return func.allow_metadata_inventory_put(...) end,
  430. allow_metadata_inventory_move = function(...)
  431. return func.allow_metadata_inventory_move(...) end,
  432. allow_metadata_inventory_take = function(...)
  433. return func.allow_metadata_inventory_take(...) end,
  434. on_player_walk_over = feet_burning_func,
  435. })
  436. end
  437. end
  438. local c = "gen2:core"
  439. local f = generator.modpath .. "/generator.lua"
  440. reload.register_file(c, f, false)
  441. generator.gen2_loaded = true
  442. end