aboutsummaryrefslogtreecommitdiff
path: root/advtrains_interlocking/approach.lua
blob: 6157a1792fee47ac1b2dd869bdd317538ba68476 (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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
-- Interlocking counterpart of LZB, which has been moved into the core...
-- Registers LZB callback for signal management.

--[[
usage of lzbdata:
{
	travsht = boolean indicating whether the train will be a shunt move at "trav"
	travspd = speed restriction at end of traverser
	travwspd = warning speed res.t
}
]]

local SHUNT_SPEED_MAX = advtrains.SHUNT_SPEED_MAX

local il = advtrains.interlocking

local function get_over_function(speed, shunt)
	return function(pos, id, train, index, speed, lzbdata)
		if speed == 0 and minetest.settings:get_bool("at_il_force_lzb_halt") then
			atwarn(id,"overrun LZB 0 restriction (red signal) ",pos)
			-- Set train 1 index backward. Hope this does not lead to bugs...
			train.index = index - 0.5
			train.velocity = 0
			train.ctrl.lzb = 0
			minetest.after(0, advtrains.invalidate_path, id)
		else
			train.speed_restriction = speed
			train.is_shunt = shunt
		end
	end
end

advtrains.tnc_register_on_approach(function(pos, id, train, index, lzbdata)

	--atdebug(id,"IL ApprC",pos,index,lzbdata)
	--train.debug = advtrains.print_concat_table({train.is_shunt,"|",index,"|",lzbdata})

	local pts = advtrains.roundfloorpts(pos)
	local cn  = train.path_cn[index]
	local travsht = lzbdata.travsht
	
	if travsht==nil then
		travsht = train.is_shunt
	end
	
	local travspd = lzbdata.travspd
	local travwspd = lzbdata.travwspd
	
	-- check for signal
	local asp, spos = il.db.get_ip_signal_asp(pts, cn)
	
	-- do ARS if needed
	local ars_enabled = not train.ars_disable
	-- Note on ars_disable:
	-- Theoretically, the ars_disable flag would need to behave like the speed restriction field: it should be
	-- stored in lzbdata and updated once the train drives over. However, for the sake of simplicity, it is simply
	-- a value in the train. In this case, this is sufficient because once a train triggers ARS for the first time,
	-- resetting the path does not matter to the set route and ARS doesn't need to be called again.
	if spos and ars_enabled then
		--atdebug(id,"IL Spos (ARS)",spos,asp)
		local sigd = il.db.get_sigd_for_signal(spos)
		if sigd then
			il.ars_check(sigd, train)
		end
	end
	--atdebug("trav: ",pos, cn, asp, spos, "travsht=", lzb.travsht)
	local lspd
	if asp then
		--atdebug(id,"IL Signal",spos,asp)
		local nspd = 0
		--interpreting aspect and determining speed to proceed
		if travsht then
			--shunt move
			if asp.shunt.free then
				nspd = SHUNT_SPEED_MAX
			elseif asp.shunt.proceed_as_main and asp.main.free then
				nspd = asp.main.speed
				travsht = false
			end
		else
			--train move
			if asp.main.free then
				nspd = asp.main.speed
			elseif asp.shunt.free then
				nspd = SHUNT_SPEED_MAX
				travsht = true
			end
		end
		-- nspd can now be: 1. !=0: new speed restriction, 2. =0: stop here or 3. nil: keep travspd
		if nspd then
			if nspd == -1 then
				travspd = nil
			else
				travspd = nspd
			end
		end
		
		local nwspd = asp.info.w_speed
		if nwspd then
			if nwspd == -1 then
				travwspd = nil
			else
				travwspd = nwspd
			end
		end
		--atdebug("ns,wns,ts,wts", nspd, nwspd, travspd, travwspd)
		lspd = travspd
		if travwspd and (not lspd or lspd>travwspd) then
			lspd = travwspd
		end
		
		local udata = {signal_pos = spos}
		local callback = get_over_function(lspd, travsht)
		lzbdata.travsht = travsht
		lzbdata.travspd = travspd
		lzbdata.travwspd = travwspd
		advtrains.lzb_add_checkpoint(train, index, lspd, callback, lzbdata)
	end
end)

-- Set the ars_disable flag to the value passed
-- Triggers a path invalidation if set to false
function advtrains.interlocking.ars_set_disable(train, value)
	if value then
		train.ars_disable = true
	else
		train.ars_disable = nil
		minetest.after(0, advtrains.path_invalidate, train)
	end
end