aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authororwell <orwell@bleipb.de>2024-11-14 00:03:38 +0100
committerorwell <orwell@bleipb.de>2024-11-14 00:03:38 +0100
commitfe57e7dd089653e2361a4ebb0b34137a3261e198 (patch)
tree0bc1be5e530f6a7af857b8cefe29c1da5ae29b8b
parentd42f1bcf1a7ec18d392671be54636e7cad8b788b (diff)
downloadadvtrains-fe57e7dd089653e2361a4ebb0b34137a3261e198.tar.gz
advtrains-fe57e7dd089653e2361a4ebb0b34137a3261e198.tar.bz2
advtrains-fe57e7dd089653e2361a4ebb0b34137a3261e198.zip
Add Blocksignal mode for signals to autocreate simple block route
-rw-r--r--advtrains_interlocking/database.lua7
-rw-r--r--advtrains_interlocking/route_prog.lua10
-rw-r--r--advtrains_interlocking/route_ui.lua3
-rw-r--r--advtrains_interlocking/routesetting.lua11
-rw-r--r--advtrains_interlocking/signal_api.lua2
-rwxr-xr-xadvtrains_interlocking/tcb_ts_ui.lua177
-rwxr-xr-xadvtrains_signals_ks/init.lua8
7 files changed, 143 insertions, 75 deletions
diff --git a/advtrains_interlocking/database.lua b/advtrains_interlocking/database.lua
index a8d9584..e77d073 100644
--- a/advtrains_interlocking/database.lua
+++ b/advtrains_interlocking/database.lua
@@ -261,8 +261,9 @@ routes = {
-- it is assumed that the next main signal will have its own distant sig
-- true: start signal sets distant signal to the next signal on the route with route_role "main" (typically the end signal)
-- for short blocks where end signal doesn't have its own distant sig
- -- Fields used by the autorouter:
- ar_end_sigd = <sigd> -- the sigd describing the end of the route. Used for merging route options on recalculation
+ terminal = <sigd> -- the sigd describing the end of the route (e.g. the "next" entry in the final route segment).
+ -- Might be missing or wrong. Routesetting currently does not care about this value being present.
+ default_autoworking = false -- if true, when route is set autoworking will be by default on. Used for Blocksignal mode
}
}
@@ -771,7 +772,7 @@ function ildb.update_rs_cache(ts_id)
end
-- warn about superfluous entry
for sup_end_pkey, sup_entry in pairs(result_table) do
- --atwarn("In update_rs_cache for section",ts_id,"found superfluous endpoint",sup_end_pkey,"->",sup_entry)
+ atwarn("In update_rs_cache for section",ts_id,"found superfluous endpoint",sup_end_pkey,"->",sup_entry)
end
end
ts.rs_cache = rscache
diff --git a/advtrains_interlocking/route_prog.lua b/advtrains_interlocking/route_prog.lua
index 3ab5686..2f0f8ee 100644
--- a/advtrains_interlocking/route_prog.lua
+++ b/advtrains_interlocking/route_prog.lua
@@ -111,15 +111,7 @@ end
--[[
Route definition:
-route = {
- name = <string>
- [n] = {
- next = <sigd>, -- of the next (note: next) TCB on the route
- locks = {<pts> = "state"} -- route locks of this route segment
- }
- terminal = <sigd>,
- aspect = <signal aspect>,--note, might change in future
-}
+=== See database.lua L238
The first item in the TCB path (namely i=0) is always the start signal of this route,
so this is left out.
All subsequent entries, starting from 1, contain:
diff --git a/advtrains_interlocking/route_ui.lua b/advtrains_interlocking/route_ui.lua
index 89580a8..2b79f68 100644
--- a/advtrains_interlocking/route_ui.lua
+++ b/advtrains_interlocking/route_ui.lua
@@ -110,7 +110,7 @@ function atil.show_route_edit_form(pname, sigd, routeid)
form = form.."button[2.5,6;1,1;next;>>>]"
- if route.smartroute_generated then
+ if route.smartroute_generated or route.default_autoworking then
form = form.."button[3.5,6;2,1;noautogen;Clr Autogen]"
end
form = form.."button[5.5,6;3,1;delete;Delete Route]"
@@ -180,6 +180,7 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
if fields.noautogen then
route.smartroute_generated = nil
+ route.default_autoworking = nil
end
if fields.delete then
diff --git a/advtrains_interlocking/routesetting.lua b/advtrains_interlocking/routesetting.lua
index a72f644..f2a00cd 100644
--- a/advtrains_interlocking/routesetting.lua
+++ b/advtrains_interlocking/routesetting.lua
@@ -171,7 +171,7 @@ function ilrs.set_route(signal, route, try)
-- note the signals are iterated backwards. Switch depending on the role
local sig = signals[i]
-- apply mainaspect
- sig.tcbs_ref.route_aspect = sig.masp_override or route.main_aspect or "_default"
+ sig.tcbs_ref.route_aspect = sig.masp_override or "_default" -- or route.main_aspect : TODO this does not work if a distant signal is on the path! Implement per-sig aspects!
if sig.role == "distant" or sig.role == "distant_repeater" or sig.role == "main_distant" then
if last_mainsig then
-- assign the remote as the last mainsig if desired
@@ -192,6 +192,8 @@ function ilrs.set_route(signal, route, try)
-- update the signal aspect on map
advtrains.interlocking.signal.update_route_aspect(sig.tcbs_ref, i ~= 1)
end
+ -- Only for the first signal on the route, set route aspect. TODO: remove when masp_overrides are implemented
+ signal.route_aspect = route.main_aspect or "_default"
return true
end
@@ -366,8 +368,9 @@ function ilrs.update_route(sigd, tcbs, newrte, cancel)
if newrte then tcbs.routeset = newrte end
--atdebug("Setting:",tcbs.routeset)
local succ, rsn, cbts, cblk
- if tcbs.routes[tcbs.routeset] then
- succ, rsn, cbts, cblk = ilrs.set_route(sigd, tcbs.routes[tcbs.routeset])
+ local route = tcbs.routes[tcbs.routeset]
+ if route then
+ succ, rsn, cbts, cblk = ilrs.set_route(sigd, route)
else
succ = false
rsn = attrans("Route state changed.")
@@ -390,6 +393,8 @@ function ilrs.update_route(sigd, tcbs, newrte, cancel)
--atdebug("Committed Route:",tcbs.routeset)
-- set_route now sets the signal aspects
--has_changed_aspect = true
+ -- route success. apply default_autoworking flag if requested
+ tcbs.route_auto = route.default_autoworking
end
end
if has_changed_aspect then
diff --git a/advtrains_interlocking/signal_api.lua b/advtrains_interlocking/signal_api.lua
index bf14247..9b0479f 100644
--- a/advtrains_interlocking/signal_api.lua
+++ b/advtrains_interlocking/signal_api.lua
@@ -312,7 +312,7 @@ function signal.get_aspect_internal(pos, aspt)
-- case is fine, distant only signal
masp = signal.MASP_DEFAULT
else
- assert(ndefat.main_aspects, "With named aspects, node needs advtrains.main_aspects table!")
+ assert(ndefat.main_aspects, "With named aspects, node "..node.name.." needs advtrains.main_aspects table!")
-- resolve the main aspect from the mainaspects table
if not ndefat.main_aspects_lookup then
cache_mainaspects(ndefat)
diff --git a/advtrains_interlocking/tcb_ts_ui.lua b/advtrains_interlocking/tcb_ts_ui.lua
index e7ff685..1cdbb29 100755
--- a/advtrains_interlocking/tcb_ts_ui.lua
+++ b/advtrains_interlocking/tcb_ts_ui.lua
@@ -618,48 +618,78 @@ function advtrains.interlocking.show_signalling_form(sigd, pname, sel_rte, calle
form = form.."button[0.5,6; 5,1;cancelroute;Cancel Route]"
else
if not tcbs.route_origin then
- local strtab = {}
- for idx, route in ipairs(tcbs.routes) do
- local clr = ""
- if route.smartroute_generated then
- clr = "#FFFF55"
- end
- if route.ars then
- clr = "#FF5555"
- if route.ars.default then
- clr = "#55FF55"
+ if #tcbs.routes > 0 then
+ -- at least one route is defined, show normal dialog
+ local strtab = {}
+ for idx, route in ipairs(tcbs.routes) do
+ local clr = ""
+ if route.smartroute_generated then
+ clr = "#FFFF55"
+ end
+ if route.ars then
+ clr = "#FF5555"
+ if route.ars.default then
+ clr = "#55FF55"
+ end
end
+ strtab[#strtab+1] = clr .. minetest.formspec_escape(route.name)
end
- strtab[#strtab+1] = clr .. minetest.formspec_escape(route.name)
- end
- form = form.."label[0.5,2.5;Routes:]"
- form = form.."textlist[0.5,3;5,3;rtelist;"..table.concat(strtab, ",")
- if sel_rte then
- form = form .. ";" .. sel_rte .."]"
- form = form.."button[0.5,6; 5,1;setroute;Set Route]"
- form = form.."button[0.5,7;2,1;dsproute;Show]"
- if hasprivs then
- form = form.."button[3.5,7;2,1;editroute;Edit]"
- if sel_rte > 1 then
- form = form .. "button[5.5,4;0.5,0.3;moveup;↑]"
+ form = form.."label[0.5,2.5;Routes:]"
+ form = form.."textlist[0.5,3;5,3;rtelist;"..table.concat(strtab, ",")
+ if sel_rte then
+ form = form .. ";" .. sel_rte .."]"
+ form = form.."button[0.5,6; 5,1;setroute;Set Route]"
+ form = form.."button[0.5,7;2,1;dsproute;Show]"
+ if hasprivs then
+ form = form.."button[3.5,7;2,1;editroute;Edit]"
+ if sel_rte > 1 then
+ form = form .. "button[5.5,4;0.5,0.3;moveup;↑]"
+ end
+ if sel_rte < #strtab then
+ form = form .. "button[5.5,4.7;0.5,0.3;movedown;↓]"
+ end
end
- if sel_rte < #strtab then
- form = form .. "button[5.5,4.7;0.5,0.3;movedown;↓]"
+ else
+ form = form .. "]"
+ if tcbs.ars_disabled then
+ form = form.."label[0.5,6 ;NOTE: ARS is disabled.]"
+ form = form.."label[0.5,6.5;Routes are not automatically set.]"
end
end
+ if hasprivs then
+ form = form.."button[0.5,8;2.5,1;smartroute;Smart Route]"
+ form = form.."button[ 3,8;2.5,1;newroute;New (Manual)]"
+ form = form..string.format("checkbox[0.5,8.75;ars;Automatic routesetting;%s]", not tcbs.ars_disabled)
+ form = form..string.format("checkbox[0.5,9.25;dstarstrig;Distant signal triggers ARS;%s]", not tcbs.no_dst_ars_trig)
+ end
else
- form = form .. "]"
- if tcbs.ars_disabled then
- form = form.."label[0.5,6 ;NOTE: ARS is disabled.]"
- form = form.."label[0.5,6.5;Routes are not automatically set.]"
+ -- no route is active, and no route is so far defined
+ if not tcbs.signal then atwarn("signalling form missing signal?!", pos) return end -- safeguard, nothing else in this function checks tcbs.signal
+ local caps = advtrains.interlocking.signal.get_signal_cap_level(tcbs.signal)
+ if caps >= 3 then
+ -- offer user the "block signal mode"
+ form = form.."label[0.5,2.5;No routes are yet defined.]"
+ if hasprivs then
+ form = form.."button[0.5,4;2.5,1;smartroute;Smart Route]"
+ form = form.."button[ 3,4;2.5,1;newroute;New (Manual)]"
+
+ form = form.."label[0.5,5.5;Setup block signal route (up to following signal):]"
+ form = form.."button[0.5,6;2.5,1;setupblocklong;Long (No Dst)]"
+ form = form.."tooltip[setupblocklong;Following track section must have no turnouts and end at another signal.\n"
+ .."Sets a route into the section ahead with auto-working set on\n"
+ .."Long block: This signal does not become distant signal.]"
+ form = form.."button[ 3,6;2.5,1;setupblockshort;Short (With Dst)]"
+ form = form.."tooltip[setupblockshort;Following track section must have no turnouts and end at another signal.\n"
+ .."Sets a route into the section ahead with auto-working set on\n"
+ .."Short block: This signal becomes distant signal for next signal.]"
+ end
+ else
+ -- signal caps say it cannot be route start/end
+ form = form.."label[0.5,2.5;This is a Non-Halt signal (e.g. pure distant signal)\n"
+ .."No route is currently set through.]"
end
end
- if hasprivs then
- form = form.."button[0.5,8;2.5,1;smartroute;Smart Route]"
- form = form.."button[ 3,8;2.5,1;newroute;New (Manual)]"
- form = form..string.format("checkbox[0.5,8.75;ars;Automatic routesetting;%s]", not tcbs.ars_disabled)
- form = form..string.format("checkbox[0.5,9.25;dstarstrig;Distant signal triggers ARS;%s]", not tcbs.no_dst_ars_trig)
- end
+
elseif sigd_equal(tcbs.route_origin, sigd) then
-- something has gone wrong: tcbs.routeset should have been set...
form = form.."label[0.5,2.5;Inconsistent state: route_origin is same TCBS but no route set. Try again.]"
@@ -753,6 +783,63 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
tcbs.ars_ignore_next = nil
return
end
+ if (fields.setupblocklong or fields.setupblockshort) and hasprivs then
+ -- check adjacent section
+ if not tcbs.ts_id then
+ minetest.chat_send_player(pname, "Block route not possible: No track section ahead")
+ return
+ end
+ local ts = ildb.get_ts(tcbs.ts_id)
+ if #ts.tc_breaks ~= 2 then
+ minetest.chat_send_player(pname, "Block route not possible: Section "..(ts.name or "-").." ("..tcbs.ts_id..") has "..#ts.tc_breaks.." ends, must be 2")
+ return
+ end
+ local e_sigd
+ if vector.equals(ts.tc_breaks[1].p, pos) then
+ e_sigd = { p = ts.tc_breaks[2].p,
+ s = ts.tc_breaks[2].s==1 and 2 or 1}
+ elseif vector.equals(ts.tc_breaks[2].p, pos) then
+ e_sigd = { p = ts.tc_breaks[1].p,
+ s = ts.tc_breaks[1].s==1 and 2 or 1}
+ else
+ minetest.chat_send_player(pname, "Block route not possible: Section "..(ts.name or "-").." ("..tcbs.ts_id..") TCBs are inconsistent, check section!")
+ return
+ end
+ local e_tcbs = ildb.get_tcbs(e_sigd)
+ if not e_tcbs then
+ minetest.chat_send_player(pname, "Block route not possible: Adjacent TCB not found, check section!")
+ return
+ end
+ -- now we have the TCB at the end of the following section. check that signal is set
+ if not e_tcbs.signal then
+ minetest.chat_send_player(pname, "Block route not possible: Adjacent TCB has no signal assigned!")
+ return
+ end
+ local caps = advtrains.interlocking.signal.get_signal_cap_level(e_tcbs.signal)
+ if caps < 3 then
+ minetest.chat_send_player(pname, "Block route not possible: Following signal is not capable of displaying a Halt aspect (caplevel "..caps..")")
+ return
+ end
+ -- all preconditions checked! go ahead and create route
+ local route = {
+ name = "BS",
+ [1] = {
+ next = e_sigd, -- of the next (note: next) TCB on the route
+ locks = {} -- route locks of this route segment
+ },
+ terminal = e_sigd,
+ use_rscache = true,
+ -- main_aspect = <use default>
+ assign_dst = fields.setupblockshort and true, -- assign dst, if short block was selected
+ default_autoworking = true,
+ }
+ local rid = #tcbs.routes + 1 -- typically 1
+ tcbs.routes[rid] = route
+ -- directly set our newly created route
+ ilrs.update_route(sigd, tcbs, rid)
+ advtrains.interlocking.show_signalling_form(sigd, pname, nil, true)
+ return
+ end
if sel_rte and tcbs.routes[sel_rte] then
if fields.setroute then
ilrs.update_route(sigd, tcbs, sel_rte)
@@ -764,8 +851,6 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
end
if fields.editroute and hasprivs then
advtrains.interlocking.show_route_edit_form(pname, sigd, sel_rte)
- --local rte = tcbs.routes[sel_rte]
- --minetest.show_formspec(pname, formname.."_renroute_"..sel_rte, "field[name;Enter new route name;"..rte.name.."]")
return
end
end
@@ -803,24 +888,4 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
advtrains.interlocking.show_signalling_form(sigd, pname, sel_rte, true)
return
end
-
-
- if not hasprivs then return end
- -- rename route
- local rind, rte_id
- pts, connids, rind = string.match(formname, "^at_il_signalling_([^_]+)_(%d)_renroute_(%d+)$")
- if pts then
- pos = minetest.string_to_pos(pts)
- connid = tonumber(connids)
- rte_id = tonumber(rind)
- if not connid or connid<1 or connid>2 then return end
- end
- if pos and connid and rind and fields.name then
- local sigd = {p=pos, s=connid}
- local tcbs = ildb.get_tcbs(sigd)
- if tcbs.routes[rte_id] then
- tcbs.routes[rte_id].name = fields.name
- advtrains.interlocking.show_signalling_form(sigd, pname)
- end
- end
end)
diff --git a/advtrains_signals_ks/init.lua b/advtrains_signals_ks/init.lua
index c0e74ea..a85bec9 100755
--- a/advtrains_signals_ks/init.lua
+++ b/advtrains_signals_ks/init.lua
@@ -161,7 +161,7 @@ end
-- Main aspects shunt signal
-- Shunt signals have only two states, distant doesn't matter
-local mainaspects_shunt = {
+local mainaspects_ra = {
{
name = "shunt",
description = "Shunt",
@@ -335,6 +335,10 @@ for _, rtab in ipairs({
}) do
local sbox = table.copy(rtab.sbox)
sbox[5] = 0
+ local afunc = prts.asp
+ if type(afunc) == "table" then
+ afunc = function() return prts.asp end
+ end
minetest.register_node("advtrains_signals_ks:ra_"..typ.."_"..rot, {
description = "Ks Shunting Signal",
drawtype = "mesh",
@@ -366,7 +370,7 @@ for _, rtab in ipairs({
advtrains = {
main_aspects = mainaspects_ra,
apply_aspect = applyaspectf_ra(rot),
- get_aspect_info = prts.asp,
+ get_aspect_info = afunc,
route_role = "shunt",
trackworker_next_rot = "advtrains_signals_ks:ra_"..typ.."_"..rtab.nextrot,
trackworker_rot_incr_param2 = (rot=="60")