Exemplo n.º 1
0
        /// <summary>
        /// 
        /// </summary>
        /// <param name="aRecords">ソート対象</param>
        /// <param name="aBuffer">使用するバッファ。 aRecordsと同じ長さを持つ配列</param>
        /// <param name="aDepth">現在ソートしている桁数。最上位桁を0とする</param>
        /// <param name="aStart">ソート区間の開始。閉区間</param>
        /// <param name="aEnd">ソート区間の終端。開区間</param>
        /// <param name="toKey">レコードと呼び出しの深さから、ソートのKeyとなる値を取り出す関数。文字長を超えた場合は0を返す</param>
        private void RadixSort(List<IList<string>> aRecords, BufferItem[] aBuffer, int aDepth, int aStart, int aEnd, Func<IList<string>, int, char> toKey)
        {
            int tSize = aEnd - aStart;

            // ソート対象区間が1以下ならソート済み
            if (tSize <= 1)
                return;

            // ソート対象キーにはascii codeのみ含まれるものとする
            int[] tHistogram = new int[256];
            for (int i = aStart; i < aEnd; i++)
            {
                var tRecord = aRecords[i];
                char tKey = toKey(tRecord, aDepth);

                // 対象キーの数を数える
                tHistogram[tKey]++;
                aBuffer[i] = new BufferItem(tRecord, tKey);
            }

            // 全てのKeyがnull文字であれば、ソート済み
            if (tHistogram[0] == tSize)
            {
                return;
            }

            // tHistgram[key] = keyを持つレコードが 格納されるべきindex終端+1 になるように調整
            tHistogram[0] += aStart;
            for (int i = 1; i < tHistogram.Length; i++)
            {
                tHistogram[i] += tHistogram[i - 1];
            }

            // 後ろからソート済みになるように書き戻す
            // ついでにtHistgram[key] = keyを持つレコードが格納されているindex始端 となるように調整
            for (int i = aEnd - 1; i >= aStart; i--)
            {
                var tRecordItem = aBuffer[i];
                char tKey = tRecordItem.Key;
                int tIndex = --tHistogram[tKey];
                aRecords[tIndex] = tRecordItem.Record;
            }

            int tNewDepth = aDepth + 1;

            for (int i = 1; i < tHistogram.Length; i++)
            {
                int tNewStart = tHistogram[i - 1];
                int tNewEnd = tHistogram[i];
                RadixSort(aRecords, aBuffer, tNewDepth, tNewStart, tNewEnd, toKey);
            }
        }
Exemplo n.º 2
0
        protected override void Sort(List<IList<string>> aRecords, int aSortIndex)
        {
            int tSize = aRecords.Count;
            var tBuffer = new BufferItem[tSize];
            Func<IList<string>, int, char> toKey = (aList, aDepth) => {
                string tKeyString = aList[aSortIndex];
                if (tKeyString.Length <= aDepth)
                    return char.MinValue;

                return tKeyString[aDepth];
            };

            RadixSort(aRecords, tBuffer, 0, 0, tSize, toKey);
        }
Exemplo n.º 3
0
        /// <summary>
        /// Processes first first filled buffer in queue and disposes it if done.
        /// </summary>
        /// <param name="state">User data.</param>
        private void ProcessFirstBuffer(object state)
        {
            try{
                lock (m_pBuffers){
                    BufferItem item = m_pBuffers[0];

                    // Raise BufferFull event.

                    OnBufferFull(item.Data);

                    // Clean up.
                    WavMethods.waveInUnprepareHeader(m_pWavDevHandle, item.HeaderHandle.AddrOfPinnedObject(), Marshal.SizeOf(item.Header));
                    m_pBuffers.Remove(item);
                    item.Dispose();
                }

                EnsureBuffers();
            }
            catch {
            }
        }
Exemplo n.º 4
0
        /// <summary>
        /// This method is called when wav device generates some event.
        /// </summary>
        /// <param name="hdrvr">Handle to the waveform-audio device associated with the callback.</param>
        /// <param name="uMsg">Waveform-audio input message.</param>
        /// <param name="dwUser">User-instance data specified with waveOutOpen.</param>
        /// <param name="dwParam1">Message parameter.</param>
        /// <param name="dwParam2">Message parameter.</param>
        private void OnWaveInProc(IntPtr hdrvr, int uMsg, IntPtr dwUser, IntPtr dwParam1, IntPtr dwParam2)
        {
            // NOTE: MSDN warns, we may not call any wave related methods here.
            // This may cause deadlock. But MSDN examples do it, probably we can do it too.

            if (m_IsDisposed)
            {
                return;
            }

            try{
                if (uMsg == WavConstants.MM_WIM_DATA)
                {
                    // Free buffer and queue it for reuse.
                    //ThreadPool.QueueUserWorkItem(new WaitCallback(delegate(object state){
                    try
                    {
                        if (m_IsDisposed)
                        {
                            return;
                        }

                        BufferItem bufferItem = m_pBuffers[dwParam1.ToInt64()];

                        OnAudioFrameReceived(bufferItem.EventArgs);

                        bufferItem.Queue(true);
                    }
                    catch (Exception x)
                    {
                        Console.WriteLine(x.ToString());
                    }
                    //}));
                }
            }
            catch
            {
                // We don't care about errors here.
            }
        }
Exemplo n.º 5
0
        public IHttpActionResult Create(int intKey, BufferItem bufferItem)
        {
            if (!ModelState.IsValid)
            {
                return(BadRequest(ModelState));
            }
            if (intKey != bufferItem.Key)
            {
                return(BadRequest("Wrong data"));
            }

            var context = new MultiBufferContext();
            var query   =
                from el in context.BufferItems
                where el.Key == intKey
                select el;

            BufferItem item = query.SingleOrDefault();

            if (item == null)
            {
                try
                {
                    bufferItem.Id = 0;
                    context.BufferItems.Add(bufferItem);
                    context.SaveChanges();
                }
                catch (Exception e)
                {
                    Console.WriteLine(e);
                    throw;
                }
                return(StatusCode(HttpStatusCode.NoContent));
            }
            else
            {
                return(BadRequest("Item is already existing"));
            }
        }
Exemplo n.º 6
0
        private void ActivateTrackItem(BufferItem item)
        {
            var tbi       = item as TrackBufferItem;
            var playQueue = buffers[0];

            if (playbackManager.PlayingTrack != null && tbi.Model.TrackPtr == playbackManager.PlayingTrack.TrackPtr)
            {
                TogglePlayPause(playbackManager.IsPaused);
                return;
            }
            ClearCurrentlyPlayingTrack();
            if (buffers.CurrentListIndex == 0 && playQueue.Contains(tbi)) // if they've picked it from the play queue
            {
                int indexOfChosenTrack = playQueue.IndexOf(tbi);
                if (indexOfChosenTrack > 0)
                {
                    var skippedTracks = playQueue.Take(indexOfChosenTrack).Cast <TrackBufferItem>().Select(i => i.Model);
                    playbackManager.PutTracksIntoPreviousTracks(skippedTracks);
                    playQueue.RemoveRange(0, indexOfChosenTrack);
                }
            }
            else
            {
                playQueue.Clear();
                playbackManager.ClearPreviousTracks();
                playQueue.Add(tbi);
                if (buffers.CurrentList is PlaylistBufferList || buffers.CurrentList is AlbumBufferList) // add the remaining playlist or album to the queue
                {
                    AddRemainingTracksToQueue(item, playQueue);
                }
            }
            PlayNewTrackBufferItem(tbi);
            if (playQueue.Any())
            {
                playQueue.CurrentItemIndex = 0;
            }
        }
Exemplo n.º 7
0
        protected override void Get(ref BufferItem buffer)
        {
            buffer.Epoch = epoch;

            var frame1 = new OpenCvSharp.Mat(files[index1].FullName);

            buffer.Input.ReadFrom(frame1);
            if (RandomNoize != 0)
            {
                RandomNoize(ref buffer.Input, RandomNoize, random);
            }

            var frame2 = new OpenCvSharp.Mat(files[index2].FullName);

            buffer.Teacher.ReadFrom(frame2);

            sellection.Add(index1);
            if (sellection.Count >= files.Length)
            {
                epoch++;
                sellection.Clear();
                files  = (new System.IO.DirectoryInfo(SourceLocation)).GetFiles();
                index1 = random.Next(0, files.Length);
            }
            else
            {
                while (sellection.Contains(index1))
                {
                    index1 = random.Next(0, files.Length);
                }
            }
            index2 = index1;
            if (index2 >= files.Length)
            {
                index2 = 0;
            }
        }
        public override void Execute(object sender, HandledEventArgs e)
        {
            BufferItem item  = buffers.CurrentList.CurrentItem;
            object     model = null;

            if (item is TrackBufferItem)
            {
                model = ((TrackBufferItem)item).Model;
            }
            else if (item is PlaylistBufferItem)
            {
                model = ((PlaylistBufferItem)item).Model;
            }
            if (model != null)
            {
                ItemDetailsWindow detailsView = new ItemDetailsWindow(model);
                detailsView.ShowDialog();
            }
            else
            {
                var output = OutputManager.Instance;
                output.OutputMessage("View details is not a valid action for this type of item", true);
            }
        }
Exemplo n.º 9
0
        public BufferItem GetBuffer()
        {
            BufferItem item = null;

            while (item == null)
            {
                bool check = false;
                lock (__queuelock)
                {
                    if (ItemQueue.Count > 0)
                    {
                        item  = ItemQueue.Dequeue();
                        check = true;
                    }
                }
                if (!check)
                {
                    //Console.WriteLine("!Reader BufferWait");
                    System.Threading.Thread.Sleep(1);
                }
            }

            return(item);
        }
		// be aware:
		//   (1) path-finding works from target to start. the "next" segment is always the previous and the "previous" segment is always the next segment on the path!
		//   (2) when I use the term "lane index from right" this holds for right-hand traffic systems. On maps where you activate left-hand traffic, the "lane index from right" values represent lane indices starting from the left side.

		// 1
		private void ProcessItemMain(BufferItem item, ushort nextNodeId, ref NetNode nextNode, byte connectOffset, bool isMiddle) {
#if DEBUG
			//bool debug = nodeID == 28311u && item.m_position.m_segment == 33016;
			//bool debug = nodeID == 26128u && item.m_position.m_segment == 4139 && nextSegmentId == 27106;
			//bool debug = nodeID == 13630u && item.m_position.m_segment == 35546u;
			
#endif
#if DEBUG
			//bool debug = isTransportVehicle && isMiddle && item.m_position.m_segment == 13550;
			bool debug = false;
#else
			bool debug = false;
#endif
			NetManager instance = Singleton<NetManager>.instance;
			bool isPedestrianLane = false;
			bool isBicycleLane = false;
			int similarLaneIndexFromLeft = 0; // similar index, starting with 0 at leftmost lane
			NetInfo prevSegmentInfo = instance.m_segments.m_buffer[(int)item.m_position.m_segment].Info;
			if ((int)item.m_position.m_lane < prevSegmentInfo.m_lanes.Length) {
				NetInfo.Lane prevLane = prevSegmentInfo.m_lanes[(int)item.m_position.m_lane];
				isPedestrianLane = (prevLane.m_laneType == NetInfo.LaneType.Pedestrian);
				isBicycleLane = (prevLane.m_laneType == NetInfo.LaneType.Vehicle && prevLane.m_vehicleType == VehicleInfo.VehicleType.Bicycle);
				if ((byte)(prevLane.m_finalDirection & NetInfo.Direction.Forward) != 0) {
					similarLaneIndexFromLeft = prevLane.m_similarLaneIndex;
				} else {
					similarLaneIndexFromLeft = prevLane.m_similarLaneCount - prevLane.m_similarLaneIndex - 1;
				}
			}

			ushort prevSegment = item.m_position.m_segment;
			if (isMiddle) {
				for (int i = 0; i < 8; i++) {
					ushort nextSegmentId = nextNode.GetSegment(i);
					if (nextSegmentId <= 0)
						continue;
					this.ProcessItem(debug, item, nextNodeId, nextSegmentId, ref instance.m_segments.m_buffer[(int)nextSegmentId], ref similarLaneIndexFromLeft, connectOffset, !isPedestrianLane, isPedestrianLane);
				}
			} else if (isPedestrianLane) {
				int prevLaneIndex = (int)item.m_position.m_lane;
				if (nextNode.Info.m_class.m_service != ItemClass.Service.Beautification) {
					bool flag3 = (nextNode.m_flags & (NetNode.Flags.End | NetNode.Flags.Bend | NetNode.Flags.Junction)) != NetNode.Flags.None;
					int laneIndex;
					int laneIndex2;
					uint leftLaneId;
					uint rightLaneId;
					instance.m_segments.m_buffer[(int)prevSegment].GetLeftAndRightLanes(nextNodeId, NetInfo.LaneType.Pedestrian, VehicleInfo.VehicleType.None, prevLaneIndex, out laneIndex, out laneIndex2, out leftLaneId, out rightLaneId);
					ushort num4 = prevSegment;
					ushort num5 = prevSegment;
					if (leftLaneId == 0u || rightLaneId == 0u) {
						ushort leftSegment;
						ushort rightSegment;
						instance.m_segments.m_buffer[(int)prevSegment].GetLeftAndRightSegments(nextNodeId, out leftSegment, out rightSegment);
						int num6 = 0;
						while (leftSegment != 0 && leftSegment != prevSegment && leftLaneId == 0u) {
							int num7;
							int num8;
							uint num9;
							uint num10;
							instance.m_segments.m_buffer[(int)leftSegment].GetLeftAndRightLanes(nextNodeId, NetInfo.LaneType.Pedestrian, VehicleInfo.VehicleType.None, -1, out num7, out num8, out num9, out num10);
							if (num10 != 0u) {
								num4 = leftSegment;
								laneIndex = num8;
								leftLaneId = num10;
							} else {
								leftSegment = instance.m_segments.m_buffer[(int)leftSegment].GetLeftSegment(nextNodeId);
							}
							if (++num6 == 8) {
								break;
							}
						}
						num6 = 0;
						while (rightSegment != 0 && rightSegment != prevSegment && rightLaneId == 0u) {
							int num11;
							int num12;
							uint num13;
							uint num14;
							instance.m_segments.m_buffer[(int)rightSegment].GetLeftAndRightLanes(nextNodeId, NetInfo.LaneType.Pedestrian, VehicleInfo.VehicleType.None, -1, out num11, out num12, out num13, out num14);
							if (num13 != 0u) {
								num5 = rightSegment;
								laneIndex2 = num11;
								rightLaneId = num13;
							} else {
								rightSegment = instance.m_segments.m_buffer[(int)rightSegment].GetRightSegment(nextNodeId);
							}
							if (++num6 == 8) {
								break;
							}
						}
					}
					if (leftLaneId != 0u && (num4 != prevSegment || flag3)) {
						this.ProcessItemPedBicycle(item, nextNodeId, num4, ref instance.m_segments.m_buffer[(int)num4], connectOffset, laneIndex, leftLaneId); // ped
					}
					if (rightLaneId != 0u && rightLaneId != leftLaneId && (num5 != prevSegment || flag3)) {
						this.ProcessItemPedBicycle(item, nextNodeId, num5, ref instance.m_segments.m_buffer[(int)num5], connectOffset, laneIndex2, rightLaneId); // ped
					}
					int laneIndex3;
					uint lane3;
					if ((this._vehicleTypes & VehicleInfo.VehicleType.Bicycle) != VehicleInfo.VehicleType.None && instance.m_segments.m_buffer[(int)prevSegment].GetClosestLane((int)item.m_position.m_lane, NetInfo.LaneType.Vehicle, VehicleInfo.VehicleType.Bicycle, out laneIndex3, out lane3)) {
						this.ProcessItemPedBicycle(item, nextNodeId, prevSegment, ref instance.m_segments.m_buffer[(int)prevSegment], connectOffset, laneIndex3, lane3); // bicycle
					}
				} else {
					for (int j = 0; j < 8; j++) {
						ushort segment3 = nextNode.GetSegment(j);
						if (segment3 != 0 && segment3 != prevSegment) {
							this.ProcessItem(debug, item, nextNodeId, segment3, ref instance.m_segments.m_buffer[(int)segment3], ref similarLaneIndexFromLeft, connectOffset, false, true);
						}
					}
				}
				NetInfo.LaneType laneType = this._laneTypes & ~NetInfo.LaneType.Pedestrian;
				VehicleInfo.VehicleType vehicleType = this._vehicleTypes & ~VehicleInfo.VehicleType.Bicycle;
				if ((byte)(item.m_lanesUsed & (NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle)) != 0) {
					laneType &= ~(NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle);
				}
				int num15;
				uint lane4;
				if (laneType != NetInfo.LaneType.None && vehicleType != VehicleInfo.VehicleType.None && instance.m_segments.m_buffer[(int)prevSegment].GetClosestLane(prevLaneIndex, laneType, vehicleType, out num15, out lane4)) {
					NetInfo.Lane lane5 = prevSegmentInfo.m_lanes[num15];
					byte connectOffset2;
					if ((instance.m_segments.m_buffer[(int)prevSegment].m_flags & NetSegment.Flags.Invert) != NetSegment.Flags.None == ((byte)(lane5.m_finalDirection & NetInfo.Direction.Backward) != 0)) {
						connectOffset2 = 1;
					} else {
						connectOffset2 = 254;
					}
					this.ProcessItemPedBicycle(item, nextNodeId, prevSegment, ref instance.m_segments.m_buffer[(int)prevSegment], connectOffset2, num15, lane4); // ped
				}
			} else {
				bool blocked = (nextNode.m_flags & (NetNode.Flags.End | NetNode.Flags.OneWayOut)) != NetNode.Flags.None;
				bool pedestrianAllowed = (byte)(this._laneTypes & NetInfo.LaneType.Pedestrian) != 0;
				bool enablePedestrian = false;
				byte connectOffset3 = 0;
				if (pedestrianAllowed) {
					if (isBicycleLane) {
						connectOffset3 = connectOffset;
						enablePedestrian = (nextNode.Info.m_class.m_service == ItemClass.Service.Beautification);
					} else if (this._vehicleLane != 0u) {
						if (this._vehicleLane != item.m_laneID) {
							pedestrianAllowed = false;
						} else {
							connectOffset3 = this._vehicleOffset;
						}
					} else if (this._stablePath) {
						connectOffset3 = 128;
					} else {
						connectOffset3 = (byte)this._pathRandomizer.UInt32(1u, 254u);
					}
				}

				// NON-STOCK CODE START //
				CustomPathManager pathManager = Singleton<CustomPathManager>.instance;
				bool nextIsJunction = nextNode.CountSegments() > 2;
				bool prevIsOutgoingOneWay = TrafficLightsManual.SegmentIsOutgoingOneWay(prevSegment, nextNodeId);
				bool prevIsHighway = false;
				if (prevSegmentInfo.m_netAI is RoadBaseAI)
					prevIsHighway = ((RoadBaseAI)prevSegmentInfo.m_netAI).m_highwayRules;

				NetInfo.Direction normDirection = TrafficPriority.LeftHandDrive ? NetInfo.Direction.Forward : NetInfo.Direction.Backward; // direction to normalize indices to
				int prevRightSimilarLaneIndex;
				int prevLeftSimilarLaneIndex;

				NetInfo.Lane lane = prevSegmentInfo.m_lanes[(int)item.m_position.m_lane];
				if ((byte)(lane.m_direction & normDirection) != 0) {
					prevRightSimilarLaneIndex = lane.m_similarLaneIndex;
					prevLeftSimilarLaneIndex = lane.m_similarLaneCount - lane.m_similarLaneIndex - 1;
				} else {
					prevRightSimilarLaneIndex = lane.m_similarLaneCount - lane.m_similarLaneIndex - 1;
					prevLeftSimilarLaneIndex = lane.m_similarLaneIndex;
				}
				bool foundForced = false;
				byte totalIncomingLanes = 0;
				// NON-STOCK CODE END //

				ushort nextSegmentId = instance.m_segments.m_buffer[(int)item.m_position.m_segment].GetRightSegment(nextNodeId);

				bool hasStraight = false;
				bool hasLeft = false;
				bool hasRight = false;
				int leftRemaining = 0;
				int rightRemaining = 0;
				if (instance.m_segments.m_buffer[(int)prevSegment].m_startNode == nextNodeId) {
					hasStraight = CustomRoadAI.segmentGeometries[prevSegment].startNodeHasStraightSegment;
					leftRemaining = CustomRoadAI.segmentGeometries[prevSegment].startNodeNumLeftSegments;
					rightRemaining = CustomRoadAI.segmentGeometries[prevSegment].startNodeNumRightSegments;
				} else {
					hasStraight = CustomRoadAI.segmentGeometries[prevSegment].endNodeHasStraightSegment;
					leftRemaining = CustomRoadAI.segmentGeometries[prevSegment].endNodeNumLeftSegments;
					rightRemaining = CustomRoadAI.segmentGeometries[prevSegment].endNodeNumRightSegments;
				}
				hasLeft = leftRemaining > 0;
				hasRight = rightRemaining > 0;

				if (debug) {
					Log.Message($"Pathfind ({this._pathFindIndex}) @ node {nextNodeId}: hasStraight: {hasStraight}, hasLeft: {hasLeft}, rightRemaining: {rightRemaining}");
                }

				for (int k = 0; k < 8; k++) {
					if (nextSegmentId == 0 || nextSegmentId == item.m_position.m_segment) {
						break;
					}

					/*if (Options.nodesOverlay) {
						bool isRealRight = TrafficPriority.IsRightSegment(prevSegment, nextSegmentId, nextNodeId);
						bool isRealLeft = TrafficPriority.IsLeftSegment(prevSegment, nextSegmentId, nextNodeId);
						bool isRealStraight = !isRealRight && !isRealLeft;
						if (rightRemaining > 0) {
							if (!isRealRight)
								Log.Warning($"k={k}: segment {nextSegmentId} ({prevSegment}) is not right. rightRemaining={rightRemaining}. hasStraight={hasStraight}, hasLeft={hasLeft}. realRSL: {isRealLeft},{isRealStraight},{isRealRight}");
						} else if (rightRemaining < 0) {
							if (!isRealLeft)
								Log.Warning($"k={k}: segment {nextSegmentId} ({prevSegment}) is not left. rightRemaining={rightRemaining}. hasStraight={hasStraight}, hasLeft={hasLeft}. realRSL: {isRealLeft},{isRealStraight},{isRealRight}");
						} else if (!hasLeft) {
							if (!isRealStraight)
								Log.Warning($"k={k}: segment {nextSegmentId} ({prevSegment}) is not straight. rightRemaining={rightRemaining}. hasStraight={hasStraight}, hasLeft={hasLeft}. realRSL: {isRealLeft},{isRealStraight},{isRealRight}");
						}
					}*/

					// NON-STOCK CODE START //
					byte incomingVehicleLanes = 0;
					if (Options.allRelaxed || (Options.relaxedBusses && _transportVehicle)) {
						// NON-STOCK CODE END //
						if (ProcessItem(debug, item, nextNodeId, nextSegmentId, ref instance.m_segments.m_buffer[nextSegmentId], ref similarLaneIndexFromLeft, connectOffset, true, enablePedestrian)) {
							blocked = true;
						}
						// NON-STOCK CODE START //
					}  else if (!enablePedestrian) {
						try {
							var nextSegment = instance.m_segments.m_buffer[nextSegmentId];
							var nextSegmentInfo = nextSegment.Info;
							bool isRight = rightRemaining > 0;
							bool isStraight = rightRemaining == 0 && hasStraight;
							bool isLeft = !isRight & !isStraight;

							VehicleInfo.VehicleType vehicleType2 = this._vehicleTypes;
							NetInfo.LaneType drivingEnabledLaneTypes = this._laneTypes;
							drivingEnabledLaneTypes &= ~NetInfo.LaneType.Pedestrian;
							drivingEnabledLaneTypes &= ~NetInfo.LaneType.Parking;

							if (debug) {
								Log.Message($"Path finding ({this._pathFindIndex}): Segment {nextSegmentId}: rightRemaining: {rightRemaining}");
							}

							NetInfo.Direction nextDir = nextSegment.m_startNode != nextNodeId ? NetInfo.Direction.Forward : NetInfo.Direction.Backward;
							NetInfo.Direction nextDir2 = ((nextSegment.m_flags & NetSegment.Flags.Invert) == NetSegment.Flags.None) ? nextDir : NetInfo.InvertDirection(nextDir);

							// valid next lanes:
							int[] laneIndexes = new int[16]; // index of NetNode.Info.m_lanes
							uint[] laneIds = new uint[16]; // index of NetManager.m_lanes.m_buffer
							uint[] indexByRightSimilarLaneIndex = new uint[16];
							uint[] indexByLeftSimilarLaneIndex = new uint[16];

							bool laneArrowsDefined = false;
							uint curLaneI = 0;
							uint curLaneId = nextSegment.m_lanes;
							int i = 0;
							while (i < nextSegmentInfo.m_lanes.Length && curLaneId != 0u) {
								// determine valid lanes based on lane arrows
								NetInfo.Lane nextLane = nextSegmentInfo.m_lanes[i];

								if ((byte)(nextLane.m_finalDirection & nextDir2) != 0 && nextLane.CheckType(_laneTypes, _vehicleTypes)) {
									if (nextLane.CheckType(drivingEnabledLaneTypes, _vehicleTypes))
										++incomingVehicleLanes;
									if (debug) {
										Log.Message($"Path finding ({this._pathFindIndex}): Segment {nextSegmentId}, lane {curLaneId}, {i} is compatible (prevSegment: {prevSegment}). laneTypes: {_laneTypes.ToString()}, vehicleTypes: {_vehicleTypes.ToString()}, incomingLanes={incomingVehicleLanes}");
									}

									// calculate current similar lane index starting from right line
									int nextRightSimilarLaneIndex;
									int nextLeftSimilarLaneIndex;
									if ((byte)(nextLane.m_direction & normDirection) != 0) {
										nextRightSimilarLaneIndex = nextLane.m_similarLaneIndex;
										nextLeftSimilarLaneIndex = nextLane.m_similarLaneCount - nextLane.m_similarLaneIndex - 1;
									} else {
										nextRightSimilarLaneIndex = nextLane.m_similarLaneCount - nextLane.m_similarLaneIndex - 1;
										nextLeftSimilarLaneIndex = nextLane.m_similarLaneIndex;
									}

									if (((NetLane.Flags)instance.m_lanes.m_buffer[curLaneId].m_flags & NetLane.Flags.LeftForwardRight) != NetLane.Flags.None) {
										laneArrowsDefined = true;
									}

									if (isRight) {// TrafficPriority.IsLeftSegment(nextSegmentId, item.m_position.m_segment, targetNodeId)) {
										if (((NetLane.Flags)instance.m_lanes.m_buffer[curLaneId].m_flags & NetLane.Flags.Left) ==
											NetLane.Flags.Left) {
											laneIndexes[curLaneI] = i;
											laneIds[curLaneI] = curLaneId;
											indexByRightSimilarLaneIndex[nextRightSimilarLaneIndex] = curLaneI + 1;
											indexByLeftSimilarLaneIndex[nextLeftSimilarLaneIndex] = curLaneI + 1;
											curLaneI++;
										}
									} else if (isLeft) { // if (TrafficPriority.IsRightSegment(nextSegmentId, item.m_position.m_segment, targetNodeId)) {
										if (((NetLane.Flags)instance.m_lanes.m_buffer[curLaneId].m_flags & NetLane.Flags.Right) ==
											NetLane.Flags.Right) {
											laneIndexes[curLaneI] = i;
											laneIds[curLaneI] = curLaneId;
											indexByRightSimilarLaneIndex[nextRightSimilarLaneIndex] = curLaneI + 1;
											indexByLeftSimilarLaneIndex[nextLeftSimilarLaneIndex] = curLaneI + 1;
											curLaneI++;
										}
									} else {
										if (((NetLane.Flags)instance.m_lanes.m_buffer[curLaneId].m_flags & NetLane.Flags.Forward) != NetLane.Flags.None || ((NetLane.Flags)instance.m_lanes.m_buffer[curLaneId].m_flags & NetLane.Flags.LeftForwardRight) == NetLane.Flags.None) { // valid if straight segment and no arrows given or forward arrow is set
											laneIndexes[curLaneI] = i;
											laneIds[curLaneI] = curLaneId;
											indexByRightSimilarLaneIndex[nextRightSimilarLaneIndex] = curLaneI + 1;
											indexByLeftSimilarLaneIndex[nextLeftSimilarLaneIndex] = curLaneI + 1;
											curLaneI++;
										}
									}
								}

								curLaneId = instance.m_lanes.m_buffer[(int)((UIntPtr)curLaneId)].m_nextLane;
								i++;
							} // foreach lane

							if (laneArrowsDefined) {
								var newLaneIndex = 0;
								var newLaneId = 0u;
								int nextLaneI = -1;
								int nextCompatibleLaneCount = Convert.ToInt32(curLaneI);

								if (debug) {
									Log.Message($"Path finding ({this._pathFindIndex}): Lane arrows defined.");
								}

								if (curLaneI > 0) {
									if (Options.highwayRules && prevIsOutgoingOneWay && prevIsHighway && nextIsJunction) {
										if (isLeft) {
											// right segment joins with highway: find directly matching lanes from right
											nextLaneI = Convert.ToInt32(indexByRightSimilarLaneIndex[prevRightSimilarLaneIndex]) - 1;
										} else if (isRight) {
											// left segment joins with highway: find directly matching lanes from left
											nextLaneI = Convert.ToInt32(indexByLeftSimilarLaneIndex[prevLeftSimilarLaneIndex]) - 1;
										} else {
											// straight segment
											if (hasLeft && hasRight) {
#if DEBUG
												if (debug)
													Log.Message($"Pathfind ({this._pathFindIndex}) prevLeftSimilarLaneIndex: {prevLeftSimilarLaneIndex}, totalIncomingLanes: {totalIncomingLanes}, node: {nextNodeId}, prev segment: {prevSegment}, next segment: {nextSegmentId}");
#endif
												int nextLeftSimilarIndex = prevLeftSimilarLaneIndex - totalIncomingLanes;
												if (nextLeftSimilarIndex >= 0 && nextLeftSimilarIndex < curLaneI)
													nextLaneI = Convert.ToInt32(indexByLeftSimilarLaneIndex[nextLeftSimilarIndex]) - 1;
											} else if (hasLeft) {
												// sort right
												nextLaneI = Convert.ToInt32(indexByLeftSimilarLaneIndex[prevLeftSimilarLaneIndex]) - 1;
											} else {
												// sort left
												nextLaneI = Convert.ToInt32(indexByRightSimilarLaneIndex[prevRightSimilarLaneIndex]) - 1;
											}
										}
										if (nextLaneI < 0 || nextLaneI >= nextCompatibleLaneCount)
											goto nextIter; // no path to this lane
									} else if (curLaneI == 1) {
										nextLaneI = 0;
									} else {
										// lane matching
										int prevSimilarLaneCount = lane.m_similarLaneCount;

										int nextRightSimilarLaneIndex = -1;
										int x = 0;
										if (nextIsJunction) {
											// at junctions: try to match distinct lanes (1-to-1, n-to-1)
											x = prevRightSimilarLaneIndex;
										} else {
											HandleLaneMergesAndSplits(prevRightSimilarLaneIndex, nextCompatibleLaneCount, prevSimilarLaneCount, out nextRightSimilarLaneIndex, out x);
										}

										// find best matching lane
										for (int j = 0; j < 16; ++j) {
											if (indexByRightSimilarLaneIndex[j] == 0)
												continue;
											nextLaneI = Convert.ToInt32(indexByRightSimilarLaneIndex[j]) - 1;
											nextRightSimilarLaneIndex = j;
											if (x == 0) { // matching lane found
												break;
											}
											--x;
										}
#if DEBUG
										if (debug) {
											Log.Message($"Path finding ({this._pathFindIndex}): Exploring path from {nextSegmentId} ({nextDir}) to {item.m_position.m_segment}, lane id {item.m_position.m_lane}, {prevRightSimilarLaneIndex} from right. There are {curLaneI} candidate lanes. We choose lane {nextLaneI} (index {newLaneIndex}, id {newLaneId}, {nextRightSimilarLaneIndex} from right). lhd: {TrafficPriority.LeftHandDrive}, ped: {pedestrianAllowed}, magical flag4: {blocked}");
										}
#endif
									}
								} else {
#if DEBUG
									if (debug) {
										Log.Message($"Path finding ({this._pathFindIndex}): Exploring path from {nextSegmentId} ({nextDir}) to {item.m_position.m_segment}, lane id {item.m_position.m_lane}, {prevRightSimilarLaneIndex} from right: No compatible lanes found");
									}
#endif
									goto nextIter;
								}

								// go to matched lane
								newLaneIndex = laneIndexes[nextLaneI];
								newLaneId = laneIds[nextLaneI];

								if (ProcessItem(debug, item, nextNodeId, nextSegmentId, ref instance.m_segments.m_buffer[nextSegmentId], ref similarLaneIndexFromLeft, connectOffset, true, enablePedestrian, newLaneIndex, newLaneId, out foundForced))
									blocked = true;

								if (foundForced) {
#if DEBUG
									if (debug) {
										Log.Message($"Path finding ({this._pathFindIndex}): Exploring path from {nextSegmentId} ({nextDir}) to {item.m_position.m_segment}, lane id {item.m_position.m_lane}, {prevRightSimilarLaneIndex} from right: FORCED LANE FOUND!");
									}
#endif
								}
							} else {
#if DEBUG
								if (debug) {
									Log.Message($"Path finding ({this._pathFindIndex}): Exploring path from {nextSegmentId} ({nextDir}) to {item.m_position.m_segment}, lane id {item.m_position.m_lane}, {prevRightSimilarLaneIndex} from right: No lane arrows defined");
								}
#endif

								if (ProcessItem(debug, item, nextNodeId, nextSegmentId, ref instance.m_segments.m_buffer[nextSegmentId], ref similarLaneIndexFromLeft, connectOffset, true, enablePedestrian)) {
									blocked = true;
								}
							}
						} catch (Exception e) {
							Log.Error($"Error occurred in custom path-finding (main): {e.ToString()}");

							// stock code fallback
							if (this.ProcessItem(debug, item, nextNodeId, nextSegmentId, ref instance.m_segments.m_buffer[(int)nextSegmentId], ref similarLaneIndexFromLeft, connectOffset, true, enablePedestrian)) {
								blocked = true;
							}
						}
						// NON-STOCK CODE END
					} else {
						// stock code:
						if (this.ProcessItem(debug, item, nextNodeId, nextSegmentId, ref instance.m_segments.m_buffer[(int)nextSegmentId], ref similarLaneIndexFromLeft, connectOffset, true, enablePedestrian)) {
							blocked = true;
						}
					}

					nextIter:
					nextSegmentId = instance.m_segments.m_buffer[(int)nextSegmentId].GetRightSegment(nextNodeId);
					totalIncomingLanes += incomingVehicleLanes;
					--rightRemaining;
				} // foreach segment
				if (blocked) {
#if DEBUG
						if (debug) {
							Log.Message($"Path finding ({this._pathFindIndex}): Exploring path from {nextSegmentId} to {item.m_position.m_segment}, lane id {item.m_position.m_lane}, {prevRightSimilarLaneIndex} from right: Road may be blocked");
						}
#endif
					// vehicles may turn around if the street is blocked
					nextSegmentId = item.m_position.m_segment;
					this.ProcessItem(debug, item, nextNodeId, nextSegmentId, ref instance.m_segments.m_buffer[(int)nextSegmentId], ref similarLaneIndexFromLeft, connectOffset, true, false);
				}
				// NON-STOCK CODE START
				/*if (foundForced)
					return;*/
				// NON-STOCK CODE END
				if (pedestrianAllowed) {
#if DEBUG
						if (debug) {
							Log.Message($"Path finding ({this._pathFindIndex}): Exploring path from {nextSegmentId} to {item.m_position.m_segment}, lane id {item.m_position.m_lane}, {prevRightSimilarLaneIndex} from right: Ped allowed");
						}
#endif
					nextSegmentId = item.m_position.m_segment;
					int laneIndex4;
					uint lane6;
					if (instance.m_segments.m_buffer[(int)nextSegmentId].GetClosestLane((int)item.m_position.m_lane, NetInfo.LaneType.Pedestrian, this._vehicleTypes, out laneIndex4, out lane6)) {
						this.ProcessItemPedBicycle(item, nextNodeId, nextSegmentId, ref instance.m_segments.m_buffer[(int)nextSegmentId], connectOffset3, laneIndex4, lane6); // ped
					}
				}
			}
			if (nextNode.m_lane != 0u) {
				bool targetDisabled = (nextNode.m_flags & NetNode.Flags.Disabled) != NetNode.Flags.None;
				ushort segment4 = instance.m_lanes.m_buffer[(int)((UIntPtr)nextNode.m_lane)].m_segment;
				if (segment4 != 0 && segment4 != item.m_position.m_segment) {
#if DEBUG
						if (debug) {
							Log.Message($"Path finding ({this._pathFindIndex}): Exploring path from {segment4} to {item.m_position.m_segment}, lane id {item.m_position.m_lane}: handling special lanes");
						}
#endif
					this.ProcessItem(item, nextNodeId, targetDisabled, segment4, ref instance.m_segments.m_buffer[(int)segment4], nextNode.m_lane, nextNode.m_laneOffset, connectOffset);
				}
			}
		}
Exemplo n.º 11
0
            /// <summary>
            /// This method is called when wav device generates some event.
            /// </summary>
            /// <param name="hdrvr">Handle to the waveform-audio device associated with the callback.</param>
            /// <param name="uMsg">Waveform-audio input message.</param>
            /// <param name="dwUser">User-instance data specified with waveOutOpen.</param>
            /// <param name="dwParam1">Message parameter.</param>
            /// <param name="dwParam2">Message parameter.</param>
            private void OnWaveInProc(IntPtr hdrvr,int uMsg,int dwUser,int dwParam1,int dwParam2)
            {   
                // NOTE: MSDN warns, we may not call any wav related methods here.
                // This will cause deadlock.

                if(m_IsDisposed){
                    return;
                }

                // Do we need to lock here ? OnWaveInProc may be called for another buffer same time when we are here ?

                lock(m_pLock){
                    try{
                        if(uMsg == WavConstants.MM_WIM_DATA){
                            // Queue data for reading.
                            m_pReadBuffer.Write(m_pCurrentBuffer.Data,0,m_pCurrentBuffer.Data.Length,true);

                            BufferItem buffer = m_pCurrentBuffer;

                            m_pCurrentBuffer = m_pBuffers.Next();

                            // Free buffer and queue it for reuse.
                            ThreadPool.QueueUserWorkItem(new WaitCallback(delegate(object state){
                                try{
                                    if(m_IsDisposed){
                                        return;
                                    }

                                    // Prepare buffer for reuse.
                                    waveInUnprepareHeader(m_pWavDevHandle,buffer.HeaderHandle.AddrOfPinnedObject(),Marshal.SizeOf(buffer.Header));
                                    // Prepare new buffer.
                                    waveInPrepareHeader(m_pWavDevHandle,buffer.HeaderHandle.AddrOfPinnedObject(),Marshal.SizeOf(buffer.Header));
                                    // Append buffer for recording.
                                    waveInAddBuffer(m_pWavDevHandle,buffer.HeaderHandle.AddrOfPinnedObject(),Marshal.SizeOf(buffer.Header));
                                }
                                catch{
                                }
                            }));
                        }
                    }
                    catch{
                    }
                }
            }
 protected virtual void ProcessItem(BufferItem item, ushort targetNode, bool targetDisabled, ushort segmentID, ref NetSegment segment, uint lane, byte offset, byte connectOffset)
 {
     if ((segment.m_flags & (NetSegment.Flags.PathFailed | NetSegment.Flags.Flooded)) != NetSegment.Flags.None)
     {
         return;
     }
     NetManager instance = Singleton<NetManager>.instance;
     if (targetDisabled && ((instance.m_nodes.m_buffer[(int)segment.m_startNode].m_flags | instance.m_nodes.m_buffer[(int)segment.m_endNode].m_flags) & NetNode.Flags.Disabled) == NetNode.Flags.None)
     {
         return;
     }
     NetInfo info = segment.Info;
     NetInfo info2 = instance.m_segments.m_buffer[(int)item.m_position.m_segment].Info;
     int num = info.m_lanes.Length;
     uint num2 = segment.m_lanes;
     float num3 = 1f;
     float num4 = 1f;
     NetInfo.LaneType laneType = NetInfo.LaneType.None;
     if ((int)item.m_position.m_lane < info2.m_lanes.Length)
     {
         NetInfo.Lane lane2 = info2.m_lanes[(int)item.m_position.m_lane];
         num3 = lane2.m_speedLimit;
         laneType = lane2.m_laneType;
         if ((byte)(laneType & (NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle)) != 0)
         {
             laneType = (NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle);
         }
         num4 = this.CalculateLaneSpeed(connectOffset, item.m_position.m_offset, ref instance.m_segments.m_buffer[(int)item.m_position.m_segment], lane2);
     }
     float averageLength = instance.m_segments.m_buffer[(int)item.m_position.m_segment].m_averageLength;
     float num5 = (float)Mathf.Abs((int)(connectOffset - item.m_position.m_offset)) * 0.003921569f * averageLength;
     float num6 = item.m_methodDistance + num5;
     float num7 = item.m_comparisonValue + num5 / (num4 * this.m_maxLength);
     Vector3 b = instance.m_lanes.m_buffer[(int)((UIntPtr)item.m_laneID)].CalculatePosition((float)connectOffset * 0.003921569f);
     int num8 = 0;
     while (num8 < num && num2 != 0u)
     {
         if (lane == num2)
         {
             NetInfo.Lane lane3 = info.m_lanes[num8];
             if (lane3.CheckType(this.m_laneTypes, this.m_vehicleTypes))
             {
                 Vector3 a = instance.m_lanes.m_buffer[(int)((UIntPtr)lane)].CalculatePosition((float)offset * 0.003921569f);
                 float num9 = Vector3.Distance(a, b);
                 BufferItem item2;
                 item2.m_position.m_segment = segmentID;
                 item2.m_position.m_lane = (byte)num8;
                 item2.m_position.m_offset = offset;
                 if ((byte)(lane3.m_laneType & laneType) == 0)
                 {
                     item2.m_methodDistance = 0f;
                 }
                 else
                 {
                     item2.m_methodDistance = num6 + num9;
                 }
                 if (lane3.m_laneType != NetInfo.LaneType.Pedestrian || item2.m_methodDistance < 1000f)
                 {
                     item2.m_comparisonValue = num7 + num9 / ((num3 + lane3.m_speedLimit) * 0.5f * this.m_maxLength);
                     if ((segment.m_flags & NetSegment.Flags.Invert) != NetSegment.Flags.None)
                     {
                         item2.m_direction = NetInfo.InvertDirection(lane3.m_finalDirection);
                     }
                     else
                     {
                         item2.m_direction = lane3.m_finalDirection;
                     }
                     if (lane == this.m_startLaneA)
                     {
                         if (((byte)(item2.m_direction & NetInfo.Direction.Forward) == 0 || item2.m_position.m_offset < this.m_startOffsetA) && ((byte)(item2.m_direction & NetInfo.Direction.Backward) == 0 || item2.m_position.m_offset > this.m_startOffsetA))
                         {
                             return;
                         }
                         float num10 = this.CalculateLaneSpeed(this.m_startOffsetA, item2.m_position.m_offset, ref segment, lane3);
                         float num11 = (float)Mathf.Abs((int)(item2.m_position.m_offset - this.m_startOffsetA)) * 0.003921569f;
                         item2.m_comparisonValue += num11 * segment.m_averageLength / (num10 * this.m_maxLength);
                     }
                     if (lane == this.m_startLaneB)
                     {
                         if (((byte)(item2.m_direction & NetInfo.Direction.Forward) == 0 || item2.m_position.m_offset < this.m_startOffsetB) && ((byte)(item2.m_direction & NetInfo.Direction.Backward) == 0 || item2.m_position.m_offset > this.m_startOffsetB))
                         {
                             return;
                         }
                         float num12 = this.CalculateLaneSpeed(this.m_startOffsetB, item2.m_position.m_offset, ref segment, lane3);
                         float num13 = (float)Mathf.Abs((int)(item2.m_position.m_offset - this.m_startOffsetB)) * 0.003921569f;
                         item2.m_comparisonValue += num13 * segment.m_averageLength / (num12 * this.m_maxLength);
                     }
                     item2.m_laneID = lane;
                     item2.m_lanesUsed = (item.m_lanesUsed | lane3.m_laneType);
                     this.AddBufferItem(item2, item.m_position);
                 }
             }
             return;
         }
         num2 = instance.m_lanes.m_buffer[(int)((UIntPtr)num2)].m_nextLane;
         num8++;
     }
 }
 protected virtual void AddBufferItem(BufferItem item, PathUnit.Position target)
 {
     uint num = this.m_laneLocation[(int)((UIntPtr)item.m_laneID)];
     uint num2 = num >> 16;
     int num3 = (int)(num & 65535u);
     int num6;
     if (num2 == this.m_pathFindIndex)
     {
         if (item.m_comparisonValue >= this.m_buffer[num3].m_comparisonValue)
         {
             return;
         }
         int num4 = num3 >> 6;
         int num5 = num3 & -64;
         if (num4 < this.m_bufferMinPos || (num4 == this.m_bufferMinPos && num5 < this.m_bufferMin[num4]))
         {
             return;
         }
         num6 = Mathf.Max(Mathf.RoundToInt(item.m_comparisonValue * 1024f), this.m_bufferMinPos);
         if (num6 == num4)
         {
             this.m_buffer[num3] = item;
             this.m_laneTarget[(int)((UIntPtr)item.m_laneID)] = target;
             return;
         }
         int num7 = num4 << 6 | this.m_bufferMax[num4]--;
         BufferItem bufferItem = this.m_buffer[num7];
         this.m_laneLocation[(int)((UIntPtr)bufferItem.m_laneID)] = num;
         this.m_buffer[num3] = bufferItem;
     }
     else
     {
         num6 = Mathf.Max(Mathf.RoundToInt(item.m_comparisonValue * 1024f), this.m_bufferMinPos);
     }
     if (num6 >= 1024)
     {
         return;
     }
     while (this.m_bufferMax[num6] == 63)
     {
         num6++;
         if (num6 == 1024)
         {
             return;
         }
     }
     if (num6 > this.m_bufferMaxPos)
     {
         this.m_bufferMaxPos = num6;
     }
     num3 = (num6 << 6 | ++this.m_bufferMax[num6]);
     this.m_buffer[num3] = item;
     this.m_laneLocation[(int)((UIntPtr)item.m_laneID)] = (this.m_pathFindIndex << 16 | (uint)num3);
     this.m_laneTarget[(int)((UIntPtr)item.m_laneID)] = target;
 }
Exemplo n.º 14
0
 /// <summary>
 /// Fills recording buffers.
 /// </summary>
 private void CreateBuffers()
 {               
     while(m_pBuffers.Count < 10){
         BufferItem bufferItem = new BufferItem(m_pWavDevHandle,m_BufferSize);                    
         m_pBuffers.Add(bufferItem.HeaderHandle.AddrOfPinnedObject().ToInt64(),bufferItem);
         bufferItem.Queue(false);
     } 
 }
Exemplo n.º 15
0
		private void AddBufferItem(BufferItem item, PathUnit.Position target) {
			//bCurrentState = 0;
#if DEBUGPF
			/*if (m_queuedPathFindCount > 100 && Options.disableSomething1)
				Log._Debug($"THREAD #{Thread.CurrentThread.ManagedThreadId} PF {this._pathFindIndex}: AddBufferItem item {item.m_position.m_segment} {item.m_position.m_lane}");*/
#endif

			uint num = _laneLocation[(int)((UIntPtr)item.m_laneID)];
			uint num2 = num >> 16;
			int num3 = (int)(num & 65535u);
			int comparisonBufferPos;
			if (num2 == _pathFindIndex) {
				//bCurrentState = 1;
				if (item.m_comparisonValue >= _buffer[num3].m_comparisonValue) {
					return;
				}
				//bCurrentState = 2;
				int num4 = num3 >> 6;
				int num5 = num3 & -64;
				if (num4 < _bufferMinPos || (num4 == _bufferMinPos && num5 < _bufferMin[num4])) {
					return;
				}
				//bCurrentState = 3;
				comparisonBufferPos = Mathf.Max(Mathf.RoundToInt(item.m_comparisonValue * 1024f), _bufferMinPos);
				if (comparisonBufferPos == num4) {
					_buffer[num3] = item;
					_laneTarget[(int)((UIntPtr)item.m_laneID)] = target;
					return;
				}
				//bCurrentState = 4;
				int num7 = num4 << 6 | _bufferMax[num4]--;
				BufferItem bufferItem = _buffer[num7];
				_laneLocation[(int)((UIntPtr)bufferItem.m_laneID)] = num;
				_buffer[num3] = bufferItem;
				//bCurrentState = 5;
			} else {
				//bCurrentState = 6;
				comparisonBufferPos = Mathf.Max(Mathf.RoundToInt(item.m_comparisonValue * 1024f), _bufferMinPos);
			}
			//bCurrentState = 7;
			if (comparisonBufferPos >= 1024) {
				return;
			}
			//bCurrentState = 8;
			if (comparisonBufferPos < 0) {
#if DEBUG
				Log.Error("comparisonBufferPos < 0!");
#endif
				return;
			}
			//bCurrentState = 9;
			while (_bufferMax[comparisonBufferPos] == 63) {
				//bCurrentState = 10;
				comparisonBufferPos++;
				if (comparisonBufferPos == 1024) {
					//bCurrentState = 11;
					return;
				}
			}
			//bCurrentState = 12;
			if (comparisonBufferPos > _bufferMaxPos) {
				_bufferMaxPos = comparisonBufferPos;
			}
			//bCurrentState = 13;
			num3 = (comparisonBufferPos << 6 | ++_bufferMax[comparisonBufferPos]);
			_buffer[num3] = item;
			_laneLocation[(int)((UIntPtr)item.m_laneID)] = (_pathFindIndex << 16 | (uint)num3);
			_laneTarget[(int)((UIntPtr)item.m_laneID)] = target;
			//bCurrentState = 14;
		}
Exemplo n.º 16
0
		// 3
		private bool ProcessItemCosts(bool allowCustomLaneChanging, bool debug, BufferItem item, ushort targetNodeId, ushort nextSegmentId, ref NetSegment nextSegment, ref int laneIndexFromLeft, byte connectOffset, bool enableVehicle, bool enablePedestrian, int? forceLaneIndex, uint? forceLaneId, out bool foundForced) {
			//sCurrentState = 0;
#if DEBUGPF
			/*if (Options.disableSomething1)
				Log._Debug($"THREAD #{Thread.CurrentThread.ManagedThreadId} PF {this._pathFindIndex}: ProcessItemSub item {item.m_position.m_segment} {item.m_position.m_lane}, targetNodeId {targetNodeId}");*/
#endif

			//debug = targetNodeId == 6900;
			foundForced = false;
			bool result = false;
			if ((nextSegment.m_flags & (NetSegment.Flags.PathFailed | NetSegment.Flags.Flooded)) != NetSegment.Flags.None) {
				return result;
			}
			NetManager instance = Singleton<NetManager>.instance;
			NetInfo nextSegmentInfo = nextSegment.Info;
			NetInfo prevSegmentInfo = instance.m_segments.m_buffer[(int)item.m_position.m_segment].Info;
			int nextNumLanes = nextSegmentInfo.m_lanes.Length;
			NetInfo.Direction nextDir = (targetNodeId != nextSegment.m_startNode) ? NetInfo.Direction.Forward : NetInfo.Direction.Backward;
			NetInfo.Direction nextDir2 = ((nextSegment.m_flags & NetSegment.Flags.Invert) == NetSegment.Flags.None) ? nextDir : NetInfo.InvertDirection(nextDir);
			float num3 = 0.01f - Mathf.Min(nextSegmentInfo.m_maxTurnAngleCos, prevSegmentInfo.m_maxTurnAngleCos);
			//sCurrentState = 1;
			if (num3 < 1f) {
				Vector3 vector;
				if (targetNodeId == instance.m_segments.m_buffer[(int)item.m_position.m_segment].m_startNode) {
					vector = instance.m_segments.m_buffer[(int)item.m_position.m_segment].m_startDirection;
				} else {
					vector = instance.m_segments.m_buffer[(int)item.m_position.m_segment].m_endDirection;
				}
				Vector3 vector2;
				if ((byte)(nextDir & NetInfo.Direction.Forward) != 0) {
					vector2 = nextSegment.m_endDirection;
				} else {
					vector2 = nextSegment.m_startDirection;
				}
				float num4 = vector.x * vector2.x + vector.z * vector2.z;
				if (num4 >= num3) {
					return result;
				}
			}
			//sCurrentState = 2;
			float prevMaxSpeed = 1f;
			float prevLaneSpeed = 1f;
			NetInfo.LaneType laneType = NetInfo.LaneType.None;
			VehicleInfo.VehicleType vehicleType = VehicleInfo.VehicleType.None;
			// NON-STOCK CODE START //
			bool prevIsHighway = false;
			if (prevSegmentInfo.m_netAI is RoadBaseAI)
				prevIsHighway = ((RoadBaseAI)prevSegmentInfo.m_netAI).m_highwayRules;
			float nextSpeed = 1f;
			float nextDensity = 0f;
			int prevRightSimilarLaneIndex = -1;
			NetInfo.Direction normDirection = TrafficPriority.IsLeftHandDrive() ? NetInfo.Direction.Forward : NetInfo.Direction.Backward; // direction to normalize indices to
			int prevNumLanes = 1;
			float prevSpeed = 0f;
			bool isMiddle = connectOffset != 0 && connectOffset != 255;
			NetInfo.Lane lane = null;
			//sCurrentState = 3;
			// NON-STOCK CODE END //
			if ((int)item.m_position.m_lane < prevSegmentInfo.m_lanes.Length) {
				lane = prevSegmentInfo.m_lanes[(int)item.m_position.m_lane];
				laneType = lane.m_laneType;
				vehicleType = lane.m_vehicleType;
				prevMaxSpeed = GetLaneSpeedLimit(item.m_position.m_segment, item.m_position.m_lane, item.m_laneID, lane); // SpeedLimitManager.GetLockFreeGameSpeedLimit(item.m_position.m_segment, item.m_position.m_lane, item.m_laneID, ref lane); // NON-STOCK CODE
				prevLaneSpeed = this.CalculateLaneSpeed(prevMaxSpeed, connectOffset, item.m_position.m_offset, ref instance.m_segments.m_buffer[(int)item.m_position.m_segment], lane); // NON-STOCK CODE
				// NON-STOCK CODE START //
				prevNumLanes = lane.m_similarLaneCount;
				if ((byte)(lane.m_direction & normDirection) != 0) {
					prevRightSimilarLaneIndex = lane.m_similarLaneIndex;
				} else {
					prevRightSimilarLaneIndex = lane.m_similarLaneCount - lane.m_similarLaneIndex - 1;
				}
				prevSpeed = CustomRoadAI.laneMeanSpeeds[item.m_laneID];
				prevSpeed = (float)Math.Max(0.1f, Math.Round(prevSpeed * 0.01f * 4f) / 4f); // 0.01, 0.25, 0.5, 0.75, 1
				// NON-STOCK CODE END //
			}
			//sCurrentState = 4;
			bool useAdvancedAI = !Options.isStockLaneChangerUsed() &&
				(_extVehicleType != null &&
				(_extVehicleType & (ExtVehicleType.RoadVehicle & ~ExtVehicleType.RoadPublicTransport)) != ExtVehicleType.None) &&
				allowCustomLaneChanging &&
				!_transportVehicle &&
				!_stablePath &&
				enableVehicle &&
				(vehicleType & VehicleInfo.VehicleType.Car) != VehicleInfo.VehicleType.None &&
				(laneType & (NetInfo.LaneType.PublicTransport | NetInfo.LaneType.Pedestrian | NetInfo.LaneType.Parking)) == NetInfo.LaneType.None; // NON-STOCK CODE
			float cost = instance.m_segments.m_buffer[(int)item.m_position.m_segment].m_averageLength;
			if (!useAdvancedAI && !this._stablePath) { // NON-STOCK CODE
				Randomizer randomizer = new Randomizer(this._pathFindIndex << 16 | (uint)item.m_position.m_segment);
				cost *= (float)(randomizer.Int32(900, 1000 + (int)(instance.m_segments.m_buffer[(int)item.m_position.m_segment].m_trafficDensity * 10)) + this._pathRandomizer.Int32(20u)) * 0.001f;
			}
			if (!useAdvancedAI) {
				if (this._isHeavyVehicle && (instance.m_segments.m_buffer[(int)item.m_position.m_segment].m_flags & NetSegment.Flags.HeavyBan) != NetSegment.Flags.None) {
					cost *= 10f;
				} else if (laneType == NetInfo.LaneType.Vehicle && (vehicleType & _vehicleTypes) == VehicleInfo.VehicleType.Car && (instance.m_segments.m_buffer[(int)item.m_position.m_segment].m_flags & NetSegment.Flags.CarBan) != NetSegment.Flags.None) {
					cost *= 5f;
				}
			}
			if (this._transportVehicle && laneType == NetInfo.LaneType.TransportVehicle) {
				cost *= 0.95f;
				//cost *= Options.someValue2;
			}
			bool avoidLane = false;
			bool strictlyAvoidLane = false;
			if (
					(this._isHeavyVehicle && (nextSegment.m_flags & NetSegment.Flags.HeavyBan) != NetSegment.Flags.None) ||
					(laneType == NetInfo.LaneType.Vehicle && (vehicleType & _vehicleTypes) == VehicleInfo.VehicleType.Car && (instance.m_segments.m_buffer[(int)item.m_position.m_segment].m_flags & NetSegment.Flags.CarBan) != NetSegment.Flags.None)
					) {
				if (Options.disableSomething1 && debug) {
					Log._Debug($"Vehicle {_extVehicleType} should not use lane {item.m_position.m_lane} @ seg. {item.m_position.m_segment}, null? {lane == null}");
				}
				avoidLane = true;
			}
			if (!CanUseLane(debug, item.m_position.m_segment, item.m_position.m_lane, item.m_laneID, lane)) {
				if (Options.disableSomething1 && debug) {
					Log._Debug($"Vehicle {_extVehicleType} must not use lane {item.m_position.m_lane} @ seg. {item.m_position.m_segment}, null? {lane== null}");
				}
				strictlyAvoidLane = true;
			}
			if (!useAdvancedAI) {
				if (strictlyAvoidLane)
					cost *= Options.someValue4;
			}
			if ((byte)(laneType & (NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle)) != 0) {
				laneType = (NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle);
			}
			float prevOffsetCost = (float)Mathf.Abs((int)(connectOffset - item.m_position.m_offset)) * 0.003921569f * cost;
			float prevMethodDist = item.m_methodDistance + prevOffsetCost;
			float prevComparisonPlusOffsetCostOverSpeed = item.m_comparisonValue + prevOffsetCost / (prevLaneSpeed * this._maxLength);
			Vector3 prevLanePosition = instance.m_lanes.m_buffer[(int)((UIntPtr)item.m_laneID)].CalculatePosition((float)connectOffset * 0.003921569f);
			int newLaneIndexFromLeft = laneIndexFromLeft;
			bool transitionNode = (instance.m_nodes.m_buffer[(int)targetNodeId].m_flags & NetNode.Flags.Transition) != NetNode.Flags.None;
			NetInfo.LaneType laneType2 = this._laneTypes;
			VehicleInfo.VehicleType vehicleType2 = this._vehicleTypes;
			if (!enableVehicle) {
				vehicleType2 &= VehicleInfo.VehicleType.Bicycle;
				if (vehicleType2 == VehicleInfo.VehicleType.None) {
					laneType2 &= ~(NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle);
				}
			}
			if (!enablePedestrian) {
				laneType2 &= ~NetInfo.LaneType.Pedestrian;
			}
			// NON-STOCK CODE START //
			//NetNode targetNode = instance.m_nodes.m_buffer[targetNodeId];
			//float segmentDensity = (float)(instance.m_segments.m_buffer[(int)item.m_position.m_segment].m_trafficDensity + nextSegment.m_trafficDensity) / 2f;
			bool nextIsRealJunction = instance.m_nodes.m_buffer[targetNodeId].CountSegments() > 2;
			ushort sourceNodeId = (targetNodeId == instance.m_segments.m_buffer[item.m_position.m_segment].m_startNode) ? instance.m_segments.m_buffer[item.m_position.m_segment].m_endNode : instance.m_segments.m_buffer[item.m_position.m_segment].m_startNode; // no lane changing directly in front of a junction
			bool prevIsRealJunction = instance.m_nodes.m_buffer[sourceNodeId].CountSegments() > 2;
			//sCurrentState = 9;
			bool nextIsHighway = false;
			if (nextSegmentInfo.m_netAI is RoadBaseAI)
				nextIsHighway = ((RoadBaseAI)nextSegmentInfo.m_netAI).m_highwayRules;
			bool wantToChangeLane = false;
			if (useAdvancedAI)
				wantToChangeLane = _pathRandomizer.Int32(1, Options.getLaneChangingRandomizationTargetValue()) == 1;

			float nextDensitySum = 0f;
			if (useAdvancedAI) {
				// measure speed variance
				uint lIndex = 0;
				uint currentLaneId = nextSegment.m_lanes;
				uint nextCompatibleLanes = 0;
				while (lIndex < nextNumLanes && currentLaneId != 0u) {
					NetInfo.Lane nextLane = nextSegmentInfo.m_lanes[lIndex];
					if (nextLane.CheckType(laneType2, vehicleType2) && (nextSegmentId != item.m_position.m_segment || lIndex != (int)item.m_position.m_lane) && (byte)(nextLane.m_finalDirection & nextDir2) != 0) {
						++nextCompatibleLanes;
						nextDensitySum += CustomRoadAI.currentLaneDensities[currentLaneId];
					}

					lIndex++;
					currentLaneId = instance.m_lanes.m_buffer[currentLaneId].m_nextLane;
				}
			}
			// NON-STOCK CODE END //

			uint laneIndex = forceLaneIndex != null ? (uint)forceLaneIndex : 0u;
			uint curLaneId = (uint)(forceLaneId != null ? forceLaneId : nextSegment.m_lanes); // NON-STOCK CODE
																							  //sCurrentState = 10;
			while (laneIndex < nextNumLanes && curLaneId != 0u) {
				//sCurrentState = 11;

				//Log.Message($"PF {this._pathFindIndex} -- CustomPathfind (3): Iter #{laneIndex}, curLaneId={curLaneId}, prevSegment={item.m_position.m_segment}, targetNodeId={targetNodeId}");

				// NON-STOCK CODE START //
				if (forceLaneIndex != null && laneIndex != forceLaneIndex)
					break;
				// NON-STOCK CODE END //
				NetInfo.Lane nextLane = nextSegmentInfo.m_lanes[laneIndex];

#if DEBUGCOSTS
				bool costDebug = debug;
				//bool costDebug = Options.disableSomething1 && (nextSegmentId == 9649 || nextSegmentId == 1043);
				List<String> logBuf = null;
				if (costDebug) {
					logBuf = new List<String>();
					logBuf.Add($"Path from {nextSegmentId} (idx {laneIndex}, id {curLaneId}) to {item.m_position.m_segment} (lane {prevRightSimilarLaneIndex} from right, idx {item.m_position.m_lane}): costDebug=TRUE, explore? {nextLane.CheckType(laneType2, vehicleType2)} && {(nextSegmentId != item.m_position.m_segment || laneIndex != (int)item.m_position.m_lane)} && {(byte)(nextLane.m_finalDirection & nextDir2) != 0 && CanLanesConnect(curLaneId, item.m_laneID)}");
				}
#endif

				if ((byte)(nextLane.m_finalDirection & nextDir2) != 0 && CanLanesConnect(curLaneId, item.m_laneID)) {
					//sCurrentState = 12;
					if (nextLane.CheckType(laneType2, vehicleType2) && (nextSegmentId != item.m_position.m_segment || laneIndex != (int)item.m_position.m_lane) && (byte)(nextLane.m_finalDirection & nextDir2) != 0) {
						// NON-STOCK CODE START //
						float nextMaxSpeed = GetLaneSpeedLimit(nextSegmentId, laneIndex, curLaneId, nextLane);// SpeedLimitManager.GetLockFreeGameSpeedLimit(segmentID, laneIndex, curLaneId, ref nextLane);
						bool addCustomTrafficCosts = useAdvancedAI && curLaneId != this._startLaneA && curLaneId != this._startLaneB && curLaneId != this._endLaneA && curLaneId != this._endLaneB && (byte)(nextLane.m_laneType & laneType) != 0 && (nextLane.m_vehicleType & VehicleInfo.VehicleType.Car) != VehicleInfo.VehicleType.None && (nextLane.m_laneType & NetInfo.LaneType.PublicTransport) == NetInfo.LaneType.None;

						if (addCustomTrafficCosts) {
							nextSpeed = CustomRoadAI.laneMeanSpeeds[curLaneId];
							nextSpeed = (float)Math.Max(0.1f, Math.Round(nextSpeed * 0.01f * 4f) / 4f); // 0.01, 0.25, 0.5, 0.75, 1
							if (nextDensitySum <= 0f)
								nextDensity = 0.01f;
							else {
								nextDensity = Math.Min(1f, (float)CustomRoadAI.currentLaneDensities[curLaneId] / nextDensitySum);
								nextDensity = (float)Math.Max(0.01f, Math.Round(nextDensity * 4f) / 4f); // 0.01, 0.25, 0.5, 0.75, 1
							}

							/*if (Options.disableSomething4) {
								Log._Debug($"nextSegment={nextSegmentId} laneIndex={laneIndex} nextDensitySum={nextDensitySum} nextDensity={(float)CustomRoadAI.currentLaneDensities[curLaneId]} / {nextDensitySum} = {nextDensity}");
							}*/
						}
						// NON-STOCK CODE END //

						//sCurrentState = 13;
						float distanceOnBezier = 0f;

						Vector3 a;
						Vector3 b;

						// NON-STOCK CODE START //
						/*if (customLaneChanging) {
							a = instance.m_nodes.m_buffer[targetNodeId].m_position;
							b = meanPrevLanePosition;
							distanceOnBezier = Vector3.Distance(a, b);
						} else {*/
							// NON-STOCK CODE END //
							if ((byte)(nextDir & NetInfo.Direction.Forward) != 0) {
								a = instance.m_lanes.m_buffer[(int)((UIntPtr)curLaneId)].m_bezier.d;
							} else {
								a = instance.m_lanes.m_buffer[(int)((UIntPtr)curLaneId)].m_bezier.a;
							}
							b = prevLanePosition;
							distanceOnBezier = Vector3.Distance(a, b);

						// NON-STOCK CODE START //
						//}
						// NON-STOCK CODE END //

						//sCurrentState = 14;
						//sCurrentState = 15;
						/*if (targetNodeId == 17415) {*/
						//Log.Message($">> PF {this._pathFindIndex} -- Calculated distance: " + distanceOnBezier + " Original distance: " + Vector3.Distance(a1, b1) + " New distance: " + Vector3.Distance(a2, b2) + " next segment: " + segmentID + " from segment: " + item.m_position.m_segment + " a1: " + a1.ToString() + " b1: " + b1.ToString() + " a2: " + a2.ToString() + " b2: " + b2.ToString());
						/*}*/

#if DEBUGCOSTS
						if (costDebug)
							logBuf.Add($"ProcessItemCosts: costs from {nextSegmentId} (off {(byte)(((nextDir & NetInfo.Direction.Forward) == 0) ? 0 : 255)}) to {item.m_position.m_segment} (off {item.m_position.m_offset}), connectOffset={connectOffset}: distanceOnBezier={distanceOnBezier}");
#endif

						if (transitionNode) {
							distanceOnBezier *= 2f;
						}

						//sCurrentState = 16;
						float distanceOverMeanMaxSpeed = distanceOnBezier / ((prevMaxSpeed + nextMaxSpeed) * 0.5f * this._maxLength);
						BufferItem nextItem;
						nextItem.m_position.m_segment = nextSegmentId;
						nextItem.m_position.m_lane = (byte)laneIndex;
						nextItem.m_position.m_offset = (byte)(((nextDir & NetInfo.Direction.Forward) == 0) ? 0 : 255);
						if ((byte)(nextLane.m_laneType & laneType) == 0) {
							nextItem.m_methodDistance = 0f;
						} else {
							nextItem.m_methodDistance = prevMethodDist + distanceOnBezier;
						}

						if (nextLane.m_laneType != NetInfo.LaneType.Pedestrian || nextItem.m_methodDistance < 1000f) {
							//sCurrentState = 17;
							// NON-STOCK CODE START //
							// apply vehicle restrictions
							if (!addCustomTrafficCosts) {
								nextItem.m_comparisonValue = prevComparisonPlusOffsetCostOverSpeed + distanceOverMeanMaxSpeed;
							} else {
								nextItem.m_comparisonValue = item.m_comparisonValue;
								distanceOnBezier += prevOffsetCost;

								if (strictlyAvoidLane) {
									distanceOnBezier *= Options.someValue4;
								} else if (avoidLane && (_extVehicleType == null || (_extVehicleType & (ExtVehicleType.CargoTruck | ExtVehicleType.PassengerCar)) != ExtVehicleType.None)) {
									distanceOnBezier *= Options.someValue3;
								}

#if DEBUGCOSTS
								if (costDebug) {
									logBuf.Add($"Path from {nextSegmentId} (idx {laneIndex}, id {curLaneId}) to {item.m_position.m_segment} (lane {prevRightSimilarLaneIndex} from right, idx {item.m_position.m_lane}): useAdvancedAI={useAdvancedAI}, addCustomTrafficCosts={addCustomTrafficCosts}, distanceOnBezier={distanceOnBezier} avoidLane={avoidLane} strictlyAvoidLane={strictlyAvoidLane}");
								}
#endif
							}
							// NON-STOCK CODE END //
							nextItem.m_direction = nextDir;
							if (curLaneId == this._startLaneA) {
								if (((byte)(nextItem.m_direction & NetInfo.Direction.Forward) == 0 || nextItem.m_position.m_offset < this._startOffsetA) && ((byte)(nextItem.m_direction & NetInfo.Direction.Backward) == 0 || nextItem.m_position.m_offset > this._startOffsetA)) {
									curLaneId = instance.m_lanes.m_buffer[(int)((UIntPtr)curLaneId)].m_nextLane;
									//sCurrentState = 18;
									goto IL_90F;
								}
								float num15 = this.CalculateLaneSpeed(nextMaxSpeed, this._startOffsetA, nextItem.m_position.m_offset, ref nextSegment, nextLane); // NON-STOCK CODE
								float num16 = (float)Mathf.Abs((int)(nextItem.m_position.m_offset - this._startOffsetA)) * 0.003921569f;
								nextItem.m_comparisonValue += num16 * nextSegment.m_averageLength / (num15 * this._maxLength);
							}
							if (curLaneId == this._startLaneB) {
								if (((byte)(nextItem.m_direction & NetInfo.Direction.Forward) == 0 || nextItem.m_position.m_offset < this._startOffsetB) && ((byte)(nextItem.m_direction & NetInfo.Direction.Backward) == 0 || nextItem.m_position.m_offset > this._startOffsetB)) {
									curLaneId = instance.m_lanes.m_buffer[(int)((UIntPtr)curLaneId)].m_nextLane;
									//sCurrentState = 19;
									goto IL_90F;
								}
								float num17 = this.CalculateLaneSpeed(nextMaxSpeed, this._startOffsetB, nextItem.m_position.m_offset, ref nextSegment, nextLane); // NON-STOCK CODE
								float num18 = (float)Mathf.Abs((int)(nextItem.m_position.m_offset - this._startOffsetB)) * 0.003921569f;
								nextItem.m_comparisonValue += num18 * nextSegment.m_averageLength / (num17 * this._maxLength);
							}
							if (!this._ignoreBlocked && (nextSegment.m_flags & NetSegment.Flags.Blocked) != NetSegment.Flags.None && (byte)(nextLane.m_laneType & (NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle)) != 0) {
								if (addCustomTrafficCosts)
									distanceOnBezier *= 2f;
								else
									nextItem.m_comparisonValue += 0.1f;
								result = true;
							}
							//sCurrentState = 20;
							nextItem.m_lanesUsed = (item.m_lanesUsed | nextLane.m_laneType);
							nextItem.m_laneID = curLaneId;
							if ((byte)(nextLane.m_laneType & laneType) != 0 && nextLane.m_vehicleType == vehicleType) {
								// NON-STOCK CODE START //
								if (!addCustomTrafficCosts) {
									// NON-STOCK CODE END //
									int firstTarget = (int)instance.m_lanes.m_buffer[(int)((UIntPtr)curLaneId)].m_firstTarget;
									int lastTarget = (int)instance.m_lanes.m_buffer[(int)((UIntPtr)curLaneId)].m_lastTarget;
									if (laneIndexFromLeft < firstTarget || laneIndexFromLeft >= lastTarget) {
										nextItem.m_comparisonValue += Mathf.Max(1f, distanceOnBezier * 3f - 3f) / ((prevMaxSpeed + nextMaxSpeed) * 0.5f * this._maxLength);
									}
									if (!this._transportVehicle && nextLane.m_laneType == NetInfo.LaneType.TransportVehicle) {
										nextItem.m_comparisonValue += 20f / ((prevMaxSpeed + nextMaxSpeed) * 0.5f * this._maxLength);
									}
									// NON-STOCK CODE START //
								}
								// NON-STOCK CODE END //
							}
							//sCurrentState = 21;

							// NON-STOCK CODE START //
							bool addItem = true;
							if (addCustomTrafficCosts) {
								//sCurrentState = 22;
								int nextRightSimilarLaneIndex;
								if ((byte)(nextLane.m_direction & normDirection) != 0) {
									nextRightSimilarLaneIndex = nextLane.m_similarLaneIndex;
								} else {
									nextRightSimilarLaneIndex = nextLane.m_similarLaneCount - nextLane.m_similarLaneIndex - 1;
								}

								float laneDist = !isMiddle && nextSegmentId == item.m_position.m_segment ? Options.someValue2 : Convert.ToSingle(Math.Abs(nextRightSimilarLaneIndex - prevRightSimilarLaneIndex));

								if (forceLaneIndex == null && prevIsHighway && nextIsHighway && laneDist > 1) {
									goto IL_8F5;
								}

								if (strictlyAvoidLane) {
									nextSpeed = 0;
									nextDensity = 1;
								}

								float metric = 1f;
								float multMetric = 1f;
								float divMetric = nextMaxSpeed;
								float metricBeforeLanes = 1f;
								
								// vehicles should choose lanes with low traffic volume, but should neither change lanes too frequently nor change to too distant lanes.

								// calculate speed metric
								divMetric = nextSpeed * nextMaxSpeed; // 0 .. nextMaxSpeed

								// calculate density metric
								multMetric = Options.pathCostMultiplicator * nextDensity; // 1 .. pathCostMultiplicator

								// calculate metric
								metric = Math.Max(0.01f, multMetric) / Math.Max(0.1f, divMetric);
								metricBeforeLanes = metric;

								// multiply with lane distance
								float laneMetric = 1f;
								if ((forceLaneIndex == null || !isMiddle && nextSegmentId == item.m_position.m_segment) && _extVehicleType != ExtVehicleType.Emergency && (!wantToChangeLane || laneDist > 1)) {
									laneMetric = (float)Math.Pow(Options.someValue, laneDist);
									metric *= laneMetric;
								}
								
#if DEBUGCOSTS
								if (costDebug) {
									logBuf.Add($"Path from {nextSegmentId} (lane {nextRightSimilarLaneIndex} from right, idx {laneIndex}, id {curLaneId}) to {item.m_position.m_segment} (lane {prevRightSimilarLaneIndex} from right, idx {item.m_position.m_lane}): nextMaxSpeed={nextMaxSpeed} prevMaxSpeed={prevMaxSpeed} nextMaxSpeed={nextMaxSpeed} divMetric={divMetric} nextDensity={nextDensity} multMetric={multMetric} laneDist={laneDist} laneMetric={laneMetric} metric={metric} metricBeforeLanes={metricBeforeLanes} isMiddle={isMiddle}");
                                }
#endif

								//sCurrentState = 24;

								float oldDistanceOverMaxSpeed = distanceOverMeanMaxSpeed;
								distanceOverMeanMaxSpeed = (metric * distanceOnBezier) / this._maxLength;

#if DEBUG
								/*if ((segmentID == 25320 || segmentID == 31177) && Options.disableSomething1)
									Log._Debug($"Costs for lane {curLaneId} @ {segmentID}: prevSpeed={prevSpeed} nextSpeed={nextSpeed} prevDensity={prevDensity} nextDensity={nextDensity} divMetric={divMetric}, multMetric={multMetric} laneDist={laneDist} metric={metric} distanceOnBezier={distanceOnBezier} prevCost={item2.m_comparisonValue} newCost={distanceOnBezier+item2.m_comparisonValue}");*/
#endif

									if (distanceOverMeanMaxSpeed < 0f) {
#if DEBUG
									Log.Error($"THREAD #{Thread.CurrentThread.ManagedThreadId}, PF {this._pathFindIndex}: distanceOverMeanMaxSpeed < 0! seg. {nextSegmentId}, lane {laneIndex}, off {nextItem.m_position.m_offset} -> {item.m_position.m_segment}, lane {item.m_position.m_lane}, off {item.m_position.m_offset}. distanceOverMeanMaxSpeed={distanceOverMeanMaxSpeed}, nextSpeed={nextSpeed}, prevSpeed={prevSpeed}");
#endif
									distanceOverMeanMaxSpeed = 0f;
								} else if (Single.IsNaN(distanceOverMeanMaxSpeed) || Single.IsInfinity(distanceOverMeanMaxSpeed)) {
#if DEBUG
									//if (costDebug)
										Log.Error($"Pathfinder ({this._pathFindIndex}): distanceOverMeanMaxSpeed is NaN or Infinity: seg. {nextSegmentId}, lane {laneIndex}, off {nextItem.m_position.m_offset} -> {item.m_position.m_segment}, lane {item.m_position.m_lane}, off {item.m_position.m_offset}. {distanceOverMeanMaxSpeed} // nextMaxSpeed={nextMaxSpeed} prevMaxSpeed={prevMaxSpeed} nextMaxSpeed={nextMaxSpeed} divMetric={divMetric} nextDensity={nextDensity} multMetric={multMetric} laneDist={laneDist} laneMetric={laneMetric} metric={metric} metricBeforeLanes={metricBeforeLanes}");
#endif
#if DEBUGPF
									//Log.Error($"THREAD #{Thread.CurrentThread.ManagedThreadId}, PF {this._pathFindIndex}: distanceOverMeanMaxSpeed is NaN! distanceOverMeanMaxSpeed={distanceOverMeanMaxSpeed}, nextSpeed={nextSpeed}, prevSpeed={prevSpeed}");
#endif
									distanceOverMeanMaxSpeed = oldDistanceOverMaxSpeed;
								}
								//sCurrentState = 25;

#if DEBUGCOSTS
								if (costDebug) {
									logBuf.Add($"Path from {nextSegmentId} (lane {nextRightSimilarLaneIndex} from right, idx {laneIndex}) to {item.m_position.m_segment} (lane {prevRightSimilarLaneIndex} from right, idx {item.m_position.m_lane}.");
									//logBuf.Add($"distanceOverMeanMaxSpeed = {distanceOverMeanMaxSpeed} oldDistanceOverMaxSpeed = {oldDistanceOverMaxSpeed}, prevMaxSpeed={prevMaxSpeed}, nextMaxSpeed={nextMaxSpeed}, prevSpeed={prevSpeed}, nextSpeed={nextSpeed}");
									logBuf.Add($"distanceOverMeanMaxSpeed = {distanceOverMeanMaxSpeed} oldDistanceOverMaxSpeed = {oldDistanceOverMaxSpeed}, prevMaxSpeed={prevMaxSpeed}, nextMaxSpeed={nextMaxSpeed}, nextSpeed={nextSpeed} nextDensity={nextDensity}");
                                }
#endif

								nextItem.m_comparisonValue += distanceOverMeanMaxSpeed;
#if DEBUGCOSTS
								if (costDebug) {
									logBuf.Add($"Total cost = {distanceOverMeanMaxSpeed}, comparison value = {nextItem.m_comparisonValue}");
								}
#endif
#if DEBUGCOSTS
								if (costDebug) {
									foreach (String toLog in logBuf) {
										Log._Debug($"Pathfinder ({this._pathFindIndex}): " + toLog);
									}
								}
#endif

								//sCurrentState = 26;
								if (nextItem.m_comparisonValue < 0f) {
#if DEBUG
									Log.Error($"THREAD #{Thread.CurrentThread.ManagedThreadId}, PF {this._pathFindIndex}: Comparison value < 0! seg. {nextSegmentId}, lane {laneIndex}, off {nextItem.m_position.m_offset} -> {item.m_position.m_segment}, lane {item.m_position.m_lane}, off {item.m_position.m_offset}. distanceOverMeanMaxSpeed={distanceOverMeanMaxSpeed}, nextSpeed={nextSpeed}");
#endif
									nextItem.m_comparisonValue = 0f;
								} else if (nextItem.m_comparisonValue > 1f || Single.IsNaN(nextItem.m_comparisonValue) || Single.IsInfinity(nextItem.m_comparisonValue)) {
#if DEBUGPF
									if (debug)
										Log._Debug($"Pathfinder ({this._pathFindIndex}): comparisonValue is >1, NaN or Infinity: {nextItem.m_comparisonValue}. seg. {nextSegmentId}, lane {laneIndex}, off {nextItem.m_position.m_offset} -> {item.m_position.m_segment}, lane {item.m_position.m_lane}, off {item.m_position.m_offset}.");
#endif
#if DEBUG
									//Log.Error($"THREAD #{Thread.CurrentThread.ManagedThreadId}, PF {this._pathFindIndex}: Comparison value > 1, NaN or infinity! distanceOverMeanMaxSpeed={distanceOverMeanMaxSpeed}, nextSpeed={nextSpeed}, prevSpeed={prevSpeed}");
#endif
									addItem = false;
								}
								//sCurrentState = 27;
#if DEBUGPF
								if (debug) {
									//Log.Message($">> PF {this._pathFindIndex} -- seg {item2.m_position.m_segment}, lane {item2.m_position.m_lane} (idx {item2.m_laneID}), off {item2.m_position.m_offset}, cost {item2.m_comparisonValue}, totalCost {totalCost} = traffic={trafficCost}, junction={junctionCost}, lane={laneChangeCost}");
								}
#endif
							}
							//sCurrentState = 28;

							if (forceLaneIndex != null && laneIndex == forceLaneIndex && addItem) {
								foundForced = true;
							}

							/*if (addCustomCosts && ((item.m_position.m_segment == 2062 && item2.m_position.m_segment == 23640) || (item.m_position.m_segment == 23640 && item2.m_position.m_segment == 29505) || (item.m_position.m_segment == 29505 && item2.m_position.m_segment == 24975) || (item.m_position.m_segment == 24975 && item2.m_position.m_segment == 9535) || (item.m_position.m_segment == 9535 && item2.m_position.m_segment == 20914) || (item.m_position.m_segment == 20914 && item2.m_position.m_segment == 21545))) {
								Log.Message($">> PF {this._pathFindIndex} -- Adding item: seg {item2.m_position.m_segment}, lane {item2.m_position.m_lane} (idx {item2.m_laneID}), off {item2.m_position.m_offset} -> seg {item.m_position.m_segment}, lane {item.m_position.m_lane} (idx {item.m_laneID}), off {item.m_position.m_offset}, cost {item2.m_comparisonValue}, methodDist {item2.m_methodDistance}");
							}*/

							// NON-STOCK CODE END //

							if (addItem) {
#if DEBUGPF
								if (debug)
									Log._Debug($">> PF {this._pathFindIndex} -- Adding item: seg {nextItem.m_position.m_segment}, lane {nextItem.m_position.m_lane} (idx {nextItem.m_laneID}), off {nextItem.m_position.m_offset} -> seg {item.m_position.m_segment}, lane {item.m_position.m_lane} (idx {item.m_laneID}), off {item.m_position.m_offset}, cost {nextItem.m_comparisonValue}, previous cost {item.m_comparisonValue}, methodDist {nextItem.m_methodDistance}");
#endif
								//sCurrentState = 29;
								this.AddBufferItem(nextItem, item.m_position);
								//sCurrentState = 30;
							} else {
								//sCurrentState = 31;
#if DEBUGPF
								if (debug)
									Log._Debug($">> PF {this._pathFindIndex} -- NOT adding item");
#endif
							}
							//sCurrentState = 32;
						}
						//sCurrentState = 33;
					}
					//sCurrentState = 34;
					goto IL_8F5;
				}
				//sCurrentState = 35;
				if ((byte)(nextLane.m_laneType & laneType) != 0 && (nextLane.m_vehicleType & vehicleType) != VehicleInfo.VehicleType.None) {
					newLaneIndexFromLeft++;
					goto IL_8F5;
				}
				//sCurrentState = 36;
				goto IL_8F5;
				IL_90F:
				//sCurrentState = 37;
				laneIndex++;
				continue;
				IL_8F5:
				//sCurrentState = 38;
				curLaneId = instance.m_lanes.m_buffer[(int)((UIntPtr)curLaneId)].m_nextLane;
				goto IL_90F;
			} // foreach lane
			//sCurrentState = 39;
			laneIndexFromLeft = newLaneIndexFromLeft;
			return result;
		}
Exemplo n.º 17
0
		// 2
		private void ProcessItem2(BufferItem item, ushort targetNodeId, bool targetDisabled, ushort nextSegmentId, ref NetSegment nextSegment, uint lane, byte offset, byte connectOffset) {
			if ((nextSegment.m_flags & (NetSegment.Flags.PathFailed | NetSegment.Flags.Flooded)) != NetSegment.Flags.None) {
				return;
			}
			NetManager instance = Singleton<NetManager>.instance;
			if (targetDisabled && ((instance.m_nodes.m_buffer[(int)nextSegment.m_startNode].m_flags | instance.m_nodes.m_buffer[(int)nextSegment.m_endNode].m_flags) & NetNode.Flags.Disabled) == NetNode.Flags.None) {
				return;
			}
			NetInfo nextSegmentInfo = nextSegment.Info;
			NetInfo prevSegmentInfo = instance.m_segments.m_buffer[(int)item.m_position.m_segment].Info;
			int nextNumLanes = nextSegmentInfo.m_lanes.Length;
			uint curLaneId = nextSegment.m_lanes;
			float prevMaxSpeed = 1f;
			float num4 = 1f;
			NetInfo.LaneType laneType = NetInfo.LaneType.None;
			// NON-STOCK CODE START //
			bool nextIsJunction = instance.m_nodes.m_buffer[targetNodeId].CountSegments() > 2;
			ushort sourceNodeId = (targetNodeId == instance.m_segments.m_buffer[item.m_position.m_segment].m_startNode) ? instance.m_segments.m_buffer[item.m_position.m_segment].m_endNode : instance.m_segments.m_buffer[item.m_position.m_segment].m_startNode; // no lane changing directly in front of a junction
			bool prevIsJunction = instance.m_nodes.m_buffer[sourceNodeId].CountSegments() > 2;
			// NON-STOCK CODE END //
			if ((int)item.m_position.m_lane < prevSegmentInfo.m_lanes.Length) {
				NetInfo.Lane lane2 = prevSegmentInfo.m_lanes[(int)item.m_position.m_lane];
				prevMaxSpeed = GetLaneSpeedLimit(item.m_position.m_segment, item.m_position.m_lane, item.m_laneID, lane2); // SpeedLimitManager.GetLockFreeGameSpeedLimit(item.m_position.m_segment, item.m_position.m_lane, item.m_laneID, ref lane2); // NON-STOCK CODE
				laneType = lane2.m_laneType;
				if ((byte)(laneType & (NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle)) != 0) {
					laneType = (NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle);
				}
				num4 = this.CalculateLaneSpeed(prevMaxSpeed, connectOffset, item.m_position.m_offset, ref instance.m_segments.m_buffer[(int)item.m_position.m_segment], lane2); // NON-STOCK CODE
			}
			float averageLength = instance.m_segments.m_buffer[(int)item.m_position.m_segment].m_averageLength;
			float num5 = (float)Mathf.Abs((int)(connectOffset - item.m_position.m_offset)) * 0.003921569f * averageLength;
			float num6 = item.m_methodDistance + num5;
			float num7 = item.m_comparisonValue + num5 / (num4 * this._maxLength);
			Vector3 b = instance.m_lanes.m_buffer[(int)((UIntPtr)item.m_laneID)].CalculatePosition((float)connectOffset * 0.003921569f);
			uint laneIndex = 0;
#if DEBUG
			int wIter = 0;
#endif
			while (laneIndex < nextNumLanes && curLaneId != 0u) {
#if DEBUG
				++wIter;
				if (wIter >= 20) {
					Log.Error("Too many iterations in ProcessItem2!");
					break;
				}
#endif

				if (lane == curLaneId) {
					NetInfo.Lane lane3 = nextSegmentInfo.m_lanes[laneIndex];
					if (lane3.CheckType(this._laneTypes, this._vehicleTypes)) {
						Vector3 a = instance.m_lanes.m_buffer[(int)((UIntPtr)lane)].CalculatePosition((float)offset * 0.003921569f);
						float num9 = Vector3.Distance(a, b);
						BufferItem item2;
						item2.m_position.m_segment = nextSegmentId;
						item2.m_position.m_lane = (byte)laneIndex;
						item2.m_position.m_offset = offset;
						if ((byte)(lane3.m_laneType & laneType) == 0) {
							item2.m_methodDistance = 0f;
						} else {
							item2.m_methodDistance = num6 + num9;
						}
						float nextMaxSpeed = GetLaneSpeedLimit(nextSegmentId, laneIndex, curLaneId, lane3); // SpeedLimitManager.GetLockFreeGameSpeedLimit(nextSegmentId, laneIndex, curLaneId, ref lane3); // NON-STOCK CODE
						if (lane3.m_laneType != NetInfo.LaneType.Pedestrian || item2.m_methodDistance < 1000f) {
							item2.m_comparisonValue = num7 + num9 / ((prevMaxSpeed + nextMaxSpeed) * 0.5f * this._maxLength); // NON-STOCK CODE
							if ((nextSegment.m_flags & NetSegment.Flags.Invert) != NetSegment.Flags.None) {
								item2.m_direction = NetInfo.InvertDirection(lane3.m_finalDirection);
							} else {
								item2.m_direction = lane3.m_finalDirection;
							}
							if (lane == this._startLaneA) {
								if (((byte)(item2.m_direction & NetInfo.Direction.Forward) == 0 || item2.m_position.m_offset < this._startOffsetA) && ((byte)(item2.m_direction & NetInfo.Direction.Backward) == 0 || item2.m_position.m_offset > this._startOffsetA)) {
									return;
								}
								float num10 = this.CalculateLaneSpeed(nextMaxSpeed, this._startOffsetA, item2.m_position.m_offset, ref nextSegment, lane3); // NON-STOCK CODE
								float num11 = (float)Mathf.Abs((int)(item2.m_position.m_offset - this._startOffsetA)) * 0.003921569f;
								item2.m_comparisonValue += num11 * nextSegment.m_averageLength / (num10 * this._maxLength);
							}
							if (lane == this._startLaneB) {
								if (((byte)(item2.m_direction & NetInfo.Direction.Forward) == 0 || item2.m_position.m_offset < this._startOffsetB) && ((byte)(item2.m_direction & NetInfo.Direction.Backward) == 0 || item2.m_position.m_offset > this._startOffsetB)) {
									return;
								}
								float num12 = this.CalculateLaneSpeed(nextMaxSpeed, this._startOffsetB, item2.m_position.m_offset, ref nextSegment, lane3); // NON-STOCK CODE
								float num13 = (float)Mathf.Abs((int)(item2.m_position.m_offset - this._startOffsetB)) * 0.003921569f;
								item2.m_comparisonValue += num13 * nextSegment.m_averageLength / (num12 * this._maxLength);
							}
							item2.m_laneID = lane;
							item2.m_lanesUsed = (item.m_lanesUsed | lane3.m_laneType);
							this.AddBufferItem(item2, item.m_position);
						}
					}
					return;
				}
				curLaneId = instance.m_lanes.m_buffer[(int)((UIntPtr)curLaneId)].m_nextLane;
				laneIndex++;
			}
		}
Exemplo n.º 18
0
 public override bool FilterBuffer(BufferItem item)
 {
     return(item.TypeName == "LogEntity");
 }
Exemplo n.º 19
0
 protected abstract void Get(ref BufferItem buffer);
Exemplo n.º 20
0
 public void SetItemToClipboard(BufferItem p_item)
 {
     throw new NotImplementedException();
 }
Exemplo n.º 21
0
		private bool ProcessItemCosts(bool allowCustomLaneChanging, bool debug, BufferItem item, ushort targetNode, ushort segmentID, ref NetSegment segment, ref int laneIndexFromLeft, byte connectOffset, bool enableVehicle, bool enablePedestrian) {
			bool foundForced = false;
			return ProcessItemCosts(allowCustomLaneChanging, debug, item, targetNode, segmentID, ref segment, ref laneIndexFromLeft, connectOffset, enableVehicle, enablePedestrian, null, null, out foundForced);
		}
        private void ProcessItem2(BufferItem item, ushort targetNode, ushort segmentId, ref NetSegment segment, ref int currentTargetIndex, byte connectOffset, bool enableVehicle, bool enablePedestrian, uint laneId, int laneNum)
        {
            if ((segment.m_flags & (NetSegment.Flags.PathFailed | NetSegment.Flags.Flooded)) != NetSegment.Flags.None)
            {
                return;
            }
            var instance = Singleton<NetManager>.instance;
            var info = segment.Info;
            var info2 = instance.m_segments.m_buffer[item.Position.m_segment].Info;
            var num2 = laneId;
            var direction = (targetNode != segment.m_startNode) ? NetInfo.Direction.Forward : NetInfo.Direction.Backward;
            var direction2 = ((segment.m_flags & NetSegment.Flags.Invert) == NetSegment.Flags.None) ? direction : NetInfo.InvertDirection(direction);
            var num3 = 0.01f - Mathf.Min(info.m_maxTurnAngleCos, info2.m_maxTurnAngleCos);
            if (num3 < 1f)
            {
                Vector3 vector;
                if (targetNode == instance.m_segments.m_buffer[item.Position.m_segment].m_startNode)
                {
                    vector = instance.m_segments.m_buffer[item.Position.m_segment].m_startDirection;
                }
                else
                {
                    vector = instance.m_segments.m_buffer[item.Position.m_segment].m_endDirection;
                }
                Vector3 vector2;
                if ((byte)(direction & NetInfo.Direction.Forward) != 0)
                {
                    vector2 = segment.m_endDirection;
                }
                else
                {
                    vector2 = segment.m_startDirection;
                }
                float num4 = vector.x * vector2.x + vector.z * vector2.z;
                if (num4 >= num3)
                {
                    return;
                }
            }
            float num5 = 1f;
            float num6 = 1f;
            NetInfo.LaneType laneType = NetInfo.LaneType.None;
            VehicleInfo.VehicleType vehicleType = VehicleInfo.VehicleType.None;
            if (item.Position.m_lane < info2.m_lanes.Length)
            {
                NetInfo.Lane lane = info2.m_lanes[item.Position.m_lane];
                laneType = lane.m_laneType;
                vehicleType = lane.m_vehicleType;

                if (TrafficRoadRestrictions.IsSegment(item.Position.m_segment))
                {
                    var restrictionSegment = TrafficRoadRestrictions.GetSegment(item.Position.m_segment);

                    if (restrictionSegment.SpeedLimits[item.Position.m_lane] > 0.1f)
                    {
                        num5 = restrictionSegment.SpeedLimits[item.Position.m_lane];
                    }
                    else
                    {
                        num5 = lane.m_speedLimit;
                    }
                }
                else
                {
                    num5 = lane.m_speedLimit;
                }
                num6 = CalculateLaneSpeed(connectOffset, item.Position.m_offset, ref instance.m_segments.m_buffer[item.Position.m_segment], lane);
            }
            float num7 = instance.m_segments.m_buffer[item.Position.m_segment].m_averageLength;
            if (!_stablePath)
            {
                Randomizer randomizer = new Randomizer(_pathFindIndex << 16 | item.Position.m_segment);
                num7 *= (randomizer.Int32(900, 1000 + instance.m_segments.m_buffer[item.Position.m_segment].m_trafficDensity * 10) + _pathRandomizer.Int32(20u)) * 0.001f;
            }
            if (_isHeavyVehicle && (instance.m_segments.m_buffer[item.Position.m_segment].m_flags & NetSegment.Flags.HeavyBan) != NetSegment.Flags.None)
            {
                num7 *= 10f;
            }
            float num8 = Mathf.Abs(connectOffset - item.Position.m_offset) * 0.003921569f * num7;
            float num9 = item.MethodDistance + num8;
            float num10 = item.ComparisonValue + num8 / (num6 * _maxLength);
            Vector3 b = instance.m_lanes.m_buffer[(int)((UIntPtr)item.LaneId)].CalculatePosition(connectOffset * 0.003921569f);
            int num11 = laneNum;
            bool flag = (instance.m_nodes.m_buffer[targetNode].m_flags & NetNode.Flags.Transition) != NetNode.Flags.None;
            NetInfo.LaneType laneType2 = _laneTypes;
            if (!enableVehicle)
            {
                laneType2 &= ~NetInfo.LaneType.Vehicle;
            }
            if (!enablePedestrian)
            {
                laneType2 &= ~NetInfo.LaneType.Pedestrian;
            }
            int num12 = laneNum;

            NetInfo.Lane lane2 = info.m_lanes[num12];

            if (TrafficRoadRestrictions.IsSegment(instance.m_lanes.m_buffer[(int)((UIntPtr)num2)].m_segment))
            {
                var restrictionSegment = TrafficRoadRestrictions.GetSegment(instance.m_lanes.m_buffer[(int)((UIntPtr)num2)].m_segment);

                if (restrictionSegment.SpeedLimits[item.Position.m_lane] > 0.1f)
                {
                }
            }

            if (lane2.CheckType(laneType2, _vehicleTypes) && (segmentId != item.Position.m_segment || num12 != item.Position.m_lane) && (byte)(lane2.m_finalDirection & direction2) != 0)
            {
                Vector3 a;
                if ((byte)(direction & NetInfo.Direction.Forward) != 0)
                {
                    a = instance.m_lanes.m_buffer[(int)((UIntPtr)num2)].m_bezier.d;
                }
                else
                {
                    a = instance.m_lanes.m_buffer[(int)((UIntPtr)num2)].m_bezier.a;
                }
                var num13 = Vector3.Distance(a, b);
                if (flag)
                {
                    num13 *= 2f;
                }
                var num14 = num13 / ((num5 + lane2.m_speedLimit) * 0.5f * _maxLength);
                BufferItem item2;
                item2.Position.m_segment = segmentId;
                item2.Position.m_lane = (byte)laneNum;
                item2.Position.m_offset = (byte)(((byte)(direction & NetInfo.Direction.Forward) == 0) ? 0 : 255);
                if (laneType != lane2.m_laneType)
                {
                    item2.MethodDistance = 0f;
                }
                else
                {
                    item2.MethodDistance = num9 + num13;
                }

                item2.ComparisonValue = num10 + num14;
                if (num2 == _startLaneA)
                {
                    float num15 = CalculateLaneSpeed(_startOffsetA, item2.Position.m_offset, ref segment, lane2);
                    float num16 = Mathf.Abs(item2.Position.m_offset - _startOffsetA) * 0.003921569f;
                    item2.ComparisonValue += num16 * segment.m_averageLength / (num15 * _maxLength);
                }
                if (num2 == _startLaneB)
                {
                    float num17 = CalculateLaneSpeed(_startOffsetB, item2.Position.m_offset, ref segment, lane2);
                    float num18 = Mathf.Abs(item2.Position.m_offset - _startOffsetB) * 0.003921569f;
                    item2.ComparisonValue += num18 * segment.m_averageLength / (num17 * _maxLength);
                }
                if (!_ignoreBlocked && (segment.m_flags & NetSegment.Flags.Blocked) != NetSegment.Flags.None && lane2.m_laneType == NetInfo.LaneType.Vehicle)
                {
                    item2.ComparisonValue += 0.1f;
                }
                item2.Direction = direction;
                item2.LanesUsed = (item.LanesUsed | lane2.m_laneType);
                item2.LaneId = laneId;
                if (lane2.m_laneType == laneType && lane2.m_vehicleType == vehicleType)
                {
                    int firstTarget = instance.m_lanes.m_buffer[(int)((UIntPtr)num2)].m_firstTarget;
                    int lastTarget = instance.m_lanes.m_buffer[(int)((UIntPtr)num2)].m_lastTarget;
                    if (currentTargetIndex < firstTarget || currentTargetIndex >= lastTarget)
                    {
                        item2.ComparisonValue += Mathf.Max(1f, num13 * 3f - 3f) / ((num5 + lane2.m_speedLimit) * 0.5f * _maxLength);
                    }
                }

                AddBufferItem(item2, item.Position);
            }

            currentTargetIndex = num11;
        }
Exemplo n.º 23
0
		// 4
		private void ProcessItemPedBicycle(BufferItem item, ushort targetNodeId, ushort segmentID, ref NetSegment segment, byte connectOffset, int laneIndex, uint lane) {
			if ((segment.m_flags & (NetSegment.Flags.PathFailed | NetSegment.Flags.Flooded)) != NetSegment.Flags.None) {
				return;
			}
			NetManager instance = Singleton<NetManager>.instance;
			NetInfo info = segment.Info;
			NetInfo info2 = instance.m_segments.m_buffer[(int)item.m_position.m_segment].Info;
			int num = info.m_lanes.Length;
			float num2;
			byte offset;
			if (segmentID == item.m_position.m_segment) {
				Vector3 b = instance.m_lanes.m_buffer[(int)((UIntPtr)item.m_laneID)].CalculatePosition((float)connectOffset * 0.003921569f);
				Vector3 a = instance.m_lanes.m_buffer[(int)((UIntPtr)lane)].CalculatePosition((float)connectOffset * 0.003921569f);
				num2 = Vector3.Distance(a, b);
				offset = connectOffset;
			} else {
				NetInfo.Direction direction = (targetNodeId != segment.m_startNode) ? NetInfo.Direction.Forward : NetInfo.Direction.Backward;
				Vector3 b2 = instance.m_lanes.m_buffer[(int)((UIntPtr)item.m_laneID)].CalculatePosition((float)connectOffset * 0.003921569f);
				Vector3 a2;
				if ((byte)(direction & NetInfo.Direction.Forward) != 0) {
					a2 = instance.m_lanes.m_buffer[(int)((UIntPtr)lane)].m_bezier.d;
				} else {
					a2 = instance.m_lanes.m_buffer[(int)((UIntPtr)lane)].m_bezier.a;
				}
				num2 = Vector3.Distance(a2, b2);
				offset = (byte)(((direction & NetInfo.Direction.Forward) == 0) ? 0 : 255);
			}
			float prevMaxSpeed = 1f;
			float num4 = 1f;
			NetInfo.LaneType laneType = NetInfo.LaneType.None;
			if ((int)item.m_position.m_lane < info2.m_lanes.Length) {
				NetInfo.Lane lane2 = info2.m_lanes[(int)item.m_position.m_lane];
				prevMaxSpeed = GetLaneSpeedLimit(item.m_position.m_segment, item.m_position.m_lane, item.m_laneID, lane2); // SpeedLimitManager.GetLockFreeGameSpeedLimit(item.m_position.m_segment, item.m_position.m_lane, item.m_laneID, ref lane2); // NON-STOCK CODE
				laneType = lane2.m_laneType;
				if ((byte)(laneType & (NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle)) != 0) {
					laneType = (NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle);
				}
				num4 = this.CalculateLaneSpeed(prevMaxSpeed, connectOffset, item.m_position.m_offset, ref instance.m_segments.m_buffer[(int)item.m_position.m_segment], lane2); // NON-STOCK CODE
			}
			float averageLength = instance.m_segments.m_buffer[(int)item.m_position.m_segment].m_averageLength;
			float num5 = (float)Mathf.Abs((int)(connectOffset - item.m_position.m_offset)) * 0.003921569f * averageLength;
			float num6 = item.m_methodDistance + num5;
			float num7 = item.m_comparisonValue + num5 / (num4 * this._maxLength);
			// NON-STOCK CODE START //
			bool nextIsJunction = instance.m_nodes.m_buffer[targetNodeId].CountSegments() > 2;
			ushort sourceNodeId = (targetNodeId == instance.m_segments.m_buffer[item.m_position.m_segment].m_startNode) ? instance.m_segments.m_buffer[item.m_position.m_segment].m_endNode : instance.m_segments.m_buffer[item.m_position.m_segment].m_startNode; // no lane changing directly in front of a junction
			bool prevIsJunction = instance.m_nodes.m_buffer[sourceNodeId].CountSegments() > 2;
			// NON-STOCK CODE END //
			if (laneIndex < num) {
				NetInfo.Lane lane3 = info.m_lanes[laneIndex];
				BufferItem item2;
				item2.m_position.m_segment = segmentID;
				item2.m_position.m_lane = (byte)laneIndex;
				item2.m_position.m_offset = offset;
				if ((byte)(lane3.m_laneType & laneType) == 0) {
					item2.m_methodDistance = 0f;
				} else {
					if (item.m_methodDistance == 0f) {
						num7 += 100f / (0.25f * this._maxLength);
					}
					item2.m_methodDistance = num6 + num2;
				}
				float nextMaxSpeed = GetLaneSpeedLimit(segmentID, (uint)laneIndex, lane, lane3); // SpeedLimitManager.GetLockFreeGameSpeedLimit(segmentID, (uint)laneIndex, lane, ref lane3); // NON-STOCK CODE
				if (lane3.m_laneType != NetInfo.LaneType.Pedestrian || item2.m_methodDistance < 1000f) {
					item2.m_comparisonValue = num7 + num2 / ((prevMaxSpeed + nextMaxSpeed) * 0.25f * this._maxLength); // NON-STOCK CODE
					if ((segment.m_flags & NetSegment.Flags.Invert) != NetSegment.Flags.None) {
						item2.m_direction = NetInfo.InvertDirection(lane3.m_finalDirection);
					} else {
						item2.m_direction = lane3.m_finalDirection;
					}
					if (lane == this._startLaneA) {
						if (((byte)(item2.m_direction & NetInfo.Direction.Forward) == 0 || item2.m_position.m_offset < this._startOffsetA) && ((byte)(item2.m_direction & NetInfo.Direction.Backward) == 0 || item2.m_position.m_offset > this._startOffsetA)) {
							return;
						}
						float num8 = this.CalculateLaneSpeed(nextMaxSpeed, this._startOffsetA, item2.m_position.m_offset, ref segment, lane3); // NON-STOCK CODE
						float num9 = (float)Mathf.Abs((int)(item2.m_position.m_offset - this._startOffsetA)) * 0.003921569f;
						item2.m_comparisonValue += num9 * segment.m_averageLength / (num8 * this._maxLength);
					}
					if (lane == this._startLaneB) {
						if (((byte)(item2.m_direction & NetInfo.Direction.Forward) == 0 || item2.m_position.m_offset < this._startOffsetB) && ((byte)(item2.m_direction & NetInfo.Direction.Backward) == 0 || item2.m_position.m_offset > this._startOffsetB)) {
							return;
						}
						float num10 = this.CalculateLaneSpeed(nextMaxSpeed, this._startOffsetB, item2.m_position.m_offset, ref segment, lane3); // NON-STOCK CODE
						float num11 = (float)Mathf.Abs((int)(item2.m_position.m_offset - this._startOffsetB)) * 0.003921569f;
						item2.m_comparisonValue += num11 * segment.m_averageLength / (num10 * this._maxLength);
					}
					item2.m_laneID = lane;
					item2.m_lanesUsed = (item.m_lanesUsed | lane3.m_laneType);
					this.AddBufferItem(item2, item.m_position);
				}
			}
		}
 private void ProcessItem3(BufferItem item, bool targetDisabled, ushort segmentId, ref NetSegment segment, uint lane, byte offset, byte connectOffset)
 {
     if ((segment.m_flags & (NetSegment.Flags.PathFailed | NetSegment.Flags.Flooded)) != NetSegment.Flags.None)
     {
         return;
     }
     NetManager instance = Singleton<NetManager>.instance;
     if (targetDisabled && ((instance.m_nodes.m_buffer[segment.m_startNode].m_flags | instance.m_nodes.m_buffer[segment.m_endNode].m_flags) & NetNode.Flags.Disabled) == NetNode.Flags.None)
     {
         return;
     }
     NetInfo info = segment.Info;
     NetInfo info2 = instance.m_segments.m_buffer[item.Position.m_segment].Info;
     int num = info.m_lanes.Length;
     uint num2 = segment.m_lanes;
     float num3 = 1f;
     float num4 = 1f;
     NetInfo.LaneType laneType = NetInfo.LaneType.None;
     if (item.Position.m_lane < info2.m_lanes.Length)
     {
         NetInfo.Lane lane2 = info2.m_lanes[item.Position.m_lane];
         num3 = lane2.m_speedLimit;
         laneType = lane2.m_laneType;
         num4 = CalculateLaneSpeed(connectOffset, item.Position.m_offset, ref instance.m_segments.m_buffer[item.Position.m_segment], lane2);
     }
     float averageLength = instance.m_segments.m_buffer[item.Position.m_segment].m_averageLength;
     float num5 = Mathf.Abs(connectOffset - item.Position.m_offset) * 0.003921569f * averageLength;
     float num6 = item.MethodDistance + num5;
     float num7 = item.ComparisonValue + num5 / (num4 * _maxLength);
     Vector3 b = instance.m_lanes.m_buffer[(int)((UIntPtr)item.LaneId)].CalculatePosition(connectOffset * 0.003921569f);
     int num8 = 0;
     while (num8 < num && num2 != 0u)
     {
         if (lane == num2)
         {
             NetInfo.Lane lane3 = info.m_lanes[num8];
             if (lane3.CheckType(_laneTypes, _vehicleTypes))
             {
                 Vector3 a = instance.m_lanes.m_buffer[(int)((UIntPtr)lane)].CalculatePosition(offset * 0.003921569f);
                 float num9 = Vector3.Distance(a, b);
                 BufferItem item2;
                 item2.Position.m_segment = segmentId;
                 item2.Position.m_lane = (byte)num8;
                 item2.Position.m_offset = offset;
                 if (laneType != lane3.m_laneType)
                 {
                     item2.MethodDistance = 0f;
                 }
                 else
                 {
                     item2.MethodDistance = num6 + num9;
                 }
                 if (lane3.m_laneType != NetInfo.LaneType.Pedestrian || item2.MethodDistance < 1000f)
                 {
                     item2.ComparisonValue = num7 + num9 / ((num3 + lane3.m_speedLimit) * 0.5f * _maxLength);
                     if (lane == _startLaneA)
                     {
                         float num10 = CalculateLaneSpeed(_startOffsetA, item2.Position.m_offset, ref segment, lane3);
                         float num11 = Mathf.Abs(item2.Position.m_offset - _startOffsetA) * 0.003921569f;
                         item2.ComparisonValue += num11 * segment.m_averageLength / (num10 * _maxLength);
                     }
                     if (lane == _startLaneB)
                     {
                         float num12 = CalculateLaneSpeed(_startOffsetB, item2.Position.m_offset, ref segment, lane3);
                         float num13 = Mathf.Abs(item2.Position.m_offset - _startOffsetB) * 0.003921569f;
                         item2.ComparisonValue += num13 * segment.m_averageLength / (num12 * _maxLength);
                     }
                     if ((segment.m_flags & NetSegment.Flags.Invert) != NetSegment.Flags.None)
                     {
                         item2.Direction = NetInfo.InvertDirection(lane3.m_finalDirection);
                     }
                     else
                     {
                         item2.Direction = lane3.m_finalDirection;
                     }
                     item2.LaneId = lane;
                     item2.LanesUsed = (item.LanesUsed | lane3.m_laneType);
                     AddBufferItem(item2, item.Position);
                 }
             }
             return;
         }
         num2 = instance.m_lanes.m_buffer[(int)((UIntPtr)num2)].m_nextLane;
         num8++;
     }
 }
Exemplo n.º 25
0
		// be aware:
		//   (1) path-finding works from target to start. the "next" segment is always the previous and the "previous" segment is always the next segment on the path!
		//   (2) when I use the term "lane index from right" this holds for right-hand traffic systems. On maps where you activate left-hand traffic, the "lane index from right" values represent lane indices starting from the left side.

		// 1
		private void ProcessItemMain(uint unitId, BufferItem item, ushort nextNodeId, ref NetNode nextNode, byte connectOffset, bool isMiddle) {
			//mCurrentState = 0;
#if DEBUGPF
			//bool debug = Options.disableSomething1 && item.m_position.m_segment == 1459 && nextNodeId == 19630;
			//bool debug = Options.disableSomething1 && (item.m_position.m_segment == 3833 || item.m_position.m_segment == 9649);
			bool debug = Options.disableSomething1;
#endif
#if DEBUGPF
			/*if (m_queuedPathFindCount > 100 && Options.disableSomething1)
				Log._Debug($"THREAD #{Thread.CurrentThread.ManagedThreadId} PF {this._pathFindIndex}: processItemMain RUNNING! item: {item.m_position.m_segment}, {item.m_position.m_lane} nextNodeId: {nextNodeId}");*/
#endif
			//Log.Message($"THREAD #{Thread.CurrentThread.ManagedThreadId} Path finder: " + this._pathFindIndex + " vehicle types: " + this._vehicleTypes);
#if DEBUGPF
			//bool debug = isTransportVehicle && isMiddle && item.m_position.m_segment == 13550;
			List<String> logBuf = null;
			if (debug)
				logBuf = new List<String>();
			//bool debug = nextNodeId == 12732;
#else
			bool debug = false;
#endif
			//mCurrentState = 1;
			NetManager instance = Singleton<NetManager>.instance;
			bool isPedestrianLane = false;
			bool isBicycleLane = false;
			bool isCenterPlatform = false;
			int similarLaneIndexFromLeft = 0; // similar index, starting with 0 at leftmost lane
			NetInfo prevSegmentInfo = instance.m_segments.m_buffer[(int)item.m_position.m_segment].Info;
			int prevSimiliarLaneCount = 0;
			if ((int)item.m_position.m_lane < prevSegmentInfo.m_lanes.Length) {
				NetInfo.Lane prevLane = prevSegmentInfo.m_lanes[(int)item.m_position.m_lane];
				isPedestrianLane = (prevLane.m_laneType == NetInfo.LaneType.Pedestrian);
				isBicycleLane = (prevLane.m_laneType == NetInfo.LaneType.Vehicle && prevLane.m_vehicleType == VehicleInfo.VehicleType.Bicycle);
				isCenterPlatform = prevLane.m_centerPlatform;
				prevSimiliarLaneCount = prevLane.m_similarLaneCount;
				if ((byte)(prevLane.m_finalDirection & NetInfo.Direction.Forward) != 0) {
					similarLaneIndexFromLeft = prevLane.m_similarLaneIndex;
				} else {
					similarLaneIndexFromLeft = prevLane.m_similarLaneCount - prevLane.m_similarLaneIndex - 1;
				}
				//debug = Options.disableSomething1 && (prevLane.m_vehicleType & VehicleInfo.VehicleType.Ship) != VehicleInfo.VehicleType.None;
			}
			int firstSimilarLaneIndexFromLeft = similarLaneIndexFromLeft;
			//mCurrentState = 2;
			ushort prevSegmentId = item.m_position.m_segment;
			if (isMiddle) {
				//mCurrentState = 3;
				for (int i = 0; i < 8; i++) {
					ushort nextSegmentId = nextNode.GetSegment(i);
					if (nextSegmentId <= 0)
						continue;
					this.ProcessItemCosts(false, debug, item, nextNodeId, nextSegmentId, ref instance.m_segments.m_buffer[(int)nextSegmentId], ref similarLaneIndexFromLeft, connectOffset, !isPedestrianLane, isPedestrianLane);
				}
				//mCurrentState = 4;
			} else if (isPedestrianLane) {
				//mCurrentState = 5;
				int prevLaneIndex = (int)item.m_position.m_lane;
				if (nextNode.Info.m_class.m_service != ItemClass.Service.Beautification) {
					bool flag4 = (nextNode.m_flags & (NetNode.Flags.End | NetNode.Flags.Bend | NetNode.Flags.Junction)) != NetNode.Flags.None;
					bool flag5 = isCenterPlatform && (nextNode.m_flags & (NetNode.Flags.End | NetNode.Flags.Junction)) == NetNode.Flags.None;
					ushort num2 = prevSegmentId;
					ushort num3 = prevSegmentId;
					int laneIndex;
					int laneIndex2;
					uint leftLaneId;
					uint rightLaneId;
					instance.m_segments.m_buffer[(int)prevSegmentId].GetLeftAndRightLanes(nextNodeId, NetInfo.LaneType.Pedestrian, VehicleInfo.VehicleType.None, prevLaneIndex, flag5, out laneIndex, out laneIndex2, out leftLaneId, out rightLaneId);
					if (leftLaneId == 0u || rightLaneId == 0u) {
						ushort leftSegment;
						ushort rightSegment;
						instance.m_segments.m_buffer[(int)prevSegmentId].GetLeftAndRightSegments(nextNodeId, out leftSegment, out rightSegment);
						int num6 = 0;
						//mCurrentState = 6;
						while (leftSegment != 0 && leftSegment != prevSegmentId && leftLaneId == 0u) {
							int num7;
							int num8;
							uint num9;
							uint num10;
							instance.m_segments.m_buffer[(int)leftSegment].GetLeftAndRightLanes(nextNodeId, NetInfo.LaneType.Pedestrian, VehicleInfo.VehicleType.None, -1, flag5, out num7, out num8, out num9, out num10);
							if (num10 != 0u) {
								num2 = leftSegment;
								laneIndex = num8;
								leftLaneId = num10;
							} else {
								leftSegment = instance.m_segments.m_buffer[(int)leftSegment].GetLeftSegment(nextNodeId);
							}
							if (++num6 == 8) {
								break;
							}
						}
						//mCurrentState = 7;
						num6 = 0;
						while (rightSegment != 0 && rightSegment != prevSegmentId && rightLaneId == 0u) {
							int num11;
							int num12;
							uint num13;
							uint num14;
							instance.m_segments.m_buffer[(int)rightSegment].GetLeftAndRightLanes(nextNodeId, NetInfo.LaneType.Pedestrian, VehicleInfo.VehicleType.None, -1, flag5, out num11, out num12, out num13, out num14);
							if (num13 != 0u) {
								num3 = rightSegment;
								laneIndex2 = num11;
								rightLaneId = num13;
							} else {
								rightSegment = instance.m_segments.m_buffer[(int)rightSegment].GetRightSegment(nextNodeId);
							}
							if (++num6 == 8) {
								break;
							}
						}
						//mCurrentState = 8;
					}
					if (leftLaneId != 0u && (num2 != prevSegmentId || flag4 || flag5)) {
						this.ProcessItemPedBicycle(item, nextNodeId, num2, ref instance.m_segments.m_buffer[(int)num2], connectOffset, laneIndex, leftLaneId); // ped
					}
					if (rightLaneId != 0u && rightLaneId != leftLaneId && (num3 != prevSegmentId || flag4 || flag5)) {
						this.ProcessItemPedBicycle(item, nextNodeId, num3, ref instance.m_segments.m_buffer[(int)num3], connectOffset, laneIndex2, rightLaneId); // ped
					}
					int laneIndex3;
					uint lane3;
					if ((this._vehicleTypes & VehicleInfo.VehicleType.Bicycle) != VehicleInfo.VehicleType.None && instance.m_segments.m_buffer[(int)prevSegmentId].GetClosestLane((int)item.m_position.m_lane, NetInfo.LaneType.Vehicle, VehicleInfo.VehicleType.Bicycle, out laneIndex3, out lane3)) {
						this.ProcessItemPedBicycle(item, nextNodeId, prevSegmentId, ref instance.m_segments.m_buffer[(int)prevSegmentId], connectOffset, laneIndex3, lane3); // bicycle
					}
				} else {
					//mCurrentState = 9;
					for (int j = 0; j < 8; j++) {
						ushort segment3 = nextNode.GetSegment(j);
						if (segment3 != 0 && segment3 != prevSegmentId) {
							this.ProcessItemCosts(false, debug, item, nextNodeId, segment3, ref instance.m_segments.m_buffer[(int)segment3], ref similarLaneIndexFromLeft, connectOffset, false, true);
						}
					}
					//mCurrentState = 10;
				}
				//mCurrentState = 11;
				NetInfo.LaneType laneType = this._laneTypes & ~NetInfo.LaneType.Pedestrian;
				VehicleInfo.VehicleType vehicleType = this._vehicleTypes & ~VehicleInfo.VehicleType.Bicycle;
				if ((byte)(item.m_lanesUsed & (NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle)) != 0) {
					laneType &= ~(NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle);
				}
				int num15;
				uint lane4;
				if (laneType != NetInfo.LaneType.None && vehicleType != VehicleInfo.VehicleType.None && instance.m_segments.m_buffer[(int)prevSegmentId].GetClosestLane(prevLaneIndex, laneType, vehicleType, out num15, out lane4)) {
					NetInfo.Lane lane5 = prevSegmentInfo.m_lanes[num15];
					byte connectOffset2;
					if ((instance.m_segments.m_buffer[(int)prevSegmentId].m_flags & NetSegment.Flags.Invert) != NetSegment.Flags.None == ((byte)(lane5.m_finalDirection & NetInfo.Direction.Backward) != 0)) {
						connectOffset2 = 1;
					} else {
						connectOffset2 = 254;
					}
					//mCurrentState = 12;
					this.ProcessItemPedBicycle(item, nextNodeId, prevSegmentId, ref instance.m_segments.m_buffer[(int)prevSegmentId], connectOffset2, num15, lane4); // ped
					//mCurrentState = 13;
				}
			} else {
				//mCurrentState = 14;
				bool mayTurnAround = (nextNode.m_flags & (NetNode.Flags.End | NetNode.Flags.OneWayOut)) != NetNode.Flags.None;
				bool pedestrianAllowed = (byte)(this._laneTypes & NetInfo.LaneType.Pedestrian) != 0;
				bool enablePedestrian = false;
				byte connectOffset3 = 0;
				if (pedestrianAllowed) {
					if (isBicycleLane) {
						connectOffset3 = connectOffset;
						enablePedestrian = (nextNode.Info.m_class.m_service == ItemClass.Service.Beautification);
					} else if (this._vehicleLane != 0u) {
						if (this._vehicleLane != item.m_laneID) {
							pedestrianAllowed = false;
						} else {
							connectOffset3 = this._vehicleOffset;
						}
					} else if (this._stablePath) {
						connectOffset3 = 128;
					} else {
						connectOffset3 = (byte)this._pathRandomizer.UInt32(1u, 254u);
					}
				}
				//mCurrentState = 15;

				// NON-STOCK CODE START //
#if DEBUGPF
				if (debug)
					logBuf.Add($"Exploring path! Segment {item.m_position.m_segment} @ node {nextNodeId}: Preparation started");
#endif

				CustomPathManager pathManager = Singleton<CustomPathManager>.instance;
				bool nextIsJunction = (nextNode.m_flags & NetNode.Flags.Junction) != NetNode.Flags.None;
				bool nextIsRealJunction = nextNode.CountSegments() > 2;
				bool nextIsTransition = (nextNode.m_flags & NetNode.Flags.Transition) != NetNode.Flags.None;
				bool prevIsHighway = false;
				if (prevSegmentInfo.m_netAI is RoadBaseAI)
					prevIsHighway = ((RoadBaseAI)prevSegmentInfo.m_netAI).m_highwayRules;
				//mCurrentState = 16;
				NetInfo.Direction normDirection = TrafficPriority.IsLeftHandDrive() ? NetInfo.Direction.Forward : NetInfo.Direction.Backward; // direction to normalize indices to
				int prevRightSimilarLaneIndex;
				int prevLeftSimilarLaneIndex;

				NetInfo.Lane lane = prevSegmentInfo.m_lanes[(int)item.m_position.m_lane];
				if ((byte)(lane.m_direction & normDirection) != 0) {
					prevRightSimilarLaneIndex = lane.m_similarLaneIndex;
					prevLeftSimilarLaneIndex = lane.m_similarLaneCount - lane.m_similarLaneIndex - 1;
				} else {
					prevRightSimilarLaneIndex = lane.m_similarLaneCount - lane.m_similarLaneIndex - 1;
					prevLeftSimilarLaneIndex = lane.m_similarLaneIndex;
				}
				bool foundForced = false;
				int totalIncomingLanes = 0;
				int totalOutgoingLanes = 0;
				bool isStrictLaneArrowPolicyEnabled = IsLaneArrowChangerEnabled() && _extVehicleType != ExtVehicleType.Emergency && (nextIsJunction || nextIsTransition) && !(Options.allRelaxed || (Options.relaxedBusses && _transportVehicle)) && (this._vehicleTypes & VehicleInfo.VehicleType.Car) != VehicleInfo.VehicleType.None;
				//mCurrentState = 17;
				// geometries are validated here
#if DEBUGPF
				/*if (m_queuedPathFindCount > 100 && Options.disableSomething1)
					Log._Debug($"THREAD #{Thread.CurrentThread.ManagedThreadId} PF {this._pathFindIndex}: Getting segment geometry of {prevSegmentId} @ {nextNodeId} START");*/
#endif
				SegmentGeometry geometry = IsMasterPathFind ? CustomRoadAI.GetSegmentGeometry(prevSegmentId, nextNodeId) : CustomRoadAI.GetSegmentGeometry(prevSegmentId);
#if DEBUGPF
				/*if (m_queuedPathFindCount > 100 && Options.disableSomething1)
					Log._Debug($"THREAD #{Thread.CurrentThread.ManagedThreadId} PF {this._pathFindIndex}: Getting segment geometry of {prevSegmentId} @ {nextNodeId} END");*/
#endif
				//mCurrentState = 18;
				bool prevIsOutgoingOneWay = geometry.IsOutgoingOneWay(nextNodeId);

				//mCurrentState = 19;
#if DEBUGPF
				/*if (m_queuedPathFindCount > 100 && Options.disableSomething1)
					Log._Debug($"THREAD #{Thread.CurrentThread.ManagedThreadId} PF {this._pathFindIndex}: Verifying segment geometry of {prevSegmentId} @ {nextNodeId} START");*/
#endif
				bool nextAreOnlyOneWayHighways = true;
				for (int k = 0; k < 8; k++) {
					ushort nextSegId = instance.m_nodes.m_buffer[nextNodeId].GetSegment(k);
					if (nextSegId == 0 || nextSegId == prevSegmentId) {
						continue;
					}

					if (IsMasterPathFind) {
						geometry.VerifyConnectedSegment(nextSegId);
					}

					if (instance.m_segments.m_buffer[nextSegId].Info.m_netAI is RoadBaseAI) {
						if (!CustomRoadAI.GetSegmentGeometry(nextSegId).IsOneWay() || !((RoadBaseAI)instance.m_segments.m_buffer[nextSegId].Info.m_netAI).m_highwayRules) {
							nextAreOnlyOneWayHighways = false;
							break;
						}
					} else {
						nextAreOnlyOneWayHighways = false;
						break;
					}
				}
				//mCurrentState = 20;
				
#if DEBUGPF
				/*if (m_queuedPathFindCount > 100 && Options.disableSomething1)
					Log._Debug($"THREAD #{Thread.CurrentThread.ManagedThreadId} PF {this._pathFindIndex}: Verifying segment geometry of {prevSegmentId} @ {nextNodeId} END");*/
#endif

				ushort[] incomingStraightSegmentsArray = null;
				ushort[] incomingRightSegmentsArray = null;
				ushort[] incomingLeftSegmentsArray = null;
				bool startNode = instance.m_segments.m_buffer[(int)prevSegmentId].m_startNode == nextNodeId;
				if (isStrictLaneArrowPolicyEnabled) {
					if (startNode) {
						incomingStraightSegmentsArray = geometry.StartNodeIncomingStraightSegmentsArray;
						incomingLeftSegmentsArray = geometry.StartNodeIncomingLeftSegmentsArray;
						incomingRightSegmentsArray = geometry.StartNodeIncomingRightSegmentsArray;
					} else {
						incomingStraightSegmentsArray = geometry.EndNodeIncomingStraightSegmentsArray;
						incomingLeftSegmentsArray = geometry.EndNodeIncomingLeftSegmentsArray;
						incomingRightSegmentsArray = geometry.EndNodeIncomingRightSegmentsArray;
					}
				}

				//mCurrentState = 21
				bool explorePrevSegment = Flags.getUTurnAllowed(prevSegmentId, startNode) && !Options.isStockLaneChangerUsed() && nextIsJunction && !prevIsHighway && !prevIsOutgoingOneWay && (_extVehicleType != null && (_extVehicleType & ExtVehicleType.RoadVehicle) != ExtVehicleType.None);
				ushort nextSegmentId = explorePrevSegment ? prevSegmentId : instance.m_segments.m_buffer[prevSegmentId].GetRightSegment(nextNodeId);
#if DEBUGPF
					if (debug)
						logBuf.Add($"Exploring path! Segment {item.m_position.m_segment} @ node {nextNodeId}: Preparation ended");
#endif

#if DEBUGPF
					if (debug)
						logBuf.Add($"pathfind @ node {nextNodeId}: Path from {nextSegmentId} to {prevSegmentId}.");
#endif
#if DEBUGPF
					if (debug)
						logBuf.Add($"Exploring path from {nextSegmentId} to {item.m_position.m_segment}, lane id {item.m_position.m_lane}, {prevRightSimilarLaneIndex} from right: Custom part started");
#endif
				// NON-STOCK CODE END //
				//mCurrentState = 22;
				for (int k = 0; k < 8; k++) {
#if DEBUGPF
					if (debug)
						logBuf.Add($"Exploring path from {nextSegmentId} to {item.m_position.m_segment}, lane id {item.m_position.m_lane}, {prevRightSimilarLaneIndex} from right: Segment Iteration {k}. nextSegmentId={nextSegmentId}");
#endif
					// NON-STOCK CODE START //
					int outgoingVehicleLanes = 0;
					int incomingVehicleLanes = 0;
					bool couldFindCustomPath = false;

					if (nextSegmentId == 0) {
						break;
					}
					if (!explorePrevSegment && nextSegmentId == prevSegmentId) {
						break;
					}

					//mCurrentState = 23;
					bool nextIsHighway = false;
					if (instance.m_segments.m_buffer[nextSegmentId].Info.m_netAI is RoadBaseAI)
						nextIsHighway = ((RoadBaseAI)instance.m_segments.m_buffer[nextSegmentId].Info.m_netAI).m_highwayRules;
					bool applyHighwayRules = Options.highwayRules && nextAreOnlyOneWayHighways && prevIsOutgoingOneWay && prevIsHighway && nextIsRealJunction;
					bool applyHighwayRulesAtSegment = applyHighwayRules;
					bool isUntouchable = (instance.m_segments.m_buffer[nextSegmentId].m_flags & NetSegment.Flags.Untouchable) != NetSegment.Flags.None;
					if (!isStrictLaneArrowPolicyEnabled || isUntouchable) {
#if DEBUGPF
						if (debug)
							logBuf.Add($"Exploring path from {nextSegmentId} to {item.m_position.m_segment}, lane id {item.m_position.m_lane}, {prevRightSimilarLaneIndex} from right: strict lane arrow policy disabled. ({nextIsJunction} || {nextIsTransition}) && !({Options.allRelaxed} || ({Options.relaxedBusses} && {_transportVehicle})) && {(this._vehicleTypes & VehicleInfo.VehicleType.Car) != VehicleInfo.VehicleType.None}");
#endif

							// NON-STOCK CODE END //
							//mCurrentState = 24;
						if (ProcessItemCosts(true, debug, item, nextNodeId, nextSegmentId, ref instance.m_segments.m_buffer[nextSegmentId], ref similarLaneIndexFromLeft, connectOffset, true, enablePedestrian)) {
							mayTurnAround = true;
						}
						//mCurrentState = 25;
						// NON-STOCK CODE START //
						couldFindCustomPath = true; // not of interest
					} else if (!enablePedestrian) {
						//mCurrentState = 26;

						if ((_vehicleTypes & ~VehicleInfo.VehicleType.Car) != VehicleInfo.VehicleType.None) {
							// handle non-car paths

#if DEBUGPF
							if (debug)
								logBuf.Add($"Exploring path from {nextSegmentId} to {item.m_position.m_segment}, lane id {item.m_position.m_lane}, {prevRightSimilarLaneIndex} from right: Handling everything that is not a car: {this._vehicleTypes}");
#endif

							_vehicleTypes &= ~VehicleInfo.VehicleType.Car;
							if (ProcessItemCosts(false, debug, item, nextNodeId, nextSegmentId, ref instance.m_segments.m_buffer[nextSegmentId], ref similarLaneIndexFromLeft, connectOffset, true, enablePedestrian)) {
								mayTurnAround = true;
							}
							_vehicleTypes |= VehicleInfo.VehicleType.Car;
						}
#if DEBUGPF
						if (debug)
							logBuf.Add($"Exploring path from {nextSegmentId} to {item.m_position.m_segment}, lane id {item.m_position.m_lane}, {prevRightSimilarLaneIndex} from right: !enablePedestrian");
#endif

						//try {
						var nextSegmentInfo = instance.m_segments.m_buffer[nextSegmentId].Info;
						bool isIncomingRight = false;
						bool isIncomingStraight = false;
						bool isIncomingLeft = false;
						bool isIncomingTurn = false;

						if (nextSegmentId != prevSegmentId) {
							for (int j = 0; j < 7; ++j) {
								if (incomingRightSegmentsArray[j] == nextSegmentId)
									isIncomingRight = true;
								if (incomingLeftSegmentsArray[j] == nextSegmentId)
									isIncomingLeft = true;
								if (incomingStraightSegmentsArray[j] == nextSegmentId)
									isIncomingStraight = true;
							}
						} else {
							isIncomingTurn = true;
						}

						// we need outgoing lanes too!
						if (!isIncomingTurn && !isIncomingLeft && !isIncomingRight && !isIncomingStraight) {
#if DEBUGPF
							if (debug)
								logBuf.Add($"(PFWARN) Segment {nextSegmentId} is neither incoming left, right or straight segment @ {nextNodeId}, going to segment {prevSegmentId}");
#endif
							// recalculate geometry if segment is unknown
							geometry.VerifyConnectedSegment(nextSegmentId);

							if (!applyHighwayRulesAtSegment) {
								couldFindCustomPath = true; // not of interest
								goto nextIter;
							} else {
								// we do not stop here because we need the number of outgoing lanes in highway mode
							}
						}
						//mCurrentState = 27;
						VehicleInfo.VehicleType vehicleType2 = this._vehicleTypes;
						NetInfo.LaneType drivingEnabledLaneTypes = this._laneTypes;
						drivingEnabledLaneTypes &= ~NetInfo.LaneType.Pedestrian;
						drivingEnabledLaneTypes &= ~NetInfo.LaneType.Parking;

						//if (debug) {
						//Log.Message($"Path finding ({this._pathFindIndex}): Segment {nextSegmentId}");
						//}

						NetInfo.Direction nextDir = instance.m_segments.m_buffer[nextSegmentId].m_startNode != nextNodeId ? NetInfo.Direction.Forward : NetInfo.Direction.Backward;
						NetInfo.Direction nextDir2 = ((instance.m_segments.m_buffer[nextSegmentId].m_flags & NetSegment.Flags.Invert) == NetSegment.Flags.None) ? nextDir : NetInfo.InvertDirection(nextDir);

						// valid next lanes:
						int[] laneIndexes = new int[16]; // index of NetNode.Info.m_lanes
						uint[] laneIds = new uint[16]; // index of NetManager.m_lanes.m_buffer
						uint[] indexByRightSimilarLaneIndex = new uint[16];
						uint[] indexByLeftSimilarLaneIndex = new uint[16];

						uint curLaneI = 0;
						uint curLaneId = instance.m_segments.m_buffer[nextSegmentId].m_lanes;
						int laneIndex = 0;
#if DEBUG
						uint wIter = 0;
#endif
						//mCurrentState = 28;
						while (laneIndex < nextSegmentInfo.m_lanes.Length && curLaneId != 0u) {
							//mCurrentState = 29;
#if DEBUGPF
							if (debug)
								logBuf.Add($"Exploring path from {nextSegmentId} to {item.m_position.m_segment}, lane id {item.m_position.m_lane}, {prevRightSimilarLaneIndex} from right: Lane Iteration {laneIndex}. nextSegmentId={nextSegmentId}, curLaneId={curLaneId}");
#endif

#if DEBUG
							++wIter;
							if (wIter >= 20) {
								Log.Error("Too many iterations in ProcessItemMain!");
								break;
							}
#endif

							// determine valid lanes based on lane arrows
							NetInfo.Lane nextLane = nextSegmentInfo.m_lanes[laneIndex];
							bool incomingLane = (byte)(nextLane.m_finalDirection & nextDir2) != 0;
							bool compatibleLane = nextLane.CheckType(drivingEnabledLaneTypes, _vehicleTypes);

							if (incomingLane && compatibleLane) {
								++incomingVehicleLanes;
#if DEBUGPF
								if (debug)
									logBuf.Add($"Segment {nextSegmentId}, lane {curLaneId}, {laneIndex} is compatible (prevSegment: {prevSegmentId}). laneTypes: {_laneTypes.ToString()}, vehicleTypes: {_vehicleTypes.ToString()}, incomingLanes={incomingVehicleLanes}, isIncomingRight? {isIncomingRight}, isIncomingLeft? {isIncomingLeft}, isIncomingStraight? {isIncomingStraight}");
#endif

								// calculate current similar lane index starting from right line
								int nextRightSimilarLaneIndex;
								int nextLeftSimilarLaneIndex;
								if ((byte)(nextLane.m_direction & normDirection) != 0) {
									nextRightSimilarLaneIndex = nextLane.m_similarLaneIndex;
									nextLeftSimilarLaneIndex = nextLane.m_similarLaneCount - nextLane.m_similarLaneIndex - 1;
								} else {
									nextRightSimilarLaneIndex = nextLane.m_similarLaneCount - nextLane.m_similarLaneIndex - 1;
									nextLeftSimilarLaneIndex = nextLane.m_similarLaneIndex;
								}

								bool hasLeftArrow = ((NetLane.Flags)instance.m_lanes.m_buffer[curLaneId].m_flags & NetLane.Flags.Left) == NetLane.Flags.Left;
								bool hasRightArrow = ((NetLane.Flags)instance.m_lanes.m_buffer[curLaneId].m_flags & NetLane.Flags.Right) == NetLane.Flags.Right;
								bool hasForwardArrow = ((NetLane.Flags)instance.m_lanes.m_buffer[curLaneId].m_flags & NetLane.Flags.Forward) != NetLane.Flags.None || ((NetLane.Flags)instance.m_lanes.m_buffer[curLaneId].m_flags & NetLane.Flags.LeftForwardRight) == NetLane.Flags.None;
#if DEBUGPF
								if (debug) {
									if (hasLeftArrow) {
										logBuf.Add($"Segment {nextSegmentId}, lane {curLaneId}, {laneIndex} has LEFT arrow. isIncomingRight? {isIncomingRight}, isIncomingLeft? {isIncomingLeft}, isIncomingStraight? {isIncomingStraight}");
									}

									if (hasRightArrow) {
										logBuf.Add($"Segment {nextSegmentId}, lane {curLaneId}, {laneIndex} has RIGHT arrow. isIncomingRight? {isIncomingRight}, isIncomingLeft? {isIncomingLeft}, isIncomingStraight? {isIncomingStraight}");
									}

									if (hasForwardArrow) {
										logBuf.Add($"Segment {nextSegmentId}, lane {curLaneId}, {laneIndex} has FORWARD arrow. isIncomingRight? {isIncomingRight}, isIncomingLeft? {isIncomingLeft}, isIncomingStraight? {isIncomingStraight}");
									}
								}
#endif

								bool isValidIncomingRight = isIncomingRight && hasLeftArrow;
								bool isValidIncomingLeft = isIncomingLeft && hasRightArrow;
								bool isValidIncomingStraight = isIncomingStraight && hasForwardArrow;
								bool isValidIncomingTurn = isIncomingTurn && ((TrafficPriority.IsLeftHandDrive() && hasRightArrow) || (!TrafficPriority.IsLeftHandDrive() && hasLeftArrow));

#if DEBUGPF
								if (debug)
									logBuf.Add($"Segment {nextSegmentId}, lane {curLaneId}, {laneIndex}. isValidIncomingRight? {isValidIncomingRight}, isValidIncomingLeft? {isValidIncomingLeft}, isValidIncomingStraight? {isValidIncomingStraight} isValidIncomingTurn? {isValidIncomingTurn}");
#endif

									// add valid next lanes
								if (applyHighwayRulesAtSegment || isValidIncomingRight || isValidIncomingLeft || isValidIncomingStraight || isValidIncomingTurn) {
									laneIndexes[curLaneI] = laneIndex;
									laneIds[curLaneI] = curLaneId;
									indexByRightSimilarLaneIndex[nextRightSimilarLaneIndex] = curLaneI + 1;
									indexByLeftSimilarLaneIndex[nextLeftSimilarLaneIndex] = curLaneI + 1;
#if DEBUGPF
									if (debug)
										logBuf.Add($"Adding lane #{curLaneI} (id {curLaneId}, idx {laneIndex}), right sim. idx: {nextRightSimilarLaneIndex}, left sim. idx.: {nextLeftSimilarLaneIndex}");
#endif
									curLaneI++;
								}
							}

							if (!incomingLane && compatibleLane) {
								// outgoing lane
								++outgoingVehicleLanes;
							}

							curLaneId = instance.m_lanes.m_buffer[(int)((UIntPtr)curLaneId)].m_nextLane;
							laneIndex++;
						} // foreach lane
						//mCurrentState = 30;

						if (curLaneI > 0) {
							//mCurrentState = 31;
							// we found compatible lanes
							var nextLaneIndex = 0;
							var nextLaneId = 0u;
							int nextLaneI = -1;
							int nextCompatibleLaneCount = Convert.ToInt32(curLaneI);

#if DEBUGPF
							if (debug) {
								logBuf.Add($"Compatible lanes found.");
								logBuf.Add($"next segment: {nextSegmentId}, number of next lanes: {nextCompatibleLaneCount}, prev. segment: {prevSegmentId}, prev. lane ID: {item.m_laneID}, prev. lane idx: {item.m_position.m_lane}, prev. right sim. idx: {prevRightSimilarLaneIndex}, prev. left sim. idx: {prevLeftSimilarLaneIndex}, laneTypes: {_laneTypes.ToString()}, vehicleTypes: {_vehicleTypes.ToString()}, incomingLanes={incomingVehicleLanes}, isIncomingRight? {isIncomingRight}, isIncomingLeft? {isIncomingLeft}, isIncomingStraight? {isIncomingStraight}");
							}
#endif

							// mix of incoming/outgoing lanes on the right sight of prev segment is not allowed in highway mode
							if (totalIncomingLanes > 0 && totalOutgoingLanes > 0) {
#if DEBUGPF
								if (debug)
									logBuf.Add($"{totalIncomingLanes} incoming lanes and {totalOutgoingLanes} outgoing lanes found. Disabling highway rules.");
#endif
								applyHighwayRulesAtSegment = false;
							}

							
							if (applyHighwayRulesAtSegment) {
								//mCurrentState = 32;
								int numRightLanes = Math.Max(totalIncomingLanes, totalOutgoingLanes);
#if DEBUGPF
								if (debug)
									logBuf.Add($"Applying highway rules. {numRightLanes} right lanes found ({totalIncomingLanes} incoming, {totalOutgoingLanes} outgoing).");
#endif
								int nextLeftSimilarIndex;
								if (totalOutgoingLanes > 0) {
									nextLeftSimilarIndex = prevLeftSimilarLaneIndex + numRightLanes; // lane splitting
#if DEBUGPF
									if (debug)
										logBuf.Add($"Performing lane split. nextLeftSimilarIndex={nextLeftSimilarIndex} = prevLeftSimilarIndex({prevLeftSimilarLaneIndex}) + numRightLanes({numRightLanes})");
#endif
								} else {
									nextLeftSimilarIndex = prevLeftSimilarLaneIndex - numRightLanes; // lane merging
#if DEBUGPF
									if (debug)
										logBuf.Add($"Performing lane merge. nextLeftSimilarIndex={nextLeftSimilarIndex} = prevLeftSimilarIndex({prevLeftSimilarLaneIndex}) - numRightLanes({numRightLanes})");
#endif
								}

								if (nextLeftSimilarIndex >= 0 && nextLeftSimilarIndex < nextCompatibleLaneCount) {
									// enough lanes available
									nextLaneI = Convert.ToInt32(indexByLeftSimilarLaneIndex[nextLeftSimilarIndex]) - 1;
#if DEBUGPF
									if (debug)
										logBuf.Add($"Next lane within bounds. nextLaneI={nextLaneI}");
#endif
								} else {
									if (nextLeftSimilarIndex < 0) {
										// too few lanes at prevSegment or nextSegment: sort right
										if (totalIncomingLanes >= prevSimiliarLaneCount)
											nextLaneI = Convert.ToInt32(indexByRightSimilarLaneIndex[prevRightSimilarLaneIndex]) - 1;
									} else {
										if (totalOutgoingLanes >= nextCompatibleLaneCount)
											nextLaneI = Convert.ToInt32(indexByRightSimilarLaneIndex[0]) - 1;
									}
#if DEBUGPF
									if (debug)
										logBuf.Add($"Next lane out of bounds. nextLaneI={nextLaneI}, isIncomingLeft={isIncomingLeft}, prevRightSimilarIndex={prevRightSimilarLaneIndex}, prevLeftSimilarIndex={prevLeftSimilarLaneIndex}");
#endif
								}

								if (nextLaneI < 0 || nextLaneI >= nextCompatibleLaneCount) {
#if DEBUGPF
									if (debug)
										Log.Error($"(PFERR) Exploring path from {nextSegmentId} ({nextDir}) to {item.m_position.m_segment}, lane id {item.m_position.m_lane}, {prevRightSimilarLaneIndex} from right, {prevLeftSimilarLaneIndex} from left: Highway lane selector cannot find suitable lane! isIncomingLeft={isIncomingLeft} isIncomingRight={isIncomingRight} totalIncomingLanes={totalIncomingLanes}");
#endif
									couldFindCustomPath = true; // not of interest for us
									//mCurrentState = 33;
									goto nextIter; // no path to this lane
								}
							} else if (nextCompatibleLaneCount == 1) {
								//mCurrentState = 34;
								nextLaneI = 0;
#if DEBUGPF
								if (debug)
									logBuf.Add($"Single target lane found. nextLaneI={nextLaneI}");
#endif
							} else {
								//mCurrentState = 35;
								// lane matching
								int prevSimilarLaneCount = lane.m_similarLaneCount;

#if DEBUGPF
								if (debug)
									logBuf.Add($"Multiple target lanes found. prevSimilarLaneCount={prevSimilarLaneCount}");
#endif

								int minNextRightSimilarIndex = -1;
								int maxNextRightSimilarIndex = -1;
								if (nextIsRealJunction) {
									// at junctions: try to match distinct lanes (1-to-1, n-to-1)
									minNextRightSimilarIndex = prevRightSimilarLaneIndex;
									maxNextRightSimilarIndex = prevRightSimilarLaneIndex;

									// vehicles may change lanes at straight segments?w
									if (isIncomingStraight && Flags.getStraightLaneChangingAllowed(nextSegmentId, Singleton<NetManager>.instance.m_segments.m_buffer[nextSegmentId].m_startNode == nextNodeId)) {
										minNextRightSimilarIndex = Math.Max(0, minNextRightSimilarIndex - 1);
										maxNextRightSimilarIndex = Math.Min(nextCompatibleLaneCount - 1, maxNextRightSimilarIndex + 1);
#if DEBUGPF
										if (debug)
											logBuf.Add($"Next is incoming straight. Allowing lane changes! minNextRightSimilarIndex={minNextRightSimilarIndex}, maxNextRightSimilarIndex={maxNextRightSimilarIndex}");
#endif
									}
#if DEBUGPF
									if (debug)
										logBuf.Add($"Next is junction. minNextRightSimilarIndex={minNextRightSimilarIndex}, maxNextRightSimilarIndex={maxNextRightSimilarIndex}");
#endif
								} else {
									// lane merging/splitting
									//mCurrentState = 36;
									HandleLaneMergesAndSplits(prevRightSimilarLaneIndex, nextCompatibleLaneCount, prevSimilarLaneCount, out minNextRightSimilarIndex, out maxNextRightSimilarIndex);
									//mCurrentState = 37;
#if DEBUGPF
									if (debug)
										logBuf.Add($"Next is not a junction. nextRightSimilarLaneIndex=HandleLaneMergesAndSplits({prevRightSimilarLaneIndex}, {nextCompatibleLaneCount}, {prevSimilarLaneCount})= min. {minNextRightSimilarIndex} max. {maxNextRightSimilarIndex}");
#endif
								}

								// find best matching lane(s)
								for (int nextRightSimilarIndex = minNextRightSimilarIndex; nextRightSimilarIndex <= maxNextRightSimilarIndex; ++nextRightSimilarIndex) {
#if DEBUGPF
									if (debug)
										logBuf.Add($"current right similar index = {nextRightSimilarIndex}, min. {minNextRightSimilarIndex} max. {maxNextRightSimilarIndex}");
#endif
									//mCurrentState = 38;
									nextLaneI = FindNthCompatibleLane(ref indexByRightSimilarLaneIndex, nextRightSimilarIndex);
									//mCurrentState = 39;

#if DEBUGPF
									if (debug)
										logBuf.Add($"(*) nextLaneI = {nextLaneI}");
#endif
									if (nextLaneI < 0) {
										continue;
									}

									// go to matched lane
									nextLaneIndex = laneIndexes[nextLaneI];
									nextLaneId = laneIds[nextLaneI];

#if DEBUGPF
									if (debug)
										logBuf.Add($"Exploring path from {nextSegmentId} ({nextDir}) to {item.m_position.m_segment}, lane idx {item.m_position.m_lane}, {prevRightSimilarLaneIndex} from right. There are {curLaneI} candidate lanes. We choose lane {nextLaneI} (index {nextLaneIndex}, {nextRightSimilarIndex} compatible from right). lhd: {TrafficPriority.IsLeftHandDrive()}, ped: {pedestrianAllowed}, magical flag4: {mayTurnAround}");
#endif

									//mCurrentState = 40;
									if (ProcessItemCosts(true, debug, item, nextNodeId, nextSegmentId, ref instance.m_segments.m_buffer[nextSegmentId], ref similarLaneIndexFromLeft, connectOffset, true, enablePedestrian, nextLaneIndex, nextLaneId, out foundForced)) {
										mayTurnAround = true;
									}
									//mCurrentState = 41;
									couldFindCustomPath = true;
								}

								goto nextIter;
							}

							//mCurrentState = 42;
							if (nextLaneI < 0) {
#if DEBUGPF
								if (debug)
									Log.Error($"(PFERR) Exploring path from {nextSegmentId} ({nextDir}) to {item.m_position.m_segment}, lane id {item.m_position.m_lane}, {prevRightSimilarLaneIndex} from right: nextLaneI < 0!");
#endif
								//mCurrentState = 43;
								goto nextIter;
							}

							//mCurrentState = 44;
							// go to matched lane
							nextLaneIndex = laneIndexes[nextLaneI];
							nextLaneId = laneIds[nextLaneI];

#if DEBUGPF
							if (debug)
								logBuf.Add($"Exploring path from {nextSegmentId} ({nextDir}) to {item.m_position.m_segment}, lane id {item.m_position.m_lane}, {prevRightSimilarLaneIndex} from right: nextLaneIndex={nextLaneIndex} nextLaneId={nextLaneId}");
#endif

							//mCurrentState = 45;
							if (IsMasterPathFind && applyHighwayRulesAtSegment) {
								// udpate highway mode arrows
#if DEBUGPF
								/*if (Options.disableSomething1)
									Log._Debug($"THREAD #{Thread.CurrentThread.ManagedThreadId} PF {this._pathFindIndex}: Setting highway arrows @ lane {nextLaneId}: START");*/
#endif
								Flags.LaneArrows? prevHighwayArrows = Flags.getHighwayLaneArrowFlags(nextLaneId);
								Flags.LaneArrows newHighwayArrows = Flags.LaneArrows.None;
								if (prevHighwayArrows != null)
									newHighwayArrows = (Flags.LaneArrows)prevHighwayArrows;
								if (isIncomingRight)
									newHighwayArrows |= Flags.LaneArrows.Left;
								else if (isIncomingLeft)
									newHighwayArrows |= Flags.LaneArrows.Right;
								else if (isIncomingStraight)
									newHighwayArrows |= Flags.LaneArrows.Forward;

								if (newHighwayArrows != prevHighwayArrows && newHighwayArrows != Flags.LaneArrows.None)
									Flags.setHighwayLaneArrowFlags(nextLaneId, newHighwayArrows);
#if DEBUGPF
								/*if (Options.disableSomething1)
									Log._Debug($"THREAD #{Thread.CurrentThread.ManagedThreadId} PF {this._pathFindIndex}: Setting highway arrows @ lane {nextLaneId} to {newHighwayArrows.ToString()}: END");*/
#endif
							}
							//mCurrentState = 46;

							if (ProcessItemCosts(true, debug, item, nextNodeId, nextSegmentId, ref instance.m_segments.m_buffer[nextSegmentId], ref similarLaneIndexFromLeft, connectOffset, true, enablePedestrian, nextLaneIndex, nextLaneId, out foundForced)) {
								mayTurnAround = true;
							}
							//mCurrentState = 47;

							if (foundForced) {
#if DEBUGPF
								if (debug)
									logBuf.Add($"Exploring path from {nextSegmentId} ({nextDir}) to {item.m_position.m_segment}, lane id {item.m_position.m_lane}, {prevRightSimilarLaneIndex} from right: FORCED LANE FOUND!");
#endif
								couldFindCustomPath = true;
							}
						} else {
							// no compatible lanes found
							//mCurrentState = 48;
#if DEBUGPF
							if (debug)
								Log.Error($"(PFERR) Exploring path from {nextSegmentId} ({nextDir}) to {item.m_position.m_segment}, lane id {item.m_position.m_lane}, {prevRightSimilarLaneIndex} from right: No lane arrows defined");
#endif
							couldFindCustomPath = true; // the player did not set lane arrows. this is ok...
														/*if (ProcessItem(debug, item, nextNodeId, nextSegmentId, ref instance.m_segments.m_buffer[nextSegmentId], ref similarLaneIndexFromLeft, connectOffset, true, enablePedestrian)) {
															blocked = true;
														}*/
						}
						/*} catch (Exception e) {
							Log.Error($"(PFERR) Error occurred in custom path-finding (main): {e.ToString()}");

							couldFindCustomPath = true; // not of interest for us
														// stock code fallback
							if (this.ProcessItemSub(debug, item, nextNodeId, nextSegmentId, ref instance.m_segments.m_buffer[(int)nextSegmentId], ref similarLaneIndexFromLeft, connectOffset, true, enablePedestrian)) {
								blocked = true;
							}
						}*/
						// NON-STOCK CODE END
					} else {
						//mCurrentState = 49;
						// pedestrians

						// stock code:
						if (this.ProcessItemCosts(false, debug, item, nextNodeId, nextSegmentId, ref instance.m_segments.m_buffer[(int)nextSegmentId], ref similarLaneIndexFromLeft, connectOffset, true, enablePedestrian)) {
							mayTurnAround = true;
						}
						couldFindCustomPath = true; // not of interest for us
						//mCurrentState = 50;
					}

					nextIter:
					//mCurrentState = 51;
					if (!couldFindCustomPath) {
#if DEBUGPF
						if (debug)
							logBuf.Add($"(PFERR) Could not find custom path from segment {nextSegmentId} to segment {prevSegmentId}, lane {item.m_position.m_lane}, off {item.m_position.m_offset} at node {nextNodeId}!");
#endif
						// stock code:
						/*if (this.ProcessItem(debug, item, nextNodeId, nextSegmentId, ref instance.m_segments.m_buffer[(int)nextSegmentId], ref similarLaneIndexFromLeft, connectOffset, true, enablePedestrian)) {
							blocked = true;
						}*/
					}

					if (nextSegmentId == prevSegmentId)
						similarLaneIndexFromLeft = firstSimilarLaneIndexFromLeft; // u-turning does not "consume" a lane

					nextSegmentId = instance.m_segments.m_buffer[(int)nextSegmentId].GetRightSegment(nextNodeId);
					if (nextSegmentId != prevSegmentId) {
						totalIncomingLanes += incomingVehicleLanes;
						totalOutgoingLanes += outgoingVehicleLanes;
					}

					if (explorePrevSegment && nextSegmentId == prevSegmentId)
						break;
					//mCurrentState = 52;
				} // foreach segment
				//mCurrentState = 53;
#if DEBUGPF
				if (debug)
					logBuf.Add($"Exploring path from {nextSegmentId} to {item.m_position.m_segment}, lane id {item.m_position.m_lane}, {prevRightSimilarLaneIndex} from right: Custom part finished");
#endif
				if (mayTurnAround && (this._vehicleTypes & VehicleInfo.VehicleType.Tram) == VehicleInfo.VehicleType.None) {
					// turn-around for vehicles (if street is blocked)
#if DEBUGPF
					if (debug)
						logBuf.Add($"Exploring path from {nextSegmentId} to {item.m_position.m_segment}, lane id {item.m_position.m_lane}, {prevRightSimilarLaneIndex} from right: Road may be blocked");
#endif
					// vehicles may turn around if the street is blocked
					nextSegmentId = item.m_position.m_segment;
					//mCurrentState = 54;
					this.ProcessItemCosts(false, debug, item, nextNodeId, nextSegmentId, ref instance.m_segments.m_buffer[(int)nextSegmentId], ref similarLaneIndexFromLeft, connectOffset, true, false);
					//mCurrentState = 55;
				}
				//mCurrentState = 56;
				// NON-STOCK CODE START
				/*if (foundForced)
					return;*/
				// NON-STOCK CODE END
				if (pedestrianAllowed) {
					// turn-around for pedestrians
#if DEBUGPF
						if (debug)
							logBuf.Add($"Exploring path from {nextSegmentId} to {item.m_position.m_segment}, lane id {item.m_position.m_lane}, {prevRightSimilarLaneIndex} from right: Ped allowed");
#endif
					nextSegmentId = item.m_position.m_segment;
					int laneIndex4;
					uint lane6;
					if (instance.m_segments.m_buffer[(int)nextSegmentId].GetClosestLane((int)item.m_position.m_lane, NetInfo.LaneType.Pedestrian, this._vehicleTypes, out laneIndex4, out lane6)) {
						//mCurrentState = 57;
						this.ProcessItemPedBicycle(item, nextNodeId, nextSegmentId, ref instance.m_segments.m_buffer[(int)nextSegmentId], connectOffset3, laneIndex4, lane6); // ped
						//mCurrentState = 58;
					}
				}
			}
			if (nextNode.m_lane != 0u) {
				bool targetDisabled = (nextNode.m_flags & NetNode.Flags.Disabled) != NetNode.Flags.None;
				ushort segment4 = instance.m_lanes.m_buffer[(int)((UIntPtr)nextNode.m_lane)].m_segment;
				if (segment4 != 0 && segment4 != item.m_position.m_segment) {
#if DEBUGPF
						if (debug)
							logBuf.Add($"Exploring path from {segment4} to {item.m_position.m_segment}, lane id {item.m_position.m_lane}: handling special lanes");
#endif
					//mCurrentState = 59;
					this.ProcessItem2(item, nextNodeId, targetDisabled, segment4, ref instance.m_segments.m_buffer[(int)segment4], nextNode.m_lane, nextNode.m_laneOffset, connectOffset);
					//mCurrentState = 60;
				}
			}
			//mCurrentState = 61;
#if DEBUGPF
			if (debug) {
				foreach (String toLog in logBuf) {
					Log._Debug($"Pathfinder ({this._pathFindIndex}) for unit {unitId}: " + toLog);
				}
			}
#endif
			//mCurrentState = 62;
		}
 private void ProcessItem5(BufferItem item, ushort targetNode, ushort segmentId, ref NetSegment segment, byte connectOffset, int laneIndex, uint lane)
 {
     if ((segment.m_flags & (NetSegment.Flags.PathFailed | NetSegment.Flags.Flooded)) != NetSegment.Flags.None)
     {
         return;
     }
     var instance = Singleton<NetManager>.instance;
     var info = segment.Info;
     var info2 = instance.m_segments.m_buffer[item.Position.m_segment].Info;
     var num = info.m_lanes.Length;
     float num2;
     byte offset;
     if (segmentId == item.Position.m_segment)
     {
         Vector3 b = instance.m_lanes.m_buffer[(int)((UIntPtr)item.LaneId)].CalculatePosition(connectOffset * 0.003921569f);
         Vector3 a = instance.m_lanes.m_buffer[(int)((UIntPtr)lane)].CalculatePosition(connectOffset * 0.003921569f);
         num2 = Vector3.Distance(a, b);
         offset = connectOffset;
     }
     else
     {
         NetInfo.Direction direction = (targetNode != segment.m_startNode) ? NetInfo.Direction.Forward : NetInfo.Direction.Backward;
         Vector3 b2 = instance.m_lanes.m_buffer[(int)((UIntPtr)item.LaneId)].CalculatePosition(connectOffset * 0.003921569f);
         Vector3 a2;
         if ((byte)(direction & NetInfo.Direction.Forward) != 0)
         {
             a2 = instance.m_lanes.m_buffer[(int)((UIntPtr)lane)].m_bezier.d;
         }
         else
         {
             a2 = instance.m_lanes.m_buffer[(int)((UIntPtr)lane)].m_bezier.a;
         }
         num2 = Vector3.Distance(a2, b2);
         offset = (byte)(((byte)(direction & NetInfo.Direction.Forward) == 0) ? 0 : 255);
     }
     float num3 = 1f;
     float num4 = 1f;
     NetInfo.LaneType laneType = NetInfo.LaneType.None;
     if (item.Position.m_lane < info2.m_lanes.Length)
     {
         NetInfo.Lane lane2 = info2.m_lanes[item.Position.m_lane];
         num3 = lane2.m_speedLimit;
         laneType = lane2.m_laneType;
         num4 = CalculateLaneSpeed(connectOffset, item.Position.m_offset, ref instance.m_segments.m_buffer[item.Position.m_segment], lane2);
     }
     float averageLength = instance.m_segments.m_buffer[item.Position.m_segment].m_averageLength;
     float num5 = Mathf.Abs(connectOffset - item.Position.m_offset) * 0.003921569f * averageLength;
     float num6 = item.MethodDistance + num5;
     float num7 = item.ComparisonValue + num5 / (num4 * _maxLength);
     if (laneIndex < num)
     {
         NetInfo.Lane lane3 = info.m_lanes[laneIndex];
         BufferItem item2;
         item2.Position.m_segment = segmentId;
         item2.Position.m_lane = (byte)laneIndex;
         item2.Position.m_offset = offset;
         if (laneType != lane3.m_laneType)
         {
             item2.MethodDistance = 0f;
         }
         else
         {
             item2.MethodDistance = num6 + num2;
         }
         if (lane3.m_laneType != NetInfo.LaneType.Pedestrian || item2.MethodDistance < 1000f)
         {
             item2.ComparisonValue = num7 + num2 / ((num3 + lane3.m_speedLimit) * 0.25f * _maxLength);
             if (lane == _startLaneA)
             {
                 float num8 = CalculateLaneSpeed(_startOffsetA, item2.Position.m_offset, ref segment, lane3);
                 float num9 = Mathf.Abs(item2.Position.m_offset - _startOffsetA) * 0.003921569f;
                 item2.ComparisonValue += num9 * segment.m_averageLength / (num8 * _maxLength);
             }
             if (lane == _startLaneB)
             {
                 float num10 = CalculateLaneSpeed(_startOffsetB, item2.Position.m_offset, ref segment, lane3);
                 float num11 = Mathf.Abs(item2.Position.m_offset - _startOffsetB) * 0.003921569f;
                 item2.ComparisonValue += num11 * segment.m_averageLength / (num10 * _maxLength);
             }
             if ((segment.m_flags & NetSegment.Flags.Invert) != NetSegment.Flags.None)
             {
                 item2.Direction = NetInfo.InvertDirection(lane3.m_finalDirection);
             }
             else
             {
                 item2.Direction = lane3.m_finalDirection;
             }
             item2.LaneId = lane;
             item2.LanesUsed = (item.LanesUsed | lane3.m_laneType);
             AddBufferItem(item2, item.Position);
         }
     }
 }
Exemplo n.º 27
0
 public override bool FilterBuffer(BufferItem item)
 {
     return(item.TypeName == "ApiRequestProcessInfo");
 }
 private void AddBufferItem(BufferItem item, PathUnit.Position target)
 {
     uint num = _laneLocation[(int)((UIntPtr)item.LaneId)];
     uint num2 = num >> 16;
     int num3 = (int)(num & 65535u);
     int num6;
     if (num2 == _pathFindIndex)
     {
         if (item.ComparisonValue >= _buffer[num3].ComparisonValue)
         {
             return;
         }
         int num4 = num3 >> 6;
         int num5 = num3 & -64;
         if (num4 < _bufferMinPos || (num4 == _bufferMinPos && num5 < _bufferMin[num4]))
         {
             return;
         }
         num6 = Mathf.Max(Mathf.RoundToInt(item.ComparisonValue * 1024f), _bufferMinPos);
         if (num6 == num4)
         {
             _buffer[num3] = item;
             _laneTarget[(int)((UIntPtr)item.LaneId)] = target;
             return;
         }
         int num7 = num4 << 6 | _bufferMax[num4]--;
         BufferItem bufferItem = _buffer[num7];
         _laneLocation[(int)((UIntPtr)bufferItem.LaneId)] = num;
         _buffer[num3] = bufferItem;
     }
     else
     {
         num6 = Mathf.Max(Mathf.RoundToInt(item.ComparisonValue * 1024f), _bufferMinPos);
     }
     if (num6 >= 1024)
     {
         return;
     }
     while (_bufferMax[num6] == 63)
     {
         num6++;
         if (num6 == 1024)
         {
             return;
         }
     }
     if (num6 > _bufferMaxPos)
     {
         _bufferMaxPos = num6;
     }
     num3 = (num6 << 6 | ++_bufferMax[num6]);
     _buffer[num3] = item;
     _laneLocation[(int)((UIntPtr)item.LaneId)] = (_pathFindIndex << 16 | (uint)num3);
     _laneTarget[(int)((UIntPtr)item.LaneId)] = target;
 }
 protected virtual void ProcessItem(BufferItem item, ushort targetNode, ushort segmentID, ref NetSegment segment, byte connectOffset, int laneIndex, uint lane)
 {
     if ((segment.m_flags & (NetSegment.Flags.PathFailed | NetSegment.Flags.Flooded)) != NetSegment.Flags.None)
     {
         return;
     }
     NetManager instance = Singleton<NetManager>.instance;
     NetInfo info = segment.Info;
     NetInfo info2 = instance.m_segments.m_buffer[(int)item.m_position.m_segment].Info;
     int num = info.m_lanes.Length;
     float num2;
     byte offset;
     if (segmentID == item.m_position.m_segment)
     {
         Vector3 b = instance.m_lanes.m_buffer[(int)((UIntPtr)item.m_laneID)].CalculatePosition((float)connectOffset * 0.003921569f);
         Vector3 a = instance.m_lanes.m_buffer[(int)((UIntPtr)lane)].CalculatePosition((float)connectOffset * 0.003921569f);
         num2 = Vector3.Distance(a, b);
         offset = connectOffset;
     }
     else
     {
         NetInfo.Direction direction = (targetNode != segment.m_startNode) ? NetInfo.Direction.Forward : NetInfo.Direction.Backward;
         Vector3 b2 = instance.m_lanes.m_buffer[(int)((UIntPtr)item.m_laneID)].CalculatePosition((float)connectOffset * 0.003921569f);
         Vector3 a2;
         if ((byte)(direction & NetInfo.Direction.Forward) != 0)
         {
             a2 = instance.m_lanes.m_buffer[(int)((UIntPtr)lane)].m_bezier.d;
         }
         else
         {
             a2 = instance.m_lanes.m_buffer[(int)((UIntPtr)lane)].m_bezier.a;
         }
         num2 = Vector3.Distance(a2, b2);
         offset = (byte)(((direction & NetInfo.Direction.Forward) == 0) ? 0 : 255);
     }
     float num3 = 1f;
     float num4 = 1f;
     NetInfo.LaneType laneType = NetInfo.LaneType.None;
     if ((int)item.m_position.m_lane < info2.m_lanes.Length)
     {
         NetInfo.Lane lane2 = info2.m_lanes[(int)item.m_position.m_lane];
         num3 = lane2.m_speedLimit;
         laneType = lane2.m_laneType;
         if ((byte)(laneType & (NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle)) != 0)
         {
             laneType = (NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle);
         }
         num4 = this.CalculateLaneSpeed(connectOffset, item.m_position.m_offset, ref instance.m_segments.m_buffer[(int)item.m_position.m_segment], lane2);
     }
     float averageLength = instance.m_segments.m_buffer[(int)item.m_position.m_segment].m_averageLength;
     float num5 = (float)Mathf.Abs((int)(connectOffset - item.m_position.m_offset)) * 0.003921569f * averageLength;
     float num6 = item.m_methodDistance + num5;
     float num7 = item.m_comparisonValue + num5 / (num4 * this.m_maxLength);
     if (laneIndex < num)
     {
         NetInfo.Lane lane3 = info.m_lanes[laneIndex];
         BufferItem item2;
         item2.m_position.m_segment = segmentID;
         item2.m_position.m_lane = (byte)laneIndex;
         item2.m_position.m_offset = offset;
         if ((byte)(lane3.m_laneType & laneType) == 0)
         {
             item2.m_methodDistance = 0f;
         }
         else
         {
             if (item.m_methodDistance == 0f)
             {
                 num7 += 100f / (0.25f * this.m_maxLength);
             }
             item2.m_methodDistance = num6 + num2;
         }
         if (lane3.m_laneType != NetInfo.LaneType.Pedestrian || item2.m_methodDistance < 1000f)
         {
             item2.m_comparisonValue = num7 + num2 / ((num3 + lane3.m_speedLimit) * 0.25f * this.m_maxLength);
             if ((segment.m_flags & NetSegment.Flags.Invert) != NetSegment.Flags.None)
             {
                 item2.m_direction = NetInfo.InvertDirection(lane3.m_finalDirection);
             }
             else
             {
                 item2.m_direction = lane3.m_finalDirection;
             }
             if (lane == this.m_startLaneA)
             {
                 if (((byte)(item2.m_direction & NetInfo.Direction.Forward) == 0 || item2.m_position.m_offset < this.m_startOffsetA) && ((byte)(item2.m_direction & NetInfo.Direction.Backward) == 0 || item2.m_position.m_offset > this.m_startOffsetA))
                 {
                     return;
                 }
                 float num8 = this.CalculateLaneSpeed(this.m_startOffsetA, item2.m_position.m_offset, ref segment, lane3);
                 float num9 = (float)Mathf.Abs((int)(item2.m_position.m_offset - this.m_startOffsetA)) * 0.003921569f;
                 item2.m_comparisonValue += num9 * segment.m_averageLength / (num8 * this.m_maxLength);
             }
             if (lane == this.m_startLaneB)
             {
                 if (((byte)(item2.m_direction & NetInfo.Direction.Forward) == 0 || item2.m_position.m_offset < this.m_startOffsetB) && ((byte)(item2.m_direction & NetInfo.Direction.Backward) == 0 || item2.m_position.m_offset > this.m_startOffsetB))
                 {
                     return;
                 }
                 float num10 = this.CalculateLaneSpeed(this.m_startOffsetB, item2.m_position.m_offset, ref segment, lane3);
                 float num11 = (float)Mathf.Abs((int)(item2.m_position.m_offset - this.m_startOffsetB)) * 0.003921569f;
                 item2.m_comparisonValue += num11 * segment.m_averageLength / (num10 * this.m_maxLength);
             }
             item2.m_laneID = lane;
             item2.m_lanesUsed = (item.m_lanesUsed | lane3.m_laneType);
             this.AddBufferItem(item2, item.m_position);
         }
     }
 }
        private void ProcessItem1(BufferItem item, ushort nodeId, ref NetNode node, byte connectOffset, bool isMiddle, ref PathUnit data)
        {
            var instance = Singleton<NetManager>.instance;
            var flag = false;
            var num = 0;
            var info = instance.m_segments.m_buffer[item.Position.m_segment].Info;
            if (item.Position.m_lane < info.m_lanes.Length)
            {
                var lane = info.m_lanes[item.Position.m_lane];
                flag = (lane.m_laneType == NetInfo.LaneType.Pedestrian);
                if ((byte)(lane.m_finalDirection & NetInfo.Direction.Forward) != 0)
                {
                    num = lane.m_similarLaneIndex;
                }
                else
                {
                    num = lane.m_similarLaneCount - lane.m_similarLaneIndex - 1;
                }
            }
            if (isMiddle)
            {
                for (var j = 0; j < 8; j++)
                {
                    var segmentId = node.GetSegment(j);
                    if (segmentId != 0)
                    {
                        ProcessItem4(item, nodeId, segmentId, ref instance.m_segments.m_buffer[segmentId],
                        ref num, connectOffset, !flag, flag);
                    }
                }
            }
            else if (flag)
            {
                ushort segment2 = item.Position.m_segment;
                int lane2 = item.Position.m_lane;
                if (node.Info.m_class.m_service != ItemClass.Service.Beautification)
                {
                    bool flag2 = (node.m_flags & (NetNode.Flags.End | NetNode.Flags.Bend | NetNode.Flags.Junction)) != NetNode.Flags.None;
                    int laneIndex;
                    int laneIndex2;
                    uint num2;
                    uint num3;
                    instance.m_segments.m_buffer[segment2].GetLeftAndRightLanes(nodeId, NetInfo.LaneType.Pedestrian, VehicleInfo.VehicleType.None, lane2, out laneIndex, out laneIndex2, out num2, out num3);
                    ushort num4 = segment2;
                    ushort num5 = segment2;
                    if (num2 == 0u || num3 == 0u)
                    {
                        ushort leftSegment;
                        ushort rightSegment;
                        instance.m_segments.m_buffer[segment2].GetLeftAndRightSegments(nodeId, out leftSegment, out rightSegment);
                        int num6 = 0;
                        while (leftSegment != 0 && leftSegment != segment2 && num2 == 0u)
                        {
                            int num7;
                            int num8;
                            uint num9;
                            uint num10;
                            instance.m_segments.m_buffer[leftSegment].GetLeftAndRightLanes(nodeId, NetInfo.LaneType.Pedestrian, VehicleInfo.VehicleType.None, -1, out num7, out num8, out num9, out num10);
                            if (num10 != 0u)
                            {
                                num4 = leftSegment;
                                laneIndex = num8;
                                num2 = num10;
                            }
                            else
                            {
                                leftSegment = instance.m_segments.m_buffer[leftSegment].GetLeftSegment(nodeId);
                            }
                            if (++num6 == 8)
                            {
                                break;
                            }
                        }
                        num6 = 0;
                        while (rightSegment != 0 && rightSegment != segment2 && num3 == 0u)
                        {
                            int num11;
                            int num12;
                            uint num13;
                            uint num14;
                            instance.m_segments.m_buffer[rightSegment].GetLeftAndRightLanes(nodeId, NetInfo.LaneType.Pedestrian, VehicleInfo.VehicleType.None, -1, out num11, out num12, out num13, out num14);
                            if (num13 != 0u)
                            {
                                num5 = rightSegment;
                                laneIndex2 = num11;
                                num3 = num13;
                            }
                            else
                            {
                                rightSegment = instance.m_segments.m_buffer[rightSegment].GetRightSegment(nodeId);
                            }
                            if (++num6 == 8)
                            {
                                break;
                            }
                        }
                    }
                    if (num2 != 0u && (num4 != segment2 || flag2))
                    {
                        ProcessItem5(item, nodeId, num4, ref instance.m_segments.m_buffer[num4], connectOffset, laneIndex, num2);
                    }
                    if (num3 != 0u && num3 != num2 && (num5 != segment2 || flag2))
                    {
                        ProcessItem5(item, nodeId, num5, ref instance.m_segments.m_buffer[num5], connectOffset, laneIndex2, num3);
                    }
                }
                else
                {
                    for (int j = 0; j < 8; j++)
                    {
                        ushort segment3 = node.GetSegment(j);
                        if (segment3 != 0 && segment3 != segment2)
                        {
                            ProcessItem4(item, nodeId, segment3, ref instance.m_segments.m_buffer[segment3], ref num, connectOffset, false, true);
                        }
                    }
                }
                NetInfo.LaneType laneType = _laneTypes & ~NetInfo.LaneType.Pedestrian;
                laneType &= ~(item.LanesUsed & NetInfo.LaneType.Vehicle);
                int num15;
                uint lane3;
                if (laneType != NetInfo.LaneType.None && instance.m_segments.m_buffer[segment2].GetClosestLane(lane2, laneType, _vehicleTypes, out num15, out lane3))
                {
                    NetInfo.Lane lane4 = info.m_lanes[num15];
                    byte connectOffset2;
                    if ((instance.m_segments.m_buffer[segment2].m_flags & NetSegment.Flags.Invert) != NetSegment.Flags.None == ((byte)(lane4.m_finalDirection & NetInfo.Direction.Backward) != 0))
                    {
                        connectOffset2 = 1;
                    }
                    else
                    {
                        connectOffset2 = 254;
                    }
                    ProcessItem5(item, nodeId, segment2, ref instance.m_segments.m_buffer[segment2], connectOffset2, num15, lane3);
                }
            }
            else
            {
                bool flag3 = (node.m_flags & (NetNode.Flags.End | NetNode.Flags.OneWayOut)) != NetNode.Flags.None;
                bool flag4 = (byte)(_laneTypes & NetInfo.LaneType.Pedestrian) != 0;
                byte connectOffset3 = 0;
                if (flag4)
                {
                    if (_vehicleLane != 0u)
                    {
                        if (_vehicleLane != item.LaneId)
                        {
                            flag4 = false;
                        }
                        else
                        {
                            connectOffset3 = _vehicleOffset;
                        }
                    }
                    else if (_stablePath)
                    {
                        connectOffset3 = 128;
                    }
                    else
                    {
                        connectOffset3 = (byte)_pathRandomizer.UInt32(1u, 254u);
                    }
                }

                ushort num16 = instance.m_segments.m_buffer[item.Position.m_segment].GetRightSegment(nodeId);
                for (int k = 0; k < 8; k++)
                {
                    if (num16 == 0 || num16 == item.Position.m_segment)
                    {
                        break;
                    }

                    if (TrafficPriority.IsPrioritySegment(nodeId, num16) && data.m_position00.m_segment != num16)
                    {
                        var segment = instance.m_segments.m_buffer[num16];

                        var info2 = segment.Info;

                        uint segmentLanes = segment.m_lanes;
                        int infoLanes = 0;

                        var lanes = 0;

                        int[] laneNums = new int[16];
                        uint[] laneIds = new uint[16];

                        NetInfo.Direction dir = NetInfo.Direction.Forward;
                        if (segment.m_startNode == nodeId)
                            dir = NetInfo.Direction.Backward;
                        var dir2 = ((segment.m_flags & NetSegment.Flags.Invert) == NetSegment.Flags.None) ? dir : NetInfo.InvertDirection(dir);
                        var dir3 = TrafficPriority.LeftHandDrive ? NetInfo.InvertDirection(dir2) : dir2;

                        var lanes1 = info2.m_lanes;

                        if (TrafficPriority.LeftHandDrive)
                        {
                            lanes1 = lanes1.Reverse().ToArray();
                        }

                        var laneArrows = 0;

                        while (infoLanes < lanes1.Length && segmentLanes != 0u)
                        {
                            if (((NetLane.Flags)instance.m_lanes.m_buffer[segmentLanes].m_flags & NetLane.Flags.Left) ==
                                NetLane.Flags.Left || ((NetLane.Flags)instance.m_lanes.m_buffer[segmentLanes].m_flags & NetLane.Flags.Right) ==
                                        NetLane.Flags.Right || ((NetLane.Flags)instance.m_lanes.m_buffer[segmentLanes].m_flags & NetLane.Flags.Forward) ==
                                        NetLane.Flags.Forward)
                            {
                                laneArrows++;
                            }

                            if (lanes1[infoLanes].m_laneType == NetInfo.LaneType.Vehicle && lanes1[infoLanes].m_direction == dir3)
                            {
                                if (TrafficPriority.IsLeftSegment(num16, item.Position.m_segment, nodeId))
                                {
                                    if (((NetLane.Flags)instance.m_lanes.m_buffer[segmentLanes].m_flags & NetLane.Flags.Left) ==
                                        NetLane.Flags.Left)
                                    {
                                        laneNums[lanes] = infoLanes;
                                        laneIds[lanes] = segmentLanes;
                                        lanes++;
                                    }
                                }
                                else if (TrafficPriority.IsRightSegment(num16, item.Position.m_segment, nodeId))
                                {
                                    if (((NetLane.Flags)instance.m_lanes.m_buffer[segmentLanes].m_flags & NetLane.Flags.Right) ==
                                        NetLane.Flags.Right)
                                    {
                                        laneNums[lanes] = infoLanes;
                                        laneIds[lanes] = segmentLanes;
                                        lanes++;
                                    }
                                }
                                else
                                {
                                    if (((NetLane.Flags)instance.m_lanes.m_buffer[segmentLanes].m_flags & NetLane.Flags.Forward) ==
                                        NetLane.Flags.Forward)
                                    {
                                        laneNums[lanes] = infoLanes;
                                        laneIds[lanes] = segmentLanes;
                                        lanes++;
                                    }
                                }
                            }

                            segmentLanes = instance.m_lanes.m_buffer[(int)((UIntPtr)segmentLanes)].m_nextLane;
                            infoLanes++;
                        }

                        if (laneArrows > 0)
                        {
                            var newLaneNum = 0;
                            var newLaneId = 0u;
                            var newLane = -1;

                            if (lanes > 0)
                            {
                                if (lanes == 1)
                                {
                                    newLaneNum = laneNums[0];
                                    newLaneId = laneIds[0];
                                }
                                else
                                {
                                    var laneFound = false;

                                    if (info2.m_lanes.Length == info.m_lanes.Length)
                                    {

                                        for (var i = 0; i < laneNums.Length; i++)
                                        {
                                            if (laneNums[i] == item.Position.m_lane)
                                            {
                                                newLaneNum = laneNums[i];
                                                newLaneId = laneIds[i];
                                                laneFound = true;
                                                break;
                                            }
                                        }
                                    }

                                    if (!laneFound)
                                    {
                                        var lanePos = Mathf.Abs(info.m_lanes[item.Position.m_lane].m_position);
                                        var closest = 100f;
                                        for (var i = 0; i < lanes; i++)
                                        {
                                            var newLanePos = Mathf.Abs(info2.m_lanes[laneNums[i]].m_position);

                                            if (Math.Abs(newLanePos - lanePos) < closest)
                                            {
                                                closest = Mathf.Abs(newLanePos - lanePos);
                                                newLane = i;
                                            }
                                        }

                                        if (newLane == -1)
                                        {
                                            newLaneNum = laneNums[0];
                                            newLaneId = laneIds[0];
                                        }
                                        else
                                        {
                                            newLaneNum = laneNums[newLane];
                                            newLaneId = laneIds[newLane];
                                        }
                                    }
                                }

                                ProcessItem2(item, nodeId, num16, ref instance.m_segments.m_buffer[num16],
                                    ref num,
                                    connectOffset, true, false, newLaneId, newLaneNum);
                            }
                        }
                        else
                        {
                            if (ProcessItem4(item, nodeId, num16, ref instance.m_segments.m_buffer[num16], ref num,
                                connectOffset, true, false))
                            {
                                flag3 = true;
                            }
                        }
                    }
                    //else if (TrafficRoadRestrictions.isSegment(num16))
                    //{
                    //    var restSegment = TrafficRoadRestrictions.getSegment(num16);

                    //    var preferedLaneAllows = 100;
                    //    uint preferedLaneId = 0;
                    //    int preferedLaneNum = 0;

                    //    NetInfo.Lane lane = info.m_lanes[(int)item.Position.m_lane];

                    //    for (var i = 0; i < restSegment.lanes.Count; i++)
                    //    {
                    //        if ((byte) (lane.m_finalDirection & NetInfo.Direction.Forward) != 0)
                    //        {
                    //            if ((byte) (restSegment.lanes[i].direction & NetInfo.Direction.Forward) == 0)
                    //            {
                    //                continue;
                    //            }
                    //        }
                    //        else
                    //        {
                    //            if ((byte) (restSegment.lanes[i].direction & NetInfo.Direction.Backward) == 0)
                    //            {
                    //                continue;
                    //            }
                    //        }

                    //        if (this._vehicleType == TrafficRoadRestrictions.VehicleTypes.Car)
                    //        {
                    //            if (restSegment.lanes[i].enableCars)
                    //            {
                    //                if (restSegment.lanes[i].laneNum == num)
                    //                {
                    //                    preferedLaneId = restSegment.lanes[i].laneID;
                    //                    preferedLaneNum = restSegment.lanes[i].laneNum;
                    //                    break;
                    //                }
                    //                else if (restSegment.lanes[i].enabledTypes < preferedLaneAllows)
                    //                {
                    //                    preferedLaneId = restSegment.lanes[i].laneID;
                    //                    preferedLaneNum = restSegment.lanes[i].laneNum;
                    //                    preferedLaneAllows = restSegment.lanes[i].enabledTypes;
                    //                }
                    //            }
                    //        }
                    //        else if (this._vehicleType == TrafficRoadRestrictions.VehicleTypes.Service)
                    //        {
                    //            if (restSegment.lanes[i].enableService)
                    //            {
                    //                if (restSegment.lanes[i].laneNum == num)
                    //                {
                    //                    preferedLaneId = restSegment.lanes[i].laneID;
                    //                    preferedLaneNum = restSegment.lanes[i].laneNum;
                    //                    break;
                    //                }
                    //                else if (restSegment.lanes[i].enabledTypes < preferedLaneAllows)
                    //                {
                    //                    preferedLaneId = restSegment.lanes[i].laneID;
                    //                    preferedLaneNum = restSegment.lanes[i].laneNum;
                    //                    preferedLaneAllows = restSegment.lanes[i].enabledTypes;
                    //                }
                    //            }
                    //        }
                    //        else if (this._vehicleType == TrafficRoadRestrictions.VehicleTypes.Cargo)
                    //        {
                    //            if (restSegment.lanes[i].enableCargo)
                    //            {
                    //                if (restSegment.lanes[i].laneNum == num)
                    //                {
                    //                    preferedLaneId = restSegment.lanes[i].laneID;
                    //                    preferedLaneNum = restSegment.lanes[i].laneNum;
                    //                    break;
                    //                }
                    //                else if (restSegment.lanes[i].enabledTypes < preferedLaneAllows)
                    //                {
                    //                    preferedLaneId = restSegment.lanes[i].laneID;
                    //                    preferedLaneNum = restSegment.lanes[i].laneNum;
                    //                    preferedLaneAllows = restSegment.lanes[i].enabledTypes;
                    //                }
                    //            }
                    //        }
                    //        else if (this._vehicleType == TrafficRoadRestrictions.VehicleTypes.Transport)
                    //        {
                    //            if (restSegment.lanes[i].enableTransport)
                    //            {
                    //                if (restSegment.lanes[i].laneNum == num)
                    //                {
                    //                    preferedLaneId = restSegment.lanes[i].laneID;
                    //                    preferedLaneNum = restSegment.lanes[i].laneNum;
                    //                    break;
                    //                }
                    //                else if (restSegment.lanes[i].enabledTypes < preferedLaneAllows)
                    //                {
                    //                    preferedLaneId = restSegment.lanes[i].laneID;
                    //                    preferedLaneNum = restSegment.lanes[i].laneNum;
                    //                    preferedLaneAllows = restSegment.lanes[i].enabledTypes;
                    //                }
                    //            }
                    //        }
                    //    }

                    //    if (preferedLaneId != 0)
                    //    {
                    //        this.ProcessItem2(item, nodeID, num16, ref instance.m_segments._buffer[(int)num16],
                    //            ref num,
                    //            connectOffset, true, false, preferedLaneId, preferedLaneNum);
                    //    }
                    //}
                    else
                    {
                        if (ProcessItem4(item, nodeId, num16, ref instance.m_segments.m_buffer[num16], ref num,
                            connectOffset, true, false))
                        {
                            flag3 = true;
                        }
                    }

                    num16 = instance.m_segments.m_buffer[num16].GetRightSegment(nodeId);
                }
                if (flag3)
                {
                    num16 = item.Position.m_segment;
                    ProcessItem4(item, nodeId, num16, ref instance.m_segments.m_buffer[num16], ref num, connectOffset, true, false);
                }
                int laneIndex3;
                uint lane5;
                if (flag4 && instance.m_segments.m_buffer[num16].GetClosestLane(item.Position.m_lane, NetInfo.LaneType.Pedestrian, _vehicleTypes, out laneIndex3, out lane5))
                {
                    ProcessItem5(item, nodeId, num16, ref instance.m_segments.m_buffer[num16], connectOffset3, laneIndex3, lane5);
                }
            }
            if (node.m_lane != 0u)
            {
                var targetDisabled = (node.m_flags & NetNode.Flags.Disabled) != NetNode.Flags.None;
                var segment4 = instance.m_lanes.m_buffer[(int)((UIntPtr)node.m_lane)].m_segment;
                if (segment4 != 0 && segment4 != item.Position.m_segment)
                {
                    ProcessItem3(item, targetDisabled, segment4, ref instance.m_segments.m_buffer[segment4], node.m_lane, node.m_laneOffset, connectOffset);
                }
            }
        }
 protected virtual void ProcessItem(BufferItem item, ushort nodeID, ref NetNode node, byte connectOffset, bool isMiddle)
 {
     NetManager instance = Singleton<NetManager>.instance;
     bool flag = false;
     bool flag2 = false;
     bool flag3 = false;
     int num = 0;
     NetInfo info = instance.m_segments.m_buffer[(int)item.m_position.m_segment].Info;
     if ((int)item.m_position.m_lane < info.m_lanes.Length)
     {
         NetInfo.Lane lane = info.m_lanes[(int)item.m_position.m_lane];
         flag = (lane.m_laneType == NetInfo.LaneType.Pedestrian);
         flag2 = (lane.m_laneType == NetInfo.LaneType.Vehicle && (lane.m_vehicleType & this.m_vehicleTypes) == VehicleInfo.VehicleType.Bicycle);
         flag3 = lane.m_centerPlatform;
         if ((byte)(lane.m_finalDirection & NetInfo.Direction.Forward) != 0)
         {
             num = lane.m_similarLaneIndex;
         }
         else
         {
             num = lane.m_similarLaneCount - lane.m_similarLaneIndex - 1;
         }
     }
     if (isMiddle)
     {
         for (int i = 0; i < 8; i++)
         {
             ushort segment = node.GetSegment(i);
             if (segment != 0)
             {
                 this.ProcessItem(item, nodeID, segment, ref instance.m_segments.m_buffer[(int)segment], ref num, connectOffset, !flag, flag);
             }
         }
     }
     else if (flag)
     {
         ushort segment2 = item.m_position.m_segment;
         int lane2 = (int)item.m_position.m_lane;
         if (node.Info.m_class.m_service != ItemClass.Service.Beautification)
         {
             bool flag4 = (node.m_flags & (NetNode.Flags.End | NetNode.Flags.Bend | NetNode.Flags.Junction)) != NetNode.Flags.None;
             bool flag5 = flag3 && (node.m_flags & (NetNode.Flags.End | NetNode.Flags.Junction)) == NetNode.Flags.None;
             ushort num2 = segment2;
             ushort num3 = segment2;
             int laneIndex;
             int laneIndex2;
             uint num4;
             uint num5;
             instance.m_segments.m_buffer[(int)segment2].GetLeftAndRightLanes(nodeID, NetInfo.LaneType.Pedestrian, VehicleInfo.VehicleType.None, lane2, flag5, out laneIndex, out laneIndex2, out num4, out num5);
             if (num4 == 0u || num5 == 0u)
             {
                 ushort leftSegment;
                 ushort rightSegment;
                 instance.m_segments.m_buffer[(int)segment2].GetLeftAndRightSegments(nodeID, out leftSegment, out rightSegment);
                 int num6 = 0;
                 while (leftSegment != 0 && leftSegment != segment2 && num4 == 0u)
                 {
                     int num7;
                     int num8;
                     uint num9;
                     uint num10;
                     instance.m_segments.m_buffer[(int)leftSegment].GetLeftAndRightLanes(nodeID, NetInfo.LaneType.Pedestrian, VehicleInfo.VehicleType.None, -1, flag5, out num7, out num8, out num9, out num10);
                     if (num10 != 0u)
                     {
                         num2 = leftSegment;
                         laneIndex = num8;
                         num4 = num10;
                     }
                     else
                     {
                         leftSegment = instance.m_segments.m_buffer[(int)leftSegment].GetLeftSegment(nodeID);
                     }
                     if (++num6 == 8)
                     {
                         break;
                     }
                 }
                 num6 = 0;
                 while (rightSegment != 0 && rightSegment != segment2 && num5 == 0u)
                 {
                     int num11;
                     int num12;
                     uint num13;
                     uint num14;
                     instance.m_segments.m_buffer[(int)rightSegment].GetLeftAndRightLanes(nodeID, NetInfo.LaneType.Pedestrian, VehicleInfo.VehicleType.None, -1, flag5, out num11, out num12, out num13, out num14);
                     if (num13 != 0u)
                     {
                         num3 = rightSegment;
                         laneIndex2 = num11;
                         num5 = num13;
                     }
                     else
                     {
                         rightSegment = instance.m_segments.m_buffer[(int)rightSegment].GetRightSegment(nodeID);
                     }
                     if (++num6 == 8)
                     {
                         break;
                     }
                 }
             }
             if (num4 != 0u && (num2 != segment2 || flag4 || flag5))
             {
                 this.ProcessItem(item, nodeID, num2, ref instance.m_segments.m_buffer[(int)num2], connectOffset, laneIndex, num4);
             }
             if (num5 != 0u && num5 != num4 && (num3 != segment2 || flag4 || flag5))
             {
                 this.ProcessItem(item, nodeID, num3, ref instance.m_segments.m_buffer[(int)num3], connectOffset, laneIndex2, num5);
             }
             int laneIndex3;
             uint lane3;
             if ((this.m_vehicleTypes & VehicleInfo.VehicleType.Bicycle) != VehicleInfo.VehicleType.None && instance.m_segments.m_buffer[(int)segment2].GetClosestLane((int)item.m_position.m_lane, NetInfo.LaneType.Vehicle, VehicleInfo.VehicleType.Bicycle, out laneIndex3, out lane3))
             {
                 this.ProcessItem(item, nodeID, segment2, ref instance.m_segments.m_buffer[(int)segment2], connectOffset, laneIndex3, lane3);
             }
         }
         else
         {
             for (int j = 0; j < 8; j++)
             {
                 ushort segment3 = node.GetSegment(j);
                 if (segment3 != 0 && segment3 != segment2)
                 {
                     this.ProcessItem(item, nodeID, segment3, ref instance.m_segments.m_buffer[(int)segment3], ref num, connectOffset, false, true);
                 }
             }
         }
         NetInfo.LaneType laneType = this.m_laneTypes & ~NetInfo.LaneType.Pedestrian;
         VehicleInfo.VehicleType vehicleType = this.m_vehicleTypes & ~VehicleInfo.VehicleType.Bicycle;
         if ((byte)(item.m_lanesUsed & (NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle)) != 0)
         {
             laneType &= ~(NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle);
         }
         int num15;
         uint lane4;
         if (laneType != NetInfo.LaneType.None && vehicleType != VehicleInfo.VehicleType.None && instance.m_segments.m_buffer[(int)segment2].GetClosestLane(lane2, laneType, vehicleType, out num15, out lane4))
         {
             NetInfo.Lane lane5 = info.m_lanes[num15];
             byte connectOffset2;
             if ((instance.m_segments.m_buffer[(int)segment2].m_flags & NetSegment.Flags.Invert) != NetSegment.Flags.None == ((byte)(lane5.m_finalDirection & NetInfo.Direction.Backward) != 0))
             {
                 connectOffset2 = 1;
             }
             else
             {
                 connectOffset2 = 254;
             }
             this.ProcessItem(item, nodeID, segment2, ref instance.m_segments.m_buffer[(int)segment2], connectOffset2, num15, lane4);
         }
     }
     else
     {
         bool flag6 = (node.m_flags & (NetNode.Flags.End | NetNode.Flags.OneWayOut)) != NetNode.Flags.None;
         bool flag7 = (byte)(this.m_laneTypes & NetInfo.LaneType.Pedestrian) != 0;
         bool enablePedestrian = false;
         byte connectOffset3 = 0;
         if (flag7)
         {
             if (flag2)
             {
                 connectOffset3 = connectOffset;
                 enablePedestrian = (node.Info.m_class.m_service == ItemClass.Service.Beautification);
             }
             else if (this.m_vehicleLane != 0u)
             {
                 if (this.m_vehicleLane != item.m_laneID)
                 {
                     flag7 = false;
                 }
                 else
                 {
                     connectOffset3 = this.m_vehicleOffset;
                 }
             }
             else if (this.m_stablePath)
             {
                 connectOffset3 = 128;
             }
             else
             {
                 connectOffset3 = (byte)this.m_pathRandomizer.UInt32(1u, 254u);
             }
         }
         ushort num16 = instance.m_segments.m_buffer[(int)item.m_position.m_segment].GetRightSegment(nodeID);
         for (int k = 0; k < 8; k++)
         {
             if (num16 == 0 || num16 == item.m_position.m_segment)
             {
                 break;
             }
             if (this.ProcessItem(item, nodeID, num16, ref instance.m_segments.m_buffer[(int)num16], ref num, connectOffset, true, enablePedestrian))
             {
                 flag6 = true;
             }
             num16 = instance.m_segments.m_buffer[(int)num16].GetRightSegment(nodeID);
         }
         if (flag6 && (this.m_vehicleTypes & VehicleInfo.VehicleType.Tram) == VehicleInfo.VehicleType.None)
         {
             num16 = item.m_position.m_segment;
             this.ProcessItem(item, nodeID, num16, ref instance.m_segments.m_buffer[(int)num16], ref num, connectOffset, true, false);
         }
         if (flag7)
         {
             num16 = item.m_position.m_segment;
             int laneIndex4;
             uint lane6;
             if (instance.m_segments.m_buffer[(int)num16].GetClosestLane((int)item.m_position.m_lane, NetInfo.LaneType.Pedestrian, this.m_vehicleTypes, out laneIndex4, out lane6))
             {
                 this.ProcessItem(item, nodeID, num16, ref instance.m_segments.m_buffer[(int)num16], connectOffset3, laneIndex4, lane6);
             }
         }
     }
     if (node.m_lane != 0u)
     {
         bool targetDisabled = (node.m_flags & NetNode.Flags.Disabled) != NetNode.Flags.None;
         ushort segment4 = instance.m_lanes.m_buffer[(int)((UIntPtr)node.m_lane)].m_segment;
         if (segment4 != 0 && segment4 != item.m_position.m_segment)
         {
             this.ProcessItem(item, nodeID, targetDisabled, segment4, ref instance.m_segments.m_buffer[(int)segment4], node.m_lane, node.m_laneOffset, connectOffset);
         }
     }
 }
Exemplo n.º 32
0
 public override bool FilterBuffer(BufferItem item)
 {
     return(item is LogBufferItem);
 }
 protected virtual bool ProcessItem(BufferItem item, ushort targetNode, ushort segmentID, ref NetSegment segment, ref int currentTargetIndex, byte connectOffset, bool enableVehicle, bool enablePedestrian)
 {
     bool result = false;
     if ((segment.m_flags & (NetSegment.Flags.PathFailed | NetSegment.Flags.Flooded)) != NetSegment.Flags.None)
     {
         return result;
     }
     NetManager instance = Singleton<NetManager>.instance;
     NetInfo info = segment.Info;
     NetInfo info2 = instance.m_segments.m_buffer[(int)item.m_position.m_segment].Info;
     int num = info.m_lanes.Length;
     uint num2 = segment.m_lanes;
     NetInfo.Direction direction = (targetNode != segment.m_startNode) ? NetInfo.Direction.Forward : NetInfo.Direction.Backward;
     NetInfo.Direction direction2 = ((segment.m_flags & NetSegment.Flags.Invert) == NetSegment.Flags.None) ? direction : NetInfo.InvertDirection(direction);
     float num3 = 0.01f - Mathf.Min(info.m_maxTurnAngleCos, info2.m_maxTurnAngleCos);
     if (num3 < 1f)
     {
         Vector3 vector;
         if (targetNode == instance.m_segments.m_buffer[(int)item.m_position.m_segment].m_startNode)
         {
             vector = instance.m_segments.m_buffer[(int)item.m_position.m_segment].m_startDirection;
         }
         else
         {
             vector = instance.m_segments.m_buffer[(int)item.m_position.m_segment].m_endDirection;
         }
         Vector3 vector2;
         if ((byte)(direction & NetInfo.Direction.Forward) != 0)
         {
             vector2 = segment.m_endDirection;
         }
         else
         {
             vector2 = segment.m_startDirection;
         }
         float num4 = vector.x * vector2.x + vector.z * vector2.z;
         if (num4 >= num3)
         {
             return result;
         }
     }
     float num5 = 1f;
     float num6 = 1f;
     NetInfo.LaneType laneType = NetInfo.LaneType.None;
     VehicleInfo.VehicleType vehicleType = VehicleInfo.VehicleType.None;
     if ((int)item.m_position.m_lane < info2.m_lanes.Length)
     {
         NetInfo.Lane lane = info2.m_lanes[(int)item.m_position.m_lane];
         laneType = lane.m_laneType;
         vehicleType = lane.m_vehicleType;
         num5 = lane.m_speedLimit;
         num6 = this.CalculateLaneSpeed(connectOffset, item.m_position.m_offset, ref instance.m_segments.m_buffer[(int)item.m_position.m_segment], lane);
     }
     float num7 = instance.m_segments.m_buffer[(int)item.m_position.m_segment].m_averageLength;
     if (!this.m_stablePath)
     {
         Randomizer randomizer = new Randomizer(this.m_pathFindIndex << 16 | (uint)item.m_position.m_segment);
         num7 *= (float)(randomizer.Int32(900, 1000 + (int)(instance.m_segments.m_buffer[(int)item.m_position.m_segment].m_trafficDensity * 10)) + this.m_pathRandomizer.Int32(20u)) * 0.001f;
     }
     if (this.m_isHeavyVehicle && (instance.m_segments.m_buffer[(int)item.m_position.m_segment].m_flags & NetSegment.Flags.HeavyBan) != NetSegment.Flags.None)
     {
         num7 *= 10f;
     }
     else if (laneType == NetInfo.LaneType.Vehicle && (vehicleType & this.m_vehicleTypes) == VehicleInfo.VehicleType.Car && (instance.m_segments.m_buffer[(int)item.m_position.m_segment].m_flags & NetSegment.Flags.CarBan) != NetSegment.Flags.None)
     {
         num7 *= 5f;
     }
     if (this.m_transportVehicle && laneType == NetInfo.LaneType.TransportVehicle)
     {
         num7 *= 0.95f;
     }
     if ((byte)(laneType & (NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle)) != 0)
     {
         laneType = (NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle);
     }
     float num8 = (float)Mathf.Abs((int)(connectOffset - item.m_position.m_offset)) * 0.003921569f * num7;
     float num9 = item.m_methodDistance + num8;
     float num10 = item.m_comparisonValue + num8 / (num6 * this.m_maxLength);
     Vector3 b = instance.m_lanes.m_buffer[(int)((UIntPtr)item.m_laneID)].CalculatePosition((float)connectOffset * 0.003921569f);
     int num11 = currentTargetIndex;
     bool flag = (instance.m_nodes.m_buffer[(int)targetNode].m_flags & NetNode.Flags.Transition) != NetNode.Flags.None;
     NetInfo.LaneType laneType2 = this.m_laneTypes;
     VehicleInfo.VehicleType vehicleType2 = this.m_vehicleTypes;
     if (!enableVehicle)
     {
         vehicleType2 &= VehicleInfo.VehicleType.Bicycle;
         if (vehicleType2 == VehicleInfo.VehicleType.None)
         {
             laneType2 &= ~(NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle);
         }
     }
     if (!enablePedestrian)
     {
         laneType2 &= ~NetInfo.LaneType.Pedestrian;
     }
     int num12 = 0;
     while (num12 < num && num2 != 0u)
     {
         NetInfo.Lane lane2 = info.m_lanes[num12];
         if ((byte)(lane2.m_finalDirection & direction2) != 0)
         {
             if (lane2.CheckType(laneType2, vehicleType2) && (segmentID != item.m_position.m_segment || num12 != (int)item.m_position.m_lane) && (byte)(lane2.m_finalDirection & direction2) != 0)
             {
                 Vector3 a;
                 if ((byte)(direction & NetInfo.Direction.Forward) != 0)
                 {
                     a = instance.m_lanes.m_buffer[(int)((UIntPtr)num2)].m_bezier.d;
                 }
                 else
                 {
                     a = instance.m_lanes.m_buffer[(int)((UIntPtr)num2)].m_bezier.a;
                 }
                 float num13 = Vector3.Distance(a, b);
                 if (flag)
                 {
                     num13 *= 2f;
                 }
                 float num14 = num13 / ((num5 + lane2.m_speedLimit) * 0.5f * this.m_maxLength);
                 BufferItem item2;
                 item2.m_position.m_segment = segmentID;
                 item2.m_position.m_lane = (byte)num12;
                 item2.m_position.m_offset = (byte)(((direction & NetInfo.Direction.Forward) == 0) ? 0 : 255);
                 if ((byte)(lane2.m_laneType & laneType) == 0)
                 {
                     item2.m_methodDistance = 0f;
                 }
                 else
                 {
                     item2.m_methodDistance = num9 + num13;
                 }
                 if (lane2.m_laneType != NetInfo.LaneType.Pedestrian || item2.m_methodDistance < 1000f)
                 {
                     item2.m_comparisonValue = num10 + num14;
                     item2.m_direction = direction;
                     if (num2 == this.m_startLaneA)
                     {
                         if (((byte)(item2.m_direction & NetInfo.Direction.Forward) == 0 || item2.m_position.m_offset < this.m_startOffsetA) && ((byte)(item2.m_direction & NetInfo.Direction.Backward) == 0 || item2.m_position.m_offset > this.m_startOffsetA))
                         {
                             num2 = instance.m_lanes.m_buffer[(int)((UIntPtr)num2)].m_nextLane;
                             num12++;
                             continue;
                         }
                         float num15 = this.CalculateLaneSpeed(this.m_startOffsetA, item2.m_position.m_offset, ref segment, lane2);
                         float num16 = (float)Mathf.Abs((int)(item2.m_position.m_offset - this.m_startOffsetA)) * 0.003921569f;
                         item2.m_comparisonValue += num16 * segment.m_averageLength / (num15 * this.m_maxLength);
                     }
                     if (num2 == this.m_startLaneB)
                     {
                         if (((byte)(item2.m_direction & NetInfo.Direction.Forward) == 0 || item2.m_position.m_offset < this.m_startOffsetB) && ((byte)(item2.m_direction & NetInfo.Direction.Backward) == 0 || item2.m_position.m_offset > this.m_startOffsetB))
                         {
                             num2 = instance.m_lanes.m_buffer[(int)((UIntPtr)num2)].m_nextLane;
                             num12++;
                             continue;
                         }
                         float num17 = this.CalculateLaneSpeed(this.m_startOffsetB, item2.m_position.m_offset, ref segment, lane2);
                         float num18 = (float)Mathf.Abs((int)(item2.m_position.m_offset - this.m_startOffsetB)) * 0.003921569f;
                         item2.m_comparisonValue += num18 * segment.m_averageLength / (num17 * this.m_maxLength);
                     }
                     if (!this.m_ignoreBlocked && (segment.m_flags & NetSegment.Flags.Blocked) != NetSegment.Flags.None && (byte)(lane2.m_laneType & (NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle)) != 0)
                     {
                         item2.m_comparisonValue += 0.1f;
                         result = true;
                     }
                     item2.m_lanesUsed = (item.m_lanesUsed | lane2.m_laneType);
                     item2.m_laneID = num2;
                     if ((byte)(lane2.m_laneType & laneType) != 0 && (lane2.m_vehicleType & this.m_vehicleTypes) != VehicleInfo.VehicleType.None)
                     {
                         int firstTarget = (int)instance.m_lanes.m_buffer[(int)((UIntPtr)num2)].m_firstTarget;
                         int lastTarget = (int)instance.m_lanes.m_buffer[(int)((UIntPtr)num2)].m_lastTarget;
                         if (currentTargetIndex < firstTarget || currentTargetIndex >= lastTarget)
                         {
                             item2.m_comparisonValue += Mathf.Max(1f, num13 * 3f - 3f) / ((num5 + lane2.m_speedLimit) * 0.5f * this.m_maxLength);
                         }
                         if (!this.m_transportVehicle && lane2.m_laneType == NetInfo.LaneType.TransportVehicle)
                         {
                             item2.m_comparisonValue += 20f / ((num5 + lane2.m_speedLimit) * 0.5f * this.m_maxLength);
                         }
                     }
                     this.AddBufferItem(item2, item.m_position);
                 }
             }
             num2 = instance.m_lanes.m_buffer[(int)((UIntPtr)num2)].m_nextLane;
             num12++;
             continue;
         }
         if ((byte)(lane2.m_laneType & laneType) != 0 && (lane2.m_vehicleType & vehicleType) != VehicleInfo.VehicleType.None)
         {
             num11++;
         }
         num2 = instance.m_lanes.m_buffer[(int)((UIntPtr)num2)].m_nextLane;
         num12++;
     }
     currentTargetIndex = num11;
     return result;
 }
Exemplo n.º 34
0
 public override bool FilterBuffer(BufferItem item)
 {
     return(item is SilverDollarBufferItem);
 }
Exemplo n.º 35
0
            /// <summary>
            /// Fills recording buffers.
            /// </summary>
            private void CreateBuffers()
            {               
                while(m_pBuffers.Count < 10){
                    byte[]   data       = new byte[m_BufferSize];
                    GCHandle dataHandle = GCHandle.Alloc(data,GCHandleType.Pinned);

                    WAVEHDR wavHeader = new WAVEHDR();
                    wavHeader.lpData          = dataHandle.AddrOfPinnedObject();
                    wavHeader.dwBufferLength  = (uint)data.Length;
                    wavHeader.dwBytesRecorded = 0;
                    wavHeader.dwUser          = IntPtr.Zero;
                    wavHeader.dwFlags         = 0;
                    wavHeader.dwLoops         = 0;
                    wavHeader.lpNext          = IntPtr.Zero;
                    wavHeader.reserved        = 0;
                    GCHandle headerHandle = GCHandle.Alloc(wavHeader,GCHandleType.Pinned);
                    int result = 0;        
                    result = waveInPrepareHeader(m_pWavDevHandle,headerHandle.AddrOfPinnedObject(),Marshal.SizeOf(wavHeader));                    
                    if(result != MMSYSERR.NOERROR){
                        throw new Exception("Error preparing wave in buffer, error: " + result + ".");
                    }
                    else{
                        m_pBuffers.Add(new BufferItem(ref headerHandle,ref dataHandle,m_BufferSize));

                        result = waveInAddBuffer(m_pWavDevHandle,headerHandle.AddrOfPinnedObject(),Marshal.SizeOf(wavHeader));
                        if(result != MMSYSERR.NOERROR){
                            throw new Exception("Error adding wave in buffer, error: " + result + ".");
                        }
                    }
                } 
               
                m_pCurrentBuffer = m_pBuffers[0];
            }
		// 3
		private bool ProcessItem(bool debug, BufferItem item, ushort targetNodeId, ushort segmentID, ref NetSegment nextSegment, ref int laneIndexFromLeft, byte connectOffset, bool enableVehicle, bool enablePedestrian, int? forceLaneIndex, uint? forceLaneId, out bool foundForced) {
			//debug = targetNodeId == 6900;
			foundForced = false;
			bool result = false;
			if ((nextSegment.m_flags & (NetSegment.Flags.PathFailed | NetSegment.Flags.Flooded)) != NetSegment.Flags.None) {
				return result;
			}
			NetManager instance = Singleton<NetManager>.instance;
			NetInfo nextSegmentInfo = nextSegment.Info;
			NetInfo prevSegmentInfo = instance.m_segments.m_buffer[(int)item.m_position.m_segment].Info;
			int nextNumLanes = nextSegmentInfo.m_lanes.Length;
			uint curLaneId = (uint)(forceLaneId != null ? forceLaneId : nextSegment.m_lanes); // NON-STOCK CODE
			NetInfo.Direction nextDir = (targetNodeId != nextSegment.m_startNode) ? NetInfo.Direction.Forward : NetInfo.Direction.Backward;
			NetInfo.Direction nextDir2 = ((nextSegment.m_flags & NetSegment.Flags.Invert) == NetSegment.Flags.None) ? nextDir : NetInfo.InvertDirection(nextDir);
			float num3 = 0.01f - Mathf.Min(nextSegmentInfo.m_maxTurnAngleCos, prevSegmentInfo.m_maxTurnAngleCos);
			if (num3 < 1f) {
				Vector3 vector;
				if (targetNodeId == instance.m_segments.m_buffer[(int)item.m_position.m_segment].m_startNode) {
					vector = instance.m_segments.m_buffer[(int)item.m_position.m_segment].m_startDirection;
				} else {
					vector = instance.m_segments.m_buffer[(int)item.m_position.m_segment].m_endDirection;
				}
				Vector3 vector2;
				if ((byte)(nextDir & NetInfo.Direction.Forward) != 0) {
					vector2 = nextSegment.m_endDirection;
				} else {
					vector2 = nextSegment.m_startDirection;
				}
				float num4 = vector.x * vector2.x + vector.z * vector2.z;
				if (num4 >= num3) {
					return result;
				}
			}
			float prevMaxSpeed = 1f;
			float prevLaneSpeed = 1f;
			NetInfo.LaneType laneType = NetInfo.LaneType.None;
			VehicleInfo.VehicleType vehicleType = VehicleInfo.VehicleType.None;
			// NON-STOCK CODE START //
			bool customLaneChanging = !Options.isStockLaneChangerUsed() && !this._transportVehicle;
			bool prevIsHighway = false;
			if (prevSegmentInfo.m_netAI is RoadBaseAI)
				prevIsHighway = ((RoadBaseAI)prevSegmentInfo.m_netAI).m_highwayRules;
			bool prevIsOutgoingOneWay = TrafficLightsManual.SegmentIsOutgoingOneWay(item.m_position.m_segment, targetNodeId);
			float nextDensity = 0f;
			int prevRightSimilarLaneIndex = -1;
			NetInfo.Direction normDirection = TrafficPriority.LeftHandDrive ? NetInfo.Direction.Forward : NetInfo.Direction.Backward; // direction to normalize indices to
			int prevLanes = 1;
			float prevDensity = 0f;
			// NON-STOCK CODE END //
			if ((int)item.m_position.m_lane < prevSegmentInfo.m_lanes.Length) {
				NetInfo.Lane lane = prevSegmentInfo.m_lanes[(int)item.m_position.m_lane];
				laneType = lane.m_laneType;
				vehicleType = lane.m_vehicleType;
				prevMaxSpeed = lane.m_speedLimit;
				prevLaneSpeed = this.CalculateLaneSpeed(connectOffset, item.m_position.m_offset, ref instance.m_segments.m_buffer[(int)item.m_position.m_segment], lane);
				// NON-STOCK CODE START //
				prevLanes = lane.m_similarLaneCount;
				if ((byte)(lane.m_direction & normDirection) != 0) {
					prevRightSimilarLaneIndex = lane.m_similarLaneIndex;
				} else {
					prevRightSimilarLaneIndex = lane.m_similarLaneCount - lane.m_similarLaneIndex - 1;
				}
				prevDensity = CustomRoadAI.laneMeanTrafficDensity[item.m_laneID];
				// NON-STOCK CODE END //
			}
			float cost = instance.m_segments.m_buffer[(int)item.m_position.m_segment].m_averageLength;
			if (!customLaneChanging && !this._stablePath) { // NON-STOCK CODE
				Randomizer randomizer = new Randomizer(this._pathFindIndex << 16 | (uint)item.m_position.m_segment);
				cost *= (float)(randomizer.Int32(900, 1000 + (int)(instance.m_segments.m_buffer[(int)item.m_position.m_segment].m_trafficDensity * 10)) + this._pathRandomizer.Int32(20u)) * 0.001f;
			}
			if (this._isHeavyVehicle && (instance.m_segments.m_buffer[(int)item.m_position.m_segment].m_flags & NetSegment.Flags.HeavyBan) != NetSegment.Flags.None) {
				cost *= customLaneChanging ? 15f : 10f; // NON-STOCK CODE
			} else if (laneType == NetInfo.LaneType.Vehicle && vehicleType == VehicleInfo.VehicleType.Car && (instance.m_segments.m_buffer[(int)item.m_position.m_segment].m_flags & NetSegment.Flags.CarBan) != NetSegment.Flags.None) {
				cost *= customLaneChanging ? 10f : 5f; // NON-STOCK CODE
			}
			if (this._transportVehicle && laneType == NetInfo.LaneType.TransportVehicle) {
				cost *= 0.95f;
			}
			if ((byte)(laneType & (NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle)) != 0) {
				laneType = (NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle);
			}
			float prevOffset = (float)Mathf.Abs((int)(connectOffset - item.m_position.m_offset)) * 0.003921569f * cost;
			float prevMethodDist = item.m_methodDistance + prevOffset;
			float prevComparisonPlusOffsetOverSpeed = item.m_comparisonValue + prevOffset / (prevLaneSpeed * this._maxLength);
			Vector3 prevLanePosition = instance.m_lanes.m_buffer[(int)((UIntPtr)item.m_laneID)].CalculatePosition((float)connectOffset * 0.003921569f);
			int num11 = laneIndexFromLeft;
			bool transitionNode = (instance.m_nodes.m_buffer[(int)targetNodeId].m_flags & NetNode.Flags.Transition) != NetNode.Flags.None;
			NetInfo.LaneType laneType2 = this._laneTypes;
			VehicleInfo.VehicleType vehicleType2 = this._vehicleTypes;
			if (!enableVehicle) {
				vehicleType2 &= VehicleInfo.VehicleType.Bicycle;
				if (vehicleType2 == VehicleInfo.VehicleType.None) {
					laneType2 &= ~(NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle);
				}
			}
			if (!enablePedestrian) {
				laneType2 &= ~NetInfo.LaneType.Pedestrian;
			}
			// NON-STOCK CODE START //
			//NetNode targetNode = instance.m_nodes.m_buffer[targetNodeId];
			//float segmentDensity = (float)(instance.m_segments.m_buffer[(int)item.m_position.m_segment].m_trafficDensity + nextSegment.m_trafficDensity) / 2f;
			bool nextIsJunction = instance.m_nodes.m_buffer[targetNodeId].CountSegments() > 2;
			ushort sourceNodeId = (targetNodeId == instance.m_segments.m_buffer[item.m_position.m_segment].m_startNode) ? instance.m_segments.m_buffer[item.m_position.m_segment].m_endNode : instance.m_segments.m_buffer[item.m_position.m_segment].m_startNode; // no lane changing directly in front of a junction
																																																																   //NetNode sourceNode = instance.m_nodes.m_buffer[sourceNodeId];
			bool prevIsJunction = instance.m_nodes.m_buffer[sourceNodeId].CountSegments() > 2;
			int laneTargetValue = Options.getLaneChangingRandomizationTargetValue();
			if (this._isHeavyVehicle)
				laneTargetValue *= 2;
			bool changeLane =
				!prevIsJunction &&
				!this._stablePath &&
				forceLaneIndex == null &&
				customLaneChanging &&
				_pathRandomizer.Int32(1, laneTargetValue) == 1; // lane randomization
			int laneIndex = (int)(forceLaneIndex != null ? forceLaneIndex : 0);
			bool nextIsHighway = false;
			if (nextSegmentInfo.m_netAI is RoadBaseAI)
				nextIsHighway = ((RoadBaseAI)nextSegmentInfo.m_netAI).m_highwayRules;
			// NON-STOCK CODE END //
			while (laneIndex < nextNumLanes && curLaneId != 0u) {
				// NON-STOCK CODE START //
				if (forceLaneIndex != null && laneIndex != forceLaneIndex)
					break;
				if (customLaneChanging) {
					nextDensity = CustomRoadAI.laneMeanTrafficDensity[curLaneId];
				}
				// NON-STOCK CODE END //

				NetInfo.Lane nextLane = nextSegmentInfo.m_lanes[laneIndex];
				if ((byte)(nextLane.m_finalDirection & nextDir2) != 0) {
					if (nextLane.CheckType(laneType2, vehicleType2) && (segmentID != item.m_position.m_segment || laneIndex != (int)item.m_position.m_lane) && (byte)(nextLane.m_finalDirection & nextDir2) != 0) {
						float distanceOnBezier = 0f;
						Vector3 a;
						// NON-STOCK CODE START //
						if (customLaneChanging && !this._stablePath) {
							a = instance.m_nodes.m_buffer[targetNodeId].m_position;
						} else {
						// NON-STOCK CODE END //
							if ((byte)(nextDir & NetInfo.Direction.Forward) != 0) {
								a = instance.m_lanes.m_buffer[(int)((UIntPtr)curLaneId)].m_bezier.d;
							} else {
								a = instance.m_lanes.m_buffer[(int)((UIntPtr)curLaneId)].m_bezier.a;
							}
						// NON-STOCK CODE START //
						}
						// NON-STOCK CODE END //
						distanceOnBezier = Vector3.Distance(a, prevLanePosition);
						/*if (targetNodeId == 5456) {
							Log.Message("Original distance: " + Vector3.Distance(a1, prevLanePosition) + " New distance: " + Vector3.Distance(a2, prevLanePosition) + " Other: " + Vector3.Distance(a3, prevLanePosition));
						}*/
						
						if (transitionNode || (customLaneChanging && prevIsJunction)) { // NON-STOCK CODE
							distanceOnBezier *= 2f;
						}
						float distanceOverMeanMaxSpeed = distanceOnBezier / ((prevMaxSpeed + nextLane.m_speedLimit) * 0.5f * this._maxLength);
						BufferItem item2;
						// NON-STOCK CODE START //
						bool addCustomCosts = customLaneChanging && curLaneId != this._startLaneA && curLaneId != this._startLaneB && curLaneId != this._endLaneA && curLaneId != this._endLaneB && forceLaneIndex == null && nextLane.m_similarLaneCount > 1;
						if (nextIsJunction)
							item2.m_numSegmentsToJunction = 0;
						else if (prevIsJunction)
							item2.m_numSegmentsToJunction = 1;
						else
							item2.m_numSegmentsToJunction = item.m_numSegmentsToJunction + 1;
						// NON-STOCK CODE END //
						item2.m_position.m_segment = segmentID;
						item2.m_position.m_lane = (byte)laneIndex;
						item2.m_position.m_offset = (byte)(((nextDir & NetInfo.Direction.Forward) == 0) ? 0 : 255);
						if ((byte)(nextLane.m_laneType & laneType) == 0) {
							item2.m_methodDistance = 0f;
						} else {
							item2.m_methodDistance = prevMethodDist + distanceOnBezier;
						}
						if (nextLane.m_laneType != NetInfo.LaneType.Pedestrian || item2.m_methodDistance < 1000f) {
							item2.m_comparisonValue = prevComparisonPlusOffsetOverSpeed + distanceOverMeanMaxSpeed;
							item2.m_direction = nextDir;
							if (curLaneId == this._startLaneA) {
								if (((byte)(item2.m_direction & NetInfo.Direction.Forward) == 0 || item2.m_position.m_offset < this._startOffsetA) && ((byte)(item2.m_direction & NetInfo.Direction.Backward) == 0 || item2.m_position.m_offset > this._startOffsetA)) {
									curLaneId = instance.m_lanes.m_buffer[(int)((UIntPtr)curLaneId)].m_nextLane;
									goto IL_90F;
								}
								float num15 = this.CalculateLaneSpeed(this._startOffsetA, item2.m_position.m_offset, ref nextSegment, nextLane);
								float num16 = (float)Mathf.Abs((int)(item2.m_position.m_offset - this._startOffsetA)) * 0.003921569f;
								item2.m_comparisonValue += num16 * nextSegment.m_averageLength / (num15 * this._maxLength);
							}
							if (curLaneId == this._startLaneB) {
								if (((byte)(item2.m_direction & NetInfo.Direction.Forward) == 0 || item2.m_position.m_offset < this._startOffsetB) && ((byte)(item2.m_direction & NetInfo.Direction.Backward) == 0 || item2.m_position.m_offset > this._startOffsetB)) {
									curLaneId = instance.m_lanes.m_buffer[(int)((UIntPtr)curLaneId)].m_nextLane;
									goto IL_90F;
								}
								float num17 = this.CalculateLaneSpeed(this._startOffsetB, item2.m_position.m_offset, ref nextSegment, nextLane);
								float num18 = (float)Mathf.Abs((int)(item2.m_position.m_offset - this._startOffsetB)) * 0.003921569f;
								item2.m_comparisonValue += num18 * nextSegment.m_averageLength / (num17 * this._maxLength);
							}
							if (!this._ignoreBlocked && (nextSegment.m_flags & NetSegment.Flags.Blocked) != NetSegment.Flags.None && (byte)(nextLane.m_laneType & (NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle)) != 0) {
								item2.m_comparisonValue += 0.1f;
								result = true;
							}
							item2.m_lanesUsed = (item.m_lanesUsed | nextLane.m_laneType);
							item2.m_laneID = curLaneId;
							if ((byte)(nextLane.m_laneType & laneType) != 0 && nextLane.m_vehicleType == vehicleType) {
								// NON-STOCK CODE START //
								if (!customLaneChanging/* || !addCustomCosts*/) {
								// NON-STOCK CODE END //
									int firstTarget = (int)instance.m_lanes.m_buffer[(int)((UIntPtr)curLaneId)].m_firstTarget;
									int lastTarget = (int)instance.m_lanes.m_buffer[(int)((UIntPtr)curLaneId)].m_lastTarget;
									if (laneIndexFromLeft < firstTarget || laneIndexFromLeft >= lastTarget) {
										item2.m_comparisonValue += Mathf.Max(1f, distanceOnBezier * 3f - 3f) / ((prevMaxSpeed + nextLane.m_speedLimit) * 0.5f * this._maxLength);
									}
								// NON-STOCK CODE START //
								}
								// NON-STOCK CODE END //

								if (!this._transportVehicle && nextLane.m_laneType == NetInfo.LaneType.TransportVehicle) {
									item2.m_comparisonValue += 20f / ((prevMaxSpeed + nextLane.m_speedLimit) * 0.5f * this._maxLength);
								}
							}

							// NON-STOCK CODE START //
							try {
								if (addCustomCosts) {
									int nextRightSimilarLaneIndex;
									if ((byte)(nextLane.m_direction & normDirection) != 0) {
										nextRightSimilarLaneIndex = nextLane.m_similarLaneIndex;
									} else {
										nextRightSimilarLaneIndex = nextLane.m_similarLaneCount - nextLane.m_similarLaneIndex - 1;
									}
									int maxLaneDiff = Math.Max(prevLanes, nextLane.m_similarLaneCount);

									bool doLaneChange = changeLane;

									// vehicles should choose lanes with low traffic volume if possible, especially before junctions.
									float trafficCost = 0f;
									int laneDist = Math.Abs(nextRightSimilarLaneIndex - prevRightSimilarLaneIndex);
									trafficCost = UnityEngine.Random.Range(0f, (prevDensity - nextDensity + 1f) / 2f);

									if (trafficCost > 1) {
										Log.Error($"Traffic cost > 1! {prevDensity} {nextDensity}");
									}

									// vehicles should generally avoid changing more than one lane.
									float laneChangeCost = 0f;
									if (laneDist > 1)
										laneChangeCost = Math.Min(1f, Math.Max(0f, (float)(laneDist * laneDist) / (float)(maxLaneDiff * maxLaneDiff))); // (*)

									// highway exit handling
									float junctionCost = 0f;
									bool applyHighwayRules = Options.highwayRules && laneDist > 0 && nextIsHighway && prevIsOutgoingOneWay;
									if (applyHighwayRules) {
										// calculate costs for changing lane near highway junctions
										// on highways: vehicles should not switch lanes directly before an exit.
										int decelerationLaneLength = _pathRandomizer.Int32(1, 4);
										if (item2.m_numSegmentsToJunction <= decelerationLaneLength) {
											// stay on lane before exit
											junctionCost = Math.Min(1f, Math.Max(0f, (float)laneDist / (float)maxLaneDiff));
											doLaneChange = false;
										}
									}

									if ((laneDist == 1 && !doLaneChange) || (laneDist == 0 && doLaneChange)) {
										// do not change lane / change lane
										laneChangeCost = 1f / (float)(maxLaneDiff * maxLaneDiff); // should be similarily calculated as (*)
									}

									float totalCost = 0f;
									float weight;
									if (applyHighwayRules) {
										if (this._isHeavyVehicle)
											weight = UnityEngine.Random.Range(Math.Max(0f, Options.truckHighwayTrafficSensitivity - 0.1f), Math.Min(1f, Options.truckHighwayTrafficSensitivity + 0.1f));
										else
											weight = UnityEngine.Random.Range(Math.Max(0f, Options.carHighwayTrafficSensitivity - 0.1f), Math.Min(1f, Options.carHighwayTrafficSensitivity + 0.1f));
										totalCost = weight * trafficCost + 0.2f * junctionCost + (0.8f - weight) * laneChangeCost;
									} else {
										if (this._isHeavyVehicle)
											weight = UnityEngine.Random.Range(Math.Max(0f, Options.truckCityTrafficSensitivity - 0.1f), Math.Min(1f, Options.truckCityTrafficSensitivity + 0.1f));
										else
											weight = UnityEngine.Random.Range(Math.Max(0f, Options.carCityTrafficSensitivity - 0.1f), Math.Min(1f, Options.carCityTrafficSensitivity + 0.1f));
										// prevent lane changes before junctions
										int trafficFactor = Math.Max(1, 5 - (int)item2.m_numSegmentsToJunction);
										weight /= weightDimByTrafficFactor[trafficFactor];
										totalCost = weight * trafficCost + (1f - weight) * laneChangeCost;
									}
									item2.m_comparisonValue += totalCost * nextSegment.m_averageLength * Options.getPathCostMultiplicator() / (nextLane.m_speedLimit * this._maxLength);

									//item2.m_comparisonValue = Math.Max(0f, Math.Min(1f, item2.m_comparisonValue));
									item2.m_comparisonValue = Math.Max(0f, item2.m_comparisonValue);
									if (debug) {
										Log.Message($">> seg {item2.m_position.m_segment}, lane {item2.m_position.m_lane} (idx {item2.m_laneID}), off {item2.m_position.m_offset}, cost {item2.m_comparisonValue}, totalCost {totalCost} = traffic={trafficCost}, junction={junctionCost}, lane={laneChangeCost}, weight={weight}");
									}
								}
								if (forceLaneIndex != null && laneIndex == forceLaneIndex)
									foundForced = true;

								if (debug) {
									Log.Message($">> Adding item: seg {item2.m_position.m_segment}, lane {item2.m_position.m_lane} (idx {item2.m_laneID}), off {item2.m_position.m_offset}, cost {item2.m_comparisonValue}");
								}
							} catch (Exception e) {
								Log.Error($"Error occurred in custom path-finding (sub): {e.ToString()}");
							}
							// NON-STOCK CODE END //

							this.AddBufferItem(item2, item.m_position);
						}
					}
					goto IL_8F5;
				}
				if ((byte)(nextLane.m_laneType & laneType) != 0 && nextLane.m_vehicleType == vehicleType) {
					num11++;
					goto IL_8F5;
				}
				goto IL_8F5;
				IL_90F:
				laneIndex++;
				continue;
				IL_8F5:
				curLaneId = instance.m_lanes.m_buffer[(int)((UIntPtr)curLaneId)].m_nextLane;
				goto IL_90F;
			} // foreach lane
			laneIndexFromLeft = num11;
			return result;
		}