mirror of
https://cheapiesystems.com/git/digiscreen
synced 2024-12-04 20:53:44 +01:00
187 lines
6.1 KiB
Lua
187 lines
6.1 KiB
Lua
local function removeEntity(pos)
|
|
local entitiesNearby = minetest.get_objects_inside_radius(pos,0.5)
|
|
for _,i in pairs(entitiesNearby) do
|
|
if i:get_luaentity() and i:get_luaentity().name == "digiscreen:image" then
|
|
i:remove()
|
|
end
|
|
end
|
|
end
|
|
|
|
local function generateTexture(pos,serdata)
|
|
--The data *should* always be valid, but it pays to double-check anyway due to how easily this could crash if something did go wrong
|
|
if type(serdata) ~= "string" then
|
|
minetest.log("error","[digiscreen] Serialized display data appears to be missing at "..minetest.pos_to_string(pos,0))
|
|
return
|
|
end
|
|
local data = minetest.deserialize(serdata)
|
|
if type(data) ~= "table" then
|
|
minetest.log("error","[digiscreen] Failed to deserialize display data at "..minetest.pos_to_string(pos,0))
|
|
return
|
|
end
|
|
local bincolors = ""
|
|
for y=1,16,1 do
|
|
if type(data[y]) ~= "table" then data[y] = {} end
|
|
for x=1,16,1 do
|
|
local colorspec = 0
|
|
if data[y][x] then
|
|
colorspec = tonumber(data[y][x],16) or 0
|
|
end
|
|
colorspec = 0xFF000000 + colorspec
|
|
bincolors = bincolors..minetest.colorspec_to_bytes(colorspec)
|
|
end
|
|
end
|
|
local img = minetest.encode_png(16,16,bincolors,0)
|
|
return "[png:"..minetest.encode_base64(img)
|
|
end
|
|
|
|
local function updateDisplay(pos)
|
|
removeEntity(pos)
|
|
local meta = minetest.get_meta(pos)
|
|
local data = meta:get_string("data")
|
|
local entity = minetest.add_entity(pos,"digiscreen:image")
|
|
local fdir = minetest.facedir_to_dir(minetest.get_node(pos).param2)
|
|
local etex = "digiscreen_pixel.png"
|
|
etex = generateTexture(pos,data) or etex
|
|
entity:set_properties({textures={etex}})
|
|
entity:set_yaw((fdir.x ~= 0) and math.pi/2 or 0)
|
|
entity:set_pos(vector.add(pos,vector.multiply(fdir,0.39)))
|
|
end
|
|
|
|
minetest.register_entity("digiscreen:image",{
|
|
initial_properties = {
|
|
visual = "upright_sprite",
|
|
physical = false,
|
|
collisionbox = {0,0,0,0,0,0,},
|
|
textures = {"digiscreen_pixel.png",},
|
|
},
|
|
})
|
|
|
|
minetest.register_node("digiscreen:digiscreen",{
|
|
description = "Digilines Graphical Display",
|
|
tiles = {"digiscreen_pixel.png",},
|
|
groups = {cracky = 3,},
|
|
paramtype = "light",
|
|
paramtype2 = "facedir",
|
|
on_rotate = minetest.global_exists("screwdriver") and screwdriver.rotate_simple,
|
|
drawtype = "nodebox",
|
|
node_box = {
|
|
type = "fixed",
|
|
fixed = {-0.5,-0.5,0.4,0.5,0.5,0.5},
|
|
},
|
|
_digistuff_channelcopier_fieldname = "channel",
|
|
light_source = 10,
|
|
on_construct = function(pos)
|
|
local meta = minetest.get_meta(pos)
|
|
meta:set_string("formspec","field[channel;Channel;${channel}]")
|
|
local disp = {}
|
|
for y=1,16,1 do
|
|
disp[y] = {}
|
|
for x=1,16,1 do
|
|
disp[y][x] = "000000"
|
|
end
|
|
end
|
|
meta:set_string("data",minetest.serialize(disp))
|
|
updateDisplay(pos)
|
|
end,
|
|
on_destruct = removeEntity,
|
|
on_receive_fields = function(pos,_,fields,sender)
|
|
local name = sender:get_player_name()
|
|
if not fields.channel then return end
|
|
if minetest.is_protected(pos,name) and not minetest.check_player_privs(name,"protection_bypass") then
|
|
minetest.record_protection_violation(pos,name)
|
|
return
|
|
end
|
|
local meta = minetest.get_meta(pos)
|
|
meta:set_string("channel",fields.channel)
|
|
end,
|
|
on_punch = function(screenpos,_,player)
|
|
if player and not player.is_fake_player then
|
|
local eyepos = vector.add(player:get_pos(),vector.add(player:get_eye_offset(),vector.new(0,1.5,0)))
|
|
local lookdir = player:get_look_dir()
|
|
local distance = vector.distance(eyepos,screenpos)
|
|
local endpos = vector.add(eyepos,vector.multiply(lookdir,distance+1))
|
|
local ray = minetest.raycast(eyepos,endpos,true,false)
|
|
local pointed,screen,hitpos
|
|
repeat
|
|
pointed = ray:next()
|
|
if pointed and pointed.type == "node" then
|
|
local node = minetest.get_node(pointed.under)
|
|
if node.name == "digiscreen:digiscreen" then
|
|
screen = pointed.under
|
|
hitpos = vector.subtract(pointed.intersection_point,screen)
|
|
end
|
|
end
|
|
until screen or not pointed
|
|
if not hitpos then return end
|
|
local facedir = minetest.facedir_to_dir(minetest.get_node(screen).param2)
|
|
if facedir.x > 0 then
|
|
hitpos.x = -1*hitpos.z
|
|
elseif facedir.x < 0 then
|
|
hitpos.x = hitpos.z
|
|
elseif facedir.z < 0 then
|
|
hitpos.x = -1*hitpos.x
|
|
end
|
|
hitpos.y = -1*hitpos.y
|
|
local hitpixel = {}
|
|
hitpixel.x = math.floor((hitpos.x+0.5)*16+0.5)+1
|
|
hitpixel.y = math.floor((hitpos.y+0.5)*16+0.5)+1
|
|
if hitpixel.x < 1 or hitpixel.x > 16 or hitpixel.y < 1 or hitpixel.y > 16 then return end
|
|
local message = {
|
|
x = hitpixel.x,
|
|
y = hitpixel.y,
|
|
player = player:get_player_name(),
|
|
}
|
|
digilines.receptor_send(screenpos,digilines.rules.default,minetest.get_meta(screenpos):get_string("channel"),message)
|
|
end
|
|
end,
|
|
digiline = {
|
|
wire = {
|
|
rules = digilines.rules.default,
|
|
},
|
|
effector = {
|
|
action = function(pos,_,channel,msg)
|
|
local meta = minetest.get_meta(pos)
|
|
local setchan = meta:get_string("channel")
|
|
if type(msg) ~= "table" or setchan ~= channel then return end
|
|
local data = {}
|
|
for y=1,16,1 do
|
|
data[y] = {}
|
|
if type(msg[y]) ~= "table" then msg[y] = {} end
|
|
for x=1,16,1 do
|
|
if type(msg[y][x]) == "string" and string.len(msg[y][x]) == 7 and string.sub(msg[y][x],1,1) == "#" then
|
|
msg[y][x] = string.sub(msg[y][x],2,-1)
|
|
end
|
|
if type(msg[y][x]) ~= "string" or string.len(msg[y][x]) ~= 6 then msg[y][x] = "000000" end
|
|
msg[y][x] = string.upper(msg[y][x])
|
|
for i=1,6,1 do
|
|
if not tonumber(string.sub(msg[y][x],i,i),16) then
|
|
msg[y][x] = "000000"
|
|
end
|
|
end
|
|
data[y][x] = msg[y][x]
|
|
end
|
|
end
|
|
meta:set_string("data",minetest.serialize(data))
|
|
updateDisplay(pos)
|
|
end,
|
|
},
|
|
},
|
|
})
|
|
|
|
minetest.register_lbm({
|
|
name = "digiscreen:respawn",
|
|
label = "Respawn digiscreen entities",
|
|
nodenames = {"digiscreen:digiscreen"},
|
|
run_at_every_load = true,
|
|
action = updateDisplay,
|
|
})
|
|
|
|
minetest.register_craft({
|
|
output = "digiscreen:digiscreen",
|
|
recipe = {
|
|
{"mesecons_luacontroller:luacontroller0000","rgblightstone:rgblightstone_truecolor_0","rgblightstone:rgblightstone_truecolor_0",},
|
|
{"rgblightstone:rgblightstone_truecolor_0","rgblightstone:rgblightstone_truecolor_0","rgblightstone:rgblightstone_truecolor_0",},
|
|
{"rgblightstone:rgblightstone_truecolor_0","rgblightstone:rgblightstone_truecolor_0","rgblightstone:rgblightstone_truecolor_0",},
|
|
},
|
|
})
|