Fix dynamic media race condition
Wait for *all* players to receive the texture before using it. Previously this would wait for *any* player to receive the texture. This works fine in singleplayer (or on pre-5.5, where dynamic_add_media would block until all players have received the texture), but it may fail otherwise: Either entity textures won't be available in time, or, even worse, the HUD texture is unavailable. Both produce an error in chat for clients.
This commit is contained in:
parent
4fa5c94515
commit
df5bd3c4ec
|
@ -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
|
||||||
|
)
|
22
init.lua
22
init.lua
|
@ -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
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue