minetest-mm/mods-old/streets/streets_matrix_screen/init.lua

232 lines
5.8 KiB
Lua
Raw Normal View History

2021-12-05 14:17:16 +01:00
--[[
## StreetsMod 2.0 ##
Submod: matrix_screen
Optional: true
]]
-- This submod was made by HybridDog and modified by Thomas S.
local matrix_px = 16
-- gets the object at pos
local function get_screen(pos)
local object
local objects = minetest.get_objects_inside_radius(pos, 0.5) or {}
for _, obj in pairs(objects) do
local ent = obj:get_luaentity()
if ent then
if ent.name == "streets:matrix_screen_lights" then
-- Remove duplicates
if object then
obj:remove()
else
object = obj
end
end
end
end
return object
end
-- used to get the texture for the object
local function generate_textures(data)
local texture, n = { "streets_matrix_screen_front.png^[combine:" .. matrix_px .. "x" .. matrix_px }, 2
for y = 1, matrix_px do
local xs = data[y]
for x = 1, matrix_px do
if xs[x] then
texture[n] = ":" .. x - 1 .. "," .. y - 1 .. "=streets_matrix_px.png"
n = n + 1
end
end
end
texture[n] = "^streets_matrix_screen_lines.png"
texture = table.concat(texture, "")
return { texture, texture, texture, texture, texture, texture }
end
-- updates texture of screen
local function update_screen(pos, data)
local obj = get_screen(pos) or minetest.add_entity(pos, "streets:matrix_screen_lights")
obj:set_properties({ textures = generate_textures(data) })
end
-- returns an empty toggleds table
local function new_toggleds()
local t = {}
for y = 1, matrix_px do
t[y] = {}
end
return t
end
-- gets the toggleds of the node from meta
local function get_data(meta)
local data = minetest.deserialize(minetest.decompress(meta:get_string("toggleds")))
if type(data) ~= "table" then
data = new_toggleds()
end
return data
end
-- update toggleds via a table sent by digiline
local function apply_changes(toggleds, t)
if type(t) ~= "table" then
return false, "matrix screen: got unsupported thing: " .. dump(t)
end
for y = 1, matrix_px do
toggleds[y] = {}
end
for y = 1, 16 do
local xs = t[y]
if type(xs) == "table" then
for x = 1, 16 do
local enabled = xs[x]
if enabled and enabled ~= 0 then
toggleds[y][x] = true
elseif enabled == false or enabled == 0 then
toggleds[y][x] = nil
end
end
elseif type(xs) == "number" then
for x = 1, 16 do
if math.floor(xs/2^(16-x))%2 == 1 then
toggleds[y][x] = true
else
toggleds[y][x] = nil
end
end
end
end
return true
end
-- sets the toggleds of the node to meta
local function set_data(meta, toggleds)
meta:set_string("toggleds", minetest.compress(minetest.serialize(toggleds)))
end
minetest.register_node("streets:matrix_screen_base", {
description = "digiline controllable matrix screen",
tiles = { "streets_matrix_screen_front.png" },
drawtype = "nodebox",
paramtype = "light",
paramtype2 = "facedir",
groups = { cracky = 3, oddly_breakable_by_hand = 2 },
sounds = default.node_sound_stone_defaults(),
light_source = 14,
node_box = {
type = "fixed",
fixed = {
{ -0.5, -0.5, -0.49, 0.5, 0.5, 0.5 },
},
},
on_receive_fields = function(pos, formname, fields, sender)
local name = sender:get_player_name()
if minetest.is_protected(pos, name) and not minetest.check_player_privs(name, { protection_bypass = true }) then
minetest.record_protection_violation(pos, name)
return
end
if (fields.channel) then
minetest.get_meta(pos):set_string("channel", fields.channel)
end
end,
on_construct = function(pos)
local meta = minetest.get_meta(pos)
meta:set_string("formspec", "field[channel;Channel;${channel}]")
meta:set_string("channel", "matrix_screen")
minetest.add_entity(pos, "streets:matrix_screen_lights")
end,
on_destruct = function(pos)
local obj = get_screen(pos)
if obj then
obj:remove()
end
end,
digiline = {
receptor = {},
effector = {
action = function(pos, node, channel, t)
local meta = minetest.get_meta(pos)
local toggleds = get_data(meta)
if channel == meta:get_string("channel") .. "_reset" then
for y = 1, matrix_px do
toggleds[y] = {}
end
set_data(meta, toggleds)
update_screen(pos, toggleds)
end
if channel ~= meta:get_string("channel") then
return
end
apply_changes(toggleds, t)
set_data(meta, toggleds)
update_screen(pos, toggleds)
end,
rules = {
{ x = 1, y = 0, z = 0 },
{ x = 1, y = 1, z = 0 },
{ x = 1, y = -1, z = 0 },
{ x = -1, y = 0, z = 0 },
{ x = -1, y = 1, z = 0 },
{ x = -1, y = -1, z = 0 },
{ x = 0, y = 1, z = 0 },
{ x = 0, y = 1, z = 1 },
{ x = 0, y = 1, z = -1 },
{ x = 0, y = -1, z = 0 },
{ x = 0, y = -1, z = 1 },
{ x = 0, y = -1, z = -1 },
{ x = 0, y = 0, z = 1 },
{ x = 0, y = 0, z = -1 },
}
},
},
})
-- ensure the screen existence
minetest.register_abm({
interval = 5,
chance = 1,
nodenames = { "streets:matrix_screen_base" },
action = function(pos, node)
if not get_screen(pos) then
local toggleds = get_data(minetest.get_meta(pos))
update_screen(pos, toggleds)
minetest.log("info", "[streets] matrix screen object was missing")
end
end,
})
-- the screen
minetest.register_entity("streets:matrix_screen_lights", {
collisionbox = { 0, 0, 0, 0, 0, 0 },
physical = false,
visual = "cube",
visual_size = { x = 0.99, y = 0.99 },
on_activate = function(self, staticdata)
local pos = self.object:get_pos()
if not vector.equals(pos, vector.round(pos)) then
self.object:remove()
return
end
local node = minetest.get_node(pos)
if node.name ~= "streets:matrix_screen_base"
and node.name ~= "ignore" then
self.object:remove()
return
end
minetest.after(0, function(pos)
update_screen(pos, get_data(minetest.get_meta(pos)))
end, pos)
end,
})
minetest.register_craft({
output = "streets:matrix_screen_base",
recipe = {
{ "dye:yellow", "default:steel_ingot", "dye:yellow" },
{ "default:steel_ingot", "digilines:lcd", "default:steel_ingot" },
{ "dye:yellow", "default:steel_ingot", "dye:yellow" },
}
})