164 lines
4.7 KiB
Lua
164 lines
4.7 KiB
Lua
--- Signal aspect accessors
|
|
-- @module advtrains.interlocking
|
|
|
|
local A = advtrains.interlocking.aspect
|
|
local D = advtrains.distant
|
|
local I = advtrains.interlocking
|
|
local N = advtrains.ndb
|
|
local pts = advtrains.roundfloorpts
|
|
|
|
local get_aspect
|
|
|
|
local supposed_aspects = {}
|
|
|
|
--- Replace the signal aspect cache.
|
|
-- @function load_supposed_aspects
|
|
-- @param db The new database.
|
|
function I.load_supposed_aspects(tbl)
|
|
if tbl then
|
|
supposed_aspects = {}
|
|
for k, v in pairs(tbl) do
|
|
supposed_aspects[k] = A(v)
|
|
end
|
|
end
|
|
end
|
|
|
|
--- Retrieve the signal aspect cache.
|
|
-- @function save_supposed_aspects
|
|
-- @return The current database in use.
|
|
function I.save_supposed_aspects()
|
|
local t = {}
|
|
for k, v in pairs(supposed_aspects) do
|
|
t[k] = v:plain(true)
|
|
end
|
|
return t
|
|
end
|
|
|
|
--- Read the aspect of a signal strictly from cache.
|
|
-- @param pos The position of the signal.
|
|
-- @return[1] The aspect of the signal (if present in cache).
|
|
-- @return[2] The nil constant (otherwise).
|
|
local function get_supposed_aspect(pos)
|
|
return supposed_aspects[pts(pos)]
|
|
end
|
|
|
|
--- Update the signal aspect information in cache.
|
|
-- @param pos The position of the signal.
|
|
-- @param asp The new signal aspect
|
|
local function set_supposed_aspect(pos, asp)
|
|
supposed_aspects[pts(pos)] = asp
|
|
end
|
|
|
|
--- Get the definition of a node.
|
|
-- @param pos The position of the node.
|
|
-- @return[1] The definition of the node (if present).
|
|
-- @return[2] An empty table (otherwise).
|
|
local function get_ndef(pos)
|
|
local node = N.get_node(pos)
|
|
return (minetest.registered_nodes[node.name] or {}), node
|
|
end
|
|
|
|
--- Get the aspects supported by a signal.
|
|
-- @function signal_get_supported_aspects
|
|
-- @param pos The position of the signal.
|
|
-- @return[1] The table of supported aspects (if present).
|
|
-- @return[2] The nil constant (otherwise).
|
|
local function get_supported_aspects(pos)
|
|
local ndef = get_ndef(pos)
|
|
if ndef.advtrains and ndef.advtrains.supported_aspects then
|
|
return ndef.advtrains.supported_aspects
|
|
end
|
|
return nil
|
|
end
|
|
|
|
--- Adjust a new signal aspect to fit a signal.
|
|
-- @param pos The position of the signal.
|
|
-- @param asp The new signal aspect.
|
|
-- @return The adjusted signal aspect.
|
|
-- @return The information to pass to the `advtrains.set_aspect` field in the node definitions.
|
|
local function adjust_aspect(pos, asp)
|
|
local asp = A(asp)
|
|
|
|
local mainpos = D.get_main(pos)
|
|
local nxtasp
|
|
if mainpos then
|
|
nxtasp = get_aspect(mainpos)
|
|
end
|
|
local suppasp = get_supported_aspects(pos)
|
|
if not suppasp then
|
|
return asp
|
|
end
|
|
return asp:adjust_distant(nxtasp, suppasp.dst_shift):to_group(suppasp.group)
|
|
end
|
|
|
|
--- Get the aspect of a signal without accessing the cache.
|
|
-- For most cases, `get_aspect` should be used instead.
|
|
-- @function signal_get_real_aspect
|
|
-- @param pos The position of the signal.
|
|
-- @return[1] The signal aspect adjusted using `adjust_aspect` (if present).
|
|
-- @return[2] The nil constant (otherwise).
|
|
local function get_real_aspect(pos)
|
|
local ndef, node = get_ndef(pos)
|
|
if ndef.advtrains and ndef.advtrains.get_aspect then
|
|
local asp = ndef.advtrains.get_aspect(pos, node) or I.DANGER
|
|
return adjust_aspect(pos, asp)
|
|
end
|
|
return nil
|
|
end
|
|
|
|
--- Get the aspect of a signal.
|
|
-- @function signal_get_aspect
|
|
-- @param pos The position of the signal.
|
|
-- @return[1] The aspect of the signal (if present).
|
|
-- @return[2] The nil constant (otherwise).
|
|
get_aspect = function(pos)
|
|
local asp = get_supposed_aspect(pos)
|
|
if not asp then
|
|
asp = get_real_aspect(pos)
|
|
set_supposed_aspect(pos, asp)
|
|
end
|
|
return asp
|
|
end
|
|
|
|
--- Set the aspect of a signal.
|
|
-- @function signal_set_aspect
|
|
-- @param pos The position of the signal.
|
|
-- @param asp The new signal aspect.
|
|
-- @param[opt=false] skipdst Whether to skip updating distant signals.
|
|
local function set_aspect(pos, asp, skipdst)
|
|
local node = N.get_node(pos)
|
|
local ndef = minetest.registered_nodes[node.name]
|
|
if ndef and ndef.advtrains and ndef.advtrains.set_aspect then
|
|
local oldasp = I.signal_get_aspect(pos) or DANGER
|
|
local newasp = adjust_aspect(pos, asp)
|
|
set_supposed_aspect(pos, newasp)
|
|
ndef.advtrains.set_aspect(pos, node, newasp)
|
|
I.signal_on_aspect_changed(pos)
|
|
local aspect_changed = oldasp ~= newasp
|
|
if (not skipdst) and aspect_changed then
|
|
D.update_main(pos)
|
|
end
|
|
end
|
|
end
|
|
|
|
--- Remove a signal from cache.
|
|
-- @function signal_clear_aspect
|
|
-- @param pos The position of the signal.
|
|
local function clear_aspect(pos)
|
|
set_supposed_aspect(pos, nil)
|
|
end
|
|
|
|
--- Readjust the aspect of a signal.
|
|
-- @function signal_readjust_aspect
|
|
-- @param pos The position of the signal.
|
|
local function readjust_aspect(pos)
|
|
set_aspect(pos, get_aspect(pos))
|
|
end
|
|
|
|
I.signal_get_supported_aspects = get_supported_aspects
|
|
I.signal_get_real_aspect = get_real_aspect
|
|
I.signal_get_aspect = get_aspect
|
|
I.signal_set_aspect = set_aspect
|
|
I.signal_clear_aspect = clear_aspect
|
|
I.signal_readjust_aspect = readjust_aspect
|