init.lua 4.4 KB

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