From 452102cc7cc0928ac6fd13075994f6b4c8fc2568 Mon Sep 17 00:00:00 2001 From: Vanessa Dannenberg Date: Mon, 20 Aug 2018 19:25:53 -0400 Subject: [PATCH] use printable strings for color codes instead of string.char(0-27), use "/" as an escape followed by "[0-9][A-R][a-r]", all inside the string. e.g. digiline_send("chan", "/0this /1is /2some /3colorful /4text") "/" followed by any other character than the above will be treated as an invalid color code and will be taken literally. "//" will print a single slash. Note: on receipt, all instances of "//" in a message are actually translated to string.char(30) -- one for each pair. This makes the scrolling code easier. Keep this in mind if you use the "getstr" and "getindex" commands. Also, this expands the max string length to 6 kB, to allow a full 80x25 display with one color code er character. "clear" and "allon" remain at 2kB since that's still enough. --- init.lua | 135 ++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 109 insertions(+), 26 deletions(-) diff --git a/init.lua b/init.lua index 5bfc1e0..b0d1715 100644 --- a/init.lua +++ b/init.lua @@ -10,6 +10,68 @@ else S = function(s) return s end end +local color_to_char = { + "0", + "1", + "2", + "3", + "4", + "5", + "6", + "7", + "8", + "9", + "A", + "B", + "C", + "D", + "E", + "F", + "G", + "H", + "I", + "J", + "K", + "L", + "M", + "N", + "O", + "P", + "Q", + "R" +} + +local char_to_color = { + ["0"] = 0, + ["1"] = 1, + ["2"] = 2, + ["3"] = 3, + ["4"] = 4, + ["5"] = 5, + ["6"] = 6, + ["7"] = 7, + ["8"] = 8, + ["9"] = 9, + ["A"] = 10, + ["B"] = 11, + ["C"] = 12, + ["D"] = 13, + ["E"] = 14, + ["F"] = 15, + ["G"] = 16, + ["H"] = 17, + ["I"] = 18, + ["J"] = 19, + ["K"] = 20, + ["L"] = 21, + ["M"] = 22, + ["N"] = 23, + ["O"] = 24, + ["P"] = 25, + ["Q"] = 26, + ["R"] = 27 +} + -- the following functions based on the so-named ones in Jeija's digilines mod local reset_meta = function(pos) @@ -71,31 +133,35 @@ led_marquee.scroll_text = function(pos, elapsed, skip) local msg = meta:get_string("last_msg") local channel = meta:get_string("channel") local index = meta:get_int("index") + local color = meta:get_int("last_color") + local colorchar = color_to_char[color+1] 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 + -- search backward to find the most recent color code in the string + local r = index + while r > 0 and not string.match(string.sub(msg, r, r+1), "/[0-9A-Ra-r]") do + r = r - 1 + end + if r == 0 then r = 1 end + if string.match(string.sub(msg, r, r+1), "/[0-9A-Ra-r]") then + colorchar = string.sub(msg, r+1, r+1) 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 + -- search forward to find the next printable symbol after the current index + local f = index + while f < len do + if string.match(string.sub(msg, f, f+1), "/[0-9A-Ra-r]") then + f = f + 2 + else + break 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) + led_marquee.display_msg(pos, channel, "/"..colorchar..string.sub(msg, f)..string.rep(" ", skip + 1)) + meta:set_int("index", f) if not elapsed or elapsed < 0.5 then return false end return true end @@ -118,10 +184,14 @@ local cbox = { wall_side = { -8/16, -8/16, -8/16, -7/16, 8/16, 8/16 } } +led_marquee.decode_color = function(msg) + +end + led_marquee.display_msg = function(pos, channel, msg) - msg = string.sub(msg, 1, 4096) + msg = string.sub(msg, 1, 6144).." " if string.sub(msg,1,1) == string.char(255) then -- treat it as incoming UTF-8 - msg = make_iso(string.sub(msg, 2, 4096)) + msg = make_iso(string.sub(msg, 2, 6144)) end local master_fdir = minetest.get_node(pos).param2 % 8 @@ -168,17 +238,32 @@ led_marquee.display_msg = function(pos, channel, msg) pos2.z = pos.z + (fdir_to_right[fdir+1][2])*c i = i + 3 wrapped = nil + elseif asc == 30 then -- translate to slash for printing + minetest.swap_node(pos2, { name = "led_marquee:char_47", param2 = master_fdir + (last_color*8)}) + pos2.x = pos2.x + fdir_to_right[fdir+1][1] + pos2.z = pos2.z + fdir_to_right[fdir+1][2] + i = i + 1 + elseif asc == 47 then -- slash + local ccode = string.sub(msg, i+1, i+1) + if ccode then + if char_to_color[ccode] then + last_color = char_to_color[ccode] + i = i + 2 + else + minetest.swap_node(pos2, { name = "led_marquee:char_47", param2 = master_fdir + (last_color*8)}) + pos2.x = pos2.x + fdir_to_right[fdir+1][1] + pos2.z = pos2.z + fdir_to_right[fdir+1][2] + i = i + 1 + end + end + master_meta:set_int("last_color", last_color) + wrapped = nil elseif asc > 30 and asc < 256 then minetest.swap_node(pos2, { name = "led_marquee:char_"..asc, param2 = master_fdir + (last_color*8)}) pos2.x = pos2.x + fdir_to_right[fdir+1][1] pos2.z = pos2.z + fdir_to_right[fdir+1][2] i = i + 1 wrapped = nil - elseif asc < 28 then - last_color = asc - master_meta:set_int("last_color", asc) - i = i + 1 - wrapped = nil end end end @@ -230,6 +315,7 @@ local on_digiline_receive_string = function(pos, node, channel, msg) elseif msg == "getindex" then -- get the scroll index digilines.receptor_send(pos, digiline.rules.default, channel, meta:get_int("index")) else + msg = string.gsub(msg, "//", string.char(30)) led_marquee.set_timer(pos, 0) meta:set_string("last_msg", msg) led_marquee.display_msg(pos, channel, msg) @@ -237,13 +323,10 @@ local on_digiline_receive_string = function(pos, node, channel, msg) end else local asc = string.byte(msg) - if asc > 30 and asc < 256 then + if asc > 29 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) end end elseif msg and type(msg) == "number" then