aboutsummaryrefslogtreecommitdiff
path: root/assets/lyx_img
Commit message (Expand)AuthorAge
* Update interlocking manualorwell962019-01-15
* Update manual againorwell962018-10-15
* Add interlocking guide/manual, silence debug outputsorwell962018-09-14
19'>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
-- atc_rail.lua
-- registers and handles the ATC rail. Active component.
-- This is the only component that can interface with trains, so train interface goes here too.

--Using subtable
local r={}

-- Note on appr_internal:
-- The Approach callback is a special corner case: the train is not on the node, and it is executed synchronized 
-- (in the train step right during LZB traversal). We therefore need access to the train id and the lzbdata table
function r.fire_event(pos, evtdata, appr_internal)
	
	local ph=minetest.pos_to_string(pos)
	local railtbl = atlatc.active.nodes[ph]
	
	if not railtbl then
		atwarn("LuaAutomation ATC interface rail at",ph,": Data not in memory! Please visit position and click 'Save'!")
		return
	end
	
	
	local arrowconn = railtbl.arrowconn
	if not arrowconn then
		atwarn("LuaAutomation ATC interface rail at",ph,": Incomplete Data! Please visit position and click 'Save'!")
		return
	end
	
	--prepare ingame API for ATC. Regenerate each time since pos needs to be known
	--If no train, then return false.
	local train_id=advtrains.get_train_at_pos(pos)
	local train, atc_arrow, tvel
	if train_id then train=advtrains.trains[train_id] end
	
	if not train and appr_internal then
		-- also use the train when called as an approach callback
		train_id = appr_internal.train_id
		train = appr_internal.train
	end
	
	if train then 
		if not train.path then
			--we happened to get in between an invalidation step
			--delay
			atlatc.interrupt.add(0,pos,evtdata)
			return
		end
		local index = advtrains.path_lookup(train, pos)
				
		local iconnid = 1
		if index then
			iconnid = train.path_cn[index]
		else
			atwarn("ATC rail at", pos, ": Rail not on train's path! Can't determine arrow direction. Assuming +!")
		end
		atc_arrow = iconnid == 1
		
		tvel=train.velocity
	end
	local customfct={
		atc_send = function(cmd)
			if not train_id then return false end
			assertt(cmd, "string")
			advtrains.atc.train_set_command(train, cmd, atc_arrow)
			return true
		end,
		split_at_index = function(index, cmd)
			if not train_id then return false end
			assertt(cmd, "string")
			if type(index) ~= "number" then
				return false
			end
			local new_id = advtrains.split_train_at_index(train, index)
			if new_id then
				minetest.after(1,advtrains.atc.train_set_command,advtrains.trains[new_id], cmd, atc_arrow)
				return true
			end
			return false
		end,
		split_at_fc = function(cmd, len)
			assertt(cmd, "string")
			if not train_id then return false end
			local new_id, fc = advtrains.split_train_at_fc(train, false, len)
			if new_id then
				minetest.after(1,advtrains.atc.train_set_command,advtrains.trains[new_id], cmd, atc_arrow)
			end
			return fc or ""
		end,
		split_off_locomotive = function(cmd, len)
			assertt(cmd, "string")
			if not train_id then return false end
			local new_id, fc = advtrains.split_train_at_fc(train, true, len)
			if new_id then
				minetest.after(1,advtrains.atc.train_set_command,advtrains.trains[new_id], cmd, atc_arrow)
			end						
		end,
		train_length = function ()
			if not train_id then return false end
			return #train.trainparts
		end,
		step_fc = function()
			if not train_id then return false end
			advtrains.train_step_fc(train)
		end,
		set_shunt = function()
			-- enable shunting mode
			if not train_id then return false end
			train.is_shunt = true
		end,
		set_line = function(line)
			if type(line)~="string" and type(line)~="number" then
				return false
			end
			train.line = line .. ""
			minetest.after(0, advtrains.invalidate_path, train_id)
			return true
		end,
		get_line = function()
			return train.line
		end,
		set_rc = function(rc)
			if type(rc)~="string"then
				return false
			end
			train.routingcode = rc
			minetest.after(0, advtrains.invalidate_path, train_id)
			return true
		end,
		get_rc = function()
			return train.routingcode
		end,
		atc_reset = function(cmd)
			if not train_id then return false end
			assertt(cmd, "string")
			advtrains.atc.train_reset_command(train)
			return true
		end,
		atc_arrow = atc_arrow,
		atc_id = train_id,
		atc_speed = tvel,
		atc_set_text_outside = function(text)
			if not train_id then return false end
			if text then assertt(text, "string") end
			advtrains.trains[train_id].text_outside=text
			return true
		end,
		atc_set_text_inside = function(text)
			if not train_id then return false end
			if text then assertt(text, "string") end
			advtrains.trains[train_id].text_inside=text
			return true
		end,
		atc_set_lzb_tsr = function(speed)
			if not appr_internal then
				error("atc_set_lzb_tsr() can only be used during 'approach' events!")
			end
			assert(tonumber(speed), "Number expected!")
			
			local index = appr_internal.index
			advtrains.lzb_add_checkpoint(train, index, speed, nil)
			
			return true
		end,
	}
	-- interlocking specific
	if advtrains.interlocking then
		customfct.atc_set_ars_disable = function(value)
			advtrains.interlocking.ars_set_disable(train, value)
		end
	end
	
	atlatc.active.run_in_env(pos, evtdata, customfct)
	
end

advtrains.register_tracks("default", {
	nodename_prefix="advtrains_luaautomation:dtrack",
	texture_prefix="advtrains_dtrack_atc",
	models_prefix="advtrains_dtrack",
	models_suffix=".b3d",
	shared_texture="advtrains_dtrack_shared_atc.png",
	description=atltrans("LuaAutomation ATC Rail"),
	formats={},
	get_additional_definiton = function(def, preset, suffix, rotation)
		return {
			after_place_node = atlatc.active.after_place_node,
			after_dig_node = atlatc.active.after_dig_node,

			on_receive_fields = function(pos, ...)
				atlatc.active.on_receive_fields(pos, ...)
				
				--set arrowconn (for ATC)
				local ph=minetest.pos_to_string(pos)
				local _, conns=advtrains.get_rail_info_at(pos, advtrains.all_tracktypes)
				atlatc.active.nodes[ph].arrowconn=conns[1].c
			end,

			advtrains = {
				on_train_enter = function(pos, train_id)
					--do async. Event is fired in train steps
					atlatc.interrupt.add(0, pos, {type="train", train=true, id=train_id})
				end,
				on_train_approach = function(pos, train_id, train, index, has_entered, lzbdata)
					-- Insert an event only if the rail indicated that it supports approach callbacks
					local ph=minetest.pos_to_string(pos)
					local railtbl = atlatc.active.nodes[ph]
					-- uses a "magic variable" in the local environment of the node
					-- This hack is necessary because code might not be prepared to get approach events...
					if railtbl and railtbl.data and railtbl.data.__approach_callback_mode then
						local acm = railtbl.data.__approach_callback_mode
						if acm==2 or (acm==1 and train.path_cn[index] == 1) then
							local evtdata = {type="approach", approach=true, id=train_id, has_entered = has_entered}
							-- This event is *required* to run synchronously, because it might set the ars_disable flag on the train and add LZB checkpoints,
							-- although this is generally discouraged because this happens right in a train step
							-- At this moment, I am not aware whether this may cause side effects, and I must encourage users not to do expensive calculations here.
							r.fire_event(pos, evtdata, {train_id = train_id, train = train, index = index, lzbdata = lzbdata})
						end
					end
				end,
			},
			luaautomation = {
				fire_event=r.fire_event
			},
			digiline = {
				receptor = {},
				effector = {
					action = atlatc.active.on_digiline_receive
				},
			},
		}
	end,
}, advtrains.trackpresets.t_30deg_straightonly)


atlatc.rail = r