void FloodFill(IntVector StartLocation, int IslandId, HashSet <IntVector> Visited, List <FloorIslandNode> IslandNodes, FloorChunkDB ChunkDB) { FloorChunk PreferedChunk = ChunkDB.GetChunkAt(StartLocation); if (!PreferedChunk.bConnectDoors) { // We don't want doors here return; } if (PreferedChunk == null) { return; } Queue <IntVector> Queue = new Queue <IntVector>(); Queue.Enqueue(StartLocation); while (Queue.Count > 0) { IntVector Location = Queue.Dequeue(); FloorChunk CurrentChunk = ChunkDB.GetChunkAt(Location); if (CurrentChunk != PreferedChunk) { continue; } // Create a node here FloorIslandNode Node = new FloorIslandNode(); Node.IslandId = IslandId; Node.Chunk = CurrentChunk; Node.Location = Location; IslandNodes.Add(Node); // Add the neighbors to the queue List <IntVector> Neighbors = new List <IntVector>(); Neighbors.Add(Location + new IntVector(-1, 0, 0)); Neighbors.Add(Location + new IntVector(1, 0, 0)); Neighbors.Add(Location + new IntVector(0, 0, 1)); Neighbors.Add(Location + new IntVector(0, 0, -1)); foreach (IntVector Neighbor in Neighbors) { if (Visited.Contains(Neighbor)) { continue; } FloorChunk NeighborChunk = ChunkDB.GetChunkAt(Neighbor); if (NeighborChunk != null && NeighborChunk.Id == CurrentChunk.Id) { Queue.Enqueue(Neighbor); Visited.Add(Neighbor); } } } }
void CreateDoors(int y) { // Tag all islands // Create adjacency list // Do a DFS on the tagged islands and connect the islands with doors HashSet <IntVector> Visited = new HashSet <IntVector>(); List <FloorIslandNode> IslandNodes = new List <FloorIslandNode>(); int TotalIslands = 0; // Tag islands with a flood fill. This helps if custom volume split existing // rooms into multiple parts and needs to be treated separately (islands) { int IslandId = 0; for (int x = 0; x < floorPlanConfig.BuildingSize.x; x++) { for (int z = 0; z < floorPlanConfig.BuildingSize.z; z++) { IntVector Location = new IntVector(x, y, z); if (!Visited.Contains(Location)) { // Flood fill from here Visited.Add(Location); FloodFill(Location, IslandId, Visited, IslandNodes, ChunkDB); IslandId++; } } } TotalIslands = IslandId; } // Create a node map for faster access Dictionary <IntVector, FloorIslandNode> IslandNodeByLocation = new Dictionary <IntVector, FloorIslandNode>(); foreach (FloorIslandNode Node in IslandNodes) { if (Node.IslandId == -1) { continue; } IslandNodeByLocation.Add(Node.Location, Node); } // Create adjacency list for each island List <FloorIslandAdjacency> AdjacencyList = new List <FloorIslandAdjacency>(); for (int x = 0; x < floorPlanConfig.BuildingSize.x; x++) { for (int z = 0; z < floorPlanConfig.BuildingSize.z; z++) { IntVector Loc00 = new IntVector(x, y, z); if (!IslandNodeByLocation.ContainsKey(Loc00)) { continue; } FloorIslandNode Node00 = IslandNodeByLocation[Loc00]; if (Node00.IslandId == -1) { continue; } // Test along the left cell { IntVector Loc10 = new IntVector(x + 1, y, z); if (IslandNodeByLocation.ContainsKey(Loc10)) { FloorIslandNode Node10 = IslandNodeByLocation[Loc10]; if (Node10.IslandId != -1 && Node00.IslandId != Node10.IslandId) { // Different adjacent nodes. Add to the list FloorIslandAdjacency Adjacency = new FloorIslandAdjacency(); Adjacency.A = Node00; Adjacency.B = Node10; AdjacencyList.Add(Adjacency); } } } // Test along the bottom cell { IntVector Loc01 = new IntVector(x, y, z + 1); if (IslandNodeByLocation.ContainsKey(Loc01)) { FloorIslandNode Node01 = IslandNodeByLocation[Loc01]; if (Node01.IslandId != -1 && Node00.IslandId != Node01.IslandId) { // Different adjacent nodes. Add to the list FloorIslandAdjacency Adjacency = new FloorIslandAdjacency(); Adjacency.A = Node00; Adjacency.B = Node01; AdjacencyList.Add(Adjacency); } } } } } // Create another lookup for faster access Dictionary <int, List <FloorIslandAdjacency> > AdjacencyByIsland = new Dictionary <int, List <FloorIslandAdjacency> >(); foreach (FloorIslandAdjacency Adjacency in AdjacencyList) { int IslandA = Adjacency.A.IslandId; int IslandB = Adjacency.B.IslandId; if (!AdjacencyByIsland.ContainsKey(IslandA)) { AdjacencyByIsland.Add(IslandA, new List <FloorIslandAdjacency>()); } if (!AdjacencyByIsland.ContainsKey(IslandB)) { AdjacencyByIsland.Add(IslandB, new List <FloorIslandAdjacency>()); } AdjacencyByIsland[IslandA].Add(Adjacency); AdjacencyByIsland[IslandB].Add(Adjacency); } Dictionary <int, FloorChunk> IslandToChunkMap = new Dictionary <int, FloorChunk>(); foreach (FloorIslandNode IslandNode in IslandNodes) { if (IslandToChunkMap.ContainsKey(IslandNode.IslandId)) { continue; } IslandToChunkMap.Add(IslandNode.IslandId, IslandNode.Chunk); } // Connect the islands to the main network with doors HashSet <int> IslandVisited = new HashSet <int>(); for (int IslandId = 0; IslandId < TotalIslands; IslandId++) { ConnectIslandRecursive(IslandId, AdjacencyByIsland, IslandVisited, random, DoorManager, IslandToChunkMap); } }