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.
This commit is contained in:
Vanessa Dannenberg 2018-08-20 19:25:53 -04:00
parent bee8d5c32d
commit 452102cc7c

135
init.lua

@ -10,6 +10,68 @@ else
S = function(s) return s end S = function(s) return s end
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 -- the following functions based on the so-named ones in Jeija's digilines mod
local reset_meta = function(pos) 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 msg = meta:get_string("last_msg")
local channel = meta:get_string("channel") local channel = meta:get_string("channel")
local index = meta:get_int("index") 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 if not index or index < 1 or not string.byte(msg, index) then index = 1 end
local len = string.len(msg) local len = string.len(msg)
skip = skip or 1 skip = skip or 1
index = index + skip index = index + skip
while index < len and string.byte(msg, index) < 28 do -- search backward to find the most recent color code in the string
index = index + 1 local r = index
if index > len then index = 1 break end 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 end
if string.byte(msg, index - 1) < 28 then -- search forward to find the next printable symbol after the current index
led_marquee.display_msg(pos, channel, string.sub(msg, index - 1)..string.rep(" ", skip + 1)) local f = index
else while f < len do
local i = index - 1 if string.match(string.sub(msg, f, f+1), "/[0-9A-Ra-r]") then
local color = "" f = f + 2
while i > 0 and string.byte(msg, i) > 27 do else
i = i - 1 break
if i == 0 then break end
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 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 if not elapsed or elapsed < 0.5 then return false end
return true return true
end end
@ -118,10 +184,14 @@ local cbox = {
wall_side = { -8/16, -8/16, -8/16, -7/16, 8/16, 8/16 } 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) 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 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 end
local master_fdir = minetest.get_node(pos).param2 % 8 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 pos2.z = pos.z + (fdir_to_right[fdir+1][2])*c
i = i + 3 i = i + 3
wrapped = nil 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 elseif asc > 30 and asc < 256 then
minetest.swap_node(pos2, { name = "led_marquee:char_"..asc, param2 = master_fdir + (last_color*8)}) 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.x = pos2.x + fdir_to_right[fdir+1][1]
pos2.z = pos2.z + fdir_to_right[fdir+1][2] pos2.z = pos2.z + fdir_to_right[fdir+1][2]
i = i + 1 i = i + 1
wrapped = nil wrapped = nil
elseif asc < 28 then
last_color = asc
master_meta:set_int("last_color", asc)
i = i + 1
wrapped = nil
end end
end 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 elseif msg == "getindex" then -- get the scroll index
digilines.receptor_send(pos, digiline.rules.default, channel, meta:get_int("index")) digilines.receptor_send(pos, digiline.rules.default, channel, meta:get_int("index"))
else else
msg = string.gsub(msg, "//", string.char(30))
led_marquee.set_timer(pos, 0) led_marquee.set_timer(pos, 0)
meta:set_string("last_msg", msg) meta:set_string("last_msg", msg)
led_marquee.display_msg(pos, channel, msg) led_marquee.display_msg(pos, channel, msg)
@ -237,13 +323,10 @@ local on_digiline_receive_string = function(pos, node, channel, msg)
end end
else else
local asc = string.byte(msg) 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)}) minetest.swap_node(pos, { name = "led_marquee:char_"..asc, param2 = fdir + (last_color*8)})
meta:set_string("last_msg", tostring(msg)) meta:set_string("last_msg", tostring(msg))
meta:set_int("index", 1) meta:set_int("index", 1)
elseif asc < 28 then
last_color = asc
meta:set_int("last_color", asc)
end end
end end
elseif msg and type(msg) == "number" then elseif msg and type(msg) == "number" then