aboutsummaryrefslogtreecommitdiff
path: root/assets/manual.lyx
blob: 3255f682434dd73ed03444589ef5cd6299a5bbb0 (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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
#LyX 2.2 created this file. For more info see http://www.lyx.org/
\lyxformat 508
\begin_document
\begin_header
\save_transient_properties true
\origin unavailable
\textclass paper
\use_default_options true
\maintain_unincluded_children false
\language english
\language_package default
\inputencoding auto
\fontencoding global
\font_roman "default" "default"
\font_sans "default" "default"
\font_typewriter "default" "default"
\font_math "auto" "auto"
\font_default_family default
\use_non_tex_fonts false
\font_sc false
\font_osf false
\font_sf_scale 100 100
\font_tt_scale 100 100
\graphics default
\default_output_format default
\output_sync 0
\bibtex_command default
\index_command default
\paperfontsize default
\spacing single
\use_hyperref false
\papersize default
\use_geometry true
\use_package amsmath 1
\use_package amssymb 1
\use_package cancel 1
\use_package esint 1
\use_package mathdots 1
\use_package mathtools 1
\use_package mhchem 1
\use_package stackrel 1
\use_package stmaryrd 1
\use_package undertilde 1
\cite_engine basic
\cite_engine_type default
\biblio_style plain
\use_bibtopic false
\use_indices false
\paperorientation portrait
\suppress_date false
\justification true
\use_refstyle 1
\index Index
\shortcut idx
\color #008000
\end_index
\leftmargin 1cm
\topmargin 1cm
\rightmargin 1cm
\bottommargin 1cm
\secnumdepth 3
\tocdepth 3
\paragraph_separation indent
\paragraph_indentation default
\quotes_language english
\papercolumns 1
\papersides 1
\paperpagestyle default
\tracking_changes false
\output_changes false
\html_math_output 0
\html_css_as_file 0
\html_be_strict false
\end_header

\begin_body

\begin_layout Part*
Advanced Trains 
\end_layout

\begin_layout Standard
This mod aims to provide realistic, good-looking and functional trains by
 introducing a revolutionary rail placement system.
 It features several wagons that can be coupled together.
\end_layout

\begin_layout Standard
This mod is not finished.
 If you miss features, suggest them, but do not denounce this mod just because
 they are not yet implemented.
 They will be.
\end_layout

\begin_layout Subsection*
Placing Rails
\end_layout

\begin_layout Standard
Minetest's in-house rail system features rails that turn at an angle of
 90 degrees – totally impractical for the use with realistic trains.
 So we have our own rails.
 Remember: Carts can't drive on the rails provided by this mod, as do trains
 not drive on minetest's default rails because of their different track
 widths.
\end_layout

\begin_layout Standard
First, craft some rails.
\end_layout

\begin_layout Standard
\begin_inset Graphics
	filename manual_img/Bildschirmfoto_2016-09-17_09-43-29.png
	width 5cm

\end_inset


\end_layout

\begin_layout Standard
Now, place one at any position and another one right next to it: you have
 made your first railway track!
\end_layout

\begin_layout Standard
To learn how to make turns have a look at the following examples.
 A rail node has been placed only at the red-marked places.
\end_layout

\begin_layout Standard
\begin_inset Graphics
	filename manual_img/Bildschirmfoto_2016-09-17_10-04-12.png
	width 5cm

\end_inset


\begin_inset Graphics
	filename manual_img/Bildschirmfoto_2016-09-17_10-04-57.png
	width 4cm

\end_inset


\end_layout

\begin_layout Standard
\begin_inset Graphics
	filename manual_img/Bildschirmfoto_2016-09-17_10-05-51.png
	width 5cm

\end_inset


\begin_inset Graphics
	filename manual_img/Bildschirmfoto_2016-09-17_10-07-13.png
	width 5cm

\end_inset


\end_layout

\begin_layout Standard
As shown in the illustrations above, the 30-degree angled rails use a knight's
 move (2 ahead, 1 aside) for placement.
 For the rails to look realistic, I encourage you not to build turns that
 are too narrow.
 IMO the angles you can build with this are still way to narrow, but this
 is the best compromise I can find.
 
\end_layout

\begin_layout Subsection*
Switches
\end_layout

\begin_layout Standard
To create switches we need the trackworker tool.
 ATM it looks like a Doctor Who Sonic Screwdriver.
 Aside from turning rails into switches, it is also capable of rotating
 everything (rails, bumpers, signals) in this mod.
 Due to internal mechanics, nothing can be rotated using the default screwdriver.
\end_layout

\begin_layout Standard
\begin_inset Graphics
	filename manual_img/Bildschirmfoto_2016-09-17_09-56-34.png
	width 5cm

\end_inset


\end_layout

\begin_layout Standard
Place some rails.
 Then left-click 1-2 times on one of these rails, until you see a switch.
 Use right-click to rotate it how you need it.
 You can change the switch direction by right-clicking the switch or by
 powering it with mesecons.
\end_layout

\begin_layout Standard
Unfortunately tracks that are placed next to switches don't always automatically
 connect to them.
 You need to correct manually using the Trackworker.
 One day I will implement proper handling for these.
 When you are finished it could look like this:
\end_layout

\begin_layout Standard
\begin_inset Graphics
	filename manual_img/Bildschirmfoto_2016-09-17_10-08-02.png
	width 5cm

\end_inset


\end_layout

\begin_layout Subsection*
Rail crosses
\end_layout

\begin_layout Standard
There are no real cross-rail nodes.
 However you can create crossing rails by being creative and using the knight's
 move or by placing opposing 45-degree rails.
\end_layout

\begin_layout Standard
\begin_inset Graphics
	filename manual_img/Bildschirmfoto_2016-09-17_10-09-01.png
	width 5cm

\end_inset


\begin_inset Graphics
	filename manual_img/Bildschirmfoto_2016-09-17_10-10-15.png
	width 5cm

\end_inset


\end_layout

\begin_layout Subsection*
Height differences 
\end_layout

\begin_layout Standard
To master height differences you can craft slope nodes:
\end_layout

\begin_layout Standard
\begin_inset Graphics
	filename manual_img/Bildschirmfoto_2016-09-17_09-45-38.png
	width 5cm

\end_inset


\end_layout

\begin_layout Standard
To place them, you have to prepare the base, then stand in the right direction
 and point to the slope start point, then place it.
 A slope will be constructed in the direction you are facing (45 degree
 steps) leaned against the next solid node.
 The right number of slopes is subtracted from the item stack if you are
 in survival.
\end_layout

\begin_layout Subsection*
Bumpers, platforms, signals and detector rails
\end_layout

\begin_layout Standard
\begin_inset Graphics
	filename manual_img/Bildschirmfoto_2016-09-17_09-48-54.png
	width 5cm

\end_inset


\end_layout

\begin_layout Standard
Bumpers are objects that are usually placed at the end of a track to prevent
 trains rolling off it.
 After placed, they can be rotated using the Trackworker.
\end_layout

\begin_layout Standard
\begin_inset Graphics
	filename manual_img/Bildschirmfoto_2016-09-17_09-50-27.png
	width 5cm

\end_inset


\begin_inset Graphics
	filename manual_img/Bildschirmfoto_2016-09-17_09-51-02.png
	width 5cm

\end_inset


\end_layout

\begin_layout Standard
These are a regular analog signal and an electric signal.
 Like everything, you can rotate them using the Trackworker.
 Right-click or power with mesecons to signal trains that they can pass
 or have to stop.
 The signals do not have any effect on trains, they can only signal the
 driver.
 A more advanced signalling system (with distant signals/signal combinations)
 is planned.
\end_layout

\begin_layout Standard
\begin_inset Graphics
	filename manual_img/Bildschirmfoto_2016-09-17_09-58-39.png
	width 5cm

\end_inset


\begin_inset Graphics
	filename manual_img/Bildschirmfoto_2016-09-17_09-58-20.png
	width 5cm

\end_inset


\end_layout

\begin_layout Standard
These are some platform nodes.
 I suggest using the left one, it's only half height and looks better.
 These nodes also have a sandstone variant, craft with sandstone bricks
\end_layout

\begin_layout Standard
\begin_inset Graphics
	filename manual_img/Bildschirmfoto_2017-03-09_11-33-09.png
	width 5cm

\end_inset


\end_layout

\begin_layout Standard
These detector rails turn adjacent mesecons on when a train is standing/driving
 over them.
\end_layout

\begin_layout Standard
Notice: Detector rails and bumpers currently aren't aligned to the regular
 tracks.
 This will be fixed soon.
 Meanwhile, you need to rotate them manually.
\end_layout

\begin_layout Subsection*
Trains
\end_layout

\begin_layout Standard
There are some wagons included in this modpack, however community members
 (namely mbb and Andrey) have made some more wagons that can be downloaded
 and enabled separately.
 Visit the forum topic (
\begin_inset Flex URL
status collapsed

\begin_layout Plain Layout

https://forum.minetest.net/viewtopic.php?f=11&t=14726
\end_layout

\end_inset

) to download them.
\end_layout

\begin_layout Standard
To see what's included, look up in a craft guide or consult the creative
 mode inventory.
\end_layout

\begin_layout Standard
To place wagons simply craft and click a track.
 To remove a wagon, punch it.
 Only the person who placed the wagon can do this.
 In survival if you destroy trains you get only some of your steel back,
 so you will be asked to confirm if you really want to destroy a wagon.
\end_layout

\begin_layout Subsection*
Driving trains
\end_layout

\begin_layout Standard
Right-click any wagon to get on.
 This will attach you to the wagon and register you as passenger.
 Depending on how the wagon is set up, you are either in a passenger seat
 or inside a driver stand.
 Right-clicking again will show your possibilities on what you can do in/with
 the wagon.
\end_layout

\begin_layout Standard
Example:
\end_layout

\begin_layout Standard
\begin_inset Graphics
	filename manual_img/Bildschirmfoto_2017-03-09_11-42-49.png
	width 5cm

\end_inset


\end_layout

\begin_layout Standard
When entering a subway wagon, you are formally inside the passenger area.
 You can see this by the fact that there's no head-up display.
 Right-clicking brings up this form.
\end_layout

\begin_layout Standard
The first button will make you move to the Driver stand, so you can drive
 the train.
\end_layout

\begin_layout Standard
The second button should say 
\begin_inset Quotes eld
\end_inset

Wagon properties
\begin_inset Quotes erd
\end_inset

 and appears only for the wagon owner.
 See 
\begin_inset Quotes eld
\end_inset

Wagon Properties
\begin_inset Quotes erd
\end_inset

.
\end_layout

\begin_layout Standard
The last button tells that the doors are closed, so you can't get off at
 this time.
 If the doors are open or the wagon has no doors, this button says 
\begin_inset Quotes eld
\end_inset

Get off
\begin_inset Quotes erd
\end_inset

.
\end_layout

\begin_layout Standard
It is always possible to bypass closed doors and get off by holding the
 Sneak key and right-clicking the wagon or by holding Sneak and Use at the
 same time.
 Remember that this may result in your death when the train is travelling
 fast.
\end_layout

\begin_layout Standard
The Japanese train and the Subway train support automatic getting on by
 just walking into the wagon.
 As soon as you stand on a platform and walk towards a door, you will automatica
lly get on the wagon.
 On these, pressing W or S while inside the Passenger Area will also make
 you get off.
\end_layout

\begin_layout Subsection*
Train controls
\end_layout

\begin_layout Standard
If you are inside a driver stand you are presented with a head-up display:
\end_layout

\begin_layout Standard
The upper bar shows your current speed and the lower bar shows what speed
 you ordered the train to hold.
 Assuming you have the default controls (WASD, Shift for sneak, Space for
 jump), the following key bindings apply: 
\end_layout

\begin_layout Itemize
W - faster
\end_layout

\begin_layout Itemize
S - slower / change direction
\end_layout

\begin_layout Itemize
A / D – open/close doors
\end_layout

\begin_layout Itemize
Space: brake (shown by =B=, target speed will be decreased automatically)
\end_layout

\begin_layout Itemize
Sneak+S: set speed to 0 (train rolls out, brake to stop!)
\end_layout

\begin_layout Itemize
Sneak+W: Set full speed
\end_layout

\begin_layout Itemize
Sneak+A: Set speed to 4 (~40km/h)
\end_layout

\begin_layout Itemize
Sneak+D: Set speed to 8 (~100km/h)
\end_layout

\begin_layout Itemize
Sneak+Space: toggle brake (the brake will not release when releasing the
 keys, shown by =^B=)
\end_layout

\begin_layout Subsection*
Coupling wagons
\end_layout

\begin_layout Standard
You just learned how to drive an engine.
 Now place a wagon anywhere and drive your engine slowly towards that wagon.
 As soon as they collided your engine will stop.
 Now get off and right-click the green icon that appeared between the engine
 and the train.
 You have coupled the wagon to the engine.
\end_layout

\begin_layout Standard
\begin_inset Graphics
	filename manual_img/screenshot_20161203_231622.png
	width 5cm

\end_inset


\end_layout

\begin_layout Standard
To discouple a wagon, punch the red icon between the wagons you want to
 discouple while the train is standing.
\end_layout

\begin_layout Subsection*
Automatic Train Control (ATC)
\end_layout

\begin_layout Standard
ATC rails allow you to automate train operation.
 There are two types of ATC rails:
\end_layout

\begin_layout Subsubsection*
Regular ATC
\end_layout

\begin_layout Standard
The ATC rail does not have a crafting recipe.
 When placed, you can set a command and it will be sent to any train driving
 over the controller.
 
\end_layout

\begin_layout Standard
Only the static mode is implemented, changing the mode has no effect.
\end_layout

\begin_layout Standard
For a detailed explanation how ATC commands work and their syntax see atc_comman
d.txt
\end_layout

\begin_layout Standard
Note: to rotate ATC rails, you need to bypass the formspec that is set for
 the node.
 To do this, hold Sneak when right-clicking the rail with the trackworker
 tool.
\end_layout

\begin_layout Subsubsection*
LUA ATC
\end_layout

\begin_layout Standard
The LUA ATC suite is part of the mod advtrains_luaautomation.
 The LUA ATC components are quite similar to Mesecons Luacontrollers and
 allow to create all kinds of automation systems.
 This tool is not intended for beginners or regular players, but for server
 admins who wish to create a heavily automated subway system.
\end_layout

\begin_layout Standard
More information on those can be found inside the mod directory of advtrains_lua
automation.
\end_layout

\end_body
\end_document
pan class="hl com"> locks = {[n] = <pts>} next = <sigd> } -- Set whenever a route has been set through this TC. It saves the origin tcb id and side -- (=the origin signal). rsn is some description to be shown to the user -- first says whether to clear the routesetting status from the origin signal. -- locks contains the positions where locks are held by this ts. -- 'route' is cleared when train enters the section, while 'route_post' cleared when train leaves section. trains = {<id>, ...} -- Set whenever a train (or more) reside in this TC } Signal specifier (sigd) (a pair of TCB/Side): {p = <pos>, s = <1/2>} Signal Assignments: reverse lookup of signals assigned to TCBs signal_assignments = { [<signal pts>] = <sigd> } ]] -- function ildb.create_tcb(pos) local new_tcb = { [1] = {}, [2] = {}, } local pts = advtrains.roundfloorpts(pos) if not track_circuit_breaks[pts] then track_circuit_breaks[pts] = new_tcb return true else return false end end function ildb.get_tcb(pos) local pts = advtrains.roundfloorpts(pos) return track_circuit_breaks[pts] end function ildb.get_tcbs(sigd) local tcb = ildb.get_tcb(sigd.p) if not tcb then return nil end return tcb[sigd.s] end function ildb.create_ts(sigd) local tcbs = ildb.get_tcbs(sigd) local id = advtrains.random_id() while track_sections[id] do id = advtrains.random_id() end track_sections[id] = { name = "Section "..id, tc_breaks = { sigd } } tcbs.ts_id = id end function ildb.get_ts(id) return track_sections[id] end -- various helper functions handling sigd's local sigd_equal = advtrains.interlocking.sigd_equal local function insert_sigd_nodouble(list, sigd) for idx, cmp in pairs(list) do if sigd_equal(sigd, cmp) then return end end table.insert(list, sigd) end -- This function will actually handle the node that is in connid direction from the node at pos -- so, this needs the conns of the node at pos, since these are already calculated local function traverser(found_tcbs, pos, conns, connid, count, brk_when_found_n) local adj_pos, adj_connid, conn_idx, nextrail_y, next_conns = advtrains.get_adjacent_rail(pos, conns, connid, advtrains.all_tracktypes) if not adj_pos then --atdebug("Traverser found end-of-track at",pos, connid) return end -- look whether there is a TCB here if #next_conns == 2 then --if not, don't even try! local tcb = ildb.get_tcb(adj_pos) if tcb then -- done with this branch --atdebug("Traverser found tcb at",adj_pos, adj_connid) insert_sigd_nodouble(found_tcbs, {p=adj_pos, s=adj_connid}) return end end -- recursion abort condition if count > TRAVERSER_LIMIT then --atdebug("Traverser hit counter at",adj_pos, adj_connid) return true end -- continue traversing local counter_hit = false for nconnid, nconn in ipairs(next_conns) do if adj_connid ~= nconnid then counter_hit = counter_hit or traverser(found_tcbs, adj_pos, next_conns, nconnid, count + 1, brk_when_found_n) if brk_when_found_n and #found_tcbs>=brk_when_found_n then break end end end return counter_hit end -- Merges the TS with merge_id into root_id and then deletes merge_id local function merge_ts(root_id, merge_id) local rts = ildb.get_ts(root_id) local mts = ildb.get_ts(merge_id) if not mts then return end -- This may be the case when sync_tcb_neighbors -- inserts the same id twice. do nothing. if not ildb.may_modify_ts(rts) then return false end if not ildb.may_modify_ts(mts) then return false end -- cobble together the list of TCBs for _, msigd in ipairs(mts.tc_breaks) do local tcbs = ildb.get_tcbs(msigd) if tcbs then insert_sigd_nodouble(rts.tc_breaks, msigd) tcbs.ts_id = root_id end advtrains.interlocking.show_tcb_marker(msigd.p) end -- done track_sections[merge_id] = nil end local lntrans = { "A", "B" } local function sigd_to_string(sigd) return minetest.pos_to_string(sigd.p).." / "..lntrans[sigd.s] end -- Check for near TCBs and connect to their TS if they have one, and syncs their data. function ildb.sync_tcb_neighbors(pos, connid) local found_tcbs = { {p = pos, s = connid} } local node_ok, conns, rhe = advtrains.get_rail_info_at(pos, advtrains.all_tracktypes) if not node_ok then atwarn("update_tcb_neighbors but node is NOK: "..minetest.pos_to_string(pos)) return end --atdebug("Traversing from ",pos, connid) local counter_hit = traverser(found_tcbs, pos, conns, connid, 0) local ts_id local list_eoi = {} local list_ok = {} local list_mismatch = {} local ts_to_merge = {} for idx, sigd in pairs(found_tcbs) do local tcbs = ildb.get_tcbs(sigd) if not tcbs.ts_id then --atdebug("Sync: put",sigd_to_string(sigd),"into list_eoi") table.insert(list_eoi, sigd) elseif not ts_id and tcbs.ts_id then if not ildb.get_ts(tcbs.ts_id) then atwarn("Track section database is inconsistent, there's no TS with ID=",tcbs.ts_id) tcbs.ts_id = nil table.insert(list_eoi, sigd) else --atdebug("Sync: put",sigd_to_string(sigd),"into list_ok") ts_id = tcbs.ts_id table.insert(list_ok, sigd) end elseif ts_id and tcbs.ts_id and tcbs.ts_id ~= ts_id then atwarn("Track section database is inconsistent, sections share track!") atwarn("Merging",tcbs.ts_id,"into",ts_id,".") table.insert(list_mismatch, sigd) table.insert(ts_to_merge, tcbs.ts_id) end end if ts_id then local ts = ildb.get_ts(ts_id) for _, sigd in ipairs(list_eoi) do local tcbs = ildb.get_tcbs(sigd) tcbs.ts_id = ts_id table.insert(ts.tc_breaks, sigd) advtrains.interlocking.show_tcb_marker(sigd.p) end for _, mts in ipairs(ts_to_merge) do merge_ts(ts_id, mts) end end end function ildb.link_track_sections(merge_id, root_id) if merge_id == root_id then return end merge_ts(root_id, merge_id) end function ildb.remove_from_interlocking(sigd) local tcbs = ildb.get_tcbs(sigd) if not ildb.may_modify_tcbs(tcbs) then return false end if tcbs.ts_id then local tsid = tcbs.ts_id local ts = ildb.get_ts(tsid) if not ts then tcbs.ts_id = nil return true end -- remove entry from the list local idx = 1 while idx <= #ts.tc_breaks do local cmp = ts.tc_breaks[idx] if sigd_equal(sigd, cmp) then table.remove(ts.tc_breaks, idx) else idx = idx + 1 end end tcbs.ts_id = nil --ildb.sync_tcb_neighbors(sigd.p, sigd.s) if #ts.tc_breaks == 0 then track_sections[tsid] = nil end end advtrains.interlocking.show_tcb_marker(sigd.p) if tcbs.signal then return false end return true end function ildb.remove_tcb(pos) local pts = advtrains.roundfloorpts(pos) if not track_circuit_breaks[pts] then return end for connid=1,2 do if not ildb.remove_from_interlocking({p=pos, s=connid}) then return false end end track_circuit_breaks[pts] = nil return true end function ildb.dissolve_ts(ts_id) local ts = ildb.get_ts(ts_id) if not ildb.may_modify_ts(ts) then return false end local tcbr = advtrains.merge_tables(ts.tc_breaks) for _,sigd in ipairs(tcbr) do ildb.remove_from_interlocking(sigd) end -- Note: ts gets removed in the moment of the removal of the last TCB. return true end -- Returns true if it is allowed to modify any property of a track section, such as -- - removing TCBs -- - merging and dissolving sections -- As of now the action will be denied if a route is set or if a train is in the section. function ildb.may_modify_ts(ts) if ts.route or ts.route_post or (ts.trains and #ts.trains>0) then return false end return true end function ildb.may_modify_tcbs(tcbs) if tcbs.ts_id then local ts = ildb.get_ts(tcbs.ts_id) if ts and not ildb.may_modify_ts(ts) then return false end end return true end -- Utilize the traverser to find the track section at the specified position -- Returns: -- ts_id, origin - the first found ts and the sigd of the found tcb -- nil - there were no TCBs in TRAVERSER_MAX range of the position -- false - the first found TCB stated End-Of-Interlocking, or track ends were reached function ildb.get_ts_at_pos(pos) local node_ok, conns, rhe = advtrains.get_rail_info_at(pos, advtrains.all_tracktypes) if not node_ok then error("get_ts_at_pos but node is NOK: "..minetest.pos_to_string(pos)) end local limit_hit = false local found_tcbs = {} for connid, conn in ipairs(conns) do -- Note: a breadth-first-search would be better for performance limit_hit = limit_hit or traverser(found_tcbs, pos, conns, connid, 0, 1) if #found_tcbs >= 1 then local tcbs = ildb.get_tcbs(found_tcbs[1]) local ts if tcbs.ts_id then return tcbs.ts_id, found_tcbs[1] else return false end end end if limit_hit then -- there was at least one limit hit return nil else -- all traverser ends were track ends return false end end -- returns the sigd the signal at pos belongs to, if this is known function ildb.get_sigd_for_signal(pos) local pts = advtrains.roundfloorpts(pos) local sigd = signal_assignments[pts] if sigd then if not ildb.get_tcbs(sigd) then signal_assignments[pts] = nil return nil end return sigd end return nil end function ildb.set_sigd_for_signal(pos, sigd) local pts = advtrains.roundfloorpts(pos) signal_assignments[pts] = sigd end -- checks if a signal is influencing here function ildb.get_ip_signal(pts, connid) if influence_points[pts] then return influence_points[pts][connid] end end -- Tries to get aspect to obey here, if there -- is a signal ip at this location -- auto-clears invalid assignments function ildb.get_ip_signal_asp(pts, connid) local p = ildb.get_ip_signal(pts, connid) if p then local asp = advtrains.interlocking.signal_get_aspect(p) if not asp then atlog("Clearing orphaned signal influence point", pts, "/", connid) ildb.clear_ip_signal(pts, connid) return nil end return asp, p end return nil end -- set signal assignment. function ildb.set_ip_signal(pts, connid, spos) ildb.clear_ip_by_signalpos(spos) if not influence_points[pts] then influence_points[pts] = {} end influence_points[pts][connid] = spos end -- clear signal assignment. function ildb.clear_ip_signal(pts, connid) influence_points[pts][connid] = nil for _,_ in pairs(influence_points[pts]) do return end influence_points[pts] = nil end function ildb.get_ip_by_signalpos(spos) for pts,tab in pairs(influence_points) do for connid,pos in pairs(tab) do if vector.equals(pos, spos) then return pts, connid end end end end -- clear signal assignment given the signal position function ildb.clear_ip_by_signalpos(spos) local pts, connid = ildb.get_ip_by_signalpos(spos) if pts then ildb.clear_ip_signal(pts, connid) end end advtrains.interlocking.db = ildb