From 842a85606e4495dd631c2916d09a760d74a0ce13 Mon Sep 17 00:00:00 2001 From: orwell96 Date: Wed, 10 Oct 2018 22:41:59 +0200 Subject: Properly implement invalidate_all_paths, recheck lzb on aspect change --- advtrains/occupation.lua | 20 +++++++++++++++++++- advtrains/trainlogic.lua | 29 +++++++++++++---------------- advtrains_interlocking/database.lua | 5 +++++ advtrains_interlocking/lzb.lua | 12 ++++++++++-- advtrains_interlocking/signal_api.lua | 31 ++++++++++++++++++++++++++++++- 5 files changed, 77 insertions(+), 20 deletions(-) diff --git a/advtrains/occupation.lua b/advtrains/occupation.lua index dd0235a..568f308 100644 --- a/advtrains/occupation.lua +++ b/advtrains/occupation.lua @@ -208,7 +208,7 @@ function o.get_occupations(train, index) return r, pos end -- 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) local pos = advtrains.round_vector_floor_y(ppos) local t = occget(pos) @@ -226,4 +226,22 @@ function o.get_trains_at(ppos) return r 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 diff --git a/advtrains/trainlogic.lua b/advtrains/trainlogic.lua index f26f7da..7147787 100644 --- a/advtrains/trainlogic.lua +++ b/advtrains/trainlogic.lua @@ -1037,26 +1037,23 @@ function advtrains.get_train_at_pos(pos) end end + +-- ehm... I never adapted this function to the new path system ?! function advtrains.invalidate_all_paths(pos) - --if a position is given, only invalidate inside a radius to save performance - local inv_radius=50 - atprint("invalidating all paths") - for k,v in pairs(advtrains.trains) do - local exec=true - if pos and v.path and v.index and v.end_index then - --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 + local tab + if pos then + -- if position given, check occupation system + tab = advtrains.occ.get_trains_over(pos) + else + tab = advtrains.trains + end + + for id, _ in pairs(tab) do + advtrains.invalidate_path(id) end end function advtrains.invalidate_path(id) + atdebug("Path invalidate:",id) local v=advtrains.trains[id] if not v then return end advtrains.path_invalidate(v) diff --git a/advtrains_interlocking/database.lua b/advtrains_interlocking/database.lua index af90880..a2df111 100644 --- a/advtrains_interlocking/database.lua +++ b/advtrains_interlocking/database.lua @@ -105,6 +105,7 @@ local signal_assignments = {} -- track+direction -> signal position local influence_points = {} + function ildb.load(data) if not data then return end if data.tcbs then @@ -119,6 +120,9 @@ function ildb.load(data) if data.rs_locks then advtrains.interlocking.route.rte_locks = data.rs_locks end + if data.rs_callbacks then + advtrains.interlocking.route.rte_callbacks = data.rs_callbacks + end if data.influence_points then influence_points = data.influence_points end @@ -130,6 +134,7 @@ function ildb.save() ts=track_sections, signalass = signal_assignments, rs_locks = advtrains.interlocking.route.rte_locks, + rs_callbacks = advtrains.interlocking.route.rte_callbacks, influence_points = influence_points, } end diff --git a/advtrains_interlocking/lzb.lua b/advtrains_interlocking/lzb.lua index c9e40ab..8781d40 100644 --- a/advtrains_interlocking/lzb.lua +++ b/advtrains_interlocking/lzb.lua @@ -177,14 +177,22 @@ local function apply_control(id, train) train.ctrl.lzb = nil end - -advtrains.te_register_on_new_path(function(id, train) +local function invalidate(train) train.lzb = { trav = atfloor(train.index), travsht = train.is_shunt, oncoming = {} } 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) end) diff --git a/advtrains_interlocking/signal_api.lua b/advtrains_interlocking/signal_api.lua index 90fe1fc..3a042c0 100644 --- a/advtrains_interlocking/signal_api.lua +++ b/advtrains_interlocking/signal_api.lua @@ -66,9 +66,10 @@ advtrains = { -- The aspect passed in here can always be queried using the -- 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 - -- 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. end 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, 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 = { @@ -128,6 +141,22 @@ function advtrains.interlocking.signal_set_aspect(pos, asp) local ndef=minetest.registered_nodes[node.name] if ndef and ndef.advtrains and ndef.advtrains.set_aspect then 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 -- cgit v1.2.3