Improve route programming:
- Formspec for TCBs instead of unhandy chatcommands - Ability to advance route over the next secction without punching end - Better visualization - Ability to route into dead-end sectionsmaster
|
@ -11,6 +11,8 @@ end
|
||||||
|
|
||||||
--advtrains
|
--advtrains
|
||||||
|
|
||||||
|
DUMP_DEBUG_SAVE = false
|
||||||
|
|
||||||
--Constant for maximum connection value/division of the circle
|
--Constant for maximum connection value/division of the circle
|
||||||
AT_CMAX = 16
|
AT_CMAX = 16
|
||||||
|
|
||||||
|
@ -108,9 +110,9 @@ sid=function(id) if id then return string.sub(id, -6) end end
|
||||||
|
|
||||||
--ONLY use this function for temporary debugging. for consistent debug prints use atprint
|
--ONLY use this function for temporary debugging. for consistent debug prints use atprint
|
||||||
atdebug=function(t, ...)
|
atdebug=function(t, ...)
|
||||||
-- local text=advtrains.print_concat_table({t, ...})
|
local text=advtrains.print_concat_table({t, ...})
|
||||||
-- minetest.log("action", "[advtrains]"..text)
|
minetest.log("action", "[advtrains]"..text)
|
||||||
-- minetest.chat_send_all("[advtrains]"..text)
|
minetest.chat_send_all("[advtrains]"..text)
|
||||||
end
|
end
|
||||||
|
|
||||||
if minetest.settings:get_bool("advtrains_enable_debugging") then
|
if minetest.settings:get_bool("advtrains_enable_debugging") then
|
||||||
|
@ -320,6 +322,15 @@ advtrains.avt_save = function(remove_players_from_wagons)
|
||||||
end
|
end
|
||||||
file:write(datastr)
|
file:write(datastr)
|
||||||
file:close()
|
file:close()
|
||||||
|
|
||||||
|
if DUMP_DEBUG_SAVE then
|
||||||
|
local file, err = io.open(advtrains.fpath.."_DUMP", "w")
|
||||||
|
if err then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
file:write(dump(save_tbl))
|
||||||
|
file:close()
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--## MAIN LOOP ##--
|
--## MAIN LOOP ##--
|
||||||
|
|
|
@ -250,7 +250,7 @@ end
|
||||||
local function traverser(found_tcbs, pos, conns, connid, count, brk_when_found_n)
|
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)
|
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
|
if not adj_pos then
|
||||||
atdebug("Traverser found end-of-track at",pos, connid)
|
--atdebug("Traverser found end-of-track at",pos, connid)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
-- look whether there is a TCB here
|
-- look whether there is a TCB here
|
||||||
|
@ -258,14 +258,14 @@ local function traverser(found_tcbs, pos, conns, connid, count, brk_when_found_n
|
||||||
local tcb = ildb.get_tcb(adj_pos)
|
local tcb = ildb.get_tcb(adj_pos)
|
||||||
if tcb then
|
if tcb then
|
||||||
-- done with this branch
|
-- done with this branch
|
||||||
atdebug("Traverser found tcb at",adj_pos, adj_connid)
|
--atdebug("Traverser found tcb at",adj_pos, adj_connid)
|
||||||
insert_sigd_nodouble(found_tcbs, {p=adj_pos, s=adj_connid})
|
insert_sigd_nodouble(found_tcbs, {p=adj_pos, s=adj_connid})
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
-- recursion abort condition
|
-- recursion abort condition
|
||||||
if count > TRAVERSER_LIMIT then
|
if count > TRAVERSER_LIMIT then
|
||||||
atdebug("Traverser hit counter at",adj_pos, adj_connid)
|
--atdebug("Traverser hit counter at",adj_pos, adj_connid)
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
-- continue traversing
|
-- continue traversing
|
||||||
|
@ -316,7 +316,7 @@ function ildb.sync_tcb_neighbors(pos, connid)
|
||||||
error("update_tcb_neighbors but node is NOK: "..minetest.pos_to_string(pos))
|
error("update_tcb_neighbors but node is NOK: "..minetest.pos_to_string(pos))
|
||||||
end
|
end
|
||||||
|
|
||||||
atdebug("Traversing from ",pos, connid)
|
--atdebug("Traversing from ",pos, connid)
|
||||||
local counter_hit = traverser(found_tcbs, pos, conns, connid, 0)
|
local counter_hit = traverser(found_tcbs, pos, conns, connid, 0)
|
||||||
|
|
||||||
local ts_id
|
local ts_id
|
||||||
|
@ -328,7 +328,7 @@ function ildb.sync_tcb_neighbors(pos, connid)
|
||||||
for idx, sigd in pairs(found_tcbs) do
|
for idx, sigd in pairs(found_tcbs) do
|
||||||
local tcbs = ildb.get_tcbs(sigd)
|
local tcbs = ildb.get_tcbs(sigd)
|
||||||
if not tcbs.ts_id then
|
if not tcbs.ts_id then
|
||||||
atdebug("Sync: put",sigd_to_string(sigd),"into list_eoi")
|
--atdebug("Sync: put",sigd_to_string(sigd),"into list_eoi")
|
||||||
table.insert(list_eoi, sigd)
|
table.insert(list_eoi, sigd)
|
||||||
elseif not ts_id and tcbs.ts_id then
|
elseif not ts_id and tcbs.ts_id then
|
||||||
if not ildb.get_ts(tcbs.ts_id) then
|
if not ildb.get_ts(tcbs.ts_id) then
|
||||||
|
@ -336,7 +336,7 @@ function ildb.sync_tcb_neighbors(pos, connid)
|
||||||
tcbs.ts_id = nil
|
tcbs.ts_id = nil
|
||||||
table.insert(list_eoi, sigd)
|
table.insert(list_eoi, sigd)
|
||||||
else
|
else
|
||||||
atdebug("Sync: put",sigd_to_string(sigd),"into list_ok")
|
--atdebug("Sync: put",sigd_to_string(sigd),"into list_ok")
|
||||||
ts_id = tcbs.ts_id
|
ts_id = tcbs.ts_id
|
||||||
table.insert(list_ok, sigd)
|
table.insert(list_ok, sigd)
|
||||||
end
|
end
|
||||||
|
|
|
@ -112,13 +112,16 @@ route = {
|
||||||
next = <sigd>, -- of the next (note: next) TCB on the route
|
next = <sigd>, -- of the next (note: next) TCB on the route
|
||||||
locks = {<pts> = "state"} -- route locks of this route segment
|
locks = {<pts> = "state"} -- route locks of this route segment
|
||||||
}
|
}
|
||||||
|
terminal =
|
||||||
}
|
}
|
||||||
The first item in the TCB path (namely i=0) is always the start signal of this route,
|
The first item in the TCB path (namely i=0) is always the start signal of this route,
|
||||||
so this is left out.
|
so this is left out.
|
||||||
All subsequent entries, starting from 1, contain:
|
All subsequent entries, starting from 1, contain:
|
||||||
- all route locks of the segment on TS between the (i-1). and the i. TCB
|
- all route locks of the segment on TS between the (i-1). and the i. TCB
|
||||||
- the next TCB signal describer in proceeding direction of the route.
|
- the next TCB signal describer in proceeding direction of the route.
|
||||||
|
'Terminal' once again repeats the "next" entry of the last route segment.
|
||||||
|
It is needed for distant signal aspect determination. If it is not set,
|
||||||
|
the distant signal aspect is determined as DANGER.
|
||||||
]]--
|
]]--
|
||||||
|
|
||||||
local function chat(pname, message)
|
local function chat(pname, message)
|
||||||
|
@ -129,6 +132,10 @@ local function clear_lock(locks, pname, pts)
|
||||||
chat(pname, pts.." is no longer affected when this route is set.")
|
chat(pname, pts.." is no longer affected when this route is set.")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function otherside(s)
|
||||||
|
if s==1 then return 2 else return 1 end
|
||||||
|
end
|
||||||
|
|
||||||
function advtrains.interlocking.clear_visu_context(context)
|
function advtrains.interlocking.clear_visu_context(context)
|
||||||
if not markerent[context] then return end
|
if not markerent[context] then return end
|
||||||
for key, obj in pairs(markerent[context]) do
|
for key, obj in pairs(markerent[context]) do
|
||||||
|
@ -150,22 +157,51 @@ function advtrains.interlocking.visualize_route(origin, route, context, tmp_lcks
|
||||||
end
|
end
|
||||||
routemarker(context, origin.p, "rte_origin", "at_il_route_start.png", oyaw, route.name)
|
routemarker(context, origin.p, "rte_origin", "at_il_route_start.png", oyaw, route.name)
|
||||||
|
|
||||||
|
local c_sigd = origin
|
||||||
for k,v in ipairs(route) do
|
for k,v in ipairs(route) do
|
||||||
local sigd = v.next
|
c_sigd = v.next
|
||||||
local yaw = 0
|
-- display route path
|
||||||
local node_ok, conns, rhe = advtrains.get_rail_info_at(sigd.p, advtrains.all_tracktypes)
|
-- Final "next" marker can be EOI, thus undefined. This is legitimate.
|
||||||
if node_ok then
|
if c_sigd then
|
||||||
yaw = advtrains.dir_to_angle(conns[sigd.s].c)
|
local yaw = 0
|
||||||
|
local node_ok, conns, rhe = advtrains.get_rail_info_at(c_sigd.p, advtrains.all_tracktypes)
|
||||||
|
if node_ok then
|
||||||
|
yaw = advtrains.dir_to_angle(conns[c_sigd.s].c)
|
||||||
|
end
|
||||||
|
local img = "at_il_route_set.png"
|
||||||
|
if k==#route and not tmp_lcks then
|
||||||
|
img = "at_il_route_end.png"
|
||||||
|
end
|
||||||
|
routemarker(context, c_sigd.p, "rte"..k, img, yaw, route.name.." #"..k)
|
||||||
end
|
end
|
||||||
local img = "at_il_route_set.png"
|
-- display locks
|
||||||
if k == #route then img = "at_il_route_end.png" end
|
|
||||||
routemarker(context, sigd.p, "rte"..k, img, yaw, route.name.." #"..k)
|
|
||||||
for pts, state in pairs(v.locks) do
|
for pts, state in pairs(v.locks) do
|
||||||
local pos = minetest.string_to_pos(pts)
|
local pos = minetest.string_to_pos(pts)
|
||||||
routesprite(context, pos, "fix"..k..pts, "at_il_route_lock.png", "Fixed in state '"..state.."' by route "..route.name.." until segment #"..k.." is freed.")
|
routesprite(context, pos, "fix"..k..pts, "at_il_route_lock.png", "Fixed in state '"..state.."' by route "..route.name.." until segment #"..k.." is freed.")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- The presence of tmp_lcks tells us that we are displaying during route programming.
|
||||||
if tmp_lcks then
|
if tmp_lcks then
|
||||||
|
-- display route end markers at appropriate places (check next TS, if it exists)
|
||||||
|
local terminal = c_sigd
|
||||||
|
if terminal then
|
||||||
|
local term_tcbs = advtrains.interlocking.db.get_tcbs(terminal)
|
||||||
|
if term_tcbs.ts_id then
|
||||||
|
local over_ts = advtrains.interlocking.db.get_ts(term_tcbs.ts_id)
|
||||||
|
for i, sigd in ipairs(over_ts.tc_breaks) do
|
||||||
|
if not vector.equals(sigd.p, terminal.p) then
|
||||||
|
local yaw = 0
|
||||||
|
local node_ok, conns, rhe = advtrains.get_rail_info_at(sigd.p, advtrains.all_tracktypes)
|
||||||
|
if node_ok then
|
||||||
|
yaw = advtrains.dir_to_angle(conns[otherside(sigd.s)].c)
|
||||||
|
end
|
||||||
|
routemarker(context, sigd.p, "rteterm"..i, "at_il_route_end.png", yaw, route.name.." Terminal "..i)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- display locks set by player
|
||||||
for pts, state in pairs(tmp_lcks) do
|
for pts, state in pairs(tmp_lcks) do
|
||||||
local pos = minetest.string_to_pos(pts)
|
local pos = minetest.string_to_pos(pts)
|
||||||
routesprite(context, pos, "fixp"..pts, "at_il_route_lock_edit.png", "Fixed in state '"..state.."' by route "..route.name.." (punch to unfix)",
|
routesprite(context, pos, "fixp"..pts, "at_il_route_lock_edit.png", "Fixed in state '"..state.."' by route "..route.name.." (punch to unfix)",
|
||||||
|
@ -201,10 +237,267 @@ local function get_last_route_item(origin, route)
|
||||||
return route[#route].next
|
return route[#route].next
|
||||||
end
|
end
|
||||||
|
|
||||||
local function otherside(s)
|
local function do_advance_route(pname, rp, sigd, tsname)
|
||||||
if s==1 then return 2 else return 1 end
|
table.insert(rp.route, {next = sigd, locks = rp.tmp_lcks})
|
||||||
|
rp.tmp_lcks = {}
|
||||||
|
chat(pname, "Added track section '"..tsname.."' to the route (revert with /at_rp_back)")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function finishrpform(pname)
|
||||||
|
local rp = player_rte_prog[pname]
|
||||||
|
if not rp then return end
|
||||||
|
|
||||||
|
local form = "size[7,6]label[0.5,0.5;Finish programming route]"
|
||||||
|
local terminal = get_last_route_item(rp.origin, rp.route)
|
||||||
|
if terminal then
|
||||||
|
local term_tcbs = advtrains.interlocking.db.get_tcbs(terminal)
|
||||||
|
|
||||||
|
if term_tcbs.signal then
|
||||||
|
form = form .. "label[0.5,1.5;Route ends at signal:]"
|
||||||
|
form = form .. "label[0.5,2 ;"..term_tcbs.signal_name.."]"
|
||||||
|
else
|
||||||
|
form = form .. "label[0.5,1.5;WARNING: Route does not end at a signal.]"
|
||||||
|
form = form .. "label[0.5,2 ;Routes should in most cases end at signals.]"
|
||||||
|
form = form .. "label[0.5,2.5;Cancel if you are unsure!]"
|
||||||
|
end
|
||||||
|
else
|
||||||
|
form = form .. "label[0.5,1.5;Route leads into]"
|
||||||
|
form = form .. "label[0.5,2 ;non-interlocked area]"
|
||||||
|
end
|
||||||
|
form = form.."field[0.8,3.5;5.2,1;name;Enter Route Name;]"
|
||||||
|
form = form.."button_exit[0.5,4.5; 5,1;save;Save Route]"
|
||||||
|
|
||||||
|
|
||||||
|
minetest.show_formspec(pname, "at_il_routepf", form)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local function check_advance_valid(tcbpos, rp)
|
||||||
|
-- track circuit break, try to advance route over it
|
||||||
|
local lri = get_last_route_item(rp.origin, rp.route)
|
||||||
|
if not lri then
|
||||||
|
return false, false
|
||||||
|
end
|
||||||
|
|
||||||
|
local is_endpoint = false
|
||||||
|
|
||||||
|
local this_sigd, this_ts, adv_side
|
||||||
|
|
||||||
|
if vector.equals(lri.p, tcbpos) then
|
||||||
|
-- If the player just punched the last TCB again, it's of course possible to
|
||||||
|
-- finish the route here (although it can't be advanced by here.
|
||||||
|
-- Fun fact: you can now program routes that end exactly where they begin :)
|
||||||
|
is_endpoint = true
|
||||||
|
this_sigd = lri
|
||||||
|
else
|
||||||
|
-- else, we need to check whether this TS actually borders
|
||||||
|
local start_tcbs = advtrains.interlocking.db.get_tcbs(lri)
|
||||||
|
if not start_tcbs.ts_id then
|
||||||
|
return false, false
|
||||||
|
end
|
||||||
|
|
||||||
|
this_ts = advtrains.interlocking.db.get_ts(start_tcbs.ts_id)
|
||||||
|
for _,sigd in ipairs(this_ts.tc_breaks) do
|
||||||
|
if vector.equals(sigd.p, tcbpos) then
|
||||||
|
adv_side = otherside(sigd.s)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if not adv_side then
|
||||||
|
-- this TCB is not bordering to the section
|
||||||
|
return false, false
|
||||||
|
end
|
||||||
|
this_sigd = {p=tcbpos, s=adv_side}
|
||||||
|
end
|
||||||
|
|
||||||
|
-- check whether the ts at the other end is capable of "end over"
|
||||||
|
local adv_tcbs = advtrains.interlocking.db.get_tcbs(this_sigd)
|
||||||
|
local next_tsid = adv_tcbs.ts_id
|
||||||
|
local can_over, over_ts, next_tc_bs = false, nil, nil
|
||||||
|
local cannotover_rsn = "Next section is diverging (>2 TCBs)"
|
||||||
|
if next_tsid then
|
||||||
|
-- you may not advance over EOI. While this is technically possible,
|
||||||
|
-- in practise this just enters an unnecessary extra empty route item.
|
||||||
|
over_ts = advtrains.interlocking.db.get_ts(adv_tcbs.ts_id)
|
||||||
|
next_tc_bs = over_ts.tc_breaks
|
||||||
|
can_over = #next_tc_bs <= 2
|
||||||
|
else
|
||||||
|
cannotover_rsn = "End of interlocking"
|
||||||
|
end
|
||||||
|
|
||||||
|
local over_sigd = nil
|
||||||
|
if can_over then
|
||||||
|
if next_tc_bs and #next_tc_bs == 2 then
|
||||||
|
local sdt
|
||||||
|
if vector.equals(next_tc_bs[1].p, tcbpos) then
|
||||||
|
sdt = next_tc_bs[2]
|
||||||
|
end
|
||||||
|
if vector.equals(next_tc_bs[2].p, tcbpos) then
|
||||||
|
sdt = next_tc_bs[1]
|
||||||
|
end
|
||||||
|
if not sdt then
|
||||||
|
error("Inconsistency: "..dump(next_ts))
|
||||||
|
end
|
||||||
|
-- swap TCB direction
|
||||||
|
over_sigd = {p = sdt.p, s = otherside(sdt.s) }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return is_endpoint, true, this_sigd, this_ts, can_over, over_ts, over_sigd, cannotover_rsn
|
||||||
|
end
|
||||||
|
|
||||||
|
local function show_routing_form(pname, tcbpos, message)
|
||||||
|
|
||||||
|
local rp = player_rte_prog[pname]
|
||||||
|
|
||||||
|
if not rp then return end
|
||||||
|
|
||||||
|
local is_endpoint, advance_valid, this_sigd, this_ts, can_over, over_ts, over_sigd, cannotover_rsn = check_advance_valid(tcbpos, rp)
|
||||||
|
|
||||||
|
-- at this place, advance_valid shows whether the current route can be advanced
|
||||||
|
-- over this TCB.
|
||||||
|
-- If it can:
|
||||||
|
-- Advance over (continue programming)
|
||||||
|
-- End here
|
||||||
|
-- Advance and end (only <=2 TCBs, terminal signal needs to be known)
|
||||||
|
-- if not:
|
||||||
|
-- show nothing at all
|
||||||
|
-- In all cases, Discard and Backtrack buttons needed.
|
||||||
|
|
||||||
|
local form = "size[7,9.5]label[0.5,0.5;Advance/Complete Route]"
|
||||||
|
if message then
|
||||||
|
form = form .. "label[0.5,1;"..message.."]"
|
||||||
|
end
|
||||||
|
|
||||||
|
if advance_valid and not is_endpoint then
|
||||||
|
form = form.. "label[0.5,1.8;Advance to next route section]"
|
||||||
|
form = form.."image_button[0.5,2.2; 5,1;at_il_routep_advance.png;advance;]"
|
||||||
|
|
||||||
|
form = form.. "label[0.5,3.5;-------------------------]"
|
||||||
|
else
|
||||||
|
form = form.. "label[0.5,2.3;This TCB is not suitable as]"
|
||||||
|
form = form.. "label[0.5,2.8;route continuation.]"
|
||||||
|
end
|
||||||
|
if advance_valid or is_endpoint then
|
||||||
|
form = form.. "label[0.5,3.8;Finish route HERE]"
|
||||||
|
form = form.."image_button[0.5, 4.2; 5,1;at_il_routep_end_here.png;endhere;]"
|
||||||
|
if can_over then
|
||||||
|
form = form.. "label[0.5,5.3;Finish route at end of NEXT section]"
|
||||||
|
form = form.."image_button[0.5,5.7; 5,1;at_il_routep_end_over.png;endover;]"
|
||||||
|
else
|
||||||
|
form = form.. "label[0.5,5.3;Advancing over next section is]"
|
||||||
|
form = form.. "label[0.5,5.8;impossible at this place.]"
|
||||||
|
if cannotover_rsn then
|
||||||
|
form = form.. "label[0.5,6.3;"..cannotover_rsn.."]"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
form = form.. "label[0.5,7;-------------------------]"
|
||||||
|
if #rp.route > 0 then
|
||||||
|
form = form.."button[0.5,7.4; 5,1;retract;Step back one section]"
|
||||||
|
end
|
||||||
|
form = form.."button[0.5,8.4; 5,1;cancel;Cancel route programming]"
|
||||||
|
|
||||||
|
minetest.show_formspec(pname, "at_il_rprog_"..minetest.pos_to_string(tcbpos), form)
|
||||||
|
end
|
||||||
|
|
||||||
|
minetest.register_on_player_receive_fields(function(player, formname, fields)
|
||||||
|
local pname = player:get_player_name()
|
||||||
|
|
||||||
|
local tcbpts = string.match(formname, "^at_il_rprog_([^_]+)$")
|
||||||
|
local tcbpos
|
||||||
|
if tcbpts then
|
||||||
|
tcbpos = minetest.string_to_pos(tcbpts)
|
||||||
|
end
|
||||||
|
if tcbpos then
|
||||||
|
-- RPROG form
|
||||||
|
local rp = player_rte_prog[pname]
|
||||||
|
if not rp then
|
||||||
|
minetest.close_formspec(pname, formname)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local is_endpoint, advance_valid, this_sigd, this_ts, can_over, over_ts, over_sigd = check_advance_valid(tcbpos, rp)
|
||||||
|
|
||||||
|
if advance_valid then
|
||||||
|
if fields.advance then
|
||||||
|
-- advance route
|
||||||
|
if not is_endpoint then
|
||||||
|
do_advance_route(pname, rp, this_sigd, this_ts.name)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if fields.endhere then
|
||||||
|
if not is_endpoint then
|
||||||
|
do_advance_route(pname, rp, this_sigd, this_ts.name)
|
||||||
|
end
|
||||||
|
finishrpform(pname)
|
||||||
|
end
|
||||||
|
if can_over and fields.endover then
|
||||||
|
if not is_endpoint then
|
||||||
|
do_advance_route(pname, rp, this_sigd, this_ts.name)
|
||||||
|
end
|
||||||
|
do_advance_route(pname, rp, over_sigd, over_ts and over_ts.name or "--EOI--")
|
||||||
|
finishrpform(pname)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if fields.retract then
|
||||||
|
if #rp.route <= 0 then
|
||||||
|
minetest.close_formspec(pname, formname)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
rp.tmp_locks = rp.route[#rp.route].locks
|
||||||
|
rp.route[#rp.route] = nil
|
||||||
|
chat(pname, "Route section "..(#rp.route+1).." removed.")
|
||||||
|
end
|
||||||
|
if fields.cancel then
|
||||||
|
player_rte_prog[pname] = nil
|
||||||
|
advtrains.interlocking.clear_visu_context("prog_"..pname)
|
||||||
|
chat(pname, "Route discarded.")
|
||||||
|
minetest.close_formspec(pname, formname)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
advtrains.interlocking.visualize_route(rp.origin, rp.route, "prog_"..pname, rp.tmp_lcks, pname)
|
||||||
|
minetest.close_formspec(pname, formname)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
if formname == "at_il_routepf" then
|
||||||
|
if not fields.save or not fields.name then return end
|
||||||
|
if fields.name == "" then
|
||||||
|
-- show form again
|
||||||
|
finishrpform(pname)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local rp = player_rte_prog[pname]
|
||||||
|
if rp then
|
||||||
|
if #rp.route <= 0 then
|
||||||
|
chat(pname, "Cannot program route without a target")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local tcbs = advtrains.interlocking.db.get_tcbs(rp.origin)
|
||||||
|
if not tcbs then
|
||||||
|
chat(pname, "The origin TCB has become unknown during programming. Try again.")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local terminal = get_last_route_item(rp.origin, rp.route)
|
||||||
|
rp.route.terminal = terminal
|
||||||
|
rp.route.name = fields.name
|
||||||
|
|
||||||
|
table.insert(tcbs.routes, rp.route)
|
||||||
|
|
||||||
|
advtrains.interlocking.clear_visu_context("prog_"..pname)
|
||||||
|
player_rte_prog[pname] = nil
|
||||||
|
chat(pname, "Successfully programmed route.")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
|
||||||
-- Central route programming punch callback
|
-- Central route programming punch callback
|
||||||
minetest.register_on_punchnode(function(pos, node, player, pointed_thing)
|
minetest.register_on_punchnode(function(pos, node, player, pointed_thing)
|
||||||
local pname = player:get_player_name()
|
local pname = player:get_player_name()
|
||||||
|
@ -224,38 +517,12 @@ minetest.register_on_punchnode(function(pos, node, player, pointed_thing)
|
||||||
end
|
end
|
||||||
local tcbpos = minetest.string_to_pos(tcbpts)
|
local tcbpos = minetest.string_to_pos(tcbpts)
|
||||||
|
|
||||||
-- track circuit break, try to advance route over it
|
-- show formspec
|
||||||
local lri = get_last_route_item(rp.origin, rp.route)
|
|
||||||
if vector.equals(lri.p, tcbpos) then
|
|
||||||
chat(pname, "You cannot continue the route to where you came from!")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
local start_tcbs = advtrains.interlocking.db.get_tcbs(lri)
|
show_routing_form(pname, tcbpos)
|
||||||
if not start_tcbs.ts_id then
|
|
||||||
chat(pname, "The previous TCB was End of Interlocking. Please complete route programming using '/at_rp_set <name>'")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
local ts = advtrains.interlocking.db.get_ts(start_tcbs.ts_id)
|
|
||||||
if not ts then atwarn("Internal error, ts inexistant for id!") return end
|
|
||||||
local found = nil
|
|
||||||
for _,sigd in ipairs(ts.tc_breaks) do
|
|
||||||
if vector.equals(sigd.p, tcbpos) then
|
|
||||||
found = otherside(sigd.s)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if not found then
|
|
||||||
chat(pname, "Previous and this TCB belong to different track sections!")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
-- TODO check the path: are all route turnouts locked to the right position?
|
|
||||||
|
|
||||||
-- everything worked, just add the other side to the list
|
|
||||||
table.insert(rp.route, {next = {p = tcbpos, s = found}, locks = rp.tmp_lcks})
|
|
||||||
rp.tmp_lcks = {}
|
|
||||||
chat(pname, "Added track section '"..ts.name.."' to the route (revert with /at_rp_back)")
|
|
||||||
advtrains.interlocking.visualize_route(rp.origin, rp.route, "prog_"..pname, rp.tmp_lcks, pname)
|
advtrains.interlocking.visualize_route(rp.origin, rp.route, "prog_"..pname, rp.tmp_lcks, pname)
|
||||||
|
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
if advtrains.is_passive(pos) then
|
if advtrains.is_passive(pos) then
|
||||||
|
@ -274,90 +541,6 @@ minetest.register_on_punchnode(function(pos, node, player, pointed_thing)
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
minetest.register_chatcommand("at_rp_set",
|
|
||||||
{
|
|
||||||
params = "<name>", -- Short parameter description
|
|
||||||
description = "Completes route programming procedure", -- Full description
|
|
||||||
privs = {interlocking = true},
|
|
||||||
func = function(pname, param)
|
|
||||||
return advtrains.pcall(function()
|
|
||||||
if param=="" then
|
|
||||||
return false, "Missing name parameter!"
|
|
||||||
end
|
|
||||||
local rp = player_rte_prog[pname]
|
|
||||||
if rp then
|
|
||||||
if #rp.route <= 0 then
|
|
||||||
return false, "Cannot program route without a target"
|
|
||||||
end
|
|
||||||
rp.route.name = param
|
|
||||||
|
|
||||||
local tcbs = advtrains.interlocking.db.get_tcbs(rp.origin)
|
|
||||||
if not tcbs then
|
|
||||||
return false, "The origin TCB of this route doesn't exist!"
|
|
||||||
end
|
|
||||||
|
|
||||||
table.insert(tcbs.routes, rp.route)
|
|
||||||
|
|
||||||
advtrains.interlocking.clear_visu_context("prog_"..pname)
|
|
||||||
player_rte_prog[pname] = nil
|
|
||||||
return true, "Successfully programmed route"
|
|
||||||
end
|
|
||||||
return false, "You are not programming a route!"
|
|
||||||
end)
|
|
||||||
end,
|
|
||||||
})
|
|
||||||
|
|
||||||
minetest.register_chatcommand("at_rp_back",
|
|
||||||
{
|
|
||||||
params = "", -- Short parameter description
|
|
||||||
description = "Remove last route segment", -- Full description
|
|
||||||
privs = {interlocking = true},
|
|
||||||
func = function(pname, param)
|
|
||||||
return advtrains.pcall(function()
|
|
||||||
local rp = player_rte_prog[pname]
|
|
||||||
if rp then
|
|
||||||
if #rp.route <= 0 then
|
|
||||||
return false, "Cannot backtrack when there are no route elements"
|
|
||||||
end
|
|
||||||
rp.tmp_locks = rp.route[#rp.route].locks
|
|
||||||
rp.route[#rp.route] = nil
|
|
||||||
advtrains.interlocking.visualize_route(rp.origin, rp.route, "prog_"..pname)
|
|
||||||
return true, "Route section "..(#rp.route+1).." removed."
|
|
||||||
end
|
|
||||||
return false, "You are not programming a route!"
|
|
||||||
end)
|
|
||||||
end,
|
|
||||||
})
|
|
||||||
minetest.register_chatcommand("at_rp_mark",
|
|
||||||
{
|
|
||||||
params = "", -- Short parameter description
|
|
||||||
description = "Re-set route programming markers", -- Full description
|
|
||||||
privs = {interlocking = true},
|
|
||||||
func = function(pname, param)
|
|
||||||
return advtrains.pcall(function()
|
|
||||||
local rp = player_rte_prog[pname]
|
|
||||||
if rp then
|
|
||||||
advtrains.interlocking.visualize_route(rp.origin, rp.route, "prog_"..pname)
|
|
||||||
return true, "Redrawn route markers"
|
|
||||||
end
|
|
||||||
return false, "You are not programming a route!"
|
|
||||||
end)
|
|
||||||
end,
|
|
||||||
})
|
|
||||||
minetest.register_chatcommand("at_rp_discard",
|
|
||||||
{
|
|
||||||
params = "", -- Short parameter description
|
|
||||||
description = "Discards the currently programmed route", -- Full description
|
|
||||||
privs = {interlocking = true},
|
|
||||||
func = function(pname, param)
|
|
||||||
return advtrains.pcall(function()
|
|
||||||
player_rte_prog[pname] = nil
|
|
||||||
advtrains.interlocking.clear_visu_context("prog_"..pname)
|
|
||||||
return true, "Route discarded"
|
|
||||||
end)
|
|
||||||
end,
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
--TODO on route setting
|
--TODO on route setting
|
||||||
-- routes should end at signals. complete route setting by punching a signal, and command as exceptional route completion
|
-- routes should end at signals. complete route setting by punching a signal, and command as exceptional route completion
|
||||||
|
|
|
@ -163,7 +163,7 @@ function ilrs.free_route_locks_indiv(pts, ts, nocallbacks)
|
||||||
local i = 1
|
local i = 1
|
||||||
while i <= #e do
|
while i <= #e do
|
||||||
if e[i].by == ts then
|
if e[i].by == ts then
|
||||||
atdebug("free_route_locks_indiv",pts,"clearing entry",e[i].by,e[i].rsn)
|
--atdebug("free_route_locks_indiv",pts,"clearing entry",e[i].by,e[i].rsn)
|
||||||
table.remove(e,i)
|
table.remove(e,i)
|
||||||
else
|
else
|
||||||
i = i + 1
|
i = i + 1
|
||||||
|
@ -244,7 +244,7 @@ function ilrs.update_route(sigd, tcbs, newrte, cancel)
|
||||||
tcbs.aspect = nil
|
tcbs.aspect = nil
|
||||||
if (newrte and tcbs.routeset and tcbs.routeset ~= newrte) or cancel then
|
if (newrte and tcbs.routeset and tcbs.routeset ~= newrte) or cancel then
|
||||||
if tcbs.route_committed then
|
if tcbs.route_committed then
|
||||||
atdebug("Cancelling:",tcbs.routeset)
|
--atdebug("Cancelling:",tcbs.routeset)
|
||||||
advtrains.interlocking.route.cancel_route_from(sigd)
|
advtrains.interlocking.route.cancel_route_from(sigd)
|
||||||
end
|
end
|
||||||
tcbs.route_committed = nil
|
tcbs.route_committed = nil
|
||||||
|
@ -253,24 +253,24 @@ function ilrs.update_route(sigd, tcbs, newrte, cancel)
|
||||||
end
|
end
|
||||||
if newrte or tcbs.routeset then
|
if newrte or tcbs.routeset then
|
||||||
if newrte then tcbs.routeset = newrte end
|
if newrte then tcbs.routeset = newrte end
|
||||||
atdebug("Setting:",tcbs.routeset)
|
--atdebug("Setting:",tcbs.routeset)
|
||||||
local succ, rsn, cbts, cblk = ilrs.set_route(sigd, tcbs.routes[tcbs.routeset])
|
local succ, rsn, cbts, cblk = ilrs.set_route(sigd, tcbs.routes[tcbs.routeset])
|
||||||
if not succ then
|
if not succ then
|
||||||
tcbs.route_rsn = rsn
|
tcbs.route_rsn = rsn
|
||||||
atdebug("Routesetting failed:",rsn)
|
--atdebug("Routesetting failed:",rsn)
|
||||||
-- add cbts or cblk to callback table
|
-- add cbts or cblk to callback table
|
||||||
if cbts then
|
if cbts then
|
||||||
atdebug("cbts =",cbts)
|
--atdebug("cbts =",cbts)
|
||||||
if not ilrs.rte_callbacks.ts[cbts] then ilrs.rte_callbacks.ts[cbts]={} end
|
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)
|
advtrains.insert_once(ilrs.rte_callbacks.ts[cbts], sigd, sigd_equal)
|
||||||
end
|
end
|
||||||
if cblk then
|
if cblk then
|
||||||
atdebug("cblk =",cblk)
|
--atdebug("cblk =",cblk)
|
||||||
if not ilrs.rte_callbacks.lck[cblk] then ilrs.rte_callbacks.lck[cblk]={} end
|
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)
|
advtrains.insert_once(ilrs.rte_callbacks.lck[cblk], sigd, sigd_equal)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
atdebug("Committed Route:",tcbs.routeset)
|
--atdebug("Committed Route:",tcbs.routeset)
|
||||||
tcbs.route_committed = true
|
tcbs.route_committed = true
|
||||||
tcbs.route_rsn = false
|
tcbs.route_rsn = false
|
||||||
tcbs.aspect = asp_generic_free
|
tcbs.aspect = asp_generic_free
|
||||||
|
@ -283,12 +283,12 @@ end
|
||||||
-- sys can be one of "ts" and "lck"
|
-- sys can be one of "ts" and "lck"
|
||||||
-- key is then ts_id or pts respectively
|
-- key is then ts_id or pts respectively
|
||||||
function ilrs.update_waiting(sys, key)
|
function ilrs.update_waiting(sys, key)
|
||||||
atdebug("update_waiting:",sys,".",key)
|
--atdebug("update_waiting:",sys,".",key)
|
||||||
local t = ilrs.rte_callbacks[sys][key]
|
local t = ilrs.rte_callbacks[sys][key]
|
||||||
ilrs.rte_callbacks[sys][key] = nil
|
ilrs.rte_callbacks[sys][key] = nil
|
||||||
if t then
|
if t then
|
||||||
for _,sigd in ipairs(t) do
|
for _,sigd in ipairs(t) do
|
||||||
atdebug("Updating", sigd)
|
--atdebug("Updating", sigd)
|
||||||
-- While these are run, the table we cleared before may be populated again, which is in our interest.
|
-- 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)
|
-- (that's the reason we needed to copy it)
|
||||||
local tcbs = ildb.get_tcbs(sigd)
|
local tcbs = ildb.get_tcbs(sigd)
|
||||||
|
|
Before Width: | Height: | Size: 382 B After Width: | Height: | Size: 534 B |
Before Width: | Height: | Size: 514 B After Width: | Height: | Size: 533 B |
After Width: | Height: | Size: 304 B |
After Width: | Height: | Size: 243 B |
After Width: | Height: | Size: 281 B |
After Width: | Height: | Size: 277 B |
|
@ -164,7 +164,7 @@ advtrains.te_register_on_create(function(id, train)
|
||||||
elseif ts_id==nil then
|
elseif ts_id==nil then
|
||||||
atwarn("Train",id,": Unable to determine whether to block a track section!")
|
atwarn("Train",id,": Unable to determine whether to block a track section!")
|
||||||
else
|
else
|
||||||
atdebug("Train",id,": Outside of interlocked area!")
|
--atdebug("Train",id,": Outside of interlocked area!")
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
|
|
@ -443,33 +443,47 @@ of the route. Now:
|
||||||
<ul class="itemize1">
|
<ul class="itemize1">
|
||||||
<li class="itemize">Put any turnouts you need to lock in the correct position (e.g. by right-clicking them). This includes flank protection.
|
<li class="itemize">Put any turnouts you need to lock in the correct position (e.g. by right-clicking them). This includes flank protection.
|
||||||
</li>
|
</li>
|
||||||
<li class="itemize">Punch them. This makes a marker saying “Route Lock Editing” appear.
|
<li class="itemize">Punch them. This makes a marker with a blue lock symbol appear.
|
||||||
</li>
|
</li>
|
||||||
<li class="itemize">If you punch a turnout again, or punch the marker, you can remove the lock again.
|
<li class="itemize">If you punch a turnout again, or punch the marker, you can remove the lock again.
|
||||||
</li>
|
</li>
|
||||||
<li class="itemize">When you’ve locked all turnouts in the current section, go to and punch the TCB that is the border to the next track
|
<li class="itemize">When you’ve locked all turnouts in the current section, go to and punch the TCB that is the border to the next track
|
||||||
section the train proceeds into.</li></ul>
|
section the train proceeds into.</li></ul>
|
||||||
<!--l. 364--><p class="noindent" >Once you’ve done this, the lock markers change to “Route Lock”, telling they can’t be changed anymore. Repeat the above procedure until
|
<!--l. 364--><p class="noindent" >Depending on the situation, you are now offered some possibilities to proceed:
|
||||||
you have punched the final TCB, at which the route should end. As mentioned before, there should be a signal at this place,
|
<ul class="itemize1">
|
||||||
however this is not enforced. Now, run the chat command <span
|
<li class="itemize">Click the “Advance to next section” button if your route consists of more sections with turnouts to lock, and you need to
|
||||||
class="ectt-1000">/at_rp_set <name of route> </span>to complete programming the
|
continue programming. Follow the above steps to set locks for the next section.</li></ul>
|
||||||
route.
|
<!--l. 371--><p class="noindent" >Once you’ve clicked the “Advance” button, the lock markers change to a red lock symbol, telling they can’t be changed anymore. Repeat
|
||||||
<!--l. 371--><p class="noindent" >A few hints:
|
the above procedure until you are ready to complete the programming procedure:
|
||||||
|
<ul class="itemize1">
|
||||||
|
<li class="itemize">Click the “Finish route HERE” button when you’ve set up the locks for the last track section of the route and punched the
|
||||||
|
final TCB (the one with the next signal). You will be asked for a route name and your route will be saved.
|
||||||
|
</li>
|
||||||
|
<li class="itemize">The “Finish route at end of NEXT section” button (third button) is an useful quickhand to make the route proceed one
|
||||||
|
more section. Using this button is equivalent to first clicking the “Advance” button, then flying to the end of the next track
|
||||||
|
section and finishing the route there. You can not (officially) set turnout locks in the final section using this method.</li></ul>
|
||||||
|
<!--l. 387--><p class="noindent" >A few hints:
|
||||||
<ul class="itemize1">
|
<ul class="itemize1">
|
||||||
<li class="itemize">If one turnout should be locked by more than one section, set the lock only in the <span
|
<li class="itemize">If one turnout should be locked by more than one section, set the lock only in the <span
|
||||||
class="ectt-1000">last </span>of those sections. Locking the same
|
class="ectt-1000">last </span>of those sections. Locking the same
|
||||||
turnout in multiple sections of a single route results in undefined behavior!
|
turnout in multiple sections of a single route results in undefined behavior!
|
||||||
</li>
|
</li>
|
||||||
<li class="itemize">If you accidentally punched a TCB, you can run <span
|
<li class="itemize">If you accidentally advanced the route wrongly, you can use the “Step back one section” button to undo this.
|
||||||
class="ectt-1000">/at_rp_back </span>to undo this and return to the previous section. Due to a
|
|
||||||
bug, you have to re-set all locks of this section.
|
|
||||||
</li>
|
</li>
|
||||||
<li class="itemize">If you want to stop programming the entire route without saving it, run <span
|
<li class="itemize">If you want to stop programming the entire route without saving it, use the “Cancel route programming” button.
|
||||||
class="ectt-1000">/at_rp_discard</span></li></ul>
|
</li>
|
||||||
<!--l. 384--><p class="noindent" >
|
<li class="itemize">The third button is especially useful for programming simple block sections on a main running line, since you can stay at
|
||||||
|
the starting signal (punch starting TCB and select third button).
|
||||||
|
</li>
|
||||||
|
<li class="itemize">If a route should end in a dead end, you MUST use the “Finish in NEXT section” button, because there is no final TCB
|
||||||
|
that you could punch.
|
||||||
|
</li>
|
||||||
|
<li class="itemize">The third button does NOT work on sections with more than 2 exits, because the system won’t be able to determine the
|
||||||
|
final TCB of the route then.</li></ul>
|
||||||
|
<!--l. 408--><p class="noindent" >
|
||||||
<a
|
<a
|
||||||
id="x1-47r4"></a>
|
id="x1-47r4"></a>
|
||||||
<!--l. 384--><p class="noindent" ><span
|
<!--l. 408--><p class="noindent" ><span
|
||||||
class="ecsx-1200">4</span> <span
|
class="ecsx-1200">4</span> <span
|
||||||
class="ecsx-1200">Interlocking</span>
|
class="ecsx-1200">Interlocking</span>
|
||||||
<span
|
<span
|
||||||
|
@ -478,15 +492,15 @@ class="ecsx-1200">system</span>
|
||||||
class="ecsx-1200">operation</span>
|
class="ecsx-1200">operation</span>
|
||||||
<a
|
<a
|
||||||
id="Q1-1-0"></a>
|
id="Q1-1-0"></a>
|
||||||
<!--l. 386--><p class="noindent" >Setting up the interlocking for a portion of a railway network requires some time, experience and planning, but once done, there’s not
|
<!--l. 410--><p class="noindent" >Setting up the interlocking for a portion of a railway network requires some time, experience and planning, but once done, there’s not
|
||||||
much to do anymore to make trains run on your, now safer, railway. This section covers some useful practices to route trains across your
|
much to do anymore to make trains run on your, now safer, railway. This section covers some useful practices to route trains across your
|
||||||
network.
|
network.
|
||||||
<!--l. 391--><p class="noindent" >At the moment, routes can only be set by clicking the signal or via LuaATC, except if you use automatic working. It is planned to control
|
<!--l. 415--><p class="noindent" >At the moment, routes can only be set by clicking the signal or via LuaATC, except if you use automatic working. It is planned to control
|
||||||
this via the onboard computer and via a “signal box” view based on the currently broken itrainmap.
|
this via the onboard computer and via a “signal box” view based on the currently broken itrainmap.
|
||||||
<!--l. 396--><p class="noindent" >
|
<!--l. 420--><p class="noindent" >
|
||||||
<a
|
<a
|
||||||
id="x1-48r1"></a>
|
id="x1-48r1"></a>
|
||||||
<!--l. 396--><p class="noindent" ><span
|
<!--l. 420--><p class="noindent" ><span
|
||||||
class="ecsx-1200">4.1</span> <span
|
class="ecsx-1200">4.1</span> <span
|
||||||
class="ecsx-1200">Simple</span>
|
class="ecsx-1200">Simple</span>
|
||||||
<span
|
<span
|
||||||
|
@ -499,44 +513,44 @@ class="ecsx-1200">and</span>
|
||||||
class="ecsx-1200">cancelling</span>
|
class="ecsx-1200">cancelling</span>
|
||||||
<a
|
<a
|
||||||
id="Q1-1-0"></a>
|
id="Q1-1-0"></a>
|
||||||
<!--l. 398--><p class="noindent" >To set a route, simply right-click the signal, select a route and click “set route”. If there are no conflicts, the signal turns green and the
|
<!--l. 422--><p class="noindent" >To set a route, simply right-click the signal, select a route and click “set route”. If there are no conflicts, the signal turns green and the
|
||||||
train is allowed to proceed.
|
train is allowed to proceed.
|
||||||
<!--l. 402--><p class="noindent" >It may be possible that the route can not be set, because one or more other routes conflict with the current one, or a section is blocked. In
|
<!--l. 426--><p class="noindent" >It may be possible that the route can not be set, because one or more other routes conflict with the current one, or a section is blocked. In
|
||||||
this case, the signal stays red, and the conflicting item is shown in the formspec. As soon as the conflict is resolved (by cancellation
|
this case, the signal stays red, and the conflicting item is shown in the formspec. As soon as the conflict is resolved (by cancellation
|
||||||
or release of the conflicting route, or the section becoming free), the requested route will be set and the signal turns
|
or release of the conflicting route, or the section becoming free), the requested route will be set and the signal turns
|
||||||
green.
|
green.
|
||||||
<!--l. 409--><p class="noindent" >If a route is either requested or set, it can be cancelled from the signalling formspec. This means that all turnouts and sections are
|
<!--l. 433--><p class="noindent" >If a route is either requested or set, it can be cancelled from the signalling formspec. This means that all turnouts and sections are
|
||||||
released, and the signal reverts back to red. This of course only works when the train has not passed the signal yet. There is no
|
released, and the signal reverts back to red. This of course only works when the train has not passed the signal yet. There is no
|
||||||
mechanism for Approach Locking.
|
mechanism for Approach Locking.
|
||||||
<!--l. 415--><p class="noindent" >
|
<!--l. 439--><p class="noindent" >
|
||||||
<a
|
<a
|
||||||
id="x1-49r2"></a>
|
id="x1-49r2"></a>
|
||||||
<!--l. 415--><p class="noindent" ><span
|
<!--l. 439--><p class="noindent" ><span
|
||||||
class="ecsx-1200">4.2</span> <span
|
class="ecsx-1200">4.2</span> <span
|
||||||
class="ecsx-1200">Automatic</span>
|
class="ecsx-1200">Automatic</span>
|
||||||
<span
|
<span
|
||||||
class="ecsx-1200">Working</span>
|
class="ecsx-1200">Working</span>
|
||||||
<a
|
<a
|
||||||
id="Q1-1-0"></a>
|
id="Q1-1-0"></a>
|
||||||
<!--l. 417--><p class="noindent" >Block signals on main running lines usually only have a single route to set, the one proceeding along the main line. Their purpose is only
|
<!--l. 441--><p class="noindent" >Block signals on main running lines usually only have a single route to set, the one proceeding along the main line. Their purpose is only
|
||||||
to show whether there are trains in the next section. So, it would be convenient if this only route would set itself again after a train
|
to show whether there are trains in the next section. So, it would be convenient if this only route would set itself again after a train
|
||||||
passed.
|
passed.
|
||||||
<!--l. 423--><p class="noindent" >This is what Automatic Working is for. Set a route, click “Enable Automatic Working”, and as soon as a train passes, the route is
|
<!--l. 447--><p class="noindent" >This is what Automatic Working is for. Set a route, click “Enable Automatic Working”, and as soon as a train passes, the route is
|
||||||
automatically re-set.
|
automatically re-set.
|
||||||
<!--l. 427--><p class="noindent" >This function is nearly identical to SimSig automatic signals. It can also be useful on a line with high traffic, when there’s a
|
<!--l. 451--><p class="noindent" >This function is nearly identical to SimSig automatic signals. It can also be useful on a line with high traffic, when there’s a
|
||||||
low-frequented access to a siding. You’d enable automatic working for the main route and cancel it only when you need a train to go into
|
low-frequented access to a siding. You’d enable automatic working for the main route and cancel it only when you need a train to go into
|
||||||
the siding.
|
the siding.
|
||||||
<!--l. 432--><p class="noindent" >
|
<!--l. 456--><p class="noindent" >
|
||||||
<a
|
<a
|
||||||
id="x1-50r5"></a>
|
id="x1-50r5"></a>
|
||||||
<!--l. 432--><p class="noindent" ><span
|
<!--l. 456--><p class="noindent" ><span
|
||||||
class="ecsx-1200">5</span> <span
|
class="ecsx-1200">5</span> <span
|
||||||
class="ecsx-1200">Final</span>
|
class="ecsx-1200">Final</span>
|
||||||
<span
|
<span
|
||||||
class="ecsx-1200">notes</span>
|
class="ecsx-1200">notes</span>
|
||||||
<a
|
<a
|
||||||
id="Q1-1-0"></a>
|
id="Q1-1-0"></a>
|
||||||
<!--l. 434--><p class="noindent" >The interlocking system is mainly finished, though there are still some plans and ideas. They include:
|
<!--l. 458--><p class="noindent" >The interlocking system is mainly finished, though there are still some plans and ideas. They include:
|
||||||
<ul class="itemize1">
|
<ul class="itemize1">
|
||||||
<li class="itemize">Setting routes from inside a train (via onboard computer)
|
<li class="itemize">Setting routes from inside a train (via onboard computer)
|
||||||
</li>
|
</li>
|
||||||
|
@ -547,11 +561,11 @@ class="ecsx-1200">notes</span>
|
||||||
<li class="itemize">Distant signals
|
<li class="itemize">Distant signals
|
||||||
</li>
|
</li>
|
||||||
<li class="itemize">On-Train head-up display for oncoming signals (they have something like this in Czech Republic, I forgot how it’s called.)</li></ul>
|
<li class="itemize">On-Train head-up display for oncoming signals (they have something like this in Czech Republic, I forgot how it’s called.)</li></ul>
|
||||||
<!--l. 444--><p class="noindent" >Apart from this, there’s the large oncoming project of a new timetable-based train automation system, but this will take some time to
|
<!--l. 468--><p class="noindent" >Apart from this, there’s the large oncoming project of a new timetable-based train automation system, but this will take some time to
|
||||||
evolve and is out of the scope of this document.
|
evolve and is out of the scope of this document.
|
||||||
<!--l. 448--><p class="noindent" >If you have any suggestions, corrections, improvements, criticism or cute kittens and stuff, you can always contact me by various means
|
<!--l. 472--><p class="noindent" >If you have any suggestions, corrections, improvements, criticism or cute kittens and stuff, you can always contact me by various means
|
||||||
(Forum PM, E-Mail (orwell@bleipb.de), Linuxworks server chat a.s.o.). Have fun!
|
(Forum PM, E-Mail (orwell@bleipb.de), Linuxworks server chat a.s.o.). Have fun!
|
||||||
<!--l. 453--><p class="noindent" >- orwell
|
<!--l. 477--><p class="noindent" >- orwell
|
||||||
</body></html>
|
</body></html>
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -933,15 +933,7 @@ Put any turnouts you need to lock in the correct position (e.g.
|
||||||
|
|
||||||
\begin_layout Itemize
|
\begin_layout Itemize
|
||||||
Punch them.
|
Punch them.
|
||||||
This makes a marker saying
|
This makes a marker with a blue lock symbol appear.
|
||||||
\begin_inset Quotes eld
|
|
||||||
\end_inset
|
|
||||||
|
|
||||||
Route Lock Editing
|
|
||||||
\begin_inset Quotes erd
|
|
||||||
\end_inset
|
|
||||||
|
|
||||||
appear.
|
|
||||||
\end_layout
|
\end_layout
|
||||||
|
|
||||||
\begin_layout Itemize
|
\begin_layout Itemize
|
||||||
|
@ -956,24 +948,75 @@ When you've locked all turnouts in the current section, go to and punch
|
||||||
\end_layout
|
\end_layout
|
||||||
|
|
||||||
\begin_layout Standard
|
\begin_layout Standard
|
||||||
Once you've done this, the lock markers change to
|
Depending on the situation, you are now offered some possibilities to proceed:
|
||||||
|
\end_layout
|
||||||
|
|
||||||
|
\begin_layout Itemize
|
||||||
|
Click the
|
||||||
\begin_inset Quotes eld
|
\begin_inset Quotes eld
|
||||||
\end_inset
|
\end_inset
|
||||||
|
|
||||||
Route Lock
|
Advance to next section
|
||||||
\begin_inset Quotes erd
|
\begin_inset Quotes erd
|
||||||
\end_inset
|
\end_inset
|
||||||
|
|
||||||
, telling they can't be changed anymore.
|
button if your route consists of more sections with turnouts to lock, and
|
||||||
Repeat the above procedure until you have punched the final TCB, at which
|
you need to continue programming.
|
||||||
the route should end.
|
Follow the above steps to set locks for the next section.
|
||||||
As mentioned before, there should be a signal at this place, however this
|
\end_layout
|
||||||
is not enforced.
|
|
||||||
Now, run the chat command
|
\begin_layout Standard
|
||||||
\family typewriter
|
Once you've clicked the
|
||||||
/at_rp_set <name of route>
|
\begin_inset Quotes eld
|
||||||
\family default
|
\end_inset
|
||||||
to complete programming the route.
|
|
||||||
|
Advance
|
||||||
|
\begin_inset Quotes erd
|
||||||
|
\end_inset
|
||||||
|
|
||||||
|
button, the lock markers change to a red lock symbol, telling they can't
|
||||||
|
be changed anymore.
|
||||||
|
Repeat the above procedure until you are ready to complete the programming
|
||||||
|
procedure:
|
||||||
|
\end_layout
|
||||||
|
|
||||||
|
\begin_layout Itemize
|
||||||
|
Click the
|
||||||
|
\begin_inset Quotes eld
|
||||||
|
\end_inset
|
||||||
|
|
||||||
|
Finish route HERE
|
||||||
|
\begin_inset Quotes erd
|
||||||
|
\end_inset
|
||||||
|
|
||||||
|
button when you've set up the locks for the last track section of the route
|
||||||
|
and punched the final TCB (the one with the next signal).
|
||||||
|
You will be asked for a route name and your route will be saved.
|
||||||
|
\end_layout
|
||||||
|
|
||||||
|
\begin_layout Itemize
|
||||||
|
The
|
||||||
|
\begin_inset Quotes eld
|
||||||
|
\end_inset
|
||||||
|
|
||||||
|
Finish route at end of NEXT section
|
||||||
|
\begin_inset Quotes erd
|
||||||
|
\end_inset
|
||||||
|
|
||||||
|
button (third button) is an useful quickhand to make the route proceed
|
||||||
|
one more section.
|
||||||
|
Using this button is equivalent to first clicking the
|
||||||
|
\begin_inset Quotes eld
|
||||||
|
\end_inset
|
||||||
|
|
||||||
|
Advance
|
||||||
|
\begin_inset Quotes erd
|
||||||
|
\end_inset
|
||||||
|
|
||||||
|
button, then flying to the end of the next track section and finishing
|
||||||
|
the route there.
|
||||||
|
You can not (officially) set turnout locks in the final section using this
|
||||||
|
method.
|
||||||
\end_layout
|
\end_layout
|
||||||
|
|
||||||
\begin_layout Standard
|
\begin_layout Standard
|
||||||
|
@ -994,19 +1037,51 @@ last
|
||||||
\end_layout
|
\end_layout
|
||||||
|
|
||||||
\begin_layout Itemize
|
\begin_layout Itemize
|
||||||
If you accidentally punched a TCB, you can run
|
If you accidentally advanced the route wrongly, you can use the
|
||||||
\family typewriter
|
\begin_inset Quotes eld
|
||||||
/at_rp_back
|
\end_inset
|
||||||
\family default
|
|
||||||
to undo this and return to the previous section.
|
Step back one section
|
||||||
Due to a bug, you have to re-set all locks of this section.
|
\begin_inset Quotes erd
|
||||||
|
\end_inset
|
||||||
|
|
||||||
|
button to undo this.
|
||||||
\end_layout
|
\end_layout
|
||||||
|
|
||||||
\begin_layout Itemize
|
\begin_layout Itemize
|
||||||
If you want to stop programming the entire route without saving it, run
|
If you want to stop programming the entire route without saving it, use
|
||||||
|
the
|
||||||
|
\begin_inset Quotes eld
|
||||||
|
\end_inset
|
||||||
|
|
||||||
\family typewriter
|
Cancel route programming
|
||||||
/at_rp_discard
|
\begin_inset Quotes erd
|
||||||
|
\end_inset
|
||||||
|
|
||||||
|
button.
|
||||||
|
\end_layout
|
||||||
|
|
||||||
|
\begin_layout Itemize
|
||||||
|
The third button is especially useful for programming simple block sections
|
||||||
|
on a main running line, since you can stay at the starting signal (punch
|
||||||
|
starting TCB and select third button).
|
||||||
|
\end_layout
|
||||||
|
|
||||||
|
\begin_layout Itemize
|
||||||
|
If a route should end in a dead end, you MUST use the
|
||||||
|
\begin_inset Quotes eld
|
||||||
|
\end_inset
|
||||||
|
|
||||||
|
Finish in NEXT section
|
||||||
|
\begin_inset Quotes erd
|
||||||
|
\end_inset
|
||||||
|
|
||||||
|
button, because there is no final TCB that you could punch.
|
||||||
|
\end_layout
|
||||||
|
|
||||||
|
\begin_layout Itemize
|
||||||
|
The third button does NOT work on sections with more than 2 exits, because
|
||||||
|
the system won't be able to determine the final TCB of the route then.
|
||||||
\end_layout
|
\end_layout
|
||||||
|
|
||||||
\begin_layout Section
|
\begin_layout Section
|
||||||
|
|
|
@ -933,15 +933,7 @@ Put any turnouts you need to lock in the correct position (e.g.
|
||||||
|
|
||||||
\begin_layout Itemize
|
\begin_layout Itemize
|
||||||
Punch them.
|
Punch them.
|
||||||
This makes a marker saying
|
This makes a marker with a blue lock symbol appear.
|
||||||
\begin_inset Quotes eld
|
|
||||||
\end_inset
|
|
||||||
|
|
||||||
Route Lock Editing
|
|
||||||
\begin_inset Quotes erd
|
|
||||||
\end_inset
|
|
||||||
|
|
||||||
appear.
|
|
||||||
\end_layout
|
\end_layout
|
||||||
|
|
||||||
\begin_layout Itemize
|
\begin_layout Itemize
|
||||||
|
@ -956,24 +948,75 @@ When you've locked all turnouts in the current section, go to and punch
|
||||||
\end_layout
|
\end_layout
|
||||||
|
|
||||||
\begin_layout Standard
|
\begin_layout Standard
|
||||||
Once you've done this, the lock markers change to
|
Depending on the situation, you are now offered some possibilities to proceed:
|
||||||
|
\end_layout
|
||||||
|
|
||||||
|
\begin_layout Itemize
|
||||||
|
Click the
|
||||||
\begin_inset Quotes eld
|
\begin_inset Quotes eld
|
||||||
\end_inset
|
\end_inset
|
||||||
|
|
||||||
Route Lock
|
Advance to next section
|
||||||
\begin_inset Quotes erd
|
\begin_inset Quotes erd
|
||||||
\end_inset
|
\end_inset
|
||||||
|
|
||||||
, telling they can't be changed anymore.
|
button if your route consists of more sections with turnouts to lock, and
|
||||||
Repeat the above procedure until you have punched the final TCB, at which
|
you need to continue programming.
|
||||||
the route should end.
|
Follow the above steps to set locks for the next section.
|
||||||
As mentioned before, there should be a signal at this place, however this
|
\end_layout
|
||||||
is not enforced.
|
|
||||||
Now, run the chat command
|
\begin_layout Standard
|
||||||
\family typewriter
|
Once you've clicked the
|
||||||
/at_rp_set <name of route>
|
\begin_inset Quotes eld
|
||||||
\family default
|
\end_inset
|
||||||
to complete programming the route.
|
|
||||||
|
Advance
|
||||||
|
\begin_inset Quotes erd
|
||||||
|
\end_inset
|
||||||
|
|
||||||
|
button, the lock markers change to a red lock symbol, telling they can't
|
||||||
|
be changed anymore.
|
||||||
|
Repeat the above procedure until you are ready to complete the programming
|
||||||
|
procedure:
|
||||||
|
\end_layout
|
||||||
|
|
||||||
|
\begin_layout Itemize
|
||||||
|
Click the
|
||||||
|
\begin_inset Quotes eld
|
||||||
|
\end_inset
|
||||||
|
|
||||||
|
Finish route HERE
|
||||||
|
\begin_inset Quotes erd
|
||||||
|
\end_inset
|
||||||
|
|
||||||
|
button when you've set up the locks for the last track section of the route
|
||||||
|
and punched the final TCB (the one with the next signal).
|
||||||
|
You will be asked for a route name and your route will be saved.
|
||||||
|
\end_layout
|
||||||
|
|
||||||
|
\begin_layout Itemize
|
||||||
|
The
|
||||||
|
\begin_inset Quotes eld
|
||||||
|
\end_inset
|
||||||
|
|
||||||
|
Finish route at end of NEXT section
|
||||||
|
\begin_inset Quotes erd
|
||||||
|
\end_inset
|
||||||
|
|
||||||
|
button (third button) is an useful quickhand to make the route proceed
|
||||||
|
one more section.
|
||||||
|
Using this button is equivalent to first clicking the
|
||||||
|
\begin_inset Quotes eld
|
||||||
|
\end_inset
|
||||||
|
|
||||||
|
Advance
|
||||||
|
\begin_inset Quotes erd
|
||||||
|
\end_inset
|
||||||
|
|
||||||
|
button, then flying to the end of the next track section and finishing
|
||||||
|
the route there.
|
||||||
|
You can not (officially) set turnout locks in the final section using this
|
||||||
|
method.
|
||||||
\end_layout
|
\end_layout
|
||||||
|
|
||||||
\begin_layout Standard
|
\begin_layout Standard
|
||||||
|
@ -994,19 +1037,46 @@ last
|
||||||
\end_layout
|
\end_layout
|
||||||
|
|
||||||
\begin_layout Itemize
|
\begin_layout Itemize
|
||||||
If you accidentally punched a TCB, you can run
|
If you accidentally advanced the route wrongly, you can use the
|
||||||
\family typewriter
|
\begin_inset Quotes eld
|
||||||
/at_rp_back
|
\end_inset
|
||||||
\family default
|
|
||||||
to undo this and return to the previous section.
|
Step back one section
|
||||||
Due to a bug, you have to re-set all locks of this section.
|
\begin_inset Quotes erd
|
||||||
|
\end_inset
|
||||||
|
|
||||||
|
button to undo this.
|
||||||
\end_layout
|
\end_layout
|
||||||
|
|
||||||
\begin_layout Itemize
|
\begin_layout Itemize
|
||||||
If you want to stop programming the entire route without saving it, run
|
If you want to stop programming the entire route without saving it, use
|
||||||
|
the
|
||||||
|
\begin_inset Quotes eld
|
||||||
|
\end_inset
|
||||||
|
|
||||||
\family typewriter
|
Cancel route programming
|
||||||
/at_rp_discard
|
\begin_inset Quotes erd
|
||||||
|
\end_inset
|
||||||
|
|
||||||
|
button.
|
||||||
|
\end_layout
|
||||||
|
|
||||||
|
\begin_layout Itemize
|
||||||
|
The third button is especially useful for programming simple block sections
|
||||||
|
on a main running line, since you can stay at the starting signal (punch
|
||||||
|
starting TCB and select third button).
|
||||||
|
\end_layout
|
||||||
|
|
||||||
|
\begin_layout Itemize
|
||||||
|
If a route should end in a dead end, you MUST use the
|
||||||
|
\begin_inset Quotes eld
|
||||||
|
\end_inset
|
||||||
|
|
||||||
|
Finish in NEXT section
|
||||||
|
\begin_inset Quotes erd
|
||||||
|
\end_inset
|
||||||
|
|
||||||
|
button, because there is no final TCB that you could punch.
|
||||||
\end_layout
|
\end_layout
|
||||||
|
|
||||||
\begin_layout Section
|
\begin_layout Section
|
||||||
|
@ -1105,5 +1175,53 @@ d access to a siding.
|
||||||
you need a train to go into the siding.
|
you need a train to go into the siding.
|
||||||
\end_layout
|
\end_layout
|
||||||
|
|
||||||
|
\begin_layout Section
|
||||||
|
Final notes
|
||||||
|
\end_layout
|
||||||
|
|
||||||
|
\begin_layout Standard
|
||||||
|
The interlocking system is mainly finished, though there are still some
|
||||||
|
plans and ideas.
|
||||||
|
They include:
|
||||||
|
\end_layout
|
||||||
|
|
||||||
|
\begin_layout Itemize
|
||||||
|
Setting routes from inside a train (via onboard computer)
|
||||||
|
\end_layout
|
||||||
|
|
||||||
|
\begin_layout Itemize
|
||||||
|
Signalbox panels, as revival of itrainmap
|
||||||
|
\end_layout
|
||||||
|
|
||||||
|
\begin_layout Itemize
|
||||||
|
Individual signal aspects for routes
|
||||||
|
\end_layout
|
||||||
|
|
||||||
|
\begin_layout Itemize
|
||||||
|
Distant signals
|
||||||
|
\end_layout
|
||||||
|
|
||||||
|
\begin_layout Itemize
|
||||||
|
On-Train head-up display for oncoming signals (they have something like
|
||||||
|
this in Czech Republic, I forgot how it's called.)
|
||||||
|
\end_layout
|
||||||
|
|
||||||
|
\begin_layout Standard
|
||||||
|
Apart from this, there's the large oncoming project of a new timetable-based
|
||||||
|
train automation system, but this will take some time to evolve and is
|
||||||
|
out of the scope of this document.
|
||||||
|
\end_layout
|
||||||
|
|
||||||
|
\begin_layout Standard
|
||||||
|
If you have any suggestions, corrections, improvements, criticism or cute
|
||||||
|
kittens and stuff, you can always contact me by various means (Forum PM,
|
||||||
|
E-Mail (orwell@bleipb.de), Linuxworks server chat a.s.o.).
|
||||||
|
Have fun!
|
||||||
|
\end_layout
|
||||||
|
|
||||||
|
\begin_layout Standard
|
||||||
|
- orwell
|
||||||
|
\end_layout
|
||||||
|
|
||||||
\end_body
|
\end_body
|
||||||
\end_document
|
\end_document
|
||||||
|
|