diff --git a/README.md b/README.md index f8336965..763de341 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,14 @@ A work-in-progress modification for **Cities: Skylines** to add additional traff User manual: http://www.viathinksoft.de/tmpe # Changelog +1.9.4, 05/23/2017 +- New option: Ban private cars and trucks on bus lanes +- Updated Spanish and French translation +- Optimized path-finding +- Increased path-finding cost for private cars driving on bus lanes +- Increased path-finding cost for disregarding vehicle restrictions +- Bugfix: Path-finding is unable to calculate certain paths after modifying the road network + 1.9.3, 05/22/2017 - Disabled notification of route recalculating because some players report crashes - Removed default vehicle restrictions from bus lanes diff --git a/TLM/TLM/Custom/PathFinding/CustomPathFind.cs b/TLM/TLM/Custom/PathFinding/CustomPathFind.cs index a9132f8c..999d32db 100644 --- a/TLM/TLM/Custom/PathFinding/CustomPathFind.cs +++ b/TLM/TLM/Custom/PathFinding/CustomPathFind.cs @@ -22,6 +22,8 @@ using TrafficManager.Traffic; using static TrafficManager.Manager.RoutingManager; using CSUtil.Commons; +using static TrafficManager.Manager.TrafficMeasurementManager; +using static TrafficManager.Manager.VehicleRestrictionsManager; namespace TrafficManager.Custom.PathFinding { public class CustomPathFind : PathFind { @@ -343,7 +345,8 @@ protected void PathFindImplementation(uint unit, ref PathUnit data) { #if DEBUGNEWPF && DEBUG bool debug = this._debug = _conf.DebugSwitches[0] && ((_conf.PathFindDebugExtVehicleType == ExtVehicleType.None && (_extVehicleType == null || _extVehicleType == ExtVehicleType.None)) || (_extVehicleType != null && (_extVehicleType & _conf.PathFindDebugExtVehicleType) != ExtVehicleType.None)) && - (_conf.PathFindDebugStartSegmentId < 0 || data.m_position00.m_segment == _conf.PathFindDebugStartSegmentId || data.m_position02.m_segment == _conf.PathFindDebugStartSegmentId) + (_conf.PathFindDebugStartSegmentId <= 0 || data.m_position00.m_segment == _conf.PathFindDebugStartSegmentId || data.m_position02.m_segment == _conf.PathFindDebugStartSegmentId) && + (_conf.PathFindDebugVehicleId <= 0 || _vehicleId == _conf.PathFindDebugVehicleId) ; if (debug) { Log._Debug($"CustomPathFind.PathFindImplementation: START calculating path unit {unit}, type {_extVehicleType}"); @@ -540,6 +543,19 @@ protected void PathFindImplementation(uint unit, ref PathUnit data) { if ((byte)(candidateItem.m_direction & direction) != 0 && (!flag2 || (instance.m_nodes.m_buffer[specialNodeId].m_flags & NetNode.Flags.Disabled) != NetNode.Flags.None)) { bool isStartNode = specialNodeId == startNode2; uint laneRoutingIndex = routingManager.GetLaneEndRoutingIndex(candidateItem.m_laneID, isStartNode); +#if DEBUGNEWPF && DEBUG + if (debug) { + Log._Debug($"CustomPathFind.PathFindImplementation: Handling special node for path unit {unit}, type {_extVehicleType}:\n" + + $"\tcandidateItem.m_position.m_segment={candidateItem.m_position.m_segment}\n" + + $"\tcandidateItem.m_position.m_lane={candidateItem.m_position.m_lane}\n" + + $"\tcandidateItem.m_laneID={candidateItem.m_laneID}\n" + + $"\tspecialNodeId={specialNodeId}\n" + + $"\tstartNode2={startNode2}\n" + + $"\tendNode2={endNode2}\n" + + $"\tlaneRoutingIndex={laneRoutingIndex}\n" + ); + } +#endif this.ProcessItemMain(unit, candidateItem, ref instance.m_segments.m_buffer[candidateItem.m_position.m_segment], ref routingManager.segmentRoutings[candidateItem.m_position.m_segment], ref routingManager.laneEndRoutings[laneRoutingIndex], specialNodeId, isStartNode, ref instance.m_nodes.m_buffer[specialNodeId], laneOffset, true); } specialNodeId = instance.m_nodes.m_buffer[specialNodeId].m_nextLaneNode; @@ -742,7 +758,7 @@ protected void PathFindImplementation(uint unit, ref PathUnit data) { // 1 private void ProcessItemMain(uint unitId, BufferItem item, ref NetSegment prevSegment, ref SegmentRoutingData prevSegmentRouting, ref LaneEndRoutingData prevLaneEndRouting, ushort nextNodeId, bool nextIsStartNode, ref NetNode nextNode, byte connectOffset, bool isMiddle) { #if DEBUGNEWPF && DEBUG - bool debug = this._debug && (_conf.PathFindDebugNodeId < 0 || nextNodeId == _conf.PathFindDebugNodeId); + bool debug = this._debug && (_conf.PathFindDebugNodeId <= 0 || nextNodeId == _conf.PathFindDebugNodeId); if (debug) { if (! _debugPositions.ContainsKey(item.m_position.m_segment)) { _debugPositions[item.m_position.m_segment] = new List(); @@ -1028,15 +1044,15 @@ private void ProcessItemMain(uint unitId, BufferItem item, ref NetSegment prevSe // determine if the vehicle may u-turn at the target node bool explorePrevSegment = - nextIsEndOrOneWayOut || // stock u-turn points + _isRoadVehicle && // only road vehicles may perform u-turns + (nextIsEndOrOneWayOut || // stock u-turn points (Options.junctionRestrictionsEnabled && isCustomUturnAllowed && // only do u-turns if allowed !nextIsBeautificationNode && // no u-turns at beautification nodes prevIsCarLane && // u-turns for road vehicles only - _isRoadVehicle && // only road vehicles may perform u-turns !_isHeavyVehicle && // only small vehicles may perform u-turns (nextIsTransitionOrJunction || nextIsBend) && // perform u-turns at transitions, junctions and bend nodes - !prevIsOutgoingOneWay); // do not u-turn on one-ways + !prevIsOutgoingOneWay)); // do not u-turn on one-ways bool isStrictLaneArrowPolicyEnabled = !nextIsBeautificationNode && // do not obey lane arrows at beautification nodes @@ -1049,7 +1065,7 @@ private void ProcessItemMain(uint unitId, BufferItem item, ref NetSegment prevSe #endif (Options.relaxedBusses && _extVehicleType == ExtVehicleType.Bus)); // option: busses may ignore lane arrows - bool useRouting = prevLaneEndRouting.routed && !nextIsBeautificationNode; + //bool useRouting = prevLaneEndRouting.routed && !nextIsBeautificationNode; bool handleStockUturn = !explorePrevSegment && (this._vehicleTypes & VehicleInfo.VehicleType.Tram) == VehicleInfo.VehicleType.None; @@ -1058,7 +1074,7 @@ private void ProcessItemMain(uint unitId, BufferItem item, ref NetSegment prevSe //LaneEndGeometry prevLaneEndGeo = prevGeometry.GetLane(item.m_position.m_lane, false)?.GetEnd(!nextIsStartNode); #if DEBUGNEWPF if (debug) - logBuf.Add($"item: seg. {item.m_position.m_segment}, lane {item.m_position.m_lane}, node {nextNodeId}:\n" + + logBuf.Add($"item: seg. {item.m_position.m_segment}, lane {item.m_position.m_lane}, node {nextNodeId} ({nextIsStartNode}):\n" + "\t" + $"_extPathType={_extPathType}\n" + "\t" + $"_vehicleTypes={_vehicleTypes}, _laneTypes={_laneTypes}\n" + "\t" + $"_extVehicleType={_extVehicleType}\n" + @@ -1127,26 +1143,37 @@ private void ProcessItemMain(uint unitId, BufferItem item, ref NetSegment prevSe #endif for (int i = 0; i < 8; ++i) { - ushort nextSegmentId = nextNode.GetSegment(i); - if (nextSegmentId == 0) { + LaneTransitionData[] laneTransitions = prevLaneEndRouting.GetTransitions(i); + + if (laneTransitions == null) { continue; } - if (nextSegmentId == prevSegmentId) { - if (explorePrevSegment) { - // prevent double exploration of previous segment during this method execution - handleStockUturn = false; - } else { +#if DEBUGNEWPF + if (debug) + logBuf.Add( + $"item: seg. {item.m_position.m_segment}, lane {item.m_position.m_lane}, node {nextNodeId}:\n" + + "\t" + $"CUSTOM exploration iteration {i}\n" + ); +#endif + + + for (int k = 0; k < laneTransitions.Length; ++k) { + ushort nextSegmentId = laneTransitions[k].segmentId; + + if (nextSegmentId == 0) { continue; } - } - LaneTransitionData[] laneTransitions = prevLaneEndRouting.GetTransitions(i); - if (laneTransitions == null) { - continue; - } + if (nextSegmentId == prevSegmentId) { + if (explorePrevSegment) { + // prevent double exploration of previous segment during this method execution + handleStockUturn = false; + } else { + continue; + } + } - for (int k = 0; k < laneTransitions.Length; ++k) { if (laneTransitions[k].type == LaneEndTransitionType.Invalid || (isStrictLaneArrowPolicyEnabled && laneTransitions[k].type == LaneEndTransitionType.Relaxed)) { continue; @@ -1156,9 +1183,10 @@ private void ProcessItemMain(uint unitId, BufferItem item, ref NetSegment prevSe if (debug) { logBuf.Add( $"item: seg. {item.m_position.m_segment}, lane {item.m_position.m_lane}, node {nextNodeId}:\n" + - "\t" + $"-> CUSTOM exploration iteration {i}\n" + - "\t" + $"next seg={nextSegmentId}, idx={laneTransitions[k].laneIndex}, id={laneTransitions[k].laneId}, type={laneTransitions[k].type}, dist={laneTransitions[k].distance}\n" - ); + "\t" + $"CUSTOM exploration iteration {i}:\n" + + "\t" + $"transition iteration {k}:\n" + + "\t" + $"{laneTransitions[k].ToString()}\n" + ); FlushMainLog(logBuf, unitId); } #endif @@ -1461,37 +1489,36 @@ private bool ProcessItemCosts(bool debug, bool allowAdvancedAI, bool obeyStockLa } else if (calculateTrafficStats) { NetInfo.Direction prevFinalDir = nextIsStartNodeOfPrevSegment ? NetInfo.Direction.Forward : NetInfo.Direction.Backward; prevFinalDir = ((prevSegment.m_flags & NetSegment.Flags.Invert) == NetSegment.Flags.None) ? prevFinalDir : NetInfo.InvertDirection(prevFinalDir); + int prevDirIndex = trafficMeasurementManager.GetDirIndex(item.m_position.m_segment, prevFinalDir); + int nextDirIndex = trafficMeasurementManager.GetDirIndex(nextSegmentId, nextFinalDir); TrafficMeasurementManager.LaneTrafficData[] prevLanesTrafficData; - TrafficMeasurementManager.SegmentDirTrafficData prevDirTrafficData; - TrafficMeasurementManager.SegmentDirTrafficData nextDirTrafficData; - if (trafficMeasurementManager.GetTrafficData(item.m_position.m_segment, prevSegmentInfo, out prevLanesTrafficData) && - trafficMeasurementManager.GetTrafficData(item.m_position.m_segment, prevFinalDir, out prevDirTrafficData) && - trafficMeasurementManager.GetTrafficData(nextSegmentId, nextFinalDir, out nextDirTrafficData) - ) { + if (trafficMeasurementManager.GetLaneTrafficData(item.m_position.m_segment, prevSegmentInfo, out prevLanesTrafficData)) { + float prevCongestionRatio = trafficMeasurementManager.segmentDirTrafficData[prevDirIndex].numCongestionMeasurements > 0 ? ((uint)trafficMeasurementManager.segmentDirTrafficData[prevDirIndex].numCongested * 100u) / (uint)trafficMeasurementManager.segmentDirTrafficData[prevDirIndex].numCongestionMeasurements : 0; // now in % + float nextCongestionRatio = trafficMeasurementManager.segmentDirTrafficData[nextDirIndex].numCongestionMeasurements > 0 ? ((uint)trafficMeasurementManager.segmentDirTrafficData[nextDirIndex].numCongested * 100u) / (uint)trafficMeasurementManager.segmentDirTrafficData[nextDirIndex].numCongestionMeasurements : 0; // now in % + + // get the path-finding lane utilization for the previous lane + if (trafficMeasurementManager.segmentDirTrafficData[prevDirIndex].totalPathFindTrafficBuffer > 0) { + prevUsage = Mathf.Clamp(((prevLanesTrafficData[item.m_position.m_lane].lastPathFindTrafficBuffer * 100u) / trafficMeasurementManager.segmentDirTrafficData[prevDirIndex].totalPathFindTrafficBuffer), 0, 100); + } else { + prevUsage = 0; + } + + // get the min. speed for the previous segment + prevTraffic = Mathf.Clamp(100 - (int)trafficMeasurementManager.segmentDirTrafficData[prevDirIndex].meanSpeed / 100, 0, 100); + + // get the direction-average minimum speed for the previous segment #if MARKCONGESTEDSEGMENTS //int dirIndex = prevLaneInfo.m_finalDirection == NetInfo.Direction.Backward ? 1 : 0; - float prevCongestionRatio = prevDirTrafficData.numCongestionMeasurements > 0 ? ((uint)prevDirTrafficData.numCongested * 100u) / (uint)prevDirTrafficData.numCongestionMeasurements : 0; // now in % - float nextCongestionRatio = nextDirTrafficData.numCongestionMeasurements > 0 ? ((uint)nextDirTrafficData.numCongested * 100u) / (uint)nextDirTrafficData.numCongestionMeasurements : 0; // now in % + isCongested = prevCongestionRatio >= _conf.CongestionFrequencyThreshold || nextCongestionRatio >= _conf.CongestionFrequencyThreshold; float maxCongestionRatio = Math.Max(prevCongestionRatio, nextCongestionRatio); congestionLaneChangingCosts = 1f + maxCongestionRatio * 0.01f * _conf.CongestionLaneChangingBaseCost; wantToChangeLane = _pathRandomizer.Int32((uint)maxCongestionRatio + _conf.RandomizedLaneChangingModulo) == 0; #endif - // get the path-finding lane utilization for the previous lane - uint totalBuf = prevDirTrafficData.totalPathFindTrafficBuffer; - if (totalBuf > 0) { - prevUsage = Mathf.Clamp(((prevLanesTrafficData[item.m_position.m_lane].lastPathFindTrafficBuffer * 100u) / totalBuf), 0, 100); - } else { - prevUsage = 0; - } - - // get the min. speed for the previous segment - prevTraffic = Mathf.Clamp(100 - (int)prevDirTrafficData.meanSpeed / 100, 0, 100); - // prevUsage, prevTraffic is now in % #if DEBUGNEWPF float oldUsageRand = usageRand; @@ -2542,7 +2569,7 @@ protected virtual bool CanUseLane(bool debug, ushort segmentId, NetInfo segmentI if (!Options.vehicleRestrictionsEnabled) return true; - if (_extVehicleType == null || _extVehicleType == ExtVehicleType.None /*|| _extVehicleType == ExtVehicleType.Tram*/) + if (_extVehicleType == null || _extVehicleType == ExtVehicleType.None || _extVehicleType == ExtVehicleType.Tram) return true; /*if (laneInfo == null) @@ -2551,7 +2578,7 @@ protected virtual bool CanUseLane(bool debug, ushort segmentId, NetInfo segmentI if ((laneInfo.m_vehicleType & (VehicleInfo.VehicleType.Car | VehicleInfo.VehicleType.Train)) == VehicleInfo.VehicleType.None) return true; - ExtVehicleType allowedTypes = vehicleRestrictionsManager.GetAllowedVehicleTypes(segmentId, segmentInfo, laneIndex, laneInfo, false); + ExtVehicleType allowedTypes = vehicleRestrictionsManager.GetAllowedVehicleTypes(segmentId, segmentInfo, laneIndex, laneInfo, RestrictionMode.Configured); #if DEBUGPF if (debug) { Log._Debug($"CanUseLane: segmentId={segmentId} laneIndex={laneIndex} _extVehicleType={_extVehicleType} _vehicleTypes={_vehicleTypes} _laneTypes={_laneTypes} _transportVehicle={_transportVehicle} _isHeavyVehicle={_isHeavyVehicle} allowedTypes={allowedTypes} res={((allowedTypes & _extVehicleType) != ExtVehicleType.None)}"); diff --git a/TLM/TLM/Manager/AbstractSegmentGeometryObservingManager.cs b/TLM/TLM/Manager/AbstractSegmentGeometryObservingManager.cs index 2551fb8e..5a7a819e 100644 --- a/TLM/TLM/Manager/AbstractSegmentGeometryObservingManager.cs +++ b/TLM/TLM/Manager/AbstractSegmentGeometryObservingManager.cs @@ -77,13 +77,13 @@ public override void OnLevelUnloading() { public void OnUpdate(SegmentGeometry geometry) { if (!geometry.IsValid()) { - Log._Debug($"{this.GetType().Name}.HandleInvalidSegment({geometry.SegmentId})"); + //Log._Debug($"{this.GetType().Name}.HandleInvalidSegment({geometry.SegmentId})"); HandleInvalidSegment(geometry); if (!AllowInvalidSegments) { UnsubscribeFromSegmentGeometry(geometry.SegmentId); } } else { - Log._Debug($"{this.GetType().Name}.HandleValidSegment({geometry.SegmentId})"); + //Log._Debug($"{this.GetType().Name}.HandleValidSegment({geometry.SegmentId})"); HandleValidSegment(geometry); } } diff --git a/TLM/TLM/Manager/OptionsManager.cs b/TLM/TLM/Manager/OptionsManager.cs index 430cb1a1..e137f8f1 100644 --- a/TLM/TLM/Manager/OptionsManager.cs +++ b/TLM/TLM/Manager/OptionsManager.cs @@ -148,6 +148,10 @@ public bool LoadData(byte[] data) { Options.setParkingRestrictionsOverlay(data[31] == (byte)1); } + if (data.Length >= 33) { + Options.setBanRegularTrafficOnBusLanes(data[32] == (byte)1); + } + return true; } @@ -184,7 +188,8 @@ public byte[] SaveData(ref bool success) { (byte)(Options.evacBussesMayIgnoreRules ? 1 : 0), (byte)(Options.instantEffects ? 1 : 0), (byte)(Options.parkingRestrictionsEnabled ? 1 : 0), - (byte)(Options.parkingRestrictionsOverlay ? 1 : 0) + (byte)(Options.parkingRestrictionsOverlay ? 1 : 0), + (byte)(Options.banRegularTrafficOnBusLanes ? 1 : 0) }; } } diff --git a/TLM/TLM/Manager/RoutingManager.cs b/TLM/TLM/Manager/RoutingManager.cs index d8bf8254..51a93790 100644 --- a/TLM/TLM/Manager/RoutingManager.cs +++ b/TLM/TLM/Manager/RoutingManager.cs @@ -161,46 +161,29 @@ public struct LaneTransitionData { public byte laneIndex; public LaneEndTransitionType type; public byte distance; -#if DEBUG public ushort segmentId; -#endif public override string ToString() { return $"[LaneTransitionData\n" + "\t" + $"laneId = {laneId}\n" + "\t" + $"laneIndex = {laneIndex}\n" + -#if DEBUG "\t" + $"segmentId = {segmentId}\n" + -#endif "\t" + $"type = {type}\n" + "\t" + $"distance = {distance}\n" + "LaneTransitionData]"; } - public void Set(uint laneId, byte laneIndex, LaneEndTransitionType type, byte distance -#if DEBUG - , ushort segmentId -#endif + public void Set(uint laneId, byte laneIndex, LaneEndTransitionType type, byte distance, ushort segmentId ) { this.laneId = laneId; this.laneIndex = laneIndex; this.type = type; this.distance = distance; -#if DEBUG this.segmentId = segmentId; -#endif } - public void Set(uint laneId, byte laneIndex, LaneEndTransitionType type -#if DEBUG - , ushort segmentId -#endif - ) { - Set(laneId, laneIndex, type, 0 -#if DEBUG - , segmentId -#endif - ); + public void Set(uint laneId, byte laneIndex, LaneEndTransitionType type, ushort segmentId) { + Set(laneId, laneIndex, type, 0, segmentId); } } @@ -700,11 +683,7 @@ protected void RecalculateLaneEndRoutingData(ushort segmentId, int laneIndex, ui // lane can be used by all vehicles that may disregard lane arrows transitionType = LaneEndTransitionType.Relaxed; if (numNextRelaxedTransitionDatas < MAX_NUM_TRANSITIONS) { - nextRelaxedTransitionDatas[numNextRelaxedTransitionDatas++].Set(nextLaneId, nextLaneIndex, transitionType, GlobalConfig.Instance.IncompatibleLaneDistance -#if DEBUG - , nextSegmentId -#endif - ); + nextRelaxedTransitionDatas[numNextRelaxedTransitionDatas++].Set(nextLaneId, nextLaneIndex, transitionType, GlobalConfig.Instance.IncompatibleLaneDistance, nextSegmentId); } else { Log.Warning($"nextTransitionDatas overflow @ source lane {prevLaneId}, idx {prevLaneIndex} @ seg. {prevSegmentId}"); } @@ -719,11 +698,7 @@ protected void RecalculateLaneEndRoutingData(ushort segmentId, int laneIndex, ui if (numNextCompatibleTransitionDatas < MAX_NUM_TRANSITIONS) { nextCompatibleOuterSimilarIndices[numNextCompatibleTransitionDatas] = nextOuterSimilarLaneIndex; //compatibleLaneIndicesMask |= POW2MASKS[numNextCompatibleTransitionDatas]; - nextCompatibleTransitionDatas[numNextCompatibleTransitionDatas++].Set(nextLaneId, nextLaneIndex, transitionType -#if DEBUG - , nextSegmentId -#endif - ); + nextCompatibleTransitionDatas[numNextCompatibleTransitionDatas++].Set(nextLaneId, nextLaneIndex, transitionType, nextSegmentId); } else { Log.Warning($"nextCompatibleTransitionDatas overflow @ source lane {prevLaneId}, idx {prevLaneIndex} @ seg. {prevSegmentId}"); } @@ -1055,7 +1030,7 @@ protected void RecalculateLaneEndRoutingData(ushort segmentId, int laneIndex, ui nextTransitionDatas[j++] = nextRelaxedTransitionDatas[i]; } - routing.SetTransitions(GetSegmentNodeIndex(nextNodeId, nextSegmentId), nextTransitionDatas); + routing.SetTransitions(k, nextTransitionDatas); } // valid segment if (nextSegmentId != prevSegmentId) { @@ -1122,7 +1097,7 @@ private void UpdateHighwayLaneArrows(uint laneId, bool startNode, ArrowDirection } } - private int GetSegmentNodeIndex(ushort nodeId, ushort segmentId) { + /*private int GetSegmentNodeIndex(ushort nodeId, ushort segmentId) { int i = -1; Services.NetService.IterateNodeSegments(nodeId, delegate (ushort segId, ref NetSegment segment) { ++i; @@ -1132,10 +1107,10 @@ private int GetSegmentNodeIndex(ushort nodeId, ushort segmentId) { return true; }); return i; - } + }*/ internal uint GetLaneEndRoutingIndex(uint laneId, bool startNode) { - return (uint)(laneId + (startNode ? 0 : NetManager.MAX_LANE_COUNT)); + return (uint)(laneId + (startNode ? 0u : (uint)NetManager.MAX_LANE_COUNT)); } public int CalcInnerLaneSimilarIndex(ushort segmentId, int laneIndex) { diff --git a/TLM/TLM/Manager/SegmentEndManager.cs b/TLM/TLM/Manager/SegmentEndManager.cs index 4d8417f8..f21aa3be 100644 --- a/TLM/TLM/Manager/SegmentEndManager.cs +++ b/TLM/TLM/Manager/SegmentEndManager.cs @@ -114,7 +114,7 @@ protected override void HandleValidSegment(SegmentGeometry geometry) { protected void DestroySegmentEnd(int index) { #if DEBUG - Log.Warning($"SegmentEndManager.DestroySegmentEnd({index}) called"); + Log._Debug($"SegmentEndManager.DestroySegmentEnd({index}) called"); #endif SegmentEnds[index]?.Destroy(); SegmentEnds[index] = null; diff --git a/TLM/TLM/Manager/TrafficMeasurementManager.cs b/TLM/TLM/Manager/TrafficMeasurementManager.cs index 19c31253..2bd0964d 100644 --- a/TLM/TLM/Manager/TrafficMeasurementManager.cs +++ b/TLM/TLM/Manager/TrafficMeasurementManager.cs @@ -18,7 +18,7 @@ public class TrafficMeasurementManager : AbstractCustomManager { public const ushort MAX_SPEED = 10000; - public class LaneTrafficData { + public struct LaneTrafficData { /// /// Number of seen vehicles since last speed measurement /// @@ -65,7 +65,7 @@ public override string ToString() { } } - public class SegmentDirTrafficData { + public struct SegmentDirTrafficData { #if MEASUREDENSITY /// /// Current accumulated densities @@ -92,9 +92,9 @@ public class SegmentDirTrafficData { /// public uint totalPathFindTrafficBuffer; - public SegmentDirTrafficData() { + /*public SegmentDirTrafficData() { minSpeed = MAX_SPEED; - } + }*/ public override string ToString() { return $"[SegmentDirTrafficData\n" + @@ -118,7 +118,7 @@ public override string ToString() { /// /// Traffic data per segment and traffic direction /// - private SegmentDirTrafficData[][] segmentDirTrafficData; + internal SegmentDirTrafficData[] segmentDirTrafficData; private SegmentDirTrafficData defaultSegmentDirTrafficData; @@ -129,10 +129,18 @@ public override string ToString() { private uint[] meanSpeeds = { 0, 0 }; private int[] meanSpeedLanes = { 0, 0 }; + private int[] segDirIndices = { 0, 0 }; + private TrafficMeasurementManager() { laneTrafficData = new LaneTrafficData[NetManager.MAX_SEGMENT_COUNT][]; - segmentDirTrafficData = new SegmentDirTrafficData[NetManager.MAX_SEGMENT_COUNT][]; + segmentDirTrafficData = new SegmentDirTrafficData[NetManager.MAX_SEGMENT_COUNT * 2]; defaultSegmentDirTrafficData = new SegmentDirTrafficData(); + defaultSegmentDirTrafficData.minSpeed = MAX_SPEED; + defaultSegmentDirTrafficData.meanSpeed = MAX_SPEED; + for (int i = 0; i < segmentDirTrafficData.Length; ++i) { + segmentDirTrafficData[i].minSpeed = MAX_SPEED; + segmentDirTrafficData[i].meanSpeed = MAX_SPEED; + } ResetTrafficStats(); } @@ -158,13 +166,7 @@ protected override void InternalPrintDebugInfo() { Log._Debug($"\t"); } else { for (int i = 0; i < segmentDirTrafficData.Length; ++i) { - if (segmentDirTrafficData[i] == null) { - continue; - } - Log._Debug($"\tSegment {i}:"); - for (int k = 0; k < segmentDirTrafficData[i].Length; ++k) { - Log._Debug($"\t\tDir {k}: {segmentDirTrafficData[i][k]}"); - } + Log._Debug($"\tIndex {i}: {segmentDirTrafficData[i]}"); } } } @@ -177,17 +179,10 @@ public void SimulationStep(ushort segmentId, ref NetSegment segmentData) { uint curLaneId = segmentData.m_lanes; int numLanes = segmentInfo.m_lanes.Length; - // ensure valid array sizes - if (segmentDirTrafficData[segmentId] == null) { - segmentDirTrafficData[segmentId] = new SegmentDirTrafficData[2]; - segmentDirTrafficData[segmentId][0] = new SegmentDirTrafficData(); - segmentDirTrafficData[segmentId][1] = new SegmentDirTrafficData(); - } - if (laneTrafficData[segmentId] == null || laneTrafficData[segmentId].Length < numLanes) { laneTrafficData[segmentId] = new LaneTrafficData[numLanes]; for (int i = 0; i < numLanes; ++i) { - laneTrafficData[segmentId][i] = new LaneTrafficData(); + //laneTrafficData[segmentId][i] = new LaneTrafficData(); laneTrafficData[segmentId][i].meanSpeed = MAX_SPEED; } } @@ -199,6 +194,7 @@ public void SimulationStep(ushort segmentId, ref NetSegment segmentData) { meanSpeeds[i] = 0; meanSpeedLanes[i] = 0; + segDirIndices[i] = 0; totalPfBuf[i] = 0; } @@ -305,31 +301,36 @@ public void SimulationStep(ushort segmentId, ref NetSegment segmentData) { curLaneId = Singleton.instance.m_lanes.m_buffer[curLaneId].m_nextLane; } + segDirIndices[0] = GetDirIndex(segmentId, NetInfo.Direction.Forward); + segDirIndices[1] = GetDirIndex(segmentId, NetInfo.Direction.Backward); + for (int i = 0; i < 2; ++i) { - if (segmentDirTrafficData[segmentId][i].numCongestionMeasurements > conf.MaxNumCongestionMeasurements) { - segmentDirTrafficData[segmentId][i].numCongestionMeasurements >>= 1; - segmentDirTrafficData[segmentId][i].numCongested >>= 1; + int segDirIndex = segDirIndices[i]; + + if (segmentDirTrafficData[segDirIndex].numCongestionMeasurements > conf.MaxNumCongestionMeasurements) { + segmentDirTrafficData[segDirIndex].numCongestionMeasurements >>= 1; + segmentDirTrafficData[segDirIndex].numCongested >>= 1; } - segmentDirTrafficData[segmentId][i].minSpeed = minSpeeds[i]; - ++segmentDirTrafficData[segmentId][i].numCongestionMeasurements; + segmentDirTrafficData[segDirIndex].minSpeed = minSpeeds[i]; + ++segmentDirTrafficData[segDirIndex].numCongestionMeasurements; if (minSpeeds[i] / 100u < conf.CongestionSpeedThreshold) { - ++segmentDirTrafficData[segmentId][i].numCongested; + ++segmentDirTrafficData[segDirIndex].numCongested; } #if MEASUREDENSITY segmentDirTrafficData[segmentId][i].accumulatedDensities = densities[i]; #endif - segmentDirTrafficData[segmentId][i].totalPathFindTrafficBuffer = totalPfBuf[i]; + segmentDirTrafficData[segDirIndex].totalPathFindTrafficBuffer = totalPfBuf[i]; if (meanSpeedLanes[i] > 0) { - segmentDirTrafficData[segmentId][i].meanSpeed = (ushort)(meanSpeeds[i] / meanSpeedLanes[i]); + segmentDirTrafficData[segDirIndex].meanSpeed = (ushort)(meanSpeeds[i] / meanSpeedLanes[i]); } else { - segmentDirTrafficData[segmentId][i].meanSpeed = MAX_SPEED; + segmentDirTrafficData[segDirIndex].meanSpeed = MAX_SPEED; } } } - public bool GetTrafficData(ushort segmentId, NetInfo segmentInfo, out LaneTrafficData[] trafficData) { + public bool GetLaneTrafficData(ushort segmentId, NetInfo segmentInfo, out LaneTrafficData[] trafficData) { if (laneTrafficData[segmentId] == null || laneTrafficData[segmentId].Length != segmentInfo.m_lanes.Length) { trafficData = null; return false; @@ -339,19 +340,19 @@ public bool GetTrafficData(ushort segmentId, NetInfo segmentInfo, out LaneTraffi } } - public bool GetTrafficData(ushort segmentId, NetInfo.Direction dir, out SegmentDirTrafficData trafficData) { - if (segmentDirTrafficData[segmentId] == null) { - trafficData = defaultSegmentDirTrafficData; - return false; - } else { - trafficData = segmentDirTrafficData[segmentId][GetDirIndex(dir)]; - return true; - } - } - public void DestroySegmentStats(ushort segmentId) { laneTrafficData[segmentId] = null; - segmentDirTrafficData[segmentId] = null; + + int fwdIndex = GetDirIndex(segmentId, NetInfo.Direction.Forward); + int backIndex = GetDirIndex(segmentId, NetInfo.Direction.Backward); + + segmentDirTrafficData[fwdIndex] = default(SegmentDirTrafficData); + segmentDirTrafficData[fwdIndex].minSpeed = MAX_SPEED; + segmentDirTrafficData[fwdIndex].meanSpeed = MAX_SPEED; + + segmentDirTrafficData[backIndex] = default(SegmentDirTrafficData); + segmentDirTrafficData[backIndex].minSpeed = MAX_SPEED; + segmentDirTrafficData[backIndex].meanSpeed = MAX_SPEED; } public void ResetTrafficStats() { @@ -381,7 +382,11 @@ public void AddPathFindTraffic(ushort segmentId, byte laneIndex) { lanesData[laneIndex].pathFindTrafficBuffer += (uint)(100u - lanesData[laneIndex].meanSpeed / 100); } - protected int GetDirIndex(NetInfo.Direction dir) { + internal int GetDirIndex(ushort segmentId, NetInfo.Direction dir) { + return (int)segmentId + (dir == NetInfo.Direction.Backward ? NetManager.MAX_SEGMENT_COUNT : 0); + } + + internal int GetDirIndex(NetInfo.Direction dir) { return dir == NetInfo.Direction.Backward ? 1 : 0; } diff --git a/TLM/TLM/Manager/VehicleRestrictionsManager.cs b/TLM/TLM/Manager/VehicleRestrictionsManager.cs index 5e0a264c..83134613 100644 --- a/TLM/TLM/Manager/VehicleRestrictionsManager.cs +++ b/TLM/TLM/Manager/VehicleRestrictionsManager.cs @@ -10,6 +10,21 @@ namespace TrafficManager.Manager { public class VehicleRestrictionsManager : AbstractSegmentGeometryObservingManager, ICustomDataManager> { + public enum RestrictionMode { + /// + /// Interpret bus lanes as "free for all" + /// + Unrestricted, + /// + /// Interpret bus lanes according to the configuration + /// + Configured, + /// + /// Interpret bus lanes as restricted + /// + Restricted + } + public const NetInfo.LaneType LANE_TYPES = NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle; public const VehicleInfo.VehicleType VEHICLE_TYPES = VehicleInfo.VehicleType.Car | VehicleInfo.VehicleType.Train | VehicleInfo.VehicleType.Tram; public const ExtVehicleType EXT_VEHICLE_TYPES = ExtVehicleType.PassengerTrain | ExtVehicleType.CargoTrain | ExtVehicleType.PassengerCar | ExtVehicleType.Bus | ExtVehicleType.Taxi | ExtVehicleType.CargoTruck | ExtVehicleType.Service | ExtVehicleType.Emergency; @@ -38,9 +53,9 @@ protected override void InternalPrintDebugInfo() { /// /// [Obsolete] - internal ExtVehicleType GetAllowedVehicleTypes(ushort segmentId, ushort nodeId, bool includeBusLanes) { // TODO optimize method (don't depend on collections!) + internal ExtVehicleType GetAllowedVehicleTypes(ushort segmentId, ushort nodeId, RestrictionMode busLaneMode) { // TODO optimize method (don't depend on collections!) ExtVehicleType ret = ExtVehicleType.None; - foreach (ExtVehicleType vehicleType in GetAllowedVehicleTypesAsSet(segmentId, nodeId, includeBusLanes)) { + foreach (ExtVehicleType vehicleType in GetAllowedVehicleTypesAsSet(segmentId, nodeId, busLaneMode)) { ret |= vehicleType; } return ret; @@ -53,8 +68,8 @@ internal ExtVehicleType GetAllowedVehicleTypes(ushort segmentId, ushort nodeId, /// /// [Obsolete] - internal HashSet GetAllowedVehicleTypesAsSet(ushort segmentId, ushort nodeId, bool includeBusLanes) { - HashSet ret = new HashSet(GetAllowedVehicleTypesAsDict(segmentId, nodeId, includeBusLanes).Values); + internal HashSet GetAllowedVehicleTypesAsSet(ushort segmentId, ushort nodeId, RestrictionMode busLaneMode) { + HashSet ret = new HashSet(GetAllowedVehicleTypesAsDict(segmentId, nodeId, busLaneMode).Values); return ret; } @@ -64,7 +79,7 @@ internal HashSet GetAllowedVehicleTypesAsSet(ushort segmentId, u /// /// /// - internal IDictionary GetAllowedVehicleTypesAsDict(ushort segmentId, ushort nodeId, bool includeBusLanes) { + internal IDictionary GetAllowedVehicleTypesAsDict(ushort segmentId, ushort nodeId, RestrictionMode busLaneMode) { IDictionary ret = new TinyDictionary(); NetManager netManager = Singleton.instance; @@ -85,7 +100,7 @@ internal IDictionary GetAllowedVehicleTypesAsDict(ushort s if (laneInfo.m_vehicleType != VehicleInfo.VehicleType.None) { ushort toNodeId = (laneInfo.m_finalDirection & dir2) != NetInfo.Direction.None ? netManager.m_segments.m_buffer[segmentId].m_endNode : netManager.m_segments.m_buffer[segmentId].m_startNode; if ((laneInfo.m_finalDirection & NetInfo.Direction.Both) == NetInfo.Direction.Both || toNodeId == nodeId) { - ExtVehicleType vehicleTypes = GetAllowedVehicleTypes(segmentId, segmentInfo, laneIndex, laneInfo, includeBusLanes); + ExtVehicleType vehicleTypes = GetAllowedVehicleTypes(segmentId, segmentInfo, laneIndex, laneInfo, busLaneMode); ret[(byte)laneIndex] = vehicleTypes; } } @@ -104,20 +119,20 @@ internal IDictionary GetAllowedVehicleTypesAsDict(ushort s /// /// /// - internal ExtVehicleType GetAllowedVehicleTypes(ushort segmentId, NetInfo segmentInfo, uint laneIndex, NetInfo.Lane laneInfo, bool includeBusLanes) { + internal ExtVehicleType GetAllowedVehicleTypes(ushort segmentId, NetInfo segmentInfo, uint laneIndex, NetInfo.Lane laneInfo, RestrictionMode busLaneMode) { ExtVehicleType?[] fastArray = Flags.laneAllowedVehicleTypesArray[segmentId]; if (fastArray != null && fastArray.Length > laneIndex && fastArray[laneIndex] != null) { return (ExtVehicleType)fastArray[laneIndex]; } - return GetDefaultAllowedVehicleTypes(segmentId, segmentInfo, laneIndex, laneInfo, includeBusLanes); + return GetDefaultAllowedVehicleTypes(segmentId, segmentInfo, laneIndex, laneInfo, busLaneMode); } internal bool HasSegmentRestrictions(ushort segmentId) { // TODO clean up restrictions (currently we do not check if restrictions are equal with the base type) bool ret = false; Services.NetService.IterateSegmentLanes(segmentId, delegate (uint laneId, ref NetLane lane, NetInfo.Lane laneInfo, ushort segId, ref NetSegment segment, byte laneIndex) { - ExtVehicleType defaultMask = GetDefaultAllowedVehicleTypes(laneInfo, false); - ExtVehicleType currentMask = GetAllowedVehicleTypes(segmentId, segment.Info, laneIndex, laneInfo, false); + ExtVehicleType defaultMask = GetDefaultAllowedVehicleTypes(laneInfo, RestrictionMode.Unrestricted); + ExtVehicleType currentMask = GetAllowedVehicleTypes(segmentId, segment.Info, laneIndex, laneInfo, RestrictionMode.Configured); if (defaultMask != currentMask) { ret = true; @@ -137,36 +152,44 @@ internal ExtVehicleType GetAllowedVehicleTypes(ushort segmentId, NetInfo segment /// /// /// - public ExtVehicleType GetDefaultAllowedVehicleTypes(ushort segmentId, NetInfo segmentInfo, uint laneIndex, NetInfo.Lane laneInfo, bool includeBusLanes) { + public ExtVehicleType GetDefaultAllowedVehicleTypes(ushort segmentId, NetInfo segmentInfo, uint laneIndex, NetInfo.Lane laneInfo, RestrictionMode busLaneMode) { // manage cached default vehicle types if (defaultVehicleTypeCache == null) { defaultVehicleTypeCache = new ExtVehicleType?[NetManager.MAX_SEGMENT_COUNT][][]; } - ExtVehicleType?[] cachedDefaultTypes = defaultVehicleTypeCache[segmentId] == null ? null : defaultVehicleTypeCache[segmentId][includeBusLanes ? 1 : 0]; + ExtVehicleType?[] cachedDefaultTypes = null; + int cacheIndex = (int)busLaneMode; + + if (defaultVehicleTypeCache[segmentId] != null) { + cachedDefaultTypes = defaultVehicleTypeCache[segmentId][cacheIndex]; + } + if (cachedDefaultTypes == null || cachedDefaultTypes.Length != segmentInfo.m_lanes.Length) { - defaultVehicleTypeCache[segmentId] = new ExtVehicleType?[2][]; + defaultVehicleTypeCache[segmentId] = new ExtVehicleType?[3][]; defaultVehicleTypeCache[segmentId][0] = new ExtVehicleType?[segmentInfo.m_lanes.Length]; defaultVehicleTypeCache[segmentId][1] = new ExtVehicleType?[segmentInfo.m_lanes.Length]; + defaultVehicleTypeCache[segmentId][2] = new ExtVehicleType?[segmentInfo.m_lanes.Length]; - cachedDefaultTypes = includeBusLanes ? defaultVehicleTypeCache[segmentId][1] : defaultVehicleTypeCache[segmentId][0]; + cachedDefaultTypes = defaultVehicleTypeCache[segmentId][cacheIndex]; } ExtVehicleType? defaultVehicleType = cachedDefaultTypes[laneIndex]; if (defaultVehicleType == null) { - defaultVehicleType = GetDefaultAllowedVehicleTypes(laneInfo, includeBusLanes); + defaultVehicleType = GetDefaultAllowedVehicleTypes(laneInfo, busLaneMode); cachedDefaultTypes[laneIndex] = defaultVehicleType; } return (ExtVehicleType)defaultVehicleType; } - public ExtVehicleType GetDefaultAllowedVehicleTypes(NetInfo.Lane laneInfo, bool includeBusLanes) { + public ExtVehicleType GetDefaultAllowedVehicleTypes(NetInfo.Lane laneInfo, RestrictionMode busLaneMode) { ExtVehicleType ret = ExtVehicleType.None; if ((laneInfo.m_vehicleType & VehicleInfo.VehicleType.Bicycle) != VehicleInfo.VehicleType.None) ret |= ExtVehicleType.Bicycle; if ((laneInfo.m_vehicleType & VehicleInfo.VehicleType.Tram) != VehicleInfo.VehicleType.None) ret |= ExtVehicleType.Tram; - if (includeBusLanes) { + if (busLaneMode == RestrictionMode.Restricted || + (busLaneMode == RestrictionMode.Configured && Options.banRegularTrafficOnBusLanes)) { if ((laneInfo.m_laneType & NetInfo.LaneType.TransportVehicle) != NetInfo.LaneType.None) ret |= ExtVehicleType.RoadPublicTransport | ExtVehicleType.Service | ExtVehicleType.Emergency; else if ((laneInfo.m_vehicleType & VehicleInfo.VehicleType.Car) != VehicleInfo.VehicleType.None) @@ -198,7 +221,7 @@ public ExtVehicleType GetDefaultAllowedVehicleTypes(NetInfo.Lane laneInfo, bool /// /// /// - internal ExtVehicleType GetDefaultAllowedVehicleTypes(uint laneId, bool includeBusLanes) { + internal ExtVehicleType GetDefaultAllowedVehicleTypes(uint laneId, RestrictionMode busLaneMode) { if (((NetLane.Flags)Singleton.instance.m_lanes.m_buffer[laneId].m_flags & NetLane.Flags.Created) == NetLane.Flags.None) return ExtVehicleType.None; ushort segmentId = Singleton.instance.m_lanes.m_buffer[laneId].m_segment; @@ -212,7 +235,7 @@ internal ExtVehicleType GetDefaultAllowedVehicleTypes(uint laneId, bool includeB while (laneIndex < numLanes && curLaneId != 0u) { NetInfo.Lane laneInfo = segmentInfo.m_lanes[laneIndex]; if (curLaneId == laneId) { - return GetDefaultAllowedVehicleTypes(segmentId, segmentInfo, laneIndex, laneInfo, includeBusLanes); + return GetDefaultAllowedVehicleTypes(segmentId, segmentInfo, laneIndex, laneInfo, busLaneMode); } curLaneId = Singleton.instance.m_lanes.m_buffer[curLaneId].m_nextLane; ++laneIndex; @@ -239,7 +262,7 @@ internal bool SetAllowedVehicleTypes(ushort segmentId, NetInfo segmentInfo, uint return false; } - allowedTypes &= GetBaseMask(segmentInfo.m_lanes[laneIndex], false); // ensure default base mask + allowedTypes &= GetBaseMask(segmentInfo.m_lanes[laneIndex], RestrictionMode.Configured); // ensure default base mask Flags.setLaneAllowedVehicleTypes(segmentId, laneIndex, laneId, allowedTypes); SubscribeToSegmentGeometry(segmentId); NotifyStartEndNode(segmentId); @@ -270,9 +293,9 @@ public void AddAllowedType(ushort segmentId, NetInfo segmentInfo, uint laneIndex return; } - ExtVehicleType allowedTypes = GetAllowedVehicleTypes(segmentId, segmentInfo, laneIndex, laneInfo, false); + ExtVehicleType allowedTypes = GetAllowedVehicleTypes(segmentId, segmentInfo, laneIndex, laneInfo, RestrictionMode.Configured); allowedTypes |= vehicleType; - allowedTypes &= GetBaseMask(segmentInfo.m_lanes[laneIndex], false); // ensure default base mask + allowedTypes &= GetBaseMask(segmentInfo.m_lanes[laneIndex], RestrictionMode.Configured); // ensure default base mask Flags.setLaneAllowedVehicleTypes(segmentId, laneIndex, laneId, allowedTypes); SubscribeToSegmentGeometry(segmentId); NotifyStartEndNode(segmentId); @@ -301,9 +324,9 @@ public void RemoveAllowedType(ushort segmentId, NetInfo segmentInfo, uint laneIn return; } - ExtVehicleType allowedTypes = GetAllowedVehicleTypes(segmentId, segmentInfo, laneIndex, laneInfo, false); + ExtVehicleType allowedTypes = GetAllowedVehicleTypes(segmentId, segmentInfo, laneIndex, laneInfo, RestrictionMode.Configured); allowedTypes &= ~vehicleType; - allowedTypes &= GetBaseMask(segmentInfo.m_lanes[laneIndex], false); // ensure default base mask + allowedTypes &= GetBaseMask(segmentInfo.m_lanes[laneIndex], RestrictionMode.Configured); // ensure default base mask Flags.setLaneAllowedVehicleTypes(segmentId, laneIndex, laneId, allowedTypes); SubscribeToSegmentGeometry(segmentId); NotifyStartEndNode(segmentId); @@ -325,7 +348,7 @@ public void ToggleAllowedType(ushort segmentId, NetInfo segmentInfo, uint laneIn /// /// /// - public ExtVehicleType GetBaseMask(NetInfo.Lane laneInfo, bool includeBusLanes) { + public ExtVehicleType GetBaseMask(NetInfo.Lane laneInfo, RestrictionMode includeBusLanes) { return GetDefaultAllowedVehicleTypes(laneInfo, includeBusLanes); } @@ -334,7 +357,7 @@ public ExtVehicleType GetBaseMask(NetInfo.Lane laneInfo, bool includeBusLanes) { /// /// /// - public ExtVehicleType GetBaseMask(uint laneId, bool includeBusLanes) { + public ExtVehicleType GetBaseMask(uint laneId, RestrictionMode includeBusLanes) { if (((NetLane.Flags)Singleton.instance.m_lanes.m_buffer[laneId].m_flags & NetLane.Flags.Created) == NetLane.Flags.None) return ExtVehicleType.None; ushort segmentId = Singleton.instance.m_lanes.m_buffer[laneId].m_segment; @@ -453,6 +476,10 @@ internal void ClearCache(ushort segmentId) { } } + internal void ClearCache() { + defaultVehicleTypeCache = null; + } + public void NotifyStartEndNode(ushort segmentId) { // notify observers of start node and end node (e.g. for separate traffic lights) ushort startNodeId = Singleton.instance.m_segments.m_buffer[segmentId].m_startNode; @@ -474,7 +501,7 @@ protected override void HandleValidSegment(SegmentGeometry geometry) { public override void OnLevelUnloading() { base.OnLevelUnloading(); - defaultVehicleTypeCache = null; + ClearCache(); } public bool LoadData(List data) { @@ -485,7 +512,7 @@ public bool LoadData(List data) { if (!Services.NetService.IsLaneValid(laneVehicleTypes.laneId)) continue; - ExtVehicleType baseMask = GetBaseMask(laneVehicleTypes.laneId, false); + ExtVehicleType baseMask = GetBaseMask(laneVehicleTypes.laneId, RestrictionMode.Configured); ExtVehicleType maskedType = laneVehicleTypes.vehicleTypes & baseMask; Log._Debug($"Loading lane vehicle restriction: lane {laneVehicleTypes.laneId} = {laneVehicleTypes.vehicleTypes}, masked = {maskedType}"); if (maskedType != baseMask) { diff --git a/TLM/TLM/Resources/lang.txt b/TLM/TLM/Resources/lang.txt index 4969a102..4ee477b1 100644 --- a/TLM/TLM/Resources/lang.txt +++ b/TLM/TLM/Resources/lang.txt @@ -169,4 +169,6 @@ Lock_main_menu_position Lock main menu position Recalculating_lane_routing Recalculating lane routing Please_wait Please wait Parking_restrictions Parking restrictions -Simulation Simulation \ No newline at end of file +Simulation Simulation +On_roads On roads +Ban_private_cars_and_trucks_on_bus_lanes Ban private cars and trucks on bus lanes \ No newline at end of file diff --git a/TLM/TLM/Resources/lang_de.txt b/TLM/TLM/Resources/lang_de.txt index 765cfaf4..ba50316d 100644 --- a/TLM/TLM/Resources/lang_de.txt +++ b/TLM/TLM/Resources/lang_de.txt @@ -168,4 +168,6 @@ Lock_main_menu_position Position des Hauptmenüs sperren Recalculating_lane_routing Berechne Routenführung neu Please_wait Bitte warten Parking_restrictions Parkverbote -Simulation Simulation \ No newline at end of file +Simulation Simulation +On_roads Auf Straßen +Ban_private_cars_and_trucks_on_bus_lanes Verbiete private Fahrzeuge und Lieferwagen auf Busspuren \ No newline at end of file diff --git a/TLM/TLM/Resources/lang_es.txt b/TLM/TLM/Resources/lang_es.txt index c2eb9097..f6e7c836 100644 --- a/TLM/TLM/Resources/lang_es.txt +++ b/TLM/TLM/Resources/lang_es.txt @@ -124,48 +124,50 @@ Unit_system Sistema de medida Metric Métrico Imperial Imperial Use_more_CPU_cores_for_route_calculation_if_available Usar más nucleos del procesador para el cálculo de rutas (si está disponible) -Activated_features Activated features -Junction_restrictions Junction restrictions -Prohibit_spawning_of_pocket_cars Prohibit spawning of pocket cars -Reset_stuck_cims_and_vehicles Reset stuck cims and vehicles -Default_speed_limits Default speed limits -Looking_for_a_parking_spot Looking for a parking spot -Driving_to_a_parking_spot Driving to a parking spot -Driving_to_another_parking_spot Driving to another parking spot -Entering_vehicle Entering vehicle -Walking_to_car Walking to car -Using_public_transport Using public transport -Walking Walking -Thinking_of_a_good_parking_spot Thinking of a good parking spot -Switch_view Switch view -Outgoing_demand Outgoing demand -Incoming_demand Incoming demand -Advanced_Vehicle_AI Advanced Vehicle AI -Heavy_trucks_prefer_outer_lanes_on_highways Heavy vehicles prefer outer lanes on highways -Parking_AI Parking AI -Enable_more_realistic_parking Enable more realistic parking -Reset_custom_speed_limits Reset custom speed limits -Reload_global_configuration Reload global configuration -Reset_global_configuration Reset global configuration +Activated_features Características activadas +Junction_restrictions Restricciones del cruce +Prohibit_spawning_of_pocket_cars Prohibir la creación de autos pequeños +Reset_stuck_cims_and_vehicles Restablecer cims y vehículos atascados +Default_speed_limits Límites de velocidad por defecto +Looking_for_a_parking_spot Buscando un estacionamiento +Driving_to_a_parking_spot Conduciendo a un estacionamiento +Driving_to_another_parking_spot Conduciendo a otro estacionamiento +Entering_vehicle Vehículo entrante +Walking_to_car Caminando al auto +Using_public_transport Usando transporte público +Walking Caminando +Thinking_of_a_good_parking_spot Pensando en un buen estacionamiento +Switch_view Cambiar vista +Outgoing_demand Demanda saliente +Incoming_demand Demanda entrante +Advanced_Vehicle_AI IA de vehículos avanzada +Heavy_trucks_prefer_outer_lanes_on_highways Camiones prefieren los carriles exteriores en las autopistas +Parking_AI IA de estacionamientos +Enable_more_realistic_parking Activar estacionamientos más realista +Reset_custom_speed_limits Restablecer límites de velocidad personalizados +Reload_global_configuration Recargar configuración global +Reset_global_configuration Restablecer configuración global General General -Gameplay Gameplay -Overlays Overlays -Realistic_speeds Realistic speeds -Evacuation_busses_may_ignore_traffic_rules Evacuation busses may ignore traffic rules -Evacuation_busses_may_only_be_used_to_reach_a_shelter Evacuation busses may only be used to reach a shelter -Vehicle_behavior Vehicle behavior -Policies_&_Restrictions Policies & Restrictions -At_junctions At junctions -In_case_of_emergency In case of emergency -Show_lane-wise_speed_limits Show lane-wise speed limits -Language Language -Game_language Game language -requires_game_restart requires game restart -Customizations_come_into_effect_instantaneously Customizations come into effect instantaneously -Options Options -Lock_main_menu_button_position Lock main menu button position -Lock_main_menu_position Lock main menu position -Recalculating_lane_routing Recalculating lane routing -Please_wait Please wait -Parking_restrictions Parking restrictions -Simulation Simulation \ No newline at end of file +Gameplay Jugabilidad +Overlays Capas de información +Realistic_speeds Velocidades realistas +Evacuation_busses_may_ignore_traffic_rules Los buses de evacuación pueden ignorar reglas de tránsito +Evacuation_busses_may_only_be_used_to_reach_a_shelter Los buses de evacuación sólo pueden usarse para llegar a un refugio +Vehicle_behavior Comportamiento vehícular +Policies_&_Restrictions Normas y restricciones +At_junctions En los cruces +In_case_of_emergency En caso de emergencia +Show_lane-wise_speed_limits Mostrar límite de velocidad en el carril +Language Idioma +Game_language Idioma del juego +requires_game_restart Requiere reiniciar el juego +Customizations_come_into_effect_instantaneously Los modificaciones tendrán efecto instantáneamente +Options Opciones +Lock_main_menu_button_position Bloquear la posición del menú principal +Lock_main_menu_position Bloquear posición del menú principal +Recalculating_lane_routing Recalculando la ruta del carril +Please_wait Espera por favor +Parking_restrictions Restricciones de los estacionamientos +Simulation Simulation +On_roads On roads +Ban_private_cars_and_trucks_on_bus_lanes Ban private cars and trucks on bus lanes \ No newline at end of file diff --git a/TLM/TLM/Resources/lang_fr.txt b/TLM/TLM/Resources/lang_fr.txt index 0d695663..8fd187ba 100644 --- a/TLM/TLM/Resources/lang_fr.txt +++ b/TLM/TLM/Resources/lang_fr.txt @@ -157,15 +157,17 @@ Vehicle_behavior Comportement des véhicules Policies_&_Restrictions Restrictions et politiques At_junctions Aux jonctions In_case_of_emergency En cas d'urgence -Show_lane-wise_speed_limits Show lane-wise speed limits -Language Language -Game_language Game language -requires_game_restart requires game restart -Customizations_come_into_effect_instantaneously Customizations come into effect instantaneously +Show_lane-wise_speed_limits Voir limites de vitesse par voie +Language Langue +Game_language Langue du jeu +requires_game_restart nécessite le redémarrage du jeu +Customizations_come_into_effect_instantaneously Les personnalisations prennent effet instantanément Options Options -Lock_main_menu_button_position Lock main menu button position -Lock_main_menu_position Lock main menu position -Recalculating_lane_routing Recalculating lane routing -Please_wait Please wait -Parking_restrictions Parking restrictions -Simulation Simulation \ No newline at end of file +Lock_main_menu_button_position Verrouiller la position du bouton du menu principal +Lock_main_menu_position Verrouiller la position du menu principal +Recalculating_lane_routing Recalcul en cours des routing des voies +Please_wait Merci de patienter +Parking_restrictions Restrictions de parking +Simulation Simulation +On_roads On roads +Ban_private_cars_and_trucks_on_bus_lanes Ban private cars and trucks on bus lanes \ No newline at end of file diff --git a/TLM/TLM/Resources/lang_it.txt b/TLM/TLM/Resources/lang_it.txt index c7712dee..f7c9ed99 100644 --- a/TLM/TLM/Resources/lang_it.txt +++ b/TLM/TLM/Resources/lang_it.txt @@ -168,4 +168,6 @@ Lock_main_menu_position Lock main menu position Recalculating_lane_routing Recalculating lane routing Please_wait Please wait Parking_restrictions Parking restrictions -Simulation Simulation \ No newline at end of file +Simulation Simulation +On_roads On roads +Ban_private_cars_and_trucks_on_bus_lanes Ban private cars and trucks on bus lanes \ No newline at end of file diff --git a/TLM/TLM/Resources/lang_ja.txt b/TLM/TLM/Resources/lang_ja.txt index 424b529f..3e7cb96d 100644 --- a/TLM/TLM/Resources/lang_ja.txt +++ b/TLM/TLM/Resources/lang_ja.txt @@ -169,4 +169,6 @@ Lock_main_menu_position Lock main menu position Recalculating_lane_routing Recalculating lane routing Please_wait Please wait Parking_restrictions Parking restrictions -Simulation Simulation \ No newline at end of file +Simulation Simulation +On_roads On roads +Ban_private_cars_and_trucks_on_bus_lanes Ban private cars and trucks on bus lanes \ No newline at end of file diff --git a/TLM/TLM/Resources/lang_kr.txt b/TLM/TLM/Resources/lang_kr.txt index d6d6e926..38a15d98 100644 --- a/TLM/TLM/Resources/lang_kr.txt +++ b/TLM/TLM/Resources/lang_kr.txt @@ -169,4 +169,6 @@ Lock_main_menu_position TMPE 모드매뉴 위치 잠금 Recalculating_lane_routing 차선 경로 재 계산하기 Please_wait 잠시만 기다려주십시오 Parking_restrictions 주차 제한 -Simulation 시뮬레이션 \ No newline at end of file +Simulation 시뮬레이션 +On_roads On roads +Ban_private_cars_and_trucks_on_bus_lanes Ban private cars and trucks on bus lanes \ No newline at end of file diff --git a/TLM/TLM/Resources/lang_nl.txt b/TLM/TLM/Resources/lang_nl.txt index aa46231d..848eab5c 100644 --- a/TLM/TLM/Resources/lang_nl.txt +++ b/TLM/TLM/Resources/lang_nl.txt @@ -168,4 +168,6 @@ Lock_main_menu_button_position Vergendel positie van hoofdmenuknop Lock_main_menu_position Vergrendel positie van hoofdmenu Recalculating_lane_routing Rijstrookroutering wordt herberekend Please_wait Even geduld graag -Parking_restrictions Parkeerbeperkingen \ No newline at end of file +Parking_restrictions Parkeerbeperkingen +On_roads On roads +Ban_private_cars_and_trucks_on_bus_lanes Ban private cars and trucks on bus lanes \ No newline at end of file diff --git a/TLM/TLM/Resources/lang_pl.txt b/TLM/TLM/Resources/lang_pl.txt index 2a225f76..fd52ede5 100644 --- a/TLM/TLM/Resources/lang_pl.txt +++ b/TLM/TLM/Resources/lang_pl.txt @@ -168,4 +168,6 @@ Lock_main_menu_position Zablokuj pozycjê menu g³ównego Recalculating_lane_routing Ponowne obliczanie tras Please_wait Proszê czekaæ Parking_restrictions Ograniczenia parkingowe -Simulation Simulation \ No newline at end of file +Simulation Simulation +On_roads On roads +Ban_private_cars_and_trucks_on_bus_lanes Ban private cars and trucks on bus lanes \ No newline at end of file diff --git a/TLM/TLM/Resources/lang_pt.txt b/TLM/TLM/Resources/lang_pt.txt index a1f3383a..62903b96 100644 --- a/TLM/TLM/Resources/lang_pt.txt +++ b/TLM/TLM/Resources/lang_pt.txt @@ -170,4 +170,6 @@ Please_wait Por favor, aguarde Parking_restrictions Restrições de estacionamento Please_wait Please wait Parking_restrictions Parking restrictions -Simulation Simulation \ No newline at end of file +Simulation Simulation +On_roads On roads +Ban_private_cars_and_trucks_on_bus_lanes Ban private cars and trucks on bus lanes \ No newline at end of file diff --git a/TLM/TLM/Resources/lang_ru.txt b/TLM/TLM/Resources/lang_ru.txt index b9c27a97..9bd8ff9d 100644 --- a/TLM/TLM/Resources/lang_ru.txt +++ b/TLM/TLM/Resources/lang_ru.txt @@ -169,4 +169,6 @@ Lock_main_menu_position Блокировка позиции главного м Recalculating_lane_routing Обновление маршрута Please_wait Подождите пожалуйста Parking_restrictions Ограничения парковки -Simulation Simulation \ No newline at end of file +Simulation Simulation +On_roads On roads +Ban_private_cars_and_trucks_on_bus_lanes Ban private cars and trucks on bus lanes \ No newline at end of file diff --git a/TLM/TLM/Resources/lang_template.txt b/TLM/TLM/Resources/lang_template.txt index 123304bc..0725a64e 100644 --- a/TLM/TLM/Resources/lang_template.txt +++ b/TLM/TLM/Resources/lang_template.txt @@ -168,4 +168,6 @@ Lock_main_menu_position Recalculating_lane_routing Please_wait Parking_restrictions -Simulation \ No newline at end of file +Simulation +On_roads +Ban_private_cars_and_trucks_on_bus_lanes \ No newline at end of file diff --git a/TLM/TLM/Resources/lang_zh-tw.txt b/TLM/TLM/Resources/lang_zh-tw.txt index 06e02016..0deeede5 100644 --- a/TLM/TLM/Resources/lang_zh-tw.txt +++ b/TLM/TLM/Resources/lang_zh-tw.txt @@ -169,4 +169,6 @@ Lock_main_menu_position 鎖定主選單的位置 Recalculating_lane_routing 重新規劃行駛路線 Please_wait 請稍候 Parking_restrictions 停車限制 -Simulation Simulation \ No newline at end of file +Simulation Simulation +On_roads On roads +Ban_private_cars_and_trucks_on_bus_lanes Ban private cars and trucks on bus lanes \ No newline at end of file diff --git a/TLM/TLM/Resources/lang_zh.txt b/TLM/TLM/Resources/lang_zh.txt index c372919c..ae7d0c7c 100644 --- a/TLM/TLM/Resources/lang_zh.txt +++ b/TLM/TLM/Resources/lang_zh.txt @@ -168,4 +168,6 @@ Lock_main_menu_position 主菜单位置 Recalculating_lane_routing 重新计算车道路线 Please_wait 请稍候 Parking_restrictions 道路边停车控制管理 -Simulation 模拟 \ No newline at end of file +Simulation 模拟 +On_roads On roads +Ban_private_cars_and_trucks_on_bus_lanes Ban private cars and trucks on bus lanes \ No newline at end of file diff --git a/TLM/TLM/State/GlobalConfig.cs b/TLM/TLM/State/GlobalConfig.cs index 2cfbb142..e6cede45 100644 --- a/TLM/TLM/State/GlobalConfig.cs +++ b/TLM/TLM/State/GlobalConfig.cs @@ -17,7 +17,7 @@ namespace TrafficManager.State { public class GlobalConfig { public const string FILENAME = "TMPE_GlobalConfig.xml"; public const string BACKUP_FILENAME = FILENAME + ".bak"; - private static int LATEST_VERSION = 8; + private static int LATEST_VERSION = 9; #if DEBUG private static uint lastModificationCheckFrame = 0; #endif @@ -81,6 +81,7 @@ internal static void OnLevelUnloading() { #if DEBUG public int PathFindDebugNodeId = 0; public int PathFindDebugStartSegmentId = 0; + public int PathFindDebugVehicleId = 0; public ExtVehicleType PathFindDebugExtVehicleType = ExtVehicleType.None; public ushort TTLDebugNodeId = 0; #endif @@ -185,12 +186,12 @@ internal static void OnLevelUnloading() { /// /// penalty for busses not driving on bus lanes /// - public float PublicTransportLanePenalty = 4f; + public float PublicTransportLanePenalty = 10f; /// /// reward for public transport staying on transport lane /// - public float PublicTransportLaneReward = 0.25f; + public float PublicTransportLaneReward = 0.1f; /// /// maximum penalty for heavy vehicles driving on an inner lane (in %) @@ -200,7 +201,7 @@ internal static void OnLevelUnloading() { /// /// Path cost multiplier for vehicle restrictions /// - public float VehicleRestrictionsPenalty = 50f; + public float VehicleRestrictionsPenalty = 100f; /// diff --git a/TLM/TLM/State/Options.cs b/TLM/TLM/State/Options.cs index 563d3dfd..35a96242 100644 --- a/TLM/TLM/State/Options.cs +++ b/TLM/TLM/State/Options.cs @@ -43,6 +43,7 @@ public class Options : MonoBehaviour { private static UICheckBox allowEnterBlockedJunctionsToggle = null; private static UICheckBox allowUTurnsToggle = null; private static UICheckBox allowLaneChangesWhileGoingStraightToggle = null; + private static UICheckBox banRegularTrafficOnBusLanesToggle = null; private static UICheckBox enableDespawningToggle = null; private static UICheckBox strongerRoadConditionEffectsToggle = null; @@ -100,6 +101,7 @@ public class Options : MonoBehaviour { public static bool allowEnterBlockedJunctions = false; public static bool allowUTurns = false; public static bool allowLaneChangesWhileGoingStraight = false; + public static bool banRegularTrafficOnBusLanes = false; public static bool advancedAI = false; public static bool highwayRules = false; #if DEBUG @@ -252,6 +254,9 @@ public static void makeSettings(UIHelperBase helper) { allowUTurnsToggle = atJunctionsGroup.AddCheckbox(Translation.GetString("Vehicles_may_do_u-turns_at_junctions"), allowUTurns, onAllowUTurnsChanged) as UICheckBox; allowLaneChangesWhileGoingStraightToggle = atJunctionsGroup.AddCheckbox(Translation.GetString("Vehicles_going_straight_may_change_lanes_at_junctions"), allowLaneChangesWhileGoingStraight, onAllowLaneChangesWhileGoingStraightChanged) as UICheckBox; + var onRoadsGroup = panelHelper.AddGroup(Translation.GetString("On_roads")); + banRegularTrafficOnBusLanesToggle = onRoadsGroup.AddCheckbox(Translation.GetString("Ban_private_cars_and_trucks_on_bus_lanes"), banRegularTrafficOnBusLanes, onBanRegularTrafficOnBusLanesChanged) as UICheckBox; + if (SteamHelper.IsDLCOwned(SteamHelper.DLC.NaturalDisastersDLC)) { var inCaseOfEmergencyGroup = panelHelper.AddGroup(Translation.GetString("In_case_of_emergency")); evacBussesMayIgnoreRulesToggle = inCaseOfEmergencyGroup.AddCheckbox(Translation.GetString("Evacuation_busses_may_ignore_traffic_rules"), evacBussesMayIgnoreRules, onEvacBussesMayIgnoreRulesChanged) as UICheckBox; @@ -659,6 +664,16 @@ private static void onAllowLaneChangesWhileGoingStraightChanged(bool newValue) { allowLaneChangesWhileGoingStraight = newValue; } + private static void onBanRegularTrafficOnBusLanesChanged(bool newValue) { + if (!checkGameLoaded()) + return; + + Log._Debug($"banRegularTrafficOnBusLanes changed to {newValue}"); + banRegularTrafficOnBusLanes = newValue; + VehicleRestrictionsManager.Instance.ClearCache(); + UIBase.GetTrafficManagerTool(false)?.InitializeSubTools(); + } + private static void onStrongerRoadConditionEffectsChanged(bool newStrongerRoadConditionEffects) { if (!checkGameLoaded()) return; @@ -907,40 +922,61 @@ public static void setAllowLaneChangesWhileGoingStraight(bool value) { allowLaneChangesWhileGoingStraightToggle.isChecked = value; } + public static void setBanRegularTrafficOnBusLanes(bool value) { + banRegularTrafficOnBusLanes = value; + if (banRegularTrafficOnBusLanesToggle != null) + banRegularTrafficOnBusLanesToggle.isChecked = value; + + VehicleRestrictionsManager.Instance.ClearCache(); + UIBase.GetTrafficManagerTool(false)?.InitializeSubTools(); + } + public static void setPrioritySignsOverlay(bool newPrioritySignsOverlay) { prioritySignsOverlay = newPrioritySignsOverlay; if (prioritySignsOverlayToggle != null) prioritySignsOverlayToggle.isChecked = newPrioritySignsOverlay; + + UIBase.GetTrafficManagerTool(false)?.InitializeSubTools(); } public static void setTimedLightsOverlay(bool newTimedLightsOverlay) { timedLightsOverlay = newTimedLightsOverlay; if (timedLightsOverlayToggle != null) timedLightsOverlayToggle.isChecked = newTimedLightsOverlay; + + UIBase.GetTrafficManagerTool(false)?.InitializeSubTools(); } public static void setSpeedLimitsOverlay(bool newSpeedLimitsOverlay) { speedLimitsOverlay = newSpeedLimitsOverlay; if (speedLimitsOverlayToggle != null) speedLimitsOverlayToggle.isChecked = newSpeedLimitsOverlay; + + UIBase.GetTrafficManagerTool(false)?.InitializeSubTools(); } public static void setVehicleRestrictionsOverlay(bool newVehicleRestrictionsOverlay) { vehicleRestrictionsOverlay = newVehicleRestrictionsOverlay; if (vehicleRestrictionsOverlayToggle != null) vehicleRestrictionsOverlayToggle.isChecked = newVehicleRestrictionsOverlay; + + UIBase.GetTrafficManagerTool(false)?.InitializeSubTools(); } public static void setParkingRestrictionsOverlay(bool newParkingRestrictionsOverlay) { parkingRestrictionsOverlay = newParkingRestrictionsOverlay; if (parkingRestrictionsOverlayToggle != null) parkingRestrictionsOverlayToggle.isChecked = newParkingRestrictionsOverlay; + + UIBase.GetTrafficManagerTool(false)?.InitializeSubTools(); } public static void setJunctionRestrictionsOverlay(bool newValue) { junctionRestrictionsOverlay = newValue; if (junctionRestrictionsOverlayToggle != null) junctionRestrictionsOverlayToggle.isChecked = newValue; + + UIBase.GetTrafficManagerTool(false)?.InitializeSubTools(); } public static void setConnectedLanesOverlay(bool newValue) { @@ -953,6 +989,8 @@ public static void setNodesOverlay(bool newNodesOverlay) { nodesOverlay = newNodesOverlay; if (nodesOverlayToggle != null) nodesOverlayToggle.isChecked = newNodesOverlay; + + UIBase.GetTrafficManagerTool(false)?.InitializeSubTools(); } public static void setVehicleOverlay(bool newVal) { diff --git a/TLM/TLM/TrafficLight/CustomSegmentLights.cs b/TLM/TLM/TrafficLight/CustomSegmentLights.cs index fe9a4380..a8702633 100644 --- a/TLM/TLM/TrafficLight/CustomSegmentLights.cs +++ b/TLM/TLM/TrafficLight/CustomSegmentLights.cs @@ -12,6 +12,7 @@ using System.Linq; using TrafficManager.Util; using CSUtil.Commons; +using static TrafficManager.Manager.VehicleRestrictionsManager; namespace TrafficManager.TrafficLight { /// @@ -462,8 +463,8 @@ internal void housekeeping(bool mayDelete, bool calculateAutoPedLight, RoadBaseA ushort nodeId = NodeId; HashSet setupLights = new HashSet(); // TODO improve - IDictionary allAllowedTypes = VehicleRestrictionsManager.Instance.GetAllowedVehicleTypesAsDict(SegmentId, nodeId, true); // TODO improve - ExtVehicleType allAllowedMask = VehicleRestrictionsManager.Instance.GetAllowedVehicleTypes(SegmentId, nodeId, true); + IDictionary allAllowedTypes = VehicleRestrictionsManager.Instance.GetAllowedVehicleTypesAsDict(SegmentId, nodeId, RestrictionMode.Restricted); // TODO improve + ExtVehicleType allAllowedMask = VehicleRestrictionsManager.Instance.GetAllowedVehicleTypes(SegmentId, nodeId, RestrictionMode.Restricted); SeparateVehicleTypes = ExtVehicleType.None; #if DEBUGHK Log._Debug($"CustomSegmentLights: housekeeping @ seg. {segmentId}, node {nodeId}, allAllowedTypes={string.Join(", ", allAllowedTypes.Select(x => x.ToString()).ToArray())}"); diff --git a/TLM/TLM/TrafficManagerMod.cs b/TLM/TLM/TrafficManagerMod.cs index 2193ba9d..3b9c0f88 100644 --- a/TLM/TLM/TrafficManagerMod.cs +++ b/TLM/TLM/TrafficManagerMod.cs @@ -6,7 +6,7 @@ namespace TrafficManager { public class TrafficManagerMod : IUserMod { - public static readonly string Version = "1.9.3"; + public static readonly string Version = "1.9.4"; public static readonly uint GameVersion = 163702032u; public static readonly uint GameVersionA = 1u; diff --git a/TLM/TLM/UI/SubTools/VehicleRestrictionsTool.cs b/TLM/TLM/UI/SubTools/VehicleRestrictionsTool.cs index b7c3057b..b7fe22e6 100644 --- a/TLM/TLM/UI/SubTools/VehicleRestrictionsTool.cs +++ b/TLM/TLM/UI/SubTools/VehicleRestrictionsTool.cs @@ -12,6 +12,7 @@ using TrafficManager.TrafficLight; using TrafficManager.Util; using UnityEngine; +using static TrafficManager.Manager.VehicleRestrictionsManager; using static TrafficManager.UI.TrafficManagerTool; using static TrafficManager.Util.SegmentLaneTraverser; @@ -168,12 +169,12 @@ private void _guiVehicleRestrictionsWindow(int num) { byte laneIndex = laneData.laneIndex; NetInfo.Lane laneInfo = selectedSegmentInfo.m_lanes[laneIndex]; - ExtVehicleType baseMask = VehicleRestrictionsManager.Instance.GetBaseMask(laneInfo, false); + ExtVehicleType baseMask = VehicleRestrictionsManager.Instance.GetBaseMask(laneInfo, RestrictionMode.Configured); if (baseMask == ExtVehicleType.None) continue; - ExtVehicleType allowedTypes = VehicleRestrictionsManager.Instance.GetAllowedVehicleTypes(SelectedSegmentId, selectedSegmentInfo, laneIndex, laneInfo, false); + ExtVehicleType allowedTypes = VehicleRestrictionsManager.Instance.GetAllowedVehicleTypes(SelectedSegmentId, selectedSegmentInfo, laneIndex, laneInfo, RestrictionMode.Configured); allowedTypes = ~(allowedTypes & VehicleRestrictionsManager.EXT_VEHICLE_TYPES) & baseMask; VehicleRestrictionsManager.Instance.SetAllowedVehicleTypes(SelectedSegmentId, selectedSegmentInfo, laneIndex, laneInfo, laneId, allowedTypes); } @@ -191,7 +192,7 @@ private void _guiVehicleRestrictionsWindow(int num) { byte laneIndex = laneData.laneIndex; NetInfo.Lane laneInfo = selectedSegmentInfo.m_lanes[laneIndex]; - ExtVehicleType baseMask = VehicleRestrictionsManager.Instance.GetBaseMask(laneInfo, false); + ExtVehicleType baseMask = VehicleRestrictionsManager.Instance.GetBaseMask(laneInfo, RestrictionMode.Configured); if (baseMask == ExtVehicleType.None) continue; @@ -211,7 +212,7 @@ private void _guiVehicleRestrictionsWindow(int num) { byte laneIndex = laneData.laneIndex; NetInfo.Lane laneInfo = selectedSegmentInfo.m_lanes[laneIndex]; - ExtVehicleType baseMask = VehicleRestrictionsManager.Instance.GetBaseMask(laneInfo, false); + ExtVehicleType baseMask = VehicleRestrictionsManager.Instance.GetBaseMask(laneInfo, RestrictionMode.Configured); if (baseMask == ExtVehicleType.None) continue; @@ -256,14 +257,14 @@ private void ApplyRestrictionsToAllSegments(int? sortedLaneIndex=null) { byte laneIndex = data.curLanePos.laneIndex; NetInfo.Lane laneInfo = segmentInfo.m_lanes[laneIndex]; - ExtVehicleType baseMask = VehicleRestrictionsManager.Instance.GetBaseMask(laneInfo, false); + ExtVehicleType baseMask = VehicleRestrictionsManager.Instance.GetBaseMask(laneInfo, RestrictionMode.Configured); if (baseMask == ExtVehicleType.None) { return true; } // apply restrictions of selected segment & lane ExtVehicleType mask = ~VehicleRestrictionsManager.EXT_VEHICLE_TYPES & baseMask; // ban all possible controllable vehicles - mask |= VehicleRestrictionsManager.EXT_VEHICLE_TYPES & VehicleRestrictionsManager.Instance.GetAllowedVehicleTypes(SelectedSegmentId, selectedSegmentInfo, selectedLaneIndex, selectedLaneInfo, false); // allow all enabled and controllable vehicles + mask |= VehicleRestrictionsManager.EXT_VEHICLE_TYPES & VehicleRestrictionsManager.Instance.GetAllowedVehicleTypes(SelectedSegmentId, selectedSegmentInfo, selectedLaneIndex, selectedLaneInfo, RestrictionMode.Configured); // allow all enabled and controllable vehicles VehicleRestrictionsManager.Instance.SetAllowedVehicleTypes(segmentId, segmentInfo, laneIndex, laneInfo, laneId, mask); @@ -340,7 +341,7 @@ private bool drawVehicleRestrictionHandles(ushort segmentId, ref NetSegment segm continue; } - ExtVehicleType allowedTypes = VehicleRestrictionsManager.Instance.GetAllowedVehicleTypes(segmentId, segmentInfo, laneIndex, laneInfo, false); + ExtVehicleType allowedTypes = VehicleRestrictionsManager.Instance.GetAllowedVehicleTypes(segmentId, segmentInfo, laneIndex, laneInfo, RestrictionMode.Configured); uint y = 0; #if DEBUGx diff --git a/TLM/TLM/UI/TrafficManagerTool.cs b/TLM/TLM/UI/TrafficManagerTool.cs index 77a051fd..8fb7b517 100644 --- a/TLM/TLM/UI/TrafficManagerTool.cs +++ b/TLM/TLM/UI/TrafficManagerTool.cs @@ -20,6 +20,8 @@ using TrafficManager.Util; using TrafficManager.UI.MainMenu; using CSUtil.Commons; +using static TrafficManager.Manager.TrafficMeasurementManager; +using static TrafficManager.Manager.VehicleRestrictionsManager; namespace TrafficManager.UI { [UsedImplicitly] @@ -632,7 +634,7 @@ private void _guiLanes(ushort segmentId, ref NetSegment segment, ref NetInfo seg }*/ TrafficMeasurementManager.LaneTrafficData[] laneTrafficData; - bool laneTrafficDataLoaded = TrafficMeasurementManager.Instance.GetTrafficData(segmentId, segmentInfo, out laneTrafficData); + bool laneTrafficDataLoaded = TrafficMeasurementManager.Instance.GetLaneTrafficData(segmentId, segmentInfo, out laneTrafficData); uint curLaneId = segment.m_lanes; String labelStr = ""; @@ -642,22 +644,20 @@ private void _guiLanes(ushort segmentId, ref NetSegment segment, ref NetInfo seg NetInfo.Lane laneInfo = segmentInfo.m_lanes[i]; - TrafficMeasurementManager.SegmentDirTrafficData dirTrafficData; - bool dirTrafficDataLoaded = TrafficMeasurementManager.Instance.GetTrafficData(segmentId, laneInfo.m_finalDirection, out dirTrafficData); + uint pfTrafficBuf = TrafficMeasurementManager.Instance.segmentDirTrafficData[TrafficMeasurementManager.Instance.GetDirIndex(segmentId, laneInfo.m_finalDirection)].totalPathFindTrafficBuffer; + //TrafficMeasurementManager.Instance.GetTrafficData(segmentId, laneInfo.m_finalDirection, out dirTrafficData); //int dirIndex = laneInfo.m_finalDirection == NetInfo.Direction.Backward ? 1 : 0; labelStr += "Lane idx " + i + ", id " + curLaneId; #if DEBUG - labelStr += ", inner: " + RoutingManager.Instance.CalcInnerLaneSimilarIndex(segmentId, i) + ", outer: " + RoutingManager.Instance.CalcOuterLaneSimilarIndex(segmentId, i) + ", flags: " + ((NetLane.Flags)Singleton.instance.m_lanes.m_buffer[curLaneId].m_flags).ToString() + ", limit: " + SpeedLimitManager.Instance.GetCustomSpeedLimit(curLaneId) + " km/h, restr: " + VehicleRestrictionsManager.Instance.GetAllowedVehicleTypes(segmentId, segmentInfo, (uint)i, laneInfo, false) + ", dir: " + laneInfo.m_direction + ", final: " + laneInfo.m_finalDirection + ", pos: " + String.Format("{0:0.##}", laneInfo.m_position) + ", sim. idx: " + laneInfo.m_similarLaneIndex + " for " + laneInfo.m_vehicleType + "/" + laneInfo.m_laneType; + labelStr += ", inner: " + RoutingManager.Instance.CalcInnerLaneSimilarIndex(segmentId, i) + ", outer: " + RoutingManager.Instance.CalcOuterLaneSimilarIndex(segmentId, i) + ", flags: " + ((NetLane.Flags)Singleton.instance.m_lanes.m_buffer[curLaneId].m_flags).ToString() + ", limit: " + SpeedLimitManager.Instance.GetCustomSpeedLimit(curLaneId) + " km/h, restr: " + VehicleRestrictionsManager.Instance.GetAllowedVehicleTypes(segmentId, segmentInfo, (uint)i, laneInfo, RestrictionMode.Configured) + ", dir: " + laneInfo.m_direction + ", final: " + laneInfo.m_finalDirection + ", pos: " + String.Format("{0:0.##}", laneInfo.m_position) + ", sim. idx: " + laneInfo.m_similarLaneIndex + " for " + laneInfo.m_vehicleType + "/" + laneInfo.m_laneType; #endif if (laneTrafficDataLoaded) { labelStr += ", avg. speed: " + (laneTrafficData[i].meanSpeed / 100) + "%"; #if DEBUG labelStr += ", buf: " + laneTrafficData[i].trafficBuffer + ", acc: " + laneTrafficData[i].accumulatedSpeeds; - if (dirTrafficDataLoaded) { - labelStr += ", pfBuf: " + laneTrafficData[i].pathFindTrafficBuffer + "/" + laneTrafficData[i].lastPathFindTrafficBuffer + ", (" + (dirTrafficData.totalPathFindTrafficBuffer > 0 ? "" + ((laneTrafficData[i].lastPathFindTrafficBuffer * 100u) / dirTrafficData.totalPathFindTrafficBuffer) : "n/a") + " %)"; - } + labelStr += ", pfBuf: " + laneTrafficData[i].pathFindTrafficBuffer + "/" + laneTrafficData[i].lastPathFindTrafficBuffer + ", (" + (pfTrafficBuf > 0 ? "" + ((laneTrafficData[i].lastPathFindTrafficBuffer * 100u) / pfTrafficBuf) : "n/a") + " %)"; #endif #if MEASUREDENSITY if (dirTrafficDataLoaded) { @@ -686,6 +686,8 @@ private void _guiLanes(ushort segmentId, ref NetSegment segment, ref NetInfo seg /// Displays segment ids over segments /// private void _guiSegments() { + TrafficMeasurementManager trafficMeasurementManager = TrafficMeasurementManager.Instance; + GUIStyle _counterStyle = new GUIStyle(); SegmentEndManager endMan = SegmentEndManager.Instance; Array16 segments = Singleton.instance.m_segments; @@ -741,22 +743,22 @@ private void _guiSegments() { labelStr += "\nTraffic: " + segments.m_buffer[i].m_trafficDensity + " %"; #if DEBUG - TrafficMeasurementManager.SegmentDirTrafficData forwardTrafficData; - TrafficMeasurementManager.SegmentDirTrafficData backwardTrafficData; - if (TrafficMeasurementManager.Instance.GetTrafficData((ushort)i, NetInfo.Direction.Forward, out forwardTrafficData) && - TrafficMeasurementManager.Instance.GetTrafficData((ushort)i, NetInfo.Direction.Backward, out backwardTrafficData)) { - float fwdCongestionRatio = forwardTrafficData.numCongestionMeasurements > 0 ? ((uint)forwardTrafficData.numCongested * 100u) / (uint)forwardTrafficData.numCongestionMeasurements : 0; // now in % - float backCongestionRatio = backwardTrafficData.numCongestionMeasurements > 0 ? ((uint)backwardTrafficData.numCongested * 100u) / (uint)backwardTrafficData.numCongestionMeasurements : 0; // now in % - - labelStr += "\nmin speeds: "; - labelStr += " " + (forwardTrafficData.minSpeed / 100) + "%/" + (backwardTrafficData.minSpeed / 100) + "%"; - labelStr += ", mean speeds: "; - labelStr += " " + (forwardTrafficData.meanSpeed / 100) + "%/" + (backwardTrafficData.meanSpeed / 100) + "%"; - labelStr += "\npf bufs: "; - labelStr += " " + (forwardTrafficData.totalPathFindTrafficBuffer) + "/" + (backwardTrafficData.totalPathFindTrafficBuffer); - labelStr += ", cong: "; - labelStr += " " + fwdCongestionRatio + "% (" + forwardTrafficData.numCongested + "/" + forwardTrafficData.numCongestionMeasurements + ")/" + backCongestionRatio + "% (" + backwardTrafficData.numCongested + "/" + backwardTrafficData.numCongestionMeasurements + ")"; - } + + int fwdSegIndex = trafficMeasurementManager.GetDirIndex((ushort)i, NetInfo.Direction.Forward); + int backSegIndex = trafficMeasurementManager.GetDirIndex((ushort)i, NetInfo.Direction.Backward); + + + float fwdCongestionRatio = trafficMeasurementManager.segmentDirTrafficData[fwdSegIndex].numCongestionMeasurements > 0 ? ((uint)trafficMeasurementManager.segmentDirTrafficData[fwdSegIndex].numCongested * 100u) / (uint)trafficMeasurementManager.segmentDirTrafficData[fwdSegIndex].numCongestionMeasurements : 0; // now in % + float backCongestionRatio = trafficMeasurementManager.segmentDirTrafficData[backSegIndex].numCongestionMeasurements > 0 ? ((uint)trafficMeasurementManager.segmentDirTrafficData[backSegIndex].numCongested * 100u) / (uint)trafficMeasurementManager.segmentDirTrafficData[backSegIndex].numCongestionMeasurements : 0; // now in % + + labelStr += "\nmin speeds: "; + labelStr += " " + (trafficMeasurementManager.segmentDirTrafficData[fwdSegIndex].minSpeed / 100) + "%/" + (trafficMeasurementManager.segmentDirTrafficData[backSegIndex].minSpeed / 100) + "%"; + labelStr += ", mean speeds: "; + labelStr += " " + (trafficMeasurementManager.segmentDirTrafficData[fwdSegIndex].meanSpeed / 100) + "%/" + (trafficMeasurementManager.segmentDirTrafficData[backSegIndex].meanSpeed / 100) + "%"; + labelStr += "\npf bufs: "; + labelStr += " " + (trafficMeasurementManager.segmentDirTrafficData[fwdSegIndex].totalPathFindTrafficBuffer) + "/" + (trafficMeasurementManager.segmentDirTrafficData[backSegIndex].totalPathFindTrafficBuffer); + labelStr += ", cong: "; + labelStr += " " + fwdCongestionRatio + "% (" + trafficMeasurementManager.segmentDirTrafficData[fwdSegIndex].numCongested + "/" + trafficMeasurementManager.segmentDirTrafficData[fwdSegIndex].numCongestionMeasurements + ")/" + backCongestionRatio + "% (" + trafficMeasurementManager.segmentDirTrafficData[backSegIndex].numCongested + "/" + trafficMeasurementManager.segmentDirTrafficData[backSegIndex].numCongestionMeasurements + ")"; labelStr += "\nstart: " + segments.m_buffer[i].m_startNode + ", end: " + segments.m_buffer[i].m_endNode; #endif