Fix dynamic media race condition #2

Open
appgurueu wants to merge 1 commits from appgurueu/xmaps:master into master
2 changed files with 68 additions and 17 deletions

63
dynamic_add_media_all.lua Normal file
View File

@ -0,0 +1,63 @@
local on_leaves = {} -- functions(name)
local timeout = 5 -- seconds
xmaps.dynamic_add_media_all = function(path, on_all_received)
if not minetest.features.dynamic_add_media_table then
-- minetest.dynamic_add_media() blocks in
-- Minetest 5.3 and 5.4 until media loads
minetest.dynamic_add_media(path, function() end)
on_all_received()
return
end
-- minetest.dynamic_add_media() never blocks
-- in Minetest 5.5, callback runs *for each client*
-- who has received & loaded the media
-- all players currently online must still receive it
local to_receive = {}
for _, player in pairs(minetest.get_connected_players()) do
local name = player:get_player_name()
-- Only clients with protocol version >= 39 can receive dynamic media.
if minetest.get_player_information(name).protocol_version >= 39 then
to_receive[name] = true
end
end
local function remove_to_receive(name)
to_receive[name] = nil
if next(to_receive) == nil then
on_leaves[remove_to_receive] = nil
on_all_received()
end
end
on_leaves[remove_to_receive] = true
minetest.dynamic_add_media(
{filepath = path},
function(name)
assert(name)
if not to_receive[name] then
minetest.log("warning", ("xmaps: %s received media despite not being connected"):format(name))
return
end
remove_to_receive(name)
end
)
minetest.after(timeout, function()
if next(to_receive) ~= nil then
local names = {}
for name in pairs(to_receive) do
table.insert(names, name)
end
table.sort(names)
minetest.log("warning", ("xmaps: sending media to %s timed out"):format(table.concat(names, ", ")))
end
on_leaves[remove_to_receive] = nil
on_all_received()
end)
end
minetest.register_on_leaveplayer(
function(player)
local player_name = player:get_player_name()
for on_leave in pairs(on_leaves) do
on_leave(player_name)
end
end
)

View File

@ -48,6 +48,8 @@ end
xmaps = {} xmaps = {}
dofile(minetest.get_modpath(minetest.get_current_modname()) .. "/dynamic_add_media_all.lua")
xmaps.dark = {} -- key: player name; value: is it dark? xmaps.dark = {} -- key: player name; value: is it dark?
xmaps.huds = {} -- key: player name; value: player huds xmaps.huds = {} -- key: player name; value: player huds
xmaps.maps = {} -- key: player name; value: map texture xmaps.maps = {} -- key: player name; value: map texture
@ -393,26 +395,12 @@ xmaps.load_map = function(map_id)
end end
local filename = xmaps.get_map_filename(map_id) local filename = xmaps.get_map_filename(map_id)
local path = textures_dir .. filename
if not xmaps.sent[map_id] then if not xmaps.sent[map_id] then
if not minetest.features.dynamic_add_media_table then xmaps.dynamic_add_media_all(path, function()
-- minetest.dynamic_add_media() blocks in
-- Minetest 5.3 and 5.4 until media loads
minetest.dynamic_add_media(
textures_dir .. filename,
function() end
)
xmaps.load[map_id] = true xmaps.load[map_id] = true
else end)
-- minetest.dynamic_add_media() never blocks
-- in Minetest 5.5, callback runs after load
minetest.dynamic_add_media(
textures_dir .. filename,
function()
xmaps.load[map_id] = true
end
)
end
xmaps.sent[map_id] = true xmaps.sent[map_id] = true
end end