public static SegmentLanes IdentifyLanes(NetManager netManager, NetInfo netInfo, ushort segmentID)
        {
            var lanes = new SegmentLanes();

            uint laneId = netManager.m_segments.m_buffer[segmentID].m_lanes;

            foreach (var lane in netInfo.m_lanes)
            {
                bool isVehicleLane = (lane.m_laneType & vehicleLaneTypes) != 0;
                bool isCarLane     = (lane.m_vehicleType & VehicleInfo.VehicleType.Car) != 0;
                if (!isVehicleLane || !isCarLane)
                {
                    // Pedestrian lanes, parking lanes, bicycle lanes etc. - ignore
                    laneId = netManager.m_lanes.m_buffer[laneId].m_nextLane;
                    continue;
                }

                bool isForwardDirection = (lane.m_finalDirection & NetInfo.Direction.Forward) != 0;

                if (isForwardDirection)
                {
                    if (lanes.forward.lanes.ContainsKey(lane.m_position))
                    {
                        Mod.LogMessage("Segment " + segmentID + " lane " + laneId + " has the same position as another lane and will be skipped");
                    }
                    else
                    {
                        lanes.forward.lanes.Add(lane.m_position, laneId);

                        if (IsBusLane(lane))
                        {
                            lanes.forward.busLaneIds.Add(laneId);
                        }
                    }
                }
                else
                {
                    if (lanes.backward.lanes.ContainsKey(-lane.m_position))
                    {
                        Mod.LogMessage("Segment " + segmentID + " lane " + laneId + " has the same position as another lane and will be skipped");
                    }
                    else
                    {
                        lanes.backward.lanes.Add(-lane.m_position, laneId);

                        if (IsBusLane(lane))
                        {
                            lanes.backward.busLaneIds.Add(laneId);
                        }
                    }
                }

                laneId = netManager.m_lanes.m_buffer[laneId].m_nextLane;
            }

            return(lanes);
        }
        // Adapted from NetNode.CountLanes
        private static JunctionInfo AnalyseNode(NetNode node,
                                                ushort nodeID,
                                                ushort ignoreSegmentID,
                                                NetInfo.LaneType laneTypes,
                                                VehicleInfo.VehicleType vehicleTypes,
                                                Vector3 directionVector)
        {
            var nodeInfo = new JunctionInfo();

            if (node.m_flags == NetNode.Flags.None)
            {
                return(nodeInfo);
            }

            NetManager netManager = Singleton <NetManager> .instance;

            for (int i = 0; i < 8; i++)
            {
                ushort segmentID = node.GetSegment(i);
                if (segmentID == 0 || segmentID == ignoreSegmentID)
                {
                    continue;
                }

                var segment = netManager.m_segments.m_buffer[segmentID];

                if (segment.Info == null)
                {
                    continue; // may happen if loading a map with a missing road asset
                }

                bool isInverted  = (segment.m_flags & NetSegment.Flags.Invert) != 0;
                bool isStartNode = segment.m_startNode == nodeID;

                SegmentLanes lanes = SegmentAnalyser.IdentifyLanes(netManager, segment.Info, segmentID);

                Vector3 vector = isStartNode ? segment.m_startDirection : segment.m_endDirection;

                float angleDeg = GetAngleDeg(vector, directionVector);

                nodeInfo.AddLanes(isStartNode ^ isInverted ? lanes.forward : lanes.backward, angleDeg);
            }

            return(nodeInfo);
        }
Esempio n. 3
0
        public static void Postfix(ushort segmentID, ref NetSegment data, NetInfo ___m_info)
        {
            if (___m_info.m_lanes.Length == 0)
            {
                return;
            }

            NetManager netManager = Singleton <NetManager> .instance;

            SegmentLanes lanes = SegmentAnalyser.IdentifyLanes(netManager, ___m_info, segmentID);

            // Every other segment is "inverted"
            bool invertedSegment = (netManager.m_segments.m_buffer[segmentID].m_flags & NetSegment.Flags.Invert) != 0;

            NetNode startNode = netManager.m_nodes.m_buffer[data.m_startNode];
            NetNode endNode   = netManager.m_nodes.m_buffer[data.m_endNode];

            bool lht = Singleton <SimulationManager> .instance.m_metaData.m_invertTraffic == SimulationMetaData.MetaBool.True;

            if (lanes.forward.lanes.Count > 0)
            {
                var actualEndNode = invertedSegment ? startNode : endNode;

                if (IsJunctionNode(actualEndNode))
                {
                    var nodeID    = invertedSegment ? data.m_startNode : data.m_endNode;
                    var outVector = invertedSegment ? -data.m_startDirection : -data.m_endDirection;
                    LaneConnector.AssignLanes(lanes.forward, outVector, segmentID, nodeID, actualEndNode, lht);
                }
            }

            if (lanes.backward.lanes.Count > 0)
            {
                var actualEndNode = invertedSegment ? endNode : startNode; // other way around than for forward lanes

                if (IsJunctionNode(actualEndNode))
                {
                    var nodeID    = invertedSegment ? data.m_endNode : data.m_startNode;
                    var outVector = invertedSegment ? -data.m_endDirection : -data.m_startDirection;

                    LaneConnector.AssignLanes(lanes.backward, outVector, segmentID, nodeID, actualEndNode, lht);
                }
            }
        }