summaryrefslogtreecommitdiff
path: root/led_marquee/init.lua
diff options
context:
space:
mode:
Diffstat (limited to 'led_marquee/init.lua')
-rw-r--r--led_marquee/init.lua135
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 = {