public void SimulationStep()
        {
            //Log.Warning("step: " + NodeId);
            var currentFrameIndex = Singleton <SimulationManager> .instance.m_currentFrameIndex;

            if (TimedTrafficLightsActive)
            {
                var timedNode = TrafficLightsTimed.GetTimedLight(nodeId);
                if (timedNode != null)
                {
                    timedNode.CheckCurrentStep();
                }
            }

            var node = getNode();

            for (var l = 0; l < 8; l++)
            {
                var segment = node.GetSegment(l);
                if (segment == 0)
                {
                    continue;
                }
                if (!TrafficLightsManual.IsSegmentLight(nodeId, segment))
                {
                    continue;
                }

                var segmentLight = TrafficLightsManual.GetSegmentLight(nodeId, segment);

                segmentLight.LastChange = (currentFrameIndex >> 6) - segmentLight.LastChangeFrame;
            }
        }
        public long CheckNextChange(ushort segmentId, int lightType)
        {
            var curStep   = CurrentStep;
            var nextStep  = CurrentStep + 1;
            var numFrames = Steps[CurrentStep].MaxTimeRemaining();

            RoadBaseAI.TrafficLightState currentState;

            if (lightType == 0)
            {
                currentState = TrafficLightsManual.GetSegmentLight(nodeId, segmentId).GetLightMain();
            }
            else if (lightType == 1)
            {
                currentState = TrafficLightsManual.GetSegmentLight(nodeId, segmentId).GetLightLeft();
            }
            else if (lightType == 2)
            {
                currentState = TrafficLightsManual.GetSegmentLight(nodeId, segmentId).GetLightRight();
            }
            else
            {
                currentState = TrafficLightsManual.GetSegmentLight(nodeId, segmentId).GetLightPedestrian();
            }


            while (true)
            {
                if (nextStep == curStep)
                {
                    numFrames = 99;
                    break;
                }

                var light = Steps[nextStep].GetLight(segmentId, lightType);

                if (light != currentState)
                {
                    break;
                }
                else
                {
                    numFrames += Steps[nextStep].maxTime;
                }

                nextStep = (nextStep + 1) % NumSteps();
            }

            return(numFrames);
        }
        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();
                        }
                    }
                }
            }
        }