Properly handle repeater signals

This commit is contained in:
Y. Wang 2022-10-24 13:51:03 +02:00
parent 34405b8431
commit 30a0f86248
No known key found for this signature in database
GPG Key ID: 54A05DDF18D7A0EB
6 changed files with 77 additions and 37 deletions

View File

@ -4,6 +4,27 @@ local I = advtrains.interlocking
local N = advtrains.ndb local N = advtrains.ndb
local pts = advtrains.roundfloorpts local pts = advtrains.roundfloorpts
local signal_aspect_metatable = {
__tostring = function(asp)
local st = {}
if asp.type2group and asp.type2name then
table.insert(st, string.format("%q in group %q", asp.type2name, asp.type2group))
end
if asp.main then
table.insert(st, string.format("current %d", asp.main))
end
if asp.main ~= 0 then
if asp.dst then
table.insert(st, string.format("next %d", asp.dst))
end
if asp.proceed_as_main then
table.insert(st, "proceed as main")
end
end
return string.format("[%s]", table.concat(st, ", "))
end,
}
local get_aspect local get_aspect
local supposed_aspects = {} local supposed_aspects = {}
@ -11,6 +32,9 @@ local supposed_aspects = {}
function I.load_supposed_aspects(tbl) function I.load_supposed_aspects(tbl)
if tbl then if tbl then
supposed_aspects = tbl supposed_aspects = tbl
for _, v in pairs(tbl) do
setmetatable(v, signal_aspect_metatable)
end
end end
end end
@ -41,11 +65,14 @@ end
local function adjust_aspect(pos, asp) local function adjust_aspect(pos, asp)
asp = table.copy(I.signal_convert_aspect_if_necessary(asp)) asp = table.copy(I.signal_convert_aspect_if_necessary(asp))
setmetatable(asp, signal_aspect_metatable)
local mainpos = D.get_main(pos) local mainpos = D.get_main(pos)
local nxtasp local nxtasp
if asp.main ~= 0 and mainpos then if mainpos then
nxtasp = get_aspect(mainpos) nxtasp = get_aspect(mainpos)
end
if asp.main ~= 0 and mainpos then
asp.dst = nxtasp.main asp.dst = nxtasp.main
else else
asp.dst = nil asp.dst = nil
@ -59,7 +86,10 @@ local function adjust_aspect(pos, asp)
if stype == 2 then if stype == 2 then
local group = suppasp.group local group = suppasp.group
local name local name
if asp.main ~= 0 and nxtasp and nxtasp.type2group == group and nxtasp.type2name then if suppasp.dst_shift and nxtasp then
asp.main = nil
name = A.type1_to_type2main(nxtasp, group, suppasp.dst_shift)
elseif asp.main ~= 0 and nxtasp and nxtasp.type2group == group and nxtasp.type2name then
name = A.get_type2_dst(group, nxtasp.type2name) name = A.get_type2_dst(group, nxtasp.type2name)
else else
name = A.type1_to_type2main(asp, group) name = A.type1_to_type2main(asp, group)
@ -79,7 +109,7 @@ local function get_real_aspect(pos)
local asp = ndef.advtrains.get_aspect(pos, node) or I.DANGER local asp = ndef.advtrains.get_aspect(pos, node) or I.DANGER
local suppasp = get_supported_aspects(pos) local suppasp = get_supported_aspects(pos)
if suppasp.type == 2 then if suppasp.type == 2 then
asp = A.type2main_to_type1(suppasp.group, asp) asp = A.type2_to_type1(suppasp, asp)
end end
return adjust_aspect(pos, asp) return adjust_aspect(pos, asp)
end end
@ -108,11 +138,6 @@ local function set_aspect(pos, asp, skipdst)
if (not skipdst) and aspect_changed then if (not skipdst) and aspect_changed then
D.update_main(pos) D.update_main(pos)
end end
--[[
local dbgmsg = string.format("[%s]set_aspect(%s,%s,%s)", os.clock(), minetest.pos_to_string(pos), minetest.serialize(asp), tostring(skipdst))
dbgmsg = debug.traceback(dbgmsg, 2)
minetest.chat_send_all(dbgmsg)
--]]
end end
end end

View File

@ -219,7 +219,7 @@ local function get_aspect_from_formspec_t1(suppasp, fields)
end end
local function get_aspect_from_formspec_t2(suppasp, fields) local function get_aspect_from_formspec_t2(suppasp, fields)
local asp = advtrains.interlocking.aspects.type2main_to_type1(suppasp.group, tonumber(fields.asp)) local asp = advtrains.interlocking.aspects.type2_to_type1(suppasp, tonumber(fields.asp))
return asp return asp
end end

View File

@ -67,7 +67,9 @@ local function get_type2_dst(group, name)
return def.main[math.max(1, aspidx-1)].name return def.main[math.max(1, aspidx-1)].name
end end
local function type2main_to_type1(name, asp) local function type2_to_type1(suppasp, asp)
local name = suppasp.group
local shift = suppasp.dst_shift
local def = type2defs[name] local def = type2defs[name]
if not def then if not def then
return nil return nil
@ -78,18 +80,26 @@ local function type2main_to_type1(name, asp)
else else
aspidx = def.main[asp] or 2 aspidx = def.main[asp] or 2
end end
local asptbl = def.main[aspidx] local realidx = math.min(#def.main, aspidx+(shift or 0))
local asptbl = def.main[realidx]
if not asptbl then if not asptbl then
return nil return nil
end end
if type(asp) == "number" then if type(asp) == "number" then
asp = asptbl.name asp = asptbl.name
end end
local dst = def.main[math.min(#def.main, aspidx+1)].main local main, shunt, dst
if shift then
dst = asptbl.main
else
main = asptbl.main
shunt = asptbl.shunt
dst = def.main[math.min(#def.main, aspidx+1)].main
end
local t = { local t = {
main = asptbl.main, main = main,
shunt = asptbl.shunt, shunt = shunt,
proceed_as_main = asptbl.proceed_as_main, proceed_as_main = asptbl.proceed_as_main,
type2name = asp, type2name = asp,
type2group = name, type2group = name,
@ -101,31 +111,28 @@ local function type2main_to_type1(name, asp)
return t return t
end end
local function type1_to_type2main(asp, group) local function type1_to_type2main(asp, group, shift)
local def = type2defs[group] local def = type2defs[group]
if not def then if not def then
return nil return nil
end end
if group == asp.type2group and def.main[asp.type2name] then
return asp.type2name
end
local t_main = def.main local t_main = def.main
local idx local idx
if not asp.main or asp.main == -1 then if group == asp.type2group and t_main[asp.type2name] then
idx = t_main[asp.type2name]
elseif not asp.main or asp.main == -1 then
idx = 1 idx = 1
elseif asp.main == 0 then elseif asp.main == 0 then
idx = #t_main idx = #t_main
else else
idx = math.max(#t_main-1, 1) idx = #t_main-1
end end
return t_main[idx].name return t_main[math.max(1, idx-(shift or 0))].name
end end
local function equalp(asp1, asp2) local function equalp(asp1, asp2)
if asp1 == asp2 then -- same reference if asp1 == asp2 then -- same reference
return true return true
elseif asp1.type2group and asp1.type2group == asp2.type2group then -- type2 with the same group
return asp1.type2name == asp2.type2name
else else
for _, k in pairs {"main", "shunt", "dst"} do for _, k in pairs {"main", "shunt", "dst"} do
if asp1[k] ~= asp2[k] then if asp1[k] ~= asp2[k] then
@ -133,6 +140,9 @@ local function equalp(asp1, asp2)
end end
end end
end end
if asp1.type2group and asp1.type2group == asp2.type2group then
return asp1.type2name == asp2.type2name
end
return true return true
end end
@ -144,7 +154,7 @@ return {
register_type2 = register_type2, register_type2 = register_type2,
get_type2_definition = get_type2_definition, get_type2_definition = get_type2_definition,
get_type2_dst = get_type2_dst, get_type2_dst = get_type2_dst,
type2main_to_type1 = type2main_to_type1, type2_to_type1 = type2_to_type1,
type1_to_type2main = type1_to_type2main, type1_to_type2main = type1_to_type2main,
equalp = equalp, equalp = equalp,
not_equalp = not_equalp, not_equalp = not_equalp,

View File

@ -44,7 +44,7 @@ world.layout {
describe("API for supposed signal aspects", function() describe("API for supposed signal aspects", function()
it("should load and save data properly", function() it("should load and save data properly", function()
local tbl = {_foo = true} local tbl = {_foo = {}}
I.load_supposed_aspects(tbl) I.load_supposed_aspects(tbl)
assert.same(tbl, I.save_supposed_aspects()) assert.same(tbl, I.save_supposed_aspects())
end) end)

View File

@ -198,20 +198,24 @@ minetest.register_on_punchnode(function(pos, node, player, pointed_thing)
if is_signal then if is_signal then
local ndef = minetest.registered_nodes[node.name] local ndef = minetest.registered_nodes[node.name]
if ndef and ndef.advtrains and ndef.advtrains.set_aspect then if ndef and ndef.advtrains and ndef.advtrains.set_aspect then
local tcbs = ildb.get_tcbs(sigd) if ndef.advtrains.supported_aspects and not ndef.advtrains.supported_aspects.dst_shift then
if tcbs then local tcbs = ildb.get_tcbs(sigd)
tcbs.signal = pos if tcbs then
if not tcbs.signal_name then tcbs.signal = pos
tcbs.signal_name = "Signal at "..minetest.pos_to_string(sigd.p) if not tcbs.signal_name then
tcbs.signal_name = "Signal at "..minetest.pos_to_string(sigd.p)
end
if not tcbs.routes then
tcbs.routes = {}
end
ildb.set_sigd_for_signal(pos, sigd)
minetest.chat_send_player(pname, "Configuring TCB: Successfully assigned signal.")
advtrains.interlocking.show_ip_form(pos, pname, true)
else
minetest.chat_send_player(pname, "Configuring TCB: Internal error, TCBS doesn't exist. Aborted.")
end end
if not tcbs.routes then
tcbs.routes = {}
end
ildb.set_sigd_for_signal(pos, sigd)
minetest.chat_send_player(pname, "Configuring TCB: Successfully assigned signal.")
advtrains.interlocking.show_ip_form(pos, pname, true)
else else
minetest.chat_send_player(pname, "Configuring TCB: Internal error, TCBS doesn't exist. Aborted.") minetest.chat_send_player(pname, "Configuring TCB: Cannot use distant signal. Aborted.")
end end
else else
minetest.chat_send_player(pname, "Configuring TCB: Cannot use static signals for routesetting. Aborted.") minetest.chat_send_player(pname, "Configuring TCB: Cannot use static signals for routesetting. Aborted.")

View File

@ -401,6 +401,7 @@ for _, rtab in ipairs {
supported_aspects = { supported_aspects = {
type = 2, type = 2,
group = siginfo.typename, group = siginfo.typename,
dst_shift = siginfo.isdst and 0,
}, },
get_aspect = function() get_aspect = function()
return asp return asp