aboutsummaryrefslogtreecommitdiff
path: root/advtrains_interlocking/distant_signals.lua
blob: 340cf74144a11d4dd9d76dd8f73da677e9707c75 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
--[[
Distant signaling modes:
	true: set route for the next signal
	false: do not set route for the next signal
	nil: hide distant signal information
]]

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
		if tcbs.distant_mode == nil then
			asp.dst = nil
		else
			asp.dst = (ildb.get_tcbs(tcbs.distant_of[1]).aspect or interlocking.DANGER).main
		end
	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
			if s.distant_mode == nil then
				s.aspect.dst = nil
			else
				s.aspect.dst = asp.main
			end
			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,
}