aboutsummaryrefslogtreecommitdiff
path: root/advtrains_luaautomation/atc_rail.lua
diff options
context:
space:
mode:
Diffstat (limited to 'advtrains_luaautomation/atc_rail.lua')
-rw-r--r--advtrains_luaautomation/atc_rail.lua247
1 files changed, 247 insertions, 0 deletions
diff --git a/advtrains_luaautomation/atc_rail.lua b/advtrains_luaautomation/atc_rail.lua
new file mode 100644
index 0000000..2d6efe5
--- /dev/null
+++ b/advtrains_luaautomation/atc_rail.lua
@@ -0,0 +1,247 @@
+-- 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
+
+ --prepare ingame API for ATC. Regenerate each time since pos needs to be known
+ --If no train, then return false.
+
+ -- try to get the train from the event data
+ -- This workaround is required because the callback is one step delayed, and a fast train may have already left the node.
+ -- Also used for approach callback
+ local train_id = evtdata._train_id
+ local atc_arrow = evtdata._train_arrow
+ local train, tvel
+
+ if train_id then
+ train=advtrains.trains[train_id]
+ -- speed
+ tvel=train.velocity
+ -- if still no train_id available, try to get the train at my position
+ else
+ train_id=advtrains.get_train_at_pos(pos)
+ if train_id then
+ train=advtrains.trains[train_id]
+ advtrains.train_ensure_init(train_id, train)
+ -- look up atc_arrow
+ local index = advtrains.path_lookup(train, pos)
+ atc_arrow = (train.path_cn[index] == 1)
+ -- speed
+ tvel=train.velocity
+ end
+ 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,
+ unset_shunt = function()
+ if not train_id then return false end
+ train.is_shunt = nil
+ end,
+ set_autocouple = function ()
+ if not train_id then return false end
+ train.autocouple = true
+ end,
+ unset_autocouple = function ()
+ if not train_id then return false end
+ train.autocouple = nil
+ 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_get_text_outside = function()
+ if not train_id then return false end
+ return advtrains.trains[train_id].text_outside
+ end,
+ atc_get_text_inside = function(text)
+ if not train_id then return false end
+ return advtrains.trains[train_id].text_inside
+ 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, train, index)
+ --do async. Event is fired in train steps
+ atlatc.interrupt.add(0, pos, {type="train", train=true, id=train_id,
+ _train_id = train_id, _train_arrow = (train.path_cn[index] == 1)})
+ 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
+ local in_arrow = (train.path_cn[index] == 1)
+ if acm==2 or (acm==1 and in_arrow) then
+ local evtdata = {type="approach", approach=true, id=train_id, has_entered = has_entered,
+ _train_id = train_id, _train_arrow = in_arrow} -- reuses code from train_enter
+ -- 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