-- Track Circuit Breaks and Track Sections - Player interactionlocal players_assign_tcb = {}local players_assign_signal = {}local players_link_ts = {}local ildb = advtrains.interlocking.db
local ilrs = advtrains.interlocking.route
local sigd_equal = advtrains.interlocking.sigd_equal
local lntrans = {"A","B"}local functionsigd_to_string(sigd)return minetest.pos_to_string(sigd.p).." / "..lntrans[sigd.s]end
minetest.register_node("advtrains_interlocking:tcb_node", {
drawtype ="mesh",
paramtype="light",
paramtype2="facedir",
walkable =false,
selection_box = {type="fixed",
fixed = {-1/6, -1/2, -1/6,1/6,1/4,1/6},},
mesh ="at_il_tcb_node.obj",
tiles = {"at_il_tcb_node.png"},
description="Track Circuit Break",
sunlight_propagates=true,
groups = {
cracky=3,
not_blocking_trains=1,--save_in_at_nodedb=2,
at_il_track_circuit_break =1,},
after_place_node =function(pos, node, player)local meta = minetest.get_meta(pos)
meta:set_string("infotext","Unconfigured Track Circuit Break, right-click to assign.")end,
on_rightclick =function(pos, node, player)local pname = player:get_player_name()if not minetest.check_player_privs(pname,"interlocking")then
minetest.chat_send_player(pname,"Insufficient privileges to use this!")returnendlocal meta = minetest.get_meta(pos)local tcbpts = meta:get_string("tcb_pos")if tcbpts ~=""thenlocal tcbpos = minetest.string_to_pos(tcbpts)local tcb = ildb.get_tcb(tcbpos)if tcb then
advtrains.interlocking.show_tcb_form(tcbpos, pname)else
minetest.chat_send_player(pname,"This TCB has been removed. Please dig marker.")endelse--unconfigured
minetest.chat_send_player(pname,"Configuring TCB: Please punch the rail you want to assign this TCB to.")
players_assign_tcb[pname] = pos
endend,--on_punch = function(pos, node, player)-- local meta = minetest.get_meta(pos)-- local tcbpts = meta:get_string("tcb_pos")-- if tcbpts ~= "" then-- local tcbpos = minetest.string_to_pos(tcbpts)-- advtrains.interlocking.show_tcb_marker(tcbpos)-- end --end,
can_dig =function(pos, player)if player ==nil then return false endlocal pname = player:get_player_name()-- Those markers can only be dug when all adjacent TS's are set-- as EOI.local meta = minetest.get_meta(pos)local tcbpts = meta:get_string("tcb_pos")if tcbpts ~=""thenif not minetest.check_player_privs(pname,"interlocking")then
minetest.chat_send_player(pname,"Insufficient privileges to use this!")returnendlocal tcbpos = minetest.string_to_pos(tcbpts)local tcb = ildb.get_tcb(tcbpos)if not tcb then return true endfor connid=1,2doif tcb[connid].signal then
minetest.chat_send_player(pname,"Can't remove TCB: Both sides must have no signal assigned!")return falseendendendreturn trueend,
after_dig_node =function(pos, oldnode, oldmetadata, player)if not oldmetadata or not oldmetadata.fields then return endlocal tcbpts = oldmetadata.fields.tcb_pos
if tcbpts and tcbpts ~=""thenlocal tcbpos = minetest.string_to_pos(tcbpts)
ildb.remove_tcb_at(tcbpos)endend,})-- Crafting-- set some fallbackslocal tcb_core ="default:mese_crystal"local tcb_secondary ="default:mese_crystal_fragment"--alternative recipe items--coreif minetest.get_modpath("basic_materials")then
tcb_core ="basic_materials:ic"elseif minetest.get_modpath("technic")then
tcb_core ="technic:control_logic_unit"end--print("TCB Core: "..tcb_core)--secondaryif minetest.get_modpath("mesecons")then
tcb_secondary ='mesecons:wire_00000000_off'end--print("TCB Secondary: "..tcb_secondary)
minetest.register_craft({
output ='advtrains_interlocking:tcb_node 4',
recipe = {{tcb_secondary,tcb_core,tcb_secondary},{'advtrains:dtrack_placer','','advtrains:dtrack_placer'}},--actually use track in the tcb recipe
replacements = {{"advtrains:dtrack_placer","advtrains:dtrack_placer"},{"advtrains:dtrack_placer","advtrains:dtrack_placer"},}})--nil the temp crafting variables
tcb_core=nil
tcb_secondary =nil
minetest.register_on_punchnode(function(pos, node, player, pointed_thing)local pname = player:get_player_name()if not minetest.check_player_privs(pname,"interlocking")thenreturnend-- TCB assignmentlocal tcbnpos = players_assign_tcb[pname]if tcbnpos thenif vector.distance(pos, tcbnpos)<=20thenlocal node_ok, conns, rhe = advtrains.get_rail_info_at(pos, advtrains.all_tracktypes)if node_ok and#conns ==2then-- if there is already a tcb here, reassign itif 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)endlocal meta = minetest.get_meta(tcbnpos)
meta:set_string("tcb_pos", minetest.pos_to_string(pos))
meta:set_string("infotext","TCB assigned to "..minetest.pos_to_string(pos))
minetest.chat_send_player(pname,"Configuring TCB: Successfully configured TCB")else
minetest.chat_send_player(pname,"Configuring TCB: This is not a normal two-connection rail! Aborted.")endelse
minetest.chat_send_player(pname,"Configuring TCB: Node is too far away. Aborted.")end
players_assign_tcb[pname] =nilend-- Signal assignmentlocal sigd = players_assign_signal[pname]if sigd thenif vector.distance(pos, sigd.p)<=50thenlocal is_signal = minetest.get_item_group(node.name,"advtrains_signal") >=2if is_signal thenlocal ndef = minetest.registered_nodes[node.name]if ndef and ndef.advtrains and ndef.advtrains.set_aspect thenlocal tcbs = ildb.get_tcbs(sigd)if tcbs then
tcbs.signal = pos
if not tcbs.signal_name then
tcbs.signal_name ="Signal at "..minetest.pos_to_string(sigd.p)endif 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.")endelse
minetest.chat_send_player(pname,"Configuring TCB: Cannot use static signals for routesetting. Aborted.")endelse
minetest.chat_send_player(pname,"Configuring TCB: Not a compatible signal. Aborted.")endelse
minetest.chat_send_player(pname,"Configuring TCB: Node is too far away. Aborted.")end
players_assign_signal[pname] =nilendend)-- TCB Formlocal functionmktcbformspec(tcbs, btnpref, offset, pname)local form =""local ts
if tcbs.ts_id then
ts = ildb.get_ts(tcbs.ts_id)endif ts then
form = form.."label[0.5,"..offset..";Side "..btnpref..": "..minetest.formspec_escape(ts.name or tcbs.ts_id).."]"
form = form.."button[0.5,"..(offset+0.5)..";5,1;"..btnpref.."_gotots;Show track section]"else
tcbs.ts_id =nil
form = form.."label[0.5,"..offset..";Side "..btnpref..": ".."End of interlocking]"
form = form.."button[0.5,"..(offset+0.5)..";5,1;"..btnpref.."_makeil;Create Interlocked Track Section]"endif tcbs.signal then
form = form.."button[0.5,"..(offset+2.5)..";5,1;"..btnpref.."_sigdia;Signalling]"else
form = form.."button[0.5,"..(offset+2.5)..";5,1;"..btnpref.."_asnsig;Assign a signal]"endreturn form
endfunction advtrains.interlocking.show_tcb_form(pos, pname)if not minetest.check_player_privs(pname,"interlocking")then
minetest.chat_send_player(pname,"Insufficient privileges to use this!")returnendlocal tcb = ildb.get_tcb(pos)if not tcb then return endlocal form ="size[6,9] label[0.5,0.5;Track Circuit Break Configuration]"
form = form ..mktcbformspec(tcb[1],"A",1, pname)
form = form ..mktcbformspec(tcb[2],"B",5, pname)
minetest.show_formspec(pname,"at_il_tcbconfig_"..minetest.pos_to_string(pos), form)
advtrains.interlocking.show_tcb_marker(pos)end--helper: length of nil table is 0local functionnlen(t)if not t then return0endreturn#t
end
minetest.register_on_player_receive_fields(function(player, formname, fields)local pname = player:get_player_name()if not minetest.check_player_privs(pname,"interlocking")thenreturnendlocal pts =string.match(formname,"^at_il_tcbconfig_(.+)$")local pos
if pts then
pos = minetest.string_to_pos(pts)endif pos and not fields.quit thenlocal tcb = ildb.get_tcb(pos)if not tcb then return endlocal f_gotots = {fields.A_gotots, fields.B_gotots}local f_makeil = {fields.A_makeil, fields.B_makeil}local f_asnsig = {fields.A_asnsig, fields.B_asnsig}local f_sigdia = {fields.A_sigdia, fields.B_sigdia}for connid=1,2dolocal tcbs = tcb[connid]if tcbs.ts_id thenif f_gotots[connid]then
advtrains.interlocking.show_ts_form(tcbs.ts_id, pname)returnendelseif f_makeil[connid]thenif not tcbs.ts_id then
ildb.create_ts_from_tcbs({p=pos, s=connid})endendendif f_asnsig[connid]and not tcbs.signal then
minetest.chat_send_player(pname,"Configuring TCB: Please punch the signal to assign.")
players_assign_signal[pname] = {p=pos, s=connid}
minetest.close_formspec(pname, formname)returnendif f_sigdia[connid]and tcbs.signal then
advtrains.interlocking.show_signalling_form({p=pos, s=connid}, pname)returnendend
advtrains.interlocking.show_tcb_form(pos, pname)endend)-- TS Formspecfunction advtrains.interlocking.show_ts_form(ts_id, pname)if not minetest.check_player_privs(pname,"interlocking")then
minetest.chat_send_player(pname,"Insufficient privileges to use this!")returnendlocal ts = ildb.get_ts(ts_id)if not ts_id then return endlocal form ="size[10,10]label[0.5,0.5;Track Section Detail - "..ts_id.."]"
form = form.."field[0.8,2;5.2,1;name;Section name;"..minetest.formspec_escape(ts.name or"").."]"
form = form.."button[5.5,1.7;1,1;setname;Set]"local hint
local strtab = {}for idx, sigd inipairs(ts.tc_breaks)do
strtab[#strtab+1] = minetest.formspec_escape(sigd_to_string(sigd))
advtrains.interlocking.show_tcb_marker(sigd.p)end
form = form.."textlist[0.5,3;5,3;tcblist;"..table.concat(strtab,",").."]"if ildb.may_modify_ts(ts)then
form = form.."button[5.5,4;4,1;remove;Remove Section]"
form = form.."tooltip[dissolve;This will remove the track section and set all its end points to End Of Interlocking]"else
hint=3endif ts.route then
form = form.."label[0.5,6.1;Route is set: "..ts.route.rsn.."]"elseif ts.route_post then
form = form.."label[0.5,6.1;Section holds "..#(ts.route_post.lcks or{}).." route locks.]"end-- occupying trainsif ts.trains and#ts.trains>0then
form = form.."label[0.5,7.1;Trains on this section:]"
form = form.."textlist[0.5,7.7;3,2;trnlist;"..table.concat(ts.trains,",").."]"else
form = form.."label[0.5,7.1;No trains on this section.]"end
form = form.."button[5.5,7;4,1;reset;Reset section state]"if hint ==3then
form = form.."label[0.5,0.75;You cannot modify track sections when a route is set or a train is on the section.]"--form = form.."label[0.5,1;Trying to unlink a TCB directly connected to this track will not work.]"end
minetest.show_formspec(pname,"at_il_tsconfig_"..ts_id, form)end
minetest.register_on_player_receive_fields(function(player, formname, fields)local pname = player:get_player_name()if not minetest.check_player_privs(pname,"interlocking")thenreturnend-- independent of the formspec, clear this whenever some formspec event happenslocal ts_id =string.match(formname,"^at_il_tsconfig_(.+)$")if ts_id and not fields.quit thenlocal ts = ildb.get_ts(ts_id)if not ts then return endif ildb.may_modify_ts(ts)thenif fields.removethen
ildb.remove_ts(ts_id)
minetest.close_formspec(pname, formname)returnendendif fields.setname then
ts.name = fields.name
if ts.name ==""then
ts.name =nilendendif fields.reset then-- User requested resetting the section-- Show him what this means...local form ="size[7,5]label[0.5,0.5;Reset track section]"
form = form.."label[0.5,1;This will clear the list of trains\nand the routesetting status of this section.\nAre you sure?]"
form = form.."button_exit[0.5,2.5; 5,1;reset;Yes]"
form = form.."button_exit[0.5,3.5; 5,1;cancel;Cancel]"
minetest.show_formspec(pname,"at_il_tsreset_"..ts_id, form)returnend
advtrains.interlocking.show_ts_form(ts_id, pname, sel_tcb)returnend
ts_id =string.match(formname,"^at_il_tsreset_(.+)$")if ts_id and fields.reset thenlocal ts = ildb.get_ts(ts_id)if not ts then return end
ts.trains = {}if ts.route_post then
advtrains.interlocking.route.free_route_locks(ts_id, ts.route_post.locks)end
ts.route_post =nil
ts.route =nilfor _, sigd inipairs(ts.tc_breaks)dolocal tcbs = ildb.get_tcbs(sigd)
advtrains.interlocking.update_signal_aspect(tcbs)end
minetest.chat_send_player(pname,"Reset track section "..ts_id.."!")endend)-- TCB marker entities-- table with objectRefslocal markerent = {}
minetest.register_entity("advtrains_interlocking:tcbmarker", {
visual ="mesh",
mesh ="trackplane.b3d",
textures = {"at_il_tcb_marker.png"},
collisionbox = {-1,-0.5,-1,1,-0.4,1},
visual_size = {x=10, y=10},
on_punch =function(self)
self.object:remove()end,
on_rightclick =function(self, player)if self.tcbpos and player then
advtrains.interlocking.show_tcb_form(self.tcbpos, player:get_player_name())endend,
get_staticdata =function()return"STATIC"end,
on_activate =function(self, sdata)if sdata=="STATIC"then self.object:remove()end end,
static_save =false,})function advtrains.interlocking.show_tcb_marker(pos)--atdebug("showing tcb marker",pos)local tcb = ildb.get_tcb(pos)if not tcb then return endlocal node_ok, conns, rhe = advtrains.get_rail_info_at(pos, advtrains.all_tracktypes)if not node_ok then return endlocal yaw = advtrains.conn_angle_median(conns[2].c, conns[1].c)local itex = {}for connid=1,2dolocal tcbs = tcb[connid]local ts
if tcbs.ts_id then
ts = ildb.get_ts(tcbs.ts_id)endif ts then
itex[connid] = ts.name or tcbs.ts_id or"???"else
itex[connid] ="--EOI--"endendlocal pts = advtrains.roundfloorpts(pos)if markerent[pts]then
markerent[pts]:remove()endlocal obj = minetest.add_entity(pos,"advtrains_interlocking:tcbmarker")if not obj then return end
obj:set_yaw(yaw)
obj:set_properties({
infotext ="A = "..itex[1].."\nB = "..itex[2]})local le = obj:get_luaentity()if le then le.tcbpos = pos end
markerent[pts] = obj
endfunction advtrains.interlocking.remove_tcb_marker(pos)local pts = advtrains.roundfloorpts(pos)if markerent[pts]then
markerent[pts]:remove()end
markerent[pts] =nilend-- Spawns particles to highlight the clicked track section-- TODO: Adapt behavior to not dumb-walk anymorefunction advtrains.interlocking.highlight_track_section(pos)local ti = advtrains.get_track_iterator(pos,nil,100,true)local pos, connid, bconnid, tcb
while ti:has_next_branch()do
pos, connid = ti:next_branch()--atdebug("highlight_track_section: BRANCH: ",pos, connid)
bconnid =nilrepeat-- spawn particles
minetest.add_particle({
pos = pos,
velocity = {x=0, y=0, z=0},
acceleration = {x=0, y=0, z=0},
expirationtime =10,
size =7,
vertical =true,
texture ="at_il_ts_highlight_particle.png",
glow =6,})-- abort if TCB is found
tcb = ildb.get_tcb(pos)if tcb then
advtrains.interlocking.show_tcb_marker(pos)breakend
pos, connid, bconnid = ti:next_track()--atdebug("highlight_track_section: TRACK: ",pos, connid, bconnid)until not pos
endend-- Signalling formspec - set routes a.s.o-- textlist selection temporary storagelocal sig_pselidx = {}-- Players having a signalling form openlocal p_open_sig_form = {}function advtrains.interlocking.show_signalling_form(sigd, pname, sel_rte, called_from_form_update)if not minetest.check_player_privs(pname,"train_operator")then
minetest.chat_send_player(pname,"Insufficient privileges to use this!")returnendlocal hasprivs = minetest.check_player_privs(pname,"interlocking")local tcbs = ildb.get_tcbs(sigd)if not tcbs.signal then return endif not tcbs.signal_name then tcbs.signal_name ="Signal at "..minetest.pos_to_string(sigd.p)endif not tcbs.routes then tcbs.routes = {}endlocal form ="size[7,10]label[0.5,0.5;Signal at "..minetest.pos_to_string(sigd.p).."]"
form = form.."field[0.8,1.5;5.2,1;name;Signal name;"..minetest.formspec_escape(tcbs.signal_name).."]"
form = form.."button[5.5,1.2;1,1;setname;Set]"if tcbs.routeset thenlocal rte = tcbs.routes[tcbs.routeset]if not rte thenatwarn("Unknown route set from signal!")
tcbs.routeset =nilreturnend
form = form.."label[0.5,2.5;A route is requested from this signal:]"
form = form.."label[0.5,3.0;"..minetest.formspec_escape(rte.name).."]"if tcbs.route_committed then
form = form.."label[0.5,3.5;Route has been set.]"else
form = form.."label[0.5,3.5;Waiting for route to be set...]"if tcbs.route_rsn then
form = form.."label[0.5,4;"..minetest.formspec_escape(tcbs.route_rsn).."]"endendif not tcbs.route_auto then
form = form.."button[0.5,7; 5,1;auto;Enable Automatic Working]"else
form = form.."label[0.5,7 ;Automatic Working is active.]"
form = form.."label[0.5,7.3;Route is re-set when a train passed.]"
form = form.."button[0.5,7.7; 5,1;noauto;Disable Automatic Working]"end
form = form.."button[0.5,6; 5,1;cancelroute;Cancel Route]"elseif not tcbs.route_origin thenlocal strtab = {}for idx, route inipairs(tcbs.routes)dolocal clr =""if route.ars then
clr ="#FF5555"if route.ars.default then
clr ="#55FF55"endend
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.."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]"endelseif 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.]"endendif hasprivs then
form = form.."button[0.5,8;2.5,1;newroute;New Route]"
form = form.."button[ 3,8;2.5,1;unassign;Unassign Signal]"
form = form.."button[ 3,9;2.5,1;influp;Influence Point]"endif tcbs.ars_disabled then
form = form.."button[0.5,9;2.5,1;arsenable;Enable ARS]"else
form = form.."button[0.5,9;2.5,1;arsdisable;Disable ARS]"endelseifsigd_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.]"
ilrs.cancel_route_from(sigd)else
form = form.."label[0.5,2.5;Route is set over this signal by:\n"..sigd_to_string(tcbs.route_origin).."]"
form = form.."label[0.5,4;Wait for this route to be cancelled in order to do anything here.]"endend
sig_pselidx[pname] = sel_rte
minetest.show_formspec(pname,"at_il_signalling_"..minetest.pos_to_string(sigd.p).."_"..sigd.s, form)
p_open_sig_form[pname] = sigd
-- always a good idea to update the signal aspectif not called_from_form_update then-- FIX prevent a callback loop
advtrains.interlocking.update_signal_aspect(tcbs)endendfunction advtrains.interlocking.update_player_forms(sigd)for pname, tsigd inpairs(p_open_sig_form)doif advtrains.interlocking.sigd_equal(sigd, tsigd)then
advtrains.interlocking.show_signalling_form(sigd, pname,nil)endendend
minetest.register_on_player_receive_fields(function(player, formname, fields)local pname = player:get_player_name()if not minetest.check_player_privs(pname,"train_operator")thenreturnendlocal hasprivs = minetest.check_player_privs(pname,"interlocking")-- independent of the formspec, clear this whenever some formspec event happenslocal tpsi = sig_pselidx[pname]
sig_pselidx[pname] =nil
p_open_sig_form[pname] =nillocal pts, connids =string.match(formname,"^at_il_signalling_([^_]+)_(%d)$")local pos, connid
if pts then
pos = minetest.string_to_pos(pts)
connid =tonumber(connids)if not connid or connid<1or connid>2then return endendif pos and connid thenlocal sigd = {p=pos, s=connid}local tcbs = ildb.get_tcbs(sigd)if not tcbs then return endif fields.quit then-- form quit: disable temporary ARS ignore
tcbs.ars_ignore_next =nilreturnendlocal sel_rte
if fields.rtelist thenlocal tev = minetest.explode_textlist_event(fields.rtelist)
sel_rte = tev.index
elseif tpsi then
sel_rte = tpsi
endif fields.setname and fields.name and hasprivs then
tcbs.signal_name = fields.name
endif tcbs.routeset and fields.cancelroute thenif tcbs.routes[tcbs.routeset]and tcbs.routes[tcbs.routeset].ars then
tcbs.ars_ignore_next =trueend-- if route committed, cancel route ts info
ilrs.update_route(sigd, tcbs,nil,true)endif not tcbs.routeset thenif fields.newroute and hasprivs then
advtrains.interlocking.init_route_prog(pname, sigd)
minetest.close_formspec(pname, formname)
tcbs.ars_ignore_next =nilreturnendif sel_rte and tcbs.routes[sel_rte]thenif fields.setroute then
ilrs.update_route(sigd, tcbs, sel_rte)endif fields.dsproute thenlocal t = os.clock()
advtrains.interlocking.visualize_route(sigd, tcbs.routes[sel_rte],"disp_"..t)
minetest.after(10,function() advtrains.interlocking.clear_visu_context("disp_"..t)end)endif 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.."]")returnendendendif fields.unassign and hasprivs then-- unassigning the signal from the tcbs-- only when no route is set.-- Routes and name remain saved, in case the player wants to reassign a new signalif not tcbs.routeset thenlocal signal_pos = tcbs.signal
ildb.set_sigd_for_signal(signal_pos,nil)
tcbs.signal =nil
tcbs.aspect =nil
minetest.close_formspec(pname, formname)
minetest.chat_send_player(pname,"Signal has been unassigned. Name and routes are kept for reuse.")returnelse
minetest.chat_send_player(pname,"Please cancel route first!")endendif fields.influp and hasprivs then
advtrains.interlocking.show_ip_form(tcbs.signal, pname)returnendif tcbs.ars_disabled and fields.arsenable then
tcbs.ars_disabled =nilendif not tcbs.ars_disabled and fields.arsdisable then
tcbs.ars_disabled =trueendif fields.auto then
tcbs.route_auto =trueendif fields.noauto then
tcbs.route_auto =falseend
advtrains.interlocking.show_signalling_form(sigd, pname, sel_rte,true)returnendif not hasprivs then return end-- rename routelocal 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<1or connid>2then return endendif pos and connid and rind and fields.name thenlocal 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)endendend)