diff options
author | orwell <orwell@bleipb.de> | 2024-04-08 21:52:32 +0200 |
---|---|---|
committer | orwell <orwell@bleipb.de> | 2024-04-08 21:52:32 +0200 |
commit | 852da6bcaeeb8c39ce73639ef64f10ebc5b127b0 (patch) | |
tree | ebd944b0b8a763b63f128e7a7bf81882a4e8c29f /advtrains_interlocking/distant.lua | |
parent | 9fa43cb7bfc25ba71d16c8210f0074797a7bca1a (diff) | |
parent | 1f74697e85d456e97e201cdd9edef91a2df4fc14 (diff) | |
download | advtrains-852da6bcaeeb8c39ce73639ef64f10ebc5b127b0.tar.gz advtrains-852da6bcaeeb8c39ce73639ef64f10ebc5b127b0.tar.bz2 advtrains-852da6bcaeeb8c39ce73639ef64f10ebc5b127b0.zip |
Merge branch 'new-ks-orwell' into route_prog_rework
Diffstat (limited to 'advtrains_interlocking/distant.lua')
-rw-r--r-- | advtrains_interlocking/distant.lua | 200 |
1 files changed, 200 insertions, 0 deletions
diff --git a/advtrains_interlocking/distant.lua b/advtrains_interlocking/distant.lua new file mode 100644 index 0000000..32ada82 --- /dev/null +++ b/advtrains_interlocking/distant.lua @@ -0,0 +1,200 @@ +--- Distant signaling. +-- This module implements a database backend for distant signal assignments. +-- The actual modifications to signal aspects are still done by signal aspect accessors. +-- @module advtrains.interlocking.distant + +local db_distant = {} +local db_distant_of = {} + +local pts = advtrains.encode_pos +local stp = advtrains.decode_pos + +--- Replace the distant signal assignment database. +-- @function load +-- @param db The new database to load. +local function db_load(x) + if type(x) ~= "table" then + return + end + db_distant = x.distant + db_distant_of = x.distant_of +end + +--- Retrieve the current distant signal assignment database. +-- @function save +-- @return The current database. +local function db_save() + return { + distant = db_distant, + distant_of = db_distant_of, + } +end + +local update_signal, update_main, update_dst + +--- Unassign a distant signal. +-- @function unassign_dst +-- @param dst The position of the distant signal. +-- @param[opt=false] force Whether to skip callbacks. +local function unassign_dst(dst, force) + local pts_dst = pts(dst) + local main = db_distant_of[pts_dst] + db_distant_of[pts_dst] = nil + if main then + local pts_main = main[1] + local t = db_distant[pts_main] + if t then + t[pts_dst] = nil + end + end + if not force then + update_dst(dst) + end +end + +--- Unassign a main signal. +-- @function unassign_main +-- @param main The position of the main signal. +-- @param[opt=false] force Whether to skip callbacks. +local function unassign_main(main, force) + local pts_main = pts(main) + local t = db_distant[pts_main] + if not t then + return + end + for pts_dst in pairs(t) do + local realmain = db_distant_of[pts_dst] + if realmain and realmain[1] == pts_main then + db_distant_of[pts_dst] = nil + if not force then + local dst = stp(pts_dst) + update_dst(dst) + end + end + end + db_distant[pts_main] = nil +end + +--- Remove all (main and distant) signal assignments from a signal. +-- @function unassign_all +-- @param pos The position of the signal. +-- @param[opt=false] force Whether to skip callbacks. +local function unassign_all(pos, force) + unassign_main(pos) + unassign_dst(pos, force) +end + +--- Check whether a signal is "appropriate" for the distant signal system. +-- Currently, a signal is considered appropriate if its signal aspect can be set. +-- @function appropriate_signal +-- @param pos The position of the signal +local function appropriate_signal(pos) + local node = advtrains.ndb.get_node(pos) + local ndef = minetest.registered_nodes[node.name] or {} + if not ndef then + return false + end + local atdef = ndef.advtrains + if not atdef then + return false + end + return atdef.supported_aspects and atdef.set_aspect and true +end + +--- Assign a distant signal to a main signal. +-- @function assign +-- @param main The position of the main signal. +-- @param dst The position of the distant signal. +-- @param[opt="manual"] by The method of assignment. +-- @param[opt=false] skip_update Whether to skip callbacks. +local function assign(main, dst, by, skip_update) + if not (appropriate_signal(main) and appropriate_signal(dst)) then + return + end + local pts_main = pts(main) + local pts_dst = pts(dst) + local t = db_distant[pts_main] + if not t then + t = {} + db_distant[pts_main] = t + end + if not by then + by = "manual" + end + unassign_dst(dst, true) + t[pts_dst] = by + db_distant_of[pts_dst] = {pts_main, by} + if not skip_update then + update_dst(dst) + end +end + +--- Get the distant signals assigned to a main signal. +-- @function get_distant +-- @param main The position of the main signal. +-- @treturn {[pos]=by,...} A table of distant signals, with the positions encoded using `advtrains.encode_pos`. +local function get_distant(main) + local pts_main = pts(main) + return db_distant[pts_main] or {} +end + +--- Get the main signal assigned the a distant signal. +-- @function get_main +-- @param dst The position of the distant signal. +-- @return The position of the main signal. +-- @return The method of assignment. +local function get_main(dst) + local pts_dst = pts(dst) + local main = db_distant_of[pts_dst] + if not main then + return + end + if main[1] then + return stp(main[1]), unpack(main, 2) + else + return unpack(main) + end +end + +--- Update all distant signals assigned to a main signal. +-- @function update_main +-- @param main The position of the main signal. +update_main = function(main) + local pts_main = pts(main) + local t = get_distant(main) + for pts_dst in pairs(t) do + local dst = stp(pts_dst) + advtrains.interlocking.signal_readjust_aspect(dst) + end +end + +--- Update the aspect of a distant signal. +-- @function update_dst +-- @param dst The position of the distant signal. +update_dst = function(dst) + advtrains.interlocking.signal_readjust_aspect(dst) +end + +--- Update the aspect of a combined (main and distant) signal and all distant signals assigned to it. +-- @function update_signal +-- @param pos The position of the signal. +update_signal = function(pos) + update_main(pos) + update_dst(pos) +end + +advtrains.distant = { + load = db_load, + save = db_save, + assign = assign, + unassign_dst = unassign_dst, + unassign_main = unassign_main, + unassign_all = unassign_all, + get_distant = get_distant, + get_dst = get_distant, + get_main = get_main, + update_main = update_main, + update_dst = update_dst, + update_signal = update_signal, + appropriate_signal = appropriate_signal, +} |