public static void housekeeping() { try { // delete invalid segments List <ushort> segmentIdsToDelete = new List <ushort>(); foreach (KeyValuePair <ushort, TrafficSegment> e in PrioritySegments) { var segmentId = e.Key; if (segmentId <= 0) { segmentIdsToDelete.Add(segmentId); continue; } NetSegment segment = Singleton <NetManager> .instance.m_segments.m_buffer[segmentId]; if (segment.m_flags == NetSegment.Flags.None || (!priorityNodes.Contains(segment.m_startNode) && !priorityNodes.Contains(segment.m_endNode))) { segmentIdsToDelete.Add(segmentId); } } foreach (var sId in segmentIdsToDelete) { Log.Warning("Housekeeping: Deleting segment " + sId); PrioritySegments.Remove(sId); TrafficLightsManual.RemoveSegmentLight(sId); } // delete invalid nodes List <ushort> nodeIdsToDelete = new List <ushort>(); foreach (ushort nodeId in priorityNodes) { NodeValidityState nodeState = NodeValidityState.Valid; if (!isValidPriorityNode(nodeId, out nodeState)) { if (nodeState != NodeValidityState.SimWithoutLight) { nodeIdsToDelete.Add(nodeId); } switch (nodeState) { case NodeValidityState.SimWithoutLight: Log.Warning("Housekeeping: Re-adding traffic light at node " + nodeId); Singleton <NetManager> .instance.m_nodes.m_buffer[nodeId].m_flags |= NetNode.Flags.TrafficLights; break; case NodeValidityState.Unused: // delete traffic light simulation Log.Warning("Housekeeping: RemoveNodeFromSimulation " + nodeId); RemoveNodeFromSimulation(nodeId); break; default: break; } } } foreach (var nId in nodeIdsToDelete) { Log.Warning("Housekeeping: Deleting node " + nId); RemovePrioritySegments(nId); } // add newly created segments to timed traffic lights foreach (KeyValuePair <ushort, TrafficLightsTimed> e in TrafficLightsTimed.TimedScripts) { TrafficLightsTimed timedLights = e.Value; ushort nodeId = e.Key; timedLights.handleNewSegments(); } } catch (Exception e) { Log.Warning($"Housekeeping failed: {e.Message}"); } }
private static bool isValidPriorityNode(ushort nodeId, out NodeValidityState nodeState) { nodeState = NodeValidityState.Valid; if (nodeId <= 0) { nodeState = NodeValidityState.Invalid; Log.Warning($"Housekeeping: Node {nodeId} is invalid!"); return false; } NetManager netManager = Singleton<NetManager>.instance; if ((netManager.m_nodes.m_buffer[nodeId].m_flags & NetNode.Flags.Created) == NetNode.Flags.None) { nodeState = NodeValidityState.Unused; Log.Warning($"Housekeeping: Node {nodeId} is unused!"); return false; // node is unused } bool hasTrafficLight = (netManager.m_nodes.m_buffer[nodeId].m_flags & NetNode.Flags.TrafficLights) != NetNode.Flags.None; var nodeSim = TrafficLightSimulation.GetNodeSimulation(nodeId); if (nodeSim != null) { if (! Flags.mayHaveTrafficLight(nodeId)) { nodeState = NodeValidityState.IllegalSim; Log.Warning($"Housekeeping: Node {nodeId} has traffic light simulation but must not have a traffic light!"); return false; } if (!hasTrafficLight) { // traffic light simulation is active but node does not have a traffic light nodeState = NodeValidityState.SimWithoutLight; Log.Warning($"Housekeeping: Node {nodeId} has traffic light simulation but no traffic light!"); return false; } else { // check if all timed step segments are valid if (nodeSim.IsTimedLightActive()) { TimedTrafficLights timedLight = nodeSim.TimedLight; if (timedLight == null || timedLight.Steps.Count <= 0) { Log.Warning("Housekeeping: Timed light is null or no steps for node {nodeId}!"); TrafficLightSimulation.RemoveNodeFromSimulation(nodeId, false); return false; } /*foreach (var segmentId in timedLight.Steps[0].segmentIds) { if (! IsPrioritySegment(nodeId, segmentId)) { Log.Warning("Housekeeping: Timed light - Priority segment has gone away!"); RemoveNodeFromSimulation(nodeId); return false; } }*/ } return true; } } else { byte numSegmentsWithSigns = 0; for (var s = 0; s < 8; s++) { var segmentId = netManager.m_nodes.m_buffer[nodeId].GetSegment(s); if (segmentId <= 0) continue; if (netManager.m_segments.m_buffer[segmentId].m_startNode != nodeId && netManager.m_segments.m_buffer[segmentId].m_endNode != nodeId) continue; SegmentEnd prioritySegment = GetPrioritySegment(nodeId, segmentId); if (prioritySegment == null) { continue; } // if node is a traffic light, it must not have priority signs if (hasTrafficLight && prioritySegment.Type != SegmentEnd.PriorityType.None) { Log.Warning($"Housekeeping: Node {nodeId}, Segment {segmentId} is a priority sign but node has a traffic light!"); prioritySegment.Type = SegmentEnd.PriorityType.None; } // if a priority sign is set, everything is ok if (prioritySegment.Type != SegmentEnd.PriorityType.None) { ++numSegmentsWithSigns; } } if (numSegmentsWithSigns > 0) { // add priority segments for newly created segments numSegmentsWithSigns += AddPriorityNode(nodeId); } bool ok = numSegmentsWithSigns >= 2; if (!ok) { Log.Warning($"Housekeeping: Node {nodeId} does not have valid priority segments!"); nodeState = NodeValidityState.NoValidSegments; } return ok; } }
private static bool isValidPriorityNode(ushort nodeId, out NodeValidityState nodeState) { nodeState = NodeValidityState.Valid; if (nodeId <= 0) { nodeState = NodeValidityState.Invalid; return(false); } var node = Singleton <NetManager> .instance.m_nodes.m_buffer[nodeId]; if (node.m_flags == NetNode.Flags.None) { nodeState = NodeValidityState.Unused; return(false); // node is unused } var nodeSim = GetNodeSimulation(nodeId); if (nodeSim != null) { if ((node.m_flags & NetNode.Flags.TrafficLights) == NetNode.Flags.None) { // traffic light simulation is active but node does not have a traffic light nodeState = NodeValidityState.SimWithoutLight; return(false); } else { // check if all timed step segments are valid if (nodeSim.FlagTimedTrafficLights && nodeSim.TimedTrafficLightsActive) { TrafficLightsTimed timedLight = TrafficLightsTimed.GetTimedLight(nodeId); if (timedLight == null || timedLight.Steps.Count <= 0) { Log.Warning("Housekeeping: Timed light is null or no steps!"); RemoveNodeFromSimulation(nodeId); return(false); } /*foreach (var segmentId in timedLight.Steps[0].segmentIds) { * if (! IsPrioritySegment(nodeId, segmentId)) { * Log.Warning("Housekeeping: Timed light - Priority segment has gone away!"); * RemoveNodeFromSimulation(nodeId); * return false; * } * }*/ } return(true); } } else { bool ok = false; for (var s = 0; s < 8; s++) { var segmentId = node.GetSegment(s); if (segmentId <= 0) { continue; } NetSegment segment = Singleton <NetManager> .instance.m_segments.m_buffer[segmentId]; if (segment.m_startNode != nodeId && segment.m_endNode != nodeId) { continue; } PrioritySegment prioritySegment = GetPrioritySegment(nodeId, segmentId); if (prioritySegment == null) { continue; } // if node is a traffic light, it must not have priority signs if ((node.m_flags & NetNode.Flags.TrafficLights) != NetNode.Flags.None) { prioritySegment.Type = PrioritySegment.PriorityType.None; } // if a priority sign is set, everything is ok if (prioritySegment.Type != PrioritySegment.PriorityType.None) { ok = true; break; } } if (!ok) { nodeState = NodeValidityState.NoValidSegments; } return(ok); } }