private void SetupSegmentEnd(ushort segmentId) { if (segmentId <= 0) { return; } //SegmentGeometry.Get(segmentId).Recalculate(true, true); if (!TrafficPriority.IsPrioritySegment(NodeId, segmentId)) { TrafficPriority.AddPrioritySegment(NodeId, segmentId, SegmentEnd.PriorityType.None); } /*if (!CustomTrafficLights.IsSegmentLight(nodeId, segmentId)) * CustomTrafficLights.AddSegmentLights(nodeId, segmentId);*/ }
public TimedTrafficLights(ushort nodeId, IEnumerable <ushort> nodeGroup) { this.NodeId = nodeId; NodeGroup = new List <ushort>(nodeGroup); masterNodeId = NodeGroup[0]; // setup priority segments & live traffic lights foreach (ushort slaveNodeId in nodeGroup) { for (int s = 0; s < 8; ++s) { ushort segmentId = Singleton <NetManager> .instance.m_nodes.m_buffer[slaveNodeId].GetSegment(s); if (segmentId <= 0) { continue; } CustomRoadAI.GetSegmentGeometry(segmentId).Recalculate(true, true); TrafficPriority.AddPrioritySegment(slaveNodeId, segmentId, SegmentEnd.PriorityType.None); CustomTrafficLights.AddLiveSegmentLights(slaveNodeId, segmentId); } } started = false; }
public override void OnClickOverlay() { if (SelectedNodeId != 0) { return; } TrafficLightSimulation sim = TrafficLightSimulation.GetNodeSimulation(HoveredNodeId); if (sim == null || !sim.IsTimedLight()) { if ((Singleton <NetManager> .instance.m_nodes.m_buffer[HoveredNodeId].m_flags & NetNode.Flags.TrafficLights) == NetNode.Flags.None) { TrafficPriority.RemovePrioritySegments(HoveredNodeId); Flags.setNodeTrafficLight(HoveredNodeId, true); } SelectedNodeId = HoveredNodeId; sim = TrafficLightSimulation.AddNodeToSimulation(SelectedNodeId); sim.SetupManualTrafficLight(); for (var s = 0; s < 8; s++) { var segment = Singleton <NetManager> .instance.m_nodes.m_buffer[SelectedNodeId].GetSegment(s); if (segment != 0 && !TrafficPriority.IsPrioritySegment(SelectedNodeId, segment)) { TrafficPriority.AddPrioritySegment(SelectedNodeId, segment, SegmentEnd.PriorityType.None); } } } else { MainTool.ShowTooltip(Translation.GetString("NODE_IS_TIMED_LIGHT"), Singleton <NetManager> .instance.m_nodes.m_buffer[HoveredNodeId].m_position); } }
private static void LoadDataState() { Log.Info("Loading State from Config"); if (_configuration == null) { Log.Warning("Configuration NULL, Couldn't load save data. Possibly a new game?"); return; } // load priority segments if (_configuration.PrioritySegments != null) { Log.Info($"Loading {_configuration.PrioritySegments.Count()} priority segments"); foreach (var segment in _configuration.PrioritySegments) { try { if (segment.Length < 3) { continue; } #if DEBUG bool debug = segment[0] == 13630; #endif if ((SegmentEnd.PriorityType)segment[2] == SegmentEnd.PriorityType.None) { #if DEBUG if (debug) { Log._Debug($"Loading priority segment: Not adding 'None' priority segment: {segment[1]} @ node {segment[0]}"); } #endif continue; } if ((Singleton <NetManager> .instance.m_nodes.m_buffer[segment[0]].m_flags & NetNode.Flags.Created) == NetNode.Flags.None) { #if DEBUG if (debug) { Log._Debug($"Loading priority segment: node {segment[0]} is invalid"); } #endif continue; } if ((Singleton <NetManager> .instance.m_segments.m_buffer[segment[1]].m_flags & NetSegment.Flags.Created) == NetSegment.Flags.None) { #if DEBUG if (debug) { Log._Debug($"Loading priority segment: segment {segment[1]} @ node {segment[0]} is invalid"); } #endif continue; } if (TrafficPriority.IsPrioritySegment((ushort)segment[0], (ushort)segment[1])) { #if DEBUG if (debug) { Log._Debug($"Loading priority segment: segment {segment[1]} @ node {segment[0]} is already a priority segment"); } #endif TrafficPriority.GetPrioritySegment((ushort)segment[0], (ushort)segment[1]).Type = (SegmentEnd.PriorityType)segment[2]; continue; } #if DEBUG Log._Debug($"Adding Priority Segment of type: {segment[2].ToString()} to segment {segment[1]} @ node {segment[0]}"); #endif TrafficPriority.AddPrioritySegment((ushort)segment[0], (ushort)segment[1], (SegmentEnd.PriorityType)segment[2]); } catch (Exception e) { // ignore, as it's probably corrupt save data. it'll be culled on next save Log.Warning("Error loading data from Priority segments: " + e.ToString()); } } } else { Log.Warning("Priority segments data structure undefined!"); } // load vehicle restrictions (warning: has to be done before loading timed lights!) if (_configuration.LaneAllowedVehicleTypes != null) { Log.Info($"Loading lane vehicle restriction data. {_configuration.LaneAllowedVehicleTypes.Count} elements"); foreach (Configuration.LaneVehicleTypes laneVehicleTypes in _configuration.LaneAllowedVehicleTypes) { try { ExtVehicleType baseMask = VehicleRestrictionsManager.GetBaseMask(laneVehicleTypes.laneId); ExtVehicleType maskedType = laneVehicleTypes.vehicleTypes & baseMask; Log._Debug($"Loading lane vehicle restriction: lane {laneVehicleTypes.laneId} = {laneVehicleTypes.vehicleTypes}, masked = {maskedType}"); if (maskedType != baseMask) { Flags.setLaneAllowedVehicleTypes(laneVehicleTypes.laneId, maskedType); } else { Log._Debug($"Masked type does not differ from base type. Ignoring."); } } catch (Exception e) { // ignore, as it's probably corrupt save data. it'll be culled on next save Log.Warning("Error loading data from vehicle restrictions: " + e.ToString()); } } } else { Log.Warning("Vehicle restrctions structure undefined!"); } var timedStepCount = 0; var timedStepSegmentCount = 0; NetManager netManager = Singleton <NetManager> .instance; if (_configuration.TimedLights != null) { Log.Info($"Loading {_configuration.TimedLights.Count()} timed traffic lights (new method)"); foreach (Configuration.TimedTrafficLights cnfTimedLights in _configuration.TimedLights) { try { if ((Singleton <NetManager> .instance.m_nodes.m_buffer[cnfTimedLights.nodeId].m_flags & NetNode.Flags.Created) == NetNode.Flags.None) { continue; } Flags.setNodeTrafficLight(cnfTimedLights.nodeId, true); Log._Debug($"Adding Timed Node at node {cnfTimedLights.nodeId}"); TrafficLightSimulation sim = TrafficLightSimulation.AddNodeToSimulation(cnfTimedLights.nodeId); sim.SetupTimedTrafficLight(cnfTimedLights.nodeGroup); var timedNode = sim.TimedLight; int j = 0; foreach (Configuration.TimedTrafficLightsStep cnfTimedStep in cnfTimedLights.timedSteps) { Log._Debug($"Loading timed step {j} at node {cnfTimedLights.nodeId}"); TimedTrafficLightsStep step = timedNode.AddStep(cnfTimedStep.minTime, cnfTimedStep.maxTime, cnfTimedStep.waitFlowBalance); foreach (KeyValuePair <ushort, Configuration.CustomSegmentLights> e in cnfTimedStep.segmentLights) { Log._Debug($"Loading timed step {j}, segment {e.Key} at node {cnfTimedLights.nodeId}"); CustomSegmentLights lights = null; if (!step.segmentLights.TryGetValue(e.Key, out lights)) { Log._Debug($"No segment lights found at timed step {j} for segment {e.Key}, node {cnfTimedLights.nodeId}"); continue; } Configuration.CustomSegmentLights cnfLights = e.Value; Log._Debug($"Loading pedestrian light @ seg. {e.Key}, step {j}: {cnfLights.pedestrianLightState} {cnfLights.manualPedestrianMode}"); lights.ManualPedestrianMode = cnfLights.manualPedestrianMode; lights.PedestrianLightState = cnfLights.pedestrianLightState; foreach (KeyValuePair <ExtVehicleType, Configuration.CustomSegmentLight> e2 in cnfLights.customLights) { Log._Debug($"Loading timed step {j}, segment {e.Key}, vehicleType {e2.Key} at node {cnfTimedLights.nodeId}"); CustomSegmentLight light = null; if (!lights.CustomLights.TryGetValue(e2.Key, out light)) { Log._Debug($"No segment light found for timed step {j}, segment {e.Key}, vehicleType {e2.Key} at node {cnfTimedLights.nodeId}"); continue; } Configuration.CustomSegmentLight cnfLight = e2.Value; light.CurrentMode = (CustomSegmentLight.Mode)cnfLight.currentMode; light.LightLeft = cnfLight.leftLight; light.LightMain = cnfLight.mainLight; light.LightRight = cnfLight.rightLight; } } ++j; } if (cnfTimedLights.started) { timedNode.Start(); } } catch (Exception e) { // ignore, as it's probably corrupt save data. it'll be culled on next save Log.Warning("Error loading data from TimedNode (new method): " + e.ToString()); } } } else if (_configuration.TimedNodes != null && _configuration.TimedNodeGroups != null) { Log.Info($"Loading {_configuration.TimedNodes.Count()} timed traffic lights (old method)"); for (var i = 0; i < _configuration.TimedNodes.Count; i++) { try { var nodeid = (ushort)_configuration.TimedNodes[i][0]; if ((Singleton <NetManager> .instance.m_nodes.m_buffer[nodeid].m_flags & NetNode.Flags.Created) == NetNode.Flags.None) { continue; } Flags.setNodeTrafficLight(nodeid, true); Log._Debug($"Adding Timed Node {i} at node {nodeid}"); var nodeGroup = new List <ushort>(); for (var j = 0; j < _configuration.TimedNodeGroups[i].Length; j++) { nodeGroup.Add(_configuration.TimedNodeGroups[i][j]); } TrafficLightSimulation sim = TrafficLightSimulation.AddNodeToSimulation(nodeid); sim.SetupTimedTrafficLight(nodeGroup); var timedNode = sim.TimedLight; timedNode.CurrentStep = _configuration.TimedNodes[i][1]; for (var j = 0; j < _configuration.TimedNodes[i][2]; j++) { var cfgstep = _configuration.TimedNodeSteps[timedStepCount]; // old (pre 1.3.0): // cfgstep[0]: time of step // cfgstep[1]: number of segments // new (post 1.3.0): // cfgstep[0]: min. time of step // cfgstep[1]: max. time of step // cfgstep[2]: number of segments int minTime = 1; int maxTime = 1; //int numSegments = 0; float waitFlowBalance = 1f; if (cfgstep.Length == 2) { minTime = cfgstep[0]; maxTime = cfgstep[0]; //numSegments = cfgstep[1]; } else if (cfgstep.Length >= 3) { minTime = cfgstep[0]; maxTime = cfgstep[1]; //numSegments = cfgstep[2]; if (cfgstep.Length == 4) { waitFlowBalance = Convert.ToSingle(cfgstep[3]) / 10f; } if (cfgstep.Length == 5) { waitFlowBalance = Convert.ToSingle(cfgstep[4]) / 1000f; } } Log._Debug($"Adding timed step to node {nodeid}: min/max: {minTime}/{maxTime}, waitFlowBalance: {waitFlowBalance}"); timedNode.AddStep(minTime, maxTime, waitFlowBalance); var step = timedNode.Steps[j]; for (var s = 0; s < 8; s++) { var segmentId = netManager.m_nodes.m_buffer[nodeid].GetSegment(s); if (segmentId <= 0) { continue; } bool tooFewSegments = (timedStepSegmentCount >= _configuration.TimedNodeStepSegments.Count); var leftLightState = tooFewSegments ? RoadBaseAI.TrafficLightState.Red : (RoadBaseAI.TrafficLightState)_configuration.TimedNodeStepSegments[timedStepSegmentCount][0]; var mainLightState = tooFewSegments ? RoadBaseAI.TrafficLightState.Red : (RoadBaseAI.TrafficLightState)_configuration.TimedNodeStepSegments[timedStepSegmentCount][1]; var rightLightState = tooFewSegments ? RoadBaseAI.TrafficLightState.Red : (RoadBaseAI.TrafficLightState)_configuration.TimedNodeStepSegments[timedStepSegmentCount][2]; var pedLightState = tooFewSegments ? RoadBaseAI.TrafficLightState.Red : (RoadBaseAI.TrafficLightState)_configuration.TimedNodeStepSegments[timedStepSegmentCount][3]; CustomSegmentLight.Mode?mode = null; if (_configuration.TimedNodeStepSegments[timedStepSegmentCount].Length >= 5) { mode = (CustomSegmentLight.Mode)_configuration.TimedNodeStepSegments[timedStepSegmentCount][4]; } foreach (KeyValuePair <ExtVehicleType, CustomSegmentLight> e in step.segmentLights[segmentId].CustomLights) { //ManualSegmentLight segmentLight = new ManualSegmentLight(step.NodeId, step.segmentIds[k], mainLightState, leftLightState, rightLightState, pedLightState); e.Value.LightLeft = leftLightState; e.Value.LightMain = mainLightState; e.Value.LightRight = rightLightState; if (mode != null) { e.Value.CurrentMode = (CustomSegmentLight.Mode)mode; } } if (step.segmentLights[segmentId].PedestrianLightState != null) { step.segmentLights[segmentId].PedestrianLightState = pedLightState; } timedStepSegmentCount++; } timedStepCount++; } if (Convert.ToBoolean(_configuration.TimedNodes[i][3])) { timedNode.Start(); } } catch (Exception e) { // ignore, as it's probably corrupt save data. it'll be culled on next save Log.Warning("Error loading data from the TimedNodes: " + e.ToString()); } } } else { Log.Warning("Timed traffic lights data structure undefined!"); } var trafficLightDefs = _configuration.NodeTrafficLights.Split(','); Log.Info($"Loading junction traffic light data"); if (trafficLightDefs.Length <= 1) { // old method Log.Info($"Using old method to load traffic light data"); var saveDataIndex = 0; for (var i = 0; i < Singleton <NetManager> .instance.m_nodes.m_buffer.Length; i++) { //Log.Message($"Adding NodeTrafficLights iteration: {i1}"); try { if ((Singleton <NetManager> .instance.m_nodes.m_buffer[i].Info.m_class.m_service != ItemClass.Service.Road && Singleton <NetManager> .instance.m_nodes.m_buffer[i].Info.m_class.m_service != ItemClass.Service.PublicTransport) || (Singleton <NetManager> .instance.m_nodes.m_buffer[i].m_flags & NetNode.Flags.Created) == NetNode.Flags.None) { continue; } // prevent overflow if (_configuration.NodeTrafficLights.Length > saveDataIndex) { var trafficLight = _configuration.NodeTrafficLights[saveDataIndex]; #if DEBUG Log._Debug("Setting traffic light flag for node " + i + ": " + (trafficLight == '1')); #endif Flags.setNodeTrafficLight((ushort)i, trafficLight == '1'); } ++saveDataIndex; } catch (Exception e) { // ignore as it's probably bad save data. Log.Warning("Error setting the NodeTrafficLights (old): " + e.Message); } } } else { // new method foreach (var split in trafficLightDefs.Select(def => def.Split(':')).Where(split => split.Length > 1)) { try { Log.Info($"Traffic light split data: {split[0]} , {split[1]}"); var nodeId = Convert.ToUInt16(split[0]); uint flag = Convert.ToUInt16(split[1]); Flags.setNodeTrafficLight(nodeId, flag > 0); } catch (Exception e) { // ignore as it's probably bad save data. Log.Warning("Error setting the NodeTrafficLights (new): " + e.Message); } } } if (_configuration.LaneFlags != null) { Log.Info($"Loading lane arrow data"); #if DEBUG Log._Debug($"LaneFlags: {_configuration.LaneFlags}"); #endif var lanes = _configuration.LaneFlags.Split(','); if (lanes.Length > 1) { foreach (var split in lanes.Select(lane => lane.Split(':')).Where(split => split.Length > 1)) { try { Log.Info($"Split Data: {split[0]} , {split[1]}"); var laneId = Convert.ToUInt32(split[0]); uint flags = Convert.ToUInt32(split[1]); //make sure we don't cause any overflows because of bad save data. if (Singleton <NetManager> .instance.m_lanes.m_buffer.Length <= laneId) { continue; } if (flags > ushort.MaxValue) { continue; } if ((Singleton <NetManager> .instance.m_lanes.m_buffer[laneId].m_flags & (ushort)NetLane.Flags.Created) == 0 || Singleton <NetManager> .instance.m_lanes.m_buffer[laneId].m_segment == 0) { continue; } //Singleton<NetManager>.instance.m_lanes.m_buffer[laneId].m_flags = fixLaneFlags(Singleton<NetManager>.instance.m_lanes.m_buffer[laneId].m_flags); uint laneArrowFlags = flags & Flags.lfr; uint origFlags = (Singleton <NetManager> .instance.m_lanes.m_buffer[laneId].m_flags & Flags.lfr); #if DEBUG Log._Debug("Setting flags for lane " + laneId + " to " + flags + " (" + ((Flags.LaneArrows)(laneArrowFlags)).ToString() + ")"); if ((origFlags | laneArrowFlags) == origFlags) // only load if setting differs from default { Log._Debug("Flags for lane " + laneId + " are original (" + ((NetLane.Flags)(origFlags)).ToString() + ")"); } #endif Flags.setLaneArrowFlags(laneId, (Flags.LaneArrows)(laneArrowFlags)); } catch (Exception e) { Log.Error($"Error loading Lane Split data. Length: {split.Length} value: {split}\nError: {e.Message}"); } } } } else { Log.Warning("Lane arrow data structure undefined!"); } // load lane connections if (_configuration.LaneConnections != null) { Log.Info($"Loading {_configuration.LaneConnections.Count()} lane connections"); foreach (Configuration.LaneConnection conn in _configuration.LaneConnections) { try { Log._Debug($"Loading lane connection: lane {conn.lowerLaneId} -> {conn.higherLaneId}"); Singleton <LaneConnectionManager> .instance.AddLaneConnection(conn.lowerLaneId, conn.higherLaneId, conn.lowerStartNode); } catch (Exception e) { // ignore, as it's probably corrupt save data. it'll be culled on next save Log.Warning("Error loading data from lane connection: " + e.ToString()); } } } else { Log.Warning("Lane connection data structure undefined!"); } // load speed limits if (_configuration.LaneSpeedLimits != null) { Log.Info($"Loading lane speed limit data. {_configuration.LaneSpeedLimits.Count} elements"); foreach (Configuration.LaneSpeedLimit laneSpeedLimit in _configuration.LaneSpeedLimits) { try { Log._Debug($"Loading lane speed limit: lane {laneSpeedLimit.laneId} = {laneSpeedLimit.speedLimit}"); Flags.setLaneSpeedLimit(laneSpeedLimit.laneId, laneSpeedLimit.speedLimit); } catch (Exception e) { // ignore, as it's probably corrupt save data. it'll be culled on next save Log.Warning("Error loading speed limits: " + e.ToString()); } } } else { Log.Warning("Lane speed limit structure undefined!"); } // Load segment-at-node flags if (_configuration.SegmentNodeConfs != null) { Log.Info($"Loading segment-at-node data. {_configuration.SegmentNodeConfs.Count} elements"); foreach (Configuration.SegmentNodeConf segNodeConf in _configuration.SegmentNodeConfs) { try { if ((Singleton <NetManager> .instance.m_segments.m_buffer[segNodeConf.segmentId].m_flags & NetSegment.Flags.Created) == NetSegment.Flags.None) { continue; } Flags.setSegmentNodeFlags(segNodeConf.segmentId, true, segNodeConf.startNodeFlags); Flags.setSegmentNodeFlags(segNodeConf.segmentId, false, segNodeConf.endNodeFlags); } catch (Exception e) { // ignore, as it's probably corrupt save data. it'll be culled on next save Log.Warning("Error loading segment-at-node config: " + e.ToString()); } } } else { Log.Warning("Segment-at-node structure undefined!"); } }
internal void handleNewSegments() { if (Steps.Count <= 0) { return; } NetNode node = Singleton <NetManager> .instance.m_nodes.m_buffer[nodeId]; for (int s = 0; s < 8; ++s) { ushort segmentId = node.GetSegment(s); if (segmentId <= 0) { continue; } NetSegment segment = Singleton <NetManager> .instance.m_segments.m_buffer[segmentId]; List <ushort> invalidSegmentIds = new List <ushort>(); bool isNewSegment = true; foreach (KeyValuePair <ushort, ManualSegmentLight> e in Steps[0].segmentLightStates) { var fromSegmentId = e.Key; var segLightState = e.Value; if (fromSegmentId == segmentId) { isNewSegment = false; } if (!TrafficPriority.IsPrioritySegment(nodeId, fromSegmentId)) { invalidSegmentIds.Add(fromSegmentId); } } if (isNewSegment) { Log.Message($"New segment detected: {segmentId} @ {nodeId}"); // segment was created TrafficLightsManual.AddLiveSegmentLight(nodeId, segmentId); TrafficPriority.AddPrioritySegment(nodeId, segmentId, PrioritySegment.PriorityType.None); if (invalidSegmentIds.Count > 0) { var oldSegmentId = invalidSegmentIds[0]; Log.Message($"Replacing old segment {oldSegmentId} @ {nodeId} with new segment {segmentId}"); // replace the old segment with the newly created one for (int i = 0; i < Steps.Count; ++i) { ManualSegmentLight segmentLight = Steps[i].segmentLightStates[oldSegmentId]; Steps[i].segmentIds.Remove(oldSegmentId); Steps[i].segmentLightStates.Remove(oldSegmentId); segmentLight.SegmentId = segmentId; Steps[i].segmentLightStates.Add(segmentId, segmentLight); Steps[i].segmentIds.Add(segmentId); Steps[i].rebuildSegmentIds(); } } else { Log.Message($"Adding new segment {segmentId} to node {nodeId}"); // create a new manual light for (int i = 0; i < Steps.Count; ++i) { Steps[i].addSegment(segmentId); Steps[i].rebuildSegmentIds(); } } } } }
/*public static TimedTrafficLights AddTimedLight(ushort nodeid, List<ushort> nodeGroup, bool vehiclesMayEnterBlockedJunctions) { * TimedScripts.Add(nodeid, new TimedTrafficLights(nodeid, nodeGroup, vehiclesMayEnterBlockedJunctions)); * return TimedScripts[nodeid]; * } * * public static void RemoveTimedLight(ushort nodeid) { * TimedScripts.Remove(nodeid); * } * * public static bool IsTimedLight(ushort nodeid) { * return TimedScripts.ContainsKey(nodeid); * } * * public static TimedTrafficLights GetTimedLight(ushort nodeid) { * if (!IsTimedLight(nodeid)) * return null; * return TimedScripts[nodeid]; * } * * internal static void OnLevelUnloading() { * TimedScripts.Clear(); * }*/ internal void handleNewSegments() { if (NumSteps() <= 0) { // no steps defined, just create live traffic lights for (int s = 0; s < 8; ++s) { ushort segmentId = Singleton <NetManager> .instance.m_nodes.m_buffer[NodeId].GetSegment(s); if (segmentId <= 0) { continue; } CustomTrafficLights.AddLiveSegmentLights(NodeId, segmentId); } return; } for (int s = 0; s < 8; ++s) { ushort segmentId = Singleton <NetManager> .instance.m_nodes.m_buffer[NodeId].GetSegment(s); if (segmentId <= 0) { continue; } List <ushort> invalidSegmentIds = new List <ushort>(); bool isNewSegment = true; foreach (KeyValuePair <ushort, CustomSegmentLights> e in Steps[0].segmentLights) { var fromSegmentId = e.Key; if (fromSegmentId == segmentId) { isNewSegment = false; } if (!TrafficPriority.IsPrioritySegment(NodeId, fromSegmentId)) { invalidSegmentIds.Add(fromSegmentId); } } if (isNewSegment) { Log._Debug($"New segment detected: {segmentId} @ {NodeId}"); // segment was created CustomTrafficLights.AddLiveSegmentLights(NodeId, segmentId); TrafficPriority.AddPrioritySegment(NodeId, segmentId, SegmentEnd.PriorityType.None); if (invalidSegmentIds.Count > 0) { var oldSegmentId = invalidSegmentIds[0]; TrafficPriority.RemovePrioritySegment(NodeId, oldSegmentId); Log._Debug($"Replacing old segment {oldSegmentId} @ {NodeId} with new segment {segmentId}"); // replace the old segment with the newly created one for (int i = 0; i < NumSteps(); ++i) { CustomSegmentLights segmentLights = Steps[i].segmentLights[oldSegmentId]; Steps[i].segmentLights.Remove(oldSegmentId); segmentLights.SegmentId = segmentId; Steps[i].segmentLights.Add(segmentId, segmentLights); Steps[i].calcMaxSegmentLength(); CustomSegmentLights liveSegLights = CustomTrafficLights.GetSegmentLights(NodeId, segmentId); foreach (KeyValuePair <ExtVehicleType, CustomSegmentLight> e in segmentLights.CustomLights) { CustomSegmentLight liveSegLight = liveSegLights.GetCustomLight(e.Key); if (liveSegLight == null) { continue; } liveSegLight.CurrentMode = e.Value.CurrentMode; } } } else { Log._Debug($"Adding new segment {segmentId} to node {NodeId}"); // create a new manual light for (int i = 0; i < NumSteps(); ++i) { Steps[i].addSegment(segmentId, true); Steps[i].calcMaxSegmentLength(); } } } } }