Properly implement invalidate_all_paths, recheck lzb on aspect change

This commit is contained in:
orwell96 2018-10-10 22:41:59 +02:00
parent 33c839b40d
commit 842a85606e
5 changed files with 77 additions and 20 deletions

View File

@ -208,7 +208,7 @@ function o.get_occupations(train, index)
return r, pos return r, pos
end end
-- Gets a mapping of train id's to indexes of trains that stand or drive over -- Gets a mapping of train id's to indexes of trains that stand or drive over
-- returns (table with train_id->index), position -- returns (table with train_id->index)
function o.get_trains_at(ppos) function o.get_trains_at(ppos)
local pos = advtrains.round_vector_floor_y(ppos) local pos = advtrains.round_vector_floor_y(ppos)
local t = occget(pos) local t = occget(pos)
@ -226,4 +226,22 @@ function o.get_trains_at(ppos)
return r return r
end end
-- Gets a mapping of train id's to indexes of trains that have a path
-- generated over this node
-- returns (table with train_id->index)
function o.get_trains_over(ppos)
local pos = advtrains.round_vector_floor_y(ppos)
local t = occget(pos)
if not t then return {} end
local r = {}
local i = 1
while t[i] do
local train = advtrains.trains[t[i]]
local idx = t[i+1]
r[t[i]] = idx
i = i + 2
end
return r
end
advtrains.occ = o advtrains.occ = o

View File

@ -1037,26 +1037,23 @@ function advtrains.get_train_at_pos(pos)
end end
end end
-- ehm... I never adapted this function to the new path system ?!
function advtrains.invalidate_all_paths(pos) function advtrains.invalidate_all_paths(pos)
--if a position is given, only invalidate inside a radius to save performance local tab
local inv_radius=50 if pos then
atprint("invalidating all paths") -- if position given, check occupation system
for k,v in pairs(advtrains.trains) do tab = advtrains.occ.get_trains_over(pos)
local exec=true else
if pos and v.path and v.index and v.end_index then tab = advtrains.trains
--start and end pos of the train
local cmp1=v.path[atround(v.index)]
local cmp2=v.path[atround(v.end_index)]
if vector.distance(pos, cmp1)>inv_radius and vector.distance(pos, cmp2)>inv_radius then
exec=false
end
end
if exec then
advtrains.invalidate_path(k)
end end
for id, _ in pairs(tab) do
advtrains.invalidate_path(id)
end end
end end
function advtrains.invalidate_path(id) function advtrains.invalidate_path(id)
atdebug("Path invalidate:",id)
local v=advtrains.trains[id] local v=advtrains.trains[id]
if not v then return end if not v then return end
advtrains.path_invalidate(v) advtrains.path_invalidate(v)

View File

@ -105,6 +105,7 @@ local signal_assignments = {}
-- track+direction -> signal position -- track+direction -> signal position
local influence_points = {} local influence_points = {}
function ildb.load(data) function ildb.load(data)
if not data then return end if not data then return end
if data.tcbs then if data.tcbs then
@ -119,6 +120,9 @@ function ildb.load(data)
if data.rs_locks then if data.rs_locks then
advtrains.interlocking.route.rte_locks = data.rs_locks advtrains.interlocking.route.rte_locks = data.rs_locks
end end
if data.rs_callbacks then
advtrains.interlocking.route.rte_callbacks = data.rs_callbacks
end
if data.influence_points then if data.influence_points then
influence_points = data.influence_points influence_points = data.influence_points
end end
@ -130,6 +134,7 @@ function ildb.save()
ts=track_sections, ts=track_sections,
signalass = signal_assignments, signalass = signal_assignments,
rs_locks = advtrains.interlocking.route.rte_locks, rs_locks = advtrains.interlocking.route.rte_locks,
rs_callbacks = advtrains.interlocking.route.rte_callbacks,
influence_points = influence_points, influence_points = influence_points,
} }
end end

View File

@ -177,14 +177,22 @@ local function apply_control(id, train)
train.ctrl.lzb = nil train.ctrl.lzb = nil
end end
local function invalidate(train)
advtrains.te_register_on_new_path(function(id, train)
train.lzb = { train.lzb = {
trav = atfloor(train.index), trav = atfloor(train.index),
travsht = train.is_shunt, travsht = train.is_shunt,
oncoming = {} oncoming = {}
} }
train.ctrl.lzb = nil train.ctrl.lzb = nil
end
function advtrains.interlocking.lzb_invalidate(train)
invalidate(train)
end
advtrains.te_register_on_new_path(function(id, train)
invalidate(train)
look_ahead(id, train) look_ahead(id, train)
end) end)

View File

@ -66,9 +66,10 @@ advtrains = {
-- The aspect passed in here can always be queried using the -- The aspect passed in here can always be queried using the
-- advtrains.interlocking.signal_get_supposed_aspect(pos) function. -- advtrains.interlocking.signal_get_supposed_aspect(pos) function.
-- It is always DANGER when the signal is not used as route signal.
-- For static signals, this function should be completely omitted -- For static signals, this function should be completely omitted
-- If this function is ommitted, it won't be possible to use -- If this function is omitted, it won't be possible to use
-- route setting on this signal. -- route setting on this signal.
end end
function get_aspect(pos, node) function get_aspect(pos, node)
@ -89,6 +90,18 @@ after_dig_node = advtrains.interlocking.signal_after_dig
(If you need to specify custom can_dig or after_dig_node callbacks, (If you need to specify custom can_dig or after_dig_node callbacks,
please call those functions anyway!) please call those functions anyway!)
Important note: If your signal should support external ways to set its
aspect (e.g. via mesecons), there are some things that need to be considered:
- advtrains.interlocking.signal_get_supposed_aspect(pos) won't respect this
- Whenever you change the signal aspect, and that aspect change
did not happen through a call to
advtrains.interlocking.signal_set_aspect(pos, asp), you are
*required* to call this function:
advtrains.interlocking.signal_on_aspect_changed(pos)
in order to notify trains about the aspect change.
This function will query get_aspect to retrieve the new aspect.
]]-- ]]--
local DANGER = { local DANGER = {
@ -128,6 +141,22 @@ function advtrains.interlocking.signal_set_aspect(pos, asp)
local ndef=minetest.registered_nodes[node.name] local ndef=minetest.registered_nodes[node.name]
if ndef and ndef.advtrains and ndef.advtrains.set_aspect then if ndef and ndef.advtrains and ndef.advtrains.set_aspect then
ndef.advtrains.set_aspect(pos, node, asp) ndef.advtrains.set_aspect(pos, node, asp)
advtrains.interlocking.signal_on_aspect_changed(pos)
end
end
-- should be called when aspect has changed on this signal.
function advtrains.interlocking.signal_on_aspect_changed(pos)
local ipts, iconn = advtrains.interlocking.db.get_ip_by_signalpos(pos)
if not ipts then return end
local ipos = minetest.string_to_pos(ipts)
local tns = advtrains.occ.get_trains_over(ipos)
for id, sidx in pairs(tns) do
local train = advtrains.trains[id]
if train.index <= sidx then
advtrains.interlocking.lzb_invalidate(train)
end
end end
end end