2018-08-15 07:27:39 +02:00
|
|
|
-- simple LED marquee mod
|
|
|
|
-- by Vanessa Dannenberg
|
|
|
|
|
2018-08-17 05:09:20 +02:00
|
|
|
led_marquee = {}
|
|
|
|
|
2018-08-15 07:27:39 +02:00
|
|
|
local S
|
|
|
|
if minetest.get_modpath("intllib") then
|
2018-08-15 19:09:30 +02:00
|
|
|
S = intllib.make_gettext_pair()
|
2018-08-15 07:27:39 +02:00
|
|
|
else
|
|
|
|
S = function(s) return s end
|
|
|
|
end
|
|
|
|
|
2018-08-21 01:25:53 +02:00
|
|
|
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,
|
2018-08-21 02:58:10 +02:00
|
|
|
|
2018-08-21 01:25:53 +02:00
|
|
|
["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,
|
2018-08-21 02:58:10 +02:00
|
|
|
["R"] = 27,
|
|
|
|
|
|
|
|
["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
|
|
|
|
|
2018-08-21 01:25:53 +02:00
|
|
|
}
|
|
|
|
|
2018-08-15 07:27:39 +02:00
|
|
|
-- the following functions based on the so-named ones in Jeija's digilines mod
|
|
|
|
|
|
|
|
local reset_meta = function(pos)
|
|
|
|
minetest.get_meta(pos):set_string("formspec", "field[channel;Channel;${channel}]")
|
|
|
|
end
|
|
|
|
|
|
|
|
local on_digiline_receive_std = function(pos, node, channel, msg)
|
|
|
|
local meta = minetest.get_meta(pos)
|
|
|
|
local setchan = meta:get_string("channel")
|
|
|
|
if setchan ~= channel then return end
|
|
|
|
local num = tonumber(msg)
|
|
|
|
if msg == "colon" or msg == "period" or msg == "off" or (num and (num >= 0 and num <= 9)) then
|
|
|
|
minetest.swap_node(pos, { name = "led_marquee:marquee_"..msg, param2 = node.param2})
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2018-08-16 19:10:06 +02:00
|
|
|
-- convert Lua's idea of a UTF-8 char to ISO-8859-1
|
|
|
|
|
|
|
|
-- first char is non-break space, 0xA0
|
2018-08-16 19:21:28 +02:00
|
|
|
local iso_chars=" ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ"
|
2018-08-16 19:10:06 +02:00
|
|
|
|
2018-08-16 19:22:02 +02:00
|
|
|
local get_iso = function(c)
|
2018-08-16 19:10:06 +02:00
|
|
|
local hb = string.byte(c,1) or 0
|
|
|
|
local lb = string.byte(c,2) or 0
|
|
|
|
local dec = lb+hb*256
|
|
|
|
local char = dec - 49664
|
|
|
|
if dec > 49855 then char = dec - 49856 end
|
|
|
|
return char
|
|
|
|
end
|
|
|
|
|
2018-08-16 19:22:02 +02:00
|
|
|
local make_iso = function(s)
|
2018-08-16 19:10:06 +02:00
|
|
|
local i = 1
|
|
|
|
local s2 = ""
|
|
|
|
while i <= string.len(s) do
|
|
|
|
if string.byte(s,i) > 159 then
|
|
|
|
s2 = s2..string.char(get_iso(string.sub(s, i, i+1)))
|
|
|
|
i = i + 2
|
|
|
|
else
|
|
|
|
s2 = s2..string.sub(s, i, i)
|
|
|
|
i = i + 1
|
|
|
|
end
|
|
|
|
end
|
|
|
|
return s2
|
|
|
|
end
|
|
|
|
|
2018-08-17 05:09:20 +02:00
|
|
|
-- scrolling
|
|
|
|
|
|
|
|
led_marquee.set_timer = function(pos, timeout)
|
|
|
|
local timer = minetest.get_node_timer(pos)
|
|
|
|
timer:stop()
|
|
|
|
if timeout > 0 then
|
2018-08-17 16:48:33 +02:00
|
|
|
local meta = minetest.get_meta(pos)
|
2018-08-17 05:09:20 +02:00
|
|
|
timer:start(timeout)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2018-08-17 23:12:49 +02:00
|
|
|
led_marquee.scroll_text = function(pos, elapsed, skip)
|
2018-08-17 05:09:20 +02:00
|
|
|
local meta = minetest.get_meta(pos)
|
|
|
|
local msg = meta:get_string("last_msg")
|
|
|
|
local channel = meta:get_string("channel")
|
2018-08-17 21:43:13 +02:00
|
|
|
local index = meta:get_int("index")
|
2018-08-21 01:25:53 +02:00
|
|
|
local color = meta:get_int("last_color")
|
|
|
|
local colorchar = color_to_char[color+1]
|
2018-08-17 21:18:57 +02:00
|
|
|
if not index or index < 1 or not string.byte(msg, index) then index = 1 end
|
|
|
|
local len = string.len(msg)
|
2018-08-17 23:12:49 +02:00
|
|
|
skip = skip or 1
|
|
|
|
index = index + skip
|
2018-08-17 21:18:57 +02:00
|
|
|
|
2018-08-21 01:25:53 +02:00
|
|
|
-- 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)
|
2018-08-17 21:18:57 +02:00
|
|
|
end
|
2018-08-17 21:43:13 +02:00
|
|
|
|
2018-08-21 01:25:53 +02:00
|
|
|
-- 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
|
2018-08-17 21:18:57 +02:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2018-08-21 01:25:53 +02:00
|
|
|
led_marquee.display_msg(pos, channel, "/"..colorchar..string.sub(msg, f)..string.rep(" ", skip + 1))
|
|
|
|
meta:set_int("index", f)
|
2018-08-17 16:07:34 +02:00
|
|
|
if not elapsed or elapsed < 0.5 then return false end
|
2018-08-17 05:09:20 +02:00
|
|
|
return true
|
|
|
|
end
|
|
|
|
|
2018-08-15 07:27:39 +02:00
|
|
|
-- the nodes:
|
|
|
|
|
|
|
|
local fdir_to_right = {
|
|
|
|
{ 0, -1 },
|
2018-08-15 20:27:55 +02:00
|
|
|
{ 0, -1 },
|
|
|
|
{ 0, -1 },
|
2018-08-15 20:57:20 +02:00
|
|
|
{ 0, 1 },
|
2018-08-15 20:27:55 +02:00
|
|
|
{ 1, 0 },
|
|
|
|
{ -1, 0 },
|
|
|
|
}
|
|
|
|
|
|
|
|
local cbox = {
|
|
|
|
type = "wallmounted",
|
|
|
|
wall_top = { -8/16, 7/16, -8/16, 8/16, 8/16, 8/16 },
|
|
|
|
wall_bottom = { -8/16, -8/16, -8/16, 8/16, -7/16, 8/16 },
|
|
|
|
wall_side = { -8/16, -8/16, -8/16, -7/16, 8/16, 8/16 }
|
2018-08-15 07:27:39 +02:00
|
|
|
}
|
|
|
|
|
2018-08-21 01:25:53 +02:00
|
|
|
led_marquee.decode_color = function(msg)
|
|
|
|
|
|
|
|
end
|
|
|
|
|
2018-08-17 05:09:20 +02:00
|
|
|
led_marquee.display_msg = function(pos, channel, msg)
|
2018-08-21 01:25:53 +02:00
|
|
|
msg = string.sub(msg, 1, 6144).." "
|
2018-08-17 05:40:35 +02:00
|
|
|
if string.sub(msg,1,1) == string.char(255) then -- treat it as incoming UTF-8
|
2018-08-21 01:25:53 +02:00
|
|
|
msg = make_iso(string.sub(msg, 2, 6144))
|
2018-08-15 07:27:39 +02:00
|
|
|
end
|
2018-08-16 19:10:06 +02:00
|
|
|
|
2018-08-16 00:51:44 +02:00
|
|
|
local master_fdir = minetest.get_node(pos).param2 % 8
|
|
|
|
local master_meta = minetest.get_meta(pos)
|
|
|
|
local last_color = master_meta:get_int("last_color")
|
basic multi-line support
Stack up a wall of LED panels, any horizontal and vertical amount
Set a channel on the upper left panel, leave the others un-set, and
connect a LuaC to it via digilines.
Long strings sent to that channel will be displayed using all panels,
starting at the upper-left and working from left to right, top to
bottom, wrapping from line to line as appropriate (similar to printing
to a shell terminal).
string.char(28) can be inserted anywhere to force a linefeed.
As usual, printing continues from node to node until the program either
finds a panel with a different non-empty channel than the first one, or
it finds a panel that's facing the wrong way.
If the program finds something other than a panel, it wraps to the next
line. If it finds something other than a panel twice in a row, that
signals that text has wrapped off of the last row, and printing is cut
off.
Lines of panels don't need to be the same length, the program will wrap
as needed.
This commit also gets rid of the end-of-line padding, uses proper
string.rep() to create the all-off and all-on fills (each of which is
1kB), and fixes one or two other minor issues.
Strings are trimmed to 1 kB.
Panels are not erased between prints.
2018-08-16 07:28:36 +02:00
|
|
|
local pos2 = table.copy(pos)
|
2018-08-16 01:29:23 +02:00
|
|
|
if not last_color or last_color < 0 or last_color > 27 then
|
2018-08-16 00:51:44 +02:00
|
|
|
last_color = 0
|
|
|
|
master_meta:set_int("last_color", 0)
|
2018-08-15 09:08:05 +02:00
|
|
|
end
|
basic multi-line support
Stack up a wall of LED panels, any horizontal and vertical amount
Set a channel on the upper left panel, leave the others un-set, and
connect a LuaC to it via digilines.
Long strings sent to that channel will be displayed using all panels,
starting at the upper-left and working from left to right, top to
bottom, wrapping from line to line as appropriate (similar to printing
to a shell terminal).
string.char(28) can be inserted anywhere to force a linefeed.
As usual, printing continues from node to node until the program either
finds a panel with a different non-empty channel than the first one, or
it finds a panel that's facing the wrong way.
If the program finds something other than a panel, it wraps to the next
line. If it finds something other than a panel twice in a row, that
signals that text has wrapped off of the last row, and printing is cut
off.
Lines of panels don't need to be the same length, the program will wrap
as needed.
This commit also gets rid of the end-of-line padding, uses proper
string.rep() to create the all-off and all-on fills (each of which is
1kB), and fixes one or two other minor issues.
Strings are trimmed to 1 kB.
Panels are not erased between prints.
2018-08-16 07:28:36 +02:00
|
|
|
local i = 1
|
2018-08-17 05:09:20 +02:00
|
|
|
local len = string.len(msg)
|
basic multi-line support
Stack up a wall of LED panels, any horizontal and vertical amount
Set a channel on the upper left panel, leave the others un-set, and
connect a LuaC to it via digilines.
Long strings sent to that channel will be displayed using all panels,
starting at the upper-left and working from left to right, top to
bottom, wrapping from line to line as appropriate (similar to printing
to a shell terminal).
string.char(28) can be inserted anywhere to force a linefeed.
As usual, printing continues from node to node until the program either
finds a panel with a different non-empty channel than the first one, or
it finds a panel that's facing the wrong way.
If the program finds something other than a panel, it wraps to the next
line. If it finds something other than a panel twice in a row, that
signals that text has wrapped off of the last row, and printing is cut
off.
Lines of panels don't need to be the same length, the program will wrap
as needed.
This commit also gets rid of the end-of-line padding, uses proper
string.rep() to create the all-off and all-on fills (each of which is
1kB), and fixes one or two other minor issues.
Strings are trimmed to 1 kB.
Panels are not erased between prints.
2018-08-16 07:28:36 +02:00
|
|
|
local wrapped = nil
|
|
|
|
while i <= len do
|
2018-08-15 07:27:39 +02:00
|
|
|
local node = minetest.get_node(pos2)
|
2018-08-16 00:51:44 +02:00
|
|
|
local fdir = node.param2 % 8
|
2018-08-15 07:27:39 +02:00
|
|
|
local meta = minetest.get_meta(pos2)
|
basic multi-line support
Stack up a wall of LED panels, any horizontal and vertical amount
Set a channel on the upper left panel, leave the others un-set, and
connect a LuaC to it via digilines.
Long strings sent to that channel will be displayed using all panels,
starting at the upper-left and working from left to right, top to
bottom, wrapping from line to line as appropriate (similar to printing
to a shell terminal).
string.char(28) can be inserted anywhere to force a linefeed.
As usual, printing continues from node to node until the program either
finds a panel with a different non-empty channel than the first one, or
it finds a panel that's facing the wrong way.
If the program finds something other than a panel, it wraps to the next
line. If it finds something other than a panel twice in a row, that
signals that text has wrapped off of the last row, and printing is cut
off.
Lines of panels don't need to be the same length, the program will wrap
as needed.
This commit also gets rid of the end-of-line padding, uses proper
string.rep() to create the all-off and all-on fills (each of which is
1kB), and fixes one or two other minor issues.
Strings are trimmed to 1 kB.
Panels are not erased between prints.
2018-08-16 07:28:36 +02:00
|
|
|
local setchan = nil
|
|
|
|
if meta then setchan = meta:get_string("channel") end
|
2018-08-17 05:09:20 +02:00
|
|
|
local asc = string.byte(msg, i, i)
|
basic multi-line support
Stack up a wall of LED panels, any horizontal and vertical amount
Set a channel on the upper left panel, leave the others un-set, and
connect a LuaC to it via digilines.
Long strings sent to that channel will be displayed using all panels,
starting at the upper-left and working from left to right, top to
bottom, wrapping from line to line as appropriate (similar to printing
to a shell terminal).
string.char(28) can be inserted anywhere to force a linefeed.
As usual, printing continues from node to node until the program either
finds a panel with a different non-empty channel than the first one, or
it finds a panel that's facing the wrong way.
If the program finds something other than a panel, it wraps to the next
line. If it finds something other than a panel twice in a row, that
signals that text has wrapped off of the last row, and printing is cut
off.
Lines of panels don't need to be the same length, the program will wrap
as needed.
This commit also gets rid of the end-of-line padding, uses proper
string.rep() to create the all-off and all-on fills (each of which is
1kB), and fixes one or two other minor issues.
Strings are trimmed to 1 kB.
Panels are not erased between prints.
2018-08-16 07:28:36 +02:00
|
|
|
if not string.match(node.name, "led_marquee:char_") then
|
|
|
|
if not wrapped then
|
|
|
|
pos2.x = pos.x
|
|
|
|
pos2.y = pos2.y-1
|
|
|
|
pos2.z = pos.z
|
|
|
|
wrapped = true
|
|
|
|
else
|
|
|
|
break
|
|
|
|
end
|
|
|
|
elseif string.match(node.name, "led_marquee:char_")
|
|
|
|
and fdir ~= master_fdir or (setchan ~= nil and setchan ~= "" and setchan ~= channel) then
|
|
|
|
break
|
2018-08-21 02:25:44 +02:00
|
|
|
elseif asc == 10 then
|
basic multi-line support
Stack up a wall of LED panels, any horizontal and vertical amount
Set a channel on the upper left panel, leave the others un-set, and
connect a LuaC to it via digilines.
Long strings sent to that channel will be displayed using all panels,
starting at the upper-left and working from left to right, top to
bottom, wrapping from line to line as appropriate (similar to printing
to a shell terminal).
string.char(28) can be inserted anywhere to force a linefeed.
As usual, printing continues from node to node until the program either
finds a panel with a different non-empty channel than the first one, or
it finds a panel that's facing the wrong way.
If the program finds something other than a panel, it wraps to the next
line. If it finds something other than a panel twice in a row, that
signals that text has wrapped off of the last row, and printing is cut
off.
Lines of panels don't need to be the same length, the program will wrap
as needed.
This commit also gets rid of the end-of-line padding, uses proper
string.rep() to create the all-off and all-on fills (each of which is
1kB), and fixes one or two other minor issues.
Strings are trimmed to 1 kB.
Panels are not erased between prints.
2018-08-16 07:28:36 +02:00
|
|
|
pos2.x = pos.x
|
|
|
|
pos2.y = pos2.y-1
|
|
|
|
pos2.z = pos.z
|
|
|
|
i = i + 1
|
|
|
|
wrapped = nil
|
2018-08-16 08:25:31 +02:00
|
|
|
elseif asc == 29 then
|
2018-08-17 05:09:20 +02:00
|
|
|
local c = string.byte(msg, i+1, i+1) or 0
|
|
|
|
local r = string.byte(msg, i+2, i+2) or 0
|
2018-08-16 08:25:31 +02:00
|
|
|
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
|
|
|
|
i = i + 3
|
|
|
|
wrapped = nil
|
2018-08-21 01:25:53 +02:00
|
|
|
elseif asc == 30 then -- translate to slash for printing
|
|
|
|
minetest.swap_node(pos2, { name = "led_marquee:char_47", param2 = master_fdir + (last_color*8)})
|
2018-08-15 09:08:05 +02:00
|
|
|
pos2.x = pos2.x + fdir_to_right[fdir+1][1]
|
|
|
|
pos2.z = pos2.z + fdir_to_right[fdir+1][2]
|
basic multi-line support
Stack up a wall of LED panels, any horizontal and vertical amount
Set a channel on the upper left panel, leave the others un-set, and
connect a LuaC to it via digilines.
Long strings sent to that channel will be displayed using all panels,
starting at the upper-left and working from left to right, top to
bottom, wrapping from line to line as appropriate (similar to printing
to a shell terminal).
string.char(28) can be inserted anywhere to force a linefeed.
As usual, printing continues from node to node until the program either
finds a panel with a different non-empty channel than the first one, or
it finds a panel that's facing the wrong way.
If the program finds something other than a panel, it wraps to the next
line. If it finds something other than a panel twice in a row, that
signals that text has wrapped off of the last row, and printing is cut
off.
Lines of panels don't need to be the same length, the program will wrap
as needed.
This commit also gets rid of the end-of-line padding, uses proper
string.rep() to create the all-off and all-on fills (each of which is
1kB), and fixes one or two other minor issues.
Strings are trimmed to 1 kB.
Panels are not erased between prints.
2018-08-16 07:28:36 +02:00
|
|
|
i = i + 1
|
2018-08-21 01:25:53 +02:00
|
|
|
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)
|
basic multi-line support
Stack up a wall of LED panels, any horizontal and vertical amount
Set a channel on the upper left panel, leave the others un-set, and
connect a LuaC to it via digilines.
Long strings sent to that channel will be displayed using all panels,
starting at the upper-left and working from left to right, top to
bottom, wrapping from line to line as appropriate (similar to printing
to a shell terminal).
string.char(28) can be inserted anywhere to force a linefeed.
As usual, printing continues from node to node until the program either
finds a panel with a different non-empty channel than the first one, or
it finds a panel that's facing the wrong way.
If the program finds something other than a panel, it wraps to the next
line. If it finds something other than a panel twice in a row, that
signals that text has wrapped off of the last row, and printing is cut
off.
Lines of panels don't need to be the same length, the program will wrap
as needed.
This commit also gets rid of the end-of-line padding, uses proper
string.rep() to create the all-off and all-on fills (each of which is
1kB), and fixes one or two other minor issues.
Strings are trimmed to 1 kB.
Panels are not erased between prints.
2018-08-16 07:28:36 +02:00
|
|
|
wrapped = nil
|
2018-08-21 01:25:53 +02:00
|
|
|
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]
|
basic multi-line support
Stack up a wall of LED panels, any horizontal and vertical amount
Set a channel on the upper left panel, leave the others un-set, and
connect a LuaC to it via digilines.
Long strings sent to that channel will be displayed using all panels,
starting at the upper-left and working from left to right, top to
bottom, wrapping from line to line as appropriate (similar to printing
to a shell terminal).
string.char(28) can be inserted anywhere to force a linefeed.
As usual, printing continues from node to node until the program either
finds a panel with a different non-empty channel than the first one, or
it finds a panel that's facing the wrong way.
If the program finds something other than a panel, it wraps to the next
line. If it finds something other than a panel twice in a row, that
signals that text has wrapped off of the last row, and printing is cut
off.
Lines of panels don't need to be the same length, the program will wrap
as needed.
This commit also gets rid of the end-of-line padding, uses proper
string.rep() to create the all-off and all-on fills (each of which is
1kB), and fixes one or two other minor issues.
Strings are trimmed to 1 kB.
Panels are not erased between prints.
2018-08-16 07:28:36 +02:00
|
|
|
i = i + 1
|
|
|
|
wrapped = nil
|
2018-08-21 03:33:04 +02:00
|
|
|
else
|
|
|
|
i = i + 1
|
2018-08-15 07:27:39 +02:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
local on_digiline_receive_string = function(pos, node, channel, msg)
|
|
|
|
local meta = minetest.get_meta(pos)
|
|
|
|
local setchan = meta:get_string("channel")
|
2018-08-16 00:51:44 +02:00
|
|
|
local last_color = meta:get_int("last_color")
|
2018-08-16 01:29:23 +02:00
|
|
|
if not last_color or last_color < 0 or last_color > 27 then
|
2018-08-16 00:51:44 +02:00
|
|
|
last_color = 0
|
|
|
|
meta:set_int("last_color", 0)
|
2018-08-15 09:08:05 +02:00
|
|
|
end
|
2018-08-16 00:51:44 +02:00
|
|
|
local fdir = node.param2 % 8
|
2018-08-15 09:08:05 +02:00
|
|
|
|
2018-08-15 07:27:39 +02:00
|
|
|
if setchan ~= channel then return end
|
|
|
|
if msg and msg ~= "" and type(msg) == "string" then
|
|
|
|
if string.len(msg) > 1 then
|
2018-08-17 23:13:34 +02:00
|
|
|
if msg == "clear" then
|
2018-08-17 15:49:26 +02:00
|
|
|
led_marquee.set_timer(pos, 0)
|
2018-08-19 08:04:46 +02:00
|
|
|
msg = string.rep(" ", 2048)
|
2018-08-17 05:40:35 +02:00
|
|
|
meta:set_string("last_msg", msg)
|
|
|
|
led_marquee.display_msg(pos, channel, msg)
|
2018-08-17 17:20:49 +02:00
|
|
|
meta:set_int("index", 1)
|
2018-08-17 23:13:34 +02:00
|
|
|
elseif msg == "allon" then
|
2018-08-17 15:49:26 +02:00
|
|
|
led_marquee.set_timer(pos, 0)
|
2018-08-19 08:04:46 +02:00
|
|
|
msg = string.rep(string.char(144), 2048)
|
2018-08-17 05:40:35 +02:00
|
|
|
meta:set_string("last_msg", msg)
|
|
|
|
led_marquee.display_msg(pos, channel, msg)
|
2018-08-17 17:20:49 +02:00
|
|
|
meta:set_int("index", 1)
|
2018-08-17 05:09:20 +02:00
|
|
|
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
|
2018-08-17 15:49:26 +02:00
|
|
|
led_marquee.set_timer(pos, 0)
|
|
|
|
return
|
2018-08-17 05:09:20 +02:00
|
|
|
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)
|
2018-08-17 23:12:49 +02:00
|
|
|
elseif string.sub(msg, 1, 11) == "scroll_step" then
|
|
|
|
local skip = tonumber(string.sub(msg, 12))
|
|
|
|
led_marquee.scroll_text(pos, nil, skip)
|
2018-08-17 16:36:20 +02:00
|
|
|
elseif msg == "get" then -- get the master panel's displayed char as ASCII numerical value
|
2018-08-17 17:17:09 +02:00
|
|
|
digilines.receptor_send(pos, digiline.rules.default, channel, tonumber(string.match(minetest.get_node(pos).name,"led_marquee:char_(.+)"))) -- wonderfully horrible string manipulaiton
|
2018-08-17 16:36:20 +02:00
|
|
|
elseif msg == "getstr" then -- get the last stored message
|
2018-08-17 17:17:09 +02:00
|
|
|
digilines.receptor_send(pos, digiline.rules.default, channel, meta:get_string("last_msg"))
|
2018-08-17 17:03:07 +02:00
|
|
|
elseif msg == "getindex" then -- get the scroll index
|
2018-08-17 17:17:09 +02:00
|
|
|
digilines.receptor_send(pos, digiline.rules.default, channel, meta:get_int("index"))
|
2018-08-15 07:27:39 +02:00
|
|
|
else
|
2018-08-21 01:25:53 +02:00
|
|
|
msg = string.gsub(msg, "//", string.char(30))
|
2018-08-17 15:49:26 +02:00
|
|
|
led_marquee.set_timer(pos, 0)
|
2018-08-17 05:09:20 +02:00
|
|
|
meta:set_string("last_msg", msg)
|
|
|
|
led_marquee.display_msg(pos, channel, msg)
|
2018-08-17 17:20:49 +02:00
|
|
|
meta:set_int("index", 1)
|
2018-08-15 07:27:39 +02:00
|
|
|
end
|
|
|
|
else
|
|
|
|
local asc = string.byte(msg)
|
2018-08-21 01:25:53 +02:00
|
|
|
if asc > 29 and asc < 256 then
|
2018-08-16 00:51:44 +02:00
|
|
|
minetest.swap_node(pos, { name = "led_marquee:char_"..asc, param2 = fdir + (last_color*8)})
|
2018-08-17 16:29:10 +02:00
|
|
|
meta:set_string("last_msg", tostring(msg))
|
2018-08-17 17:20:49 +02:00
|
|
|
meta:set_int("index", 1)
|
2018-08-15 07:27:39 +02:00
|
|
|
end
|
|
|
|
end
|
|
|
|
elseif msg and type(msg) == "number" then
|
2018-08-17 16:27:27 +02:00
|
|
|
meta:set_string("last_msg", tostring(msg))
|
2018-08-17 16:25:12 +02:00
|
|
|
led_marquee.display_msg(pos, channel, tostring(msg))
|
2018-08-17 17:20:49 +02:00
|
|
|
meta:set_int("index", 1)
|
2018-08-15 07:27:39 +02:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2018-08-17 05:09:20 +02:00
|
|
|
-- the nodes!
|
|
|
|
|
2018-08-15 23:02:30 +02:00
|
|
|
for i = 31, 255 do
|
2018-08-15 07:27:39 +02:00
|
|
|
local groups = { cracky = 2, not_in_creative_inventory = 1}
|
|
|
|
local light = LIGHT_MAX-2
|
|
|
|
local description = S("Alphanumeric LED marquee panel ("..i..")")
|
2018-08-15 09:47:56 +02:00
|
|
|
local tiles = {
|
|
|
|
{ name="led_marquee_base.png", color="white"},
|
|
|
|
{ name="led_marquee_leds_off.png", color="white"},
|
|
|
|
"led_marquee_char_"..i..".png",
|
|
|
|
}
|
2018-08-15 07:27:39 +02:00
|
|
|
|
2018-08-15 23:02:30 +02:00
|
|
|
if i == 31 then
|
2018-08-15 09:47:56 +02:00
|
|
|
tiles = {
|
|
|
|
{ name="led_marquee_base.png", color="white"},
|
|
|
|
{ name="led_marquee_leds_off.png", color="white"},
|
|
|
|
{
|
2018-08-15 23:02:30 +02:00
|
|
|
name = "led_marquee_char_31.png",
|
2018-08-15 09:47:56 +02:00
|
|
|
animation = {type = "vertical_frames", aspect_w = 32, aspect_h = 32, length = 0.75}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
end
|
|
|
|
|
2018-08-15 23:02:30 +02:00
|
|
|
if i == 32 then
|
|
|
|
groups = {cracky = 2}
|
|
|
|
light = nil
|
|
|
|
description = S("Alphanumeric LED marquee panel")
|
|
|
|
end
|
|
|
|
|
2018-08-15 07:27:39 +02:00
|
|
|
minetest.register_node("led_marquee:char_"..i, {
|
|
|
|
description = description,
|
|
|
|
drawtype = "mesh",
|
|
|
|
mesh = "led_marquee.obj",
|
2018-08-15 09:47:56 +02:00
|
|
|
tiles = tiles,
|
2018-08-16 00:35:29 +02:00
|
|
|
palette="led_marquee_palette.png",
|
2018-08-15 07:27:39 +02:00
|
|
|
use_texture_alpha = true,
|
|
|
|
groups = groups,
|
|
|
|
paramtype = "light",
|
2018-08-15 16:45:40 +02:00
|
|
|
paramtype2 = "colorwallmounted",
|
2018-08-15 07:27:39 +02:00
|
|
|
light_source = light,
|
2018-08-15 20:27:55 +02:00
|
|
|
selection_box = cbox,
|
|
|
|
node_box = cbox,
|
2018-08-15 07:27:39 +02:00
|
|
|
on_construct = function(pos)
|
|
|
|
reset_meta(pos)
|
|
|
|
end,
|
|
|
|
on_receive_fields = function(pos, formname, fields, sender)
|
|
|
|
if (fields.channel) then
|
|
|
|
minetest.get_meta(pos):set_string("channel", fields.channel)
|
|
|
|
end
|
|
|
|
end,
|
|
|
|
digiline = {
|
|
|
|
receptor = {},
|
|
|
|
effector = {
|
|
|
|
action = on_digiline_receive_string,
|
|
|
|
},
|
|
|
|
},
|
2018-08-17 05:09:20 +02:00
|
|
|
drop = "led_marquee:char_32",
|
|
|
|
on_timer = led_marquee.scroll_text
|
2018-08-15 07:27:39 +02:00
|
|
|
})
|
|
|
|
end
|
|
|
|
|
|
|
|
-- crafts
|
|
|
|
|
|
|
|
minetest.register_craft({
|
2018-08-15 09:33:07 +02:00
|
|
|
output = "led_marquee:char_32 6",
|
2018-08-15 07:27:39 +02:00
|
|
|
recipe = {
|
2018-08-15 09:33:07 +02:00
|
|
|
{ "default:glass", "default:glass", "default:glass" },
|
|
|
|
{ "mesecons_lamp:lamp_off", "mesecons_lamp:lamp_off", "mesecons_lamp:lamp_off" },
|
|
|
|
{ "group:wood", "mesecons_microcontroller:microcontroller0000", "group:wood" }
|
2018-08-15 07:27:39 +02:00
|
|
|
},
|
|
|
|
})
|
|
|
|
|