From dcceb65ff04573375016f2460edcbd349e506a4e Mon Sep 17 00:00:00 2001 From: orwell Date: Wed, 12 Jun 2024 00:25:14 +0200 Subject: Respect route_role of signals during routesetting, assign distant signals in routes --- advtrains_interlocking/routesetting.lua | 46 +++++++++++++++++++++++-------- advtrains_interlocking/signal_api.lua | 22 +++++++++++---- advtrains_interlocking/tcb_ts_ui.lua | 3 +- advtrains_interlocking/train_sections.lua | 33 ++++++++-------------- 4 files changed, 65 insertions(+), 39 deletions(-) (limited to 'advtrains_interlocking') diff --git a/advtrains_interlocking/routesetting.lua b/advtrains_interlocking/routesetting.lua index 51709dc..d619aac 100644 --- a/advtrains_interlocking/routesetting.lua +++ b/advtrains_interlocking/routesetting.lua @@ -45,6 +45,7 @@ function ilrs.set_route(signal, route, try) local rtename = route.name local signalname = (ildb.get_tcbs(signal).signal_name or "") .. sigd_to_string(signal) local c_tcbs, c_ts_id, c_ts, c_rseg, c_lckp + -- signals = { { pos = ., tcbs_ref = , role = "main_distant", masp_override = nil, dst_type = "next_main" or "none" } local signals = {} local nodst while c_sigd and i<=#route do @@ -67,11 +68,11 @@ function ilrs.set_route(signal, route, try) if c_ts.route then if not try then atwarn("Encountered ts lock during a real run of routesetting routine, at ts=",c_ts_id,"while setting route",rtename,"of",signal) end - return false, "Section '"..c_ts.name.."' already has route set from "..sigd_to_string(c_ts.route.origin)..":\n"..c_ts.route.rsn, c_ts_id, nil + return false, "Section '"..(c_ts.name or c_ts_id).."' already has route set from "..sigd_to_string(c_ts.route.origin)..":\n"..c_ts.route.rsn, c_ts_id, nil end if c_ts.trains and #c_ts.trains>0 then if not try then atwarn("Encountered ts occupied during a real run of routesetting routine, at ts=",c_ts_id,"while setting route",rtename,"of",signal) end - return false, "Section '"..c_ts.name.."' is occupied!", c_ts_id, nil + return false, "Section '"..(c_ts.name or c_ts_id).."' is occupied!", c_ts_id, nil end -- collect locks from rs cache and from route def @@ -138,9 +139,17 @@ function ilrs.set_route(signal, route, try) } if c_tcbs.signal then c_tcbs.route_committed = true - c_tcbs.aspect = advtrains.interlocking.signal.MASP_FREE c_tcbs.route_origin = signal - signals[#signals+1] = c_tcbs + -- determine route role + local ndef = advtrains.ndb.get_ndef(c_tcbs.signal) + local sig_table = { + pos = c_tcbs.signal, + tcbs_ref = c_tcbs, + role = ndef and ndef.advtrains and ndef.advtrains.route_role, + masp_override = c_rseg.masp_override, --TODO implement masp_override on UI side + dst_type = "next_main", --TODO allow user differentiate + } + signals[#signals+1] = sig_table end end -- advance @@ -149,18 +158,31 @@ function ilrs.set_route(signal, route, try) i = i + 1 end - -- Distant signaling - local lastsig = nil + -- Get reference to signal at end of route + local last_mainsig = nil if c_sigd then local e_tcbs = ildb.get_tcbs(c_sigd) local pos = e_tcbs and e_tcbs.signal if pos then - lastsig = pos + last_mainsig = pos end end for i = #signals, 1, -1 do - -- TODO add logic for distant signal assign - advtrains.interlocking.signal.update_route_aspect(signals[i], i ~= 1) + -- note the signals are iterated backwards. Switch depending on the role + local sig = signals[i] + -- apply mainaspect + sig.tcbs_ref.route_aspect = sig.masp_override or "_default" + if sig.role == "distant" or sig.role == "distant_repeater" or sig.role == "main_distant" then + -- assign the remote as the last mainsig + sig.tcbs_ref.route_remote = last_mainsig + end + if sig.role == "main" or sig.role == "main_distant" or sig.role == "end" then + -- record this as the new last mainsig + last_mainsig = sig.pos + end + -- for shunt signals nothing happens + -- update the signal aspect on map + advtrains.interlocking.signal.update_route_aspect(sig.tcbs_ref, i ~= 1) end return true @@ -266,7 +288,8 @@ function ilrs.cancel_route_from(sigd) --atdebug("cancelling",c_ts.route.rsn) -- clear signal aspect and routesetting state c_tcbs.route_committed = nil - c_tcbs.aspect = nil + c_tcbs.route_aspect = nil + c_tcbs.route_remote = nil c_tcbs.routeset = nil c_tcbs.route_auto = nil c_tcbs.route_origin = nil @@ -321,7 +344,8 @@ function ilrs.update_route(sigd, tcbs, newrte, cancel) advtrains.interlocking.route.cancel_route_from(sigd) end tcbs.route_committed = nil - tcbs.aspect = nil + tcbs.route_aspect = nil + tcbs.route_remote = nil has_changed_aspect = true tcbs.routeset = nil tcbs.route_auto = nil diff --git a/advtrains_interlocking/signal_api.lua b/advtrains_interlocking/signal_api.lua index b1e8b20..65fc787 100644 --- a/advtrains_interlocking/signal_api.lua +++ b/advtrains_interlocking/signal_api.lua @@ -96,11 +96,12 @@ ndef.advtrains = { -- Returns the aspect info table (main, shunt, dst etc.) distant_support = true or false -- If true, signal is considered in distant signalling. If false or nil, rem_aspect and rem_aspinfo are never set. - route_role = one of "main", "shunt", "distant", "distant_repeater", "end" + route_role = one of "main", "main_distant", "shunt", "distant", "distant_repeater", "end" -- Determines how the signal behaves when routes are set. Only in effect when signal is assigned to a TCB. -- main: The signal is a possible endpoint for a train move route. Distant signals before it refer to it. -- shunt: The signal is a possible endpoint for a shunt move route. Ignored for distant signals. -- distant, distant_repeater: When route is set, signal is always assigned its first main aspect. The next signal with role="main" is set as the remote signal. (currently no further distinction) + -- main_distant: Combination of main and distant - like "main", but additionally gets assigned to the next main like a "distant" -- end: like main, but signifies that it marks an end of track and trains cannot continue further. (currently no practical implications above main) } @@ -329,9 +330,17 @@ function signal.get_aspect_info(pos) local masp, remote, node, ndef = signal.get_aspect_internal(pos, aspt) -- call into ndef if ndef.advtrains and ndef.advtrains.get_aspect_info then - local ai = ndef.advtrains.get_aspect_info(pos, masp) - atdebug(pos,"aspectinfo",ai) - return ai + local ai = ndef.advtrains.get_aspect_info + if type(ai)=="function" then + ai = ai(pos, masp) + end + if type(ai)=="table" then + atdebug(pos,"aspectinfo",ai) + return ai + else + error("For node "..node.name..": ndef.advtrains.get_aspect_info must be function or table") + end + end end @@ -380,8 +389,9 @@ end -- function signal.update_route_aspect(tcbs, skip_dst_notify) if tcbs.signal then - local asp = tcbs.aspect or signal.MASP_HALT - signal.set_aspect(tcbs.signal, asp.name, asp.speed, asp.remote, skip_dst_notify) + local asp = tcbs.route_aspect or "_halt" + local rem = tcbs.route_remote + signal.set_aspect(tcbs.signal, asp, rem, skip_dst_notify) end end diff --git a/advtrains_interlocking/tcb_ts_ui.lua b/advtrains_interlocking/tcb_ts_ui.lua index caf22e3..60be5f3 100755 --- a/advtrains_interlocking/tcb_ts_ui.lua +++ b/advtrains_interlocking/tcb_ts_ui.lua @@ -756,7 +756,8 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) local signal_pos = tcbs.signal ildb.set_sigd_for_signal(signal_pos, nil) tcbs.signal = nil - tcbs.aspect = nil + tcbs.route_aspect = nil + tcbs.route_remote = nil minetest.close_formspec(pname, formname) minetest.chat_send_player(pname, "Signal has been unassigned. Name and routes are kept for reuse.") return diff --git a/advtrains_interlocking/train_sections.lua b/advtrains_interlocking/train_sections.lua index 260f5a4..41da747 100644 --- a/advtrains_interlocking/train_sections.lua +++ b/advtrains_interlocking/train_sections.lua @@ -86,31 +86,22 @@ local function setsection(tid, train, ts_id, ts, sigd) advtrains.interlocking.route.cancel_route_from(ts.route.origin) atwarn("Route was cancelled.") else - -- train entered route regularily. Reset route and signal - tcbs.route_committed = nil - tcbs.route_comitted = nil -- TODO compatibility cleanup - tcbs.aspect = nil - tcbs.route_origin = nil - if tcbs.signal then - local spos = tcbs.signal - local _, setter = advtrains.distant.get_main(spos) - if setter == "routesetting" then - advtrains.distant.unassign_dst(spos, true) - end - end - advtrains.interlocking.update_signal_aspect(tcbs) - if tcbs.signal and sigd_equal(ts.route.entry, ts.route.origin) then - if tcbs.route_auto and tcbs.routeset then - --atdebug("Resetting route (",ts.route.origin,")") - advtrains.interlocking.route.update_route(ts.route.origin, tcbs) - else - tcbs.routeset = nil - end - end + -- train entered route regularily. end ts.route = nil end if tcbs.signal then + -- Reset route and signal + -- Note that the hit-route case is already handled by cancel_route_from + -- this code only handles signal at entering tcb and also triggers for non-route ts + tcbs.route_committed = nil + tcbs.route_aspect = nil + tcbs.route_remote = nil + tcbs.route_origin = nil + if not tcbs.route_auto then + tcbs.routeset = nil + end + advtrains.interlocking.signal.update_route_aspect(tcbs) advtrains.interlocking.route.update_route(sigd, tcbs) end end -- cgit v1.2.3