diff options
Diffstat (limited to 'advtrains_interlocking')
-rw-r--r-- | advtrains_interlocking/approach.lua | 9 | ||||
-rw-r--r-- | advtrains_interlocking/ars.lua | 4 | ||||
-rw-r--r-- | advtrains_interlocking/database.lua | 22 | ||||
-rw-r--r-- | advtrains_interlocking/signal_api.lua | 32 | ||||
-rw-r--r-- | advtrains_interlocking/spec/ars_spec.lua | 67 | ||||
-rwxr-xr-x | advtrains_interlocking/tcb_ts_ui.lua | 13 |
6 files changed, 135 insertions, 12 deletions
diff --git a/advtrains_interlocking/approach.lua b/advtrains_interlocking/approach.lua index f60468a..eecf09a 100644 --- a/advtrains_interlocking/approach.lua +++ b/advtrains_interlocking/approach.lua @@ -14,19 +14,19 @@ local SHUNT_SPEED_MAX = advtrains.SHUNT_SPEED_MAX local il = advtrains.interlocking -local function get_over_function(speed, shunt) +local function get_over_function(speed, shunt, asptype) return function(pos, id, train, index, speed, lzbdata) if speed == 0 and minetest.settings:get_bool("at_il_force_lzb_halt") then atwarn(id,"overrun LZB 0 restriction (red signal) ",pos) -- Set train 1 index backward. Hope this does not lead to bugs... --train.index = index - 0.5 - train.speed_restriction = 0 + advtrains.speed.set_restriction(train, "main", 0) --TODO temporary --advtrains.drb_dump(id) --error("Debug: "..id.." triggered LZB-0") else - train.speed_restriction = speed + advtrains.speed.set_restriction(train, asptype, speed or -1) train.is_shunt = shunt end --atdebug("train drove over IP: speed=",speed,"shunt=",shunt) @@ -94,6 +94,7 @@ advtrains.tnc_register_on_approach(function(pos, id, train, index, has_entered, end -- nspd can now be: 1. !=0: new speed restriction, 2. =0: stop here or 3. nil: keep travspd if nspd then + travspd = nspd if nspd == -1 then travspd = nil else @@ -106,7 +107,7 @@ advtrains.tnc_register_on_approach(function(pos, id, train, index, has_entered, lspd = travspd local udata = {signal_pos = spos} - local callback = get_over_function(lspd, travsht) + local callback = get_over_function(lspd, travsht, asp.type) lzbdata.il_shunt = travsht lzbdata.il_speed = travspd --atdebug("new lzbdata",lzbdata) diff --git a/advtrains_interlocking/ars.lua b/advtrains_interlocking/ars.lua index 434ae2c..4f50df9 100644 --- a/advtrains_interlocking/ars.lua +++ b/advtrains_interlocking/ars.lua @@ -133,9 +133,11 @@ function advtrains.interlocking.ars_check(sigd, train) local tcbs = il.db.get_tcbs(sigd) if not tcbs or not tcbs.routes then return end - if tcbs.ars_disabled then + if tcbs.ars_disabled or tcbs.ars_ignore_next then -- No-ARS mode of signal. -- ignore... + -- Note: ars_ignore_next is set by signalling formspec when route is cancelled + tcbs.ars_ignore_next = nil return end diff --git a/advtrains_interlocking/database.lua b/advtrains_interlocking/database.lua index a35d446..6787c50 100644 --- a/advtrains_interlocking/database.lua +++ b/advtrains_interlocking/database.lua @@ -634,6 +634,28 @@ function ildb.get_ip_by_signalpos(spos) end end end +function ildb.check_for_duplicate_ip(spos) + local main_ip_found = false + -- first pass: check for duplicates + for pts,tab in pairs(influence_points) do + for connid,pos in pairs(tab) do + if vector.equals(pos, spos) then + if main_ip_found then + atwarn("Signal at",spos,": Deleting duplicate signal influence point at",pts,"/",connid) + tab[connid] = nil + end + main_ip_found = true + end + end + end + -- second pass: delete empty tables + for pts,tab in pairs(influence_points) do + if not tab[1] and not tab[2] then -- only those two connids may exist + influence_points[pts] = nil + end + end +end + -- clear signal assignment given the signal position function ildb.clear_ip_by_signalpos(spos) local pts, connid = ildb.get_ip_by_signalpos(spos) diff --git a/advtrains_interlocking/signal_api.lua b/advtrains_interlocking/signal_api.lua index a44eda6..83fae4a 100644 --- a/advtrains_interlocking/signal_api.lua +++ b/advtrains_interlocking/signal_api.lua @@ -326,6 +326,7 @@ function advtrains.interlocking.show_ip_form(pos, pname, only_notset) return end local form = "size[7,5]label[0.5,0.5;Signal at "..minetest.pos_to_string(pos).."]" + advtrains.interlocking.db.check_for_duplicate_ip(pos) local pts, connid = advtrains.interlocking.db.get_ip_by_signalpos(pos) if pts then form = form.."label[0.5,1.5;Influence point is set at "..pts.."/"..connid.."]" @@ -428,7 +429,7 @@ function advtrains.interlocking.show_signal_aspect_selector(pname, p_suppasp, p_ } local purpose = p_purpose or "" - local form = "size[7,5]label[0.5,0.5;Select Signal Aspect:]" + local form = "size[7,7]label[0.5,0.5;Select Signal Aspect:]" form = form.."label[0.5,1;"..purpose.."]" form = form.."label[0.5,1.5;== Main Signal ==]" @@ -460,8 +461,29 @@ function advtrains.interlocking.show_signal_aspect_selector(pname, p_suppasp, p_ if isasp and isasp.shunt then st=2 end form = form.."dropdown[0.5,3.5;6;shunt_free;---,allowed;"..st.."]" end - - form = form.."button_exit[0.5,4.5; 5,1;save;OK]" + + form = form.."label[0.5,4.5;== Distant Signal ==]" + local selid = 1 + local entries = {} + for idx, spv in ipairs(suppasp.dst) do + local entry + if spv == 0 then + entry = "Expect to stop at the next signal" + elseif spv == -1 then + entry = "Expect to pass the next signal at maximum speed" + elseif not spv then + entry = "No info" + else + entry = string.format("Expect to pass the next signal at speed of %d", spv) + end + entries[idx] = idx.."| "..entry + if isasp and spv == (isasp.dst or false) then + selid = idx + end + end + form = form.."dropdown[0.5,5;6;dst;"..table.concat(entries, ",")..";"..selid.."]" + + form = form.."button_exit[0.5,6;5,1;save;Save signal aspect]" local token = advtrains.random_id() @@ -499,9 +521,11 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) if fields.save then local maini = ddindex(fields.main) if not maini then return end + local dsti = ddindex(fields.dst) + if not dsti then return end local asp = { main = psl.suppasp.main[maini], - dst = false, + dst = psl.suppasp.dst[dsti], shunt = usebool(psl.suppasp.shunt, fields.shunt_free, "allowed"), info = {} } diff --git a/advtrains_interlocking/spec/ars_spec.lua b/advtrains_interlocking/spec/ars_spec.lua new file mode 100644 index 0000000..085dbcb --- /dev/null +++ b/advtrains_interlocking/spec/ars_spec.lua @@ -0,0 +1,67 @@ +-- test the serialization function + + +package.path = "../?.lua;" .. package.path + + + + +_G.advtrains = {} +_G.advtrains.interlocking = {} + +require("ars") + +local arstb = {{ ln="Foo"}, {c="Bar"}, {n=true, rc="Boo"}} +local arsdef = {{ ln="Foo"}, {c="Bar"}, {rc="Boo"}, default=true} +local arstr = [[LN Foo +#Bar +!RC Boo]] +local defstr = [[* +LN Foo +#Bar +RC Boo]] +il = _G.advtrains.interlocking + +describe("ars_to_text", function () + it("read table", function () + assert.equals(il.ars_to_text(arstb),arstr) + end) + it("reads back and forth", function () + assert.equals(il.ars_to_text(il.text_to_ars(arstr)),arstr) + end) + it("handles default routes properly", function () + assert.equals(il.ars_to_text(arsdef),defstr) + end) +end) + +describe("text_to_ars", function () + it("writes table", function() + assert.same(il.text_to_ars(arstr),arstb) + end) + it("handles default routes properly", function () + assert.same(il.text_to_ars(defstr),arsdef) + end) +end) + +train1 = {} +train2 = {} +train3 = {} +train1.line = "Foo" +train1.routingcode = "Boo" +train2.line= "Bar" +train2.routingcode = "NotBoo NotBoo" +train3.routingcode = "Foo Boo Moo Zoo" + +describe("check_rule_match", function () + it("matches rules correctly", function() + assert.equals(il.ars_check_rule_match(arstb,train1),1) + assert.equals(il.ars_check_rule_match(arsdef,train2),nil) + end) + it("matches negative rules", function() + assert.equals(il.ars_check_rule_match(arstb,train2),3) + assert.equals(il.ars_check_rule_match(arstb,train3),nil) + end) + it("matches RC in a list correctly", function() + assert.equals(il.ars_check_rule_match(arsdef,train3),3) + end) +end) diff --git a/advtrains_interlocking/tcb_ts_ui.lua b/advtrains_interlocking/tcb_ts_ui.lua index 34fbf7f..0cc10da 100755 --- a/advtrains_interlocking/tcb_ts_ui.lua +++ b/advtrains_interlocking/tcb_ts_ui.lua @@ -723,11 +723,17 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) connid = tonumber(connids) if not connid or connid<1 or connid>2 then return end end - if pos and connid and not fields.quit then + if pos and connid then local sigd = {p=pos, s=connid} local tcbs = ildb.get_tcbs(sigd) if not tcbs then return end - + + if fields.quit then + -- form quit: disable temporary ARS ignore + tcbs.ars_ignore_next = nil + return + end + local sel_rte if fields.rtelist then local tev = minetest.explode_textlist_event(fields.rtelist) @@ -740,7 +746,7 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) end if tcbs.routeset and fields.cancelroute then if tcbs.routes[tcbs.routeset] and tcbs.routes[tcbs.routeset].ars then - tcbs.ars_disabled = true + tcbs.ars_ignore_next = true end -- if route committed, cancel route ts info ilrs.update_route(sigd, tcbs, nil, true) @@ -749,6 +755,7 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) if fields.newroute and hasprivs then advtrains.interlocking.init_route_prog(pname, sigd) minetest.close_formspec(pname, formname) + tcbs.ars_ignore_next = nil return end if sel_rte and tcbs.routes[sel_rte] then |