From 950d6f640cae76d28253fadb7974a064017b104c Mon Sep 17 00:00:00 2001 From: orwell96 Date: Mon, 4 Sep 2023 19:34:47 +0200 Subject: Begin major rework of track registration system --- advtrains/trackplacer.lua | 592 ++++++++++++++++++---------------------------- 1 file changed, 231 insertions(+), 361 deletions(-) (limited to 'advtrains/trackplacer.lua') diff --git a/advtrains/trackplacer.lua b/advtrains/trackplacer.lua index fe76290..9d63199 100644 --- a/advtrains/trackplacer.lua +++ b/advtrains/trackplacer.lua @@ -3,311 +3,204 @@ --all new trackplacer code local tp={ - tracks={} + groups={} } -function tp.register_tracktype(nnprefix, n_suffix) - if tp.tracks[nnprefix] then return end--due to the separate registration of slopes and flats for the same nnpref, definition would be overridden here. just don't. - tp.tracks[nnprefix]={ - default=n_suffix, - single_conn={}, - single_conn_1={}, - single_conn_2={}, - double_conn={}, - double_conn_1={}, - double_conn_2={}, - --keys:conn1_conn2 (example:1_4) - --values:{name=x, param2=x} - twcycle={}, - twrotate={},--indexed by suffix, list, tells order of rotations - modify={}, - } -end -function tp.add_double_conn(nnprefix, suffix, rotation, conns) - local nodename=nnprefix.."_"..suffix..rotation - for i=0,3 do - tp.tracks[nnprefix].double_conn[((conns.conn1+4*i)%16).."_"..((conns.conn2+4*i)%16)]={name=nodename, param2=i} - tp.tracks[nnprefix].double_conn[((conns.conn2+4*i)%16).."_"..((conns.conn1+4*i)%16)]={name=nodename, param2=i} - tp.tracks[nnprefix].double_conn_1[((conns.conn1+4*i)%16).."_"..((conns.conn2+4*i)%16)]={name=nodename, param2=i} - tp.tracks[nnprefix].double_conn_2[((conns.conn2+4*i)%16).."_"..((conns.conn1+4*i)%16)]={name=nodename, param2=i} - end - tp.tracks[nnprefix].modify[nodename]=true -end -function tp.add_single_conn(nnprefix, suffix, rotation, conns) - local nodename=nnprefix.."_"..suffix..rotation - for i=0,3 do - tp.tracks[nnprefix].single_conn[((conns.conn1+4*i)%16)]={name=nodename, param2=i} - tp.tracks[nnprefix].single_conn[((conns.conn2+4*i)%16)]={name=nodename, param2=i} - tp.tracks[nnprefix].single_conn_1[((conns.conn1+4*i)%16)]={name=nodename, param2=i} - tp.tracks[nnprefix].single_conn_2[((conns.conn2+4*i)%16)]={name=nodename, param2=i} - end - tp.tracks[nnprefix].modify[nodename]=true -end +--[[ New in version 2.5: +The track placer no longer uses hacky nodename pattern matching. +The base criterion for rotating or matching tracks is the common "ndef.advtrains.track_place_group" property. +Only rails where this field is set are considered for replacement. Other rails can still be considered for connection. +Replacement ("bending") of rails can only happen within their respective track place group. Only two-conn rails are allowed in the trackplacer. -function tp.add_worked(nnprefix, suffix, rotation, cycle_follows) - tp.tracks[nnprefix].twcycle[suffix]=cycle_follows - if not tp.tracks[nnprefix].twrotate[suffix] then tp.tracks[nnprefix].twrotate[suffix]={} end - table.insert(tp.tracks[nnprefix].twrotate[suffix], rotation) -end +The track registration functions register the candidates for any given track_place_group in two separate collections: +- double: tracks that can be used to connect both ends of the rail +- single: tracks that will be used to connect conn1 when only a single end is to be connected +When track placing is requested, the calling code just supplies the track_place_group to be placed. ---[[ - rewrite algorithm. - selection criteria: these will never be changed or even selected: - - tracks being already connected on both sides - - tracks that are already connected on one side but are not bendable to the desired position - the following situations can occur: - 1. there are two more than two rails around - 1.1 there is one or more subset(s) that can be directly connected - -> choose the first possibility - 2.2 not - -> choose the first one and orient straight - 2. there's exactly 1 rail around - -> choose and orient straight - 3. there's no rail around - -> set straight -]] +]]-- -local function istrackandbc(pos_p, conn) - local tpos = pos_p - local cnode=minetest.get_node(advtrains.dirCoordSet(tpos, conn.c)) - if advtrains.is_track_and_drives_on(cnode.name, advtrains.all_tracktypes) then - local cconns=advtrains.get_track_connections(cnode.name, cnode.param2) - return advtrains.conn_matches_to(conn, cconns) - end - --try the same 1 node below - tpos = {x=tpos.x, y=tpos.y-1, z=tpos.z} - cnode=minetest.get_node(advtrains.dirCoordSet(tpos, conn.c)) - if advtrains.is_track_and_drives_on(cnode.name, advtrains.all_tracktypes) then - local cconns=advtrains.get_track_connections(cnode.name, cnode.param2) - return advtrains.conn_matches_to(conn, cconns) - end - return false +local function rotate(conn, rot) + return (conn + rot) % 16 end -function tp.find_already_connected(pos) - local dnode=minetest.get_node(pos) - local dconns=advtrains.get_track_connections(dnode.name, dnode.param2) - local found_conn - for connid, conn in ipairs(dconns) do - if istrackandbc(pos, conn) then - if found_conn then --we found one in previous iteration - return true, true --signal that it's connected - else - found_conn = conn.c +-- Register a track node as candidate +-- tpg: the track place group to register the candidates for +-- name, ndef: the node name and node definition table to register +-- as_single: whether the rail should be considered as candidate for one-endpoint connection +-- Typically only set for the straight rail variants +-- as_double: whether the rail should be considered as candidate for two-endpoint connection +-- Typically set for straights and curves +function tp.register_candidate(tpg, name, ndef, as_single, as_double) + --get or create TP group + if not tp.groups[tpg] then + tp.groups[tpg] = {double = {}, single1 = {}, single2 = {}, default = {name = name, param2 = 0} } + -- note: this causes the first candidate to ever be registered to be the default (which is typically what you want) + end + local g = tp.groups[tpg] + + -- get conns + assert(#ndef.at_conns == 2) + local c1, c2 = ndef.at_conns[1].c, ndef.at_conns[2].c + local is_symmetrical = (rotate(c1, 8) == c2) + + -- store all possible rotations (param2 values) + for i=0,3 do + if as_double then + g.double[rotate(c1,i*4).."_"..rotate(c2,i*4)] = {name=name, param2=i} + if not is_symmmetrical then + g.double[rotate(c2,i*4).."_"..rotate(c1,i*4)] = {name=name, param2=i} + -- if the track is unsymmetric (e.g. a curve), we may require the "wrong" orientation to fill a gap. end end + if as_single then + g.single1[rotate(c1,i*4)] = {name=name, param2=i} + g.single2[rotate(c2,i*4)] = {name=name, param2=i} + end end - return found_conn end -function tp.rail_and_can_be_bent(originpos, conn) - local pos=advtrains.dirCoordSet(originpos, conn) - local newdir=(conn+8)%16 - local node=minetest.get_node(pos) - if not advtrains.is_track_and_drives_on(node.name, advtrains.all_tracktypes) then + +local function check_or_bend_rail(origin, dir, pname, commit) + local pos = advtrains.pos_add_dir(origin, dir) + local back_dir = advtrains.oppd(dir); + + local node_ok, conns = advtrains.get_rail_info_at(pos) + if not node_ok then + -- try the node one level below + pos.y = pos.y - 1 + node_ok, conns = advtrains.get_rail_info_at(pos) + end + if not node_ok then return false end - local ndef=minetest.registered_nodes[node.name] - local nnpref = ndef and ndef.at_nnpref - if not nnpref then return false end - local tr=tp.tracks[nnpref] - if not tr then return false end - if not tr.modify[node.name] then - --we actually can use this rail, but only if it already points to the desired direction. - if advtrains.is_track_and_drives_on(node.name, advtrains.all_tracktypes) then - local cconns=advtrains.get_track_connections(node.name, node.param2) - return advtrains.conn_matches_to(conn, cconns) + -- if one conn of the node here already points towards us, nothing to do + for connid, conn in ipairs(conns) do + if back_dir == conn.c then + return true end end - -- If the rail is not allowed to be modified, also only use if already in desired direction + -- can we bend the node here? + local node = advtrains.ndb.get_node(pos) + local ndef = minetest.registered_nodes[node.name] + if not ndef or not ndef.advtrains or not ndef.advtrains.track_place_group then + return false + end + -- now the track must be two-conn, else it wouldn't be allowed to have track_place_group set. + assert(#conns == 2) + -- Is player and game allowed to do this? if not advtrains.can_dig_or_modify_track(pos) then - local cconns=advtrains.get_track_connections(node.name, node.param2) - return advtrains.conn_matches_to(conn, cconns) + return false end - --rail at other end? - local adj1, adj2=tp.find_already_connected(pos) - if adj1 and adj2 then - return false--dont destroy existing track - elseif adj1 and not adj2 then - if tr.double_conn[adj1.."_"..newdir] then - return true--if exists, connect new rail and old end - end + if not advtrains.check_track_protection(pos, pname) then return false - else - if tr.single_conn[newdir] then--just rotate old rail to right orientation - return true + end + -- we confirmed that track can be modified. Does there exist a suitable connection candidate? + -- check if there are any unbound ends + local bound_connids = {} + for connid, conn in ipairs(conns) do + local adj_pos, adj_connid = advtrains.get_adjacent_rail(pos, conns, connid) + if adj_pos then + bound_connids[#bound_connids+1] = connid end - return false end -end -function tp.bend_rail(originpos, conn) - local pos=advtrains.dirCoordSet(originpos, conn) - local newdir=advtrains.oppd(conn) - local node=minetest.get_node(pos) - local ndef=minetest.registered_nodes[node.name] - local nnpref = ndef and ndef.at_nnpref - if not nnpref then return false end - local tr=tp.tracks[nnpref] - if not tr then return false end - --is rail already connected? no need to bend. - local conns=advtrains.get_track_connections(node.name, node.param2) - if advtrains.conn_matches_to(conn, conns) then - return + -- depending on the nummber of ends, decide + if #bound_connids == 2 then + -- rail is within a fixed track, do not break up + return false end - --rail at other end? - local adj1, adj2=tp.find_already_connected(pos) - if adj1 and adj2 then - return false--dont destroy existing track - elseif adj1 and not adj2 then - if tr.double_conn[adj1.."_"..newdir] then - advtrains.ndb.swap_node(pos, tr.double_conn[adj1.."_"..newdir]) - return true--if exists, connect new rail and old end + -- obtain the group table + local g = tp.groups[ndef.advtrains.track_place_group] + if #bound_connids == 1 then + -- we can attempt double + local bound_dir = conns[bound_connids[1]].c + if g.double[back_dir.."_"..bound_dir] then + if commit then + advtrains.ndb.swap_node(pos, g.double[back_dir.."_"..bound_dir]) + end + return true end - return false else - if tr.single_conn[newdir] then--just rotate old rail to right orientation - advtrains.ndb.swap_node(pos, tr.single_conn[newdir]) + -- rail is entirely unbound, we can attempt single1 + if g.single1[back_dir] then + if commit then + advtrains.ndb.swap_node(pos, g.single1[back_dir]) + end return true end - return false end end -function tp.placetrack(pos, nnpref, placer, itemstack, pointed_thing, yaw) - --1. find all rails that are likely to be connected - local tr=tp.tracks[nnpref] - local p_rails={} - local p_railpos={} + +local function track_place_node(pos, node, ndef) + advtrains.ndb.swap_node(pos, node) + local ndef = minetest.registered_nodes[node.name] + if ndef and ndef.after_place_node then + ndef.after_place_node(pos) + end +end + + +-- Main API function to place a track. Replaces the older "placetrack" +-- This function will attempt to place a track of the specified track placing group at the specified position, connecting it +-- with neighboring rails. Neighboring rails can themselves be replaced ("bent") within their own track place group, +-- if the player is permitted to do this. +-- Order of preference is: +-- Connect two track ends if possible +-- Connect one track end if any rail is near +-- Place the default track if no tracks are near +-- The function returns true on success. +function tp.place_track(pos, tpg, pname, yaw) + -- 1. collect neighboring tracks and whether they can be connected + local cand = {} for i=0,15 do - if tp.rail_and_can_be_bent(pos, i, nnpref) then - p_rails[#p_rails+1]=i - p_railpos[i] = pos - else - local upos = {x=pos.x, y=pos.y-1, z=pos.z} - if tp.rail_and_can_be_bent(upos, i, nnpref) then - p_rails[#p_rails+1]=i - p_railpos[i] = upos - end + if check_or_bend_rail(pos, i, pname) then + cand[#cand+1] = i end end - - -- try double_conn - if #p_rails > 1 then - --iterate subsets - for k1, conn1 in ipairs(p_rails) do - for k2, conn2 in ipairs(p_rails) do - if k1~=k2 then - local dconn1 = tr.double_conn_1 - local dconn2 = tr.double_conn_2 - if not (advtrains.yawToDirection(yaw, conn1, conn2) == conn1) then - dconn1 = tr.double_conn_2 - dconn2 = tr.double_conn_1 - end - -- Checks are made this way round so that dconn1 has priority (this will make arrows of atc rails - -- point in the right direction) - local using - if (dconn2[conn1.."_"..conn2]) then - using = dconn2[conn1.."_"..conn2] - end - if (dconn1[conn1.."_"..conn2]) then - using = dconn1[conn1.."_"..conn2] - end - if using then - -- has found a fitting rail in either direction - -- if not, continue loop - tp.bend_rail(p_railpos[conn1], conn1, nnpref) - tp.bend_rail(p_railpos[conn2], conn2, nnpref) - advtrains.ndb.swap_node(pos, using) - local nname=using.name - if minetest.registered_nodes[nname] and minetest.registered_nodes[nname].after_place_node then - minetest.registered_nodes[nname].after_place_node(pos, placer, itemstack, pointed_thing) - end - return + -- obtain the group table + local g = tp.groups[tpg] + -- 2. try all possible two-endpoint connections + for k1, conn1 in ipairs(cand) do + for k2, conn2 in ipairs(cand) do + if k1~=k2 then + -- order of conn1/conn2: prefer conn2 being in the direction of the player facing. + -- the combination the other way round will be run through in a later loop iteration + if advtrains.yawToDirection(yaw, conn1, conn2) == conn2 then + -- does there exist a suitable double-connection rail? + local node = g.double[conn1.."_"..conn2] + if node then + check_or_bend_rail(pos, conn1, pname, true) + check_or_bend_rail(pos, conn2, pname, true) + track_place_node(pos, node) -- calls after_place_node implicitly + return true end end end end end - -- try single_conn - if #p_rails > 0 then - for ix, p_rail in ipairs(p_rails) do - local sconn1 = tr.single_conn_1 - local sconn2 = tr.single_conn_2 - if not (advtrains.yawToDirection(yaw, p_rail, (p_rail+8)%16) == p_rail) then - sconn1 = tr.single_conn_2 - sconn2 = tr.single_conn_1 - end - if sconn1[p_rail] then - local using = sconn1[p_rail] - tp.bend_rail(p_railpos[p_rail], p_rail, nnpref) - advtrains.ndb.swap_node(pos, using) - local nname=using.name - if minetest.registered_nodes[nname] and minetest.registered_nodes[nname].after_place_node then - minetest.registered_nodes[nname].after_place_node(pos, placer, itemstack, pointed_thing) - end - return - end - if sconn2[p_rail] then - local using = sconn2[p_rail] - tp.bend_rail(p_railpos[p_rail], p_rail, nnpref) - advtrains.ndb.swap_node(pos, using) - local nname=using.name - if minetest.registered_nodes[nname] and minetest.registered_nodes[nname].after_place_node then - minetest.registered_nodes[nname].after_place_node(pos, placer, itemstack, pointed_thing) - end - return - end + -- 3. try all possible one_endpoint connections + for k1, conn1 in ipairs(cand) do + -- select single1 or single2? depending on yaw + local single + if advtrains.yawToDirection(yaw, conn1, advtrains.oppd(conn1)) == conn1 then + single = g.single1 + else + single = g.single2 + end + local node = single[conn1] + if node then + check_or_bend_rail(pos, conn1, pname, true) + track_place_node(pos, node) -- calls after_place_node implicitly + return true end end - --use default - minetest.set_node(pos, {name=nnpref.."_"..tr.default}) - if minetest.registered_nodes[nnpref.."_"..tr.default] and minetest.registered_nodes[nnpref.."_"..tr.default].after_place_node then - minetest.registered_nodes[nnpref.."_"..tr.default].after_place_node(pos, placer, itemstack, pointed_thing) - end + -- 4. if nothing worked, set the default + local node = g.default + track_place_node(pos, node) -- calls after_place_node implicitly + return true end - -function tp.register_track_placer(nnprefix, imgprefix, dispname, def) - minetest.register_craftitem(":"..nnprefix.."_placer",{ - description = dispname, - inventory_image = imgprefix.."_placer.png", - wield_image = imgprefix.."_placer.png", - groups={advtrains_trackplacer=1, digtron_on_place=1}, - liquids_pointable = def.liquids_pointable, - on_place = function(itemstack, placer, pointed_thing) - local name = placer:get_player_name() - if not name then - return itemstack, false - end - if pointed_thing.type=="node" then - local pos=pointed_thing.above - local upos=vector.subtract(pointed_thing.above, {x=0, y=1, z=0}) - if not advtrains.check_track_protection(pos, name) then - return itemstack, false - end - if minetest.registered_nodes[minetest.get_node(pos).name] and minetest.registered_nodes[minetest.get_node(pos).name].buildable_to then - local s - if def.suitable_substrate then - s = def.suitable_substrate(upos) - else - s = minetest.registered_nodes[minetest.get_node(upos).name] and minetest.registered_nodes[minetest.get_node(upos).name].walkable - end - if s then --- minetest.chat_send_all(nnprefix) - local yaw = placer:get_look_horizontal() - tp.placetrack(pos, nnprefix, placer, itemstack, pointed_thing, yaw) - if not advtrains.is_creative(name) then - itemstack:take_item() - end - end - end - end - return itemstack, true - end, - }) -end - - +-- TRACK WORKER -- minetest.register_craftitem("advtrains:trackworker",{ description = attrans("Track Worker Tool\n\nLeft-click: change rail type (straight/curve/switch)\nRight-click: rotate rail/bumper/signal/etc."), @@ -316,116 +209,93 @@ minetest.register_craftitem("advtrains:trackworker",{ wield_image = "advtrains_trackworker.png", stack_max = 1, on_place = function(itemstack, placer, pointed_thing) - local name = placer:get_player_name() - if not name then + local name = placer:get_player_name() + if not name then + return + end + local has_aux1_down = placer:get_player_control().aux1 + if pointed_thing.type=="node" then + local pos=pointed_thing.under + if not advtrains.check_track_protection(pos, name) then return end - local has_aux1_down = placer:get_player_control().aux1 - if pointed_thing.type=="node" then - local pos=pointed_thing.under - if not advtrains.check_track_protection(pos, name) then - return - end - local node=minetest.get_node(pos) + local node=minetest.get_node(pos) - --if not advtrains.is_track_and_drives_on(minetest.get_node(pos).name, advtrains.all_tracktypes) then return end - - local nnprefix, suffix, rotation=string.match(node.name, "^(.+)_([^_]+)(_[^_]+)$") - --atdebug(node.name.."\npattern recognizes:"..nnprefix.." / "..suffix.." / "..rotation) - --atdebug("nntab: ",tp.tracks[nnprefix]) - if not tp.tracks[nnprefix] or not tp.tracks[nnprefix].twrotate[suffix] then - nnprefix, suffix=string.match(node.name, "^(.+)_([^_]+)$") - rotation = "" - if not tp.tracks[nnprefix] or not tp.tracks[nnprefix].twrotate[suffix] then - minetest.chat_send_player(placer:get_player_name(), attrans("This node can't be rotated using the trackworker!")) - return - end - end - - -- check if the node is modify-protected - if advtrains.is_track_and_drives_on(minetest.get_node(pos).name, advtrains.all_tracktypes) then - -- is a track, we can query - local can_modify, reason = advtrains.can_dig_or_modify_track(pos) - if not can_modify then - local str = attrans("This track can not be rotated!") - if reason then - str = str .. " " .. reason - end - minetest.chat_send_player(placer:get_player_name(), str) - return + -- New since 2.5: only the fields in the node definition are considered, no more hacky pattern matching on the nodename + + local ndef = minetest.registered_nodes[node.name] + + if not ndef.advtrains or not ndef.advtrains.trackworker_next_rot then + minetest.chat_send_player(placer:get_player_name(), attrans("This node can't be rotated using the trackworker!")) + return + end + + -- check if the node is modify-protected + if advtrains.is_track(node.name) then + -- is a track, we can query + local can_modify, reason = advtrains.can_dig_or_modify_track(pos) + if not can_modify then + local str = attrans("This track can not be rotated!") + if reason then + str = str .. " " .. reason end - end - - if has_aux1_down then - --feature: flip the node by 180° - --i've always wanted this! - advtrains.ndb.swap_node(pos, {name=node.name, param2=(node.param2+2)%4}) + minetest.chat_send_player(placer:get_player_name(), str) return end - - local modext=tp.tracks[nnprefix].twrotate[suffix] - - if rotation==modext[#modext] then --increase param2 - advtrains.ndb.swap_node(pos, {name=nnprefix.."_"..suffix..modext[1], param2=(node.param2+1)%4}) - return - else - local modpos - for k,v in pairs(modext) do - if v==rotation then modpos=k end - end - if not modpos then - minetest.chat_send_player(placer:get_player_name(), attrans("This node can't be rotated using the trackworker!")) - return - end - advtrains.ndb.swap_node(pos, {name=nnprefix.."_"..suffix..modext[modpos+1], param2=node.param2}) - end end + + if has_aux1_down then + --feature: flip the node by 180° + --i've always wanted this! + advtrains.ndb.swap_node(pos, {name=node.name, param2=(node.param2+2)%4}) + return + end + + local new_node = {name = ndef.advtrains.trackworker_next_rot, param2 = node.param2} + if ndef.advtrains.trackworker_rot_incr_param2 then + new_node.param2 = ((node.param2 + 1) % 4) + end + advtrains.ndb.swap_node(pos, new_node) + end end, on_use=function(itemstack, user, pointed_thing) - local name = user:get_player_name() - if not name then - return + local name = user:get_player_name() + if not name then + return + end + if pointed_thing.type=="node" then + local pos=pointed_thing.under + local node=minetest.get_node(pos) + if not advtrains.check_track_protection(pos, name) then + return end - if pointed_thing.type=="node" then - local pos=pointed_thing.under - local node=minetest.get_node(pos) - if not advtrains.check_track_protection(pos, name) then - return - end - - --if not advtrains.is_track_and_drives_on(minetest.get_node(pos).name, advtrains.all_tracktypes) then return end - if advtrains.get_train_at_pos(pos) then return end - local nnprefix, suffix, rotation=string.match(node.name, "^(.+)_([^_]+)(_[^_]+)$") - --atdebug(node.name.."\npattern recognizes:"..nodeprefix.." / "..railtype.." / "..rotation) - if not tp.tracks[nnprefix] or not tp.tracks[nnprefix].twcycle[suffix] then - nnprefix, suffix=string.match(node.name, "^(.+)_([^_]+)$") - rotation = "" - if not tp.tracks[nnprefix] or not tp.tracks[nnprefix].twcycle[suffix] then - minetest.chat_send_player(user:get_player_name(), attrans("This node can't be changed using the trackworker!")) - return - end - end - - -- check if the node is modify-protected - if advtrains.is_track_and_drives_on(minetest.get_node(pos).name, advtrains.all_tracktypes) then - -- is a track, we can query - local can_modify, reason = advtrains.can_dig_or_modify_track(pos) - if not can_modify then - local str = attrans("This track can not be changed!") - if reason then - str = str .. " " .. reason - end - minetest.chat_send_player(user:get_player_name(), str) - return + + -- New since 2.5: only the fields in the node definition are considered, no more hacky pattern matching on the nodename + + local ndef = minetest.registered_nodes[node.name] + + if not ndef.advtrains or not ndef.advtrains.trackworker_next_var then + minetest.chat_send_player(placer:get_player_name(), attrans("This node can't be changed using the trackworker!")) + return + end + + -- check if the node is modify-protected + if advtrains.is_track(node.name) then + -- is a track, we can query + local can_modify, reason = advtrains.can_dig_or_modify_track(pos) + if not can_modify then + local str = attrans("This track can not be rotated!") + if reason then + str = str .. " " .. reason end + minetest.chat_send_player(placer:get_player_name(), str) + return end - - local nextsuffix=tp.tracks[nnprefix].twcycle[suffix] - advtrains.ndb.swap_node(pos, {name=nnprefix.."_"..nextsuffix..rotation, param2=node.param2}) - - else - atprint(name, dump(tp.tracks)) end + + local new_node = {name = ndef.advtrains.trackworker_next_var, param2 = node.param2} + advtrains.ndb.swap_node(pos, new_node) + end end, }) -- cgit v1.2.3