rubenwardy wrote:For each loaded map block,
rubenwardy wrote:Try disabling catch up in the abm definition
Hybrid Dog wrote:l can't, it's locked because of content of SME
paramat wrote:Also, ABMs are active for nodes up to 32 nodes (2 mapblocks) from a player, this range is definable in .conf.
paramat wrote:Ambience sounds by ABM may be a good method, the fire sounds implementation in the fire mod is hacky, heavy and buggy, not a good example, it needs improving.
for _,player in ipairs(minetest.get_connected_players()) do
local ppos = player:getpos()
-- no new sounds if player is underground. Should use heightmap
if ppos.y < 0 then return end
end
-- don't play ocean sounds in a puddle
local node1 = minetest.get_node({x=pos.x, y=pos.y, z=pos.z-10})
local node2 = minetest.get_node({x=pos.x, y=pos.y, z=pos.z+10})
local node3 = minetest.get_node({x=pos.x-10, y=pos.y, z=pos.z})
local node4 = minetest.get_node({x=pos.x+10, y=pos.y, z=pos.z})
-- skip some ABM calls and play sounds only at sea level
if ocean_sound_timer > 8 and pos.y == 1
and node1.name == "default:water_source"
and node2.name == "default:water_source"
and node3.name == "default:water_source"
and node4.name == "default:water_source" then
minetest.sound_play("ambplus_ocean", {
pos = pos,
catch_up = false,
max_hear_distance = 60,
gain = 1.5,
})
ocean_sound_timer = 0
end
ocean_sound_timer = ocean_sound_timer + os.clock() - ocean_sound_last_time
ocean_sound_last_time = os.clock()
local player_on_ocean
local function is_player_on_ocean()
if player_on_ocean ~= nil then
return player_on_ocean
end
minetest.after(0.3, function()
player_on_ocean = nil
end)
-- no new sounds if player is underground. Should use heightmap
for _,player in ipairs(minetest.get_connected_players()) do
local ppos = player:getpos()
if ppos.y > 0 then
player_on_ocean = true
return true
end
end
player_on_ocean = false
return false
end
-- don't play ocean sounds in a puddle
local function get_approximate_pos(pos)
return {
x = math.floor(pos.x/5+0.5)*5,
y = 1,--math.floor(pos.y/3)*3,
z = math.floor(pos.z/5+0.5)*5
}
end
local known_water,known_removing = {}
local function get_water(pos)
pos = get_approximate_pos(pos)
local vi = minetest.hash_node_position(pos)
local is_water = known_water[vi]
if is_water ~= nil then
return is_water
end
is_water = minetest.get_node(pos).name == "default:water_source"
known_water[vi] = is_water
if not known_removing then
known_removing = true
minetest.after(3, function()
known_removing = false
known_water = {}
end)
end
return is_water
end
local function is_ocean(pos)
return get_water({x=pos.x, y=pos.y, z=pos.z-10})
and get_water({x=pos.x, y=pos.y, z=pos.z+10})
and get_water({x=pos.x-10, y=pos.y, z=pos.z})
and get_water({x=pos.x+10, y=pos.y, z=pos.z})
end
local ocean_sound_interval = 8 *1000000
local ocean_sound_last_time = minetest.get_us_time() - ocean_sound_interval
minetest.register_abm({
-- only nodes at the surface
nodenames = {"default:water_source"},
neighbors = {"default:air"},
interval = 20,
chance = 100,
action = function(pos, node)
if pos.y ~= 1 then
return
end
-- play sound only every 8 seconds
local time = minetest.get_us_time()
if time - ocean_sound_last_time < ocean_sound_interval then
return
end
if not is_player_on_ocean()
or not is_ocean(pos) then
return
end
minetest.sound_play("ambplus_ocean", {
pos = pos,
catch_up = false,
max_hear_distance = 60,
gain = 1.5,
})
ocean_sound_last_time = time
end,
})
Hybrid Dog wrote:This only works correctly with just one player (e.g. in singleplayer mode) because it aborts the abm even if only one player is below 0.
And it can be cached if players are above 0, so it would test this only one time, not 50 times.
Hybrid Dog wrote:Here minetest.get_node is executed 4 times (cumulatively 200 times at once every 100 seconds) even if it's not needed.
Hybrid Dog wrote:l don't know if minetest.sound_play supports the catch_up field.
Hybrid Dog wrote:os.clock shouldn't be used here because it measures the cpu time, minetest.get_us_time can be used here l think. ln my benchmark test minetest.get_us_time worked faster than os.clock.
Hybrid Dog wrote:l changed the code, l'm not sure if l did mistakes:
if not is_player_on_ocean()
burli wrote:Edit:Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
- Code: Select all
if not is_player_on_ocean()
Ocean sounds should be played even if the player is not in the ocean. I like the idea to hear the ocean before you see him, e.g. if you are in a forest
Hybrid Dog wrote:l tried to make it use minetest.get_node infrequently, so it looks for water at approximate positions and it uses minetest.get_node only if it isn't used there yet, else it returns its previous result, after three seconds the cache gets removed because the water may possibly be removed, which should stop playing sounds there.
ocean_sound_timer = 1
minetest.register_abm({
nodenames = {"default:water_source"},
neighbors = {"air"},
interval = 10,
chance = 250,
action = function(pos, node, active_object_count, active_object_count_wider)
if ocean_sound_timer == 1 then
minetest.after(1, function()
--print(dump(nodelist[math.random(1, #nodelist)]))
minetest.set_node(nodelist[math.random(1, #nodelist)], {name="default:meselamp"})
ocean_sound_timer = 1
nodelist = {}
end)
ocean_sound_timer = 0
table.insert(nodelist, pos)
else
table.insert(nodelist, pos)
end
end
Hi, my username is azekill_DIABLO and i'm an exelent bug-maker(yeah...i know...i have a bad reputation)
Users browsing this forum: No registered users and 7 guests