diff options
Diffstat (limited to 'advtrains/signals.lua')
-rw-r--r-- | advtrains/signals.lua | 362 |
1 files changed, 362 insertions, 0 deletions
diff --git a/advtrains/signals.lua b/advtrains/signals.lua new file mode 100644 index 0000000..5fb1d1b --- /dev/null +++ b/advtrains/signals.lua @@ -0,0 +1,362 @@ +--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 = (not b) and 0, -- b ? false : 0 + shunt = false, + proceed_as_main = true, + dst = false, + info = {} +} +end + +local suppasp = { + main = {0, false}, + 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, + } +) |