bat2.lua 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416
  1. bat2 = bat2 or {}
  2. bat2_lv = bat2_lv or {}
  3. bat2_mv = bat2_mv or {}
  4. bat2_hv = bat2_hv or {}
  5. -- Localize for performance.
  6. local math_floor = math.floor
  7. for k, v in ipairs({
  8. {tier="lv", up="LV", name="LV", buffer=tech.battery_lv.buffer},
  9. {tier="mv", up="MV", name="MV", buffer=tech.battery_mv.buffer},
  10. {tier="hv", up="HV", name="HV", buffer=tech.battery_hv.buffer},
  11. }) do
  12. -- Which function table are we operating on?
  13. local functable = _G["bat2_" .. v.tier]
  14. functable.on_energy_put =
  15. function(pos, energy)
  16. --minetest.chat_send_all("# Server: Got " .. energy .. " energy!")
  17. local meta = minetest.get_meta(pos)
  18. local chg, max = functable.get_energy_status(meta)
  19. local canfit = max - chg
  20. local toput = energy
  21. if toput > canfit then
  22. toput = canfit
  23. end
  24. local total = chg + toput
  25. meta:set_int("energy", total)
  26. energy = energy - toput
  27. functable.trigger_update(pos)
  28. return energy
  29. end
  30. functable.on_energy_get =
  31. function(pos, energy)
  32. local meta = minetest.get_meta(pos)
  33. local have = meta:get_int("energy")
  34. if have < energy then
  35. meta:set_int("energy", 0)
  36. functable.trigger_update(pos)
  37. return have
  38. end
  39. have = have - energy
  40. meta:set_int("energy", have)
  41. functable.trigger_update(pos)
  42. return energy
  43. end
  44. functable.compose_infotext =
  45. function(pos)
  46. local meta = minetest.get_meta(pos)
  47. local inv = meta:get_inventory()
  48. local chg, max = functable.get_energy_status(meta)
  49. local size = inv:get_size("batteries")
  50. local cnt = functable.get_battery_count(inv)
  51. local infotext = v.up .. " Battery Array\n" ..
  52. "Internal Battery Units: " .. cnt .. "/" .. size .. "\n" ..
  53. "Energy: " .. chg .. "/" .. max .. " EUs\n"
  54. if max > 0 then
  55. local percent = math_floor(chg / max * 100)
  56. infotext = infotext .. "Charge: " .. percent .. "%"
  57. else
  58. infotext = infotext .. "Charge: 0%"
  59. end
  60. meta:set_string("infotext", infotext)
  61. end
  62. functable.compose_formspec =
  63. function(pos)
  64. local meta = minetest.get_meta(pos)
  65. local chg, max = functable.get_energy_status(meta)
  66. local charge_desc = v.name .. " Charge Status: " ..
  67. chg .. "/" .. max .. " EUs"
  68. local formspec =
  69. "size[8,8.5]" ..
  70. default.formspec.get_form_colors() ..
  71. default.formspec.get_form_image() ..
  72. default.formspec.get_slot_colors() ..
  73. "label[0,0;" .. minetest.formspec_escape(charge_desc) .. "]" ..
  74. "label[0,0.5;NRAIB (Non-Redundant Array of Independant Batteries)]" ..
  75. "item_image[7,0;1,1;battery:battery]" ..
  76. "list[context;batteries;0,1;8,2;]" ..
  77. "list[current_player;main;0,4.25;8,1;]" ..
  78. "list[current_player;main;0,5.5;8,3;8]" ..
  79. "listring[context;batteries]"..
  80. "listring[current_player;main]"..
  81. default.get_hotbar_bg(0, 4.25)
  82. meta:set_string("formspec", formspec)
  83. end
  84. functable.update_charge_visual =
  85. function(pos)
  86. local meta = minetest.get_meta(pos)
  87. local chg, max = functable.get_energy_status(meta)
  88. local name = "bat2:bt0_" .. v.tier
  89. if max > 0 then -- Avoid divide-by-zero.
  90. local percent = math_floor((chg / max) * 100)
  91. local sz = math.ceil(100 / 12)
  92. for i = 0, 12, 1 do
  93. if percent <= sz*i then
  94. name = "bat2:bt" .. i .. "_" .. v.tier
  95. break
  96. end
  97. end
  98. end
  99. machines.swap_node(pos, name)
  100. end
  101. functable.on_punch =
  102. function(pos, node, puncher, pointed_thing)
  103. functable.trigger_update(pos)
  104. functable.privatize(minetest.get_meta(pos))
  105. end
  106. functable.can_dig =
  107. function(pos, player)
  108. local meta = minetest.get_meta(pos)
  109. local inv = meta:get_inventory()
  110. return inv:is_empty("batteries")
  111. end
  112. functable.allow_metadata_inventory_put =
  113. function(pos, listname, index, stack, player)
  114. local NBATT = "battery:battery"
  115. local pname = player:get_player_name()
  116. if minetest.test_protection(pos, pname) then
  117. return 0
  118. end
  119. if stack:get_name() == NBATT then
  120. return stack:get_count()
  121. end
  122. return 0
  123. end
  124. functable.allow_metadata_inventory_move =
  125. function(pos, from_list, from_index, to_list, to_index, count, player)
  126. local meta = minetest.get_meta(pos)
  127. local inv = meta:get_inventory()
  128. local stack = inv:get_stack(from_list, from_index)
  129. return functable.allow_metadata_inventory_put(pos, to_list, to_index, stack, player)
  130. end
  131. functable.allow_metadata_inventory_take =
  132. function(pos, listname, index, stack, player)
  133. local pname = player:get_player_name()
  134. if minetest.test_protection(pos, pname) then
  135. return 0
  136. end
  137. return stack:get_count()
  138. end
  139. functable.get_battery_count =
  140. function(inv)
  141. local batteries = inv:get_list("batteries")
  142. local count = 0
  143. for k, v in ipairs(batteries) do
  144. if v:get_name() == "battery:battery" then
  145. -- Only 1 battery allowed per stack.
  146. count = count + 1
  147. end
  148. end
  149. return count
  150. end
  151. functable.update_maximum_charge =
  152. function(meta)
  153. local count = functable.get_battery_count(meta:get_inventory())
  154. local max
  155. if v.tier == "lv" then
  156. max = count * v.buffer
  157. elseif v.tier == "mv" then
  158. max = count * v.buffer
  159. elseif v.tier == "hv" then
  160. max = count * v.buffer
  161. end
  162. local chg = meta:get_int("energy")
  163. -- Ensure charge isn't over max. This can happen if user removed a battery.
  164. if chg > max then
  165. meta:set_int("energy", max)
  166. end
  167. meta:set_int("max", max)
  168. end
  169. functable.on_timer =
  170. function(pos, elapsed)
  171. local meta = minetest.get_meta(pos)
  172. local current_amount = meta:get_int("energy")
  173. local old_eu_amount = meta:get_int("old_eu")
  174. -- Todo: here, we can respond to changes in EU amount since last update.
  175. meta:set_int("old_eu", current_amount)
  176. -- Needed in case the operator removes or adds a battery.
  177. -- Also, EUs can be added/drained from batteries without going through a distributer.
  178. functable.update_maximum_charge(meta)
  179. functable.update_charge_visual(pos)
  180. functable.compose_infotext(pos)
  181. functable.compose_formspec(pos)
  182. end
  183. functable.on_blast =
  184. function(pos)
  185. local drops = {}
  186. default.get_inventory_drops(pos, "batteries", drops)
  187. drops[#drops+1] = "bat2:bt0_" .. v.tier
  188. minetest.remove_node(pos)
  189. return drops
  190. end
  191. functable.on_construct =
  192. function(pos)
  193. local meta = minetest.get_meta(pos)
  194. local inv = meta:get_inventory()
  195. inv:set_size("batteries", 8*2)
  196. functable.update_maximum_charge(meta)
  197. functable.compose_infotext(pos)
  198. functable.compose_formspec(pos)
  199. meta:set_string("nodename", "DUMMY")
  200. meta:set_string("owner", "DUMMY")
  201. meta:set_int("energy", 0)
  202. meta:set_int("old_eu", 0)
  203. meta:set_int("max", 0)
  204. functable.privatize(meta)
  205. end
  206. functable.privatize =
  207. function(meta)
  208. meta:mark_as_private({
  209. "nodename",
  210. "owner",
  211. "energy",
  212. "old_eu",
  213. "max",
  214. })
  215. end
  216. functable.on_destruct =
  217. function(pos)
  218. local meta = minetest.get_meta(pos)
  219. net2.clear_caches(pos, meta:get_string("owner"), v.tier)
  220. nodestore.del_node(pos)
  221. end
  222. functable.after_place_node =
  223. function(pos, placer, itemstack, pointed_thing)
  224. local meta = minetest.get_meta(pos)
  225. local owner = placer:get_player_name()
  226. meta:set_string("nodename", minetest.get_node(pos).name)
  227. meta:set_string("owner", owner)
  228. net2.clear_caches(pos, owner, v.tier)
  229. nodestore.add_node(pos)
  230. end
  231. functable.on_metadata_inventory_move =
  232. function(pos)
  233. functable.trigger_update(pos)
  234. end
  235. functable.on_metadata_inventory_put =
  236. function(pos)
  237. functable.trigger_update(pos)
  238. end
  239. functable.on_metadata_inventory_take =
  240. function(pos)
  241. functable.trigger_update(pos)
  242. end
  243. functable.trigger_update =
  244. function(pos)
  245. local timer = minetest.get_node_timer(pos)
  246. if not timer:is_started() then
  247. timer:start(1.0)
  248. end
  249. end
  250. -- Read the current & max charge of the battery, but do not trigger any update.
  251. -- Function shall be used internally ONLY.
  252. functable.get_energy_status =
  253. function(meta)
  254. local chg = meta:get_int("energy")
  255. local max = meta:get_int("max")
  256. return chg, max
  257. end
  258. end
  259. if not bat2.run_once then
  260. local nodebox = {
  261. {0, 0, 0, 5, 16, 5},
  262. {11, 0, 0, 16, 16, 5},
  263. {0, 0, 11, 5, 16, 16},
  264. {11, 0, 11, 16, 16, 16},
  265. {1, 1, 1, 15, 15, 15},
  266. {0, 0, 0, 16, 1, 16},
  267. {0, 15, 0, 16, 16, 16},
  268. }
  269. local selectbox = {
  270. {0, 0, 0, 16, 16, 16},
  271. }
  272. utility.transform_nodebox(nodebox)
  273. utility.transform_nodebox(selectbox)
  274. for k, v in ipairs({
  275. {tier="lv", title="LV"},
  276. {tier="mv", title="MV"},
  277. {tier="hv", title="HV"},
  278. }) do
  279. -- Register 13 nodes for each tier; each node has a different texture set to show the charge level.
  280. for i = 0, 12, 1 do
  281. -- Which function table are we operating on?
  282. local functable = _G["bat2_" .. v.tier]
  283. minetest.register_node(":bat2:bt" .. i .. "_" .. v.tier, {
  284. drawtype = "nodebox",
  285. description = v.title .. " Battery Box",
  286. tiles = {
  287. "technic_" .. v.tier .. "_battery_box_top.png",
  288. "technic_" .. v.tier .. "_battery_box_bottom.png",
  289. "technic_" .. v.tier .. "_battery_box_side.png^battery_meter" .. i .. ".png",
  290. "technic_" .. v.tier .. "_battery_box_side.png^battery_meter" .. i .. ".png",
  291. "technic_" .. v.tier .. "_battery_box_side.png^battery_meter" .. i .. ".png",
  292. "technic_" .. v.tier .. "_battery_box_side.png^battery_meter" .. i .. ".png",
  293. },
  294. groups = utility.dig_groups("machine"),
  295. paramtype = "light",
  296. paramtype2 = "facedir",
  297. is_ground_content = false,
  298. sounds = default.node_sound_metal_defaults(),
  299. drop = "bat2:bt0_" .. v.tier,
  300. node_box = {
  301. type = "fixed",
  302. fixed = nodebox,
  303. },
  304. selection_box = {
  305. type = "fixed",
  306. fixed = selectbox,
  307. },
  308. on_energy_put = function(...)
  309. return functable.on_energy_put(...) end,
  310. on_energy_get = function(...)
  311. return functable.on_energy_get(...) end,
  312. on_punch = function(...)
  313. return functable.on_punch(...) end,
  314. can_dig = function(...)
  315. return functable.can_dig(...) end,
  316. on_timer = function(...)
  317. return functable.on_timer(...) end,
  318. on_construct = function(...)
  319. return functable.on_construct(...) end,
  320. on_destruct = function(...)
  321. return functable.on_destruct(...) end,
  322. after_place_node = function(...)
  323. return functable.after_place_node(...) end,
  324. on_metadata_inventory_move = function(...)
  325. return functable.on_metadata_inventory_move(...) end,
  326. on_metadata_inventory_put = function(...)
  327. return functable.on_metadata_inventory_put(...) end,
  328. on_metadata_inventory_take = function(...)
  329. return functable.on_metadata_inventory_take(...) end,
  330. on_blast = function(...)
  331. return functable.on_blast(...) end,
  332. on_rotate = function(...)
  333. return screwdriver.rotate_simple(...) end,
  334. allow_metadata_inventory_put = function(...)
  335. return functable.allow_metadata_inventory_put(...) end,
  336. allow_metadata_inventory_move = function(...)
  337. return functable.allow_metadata_inventory_move(...) end,
  338. allow_metadata_inventory_take = function(...)
  339. return functable.allow_metadata_inventory_take(...) end,
  340. })
  341. end
  342. end
  343. local c = "bat2:core"
  344. local f = battery.modpath .. "/bat2.lua"
  345. reload.register_file(c, f, false)
  346. bat2.run_once = true
  347. end