led_marquee/init.lua
Vanessa Dannenberg a6502f0d90 multi-color support
send string.char(0 to 7) to change colors
(red=0, orange, yellow, green, cyan, blue, purple, magenta=7)

the panel remembers the last color used (saved in the meta of the
left-most/"master" panel node)
2018-08-15 03:08:05 -04:00

190 lines
5.9 KiB
Lua

-- simple LED marquee mod
-- by Vanessa Dannenberg
led_marquee = {}
local S
if minetest.get_modpath("intllib") then
S = intllib.Getter()
else
S = function(s) return s end
end
local marquee_cbox = {
type = "fixed",
fixed = { -16/32, -8/16, 15/32, 16/32, 8/16, 16/32 }
}
-- 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
-- the nodes:
local fdir_to_right = {
{ 1, 0 },
{ 0, -1 },
{ -1, 0 },
{ 0, 1 },
}
local padding = " "
local allon = string.char(128)
for i = 1, 64 do
padding = padding.." "
allon = allon..string.char(128)
end
local display_string = function(pos, channel, string)
if string == "off_multi" then
string = ""
elseif string == "allon_multi" then
string = allon
end
local padded_string = string.sub(string..padding, 1, 64)
local fdir = minetest.get_node(pos).param2 % 4
local pos2 = pos
local mastermeta = minetest.get_meta(pos)
local lastcolor = mastermeta:get_int("lastcolor")
if not lastcolor or lastcolor < 0 or lastcolor > 7 then
lastcolor = 0
mastermeta:set_int("lastcolor", 0)
end
for i = 1, 64 do
local node = minetest.get_node(pos2)
local meta = minetest.get_meta(pos2)
local setchan = meta:get_string("channel")
if not string.match(node.name, "led_marquee:char_") or (setchan ~= nil and setchan ~= "" and setchan ~= channel) then break end
local asc = string.byte(padded_string, i, i)
if (node.param2 % 4) == fdir and asc > 31 and asc < 130 then
minetest.swap_node(pos2, { name = "led_marquee:char_"..asc, param2 = (node.param2 % 4) + (lastcolor*32)})
pos2.x = pos2.x + fdir_to_right[fdir+1][1]
pos2.z = pos2.z + fdir_to_right[fdir+1][2]
elseif asc < 8 then
lastcolor = asc
mastermeta:set_int("lastcolor", asc)
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")
local lastcolor = meta:get_int("lastcolor")
if not lastcolor or lastcolor < 0 or lastcolor > 7 then
lastcolor = 0
meta:set_int("lastcolor", 0)
end
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 = (node.param2 % 4) + (lastcolor*32)})
elseif msg == "colon" then
minetest.swap_node(pos, { name = "led_marquee:char_58", param2 = (node.param2 % 4) + (lastcolor*32)})
elseif msg == "period" then
minetest.swap_node(pos, { name = "led_marquee:char_46", param2 = (node.param2 % 4) + (lastcolor*32)})
elseif msg == "del" then
minetest.swap_node(pos, { name = "led_marquee:char_127", param2 = (node.param2 % 4) + (lastcolor*32)})
elseif msg == "allon" then
minetest.swap_node(pos, { name = "led_marquee:char_128", param2 = (node.param2 % 4) + (lastcolor*32)})
elseif msg == "cursor" then
minetest.swap_node(pos, { name = "led_marquee:char_129", param2 = (node.param2 % 4) + (lastcolor*32)})
else
display_string(pos, channel, msg)
end
else
local asc = string.byte(msg)
if asc > 31 and asc < 130 then
minetest.swap_node(pos, { name = "led_marquee:char_"..asc, param2 = (node.param2 % 4) + (lastcolor*32)})
elseif asc < 8 then
lastcolor = asc
meta:set_int("lastcolor", 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 = (node.param2 % 4) + (lastcolor*32)})
elseif msg > 31 and alnum_chars[msg - 31] ~= nil then
minetest.swap_node(pos, { name = "led_marquee:char_"..tostring(msg), param2 = (node.param2 % 4) + (lastcolor*32)})
end
end
end
for i = 32, 129 do
local groups = { cracky = 2, not_in_creative_inventory = 1}
local light = LIGHT_MAX-2
local description = S("Alphanumeric LED marquee panel ("..i..")")
if i == 32 then
groups = {cracky = 2}
light = nil
description = S("Alphanumeric LED marquee panel")
end
minetest.register_node("led_marquee:char_"..i, {
description = description,
drawtype = "mesh",
mesh = "led_marquee.obj",
tiles = {
{ name="led_marquee_base.png", color="white"},
{ name="led_marquee_leds_off.png", color="white"},
"led_marquee_char_"..i..".png",
},
palette="palette.png",
use_texture_alpha = true,
groups = groups,
paramtype = "light",
paramtype2 = "colorfacedir",
light_source = light,
selection_box = marquee_cbox,
collision_box = marquee_cbox,
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,
},
},
drop = "led_marquee:char_32"
})
end
-- crafts
minetest.register_craft({
output = "led_marquee:char_32 4",
recipe = {
{ "", "default:glass", "" },
{ "default:glass", "default:sign_wall", "default:glass" },
{ "default:glass", "default:mese_crystal", "default:glass" }
},
})