minetest-mm/mods/advtrains/advtrains/signals.lua

363 lines
11 KiB
Lua

--advtrains by orwell96
--signals.lua
local mrules_wallsignal = advtrains.meseconrules
local function can_dig_func(pos)
if advtrains.interlocking then
return advtrains.interlocking.signal_can_dig(pos)
end
return true
end
local function after_dig_func(pos)
if advtrains.interlocking then
return advtrains.interlocking.signal_after_dig(pos)
end
return true
end
local function aspect(b)
return {
main = b and -1 or 0,
shunt = false,
proceed_as_main = true,
dst = false,
info = {}
}
end
local suppasp = {
main = {0, -1},
dst = {false},
shunt = nil,
proceed_as_main = true,
info = {
call_on = false,
dead_end = false,
w_speed = nil,
}
}
for r,f in pairs({on={as="off", ls="green", als="red"}, off={as="on", ls="red", als="green"}}) do
advtrains.trackplacer.register_tracktype("advtrains:retrosignal", "")
advtrains.trackplacer.register_tracktype("advtrains:signal", "")
for rotid, rotation in ipairs({"", "_30", "_45", "_60"}) do
local crea=1
if rotid==1 and r=="off" then crea=0 end
minetest.register_node("advtrains:retrosignal_"..r..rotation, {
drawtype = "mesh",
paramtype="light",
paramtype2="facedir",
walkable = false,
selection_box = {
type = "fixed",
fixed = {-1/4, -1/2, -1/4, 1/4, 2, 1/4},
},
mesh = "advtrains_retrosignal_"..r..rotation..".b3d",
tiles = {"advtrains_retrosignal.png"},
inventory_image="advtrains_retrosignal_inv.png",
drop="advtrains:retrosignal_off",
description=attrans("Lampless Signal (@1)", attrans(r..rotation)),
sunlight_propagates=true,
groups = {
cracky=3,
not_blocking_trains=1,
not_in_creative_inventory=crea,
save_in_at_nodedb=1,
advtrains_signal = 2,
},
mesecons = {effector = {
rules=advtrains.meseconrules,
["action_"..f.as] = function (pos, node)
advtrains.ndb.swap_node(pos, {name = "advtrains:retrosignal_"..f.as..rotation, param2 = node.param2}, true)
if advtrains.interlocking then
advtrains.interlocking.signal_on_aspect_changed(pos)
end
end
}},
on_rightclick=function(pos, node, player)
local pname = player:get_player_name()
local sigd = advtrains.interlocking and advtrains.interlocking.db.get_sigd_for_signal(pos)
if sigd then
advtrains.interlocking.show_signalling_form(sigd, pname)
elseif advtrains.interlocking and player:get_player_control().aux1 then
advtrains.interlocking.show_ip_form(pos, pname)
elseif advtrains.check_turnout_signal_protection(pos, player:get_player_name()) then
advtrains.ndb.swap_node(pos, {name = "advtrains:retrosignal_"..f.as..rotation, param2 = node.param2}, true)
if advtrains.interlocking then
advtrains.interlocking.signal_on_aspect_changed(pos)
end
end
end,
-- new signal API
advtrains = {
set_aspect = function(pos, node, asp)
if asp.main ~= 0 then
advtrains.ndb.swap_node(pos, {name = "advtrains:retrosignal_on"..rotation, param2 = node.param2}, true)
else
advtrains.ndb.swap_node(pos, {name = "advtrains:retrosignal_off"..rotation, param2 = node.param2}, true)
end
end,
get_aspect = function(pos, node)
return aspect(r=="on")
end,
supported_aspects = suppasp,
},
can_dig = can_dig_func,
after_dig_node = after_dig_func,
})
advtrains.trackplacer.add_worked("advtrains:retrosignal", r, rotation, nil)
minetest.register_node("advtrains:signal_"..r..rotation, {
drawtype = "mesh",
paramtype="light",
paramtype2="facedir",
walkable = false,
selection_box = {
type = "fixed",
fixed = {-1/4, -1/2, -1/4, 1/4, 2, 1/4},
},
mesh = "advtrains_signal"..rotation..".b3d",
tiles = {"advtrains_signal_"..r..".png"},
inventory_image="advtrains_signal_inv.png",
drop="advtrains:signal_off",
description=attrans("Signal (@1)", attrans(r..rotation)),
groups = {
cracky=3,
not_blocking_trains=1,
not_in_creative_inventory=crea,
save_in_at_nodedb=1,
advtrains_signal = 2,
},
light_source = 1,
sunlight_propagates=true,
mesecons = {effector = {
rules=advtrains.meseconrules,
["action_"..f.as] = function (pos, node)
advtrains.setstate(pos, f.als, node)
if advtrains.interlocking then
advtrains.interlocking.signal_on_aspect_changed(pos)
end
end
}},
on_rightclick=function(pos, node, player)
local pname = player:get_player_name()
local sigd = advtrains.interlocking and advtrains.interlocking.db.get_sigd_for_signal(pos)
if sigd then
advtrains.interlocking.show_signalling_form(sigd, pname)
elseif advtrains.interlocking and player:get_player_control().aux1 then
advtrains.interlocking.show_ip_form(pos, pname)
elseif advtrains.check_turnout_signal_protection(pos, player:get_player_name()) then
advtrains.setstate(pos, f.als, node)
if advtrains.interlocking then
advtrains.interlocking.signal_on_aspect_changed(pos)
end
end
end,
-- new signal API
advtrains = {
set_aspect = function(pos, node, asp)
if asp.main ~= 0 then
advtrains.ndb.swap_node(pos, {name = "advtrains:signal_on"..rotation, param2 = node.param2}, true)
else
advtrains.ndb.swap_node(pos, {name = "advtrains:signal_off"..rotation, param2 = node.param2}, true)
end
end,
get_aspect = function(pos, node)
return aspect(r=="on")
end,
supported_aspects = suppasp,
getstate = f.ls,
setstate = function(pos, node, newstate)
if newstate == f.als then
advtrains.ndb.swap_node(pos, {name = "advtrains:signal_"..f.as..rotation, param2 = node.param2}, true)
end
end,
},
can_dig = can_dig_func,
after_dig_node = after_dig_func,
})
advtrains.trackplacer.add_worked("advtrains:signal", r, rotation, nil)
end
local crea=1
if r=="off" then crea=0 end
--tunnel signals. no rotations.
for loc, sbox in pairs({l={-1/2, -1/2, -1/4, 0, 1/2, 1/4}, r={0, -1/2, -1/4, 1/2, 1/2, 1/4}, t={-1/2, 0, -1/4, 1/2, 1/2, 1/4}}) do
minetest.register_node("advtrains:signal_wall_"..loc.."_"..r, {
drawtype = "mesh",
paramtype="light",
paramtype2="facedir",
walkable = false,
selection_box = {
type = "fixed",
fixed = sbox,
},
mesh = "advtrains_signal_wall_"..loc..".b3d",
tiles = {"advtrains_signal_wall_"..r..".png"},
drop="advtrains:signal_wall_"..loc.."_off",
description=attrans("Wallmounted Signal ("..loc..")"),
groups = {
cracky=3,
not_blocking_trains=1,
not_in_creative_inventory=crea,
save_in_at_nodedb=1,
advtrains_signal = 2,
},
light_source = 1,
sunlight_propagates=true,
mesecons = {effector = {
rules = mrules_wallsignal,
["action_"..f.as] = function (pos, node)
advtrains.setstate(pos, f.als, node)
if advtrains.interlocking then
advtrains.interlocking.signal_on_aspect_changed(pos)
end
end
}},
on_rightclick=function(pos, node, player)
local pname = player:get_player_name()
local sigd = advtrains.interlocking and advtrains.interlocking.db.get_sigd_for_signal(pos)
if sigd then
advtrains.interlocking.show_signalling_form(sigd, pname)
elseif advtrains.interlocking and player:get_player_control().aux1 then
advtrains.interlocking.show_ip_form(pos, pname)
elseif advtrains.check_turnout_signal_protection(pos, player:get_player_name()) then
advtrains.setstate(pos, f.als, node)
if advtrains.interlocking then
advtrains.interlocking.signal_on_aspect_changed(pos)
end
end
end,
-- new signal API
advtrains = {
set_aspect = function(pos, node, asp)
if asp.main ~= 0 then
advtrains.ndb.swap_node(pos, {name = "advtrains:signal_wall_"..loc.."_on", param2 = node.param2}, true)
else
advtrains.ndb.swap_node(pos, {name = "advtrains:signal_wall_"..loc.."_off", param2 = node.param2}, true)
end
end,
get_aspect = function(pos, node)
return aspect(r=="on")
end,
supported_aspects = suppasp,
getstate = f.ls,
setstate = function(pos, node, newstate)
if newstate == f.als then
advtrains.ndb.swap_node(pos, {name = "advtrains:signal_wall_"..loc.."_"..f.as, param2 = node.param2}, true)
end
end,
},
can_dig = can_dig_func,
after_dig_node = after_dig_func,
})
end
end
-- level crossing
-- german version (Andrew's Cross)
minetest.register_node("advtrains:across_off", {
drawtype = "mesh",
paramtype="light",
paramtype2="facedir",
walkable = false,
selection_box = {
type = "fixed",
fixed = {-1/4, -1/2, -1/2, 1/4, 1.5, 0},
},
mesh = "advtrains_across.obj",
tiles = {"advtrains_across.png"},
drop="advtrains:across_off",
description=attrans("Andrew's Cross"),
groups = {
cracky=3,
not_blocking_trains=1,
save_in_at_nodedb=1,
not_in_creative_inventory=nil,
},
light_source = 1,
sunlight_propagates=true,
mesecons = {effector = {
rules = advtrains.meseconrules,
action_on = function (pos, node)
advtrains.ndb.swap_node(pos, {name = "advtrains:across_on", param2 = node.param2}, true)
end
}},
advtrains = {
getstate = "off",
setstate = function(pos, node, newstate)
if newstate == "on" then
advtrains.ndb.swap_node(pos, {name = "advtrains:across_on", param2 = node.param2}, true)
end
end,
},
on_rightclick=function(pos, node, player)
if advtrains.check_turnout_signal_protection(pos, player:get_player_name()) then
advtrains.ndb.swap_node(pos, {name = "advtrains:across_on", param2 = node.param2}, true)
end
end,
})
minetest.register_node("advtrains:across_on", {
drawtype = "mesh",
paramtype="light",
paramtype2="facedir",
walkable = false,
selection_box = {
type = "fixed",
fixed = {-1/4, -1/2, -1/2, 1/4, 1.5, 0},
},
mesh = "advtrains_across.obj",
tiles = {{name="advtrains_across_anim.png", animation={type="vertical_frames", aspect_w=64, aspect_h=64, length=1.0}}},
drop="advtrains:across_off",
description=attrans("Andrew's Cross (on) (you hacker you)"),
groups = {
cracky=3,
not_blocking_trains=1,
save_in_at_nodedb=1,
not_in_creative_inventory=1,
},
light_source = 1,
sunlight_propagates=true,
mesecons = {effector = {
rules = advtrains.meseconrules,
action_off = function (pos, node)
advtrains.ndb.swap_node(pos, {name = "advtrains:across_off", param2 = node.param2}, true)
end
}},
advtrains = {
getstate = "on",
setstate = function(pos, node, newstate)
if newstate == "off" then
advtrains.ndb.swap_node(pos, {name = "advtrains:across_off", param2 = node.param2}, true)
end
end,
fallback_state = "off",
},
on_rightclick=function(pos, node, player)
if advtrains.check_turnout_signal_protection(pos, player:get_player_name()) then
advtrains.ndb.swap_node(pos, {name = "advtrains:across_off", param2 = node.param2}, true)
end
end,
})
minetest.register_abm(
{
label = "Sound for Level Crossing",
nodenames = {"advtrains:across_on"},
interval = 3,
chance = 1,
action = function(pos, node, active_object_count, active_object_count_wider)
minetest.sound_play("advtrains_crossing_bell", {
pos = pos,
gain = 1.0, -- default
max_hear_distance = 16, -- default, uses an euclidean metric
})
end,
}
)