generator.lua 15 KB

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