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