aboutsummaryrefslogtreecommitdiff
path: root/advtrains_train_track/init.lua
blob: f551ec517722fc91323fefb468e96a510490ee60 (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
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
-- Default tracks for advtrains
-- (c) orwell96 and contributors

local default_boxen = {
    ["st"] = {
        [""] = {
            selection_box = {
                type = "fixed",
                fixed = {-1/2-1/16, -1/2, -1/2, 1/2+1/16, -1/2+2/16, 1/2},
            }
        },
        ["_30"] = {
            selection_box = {
                type = "fixed",
                fixed = {
                    {-0.5000, -0.5000, -1.000, 0.5000, -0.3750, 1.000},
                    {-0.8750, -0.5000, -1.000, -0.5000, -0.3750, 0.2500},
                    {0.5000, -0.5000, -0.2500, 0.8750, -0.3750, 1.000},
                    {-0.1250, -0.5000, -1.375, 0.1875, -0.3750, -1.000}
                }
            }
        },
        ["_45"] = {
            selection_box = {
                type = "fixed",
                fixed = {
                    {-0.5000, -0.5000, -0.8750, 0.5000, -0.3750, 0.8750},
                    {0.5000, -0.5000, -0.5000, 0.8750, -0.3750, 0.5000},
                    {-0.8750, -0.5000, -0.5000, -0.5000, -0.3750, 0.5000}
                }
            }
        },
        ["_60"] = {
            selection_box = {
                type = "fixed",
                fixed = {
                    {-1.000, -0.5000, -0.5000, 1.000, -0.3750, 0.5000},
                    {-1.000, -0.5000, -0.8750, 0.2500, -0.3750, -0.5000},
                    {-0.2500, -0.5000, 0.5000, 1.000, -0.3750, 0.8750},
                    {-1.375, -0.5000, -0.1250, -1.000, -0.3750, 0.1875}
                }
            }
        },
    },

    ["cr"] = {
        [""] = {
            selection_box = {
                type = "fixed",
                fixed = {
                    {-0.5000, -0.5000, -0.5000, 0.6875, -0.3750, 0.5000},
                    {-0.3750, -0.5000, -1.000, 1.000, -0.3750, 0.000}
                }
            }
        },
        ["_30"] = {
            selection_box = {
                type = "fixed",
                fixed = {
                    {-0.5000, -0.5000, -0.5000, 0.7500, -0.3750, 0.8750},
                    {-0.3750, -0.5000, 0.8750, 0.2500, -0.3750, 1.188},
                    {0.7500, -0.5000, 0.2500, 1.063, -0.3750, 0.8750}
                }
            }
        },
        ["_45"] = {
            selection_box = {
                type = "fixed",
                fixed = {
                    {-0.5000, -0.5000, -1.125, 0.5000, -0.3750, 0.6875},
                    {-0.8750, -0.5000, -0.9375, -0.5000, -0.3750, 0.06250},
                    {0.5000, -0.5000, -0.5000, 0.8750, -0.3750, 0.5000}
                }
            }
        },
        ["_60"] = {
            selection_box = {
                type = "fixed",
                fixed = {
                    {-0.8125, -0.5000, -0.5000, 1.188, -0.3750, 0.5000},
                    {-0.1875, -0.5000, 0.5000, 0.8750, -0.3125, 0.8750},
                    {-0.2500, -0.5000, -0.9375, 0.3125, -0.3125, -0.5000}
                }
            }
        },
    },

    ["swlst"] = {
        [""] = {
            selection_box = {
                type = "fixed",
                fixed = {
                    {-0.5000, -0.5000, -0.5000, 0.6250, -0.3750, 0.5000},
                    {-0.3125, -0.5000, -1.000, 0.9375, -0.3125, -0.06250}
                }
            }
        },
        ["_30"] = {
            selection_box = {
                type = "fixed",
                fixed = {
                    {-0.5000, -0.5000, -1.000, 0.5000, -0.3750, 1.000},
                    {-0.8750, -0.5000, -1.000, -0.5000, -0.3750, 0.2500},
                    {0.5000, -0.5000, -0.2500, 0.8750, -0.3750, 1.000},
                    {-0.1250, -0.5000, -1.375, 0.1875, -0.3750, -1.000}
                }
            }
        },
        ["_45"] = {
            selection_box = {
                type = "fixed",
                fixed = {
                    {-0.5000, -0.5000, -1.1875, 0.5000, -0.3750, 0.8750},
                    {0.5000, -0.5000, -0.5000, 0.8750, -0.3750, 0.5000},
                    {-0.8750, -0.5000, -0.8125, -0.5000, -0.3750, 0.5000}
                }
            }
        },
        ["_60"] = {
            selection_box = {
                type = "fixed",
                fixed = {
                    {-1.000, -0.5000, -0.5000, 1.000, -0.3750, 0.5000},
                    {-1.000, -0.5000, -0.8750, 0.2500, -0.3750, -0.5000},
                    {-0.2500, -0.5000, 0.5000, 1.000, -0.3750, 0.8750},
                    {-1.375, -0.5000, -0.1250, -1.000, -0.3750, 0.1875}
                }
            }
        },
    },

    ["swrst"] = {
        [""] = {
            selection_box = {
                type = "fixed",
                fixed = {
                    {-0.5000, -0.5000, -0.5000, 0.6250, -0.3750, 0.5000},
                    {-0.8125, -0.5000, -1.000, 0.4375, -0.3125, -0.06250}
                }
            }
        },
        ["_30"] = {
            selection_box = {
                type = "fixed",
                fixed = {
                    {-0.5000, -0.5000, -1.000, 0.5000, -0.3750, 1.000},
                    {-0.8750, -0.5000, -1.000, -0.5000, -0.3750, 0.2500},
                    {0.5000, -0.5000, -0.2500, 0.8750, -0.3750, 1.000},
                    {-0.1250, -0.5000, -1.375, 0.1875, -0.3750, -1.000}
                }
            }
        },
        ["_45"] = {
            selection_box = {
                type = "fixed",
                fixed = {
                    {-1.1875, -0.5000, -0.5000, 0.8750, -0.3750, 0.5000},
                    {-0.5000, -0.5000, 0.5000, 0.5000, -0.3750, 0.8750},
                    {-0.8125, -0.5000, -0.8750, 0.5000, -0.3750, -0.5000}
                }
            }
        },
        ["_60"] = {
            selection_box = {
                type = "fixed",
                fixed = {
                    {-1.000, -0.5000, -0.5000, 1.000, -0.3750, 0.5000},
                    {-1.000, -0.5000, -0.8750, 0.2500, -0.3750, -0.5000},
                    {-0.2500, -0.5000, 0.5000, 1.000, -0.3750, 0.8750},
                    {-1.375, -0.5000, -0.1250, -1.000, -0.3750, 0.1875}
                }
            }
        },
    },
}

default_boxen["swlcr"] = default_boxen["swlst"]
default_boxen["swrcr"] = default_boxen["swrst"]

--flat
advtrains.register_tracks("default", {
	nodename_prefix="advtrains:dtrack",
	texture_prefix="advtrains_dtrack",
	models_prefix="advtrains_dtrack",
	models_suffix=".b3d",
	shared_texture="advtrains_dtrack_shared.png",
	description=attrans("Track"),
	formats={},

    get_additional_definiton = function(def, preset, suffix, rotation)
        if default_boxen[suffix] ~= nil and default_boxen[suffix][rotation] ~= nil then
            return default_boxen[suffix][rotation]
        else
            return {}
        end
    end,
}, advtrains.ap.t_30deg_flat)

minetest.register_craft({
	output = 'advtrains:dtrack_placer 50',
	recipe = {
		{'default:steel_ingot', 'group:stick', 'default:steel_ingot'},
		{'default:steel_ingot', 'group:stick', 'default:steel_ingot'},
		{'default:steel_ingot', 'group:stick', 'default:steel_ingot'},
	},
})

local y3_boxen = {
    [""] = {
        selection_box = {
            type = "fixed",
            fixed = {
                {-0.8750, -0.5000, -1.125, 0.8750, -0.3750, 0.4375}
            }
        }
    },

    ["_30"] = {
        selection_box = {
            type = "fixed",
            fixed = {
                {-0.5000, -0.5000, -0.875, 0.5000, -0.3750, 1.000},
                {-0.8750, -0.5000, -0.4375, -0.5000, -0.3750, 0.5625},
                {0.5000, -0.5000, -0.2500, 0.8125, -0.3750, 1.000},
            }
        }
    },

    --UX FIXME: - 3way - have to place straight route before l and r or the 
    --nodebox overlaps too much and can't place the straight track node.
    ["_45"] = {
        selection_box = {
            type = "fixed",
            fixed = {
                {-0.5000, -0.5000, -1.1250, 0.5000, -0.3750, 0.8750},
                {0.5000, -0.5000, -0.5000, 0.8750, -0.3750, 0.5000},
                {-1.1250, -0.5000, -0.9375, -0.5000, -0.3750, 0.5000}
            }
        }
    },

    ["_60"] = {
        selection_box = {
            type = "fixed",
            fixed = {
                --{-0.5000, -0.5000, -0.875, 0.5000, -0.3750, 1.000},
                {-0.875, -0.5000, -0.5, 1.0, -0.3750, 0.5},
                --{-0.8750, -0.5000, -0.4375, -0.5000, -0.3750, 0.5625},
                {-0.4375, -0.5000, -0.8750, 0.5625, -0.3750, -0.5000},
                --{0.5000, -0.5000, -0.2500, 0.8125, -0.3750, 1.000},
                {-0.2500, -0.5000, -0.2500, 1.0000, -0.3750, 0.8125},
            }
        }
    },
}


local function y3_turnouts_addef(def, preset, suffix, rotation)
    return y3_boxen[rotation] or {}
end
-- y-turnout
advtrains.register_tracks("default", {
	nodename_prefix="advtrains:dtrack_sy",
	texture_prefix="advtrains_dtrack_sy",
	models_prefix="advtrains_dtrack_sy",
	models_suffix=".obj",
	shared_texture="advtrains_dtrack_shared.png",
	description=attrans("Y-turnout"),
	formats = {},
    get_additional_definiton = y3_turnouts_addef,
}, advtrains.ap.t_yturnout)
minetest.register_craft({
	output = 'advtrains:dtrack_sy_placer 2',
	recipe = {
		{'advtrains:dtrack_placer', '', 'advtrains:dtrack_placer'},
		{'', 'advtrains:dtrack_placer', ''},
		{'', 'advtrains:dtrack_placer', ''},
	},
})
--3-way turnout
advtrains.register_tracks("default", {
	nodename_prefix="advtrains:dtrack_s3",
	texture_prefix="advtrains_dtrack_s3",
	models_prefix="advtrains_dtrack_s3",
	models_suffix=".obj",
	shared_texture="advtrains_dtrack_shared.png",
	description=attrans("3-way turnout"),
	formats = {},
    get_additional_definiton = y3_turnouts_addef,
}, advtrains.ap.t_s3way)
minetest.register_craft({
	output = 'advtrains:dtrack_s3_placer 1',
	recipe = {
		{'advtrains:dtrack_placer', 'advtrains:dtrack_placer', 'advtrains:dtrack_placer'},
		{'', 'advtrains:dtrack_placer', ''},
		{'', '', ''},
	},
})

-- Diamond Crossings

local perp_boxen = {
    [""] = {}, --default size
    ["_30"] = {
        selection_box = {
            type = "fixed",
            fixed = {
                {-1.000, -0.5000, -1.000, 1.000, -0.3750, 1.000}
            }
        }
    },
    ["_45"] = {
        selection_box = {
            type = "fixed",
            fixed = {
                {-0.8125, -0.5000, -0.8125, 0.8125, -0.3750, 0.8125}
            }
        }
    },
    ["_60"] = {
        selection_box = {
            type = "fixed",
            fixed = {
                {-1.000, -0.5000, -1.000, 1.000, -0.3750, 1.000}
            }
        }
    },
}

-- perpendicular
advtrains.register_tracks("default", {
	nodename_prefix="advtrains:dtrack_xing",
	texture_prefix="advtrains_dtrack_xing",
	models_prefix="advtrains_dtrack_xing",
	models_suffix=".obj",
	shared_texture="advtrains_dtrack_shared.png",
	description=attrans("Perpendicular Diamond Crossing Track"),
	formats = {},
    get_additional_definiton = function(def, preset, suffix, rotation)
        return perp_boxen[rotation] or {}
    end
}, advtrains.ap.t_perpcrossing)

minetest.register_craft({
	output = 'advtrains:dtrack_xing_placer 3',
	recipe = {
		{'', 'advtrains:dtrack_placer', ''},
		{'advtrains:dtrack_placer', 'advtrains:dtrack_placer', 'advtrains:dtrack_placer'},
		{'', 'advtrains:dtrack_placer', ''}
	}
})

local ninety_plus_boxen = {
    ["30l"] = {
        selection_box = {
            type = "fixed",
            fixed = {
                {-0.5000, -0.5000, -1.000, 0.5000, -0.3750, 1.000},
                {-0.8750, -0.5000, -1.000, -0.5000, -0.3750, 0.2500},
                {0.5000, -0.5000, -0.2500, 0.8750, -0.3750, 1.000},
                {-0.1250, -0.5000, -1.375, 0.1875, -0.3750, -1.000}
            }
        }
    },
    ["30r"] = {
        selection_box = {
            type = "fixed",
            fixed = {
                {0.5000, -0.5000, -1.000, -0.5000, -0.3750, 1.000},
                {0.8750, -0.5000, -1.000, 0.5000, -0.3750, 0.2500},
                {-0.5000, -0.5000, -0.2500, -0.8750, -0.3750, 1.000},
                {0.1250, -0.5000, -1.375, -0.1875, -0.3750, -1.000}
            }
        }
    },
    ["45l"] = {
        selection_box = {
            type = "fixed",
            fixed = {
                {-0.5000, -0.5000, -0.8750, 0.5000, -0.3750, 0.8750},
                {0.5000, -0.5000, -0.5000, 0.8750, -0.3750, 0.5000},
                {-0.8750, -0.5000, -0.5000, -0.5000, -0.3750, 0.5000}
            }
        }
    },
    ["45r"] = {
        selection_box = {
            type = "fixed",
            fixed = {
                {-0.5000, -0.5000, -0.8750, 0.5000, -0.3750, 0.8750},
                {0.5000, -0.5000, -0.5000, 0.8750, -0.3750, 0.5000},
                {-0.8750, -0.5000, -0.5000, -0.5000, -0.3750, 0.5000}
            }
        }
    },
    ["60l"] = {
        selection_box = {
            type = "fixed",
            fixed = {
                {-1.000, -0.5000, -0.5000, 1.000, -0.3750, 0.5000},
                {-1.000, -0.5000, -0.8750, 0.2500, -0.3750, -0.5000},
                {-0.2500, -0.5000, 0.5000, 1.000, -0.3750, 0.8750},
                {-1.375, -0.5000, -0.1250, -1.000, -0.3750, 0.1875}
            }
        }
    },
    ["60r"] = {
        selection_box = {
            type = "fixed",
            fixed = {
                {1.000, -0.5000, -0.5000, -1.000, -0.3750, 0.5000},
                {1.000, -0.5000, -0.8750, -0.2500, -0.3750, -0.5000},
                {0.2500, -0.5000, 0.5000, -1.000, -0.3750, 0.8750},
                {1.375, -0.5000, -0.1250, 1.000, -0.3750, 0.1875}
            }
        }
    },
}

-- 90plusx
-- When you face east and param2=0, then this set of rails has a rail at 90
-- degrees to the viewer, plus another rail crossing at 30, 45 or 60 degrees.
advtrains.register_tracks("default", {
	nodename_prefix="advtrains:dtrack_xing90plusx",
	texture_prefix="advtrains_dtrack_xing4590",
	models_prefix="advtrains_dtrack_xing90plusx",
	models_suffix=".obj",
	shared_texture="advtrains_dtrack_shared.png",
	description=attrans("90+Angle Diamond Crossing Track"),
	formats = {},
    get_additional_definiton = function(def, preset, suffix, rotation)
        return ninety_plus_boxen[suffix] or {}
    end,
}, advtrains.ap.t_90plusx_crossing)
minetest.register_craft({
	output = 'advtrains:dtrack_xing90plusx_placer 2',
	recipe = {
		{'advtrains:dtrack_placer', '', ''},
		{'advtrains:dtrack_placer', 'advtrains:dtrack_placer', 'advtrains:dtrack_placer'},
		{'', '', 'advtrains:dtrack_placer'}
	}
})

-- Deprecate any rails using the old name scheme
minetest.register_lbm({
	label = "Upgrade legacy 4590 rails",
	name = "advtrains_train_track:replace_legacy_4590",
	nodenames = {"advtrains:dtrack_xing4590_st"},
	run_at_every_load = true,
	action = function(pos, node)
		minetest.log("actionPos!: " .. pos.x .. "," .. pos.y .. "," .. pos.z)
		minetest.log("node!: " .. node.name .. "," .. node.param1 .. "," .. node.param2)
		advtrains.ndb.swap_node(pos,
		{
			name="advtrains:dtrack_xing90plusx_45l",
			param1=node.param1,
			param2=node.param2,
		})
	end
})
-- This will replace any items left in the inventory
minetest.register_alias("advtrains:dtrack_xing4590_placer", "advtrains:dtrack_xing90plusx_placer")

local diagonal_boxen = {
    ["30r45l"] = {
        selection_box = {
            type = "fixed",
            fixed = {
                {0.5000, -0.5000, -1.000, -0.5000, -0.3750, 1.000},
                {0.8750, -0.5000, -1.000, 0.5000, -0.3750, 0.2500},
                {-0.5000, -0.5000, -0.2500, -0.8750, -0.3750, 1.000},
                {0.1250, -0.5000, -1.375, -0.1875, -0.3750, -1.000}
            }
        }
    },
    ["60l30l"] = {
        selection_box = {
            type = "fixed",
            fixed = {
                {-1.000, -0.5000, -0.5000, 1.000, -0.3750, 0.5000},
                {-1.000, -0.5000, -0.8750, 0.2500, -0.3750, -0.5000},
                {-0.2500, -0.5000, 0.5000, 1.000, -0.3750, 0.8750},
                {-1.375, -0.5000, -0.1250, -1.000, -0.3750, 0.1875}
            }
        }
    },
    ["60l60r"] = {
        selection_box = {
            type = "fixed",
            fixed = {
                {-1.000, -0.5000, -1.000, 1.000, -0.3750, 1.000}
            }
        }
    },
    ["60r30r"] = {
        selection_box = {
            type = "fixed",
            fixed = {
                {1.000, -0.5000, -0.5000, -1.000, -0.3750, 0.5000},
                {1.000, -0.5000, -0.8750, -0.2500, -0.3750, -0.5000},
                {0.2500, -0.5000, 0.5000, -1.000, -0.3750, 0.8750},
                {1.375, -0.5000, -0.1250, 1.000, -0.3750, 0.1875}
            }
        }
    },
    ["30l45r"] = {
        selection_box = {
            type = "fixed",
            fixed = {
                {-0.5000, -0.5000, -1.000, 0.5000, -0.3750, 1.000},
                {-0.8750, -0.5000, -1.000, -0.5000, -0.3750, 0.2500},
                {0.5000, -0.5000, -0.2500, 0.8750, -0.3750, 1.000},
                {-0.1250, -0.5000, -1.375, 0.1875, -0.3750, -1.000}
            }
        }
    },
    ["60l45r"] = {
        selection_box = {
            type = "fixed",
            fixed = {
                {-1.000, -0.5000, -0.5000, 1.000, -0.3750, 0.5000},
                {-1.000, -0.5000, -0.8750, 0.2500, -0.3750, -0.5000},
                {-0.2500, -0.5000, 0.5000, 1.000, -0.3750, 0.8750},
                {-1.375, -0.5000, -0.1250, -1.000, -0.3750, 0.1875}
            }
        }
    },
    ["60r45l"] = {
        selection_box = {
            type = "fixed",
            fixed = {
                {1.000, -0.5000, -0.5000, -1.000, -0.3750, 0.5000},
                {1.000, -0.5000, -0.8750, -0.2500, -0.3750, -0.5000},
                {0.2500, -0.5000, 0.5000, -1.000, -0.3750, 0.8750},
                {1.375, -0.5000, -0.1250, 1.000, -0.3750, 0.1875}
            }
        }
    },
}

-- Diagonal
-- This set of rail crossings is named based on the angle of each intersecting
-- direction when facing east and param2=0. Rails with l/r swapped are mirror
-- images. For example, 30r45l is the mirror image of 30l45r.
advtrains.register_tracks("default", {
	nodename_prefix="advtrains:dtrack_xingdiag",
	texture_prefix="advtrains_dtrack_xingdiag",
	models_prefix="advtrains_dtrack_xingdiag",
	models_suffix=".obj",
	shared_texture="advtrains_dtrack_shared.png",
	description=attrans("Diagonal Diamond Crossing Track"),
	formats = {},
    get_additional_definiton = function(def, preset, suffix, rotation)
        return diagonal_boxen[suffix] or {}
    end,
}, advtrains.ap.t_diagonalcrossing)
minetest.register_craft({
	output = 'advtrains:dtrack_xingdiag_placer 2',
	recipe = {
		{'advtrains:dtrack_placer', '', 'advtrains:dtrack_placer'},
		{'', 'advtrains:dtrack_placer', ''},
		{'advtrains:dtrack_placer', '', 'advtrains:dtrack_placer'}
	}
})
---- Not included: very shallow crossings like (30/60)+45.
---- At an angle of only 18.4 degrees, the models would not
---- translate well to a block game.
-- END crossings

--slopes
advtrains.register_tracks("default", {
	nodename_prefix="advtrains:dtrack",
	texture_prefix="advtrains_dtrack",
	models_prefix="advtrains_dtrack",
	models_suffix=".obj",
	shared_texture="advtrains_dtrack_shared.png",
	second_texture="default_gravel.png",
	description=attrans("Track"),
	formats={vst1={true, false, true}, vst2={true, false, true}, vst31={true}, vst32={true}, vst33={true}},
}, advtrains.ap.t_30deg_slope)

minetest.register_craft({
	type = "shapeless",
	output = 'advtrains:dtrack_slopeplacer 2',
	recipe = {
		"advtrains:dtrack_placer",
		"advtrains:dtrack_placer",
		"default:gravel",
	},
})


--bumpers
advtrains.register_tracks("default", {
	nodename_prefix="advtrains:dtrack_bumper",
	texture_prefix="advtrains_dtrack_bumper",
	models_prefix="advtrains_dtrack_bumper",
	models_suffix=".b3d",
	shared_texture="advtrains_dtrack_rail.png",
	--bumpers still use the old texture until the models are redone.
	description=attrans("Bumper"),
	formats={},
	get_additional_definiton = function(def, preset, suffix, rotation)
		-- 2024-11-25: Bumpers get the additional feature of being both a signal and a self-contained TCB, when interlocking is used.
		if advtrains.interlocking then
			return {
				-- use the special callbacks for self_tcb (see tcb_ts_ui.lua)
				can_dig = advtrains.interlocking.self_tcb_make_can_dig_callback(true),
				after_dig_node = advtrains.interlocking.self_tcb_make_after_dig_callback(true),
				after_place_node = advtrains.interlocking.self_tcb_make_after_place_callback(true, true),
				on_rightclick = advtrains.interlocking.self_tcb_make_on_rightclick_callback(false, true),
				advtrains = {
					main_aspects = {
						-- No main aspects, it always shows Stop.
						-- But we need to define the table so that signal caplevel is 3
					},
					apply_aspect = function(pos, node, main_aspect, rem_aspect, rem_aspinfo)
						-- is a no-op for bumpers, it always shows Stop
					end,
					get_aspect_info = function(pos, main_aspect)
						-- it always shows Stop
						return advtrains.interlocking.signal.ASPI_HALT
					end,
					distant_support = false, -- not a distant
					route_role = "end", -- the end is nigh!
				}
			}
		else
			return {} -- no additional defs when interlocking is not used
		end
	end,
}, advtrains.ap.t_30deg_straightonly)
minetest.register_craft({
	output = 'advtrains:dtrack_bumper_placer 2',
	recipe = {
		{'group:wood', 'dye:red'},
		{'default:steel_ingot', 'default:steel_ingot'},
		{'advtrains:dtrack_placer', 'advtrains:dtrack_placer'},
	},
})
--legacy bumpers
for _,rot in ipairs({"", "_30", "_45", "_60"}) do
	minetest.register_alias("advtrains:dtrack_bumper"..rot, "advtrains:dtrack_bumper_st"..rot)
end
-- atc track
advtrains.register_tracks("default", {
	nodename_prefix="advtrains:dtrack_atc",
	texture_prefix="advtrains_dtrack_atc",
	models_prefix="advtrains_dtrack",
	models_suffix=".b3d",
	shared_texture="advtrains_dtrack_shared_atc.png",
	description=attrans("ATC controller"),
	formats={},
	get_additional_definiton = advtrains.atc_function
}, advtrains.trackpresets.t_30deg_straightonly)


-- Tracks for loading and unloading trains
-- Copyright (C) 2017 Gabriel Pérez-Cerezo <gabriel@gpcf.eu>

local function get_far_node(pos)
	local node = minetest.get_node(pos)
	if node.name == "ignore" then
		minetest.get_voxel_manip():read_from_map(pos, pos)
		node = minetest.get_node(pos)
	end
	return node
end


local function show_fc_formspec(pos,player)
	local pname = player:get_player_name()
	if minetest.is_protected(pos,pname) then
		minetest.chat_send_player(pname, "Position is protected!")
		return
	end
	
	local meta = minetest.get_meta(pos)
	local fc = meta:get_string("fc") or ""
	
	local form = 'formspec_version[4]'..
		'size[10,5]'..
		'label[0.5,0.4;Advtrains Loading/Unloading Track]'..
		'label[0.5,1.1;Set the code to match against the wagon\'s freight code]'..
		'label[0.5,1.6;A blank field matches all wagons (default)]'..
		'label[0.5,2.1;Use code # to disable the track section]'..
		'field[0.5,3;5.5,1;fc;FC;'..minetest.formspec_escape(fc)..']'..
		'button[6.5,3;3,1;save;Submit]'
	minetest.show_formspec(pname, "at_load_unload_"..advtrains.encode_pos(pos), form)
end

minetest.register_on_player_receive_fields(function(player, formname, fields)
	local pname = player:get_player_name()
	local pe = string.match(formname, "^at_load_unload_(............)$")
	local pos = advtrains.decode_pos(pe)
	if pos then
		if minetest.is_protected(pos, pname) then
			minetest.chat_send_player(pname, "Position is protected!")
			return
		end
		
		if fields.save then
			minetest.get_meta(pos):set_string("fc",tostring(fields.fc))
			minetest.chat_send_player(pname,"Freight code set: "..tostring(fields.fc))
			show_fc_formspec(pos,player)
		end
	end
end)

local function load_wagon(wagon_id, node_inv, node_fc, unload)
	local inv_modified = false
	local w_inv=minetest.get_inventory({type="detached", name="advtrains_wgn_"..wagon_id})
	if w_inv and w_inv:get_list("box") then
	
		local wagon_data = advtrains.wagons[wagon_id]
		local wagon_fc
		if wagon_data.fc then
			if not wagon_data.fcind then wagon_data.fcind = 1 end
			wagon_fc = tostring(wagon_data.fc[wagon_data.fcind]) or ""
		end
		
		if node_fc == "" or wagon_fc == node_fc then
			if not unload then
				for _, item in ipairs(node_inv:get_list("main")) do
					if w_inv:get_list("box") and w_inv:room_for_item("box", item)  then
						w_inv:add_item("box", item)
						node_inv:remove_item("main", item)
						if item.name ~= "" then inv_modified = true end
					end
				end
			else
				for _, item in ipairs(w_inv:get_list("box")) do
					if node_inv:get_list("main") and node_inv:room_for_item("main", item)  then
						w_inv:remove_item("box", item)
						node_inv:add_item("main", item)
						if item.name ~= "" then inv_modified = true end
					end
				end
			end
		end
	end
	return inv_modified
end

local function load_entire_train(pos, train_id, unload) -- flood load when not in an active area
	if advtrains.is_node_loaded(pos) then -- leave the loading to the nodetimer if area is loaded
		return 
	end
	local train=advtrains.trains[train_id]
	local below = get_far_node({x=pos.x, y=pos.y-1, z=pos.z})
	if not string.match(below.name, "chest") then
		atprint("this is not a chest! at "..minetest.pos_to_string(pos))
		return
	end
	
	local node_fc = minetest.get_meta(pos):get_string("fc") or ""
	if node_fc == "#" then
		--track section is disabled
		return
	end
	local node_inv = minetest.get_inventory({type="node", pos={x=pos.x, y=pos.y-1, z=pos.z}})
	if node_inv and train.velocity <= 2 then
		for _, wagon_id in ipairs(train.trainparts) do
			load_wagon(wagon_id, node_inv, node_fc, unload)
		end
	end
end

local function load_wagon_on_timer(pos, unload) -- loading ramp when in an active area
	if not advtrains.is_node_loaded(pos) then -- leave the loading for the flood load function. we're out of area
		return true -- reset the nodetimer until the node is loaded again
	end
	local tid, tidx = advtrains.get_train_at_pos(pos)
	if not tid or tid == "" then
		return true
	end -- no train to load.

	local train = advtrains.trains[tid]
	local below = get_far_node({x=pos.x, y=pos.y-1, z=pos.z})
	if not string.match(below.name, "chest") then
		atprint("this is not a chest! at "..minetest.pos_to_string(pos))
		return true
	end
	local node_fc = minetest.get_meta(pos):get_string("fc") or ""
	if node_fc == "#" then
		--track section is disabled
		return true
	end
	local node_inv = minetest.get_inventory({type="node", pos={x=pos.x, y=pos.y-1, z=pos.z}})
	if node_inv and train.velocity <= 2 then
		local _, wagon_id, wagon_data = advtrains.get_wagon_at_index(tid, tidx)
		if wagon_id then
			local inv_modified = load_wagon(wagon_id, node_inv, node_fc, unload)
			if inv_modified then
				if advtrains.wagon_prototypes[advtrains.get_wagon_prototype(wagon_data)].set_textures then
					local wagon_object = advtrains.wagon_objects[wagon_id]
					if wagon_object and wagon_data then
						local ent = wagon_object:get_luaentity()
						if ent and ent.set_textures then
							ent:set_textures(wagon_data)
						end
					end
				end
			end
		end
	end
	return true
end

local nodetimer_interval = minetest.settings:get("advtrains_loading_track_timer") or 1
local function start_nodetimer(pos)
	local timer = minetest.get_node_timer(pos)
	timer:start(nodetimer_interval)
end

advtrains.register_tracks("default", {
	nodename_prefix="advtrains:dtrack_unload",
	texture_prefix="advtrains_dtrack_unload",
	models_prefix="advtrains_dtrack",
	models_suffix=".b3d",
	shared_texture="advtrains_dtrack_shared_unload.png",
	description=attrans("Unloading Track"),
	formats={},
	get_additional_definiton = function(def, preset, suffix, rotation)
		return {
			after_dig_node=function(pos)
				advtrains.invalidate_all_paths()
				advtrains.ndb.clear(pos)
			end,
			on_rightclick = function(pos, node, player)
				show_fc_formspec(pos, player)
			end,
			after_place_node = function(pos)
				advtrains.ndb.update(pos)
				start_nodetimer(pos)
			end,
			on_timer = function(pos)
				return load_wagon_on_timer(pos, true)
			end,
			advtrains = {
				on_train_enter = function(pos, train_id)
					load_entire_train(pos, train_id, true)
				end,
			},
		}
	end
				     }, advtrains.trackpresets.t_30deg_straightonly)
advtrains.register_tracks("default", {
	nodename_prefix="advtrains:dtrack_load",
	texture_prefix="advtrains_dtrack_load",
	models_prefix="advtrains_dtrack",
	models_suffix=".b3d",
	shared_texture="advtrains_dtrack_shared_load.png",
	description=attrans("Loading Track"),
	formats={},
	get_additional_definiton = function(def, preset, suffix, rotation)
		return {
			after_dig_node=function(pos)
				advtrains.invalidate_all_paths()
				advtrains.ndb.clear(pos)
			end,
			on_rightclick = function(pos, node, player)
				show_fc_formspec(pos, player)
			end,
			after_place_node = function(pos)
				advtrains.ndb.update(pos)
				start_nodetimer(pos)
			end,
			on_timer = function(pos)
				return load_wagon_on_timer(pos, false)
			end,
			advtrains = {
				on_train_enter = function(pos, train_id)
					load_entire_train(pos, train_id, false)
				end,
			},
		}
	end
				     }, advtrains.trackpresets.t_30deg_straightonly)

-- mod-dependent crafts
local loader_core = "default:mese_crystal"  --fallback
if minetest.get_modpath("basic_materials") then
	loader_core = "basic_materials:ic"
elseif minetest.get_modpath("technic") then
	loader_core = "technic:control_logic_unit"
end

minetest.register_craft({
	type="shapeless",
	output = 'advtrains:dtrack_load_placer',
	recipe = {
		"advtrains:dtrack_placer",
		loader_core,
		"default:chest"
	},
})
loader_core = nil --nil the crafting variable

--craft between load/unload tracks
minetest.register_craft({
	type="shapeless",
	output = 'advtrains:dtrack_unload_placer',
	recipe = {
		"advtrains:dtrack_load_placer",
	},
})
minetest.register_craft({
	type="shapeless",
	output = 'advtrains:dtrack_load_placer',
	recipe = {
		"advtrains:dtrack_unload_placer",
	},
})


if mesecon then
	advtrains.register_tracks("default", {
		nodename_prefix="advtrains:dtrack_detector_off",
		texture_prefix="advtrains_dtrack_detector",
		models_prefix="advtrains_dtrack",
		models_suffix=".b3d",
		shared_texture="advtrains_dtrack_shared_detector_off.png",
		description=attrans("Detector Rail"),
		formats={},
		get_additional_definiton = function(def, preset, suffix, rotation)
			return {
				mesecons = {
					receptor = {
						state = mesecon.state.off,
						rules = advtrains.meseconrules
					}
				},
				advtrains = {
					on_updated_from_nodedb = function(pos, node)
						mesecon.receptor_off(pos, advtrains.meseconrules)
					end,
					on_train_enter=function(pos, train_id)
						advtrains.ndb.swap_node(pos, {name="advtrains:dtrack_detector_on".."_"..suffix..rotation, param2=advtrains.ndb.get_node(pos).param2})
						if advtrains.is_node_loaded(pos) then
							mesecon.receptor_on(pos, advtrains.meseconrules)
						end
					end
				}
			}
		end
	}, advtrains.ap.t_30deg_straightonly)
	advtrains.register_tracks("default", {
		nodename_prefix="advtrains:dtrack_detector_on",
		texture_prefix="advtrains_dtrack",
		models_prefix="advtrains_dtrack",
		models_suffix=".b3d",
		shared_texture="advtrains_dtrack_shared_detector_on.png",
		description="Detector(on)(you hacker you)",
		formats={},
		get_additional_definiton = function(def, preset, suffix, rotation)
			return {
				mesecons = {
					receptor = {
						state = mesecon.state.on,
						rules = advtrains.meseconrules
					}
				},
				advtrains = {
					on_updated_from_nodedb = function(pos, node)
						mesecon.receptor_on(pos, advtrains.meseconrules)
					end,
					on_train_leave=function(pos, train_id)
						advtrains.ndb.swap_node(pos, {name="advtrains:dtrack_detector_off".."_"..suffix..rotation, param2=advtrains.ndb.get_node(pos).param2})
						if advtrains.is_node_loaded(pos) then
							mesecon.receptor_off(pos, advtrains.meseconrules)
						end
					end
				}
			}
		end
	}, advtrains.ap.t_30deg_straightonly_noplacer)
minetest.register_craft({
	type="shapeless",
	output = 'advtrains:dtrack_detector_off_placer',
	recipe = {
		"advtrains:dtrack_placer",
		"mesecons:wire_00000000_off"
	},
})
end
--TODO legacy
--I know lbms are better for this purpose
for name,rep in pairs({swl_st="swlst", swr_st="swrst", swl_cr="swlcr", swr_cr="swrcr", }) do
	minetest.register_abm({
    --  In the following two fields, also group:groupname will work.
        nodenames = {"advtrains:track_"..name},
       interval = 1.0, -- Operation interval in seconds
       chance = 1, -- Chance of trigger per-node per-interval is 1.0 / this
       action = function(pos, node, active_object_count, active_object_count_wider) minetest.set_node(pos, {name="advtrains:track_"..rep, param2=node.param2}) end,
    })
    minetest.register_abm({
    --  In the following two fields, also group:groupname will work.
        nodenames = {"advtrains:track_"..name.."_45"},
       interval = 1.0, -- Operation interval in seconds
       chance = 1, -- Chance of trigger per-node per-interval is 1.0 / this
       action = function(pos, node, active_object_count, active_object_count_wider) minetest.set_node(pos, {name="advtrains:track_"..rep.."_45", param2=node.param2}) end,
    })
end

if advtrains.register_replacement_lbms then
minetest.register_lbm({
	name = "advtrains:ramp_replacement_1",
--  In the following two fields, also group:groupname will work.
	nodenames = {"advtrains:track_vert1"},
	action = function(pos, node, active_object_count, active_object_count_wider) minetest.set_node(pos, {name="advtrains:dtrack_vst1", param2=(node.param2+2)%4}) end,
})
minetest.register_lbm({
	name = "advtrains:ramp_replacement_1",
--  --  In the following two fields, also group:groupname will work.
	nodenames = {"advtrains:track_vert2"},
	action = function(pos, node, active_object_count, active_object_count_wider) minetest.set_node(pos, {name="advtrains:dtrack_vst2", param2=(node.param2+2)%4}) end,
})
	minetest.register_abm({
		name = "advtrains:st_rep_1",
	--  In the following two fields, also group:groupname will work.
		nodenames = {"advtrains:track_st"},
		interval=1,
		chance=1,
		action = function(pos, node, active_object_count, active_object_count_wider) minetest.set_node(pos, {name="advtrains:dtrack_st", param2=node.param2}) end,
	})
	minetest.register_lbm({
		name = "advtrains:st_rep_1",
	--  --  In the following two fields, also group:groupname will work.
		nodenames = {"advtrains:track_st_45"},
		action = function(pos, node, active_object_count, active_object_count_wider) minetest.set_node(pos, {name="advtrains:dtrack_st_45", param2=node.param2}) end,
	})
end