public void SimulationStep(ref NetNode data)
        {
            NetManager instance          = Singleton <NetManager> .instance;
            uint       currentFrameIndex = Singleton <SimulationManager> .instance.m_currentFrameIndex;

            if (TrafficLightsTimed.IsTimedLight(NodeId) && TimedTrafficLightsActive)
            {
                var timedNode = TrafficLightsTimed.GetTimedLight(NodeId);
                timedNode.checkStep(currentFrameIndex >> 6);
            }

            for (int l = 0; l < 8; l++)
            {
                ushort segment = data.GetSegment(l);
                if (segment != 0)
                {
                    if (TrafficLightsManual.IsSegmentLight(NodeId, segment))
                    {
                        var segmentLight = TrafficLightsManual.GetSegmentLight(NodeId, segment);

                        segmentLight.lastChange = (currentFrameIndex >> 6) - segmentLight.lastChangeFrame;
                    }
                }
            }
        }
Example #2
0
        public override void OnLevelUnloading()
        {
            base.OnLevelUnloading();
            if (Instance == null)
            {
                Instance = this;
            }
            revertDetours();

            try {
                TrafficPriority.OnLevelUnloading();
                CustomCarAI.OnLevelUnloading();
                TrafficLightsManual.OnLevelUnloading();
                TrafficLightsTimed.OnLevelUnloading();

                if (Instance != null)
                {
                    Instance.NodeSimulationLoaded = false;
                }
            } catch (Exception e) {
                Log.Error("Exception unloading mod. " + e.Message);
                // ignored - prevents collision with other mods
            }
        }
        private static void AddTimedTrafficLight(int i, Configuration configuration)
        {
            try {
                if (!TrafficLightsTimed.TimedScripts.ContainsKey((ushort)i))
                {
                    return;
                }

                var timedNode = TrafficLightsTimed.GetTimedLight((ushort)i);

                configuration.TimedNodes.Add(new[]
                {
                    timedNode.nodeId, timedNode.CurrentStep, timedNode.NumSteps(),
                    Convert.ToInt32(timedNode.IsStarted())
                });

                var nodeGroup = new ushort[timedNode.NodeGroup.Count];

                for (var j = 0; j < timedNode.NodeGroup.Count; j++)
                {
                    nodeGroup[j] = timedNode.NodeGroup[j];
                }

                configuration.TimedNodeGroups.Add(nodeGroup);

                // get segment ids which are still defined but for which real road segments are missing
                HashSet <ushort> invalidSegmentIds = timedNode.getInvalidSegmentIds();

                for (var j = 0; j < timedNode.NumSteps(); j++)
                {
                    int validCount = timedNode.Steps[j].segmentIds.Count - invalidSegmentIds.Count;

                    configuration.TimedNodeSteps.Add(new[]
                    {
                        timedNode.Steps[j].minTime,
                        timedNode.Steps[j].maxTime,
                        validCount
                    });

                    for (var k = 0; k < timedNode.Steps[j].segmentIds.Count; k++)
                    {
                        var segmentId = timedNode.Steps[j].segmentIds[k];

                        if (invalidSegmentIds.Contains(segmentId))
                        {
                            continue;
                        }

                        var segLight = timedNode.Steps[j].segmentLightStates[segmentId];
                        configuration.TimedNodeStepSegments.Add(new[]
                        {
                            (int)segLight.LightLeft,
                            (int)segLight.LightMain,
                            (int)segLight.LightRight,
                            (int)segLight.LightPedestrian
                        });
                    }
                }
            } catch (Exception e) {
                Log.Error($"Error adding TimedTrafficLights to save {e.Message}");
            }
        }
        private static void LoadDataState()
        {
            Log.Message("Loading State from Config");
            if (_configuration == null)
            {
                Log.Message("Configuration NULL, Couldn't load save data. Possibly a new game?");
                return;
            }
            foreach (var segment in _configuration.PrioritySegments)
            {
                if (segment.Length < 3)
                {
                    continue;
                }
                if (TrafficPriority.IsPrioritySegment((ushort)segment[0], (ushort)segment[1]))
                {
                    continue;
                }
                Log.Message($"Adding Priority Segment of type: {segment[2].ToString()}");
                TrafficPriority.AddPrioritySegment((ushort)segment[0], (ushort)segment[1], (PrioritySegment.PriorityType)segment[2]);
            }

            foreach (var node in _configuration.NodeDictionary)
            {
                if (node.Length < 4)
                {
                    continue;
                }
                if (TrafficPriority.GetNodeSimulation((ushort)node[0]) != null)
                {
                    continue;
                }

                Log.Message($"Adding Node do Simulation {node[0]}");
                try {
                    TrafficPriority.AddNodeToSimulation((ushort)node[0]);
                    var nodeDict = TrafficPriority.GetNodeSimulation((ushort)node[0]);

                    nodeDict.ManualTrafficLights      = Convert.ToBoolean(node[1]);
                    nodeDict.TimedTrafficLights       = Convert.ToBoolean(node[2]);
                    nodeDict.TimedTrafficLightsActive = Convert.ToBoolean(node[3]);
                } catch (Exception e) {
                    // if we failed, just means it's old corrupt data. Ignore it and continue.
                    Log.Warning("Error loading data from the NodeDictionary: " + e.Message);
                }
            }

            foreach (var segmentData in _configuration.ManualSegments)
            {
                if (segmentData.Length < 10)
                {
                    continue;
                }

                if (TrafficLightsManual.IsSegmentLight((ushort)segmentData[0], (ushort)segmentData[1]))
                {
                    continue;
                }

                Log.Message($"Adding Light to Segment {segmentData[0]}");
                try {
                    TrafficLightsManual.AddSegmentLight((ushort)segmentData[0], (ushort)segmentData[1], RoadBaseAI.TrafficLightState.Green);
                    var segment = TrafficLightsManual.GetSegmentLight((ushort)segmentData[0], (ushort)segmentData[1]);
                    segment.CurrentMode       = (ManualSegmentLight.Mode)segmentData[2];
                    segment.LightLeft         = (RoadBaseAI.TrafficLightState)segmentData[3];
                    segment.LightMain         = (RoadBaseAI.TrafficLightState)segmentData[4];
                    segment.LightRight        = (RoadBaseAI.TrafficLightState)segmentData[5];
                    segment.LightPedestrian   = (RoadBaseAI.TrafficLightState)segmentData[6];
                    segment.LastChange        = (uint)segmentData[7];
                    segment.LastChangeFrame   = (uint)segmentData[8];
                    segment.PedestrianEnabled = Convert.ToBoolean(segmentData[9]);
                } catch (Exception e) {
                    // if we failed, just means it's old corrupt data. Ignore it and continue.
                    Log.Warning("Error loading data from the ManualSegments: " + e.Message);
                }
            }

            var timedStepCount        = 0;
            var timedStepSegmentCount = 0;

            if (_configuration.TimedNodes.Count > 0)
            {
                for (var i = 0; i < _configuration.TimedNodes.Count; i++)
                {
                    try {
                        var nodeid = (ushort)_configuration.TimedNodes[i][0];
                        Log.Message($"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]);
                        }

                        if (TrafficLightsTimed.IsTimedLight(nodeid))
                        {
                            continue;
                        }
                        TrafficLightsTimed.AddTimedLight(nodeid, nodeGroup);
                        var timedNode = TrafficLightsTimed.GetTimedLight(nodeid);

                        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;

                            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];
                            }

                            timedNode.AddStep(minTime, maxTime);

                            var step = timedNode.Steps[j];
                            if (numSegments <= step.segmentIds.Count)
                            {
                                for (var k = 0; k < numSegments; k++)
                                {
                                    ushort stepSegmentId = (ushort)step.segmentIds[k];

                                    var leftLightState  = (RoadBaseAI.TrafficLightState)_configuration.TimedNodeStepSegments[timedStepSegmentCount][0];
                                    var mainLightState  = (RoadBaseAI.TrafficLightState)_configuration.TimedNodeStepSegments[timedStepSegmentCount][1];
                                    var rightLightState = (RoadBaseAI.TrafficLightState)_configuration.TimedNodeStepSegments[timedStepSegmentCount][2];
                                    var pedLightState   = (RoadBaseAI.TrafficLightState)_configuration.TimedNodeStepSegments[timedStepSegmentCount][3];

                                    //ManualSegmentLight segmentLight = new ManualSegmentLight(step.NodeId, step.segmentIds[k], mainLightState, leftLightState, rightLightState, pedLightState);
                                    step.segmentLightStates[stepSegmentId].LightLeft       = leftLightState;
                                    step.segmentLightStates[stepSegmentId].LightMain       = mainLightState;
                                    step.segmentLightStates[stepSegmentId].LightRight      = rightLightState;
                                    step.segmentLightStates[stepSegmentId].LightPedestrian = 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.Message);
                    }
                }
            }

            Log.Message($"Config Nodes: {_configuration.NodeTrafficLights.Length}\nLevel Nodes: {Singleton<NetManager>.instance.m_nodes.m_buffer.Length}");
            var saveDataIndex = 0;
            var nodeCount     = Singleton <NetManager> .instance.m_nodes.m_buffer.Length;

            if (nodeCount > 0)
            {
                for (var i = 0; i < nodeCount; 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].m_flags == 0)
                        {
                            continue;
                        }

                        // prevent overflow
                        if (_configuration.NodeTrafficLights.Length > saveDataIndex)
                        {
                            var trafficLight = _configuration.NodeTrafficLights[saveDataIndex];
                            if (trafficLight == '1')
                            {
                                //Log.Message($"Adding Traffic Light at Segment: {Singleton<NetManager>.instance.m_nodes.m_buffer[i].Info.name}");
                                Singleton <NetManager> .instance.m_nodes.m_buffer[i].m_flags |=
                                    NetNode.Flags.TrafficLights;
                            }
                            else
                            {
                                //Log.Message($"Removing Traffic Light from Segment: {Singleton<NetManager>.instance.m_nodes.m_buffer[i].Info.name}");
                                Singleton <NetManager> .instance.m_nodes.m_buffer[i].m_flags &=
                                    ~NetNode.Flags.TrafficLights;
                            }
                        }

                        if (_configuration.NodeCrosswalk.Length > saveDataIndex)
                        {
                            var crossWalk = _configuration.NodeCrosswalk[saveDataIndex];

                            if (crossWalk == '1')
                            {
                                Singleton <NetManager> .instance.m_nodes.m_buffer[i].m_flags |= NetNode.Flags.Junction;
                            }
                            else
                            {
                                Singleton <NetManager> .instance.m_nodes.m_buffer[i].m_flags &= ~NetNode.Flags.Junction;
                            }
                        }
                        ++saveDataIndex;
                    } catch (Exception e) {
                        // ignore as it's probably bad save data.
                        Log.Warning("Error setting the NodeTrafficLights: " + e.Message);
                    }
                }
            }

            // For Traffic++ compatibility
            if (!LoadingExtension.IsPathManagerCompatible)
            {
                return;
            }

            Log.Message($"LaneFlags: {_configuration.LaneFlags}");
            var lanes = _configuration.LaneFlags.Split(',');

            if (lanes.Length <= 1)
            {
                return;
            }
            foreach (var split in lanes.Select(lane => lane.Split(':')).Where(split => split.Length > 1))
            {
                try {
                    Log.Message($"Split Data: {split[0]} , {split[1]}");
                    var laneIndex = Convert.ToInt32(split[0]);

                    //make sure we don't cause any overflows because of bad save data.
                    if (Singleton <NetManager> .instance.m_lanes.m_buffer.Length <= laneIndex)
                    {
                        continue;
                    }

                    if (Convert.ToInt32(split[1]) > ushort.MaxValue)
                    {
                        continue;
                    }

                    Log.Message("Setting flags for lane " + Convert.ToInt32(split[0]) + " to " + Convert.ToUInt16(split[1]));
                    Singleton <NetManager> .instance.m_lanes.m_buffer[Convert.ToInt32(split[0])].m_flags =
                        Convert.ToUInt16(split[1]);
                } catch (Exception e) {
                    Log.Error(
                        $"Error loading Lane Split data. Length: {split.Length} value: {split}\nError: {e.Message}");
                }
            }
        }
Example #5
0
        private static void OnLoadDataTimed(System.Object source, ElapsedEventArgs e)
        {
            byte[] data = SerializableData.LoadData(dataID);

            for (var i = 0; i < data.Length - 3; i++)
            {
                uniqueID = BitConverter.ToUInt32(data, i);
            }

            var filepath = Path.Combine(Application.dataPath, "trafficManagerSave_" + uniqueID + ".xml");

            _timer.Enabled = false;

            if (!File.Exists(filepath))
            {
                return;
            }

            var configuration = Configuration.Deserialize(filepath);

            for (var i = 0; i < configuration.prioritySegments.Count; i++)
            {
                if (
                    !TrafficPriority.isPrioritySegment((ushort)configuration.prioritySegments[i][0],
                                                       configuration.prioritySegments[i][1]))
                {
                    TrafficPriority.addPrioritySegment((ushort)configuration.prioritySegments[i][0],
                                                       configuration.prioritySegments[i][1],
                                                       (PrioritySegment.PriorityType)configuration.prioritySegments[i][2]);
                }
            }

            for (var i = 0; i < configuration.nodeDictionary.Count; i++)
            {
                if (CustomRoadAI.GetNodeSimulation((ushort)configuration.nodeDictionary[i][0]) == null)
                {
                    CustomRoadAI.AddNodeToSimulation((ushort)configuration.nodeDictionary[i][0]);
                    var nodeDict = CustomRoadAI.GetNodeSimulation((ushort)configuration.nodeDictionary[i][0]);

                    nodeDict._manualTrafficLights     = Convert.ToBoolean(configuration.nodeDictionary[i][1]);
                    nodeDict._timedTrafficLights      = Convert.ToBoolean(configuration.nodeDictionary[i][2]);
                    nodeDict.TimedTrafficLightsActive = Convert.ToBoolean(configuration.nodeDictionary[i][3]);
                }
            }

            for (var i = 0; i < configuration.manualSegments.Count; i++)
            {
                var segmentData = configuration.manualSegments[i];

                if (!TrafficLightsManual.IsSegmentLight((ushort)segmentData[0], segmentData[1]))
                {
                    TrafficLightsManual.AddSegmentLight((ushort)segmentData[0], segmentData[1],
                                                        RoadBaseAI.TrafficLightState.Green);
                    var segment = TrafficLightsManual.GetSegmentLight((ushort)segmentData[0], segmentData[1]);
                    segment.currentMode       = (ManualSegmentLight.Mode)segmentData[2];
                    segment.lightLeft         = (RoadBaseAI.TrafficLightState)segmentData[3];
                    segment.lightMain         = (RoadBaseAI.TrafficLightState)segmentData[4];
                    segment.lightRight        = (RoadBaseAI.TrafficLightState)segmentData[5];
                    segment.lightPedestrian   = (RoadBaseAI.TrafficLightState)segmentData[6];
                    segment.lastChange        = (uint)segmentData[7];
                    segment.lastChangeFrame   = (uint)segmentData[8];
                    segment.pedestrianEnabled = Convert.ToBoolean(segmentData[9]);
                }
            }

            var timedStepCount        = 0;
            var timedStepSegmentCount = 0;

            for (var i = 0; i < configuration.timedNodes.Count; i++)
            {
                var nodeid = (ushort)configuration.timedNodes[i][0];

                var nodeGroup = new List <ushort>();
                for (var j = 0; j < configuration.timedNodeGroups[i].Length; j++)
                {
                    nodeGroup.Add(configuration.timedNodeGroups[i][j]);
                }

                if (!TrafficLightsTimed.IsTimedLight(nodeid))
                {
                    TrafficLightsTimed.AddTimedLight(nodeid, nodeGroup);
                    var timedNode = TrafficLightsTimed.GetTimedLight(nodeid);

                    timedNode.currentStep = configuration.timedNodes[i][1];

                    for (var j = 0; j < configuration.timedNodes[i][2]; j++)
                    {
                        var cfgstep = configuration.timedNodeSteps[timedStepCount];

                        timedNode.addStep(cfgstep[0]);

                        var step = timedNode.steps[j];

                        for (var k = 0; k < cfgstep[1]; k++)
                        {
                            step.lightLeft[k]       = (RoadBaseAI.TrafficLightState)configuration.timedNodeStepSegments[timedStepSegmentCount][0];
                            step.lightMain[k]       = (RoadBaseAI.TrafficLightState)configuration.timedNodeStepSegments[timedStepSegmentCount][1];
                            step.lightRight[k]      = (RoadBaseAI.TrafficLightState)configuration.timedNodeStepSegments[timedStepSegmentCount][2];
                            step.lightPedestrian[k] = (RoadBaseAI.TrafficLightState)configuration.timedNodeStepSegments[timedStepSegmentCount][3];

                            timedStepSegmentCount++;
                        }

                        timedStepCount++;
                    }

                    if (timedNode.isStarted())
                    {
                        timedNode.start();
                    }
                }
            }

            var j1 = 0;

            for (var i1 = 0; i1 < 32768; i1++)
            {
                if (Singleton <NetManager> .instance.m_nodes.m_buffer[i1].Info.m_class.m_service ==
                    ItemClass.Service.Road && Singleton <NetManager> .instance.m_nodes.m_buffer[i1].m_flags != 0)
                {
                    var trafficLight = configuration.nodeTrafficLights[j1];

                    if (trafficLight == '1')
                    {
                        Singleton <NetManager> .instance.m_nodes.m_buffer[i1].m_flags |= NetNode.Flags.TrafficLights;
                    }
                    else
                    {
                        Singleton <NetManager> .instance.m_nodes.m_buffer[i1].m_flags &= ~NetNode.Flags.TrafficLights;
                    }

                    j1++;
                }
            }

            var j2 = 0;

            for (var i2 = 0; i2 < 32768; i2++)
            {
                if (Singleton <NetManager> .instance.m_nodes.m_buffer[i2].Info.m_class.m_service ==
                    ItemClass.Service.Road && Singleton <NetManager> .instance.m_nodes.m_buffer[i2].m_flags != 0)
                {
                    var crossWalk = configuration.nodeCrosswalk[j2];

                    if (crossWalk == '1')
                    {
                        Singleton <NetManager> .instance.m_nodes.m_buffer[i2].m_flags |= NetNode.Flags.Junction;
                    }
                    else
                    {
                        Singleton <NetManager> .instance.m_nodes.m_buffer[i2].m_flags &= ~NetNode.Flags.Junction;
                    }

                    j2++;
                }
            }

            var lanes = configuration.laneFlags.Split(',');

            for (var i = 0; i < lanes.Length; i++)
            {
                var split = lanes[i].Split(':');

                Singleton <NetManager> .instance.m_lanes.m_buffer[Convert.ToInt32(split[0])].m_flags =
                    Convert.ToUInt16(split[1]);
            }
        }
Example #6
0
        public void OnSaveData()
        {
            FastList <byte> data = new FastList <byte>();

            GenerateUniqueID();

            byte[] uniqueIdBytes = BitConverter.GetBytes(uniqueID);
            foreach (byte uniqueIdByte in uniqueIdBytes)
            {
                data.Add(uniqueIdByte);
            }

            byte[] dataToSave = data.ToArray();
            SerializableData.SaveData(dataID, dataToSave);

            var filepath = Path.Combine(Application.dataPath, "trafficManagerSave_" + uniqueID + ".xml");

            var configuration = new Configuration();

            for (var i = 0; i < 32768; i++)
            {
                if (TrafficPriority.prioritySegments.ContainsKey(i))
                {
                    if (TrafficPriority.prioritySegments[i].node_1 != 0)
                    {
                        configuration.prioritySegments.Add(new int[3] {
                            TrafficPriority.prioritySegments[i].node_1, i, (int)TrafficPriority.prioritySegments[i].instance_1.type
                        });
                    }
                    if (TrafficPriority.prioritySegments[i].node_2 != 0)
                    {
                        configuration.prioritySegments.Add(new int[3] {
                            TrafficPriority.prioritySegments[i].node_2, i, (int)TrafficPriority.prioritySegments[i].instance_2.type
                        });
                    }
                }

                if (CustomRoadAI.nodeDictionary.ContainsKey((ushort)i))
                {
                    var nodeDict = CustomRoadAI.nodeDictionary[(ushort)i];

                    configuration.nodeDictionary.Add(new int[4] {
                        nodeDict.NodeId, Convert.ToInt32(nodeDict._manualTrafficLights), Convert.ToInt32(nodeDict._timedTrafficLights), Convert.ToInt32(nodeDict.TimedTrafficLightsActive)
                    });
                }

                if (TrafficLightsManual.ManualSegments.ContainsKey(i))
                {
                    if (TrafficLightsManual.ManualSegments[i].node_1 != 0)
                    {
                        var manualSegment = TrafficLightsManual.ManualSegments[i].instance_1;

                        configuration.manualSegments.Add(new int[10]
                        {
                            (int)manualSegment.node,
                            manualSegment.segment,
                            (int)manualSegment.currentMode,
                            (int)manualSegment.lightLeft,
                            (int)manualSegment.lightMain,
                            (int)manualSegment.lightRight,
                            (int)manualSegment.lightPedestrian,
                            (int)manualSegment.lastChange,
                            (int)manualSegment.lastChangeFrame,
                            Convert.ToInt32(manualSegment.pedestrianEnabled)
                        });
                    }
                    if (TrafficLightsManual.ManualSegments[i].node_2 != 0)
                    {
                        var manualSegment = TrafficLightsManual.ManualSegments[i].instance_2;

                        configuration.manualSegments.Add(new int[10]
                        {
                            (int)manualSegment.node,
                            manualSegment.segment,
                            (int)manualSegment.currentMode,
                            (int)manualSegment.lightLeft,
                            (int)manualSegment.lightMain,
                            (int)manualSegment.lightRight,
                            (int)manualSegment.lightPedestrian,
                            (int)manualSegment.lastChange,
                            (int)manualSegment.lastChangeFrame,
                            Convert.ToInt32(manualSegment.pedestrianEnabled)
                        });
                    }
                }

                if (TrafficLightsTimed.timedScripts.ContainsKey((ushort)i))
                {
                    var timedNode = TrafficLightsTimed.GetTimedLight((ushort)i);

                    configuration.timedNodes.Add(new int[3] {
                        timedNode.nodeID, timedNode.currentStep, timedNode.NumSteps()
                    });

                    var nodeGroup = new ushort[timedNode.nodeGroup.Count];

                    for (var j = 0; j < timedNode.nodeGroup.Count; j++)
                    {
                        nodeGroup[j] = timedNode.nodeGroup[j];
                    }

                    configuration.timedNodeGroups.Add(nodeGroup);

                    for (var j = 0; j < timedNode.NumSteps(); j++)
                    {
                        configuration.timedNodeSteps.Add(new int[2]
                        {
                            timedNode.steps[j].numSteps,
                            timedNode.steps[j].segments.Count
                        });

                        for (var k = 0; k < timedNode.steps[j].segments.Count; k++)
                        {
                            configuration.timedNodeStepSegments.Add(new int[4]
                            {
                                (int)timedNode.steps[j].lightLeft[k],
                                (int)timedNode.steps[j].lightMain[k],
                                (int)timedNode.steps[j].lightRight[k],
                                (int)timedNode.steps[j].lightPedestrian[k],
                            });
                        }
                    }
                }
            }

            for (var i = 0; i < Singleton <NetManager> .instance.m_nodes.m_buffer.Length; i++)
            {
                var nodeFlags = Singleton <NetManager> .instance.m_nodes.m_buffer[i].m_flags;

                if (nodeFlags != 0)
                {
                    if (Singleton <NetManager> .instance.m_nodes.m_buffer[i].Info.m_class.m_service ==
                        ItemClass.Service.Road)
                    {
                        configuration.nodeTrafficLights +=
                            Convert.ToInt16((nodeFlags & NetNode.Flags.TrafficLights) != NetNode.Flags.None);
                        configuration.nodeCrosswalk +=
                            Convert.ToInt16((nodeFlags & NetNode.Flags.Junction) != NetNode.Flags.None);
                    }
                }
            }

            for (var i = 0; i < Singleton <NetManager> .instance.m_lanes.m_buffer.Length; i++)
            {
                var laneSegment = Singleton <NetManager> .instance.m_lanes.m_buffer[i].m_segment;

                if (TrafficPriority.prioritySegments.ContainsKey(laneSegment))
                {
                    configuration.laneFlags += i + ":" + Singleton <NetManager> .instance.m_lanes.m_buffer[i].m_flags + ",";
                }
            }

            Configuration.Serialize(filepath, configuration);
        }
        public void Update()
        {
            uint currentFrameIndex = Singleton <SimulationManager> .instance.m_currentFrameIndex >> 6;

            if (lastFrame < currentFrameIndex)
            {
                lastFrame = currentFrameIndex;

                List <ushort> clearedNodes = new List <ushort>();

                foreach (var nodeID in nodeDictionary.Keys)
                {
                    var data = TrafficLightTool.GetNetNode(nodeID);

                    try
                    {
                        for (var i = 0; i < 8; i++)
                        {
                            var sgmid = data.GetSegment(i);

                            if (sgmid != 0)
                            {
                                if (!TrafficLightsManual.IsSegmentLight(nodeID, sgmid))
                                {
                                    if (nodeDictionary[nodeID].FlagTimedTrafficLights)
                                    {
                                        var timedNode = TrafficLightsTimed.GetTimedLight(nodeID);

                                        for (var j = 0; j < timedNode.nodeGroup.Count; j++)
                                        {
                                            var nodeSim = CustomRoadAI.GetNodeSimulation(timedNode.nodeGroup[j]);

                                            nodeSim.TimedTrafficLightsActive = false;

                                            clearedNodes.Add(timedNode.nodeGroup[j]);
                                            TrafficLightsTimed.RemoveTimedLight(timedNode.nodeGroup[j]);
                                        }
                                    }
                                }
                            }
                        }
                    }
                    catch (Exception e)
                    {
                        //Log.Warning("Error on Update: \n" + e.Message + "\n\nStacktrace:\n\n" + e.StackTrace);
                    }
                }

                if (clearedNodes.Count > 0)
                {
                    for (var i = 0; i < clearedNodes.Count; i++)
                    {
                        CustomRoadAI.RemoveNodeFromSimulation(clearedNodes[i]);
                    }
                }

                foreach (var nodeID in nodeDictionary.Keys)
                {
                    var node = GetNodeSimulation(nodeID);

                    if (node.FlagManualTrafficLights || (node.FlagTimedTrafficLights && node.TimedTrafficLightsActive))
                    {
                        var data = TrafficLightTool.GetNetNode(nodeID);

                        node.SimulationStep(ref data);
                        TrafficLightTool.SetNetNode(nodeID, data);

                        if (clearedNodes.Count > 0)
                        {
                            break;
                        }
                    }
                }
            }
        }