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
|
-- 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.speed_restriction = 0
else
train.speed_restriction = speed
train.is_shunt = shunt
end
--atdebug("train drove over IP: speed=",speed,"shunt=",shunt)
end
end
advtrains.tnc_register_on_approach(function(pos, id, train, index, has_entered, 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.il_shunt
local travspd = lzbdata.il_speed
if travsht==nil then
-- lzbdata has reset
travspd = train.speed_restriction
travsht = train.is_shunt or false
end
-- 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, lzbdata, "trainstate", train.speed_restriction, train.is_shunt)
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
--atdebug("ns,ts", nspd, travspd)
lspd = travspd
local udata = {signal_pos = spos}
local callback = get_over_function(lspd, travsht)
lzbdata.il_shunt = travsht
lzbdata.il_speed = travspd
--atdebug("new lzbdata",lzbdata)
advtrains.lzb_add_checkpoint(train, index, lspd, callback, lzbdata, udata)
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
|