physics.lua 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. local has_monitoring = minetest.get_modpath("monitoring")
  2. local has_technic = minetest.get_modpath("technic")
  3. local has_mesecons_random = minetest.get_modpath("mesecons_random")
  4. local MP = minetest.get_modpath("vacuum")
  5. local throttle = dofile(MP .. "/util/throttle.lua")
  6. local metric_space_vacuum_abm
  7. local metric_space_vacuum_leak_abm
  8. if has_monitoring then
  9. metric_space_vacuum_abm = monitoring.counter("vacuum_abm_count", "number of space vacuum abm calls")
  10. metric_space_vacuum_leak_abm = monitoring.counter("vacuum_abm_leak_count", "number of space vacuum leak abm calls")
  11. end
  12. -- air leaking nodes
  13. local leaky_nodes = {
  14. "group:door",
  15. "group:soil",
  16. "group:pipe", "group:tube"
  17. }
  18. if has_mesecons_random then
  19. table.insert(leaky_nodes, "mesecons_random:ghoststone_active")
  20. end
  21. if has_technic then
  22. table.insert(leaky_nodes, "technic:lv_cable")
  23. table.insert(leaky_nodes, "technic:mv_cable")
  24. table.insert(leaky_nodes, "technic:hv_cable")
  25. end
  26. local near_powered_airpump = function(pos)
  27. local pos1 = vector.subtract(pos, {x=vacuum.air_pump_range, y=vacuum.air_pump_range, z=vacuum.air_pump_range})
  28. local pos2 = vector.add(pos, {x=vacuum.air_pump_range, y=vacuum.air_pump_range, z=vacuum.air_pump_range})
  29. local nodes = minetest.find_nodes_in_area(pos1, pos2, {"vacuum:airpump"})
  30. for _,node in ipairs(nodes) do
  31. local meta = minetest.get_meta(node)
  32. if vacuum.airpump_active(meta) then
  33. return true
  34. end
  35. end
  36. return false
  37. end
  38. -- vacuum/air propagation
  39. minetest.register_abm({
  40. label = "space vacuum",
  41. nodenames = {"air"},
  42. neighbors = {"vacuum:vacuum"},
  43. interval = 1,
  44. chance = 1,
  45. action = throttle(1000, function(pos)
  46. if metric_space_vacuum_abm ~= nil then metric_space_vacuum_abm.inc() end
  47. if vacuum.no_vacuum_abm(pos) then
  48. return
  49. end
  50. if not vacuum.is_pos_in_space(pos) or near_powered_airpump(pos) then
  51. -- on earth or near a powered airpump
  52. local node = minetest.find_node_near(pos, 1, {"vacuum:vacuum"})
  53. if node ~= nil then
  54. minetest.set_node(node, {name = "air"})
  55. end
  56. else
  57. -- in space, evacuate air
  58. minetest.set_node(pos, {name = "vacuum:vacuum"})
  59. end
  60. end)
  61. })
  62. -- weird behaving nodes in vacuum
  63. local drop_nodes = {
  64. "default:torch",
  65. "default:torch_wall",
  66. "default:torch_ceiling",
  67. "default:ladder_wood",
  68. "default:ladder_steel",
  69. "default:dry_shrub",
  70. "default:papyrus",
  71. "default:cactus",
  72. "group:wool",
  73. "group:wood",
  74. "group:tree",
  75. -- "group:mesecon", TODO: add hardcore setting for that one
  76. -- TODO: maybe: group:dig_immediate
  77. }
  78. -- special drop cases
  79. local get_drop_name = function(name)
  80. if name == "default:torch_wall" or name == "default:torch_ceiling" then
  81. return "default:torch"
  82. else
  83. return name
  84. end
  85. end
  86. -- weird nodes in vacuum
  87. minetest.register_abm({
  88. label = "space drop nodes",
  89. nodenames = drop_nodes,
  90. neighbors = {"vacuum:vacuum"},
  91. interval = 1,
  92. chance = 1,
  93. action = throttle(100, function(pos)
  94. if not vacuum.is_pos_in_space(pos) or near_powered_airpump(pos) then
  95. return
  96. end
  97. local node = minetest.get_node(pos)
  98. minetest.set_node(pos, {name = "vacuum:vacuum"})
  99. local dropname = get_drop_name(node.name)
  100. if dropname then
  101. minetest.add_item(pos, {name = dropname})
  102. end
  103. end)
  104. })
  105. -- various dirts in vacuum
  106. minetest.register_abm({
  107. label = "space vacuum soil dry",
  108. nodenames = {
  109. "default:dirt",
  110. "default:dirt_with_grass",
  111. "default:dirt_with_snow",
  112. "default:dirt_with_dry_grass",
  113. "default:dirt_with_grass_footsteps",
  114. "default:dirt_with_rainforest_litter",
  115. "default:dirt_with_coniferous_litter"
  116. },
  117. neighbors = {"vacuum:vacuum"},
  118. interval = 1,
  119. chance = 1,
  120. action = throttle(100, function(pos)
  121. minetest.set_node(pos, {name = "default:gravel"})
  122. end)
  123. })
  124. -- plants in vacuum
  125. minetest.register_abm({
  126. label = "space vacuum plants",
  127. nodenames = {
  128. "group:sapling",
  129. "group:plant",
  130. "group:flora",
  131. "group:flower",
  132. "group:leafdecay",
  133. "ethereal:banana", -- ethereal compat
  134. "ethereal:orange",
  135. "ethereal:strawberry"
  136. },
  137. neighbors = {"vacuum:vacuum"},
  138. interval = 1,
  139. chance = 1,
  140. action = throttle(100, function(pos)
  141. minetest.set_node(pos, {name = "default:dry_shrub"})
  142. end)
  143. })
  144. -- sublimate nodes in vacuum
  145. minetest.register_abm({
  146. label = "space vacuum sublimate",
  147. nodenames = {"group:snowy", "group:leaves", "group:water"},
  148. neighbors = {"vacuum:vacuum"},
  149. interval = 1,
  150. chance = 1,
  151. action = throttle(100, function(pos)
  152. if not vacuum.is_pos_in_space(pos) or near_powered_airpump(pos) then
  153. return
  154. end
  155. minetest.set_node(pos, {name = "vacuum:vacuum"})
  156. end)
  157. })
  158. -- depressurize through leaky nodes
  159. minetest.register_abm({
  160. label = "space vacuum depressurize",
  161. nodenames = leaky_nodes,
  162. neighbors = {"vacuum:vacuum"},
  163. interval = 2,
  164. chance = 2,
  165. action = throttle(250, function(pos)
  166. if metric_space_vacuum_leak_abm ~= nil then metric_space_vacuum_leak_abm.inc() end
  167. if not vacuum.is_pos_in_space(pos) or near_powered_airpump(pos) then
  168. -- on earth: TODO: replace vacuum with air
  169. return
  170. else
  171. local node = minetest.get_node(pos)
  172. if node.name == "pipeworks:entry_panel_empty" or node.name == "pipeworks:entry_panel_loaded" then
  173. -- air thight pipes
  174. return
  175. end
  176. if node.name == "vacuum:airpump" then
  177. -- pump is airthight
  178. return
  179. end
  180. -- TODO check n nodes down (multiple simple door airlock hack)
  181. -- in space: replace air with vacuum
  182. local surrounding_node = minetest.find_node_near(pos, 1, {"air"})
  183. if surrounding_node ~= nil then
  184. if vacuum.debug then
  185. -- debug mode, set
  186. minetest.set_node(surrounding_node, {name = "default:cobble"})
  187. else
  188. -- normal case
  189. minetest.set_node(surrounding_node, {name = "vacuum:vacuum"})
  190. end
  191. end
  192. end
  193. end)
  194. })