aboutsummaryrefslogtreecommitdiff
path: root/advtrains_interlocking/routesetting.lua
diff options
context:
space:
mode:
authorSingularis <singularis@volny.cz>2025-04-21 07:21:53 +0200
committerorwell <orwell@bleipb.de>2025-05-27 20:22:01 +0200
commit95a5586e0fe196e2291acaf128b8d1b4f8a32510 (patch)
tree6cc5ff9a64e533c8d9262f965e2246dfa2b3da24 /advtrains_interlocking/routesetting.lua
parent1d6913cec797b3848c93e8c6b16c3b6b2711d38c (diff)
downloadadvtrains-95a5586e0fe196e2291acaf128b8d1b4f8a32510.tar.gz
advtrains-95a5586e0fe196e2291acaf128b8d1b4f8a32510.tar.bz2
advtrains-95a5586e0fe196e2291acaf128b8d1b4f8a32510.zip
[advtrains] přechod na Advtrains 2.5.0 (první pokus)
- [ch_core/lib] drobná oprava - [advtrains_attachment_offset_patch] použití initial_properties
Diffstat (limited to 'advtrains_interlocking/routesetting.lua')
-rw-r--r--advtrains_interlocking/routesetting.lua165
1 files changed, 139 insertions, 26 deletions
diff --git a/advtrains_interlocking/routesetting.lua b/advtrains_interlocking/routesetting.lua
index 67efaea..6544a92 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", main_aspect = 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
@@ -60,42 +66,79 @@ function ilrs.set_route(signal, route, try)
c_rseg = route[i]
c_lckp = {}
- if c_ts.route then
+ if not c_ts then
+ if not try then atwarn("Encountered ts missing during a real run of routesetting routine, at ts=",c_ts_id,"while setting route",rtename,"of",signal) end
+ return false, "Section '"..(c_ts_id).."' not found!", c_ts_id, nil
+ elseif 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
+ if c_rseg.call_on then
+ --atdebug("Routesetting: Call-on situation in", c_ts_id)
+ else
+ 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 or c_ts_id).."' is occupied!", c_ts_id, nil
+ end
end
- for pts, state in pairs(c_rseg.locks) do
- local confl = ilrs.has_route_lock(pts, state)
+ -- 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 lp, state in pairs(c_locks) do
+ local confl = ilrs.has_route_lock(lp, 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
+ -- sanity check, is section at next the same as the current?
+ local nvar = c_rseg.next
+ if nvar then
+ local re_tcbs = ildb.get_tcbs({p = nvar.p, s = (nvar.s==1) and 2 or 1})
+ if (not re_tcbs or not re_tcbs.ts_id or re_tcbs.ts_id~=c_ts_id)
+ and route[i+1] then --FIX 2025-01-08: in old worlds the final TCB may be wrong (it didn't matter back then), don't error out here (route still shown invalid in UI)
+ if not try then atwarn("Encountered inconsistent ts (front~=back) while a real run of routesetting routine, at position",pts,"while setting route",rtename,"of",signal) end
+ return false, "TCB at "..minetest.pos_to_string(nvar.p).." has different section than previous TCB. Please update track section or reconfigure route!"
end
end
-- reserve ts and write locks
if not try then
- local nvar = c_rseg.next
if not route[i+1] then
-- We shouldn't use the "next" value of the final route segment, because this can lead to accidental route-cancelling of already set routes from another signal.
nvar = nil
@@ -112,9 +155,22 @@ 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_origin = signal
- advtrains.interlocking.update_signal_aspect(c_tcbs)
+ -- determine route role
+ local ndef = advtrains.ndb.get_ndef(c_tcbs.signal)
+ local assign_dst = c_rseg.assign_dst
+ if assign_dst == nil then
+ assign_dst = (i~=1) -- special behavior when assign_dst is nil (and not false):
+ -- defaults to false for the very first signal and true for all others (= minimal user configuration overhead)
+ end
+ local sig_table = {
+ pos = c_tcbs.signal,
+ tcbs_ref = c_tcbs,
+ role = ndef and ndef.advtrains and ndef.advtrains.route_role,
+ main_aspect = c_rseg.main_aspect,
+ assign_dst = assign_dst
+ }
+ signals[#signals+1] = sig_table
end
end
-- advance
@@ -122,10 +178,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.main_aspect or "_default" -- or route.main_aspect : TODO this does not work if a distant signal is on the path! Implement per-sig aspects!
+ 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)
@@ -172,6 +265,11 @@ function ilrs.free_route_locks(ts, lcks, nocallbacks)
end
function ilrs.free_route_locks_indiv(pts, ts, nocallbacks)
+ -- legacy: if starts with bracket then pts is still in old pos_to_string format (may happen because ts.route_post is not migrated)
+ if string.match(pts, "^%(") then
+ atdebug("free_route_locks_indiv: converting position",pts)
+ pts = advtrains.encode_pos(minetest.string_to_pos(pts))
+ end
local e = ilrs.rte_locks[pts]
if not e then return nil
elseif #e==0 then
@@ -191,7 +289,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
@@ -224,12 +322,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
@@ -273,17 +372,19 @@ function ilrs.update_route(sigd, tcbs, newrte, cancel)
--atdebug("Signal not in control, held by",tcbs.signal_name)
return
end
+ -- clear route_rsn, it will be set again if needed
+ tcbs.route_rsn = nil
if (newrte and tcbs.routeset and tcbs.routeset ~= newrte) or cancel then
if tcbs.route_committed then
--atdebug("Cancelling:",tcbs.routeset)
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
- tcbs.route_rsn = nil
end
if newrte or tcbs.routeset then
if tcbs.route_committed then
@@ -291,7 +392,14 @@ function ilrs.update_route(sigd, tcbs, newrte, cancel)
end
if newrte then tcbs.routeset = newrte end
--atdebug("Setting:",tcbs.routeset)
- local succ, rsn, cbts, cblk = ilrs.set_route(sigd, tcbs.routes[tcbs.routeset])
+ local succ, rsn, cbts, cblk
+ local route = tcbs.routes[tcbs.routeset]
+ if route then
+ succ, rsn, cbts, cblk = ilrs.set_route(sigd, route)
+ else
+ succ = false
+ rsn = attrans("Route state changed.")
+ end
if not succ then
tcbs.route_rsn = rsn
--atdebug("Routesetting failed:",rsn)
@@ -308,12 +416,17 @@ 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
+ -- route success. apply default_autoworking flag if requested
+ if route.default_autoworking then
+ tcbs.route_auto = true --FIX 2025-01-08: never set it to false if it was true!
+ end
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