functions.lua 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. -- Localize for performance.
  2. local math_floor = math.floor
  3. distributer.update_formspec =
  4. function(pos, chg, max, cnt)
  5. local meta = minetest.get_meta(pos)
  6. local inv = meta:get_inventory()
  7. local status_string = "Network EU Status: Total Arrays: " .. cnt ..
  8. ", Total Charge: " .. chg .. "/" .. max
  9. local formspec =
  10. "size[8,8.5]" ..
  11. default.formspec.get_form_colors() ..
  12. default.formspec.get_form_image() ..
  13. default.formspec.get_slot_colors() ..
  14. "label[0,0;" .. minetest.formspec_escape(status_string) .. "]" ..
  15. "label[0,0.5;Configuration Slots]" ..
  16. "list[context;config;0,1;8,2;]" ..
  17. "list[current_player;main;0,4.25;8,1;]" ..
  18. "list[current_player;main;0,5.5;8,3;8]" ..
  19. "listring[context;config]" ..
  20. "listring[current_player;main]" ..
  21. default.get_hotbar_bg(0, 4.25)
  22. meta:set_string("formspec", formspec)
  23. end
  24. -- Typedata is used when traversing the network, without touching the node.
  25. -- It must contain as much data as needed to get the node even if unloaded.
  26. -- This must be done after node construction.
  27. -- This should also be done when punched, to allow old nodes to be upgraded.
  28. distributer.initialize_typedata =
  29. function(pos)
  30. local meta = minetest.get_meta(pos)
  31. meta:set_string("technic_machine", "yes")
  32. meta:set_string("technic_type", "utility")
  33. meta:set_string("technic_tier", "lv|mv|hv")
  34. meta:set_string("technic_name", "distributer:distributer")
  35. end
  36. distributer.on_punch =
  37. function(pos, node, puncher, pointed_thing)
  38. distributer.initialize_typedata(pos)
  39. distributer.trigger_update(pos)
  40. end
  41. distributer.can_dig =
  42. function(pos, player)
  43. local meta = minetest.get_meta(pos)
  44. local inv = meta:get_inventory()
  45. return inv:is_empty("config")
  46. end
  47. distributer.allow_metadata_inventory_put =
  48. function(pos, listname, index, stack, player)
  49. local pname = player:get_player_name()
  50. if minetest.test_protection(pos, pname) then
  51. return 0
  52. end
  53. local NCONFIG = "cfg:dev"
  54. if listname == "config" and stack:get_name() == NCONFIG then
  55. return stack:get_count()
  56. end
  57. return 0
  58. end
  59. distributer.allow_metadata_inventory_move =
  60. function(pos, from_list, from_index, to_list, to_index, count, player)
  61. local pname = player:get_player_name()
  62. if minetest.test_protection(pos, pname) then
  63. return 0
  64. end
  65. return count
  66. end
  67. distributer.allow_metadata_inventory_take =
  68. function(pos, listname, index, stack, player)
  69. local pname = player:get_player_name()
  70. if minetest.test_protection(pos, pname) then
  71. return 0
  72. end
  73. return stack:get_count()
  74. end
  75. distributer.update_infotext =
  76. function(pos, chg, max, cnt)
  77. local meta = minetest.get_meta(pos)
  78. local inv = meta:get_inventory()
  79. local infotext = "Network EU Observer\n" ..
  80. "Total Arrays: " .. cnt .. "\n" ..
  81. "Stored EUs: " .. chg .. "/" .. max .. "\n"
  82. if max > 0 then
  83. local percent = math_floor(chg / max * 100)
  84. infotext = infotext .. "Total Charge: " .. percent .. "%"
  85. else
  86. infotext = infotext .. "Total Charge: 0%"
  87. end
  88. meta:set_string("infotext", infotext)
  89. end
  90. distributer.on_timer =
  91. function(pos, elapsed)
  92. machines.log_update(pos, "Observer")
  93. local table_in = {
  94. purpose = "controler_update",
  95. }
  96. local table_out = {}
  97. local traversal = {}
  98. -- Do not process self.
  99. local hash = minetest.hash_node_position(pos)
  100. traversal[hash] = 0
  101. -- TODO: why do we unconditionally update all controlers?
  102. -- This may cause a huge update cascade, usually for no reason, since energy
  103. -- may not have changed. Also, we should only update generators when energy
  104. -- is drained. Consumers should only be auto-updated with energy increases.
  105. -- Currenty, we're just updating everybody whenever the distributer updates.
  106. -- Update controlers on all adjacent networks of any tier.
  107. local hubs = machines.get_adjacent_network_hubs(pos)
  108. if hubs then
  109. for k, v in ipairs(hubs) do
  110. local node = minetest.get_node(v)
  111. local def = minetest.reg_ns_nodes[node.name]
  112. if def and def.on_machine_execute then
  113. def.on_machine_execute(v, table_in, table_out, traversal)
  114. end
  115. end
  116. end
  117. local chg, max, cnt = distributer.get_energy_status(pos)
  118. distributer.update_infotext(pos, chg, max, cnt)
  119. distributer.update_formspec(pos, chg, max, cnt)
  120. end
  121. distributer.on_blast =
  122. function(pos)
  123. local drops = {}
  124. default.get_inventory_drops(pos, "config", drops)
  125. drops[#drops+1] = "distributer:distributer"
  126. minetest.remove_node(pos)
  127. return drops
  128. end
  129. distributer.on_construct =
  130. function(pos)
  131. distributer.initialize_typedata(pos)
  132. local meta = minetest.get_meta(pos)
  133. local inv = meta:get_inventory()
  134. inv:set_size("config", 8*2)
  135. distributer.update_infotext(pos, 0, 0, 0)
  136. distributer.update_formspec(pos, 0, 0, 0)
  137. end
  138. distributer.after_place_node =
  139. function(pos, placer, itemstack, pointed_thing)
  140. end
  141. distributer.on_metadata_inventory_move =
  142. function(pos)
  143. distributer.trigger_update(pos)
  144. end
  145. distributer.on_metadata_inventory_put =
  146. function(pos)
  147. distributer.trigger_update(pos)
  148. end
  149. distributer.on_metadata_inventory_take =
  150. function(pos)
  151. distributer.trigger_update(pos)
  152. end
  153. distributer.trigger_update =
  154. function(pos)
  155. local timer = minetest.get_node_timer(pos)
  156. if not timer:is_started() then
  157. timer:start(1.0)
  158. end
  159. end
  160. -- Read the combined energy storage and max possible storage for all batteries.
  161. -- Do not trigger an update. This function shall not be called externally.
  162. distributer.get_energy_status =
  163. function(pos)
  164. local table_in = {
  165. purpose = "get_eu_status",
  166. }
  167. local table_out = {}
  168. local traversal = {}
  169. -- Do not process self.
  170. local hash = minetest.hash_node_position(pos)
  171. traversal[hash] = 0
  172. -- Get data from all batteries on network. Any tier is allowed.
  173. local hubs = machines.get_adjacent_network_hubs(pos)
  174. if hubs then
  175. for k, v in ipairs(hubs) do
  176. local node = minetest.get_node(v)
  177. local def = minetest.reg_ns_nodes[node.name]
  178. if def and def.on_machine_execute then
  179. def.on_machine_execute(v, table_in, table_out, traversal)
  180. end
  181. end
  182. end
  183. return (table_out.eu_chg or 0),
  184. (table_out.eu_max or 0),
  185. (table_out.num_batteries or 0)
  186. end
  187. distributer.on_machine_execute =
  188. function(pos, table_in, table_out, traversal)
  189. -- No recursion check, because distributers do not take part in chains.
  190. -- This also allows them to function at the very end of a switching chain.
  191. -- Do not process this node more than once.
  192. local hash = minetest.hash_node_position(pos)
  193. if traversal[hash] then return end
  194. traversal[hash] = 0
  195. local purpose = table_in.purpose
  196. if purpose == "refresh_eu_status" then
  197. distributer.trigger_update(pos)
  198. end
  199. end
  200. if not distributer.functions_loaded then
  201. local c = "distributer:core"
  202. local f = distributer.modpath .. "/functions.lua"
  203. reload.register_file(c, f, false)
  204. distributer.functions_loaded = true
  205. end