/// <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); } }
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); }
/// <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 { } }
/// <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. } }
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")); } }
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; } }
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); } }
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); } } }
/// <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; }
/// <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); } }
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; }
// 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; }
// 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++; } }
public override bool FilterBuffer(BufferItem item) { return(item.TypeName == "LogEntity"); }
protected abstract void Get(ref BufferItem buffer);
public void SetItemToClipboard(BufferItem p_item) { throw new NotImplementedException(); }
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; }
// 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++; } }
// 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); } } }
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); } } }
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; }
public override bool FilterBuffer(BufferItem item) { return(item is SilverDollarBufferItem); }
/// <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; }