public void Unlink(ref ExtVehicle extVehicle) { #if DEBUG if (DebugSwitch.VehicleLinkingToSegmentEnd.Get()) { Log._Debug( $"ExtVehicleManager.Unlink({extVehicle.vehicleId}) called: Unlinking vehicle " + $"from all segment ends\nstate:{extVehicle}"); } ushort prevSegmentId = extVehicle.currentSegmentId; bool prevStartNode = extVehicle.currentStartNode; #endif extVehicle.lastPositionUpdate = Now(); if (extVehicle.previousVehicleIdOnSegment != 0) { ExtVehicles[extVehicle.previousVehicleIdOnSegment].nextVehicleIdOnSegment = extVehicle.nextVehicleIdOnSegment; } else if (extVehicle.currentSegmentId != 0) { IExtSegmentEndManager segmentEndMan = Constants.ManagerFactory.ExtSegmentEndManager; int endIndex = segmentEndMan.GetIndex( extVehicle.currentSegmentId, extVehicle.currentStartNode); if (segmentEndMan.ExtSegmentEnds[endIndex].firstVehicleId == extVehicle.vehicleId) { segmentEndMan.ExtSegmentEnds[endIndex].firstVehicleId = extVehicle.nextVehicleIdOnSegment; } else { Log.Error( $"ExtVehicleManager.Unlink({extVehicle.vehicleId}): Unexpected first " + $"vehicle on segment {extVehicle.currentSegmentId}: " + $"{segmentEndMan.ExtSegmentEnds[endIndex].firstVehicleId}"); } } if (extVehicle.nextVehicleIdOnSegment != 0) { ExtVehicles[extVehicle.nextVehicleIdOnSegment].previousVehicleIdOnSegment = extVehicle.previousVehicleIdOnSegment; } extVehicle.nextVehicleIdOnSegment = 0; extVehicle.previousVehicleIdOnSegment = 0; extVehicle.currentSegmentId = 0; extVehicle.currentStartNode = false; extVehicle.currentLaneIndex = 0; extVehicle.lastPathId = 0; extVehicle.lastPathPositionIndex = 0; #if DEBUG if (DebugSwitch.PedestrianPathfinding.Get()) { string vehicleChainDebugInfo = ExtSegmentEndManager.Instance.GenerateVehicleChainDebugInfo( prevSegmentId, prevStartNode); Log._Debug( $"ExtVehicleManager.Unlink({extVehicle.vehicleId}) finished: Unlinked vehicle " + $"from all segment ends\nstate:{extVehicle}\nold segment end vehicle chain: " + vehicleChainDebugInfo); } #endif }
public void UpdatePosition(ref ExtVehicle extVehicle, ref Vehicle vehicleData, ref ExtSegmentEnd segEnd, ref PathUnit.Position curPos, ref PathUnit.Position nextPos) { #if DEBUG bool logVehicleLinking = DebugSwitch.VehicleLinkingToSegmentEnd.Get(); #else const bool logVehicleLinking = false; #endif if (logVehicleLinking) { Log._Debug($"ExtVehicleManager.UpdatePosition({extVehicle.vehicleId}) called: {extVehicle}"); } if ((extVehicle.flags & ExtVehicleFlags.Spawned) == ExtVehicleFlags.None) { if (logVehicleLinking) { Log._Debug( $"ExtVehicleManager.UpdatePosition({extVehicle.vehicleId}): Vehicle is not yet spawned."); } OnSpawn(ref extVehicle, ref vehicleData); } if (extVehicle.nextSegmentId != nextPos.m_segment || extVehicle.nextLaneIndex != nextPos.m_lane) { extVehicle.nextSegmentId = nextPos.m_segment; extVehicle.nextLaneIndex = nextPos.m_lane; } bool startNode = IsTransitNodeCurStartNode(ref curPos, ref nextPos); if (extVehicle.currentSegmentId != segEnd.segmentId || extVehicle.currentStartNode != segEnd.startNode || extVehicle.currentLaneIndex != curPos.m_lane) { if (logVehicleLinking) { Log._Debug( $"ExtVehicleManager.UpdatePosition({extVehicle.vehicleId}): " + $"Current segment end changed. seg. {extVehicle.currentSegmentId}, " + $"start {extVehicle.currentStartNode}, lane {extVehicle.currentLaneIndex} -> " + $"seg. {segEnd.segmentId}, start {segEnd.startNode}, lane {curPos.m_lane}"); } if (extVehicle.currentSegmentId != 0) { if (logVehicleLinking) { Log._Debug( $"ExtVehicleManager.UpdatePosition({extVehicle.vehicleId}): " + "Unlinking from current segment end"); } Unlink(ref extVehicle); } extVehicle.lastPathId = vehicleData.m_path; extVehicle.lastPathPositionIndex = vehicleData.m_pathPositionIndex; extVehicle.waitTime = 0; #if DEBUGVSTATE if (logVehicleLinking) { Log._DebugFormat( "ExtVehicleManager.UpdatePosition({0}): Linking vehicle to segment end {1} " + "@ {2} ({3}). Current position: Seg. {4}, lane {5}, offset {6} / " + "Next position: Seg. {7}, lane {8}, offset {9}", extVehicle.vehicleId, segEnd.segmentId, segEnd.startNode, segEnd.nodeId, curPos.m_segment, curPos.m_lane, curPos.m_offset, nextPos.m_segment, nextPos.m_lane, nextPos.m_offset); } #endif if (segEnd.segmentId != 0) { Link(ref extVehicle, ref segEnd, curPos.m_lane); } SetJunctionTransitState(ref extVehicle, VehicleJunctionTransitState.Approach); } if (logVehicleLinking) { Log._Debug($"ExtVehicleManager.UpdatePosition({extVehicle.vehicleId}) finshed: {extVehicle}"); } }
protected void MeasureOutgoingVehicle(bool logDebug, IDictionary <ushort, uint>[] ret, bool includeStopped, uint avgSegmentLength, ushort vehicleId, ref Vehicle vehicle, ref ExtVehicle state, ref int numProcessed) { if (logDebug) { Log._DebugFormat( " MeasureOutgoingVehicle: (Segment {0}, Node {1} (start={2})) Checking vehicle {3}. " + "Coming from seg. {4}, start {5}, lane {6} going to seg. {7}, lane {8}", SegmentId, NodeId, StartNode, vehicleId, state.currentSegmentId, state.currentStartNode, state.currentLaneIndex, state.nextSegmentId, state.nextLaneIndex); } if ((state.flags & ExtVehicleFlags.Spawned) == ExtVehicleFlags.None) { Log._DebugIf( logDebug, () => $" MeasureOutgoingVehicle: Vehicle {vehicleId} is unspawned. Ignoring."); return; } #if DEBUG if (state.currentSegmentId != SegmentId || state.currentStartNode != StartNode) { if (logDebug) { Log._Debug( $" MeasureOutgoingVehicle: (Segment {SegmentId}, Node {NodeId} " + $"(start={StartNode})) Vehicle {vehicleId} error: Segment end mismatch! {state}"); } return; } #endif if (state.nextSegmentId == 0) { if (logDebug) { Log._Debug($" MeasureOutgoingVehicle: (Segment {SegmentId}, Node {NodeId} " + $"(start={StartNode})) Vehicle {vehicleId}: Ignoring vehicle"); } return; } if (state.currentLaneIndex >= ret.Length || !ret[state.currentLaneIndex].ContainsKey(state.nextSegmentId)) { if (logDebug) { Log._DebugFormat( " MeasureOutgoingVehicle: (Segment {0}, Node {1} (start={2})) Vehicle {3} is " + "on lane {4} and wants to go to segment {5} but one or both are invalid: {6}", SegmentId, NodeId, StartNode, vehicleId, state.currentLaneIndex, state.nextSegmentId, ret.CollectionToString()); } return; } if (!includeStopped && vehicle.GetLastFrameVelocity().sqrMagnitude < GlobalConfig.Instance.PriorityRules.MaxStopVelocity * GlobalConfig.Instance.PriorityRules.MaxStopVelocity) { if (logDebug) { Log._DebugFormat( " MeasureOutgoingVehicle: (Segment {0}, Node {1}) Vehicle {2}: too slow ({3})", SegmentId, NodeId, vehicleId, vehicle.GetLastFrameVelocity().sqrMagnitude); } ++numProcessed; return; } uint normLength = 10u; if (avgSegmentLength > 0) { // TODO +1 because the vehicle length calculation for trains/monorail in the method VehicleState.OnVehicleSpawned returns 0 (or a very small number maybe?) normLength = Math.Min(100u, (uint)(Math.Max(1u, state.totalLength) * 100u) / avgSegmentLength) + 1; } if (logDebug) { Log._DebugFormat( " MeasureOutgoingVehicle: (Segment {0}, Node {1}) NormLength of vehicle {2}: " + "{3} -> {4} (avgSegmentLength={5})", SegmentId, NodeId, vehicleId, state.totalLength, normLength, avgSegmentLength); } ret[state.currentLaneIndex][state.nextSegmentId] += normLength; ++numProcessed; if (logDebug) { Log._DebugFormat( " MeasureOutgoingVehicle: (Segment {0}, Node {1}) Vehicle {2}: ***ADDED*** " + "({3}@{4} -> {5}@{6})!", SegmentId, NodeId, vehicleId, state.currentSegmentId, state.currentLaneIndex, state.nextSegmentId, state.nextLaneIndex); } }