init.lua 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. -- This file is reloadable.
  2. if not minetest.global_exists("ambiance") then ambiance = {} end
  3. ambiance.players = ambiance.players or {}
  4. ambiance.environment_cache = ambiance.environment_cache or {}
  5. ambiance.modpath = minetest.get_modpath("ambiance")
  6. -- Localize for performance.
  7. local math_random = math.random
  8. local vround = vector.round
  9. local min = math.min
  10. local max = math.max
  11. dofile(ambiance.modpath .. "/data.lua")
  12. dofile(ambiance.modpath .. "/utility.lua")
  13. dofile(ambiance.modpath .. "/scuba.lua")
  14. dofile(ambiance.modpath .. "/particles.lua")
  15. dofile(ambiance.modpath .. "/beacon.lua")
  16. dofile(ambiance.modpath .. "/treesounds.lua")
  17. dofile(ambiance.modpath .. "/gate.lua")
  18. dofile(ambiance.modpath .. "/default_beacons.lua")
  19. -- Modifiable parameters.
  20. ambiance.server_step = 1
  21. local step_timer = 0
  22. local step_total = ambiance.server_step
  23. ambiance.globalstep = function(dtime)
  24. step_timer = step_timer + dtime
  25. if step_timer < step_total then
  26. return
  27. end
  28. step_timer = 0
  29. -- Get current time of day.
  30. local curtime = minetest.get_timeofday()
  31. local rand = math_random
  32. -- For all sounds, check if anyone can hear them. If yes, play sound to players that can hear.
  33. local allsounds = ambiance.allsounds
  34. for k, v in ipairs(allsounds) do
  35. v.timer = v.timer - step_total
  36. if v.timer <= 0 then
  37. -- Timer has expired, fire sound (if possible).
  38. -- Also reset the timer so the sound can fire again.
  39. v.timer = rand(v.mintime, v.maxtime)
  40. -- Can this sound play at the current time of day?
  41. if ambiance.check_time(v.time, curtime) then
  42. -- Scan through all players. The following checks must be done per-player.
  43. for name, pdata in pairs(ambiance.players) do
  44. local player = minetest.get_player_by_name(name)
  45. if player and player:is_player() then
  46. local pos = utility.get_foot_pos(player:get_pos())
  47. -- Is player in this sounds's Y layer?
  48. local miny = v.miny
  49. local maxy = v.maxy
  50. if v.ground_offset then
  51. local g
  52. if type(v.ground_offset) == "function" then
  53. g = v.ground_offset(vround(pos))
  54. else
  55. g = v.ground_offset
  56. end
  57. miny = g + miny
  58. maxy = g + maxy
  59. miny = max(miny, v.absminy)
  60. maxy = min(maxy, v.absmaxy)
  61. end
  62. if pos.y >= miny and pos.y <= maxy then
  63. -- Don't play sound if player is underwater (muted sounds).
  64. -- Note: player's underwater status is modified by the scuba code.
  65. local underwater = ambiance.players[name].underwater
  66. if underwater == nil then
  67. local spawnsound = true
  68. -- If have perlin object, then check if sound can spawn in this location.
  69. if v.perlin and v.noise_threshold then
  70. local noise = v.perlin:get_3d(pos)
  71. if v.absvalue then
  72. noise = math.abs(noise)
  73. end
  74. if noise < v.noise_threshold then
  75. spawnsound = false
  76. end
  77. end
  78. -- If we have a noise function, use that (allows arbitrary
  79. -- complexity in calculating where ambiance is allowed to play).
  80. -- Should be used by custom Lua mapgens + realms.
  81. if v.noise_function then
  82. if not v.noise_function(vround(pos)) then
  83. spawnsound = false
  84. end
  85. end
  86. -- If sound may only play in a particular realm ...
  87. if v.realm and rc.current_realm_at_pos(pos) ~= v.realm then
  88. spawnsound = false
  89. end
  90. if spawnsound then
  91. -- Only play sound if sound can be played indoors or out-of-doors.
  92. -- If sound doesn't care whether indoors or out-of-doors, then play it.
  93. local indoors
  94. if v.indoors ~= nil then
  95. -- Randomize position a bit in case player is just standing under an overhang.
  96. pos.x = rand(pos.x - 1, pos.x + 1)
  97. pos.y = rand(pos.y - 1, pos.y + 1)
  98. pos.z = rand(pos.z - 1, pos.z + 1)
  99. indoors = ambiance.check_indoors(name, pos)
  100. end
  101. if v.indoors == indoors then
  102. -- Play sound to current player!
  103. -- If multiple players can hear, the sound will be played at the same time to all of them.
  104. local gain = rand(v.mingain*100.0, v.maxgain*100.0)/100.0
  105. -- Clamp gain!
  106. if gain < 0.0 then gain = 0.0 end
  107. if gain > 2.0 then gain = 2.0 end
  108. minetest.sound_play(v.name, {to_player=name, gain=gain})
  109. end
  110. end
  111. end
  112. end
  113. end
  114. end
  115. end
  116. end
  117. end
  118. end
  119. -- Register our handlers only once.
  120. if not ambiance.registered then
  121. -- Store data per-player.
  122. minetest.register_on_joinplayer(function(player)
  123. local pname = player:get_player_name()
  124. ambiance.players[pname] = {}
  125. end)
  126. minetest.register_on_leaveplayer(function(player)
  127. ambiance.players[player:get_player_name()] = nil
  128. end)
  129. minetest.register_globalstep(function(...) return ambiance.globalstep(...) end)
  130. minetest.register_globalstep(function(...) return ambiance.globalstep_scuba(...) end)
  131. ambiance.registered = true
  132. end
  133. -- Register everything as reloadable.
  134. if minetest.get_modpath("reload") then
  135. local c = "ambiance:core"
  136. local f = ambiance.modpath .. "/init.lua"
  137. if not reload.file_registered(c) then
  138. reload.register_file(c, f, false)
  139. end
  140. end