From f8c2ec60d6fe1927b444aae51c3bce075ed05208 Mon Sep 17 00:00:00 2001 From: orwell Date: Sun, 17 Dec 2023 12:20:22 +0100 Subject: Signals can have nil name, documentation on route def --- advtrains_interlocking/route_prog.lua | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) (limited to 'advtrains_interlocking/route_prog.lua') diff --git a/advtrains_interlocking/route_prog.lua b/advtrains_interlocking/route_prog.lua index 6abe431..5fd9363 100644 --- a/advtrains_interlocking/route_prog.lua +++ b/advtrains_interlocking/route_prog.lua @@ -19,6 +19,11 @@ C. punch a turnout (or some other passive component) to fix its state (toggle) The route visualization will also be used to visualize routes after they have been programmed. ]]-- +-- TODO duplicate +local lntrans = { "A", "B" } +local function sigd_to_string(sigd) + return minetest.pos_to_string(sigd.p).." / "..lntrans[sigd.s] +end -- table with objectRefs local markerent = {} @@ -237,10 +242,10 @@ local function get_last_route_item(origin, route) return route[#route].next end -local function do_advance_route(pname, rp, sigd, tsname) +local function do_advance_route(pname, rp, sigd, tsref) table.insert(rp.route, {next = sigd, locks = rp.tmp_lcks}) rp.tmp_lcks = {} - chat(pname, "Added track section '"..tsname.."' to the route.") + chat(pname, "Added track section '"..(tsref and (tsref.name or "") or "--EOI--").."' to the route.") end local function finishrpform(pname) @@ -253,8 +258,9 @@ local function finishrpform(pname) local term_tcbs = advtrains.interlocking.db.get_tcbs(terminal) if term_tcbs.signal then + local signalname = (term_tcbs.signal_name or "") .. sigd_to_string(terminal) form = form .. "label[0.5,1.5;Route ends at signal:]" - form = form .. "label[0.5,2 ;"..term_tcbs.signal_name.."]" + form = form .. "label[0.5,2 ;"..signalname.."]" 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.]" @@ -423,20 +429,20 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) if fields.advance then -- advance route if not is_endpoint then - do_advance_route(pname, rp, this_sigd, this_ts.name) + do_advance_route(pname, rp, this_sigd, this_ts) end end if fields.endhere then if not is_endpoint then - do_advance_route(pname, rp, this_sigd, this_ts.name) + do_advance_route(pname, rp, this_sigd, this_ts) 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) + do_advance_route(pname, rp, this_sigd, this_ts) end - do_advance_route(pname, rp, over_sigd, over_ts and over_ts.name or "--EOI--") + do_advance_route(pname, rp, over_sigd, over_ts) finishrpform(pname) end end -- cgit v1.2.3 From 9fa43cb7bfc25ba71d16c8210f0074797a7bca1a Mon Sep 17 00:00:00 2001 From: orwell Date: Sun, 28 Jan 2024 00:42:28 +0100 Subject: Implement routesetting incorporating tscache, other improvements --- advtrains/passive.lua | 2 +- advtrains_interlocking/database.lua | 221 +++++++++++++++++++++----------- advtrains_interlocking/route_prog.lua | 2 + advtrains_interlocking/routesetting.lua | 43 +++++-- advtrains_interlocking/tcb_ts_ui.lua | 5 +- advtrains_interlocking/tool.lua | 6 +- 6 files changed, 185 insertions(+), 94 deletions(-) (limited to 'advtrains_interlocking/route_prog.lua') diff --git a/advtrains/passive.lua b/advtrains/passive.lua index 741d7df..231da82 100644 --- a/advtrains/passive.lua +++ b/advtrains/passive.lua @@ -57,7 +57,7 @@ function advtrains.setstate(parpos, newstate, pnode) return false, "train_here" end - if advtrains.interlocking and advtrains.interlocking.route.has_route_lock(minetest.pos_to_string(pos)) then + if advtrains.interlocking and advtrains.interlocking.route.has_route_lock(minetest.encode_pos(pos)) then return false, "route_lock_here" end diff --git a/advtrains_interlocking/database.lua b/advtrains_interlocking/database.lua index 5d42309..17a4199 100644 --- a/advtrains_interlocking/database.lua +++ b/advtrains_interlocking/database.lua @@ -84,11 +84,34 @@ function ildb.load(data) if pos then -- that was a pos_to_string local epos = advtrains.encode_pos(pos) + atdebug("ILDB converting TCB position format",pts,"->",epos) track_circuit_breaks[epos] = tcb else -- keep entry, it is already new track_circuit_breaks[pts] = tcb end + -- convert the routes.[].locks table keys + for t_side,tcbs in pairs(tcb) do + if tcbs.routes then + for t_rnum,route in pairs(tcbs.routes) do + for t_rsnm,rseg in ipairs(route) do + local locks_n = {} + for lpts,state in pairs(rseg.locks) do + local lpos = minetest.string_to_pos(lpts) + if lpos then + local epos = advtrains.encode_pos(lpos) + atdebug("ILDB converting tcb",pts,"side",t_side,"route",t_route,"lock position format",lpts,"->",epos) + locks_n[epos] = state + else + -- already correct format + locks_n[lpts] = state + end + end + rseg.locks = locks_n + end + end + end + end end end end @@ -99,7 +122,23 @@ function ildb.load(data) signal_assignments = data.signalass end if data.rs_locks then - advtrains.interlocking.route.rte_locks = data.rs_locks + if data.tcbpts_conversion_applied then + advtrains.interlocking.route.rte_locks = data.rs_locks + else + advtrains.interlocking.route.rte_locks = {} + for pts, lta in pairs(data.rs_locks) do + local pos = minetest.string_to_pos(pts) + if pos then + -- that was a pos_to_string + local epos = advtrains.encode_pos(pos) + atdebug("ILDB converting Route Lock position format",pts,"->",epos) + advtrains.interlocking.route.rte_locks[epos] = lta + else + -- keep entry, it is already new + advtrains.interlocking.route.rte_locks[pts] = lta + end + end + end end if data.rs_callbacks then advtrains.interlocking.route.rte_callbacks = data.rs_callbacks @@ -197,8 +236,8 @@ routes = { -- one table for each track section on the route -- Note that the section ID is implicitly inferred from the TCB 1 = { - locks = { -- component locks for this section of the route. Not used when use_rscache is true. - (-16,9,0) = st + locks = { -- component locks for this section of the route. + 800080008000 = st } next = S[(-23,9,0)/2] -- the start TCB of the next route segment (pointing forward) } @@ -208,7 +247,8 @@ routes = { } name = "" ars = { } - use_rscache = false -- if true, instead of "locks", the track section's rs_cache will be used to set locks + use_rscache = false -- if true, the track section's rs_cache will be used to set locks in addition to the locks table + -- this is disabled for legacy routes, but enabled for all new routes by default -- Fields used by the autorouter: ar_end_sigd = -- the sigd describing the end of the route. Used for merging route options on recalculation } @@ -218,10 +258,12 @@ Track section [id] = { name = "Some human-readable name" tc_breaks = { ,... } -- Bounding TC's (signal specifiers) - rs_cache = { [] = { [] = { [] = "state" } } } + rs_cache = { [startTcbPosEnc] = { [endTcbPosEnc] = { [componentPosEnc] = "state" } } } -- Saves the turnout states that need to be locked when a route is set from tcb#x to tcb#y - -- e.g. 1 = { 2 = { "800080008000" = "st" } } + -- e.g. "800080008005" = { "800080007EEA" = { "800080008000" = "st" } } + -- start TCB end TCB switch pos -- Recalculated on every change via update_rs_cache + -- Note that the tcb side number is not saved because it is unnecessary route = { origin = , -- route origin @@ -281,17 +323,24 @@ function ildb.get_all_ts() return track_sections end +function tsrepair_notify(notify_pname, ...) + if notify_pname then + minetest.chat_send_player(notify_pname, advtrains.print_concat_table({"TS Check:",...})) + end +end + -- Checks the consistency of the track section at the given position, attempts to autorepair track sections if they are inconsistent -- There are 2 operation modes: -- 1: pos is NOT a TCB, tcb_connid MUST be nil -- 2: pos is a TCB, tcb_connid MUST be given -- @param pos: the position to start from --- @param tcb_connid: If provided node is a TCB, +-- @param tcb_connid: If provided node is a TCB, the direction in which to search +-- @param notify_pname: the player to notify about reparations -- Returns: -- ts_id - the track section that was found -- nil - No track section exists -function ildb.check_and_repair_ts_at_pos(pos, tcb_connid) - atdebug("check_and_repair_ts_at_pos", pos, tcb_connid) +function ildb.check_and_repair_ts_at_pos(pos, tcb_connid, notify_pname) + --atdebug("check_and_repair_ts_at_pos", pos, tcb_connid) -- check prereqs if ildb.get_tcb(pos) then if not tcb_connid then error("check_and_repair_ts_at_pos: Startpoint is TCB, must provide tcb_connid!") end @@ -315,15 +364,17 @@ function ildb.check_and_repair_ts_at_pos(pos, tcb_connid) -- these must be the same as the first if ts_id ~= tcbs_ts_id then -- inconsistency is found, repair it - atdebug("check_and_repair_ts_at_pos: Inconsistency is found!") - return ildb.repair_ts_merge_all(all_tcbs) + --atdebug("check_and_repair_ts_at_pos: Inconsistency is found!") + tsrepair_notify(notify_pname, "Track section inconsistent here, repairing...") + return ildb.repair_ts_merge_all(all_tcbs, false, notify_pname) -- Step2 check is no longer necessary since we just created that new section end end end -- only one found (it is either nil or a ts id) - atdebug("check_and_repair_ts_at_pos: TS consistent id=",ts_id,"") + --atdebug("check_and_repair_ts_at_pos: TS consistent id=",ts_id,"") if not ts_id then + tsrepair_notify(notify_pname, "No track section found here.") return -- All TCBs agreed that there is no section here. end @@ -338,9 +389,11 @@ function ildb.check_and_repair_ts_at_pos(pos, tcb_connid) -- ildb.tcbs_ensure_ts_ref_exists(sigd) has already make sure that all tcbs are found in the ts's tc_breaks list -- That means it is sufficient to compare the LENGTHS of both lists, if one is longer then it is inconsistent if #ts.tc_breaks ~= #all_tcbs then - atdebug("check_and_repair_ts_at_pos: Partition is found!") - return ildb.repair_ts_merge_all(all_tcbs) + --atdebug("check_and_repair_ts_at_pos: Partition is found!") + tsrepair_notify(notify_pname, "Track section partition found, repairing...") + return ildb.repair_ts_merge_all(all_tcbs, false, notify_pname) end + tsrepair_notify(notify_pname, "Found section", ts.name or ts_id, "here.") return ts_id end @@ -367,7 +420,7 @@ end -- Returns: a list of sigd's describing the TCBs found (sigd's point inward): -- {p=, s=, tcbs=} function ildb.get_all_tcbs_adjacent(inipos, inidir, per_track_callback) - atdebug("get_all_tcbs_adjacent: inipos",inipos,"inidir",inidir,"") + --atdebug("get_all_tcbs_adjacent: inipos",inipos,"inidir",inidir,"") local found_sigd = {} local ti = advtrains.get_track_iterator(inipos, inidir, TS_MAX_SCAN, true) -- if initial start is TCBS and has xlink, need to add that to the TI @@ -377,7 +430,7 @@ function ildb.get_all_tcbs_adjacent(inipos, inidir, per_track_callback) ildb.validate_tcb_xlink(inisi, true) if initcbs.xlink then -- adding the tcb will happen when this branch is retrieved again using ti:next_branch() - atdebug("get_all_tcbs_adjacent: Putting xlink Branch for initial node",initcbs.xlink) + --atdebug("get_all_tcbs_adjacent: Putting xlink Branch for initial node",initcbs.xlink) ti:add_branch(initcbs.xlink.p, initcbs.xlink.s) end end @@ -400,17 +453,17 @@ function ildb.get_all_tcbs_adjacent(inipos, inidir, per_track_callback) -- A branch cannot be a TCB, as that would imply that it was a turnout/crossing (illegal) -- UNLESS: (a) it is the start point or (b) it was added via xlink -- Then the correct conn to use is connid (pointing forward) - atdebug("get_all_tcbs_adjacent: Inserting TCB at branch start",pos, connid) + --atdebug("get_all_tcbs_adjacent: Inserting TCB at branch start",pos, connid) using_connid = connid end -- add the sigd of this tcb and a reference to the tcb table in it - atdebug("get_all_tcbs_adjacent: Found TCB: ",pos, using_connid, "ts=", tcb[using_connid].ts_id) + --atdebug("get_all_tcbs_adjacent: Found TCB: ",pos, using_connid, "ts=", tcb[using_connid].ts_id) local si = {p=pos, s=using_connid, tcbs=tcb[using_connid]} -- if xlink exists, add it now (only if we are not in branch start) ildb.validate_tcb_xlink(si, true) if not is_branch_start and si.tcbs.xlink then -- adding the tcb will happen when this branch is retrieved again using ti:next_branch() - atdebug("get_all_tcbs_adjacent: Putting xlink Branch",si.tcbs.xlink) + --atdebug("get_all_tcbs_adjacent: Putting xlink Branch",si.tcbs.xlink) ti:add_branch(si.tcbs.xlink.p, si.tcbs.xlink.s) end insert_sigd_if_not_present(found_sigd, si) @@ -429,8 +482,8 @@ end -- Called by frontend functions when multiple tcbs's that logically belong to one section have been determined to have different sections -- Parameter is the output of ildb.get_all_tcbs_adjacent(pos) -- Returns the ID of the track section that results after the merge -function ildb.repair_ts_merge_all(all_tcbs, force_create) - atdebug("repair_ts_merge_all: Instructed to merge sections of following TCBs:") +function ildb.repair_ts_merge_all(all_tcbs, force_create, notify_pname) + --atdebug("repair_ts_merge_all: Instructed to merge sections of following TCBs:") -- The first loop does the following for each TCBS: -- a) Store the TS ID in the set of TS to update -- b) Set the TS ID to nil, so that the TCBS gets removed from the section @@ -439,7 +492,7 @@ function ildb.repair_ts_merge_all(all_tcbs, force_create) local any_ts = false for _,sigd in ipairs(all_tcbs) do local ts_id = sigd.tcbs.ts_id - atdebug(sigd, "ts=", ts_id) + --atdebug(sigd, "ts=", ts_id) if ts_id then local ts = track_sections[ts_id] if ts then @@ -455,7 +508,7 @@ function ildb.repair_ts_merge_all(all_tcbs, force_create) end if not any_ts and not force_create then -- nothing to do at all, just no interlocking. Why were we even called - atdebug("repair_ts_merge_all: No track section present, will not create a new one") + --atdebug("repair_ts_merge_all: No track section present, will not create a new one") return nil end -- Purge every TS in turn. TS's that are now empty will be deleted. TS's that still have TCBs will be kept @@ -464,6 +517,7 @@ function ildb.repair_ts_merge_all(all_tcbs, force_create) end -- Create a new fresh track section with all the TCBs we have in our collection local new_ts_id, new_ts = ildb.create_ts_from_tcb_list(all_tcbs) + tsrepair_notify(notify_pname, "Created track section",new_ts_id,"from TCBs:", all_tcbs) return new_ts_id end @@ -487,20 +541,20 @@ function ildb.purge_ts_tcb_refs(ts_id) i = i+1 else -- this one is to be purged - atdebug("purge_ts_tcb_refs(",ts_id,"): purging",sigd,"(backreference = ",tcbs.ts_id,")") + --atdebug("purge_ts_tcb_refs(",ts_id,"): purging",sigd,"(backreference = ",tcbs.ts_id,")") table.remove(ts.tc_breaks, i) has_changed = true end else -- if not tcbs: was anyway an orphan, remove it - atdebug("purge_ts_tcb_refs(",ts_id,"): purging",sigd,"(referred nonexisting TCB)") + --atdebug("purge_ts_tcb_refs(",ts_id,"): purging",sigd,"(referred nonexisting TCB)") table.remove(ts.tc_breaks, i) has_changed = true end end if #ts.tc_breaks == 0 then -- remove the section completely - atdebug("purge_ts_tcb_refs(",ts_id,"): after purging, the section is empty, is being deleted") + --atdebug("purge_ts_tcb_refs(",ts_id,"): after purging, the section is empty, is being deleted") track_sections[ts_id] = nil return nil else @@ -520,14 +574,14 @@ function ildb.tcbs_ensure_ts_ref_exists(sigd) if not tcbs or not tcbs.ts_id then return end local ts = ildb.get_ts(tcbs.ts_id) if not ts then - atdebug("tcbs_ensure_ts_ref_exists(",sigd,"): TS does not exist, setting to nil") + --atdebug("tcbs_ensure_ts_ref_exists(",sigd,"): TS does not exist, setting to nil") -- TS is deleted, clear own ts id tcbs.ts_id = nil return end local did_insert = insert_sigd_if_not_present(ts.tc_breaks, {p=sigd.p, s=sigd.s}) if did_insert then - atdebug("tcbs_ensure_ts_ref_exists(",sigd,"): TCBS was missing reference in TS",tcbs.ts_id) + --atdebug("tcbs_ensure_ts_ref_exists(",sigd,"): TCBS was missing reference in TS",tcbs.ts_id) ildb.update_rs_cache(tcbs.ts_id) end end @@ -538,7 +592,7 @@ function ildb.create_ts_from_tcb_list(sigd_list) while track_sections[id] do id = advtrains.random_id(8) end - atdebug("create_ts_from_tcb_list: sigd_list=",sigd_list, "new ID will be ",id) + --atdebug("create_ts_from_tcb_list: sigd_list=",sigd_list, "new ID will be ",id) local tcbr = {} -- makes a copy of the sigd list, for use in repair mechanisms where sigd may contain a tcbs field which we dont want @@ -585,23 +639,23 @@ function ildb.get_possible_out_connids(node_name, in_connid) local nt = node_from_to_state_cache[node_name] if not nt[in_connid] then local ta = {} - atdebug("Node From/To State Cache: Caching for ",node_name,"connid",in_connid) + --atdebug("Node From/To State Cache: Caching for ",node_name,"connid",in_connid) local ndef = minetest.registered_nodes[node_name] if ndef.advtrains.node_state_map then for state, tnode in pairs(ndef.advtrains.node_state_map) do local tndef = minetest.registered_nodes[tnode] -- verify that the conns table is identical - this is purely to catch setup errors! if not tndef.at_conns or not tndef.at_conn_map then - atdebug("ndef:",ndef,", tndef:",tndef) - error("In AT setup for node "..tnode..": Node set as state "..state.." of "..node_name.." in state_map, but is missing at_conns/at_conn/map!") + --atdebug("ndef:",ndef,", tndef:",tndef) + error("In AT setup for node "..tnode..": Node set as state "..state.." of "..node_name.." in state_map, but is missing at_conns/at_conn_map!") end if #ndef.at_conns ~= #tndef.at_conns then - atdebug("ndef:",ndef,", tndef:",tndef) + --atdebug("ndef:",ndef,", tndef:",tndef) error("In AT setup for node "..tnode..": Conns table does not match that of "..node_name.." (of which this is state "..state..")") end for connid=1,#ndef.at_conns do if ndef.at_conns[connid].c ~= tndef.at_conns[connid].c then - atdebug("ndef:",ndef,", tndef:",tndef) + --atdebug("ndef:",ndef,", tndef:",tndef) error("In AT setup for node "..tnode..": Conns table does not match that of "..node_name.." (of which this is state "..state..")") end end @@ -610,13 +664,13 @@ function ildb.get_possible_out_connids(node_name, in_connid) if ta[target_connid] then -- Select the variant for which the other way would back-connect. This way, turnouts will switch to the appropriate branch if the train joins local have_back_conn = (tndef.at_conn_map[target_connid])==in_connid - atdebug("Found second state mapping",in_connid,"-",target_connid,"have_back_conn=",have_back_conn) + --atdebug("Found second state mapping",in_connid,"-",target_connid,"have_back_conn=",have_back_conn) if have_back_conn then - atdebug("Overwriting",in_connid,"-",target_connid,"=",state) + --atdebug("Overwriting",in_connid,"-",target_connid,"=",state) ta[target_connid] = state end else - atdebug("Setting",in_connid,"-",target_connid,"=",state) + --atdebug("Setting",in_connid,"-",target_connid,"=",state) ta[target_connid] = state end end @@ -629,26 +683,27 @@ function ildb.get_possible_out_connids(node_name, in_connid) end local function recursively_find_routes(s_pos, s_connid, locks_found, result_table, scan_limit) - atdebug("Recursively restarting at ",s_pos, s_connid, "limit left", scan_limit) + --atdebug("Recursively restarting at ",s_pos, s_connid, "limit left", scan_limit) local ti = advtrains.get_track_iterator(s_pos, s_connid, scan_limit, false) local pos, connid, bconnid = ti:next_branch() pos, connid, bconnid = ti:next_track()-- step once to get ahead of previous turnout + local last_pos repeat local node = advtrains.ndb.get_node_or_nil(pos) - atdebug("Walk ",pos, "nodename", node.name, "entering at conn",bconnid) + --atdebug("Walk ",pos, "nodename", node.name, "entering at conn",bconnid) local ndef = minetest.registered_nodes[node.name] if ndef.advtrains and ndef.advtrains.node_state_map then -- Stop, this is a switchable node. Find out which conns we can go at - atdebug("Found turnout ",pos, "nodename", node.name, "entering at conn",bconnid) + --atdebug("Found turnout ",pos, "nodename", node.name, "entering at conn",bconnid) local pts = advtrains.encode_pos(pos) if locks_found[pts] then -- we've been here before. Stop - atdebug("Was already seen! returning") + --atdebug("Was already seen! returning") return end local out_conns = ildb.get_possible_out_connids(node.name, bconnid) for oconnid, state in pairs(out_conns) do - atdebug("Going in direction",oconnid,"state",state) + --atdebug("Going in direction",oconnid,"state",state) locks_found[pts] = state recursively_find_routes(pos, oconnid, locks_found, result_table, ti.limit) locks_found[pts] = nil @@ -656,21 +711,23 @@ local function recursively_find_routes(s_pos, s_connid, locks_found, result_tabl return end --otherwise, this might be a tcb - local tcbs = ildb.get_tcbs({p=pos, s=bconnid}) - if tcbs then + local tcb = ildb.get_tcb(pos) + if tcb then -- we found a tcb, store the current locks in the result_table - local table_key = advtrains.encode_pos(pos).."_"..bconnid - atdebug("Found end TCB", table_key,", returning") - if result_table[table_key] then + local end_pkey = advtrains.encode_pos(pos) + --atdebug("Found end TCB", pos, end_pkey,", returning") + if result_table[end_pkey] then atwarn("While caching track section routing, found multiple route paths within same track section. Only first one found will be used") else - result_table[table_key] = table.copy(locks_found) + result_table[end_pkey] = table.copy(locks_found) end return end -- Go forward + last_pos = pos pos, connid, bconnid = ti:next_track() until not pos -- this stops the loop when either the track end is reached or the limit is hit + --atdebug("recursively_find_routes: Reached track end or limit at", last_pos, ". This path is not saved, returning") end -- Updates the turnout cache of the given track section @@ -680,25 +737,33 @@ function ildb.update_rs_cache(ts_id) error("Update TS Cache called with nonexisting ts_id "..(ts_id or "nil")) end local rscache = {} - atdebug("== Running update_rs_cache for ",ts_id) + --atdebug("== Running update_rs_cache for ",ts_id) -- start on every of the TS's TCBs, walk the track forward and store locks along the way for start_tcbi, start_tcbs in ipairs(ts.tc_breaks) do - rscache[start_tcbi] = {} - atdebug("Starting for ",start_tcbi, start_tcbs) + start_pkey = advtrains.encode_pos(start_tcbs.p) + rscache[start_pkey] = {} + --atdebug("Starting for ",start_tcbi, start_tcbs) local locks_found = {} local result_table = {} recursively_find_routes(start_tcbs.p, start_tcbs.s, locks_found, result_table, TS_MAX_SCAN) -- now result_table contains found route locks. Match them with the other TCBs we have in this section for end_tcbi, end_tcbs in ipairs(ts.tc_breaks) do - local table_key = advtrains.encode_pos(end_tcbs.p).."_"..end_tcbs.s - if result_table[table_key] then - atdebug("Set RSCache entry",start_tcbi.."-"..end_tcbi,"=",result_table[table_key]) - rscache[start_tcbi][end_tcbi] = result_table[table_key] + if end_tcbi ~= start_tcbi then + end_pkey = advtrains.encode_pos(end_tcbs.p) + if result_table[end_pkey] then + --atdebug("Set RSCache entry",end_pkey.."-"..end_pkey,"=",result_table[end_pkey]) + rscache[start_pkey][end_pkey] = result_table[end_pkey] + result_table[end_pkey] = nil + end end 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) + end end ts.rs_cache = rscache - atdebug("== Done update_rs_cache for ",ts_id, "result:",rscache) + --atdebug("== Done update_rs_cache for ",ts_id, "result:",rscache) end @@ -711,21 +776,21 @@ end -- Create a new TCB at the position and update/repair the adjoining sections function ildb.create_tcb_at(pos) - atdebug("create_tcb_at",pos) + --atdebug("create_tcb_at",pos) local pts = advtrains.encode_pos(pos) track_circuit_breaks[pts] = {[1] = {}, [2] = {}} local all_tcbs_1 = ildb.get_all_tcbs_adjacent(pos, 1) - atdebug("TCBs on A side",all_tcbs_1) + --atdebug("TCBs on A side",all_tcbs_1) local all_tcbs_2 = ildb.get_all_tcbs_adjacent(pos, 2) - atdebug("TCBs on B side",all_tcbs_2) + --atdebug("TCBs on B side",all_tcbs_2) -- perform TS repair - ildb.repair_ts_merge_all(all_tcbs_1) - ildb.repair_ts_merge_all(all_tcbs_2) + ildb.repair_ts_merge_all(all_tcbs_1, false) + ildb.repair_ts_merge_all(all_tcbs_2, false) end --- Create a new TCB at the position and update/repair the now joined section +-- Remove TCB at the position and update/repair the now joined section function ildb.remove_tcb_at(pos) - atdebug("remove_tcb_at",pos) + --atdebug("remove_tcb_at",pos) local pts = advtrains.encode_pos(pos) local old_tcb = track_circuit_breaks[pts] track_circuit_breaks[pts] = nil @@ -745,7 +810,7 @@ function ildb.remove_tcb_at(pos) end advtrains.interlocking.remove_tcb_marker(pos) -- If needed, merge the track sections here - ildb.check_and_repair_ts_at_pos(pos) + ildb.check_and_repair_ts_at_pos(pos, nil) return true end @@ -758,7 +823,7 @@ function ildb.validate_tcb_xlink(sigd, suppress_repairs) if not osigd then return end local otcbs = ildb.get_tcbs(tcbs.xlink) if not otcbs then - atdebug("validate_tcb_xlink",sigd,": Link partner ",osigd,"orphaned") + --atdebug("validate_tcb_xlink",sigd,": Link partner ",osigd,"orphaned") tcbs.xlink = nil if not suppress_repairs then ildb.check_and_repair_ts_at_pos(sigd.p, sigd.s) @@ -767,16 +832,16 @@ function ildb.validate_tcb_xlink(sigd, suppress_repairs) end if otcbs.xlink then if not vector.equals(otcbs.xlink.p, sigd.p) or otcbs.xlink.s~=sigd.s then - atdebug("validate_tcb_xlink",sigd,": Link partner ",osigd,"backreferencing to someone else (namely",otcbs.xlink,") clearing it") + --atdebug("validate_tcb_xlink",sigd,": Link partner ",osigd,"backreferencing to someone else (namely",otcbs.xlink,") clearing it") tcbs.xlink = nil if not suppress_repairs then ildb.check_and_repair_ts_at_pos(sigd.p, sigd.s) - atdebug("validate_tcb_xlink",sigd,": Link partner ",osigd," was backreferencing to someone else, now updating that") + --atdebug("validate_tcb_xlink",sigd,": Link partner ",osigd," was backreferencing to someone else, now updating that") ildb.validate_tcb_xlink(osigd) end end else - atdebug("validate_tcb_xlink",sigd,": Link partner ",osigd,"wasn't backreferencing, clearing it") + --atdebug("validate_tcb_xlink",sigd,": Link partner ",osigd,"wasn't backreferencing, clearing it") tcbs.xlink = nil if not suppress_repairs then ildb.check_and_repair_ts_at_pos(sigd.p, sigd.s) @@ -785,19 +850,19 @@ function ildb.validate_tcb_xlink(sigd, suppress_repairs) end function ildb.add_tcb_xlink(sigd1, sigd2) - atdebug("add_tcb_xlink",sigd1, sigd2) + --("add_tcb_xlink",sigd1, sigd2) local tcbs1 = sigd1.tcbs or ildb.get_tcbs(sigd1) local tcbs2 = sigd2.tcbs or ildb.get_tcbs(sigd2) if vector.equals(sigd1.p, sigd2.p) then - atdebug("add_tcb_xlink Cannot xlink with same TCB") + --atdebug("add_tcb_xlink Cannot xlink with same TCB") return end if not tcbs1 or not tcbs2 then - atdebug("add_tcb_xlink TCBS doesnt exist") + --atdebug("add_tcb_xlink TCBS doesnt exist") return end if tcbs1.xlink or tcbs2.xlink then - atdebug("add_tcb_xlink One already linked") + --atdebug("add_tcb_xlink One already linked") return end -- apply link @@ -808,7 +873,7 @@ function ildb.add_tcb_xlink(sigd1, sigd2) end function ildb.remove_tcb_xlink(sigd) - atdebug("remove_tcb_xlink",sigd) + --atdebug("remove_tcb_xlink",sigd) -- Validate first. If Xlink is gone already then, nothing to do ildb.validate_tcb_xlink(sigd) -- Checking all of these already done by validate @@ -816,7 +881,7 @@ function ildb.remove_tcb_xlink(sigd) local osigd = tcbs.xlink if not osigd then -- validate already cleared us - atdebug("remove_tcb_xlink: Already gone by validate") + --atdebug("remove_tcb_xlink: Already gone by validate") return end local otcbs = ildb.get_tcbs(tcbs.xlink) @@ -829,14 +894,14 @@ function ildb.remove_tcb_xlink(sigd) end function ildb.create_ts_from_tcbs(sigd) - atdebug("create_ts_from_tcbs",sigd) + --atdebug("create_ts_from_tcbs",sigd) local all_tcbs = ildb.get_all_tcbs_adjacent(sigd.p, sigd.s) ildb.repair_ts_merge_all(all_tcbs, true) end -- Remove the given track section, leaving its TCBs with no section assigned function ildb.remove_ts(ts_id) - atdebug("remove_ts",ts_id) + --atdebug("remove_ts",ts_id) local ts = track_sections[ts_id] if not ts then error("remove_ts: "..ts_id.." doesn't exist") @@ -846,10 +911,10 @@ function ildb.remove_ts(ts_id) local sigd = ts.tc_breaks[i] local tcbs = ildb.get_tcbs(sigd) if tcbs then - atdebug("cleared TCB",sigd) + --atdebug("cleared TCB",sigd) tcbs.ts_id = nil else - atdebug("orphan TCB",sigd) + --atdebug("orphan TCB",sigd) end i = i+1 end diff --git a/advtrains_interlocking/route_prog.lua b/advtrains_interlocking/route_prog.lua index 5fd9363..34807cd 100644 --- a/advtrains_interlocking/route_prog.lua +++ b/advtrains_interlocking/route_prog.lua @@ -492,6 +492,8 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) local terminal = get_last_route_item(rp.origin, rp.route) rp.route.terminal = terminal rp.route.name = fields.name + -- new routes now always use the rscache + rp.route.use_rscache = true table.insert(tcbs.routes, rp.route) diff --git a/advtrains_interlocking/routesetting.lua b/advtrains_interlocking/routesetting.lua index ede3d49..64b8c25 100644 --- a/advtrains_interlocking/routesetting.lua +++ b/advtrains_interlocking/routesetting.lua @@ -49,7 +49,7 @@ function ilrs.set_route(signal, route, try) c_tcbs = ildb.get_tcbs(c_sigd) if not c_tcbs then if not try then atwarn("Did not find TCBS",c_sigd,"while setting route",rtename,"of",signal) end - return false, "No TCB found at "..sigd_to_string(c_sigd)..". Please reconfigure route!" + return false, "No TCB found at "..sigd_to_string(c_sigd)..". Please update or reconfigure route!" end c_ts_id = c_tcbs.ts_id if not c_ts_id then @@ -69,28 +69,49 @@ function ilrs.set_route(signal, route, try) return false, "Section '"..c_ts.name.."' is occupied!", c_ts_id, nil end - for pts, state in pairs(c_rseg.locks) do + -- collect locks from rs cache and from route def + local c_locks = {} + if route.use_rscache and c_ts.rs_cache and c_rseg.next then + -- rscache needs to be enabled, present and next must be defined + start_pkey = advtrains.encode_pos(c_sigd.p) + end_pkey = advtrains.encode_pos(c_rseg.next.p) + if c_ts.rs_cache[start_pkey] and c_ts.rs_cache[start_pkey][end_pkey] then + for lp,lst in pairs(c_ts.rs_cache[start_pkey][end_pkey]) do + atdebug("Add lock from RSCache:",lp,"->",lst) + c_locks[lp] = lst + end + elseif not try then + atwarn("While setting route",rtename,"of",signal,"segment "..i..",required path from",c_tcbs,"to",c_rseg.next,"was not found in the track section's RS cache. Please check!") + end + end + -- add all from locks, these override the rscache + for lpts,lst in pairs(c_rseg.locks) do + atdebug("Add lock from Routedef:",lp,"->",lst,"overrides",c_locks[lp] or "none") + c_locks[lp] = lst + end + + for lp, state in pairs(c_locks) do local confl = ilrs.has_route_lock(pts, state) - local pos = minetest.string_to_pos(pts) + local pos = advtrains.decode_pos(lp) if advtrains.is_passive(pos) then local cstate = advtrains.getstate(pos) if cstate ~= state then - local confl = ilrs.has_route_lock(pts) + local confl = ilrs.has_route_lock(lp) if confl then - if not try then atwarn("Encountered route lock while a real run of routesetting routine, at position",pts,"while setting route",rtename,"of",signal) end - return false, "Lock conflict at "..pts..", Held locked by:\n"..confl, nil, pts + if not try then atwarn("Encountered route lock while a real run of routesetting routine, at position",pos,"while setting route",rtename,"of",signal) end + return false, "Lock conflict at "..minetest.pos_to_string(pos)..", Held locked by:\n"..confl, nil, lp elseif not try then advtrains.setstate(pos, state) end end if not try then - ilrs.add_route_lock(pts, c_ts_id, "Route '"..rtename.."' from signal '"..signalname.."'", signal) - c_lckp[#c_lckp+1] = pts + ilrs.add_route_lock(lp, c_ts_id, "Route '"..rtename.."' from signal '"..signalname.."'", signal) + c_lckp[#c_lckp+1] = lp end else if not try then atwarn("Encountered route lock misconfiguration (no passive component) while a real run of routesetting routine, at position",pts,"while setting route",rtename,"of",signal) end - return false, "No passive component at "..pts..". Please reconfigure route!" + return false, "No passive component at "..minetest.pos_to_string(pos)..". Please update track section or reconfigure route!" end end -- reserve ts and write locks @@ -126,6 +147,8 @@ function ilrs.set_route(signal, route, try) return true end +-- Change 2024-01-27: pts is not an encoded pos, not a pos-to-string! + -- Checks whether there is a route lock that prohibits setting the component -- to the wanted state. returns string with reasons on conflict function ilrs.has_route_lock(pts) @@ -191,7 +214,7 @@ function ilrs.free_route_locks_indiv(pts, ts, nocallbacks) -- TODO use luaautomation timers? if not nocallbacks then minetest.after(0, ilrs.update_waiting, "lck", pts) - minetest.after(0.5, advtrains.set_fallback_state, minetest.string_to_pos(pts)) + minetest.after(0.5, advtrains.set_fallback_state, advtrains.decode_pos(pts)) end end -- frees all route locks, even manual ones set with the tool, at a specific position diff --git a/advtrains_interlocking/tcb_ts_ui.lua b/advtrains_interlocking/tcb_ts_ui.lua index e365f4f..9e7fcd4 100755 --- a/advtrains_interlocking/tcb_ts_ui.lua +++ b/advtrains_interlocking/tcb_ts_ui.lua @@ -99,10 +99,11 @@ minetest.register_node("advtrains_interlocking:tcb_node", { end, after_dig_node = function(pos, oldnode, oldmetadata, player) if not oldmetadata or not oldmetadata.fields then return end + local pname = player:get_player_name() local tcbpts = oldmetadata.fields.tcb_pos if tcbpts and tcbpts ~= "" then local tcbpos = minetest.string_to_pos(tcbpts) - ildb.remove_tcb_at(tcbpos) + ildb.remove_tcb_at(tcbpos, pname) end end, }) @@ -160,7 +161,7 @@ minetest.register_on_punchnode(function(pos, node, player, pointed_thing) if ildb.get_tcb(pos) then minetest.chat_send_player(pname, "Configuring TCB: Already existed at this position, it is now linked to this TCB marker") else - ildb.create_tcb_at(pos) + ildb.create_tcb_at(pos, pname) end local meta = minetest.get_meta(tcbnpos) diff --git a/advtrains_interlocking/tool.lua b/advtrains_interlocking/tool.lua index ef0f06e..4ebc56c 100644 --- a/advtrains_interlocking/tool.lua +++ b/advtrains_interlocking/tool.lua @@ -6,7 +6,7 @@ local ilrs = advtrains.interlocking.route local function node_right_click(pos, pname) if advtrains.is_passive(pos) then local form = "size[7,5]label[0.5,0.5;Route lock inspector]" - local pts = minetest.pos_to_string(pos) + local pts = advtrains.encode_pos(pos) local rtl = ilrs.has_route_lock(pts) @@ -53,7 +53,7 @@ local function node_left_click(pos, pname) return end - local ts_id = advtrains.interlocking.db.check_and_repair_ts_at_pos(pos) + local ts_id = advtrains.interlocking.db.check_and_repair_ts_at_pos(pos, nil, pname) if ts_id then advtrains.interlocking.db.update_rs_cache(ts_id) advtrains.interlocking.highlight_track_section(pos) @@ -107,7 +107,7 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) local pos local pts = string.match(formname, "^at_il_rtool_(.+)$") if pts then - pos = minetest.string_to_pos(pts) + pos = advtrains.decode_pos(pts) end if pos then if advtrains.is_passive(pos) then -- cgit v1.2.3 From baa50c03920fd0a563fce09929f3d56c3374e8bd Mon Sep 17 00:00:00 2001 From: orwell Date: Sat, 20 Jul 2024 18:02:33 +0200 Subject: ARS supports triggering distant signal, other bugfixes --- advtrains/lzb.lua | 2 +- advtrains/path.lua | 2 +- advtrains/trackplacer.lua | 8 ++-- advtrains/trainlogic.lua | 6 +-- advtrains_interlocking/approach.lua | 5 +-- advtrains_interlocking/ars.lua | 66 ++++++++++++++++++++----------- advtrains_interlocking/route_prog.lua | 4 +- advtrains_interlocking/routesetting.lua | 4 +- advtrains_interlocking/signal_api.lua | 2 +- advtrains_interlocking/tcb_ts_ui.lua | 7 +++- advtrains_interlocking/train_sections.lua | 7 +++- advtrains_signals_ks/init.lua | 22 +++++++++-- 12 files changed, 87 insertions(+), 48 deletions(-) (limited to 'advtrains_interlocking/route_prog.lua') diff --git a/advtrains/lzb.lua b/advtrains/lzb.lua index 64e4553..52c2289 100644 --- a/advtrains/lzb.lua +++ b/advtrains/lzb.lua @@ -48,7 +48,7 @@ local params = { ZONE_HOLD = 5, -- added on top of ZONE_ROLL ZONE_VSLOW = 3, -- When speed is <2, still allow accelerating - DST_FACTOR = 1.5, + DST_FACTOR = 3,--1.5, SHUNT_SPEED_MAX = advtrains.SHUNT_SPEED_MAX, } diff --git a/advtrains/path.lua b/advtrains/path.lua index 28df529..d54aebe 100644 --- a/advtrains/path.lua +++ b/advtrains/path.lua @@ -256,7 +256,7 @@ function advtrains.path_get(train, index) if next_connmap then -- only needs to be done when this track is a turnout (>2 conns) local origin_conn = train.path_ori_cp[advtrains.encode_pos(adj_pos)] if origin_conn then - atdebug("Train",train.id,"at",adj_pos,"restoring turnout origin CP",origin_conn,"for path item",index) + --atdebug("Train",train.id,"at",adj_pos,"restoring turnout origin CP",origin_conn,"for path item",index) mconnid = origin_conn end end diff --git a/advtrains/trackplacer.lua b/advtrains/trackplacer.lua index e6111dc..597e8ec 100644 --- a/advtrains/trackplacer.lua +++ b/advtrains/trackplacer.lua @@ -288,8 +288,8 @@ minetest.register_craftitem("advtrains:trackworker",{ advtrains.ndb.swap_node(pos, new_node) end end, - on_use=function(itemstack, user, pointed_thing) - local name = user:get_player_name() + on_use=function(itemstack, player, pointed_thing) + local name = player:get_player_name() if not name then return end @@ -305,7 +305,7 @@ minetest.register_craftitem("advtrains:trackworker",{ local ndef = minetest.registered_nodes[node.name] if not ndef.advtrains or not ndef.advtrains.trackworker_next_var then - minetest.chat_send_player(placer:get_player_name(), attrans("This node can't be changed using the trackworker!")) + minetest.chat_send_player(name, attrans("This node can't be changed using the trackworker!")) return end @@ -318,7 +318,7 @@ minetest.register_craftitem("advtrains:trackworker",{ if reason then str = str .. " " .. reason end - minetest.chat_send_player(placer:get_player_name(), str) + minetest.chat_send_player(name, str) return end end diff --git a/advtrains/trainlogic.lua b/advtrains/trainlogic.lua index cb1f9a6..9e9f214 100644 --- a/advtrains/trainlogic.lua +++ b/advtrains/trainlogic.lua @@ -865,7 +865,7 @@ local function tnc_call_enter_callback(pos, train_id, train, index) -- check for split points if mregnode and mregnode.at_conn_map then -- If this node has >2 conns (and a connmap), remember the connection where we came from to handle split points - atdebug("Train",train_id,"at",pos,"saving turnout origin CP",train.path_cp[index],"for path item",index) + --atdebug("Train",train_id,"at",pos,"saving turnout origin CP",train.path_cp[index],"for path item",index) train.path_ori_cp[advtrains.encode_pos(pos)] = train.path_cp[index] end end @@ -883,7 +883,7 @@ local function tnc_call_leave_callback(pos, train_id, train, index) -- split points do not matter anymore. clear them if mregnode and mregnode.at_conn_map then -- If this node has >2 conns (and a connmap), remember the connection where we came from to handle split points - atdebug("Train",train_id,"at",pos,"removing turnout origin CP for path item",index," because train has left it") + --atdebug("Train",train_id,"at",pos,"removing turnout origin CP for path item",index," because train has left it") train.path_ori_cp[advtrains.encode_pos(pos)] = nil end end @@ -1188,7 +1188,7 @@ function advtrains.invert_train(train_id) local pos = advtrains.path_get(train, index) local ok, conns, railheight, connmap = advtrains.get_rail_info_at(pos) if ok and connmap then - atdebug("Reversing Train",train.id," ori_cp Checks: at",pos,"saving turnout origin CP",train.path_cn[index],"for path item",index) + --atdebug("Reversing Train",train.id," ori_cp Checks: at",pos,"saving turnout origin CP",train.path_cn[index],"for path item",index) ori_cp_after_flip[advtrains.encode_pos(pos)] = train.path_cn[index] end end diff --git a/advtrains_interlocking/approach.lua b/advtrains_interlocking/approach.lua index eecf09a..eaf0248 100644 --- a/advtrains_interlocking/approach.lua +++ b/advtrains_interlocking/approach.lua @@ -64,10 +64,7 @@ advtrains.tnc_register_on_approach(function(pos, id, train, index, has_entered, -- resetting the path does not matter to the set route and ARS doesn't need to be called again. if spos and ars_enabled then --atdebug(id,"IL Spos (ARS)",spos,asp) - local sigd = il.db.get_sigd_for_signal(spos) - if sigd then - il.ars_check(sigd, train) - end + il.ars_check(spos, train) end --atdebug("trav: ",pos, cn, asp, spos, "travsht=", lzb.travsht) local lspd diff --git a/advtrains_interlocking/ars.lua b/advtrains_interlocking/ars.lua index 4f50df9..b3065ee 100644 --- a/advtrains_interlocking/ars.lua +++ b/advtrains_interlocking/ars.lua @@ -129,29 +129,49 @@ function il.ars_check_rule_match(ars, train) return nil end -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 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 - - if tcbs.routeset then - -- ARS is not in effect when a route is already set - -- just "punch" routesetting, just in case callback got lost. - minetest.after(0, il.route.update_route, sigd, tcbs, nil, nil) - return +function advtrains.interlocking.ars_check(signalpos, train, trig_from_dst) + -- check for distant signal + -- this whole check must be delayed until after the route setting has taken place, + -- because before that the distant signal is yet unknown + if not trig_from_dst then + minetest.after(0.5, function() + -- does signal have dst? + local _, remote = il.signal.get_aspect(signalpos) + if remote then + advtrains.interlocking.ars_check(remote, train, true) + end + end) end - - local rteid = find_rtematch(tcbs.routes, train) - if rteid then - --delay routesetting, it should not occur inside train step - -- using after here is OK because that gets called on every path recalculation - minetest.after(0, il.route.update_route, sigd, tcbs, rteid, nil) + + local sigd = il.db.get_sigd_for_signal(signalpos) + local tcbs = sigd and il.db.get_tcbs(sigd) + -- trigger ARS on this signal + if tcbs and tcbs.routes 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 + if trig_from_dst and tcbs.no_dst_ars_trig then + -- signal not to be triggered from distant + return + end + + if tcbs.routeset then + -- ARS is not in effect when a route is already set + -- just "punch" routesetting, just in case callback got lost. + minetest.after(0, il.route.update_route, sigd, tcbs, nil, nil) + return + end + + local rteid = find_rtematch(tcbs.routes, train) + if rteid then + --delay routesetting, it should not occur inside train step + -- using after here is OK because that gets called on every path recalculation + minetest.after(0, il.route.update_route, sigd, tcbs, rteid, nil) + end end end diff --git a/advtrains_interlocking/route_prog.lua b/advtrains_interlocking/route_prog.lua index 34807cd..37f751a 100644 --- a/advtrains_interlocking/route_prog.lua +++ b/advtrains_interlocking/route_prog.lua @@ -209,7 +209,7 @@ function advtrains.interlocking.visualize_route(origin, route, context, tmp_lcks end -- display locks set by player for pts, state in pairs(tmp_lcks) do - local pos = minetest.string_to_pos(pts) + local pos = advtrains.decode_pos(pts) routesprite(context, pos, "fixp"..pts, "at_il_route_lock_edit.png", "Fixed in state '"..state.."' by route "..route.name.." (punch to unfix)", function() clear_lock(tmp_lcks, pname, pts) end) end @@ -536,7 +536,7 @@ minetest.register_on_punchnode(function(pos, node, player, pointed_thing) return end if advtrains.is_passive(pos) then - local pts = advtrains.roundfloorpts(pos) + local pts = advtrains.encode_pos(pos) if rp.tmp_lcks[pts] then clear_lock(rp.tmp_lcks, pname, pts) else diff --git a/advtrains_interlocking/routesetting.lua b/advtrains_interlocking/routesetting.lua index d619aac..34a273a 100644 --- a/advtrains_interlocking/routesetting.lua +++ b/advtrains_interlocking/routesetting.lua @@ -92,8 +92,8 @@ function ilrs.set_route(signal, route, try) end -- add all from locks, these override the rscache for lpts,lst in pairs(c_rseg.locks) do - atdebug("Add lock from Routedef:",lp,"->",lst,"overrides",c_locks[lp] or "none") - c_locks[lp] = lst + atdebug("Add lock from Routedef:",lpts,"->",lst,"overrides",c_locks[lpts] or "none") + c_locks[lpts] = lst end for lp, state in pairs(c_locks) do diff --git a/advtrains_interlocking/signal_api.lua b/advtrains_interlocking/signal_api.lua index eddf9da..cede405 100644 --- a/advtrains_interlocking/signal_api.lua +++ b/advtrains_interlocking/signal_api.lua @@ -279,7 +279,7 @@ end function signal.get_aspect(pos) local aspt = signal.aspects[advtrains.encode_pos(pos)] local ma,dp = signal.get_aspect_internal(pos, aspt) - return ma, advtrains.decode_pos(dp) + return ma, dp and advtrains.decode_pos(dp) end local function cache_mainaspects(ndefat) diff --git a/advtrains_interlocking/tcb_ts_ui.lua b/advtrains_interlocking/tcb_ts_ui.lua index 7f75bb9..82a57cf 100755 --- a/advtrains_interlocking/tcb_ts_ui.lua +++ b/advtrains_interlocking/tcb_ts_ui.lua @@ -645,6 +645,7 @@ function advtrains.interlocking.show_signalling_form(sigd, pname, sel_rte, calle 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... @@ -669,7 +670,7 @@ end function advtrains.interlocking.update_player_forms(sigd) for pname, tsigd in pairs(p_open_sig_form) do if advtrains.interlocking.sigd_equal(sigd, tsigd) then - advtrains.interlocking.show_signalling_form(sigd, pname, nil) + advtrains.interlocking.show_signalling_form(sigd, pname, nil, true) end end end @@ -761,6 +762,10 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) tcbs.ars_disabled = not minetest.is_yes(fields.ars) end + if fields.dstarstrig then + tcbs.no_dst_ars_trig = not minetest.is_yes(fields.dstarstrig) + end + if fields.auto then tcbs.route_auto = true end diff --git a/advtrains_interlocking/train_sections.lua b/advtrains_interlocking/train_sections.lua index 41da747..083676b 100644 --- a/advtrains_interlocking/train_sections.lua +++ b/advtrains_interlocking/train_sections.lua @@ -75,7 +75,10 @@ local function setsection(tid, train, ts_id, ts, sigd) end -- routes - local tcbs = advtrains.interlocking.db.get_tcbs(sigd) + local tcbs + if sigd then + tcbs = advtrains.interlocking.db.get_tcbs(sigd) + end -- route setting - clear route state if ts.route then @@ -90,7 +93,7 @@ local function setsection(tid, train, ts_id, ts, sigd) end ts.route = nil end - if tcbs.signal then + if tcbs and tcbs.signal then -- Reset route and signal -- Note that the hit-route case is already handled by cancel_route_from -- this code only handles signal at entering tcb and also triggers for non-route ts diff --git a/advtrains_signals_ks/init.lua b/advtrains_signals_ks/init.lua index d0ba6cd..c449416 100755 --- a/advtrains_signals_ks/init.lua +++ b/advtrains_signals_ks/init.lua @@ -258,16 +258,16 @@ for _, rtab in ipairs({ -- Vorsignal (NEU!) for typ, prts in pairs({ -- note: the names are taken from the main signal equivalent so that the same names for the lamp images can be used - slow = {asp = advtrains.interlocking.signal.ASPI_HALT, n = "nextslow", ici=true}, + slow = {asp = function(pos) return { dst = 0, shunt = true } end, n = "nextslow", ici=true}, nextslow = { asp = function(pos) - return { dst = getzs3v(pos) or 6 } + return { dst = getzs3v(pos) or 6, shunt = true } end, n = "free" }, free = { asp = function(pos) - return { dst = -1 } + return { dst = -1, shunt = true } end, n = "slow" }, @@ -399,7 +399,9 @@ for _, rtab in ipairs({ drop = "advtrains_signals_ks:"..prefix.."_"..dtyp.."_0", inventory_image = inv, advtrains = { - get_aspect_info = asp + get_aspect_info = asp, + trackworker_next_rot = "advtrains_signals_ks:"..prefix.."_"..typ.."_"..rtab.nextrot, + trackworker_rot_incr_param2 = (rot=="60") }, on_rightclick = advtrains.interlocking.signal_rc_handler, can_dig = advtrains.interlocking.signal_can_dig, @@ -506,6 +508,10 @@ for _, rtab in ipairs({ t.mesh = "advtrains_signals_ks_zs_top_smr"..rot..".obj" t.drop = "advtrains_signals_ks:zs3_off_0" t.selection_box.fixed[1][5] = 0 + t.advtrains = { + trackworker_next_rot = "advtrains_signals_ks:zs3_"..typ.."_"..rtab.nextrot, + trackworker_rot_incr_param2 = (rot=="60") + }, minetest.register_node("advtrains_signals_ks:zs3_"..typ.."_"..rot, t) --TODO add rotation using trackworker @@ -515,6 +521,10 @@ for _, rtab in ipairs({ t.mesh = "advtrains_signals_ks_zs_bottom_smr"..rot..".obj" t.drop = "advtrains_signals_ks:zs3v_off_0" t.tiles[3] = t.tiles[3] .. "^[multiply:yellow" + t.advtrains = { + trackworker_next_rot = "advtrains_signals_ks:zs3v_"..typ.."_"..rtab.nextrot, + trackworker_rot_incr_param2 = (rot=="60") + }, minetest.register_node("advtrains_signals_ks:zs3v_"..typ.."_"..rot, t) --TODO add rotation using trackworker end @@ -539,6 +549,10 @@ for _, rtab in ipairs({ not_blocking_trains = 1, not_in_creative_inventory = (rtab.ici) and 0 or 1, }, + advtrains = { + trackworker_next_rot = "advtrains_signals_ks:mast_mast_"..rtab.nextrot, + trackworker_rot_incr_param2 = (rot=="60") + }, drop = "advtrains_signals_ks:mast_mast_0", }) --TODO add rotation using trackworker -- cgit v1.2.3 From d83d06ecdd8a23e5c36826f150c72d0ff8b644f9 Mon Sep 17 00:00:00 2001 From: 1F616EMO Date: Mon, 30 Sep 2024 19:37:18 +0800 Subject: Add "New From Route" function into route editing form This patch allows creating new routes based on what was done on another route. This can be useful to fix minor mistakes on a route, or to create similar routes. Note that the route buffer created "steps back" one section, but with turnouts kept. The new button is placed above the "Save ARS" button - I know it is ugly, so please suggest a better place for it. --- advtrains_interlocking/route_prog.lua | 27 ++++++++++++++++++++------- advtrains_interlocking/route_ui.lua | 15 ++++++++++++--- 2 files changed, 32 insertions(+), 10 deletions(-) (limited to 'advtrains_interlocking/route_prog.lua') diff --git a/advtrains_interlocking/route_prog.lua b/advtrains_interlocking/route_prog.lua index 6abe431..e8f5e8e 100644 --- a/advtrains_interlocking/route_prog.lua +++ b/advtrains_interlocking/route_prog.lua @@ -214,19 +214,32 @@ end local player_rte_prog = {} -function advtrains.interlocking.init_route_prog(pname, sigd) +function advtrains.interlocking.init_route_prog(pname, sigd, default_route) if not minetest.check_player_privs(pname, "interlocking") then minetest.chat_send_player(pname, "Insufficient privileges to use this!") return end - player_rte_prog[pname] = { + local rp = { origin = sigd, - route = { - name = "PROG["..pname.."]", - }, - tmp_lcks = {}, } - advtrains.interlocking.visualize_route(sigd, player_rte_prog[pname].route, "prog_"..pname, player_rte_prog[pname].tmp_lcks, pname) + if default_route then + rp.route = table.copy(default_route) + + -- "Step back one section", but keeping turnouts + local last_route = rp.route[#rp.route] + if last_route then + rp.tmp_lcks = last_route.locks + rp.route[#rp.route] = nil + end + rp.route.name = "PROG["..pname.."]" + else + rp.route = { + name = "PROG["..pname.."]" + } + rp.tmp_lcks = {} + end + player_rte_prog[pname] = rp + advtrains.interlocking.visualize_route(sigd, rp.route, "prog_"..pname, rp.tmp_lcks, pname) minetest.chat_send_player(pname, "Route programming mode active. Punch TCBs to add route segments, punch turnouts to lock them.") end diff --git a/advtrains_interlocking/route_ui.lua b/advtrains_interlocking/route_ui.lua index 1999941..a8fee83 100644 --- a/advtrains_interlocking/route_ui.lua +++ b/advtrains_interlocking/route_ui.lua @@ -24,7 +24,7 @@ function atil.show_route_edit_form(pname, sigd, routeid) local route = tcbs.routes[routeid] if not route then return end - local form = "size[9,10]label[0.5,0.2;Route overview]" + local form = "size[9,11]label[0.5,0.2;Route overview]" form = form.."field[0.8,1.2;6.5,1;name;Route name;"..minetest.formspec_escape(route.name).."]" form = form.."button[7.0,0.9;1.5,1;setname;Set]" @@ -85,11 +85,13 @@ function atil.show_route_edit_form(pname, sigd, routeid) form = form.."button[0.5,6;3,1;back;<<< Back to signal]" form = form.."button[4.5,6;2,1;aspect;Signal Aspect]" form = form.."button[6.5,6;2,1;delete;Delete Route]" + + form = form.."button[5.5,7;3,1;newfrom;New From Route]" --atdebug(route.ars) form = form.."style[ars;font=mono]" - form = form.."textarea[0.8,7.3;5,3;ars;ARS Rule List;"..atil.ars_to_text(route.ars).."]" - form = form.."button[5.5,7.23;3,1;savears;Save ARS List]" + form = form.."textarea[0.8,8.3;5,3;ars;ARS Rule List;"..atil.ars_to_text(route.ars).."]" + form = form.."button[5.5,8.23;3,1;savears;Save ARS List]" minetest.show_formspec(pname, "at_il_routeedit_"..minetest.pos_to_string(sigd.p).."_"..sigd.s.."_"..routeid, form) @@ -139,6 +141,13 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) table.remove(tcbs.routes, routeid) advtrains.interlocking.show_signalling_form(sigd, pname) end + + if fields.newfrom then + advtrains.interlocking.init_route_prog(pname, sigd, route) + minetest.close_formspec(pname, formname) + tcbs.ars_ignore_next = nil + return + end if fields.ars and fields.savears then route.ars = atil.text_to_ars(fields.ars) -- cgit v1.2.3 From fe57e7dd089653e2361a4ebb0b34137a3261e198 Mon Sep 17 00:00:00 2001 From: orwell Date: Thu, 14 Nov 2024 00:03:38 +0100 Subject: Add Blocksignal mode for signals to autocreate simple block route --- advtrains_interlocking/database.lua | 7 +- advtrains_interlocking/route_prog.lua | 10 +- advtrains_interlocking/route_ui.lua | 3 +- advtrains_interlocking/routesetting.lua | 11 +- advtrains_interlocking/signal_api.lua | 2 +- advtrains_interlocking/tcb_ts_ui.lua | 177 ++++++++++++++++++++++---------- advtrains_signals_ks/init.lua | 8 +- 7 files changed, 143 insertions(+), 75 deletions(-) (limited to 'advtrains_interlocking/route_prog.lua') 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 = -- the sigd describing the end of the route. Used for merging route options on recalculation + terminal = -- 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 = - [n] = { - next = , -- of the next (note: next) TCB on the route - locks = { = "state"} -- route locks of this route segment - } - terminal = , - 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 = + 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") -- cgit v1.2.3 From 922e654b7bef51c7ddaf510ec70880d48181dd35 Mon Sep 17 00:00:00 2001 From: orwell Date: Mon, 25 Nov 2024 22:31:26 +0100 Subject: Make Buffers become implicitly their own TCBs and signals when interlocking is enabled --- advtrains/signals.lua | 8 +- advtrains/trackplacer.lua | 16 ++-- advtrains/tracks.lua | 1 + advtrains_interlocking/database.lua | 41 +++++++++- advtrains_interlocking/mod.conf | 2 +- advtrains_interlocking/route_prog.lua | 7 +- advtrains_interlocking/signal_api.lua | 23 ++++-- advtrains_interlocking/tcb_ts_ui.lua | 146 ++++++++++++++++++++++++++++++++-- advtrains_train_track/init.lua | 29 +++++++ advtrains_train_track/mod.conf | 2 +- 10 files changed, 242 insertions(+), 33 deletions(-) (limited to 'advtrains_interlocking/route_prog.lua') diff --git a/advtrains/signals.lua b/advtrains/signals.lua index 4dec7f5..8bdd877 100644 --- a/advtrains/signals.lua +++ b/advtrains/signals.lua @@ -3,15 +3,15 @@ local mrules_wallsignal = advtrains.meseconrules -local function can_dig_func(pos) +local function can_dig_func(pos, player) if advtrains.interlocking then - return advtrains.interlocking.signal.can_dig(pos) + return advtrains.interlocking.signal.can_dig(pos, player) end return true end -local function after_dig_func(pos) +local function after_dig_func(pos, oldnode, oldmetadata, digger) if advtrains.interlocking then - return advtrains.interlocking.signal.after_dig(pos) + return advtrains.interlocking.signal.after_dig(pos, oldnode, oldmetadata, digger) end return true end diff --git a/advtrains/trackplacer.lua b/advtrains/trackplacer.lua index 6a2c7a8..1543209 100644 --- a/advtrains/trackplacer.lua +++ b/advtrains/trackplacer.lua @@ -152,12 +152,14 @@ local function check_or_bend_rail(origin, dir, pname, commit) end end -local function track_place_node(pos, node, ndef) +local function track_place_node(pos, node, ndef, pname) --atdebug("track_place_node: ",pos, node) advtrains.ndb.swap_node(pos, node) local ndef = minetest.registered_nodes[node.name] if ndef and ndef.after_place_node then - ndef.after_place_node(pos) + -- resolve player again + local player = pname and core.get_player_by_name(pname) or nil + ndef.after_place_node(pos, player) -- note: itemstack and pointed_thing are NOT available here anymore (crap!) end end @@ -191,16 +193,16 @@ function tp.place_track(pos, tpg, pname, yaw) for k1, conn1 in ipairs(cand) do for k2, conn2 in ipairs(cand) do if k1~=k2 then - -- order of conn1/conn2: prefer conn2 being in the direction of the player facing. + -- order of conn1/conn2: prefer conn1 being in the direction of the player facing. -- the combination the other way round will be run through in a later loop iteration - if advtrains.yawToDirection(yaw, conn1, conn2) == conn2 then + if advtrains.yawToDirection(yaw, conn1, conn2) == conn1 then -- does there exist a suitable double-connection rail? --atdebug("Try double conn: ",conn1, conn2) local node = g.double[conn1.."_"..conn2] if node then check_or_bend_rail(pos, conn1, pname, true) check_or_bend_rail(pos, conn2, pname, true) - track_place_node(pos, node) -- calls after_place_node implicitly + track_place_node(pos, node, pname) -- calls after_place_node implicitly return true end end @@ -220,13 +222,13 @@ function tp.place_track(pos, tpg, pname, yaw) local node = single[conn1] if node then check_or_bend_rail(pos, conn1, pname, true) - track_place_node(pos, node) -- calls after_place_node implicitly + track_place_node(pos, node, nil, pname) -- calls after_place_node implicitly return true end end -- 4. if nothing worked, set the default local node = g.default - track_place_node(pos, node) -- calls after_place_node implicitly + track_place_node(pos, node, nil, pname) -- calls after_place_node implicitly return true end diff --git a/advtrains/tracks.lua b/advtrains/tracks.lua index 661da8a..fa7b702 100644 --- a/advtrains/tracks.lua +++ b/advtrains/tracks.lua @@ -253,6 +253,7 @@ end -- Function called when a track is about to be dug or modified by the trackworker -- Returns either true (ok) or false,"translated string describing reason why it isn't allowed" +-- Impl Note: possibly duplicate code in "self contained TCB" - see interlocking/tcb_ts_ui.lua! function advtrains.can_dig_or_modify_track(pos) if advtrains.get_train_at_pos(pos) then return false, attrans("Position is occupied by a train.") diff --git a/advtrains_interlocking/database.lua b/advtrains_interlocking/database.lua index e77d073..75247de 100644 --- a/advtrains_interlocking/database.lua +++ b/advtrains_interlocking/database.lua @@ -802,10 +802,18 @@ function ildb.create_tcb_at(pos) end -- Remove TCB at the position and update/repair the now joined section -function ildb.remove_tcb_at(pos) +-- skip_tsrepair: should be set to true when the rail node at the TCB position is already gone. +-- Assumes the track sections are now separated and does not attempt the repair process. +function ildb.remove_tcb_at(pos, pname, skip_tsrepair) --atdebug("remove_tcb_at",pos) local pts = advtrains.encode_pos(pos) local old_tcb = track_circuit_breaks[pts] + -- unassign signals if defined + for connid=1,2 do + if old_tcb[connid].signal then + ildb.set_sigd_for_signal(old_tcb[connid].signal, nil) + end + end track_circuit_breaks[pts] = nil -- purge the track sections adjacent if old_tcb[1].ts_id then @@ -823,7 +831,9 @@ function ildb.remove_tcb_at(pos) end advtrains.interlocking.remove_tcb_marker(pos) -- If needed, merge the track sections here - ildb.check_and_repair_ts_at_pos(pos, nil) + if not skip_tsrepair then + ildb.check_and_repair_ts_at_pos(pos, pname) + end return true end @@ -973,11 +983,34 @@ function ildb.get_sigd_for_signal(pos) end return nil end -function ildb.set_sigd_for_signal(pos, sigd) +function ildb.set_sigd_for_signal(pos, sigd) -- do not use! local pts = advtrains.roundfloorpts(pos) signal_assignments[pts] = sigd end +-- Assign the signal at pos to the given TCB side. +function ildb.assign_signal_to_tcbs(pos, sigd) + local tcbs = ildb.get_tcbs(sigd) + assert(tcbs, "assign_signal_to_tcbs invalid sigd!") + tcbs.signal = pos + if not tcbs.routes then + tcbs.routes = {} + end + ildb.set_sigd_for_signal(pos, sigd) +end + +-- unassign the signal from the given sigd (looks in tcbs.signal for the signalpos) +function ildb.unassign_signal_for_tcbs(sigd) + local tcbs = advtrains.interlocking.db.get_tcbs(sigd) + if not tcbs then return end + local pos = tcbs.signal + if not pos then return end + ildb.set_sigd_for_signal(pos, nil) + tcbs.signal = nil + tcbs.route_aspect = nil + tcbs.route_remote = nil +end + -- checks if there's any influence point set to this position -- if purge is true, checks whether the associated signal still exists -- and deletes the ip if not. @@ -987,7 +1020,7 @@ function ildb.is_ip_at(pos, purge) if purge then -- is there still a signal assigned to it? for connid, sigpos in pairs(influence_points[pts]) do - local asp = advtrains.interlocking.signal_get_aspect(sigpos) + local asp = advtrains.interlocking.signal.get_aspect(sigpos) if not asp then atlog("Clearing orphaned signal influence point", pts, "/", connid) ildb.clear_ip_signal(pts, connid) diff --git a/advtrains_interlocking/mod.conf b/advtrains_interlocking/mod.conf index 3b2d029..9191dd9 100644 --- a/advtrains_interlocking/mod.conf +++ b/advtrains_interlocking/mod.conf @@ -4,4 +4,4 @@ description=Interlocking system for Advanced Trains author=orwell96 depends=advtrains -optional_depends=advtrains_train_track +#optional_depends=advtrains_train_track diff --git a/advtrains_interlocking/route_prog.lua b/advtrains_interlocking/route_prog.lua index 2f0f8ee..3bdf6d6 100644 --- a/advtrains_interlocking/route_prog.lua +++ b/advtrains_interlocking/route_prog.lua @@ -535,9 +535,12 @@ minetest.register_on_punchnode(function(pos, node, player, pointed_thing) -- show formspec show_routing_form(pname, tcbpos) - advtrains.interlocking.visualize_route(rp.origin, rp.route, "prog_"..pname, rp.tmp_lcks, pname) - + return + elseif advtrains.interlocking.database.get_tcb(pos) then + -- the punched node itself is a TCB + show_routing_form(pname, pos) + advtrains.interlocking.visualize_route(rp.origin, rp.route, "prog_"..pname, rp.tmp_lcks, pname) return end if advtrains.is_passive(pos) then diff --git a/advtrains_interlocking/signal_api.lua b/advtrains_interlocking/signal_api.lua index 9b0479f..8347b1c 100644 --- a/advtrains_interlocking/signal_api.lua +++ b/advtrains_interlocking/signal_api.lua @@ -400,7 +400,8 @@ end -- 0: not a signal at all -- 1: signal has get_aspect_info() but the aspect is not variable (e.g. a sign) -- 2: signal has apply_aspect() but does not have main aspects (e.g. a pure distant signal) --- 3: Full capabilities, signal has main aspects and can be used as main/shunt signal (can be start/endpoint of a route) +-- 3: signal has main signal role but can only ever display a halt aspect, such as a bumper (can be endpoint, but not startpoint, of a route) +-- 4: Full capabilities, signal has main aspects and can be used as main/shunt signal (can be start/endpoint of a route) function signal.get_signal_cap_level(pos) local node = advtrains.ndb.get_node_or_nil(pos) local ndef = node and minetest.registered_nodes[node.name] @@ -408,6 +409,10 @@ function signal.get_signal_cap_level(pos) if ndefat and ndefat.get_aspect_info then if ndefat.apply_aspect then if ndefat.main_aspects then + -- if the table contains anything, 4, otherwise 3 + for _,_ in pairs(ndefat.main_aspects) do + return 4 + end return 3 end return 2 @@ -419,9 +424,17 @@ end ---------------- -function signal.can_dig(pos) +function signal.can_dig(pos, player) local sigd = advtrains.interlocking.db.get_sigd_for_signal(pos) if sigd then + -- check privileges + if not player or not minetest.check_player_privs(player:get_player_name(), "interlocking") then + if not player then -- intermediate debug to uncover hard-to-find bugz + atdebug("advtrains.interlocking.signal.can_dig(",pos,") called with player==nil!") + end + return false + end + -- check if route is set local tcbs = advtrains.interlocking.db.get_tcbs(sigd) if tcbs.routeset then return false @@ -434,11 +447,7 @@ function signal.after_dig(pos, oldnode, oldmetadata, player) -- unassign signal if necessary local sigd = advtrains.interlocking.db.get_sigd_for_signal(pos) if sigd then - local tcbs = advtrains.interlocking.db.get_tcbs(sigd) - advtrains.interlocking.db.set_sigd_for_signal(pos, nil) - tcbs.signal = nil - tcbs.route_aspect = nil - tcbs.route_remote = nil + advtrains.interlocking.db.unassign_signal_for_tcbs(sigd) minetest.chat_send_player(player:get_player_name(), "Signal has been unassigned. Name and routes are kept for reuse.") end -- TODO clear influence point diff --git a/advtrains_interlocking/tcb_ts_ui.lua b/advtrains_interlocking/tcb_ts_ui.lua index 1cdbb29..2b93234 100755 --- a/advtrains_interlocking/tcb_ts_ui.lua +++ b/advtrains_interlocking/tcb_ts_ui.lua @@ -156,7 +156,7 @@ minetest.register_on_punchnode(function(pos, node, player, pointed_thing) local tcbnpos = players_assign_tcb[pname] if tcbnpos then if vector.distance(pos, tcbnpos)<=20 then - local node_ok, conns, rhe = advtrains.get_rail_info_at(pos, advtrains.all_tracktypes) + local node_ok, conns, rhe = advtrains.get_rail_info_at(pos) if node_ok and #conns == 2 then -- if there is already a tcb here, reassign it if ildb.get_tcb(pos) then @@ -189,11 +189,7 @@ minetest.register_on_punchnode(function(pos, node, player, pointed_thing) if ndef and ndef.advtrains and ndef.advtrains.apply_aspect then local tcbs = ildb.get_tcbs(sigd) if tcbs then - tcbs.signal = pos - if not tcbs.routes then - tcbs.routes = {} - end - ildb.set_sigd_for_signal(pos, sigd) + ildb.assign_signal_to_tcbs(pos, sigd) minetest.chat_send_player(pname, "Configuring TCB: Successfully assigned signal.") advtrains.interlocking.show_ip_form(pos, pname, true) else @@ -212,6 +208,138 @@ minetest.register_on_punchnode(function(pos, node, player, pointed_thing) end end) +-- "Self-contained TCB" +-- 2024-11-25: Buffers should become their own TCB (and signal) automatically to permit setting routes to them +-- These are support functions for this kind of node. + +-- Create an after_place_node callback for a self-contained TCB node. The parameters control additional behavior: +-- fail_silently_on_noprivs: (boolean) Does not give an error in case the placer does not have the interlocking privilege +-- auto_create_self_signal: (boolean) Automatically assign this same node as signal to the A side of the newly-created TCB +-- (this is useful for buffers as they serve both as TCB and as an always-halt signal) +function advtrains.interlocking.self_tcb_make_after_place_callback(fail_silently_on_noprivs, auto_create_self_signal) + return function(pos, player, itemstack, pointed_thing) + atdebug("selftcb apn ",pos, player, itemstack, pointed_thing) + local pname = player:get_player_name() + if not minetest.check_player_privs(pname, "interlocking") then + if not fail_silently_on_noprivs then + minetest.chat_send_player(pname, "Insufficient privileges to use this!") + end + return + end + if ildb.get_tcb(pos) then + minetest.chat_send_player(pname, "TCB already existed at this position, now linked to this node") + else + ildb.create_tcb_at(pos, pname) + end + if auto_create_self_signal then + local sigd = { p = pos, s = 1 } + local tcbs = ildb.get_tcbs(sigd) + -- make sure signal doesn't already exist + if tcbs.signal then + minetest.chat_send_player(pname, "Signal on B side already assigned!") + return + end + ildb.assign_signal_to_tcbs(pos, sigd) + -- assign influence point to itself + ildb.set_ip_signal(advtrains.roundfloorpts(pos), 1, pos) + end + end +end + +-- Create an can_dig callback for a self-contained TCB node. The parameters control additional behavior: +-- is_signal: (boolean) Whether this node is also a signal (in addition to being a TCB), e.g. when auto_create_self_signal was set. +-- Causes also the signal API's can_dig to be called +function advtrains.interlocking.self_tcb_make_can_dig_callback(is_signal) + return function(pos, player) + local pname = player and player:get_player_name() or "" + -- need to duplicate logic of the regular "can_dig_or_modify_track()" function in core/tracks.lua + if advtrains.get_train_at_pos(pos) then + minetest.chat_send_player(pname, "Can't remove track, a train is here!") + return false + end + -- end of standard checks + local tcb = ildb.get_tcb(pos) + if not tcb then + -- digging always allowed because the TCB hasn't been created (unless signal callback interjects) + if is_signal then + return advtrains.interlocking.signal.can_dig(pos, player) + else + return true + end + end + -- TCB exists + if not minetest.check_player_privs(pname, "interlocking") then + return false + end + -- fine to remove (unless signal callback interjects) + if is_signal then + return advtrains.interlocking.signal.can_dig(pos, player) + else + return true + end + end +end + +-- Create an after_dig_node callback for a self-contained TCB node. The parameters control additional behavior: +-- is_signal: (boolean) Whether this node is also a signal (in addition to being a TCB), e.g. when auto_create_self_signal was set. +-- Causes also the signal API's after_dig_node to be called +function advtrains.interlocking.self_tcb_make_after_dig_callback(is_signal) + return function(pos, oldnode, oldmetadata, player) + local pname = player:get_player_name() + if is_signal then + -- "dig" the signal first + advtrains.interlocking.signal.after_dig(pos, oldnode, oldmetadata, player) + end + if ildb.get_tcb(pos) then + -- remove the TCB + ildb.remove_tcb_at(pos, pname, true) + end + end +end + +-- Create an on_rightclick callback for a self-contained TCB node. The rightclick callback tries to repeat the TCB assignment +-- if necessary and otherwise shows the TCB formspec. The parameters control additional behavior: +-- fail_silently_on_noprivs: (boolean) Does not give an error in case the placer does not have the interlocking privilege +-- auto_create_self_signal: (boolean) Automatically assign this same node as signal to the B side of the +-- newly-created TCB if that has not already happened during place. +-- Otherwise, opens the signal dialog instead of the TCB dialog on rightclick +function advtrains.interlocking.self_tcb_make_on_rightclick_callback(fail_silently_on_noprivs, auto_create_self_signal) + return function(pos, node, player, itemstack, pointed_thing) + local pname = player:get_player_name() + if not minetest.check_player_privs(pname, "interlocking") then + if not fail_silently_on_noprivs then + minetest.chat_send_player(pname, "Insufficient privileges to use this!") + end + return + end + if ildb.get_tcb(pos) then + -- TCB already here. go on + else + -- otherwise create tcb + ildb.create_tcb_at(pos, pname) + end + if auto_create_self_signal then + local sigd = { p = pos, s = 1 } + local tcbs = ildb.get_tcbs(sigd) + -- make sure signal doesn't already exist + if not tcbs.signal then + -- go ahead and assign signal + ildb.assign_signal_to_tcbs(pos, sigd) + -- assign influence point to itself + ildb.set_ip_signal(advtrains.roundfloorpts(pos), 1, pos) + end + -- in any case open the signalling form nouw + local control = player:get_player_control() + advtrains.interlocking.show_signal_form(pos, node, pname, control.aux1) + return + else + -- not an autosignal. Then show the TCB form + advtrains.interlocking.show_tcb_form(pos, pname) + return + end + end +end + -- TCB Form local function mktcbformspec(pos, side, tcbs, offset, pname) @@ -666,7 +794,7 @@ function advtrains.interlocking.show_signalling_form(sigd, pname, sel_rte, calle -- 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 + if caps >= 4 then -- offer user the "block signal mode" form = form.."label[0.5,2.5;No routes are yet defined.]" if hasprivs then @@ -683,6 +811,10 @@ function advtrains.interlocking.show_signalling_form(sigd, pname, sel_rte, calle .."Sets a route into the section ahead with auto-working set on\n" .."Short block: This signal becomes distant signal for next signal.]" end + elseif caps >= 3 then + -- it's a buffer! + form = form.."label[0.5,2.5;This is an always-halt signal (e.g. a buffer)\n" + .."No routes can be set from here.]" 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" diff --git a/advtrains_train_track/init.lua b/advtrains_train_track/init.lua index 32e1235..f551ec5 100644 --- a/advtrains_train_track/init.lua +++ b/advtrains_train_track/init.lua @@ -600,6 +600,35 @@ advtrains.register_tracks("default", { --bumpers still use the old texture until the models are redone. description=attrans("Bumper"), formats={}, + get_additional_definiton = function(def, preset, suffix, rotation) + -- 2024-11-25: Bumpers get the additional feature of being both a signal and a self-contained TCB, when interlocking is used. + if advtrains.interlocking then + return { + -- use the special callbacks for self_tcb (see tcb_ts_ui.lua) + can_dig = advtrains.interlocking.self_tcb_make_can_dig_callback(true), + after_dig_node = advtrains.interlocking.self_tcb_make_after_dig_callback(true), + after_place_node = advtrains.interlocking.self_tcb_make_after_place_callback(true, true), + on_rightclick = advtrains.interlocking.self_tcb_make_on_rightclick_callback(false, true), + advtrains = { + main_aspects = { + -- No main aspects, it always shows Stop. + -- But we need to define the table so that signal caplevel is 3 + }, + apply_aspect = function(pos, node, main_aspect, rem_aspect, rem_aspinfo) + -- is a no-op for bumpers, it always shows Stop + end, + get_aspect_info = function(pos, main_aspect) + -- it always shows Stop + return advtrains.interlocking.signal.ASPI_HALT + end, + distant_support = false, -- not a distant + route_role = "end", -- the end is nigh! + } + } + else + return {} -- no additional defs when interlocking is not used + end + end, }, advtrains.ap.t_30deg_straightonly) minetest.register_craft({ output = 'advtrains:dtrack_bumper_placer 2', diff --git a/advtrains_train_track/mod.conf b/advtrains_train_track/mod.conf index 2aece3e..a7fef4d 100644 --- a/advtrains_train_track/mod.conf +++ b/advtrains_train_track/mod.conf @@ -4,4 +4,4 @@ description=Default track set for Advanced Trains author=orwell96 depends=advtrains -optional_depends=mesecons,digtron +optional_depends=mesecons,digtron,advtrains_interlocking -- cgit v1.2.3 From a45a9e27197dc98952f4ada7842f49d81899ab07 Mon Sep 17 00:00:00 2001 From: orwell Date: Wed, 15 Jan 2025 23:19:26 +0100 Subject: Fix bugs found in the video --- advtrains_interlocking/route_prog.lua | 2 +- advtrains_interlocking/signal_api.lua | 6 +++++- advtrains_interlocking/signal_aspect_ui.lua | 4 +++- 3 files changed, 9 insertions(+), 3 deletions(-) (limited to 'advtrains_interlocking/route_prog.lua') diff --git a/advtrains_interlocking/route_prog.lua b/advtrains_interlocking/route_prog.lua index 3bdf6d6..71ebdf3 100644 --- a/advtrains_interlocking/route_prog.lua +++ b/advtrains_interlocking/route_prog.lua @@ -537,7 +537,7 @@ minetest.register_on_punchnode(function(pos, node, player, pointed_thing) show_routing_form(pname, tcbpos) advtrains.interlocking.visualize_route(rp.origin, rp.route, "prog_"..pname, rp.tmp_lcks, pname) return - elseif advtrains.interlocking.database.get_tcb(pos) then + elseif advtrains.interlocking.db.get_tcb(pos) then -- the punched node itself is a TCB show_routing_form(pname, pos) advtrains.interlocking.visualize_route(rp.origin, rp.route, "prog_"..pname, rp.tmp_lcks, pname) diff --git a/advtrains_interlocking/signal_api.lua b/advtrains_interlocking/signal_api.lua index e92658d..f624f7a 100644 --- a/advtrains_interlocking/signal_api.lua +++ b/advtrains_interlocking/signal_api.lua @@ -462,7 +462,11 @@ function signal.after_dig(pos, oldnode, oldmetadata, player) advtrains.interlocking.db.unassign_signal_for_tcbs(sigd) minetest.chat_send_player(player:get_player_name(), "Signal has been unassigned. Name and routes are kept for reuse.") end - -- TODO clear influence point + -- clear influence point + local ipts,iconnid = advtrains.interlocking.db.get_ip_by_signalpos(pos) + if ipts then + advtrains.interlocking.db.clear_ip_signal(ipts, iconnid) + end advtrains.interlocking.signal.unregister_aspect(pos) end diff --git a/advtrains_interlocking/signal_aspect_ui.lua b/advtrains_interlocking/signal_aspect_ui.lua index d67572c..98a332a 100644 --- a/advtrains_interlocking/signal_aspect_ui.lua +++ b/advtrains_interlocking/signal_aspect_ui.lua @@ -247,7 +247,9 @@ minetest.register_on_punchnode(function(pos, node, player, pointed_thing) ipmarker(pos, plconnid) minetest.chat_send_player(pname, "Configuring Signal: Successfully set influence point") -- Try to find a TCB ahead and auto assign this signal there - try_auto_assign_to_tcb(signalpos, pos, plconnid, pname) + if advtrains.interlocking.signal.get_signal_cap_level(signalpos) >= 2 then + try_auto_assign_to_tcb(signalpos, pos, plconnid, pname) + end else minetest.chat_send_player(pname, "Configuring Signal: Influence point of another signal is already present!") end -- cgit v1.2.3 From 5fc9a3073f5c7800b986b0fbcdeaf98d1387e088 Mon Sep 17 00:00:00 2001 From: orwell Date: Tue, 25 Mar 2025 22:31:45 +0100 Subject: fix undeclared global accesses --- advtrains_interlocking/route_prog.lua | 3 +++ advtrains_interlocking/routesetting.lua | 4 ++-- advtrains_signals_ks/init.lua | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) (limited to 'advtrains_interlocking/route_prog.lua') diff --git a/advtrains_interlocking/route_prog.lua b/advtrains_interlocking/route_prog.lua index 71ebdf3..81aa133 100644 --- a/advtrains_interlocking/route_prog.lua +++ b/advtrains_interlocking/route_prog.lua @@ -175,6 +175,9 @@ function advtrains.interlocking.visualize_route(origin, route, context, tmp_lcks -- display locks for pts, state in pairs(v.locks) do local pos = minetest.string_to_pos(pts) + if not pos then + pos = advtrains.decode_pos(pts) + end 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 diff --git a/advtrains_interlocking/routesetting.lua b/advtrains_interlocking/routesetting.lua index 6544a92..1065cad 100644 --- a/advtrains_interlocking/routesetting.lua +++ b/advtrains_interlocking/routesetting.lua @@ -86,8 +86,8 @@ function ilrs.set_route(signal, route, try) local c_locks = {} if route.use_rscache and c_ts.rs_cache and c_rseg.next then -- rscache needs to be enabled, present and next must be defined - start_pkey = advtrains.encode_pos(c_sigd.p) - end_pkey = advtrains.encode_pos(c_rseg.next.p) + local start_pkey = advtrains.encode_pos(c_sigd.p) + local end_pkey = advtrains.encode_pos(c_rseg.next.p) if c_ts.rs_cache[start_pkey] and c_ts.rs_cache[start_pkey][end_pkey] then for lp,lst in pairs(c_ts.rs_cache[start_pkey][end_pkey]) do --atdebug("Add lock from RSCache:",lp,"->",lst) diff --git a/advtrains_signals_ks/init.lua b/advtrains_signals_ks/init.lua index 326c631..70a0ac1 100755 --- a/advtrains_signals_ks/init.lua +++ b/advtrains_signals_ks/init.lua @@ -362,7 +362,7 @@ for _, rtab in ipairs({ paramtype2 = "facedir", selection_box = { type = "fixed", - fixed = {sbox, rotation_sbox} + fixed = {sbox, {-1/4, -1/2, -1/4, 1/4, -7/16, 1/4}} }, collision_box = { type = "fixed", -- cgit v1.2.3