aboutsummaryrefslogtreecommitdiff
path: root/advtrains/advtrains_train_japan/init.lua
blob: 8816db36d1b6554ad1708db9874897991e30fa51 (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
local S
if minetest.get_modpath("intllib") then
    S = intllib.Getter()
else
    S = function(s,a,...)a={a,...}return s:gsub("@(%d+)",function(n)return a[tonumber(n)]end)end
end

advtrains.register_wagon("engine_japan", {
	mesh="advtrains_engine_japan.b3d",
	textures = {"advtrains_engine_japan.png"},
	drives_on={default=true},
	max_speed=20,
	seats = {
		{
			name=S("Driver stand"),
			attach_offset={x=0, y=8, z=13},
			view_offset={x=0, y=0, z=0},
			driving_ctrl_access=true,
			group="dstand",
		},
		{
			name="1",
			attach_offset={x=-4, y=8, z=0},
			view_offset={x=0, y=0, z=0},
			group="pass",
		},
		{
			name="2",
			attach_offset={x=4, y=8, z=0},
			view_offset={x=0, y=0, z=0},
			group="pass",
		},
		{
			name="3",
			attach_offset={x=-4, y=8, z=-8},
			view_offset={x=0, y=0, z=0},
			group="pass",
		},
		{
			name="4",
			attach_offset={x=4, y=8, z=-8},
			view_offset={x=0, y=0, z=0},
			group="pass",
		},
	},
	seat_groups = {
		dstand={
			name = "Driver Stand",
			access_to = {"pass"},
			require_doors_open=true,
		},
		pass={
			name = "Passenger area",
			access_to = {"dstand"},
			require_doors_open=true,
		},
	},
	assign_to_seat_group = {"dstand", "pass"},
	doors={
		open={
			[-1]={frames={x=0, y=20}, time=1},
			[1]={frames={x=40, y=60}, time=1}
		},
		close={
			[-1]={frames={x=20, y=40}, time=1},
			[1]={frames={x=60, y=80}, time=1}
		}
	},
	door_entry={-1},
	visual_size = {x=1, y=1},
	wagon_span=2.5,
	is_locomotive=true,
	collisionbox = {-1.0,-0.5,-1.0, 1.0,2.5,1.0},
	drops={"default:steelblock 4"},
}, S("Japanese Train Engine"), "advtrains_engine_japan_inv.png")

advtrains.register_wagon("wagon_japan", {
	mesh="advtrains_wagon_japan.b3d",
	textures = {"advtrains_wagon_japan.png"},
	drives_on={default=true},
	max_speed=20,
	seats = {
		{
			name="1",
			attach_offset={x=-4, y=8, z=8},
			view_offset={x=0, y=0, z=0},
			group="pass",
		},
		{
			name="2",
			attach_offset={x=4, y=8, z=8},
			view_offset={x=0, y=0, z=0},
			group="pass",
		},
		{
			name="1a",
			attach_offset={x=-4, y=8, z=0},
			view_offset={x=0, y=0, z=0},
			group="pass",
		},
		{
			name="2a",
			attach_offset={x=4, y=8, z=0},
			view_offset={x=0, y=0, z=0},
			group="pass",
		},
		{
			name="3",
			attach_offset={x=-4, y=8, z=-8},
			view_offset={x=0, y=0, z=0},
			group="pass",
		},
		{
			name="4",
			attach_offset={x=4, y=8, z=-8},
			view_offset={x=0, y=0, z=0},
			group="pass",
		},
	},
	seat_groups = {
		pass={
			name = "Passenger area",
			access_to = {},
			require_doors_open=true,
		},
	},
	assign_to_seat_group = {"pass"},
	doors={
		open={
			[-1]={frames={x=0, y=20}, time=1},
			[1]={frames={x=40, y=60}, time=1}
		},
		close={
			[-1]={frames={x=20, y=40}, time=1},
			[1]={frames={x=60, y=80}, time=1}
		}
	},
	door_entry={-1, 1},
	visual_size = {x=1, y=1},
	wagon_span=2.3,
	collisionbox = {-1.0,-0.5,-1.0, 1.0,2.5,1.0},
	drops={"default:steelblock 4"},
}, S("Japanese Train Wagon"), "advtrains_wagon_japan_inv.png")

"hl opt">] = pts end else if not try then atwarn("Encountered route lock misconfiguration (no passive component) while a real run of routesetting routine, at position",pts,"while setting route",rtename,"of",signal) end return false, "No passive component at "..pts..". Please reconfigure route!" end end -- reserve ts and write locks if not try then local nvar = c_rseg.next if not route[i+1] then -- We shouldn't use the "next" value of the final route segment, because this can lead to accidental route-cancelling of already set routes from another signal. nvar = nil end c_ts.route = { origin = signal, entry = c_sigd, rsn = "Route '"..rtename.."' from signal '"..signalname.."', segment #"..i, first = first, } c_ts.route_post = { locks = c_lckp, next = nvar, } if c_tcbs.signal then c_tcbs.route_committed = true c_tcbs.aspect = route.aspect or asp_generic_free c_tcbs.route_origin = signal advtrains.interlocking.update_signal_aspect(c_tcbs) end end -- advance first = nil c_sigd = c_rseg.next i = i + 1 end return true end -- Checks whether there is a route lock that prohibits setting the component -- to the wanted state. returns string with reasons on conflict function ilrs.has_route_lock(pts) -- look this up local e = ilrs.rte_locks[pts] if not e then return nil elseif #e==0 then ilrs.rte_locks[pts] = nil return nil end local txts = {} for _, ent in ipairs(e) do txts[#txts+1] = ent.rsn end return table.concat(txts, "\n") end -- adds route lock for position function ilrs.add_route_lock(pts, ts, rsn, origin) ilrs.free_route_locks_indiv(pts, ts, true) local elm = {by=ts, rsn=rsn, origin=origin} if not ilrs.rte_locks[pts] then ilrs.rte_locks[pts] = { elm } else table.insert(ilrs.rte_locks[pts], elm) end end -- adds route lock for position function ilrs.add_manual_route_lock(pts, rsn) local elm = {rsn=rsn} if not ilrs.rte_locks[pts] then ilrs.rte_locks[pts] = { elm } else table.insert(ilrs.rte_locks[pts], elm) end end -- frees route locking for all points (components) that were set by this ts function ilrs.free_route_locks(ts, lcks, nocallbacks) for _,pts in pairs(lcks) do ilrs.free_route_locks_indiv(pts, ts, nocallbacks) end end function ilrs.free_route_locks_indiv(pts, ts, nocallbacks) local e = ilrs.rte_locks[pts] if not e then return nil elseif #e==0 then ilrs.rte_locks[pts] = nil return nil end local i = 1 while i <= #e do if e[i].by == ts then --atdebug("free_route_locks_indiv",pts,"clearing entry",e[i].by,e[i].rsn) table.remove(e,i) else i = i + 1 end end -- This must be delayed, because this code is executed in-between a train step -- TODO use luaautomation timers? if not nocallbacks then minetest.after(0, ilrs.update_waiting, "lck", pts) minetest.after(0.5, advtrains.set_fallback_state, minetest.string_to_pos(pts)) end end -- frees all route locks, even manual ones set with the tool, at a specific position function ilrs.remove_route_locks(pts, nocallbacks) ilrs.rte_locks[pts] = nil -- This must be delayed, because this code is executed in-between a train step -- TODO use luaautomation timers? if not nocallbacks then minetest.after(0, ilrs.update_waiting, "lck", pts) end end -- starting from the designated sigd, clears all subsequent route and route_post -- information from the track sections. -- note that this does not clear the routesetting status from the entry signal, -- only from the ts's function ilrs.cancel_route_from(sigd) -- we start at the tc designated by signal local c_sigd = sigd local c_tcbs, c_ts_id, c_ts, c_rseg, c_lckp while c_sigd do --atdebug("cancel_route_from: at sigd",c_sigd) c_tcbs = ildb.get_tcbs(c_sigd) if not c_tcbs then atwarn("Failed to cancel route, no TCBS at",c_sigd) return false end --atdebug("cancelling",c_ts.route.rsn) -- clear signal aspect and routesetting state c_tcbs.route_committed = nil c_tcbs.aspect = nil c_tcbs.routeset = nil c_tcbs.route_auto = nil c_tcbs.route_origin = nil advtrains.interlocking.update_signal_aspect(c_tcbs) c_ts_id = c_tcbs.ts_id if not c_tcbs then atwarn("Failed to cancel route, end of interlocking at",c_sigd) return false end c_ts = ildb.get_ts(c_ts_id) if not c_ts or not c_ts.route or not sigd_equal(c_ts.route.entry, c_sigd) then --atdebug("cancel_route_from: abort (eoi/no route):") return false end c_ts.route = nil if c_ts.route_post then advtrains.interlocking.route.free_route_locks(c_ts_id, c_ts.route_post.locks) c_sigd = c_ts.route_post.next else c_sigd = nil end c_ts.route_post = nil minetest.after(0, advtrains.interlocking.route.update_waiting, "ts", c_ts_id) end --atdebug("cancel_route_from: done (no final sigd)") return true end -- TCBS Routesetting helper: generic update function for -- route setting -- Call this function to set and cancel routes! -- sigd, tcbs: self-explanatory -- newrte: If a new route should be set, the route index of it (in tcbs.routes). nil otherwise -- cancel: true in combination with newrte=nil causes cancellation of the current route. function ilrs.update_route(sigd, tcbs, newrte, cancel) --atdebug("Update_Route for",sigd,tcbs.signal_name) local has_changed_aspect = false if tcbs.route_origin and not sigd_equal(tcbs.route_origin, sigd) then --atdebug("Signal not in control, held by",tcbs.signal_name) return end if (newrte and tcbs.routeset and tcbs.routeset ~= newrte) or cancel then if tcbs.route_committed then --atdebug("Cancelling:",tcbs.routeset) advtrains.interlocking.route.cancel_route_from(sigd) end tcbs.route_committed = nil tcbs.aspect = nil has_changed_aspect = true tcbs.routeset = nil tcbs.route_auto = nil tcbs.route_rsn = nil end if newrte or tcbs.routeset then if tcbs.route_committed then return end if newrte then tcbs.routeset = newrte end --atdebug("Setting:",tcbs.routeset) local succ, rsn, cbts, cblk = ilrs.set_route(sigd, tcbs.routes[tcbs.routeset]) if not succ then tcbs.route_rsn = rsn --atdebug("Routesetting failed:",rsn) -- add cbts or cblk to callback table if cbts then --atdebug("cbts =",cbts) if not ilrs.rte_callbacks.ts[cbts] then ilrs.rte_callbacks.ts[cbts]={} end advtrains.insert_once(ilrs.rte_callbacks.ts[cbts], sigd, sigd_equal) end if cblk then --atdebug("cblk =",cblk) if not ilrs.rte_callbacks.lck[cblk] then ilrs.rte_callbacks.lck[cblk]={} end advtrains.insert_once(ilrs.rte_callbacks.lck[cblk], sigd, sigd_equal) end else --atdebug("Committed Route:",tcbs.routeset) has_changed_aspect = true end end if has_changed_aspect then -- FIX: prevent an minetest.after() loop caused by update_signal_aspect dispatching path invalidation, which in turn calls ARS again advtrains.interlocking.update_signal_aspect(tcbs) end advtrains.interlocking.update_player_forms(sigd) end -- Try to re-set routes that conflicted with this point -- sys can be one of "ts" and "lck" -- key is then ts_id or pts respectively function ilrs.update_waiting(sys, key) --atdebug("update_waiting:",sys,".",key) local t = ilrs.rte_callbacks[sys][key] ilrs.rte_callbacks[sys][key] = nil if t then for _,sigd in ipairs(t) do --atdebug("Updating", sigd) -- While these are run, the table we cleared before may be populated again, which is in our interest. -- (that's the reason we needed to copy it) local tcbs = ildb.get_tcbs(sigd) if tcbs then ilrs.update_route(sigd, tcbs) end end end end advtrains.interlocking.route = ilrs