diff options
Diffstat (limited to 'led_marquee/init.lua')
-rw-r--r-- | led_marquee/init.lua | 135 |
1 files changed, 100 insertions, 35 deletions
diff --git a/led_marquee/init.lua b/led_marquee/init.lua index f60dfbd..5bfc1e0 100644 --- a/led_marquee/init.lua +++ b/led_marquee/init.lua @@ -1,6 +1,8 @@ -- simple LED marquee mod -- by Vanessa Dannenberg +led_marquee = {} + local S if minetest.get_modpath("intllib") then S = intllib.make_gettext_pair() @@ -53,6 +55,51 @@ local make_iso = function(s) return s2 end +-- scrolling + +led_marquee.set_timer = function(pos, timeout) + local timer = minetest.get_node_timer(pos) + timer:stop() + if timeout > 0 then + local meta = minetest.get_meta(pos) + timer:start(timeout) + end +end + +led_marquee.scroll_text = function(pos, elapsed, skip) + local meta = minetest.get_meta(pos) + local msg = meta:get_string("last_msg") + local channel = meta:get_string("channel") + local index = meta:get_int("index") + if not index or index < 1 or not string.byte(msg, index) then index = 1 end + local len = string.len(msg) + skip = skip or 1 + + index = index + skip + + while index < len and string.byte(msg, index) < 28 do + index = index + 1 + if index > len then index = 1 break end + end + + if string.byte(msg, index - 1) < 28 then + led_marquee.display_msg(pos, channel, string.sub(msg, index - 1)..string.rep(" ", skip + 1)) + else + local i = index - 1 + local color = "" + while i > 0 and string.byte(msg, i) > 27 do + i = i - 1 + if i == 0 then break end + end + if i > 0 then color = string.sub(msg, i, i) end + led_marquee.display_msg(pos, channel, color..string.sub(msg, index)..string.rep(" ", skip + 1)) + end + + meta:set_int("index", index) + if not elapsed or elapsed < 0.5 then return false end + return true +end + -- the nodes: local fdir_to_right = { @@ -71,14 +118,10 @@ local cbox = { wall_side = { -8/16, -8/16, -8/16, -7/16, 8/16, 8/16 } } -local display_string = function(pos, channel, string) - string = string.sub(string, 1, 1024) - if string == "off_multi" then - string = string.rep(" ", 1024) - elseif string == "allon_multi" then - string = string.rep(string.char(144), 1024) - elseif string.sub(string,1,1) == string.char(255) then -- treat it as incoming UTF-8 - string = make_iso(string.sub(string, 2, 1024)) +led_marquee.display_msg = function(pos, channel, msg) + msg = string.sub(msg, 1, 4096) + if string.sub(msg,1,1) == string.char(255) then -- treat it as incoming UTF-8 + msg = make_iso(string.sub(msg, 2, 4096)) end local master_fdir = minetest.get_node(pos).param2 % 8 @@ -90,7 +133,7 @@ local display_string = function(pos, channel, string) master_meta:set_int("last_color", 0) end local i = 1 - local len = string.len(string) + local len = string.len(msg) local wrapped = nil while i <= len do local node = minetest.get_node(pos2) @@ -98,7 +141,7 @@ local display_string = function(pos, channel, string) local meta = minetest.get_meta(pos2) local setchan = nil if meta then setchan = meta:get_string("channel") end - local asc = string.byte(string, i, i) + local asc = string.byte(msg, i, i) if not string.match(node.name, "led_marquee:char_") then if not wrapped then pos2.x = pos.x @@ -118,8 +161,8 @@ local display_string = function(pos, channel, string) i = i + 1 wrapped = nil elseif asc == 29 then - local c = string.byte(string, i+1, i+1) or 0 - local r = string.byte(string, i+2, i+2) or 0 + local c = string.byte(msg, i+1, i+1) or 0 + local r = string.byte(msg, i+2, i+2) or 0 pos2.x = pos.x + (fdir_to_right[fdir+1][1])*c pos2.y = pos.y - r pos2.z = pos.z + (fdir_to_right[fdir+1][2])*c @@ -153,43 +196,65 @@ local on_digiline_receive_string = function(pos, node, channel, msg) if setchan ~= channel then return end if msg and msg ~= "" and type(msg) == "string" then if string.len(msg) > 1 then - if msg == "off" then - minetest.swap_node(pos, { name = "led_marquee:char_32", param2 = fdir + (last_color*8)}) - elseif msg == "colon" then - minetest.swap_node(pos, { name = "led_marquee:char_58", param2 = fdir + (last_color*8)}) - elseif msg == "period" then - minetest.swap_node(pos, { name = "led_marquee:char_46", param2 = fdir + (last_color*8)}) - elseif msg == "del" then - minetest.swap_node(pos, { name = "led_marquee:char_127", param2 = fdir + (last_color*8)}) + if msg == "clear" then + led_marquee.set_timer(pos, 0) + msg = string.rep(" ", 2048) + meta:set_string("last_msg", msg) + led_marquee.display_msg(pos, channel, msg) + meta:set_int("index", 1) elseif msg == "allon" then - minetest.swap_node(pos, { name = "led_marquee:char_144", param2 = fdir + (last_color*8)}) - elseif msg == "cursor" then - minetest.swap_node(pos, { name = "led_marquee:char_31", param2 = fdir + (last_color*8)}) + led_marquee.set_timer(pos, 0) + msg = string.rep(string.char(144), 2048) + meta:set_string("last_msg", msg) + led_marquee.display_msg(pos, channel, msg) + meta:set_int("index", 1) + elseif msg == "start_scroll" then + local timeout = meta:get_int("timeout") + if not timeout or timeout < 0.5 or timeout > 5 then timeout = 0 end + led_marquee.set_timer(pos, timeout) + elseif msg == "stop_scroll" then + led_marquee.set_timer(pos, 0) + return + elseif string.sub(msg, 1, 12) == "scroll_speed" then + local timeout = tonumber(string.sub(msg, 13)) + if not timeout or timeout < 0.5 or timeout > 5 then timeout = 0 end + meta:set_int("timeout", timeout) + led_marquee.set_timer(pos, timeout) + elseif string.sub(msg, 1, 11) == "scroll_step" then + local skip = tonumber(string.sub(msg, 12)) + led_marquee.scroll_text(pos, nil, skip) + elseif msg == "get" then -- get the master panel's displayed char as ASCII numerical value + digilines.receptor_send(pos, digiline.rules.default, channel, tonumber(string.match(minetest.get_node(pos).name,"led_marquee:char_(.+)"))) -- wonderfully horrible string manipulaiton + elseif msg == "getstr" then -- get the last stored message + digilines.receptor_send(pos, digiline.rules.default, channel, meta:get_string("last_msg")) + elseif msg == "getindex" then -- get the scroll index + digilines.receptor_send(pos, digiline.rules.default, channel, meta:get_int("index")) else - display_string(pos, channel, msg) + led_marquee.set_timer(pos, 0) + meta:set_string("last_msg", msg) + led_marquee.display_msg(pos, channel, msg) + meta:set_int("index", 1) end else local asc = string.byte(msg) if asc > 30 and asc < 256 then minetest.swap_node(pos, { name = "led_marquee:char_"..asc, param2 = fdir + (last_color*8)}) + meta:set_string("last_msg", tostring(msg)) + meta:set_int("index", 1) elseif asc < 28 then last_color = asc meta:set_int("last_color", asc) - elseif msg == "get" then -- get value as ASCII numerical value - digiline:receptor_send(pos, digiline.rules.default, channel, tonumber(string.match(minetest.get_node(pos).name,"led_marquee:char_(.+)"))) -- wonderfully horrible string manipulaiton - elseif msg == "getstr" then -- get actual char - digiline:receptor_send(pos, digiline.rules.default, channel, string.char(tonumber(string.match(minetest.get_node(pos).name,"led_marquee:char_(.+)")))) end end elseif msg and type(msg) == "number" then - if msg == 0 then - minetest.swap_node(pos, { name = "led_marquee:char_32", param2 = fdir + (last_color*8)}) - elseif msg > 30 then - minetest.swap_node(pos, { name = "led_marquee:char_"..tostring(msg), param2 = fdir + (last_color*8)}) - end + meta:set_string("last_msg", tostring(msg)) + led_marquee.display_msg(pos, channel, tostring(msg)) + meta:set_int("index", 1) end end +-- the nodes! + for i = 31, 255 do local groups = { cracky = 2, not_in_creative_inventory = 1} local light = LIGHT_MAX-2 @@ -244,13 +309,13 @@ for i = 31, 255 do action = on_digiline_receive_string, }, }, - drop = "led_marquee:char_32" + drop = "led_marquee:char_32", + on_timer = led_marquee.scroll_text }) end -- crafts - minetest.register_craft({ output = "led_marquee:char_32 6", recipe = { |