summaryrefslogtreecommitdiff
path: root/init.lua
diff options
context:
space:
mode:
authorgbl08ma <gbl08ma@gmail.com>2017-02-05 22:40:43 +0000
committergbl08ma <gbl08ma@gmail.com>2017-02-05 22:40:43 +0000
commitf2f528e5dcef4b5956ec7707ec91c2fef52fcce5 (patch)
tree7f6d802757b222c081fe4ea81507e27c7886ba5e /init.lua
Initial public release
Diffstat (limited to 'init.lua')
-rw-r--r--init.lua251
1 files changed, 251 insertions, 0 deletions
diff --git a/init.lua b/init.lua
new file mode 100644
index 0000000..a3609c5
--- /dev/null
+++ b/init.lua
@@ -0,0 +1,251 @@
+-- Textline: wide character displays for Minetest, controlled with Digilines
+-- Based on the LCD that comes with Digilines
+-- Copyright 2017 Gabriel Maia <gabriel@tny.im>, http://github.com/gbl08ma
+-- Copyright 2017 Segvault http://segvault.tny.im
+-- See the included license file LICENSE.txt
+-- Font: 04.jp.org
+
+textline = {}
+-- load characters map
+local chars_file = io.open(minetest.get_modpath("textline").."/characters", "r")
+local charmap = {}
+local max_chars = 27
+if not chars_file then
+ print("[textline] E: character map file not found")
+else
+ while true do
+ local char = chars_file:read("*l")
+ if char == nil then
+ break
+ end
+ local img = chars_file:read("*l")
+ chars_file:read("*l")
+ charmap[char] = img
+ end
+end
+
+local textlines = {
+ -- on ceiling
+ --* [0] = {delta = {x = 0, y = 0.4, z = 0}, pitch = math.pi / -2},
+ -- on ground
+ --* [1] = {delta = {x = 0, y =-0.4, z = 0}, pitch = math.pi / 2},
+ -- sides
+ [2] = {delta = {x = 0.43, y = 0, z = 0}, yaw = math.pi / -2},
+ [3] = {delta = {x = -0.43, y = 0, z = 0}, yaw = math.pi / 2},
+ [4] = {delta = {x = 0, y = 0, z = 0.43}, yaw = 0},
+ [5] = {delta = {x = 0, y = 0, z = -0.43}, yaw = math.pi},
+}
+
+local reset_meta = function(pos)
+ minetest.get_meta(pos):set_string("formspec", "field[channel;Channel;${channel}]")
+end
+
+local clearscreen = function(pos)
+ local objects = minetest.get_objects_inside_radius(pos, 0.5)
+ for _, o in ipairs(objects) do
+ if o:get_luaentity().name == "textline:text" then
+ o:remove()
+ end
+ end
+end
+
+local prepare_writing = function(pos)
+ lcd_info = textlines[minetest.get_node(pos).param2]
+ if lcd_info == nil then return end
+ local text = minetest.add_entity(
+ {x = pos.x + lcd_info.delta.x,
+ y = pos.y + lcd_info.delta.y,
+ z = pos.z + lcd_info.delta.z}, "textline:text")
+ text:setyaw(lcd_info.yaw or 0)
+ return text
+end
+
+local on_digiline_receive = function(pos, node, channel, msg)
+ local meta = minetest.get_meta(pos)
+ local setchan = meta:get_string("channel")
+ if setchan ~= channel then return end
+
+ meta:set_string("text", msg)
+ if msg ~= "" then
+ local text = meta:get_string("text")
+ local objects = minetest.get_objects_inside_radius(pos, 0.5)
+ for _, o in ipairs(objects) do
+ local lentity = o:get_luaentity()
+ if lentity ~= nil then
+ local lname = lentity.name
+ if lname ~= nil and lname == "textline:text" then
+ o:set_properties({textures={textline:generate_texture(textline:create_lines(text))}})
+ end
+ end
+ end
+ end
+end
+
+local lcd_box = {
+ type = "wallmounted",
+ wall_top = {-8/16, 7/16, -8/16, 8/16, 8/16, 8/16}
+}
+
+minetest.register_node("textline:lcd", {
+ drawtype = "nodebox",
+ description = "Textline",
+ inventory_image = "textline_icon.png",
+ wield_image = "textline_icon.png",
+ tiles = {"textline_anyside.png"},
+
+ paramtype = "light",
+ sunlight_propagates = true,
+ paramtype2 = "wallmounted",
+ node_box = lcd_box,
+ selection_box = lcd_box,
+ groups = {choppy = 3, dig_immediate = 2},
+
+ after_place_node = function (pos, placer, itemstack)
+ local param2 = minetest.get_node(pos).param2
+ if param2 == 0 or param2 == 1 then
+ minetest.add_node(pos, {name = "textline:lcd", param2 = 3})
+ end
+ prepare_writing (pos)
+ end,
+
+ on_construct = function(pos)
+ reset_meta(pos)
+ end,
+
+ on_destruct = function(pos)
+ clearscreen(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
+ },
+ },
+
+ light_source = 0,
+})
+
+minetest.register_node("textline:background", {
+ drawtype = "nodebox",
+ description = "Textline background",
+ inventory_image = "textline_background.png",
+ wield_image = "textline_background.png",
+ tiles = {"textline_anyside.png"},
+
+ paramtype = "light",
+ sunlight_propagates = true,
+ paramtype2 = "wallmounted",
+ node_box = lcd_box,
+ selection_box = lcd_box,
+ groups = {choppy = 3, dig_immediate = 2},
+
+ light_source = 0,
+})
+
+minetest.register_entity("textline:text", {
+ collisionbox = { 0, 0, 0, 0, 0, 0 },
+ visual = "upright_sprite",
+ visual_size = {x=3, y=1},
+ textures = {},
+
+ on_activate = function(self)
+ local meta = minetest.get_meta(self.object:getpos())
+ local text = meta:get_string("text")
+ self.object:set_properties({textures={textline:generate_texture(textline:create_lines(text))}})
+ end
+})
+
+-- CONSTANTS
+local LCD_WIDTH = 160
+local LCD_HEIGHT = 34
+local LCD_PADDING = 1
+
+local LINE_LENGTH = max_chars
+local NUMBER_OF_LINES = 4
+
+local LINE_HEIGHT = 7
+local LINE_SPACING = 1
+local CHAR_WIDTH = 5
+
+function textline:create_lines(text)
+ local line_num = 1
+ local tab = {}
+ for line in string.gmatch(text, '([^|\n]+)') do
+ table.insert(tab, line)
+ line_num = line_num+1
+ if line_num > NUMBER_OF_LINES then
+ return tab
+ end
+ end
+ return tab
+end
+
+function textline:generate_texture(lines)
+ local texture = "[combine:"..LCD_WIDTH .."x"..LCD_HEIGHT
+ local ypos = -2
+ for i = 1, #lines do
+ texture = texture..self:generate_line(lines[i], ypos)
+ ypos = ypos + LINE_HEIGHT + LINE_SPACING
+ end
+ return texture
+end
+
+function textline:generate_line(s, ypos)
+ local i = 1
+ local parsed = {}
+ local width = 0
+ local chars = 0
+ while chars < max_chars and i <= #s do
+ local file = nil
+ if charmap[s:sub(i, i)] ~= nil then
+ file = charmap[s:sub(i, i)]
+ i = i + 1
+ elseif i < #s and charmap[s:sub(i, i + 1)] ~= nil then
+ file = charmap[s:sub(i, i + 1)]
+ i = i + 2
+ else
+ print("[textline] W: unknown symbol in '"..s.."' at "..i)
+ i = i + 1
+ end
+ if file ~= nil then
+ width = width + CHAR_WIDTH
+ table.insert(parsed, file)
+ chars = chars + 1
+ end
+ end
+ width = width - 1
+
+ local texture = ""
+ local xpos = LCD_PADDING
+ for i = 1, #parsed do
+ texture = texture..":"..xpos..","..ypos.."="..parsed[i]..".png"
+ xpos = xpos + CHAR_WIDTH + 1
+ end
+ return texture
+end
+
+minetest.register_craft({
+ output = "textline:lcd 2",
+ recipe = {
+ {"default:steel_ingot", "digilines:wire_std_00000000", "default:steel_ingot"},
+ {"mesecons_lightstone:lightstone_green_off","mesecons_lightstone:lightstone_green_off","default:glass"},
+ {"default:glass","default:glass","default:glass"}
+ }
+})
+
+minetest.register_craft({
+ output = "textline:background 2",
+ recipe = {
+ {"default:steel_ingot", "default:glass", "default:steel_ingot"},
+ {"mesecons_lightstone:lightstone_green_off","mesecons_lightstone:lightstone_green_off","default:glass"},
+ {"default:glass","default:glass","default:glass"}
+ }
+})