generator.lua 15 KB

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