public BulldozeAction() { HashSet <Instance> newSelection = new HashSet <Instance>(selection); HashSet <Instance> extraNodes = new HashSet <Instance>(); HashSet <ushort> segments = new HashSet <ushort>(); // Segments to be removed NetManager netManager = Singleton <NetManager> .instance; // Add any segments whose node is selected foreach (Instance instance in selection) { if (instance.isValid) { if (instance.id.Type == InstanceType.NetSegment) { segments.Add(instance.id.NetSegment); } else if (instance.id.Type == InstanceType.NetNode) { for (int i = 0; i < 8; i++) { ushort segment = netManager.m_nodes.m_buffer[instance.id.NetNode].GetSegment(i); if (segment != 0) { InstanceID instanceID = default; instanceID.NetSegment = segment; if (selection.Contains(instanceID)) { continue; } newSelection.Add(new MoveableSegment(instanceID)); segments.Add(segment); } } } else if (instance.id.Type == InstanceType.Building) { Building building = (Building)((MoveableBuilding)instance).data; ushort nodeId = building.m_netNode; int c = 0; while (nodeId != 0) { NetNode node = netManager.m_nodes.m_buffer[nodeId]; if (node.m_building == 0 || node.Info.m_class.m_layer == ItemClass.Layer.WaterPipes) { // Exclude attached nodes with attached buildings (e.g. water buildings) for (int i = 0; i < 8; i++) { ushort segmentId = node.GetSegment(i); if (segmentId != 0 && MoveableSegment.isSegmentValid(segmentId) && ((netManager.m_segments.m_buffer[segmentId].m_flags & NetSegment.Flags.Untouchable) == NetSegment.Flags.None)) { InstanceID instanceID = default; instanceID.NetSegment = segmentId; if (selection.Contains(instanceID)) { continue; } newSelection.Add(new MoveableSegment(instanceID)); segments.Add(segmentId); } } } nodeId = node.m_nextBuildingNode; if (++c > 32768) { CODebugBase <LogChannel> .Error(LogChannel.Core, "Nodes: Invalid list detected!\n" + Environment.StackTrace); break; } } } } } // Add any nodes whose segments are all selected foreach (Instance instance in newSelection) { if (instance.isValid) { if (instance.id.Type == InstanceType.NetSegment) { ushort segId = instance.id.NetSegment; ushort[] nodeIds = { netManager.m_segments.m_buffer[segId].m_startNode, netManager.m_segments.m_buffer[segId].m_endNode }; foreach (ushort id in nodeIds) { bool toDelete = true; NetNode node = netManager.m_nodes.m_buffer[id]; for (int i = 0; i < 8; i++) { if (node.GetSegment(i) != 0 && !segments.Contains(node.GetSegment(i))) { toDelete = false; break; } } if (toDelete) { if (node.Info.m_class.m_layer == ItemClass.Layer.WaterPipes) { foreach (Building b in BuildingManager.instance.m_buildings.m_buffer) { if (b.m_netNode == id) { toDelete = false; break; } } } } if (toDelete) { InstanceID instanceId = default; instanceId.NetNode = id; MoveableNode mn = new MoveableNode(instanceId); if (newSelection.Contains(mn)) { continue; } extraNodes.Add(mn); } } } } } // Sort segments by buildIndex HashSet <Instance> sorted = new HashSet <Instance>(); List <uint> indexes = new List <uint>(); foreach (Instance instance in newSelection) { if (instance.id.Type != InstanceType.NetSegment) { sorted.Add(instance); } else { uint bi = ((NetSegment)instance.data).m_buildIndex; if (!indexes.Contains(bi)) { indexes.Add(bi); } } } indexes.Sort(); foreach (uint i in indexes) { foreach (Instance instance in newSelection) { if (instance.id.Type == InstanceType.NetSegment) { if (((NetSegment)instance.data).m_buildIndex == i) { sorted.Add(instance); } } } } foreach (Instance instance in sorted) { m_states.Add(instance.SaveToState()); } foreach (Instance instance in extraNodes) { m_states.Add(instance.SaveToState()); } }
public BulldozeAction() { HashSet <Instance> newSelection = new HashSet <Instance>(selection); HashSet <Instance> extraNodes = new HashSet <Instance>(); HashSet <ushort> segments = new HashSet <ushort>(); // Segments to be removed //string msg = $"\nBasic Selection: {selection.Count}\n"; // Add any segments whose node is selected foreach (Instance instance in selection) { if (instance.isValid) { if (instance.id.Type == InstanceType.NetSegment) { segments.Add(instance.id.NetSegment); } else if (instance.id.Type == InstanceType.NetNode) { for (int i = 0; i < 8; i++) { ushort segment = NetManager.instance.m_nodes.m_buffer[instance.id.NetNode].GetSegment(i); if (segment != 0) { InstanceID instanceID = default(InstanceID); instanceID.NetSegment = segment; if (selection.Contains(instanceID)) { continue; } newSelection.Add(new MoveableSegment(instanceID)); segments.Add(segment); } } } else if (instance.id.Type == InstanceType.Building) { Building building = (Building)((MoveableBuilding)instance).data; ushort nodeId = building.m_netNode; int c = 0; while (nodeId != 0) { NetNode node = NetManager.instance.m_nodes.m_buffer[nodeId]; for (int i = 0; i < 8; i++) { ushort segmentId = node.GetSegment(i); if (segmentId != 0 && MoveableSegment.isSegmentValid(segmentId) && ((NetManager.instance.m_segments.m_buffer[segmentId].m_flags & NetSegment.Flags.Untouchable) == NetSegment.Flags.None)) { InstanceID instanceID = default(InstanceID); instanceID.NetSegment = segmentId; if (selection.Contains(instanceID)) { continue; } newSelection.Add(new MoveableSegment(instanceID)); segments.Add(segmentId); } } nodeId = node.m_nextBuildingNode; if (++c > 32768) { CODebugBase <LogChannel> .Error(LogChannel.Core, "Invalid list detected!\n" + Environment.StackTrace); break; } } } } } //msg += $"Selection With Extra Segments: {newSelection.Count}\nTotal Segments: {segments.Count}\n"; // Add any nodes whose segments are all selected foreach (Instance instance in newSelection) { if (instance.isValid) { if (instance.id.Type == InstanceType.NetSegment) { ushort segId = instance.id.NetSegment; ushort[] nodeIds = { NetManager.instance.m_segments.m_buffer[segId].m_startNode, NetManager.instance.m_segments.m_buffer[segId].m_endNode }; foreach (ushort id in nodeIds) { bool toDelete = true; NetNode node = NetManager.instance.m_nodes.m_buffer[id]; for (int i = 0; i < 8; i++) { if (node.GetSegment(i) != 0 && !segments.Contains(node.GetSegment(i))) { toDelete = false; break; } } if (toDelete) { InstanceID instanceId = default(InstanceID); instanceId.NetNode = id; MoveableNode mn = new MoveableNode(instanceId); if (newSelection.Contains(mn)) { continue; } extraNodes.Add(mn); } } } } } foreach (Instance instance in newSelection) { m_states.Add(instance.GetState()); } foreach (Instance instance in extraNodes) { m_states.Add(instance.GetState()); } //Debug.Log(msg + $"Final Selection: {m_states.Count}"); }