public void Register(FloorChunk Chunk)
 {
     if (!Chunks.ContainsKey(Chunk.Id))
     {
         Chunks.Add(Chunk.Id, Chunk);
     }
 }
        public FloorChunk Create()
        {
            var Chunk = new FloorChunk();

            Chunk.Id = ++IdCounter;
            return(Chunk);
        }
        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);
                    }
                }
            }
        }
 FloorChunk GetPriorityChunk(FloorChunk A, FloorChunk B)
 {
     if (A == null)
     {
         return(B);
     }
     if (B == null)
     {
         return(A);
     }
     return(A.Priority > B.Priority ? A : B);
 }
            public int Compare(int IslandA, int IslandB)
            {
                FloorChunk ChunkA = IslandToChunkMap.ContainsKey(IslandA) ? IslandToChunkMap[IslandA] : null;
                FloorChunk ChunkB = IslandToChunkMap.ContainsKey(IslandB) ? IslandToChunkMap[IslandB] : null;

                int ScoreA = GetChunkDoorConnectionScore(ChunkA);
                int ScoreB = GetChunkDoorConnectionScore(ChunkB);

                if (ScoreA == ScoreB)
                {
                    return(0);
                }
                return(ScoreA < ScoreB ? 1 : -1);
            }
        void SplitChunk(FloorChunk Chunk, FloorChunk OutLeft, FloorChunk OutRight)
        {
            int MinRoomLength = floorPlanConfig.MinRoomSize;
            int Length        = Chunk.GetLength();
            int LengthLeft    = MinRoomLength + random.Next(0, Mathf.Max(0, Length - MinRoomLength * 2));
            int LengthRight   = Length - LengthLeft;

            OutLeft.Bounds    = Chunk.Bounds;
            OutLeft.ChunkType = FloorChunkType.Room;
            OutLeft.SetLength(LengthLeft);

            OutRight.Bounds = Chunk.Bounds;
            OutRight.OffsetAlongLength(LengthLeft);
            OutRight.ChunkType = FloorChunkType.Room;
            OutRight.SetLength(LengthRight);
        }
        void SplitChunk(FloorChunk Chunk, FloorChunk OutLeft, FloorChunk OutRight, FloorChunk OutHallway)
        {
            int HallWidth       = floorPlanConfig.HallWidth;
            int Length          = Chunk.GetLength();
            int RemainingLength = Length - HallWidth;
            int MinChunkLength  = floorPlanConfig.MinRoomSize;
            int LengthLeft      = MinChunkLength + random.Next(0, Mathf.Max(0, RemainingLength - MinChunkLength * 2 + 1));
            int LengthRight     = RemainingLength - LengthLeft;

            OutLeft.Bounds    = Chunk.Bounds;
            OutLeft.ChunkType = FloorChunkType.Room;
            OutLeft.SetLength(LengthLeft);

            OutHallway.Bounds    = Chunk.Bounds;
            OutHallway.ChunkType = FloorChunkType.Hall;
            OutHallway.OffsetAlongLength(LengthLeft);
            OutHallway.SetLength(HallWidth);

            OutRight.Bounds    = Chunk.Bounds;
            OutRight.ChunkType = FloorChunkType.Room;
            OutRight.OffsetAlongLength(LengthLeft + HallWidth);
            OutRight.SetLength(LengthRight);
        }
        string GetDoorMarkerName(FloorChunk ChunkA, FloorChunk ChunkB)
        {
            if (ChunkA == null && ChunkB == null)
            {
                return(FloorPlanMarkers.MARKER_DOOR);
            }

            FloorChunk PreferedChunk;

            if (ChunkA == null)
            {
                PreferedChunk = ChunkB;
            }
            else if (ChunkB == null)
            {
                PreferedChunk = ChunkA;
            }
            else
            {
                PreferedChunk = (ChunkA.Priority > ChunkB.Priority) ? ChunkA : ChunkB;
            }

            return(PreferedChunk.DoorMarker.Length > 0 ? PreferedChunk.DoorMarker : FloorPlanMarkers.MARKER_DOOR);
        }
 //////////////////////////// Door connection //////////////////////////
 static int GetChunkDoorConnectionScore(FloorChunk Chunk)
 {
     if (Chunk == null)
     {
         return(-1000);
     }
     if (Chunk.bReachable)
     {
         return(-500);
     }
     if (!Chunk.bConnectDoors)
     {
         return(-1000);
     }
     if (Chunk.ChunkType == FloorChunkType.Hall)
     {
         return(1000);
     }
     if (Chunk.ChunkType == FloorChunkType.Room)
     {
         return(500);
     }
     return(0);
 }
        /// <summary>
        /// Generate a layout and save it in the model
        /// </summary>
        void EmitBuildingMarkers()
        {
            floorPlanConfig = config as FloorPlanConfig;
            floorPlanModel  = model as FloorPlanModel;

            ClearSockets();

            //TArray<AFloorPlanDoorVolume*> DoorVolumes = UDungeonModelHelper::GetVolumes<AFloorPlanDoorVolume>(Dungeon)

            ClearSockets();
            int     NumFloors = Mathf.RoundToInt(floorPlanConfig.BuildingSize.y);
            Vector3 GridSize = floorPlanConfig.GridSize;
            bool    bBuildingWallLeft, bBuildingWallBottom;

            for (int y = 0; y < NumFloors; y++)
            {
                for (int x = -1; x < floorPlanConfig.BuildingSize.x; x++)
                {
                    bBuildingWallLeft = (x == -1 || x == floorPlanConfig.BuildingSize.x - 1);
                    for (int z = -1; z < floorPlanConfig.BuildingSize.z; z++)
                    {
                        bBuildingWallBottom = (z == -1 || z == floorPlanConfig.BuildingSize.z - 1);
                        FloorChunk Chunk00 = ChunkDB.GetChunkAt(x, y, z);
                        FloorChunk Chunk10 = ChunkDB.GetChunkAt(x + 1, y, z);
                        FloorChunk Chunk01 = ChunkDB.GetChunkAt(x, y, z + 1);

                        string GroundMarkerName  = FloorPlanMarkers.MARKER_GROUND;
                        string CeilingMarkerName = FloorPlanMarkers.MARKER_CEILING;

                        FloorChunk ChunkAbove         = ChunkDB.GetChunkAt(x, y + 1, z);
                        FloorChunk ChunkBelow         = ChunkDB.GetChunkAt(x, y - 1, z);
                        bool       bEmitGroundMarker  = (Chunk00 != ChunkBelow);
                        bool       bEmitCeilingMarker = (Chunk00 != ChunkAbove);

                        // Emit the ground marker
                        if (Chunk00 != null && Chunk00.ChunkType != FloorChunkType.Outside)
                        {
                            if (bEmitGroundMarker)
                            {
                                Vector3 GridLocation  = new Vector3(x + 0.5f, y, z + 0.5f);
                                Vector3 WorldLocation = Vector3.Scale(GridLocation, GridSize);
                                if (Chunk00.GroundMarker.Length > 0)
                                {
                                    GroundMarkerName = Chunk00.GroundMarker;
                                }
                                EmitMarkerAt(WorldLocation, GroundMarkerName, 0);
                            }
                            if (bEmitCeilingMarker)
                            {
                                Vector3 GridLocation  = new Vector3(x + 0.5f, y + 1, z + 0.5f);
                                Vector3 WorldLocation = Vector3.Scale(GridLocation, GridSize);
                                if (Chunk00.CeilingMarker.Length > 0)
                                {
                                    CeilingMarkerName = Chunk00.CeilingMarker;
                                }
                                EmitMarkerAt(WorldLocation, CeilingMarkerName, Quaternion.Euler(180, 0, 0));
                            }
                        }

                        int Chunk00Id = (Chunk00 != null ? Chunk00.Id : -1);
                        int Chunk10Id = (Chunk10 != null ? Chunk10.Id : -1);
                        int Chunk01Id = (Chunk01 != null ? Chunk01.Id : -1);

                        bool bEmitLeftWall   = (Chunk00Id != Chunk10Id);
                        bool bEmitBottomWall = (Chunk00Id != Chunk01Id);
                        bool bLeftDoor       = DoorManager.ContainsDoor(new IntVector(x, y, z), new IntVector(x + 1, y, z));
                        // || DoorManager.ContainsDoorVolume(Vector3.Scale(new Vector(x + 1, y, z + 0.5f) * GridSize), DoorVolumes);
                        bool bBottomDoor = DoorManager.ContainsDoor(new IntVector(x, y, z), new IntVector(x, y, z + 1));
                        // || DoorManager.ContainsDoorVolume(Vector3.Scale(new Vector(x + 0.5f, y, z + 1) * GridSize), DoorVolumes);

                        if (Chunk00 != null && Chunk10 != null && Chunk00.ChunkType == FloorChunkType.Hall && Chunk10.ChunkType == FloorChunkType.Hall)
                        {
                            // Do not block the halls with a wall
                            bEmitLeftWall = false;
                        }
                        if (Chunk00 != null && Chunk01 != null && Chunk00.ChunkType == FloorChunkType.Hall && Chunk01.ChunkType == FloorChunkType.Hall)
                        {
                            // Do not block the halls with a wall
                            bEmitBottomWall = false;
                        }

                        if (Chunk00 != null && Chunk10 != null && (!Chunk00.bEmitGroundMarker || !Chunk10.bEmitGroundMarker))
                        {
                            // We don't have ground in one of the adjacent chunks. Can't have doors
                            bLeftDoor = false;
                        }
                        if (Chunk00 != null && Chunk01 != null && (!Chunk00.bEmitGroundMarker || !Chunk01.bEmitGroundMarker))
                        {
                            // We don't have ground in one of the adjacent chunks. Can't have doors
                            bBottomDoor = false;
                        }

                        if (bEmitLeftWall)
                        {
                            FloorChunk PriorityChunk = GetPriorityChunk(Chunk00, Chunk10);
                            bEmitLeftWall = PriorityChunk != null ? PriorityChunk.bCreateWalls : true;
                        }
                        if (bEmitBottomWall)
                        {
                            FloorChunk PriorityChunk = GetPriorityChunk(Chunk00, Chunk01);
                            bEmitBottomWall = PriorityChunk != null ? PriorityChunk.bCreateWalls : true;
                        }

                        if (bEmitLeftWall)
                        {
                            Vector3 GridLocation  = new Vector3(x + 1, y, z + 0.5f);
                            Vector3 WorldLocation = Vector3.Scale(GridLocation, GridSize);

                            string MarkerName;
                            if (bLeftDoor)
                            {
                                MarkerName = GetDoorMarkerName(Chunk00, Chunk10);
                            }
                            else
                            {
                                MarkerName = FloorPlanMarkers.MARKER_WALL;
                                if (bBuildingWallLeft)
                                {
                                    MarkerName = FloorPlanMarkers.MARKER_BUILDING_WALL;
                                }
                                else
                                {
                                    if (Chunk00 != null && Chunk10 != null)
                                    {
                                        FloorChunk PriorityChunk = (Chunk00.Priority > Chunk10.Priority) ? Chunk00 : Chunk10;
                                        if (PriorityChunk.WallMarker.Length > 0)
                                        {
                                            MarkerName = PriorityChunk.WallMarker;
                                        }
                                    }
                                }
                            }

                            EmitMarkerAt(WorldLocation, MarkerName, 90);
                        }
                        if (bEmitBottomWall)
                        {
                            Vector3 GridLocation  = new Vector3(x + 0.5f, y, z + 1);
                            Vector3 WorldLocation = Vector3.Scale(GridLocation, GridSize);

                            string MarkerName;
                            if (bBottomDoor)
                            {
                                MarkerName = GetDoorMarkerName(Chunk00, Chunk01);
                            }
                            else
                            {
                                MarkerName = FloorPlanMarkers.MARKER_WALL;
                                if (bBuildingWallBottom)
                                {
                                    MarkerName = FloorPlanMarkers.MARKER_BUILDING_WALL;
                                }
                                else
                                {
                                    if (Chunk00 != null && Chunk01 != null)
                                    {
                                        FloorChunk PriorityChunk = (Chunk00.Priority > Chunk01.Priority) ? Chunk00 : Chunk01;
                                        if (PriorityChunk.WallMarker.Length > 0)
                                        {
                                            MarkerName = PriorityChunk.WallMarker;
                                        }
                                    }
                                }
                            }

                            EmitMarkerAt(WorldLocation, MarkerName, 0);
                        }
                    }
                }
            }


            // Emit center marker if specified
            List <FloorChunk> Chunks = new List <FloorChunk>();

            ChunkDB.GetChunks(Chunks);
            foreach (FloorChunk Chunk in Chunks)
            {
                if (Chunk.bEmitGroundMarker && Chunk.CenterMarker.Length > 0)
                {
                    Vector3 ChunkSize = MathUtils.ToVector3(Chunk.Bounds.Size) / 2.0f;
                    ChunkSize.y = 0;
                    Vector3 GridLocation  = MathUtils.ToVector3(Chunk.Bounds.Location) + ChunkSize;
                    Vector3 WorldLocation = Vector3.Scale(GridLocation, GridSize);
                    EmitMarkerAt(WorldLocation, Chunk.CenterMarker, 0);
                }
            }
        }
        void BuildLayout()
        {
            ChunkDB     = new FloorChunkDB();
            DoorManager = new FloorDoorManager();
            Visited.Clear();
            random = new System.Random((int)floorPlanConfig.Seed);

            int NumFloors = Mathf.RoundToInt(floorPlanConfig.BuildingSize.y);

            for (int y = 0; y < NumFloors; y++)
            {
                // Build the hallways and the intermediate floor chunks (which will hold the rooms)
                List <FloorChunk> FloorChunks = new List <FloorChunk>();
                {
                    FloorChunk InitialFloor = ChunkDB.Create();
                    InitialFloor.Bounds.Location = new IntVector(0, y, 0);
                    InitialFloor.Bounds.Size     = MathUtils.ToIntVector(floorPlanConfig.BuildingSize);

                    Stack <FloorChunk> Stack = new Stack <FloorChunk>();
                    Stack.Push(InitialFloor);
                    while (Stack.Count > 0)
                    {
                        FloorChunk Top  = Stack.Pop();
                        float      Area = Top.Area();
                        if (Area <= 0)
                        {
                            continue;
                        }
                        if (Top.Area() <= floorPlanConfig.MinRoomChunkArea)
                        {
                            FloorChunks.Add(Top);
                        }
                        else
                        {
                            // Needs to be split further
                            FloorChunk Left    = ChunkDB.Create();
                            FloorChunk Right   = ChunkDB.Create();
                            FloorChunk Hallway = ChunkDB.Create();

                            SplitChunk(Top, Left, Right, Hallway);
                            ChunkDB.Register(Hallway);

                            Stack.Push(Left);
                            Stack.Push(Right);
                        }
                    }
                }

                // Split the floor chunks (space between the hallways) to create rooms
                foreach (FloorChunk Chunk in FloorChunks)
                {
                    Stack <FloorChunk> Stack = new Stack <FloorChunk>();
                    Stack.Push(Chunk);
                    int MinArea = floorPlanConfig.MinRoomSize * floorPlanConfig.MinRoomSize;
                    int MaxArea = floorPlanConfig.MaxRoomSize * floorPlanConfig.MaxRoomSize;

                    while (Stack.Count > 0)
                    {
                        FloorChunk Top            = Stack.Pop();
                        bool       bRequiresSplit = true;
                        int        Area           = Top.Area();
                        int        Length         = Top.GetLength();
                        if (Length > floorPlanConfig.MaxRoomSize)
                        {
                            // Length is too big. force a split
                            bRequiresSplit = true;
                        }
                        else if (Area <= MinArea)
                        {
                            // This room is too small and should not be split
                            bRequiresSplit = false;
                        }
                        else if (Area <= MaxArea)
                        {
                            float SplitProbability = (Area - MinArea) / (MaxArea - MinArea);
                            SplitProbability += floorPlanConfig.RoomSplitProbabilityOffset;
                            if (Chunk.GetLength() >= Chunk.GetWidth() * 2)
                            {
                                SplitProbability += floorPlanConfig.RoomSplitProbabilityOffset;
                            }
                            bRequiresSplit = (random.Next() < SplitProbability);
                        }

                        if (bRequiresSplit)
                        {
                            FloorChunk Left  = ChunkDB.Create();
                            FloorChunk Right = ChunkDB.Create();
                            SplitChunk(Top, Left, Right);
                            Stack.Push(Left);
                            Stack.Push(Right);
                        }
                        else
                        {
                            ChunkDB.Register(Top);
                        }
                    }
                }

                /*
                 *      // Get the chunks defined by the room volumes
                 *      List<FloorChunk> RoomVolumeChunks = new List<FloorChunk>();
                 *      if (World) {
                 *              FRectangle BuildingBounds;
                 *              BuildingBounds.Location = FIntVector::ZeroValue;
                 *              BuildingBounds.Size = FMathUtils::ToIntVector(floorPlanConfig.BuildingSize);
                 *              for (TActorIterator<AFloorPlanRoomVolume> It(World); It; ++It) {
                 *                      AFloorPlanRoomVolume* Volume = *It;
                 *                      if (Volume.Dungeon != Dungeon) {
                 *                              // This volume is not supposed to affect this dungeon
                 *                              continue;
                 *                      }
                 *                      FVector GridSize = floorPlanConfig.GridSize;
                 *                      FRectangle VolumeBounds;
                 *                      Volume.GetDungeonVolumeBounds(GridSize, VolumeBounds);
                 *                      int VolumeStartZ = VolumeBounds.Location.Z;
                 *                      int VolumeEndZ = VolumeStartZ + VolumeBounds.Size.Z;
                 *
                 *                      if (z < VolumeStartZ || z >= VolumeEndZ) {
                 *                              // Out of the volume bounds
                 *                              continue;
                 *                      }
                 *
                 *                      FRectangle ChunkBounds = VolumeBounds;
                 *                      ChunkBounds.Location.Z = z;
                 *                      ChunkBounds.Size.Z = 1;
                 *                      ChunkBounds.Clip(BuildingBounds);
                 *                      if (ChunkBounds.Size.Z == 0) continue;
                 *                      int ChunkZ = ChunkBounds.Location.Z;
                 *
                 *                      FloorChunk RoomVolumeChunk = ChunkDB.Create();
                 *                      RoomVolumeChunk.Bounds = ChunkBounds;
                 *                      RoomVolumeChunk.ChunkType = FloorChunkType.Room;
                 *                      RoomVolumeChunk.bEmitGroundMarker = (ChunkZ == VolumeStartZ);
                 *                      RoomVolumeChunk.bEmitCeilingMarker = (ChunkZ == VolumeEndZ - 1);
                 *                      RoomVolumeChunk.bConnectDoors = Volume.bConnectDoors;
                 *                      RoomVolumeChunk.WallMarker = Volume.WallMarker;
                 *                      RoomVolumeChunk.GroundMarker = Volume.GroundMarker;
                 *                      RoomVolumeChunk.CeilingMarker = Volume.CeilingMarker;
                 *                      RoomVolumeChunk.DoorMarker = Volume.DoorMarker;
                 *                      RoomVolumeChunk.CenterMarker = Volume.CenterMarker;
                 *                      RoomVolumeChunk.bCreateWalls = Volume.bCreateWalls;
                 *
                 *                      // Since this chunk is defined by a volume, we can have a more detailed rasterised cell shape
                 *                      GetVolumeCells(Volume, z, RoomVolumeChunk.BoundCells);
                 *
                 *                      // Give a higher priority to the volume chunk so it overrides everything in its path
                 *                      RoomVolumeChunk.Priority = Volume.Priority;
                 *
                 *                      RoomVolumeChunks.Add(RoomVolumeChunk);
                 *                      ChunkDB.Register(RoomVolumeChunk);
                 *              }
                 *      }
                 */
            }

            ChunkDB.CacheChunkPositions();

            for (int y = 0; y < floorPlanConfig.BuildingSize.y; y++)
            {
                CreateDoors(y);
            }
        }
Example #12
0
        void BuildLayout()
        {
            ChunkDB     = new FloorChunkDB();
            DoorManager = new FloorDoorManager();
            Visited.Clear();
            random = new System.Random((int)floorPlanConfig.Seed);

            int NumFloors = Mathf.RoundToInt(floorPlanConfig.BuildingSize.y);

            for (int y = 0; y < NumFloors; y++)
            {
                // Build the hallways and the intermediate floor chunks (which will hold the rooms)
                List <FloorChunk> FloorChunks = new List <FloorChunk>();
                {
                    FloorChunk InitialFloor = ChunkDB.Create();
                    InitialFloor.Bounds.Location = new IntVector(0, y, 0);
                    InitialFloor.Bounds.Size     = MathUtils.ToIntVector(floorPlanConfig.BuildingSize);

                    Stack <FloorChunk> Stack = new Stack <FloorChunk>();
                    Stack.Push(InitialFloor);
                    while (Stack.Count > 0)
                    {
                        FloorChunk Top  = Stack.Pop();
                        float      Area = Top.Area();
                        if (Area <= 0)
                        {
                            continue;
                        }
                        if (Top.Area() <= floorPlanConfig.MinRoomChunkArea)
                        {
                            FloorChunks.Add(Top);
                        }
                        else
                        {
                            // Needs to be split further
                            FloorChunk Left    = ChunkDB.Create();
                            FloorChunk Right   = ChunkDB.Create();
                            FloorChunk Hallway = ChunkDB.Create();

                            SplitChunk(Top, Left, Right, Hallway);
                            ChunkDB.Register(Hallway);

                            Stack.Push(Left);
                            Stack.Push(Right);
                        }
                    }
                }

                // Split the floor chunks (space between the hallways) to create rooms
                foreach (FloorChunk Chunk in FloorChunks)
                {
                    Stack <FloorChunk> Stack = new Stack <FloorChunk>();
                    Stack.Push(Chunk);
                    int MinRoomSize = floorPlanConfig.MinRoomSize;
                    int MaxRoomSize = floorPlanConfig.MaxRoomSize;
                    MaxRoomSize = Mathf.Max(MinRoomSize, MaxRoomSize);

                    int MinArea = MinRoomSize * MinRoomSize;
                    int MaxArea = MaxRoomSize * MaxRoomSize;

                    while (Stack.Count > 0)
                    {
                        FloorChunk Top            = Stack.Pop();
                        bool       bRequiresSplit = true;
                        int        Area           = Top.Area();
                        int        Length         = Top.GetLength();
                        if (Length > MaxRoomSize)
                        {
                            // Length is too big. force a split
                            bRequiresSplit = true;
                        }
                        else if (Area <= MinArea)
                        {
                            // This room is too small and should not be split
                            bRequiresSplit = false;
                        }
                        else if (Area <= MaxArea)
                        {
                            float SplitProbability = (Area - MinArea) / (MaxArea - MinArea);
                            SplitProbability += floorPlanConfig.RoomSplitProbabilityOffset;
                            if (Chunk.GetLength() >= Chunk.GetWidth() * 2)
                            {
                                SplitProbability += floorPlanConfig.RoomSplitProbabilityOffset;
                            }
                            bRequiresSplit = (random.Next() < SplitProbability);
                        }

                        if (bRequiresSplit)
                        {
                            FloorChunk Left  = ChunkDB.Create();
                            FloorChunk Right = ChunkDB.Create();
                            SplitChunk(Top, Left, Right);
                            Stack.Push(Left);
                            Stack.Push(Right);
                        }
                        else
                        {
                            ChunkDB.Register(Top);
                        }
                    }
                }

                // TODO: Add support for floor plan specific volumes
                // ...
            }

            ChunkDB.CacheChunkPositions();

            for (int y = 0; y < floorPlanConfig.BuildingSize.y; y++)
            {
                CreateDoors(y);
            }
        }