celevator-cd2025/pilantern.lua
2024-09-15 12:38:00 -05:00

581 lines
20 KiB
Lua

celevator.pi = {}
celevator.lantern = {}
local boringside = "[combine:64x64"..
":0,0=celevator_cabinet_sides.png"..
":32,0=celevator_cabinet_sides.png"..
":0,32=celevator_cabinet_sides.png"..
":32,32=celevator_cabinet_sides.png"
local displaytex = boringside..":16,40=celevator_pi_background.png"
minetest.register_entity("celevator:pi_entity",{
initial_properties = {
visual = "upright_sprite",
physical = false,
collisionbox = {0,0,0,0,0,0,},
textures = {"celevator_transparent.png",},
static_save = false,
glow = minetest.LIGHT_MAX,
},
})
minetest.register_entity("celevator:incar_pi_entity",{
initial_properties = {
visual = "upright_sprite",
physical = false,
collisionbox = {0,0,0,0,0,0,},
textures = {"celevator_transparent.png",},
static_save = false,
glow = minetest.LIGHT_MAX,
},
on_step = function(self)
local pos = self.object:get_pos()
local props = self.object:get_properties()
if props.breath_max and props.breath_max ~= 0 then
local carinfo = minetest.deserialize(celevator.storage:get_string(string.format("car%d",props.breath_max)))
if not carinfo then return end
local text = carinfo.pitext or "--"
if string.len(text) < 3 then text = string.rep(" ",3-string.len(text))..text end
text = string.sub(text,1,3)
if carinfo.flash_is and os.time()%2 == 0 then
text = " IS"
elseif carinfo.flash_fs and os.time()%2 == 0 then
text = " FS"
elseif carinfo.flash_blank and os.time()%2 == 0 then
text = " "
end
local etex = celevator.pi.generatetexture(text,carinfo.piuparrow,carinfo.pidownarrow,false,true)
self.object:set_properties({textures = {etex}})
else
local carpos = vector.round(pos)
local carmeta = minetest.get_meta(carpos)
local carid = carmeta:get_int("carid")
if carid > 0 then self.object:set_properties({breath_max=carid}) end
end
end,
})
function celevator.pi.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 == "celevator:pi_entity" or i:get_luaentity().name == "celevator:incar_pi_entity") then
i:remove()
end
end
end
function celevator.pi.generatetexture(text,uparrow,downarrow,lanternoffset,carbg)
local out = "[combine:600x600:0,0=celevator_transparent.png"
if carbg then out = out..":0,0=celevator_pi_background_incar.png" end
local yp = 440
if lanternoffset then yp = 290 end
for i=1,string.len(text),1 do
local char = string.byte(string.sub(text,i,i))
if char ~= " " then out = out..string.format(":%d,%d=celevator_pi_%02X.png",(i-1)*50+260,yp,(char >= 0x20 and char < 0x7F and char or 0x2A)) end
end
if uparrow then out = out..string.format(":200,%d=celevator_pi_arrow.png",yp)
elseif downarrow then out = out..string.format(":200,%d=(celevator_pi_arrow.png^[transformFY)",yp) end
return out
end
function celevator.pi.updatedisplay(pos)
celevator.pi.removeentity(pos)
local meta = minetest.get_meta(pos)
local text = meta:get_string("text")
local entity = minetest.add_entity(pos,"celevator:pi_entity")
local fdir = minetest.facedir_to_dir(celevator.get_node(pos).param2)
local uparrow = meta:get_int("uparrow") > 0
local downarrow = meta:get_int("downarrow") > 0
local flash_fs = meta:get_int("flash_fs") > 0
local flash_is = meta:get_int("flash_is") > 0
local flashtimer = meta:get_int("flashtimer") > 0
local islantern = minetest.get_item_group(celevator.get_node(pos).name,"_celevator_lantern") == 1
local etex = celevator.pi.generatetexture(text,uparrow,downarrow,islantern)
if flash_fs then
if flashtimer then etex = celevator.pi.generatetexture(" FS",uparrow,downarrow,islantern) end
entity:set_properties({_flash_fs = true,_flash_is = false,})
elseif flash_is then
if flashtimer then etex = celevator.pi.generatetexture(" IS",uparrow,downarrow,islantern) end
entity:set_properties({_flash_fs = false,_flash_is = true,})
else
entity:set_properties({_flash_fs = false,_flash_is = false,})
end
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.47)))
end
function celevator.pi.flash(pos,what)
if minetest.get_item_group(celevator.get_node(pos).name,"_celevator_pi") ~= 1 then return end
local meta = minetest.get_meta(pos)
if what == "FS" then
meta:set_int("flash_is",0)
meta:set_int("flash_fs",1)
elseif what == "IS" then
meta:set_int("flash_is",1)
meta:set_int("flash_fs",0)
else
meta:set_int("flash_is",0)
meta:set_int("flash_fs",0)
end
celevator.pi.updatedisplay(pos)
end
function celevator.pi.settext(pos,text)
if not text then text = " --" end
if minetest.get_item_group(celevator.get_node(pos).name,"_celevator_pi") ~= 1 then return end
local meta = minetest.get_meta(pos)
if string.len(text) < 3 then
text = string.rep(" ",3-string.len(text))..text
end
meta:set_string("text",string.sub(text,1,3))
celevator.pi.updatedisplay(pos)
end
function celevator.pi.setarrow(pos,which,active)
if minetest.get_item_group(celevator.get_node(pos).name,"_celevator_pi") ~= 1 then return end
local meta = minetest.get_meta(pos)
if which == "up" then
meta:set_int("uparrow",active and 1 or 0)
elseif which == "down" then
meta:set_int("downarrow",active and 1 or 0)
end
celevator.pi.updatedisplay(pos)
end
minetest.register_node("celevator:pi",{
description = "Elevator Position Indicator",
groups = {
dig_immediate = 2,
_celevator_pi = 1,
},
tiles = {
boringside,
boringside,
boringside,
boringside,
boringside,
displaytex,
},
inventory_image = "[combine:32x32:0,5=celevator_pi_background.png",
paramtype = "light",
paramtype2 = "facedir",
drawtype = "nodebox",
light_source = 3,
node_box = {
type = "fixed",
fixed = {
{-0.25,-0.453,0.475,0.25,-0.125,0.5},
},
},
after_place_node = function(pos)
local meta = minetest.get_meta(pos)
meta:set_string("formspec","formspec_version[7]size[8,5]field[0.5,0.5;7,1;carid;Car ID;]button[3,3.5;2,1;save;Save]")
end,
on_receive_fields = function(pos,_,fields)
if tonumber(fields.carid) then
local carid = tonumber(fields.carid)
local carinfo = minetest.deserialize(celevator.storage:get_string(string.format("car%d",carid)))
if not (carinfo and carinfo.pis) then return end
table.insert(carinfo.pis,{pos=pos})
celevator.storage:set_string(string.format("car%d",carid),minetest.serialize(carinfo))
local meta = minetest.get_meta(pos)
meta:set_int("carid",carid)
meta:set_string("formspec","")
celevator.pi.settext(pos,carinfo.pitext)
end
end,
on_destruct = function(pos)
celevator.pi.removeentity(pos)
local meta = minetest.get_meta(pos)
local carid = meta:get_int("carid")
if carid == 0 then return end
local carinfo = minetest.deserialize(celevator.storage:get_string(string.format("car%d",carid)))
if not (carinfo and carinfo.pis) then return end
for i,pi in pairs(carinfo.pis) do
if vector.equals(pos,pi.pos) then
table.remove(carinfo.pis,i)
celevator.storage:set_string(string.format("car%d",carid),minetest.serialize(carinfo))
end
end
end,
on_construct = function(pos)
local meta = minetest.get_meta(pos)
meta:set_string("text","--")
celevator.pi.updatedisplay(pos)
end,
})
function celevator.lantern.setlight(pos,dir,newstate)
local node = celevator.get_node(pos)
if minetest.get_item_group(node.name,"_celevator_lantern") ~= 1 then return end
if dir == "up" then
if minetest.get_item_group(node.name,"_celevator_lantern_has_up") ~= 1 then return end
local lit = minetest.get_item_group(node.name,"_celevator_lantern_up_lit") == 1
if lit == newstate then return end
local newname = "celevator:lantern_"
if minetest.get_item_group(node.name,"_celevator_pi") == 1 then newname = "celevator:pilantern_" end
if minetest.get_item_group(node.name,"_celevator_lantern_vertical") == 1 then newname = "celevator:lantern_vertical_" end
if minetest.get_item_group(node.name,"_celevator_lantern_has_down") == 1 then
newname = newname.."both"
else
newname = newname.."up"
end
if newstate then
newname = newname.."_upon"
minetest.sound_play("celevator_chime_up",{pos = pos},true)
end
if minetest.get_item_group(node.name,"_celevator_lantern_down_lit") == 1 then
newname = newname.."_downon"
end
node.name = newname
minetest.swap_node(pos,node)
elseif dir == "down" then
if minetest.get_item_group(node.name,"_celevator_lantern_has_down") ~= 1 then return end
local lit = minetest.get_item_group(node.name,"_celevator_lantern_down_lit") == 1
if lit == newstate then return end
local newname = "celevator:lantern_"
if minetest.get_item_group(node.name,"_celevator_pi") == 1 then newname = "celevator:pilantern_" end
if minetest.get_item_group(node.name,"_celevator_lantern_vertical") == 1 then newname = "celevator:lantern_vertical_" end
if minetest.get_item_group(node.name,"_celevator_lantern_has_up") == 1 then
newname = newname.."both"
else
newname = newname.."down"
end
if minetest.get_item_group(node.name,"_celevator_lantern_up_lit") == 1 then
newname = newname.."_upon"
end
if newstate then
newname = newname.."_downon"
minetest.sound_play("celevator_chime_down",{pos = pos},true)
end
node.name = newname
minetest.swap_node(pos,node)
end
end
local function makepilanterntex(dir,upon,downon)
local tex = boringside
if dir == "up" then
tex = tex..":16,24=celevator_pi_lantern_background_up.png"
if upon then
tex = tex..":26,49=celevator_lantern_up.png"
end
elseif dir == "down" then
tex = tex..":16,24=celevator_pi_lantern_background_down.png"
if downon then
tex = tex..":27,49=celevator_lantern_down.png"
end
elseif dir == "both" then
tex = tex..":16,24=celevator_pi_lantern_background_updown.png"
if upon then
tex = tex..":20,49=celevator_lantern_up.png"
end
if downon then
tex = tex..":33,49=celevator_lantern_down.png"
end
end
return(tex)
end
local function makelanterntex(dir,upon,downon)
local tex = boringside
if dir == "up" then
tex = tex..":16,32=celevator_lantern_background_up.png"
if upon then
tex = tex..":26,36=celevator_lantern_up.png"
end
elseif dir == "down" then
tex = tex..":16,32=celevator_lantern_background_down.png"
if downon then
tex = tex..":27,36=celevator_lantern_down.png"
end
elseif dir == "both" then
tex = tex..":16,32=celevator_lantern_background_updown.png"
if upon then
tex = tex..":20,36=celevator_lantern_up.png"
end
if downon then
tex = tex..":33,36=celevator_lantern_down.png"
end
end
return(tex)
end
local function makeverticallanterntex(dir,upon,downon)
local tex = boringside
if dir == "up" then
tex = tex..":22,12=celevator_lantern_vertical_background_up.png"
if upon then
tex = tex..":27,25=celevator_lantern_up.png"
end
elseif dir == "down" then
tex = tex..":22,12=celevator_lantern_vertical_background_down.png"
if downon then
tex = tex..":27,26=celevator_lantern_down.png"
end
elseif dir == "both" then
tex = tex..":22,12=celevator_lantern_vertical_background_updown.png"
if upon then
tex = tex..":27,18=celevator_lantern_up.png"
end
if downon then
tex = tex..":27,34=celevator_lantern_down.png"
end
end
return(tex)
end
local validstates = {
{"up",false,false,"Up"},
{"up",true,false,"Up"},
{"down",false,false,"Down"},
{"down",false,true,"Down"},
{"both",false,false,"Up and Down"},
{"both",true,false,"Up and Down"},
{"both",false,true,"Up and Down"},
{"both",true,true,"Up and Down"},
}
for _,state in ipairs(validstates) do
local nname = "celevator:pilantern_"..state[1]
local dropname = nname
local light = 0
if state[2] then
nname = nname.."_upon"
light = light + 4
end
if state[3] then
nname = nname.."_downon"
light = light + 4
end
local idle = not (state[2] or state[3])
local description = string.format("Elevator %s Position Indicator/Lantern Combo%s",state[4],(idle and "" or " (on state, you hacker you!)"))
minetest.register_node(nname,{
description = description,
groups = {
dig_immediate = 2,
not_in_creative_inventory = (idle and 0 or 1),
_celevator_lantern = 1,
_celevator_lantern_has_up = (state[1] == "down" and 0 or 1),
_celevator_lantern_has_down = (state[1] == "up" and 0 or 1),
_celevator_lantern_up_lit = (state[2] and 1 or 0),
_celevator_lantern_down_lit = (state[3] and 1 or 0),
_celevator_pi = 1,
},
drop = dropname,
tiles = {
boringside,
boringside,
boringside,
boringside,
boringside,
makepilanterntex(state[1],state[2],state[3])
},
inventory_image = string.format("[combine:42x42:5,0=celevator_pi_lantern_background_%s.png",(state[1] == "both" and "updown" or state[1])),
paramtype = "light",
paramtype2 = "facedir",
drawtype = "nodebox",
light_source = light + 3,
node_box = {
type = "fixed",
fixed = {
{-0.25,-0.5,0.475,0.25,0.125,0.5},
},
},
after_place_node = function(pos)
local meta = minetest.get_meta(pos)
meta:set_string("formspec","formspec_version[7]size[8,5]field[0.5,0.5;7,1;carid;Car ID;]field[0.5,2;7,1;landing;Landing Number;]button[3,3.5;2,1;save;Save]")
end,
on_receive_fields = function(pos,_,fields)
if tonumber(fields.carid) and tonumber(fields.landing) then
local carid = tonumber(fields.carid)
local landing = tonumber(fields.landing)
local carinfo = minetest.deserialize(celevator.storage:get_string(string.format("car%d",carid)))
if not (carinfo and carinfo.pis and carinfo.lanterns) then return end
table.insert(carinfo.pis,{pos=pos})
table.insert(carinfo.lanterns,{pos=pos,landing=landing})
celevator.storage:set_string(string.format("car%d",carid),minetest.serialize(carinfo))
local meta = minetest.get_meta(pos)
meta:set_int("carid",carid)
meta:set_string("formspec","")
celevator.pi.settext(pos,carinfo.pitext)
end
end,
on_destruct = function(pos)
celevator.pi.removeentity(pos)
local meta = minetest.get_meta(pos)
local carid = meta:get_int("carid")
if carid == 0 then return end
local carinfo = minetest.deserialize(celevator.storage:get_string(string.format("car%d",carid)))
if not (carinfo and carinfo.pis and carinfo.lanterns) then return end
for i,pi in pairs(carinfo.pis) do
if vector.equals(pos,pi.pos) then
table.remove(carinfo.pis,i)
celevator.storage:set_string(string.format("car%d",carid),minetest.serialize(carinfo))
end
end
for i,lantern in pairs(carinfo.lanterns) do
if vector.equals(pos,lantern.pos) then
table.remove(carinfo.lanterns,i)
celevator.storage:set_string(string.format("car%d",carid),minetest.serialize(carinfo))
end
end
end,
on_construct = function(pos)
local meta = minetest.get_meta(pos)
meta:set_string("text","--")
celevator.pi.updatedisplay(pos)
end,
})
nname = "celevator:lantern_"..state[1]
dropname = nname
if state[2] then nname = nname.."_upon" end
if state[3] then nname = nname.."_downon" end
idle = not (state[2] or state[3])
description = string.format("Elevator %s Lantern%s",state[4],(idle and "" or " (on state, you hacker you!)"))
minetest.register_node(nname,{
description = description,
inventory_image = string.format("[combine:32x32:0,5=celevator_lantern_background_%s.png",(state[1] == "both" and "updown" or state[1])),
groups = {
dig_immediate = 2,
not_in_creative_inventory = (idle and 0 or 1),
_celevator_lantern = 1,
_celevator_lantern_has_up = (state[1] == "down" and 0 or 1),
_celevator_lantern_has_down = (state[1] == "up" and 0 or 1),
_celevator_lantern_up_lit = (state[2] and 1 or 0),
_celevator_lantern_down_lit = (state[3] and 1 or 0),
},
drop = dropname,
tiles = {
boringside,
boringside,
boringside,
boringside,
boringside,
makelanterntex(state[1],state[2],state[3])
},
after_place_node = function(pos)
local meta = minetest.get_meta(pos)
meta:set_string("formspec","formspec_version[7]size[8,5]field[0.5,0.5;7,1;carid;Car ID;]field[0.5,2;7,1;landing;Landing Number;]button[3,3.5;2,1;save;Save]")
end,
on_receive_fields = function(pos,_,fields)
if tonumber(fields.carid) and tonumber(fields.landing) then
local carid = tonumber(fields.carid)
local landing = tonumber(fields.landing)
local carinfo = minetest.deserialize(celevator.storage:get_string(string.format("car%d",carid)))
if not (carinfo and carinfo.lanterns) then return end
table.insert(carinfo.lanterns,{pos=pos,landing=landing})
celevator.storage:set_string(string.format("car%d",carid),minetest.serialize(carinfo))
local meta = minetest.get_meta(pos)
meta:set_int("carid",carid)
meta:set_string("formspec","")
end
end,
on_destruct = function(pos)
local meta = minetest.get_meta(pos)
local carid = meta:get_int("carid")
if carid == 0 then return end
local carinfo = minetest.deserialize(celevator.storage:get_string(string.format("car%d",carid)))
if not (carinfo and carinfo.lanterns) then return end
for i,lantern in pairs(carinfo.lanterns) do
if vector.equals(pos,lantern.pos) then
table.remove(carinfo.lanterns,i)
celevator.storage:set_string(string.format("car%d",carid),minetest.serialize(carinfo))
end
end
end,
paramtype = "light",
paramtype2 = "facedir",
light_source = light,
drawtype = "nodebox",
node_box = {
type = "fixed",
fixed = {
{-0.25,-0.328,0.475,0.25,0,0.5},
},
},
})
nname = "celevator:lantern_vertical_"..state[1]
dropname = nname
if state[2] then nname = nname.."_upon" end
if state[3] then nname = nname.."_downon" end
description = string.format("Elevator %s Lantern (vertical)%s",state[4],(idle and "" or " (on state, you hacker you!)"))
minetest.register_node(nname,{
description = description,
inventory_image = string.format("[combine:40x40:10,0=celevator_lantern_vertical_background_%s.png",(state[1] == "both" and "updown" or state[1])),
groups = {
dig_immediate = 2,
not_in_creative_inventory = (idle and 0 or 1),
_celevator_lantern = 1,
_celevator_lantern_has_up = (state[1] == "down" and 0 or 1),
_celevator_lantern_has_down = (state[1] == "up" and 0 or 1),
_celevator_lantern_up_lit = (state[2] and 1 or 0),
_celevator_lantern_down_lit = (state[3] and 1 or 0),
_celevator_lantern_vertical = 1,
},
drop = dropname,
tiles = {
boringside,
boringside,
boringside,
boringside,
boringside,
makeverticallanterntex(state[1],state[2],state[3])
},
after_place_node = function(pos)
local meta = minetest.get_meta(pos)
meta:set_string("formspec","formspec_version[7]size[8,5]field[0.5,0.5;7,1;carid;Car ID;]field[0.5,2;7,1;landing;Landing Number;]button[3,3.5;2,1;save;Save]")
end,
on_receive_fields = function(pos,_,fields)
if tonumber(fields.carid) and tonumber(fields.landing) then
local carid = tonumber(fields.carid)
local landing = tonumber(fields.landing)
local carinfo = minetest.deserialize(celevator.storage:get_string(string.format("car%d",carid)))
if not (carinfo and carinfo.lanterns) then return end
table.insert(carinfo.lanterns,{pos=pos,landing=landing})
celevator.storage:set_string(string.format("car%d",carid),minetest.serialize(carinfo))
local meta = minetest.get_meta(pos)
meta:set_int("carid",carid)
meta:set_string("formspec","")
end
end,
on_destruct = function(pos)
local meta = minetest.get_meta(pos)
local carid = meta:get_int("carid")
if carid == 0 then return end
local carinfo = minetest.deserialize(celevator.storage:get_string(string.format("car%d",carid)))
if not (carinfo and carinfo.lanterns) then return end
for i,lantern in pairs(carinfo.lanterns) do
if vector.equals(pos,lantern.pos) then
table.remove(carinfo.lanterns,i)
celevator.storage:set_string(string.format("car%d",carid),minetest.serialize(carinfo))
end
end
end,
paramtype = "light",
paramtype2 = "facedir",
light_source = light,
drawtype = "nodebox",
node_box = {
type = "fixed",
fixed = {
{-0.14,-0.313,0.475,0.156,0.313,0.5},
},
},
})
end
minetest.register_abm({
label = "Respawn / Flash PI displays",
nodenames = {"group:_celevator_pi"},
interval = 1,
chance = 1,
action = function(pos)
local meta = minetest.get_meta(pos)
local flashtimer = meta:get_int("flashtimer") > 0
meta:set_int("flashtimer",flashtimer and 0 or 1)
celevator.pi.updatedisplay(pos)
end,
})