aboutsummaryrefslogtreecommitdiff
path: root/advtrains_interlocking/routesetting.lua
diff options
context:
space:
mode:
Diffstat (limited to 'advtrains_interlocking/routesetting.lua')
-rw-r--r--advtrains_interlocking/routesetting.lua116
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