generator.lua 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545
  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. 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. machines.swap_node(pos, "gen2:" .. v.tier .. "_active")
  261. fuel_percent = 100
  262. keeprunning = true -- Restart timer.
  263. if is_mese then
  264. meta:set_int("eups", math_floor(v.mese))
  265. else
  266. meta:set_int("eups", v.eups)
  267. end
  268. else
  269. -- No valid fuel in fuel slot.
  270. machines.swap_node(pos, "gen2:" .. v.tier .. "_inactive")
  271. --minetest.get_node_timer(pos):stop()
  272. time2 = 0
  273. end
  274. else
  275. -- No more fuel, shutdown generator.
  276. machines.swap_node(pos, "gen2:" .. v.tier .. "_inactive")
  277. --minetest.get_node_timer(pos):stop()
  278. meta:set_int("eups", 0)
  279. time2 = 0
  280. end
  281. end
  282. -- Discharge energy into the network.
  283. if need_discharge then
  284. local energy = inv:get_stack("out", 1)
  285. local old = energy:get_count()
  286. energy:set_count(net2.put_energy(pos, owner, old, v.tier))
  287. inv:set_stack("out", 1, energy)
  288. if energy:get_count() < old then
  289. -- If we succeeded in discharging energy, keep doing so.
  290. -- Otherwise, batteries are full.
  291. keeprunning = true
  292. end
  293. end
  294. -- If generator is no longer producing energy,
  295. -- unload the buffered energy.
  296. if not keeprunning then
  297. local energy = inv:get_stack("out", 1)
  298. energy:set_count(net2.put_energy(pos, owner, energy:get_count(), v.tier))
  299. inv:set_stack("out", 1, energy)
  300. end
  301. -- Update infotext & formspec.
  302. meta:set_float("time", time)
  303. meta:set_float("time2", time2)
  304. fuel_percent = math_floor(time / maxtime * 100)
  305. item_percent = math_floor(time2 / maxtime2 * 100)
  306. meta:set_string("infotext", func.compose_infotext(pos, keeprunning))
  307. meta:set_string("formspec", func.compose_formspec(fuel_percent, item_percent))
  308. -- Determine mode (active or sleep) and set timer accordingly.
  309. if keeprunning then
  310. minetest.get_node_timer(pos):start(1.0)
  311. else
  312. -- Slow down timer during sleep periods to reduce load.
  313. minetest.get_node_timer(pos):start(math_random(1, 3*60))
  314. end
  315. end
  316. func.on_blast =
  317. function(pos)
  318. local drops = {}
  319. default.get_inventory_drops(pos, "fuel", drops)
  320. drops[#drops+1] = "gen2:" .. v.tier .. "_inactive"
  321. minetest.remove_node(pos)
  322. return drops
  323. end
  324. func.on_construct =
  325. function(pos)
  326. local meta = minetest.get_meta(pos)
  327. local inv = meta:get_inventory()
  328. meta:set_string("infotext", func.compose_infotext(pos, false))
  329. meta:set_string("formspec", func.compose_formspec(0, 0))
  330. inv:set_size("fuel", 1)
  331. inv:set_size("out", 1)
  332. -- MV and HV generators have upgrade slots.
  333. if v.tier == "mv" or v.tier == "hv" then
  334. inv:set_size("upg", 2)
  335. end
  336. end
  337. func.on_destruct =
  338. function(pos)
  339. local meta = minetest.get_meta(pos)
  340. net2.clear_caches(pos, meta:get_string("owner"), v.tier)
  341. nodestore.del_node(pos)
  342. end
  343. func.after_place_node =
  344. function(pos, placer, itemstack, pointed_thing)
  345. local meta = minetest.get_meta(pos)
  346. local node = minetest.get_node(pos)
  347. local owner = placer:get_player_name()
  348. meta:set_string("nodename", node.name)
  349. meta:set_string("owner", owner)
  350. net2.clear_caches(pos, owner, v.tier)
  351. nodestore.add_node(pos)
  352. end
  353. func.on_metadata_inventory_move =
  354. function(pos)
  355. end
  356. func.on_metadata_inventory_put =
  357. function(pos)
  358. end
  359. func.on_metadata_inventory_take =
  360. function(pos, listname, index, stack, player)
  361. end
  362. func.burn_feet = function(pos, player)
  363. if not heatdamage.is_immune(player:get_player_name()) then
  364. player:set_hp(player:get_hp() - 1)
  365. end
  366. end
  367. end
  368. if not generator.gen2_loaded then
  369. -- Register active & inactive generator nodes.
  370. -- Generates atomic energy from coal.
  371. for m, n in ipairs({
  372. {tier="lv", up="LV"},
  373. {tier="mv", up="MV"},
  374. {tier="hv", up="HV"},
  375. }) do
  376. for k, v in ipairs({
  377. {name="inactive", tile="generator_" .. n.tier .. "_front.png", light=0},
  378. {name="active", tile="generator_" .. n.tier .. "_front_active.png", light=8},
  379. }) do
  380. -- Which function table are we operating on?
  381. local func = _G["gen2_" .. n.tier]
  382. local feet_burning_func = nil
  383. if v.name == "active" then
  384. feet_burning_func = function(...)
  385. return func.burn_feet(...)
  386. end
  387. end
  388. minetest.register_node(":gen2:" .. n.tier .. "_" .. v.name, {
  389. description = n.up .. " Fuel-Activated Generator\n\nCan burn coal, kalite or mese and convert it to energy.",
  390. tiles = {
  391. "generator_" .. n.tier .. "_top.png", "generator_" .. n.tier .. "_bottom.png",
  392. "generator_" .. n.tier .. "_side.png", "generator_" .. n.tier .. "_side.png",
  393. "generator_" .. n.tier .. "_side.png", v.tile,
  394. },
  395. groups = utility.dig_groups("machine"),
  396. paramtype2 = "facedir",
  397. is_ground_content = false,
  398. sounds = default.node_sound_metal_defaults(),
  399. drop = "gen2:" .. n.tier .. "_inactive",
  400. light_source = v.light,
  401. on_energy_get = function(...)
  402. return func.on_energy_get(...) end,
  403. on_rotate = function(...)
  404. return screwdriver.rotate_simple(...) end,
  405. on_punch = function(...)
  406. return func.on_punch(...) end,
  407. can_dig = function(...)
  408. return func.can_dig(...) end,
  409. on_timer = function(...)
  410. return func.on_timer(...) end,
  411. on_construct = function(...)
  412. return func.on_construct(...) end,
  413. on_destruct = function(...)
  414. return func.on_destruct(...) end,
  415. after_place_node = function(...)
  416. return func.after_place_node(...) end,
  417. on_blast = function(...)
  418. return func.on_blast(...) end,
  419. on_metadata_inventory_move = function(...)
  420. return func.on_metadata_inventory_move(...) end,
  421. on_metadata_inventory_put = function(...)
  422. return func.on_metadata_inventory_put(...) end,
  423. on_metadata_inventory_take = function(...)
  424. return func.on_metadata_inventory_take(...) end,
  425. allow_metadata_inventory_put = function(...)
  426. return func.allow_metadata_inventory_put(...) end,
  427. allow_metadata_inventory_move = function(...)
  428. return func.allow_metadata_inventory_move(...) end,
  429. allow_metadata_inventory_take = function(...)
  430. return func.allow_metadata_inventory_take(...) end,
  431. on_player_walk_over = feet_burning_func,
  432. })
  433. end
  434. end
  435. local c = "gen2:core"
  436. local f = generator.modpath .. "/generator.lua"
  437. reload.register_file(c, f, false)
  438. generator.gen2_loaded = true
  439. end