mirror of
				https://github.com/luanti-org/minetest_game.git
				synced 2025-10-31 23:55:20 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			113 lines
		
	
	
		
			2.4 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
			
		
		
	
	
			113 lines
		
	
	
		
			2.4 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
| -- Parameters
 | |
| 
 | |
| -- Node search radius around player
 | |
| local radius = 8
 | |
| 
 | |
| local allsounds = {
 | |
| 	["env_sounds_water"] = {
 | |
| 		trigger = {"default:water_flowing", "default:river_water_flowing"},
 | |
| 		base_volume = 0.04,
 | |
| 		max_volume = 0.4,
 | |
| 		per_node = 0.004,
 | |
| 	},
 | |
| 	["env_sounds_lava"] = {
 | |
| 		trigger = {"default:lava_source", "default:lava_flowing"},
 | |
| 		base_volume = 0,
 | |
| 		max_volume = 0.6,
 | |
| 		per_node = {
 | |
| 			["default:lava_source"] = 0.008,
 | |
| 			["default:lava_flowing"] = 0.002,
 | |
| 		},
 | |
| 	},
 | |
| }
 | |
| 
 | |
| if minetest.settings:get_bool("river_source_sounds") then
 | |
| 	table.insert(allsounds["env_sounds_water"].trigger,
 | |
| 		"default:river_water_source")
 | |
| end
 | |
| 
 | |
| 
 | |
| -- Cache the union of all trigger nodes
 | |
| 
 | |
| local cache_triggers = {}
 | |
| 
 | |
| for sound, def in pairs(allsounds) do
 | |
| 	for _, name in ipairs(def.trigger) do
 | |
| 		table.insert(cache_triggers, name)
 | |
| 	end
 | |
| end
 | |
| 
 | |
| 
 | |
| -- Update sound for player
 | |
| 
 | |
| local function update_sound(player)
 | |
| 	local player_name = player:get_player_name()
 | |
| 	local ppos = player:get_pos()
 | |
| 	ppos = vector.add(ppos, player:get_properties().eye_height)
 | |
| 	local areamin = vector.subtract(ppos, radius)
 | |
| 	local areamax = vector.add(ppos, radius)
 | |
| 
 | |
| 	local pos = minetest.find_nodes_in_area(areamin, areamax, cache_triggers, true)
 | |
| 	if next(pos) == nil then -- If table empty
 | |
| 		return
 | |
| 	end
 | |
| 	for sound, def in pairs(allsounds) do
 | |
| 		-- Find average position
 | |
| 		local posav = {0, 0, 0}
 | |
| 		local count = 0
 | |
| 		for _, name in ipairs(def.trigger) do
 | |
| 			if pos[name] then
 | |
| 				for _, p in ipairs(pos[name]) do
 | |
| 					posav[1] = posav[1] + p.x
 | |
| 					posav[2] = posav[2] + p.y
 | |
| 					posav[3] = posav[3] + p.z
 | |
| 				end
 | |
| 				count = count + #pos[name]
 | |
| 			end
 | |
| 		end
 | |
| 
 | |
| 		if count > 0 then
 | |
| 			posav = vector.new(posav[1] / count, posav[2] / count,
 | |
| 				posav[3] / count)
 | |
| 
 | |
| 			-- Calculate gain
 | |
| 			local gain = def.base_volume
 | |
| 			if type(def.per_node) == 'table' then
 | |
| 				for name, multiplier in pairs(def.per_node) do
 | |
| 					if pos[name] then
 | |
| 						gain = gain + #pos[name] * multiplier
 | |
| 					end
 | |
| 				end
 | |
| 			else
 | |
| 				gain = gain + count * def.per_node
 | |
| 			end
 | |
| 			gain = math.min(gain, def.max_volume)
 | |
| 
 | |
| 			minetest.sound_play(sound, {
 | |
| 				pos = posav,
 | |
| 				to_player = player_name,
 | |
| 				gain = gain,
 | |
| 			}, true)
 | |
| 		end
 | |
| 	end
 | |
| end
 | |
| 
 | |
| 
 | |
| -- Update sound when player joins
 | |
| 
 | |
| minetest.register_on_joinplayer(function(player)
 | |
| 	update_sound(player)
 | |
| end)
 | |
| 
 | |
| 
 | |
| -- Cyclic sound update
 | |
| 
 | |
| local function cyclic_update()
 | |
| 	for _, player in pairs(minetest.get_connected_players()) do
 | |
| 		update_sound(player)
 | |
| 	end
 | |
| 	minetest.after(3.5, cyclic_update)
 | |
| end
 | |
| 
 | |
| minetest.after(0, cyclic_update)
 |