Beispiel #1
0
        private bool SimpleManualSegmentLightMode(int segmentId, Vector3 screenPos, float lightWidth, float pedestrianWidth,
                                                  float zoom, float lightHeight, CustomSegmentLight segmentDict, bool hoveredSegment)
        {
            SetAlpha(segmentId, 3);

            var myRect4 =
                new Rect(screenPos.x - lightWidth / 2 - lightWidth - pedestrianWidth + 5f * zoom,
                         screenPos.y - lightHeight / 2, lightWidth, lightHeight);

            switch (segmentDict.LightMain)
            {
            case RoadBaseAI.TrafficLightState.Green:
                GUI.DrawTexture(myRect4, TrafficLightToolTextureResources.GreenLightTexture2D);
                break;

            case RoadBaseAI.TrafficLightState.Red:
                GUI.DrawTexture(myRect4, TrafficLightToolTextureResources.RedLightTexture2D);
                break;
            }

            if (!myRect4.Contains(Event.current.mousePosition))
            {
                return(hoveredSegment);
            }
            _hoveredButton[0] = segmentId;
            _hoveredButton[1] = 3;

            if (!MainTool.CheckClicked())
            {
                return(true);
            }
            segmentDict.ChangeMainLight();
            return(true);
        }
        public object GetNodeState(int nodeIndex)
        {
            Dictionary <string, object> retObj = new Dictionary <string, object>();
            ushort nodeId = SelectNodeId(nodeIndex);

            for (int i = 0; i < 8; i++)
            {
                Dictionary <string, string> segDict = new Dictionary <string, string>();

                ushort segId             = NetManager.instance.m_nodes.m_buffer[nodeId].GetSegment(i);
                CustomSegmentLights csls = CustomTrafficLights.GetSegmentLights(nodeId, segId);

                if (csls != null)
                {
                    foreach (ExtVehicleType evt in csls.VehicleTypes)
                    {
                        CustomSegmentLight csl = csls.GetCustomLight(evt);
                        if (csl != null)
                        {
                            segDict.Add("vehicle", csl.GetVisualLightState().ToString());
                        }
                    }
                    retObj.Add("segment" + i, segDict);
                }
            }

            return(retObj);
        }
        public object SetNodeState(int nodeIndex, int segIndex, RoadBaseAI.TrafficLightState vehicleState, RoadBaseAI.TrafficLightState pedestrianState)
        {
            ushort nodeId = SelectNodeId(nodeIndex);
            ushort segId  = NetManager.instance.m_nodes.m_buffer[nodeId].GetSegment(segIndex);

            CustomSegmentLights csls = CustomTrafficLights.GetSegmentLights(nodeId, segId);

            if (csls != null)
            {
                foreach (ExtVehicleType evt in csls.VehicleTypes)
                {
                    CustomSegmentLight csl = csls.GetCustomLight(evt);
                    if (csl != null)
                    {
                        RoadBaseAI.TrafficLightState currentState = csl.GetVisualLightState();
                        if (currentState != vehicleState)
                        {
                            if (vehicleState != csl.GetLightMain())
                            {
                                csl.ChangeLightMain();
                            }
                            if (vehicleState != csl.GetLightLeft())
                            {
                                csl.ChangeLightLeft();
                            }
                            if (vehicleState != csl.GetLightRight())
                            {
                                csl.ChangeLightRight();
                            }
                        }
                    }
                }
            }
            else
            {
                return(false);
            }

            return(true);
        }
Beispiel #4
0
        public override void OnToolGUI(Event e)
        {
            var hoveredSegment = false;

            if (SelectedNodeId != 0)
            {
                CustomSegmentLightsManager    customTrafficLightsManager = CustomSegmentLightsManager.Instance;
                TrafficLightSimulationManager tlsMan = TrafficLightSimulationManager.Instance;

                var nodeSimulation = tlsMan.GetNodeSimulation(SelectedNodeId);
                if (nodeSimulation == null || !nodeSimulation.IsManualLight())
                {
                    return;
                }
                nodeSimulation.housekeeping();

                /*if (Singleton<NetManager>.instance.m_nodes.m_buffer[SelectedNode].CountSegments() == 2) {
                 *      _guiManualTrafficLightsCrosswalk(ref Singleton<NetManager>.instance.m_nodes.m_buffer[SelectedNode]);
                 *      return;
                 * }*/// TODO check

                NodeGeometry nodeGeometry = NodeGeometry.Get(SelectedNodeId);
                foreach (SegmentEndGeometry end in nodeGeometry.SegmentEndGeometries)
                {
                    if (end == null)
                    {
                        continue;
                    }

                    var position      = CalculateNodePositionForSegment(Singleton <NetManager> .instance.m_nodes.m_buffer[SelectedNodeId], ref Singleton <NetManager> .instance.m_segments.m_buffer[end.SegmentId]);
                    var segmentLights = customTrafficLightsManager.GetSegmentLights(end.SegmentId, end.StartNode, false);
                    if (segmentLights == null)
                    {
                        continue;
                    }

                    var screenPos = Camera.main.WorldToScreenPoint(position);
                    screenPos.y = Screen.height - screenPos.y;

                    if (screenPos.z < 0)
                    {
                        continue;
                    }

                    var diff = position - Camera.main.transform.position;
                    var zoom = 1.0f / diff.magnitude * 100f;

                    // original / 2.5
                    var lightWidth  = 41f * zoom;
                    var lightHeight = 97f * zoom;

                    var pedestrianWidth  = 36f * zoom;
                    var pedestrianHeight = 61f * zoom;

                    // SWITCH MODE BUTTON
                    var modeWidth  = 41f * zoom;
                    var modeHeight = 38f * zoom;

                    var guiColor = GUI.color;

                    if (segmentLights.PedestrianLightState != null)
                    {
                        // pedestrian light

                        // SWITCH MANUAL PEDESTRIAN LIGHT BUTTON
                        hoveredSegment = RenderManualPedestrianLightSwitch(zoom, end.SegmentId, screenPos, lightWidth, segmentLights, hoveredSegment);

                        // SWITCH PEDESTRIAN LIGHT
                        guiColor.a = _hoveredButton[0] == end.SegmentId && _hoveredButton[1] == 2 && segmentLights.ManualPedestrianMode ? 0.92f : 0.6f;
                        GUI.color  = guiColor;

                        var myRect3 = new Rect(screenPos.x - pedestrianWidth / 2 - lightWidth + 5f * zoom, screenPos.y - pedestrianHeight / 2 + 22f * zoom, pedestrianWidth, pedestrianHeight);

                        switch (segmentLights.PedestrianLightState)
                        {
                        case RoadBaseAI.TrafficLightState.Green:
                            GUI.DrawTexture(myRect3, TrafficLightToolTextureResources.PedestrianGreenLightTexture2D);
                            break;

                        case RoadBaseAI.TrafficLightState.Red:
                        default:
                            GUI.DrawTexture(myRect3, TrafficLightToolTextureResources.PedestrianRedLightTexture2D);
                            break;
                        }

                        hoveredSegment = IsPedestrianLightHovered(myRect3, end.SegmentId, hoveredSegment, segmentLights);
                    }

                    int lightOffset = -1;
                    foreach (ExtVehicleType vehicleType in segmentLights.VehicleTypes)
                    {
                        ++lightOffset;
                        CustomSegmentLight segmentLight = segmentLights.GetCustomLight(vehicleType);

                        Vector3 offsetScreenPos = screenPos;
                        offsetScreenPos.y -= (lightHeight + 10f * zoom) * lightOffset;

                        SetAlpha(end.SegmentId, -1);

                        var myRect1 = new Rect(offsetScreenPos.x - modeWidth / 2, offsetScreenPos.y - modeHeight / 2 + modeHeight - 7f * zoom, modeWidth, modeHeight);

                        GUI.DrawTexture(myRect1, TrafficLightToolTextureResources.LightModeTexture2D);

                        hoveredSegment = GetHoveredSegment(myRect1, end.SegmentId, hoveredSegment, segmentLight);

                        // COUNTER
                        hoveredSegment = RenderCounter(end.SegmentId, offsetScreenPos, modeWidth, modeHeight, zoom, segmentLights, hoveredSegment);

                        if (lightOffset > 0)
                        {
                            // Info sign
                            var infoWidth  = 56.125f * zoom;
                            var infoHeight = 51.375f * zoom;

                            int numInfos = 0;
                            for (int k = 0; k < TrafficManagerTool.InfoSignsToDisplay.Length; ++k)
                            {
                                if ((TrafficManagerTool.InfoSignsToDisplay[k] & vehicleType) == ExtVehicleType.None)
                                {
                                    continue;
                                }
                                var infoRect = new Rect(offsetScreenPos.x + modeWidth / 2f + 7f * zoom * (float)(numInfos + 1) + infoWidth * (float)numInfos, offsetScreenPos.y - infoHeight / 2f, infoWidth, infoHeight);
                                guiColor.a = 0.6f;
                                GUI.DrawTexture(infoRect, TrafficLightToolTextureResources.VehicleInfoSignTextures[TrafficManagerTool.InfoSignsToDisplay[k]]);
                                ++numInfos;
                            }
                        }

                        if (end.OutgoingOneWay)
                        {
                            continue;
                        }

                        var hasLeftSegment    = end.NumLeftSegments > 0;
                        var hasForwardSegment = end.NumStraightSegments > 0;
                        var hasRightSegment   = end.NumRightSegments > 0;

                        switch (segmentLight.CurrentMode)
                        {
                        case CustomSegmentLight.Mode.Simple:
                            hoveredSegment = SimpleManualSegmentLightMode(end.SegmentId, offsetScreenPos, lightWidth, pedestrianWidth, zoom, lightHeight, segmentLight, hoveredSegment);
                            break;

                        case CustomSegmentLight.Mode.SingleLeft:
                            hoveredSegment = LeftForwardRManualSegmentLightMode(hasLeftSegment, end.SegmentId, offsetScreenPos, lightWidth, pedestrianWidth, zoom, lightHeight, segmentLight, hoveredSegment, hasForwardSegment, hasRightSegment);
                            break;

                        case CustomSegmentLight.Mode.SingleRight:
                            hoveredSegment = RightForwardLSegmentLightMode(end.SegmentId, offsetScreenPos, lightWidth, pedestrianWidth, zoom, lightHeight, hasForwardSegment, hasLeftSegment, segmentLight, hasRightSegment, hoveredSegment);
                            break;

                        default:
                            // left arrow light
                            if (hasLeftSegment)
                            {
                                hoveredSegment = LeftArrowLightMode(end.SegmentId, lightWidth, hasRightSegment, hasForwardSegment, offsetScreenPos, pedestrianWidth, zoom, lightHeight, segmentLight, hoveredSegment);
                            }

                            // forward arrow light
                            if (hasForwardSegment)
                            {
                                hoveredSegment = ForwardArrowLightMode(end.SegmentId, lightWidth, hasRightSegment, offsetScreenPos, pedestrianWidth, zoom, lightHeight, segmentLight, hoveredSegment);
                            }

                            // right arrow light
                            if (hasRightSegment)
                            {
                                hoveredSegment = RightArrowLightMode(end.SegmentId, offsetScreenPos, lightWidth, pedestrianWidth, zoom, lightHeight, segmentLight, hoveredSegment);
                            }
                            break;
                        }
                    }
                }
            }

            if (hoveredSegment)
            {
                return;
            }
            _hoveredButton[0] = 0;
            _hoveredButton[1] = 0;
        }
Beispiel #5
0
        private bool ForwardArrowLightMode(int segmentId, float lightWidth, bool hasRightSegment,
                                           Vector3 screenPos, float pedestrianWidth, float zoom, float lightHeight, CustomSegmentLight segmentDict,
                                           bool hoveredSegment)
        {
            SetAlpha(segmentId, 4);

            var offsetLight = lightWidth;

            if (hasRightSegment)
            {
                offsetLight += lightWidth;
            }

            var myRect6 =
                new Rect(screenPos.x - lightWidth / 2 - offsetLight - pedestrianWidth + 5f * zoom,
                         screenPos.y - lightHeight / 2, lightWidth, lightHeight);

            switch (segmentDict.LightMain)
            {
            case RoadBaseAI.TrafficLightState.Green:
                GUI.DrawTexture(myRect6, TrafficLightToolTextureResources.GreenLightStraightTexture2D);
                break;

            case RoadBaseAI.TrafficLightState.Red:
                GUI.DrawTexture(myRect6, TrafficLightToolTextureResources.RedLightStraightTexture2D);
                break;
            }

            if (!myRect6.Contains(Event.current.mousePosition))
            {
                return(hoveredSegment);
            }

            _hoveredButton[0] = segmentId;
            _hoveredButton[1] = 4;

            if (!MainTool.CheckClicked())
            {
                return(true);
            }
            segmentDict.ChangeMainLight();
            return(true);
        }
Beispiel #6
0
        private bool RightForwardLSegmentLightMode(int segmentId, Vector3 screenPos, float lightWidth, float pedestrianWidth,
                                                   float zoom, float lightHeight, bool hasForwardSegment, bool hasLeftSegment, CustomSegmentLight segmentDict,
                                                   bool hasRightSegment, bool hoveredSegment)
        {
            SetAlpha(segmentId, 3);

            var myRect4 = new Rect(screenPos.x - lightWidth / 2 - lightWidth * 2 - pedestrianWidth + 5f * zoom,
                                   screenPos.y - lightHeight / 2, lightWidth, lightHeight);

            if (hasForwardSegment && hasLeftSegment)
            {
                switch (segmentDict.LightLeft)
                {
                case RoadBaseAI.TrafficLightState.Green:
                    GUI.DrawTexture(myRect4, TrafficLightToolTextureResources.GreenLightForwardLeftTexture2D);
                    break;

                case RoadBaseAI.TrafficLightState.Red:
                    GUI.DrawTexture(myRect4, TrafficLightToolTextureResources.RedLightForwardLeftTexture2D);
                    break;
                }
            }
            else if (!hasLeftSegment)
            {
                if (!hasRightSegment)
                {
                    myRect4 = new Rect(screenPos.x - lightWidth / 2 - lightWidth - pedestrianWidth + 5f * zoom,
                                       screenPos.y - lightHeight / 2, lightWidth, lightHeight);
                }

                switch (segmentDict.LightMain)
                {
                case RoadBaseAI.TrafficLightState.Green:
                    GUI.DrawTexture(myRect4, TrafficLightToolTextureResources.GreenLightStraightTexture2D);
                    break;

                case RoadBaseAI.TrafficLightState.Red:
                    GUI.DrawTexture(myRect4, TrafficLightToolTextureResources.RedLightStraightTexture2D);
                    break;
                }
            }
            else
            {
                if (!hasRightSegment)
                {
                    myRect4 = new Rect(screenPos.x - lightWidth / 2 - lightWidth - pedestrianWidth + 5f * zoom,
                                       screenPos.y - lightHeight / 2, lightWidth, lightHeight);
                }

                switch (segmentDict.LightMain)
                {
                case RoadBaseAI.TrafficLightState.Green:
                    GUI.DrawTexture(myRect4, TrafficLightToolTextureResources.GreenLightLeftTexture2D);
                    break;

                case RoadBaseAI.TrafficLightState.Red:
                    GUI.DrawTexture(myRect4, TrafficLightToolTextureResources.RedLightLeftTexture2D);
                    break;
                }
            }


            if (myRect4.Contains(Event.current.mousePosition))
            {
                _hoveredButton[0] = segmentId;
                _hoveredButton[1] = 3;
                hoveredSegment    = true;

                if (MainTool.CheckClicked())
                {
                    segmentDict.ChangeMainLight();
                }
            }

            var guiColor = GUI.color;

            // right arrow light
            if (hasRightSegment)
            {
                guiColor.a = _hoveredButton[0] == segmentId && _hoveredButton[1] == 4 ? 0.92f : 0.6f;
            }

            GUI.color = guiColor;

            var myRect5 =
                new Rect(screenPos.x - lightWidth / 2 - lightWidth - pedestrianWidth + 5f * zoom,
                         screenPos.y - lightHeight / 2, lightWidth, lightHeight);

            switch (segmentDict.LightRight)
            {
            case RoadBaseAI.TrafficLightState.Green:
                GUI.DrawTexture(myRect5, TrafficLightToolTextureResources.GreenLightRightTexture2D);
                break;

            case RoadBaseAI.TrafficLightState.Red:
                GUI.DrawTexture(myRect5, TrafficLightToolTextureResources.RedLightRightTexture2D);
                break;
            }


            if (!myRect5.Contains(Event.current.mousePosition))
            {
                return(hoveredSegment);
            }

            _hoveredButton[0] = segmentId;
            _hoveredButton[1] = 4;

            if (!MainTool.CheckClicked())
            {
                return(true);
            }
            segmentDict.ChangeRightLight();
            return(true);
        }
Beispiel #7
0
        private bool GetHoveredSegment(Rect myRect1, int segmentId, bool hoveredSegment, CustomSegmentLight segmentDict)
        {
            if (!myRect1.Contains(Event.current.mousePosition))
            {
                return(hoveredSegment);
            }

            //Log.Message("mouse in myRect1");
            _hoveredButton[0] = segmentId;
            _hoveredButton[1] = -1;

            if (!MainTool.CheckClicked())
            {
                return(true);
            }
            segmentDict.ChangeMode();
            return(true);
        }
        private static void SaveTimedTrafficLight(ushort i, Configuration configuration)
        {
            try {
                TrafficLightSimulation sim = TrafficLightSimulation.GetNodeSimulation(i);
                if (sim == null || !sim.IsTimedLight())
                {
                    return;
                }

                Log._Debug($"Going to save timed light at node {i}.");

                var timedNode = sim.TimedLight;
                timedNode.handleNewSegments();

                Configuration.TimedTrafficLights cnfTimedLights = new Configuration.TimedTrafficLights();
                configuration.TimedLights.Add(cnfTimedLights);

                cnfTimedLights.nodeId     = timedNode.NodeId;
                cnfTimedLights.nodeGroup  = timedNode.NodeGroup;
                cnfTimedLights.started    = timedNode.IsStarted();
                cnfTimedLights.timedSteps = new List <Configuration.TimedTrafficLightsStep>();

                for (var j = 0; j < timedNode.NumSteps(); j++)
                {
                    Log._Debug($"Saving timed light step {j} at node {i}.");
                    TimedTrafficLightsStep timedStep = timedNode.Steps[j];
                    Configuration.TimedTrafficLightsStep cnfTimedStep = new Configuration.TimedTrafficLightsStep();
                    cnfTimedLights.timedSteps.Add(cnfTimedStep);

                    cnfTimedStep.minTime         = timedStep.minTime;
                    cnfTimedStep.maxTime         = timedStep.maxTime;
                    cnfTimedStep.waitFlowBalance = timedStep.waitFlowBalance;
                    cnfTimedStep.segmentLights   = new Dictionary <ushort, Configuration.CustomSegmentLights>();
                    foreach (KeyValuePair <ushort, CustomSegmentLights> e in timedStep.segmentLights)
                    {
                        Log._Debug($"Saving timed light step {j}, segment {e.Key} at node {i}.");

                        CustomSegmentLights segLights = e.Value;
                        Configuration.CustomSegmentLights cnfSegLights = new Configuration.CustomSegmentLights();
                        cnfTimedStep.segmentLights.Add(e.Key, cnfSegLights);

                        cnfSegLights.nodeId               = segLights.NodeId;
                        cnfSegLights.segmentId            = segLights.SegmentId;
                        cnfSegLights.customLights         = new Dictionary <ExtVehicleType, Configuration.CustomSegmentLight>();
                        cnfSegLights.pedestrianLightState = segLights.PedestrianLightState;
                        cnfSegLights.manualPedestrianMode = segLights.ManualPedestrianMode;

                        Log._Debug($"Saving pedestrian light @ seg. {e.Key}, step {j}: {cnfSegLights.pedestrianLightState} {cnfSegLights.manualPedestrianMode}");

                        foreach (KeyValuePair <Traffic.ExtVehicleType, CustomSegmentLight> e2 in segLights.CustomLights)
                        {
                            Log._Debug($"Saving timed light step {j}, segment {e.Key}, vehicleType {e2.Key} at node {i}.");

                            CustomSegmentLight segLight = e2.Value;
                            Configuration.CustomSegmentLight cnfSegLight = new Configuration.CustomSegmentLight();
                            cnfSegLights.customLights.Add(e2.Key, cnfSegLight);

                            cnfSegLight.nodeId      = segLight.NodeId;
                            cnfSegLight.segmentId   = segLight.SegmentId;
                            cnfSegLight.currentMode = (int)segLight.CurrentMode;
                            cnfSegLight.leftLight   = segLight.LightLeft;
                            cnfSegLight.mainLight   = segLight.LightMain;
                            cnfSegLight.rightLight  = segLight.LightRight;
                        }
                    }
                }
            } catch (Exception e) {
                Log.Error($"Error adding TimedTrafficLights to save {e.Message}");
            }
        }
        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!");
            }
        }
        private static void LoadDataState(out bool error)
        {
            error = false;

            Log.Info("Loading State from Config");
            if (_configuration == null)
            {
                Log.Warning("Configuration NULL, Couldn't load save data. Possibly a new game?");
                return;
            }

            TrafficPriorityManager prioMan = TrafficPriorityManager.Instance();

            // 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 (!NetUtil.IsNodeValid((ushort)segment[0]))
                        {
#if DEBUG
                            if (debug)
                            {
                                Log._Debug($"Loading priority segment: node {segment[0]} is invalid");
                            }
#endif
                            continue;
                        }
                        if (!NetUtil.IsSegmentValid((ushort)segment[1]))
                        {
#if DEBUG
                            if (debug)
                            {
                                Log._Debug($"Loading priority segment: segment {segment[1]} @ node {segment[0]} is invalid");
                            }
#endif
                            continue;
                        }
                        if (prioMan.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
                            prioMan.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
                        prioMan.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());
                        error = true;
                    }
                }
            }
            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.Instance().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());
                        error = true;
                    }
                }
            }
            else
            {
                Log.Warning("Vehicle restrctions structure undefined!");
            }

            NetManager netManager = Singleton <NetManager> .instance;
            TrafficLightSimulationManager tlsMan = TrafficLightSimulationManager.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 (!NetUtil.IsNodeValid(cnfTimedLights.nodeId))
                        {
                            continue;
                        }
                        Flags.setNodeTrafficLight(cnfTimedLights.nodeId, true);

                        Log._Debug($"Adding Timed Node at node {cnfTimedLights.nodeId}");

                        TrafficLightSimulation sim = tlsMan.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());
                        error = true;
                    }
                }
            }
            else
            {
                Log.Warning("Timed traffic lights data structure undefined!");
            }

            if (_configuration.NodeTrafficLights != null)
            {
                var trafficLightDefs = _configuration.NodeTrafficLights.Split(',');

                Log.Info($"Loading junction traffic light data");

                // new method
                foreach (var split in trafficLightDefs.Select(def => def.Split(':')).Where(split => split.Length > 1))
                {
                    try {
                        Log._Debug($"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.Error($"Error setting the NodeTrafficLights: " + e.ToString());
                        error = true;
                    }
                }
            }
            else
            {
                Log.Warning("Junction traffic lights data structure undefined!");
            }

            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._Debug($"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 (!NetUtil.IsLaneValid(laneId))
                            {
                                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.ToString()}");
                            error = true;
                        }
                    }
                }
            }
            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}");
                        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.Error("Error loading data from lane connection: " + e.ToString());
                        error = true;
                    }
                }
            }
            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());
                        error = true;
                    }
                }
            }
            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 (!NetUtil.IsSegmentValid(segNodeConf.segmentId))
                        {
                            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());
                        error = true;
                    }
                }
            }
            else
            {
                Log.Warning("Segment-at-node structure undefined!");
            }
        }
Beispiel #11
0
        private static void GetCustomTrafficLightState(ushort vehicleId, ref Vehicle vehicleData, ushort nodeId, ushort fromSegmentId, ushort toSegmentId, out RoadBaseAI.TrafficLightState vehicleLightState, out RoadBaseAI.TrafficLightState pedestrianLightState, TrafficLightSimulation nodeSim = null)
        {
            if (nodeSim == null)
            {
                nodeSim = TrafficLightSimulation.GetNodeSimulation(nodeId);
                if (nodeSim == null)
                {
                    Log.Error($"GetCustomTrafficLightState: node traffic light simulation not found at node {nodeId}! Vehicle {vehicleId} comes from segment {fromSegmentId} and goes to node {nodeId}");
                    throw new ApplicationException($"GetCustomTrafficLightState: node traffic light simulation not found at node {nodeId}! Vehicle {vehicleId} comes from segment {fromSegmentId} and goes to node {nodeId}");
                }
            }

            // get vehicle position

            /*VehiclePosition vehiclePos = TrafficPriority.GetVehiclePosition(vehicleId);
             * if (!vehiclePos.Valid || vehiclePos.FromSegment != fromSegmentId || vehiclePos.ToNode != nodeId) {
             *      Log._Debug($"GetTrafficLightState: Recalculating position for vehicle {vehicleId}! FromSegment={vehiclePos.FromSegment} Valid={vehiclePos.Valid}");
             *      try {
             *              HandleVehicle(vehicleId, ref Singleton<VehicleManager>.instance.m_vehicles.m_buffer[vehicleId], false, false);
             *      } catch (Exception e) {
             *              Log.Error("VehicleAI GetTrafficLightState Error: " + e.ToString());
             *      }
             * }
             *
             * if (!vehiclePos.Valid || vehiclePos.FromSegment != fromSegmentId || vehiclePos.ToNode != nodeId) {
             *      Log.Warning($"GetTrafficLightState: Vehicle {vehicleId} is not moving at segment {fromSegmentId} to node {nodeId}! FromSegment={vehiclePos.FromSegment} ToNode={vehiclePos.ToNode} Valid={vehiclePos.Valid}");
             *      vehicleLightState = RoadBaseAI.TrafficLightState.Red;
             *      pedestrianLightState = RoadBaseAI.TrafficLightState.Red;
             *      return;
             * }*/

            // get vehicle type
            ExtVehicleType?vehicleType = CustomVehicleAI.DetermineVehicleTypeFromVehicle(vehicleId, ref vehicleData);

            if (vehicleData.Info.m_vehicleType == VehicleInfo.VehicleType.Tram && vehicleType != ExtVehicleType.Tram)
            {
                Log.Warning($"vehicleType={vehicleType} ({(int)vehicleType}) for Tram");
            }
            //Log._Debug($"GetCustomTrafficLightState: Vehicle {vehicleId} is a {vehicleType}");
            if (vehicleType == null)
            {
                Log.Warning($"GetTrafficLightState: Could not determine vehicle type of vehicle {vehicleId}!");
                vehicleLightState    = RoadBaseAI.TrafficLightState.Red;
                pedestrianLightState = RoadBaseAI.TrafficLightState.Red;
                return;
            }

            // get responsible traffic light
            CustomSegmentLights lights = CustomTrafficLights.GetSegmentLights(nodeId, fromSegmentId);
            CustomSegmentLight  light  = lights == null ? null : lights.GetCustomLight((ExtVehicleType)vehicleType);

            if (lights == null || light == null)
            {
                Log.Warning($"GetTrafficLightState: No custom light for vehicleType {vehicleType} @ node {nodeId}, segment {fromSegmentId} found. lights null? {lights == null} light null? {light == null}");
                vehicleLightState    = RoadBaseAI.TrafficLightState.Red;
                pedestrianLightState = RoadBaseAI.TrafficLightState.Red;
                return;
            }

            SegmentGeometry geometry = CustomRoadAI.GetSegmentGeometry(fromSegmentId);

            // get traffic light state from responsible traffic light
            if (geometry.IsLeftSegment(toSegmentId, nodeId))
            {
                vehicleLightState = light.GetLightLeft();
            }
            else if (geometry.IsRightSegment(toSegmentId, nodeId))
            {
                vehicleLightState = light.GetLightRight();
            }
            else
            {
                vehicleLightState = light.GetLightMain();
            }

            // get traffic lights state for pedestrians
            pedestrianLightState = (lights.PedestrianLightState != null) ? (RoadBaseAI.TrafficLightState)lights.PedestrianLightState : RoadBaseAI.TrafficLightState.Red;
        }
        public List <Configuration.TimedTrafficLights> SaveData(ref bool success)
        {
            List <Configuration.TimedTrafficLights> ret = new List <Configuration.TimedTrafficLights>();

            for (ushort nodeId = 0; nodeId < NetManager.MAX_NODE_COUNT; ++nodeId)
            {
                try {
                    TrafficLightSimulation sim = GetNodeSimulation(nodeId);
                    if (sim == null || !sim.IsTimedLight())
                    {
                        continue;
                    }

                    Log._Debug($"Going to save timed light at node {nodeId}.");

                    var timedNode = sim.TimedLight;
                    timedNode.handleNewSegments();

                    Configuration.TimedTrafficLights cnfTimedLights = new Configuration.TimedTrafficLights();
                    ret.Add(cnfTimedLights);

                    cnfTimedLights.nodeId     = timedNode.NodeId;
                    cnfTimedLights.nodeGroup  = timedNode.NodeGroup;
                    cnfTimedLights.started    = timedNode.IsStarted();
                    cnfTimedLights.timedSteps = new List <Configuration.TimedTrafficLightsStep>();

                    for (var j = 0; j < timedNode.NumSteps(); j++)
                    {
                        Log._Debug($"Saving timed light step {j} at node {nodeId}.");
                        TimedTrafficLightsStep timedStep = timedNode.Steps[j];
                        Configuration.TimedTrafficLightsStep cnfTimedStep = new Configuration.TimedTrafficLightsStep();
                        cnfTimedLights.timedSteps.Add(cnfTimedStep);

                        cnfTimedStep.minTime         = timedStep.minTime;
                        cnfTimedStep.maxTime         = timedStep.maxTime;
                        cnfTimedStep.waitFlowBalance = timedStep.waitFlowBalance;
                        cnfTimedStep.segmentLights   = new Dictionary <ushort, Configuration.CustomSegmentLights>();
                        foreach (KeyValuePair <ushort, CustomSegmentLights> e in timedStep.segmentLights)
                        {
                            Log._Debug($"Saving timed light step {j}, segment {e.Key} at node {nodeId}.");

                            CustomSegmentLights segLights = e.Value;
                            Configuration.CustomSegmentLights cnfSegLights = new Configuration.CustomSegmentLights();
                            cnfTimedStep.segmentLights.Add(e.Key, cnfSegLights);

                            cnfSegLights.nodeId               = segLights.NodeId;
                            cnfSegLights.segmentId            = segLights.SegmentId;
                            cnfSegLights.customLights         = new Dictionary <ExtVehicleType, Configuration.CustomSegmentLight>();
                            cnfSegLights.pedestrianLightState = segLights.PedestrianLightState;
                            cnfSegLights.manualPedestrianMode = segLights.ManualPedestrianMode;

                            Log._Debug($"Saving pedestrian light @ seg. {e.Key}, step {j}: {cnfSegLights.pedestrianLightState} {cnfSegLights.manualPedestrianMode}");

                            foreach (KeyValuePair <ExtVehicleType, CustomSegmentLight> e2 in segLights.CustomLights)
                            {
                                Log._Debug($"Saving timed light step {j}, segment {e.Key}, vehicleType {e2.Key} at node {nodeId}.");

                                CustomSegmentLight segLight = e2.Value;
                                Configuration.CustomSegmentLight cnfSegLight = new Configuration.CustomSegmentLight();
                                cnfSegLights.customLights.Add(e2.Key, cnfSegLight);

                                cnfSegLight.nodeId      = segLight.NodeId;
                                cnfSegLight.segmentId   = segLight.SegmentId;
                                cnfSegLight.currentMode = (int)segLight.CurrentMode;
                                cnfSegLight.leftLight   = segLight.LightLeft;
                                cnfSegLight.mainLight   = segLight.LightMain;
                                cnfSegLight.rightLight  = segLight.LightRight;
                            }
                        }
                    }
                } catch (Exception e) {
                    Log.Error($"Exception occurred while saving timed traffic light @ {nodeId}: {e.ToString()}");
                    success = false;
                }
            }
            return(ret);
        }
        public bool LoadData(List <Configuration.TimedTrafficLights> data)
        {
            bool success = true;

            Log.Info($"Loading {data.Count} timed traffic lights (new method)");

            TrafficLightManager tlm = TrafficLightManager.Instance;

            HashSet <ushort> nodesWithSimulation = new HashSet <ushort>();

            foreach (Configuration.TimedTrafficLights cnfTimedLights in data)
            {
                nodesWithSimulation.Add(cnfTimedLights.nodeId);
            }

            Dictionary <ushort, ushort>         masterNodeIdBySlaveNodeId = new Dictionary <ushort, ushort>();
            Dictionary <ushort, List <ushort> > nodeGroupByMasterNodeId   = new Dictionary <ushort, List <ushort> >();

            foreach (Configuration.TimedTrafficLights cnfTimedLights in data)
            {
                try {
                    // TODO most of this should not be necessary at all if the classes around TimedTrafficLights class were properly designed
                    List <ushort> currentNodeGroup = cnfTimedLights.nodeGroup.Distinct().ToList();                    // enforce uniqueness of node ids
                    if (!currentNodeGroup.Contains(cnfTimedLights.nodeId))
                    {
                        currentNodeGroup.Add(cnfTimedLights.nodeId);
                    }
                    // remove any nodes that are not configured to have a simulation
                    currentNodeGroup = new List <ushort>(currentNodeGroup.Intersect(nodesWithSimulation));

                    // remove invalid nodes from the group; find if any of the nodes in the group is already a master node
                    ushort masterNodeId     = 0;
                    int    foundMasterNodes = 0;
                    for (int i = 0; i < currentNodeGroup.Count;)
                    {
                        ushort nodeId = currentNodeGroup[i];
                        if (!NetUtil.IsNodeValid(currentNodeGroup[i]))
                        {
                            currentNodeGroup.RemoveAt(i);
                            continue;
                        }
                        else if (nodeGroupByMasterNodeId.ContainsKey(nodeId))
                        {
                            // this is a known master node
                            if (foundMasterNodes > 0)
                            {
                                // we already found another master node. ignore this node.
                                currentNodeGroup.RemoveAt(i);
                                continue;
                            }
                            // we found the first master node
                            masterNodeId = nodeId;
                            ++foundMasterNodes;
                        }
                        ++i;
                    }

                    if (masterNodeId == 0)
                    {
                        // no master node defined yet, set the first node as a master node
                        masterNodeId = currentNodeGroup[0];
                    }

                    // ensure the master node is the first node in the list (TimedTrafficLights depends on this at the moment...)
                    currentNodeGroup.Remove(masterNodeId);
                    currentNodeGroup.Insert(0, masterNodeId);

                    // update the saved node group and master-slave info
                    nodeGroupByMasterNodeId[masterNodeId] = currentNodeGroup;
                    foreach (ushort nodeId in currentNodeGroup)
                    {
                        masterNodeIdBySlaveNodeId[nodeId] = masterNodeId;
                    }
                } catch (Exception e) {
                    Log.Warning($"Error building timed traffic light group for TimedNode {cnfTimedLights.nodeId} (NodeGroup: {string.Join(", ", cnfTimedLights.nodeGroup.Select(x => x.ToString()).ToArray())}): " + e.ToString());
                    success = false;
                }
            }

            foreach (Configuration.TimedTrafficLights cnfTimedLights in data)
            {
                try {
                    if (!masterNodeIdBySlaveNodeId.ContainsKey(cnfTimedLights.nodeId))
                    {
                        continue;
                    }
                    ushort        masterNodeId = masterNodeIdBySlaveNodeId[cnfTimedLights.nodeId];
                    List <ushort> nodeGroup    = nodeGroupByMasterNodeId[masterNodeId];

                    Log._Debug($"Adding timed light at node {cnfTimedLights.nodeId}. NodeGroup: {string.Join(", ", nodeGroup.Select(x => x.ToString()).ToArray())}");

                    TrafficLightSimulation sim = AddNodeToSimulation(cnfTimedLights.nodeId);
                    sim.SetupTimedTrafficLight(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)
                        {
                            if (!NetUtil.IsSegmentValid(e.Key))
                            {
                                continue;
                            }

                            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.SetStates(cnfLight.mainLight, cnfLight.leftLight, cnfLight.rightLight, false);
                            }
                        }
                        ++j;
                    }
                } 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());
                    success = false;
                }
            }

            foreach (Configuration.TimedTrafficLights cnfTimedLights in data)
            {
                try {
                    TrafficLightSimulation sim = GetNodeSimulation(cnfTimedLights.nodeId);
                    if (sim == null || sim.TimedLight == null)
                    {
                        continue;
                    }

                    var timedNode = sim.TimedLight;

                    timedNode.housekeeping();
                    if (cnfTimedLights.started)
                    {
                        timedNode.Start();
                    }
                } catch (Exception e) {
                    Log.Warning($"Error starting timed light @ {cnfTimedLights.nodeId}: " + e.ToString());
                    success = false;
                }
            }

            return(success);
        }