public UndoMod() { ActionQueueItem.exceptionHandler = (a, e) => { InvalidateAll(); return(false); }; Queue = new ActionQueue(ModInfo.sa_queueCapacity); WrappersDictionary = new WrappersDictionary(); WrappedBuilding.dictionary = WrappersDictionary; }
public MakeConnections(HashSet <ConnectionPoint> borderNodes, FastList <ushort> createdNodes, WrappersDictionary dictionary, ActionGroup actionGroup) { if (!UIWindow.instance.m_connectRoadsCheckBox.isChecked) { return; } if (borderNodes == null) { return; } _networkDictionary = dictionary; _actionGroup = actionGroup; HashSet <ushort> filteredCreatedNodes = FilterCreatedNodes(createdNodes); // (Border nodes are already filtered) HashSet <ConnectionPoint> usedPoints = new HashSet <ConnectionPoint>(); HashSet <ushort> usedNodes = new HashSet <ushort>(); List <ConnectionPair> connectionPairs = new List <ConnectionPair>(); /* For each pair of nodes we make an attempt to connect them */ foreach (ushort node1 in filteredCreatedNodes) { foreach (ConnectionPoint cpoint in borderNodes) { if (RankConnection(node1, cpoint, out int rank)) { connectionPairs.Add(new ConnectionPair(node1, cpoint, rank)); } } } connectionPairs.Sort((a, b) => - a.rank.CompareTo(b.rank)); foreach (var pair in connectionPairs) { if (!usedPoints.Contains(pair.point2) && !usedNodes.Contains(pair.node1)) { ushort segment1 = NetUtil.GetFirstSegment(NetUtil.Node(pair.node1)); NetSegment netSegment1 = NetUtil.Segment(segment1); Connect(pair.node1, pair.point2.Node, -netSegment1.GetDirection(pair.node1), pair.point2.Direction, pair.point2.NetInfo, !pair.point2.DirectionBool); usedNodes.Add(pair.node1); usedPoints.Add(pair.point2); } } }
public void InvalidateAll(bool error = true) { if (error) { Debug.LogWarning("Error: Invalidate all"); Singleton <SimulationManager> .instance.AddAction(() => CleanGhostNodes()); } Queue.Clear(); WrappersDictionary.Clear(); //Invalidator.Instance.Clear(); Observing = false; ObservingOnlyBuildings = 0; Invalidated = true; }
public static void Prefix(BuildingInfo info) { if (!SmartIntersections.instance.Active) { return; } if (info.m_paths != null) { // ns start if (info.m_paths.Length > 0) { _networkDictionary = new WrappersDictionary(); _actionGroup = new ActionGroup("Build intersection"); ReleaseCollidingSegments(); } // ns end } }
public MakeConnections(HashSet <ConnectionPoint> borderNodes, FastList <ushort> createdNodes, WrappersDictionary dictionary, ActionGroup actionGroup) { if (!UIWindow.instance.m_connectRoadsCheckBox.isChecked) { return; } if (borderNodes == null) { return; } _networkDictionary = dictionary; _actionGroup = actionGroup; HashSet <ushort> filteredCreatedNodes = FilterCreatedNodes(createdNodes); // (Border nodes are already filtered) HashSet <ConnectionPoint> connectedPrimaryPoints = new HashSet <ConnectionPoint>(); /* For each pair of nodes we make an attempt to connect them */ foreach (ushort node1 in filteredCreatedNodes) { foreach (ConnectionPoint cpoint in borderNodes) { if (connectedPrimaryPoints.Contains(cpoint)) { continue; } if (TryConnect(node1, cpoint)) { connectedPrimaryPoints.Add(cpoint); break; } } } }
public static bool LoadPaths(BuildingInfo info, ushort buildingID, ref Building data, float elevation) { if (info.m_paths != null) { // ns start if (info.m_paths.Length > 0) { _networkDictionary = new WrappersDictionary(); _actionGroup = new ActionGroup("Build intersection"); //Debug.Log("LoadPaths detour"); ReleaseCollidingSegments(); } // ns end NetManager instance = Singleton <NetManager> .instance; instance.m_tempNodeBuffer.Clear(); instance.m_tempSegmentBuffer.Clear(); for (int i = 0; i < info.m_paths.Length; i++) { BuildingInfo.PathInfo pathInfo = info.m_paths[i]; if (pathInfo.m_finalNetInfo != null && pathInfo.m_nodes != null && pathInfo.m_nodes.Length != 0) { Vector3 vector = data.CalculatePosition(pathInfo.m_nodes[0]); bool flag = /*BuildingDecoration.*/ RequireFixedHeight(info, pathInfo.m_finalNetInfo, pathInfo.m_nodes[0]); if (!flag) { vector.y = NetSegment.SampleTerrainHeight(pathInfo.m_finalNetInfo, vector, false, pathInfo.m_nodes[0].y + elevation); } Ray ray = new Ray(vector + new Vector3(0f, 8f, 0f), Vector3.down); NetTool.ControlPoint controlPoint; if (!FindConnectNode(instance.m_tempNodeBuffer, vector, pathInfo.m_finalNetInfo, out controlPoint)) { if (NetTool.MakeControlPoint(ray, 16f, pathInfo.m_finalNetInfo, true, NetNode.Flags.Untouchable, NetSegment.Flags.Untouchable, Building.Flags.All, pathInfo.m_nodes[0].y + elevation - pathInfo.m_finalNetInfo.m_buildHeight, true, out controlPoint)) { Vector3 vector2 = controlPoint.m_position - vector; if (!flag) { vector2.y = 0f; } float sqrMagnitude = vector2.sqrMagnitude; if (sqrMagnitude > pathInfo.m_maxSnapDistance * pathInfo.m_maxSnapDistance) { controlPoint.m_position = vector; controlPoint.m_elevation = 0f; controlPoint.m_node = 0; controlPoint.m_segment = 0; } else { controlPoint.m_position.y = vector.y; } } else { controlPoint.m_position = vector; } } // ns start /*if (!instance.m_tempNodeBuffer.Contains(controlPoint.m_node)) * { * controlPoint.m_position = vector; * controlPoint.m_elevation = 0f; * controlPoint.m_node = 0; * controlPoint.m_segment = 0; * }*/ // ns end //CheckSplitSegmentAngle(ref controlPoint, instance.m_tempSegmentBuffer, borderNodes); // ns ushort node; ushort num2; int num3; int num4; if (controlPoint.m_node != 0) { instance.m_tempNodeBuffer.Add(controlPoint.m_node); } else if (NetTool.CreateNode(pathInfo.m_finalNetInfo, controlPoint, controlPoint, controlPoint, NetTool.m_nodePositionsSimulation, 0, false, false, false, false, pathInfo.m_invertSegments, false, 0, out node, out num2, out num3, out num4) == ToolBase.ToolErrors.None) { instance.m_tempNodeBuffer.Add(node); controlPoint.m_node = node; if (pathInfo.m_forbidLaneConnection != null && pathInfo.m_forbidLaneConnection.Length > 0 && pathInfo.m_forbidLaneConnection[0]) { NetNode[] buffer = instance.m_nodes.m_buffer; ushort num5 = node; buffer[(int)num5].m_flags = (buffer[(int)num5].m_flags | NetNode.Flags.ForbidLaneConnection); } if (pathInfo.m_trafficLights != null && pathInfo.m_trafficLights.Length > 0) { /*BuildingDecoration.*/ TrafficLightsToFlags(pathInfo.m_trafficLights[0], ref instance.m_nodes.m_buffer[(int)node].m_flags); } } for (int j = 1; j < pathInfo.m_nodes.Length; j++) { vector = data.CalculatePosition(pathInfo.m_nodes[j]); bool flag2 = /*BuildingDecoration.*/ RequireFixedHeight(info, pathInfo.m_finalNetInfo, pathInfo.m_nodes[j]); if (!flag2) { vector.y = NetSegment.SampleTerrainHeight(pathInfo.m_finalNetInfo, vector, false, pathInfo.m_nodes[j].y + elevation); } ray = new Ray(vector + new Vector3(0f, 8f, 0f), Vector3.down); NetTool.ControlPoint controlPoint2; if (!/*BuildingDecoration.*/ FindConnectNode(instance.m_tempNodeBuffer, vector, pathInfo.m_finalNetInfo, out controlPoint2)) { if (NetTool.MakeControlPoint(ray, 16f, pathInfo.m_finalNetInfo, true, NetNode.Flags.Untouchable, NetSegment.Flags.Untouchable, Building.Flags.All, pathInfo.m_nodes[j].y + elevation - pathInfo.m_finalNetInfo.m_buildHeight, true, out controlPoint2)) { Vector3 vector3 = controlPoint2.m_position - vector; if (!flag2) { vector3.y = 0f; } float sqrMagnitude2 = vector3.sqrMagnitude; if (sqrMagnitude2 > pathInfo.m_maxSnapDistance * pathInfo.m_maxSnapDistance) { controlPoint2.m_position = vector; controlPoint2.m_elevation = 0f; controlPoint2.m_node = 0; controlPoint2.m_segment = 0; } else { controlPoint2.m_position.y = vector.y; } } else { controlPoint2.m_position = vector; } } NetTool.ControlPoint middlePoint = controlPoint2; if (pathInfo.m_curveTargets != null && pathInfo.m_curveTargets.Length >= j) { middlePoint.m_position = data.CalculatePosition(pathInfo.m_curveTargets[j - 1]); if (!flag || !flag2) { middlePoint.m_position.y = NetSegment.SampleTerrainHeight(pathInfo.m_finalNetInfo, middlePoint.m_position, false, pathInfo.m_curveTargets[j - 1].y + elevation); } } else { middlePoint.m_position = (controlPoint.m_position + controlPoint2.m_position) * 0.5f; } middlePoint.m_direction = VectorUtils.NormalizeXZ(middlePoint.m_position - controlPoint.m_position); controlPoint2.m_direction = VectorUtils.NormalizeXZ(controlPoint2.m_position - middlePoint.m_position); ushort num6; ushort num7; ushort num8; int num9; int num10; if (NetTool.CreateNode(pathInfo.m_finalNetInfo, controlPoint, middlePoint, controlPoint2, NetTool.m_nodePositionsSimulation, 1, false, false, false, false, false, pathInfo.m_invertSegments, false, 0, out num6, out num7, out num8, out num9, out num10) == ToolBase.ToolErrors.None) { instance.m_tempNodeBuffer.Add(num7); instance.m_tempSegmentBuffer.Add(num8); controlPoint2.m_node = num7; if (pathInfo.m_forbidLaneConnection != null && pathInfo.m_forbidLaneConnection.Length > j && pathInfo.m_forbidLaneConnection[j]) { NetNode[] buffer2 = instance.m_nodes.m_buffer; ushort num11 = num7; buffer2[(int)num11].m_flags = (buffer2[(int)num11].m_flags | NetNode.Flags.ForbidLaneConnection); } if (pathInfo.m_trafficLights != null && pathInfo.m_trafficLights.Length > j) { /*BuildingDecoration.*/ TrafficLightsToFlags(pathInfo.m_trafficLights[j], ref instance.m_nodes.m_buffer[(int)num7].m_flags); } if (pathInfo.m_yieldSigns != null && pathInfo.m_yieldSigns.Length >= j * 2) { if (pathInfo.m_yieldSigns[j * 2 - 2]) { NetSegment[] buffer3 = instance.m_segments.m_buffer; ushort num12 = num8; buffer3[(int)num12].m_flags = (buffer3[(int)num12].m_flags | NetSegment.Flags.YieldStart); } if (pathInfo.m_yieldSigns[j * 2 - 1]) { NetSegment[] buffer4 = instance.m_segments.m_buffer; ushort num13 = num8; buffer4[(int)num13].m_flags = (buffer4[(int)num13].m_flags | NetSegment.Flags.YieldEnd); } } } controlPoint = controlPoint2; flag = flag2; } } } for (int k = 0; k < instance.m_tempNodeBuffer.m_size; k++) { ushort num14 = instance.m_tempNodeBuffer.m_buffer[k]; if ((instance.m_nodes.m_buffer[(int)num14].m_flags & NetNode.Flags.Untouchable) == NetNode.Flags.None) { if (buildingID != 0) { if ((data.m_flags & Building.Flags.Active) == Building.Flags.None && instance.m_nodes.m_buffer[(int)num14].Info.m_canDisable) { NetNode[] buffer5 = instance.m_nodes.m_buffer; ushort num15 = num14; buffer5[(int)num15].m_flags = (buffer5[(int)num15].m_flags | NetNode.Flags.Disabled); } NetNode[] buffer6 = instance.m_nodes.m_buffer; ushort num16 = num14; buffer6[(int)num16].m_flags = (buffer6[(int)num16].m_flags | NetNode.Flags.Untouchable); instance.UpdateNode(num14); instance.m_nodes.m_buffer[(int)num14].m_nextBuildingNode = data.m_netNode; data.m_netNode = num14; } else { instance.UpdateNode(num14); } } } for (int l = 0; l < instance.m_tempSegmentBuffer.m_size; l++) { ushort num17 = instance.m_tempSegmentBuffer.m_buffer[l]; if ((instance.m_segments.m_buffer[(int)num17].m_flags & NetSegment.Flags.Untouchable) == NetSegment.Flags.None) { if (buildingID != 0) { NetSegment[] buffer7 = instance.m_segments.m_buffer; ushort num18 = num17; buffer7[(int)num18].m_flags = (buffer7[(int)num18].m_flags | NetSegment.Flags.Untouchable); instance.UpdateSegment(num17); } else { if ((Singleton <ToolManager> .instance.m_properties.m_mode & ItemClass.Availability.AssetEditor) != ItemClass.Availability.None) { NetInfo info2 = instance.m_segments.m_buffer[(int)num17].Info; if ((info2.m_availableIn & ItemClass.Availability.AssetEditor) == ItemClass.Availability.None) { NetSegment[] buffer8 = instance.m_segments.m_buffer; ushort num19 = num17; buffer8[(int)num19].m_flags = (buffer8[(int)num19].m_flags | NetSegment.Flags.Untouchable); } } instance.UpdateSegment(num17); } } } // ns start AfterIntersectionBuilt(info, instance.m_tempNodeBuffer, instance.m_tempSegmentBuffer); // ns end instance.m_tempNodeBuffer.Clear(); instance.m_tempSegmentBuffer.Clear(); } return(false); // ns }
public FinalConnector(NetInfo centerNodeNetInfo, EdgeIntersections2 edgeIntersections, Ellipse ellipse, bool insertControllingVertices) { intersections = edgeIntersections?.Intersections ?? new List <RoundaboutNode>(); actionGroupTMPE = edgeIntersections?.ActionGroupTMPE ?? new ActionGroup("Set up TMPE"); actionGroupRoads = edgeIntersections?.ActionGroupRoads ?? new ActionGroup("Build roundabout"); wrappersDictionary = edgeIntersections?.networkDictionary ?? new WrappersDictionary(); this.ellipse = ellipse; pleasenoinfiniterecursion = 0; this.centerNodeNetInfo = centerNodeNetInfo; leftHandTraffic = Singleton <SimulationManager> .instance.m_metaData.m_invertTraffic == SimulationMetaData.MetaBool.True; // We ensure that the segments are not too long. For circles only (with ellipses it would be more difficult) m_maxAngDistance = Math.Min(Math.PI * 25 / ellipse.RadiusMain, Math.PI / 2 + 0.1d); bool isCircle = ellipse.IsCircle(); if (!isCircle && insertControllingVertices) { /* See doc in the method below */ InsertIntermediateNodes(); } /* If the list of edge nodes is empty, we add one default intersection. */ if (isCircle && intersections.Count == 0) { Vector3 defaultIntersection = new Vector3(ellipse.RadiusMain, 0, 0) + ellipse.Center; //ushort newNodeId = NetAccess.CreateNode(centerNodeNetInfo, defaultIntersection); WrappedNode newNodeW = new WrappedNode(); newNodeW.Position = defaultIntersection; newNodeW.NetInfo = centerNodeNetInfo; RoundaboutNode raNode = new RoundaboutNode(newNodeW); raNode.Create(actionGroupRoads); intersections.Add(raNode); } int count = intersections.Count; foreach (RoundaboutNode item in intersections) { item.angle = Ellipse.VectorsAngle(item.wrappedNode.Position - ellipse.Center); } /* We sort the nodes according to their angles */ intersections.Sort(); /* Goes over all the nodes and conntets each of them to the angulary closest neighbour. (In a given direction) */ for (int i = 0; i < count; i++) { RoundaboutNode prevNode = intersections[i]; if (isCircle) { prevNode = CheckAngularDistance(intersections[i], intersections[(i + 1) % count]); } ConnectNodes(intersections[(i + 1) % count], prevNode); } // Charge player var chargePlayerAction = new ChargePlayerAction(actionGroupRoads.DoCost(), centerNodeNetInfo.m_class); if (!chargePlayerAction.CheckMoney()) { throw new PlayerException("Not enough money!"); } actionGroupRoads.Actions.Add(chargePlayerAction); // Create ModThreading.PushAction(actionGroupRoads, actionGroupTMPE); }