From d794e382b59bb42888f3fb9b1d61f6ac6f7e2bdb Mon Sep 17 00:00:00 2001 From: "Y. Wang" Date: Wed, 13 Apr 2022 12:54:58 +0200 Subject: Primitive (not fully tested) support for route signaling --- advtrains_interlocking/init.lua | 2 + advtrains_interlocking/signal_api.lua | 13 +++- advtrains_interlocking/signal_aspect_ui.lua | 51 +++++++++++--- advtrains_interlocking/signal_aspects.lua | 102 ++++++++++++++++++++++++++++ advtrains_signals_japan/init.lua | 49 ++++++++++--- 5 files changed, 198 insertions(+), 19 deletions(-) create mode 100644 advtrains_interlocking/signal_aspects.lua diff --git a/advtrains_interlocking/init.lua b/advtrains_interlocking/init.lua index a5bf41e..d0b75a8 100644 --- a/advtrains_interlocking/init.lua +++ b/advtrains_interlocking/init.lua @@ -12,6 +12,8 @@ end local modpath = minetest.get_modpath(minetest.get_current_modname()) .. DIR_DELIM +advtrains.interlocking.aspects = dofile(modpath.."signal_aspects.lua") + dofile(modpath.."database.lua") dofile(modpath.."signal_api.lua") dofile(modpath.."signal_aspect_ui.lua") diff --git a/advtrains_interlocking/signal_api.lua b/advtrains_interlocking/signal_api.lua index 78acc0a..e4b2993 100644 --- a/advtrains_interlocking/signal_api.lua +++ b/advtrains_interlocking/signal_api.lua @@ -220,6 +220,10 @@ function advtrains.interlocking.signal_set_aspect(pos, asp) local node=advtrains.ndb.get_node(pos) local ndef=minetest.registered_nodes[node.name] if ndef and ndef.advtrains and ndef.advtrains.set_aspect then + local suppasp = advtrains.interlocking.signal_get_supported_aspects(pos) + if suppasp.type == 2 then + asp = advtrains.interlocking.aspects.type1_to_type2main(asp, suppasp.group) + end ndef.advtrains.set_aspect(pos, node, asp) advtrains.interlocking.signal_on_aspect_changed(pos) end @@ -252,7 +256,7 @@ function advtrains.interlocking.signal_rc_handler(pos, node, player, itemstack, local function callback(pname, aspect) advtrains.interlocking.signal_set_aspect(pos, aspect) end - local isasp = ndef.advtrains.get_aspect(pos, node) + local isasp = advtrains.interlocking.signal_get_aspect(pos, node) advtrains.interlocking.show_signal_aspect_selector( pname, @@ -285,8 +289,13 @@ function advtrains.interlocking.signal_get_aspect(pos) local ndef=minetest.registered_nodes[node.name] if ndef and ndef.advtrains and ndef.advtrains.get_aspect then local asp = ndef.advtrains.get_aspect(pos, node) + local suppasp = advtrains.interlocking.signal_get_supported_aspects(pos) + if suppasp.type == 2 then + asp = advtrains.interlocking.aspects.type2main_to_type1(suppasp.group, asp) + end if not asp then asp = DANGER end - return convert_aspect_if_necessary(asp) + asp = convert_aspect_if_necessary(asp) + return asp end return nil end diff --git a/advtrains_interlocking/signal_aspect_ui.lua b/advtrains_interlocking/signal_aspect_ui.lua index d5a7543..472155a 100644 --- a/advtrains_interlocking/signal_aspect_ui.lua +++ b/advtrains_interlocking/signal_aspect_ui.lua @@ -2,7 +2,7 @@ local F = advtrains.formspec local players_aspsel = {} local function make_signal_aspect_selector_t1(suppasp, purpose, isasp) - local form = {"size[7,7]"} + local form = {"size[7,7.5]"} form[#form+1] = F.S_label(0.5, 0.5, "Select signal aspect") form[#form+1] = F.label(0.5, 1, purpose) @@ -59,7 +59,29 @@ local function make_signal_aspect_selector_t1(suppasp, purpose, isasp) end form[#form+1] = F.dropdown(0.5, 5, 6, "dst", entries, selid, true) - form[#form+1] = F.S_button_exit(0.5, 6, 5, 1, "save", "Save signal aspect") + form[#form+1] = F.S_button_exit(0.5, 6, 6, 1, "save", "Save signal aspect") + return table.concat(form) +end + +local function make_signal_aspect_selector_t2(suppasp, purpose, isasp) + local form = {"size[7,4]"} + local def = advtrains.interlocking.aspects.get_type2_definition(suppasp.group) + if not def then + return nil + end + form[#form+1] = F.S_label(0.5, 0.5, "Select signal aspect") + form[#form+1] = F.label(0.5, 1, purpose) + + local entries = {} + local selid = 1 + for idx, spv in ipairs(def.main) do + if isasp and isasp.type2name == spv.name then + selid = idx + end + entries[idx] = spv.label + end + form[#form+1] = F.dropdown(0.5, 1.5, 6, "asp", entries, selid, true) + form[#form+1] = F.S_button_exit(0.5, 2.5, 6, 1, "save", "Save signal aspect") return table.concat(form) end @@ -73,9 +95,14 @@ function advtrains.interlocking.show_signal_aspect_selector(pname, p_suppasp, p_ local purpose = p_purpose or "" local form - if true then + if suppasp.type == 2 then + form = make_signal_aspect_selector_t2(suppasp, purpose, isasp) + else form = make_signal_aspect_selector_t1(suppasp, purpose, isasp) end + if not form then + return + end local token = advtrains.random_id() minetest.show_formspec(pname, "at_il_sigaspdia_"..token, form) @@ -107,18 +134,26 @@ local function get_aspect_from_formspec_t1(suppasp, fields) } end +local function get_aspect_from_formspec_t2(suppasp, fields) + local asp = advtrains.interlocking.aspects.type2main_to_type1(suppasp.group, tonumber(fields.asp)) + return asp +end + minetest.register_on_player_receive_fields(function(player, formname, fields) local pname = player:get_player_name() local psl = players_aspsel[pname] if psl then if formname == "at_il_sigaspdia_"..psl.token then + local suppasp = psl.suppasp if fields.save then local asp - if true then - asp = get_aspect_from_formspec_t1(psl.suppasp, fields) - if asp then - psl.callback(pname, asp) - end + if suppasp.type == 2 then + asp = get_aspect_from_formspec_t2(suppasp, fields) + else + asp = get_aspect_from_formspec_t1(suppasp, fields) + end + if asp then + psl.callback(pname, asp) end end else diff --git a/advtrains_interlocking/signal_aspects.lua b/advtrains_interlocking/signal_aspects.lua new file mode 100644 index 0000000..e604f9b --- /dev/null +++ b/advtrains_interlocking/signal_aspects.lua @@ -0,0 +1,102 @@ +type2defs = {} + +local function register_type2(def) + local t = {type = 2} + local name = def.name + if type2defs[name] then + return error("Name " .. name .. " already used") + elseif type(name) ~= "string" then + return error("Name is not a string") + end + t.name = name + + local label = def.label or name + if type(label) ~= "string" then + return error("Label is not a string") + end + t.label = label + + local mainasps = {} + for idx, asp in ipairs(def.main) do + local t = {} + local name = asp.name + if type(name) ~= "string" then + return error("Aspect name is not a string") + end + t.name = name + + local label = asp.label or name + if type(label) ~= "string" then + return error("Aspect label is not a string") + end + t.label = label + + t.main = asp.main + mainasps[idx] = t + mainasps[name] = idx + end + t.main = mainasps + + type2defs[name] = t +end + +local function get_type2_definition(name) + return type2defs[name] +end + +local function type2main_to_type1(name, asp) + local def = type2defs[name] + if not def then + return nil + end + local aspidx + if type(asp) == "number" then + aspidx = asp + else + aspidx = def.main[asp] + end + local asptbl = def.main[aspidx] + if not asptbl then + return nil + end + if type(asp) == "number" then + asp = asptbl.name + end + + local t = { + main = asptbl.main, + type2name = asp, + type2group = name, + } + if aspidx ~= 1 and aspidx ~= #asptbl then + t.dst = def.main[aspidx+1].main + end + return t +end + +local function type1_to_type2main(asp, group) + local def = type2defs[group] + if not def then + return nil + end + if group == asp.type2group and def.main[asp.type2name] then + return asp.type2name + end + local t_main = def.main + local idx + if not asp.main or asp.main == -1 then + idx = 1 + elseif asp.main == 0 then + idx = #t_main + else + idx = math.max(#t_main-1, 1) + end + return t_main[idx].name +end + +return { + register_type2 = register_type2, + get_type2_definition = get_type2_definition, + type2main_to_type1 = type2main_to_type1, + type1_to_type2main = type1_to_type2main, +} diff --git a/advtrains_signals_japan/init.lua b/advtrains_signals_japan/init.lua index a546847..7b11d85 100644 --- a/advtrains_signals_japan/init.lua +++ b/advtrains_signals_japan/init.lua @@ -278,14 +278,26 @@ minetest.register_node("advtrains_signals_japan:pole_0", { local sigdefs = {} local lightcolors = { red = "red", - green = "green", + green = "lime", yellow = "orange", distant = "purple", } -local function process_signal(sigdata, isrpt) +local aspnames = { + danger = "Danger (halt)", + restrictedspeed = "Restricted speed", + caution = "Caution", + reducedspeed = "Reduced speed", + clear = "Clear (proceed)", +} +local function process_signal(name, sigdata, isrpt) + local typename = "advtrains_signals_japan:" .. name + local type2def = {} + type2def.name = typename + type2def.main = {} local def = {} local tx = {} local invimg = {} + def.typename = typename def.textures = tx def.inventory_images = invimg def.desc = sigdata.desc @@ -296,7 +308,7 @@ local function process_signal(sigdata, isrpt) lightcount = lightcount+1 end def.lightcount = lightcount - for _, asp in pairs(sigdata.aspects) do + for idx, asp in ipairs(sigdata.aspects) do local aspname = asp.name local tt = { string.format("[combine:1x%d", lightcount), @@ -318,6 +330,10 @@ local function process_signal(sigdata, isrpt) end tx[aspname] = table.concat(tt, ":") invimg[aspname] = table.concat(it, ":") + type2def.main[idx] = {name = asp.name, label = S(aspnames[asp.name]), main = asp.main or false} + end + if not isrpt then + advtrains.interlocking.aspects.register_type2(type2def) end return def end @@ -326,16 +342,16 @@ for sigtype, sigdata in pairs { desc = "5A", lights = {"yellow", "yellow", "red", "yellow", "green"}, aspects = { - {name = "danger", lights = {3}}, + {name = "danger", lights = {3}, main = 0}, {name = "restrictedspeed", lights = {1, 3}}, {name = "caution", lights = {4}}, {name = "reducedspeed", lights = {2, 5}}, - {name = "clear", lights = {5}}, + {name = "clear", lights = {5}, main = -1}, } } } do - sigdefs["main_"..sigtype] = process_signal(sigdata) - sigdefs["rpt_"..sigtype] = process_signal(sigdata, true) + sigdefs["main_"..sigtype] = process_signal(sigtype, sigdata) + sigdefs["rpt_"..sigtype] = process_signal(sigtype, sigdata, true) end for k in pairs(sigdefs) do @@ -371,13 +387,28 @@ for _, rtab in ipairs { }, groups = { cracky = 2, - --advtrains_signal = 1, + advtrains_signal = 1, not_blocking_trains = 1, - --save_in_at_nodedb = 1, + save_in_at_nodedb = 1, not_in_creative_inventory = rtab.ici and 0 or 1, }, inventory_image = siginfo.inventory_images[asp], drop = "advtrains_signals_japan:"..sigtype.."_danger_0", + advtrains = { + supported_aspects = { + type = 2, + group = siginfo.typename, + }, + get_aspect = function() + return asp + end, + set_aspect = function(pos, node, asp) + advtrains.ndb.swap_node(pos, {name = "advtrains_signals_japan:"..sigtype.."_"..asp.."_"..rot, param2 = node.param2}) + end, + }, + on_rightclick = advtrains.interlocking.signal_rc_handler, + can_dig = advtrains.interlocking.signal_can_dig, + after_dig_node = advtrains.interlocking.signal_after_dig, }) advtrains.trackplacer.add_worked("advtrains_signals_japan:"..sigtype, asp, "_"..rot) end -- cgit v1.2.3