Add lag mitigation

All messages sent to the displays are firstr enqueued, then "played
back" on globalstep, similar to biome_lib's deferred-generation method.

By default, no more than 10 messages will be added to the queue.  If the
queue should exceed that, old messages will be deleted to make room for
new messages.

Messages will be pulled from the queue, one item per server tick, in the
order received, and relayed to their displays, if dtime <= 0.2s.  If
dtime is greater, messages will be withheld until it decreases.

Autoscroll now limits the speed to 0.5s per step.
This commit is contained in:
Vanessa Dannenberg 2019-08-21 18:40:08 -04:00
parent 8d3a0e92de
commit 45c89704f0

@ -2,6 +2,13 @@
-- by Vanessa Dannenberg -- by Vanessa Dannenberg
led_marquee = {} led_marquee = {}
led_marquee.scheduled_messages = {}
led_marquee.message_minimum_time = tonumber(minetest.settings:get("led_marquee_message_minimum_time")) or 0.5
led_marquee.message_schedule_dtime = tonumber(minetest.settings:get("led_marquee_message_schedule_dtime")) or 0.2
led_marquee.message_schedule_size = tonumber(minetest.settings:get("led_marquee_message_schedule_size")) or 10
led_marquee.relay_timer = 0
local S local S
if minetest.get_modpath("intllib") then if minetest.get_modpath("intllib") then
@ -148,7 +155,7 @@ end
led_marquee.set_timer = function(pos, timeout) led_marquee.set_timer = function(pos, timeout)
local timer = minetest.get_node_timer(pos) local timer = minetest.get_node_timer(pos)
timer:stop() timer:stop()
if not timeout or timeout < 0.2 or timeout > 5 then return false end if not timeout or timeout < led_marquee.message_minimum_time or timeout > 5 then return false end
if timeout > 0 then if timeout > 0 then
local meta = minetest.get_meta(pos) local meta = minetest.get_meta(pos)
@ -189,7 +196,7 @@ led_marquee.scroll_text = function(pos, elapsed, skip)
break break
end end
end end
led_marquee.display_msg(pos, channel, "/"..colorchar..string.sub(msg, f)..string.rep(" ", skip + 1)) led_marquee.schedule_msg(pos, channel, "/"..colorchar..string.sub(msg, f)..string.rep(" ", skip + 1))
meta:set_int("index", f) meta:set_int("index", f)
if not elapsed or elapsed < 0.2 then return false end if not elapsed or elapsed < 0.2 then return false end
@ -218,6 +225,27 @@ led_marquee.decode_color = function(msg)
end end
minetest.register_globalstep(function(dtime)
if dtime <= led_marquee.message_schedule_dtime
and (#led_marquee.scheduled_messages) > 0 then
led_marquee.display_msg(
led_marquee.scheduled_messages[1].pos,
led_marquee.scheduled_messages[1].channel,
led_marquee.scheduled_messages[1].msg
)
end
table.remove(led_marquee.scheduled_messages, 1)
end)
led_marquee.schedule_msg = function(pos, channel, msg)
local idx = #led_marquee.scheduled_messages
led_marquee.scheduled_messages[idx+1] = { pos=pos, channel=channel, msg=msg }
if idx >= led_marquee.message_schedule_size then
table.remove(led_marquee.scheduled_messages, 1)
end
end
led_marquee.display_msg = function(pos, channel, msg) led_marquee.display_msg = function(pos, channel, msg)
msg = string.sub(msg, 1, 6144).." " msg = string.sub(msg, 1, 6144).." "
if string.sub(msg,1,1) == string.char(255) then -- treat it as incoming UTF-8 if string.sub(msg,1,1) == string.char(255) then -- treat it as incoming UTF-8
@ -317,13 +345,13 @@ local on_digiline_receive_string = function(pos, node, channel, msg)
led_marquee.set_timer(pos, 0) led_marquee.set_timer(pos, 0)
msg = string.rep(" ", 2048) msg = string.rep(" ", 2048)
meta:set_string("last_msg", msg) meta:set_string("last_msg", msg)
led_marquee.display_msg(pos, channel, msg) led_marquee.schedule_msg(pos, channel, msg)
meta:set_int("index", 1) meta:set_int("index", 1)
elseif msg == "allon" then elseif msg == "allon" then
led_marquee.set_timer(pos, 0) led_marquee.set_timer(pos, 0)
msg = string.rep(string.char(144), 2048) msg = string.rep(string.char(144), 2048)
meta:set_string("last_msg", msg) meta:set_string("last_msg", msg)
led_marquee.display_msg(pos, channel, msg) led_marquee.schedule_msg(pos, channel, msg)
meta:set_int("index", 1) meta:set_int("index", 1)
elseif msg == "start_scroll" then elseif msg == "start_scroll" then
local timeout = meta:get_int("timeout") local timeout = meta:get_int("timeout")
@ -333,7 +361,7 @@ local on_digiline_receive_string = function(pos, node, channel, msg)
return return
elseif string.sub(msg, 1, 12) == "scroll_speed" then elseif string.sub(msg, 1, 12) == "scroll_speed" then
local timeout = tonumber(string.sub(msg, 13)) local timeout = tonumber(string.sub(msg, 13))
led_marquee.set_timer(pos, timeout) led_marquee.set_timer(pos, math.max(timeout, led_marquee.message_minimum_time))
elseif string.sub(msg, 1, 11) == "scroll_step" then elseif string.sub(msg, 1, 11) == "scroll_step" then
local skip = tonumber(string.sub(msg, 12)) local skip = tonumber(string.sub(msg, 12))
led_marquee.scroll_text(pos, nil, skip) led_marquee.scroll_text(pos, nil, skip)
@ -348,7 +376,7 @@ local on_digiline_receive_string = function(pos, node, channel, msg)
led_marquee.set_timer(pos, 0) led_marquee.set_timer(pos, 0)
local last_msg = meta:get_string("last_msg") local last_msg = meta:get_string("last_msg")
meta:set_string("last_msg", msg) meta:set_string("last_msg", msg)
led_marquee.display_msg(pos, channel, msg) led_marquee.schedule_msg(pos, channel, msg)
if last_msg ~= msg then if last_msg ~= msg then
meta:set_int("index", 1) meta:set_int("index", 1)
end end
@ -363,7 +391,7 @@ local on_digiline_receive_string = function(pos, node, channel, msg)
end end
elseif msg and type(msg) == "number" then elseif msg and type(msg) == "number" then
meta:set_string("last_msg", tostring(msg)) meta:set_string("last_msg", tostring(msg))
led_marquee.display_msg(pos, channel, tostring(msg)) led_marquee.schedule_msg(pos, channel, tostring(msg))
meta:set_int("index", 1) meta:set_int("index", 1)
end end
end end