aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authororwell <orwell@bleipb.de>2024-01-28 00:42:28 +0100
committerorwell <orwell@bleipb.de>2024-01-28 00:42:28 +0100
commit9fa43cb7bfc25ba71d16c8210f0074797a7bca1a (patch)
treeff821de8be0737ed276f382a783d3630a4197508
parentf8c2ec60d6fe1927b444aae51c3bce075ed05208 (diff)
downloadadvtrains-9fa43cb7bfc25ba71d16c8210f0074797a7bca1a.tar.gz
advtrains-9fa43cb7bfc25ba71d16c8210f0074797a7bca1a.tar.bz2
advtrains-9fa43cb7bfc25ba71d16c8210f0074797a7bca1a.zip
Implement routesetting incorporating tscache, other improvements
-rw-r--r--advtrains/passive.lua2
-rw-r--r--advtrains_interlocking/database.lua221
-rw-r--r--advtrains_interlocking/route_prog.lua2
-rw-r--r--advtrains_interlocking/routesetting.lua43
-rwxr-xr-xadvtrains_interlocking/tcb_ts_ui.lua5
-rw-r--r--advtrains_interlocking/tool.lua6
6 files changed, 185 insertions, 94 deletions
diff --git a/advtrains/passive.lua b/advtrains/passive.lua
index 741d7df..231da82 100644
--- a/advtrains/passive.lua
+++ b/advtrains/passive.lua
@@ -57,7 +57,7 @@ function advtrains.setstate(parpos, newstate, pnode)
return false, "train_here"
end
- if advtrains.interlocking and advtrains.interlocking.route.has_route_lock(minetest.pos_to_string(pos)) then
+ if advtrains.interlocking and advtrains.interlocking.route.has_route_lock(minetest.encode_pos(pos)) then
return false, "route_lock_here"
end
diff --git a/advtrains_interlocking/database.lua b/advtrains_interlocking/database.lua
index 5d42309..17a4199 100644
--- a/advtrains_interlocking/database.lua
+++ b/advtrains_interlocking/database.lua
@@ -84,11 +84,34 @@ function ildb.load(data)
if pos then
-- that was a pos_to_string
local epos = advtrains.encode_pos(pos)
+ atdebug("ILDB converting TCB position format",pts,"->",epos)
track_circuit_breaks[epos] = tcb
else
-- keep entry, it is already new
track_circuit_breaks[pts] = tcb
end
+ -- convert the routes.[].locks table keys
+ for t_side,tcbs in pairs(tcb) do
+ if tcbs.routes then
+ for t_rnum,route in pairs(tcbs.routes) do
+ for t_rsnm,rseg in ipairs(route) do
+ local locks_n = {}
+ for lpts,state in pairs(rseg.locks) do
+ local lpos = minetest.string_to_pos(lpts)
+ if lpos then
+ local epos = advtrains.encode_pos(lpos)
+ atdebug("ILDB converting tcb",pts,"side",t_side,"route",t_route,"lock position format",lpts,"->",epos)
+ locks_n[epos] = state
+ else
+ -- already correct format
+ locks_n[lpts] = state
+ end
+ end
+ rseg.locks = locks_n
+ end
+ end
+ end
+ end
end
end
end
@@ -99,7 +122,23 @@ function ildb.load(data)
signal_assignments = data.signalass
end
if data.rs_locks then
- advtrains.interlocking.route.rte_locks = data.rs_locks
+ if data.tcbpts_conversion_applied then
+ advtrains.interlocking.route.rte_locks = data.rs_locks
+ else
+ advtrains.interlocking.route.rte_locks = {}
+ for pts, lta in pairs(data.rs_locks) do
+ local pos = minetest.string_to_pos(pts)
+ if pos then
+ -- that was a pos_to_string
+ local epos = advtrains.encode_pos(pos)
+ atdebug("ILDB converting Route Lock position format",pts,"->",epos)
+ advtrains.interlocking.route.rte_locks[epos] = lta
+ else
+ -- keep entry, it is already new
+ advtrains.interlocking.route.rte_locks[pts] = lta
+ end
+ end
+ end
end
if data.rs_callbacks then
advtrains.interlocking.route.rte_callbacks = data.rs_callbacks
@@ -197,8 +236,8 @@ routes = {
-- one table for each track section on the route
-- Note that the section ID is implicitly inferred from the TCB
1 = {
- locks = { -- component locks for this section of the route. Not used when use_rscache is true.
- (-16,9,0) = st
+ locks = { -- component locks for this section of the route.
+ 800080008000 = st
}
next = S[(-23,9,0)/2] -- the start TCB of the next route segment (pointing forward)
}
@@ -208,7 +247,8 @@ routes = {
}
name = "<the route name>"
ars = { <ARS rule definition table> }
- use_rscache = false -- if true, instead of "locks", the track section's rs_cache will be used to set locks
+ use_rscache = false -- if true, the track section's rs_cache will be used to set locks in addition to the locks table
+ -- this is disabled for legacy routes, but enabled for all new routes by default
-- Fields used by the autorouter:
ar_end_sigd = <sigd> -- the sigd describing the end of the route. Used for merging route options on recalculation
}
@@ -218,10 +258,12 @@ Track section
[id] = {
name = "Some human-readable name"
tc_breaks = { <signal specifier>,... } -- Bounding TC's (signal specifiers)
- rs_cache = { [<x>] = { [<y>] = { [<encoded pos>] = "state" } } }
+ rs_cache = { [startTcbPosEnc] = { [endTcbPosEnc] = { [componentPosEnc] = "state" } } }
-- Saves the turnout states that need to be locked when a route is set from tcb#x to tcb#y
- -- e.g. 1 = { 2 = { "800080008000" = "st" } }
+ -- e.g. "800080008005" = { "800080007EEA" = { "800080008000" = "st" } }
+ -- start TCB end TCB switch pos
-- Recalculated on every change via update_rs_cache
+ -- Note that the tcb side number is not saved because it is unnecessary
route = {
origin = <signal>, -- route origin
@@ -281,17 +323,24 @@ function ildb.get_all_ts()
return track_sections
end
+function tsrepair_notify(notify_pname, ...)
+ if notify_pname then
+ minetest.chat_send_player(notify_pname, advtrains.print_concat_table({"TS Check:",...}))
+ end
+end
+
-- Checks the consistency of the track section at the given position, attempts to autorepair track sections if they are inconsistent
-- There are 2 operation modes:
-- 1: pos is NOT a TCB, tcb_connid MUST be nil
-- 2: pos is a TCB, tcb_connid MUST be given
-- @param pos: the position to start from
--- @param tcb_connid: If provided node is a TCB,
+-- @param tcb_connid: If provided node is a TCB, the direction in which to search
+-- @param notify_pname: the player to notify about reparations
-- Returns:
-- ts_id - the track section that was found
-- nil - No track section exists
-function ildb.check_and_repair_ts_at_pos(pos, tcb_connid)
- atdebug("check_and_repair_ts_at_pos", pos, tcb_connid)
+function ildb.check_and_repair_ts_at_pos(pos, tcb_connid, notify_pname)
+ --atdebug("check_and_repair_ts_at_pos", pos, tcb_connid)
-- check prereqs
if ildb.get_tcb(pos) then
if not tcb_connid then error("check_and_repair_ts_at_pos: Startpoint is TCB, must provide tcb_connid!") end
@@ -315,15 +364,17 @@ function ildb.check_and_repair_ts_at_pos(pos, tcb_connid)
-- these must be the same as the first
if ts_id ~= tcbs_ts_id then
-- inconsistency is found, repair it
- atdebug("check_and_repair_ts_at_pos: Inconsistency is found!")
- return ildb.repair_ts_merge_all(all_tcbs)
+ --atdebug("check_and_repair_ts_at_pos: Inconsistency is found!")
+ tsrepair_notify(notify_pname, "Track section inconsistent here, repairing...")
+ return ildb.repair_ts_merge_all(all_tcbs, false, notify_pname)
-- Step2 check is no longer necessary since we just created that new section
end
end
end
-- only one found (it is either nil or a ts id)
- atdebug("check_and_repair_ts_at_pos: TS consistent id=",ts_id,"")
+ --atdebug("check_and_repair_ts_at_pos: TS consistent id=",ts_id,"")
if not ts_id then
+ tsrepair_notify(notify_pname, "No track section found here.")
return
-- All TCBs agreed that there is no section here.
end
@@ -338,9 +389,11 @@ function ildb.check_and_repair_ts_at_pos(pos, tcb_connid)
-- ildb.tcbs_ensure_ts_ref_exists(sigd) has already make sure that all tcbs are found in the ts's tc_breaks list
-- That means it is sufficient to compare the LENGTHS of both lists, if one is longer then it is inconsistent
if #ts.tc_breaks ~= #all_tcbs then
- atdebug("check_and_repair_ts_at_pos: Partition is found!")
- return ildb.repair_ts_merge_all(all_tcbs)
+ --atdebug("check_and_repair_ts_at_pos: Partition is found!")
+ tsrepair_notify(notify_pname, "Track section partition found, repairing...")
+ return ildb.repair_ts_merge_all(all_tcbs, false, notify_pname)
end
+ tsrepair_notify(notify_pname, "Found section", ts.name or ts_id, "here.")
return ts_id
end
@@ -367,7 +420,7 @@ end
-- Returns: a list of sigd's describing the TCBs found (sigd's point inward):
-- {p=<pos>, s=<side>, tcbs=<ref to tcbs table>}
function ildb.get_all_tcbs_adjacent(inipos, inidir, per_track_callback)
- atdebug("get_all_tcbs_adjacent: inipos",inipos,"inidir",inidir,"")
+ --atdebug("get_all_tcbs_adjacent: inipos",inipos,"inidir",inidir,"")
local found_sigd = {}
local ti = advtrains.get_track_iterator(inipos, inidir, TS_MAX_SCAN, true)
-- if initial start is TCBS and has xlink, need to add that to the TI
@@ -377,7 +430,7 @@ function ildb.get_all_tcbs_adjacent(inipos, inidir, per_track_callback)
ildb.validate_tcb_xlink(inisi, true)
if initcbs.xlink then
-- adding the tcb will happen when this branch is retrieved again using ti:next_branch()
- atdebug("get_all_tcbs_adjacent: Putting xlink Branch for initial node",initcbs.xlink)
+ --atdebug("get_all_tcbs_adjacent: Putting xlink Branch for initial node",initcbs.xlink)
ti:add_branch(initcbs.xlink.p, initcbs.xlink.s)
end
end
@@ -400,17 +453,17 @@ function ildb.get_all_tcbs_adjacent(inipos, inidir, per_track_callback)
-- A branch cannot be a TCB, as that would imply that it was a turnout/crossing (illegal)
-- UNLESS: (a) it is the start point or (b) it was added via xlink
-- Then the correct conn to use is connid (pointing forward)
- atdebug("get_all_tcbs_adjacent: Inserting TCB at branch start",pos, connid)
+ --atdebug("get_all_tcbs_adjacent: Inserting TCB at branch start",pos, connid)
using_connid = connid
end
-- add the sigd of this tcb and a reference to the tcb table in it
- atdebug("get_all_tcbs_adjacent: Found TCB: ",pos, using_connid, "ts=", tcb[using_connid].ts_id)
+ --atdebug("get_all_tcbs_adjacent: Found TCB: ",pos, using_connid, "ts=", tcb[using_connid].ts_id)
local si = {p=pos, s=using_connid, tcbs=tcb[using_connid]}
-- if xlink exists, add it now (only if we are not in branch start)
ildb.validate_tcb_xlink(si, true)
if not is_branch_start and si.tcbs.xlink then
-- adding the tcb will happen when this branch is retrieved again using ti:next_branch()
- atdebug("get_all_tcbs_adjacent: Putting xlink Branch",si.tcbs.xlink)
+ --atdebug("get_all_tcbs_adjacent: Putting xlink Branch",si.tcbs.xlink)
ti:add_branch(si.tcbs.xlink.p, si.tcbs.xlink.s)
end
insert_sigd_if_not_present(found_sigd, si)
@@ -429,8 +482,8 @@ end
-- Called by frontend functions when multiple tcbs's that logically belong to one section have been determined to have different sections
-- Parameter is the output of ildb.get_all_tcbs_adjacent(pos)
-- Returns the ID of the track section that results after the merge
-function ildb.repair_ts_merge_all(all_tcbs, force_create)
- atdebug("repair_ts_merge_all: Instructed to merge sections of following TCBs:")
+function ildb.repair_ts_merge_all(all_tcbs, force_create, notify_pname)
+ --atdebug("repair_ts_merge_all: Instructed to merge sections of following TCBs:")
-- The first loop does the following for each TCBS:
-- a) Store the TS ID in the set of TS to update
-- b) Set the TS ID to nil, so that the TCBS gets removed from the section
@@ -439,7 +492,7 @@ function ildb.repair_ts_merge_all(all_tcbs, force_create)
local any_ts = false
for _,sigd in ipairs(all_tcbs) do
local ts_id = sigd.tcbs.ts_id
- atdebug(sigd, "ts=", ts_id)
+ --atdebug(sigd, "ts=", ts_id)
if ts_id then
local ts = track_sections[ts_id]
if ts then
@@ -455,7 +508,7 @@ function ildb.repair_ts_merge_all(all_tcbs, force_create)
end
if not any_ts and not force_create then
-- nothing to do at all, just no interlocking. Why were we even called
- atdebug("repair_ts_merge_all: No track section present, will not create a new one")
+ --atdebug("repair_ts_merge_all: No track section present, will not create a new one")
return nil
end
-- Purge every TS in turn. TS's that are now empty will be deleted. TS's that still have TCBs will be kept
@@ -464,6 +517,7 @@ function ildb.repair_ts_merge_all(all_tcbs, force_create)
end
-- Create a new fresh track section with all the TCBs we have in our collection
local new_ts_id, new_ts = ildb.create_ts_from_tcb_list(all_tcbs)
+ tsrepair_notify(notify_pname, "Created track section",new_ts_id,"from TCBs:", all_tcbs)
return new_ts_id
end
@@ -487,20 +541,20 @@ function ildb.purge_ts_tcb_refs(ts_id)
i = i+1
else
-- this one is to be purged
- atdebug("purge_ts_tcb_refs(",ts_id,"): purging",sigd,"(backreference = ",tcbs.ts_id,")")
+ --atdebug("purge_ts_tcb_refs(",ts_id,"): purging",sigd,"(backreference = ",tcbs.ts_id,")")
table.remove(ts.tc_breaks, i)
has_changed = true
end
else
-- if not tcbs: was anyway an orphan, remove it
- atdebug("purge_ts_tcb_refs(",ts_id,"): purging",sigd,"(referred nonexisting TCB)")
+ --atdebug("purge_ts_tcb_refs(",ts_id,"): purging",sigd,"(referred nonexisting TCB)")
table.remove(ts.tc_breaks, i)
has_changed = true
end
end
if #ts.tc_breaks == 0 then
-- remove the section completely
- atdebug("purge_ts_tcb_refs(",ts_id,"): after purging, the section is empty, is being deleted")
+ --atdebug("purge_ts_tcb_refs(",ts_id,"): after purging, the section is empty, is being deleted")
track_sections[ts_id] = nil
return nil
else
@@ -520,14 +574,14 @@ function ildb.tcbs_ensure_ts_ref_exists(sigd)
if not tcbs or not tcbs.ts_id then return end
local ts = ildb.get_ts(tcbs.ts_id)
if not ts then
- atdebug("tcbs_ensure_ts_ref_exists(",sigd,"): TS does not exist, setting to nil")
+ --atdebug("tcbs_ensure_ts_ref_exists(",sigd,"): TS does not exist, setting to nil")
-- TS is deleted, clear own ts id
tcbs.ts_id = nil
return
end
local did_insert = insert_sigd_if_not_present(ts.tc_breaks, {p=sigd.p, s=sigd.s})
if did_insert then
- atdebug("tcbs_ensure_ts_ref_exists(",sigd,"): TCBS was missing reference in TS",tcbs.ts_id)
+ --atdebug("tcbs_ensure_ts_ref_exists(",sigd,"): TCBS was missing reference in TS",tcbs.ts_id)
ildb.update_rs_cache(tcbs.ts_id)
end
end
@@ -538,7 +592,7 @@ function ildb.create_ts_from_tcb_list(sigd_list)
while track_sections[id] do
id = advtrains.random_id(8)
end
- atdebug("create_ts_from_tcb_list: sigd_list=",sigd_list, "new ID will be ",id)
+ --atdebug("create_ts_from_tcb_list: sigd_list=",sigd_list, "new ID will be ",id)
local tcbr = {}
-- makes a copy of the sigd list, for use in repair mechanisms where sigd may contain a tcbs field which we dont want
@@ -585,23 +639,23 @@ function ildb.get_possible_out_connids(node_name, in_connid)
local nt = node_from_to_state_cache[node_name]
if not nt[in_connid] then
local ta = {}
- atdebug("Node From/To State Cache: Caching for ",node_name,"connid",in_connid)
+ --atdebug("Node From/To State Cache: Caching for ",node_name,"connid",in_connid)
local ndef = minetest.registered_nodes[node_name]
if ndef.advtrains.node_state_map then
for state, tnode in pairs(ndef.advtrains.node_state_map) do
local tndef = minetest.registered_nodes[tnode]
-- verify that the conns table is identical - this is purely to catch setup errors!
if not tndef.at_conns or not tndef.at_conn_map then
- atdebug("ndef:",ndef,", tndef:",tndef)
- error("In AT setup for node "..tnode..": Node set as state "..state.." of "..node_name.." in state_map, but is missing at_conns/at_conn/map!")
+ --atdebug("ndef:",ndef,", tndef:",tndef)
+ error("In AT setup for node "..tnode..": Node set as state "..state.." of "..node_name.." in state_map, but is missing at_conns/at_conn_map!")
end
if #ndef.at_conns ~= #tndef.at_conns then
- atdebug("ndef:",ndef,", tndef:",tndef)
+ --atdebug("ndef:",ndef,", tndef:",tndef)
error("In AT setup for node "..tnode..": Conns table does not match that of "..node_name.." (of which this is state "..state..")")
end
for connid=1,#ndef.at_conns do
if ndef.at_conns[connid].c ~= tndef.at_conns[connid].c then
- atdebug("ndef:",ndef,", tndef:",tndef)
+ --atdebug("ndef:",ndef,", tndef:",tndef)
error("In AT setup for node "..tnode..": Conns table does not match that of "..node_name.." (of which this is state "..state..")")
end
end
@@ -610,13 +664,13 @@ function ildb.get_possible_out_connids(node_name, in_connid)
if ta[target_connid] then
-- Select the variant for which the other way would back-connect. This way, turnouts will switch to the appropriate branch if the train joins
local have_back_conn = (tndef.at_conn_map[target_connid])==in_connid
- atdebug("Found second state mapping",in_connid,"-",target_connid,"have_back_conn=",have_back_conn)
+ --atdebug("Found second state mapping",in_connid,"-",target_connid,"have_back_conn=",have_back_conn)
if have_back_conn then
- atdebug("Overwriting",in_connid,"-",target_connid,"=",state)
+ --atdebug("Overwriting",in_connid,"-",target_connid,"=",state)
ta[target_connid] = state
end
else
- atdebug("Setting",in_connid,"-",target_connid,"=",state)
+ --atdebug("Setting",in_connid,"-",target_connid,"=",state)
ta[target_connid] = state
end
end
@@ -629,26 +683,27 @@ function ildb.get_possible_out_connids(node_name, in_connid)
end
local function recursively_find_routes(s_pos, s_connid, locks_found, result_table, scan_limit)
- atdebug("Recursively restarting at ",s_pos, s_connid, "limit left", scan_limit)
+ --atdebug("Recursively restarting at ",s_pos, s_connid, "limit left", scan_limit)
local ti = advtrains.get_track_iterator(s_pos, s_connid, scan_limit, false)
local pos, connid, bconnid = ti:next_branch()
pos, connid, bconnid = ti:next_track()-- step once to get ahead of previous turnout
+ local last_pos
repeat
local node = advtrains.ndb.get_node_or_nil(pos)
- atdebug("Walk ",pos, "nodename", node.name, "entering at conn",bconnid)
+ --atdebug("Walk ",pos, "nodename", node.name, "entering at conn",bconnid)
local ndef = minetest.registered_nodes[node.name]
if ndef.advtrains and ndef.advtrains.node_state_map then
-- Stop, this is a switchable node. Find out which conns we can go at
- atdebug("Found turnout ",pos, "nodename", node.name, "entering at conn",bconnid)
+ --atdebug("Found turnout ",pos, "nodename", node.name, "entering at conn",bconnid)
local pts = advtrains.encode_pos(pos)
if locks_found[pts] then
-- we've been here before. Stop
- atdebug("Was already seen! returning")
+ --atdebug("Was already seen! returning")
return
end
local out_conns = ildb.get_possible_out_connids(node.name, bconnid)
for oconnid, state in pairs(out_conns) do
- atdebug("Going in direction",oconnid,"state",state)
+ --atdebug("Going in direction",oconnid,"state",state)
locks_found[pts] = state
recursively_find_routes(pos, oconnid, locks_found, result_table, ti.limit)
locks_found[pts] = nil
@@ -656,21 +711,23 @@ local function recursively_find_routes(s_pos, s_connid, locks_found, result_tabl
return
end
--otherwise, this might be a tcb
- local tcbs = ildb.get_tcbs({p=pos, s=bconnid})
- if tcbs then
+ local tcb = ildb.get_tcb(pos)
+ if tcb then
-- we found a tcb, store the current locks in the result_table
- local table_key = advtrains.encode_pos(pos).."_"..bconnid
- atdebug("Found end TCB", table_key,", returning")
- if result_table[table_key] then
+ local end_pkey = advtrains.encode_pos(pos)
+ --atdebug("Found end TCB", pos, end_pkey,", returning")
+ if result_table[end_pkey] then
atwarn("While caching track section routing, found multiple route paths within same track section. Only first one found will be used")
else
- result_table[table_key] = table.copy(locks_found)
+ result_table[end_pkey] = table.copy(locks_found)
end
return
end
-- Go forward
+ last_pos = pos
pos, connid, bconnid = ti:next_track()
until not pos -- this stops the loop when either the track end is reached or the limit is hit
+ --atdebug("recursively_find_routes: Reached track end or limit at", last_pos, ". This path is not saved, returning")
end
-- Updates the turnout cache of the given track section
@@ -680,25 +737,33 @@ function ildb.update_rs_cache(ts_id)
error("Update TS Cache called with nonexisting ts_id "..(ts_id or "nil"))
end
local rscache = {}
- atdebug("== Running update_rs_cache for ",ts_id)
+ --atdebug("== Running update_rs_cache for ",ts_id)
-- start on every of the TS's TCBs, walk the track forward and store locks along the way
for start_tcbi, start_tcbs in ipairs(ts.tc_breaks) do
- rscache[start_tcbi] = {}
- atdebug("Starting for ",start_tcbi, start_tcbs)
+ start_pkey = advtrains.encode_pos(start_tcbs.p)
+ rscache[start_pkey] = {}
+ --atdebug("Starting for ",start_tcbi, start_tcbs)
local locks_found = {}
local result_table = {}
recursively_find_routes(start_tcbs.p, start_tcbs.s, locks_found, result_table, TS_MAX_SCAN)
-- now result_table contains found route locks. Match them with the other TCBs we have in this section
for end_tcbi, end_tcbs in ipairs(ts.tc_breaks) do
- local table_key = advtrains.encode_pos(end_tcbs.p).."_"..end_tcbs.s
- if result_table[table_key] then
- atdebug("Set RSCache entry",start_tcbi.."-"..end_tcbi,"=",result_table[table_key])
- rscache[start_tcbi][end_tcbi] = result_table[table_key]
+ if end_tcbi ~= start_tcbi then
+ end_pkey = advtrains.encode_pos(end_tcbs.p)
+ if result_table[end_pkey] then
+ --atdebug("Set RSCache entry",end_pkey.."-"..end_pkey,"=",result_table[end_pkey])
+ rscache[start_pkey][end_pkey] = result_table[end_pkey]
+ result_table[end_pkey] = nil
+ end
end
end
+ -- warn about superfluous entry
+ for sup_end_pkey, sup_entry in pairs(result_table) do
+ --atwarn("In update_rs_cache for section",ts_id,"found superfluous endpoint",sup_end_pkey,"->",sup_entry)
+ end
end
ts.rs_cache = rscache
- atdebug("== Done update_rs_cache for ",ts_id, "result:",rscache)
+ --atdebug("== Done update_rs_cache for ",ts_id, "result:",rscache)
end
@@ -711,21 +776,21 @@ end
-- Create a new TCB at the position and update/repair the adjoining sections
function ildb.create_tcb_at(pos)
- atdebug("create_tcb_at",pos)
+ --atdebug("create_tcb_at",pos)
local pts = advtrains.encode_pos(pos)
track_circuit_breaks[pts] = {[1] = {}, [2] = {}}
local all_tcbs_1 = ildb.get_all_tcbs_adjacent(pos, 1)
- atdebug("TCBs on A side",all_tcbs_1)
+ --atdebug("TCBs on A side",all_tcbs_1)
local all_tcbs_2 = ildb.get_all_tcbs_adjacent(pos, 2)
- atdebug("TCBs on B side",all_tcbs_2)
+ --atdebug("TCBs on B side",all_tcbs_2)
-- perform TS repair
- ildb.repair_ts_merge_all(all_tcbs_1)
- ildb.repair_ts_merge_all(all_tcbs_2)
+ ildb.repair_ts_merge_all(all_tcbs_1, false)
+ ildb.repair_ts_merge_all(all_tcbs_2, false)
end
--- Create a new TCB at the position and update/repair the now joined section
+-- Remove TCB at the position and update/repair the now joined section
function ildb.remove_tcb_at(pos)
- atdebug("remove_tcb_at",pos)
+ --atdebug("remove_tcb_at",pos)
local pts = advtrains.encode_pos(pos)
local old_tcb = track_circuit_breaks[pts]
track_circuit_breaks[pts] = nil
@@ -745,7 +810,7 @@ function ildb.remove_tcb_at(pos)
end
advtrains.interlocking.remove_tcb_marker(pos)
-- If needed, merge the track sections here
- ildb.check_and_repair_ts_at_pos(pos)
+ ildb.check_and_repair_ts_at_pos(pos, nil)
return true
end
@@ -758,7 +823,7 @@ function ildb.validate_tcb_xlink(sigd, suppress_repairs)
if not osigd then return end
local otcbs = ildb.get_tcbs(tcbs.xlink)
if not otcbs then
- atdebug("validate_tcb_xlink",sigd,": Link partner ",osigd,"orphaned")
+ --atdebug("validate_tcb_xlink",sigd,": Link partner ",osigd,"orphaned")
tcbs.xlink = nil
if not suppress_repairs then
ildb.check_and_repair_ts_at_pos(sigd.p, sigd.s)
@@ -767,16 +832,16 @@ function ildb.validate_tcb_xlink(sigd, suppress_repairs)
end
if otcbs.xlink then
if not vector.equals(otcbs.xlink.p, sigd.p) or otcbs.xlink.s~=sigd.s then
- atdebug("validate_tcb_xlink",sigd,": Link partner ",osigd,"backreferencing to someone else (namely",otcbs.xlink,") clearing it")
+ --atdebug("validate_tcb_xlink",sigd,": Link partner ",osigd,"backreferencing to someone else (namely",otcbs.xlink,") clearing it")
tcbs.xlink = nil
if not suppress_repairs then
ildb.check_and_repair_ts_at_pos(sigd.p, sigd.s)
- atdebug("validate_tcb_xlink",sigd,": Link partner ",osigd," was backreferencing to someone else, now updating that")
+ --atdebug("validate_tcb_xlink",sigd,": Link partner ",osigd," was backreferencing to someone else, now updating that")
ildb.validate_tcb_xlink(osigd)
end
end
else
- atdebug("validate_tcb_xlink",sigd,": Link partner ",osigd,"wasn't backreferencing, clearing it")
+ --atdebug("validate_tcb_xlink",sigd,": Link partner ",osigd,"wasn't backreferencing, clearing it")
tcbs.xlink = nil
if not suppress_repairs then
ildb.check_and_repair_ts_at_pos(sigd.p, sigd.s)
@@ -785,19 +850,19 @@ function ildb.validate_tcb_xlink(sigd, suppress_repairs)
end
function ildb.add_tcb_xlink(sigd1, sigd2)
- atdebug("add_tcb_xlink",sigd1, sigd2)
+ --("add_tcb_xlink",sigd1, sigd2)
local tcbs1 = sigd1.tcbs or ildb.get_tcbs(sigd1)
local tcbs2 = sigd2.tcbs or ildb.get_tcbs(sigd2)
if vector.equals(sigd1.p, sigd2.p) then
- atdebug("add_tcb_xlink Cannot xlink with same TCB")
+ --atdebug("add_tcb_xlink Cannot xlink with same TCB")
return
end
if not tcbs1 or not tcbs2 then
- atdebug("add_tcb_xlink TCBS doesnt exist")
+ --atdebug("add_tcb_xlink TCBS doesnt exist")
return
end
if tcbs1.xlink or tcbs2.xlink then
- atdebug("add_tcb_xlink One already linked")
+ --atdebug("add_tcb_xlink One already linked")
return
end
-- apply link
@@ -808,7 +873,7 @@ function ildb.add_tcb_xlink(sigd1, sigd2)
end
function ildb.remove_tcb_xlink(sigd)
- atdebug("remove_tcb_xlink",sigd)
+ --atdebug("remove_tcb_xlink",sigd)
-- Validate first. If Xlink is gone already then, nothing to do
ildb.validate_tcb_xlink(sigd)
-- Checking all of these already done by validate
@@ -816,7 +881,7 @@ function ildb.remove_tcb_xlink(sigd)
local osigd = tcbs.xlink
if not osigd then
-- validate already cleared us
- atdebug("remove_tcb_xlink: Already gone by validate")
+ --atdebug("remove_tcb_xlink: Already gone by validate")
return
end
local otcbs = ildb.get_tcbs(tcbs.xlink)
@@ -829,14 +894,14 @@ function ildb.remove_tcb_xlink(sigd)
end
function ildb.create_ts_from_tcbs(sigd)
- atdebug("create_ts_from_tcbs",sigd)
+ --atdebug("create_ts_from_tcbs",sigd)
local all_tcbs = ildb.get_all_tcbs_adjacent(sigd.p, sigd.s)
ildb.repair_ts_merge_all(all_tcbs, true)
end
-- Remove the given track section, leaving its TCBs with no section assigned
function ildb.remove_ts(ts_id)
- atdebug("remove_ts",ts_id)
+ --atdebug("remove_ts",ts_id)
local ts = track_sections[ts_id]
if not ts then
error("remove_ts: "..ts_id.." doesn't exist")
@@ -846,10 +911,10 @@ function ildb.remove_ts(ts_id)
local sigd = ts.tc_breaks[i]
local tcbs = ildb.get_tcbs(sigd)
if tcbs then
- atdebug("cleared TCB",sigd)
+ --atdebug("cleared TCB",sigd)
tcbs.ts_id = nil
else
- atdebug("orphan TCB",sigd)
+ --atdebug("orphan TCB",sigd)
end
i = i+1
end
diff --git a/advtrains_interlocking/route_prog.lua b/advtrains_interlocking/route_prog.lua
index 5fd9363..34807cd 100644
--- a/advtrains_interlocking/route_prog.lua
+++ b/advtrains_interlocking/route_prog.lua
@@ -492,6 +492,8 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
local terminal = get_last_route_item(rp.origin, rp.route)
rp.route.terminal = terminal
rp.route.name = fields.name
+ -- new routes now always use the rscache
+ rp.route.use_rscache = true
table.insert(tcbs.routes, rp.route)
diff --git a/advtrains_interlocking/routesetting.lua b/advtrains_interlocking/routesetting.lua
index ede3d49..64b8c25 100644
--- a/advtrains_interlocking/routesetting.lua
+++ b/advtrains_interlocking/routesetting.lua
@@ -49,7 +49,7 @@ function ilrs.set_route(signal, route, try)
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
c_ts_id = c_tcbs.ts_id
if not c_ts_id then
@@ -69,28 +69,49 @@ function ilrs.set_route(signal, route, try)
return false, "Section '"..c_ts.name.."' is occupied!", c_ts_id, nil
end
- for pts, state in pairs(c_rseg.locks) do
+ -- 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:",lp,"->",lst,"overrides",c_locks[lp] or "none")
+ c_locks[lp] = lst
+ end
+
+ 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
@@ -126,6 +147,8 @@ function ilrs.set_route(signal, route, try)
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)
@@ -191,7 +214,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
diff --git a/advtrains_interlocking/tcb_ts_ui.lua b/advtrains_interlocking/tcb_ts_ui.lua
index e365f4f..9e7fcd4 100755
--- a/advtrains_interlocking/tcb_ts_ui.lua
+++ b/advtrains_interlocking/tcb_ts_ui.lua
@@ -99,10 +99,11 @@ minetest.register_node("advtrains_interlocking:tcb_node", {
end,
after_dig_node = function(pos, oldnode, oldmetadata, player)
if not oldmetadata or not oldmetadata.fields then return end
+ local pname = player:get_player_name()
local tcbpts = oldmetadata.fields.tcb_pos
if tcbpts and tcbpts ~= "" then
local tcbpos = minetest.string_to_pos(tcbpts)
- ildb.remove_tcb_at(tcbpos)
+ ildb.remove_tcb_at(tcbpos, pname)
end
end,
})
@@ -160,7 +161,7 @@ minetest.register_on_punchnode(function(pos, node, player, pointed_thing)
if ildb.get_tcb(pos) then
minetest.chat_send_player(pname, "Configuring TCB: Already existed at this position, it is now linked to this TCB marker")
else
- ildb.create_tcb_at(pos)
+ ildb.create_tcb_at(pos, pname)
end
local meta = minetest.get_meta(tcbnpos)
diff --git a/advtrains_interlocking/tool.lua b/advtrains_interlocking/tool.lua
index ef0f06e..4ebc56c 100644
--- a/advtrains_interlocking/tool.lua
+++ b/advtrains_interlocking/tool.lua
@@ -6,7 +6,7 @@ local ilrs = advtrains.interlocking.route
local function node_right_click(pos, pname)
if advtrains.is_passive(pos) then
local form = "size[7,5]label[0.5,0.5;Route lock inspector]"
- local pts = minetest.pos_to_string(pos)
+ local pts = advtrains.encode_pos(pos)
local rtl = ilrs.has_route_lock(pts)
@@ -53,7 +53,7 @@ local function node_left_click(pos, pname)
return
end
- local ts_id = advtrains.interlocking.db.check_and_repair_ts_at_pos(pos)
+ local ts_id = advtrains.interlocking.db.check_and_repair_ts_at_pos(pos, nil, pname)
if ts_id then
advtrains.interlocking.db.update_rs_cache(ts_id)
advtrains.interlocking.highlight_track_section(pos)
@@ -107,7 +107,7 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
local pos
local pts = string.match(formname, "^at_il_rtool_(.+)$")
if pts then
- pos = minetest.string_to_pos(pts)
+ pos = advtrains.decode_pos(pts)
end
if pos then
if advtrains.is_passive(pos) then