232 lines
5.8 KiB
Lua
232 lines
5.8 KiB
Lua
|
--[[
|
||
|
## 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" },
|
||
|
}
|
||
|
})
|