diff options
Diffstat (limited to 'advtrains_interlocking/routesetting.lua')
-rw-r--r-- | advtrains_interlocking/routesetting.lua | 116 |
1 files changed, 95 insertions, 21 deletions
diff --git a/advtrains_interlocking/routesetting.lua b/advtrains_interlocking/routesetting.lua index fd6d595..a72f644 100644 --- a/advtrains_interlocking/routesetting.lua +++ b/advtrains_interlocking/routesetting.lua @@ -43,13 +43,19 @@ function ilrs.set_route(signal, route, try) local first = true local i = 1 local rtename = route.name - local signalname = ildb.get_tcbs(signal).signal_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 = <tcbs>, role = "main_distant", masp_override = nil, dst_type = "next_main" or "none" } + local signals = {} + local nodst while c_sigd and i<=#route do c_tcbs = ildb.get_tcbs(c_sigd) if not c_tcbs then if not try then atwarn("Did not find TCBS",c_sigd,"while setting route",rtename,"of",signal) end - return false, "No TCB found at "..sigd_to_string(c_sigd)..". Please reconfigure route!" + return false, "No TCB found at "..sigd_to_string(c_sigd)..". Please update or reconfigure route!" + end + if i == 1 then + nodst = c_tcbs.nodst end c_ts_id = c_tcbs.ts_id if not c_ts_id then @@ -62,35 +68,56 @@ 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 + local c_locks = {} + if route.use_rscache and c_ts.rs_cache and c_rseg.next then + -- rscache needs to be enabled, present and next must be defined + start_pkey = advtrains.encode_pos(c_sigd.p) + end_pkey = advtrains.encode_pos(c_rseg.next.p) + if c_ts.rs_cache[start_pkey] and c_ts.rs_cache[start_pkey][end_pkey] then + for lp,lst in pairs(c_ts.rs_cache[start_pkey][end_pkey]) do + atdebug("Add lock from RSCache:",lp,"->",lst) + c_locks[lp] = lst + end + elseif not try then + atwarn("While setting route",rtename,"of",signal,"segment "..i..",required path from",c_tcbs,"to",c_rseg.next,"was not found in the track section's RS cache. Please check!") + end + end + -- add all from locks, these override the rscache + for lpts,lst in pairs(c_rseg.locks) do + atdebug("Add lock from Routedef:",lpts,"->",lst,"overrides",c_locks[lpts] or "none") + c_locks[lpts] = lst end - for pts, state in pairs(c_rseg.locks) do + for lp, state in pairs(c_locks) do local confl = ilrs.has_route_lock(pts, state) - local pos = minetest.string_to_pos(pts) + local pos = advtrains.decode_pos(lp) if advtrains.is_passive(pos) then local cstate = advtrains.getstate(pos) if cstate ~= state then - local confl = ilrs.has_route_lock(pts) + local confl = ilrs.has_route_lock(lp) if confl then - if not try then atwarn("Encountered route lock while a real run of routesetting routine, at position",pts,"while setting route",rtename,"of",signal) end - return false, "Lock conflict at "..pts..", Held locked by:\n"..confl, nil, pts + if not try then atwarn("Encountered route lock while a real run of routesetting routine, at position",pos,"while setting route",rtename,"of",signal) end + return false, "Lock conflict at "..minetest.pos_to_string(pos)..", Held locked by:\n"..confl, nil, lp elseif not try then advtrains.setstate(pos, state) end end if not try then - ilrs.add_route_lock(pts, c_ts_id, "Route '"..rtename.."' from signal '"..signalname.."'", signal) - c_lckp[#c_lckp+1] = pts + ilrs.add_route_lock(lp, c_ts_id, "Route '"..rtename.."' from signal '"..signalname.."'", signal) + c_lckp[#c_lckp+1] = lp end else if not try then atwarn("Encountered route lock misconfiguration (no passive component) while a real run of routesetting routine, at position",pts,"while setting route",rtename,"of",signal) end - return false, "No passive component at "..pts..". Please reconfigure route!" + return false, "No passive component at "..minetest.pos_to_string(pos)..". Please update track section or reconfigure route!" end end -- reserve ts and write locks @@ -112,10 +139,17 @@ function ilrs.set_route(signal, route, try) } if c_tcbs.signal then c_tcbs.route_committed = true - c_tcbs.aspect = route.aspect or advtrains.interlocking.GENERIC_FREE - c_tcbs.route_rsn = nil c_tcbs.route_origin = signal - advtrains.interlocking.update_signal_aspect(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 + assign_dst = (i~=1) or route.assign_dst -- Behavior: for first signal assign depending on route.assign_dst, all others always assign + } + signals[#signals+1] = sig_table end end -- advance @@ -123,10 +157,47 @@ function ilrs.set_route(signal, route, try) c_sigd = c_rseg.next i = i + 1 end + + -- 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 + last_mainsig = pos + end + end + for i = #signals, 1, -1 do + -- 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 route.main_aspect or "_default" + if sig.role == "distant" or sig.role == "distant_repeater" or sig.role == "main_distant" then + if last_mainsig then + -- assign the remote as the last mainsig if desired + if sig.assign_dst then + sig.tcbs_ref.route_remote = last_mainsig + end + -- if it wasn't a distant_repeater clear the mainsig + if sig.role ~= "distant_repeater" then + last_mainsig = false + end + end + 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 end +-- Change 2024-01-27: pts is not an encoded pos, not a pos-to-string! + -- Checks whether there is a route lock that prohibits setting the component -- to the wanted state. returns string with reasons on conflict function ilrs.has_route_lock(pts) @@ -192,7 +263,7 @@ function ilrs.free_route_locks_indiv(pts, ts, nocallbacks) -- TODO use luaautomation timers? if not nocallbacks then minetest.after(0, ilrs.update_waiting, "lck", pts) - minetest.after(0.5, advtrains.set_fallback_state, minetest.string_to_pos(pts)) + minetest.after(0.5, advtrains.set_fallback_state, advtrains.decode_pos(pts)) end end -- frees all route locks, even manual ones set with the tool, at a specific position @@ -225,12 +296,13 @@ 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 - advtrains.interlocking.update_signal_aspect(c_tcbs) + advtrains.interlocking.signal.update_route_aspect(c_tcbs) c_ts_id = c_tcbs.ts_id if not c_tcbs then @@ -280,7 +352,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 @@ -315,12 +388,13 @@ function ilrs.update_route(sigd, tcbs, newrte, cancel) end else --atdebug("Committed Route:",tcbs.routeset) - has_changed_aspect = true + -- set_route now sets the signal aspects + --has_changed_aspect = true end end if has_changed_aspect then -- FIX: prevent an minetest.after() loop caused by update_signal_aspect dispatching path invalidation, which in turn calls ARS again - advtrains.interlocking.update_signal_aspect(tcbs) + advtrains.interlocking.signal.update_route_aspect(tcbs) end advtrains.interlocking.update_player_forms(sigd) end |