init.lua 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. -- Parameters
  2. -- Node search radius around player
  3. local radius = 8
  4. local allsounds = {
  5. ["env_sounds_water"] = {
  6. trigger = {"default:water_flowing", "default:river_water_flowing"},
  7. base_volume = 0.04,
  8. max_volume = 0.4,
  9. per_node = 0.004,
  10. },
  11. ["env_sounds_lava"] = {
  12. trigger = {"default:lava_source", "default:lava_flowing"},
  13. base_volume = 0,
  14. max_volume = 0.6,
  15. per_node = {
  16. ["default:lava_source"] = 0.008,
  17. ["default:lava_flowing"] = 0.002,
  18. },
  19. },
  20. }
  21. if minetest.settings:get_bool("river_source_sounds") then
  22. table.insert(allsounds["env_sounds_water"].trigger,
  23. "default:river_water_source")
  24. end
  25. -- Cache the union of all trigger nodes
  26. local cache_triggers = {}
  27. for sound, def in pairs(allsounds) do
  28. for _, name in ipairs(def.trigger) do
  29. table.insert(cache_triggers, name)
  30. end
  31. end
  32. -- Update sound for player
  33. local function update_sound(player)
  34. local player_name = player:get_player_name()
  35. local ppos = player:get_pos()
  36. ppos = vector.add(ppos, player:get_properties().eye_height)
  37. local areamin = vector.subtract(ppos, radius)
  38. local areamax = vector.add(ppos, radius)
  39. local pos = minetest.find_nodes_in_area(areamin, areamax, cache_triggers, true)
  40. if next(pos) == nil then -- If table empty
  41. return
  42. end
  43. for sound, def in pairs(allsounds) do
  44. -- Find average position
  45. local posav = {0, 0, 0}
  46. local count = 0
  47. for _, name in ipairs(def.trigger) do
  48. if pos[name] then
  49. for _, p in ipairs(pos[name]) do
  50. posav[1] = posav[1] + p.x
  51. posav[2] = posav[2] + p.y
  52. posav[3] = posav[3] + p.z
  53. end
  54. count = count + #pos[name]
  55. end
  56. end
  57. if count > 0 then
  58. posav = vector.new(posav[1] / count, posav[2] / count,
  59. posav[3] / count)
  60. -- Calculate gain
  61. local gain = def.base_volume
  62. if type(def.per_node) == 'table' then
  63. for name, multiplier in pairs(def.per_node) do
  64. if pos[name] then
  65. gain = gain + #pos[name] * multiplier
  66. end
  67. end
  68. else
  69. gain = gain + count * def.per_node
  70. end
  71. gain = math.min(gain, def.max_volume)
  72. minetest.sound_play(sound, {
  73. pos = posav,
  74. to_player = player_name,
  75. gain = gain,
  76. }, true)
  77. end
  78. end
  79. end
  80. -- Update sound when player joins
  81. minetest.register_on_joinplayer(function(player)
  82. update_sound(player)
  83. end)
  84. -- Cyclic sound update
  85. local function cyclic_update()
  86. for _, player in pairs(minetest.get_connected_players()) do
  87. update_sound(player)
  88. end
  89. minetest.after(3.5, cyclic_update)
  90. end
  91. minetest.after(0, cyclic_update)