aboutsummaryrefslogtreecommitdiff
path: root/advtrains_interlocking/distant_signals.lua
diff options
context:
space:
mode:
Diffstat (limited to 'advtrains_interlocking/distant_signals.lua')
-rw-r--r--advtrains_interlocking/distant_signals.lua83
1 files changed, 83 insertions, 0 deletions
diff --git a/advtrains_interlocking/distant_signals.lua b/advtrains_interlocking/distant_signals.lua
new file mode 100644
index 0000000..0da1c10
--- /dev/null
+++ b/advtrains_interlocking/distant_signals.lua
@@ -0,0 +1,83 @@
+local interlocking = advtrains.interlocking
+local ildb = advtrains.interlocking.db
+
+local function update_distant(tcbs)
+ if not (tcbs and tcbs.signal) then return end
+ if not tcbs.aspect then tcbs.aspect = table.copy(interlocking.DANGER) end
+ local asp = tcbs.aspect
+ if tcbs.distant_of then
+ asp.dst = (ildb.get_tcbs(tcbs.distant_of[1]).aspect or interlocking.DANGER).main
+ end
+ interlocking.update_signal_aspect(tcbs)
+ if tcbs.distant then
+ local dst = tcbs.distant
+ for i = 1, #dst do
+ local s = ildb.get_tcbs(dst[i])
+ if not s.aspect then s.aspect = table.copy(interlocking.DANGER) end
+ s.aspect.dst = asp.main
+ interlocking.update_signal_aspect(s)
+ end
+ end
+end
+
+local function unassign_distant(dsts)
+ if not dsts then return end
+ local dof = dsts.distant_of
+ if not dof then return end
+ if dsts.signal and dsts.aspect then
+ dsts.aspect.dst = nil
+ interlocking.update_signal_aspect(dsts)
+ end
+ local sigd, idx = dof[1], dof[2]
+ local tcbs = ildb.get_tcbs(sigd)
+ local dst = tcbs.distant
+ dsts.distant_of = nil
+ if idx == #dst then
+ dst[#dst] = nil
+ else
+ local ent = dst[#dst]
+ dst[idx] = ent
+ dst[#dst] = nil
+ local repl = ildb.get_tcbs(ent)
+ repl.distant_of[2] = idx
+ end
+end
+
+local function assign_distant(sigd, dstd)
+ if not sigd then return end
+ if not dstd then return end
+ local tcbs = ildb.get_tcbs(sigd)
+ local dsts = ildb.get_tcbs(dstd)
+ unassign_distant(dsts)
+ if not (tcbs.signal and dsts.signal) then return end
+ local dst = tcbs.distant
+ if not dst then
+ dst = {}
+ tcbs.distant = dst
+ end
+ local newidx = #dst+1
+ dsts.distant_of = {sigd, newidx}
+ dst[newidx] = dstd
+ update_distant(dsts)
+end
+
+local function remove_distant(tcbs)
+ if not tcbs then return end
+ if tcbs.distant_of then
+ unassign_distant(tcbs)
+ end
+ if tcbs.distant then
+ local dst = tcbs.distant
+ for i = #dst, 1, -1 do
+ local s = ildb.get_tcbs(dst[i])
+ unassign_distant(s)
+ end
+ end
+end
+
+interlocking.distant = {
+ assign = assign_distant,
+ unassign = unassign_distant,
+ remove = remove_distant,
+ update = update_distant,
+}