Exemplo n.º 1
0
        private void RefreshCurrentRestrictedSegmentIds()
        {
            currentRestrictedSegmentIds.Clear();
            for (ushort segmentId = 1; segmentId < NetManager.MAX_SEGMENT_COUNT; ++segmentId)
            {
                if ((Singleton <NetManager> .instance.m_segments.m_buffer[segmentId].m_flags & NetSegment.Flags.Created) == NetSegment.Flags.None)
                {
                    continue;
                }

                if (VehicleRestrictionsManager.Instance().HasSegmentRestrictions(segmentId))
                {
                    currentRestrictedSegmentIds.Add(segmentId);
                }
            }
        }
Exemplo n.º 2
0
        private bool drawVehicleRestrictionHandles(ushort segmentId, bool viewOnly, out bool stateUpdated)
        {
            stateUpdated = false;
            if (!LoadingExtension.IsPathManagerCompatible)
            {
                return(false);
            }

            if (viewOnly && !Options.vehicleRestrictionsOverlay && TrafficManagerTool.GetToolMode() != ToolMode.VehicleRestrictions)
            {
                return(false);
            }

            Vector3 center = Singleton <NetManager> .instance.m_segments.m_buffer[segmentId].m_bounds.center;

            var screenPos = Camera.main.WorldToScreenPoint(center);

            screenPos.y = Screen.height - screenPos.y;
            if (screenPos.z < 0)
            {
                return(false);
            }
            var camPos = Singleton <SimulationManager> .instance.m_simulationView.m_position;
            var diff   = center - camPos;

            if (diff.magnitude > TrafficManagerTool.PriorityCloseLod)
            {
                return(false);                // do not draw if too distant
            }
            int numDirections;
            int numLanes = TrafficManagerTool.GetSegmentNumVehicleLanes(segmentId, null, out numDirections);

            // draw vehicle restrictions over each lane
            NetInfo segmentInfo = Singleton <NetManager> .instance.m_segments.m_buffer[segmentId].Info;
            Vector3 yu          = (Singleton <NetManager> .instance.m_segments.m_buffer[segmentId].m_endDirection - Singleton <NetManager> .instance.m_segments.m_buffer[segmentId].m_startDirection).normalized;

            if ((Singleton <NetManager> .instance.m_segments.m_buffer[segmentId].m_flags & NetSegment.Flags.Invert) == NetSegment.Flags.None)
            {
                yu = -yu;
            }
            Vector3   xu = Vector3.Cross(yu, new Vector3(0, 1f, 0)).normalized;
            float     f  = viewOnly ? 4f : 7f;        // reserved sign size in game coordinates
            ItemClass connectionClass = segmentInfo.GetConnectionClass();
            int       maxNumSigns     = 0;

            if (connectionClass.m_service == ItemClass.Service.Road)
            {
                maxNumSigns = roadVehicleTypes.Length;
            }
            else if (connectionClass.m_service == ItemClass.Service.PublicTransport && connectionClass.m_subService == ItemClass.SubService.PublicTransportTrain)
            {
                maxNumSigns = railVehicleTypes.Length;
            }
            //Vector3 zero = center - 0.5f * (float)(numLanes + numDirections - 1) * f * (xu + yu); // "bottom left"
            Vector3 zero = center - 0.5f * (float)(numLanes - 1 + numDirections - 1) * f * xu - 0.5f * (float)maxNumSigns * f * yu;             // "bottom left"

            /*if (!viewOnly)
             *      Log._Debug($"xu: {xu.ToString()} yu: {yu.ToString()} center: {center.ToString()} zero: {zero.ToString()} numLanes: {numLanes} numDirections: {numDirections}");*/

            uint                        x               = 0;
            var                         guiColor        = GUI.color;
            List <object[]>             sortedLanes     = TrafficManagerTool.GetSortedVehicleLanes(segmentId, segmentInfo, null);
            bool                        hovered         = false;
            HashSet <NetInfo.Direction> directions      = new HashSet <NetInfo.Direction>();
            int                         sortedLaneIndex = -1;

            foreach (object[] laneData in sortedLanes)
            {
                ++sortedLaneIndex;
                uint laneId    = (uint)laneData[0];
                uint laneIndex = (uint)laneData[2];

                NetInfo.Lane laneInfo = segmentInfo.m_lanes[laneIndex];
                if (!directions.Contains(laneInfo.m_direction))
                {
                    if (directions.Count > 0)
                    {
                        ++x;                         // space between different directions
                    }
                    directions.Add(laneInfo.m_direction);
                }

                ExtVehicleType[] possibleVehicleTypes = null;
                if (VehicleRestrictionsManager.Instance().IsRoadLane(laneInfo))
                {
                    possibleVehicleTypes = roadVehicleTypes;
                }
                else if (VehicleRestrictionsManager.Instance().IsRailLane(laneInfo))
                {
                    possibleVehicleTypes = railVehicleTypes;
                }
                else
                {
                    ++x;
                    continue;
                }

                ExtVehicleType allowedTypes = VehicleRestrictionsManager.Instance().GetAllowedVehicleTypes(segmentId, segmentInfo, laneIndex, laneInfo);

                uint y = 0;
#if DEBUGx
                Vector3 labelCenter = zero + f * (float)x * xu + f * (float)y * yu;                 // in game coordinates

                var labelScreenPos = Camera.main.WorldToScreenPoint(labelCenter);
                labelScreenPos.y = Screen.height - labelScreenPos.y;
                diff             = labelCenter - camPos;

                var labelZoom = 1.0f / diff.magnitude * 100f;
                _counterStyle.fontSize         = (int)(11f * labelZoom);
                _counterStyle.normal.textColor = new Color(1f, 1f, 0f);

                string  labelStr  = $"Idx {laneIndex}";
                Vector2 dim       = _counterStyle.CalcSize(new GUIContent(labelStr));
                Rect    labelRect = new Rect(labelScreenPos.x - dim.x / 2f, labelScreenPos.y, dim.x, dim.y);
                GUI.Label(labelRect, labelStr, _counterStyle);

                ++y;
#endif
                foreach (ExtVehicleType vehicleType in possibleVehicleTypes)
                {
                    bool allowed = VehicleRestrictionsManager.Instance().IsAllowed(allowedTypes, vehicleType);
                    if (allowed && viewOnly)
                    {
                        continue;                         // do not draw allowed vehicles in view-only mode
                    }
                    bool hoveredHandle;
                    DrawRestrictionsSign(viewOnly, camPos, out diff, xu, yu, f, zero, x, y, ref guiColor, TrafficLightToolTextureResources.VehicleRestrictionTextures[vehicleType][allowed], out hoveredHandle);
                    if (hoveredHandle)
                    {
                        hovered = true;
                    }

                    if (hoveredHandle && MainTool.CheckClicked())
                    {
                        // toggle vehicle restrictions
                        //Log._Debug($"Setting vehicle restrictions of segment {segmentId}, lane idx {laneIndex}, {vehicleType.ToString()} to {!allowed}");
                        VehicleRestrictionsManager.Instance().ToggleAllowedType(segmentId, segmentInfo, laneIndex, laneId, laneInfo, vehicleType, !allowed);
                        stateUpdated = true;

                        // TODO use SegmentTraverser
                        if (Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift))
                        {
                            ApplyRestrictionsToAllSegments(sortedLaneIndex);
                        }
                    }

                    ++y;
                }

                ++x;
            }

            guiColor.a = 1f;
            GUI.color  = guiColor;

            return(hovered);
        }
Exemplo n.º 3
0
        private void ApplyRestrictionsToAllSegments(int?sortedLaneIndex = null)
        {
            NetInfo         selectedSegmentInfo = Singleton <NetManager> .instance.m_segments.m_buffer[SelectedSegmentId].Info;
            List <object[]> selectedSortedLanes = TrafficManagerTool.GetSortedVehicleLanes(SelectedSegmentId, selectedSegmentInfo, null);

            LinkedList <ushort> nodesToProcess    = new LinkedList <ushort>();
            HashSet <ushort>    processedNodes    = new HashSet <ushort>();
            HashSet <ushort>    processedSegments = new HashSet <ushort>();

            processedSegments.Add(SelectedSegmentId);

            ushort selectedStartNodeId = Singleton <NetManager> .instance.m_segments.m_buffer[SelectedSegmentId].m_startNode;
            ushort selectedEndNodeId   = Singleton <NetManager> .instance.m_segments.m_buffer[SelectedSegmentId].m_endNode;

            if (selectedStartNodeId != 0)
            {
                nodesToProcess.AddFirst(selectedStartNodeId);
            }
            if (selectedEndNodeId != 0)
            {
                nodesToProcess.AddFirst(selectedEndNodeId);
            }

            while (nodesToProcess.First != null)
            {
                ushort nodeId = nodesToProcess.First.Value;
                nodesToProcess.RemoveFirst();
                processedNodes.Add(nodeId);

                if (Singleton <NetManager> .instance.m_nodes.m_buffer[nodeId].CountSegments() > 2)
                {
                    continue;                     // junction. stop.
                }
                // explore segments at node
                for (var s = 0; s < 8; s++)
                {
                    var segmentId = Singleton <NetManager> .instance.m_nodes.m_buffer[nodeId].GetSegment(s);

                    if (segmentId <= 0 || processedSegments.Contains(segmentId))
                    {
                        continue;
                    }
                    processedSegments.Add(segmentId);

                    NetInfo         segmentInfo = Singleton <NetManager> .instance.m_segments.m_buffer[segmentId].Info;
                    List <object[]> sortedLanes = TrafficManagerTool.GetSortedVehicleLanes(segmentId, segmentInfo, null);

                    if (sortedLanes.Count == selectedSortedLanes.Count)
                    {
                        // number of lanes matches selected segment
                        int sli = -1;
                        for (int i = 0; i < sortedLanes.Count; ++i)
                        {
                            ++sli;

                            if (sortedLaneIndex != null && sli != sortedLaneIndex)
                            {
                                continue;
                            }

                            object[] selectedLaneData = selectedSortedLanes[i];
                            object[] laneData         = sortedLanes[i];

                            uint         selectedLaneId    = (uint)selectedLaneData[0];
                            uint         selectedLaneIndex = (uint)selectedLaneData[2];
                            NetInfo.Lane selectedLaneInfo  = segmentInfo.m_lanes[selectedLaneIndex];

                            uint         laneId    = (uint)laneData[0];
                            uint         laneIndex = (uint)laneData[2];
                            NetInfo.Lane laneInfo  = segmentInfo.m_lanes[laneIndex];

                            // apply restrictions of selected segment & lane
                            VehicleRestrictionsManager.Instance().SetAllowedVehicleTypes(segmentId, segmentInfo, laneIndex, laneInfo, laneId, VehicleRestrictionsManager.Instance().GetAllowedVehicleTypes(SelectedSegmentId, selectedSegmentInfo, selectedLaneIndex, selectedLaneInfo));
                        }

                        // add nodes to explore
                        ushort startNodeId = Singleton <NetManager> .instance.m_segments.m_buffer[segmentId].m_startNode;
                        ushort endNodeId   = Singleton <NetManager> .instance.m_segments.m_buffer[segmentId].m_endNode;

                        if (startNodeId != 0 && !processedNodes.Contains(startNodeId))
                        {
                            nodesToProcess.AddFirst(startNodeId);
                        }
                        if (endNodeId != 0 && !processedNodes.Contains(endNodeId))
                        {
                            nodesToProcess.AddFirst(endNodeId);
                        }
                    }
                }
            }
        }
Exemplo n.º 4
0
        private void _guiVehicleRestrictionsWindow(int num)
        {
            if (GUILayout.Button(Translation.GetString("Invert")))
            {
                // invert pattern

                NetInfo         selectedSegmentInfo = Singleton <NetManager> .instance.m_segments.m_buffer[SelectedSegmentId].Info;
                List <object[]> sortedLanes         = TrafficManagerTool.GetSortedVehicleLanes(SelectedSegmentId, selectedSegmentInfo, null);        // TODO does not need to be sorted, but every lane should be a vehicle lane
                foreach (object[] laneData in sortedLanes)
                {
                    uint         laneId    = (uint)laneData[0];
                    uint         laneIndex = (uint)laneData[2];
                    NetInfo.Lane laneInfo  = selectedSegmentInfo.m_lanes[laneIndex];

                    ExtVehicleType baseMask = VehicleRestrictionsManager.Instance().GetBaseMask(laneInfo);

                    if (baseMask == ExtVehicleType.None)
                    {
                        continue;
                    }

                    ExtVehicleType allowedTypes = VehicleRestrictionsManager.Instance().GetAllowedVehicleTypes(SelectedSegmentId, selectedSegmentInfo, laneIndex, laneInfo);
                    allowedTypes = ~allowedTypes & baseMask;
                    VehicleRestrictionsManager.Instance().SetAllowedVehicleTypes(SelectedSegmentId, selectedSegmentInfo, laneIndex, laneInfo, laneId, allowedTypes);
                }
                RefreshCurrentRestrictedSegmentIds();
            }

            GUILayout.BeginHorizontal();
            if (GUILayout.Button(Translation.GetString("Allow_all_vehicles")))
            {
                // allow all vehicle types

                NetInfo         selectedSegmentInfo = Singleton <NetManager> .instance.m_segments.m_buffer[SelectedSegmentId].Info;
                List <object[]> sortedLanes         = TrafficManagerTool.GetSortedVehicleLanes(SelectedSegmentId, selectedSegmentInfo, null);        // TODO does not need to be sorted, but every lane should be a vehicle lane
                foreach (object[] laneData in sortedLanes)
                {
                    uint         laneId    = (uint)laneData[0];
                    uint         laneIndex = (uint)laneData[2];
                    NetInfo.Lane laneInfo  = selectedSegmentInfo.m_lanes[laneIndex];

                    ExtVehicleType baseMask = VehicleRestrictionsManager.Instance().GetBaseMask(laneInfo);

                    if (baseMask == ExtVehicleType.None)
                    {
                        continue;
                    }

                    VehicleRestrictionsManager.Instance().SetAllowedVehicleTypes(SelectedSegmentId, selectedSegmentInfo, laneIndex, laneInfo, laneId, baseMask);
                }
                RefreshCurrentRestrictedSegmentIds();
            }

            if (GUILayout.Button(Translation.GetString("Ban_all_vehicles")))
            {
                // ban all vehicle types

                NetInfo         selectedSegmentInfo = Singleton <NetManager> .instance.m_segments.m_buffer[SelectedSegmentId].Info;
                List <object[]> sortedLanes         = TrafficManagerTool.GetSortedVehicleLanes(SelectedSegmentId, selectedSegmentInfo, null);        // TODO does not need to be sorted, but every lane should be a vehicle lane
                foreach (object[] laneData in sortedLanes)
                {
                    uint         laneId    = (uint)laneData[0];
                    uint         laneIndex = (uint)laneData[2];
                    NetInfo.Lane laneInfo  = selectedSegmentInfo.m_lanes[laneIndex];

                    VehicleRestrictionsManager.Instance().SetAllowedVehicleTypes(SelectedSegmentId, selectedSegmentInfo, laneIndex, laneInfo, laneId, ExtVehicleType.None);
                }
                RefreshCurrentRestrictedSegmentIds();
            }
            GUILayout.EndHorizontal();

            if (GUILayout.Button(Translation.GetString("Apply_vehicle_restrictions_to_all_road_segments_between_two_junctions")))
            {
                ApplyRestrictionsToAllSegments();
                RefreshCurrentRestrictedSegmentIds();
            }

            GUI.DragWindow();
        }
        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!");
            }
        }
Exemplo n.º 6
0
        internal void housekeeping(bool mayDelete, RoadBaseAI.TrafficLightState mainState = RoadBaseAI.TrafficLightState.Red, RoadBaseAI.TrafficLightState leftState = RoadBaseAI.TrafficLightState.Red, RoadBaseAI.TrafficLightState rightState = RoadBaseAI.TrafficLightState.Red, RoadBaseAI.TrafficLightState pedState = RoadBaseAI.TrafficLightState.Red)
        {
#if TRACE
            Singleton <CodeProfiler> .instance.Start("CustomSegmentLights.housekeeping");
#endif
            // we intentionally never delete vehicle types (because we may want to retain traffic light states if a segment is upgraded or replaced)

            HashSet <ExtVehicleType>          setupLights     = new HashSet <ExtVehicleType>();
            Dictionary <byte, ExtVehicleType> allAllowedTypes = VehicleRestrictionsManager.Instance().GetAllowedVehicleTypesAsDict(segmentId, nodeId);
            ExtVehicleType allAllowedMask = VehicleRestrictionsManager.Instance().GetAllowedVehicleTypes(segmentId, nodeId);
            SeparateVehicleTypes = ExtVehicleType.None;
#if DEBUGHK
            Log._Debug($"CustomSegmentLights: housekeeping @ seg. {segmentId}, node {nodeId}, allAllowedTypes={string.Join(", ", allAllowedTypes.Select(x => x.ToString()).ToArray())}");
#endif
            bool addPedestrianLight = false;
            uint numLights          = 0;
            VehicleTypeByLaneIndex.Clear();
            HashSet <byte> laneIndicesWithoutSeparateLights = new HashSet <byte>(allAllowedTypes.Keys);
            foreach (KeyValuePair <byte, ExtVehicleType> e in allAllowedTypes)
            {
                byte           laneIndex    = e.Key;
                ExtVehicleType allowedTypes = e.Value;

                foreach (ExtVehicleType mask in singleLaneVehicleTypes)
                {
                    if (setupLights.Contains(mask))
                    {
                        break;
                    }

                    if ((allowedTypes & mask) != ExtVehicleType.None && (allowedTypes & ~(mask | ExtVehicleType.Emergency)) == ExtVehicleType.None)
                    {
#if DEBUGHK
                        Log._Debug($"CustomSegmentLights: housekeeping @ seg. {segmentId}, node {nodeId}: adding {mask} light");
#endif

                        if (!CustomLights.ContainsKey(mask))
                        {
                            CustomLights.Add(mask, new TrafficLight.CustomSegmentLight(this, nodeId, segmentId, mainState, leftState, rightState));
                            VehicleTypes.AddFirst(mask);
                        }
                        VehicleTypeByLaneIndex[laneIndex] = mask;
                        laneIndicesWithoutSeparateLights.Remove(laneIndex);
                        ++numLights;
                        addPedestrianLight        = true;
                        autoPedestrianVehicleType = mask;
                        mainSegmentLight          = CustomLights[mask];
                        setupLights.Add(mask);
                        SeparateVehicleTypes |= mask;
                        break;
                    }
                }
            }

            if (allAllowedTypes.Count > numLights)
            {
#if DEBUGHK
                Log._Debug($"CustomSegmentLights: housekeeping @ seg. {segmentId}, node {nodeId}: adding main vehicle light: {mainVehicleType}");
#endif

                // traffic lights for cars
                if (!CustomLights.ContainsKey(mainVehicleType))
                {
                    CustomLights.Add(mainVehicleType, new TrafficLight.CustomSegmentLight(this, nodeId, segmentId, mainState, leftState, rightState));
                    VehicleTypes.AddFirst(mainVehicleType);
                }
                autoPedestrianVehicleType = mainVehicleType;
                mainSegmentLight          = CustomLights[mainVehicleType];
                foreach (byte laneIndex in laneIndicesWithoutSeparateLights)
                {
                    VehicleTypeByLaneIndex[laneIndex] = ExtVehicleType.None;
                }
                addPedestrianLight = allAllowedMask == ExtVehicleType.None || (allAllowedMask & ~ExtVehicleType.RailVehicle) != ExtVehicleType.None;
            }
            else
            {
                addPedestrianLight = true;
            }

#if DEBUGHK
            if (addPedestrianLight)
            {
                Log._Debug($"CustomSegmentLights: housekeeping @ seg. {segmentId}, node {nodeId}: adding ped. light");
            }
#endif

            if (mayDelete)
            {
                // delete traffic lights for non-existing configurations
                HashSet <ExtVehicleType> vehicleTypesToDelete = new HashSet <ExtVehicleType>();
                foreach (KeyValuePair <ExtVehicleType, CustomSegmentLight> e in CustomLights)
                {
                    if (e.Key == mainVehicleType)
                    {
                        continue;
                    }
                    if (!setupLights.Contains(e.Key))
                    {
                        vehicleTypesToDelete.Add(e.Key);
                    }
                }

                foreach (ExtVehicleType vehicleType in vehicleTypesToDelete)
                {
#if DEBUGHK
                    Log._Debug($"Deleting traffic light for {vehicleType} at segment {segmentId}, node {nodeId}");
#endif
                    CustomLights.Remove(vehicleType);
                    VehicleTypes.Remove(vehicleType);
                }
            }

            if (CustomLights.ContainsKey(mainVehicleType) && VehicleTypes.First.Value != mainVehicleType)
            {
                VehicleTypes.Remove(mainVehicleType);
                VehicleTypes.AddFirst(mainVehicleType);
            }

            if (addPedestrianLight)
            {
#if DEBUGHK
                Log._Debug($"CustomSegmentLights: housekeeping @ seg. {segmentId}, node {nodeId}: adding pedestrian light");
#endif
                if (pedestrianLightState == null)
                {
                    pedestrianLightState = pedState;
                }
            }
            else
            {
                pedestrianLightState = null;
            }

#if DEBUGHK
            Log._Debug($"CustomSegmentLights: housekeeping @ seg. {segmentId}, node {nodeId}: Housekeeping complete. VehicleTypeByLaneIndex={string.Join("; ", VehicleTypeByLaneIndex.Select(x => x.Key + "=" + x.Value).ToArray())} CustomLights={string.Join("; ", CustomLights.Select(x => x.Key.ToString()).ToArray())}");
#endif
#if TRACE
            Singleton <CodeProfiler> .instance.Stop("CustomSegmentLights.housekeeping");
#endif
        }
Exemplo n.º 7
0
        /// <summary>
        /// Calculates the current metrics for flowing and waiting vehicles
        /// </summary>
        /// <param name="wait"></param>
        /// <param name="flow"></param>
        /// <returns>true if the values could be calculated, false otherwise</returns>
        public bool calcWaitFlow(out float wait, out float flow)
        {
#if TRACE
            Singleton <CodeProfiler> .instance.Start("TimedTrafficLightsStep.calcWaitFlow");
#endif

#if DEBUGMETRIC
            bool debug = timedNode.NodeId == 3201;
#else
            bool debug = false;
#endif

#if DEBUGMETRIC
            if (debug)
            {
                Log.Warning($"TimedTrafficLightsStep.calcWaitFlow: ***START*** @ node {timedNode.NodeId}");
            }
#endif

            uint numFlows    = 0;
            uint numWaits    = 0;
            uint curMeanFlow = 0;
            uint curMeanWait = 0;

            TrafficLightSimulationManager tlsMan  = TrafficLightSimulationManager.Instance();
            TrafficPriorityManager        prioMan = TrafficPriorityManager.Instance();

            // we are the master node. calculate traffic data
            foreach (ushort timedNodeId in timedNode.NodeGroup)
            {
                TrafficLightSimulation sim = tlsMan.GetNodeSimulation(timedNodeId);
                if (sim == null || !sim.IsTimedLight())
                {
                    continue;
                }
                TimedTrafficLights     slaveTimedNode = sim.TimedLight;
                TimedTrafficLightsStep slaveStep      = slaveTimedNode.Steps[timedNode.CurrentStep];

                //List<int> segmentIdsToDelete = new List<int>();

                // minimum time reached. check traffic!
                foreach (KeyValuePair <ushort, CustomSegmentLights> e in slaveStep.segmentLights)
                {
                    var fromSegmentId = e.Key;
                    var segLights     = e.Value;

                    // one of the traffic lights at this segment is green: count minimum traffic flowing through
                    SegmentEnd fromSeg = prioMan.GetPrioritySegment(timedNodeId, fromSegmentId);
                    if (fromSeg == null)
                    {
#if DEBUGMETRIC
                        if (debug)
                        {
                            Log.Warning($"TimedTrafficLightsStep.calcWaitFlow: No priority segment @ seg. {fromSegmentId} found!");
                        }
#endif
                        //Log.Warning("stepDone(): prioSeg is null");
                        //segmentIdsToDelete.Add(fromSegmentId);
                        continue;                         // skip invalid segment
                    }

                    //bool startPhase = getCurrentFrame() <= startFrame + minTime + 2; // during start phase all vehicles on "green" segments are counted as flowing
                    ExtVehicleType validVehicleTypes = VehicleRestrictionsManager.Instance().GetAllowedVehicleTypes(fromSegmentId, timedNode.NodeId);

                    foreach (KeyValuePair <byte, ExtVehicleType> e2 in segLights.VehicleTypeByLaneIndex)
                    {
                        byte           laneIndex   = e2.Key;
                        ExtVehicleType vehicleType = e2.Value;
                        if (vehicleType != ExtVehicleType.None && (validVehicleTypes & vehicleType) == ExtVehicleType.None)
                        {
                            continue;
                        }
                        CustomSegmentLight segLight = segLights.GetCustomLight(laneIndex);
                        if (segLight == null)
                        {
                            Log.Warning($"Timed traffic light step: Failed to get custom light for vehicleType {vehicleType} @ seg. {fromSegmentId}, node {timedNode.NodeId}!");
                            continue;
                        }

#if DEBUGMETRIC
                        if (debug)
                        {
                            Log._Debug($"TimedTrafficLightsStep.calcWaitFlow: Checking lane {laneIndex} @ seg. {fromSegmentId}. Vehicle types: {vehicleType}");
                        }
#endif

                        Dictionary <ushort, uint> carsFlowingToSegmentMetric = null;
                        Dictionary <ushort, uint> allCarsToSegmentMetric     = null;
                        try {
                            carsFlowingToSegmentMetric = fromSeg.GetVehicleMetricGoingToSegment(false, laneIndex, debug);
                        } catch (Exception ex) {
                            Log.Warning("calcWaitFlow (1): " + ex.ToString());
                        }

                        try {
                            allCarsToSegmentMetric = fromSeg.GetVehicleMetricGoingToSegment(true, laneIndex, debug);
                        } catch (Exception ex) {
                            Log.Warning("calcWaitFlow (2): " + ex.ToString());
                        }

                        if (carsFlowingToSegmentMetric == null)
                        {
                            continue;
                        }

                        // build directions from toSegment to fromSegment
                        Dictionary <ushort, ArrowDirection> directions = new Dictionary <ushort, ArrowDirection>();
                        foreach (KeyValuePair <ushort, uint> f in allCarsToSegmentMetric)
                        {
                            var             toSegmentId = f.Key;
                            SegmentGeometry geometry    = SegmentGeometry.Get(fromSegmentId);
                            ArrowDirection  dir         = geometry.GetDirection(toSegmentId, timedNodeId == geometry.StartNodeId());
                            directions[toSegmentId] = dir;
#if DEBUGMETRIC
                            if (debug)
                            {
                                Log._Debug($"TimedTrafficLightsStep.calcWaitFlow: Calculated direction for seg. {fromSegmentId} -> seg. {toSegmentId}: {dir}");
                            }
#endif
                        }

                        // calculate waiting/flowing traffic
                        foreach (KeyValuePair <ushort, uint> f in allCarsToSegmentMetric)
                        {
                            ushort toSegmentId               = f.Key;
                            uint   totalNormCarLength        = f.Value;
                            uint   totalFlowingNormCarLength = carsFlowingToSegmentMetric[f.Key];

#if DEBUGMETRIC
                            if (debug)
                            {
                                Log._Debug($"TimedTrafficLightsStep.calcWaitFlow: Total norm. car length of vehicles on lane {laneIndex} going to seg. {toSegmentId}: {totalNormCarLength}");
                            }
#endif

                            bool addToFlow = false;
                            switch (directions[toSegmentId])
                            {
                            case ArrowDirection.Turn:
                                addToFlow = TrafficPriorityManager.IsLeftHandDrive() ? segLight.isRightGreen() : segLight.isLeftGreen();
                                break;

                            case ArrowDirection.Left:
                                addToFlow = segLight.isLeftGreen();
                                break;

                            case ArrowDirection.Right:
                                addToFlow = segLight.isRightGreen();
                                break;

                            case ArrowDirection.Forward:
                            default:
                                addToFlow = segLight.isForwardGreen();
                                break;
                            }

                            if (addToFlow)
                            {
                                ++numFlows;
                                curMeanFlow += totalFlowingNormCarLength;
                            }
                            else
                            {
                                ++numWaits;
                                curMeanWait += totalNormCarLength;
                            }

#if DEBUGMETRIC
                            if (debug)
                            {
                                Log._Debug($"TimedTrafficLightsStep.calcWaitFlow: Vehicles on lane {laneIndex} on seg. {fromSegmentId} going to seg. {toSegmentId} flowing? {addToFlow} curMeanFlow={curMeanFlow}, curMeanWait={curMeanWait}");
                            }
#endif
                        }
                    }
                }

                // delete invalid segments from step

                /*foreach (int segmentId in segmentIdsToDelete) {
                 *      slaveStep.segmentLightStates.Remove(segmentId);
                 * }*/
            }

#if DEBUGMETRIC
            if (debug)
            {
                Log._Debug($"TimedTrafficLightsStep.calcWaitFlow: ### Calculation completed. numFlows={numFlows}, numWaits={numWaits}, curMeanFlow={curMeanFlow}, curMeanWait={curMeanWait}");
            }

            wait = curMeanWait;
            flow = curMeanFlow;
#else
            if (numFlows > 0)
            {
                curMeanFlow /= numFlows;
            }
            if (numWaits > 0)
            {
                curMeanWait /= numWaits;
            }

            float fCurMeanFlow = curMeanFlow;
            fCurMeanFlow /= waitFlowBalance;             // a value smaller than 1 rewards steady traffic currents

            wait = (float)curMeanWait;
            flow = fCurMeanFlow;
#endif
#if TRACE
            Singleton <CodeProfiler> .instance.Stop("TimedTrafficLightsStep.calcWaitFlow");
#endif
            return(true);
        }