-- Parameters

-- Node search radius around player
local radius = 8

-- cache local copy of pairs to reduce call time.
local pairs = pairs

local allsounds = {
	["env_sounds_water"] = {
		trigger = {
			"mcl_core:water_flowing",
			"mclx_core:river_water_flowing"
		},
		base_volume = 0.04,
		max_volume = 0.4,
		per_node = 0.004,
	},
	["env_sounds_lava"] = {
		trigger = {
            "mcl_core:lava_source",
            "mcl_core:lava_flowing"
        },
		base_volume = 0.08,
		max_volume = 0.6,
--		per_node = 0.004,
		per_node = {
			["mcl_core:lava_source"] = 0.008,
			["mcl_core:lava_flowing"] = 0.002,
		},

	},
}


-- 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 = core.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)

			core.sound_play(sound, {
				pos = posav,
				to_player = player_name,
				gain = gain,
			}, true)
		end
	end
end


-- Update sound when player joins
core.register_on_joinplayer(update_sound)

-- Cyclic sound update

local function cyclic_update()
	for _, player in pairs(core.get_connected_players()) do
		update_sound(player)
	end
	core.after(3.5, cyclic_update)
end

core.after(0, cyclic_update)

-- TODO: profile this code on a MP server to see if it causes lag.
