init.lua 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542
  1. springs = {}
  2. local modpath = minetest.get_modpath("springs")
  3. dofile(modpath.."/pipes.lua")
  4. dofile(modpath.."/sluice.lua")
  5. dofile(modpath.."/pump.lua")
  6. dofile(modpath.."/wells.lua")
  7. --[[
  8. TODO:
  9. water filters
  10. pipe inlet/outlet pressure checks
  11. broken outlet sharing
  12. non-connected pipes and splitters
  13. fix wells
  14. better springs texture
  15. optimize static water
  16. pumps
  17. fix spout and intake nodeboxes
  18. crafts
  19. galvanized-ish pipes (coat in tin)
  20. ]]
  21. minetest.register_node("springs:spring", {
  22. description = "Spring",
  23. tiles = {"default_cobble.png^default_river_water.png"},
  24. --paramtype = "light",
  25. --leveled = 64,
  26. --alpha = 160,
  27. drop = "default:cobble",
  28. --drowning = 1,
  29. walkable = true, -- because viscosity doesn't work for regular nodes, and the liquid hack can't be leveled
  30. -- post_effect_color = {a = 103, r = 30, g = 76, b = 120},
  31. groups = { puts_out_fire = 1, cracky = 1, is_ground_content = 1, cools_lava = 1},
  32. sounds = default.node_sound_water_defaults(),
  33. })
  34. minetest.register_node("springs:water", {
  35. description = "node ",
  36. drawtype = "nodebox",
  37. paramtype = "light",
  38. paramtype2 = "leveled",
  39. tiles = {
  40. {
  41. name = "default_river_water_source_animated.png",
  42. animation = {
  43. type = "vertical_frames",
  44. aspect_w = 16,
  45. aspect_h = 16,
  46. length = 2.0,
  47. },
  48. },
  49. },
  50. special_tiles = {
  51. {
  52. name = "default_river_water_source_animated.png",
  53. animation = {
  54. type = "vertical_frames",
  55. aspect_w = 16,
  56. aspect_h = 16,
  57. length = 2.0,
  58. },
  59. backface_culling = false,
  60. },
  61. },
  62. leveled = 64,
  63. alpha = 160,
  64. drop = "",
  65. drowning = 1,
  66. walkable = false, -- because viscosity doesn't work for regular nodes, and the liquid hack can't be leveled
  67. climbable = true, -- because viscosity doesn't work for regular nodes, and the liquid hack can't be leveled
  68. pointable = false,
  69. diggable = false,
  70. buildable_to = true,
  71. -- liquid_viscosity = 14,
  72. -- liquidtype = "source",
  73. -- liquid_alternative_flowing = "springs:water",
  74. -- liquid_alternative_source = "springs:water",
  75. -- liquid_renewable = false,
  76. -- liquid_range = 0,
  77. -- groups = {crumbly=3,soil=1,falling_node=1},
  78. post_effect_color = {a = 103, r = 30, g = 76, b = 90},
  79. groups = { puts_out_fire = 1, liquid = 3, cools_lava = 1, fresh_water=1},
  80. sounds = default.node_sound_water_defaults(),
  81. node_box = {
  82. type = "leveled",
  83. fixed = {
  84. {-0.5, -0.5, -0.5, 0.5, 0.5, 0.5}, -- NodeBox1
  85. }
  86. }
  87. })
  88. -- this is a special node used to optimize large pools of water
  89. -- its flowing abm runs much less frequently
  90. minetest.register_node("springs:water_full", {
  91. description = "node ",
  92. drawtype = "nodebox",
  93. paramtype = "light",
  94. tiles = {
  95. {
  96. name = "default_river_water_source_animated.png",
  97. animation = {
  98. type = "vertical_frames",
  99. aspect_w = 16,
  100. aspect_h = 16,
  101. length = 2.0,
  102. },
  103. },
  104. },
  105. special_tiles = {
  106. {
  107. name = "default_river_water_source_animated.png",
  108. animation = {
  109. type = "vertical_frames",
  110. aspect_w = 16,
  111. aspect_h = 16,
  112. length = 2.0,
  113. },
  114. backface_culling = false,
  115. },
  116. },
  117. leveled = 64,
  118. alpha = 160,
  119. drop = "",
  120. drowning = 1,
  121. walkable = false, -- because viscosity doesn't work for regular nodes, and the liquid hack can't be leveled
  122. climbable = true, -- because viscosity doesn't work for regular nodes, and the liquid hack can't be leveled
  123. pointable = false,
  124. diggable = false,
  125. buildable_to = true,
  126. -- liquid_viscosity = 14,
  127. -- liquidtype = "source",
  128. -- liquid_alternative_flowing = "springs:water",
  129. -- liquid_alternative_source = "springs:water",
  130. -- liquid_renewable = false,
  131. -- liquid_range = 0,
  132. -- groups = {crumbly=3,soil=1,falling_node=1},
  133. post_effect_color = {a = 103, r = 30, g = 76, b = 90},
  134. groups = { puts_out_fire = 1, liquid = 3, cools_lava = 1, fresh_water=1},
  135. sounds = default.node_sound_water_defaults(),
  136. node_box = {
  137. type = "leveled",
  138. fixed = {
  139. {-0.5, -0.5, -0.5, 0.5, 0.5, 0.5}, -- NodeBox1
  140. }
  141. }
  142. })
  143. -- spring
  144. minetest.register_abm({
  145. nodenames = {"springs:spring"},
  146. neighbors = {"group:fresh_water", "air"},
  147. interval = 5,
  148. chance = 60,
  149. action = function(pos)
  150. -- local mylevel = minetest.get_node_level(pos)
  151. -- print("spring at: "..pos.x..","..pos.y..","..pos.z)
  152. local air_nodes = minetest.find_nodes_in_area(
  153. {x=pos.x - 1, y=pos.y - 1, z=pos.z - 1},
  154. {x=pos.x + 1, y=pos.y, z=pos.z + 1},
  155. {"group:fresh_water", "air"}
  156. )
  157. if nil == air_nodes or #air_nodes == 0 then
  158. return
  159. end
  160. local tpos = air_nodes[math.random(#air_nodes)]
  161. -- calculate flow rate based on absolute location
  162. local prate = (minetest.hash_node_position(pos) % 48)
  163. local amount = math.random(1, 16) + prate
  164. local t = minetest.get_node(tpos)
  165. if t.name == "air" then
  166. minetest.set_node(tpos, {name = "springs:water"})
  167. minetest.set_node_level(tpos, amount)
  168. else -- it's group:fresh_water
  169. local tlevel = minetest.get_node_level(tpos)
  170. minetest.set_node_level(tpos, math.min(64, tlevel + amount))
  171. end
  172. end
  173. })
  174. -- evaporation
  175. minetest.register_abm({
  176. nodenames = {"group:fresh_water"},
  177. neighbors = {"air"},
  178. interval = 5,
  179. chance = 10,
  180. action = function(pos)
  181. local mylevel = minetest.get_node_level(pos)
  182. if math.random(16 - minetest.get_node_light(pos)) == 1 then
  183. if mylevel > 1 then
  184. minetest.set_node_level(pos, mylevel - 1)
  185. else
  186. minetest.set_node(pos, {name = "air"})
  187. end
  188. end
  189. end
  190. })
  191. local soak = {
  192. ["default:cobble"] = 10,
  193. ["default:desert_cobble"] = 10,
  194. ["default:mossycobble"] = 9,
  195. ["default:dirt"] = 2,
  196. ["default:dirt_with_grass"] = 2,
  197. ["default:dirt_with_grass_footsteps"] = 2,
  198. ["default:dirt_with_dry_grass"] = 2,
  199. ["default:dirt_with_coniferous_litter"] = 2,
  200. ["default:dirt_with_rainforest_litter"] = 1,
  201. ["default:gravel"] = 8,
  202. ["default:coral_orange"] = 6,
  203. ["default:coral_brown"] = 6,
  204. ["default:coral_skeleton"] = 6,
  205. ["default:sand"] = 6,
  206. ["default:sand_with_kelp"] = 6,
  207. ["default:desert_sand"] = 7,
  208. ["default:silver_sand"] = 7,
  209. ["default:snow"] = 4,
  210. ["default:snowblock"] = 4,
  211. ["default:leaves"] = 60,
  212. ["default:bush_leaves"] = 60,
  213. ["default:jungleleaves"] = 60,
  214. ["default:pine_needles"] = 60,
  215. ["default:acacia_leaves"] = 60,
  216. ["default:acacia_bush_leaves"] = 60,
  217. ["default:aspen_leaves"] = 60,
  218. -- dilution
  219. ["default:water_source"] = 65,
  220. ["default:water_flowing"] = 65,
  221. ["default:river_water_source"] = 65,
  222. ["default:river_water_flowing"] = 65,
  223. -- boiling -- TODO: steam effect
  224. ["default:lava_source"] = 65,
  225. ["default:lava_flowing"] = 65,
  226. -- no ladder hacks
  227. ["default:ladder_wood"] = 65,
  228. -- ["default:ladder_steel"] = 65, -- need to figure out a way for water to flow through ladders
  229. ["default:sign_wall_wood"] = 65,
  230. ["default:sign_wall_steel"] = 65,
  231. ["default:fence_wood"] = 65,
  232. ["default:fence_acacia_wood"] = 65,
  233. ["default:fence_junglewood"] = 65,
  234. ["default:fence_pine_wood"] = 65,
  235. ["default:fence_aspen_wood"] = 65,
  236. ["default:torch"] = 65,
  237. ["carts:rail"] = 65,
  238. ["carts:brakerail"] = 65,
  239. ["carts:powerrail"] = 65,
  240. }
  241. local soak_names = {}
  242. for n,_ in pairs(soak) do
  243. table.insert(soak_names, n)
  244. end
  245. -- soaking sideways
  246. minetest.register_abm({
  247. nodenames = {"group:fresh_water"},
  248. neighbors = soak_names,
  249. interval = 4,
  250. chance = 10,
  251. action = function(pos)
  252. -- print("\nsoak ")
  253. local soak_nodes = minetest.find_nodes_in_area(
  254. {x=pos.x - 1, y=pos.y, z=pos.z - 1},
  255. {x=pos.x + 1, y=pos.y, z=pos.z + 1},
  256. soak_names
  257. )
  258. local mylevel = minetest.get_node_level(pos)
  259. local total_loss = 0
  260. for _,spos in ipairs(soak_nodes) do
  261. local sn = minetest.get_node(spos)
  262. total_loss = total_loss + soak[sn.name]
  263. if 1 == math.random(120 / mylevel) then
  264. minetest.set_node(spos, {name = "air"})
  265. end
  266. end
  267. if total_loss == 0 then
  268. return
  269. end
  270. --print("loss: ".. total_loss)
  271. local remain = mylevel - (total_loss * (mylevel / 64))
  272. if remain > 0 then
  273. minetest.set_node_level(pos, remain)
  274. else
  275. minetest.set_node(pos, {name="air"})
  276. end
  277. end
  278. })
  279. -- de-stagnation (faster flowing)
  280. minetest.register_abm({
  281. nodenames = {"springs:water_full"},
  282. neighbors = {"air"},
  283. interval = 6,
  284. chance = 1,
  285. action = function(pos)
  286. -- if it's near air it might flow
  287. minetest.set_node(pos, {name = "springs:water"})
  288. end
  289. })
  290. -- flowing
  291. minetest.register_abm({
  292. nodenames = {"springs:water"},
  293. neighbors = {"group:fresh_water", "air"},
  294. interval = 2,
  295. chance = 2,
  296. action = function(pos)
  297. local mylevel = minetest.get_node_level(pos)
  298. -- print("\n mylevel ".. mylevel)
  299. -- falling
  300. local below = {x=pos.x, y=pos.y - 1, z=pos.z}
  301. local nbelow = minetest.get_node(below).name
  302. if nbelow == "air" then
  303. minetest.set_node(below, {name="springs:water"})
  304. minetest.set_node_level(below, mylevel)
  305. minetest.set_node(pos, {name="air"})
  306. return
  307. elseif nbelow == "springs:water" then
  308. local blevel = minetest.get_node_level(below)
  309. if blevel < 64 then
  310. local sum = mylevel + blevel
  311. minetest.set_node_level(below, math.min(64, sum))
  312. if sum > 64 then
  313. mylevel = sum - 64
  314. minetest.set_node_level(pos, mylevel)
  315. -- keep flowing the liquid. this speeds up cascades
  316. else
  317. minetest.set_node(pos, {name="air"})
  318. return
  319. end
  320. end
  321. else -- check soaking
  322. local rate = soak[nbelow]
  323. if rate ~= nil then
  324. local remains = mylevel - rate
  325. if remains > 0 then
  326. minetest.set_node_level(pos, remains)
  327. else
  328. minetest.set_node(pos, {name="air"})
  329. end
  330. if 1 == math.random(120 / mylevel) then
  331. minetest.set_node(below, {name = "air"})
  332. end
  333. mylevel = remains
  334. --return -- keep the fluid mechanics
  335. end
  336. end
  337. local air_nodes = minetest.find_nodes_in_area(
  338. {x=pos.x - 1, y=pos.y - 1, z=pos.z - 1},
  339. {x=pos.x + 1, y=pos.y, z=pos.z + 1},
  340. "air"
  341. )
  342. -- print("x: "..pos.x.." y: "..pos.y.." z: "..pos.z)
  343. -- print("air list len ".. #air_nodes)
  344. local off = math.random(0, #air_nodes or 1)
  345. -- print("off "..off)
  346. for i = 1,#air_nodes do
  347. --local theirlevel = minetest.get_node_level(fp)
  348. local fp = air_nodes[((i + off) % #air_nodes) + 1]
  349. if mylevel >= 2 then
  350. local half = math.ceil(mylevel / 2)
  351. minetest.set_node_level(pos, mylevel - half)
  352. minetest.set_node(fp, {name= "springs:water"})
  353. minetest.set_node_level(fp, half)
  354. -- minetest.check_for_falling(fp)
  355. return
  356. end
  357. end
  358. local flow_nodes = minetest.find_nodes_in_area(
  359. {x=pos.x - 1, y=pos.y , z=pos.z - 1},
  360. {x=pos.x + 1, y=pos.y, z=pos.z + 1},
  361. "group:fresh_water"
  362. )
  363. -- print("x: "..pos.x.." y: "..pos.y.." z: "..pos.z)
  364. -- print("list len ".. #flow_nodes)
  365. local off = math.random(0, #flow_nodes or 1)
  366. for i = 1,#flow_nodes do
  367. local fp = flow_nodes[((i + off) % #flow_nodes) + 1]
  368. local theirlevel = minetest.get_node_level(fp)
  369. -- print("theirlevel "..theirlevel)
  370. if mylevel - theirlevel >= 2 then
  371. local diff = (mylevel - theirlevel)
  372. local half = math.ceil(diff / 2)
  373. minetest.set_node_level(pos, mylevel - half)
  374. minetest.set_node_level(fp, theirlevel + (diff - half))
  375. return
  376. end
  377. end
  378. -- local n = minetest.get_node(fp);
  379. -- -- check above to make sure it can get here
  380. -- local na = minetest.get_node({x=fp.x, y=fp.y+1, z=fp.z})
  381. --
  382. -- -- print("name: " .. na.name .. " l: " ..g)
  383. -- if na.name == "default:river_water_flowing" or na.name == "default:river_water_flowing" then
  384. -- minetest.set_node(fp, {name=node.name})
  385. -- minetest.set_node(pos, {name=n.name})
  386. -- return
  387. -- end
  388. -- end
  389. -- stagnation: this may not work
  390. if mylevel == 64 then
  391. --print("stagnating ".. pos.x .. ","..pos.y..","..pos.z)
  392. minetest.set_node(pos, {name = "springs:water_full"})
  393. end
  394. end
  395. })
  396. -- surface water
  397. minetest.register_ore({
  398. ore_type = "scatter",
  399. ore = "springs:spring",
  400. wherein = {"default:dirt_with_grass", "default:dirt_with_coniferous_litter", "default:dirt_with_rainforest_litter"},
  401. clust_scarcity = 64 * 64 * 64,
  402. clust_num_ores = 1,
  403. clust_size = 1,
  404. y_min = -20,
  405. y_max = 200,
  406. })
  407. minetest.register_ore({
  408. ore_type = "scatter",
  409. ore = "springs:spring",
  410. wherein = "default:dirt",
  411. clust_scarcity = 48 * 48 * 48,
  412. clust_num_ores = 1,
  413. clust_size = 1,
  414. y_min = -20,
  415. y_max = 200,
  416. })
  417. -- ground water
  418. minetest.register_ore({
  419. ore_type = "scatter",
  420. ore = "springs:spring",
  421. wherein = "default:stone",
  422. clust_scarcity = 16 * 16 * 16,
  423. clust_num_ores = 3,
  424. clust_size = 3,
  425. y_min = -50,
  426. y_max = -10,
  427. })
  428. minetest.register_ore({
  429. ore_type = "scatter",
  430. ore = "springs:spring",
  431. wherein = "default:stone",
  432. clust_scarcity = 8 * 8 * 8,
  433. clust_num_ores = 5,
  434. clust_size = 4,
  435. y_min = -50,
  436. y_max = -25,
  437. })
  438. -- deep water - rare but bountiful
  439. minetest.register_ore({
  440. ore_type = "scatter",
  441. ore = "springs:spring",
  442. wherein = "default:stone",
  443. clust_scarcity = 64 * 64 * 64,
  444. clust_num_ores = 12,
  445. clust_size = 6,
  446. y_min = -32000,
  447. y_max = -100,
  448. })
  449. -- minetest.register_ore({
  450. -- ore_type = "scatter",
  451. -- ore = "springs:spring",
  452. -- wherein = "default:stone",
  453. -- clust_scarcity = 8 * 8 * 8,
  454. -- clust_num_ores = 16,
  455. -- clust_size = 5,
  456. -- y_min = -50,
  457. -- y_max = -40,
  458. -- })
  459. -- TODO: desert stone, sandstone