Esempio n. 1
0
    public void DoBuild(Tile tile)
    {
        if (buildMode == BuildMode.ROOMBEHAVIOR)
        {
            string roomBehaviorType = buildModeType;

            if (tile.Room != null && WorldController.Instance.World.IsRoomBehaviorValidForRoom(roomBehaviorType, tile.Room))
            {
                RoomBehavior proto = PrototypeManager.RoomBehavior.Get(roomBehaviorType);
                tile.Room.DesignateRoomBehavior(proto.Clone());
            }
        }
        else if (buildMode == BuildMode.FURNITURE)
        {
            // Create the Furniture and assign it to the tile
            // Can we build the furniture in the selected tile?
            // Run the ValidPlacement function!
            string furnitureType = buildModeType;

            if (
                World.Current.FurnitureManager.IsPlacementValid(furnitureType, tile, CurrentPreviewRotation) &&
                World.Current.FurnitureManager.IsWorkSpotClear(furnitureType, tile) &&
                DoesFurnitureBuildJobOverlapExistingBuildJob(tile, furnitureType, CurrentPreviewRotation) == false)
            {
                // This tile position is valid for this furniture

                // Check if there is existing furniture in this tile. If so delete it.
                if (tile.Furniture != null)
                {
                    tile.Furniture.SetDeconstructJob();
                }

                // Create a job for it to be build
                Job job;

                Furniture   toBuildProto = PrototypeManager.Furniture.Get(furnitureType);
                OrderAction orderAction  = toBuildProto.GetOrderAction <Build>();
                if (orderAction != null)
                {
                    job = orderAction.CreateJob(tile, furnitureType);
                    if (useCratedObject)
                    {
                        // We want to use a crated furniture, so set requested items to crated version.
                        job.RequestedItems.Clear();
                        job.RequestedItems.Add(this.buildModeType, new ProjectPorcupine.Jobs.RequestedItem(this.buildModeType, 1));
                        useCratedObject = false;
                    }

                    // this is here so OrderAction can be used for utility as well as furniture
                    job.OnJobCompleted += (theJob) => World.Current.FurnitureManager.ConstructJobCompleted(theJob);
                }
                else
                {
                    UnityDebugger.Debugger.LogError("BuildModeController", "There is no furniture job prototype for '" + furnitureType + "'");
                    job             = new Job(tile, furnitureType, World.Current.FurnitureManager.ConstructJobCompleted, 0.1f, null, Job.JobPriority.High);
                    job.adjacent    = true;
                    job.Description = "job_build_" + furnitureType + "_desc";
                }

                Furniture furnitureToBuild = PrototypeManager.Furniture.Get(furnitureType).Clone();
                furnitureToBuild.SetRotation(CurrentPreviewRotation);
                job.buildablePrototype = furnitureToBuild;

                // Add the job to the queue or build immediately if in Dev mode
                if (SettingsKeyHolder.DeveloperMode)
                {
                    World.Current.FurnitureManager.PlaceFurniture(furnitureToBuild, job.tile);
                }
                else
                {
                    for (int x_off = tile.X; x_off < (tile.X + job.buildablePrototype.Width); x_off++)
                    {
                        for (int y_off = tile.Y; y_off < (tile.Y + job.buildablePrototype.Height); y_off++)
                        {
                            // FIXME: I don't like having to manually and explicitly set
                            // flags that prevent conflicts. It's too easy to forget to set/clear them!
                            Tile          offsetTile       = World.Current.GetTileAt(x_off, y_off, tile.Z);
                            HashSet <Job> pendingBuildJobs = WorldController.Instance.World.GetTileAt(x_off, y_off, tile.Z).PendingBuildJobs;
                            if (pendingBuildJobs != null)
                            {
                                // if the existing buildJobs furniture is replaceable by the current furnitureType,
                                // we can pretend it does not overlap with the new build

                                // We should only have 1 furniture building job per tile, so this should return that job and only that job
                                IEnumerable <Job> pendingFurnitureJob = pendingBuildJobs.Where(pendingJob => pendingJob.buildablePrototype.GetType() == typeof(Furniture));
                                if (pendingFurnitureJob.Count() == 1)
                                {
                                    pendingFurnitureJob.Single().CancelJob();
                                }
                            }

                            offsetTile.PendingBuildJobs.Add(job);
                            job.OnJobStopped += (theJob) => offsetTile.PendingBuildJobs.Remove(job);
                        }
                    }

                    World.Current.jobQueue.Enqueue(job);

                    // Let our workspot tile know it is reserved for us
                    World.Current.ReserveTileAsWorkSpot((Furniture)job.buildablePrototype, job.tile);
                }
            }
        }
        else if (buildMode == BuildMode.UTILITY)
        {
            // Create the Furniture and assign it to the tile
            // Can we build the furniture in the selected tile?
            // Run the ValidPlacement function!
            string utilityType = buildModeType;
            if (
                World.Current.UtilityManager.IsPlacementValid(utilityType, tile) &&
                DoesSameUtilityTypeAlreadyExist(utilityType, tile) == false &&
                DoesUtilityBuildJobOverlapExistingBuildJob(utilityType, tile) == false)
            {
                // This tile position is valid for this furniture

                // Create a job for it to be build
                Job job;

                Utility     toBuildProto = PrototypeManager.Utility.Get(utilityType);
                OrderAction orderAction  = toBuildProto.GetOrderAction <Build>();
                if (orderAction != null)
                {
                    job = orderAction.CreateJob(tile, utilityType);

                    // this is here so OrderAction can be used for utility as well as furniture
                    job.OnJobCompleted += (theJob) => World.Current.UtilityManager.ConstructJobCompleted(theJob);
                }
                else
                {
                    UnityDebugger.Debugger.LogError("BuildModeController", "There is no furniture job prototype for '" + utilityType + "'");
                    job             = new Job(tile, utilityType, World.Current.UtilityManager.ConstructJobCompleted, 0.1f, null, Job.JobPriority.High);
                    job.Description = "job_build_" + utilityType + "_desc";
                }

                job.buildablePrototype = PrototypeManager.Utility.Get(utilityType);

                // Add the job to the queue or build immediately if in dev mode
                if (SettingsKeyHolder.DeveloperMode)
                {
                    World.Current.UtilityManager.PlaceUtility(job.Type, job.tile, true);
                }
                else
                {
                    // FIXME: I don't like having to manually and explicitly set
                    // flags that preven conflicts. It's too easy to forget to set/clear them!
                    Tile offsetTile = World.Current.GetTileAt(tile.X, tile.Y, tile.Z);
                    offsetTile.PendingBuildJobs.Add(job);
                    job.OnJobStopped += (theJob) => offsetTile.PendingBuildJobs.Remove(job);

                    World.Current.jobQueue.Enqueue(job);
                }
            }
        }
        else if (buildMode == BuildMode.FLOOR)
        {
            // We are in tile-changing mode.
            ////t.Type = buildModeTile;

            TileType tileType = buildModeTile;

            if (
                tile.Type != tileType &&
                tile.Furniture == null &&
                tile.PendingBuildJobs.Count == 0 &&
                tileType.CanBuildHere(tile))
            {
                // This tile position is valid tile type

                // Create a job for it to be build
                Job buildingJob = tileType.BuildingJob;

                buildingJob.tile = tile;

                // Add the job to the queue or build immediately if in Dev mode
                if (SettingsKeyHolder.DeveloperMode)
                {
                    buildingJob.tile.SetTileType(buildingJob.JobTileType);
                }
                else
                {
                    buildingJob.OnJobStopped += (theJob) => theJob.tile.PendingBuildJobs.Remove(theJob);

                    WorldController.Instance.World.jobQueue.Enqueue(buildingJob);
                }
            }
        }
        else if (buildMode == BuildMode.DECONSTRUCT)
        {
            bool canDeconstructAll = SettingsKeyHolder.DeveloperMode;

            if (tile.Furniture != null && (canDeconstructAll || tile.Furniture.HasTypeTag("Non-deconstructible") == false))
            {
                // check if this is a WALL neighbouring a pressured and pressureless environment, and if so, bail
                if (IsTilePartOfPressuredRoom(tile))
                {
                    return;
                }

                tile.Furniture.SetDeconstructJob();
            }
            else if (tile.PendingBuildJobs != null && tile.PendingBuildJobs.Count > 0)
            {
                tile.PendingBuildJobs.Last().CancelJob();
            }
            else if (tile.Utilities.Count > 0)
            {
                tile.Utilities.Last().Value.SetDeconstructJob();
            }
        }
        else if (buildMode == BuildMode.MINE)
        {
            if (tile.Furniture != null)
            {
                Job  existingMineJob;
                bool hasMineJob = tile.Furniture.Jobs.HasJobWithPredicate(x => x.OrderName == typeof(Mine).Name, out existingMineJob);
                if (!hasMineJob)
                {
                    OrderAction mineAction = tile.Furniture.GetOrderAction <Mine>();
                    if (mineAction != null)
                    {
                        // check if this is a WALL neighbouring a pressured and pressureless environment, and if so, bail
                        if (IsTilePartOfPressuredRoom(tile))
                        {
                            return;
                        }

                        Job job = mineAction.CreateJob(tile, null);
                        if (SettingsKeyHolder.DeveloperMode)
                        {
                            // complete job right away, needs buildable
                            job.buildable = tile.Furniture;
                            job.DoWork(0);
                        }
                        else
                        {
                            tile.Furniture.Jobs.Add(job);
                        }
                    }
                }
            }
        }
        else
        {
            UnityDebugger.Debugger.LogError("BuildModeController", "UNIMPLEMENTED BUILD MODE");
        }
    }
    public void DoBuild(Tile tile)
    {
        if (buildMode == BuildMode.ROOMBEHAVIOR)
        {
            string roomBehaviorType = buildModeType;

            if (tile.Room != null && WorldController.Instance.World.IsRoomBehaviorValidForRoom(roomBehaviorType, tile.Room))
            {
                RoomBehavior proto = PrototypeManager.RoomBehavior.Get(roomBehaviorType);
                tile.Room.DesignateRoomBehavior(proto.Clone());
            }
        }
        else if (buildMode == BuildMode.FURNITURE)
        {
            // Create the Furniture and assign it to the tile
            // Can we build the furniture in the selected tile?
            // Run the ValidPlacement function!
            string furnitureType = buildModeType;

            if (
                World.Current.FurnitureManager.IsPlacementValid(furnitureType, tile, CurrentPreviewRotation) &&
                World.Current.FurnitureManager.IsWorkSpotClear(furnitureType, tile) &&
                DoesFurnitureBuildJobOverlapExistingBuildJob(tile, furnitureType, CurrentPreviewRotation) == false)
            {
                // This tile position is valid for this furniture

                // Check if there is existing furniture in this tile. If so delete it.
                if (tile.Furniture != null)
                {
                    tile.Furniture.SetDeconstructJob();
                }

                // Create a job for it to be build
                Job job;

                if (PrototypeManager.FurnitureConstructJob.Has(furnitureType))
                {
                    // Make a clone of the job prototype
                    job = PrototypeManager.FurnitureConstructJob.Get(furnitureType).Clone();

                    // Assign the correct tile.
                    job.tile = tile;
                }
                else
                {
                    Debug.ULogErrorChannel("BuildModeController", "There is no furniture job prototype for '" + furnitureType + "'");
                    job             = new Job(tile, furnitureType, World.Current.FurnitureManager.ConstructJobCompleted, 0.1f, null, Job.JobPriority.High);
                    job.adjacent    = true;
                    job.Description = "job_build_" + furnitureType + "_desc";
                }

                Furniture furnituteToBuild = PrototypeManager.Furniture.Get(furnitureType).Clone();
                furnituteToBuild.SetRotation(CurrentPreviewRotation);
                job.buildablePrototype = furnituteToBuild;

                // Add the job to the queue or build immediately if in Dev mode
                if (Settings.GetSetting("DialogBoxSettings_developerModeToggle", false))
                {
                    World.Current.FurnitureManager.PlaceFurniture(furnituteToBuild, job.tile);
                }
                else
                {
                    for (int x_off = tile.X; x_off < (tile.X + job.buildablePrototype.Width); x_off++)
                    {
                        for (int y_off = tile.Y; y_off < (tile.Y + job.buildablePrototype.Height); y_off++)
                        {
                            // FIXME: I don't like having to manually and explicitly set
                            // flags that prevent conflicts. It's too easy to forget to set/clear them!
                            Tile          offsetTile       = World.Current.GetTileAt(x_off, y_off, tile.Z);
                            HashSet <Job> pendingBuildJobs = WorldController.Instance.World.GetTileAt(x_off, y_off, tile.Z).PendingBuildJobs;
                            if (pendingBuildJobs != null)
                            {
                                // if the existing buildJobs furniture is replaceable by the current furnitureType,
                                // we can pretend it does not overlap with the new build

                                // We should only have 1 furniture building job per tile, so this should return that job and only that job
                                IEnumerable <Job> pendingFurnitureJob = pendingBuildJobs.Where(pendingJob => pendingJob.buildablePrototype.GetType() == typeof(Furniture));
                                if (pendingFurnitureJob.Count() == 1)
                                {
                                    pendingFurnitureJob.Single().CancelJob();
                                }
                            }

                            offsetTile.PendingBuildJobs.Add(job);
                            job.OnJobStopped += (theJob) => offsetTile.PendingBuildJobs.Remove(job);
                        }
                    }

                    World.Current.jobQueue.Enqueue(job);

                    // Let our workspot tile know it is reserved for us
                    World.Current.ReserveTileAsWorkSpot((Furniture)job.buildablePrototype, job.tile);
                }
            }
        }
        else if (buildMode == BuildMode.UTILITY)
        {
            // Create the Furniture and assign it to the tile
            // Can we build the furniture in the selected tile?
            // Run the ValidPlacement function!
            string utilityType = buildModeType;

            // TODO: Reimplement this later: DoesBuildJobOverlapExistingBuildJob(t, furnitureType) == false)
            if (
                World.Current.UtilityManager.IsPlacementValid(utilityType, tile) &&
                DoesSameUtilityTypeAlreadyExist(utilityType, tile) == false &&
                DoesUtilityBuildJobOverlapExistingBuildJob(utilityType, tile) == false)
            {
                // This tile position is valid for this furniture

                // Create a job for it to be build
                Job job;

                if (PrototypeManager.UtilityConstructJob.Has(utilityType))
                {
                    // Make a clone of the job prototype
                    job = PrototypeManager.UtilityConstructJob.Get(utilityType).Clone();

                    // Assign the correct tile.
                    job.tile = tile;
                }
                else
                {
                    Debug.ULogErrorChannel("BuildModeController", "There is no furniture job prototype for '" + utilityType + "'");
                    job             = new Job(tile, utilityType, World.Current.UtilityManager.ConstructJobCompleted, 0.1f, null, Job.JobPriority.High);
                    job.Description = "job_build_" + utilityType + "_desc";
                }

                job.buildablePrototype = PrototypeManager.Utility.Get(utilityType);

                // Add the job to the queue or build immediately if in dev mode
                if (Settings.GetSetting("DialogBoxSettings_developerModeToggle", false))
                {
                    World.Current.UtilityManager.PlaceUtility(job.Type, job.tile, true);
                }
                else
                {
                    // FIXME: I don't like having to manually and explicitly set
                    // flags that preven conflicts. It's too easy to forget to set/clear them!
                    Tile offsetTile = World.Current.GetTileAt(tile.X, tile.Y, tile.Z);
                    offsetTile.PendingBuildJobs.Add(job);
                    job.OnJobStopped += (theJob) => offsetTile.PendingBuildJobs.Remove(job);

                    World.Current.jobQueue.Enqueue(job);
                }
            }
        }
        else if (buildMode == BuildMode.FLOOR)
        {
            // We are in tile-changing mode.
            ////t.Type = buildModeTile;

            TileType tileType = buildModeTile;

            if (
                tile.Type != tileType &&
                tile.Furniture == null &&
                tile.PendingBuildJobs.Count == 0 &&
                tileType.CanBuildHere(tile))
            {
                // This tile position is valid tile type

                // Create a job for it to be build
                Job buildingJob = tileType.BuildingJob;

                buildingJob.tile = tile;

                // Add the job to the queue or build immediately if in Dev mode
                if (Settings.GetSetting("DialogBoxSettings_developerModeToggle", false))
                {
                    buildingJob.tile.SetTileType(buildingJob.JobTileType);
                }
                else
                {
                    buildingJob.OnJobStopped += (theJob) => theJob.tile.PendingBuildJobs.Remove(theJob);

                    WorldController.Instance.World.jobQueue.Enqueue(buildingJob);
                }
            }
        }
        else if (buildMode == BuildMode.DECONSTRUCT)
        {
            // TODO
            bool canDeconstructAll = Settings.GetSetting("DialogBoxSettings_developerModeToggle", false);
            if (tile.Furniture != null && (canDeconstructAll || tile.Furniture.HasTypeTag("Non-deconstructible") == false))
            {
                // check if this is a WALL neighbouring a pressured and pressureless environment, and if so, bail
                if (tile.Furniture.HasTypeTag("Wall"))
                {
                    Tile[] neighbors          = tile.GetNeighbours(); // diagOkay??
                    int    pressuredNeighbors = 0;
                    int    vacuumNeighbors    = 0;
                    foreach (Tile neighbor in neighbors)
                    {
                        if (neighbor != null && neighbor.Room != null)
                        {
                            if (neighbor.Room.IsOutsideRoom() || MathUtilities.IsZero(neighbor.Room.GetTotalGasPressure()))
                            {
                                vacuumNeighbors++;
                            }
                            else
                            {
                                pressuredNeighbors++;
                            }
                        }
                    }

                    if (vacuumNeighbors > 0 && pressuredNeighbors > 0)
                    {
                        Debug.ULogChannel("BuildModeController", "Someone tried to deconstruct a wall between a pressurized room and vacuum!");
                        return;
                    }
                }

                tile.Furniture.SetDeconstructJob();
            }
            else if (tile.PendingBuildJobs != null)
            {
                tile.PendingBuildJobs.Last().CancelJob();
            }
            else if (tile.Utilities.Count > 0)
            {
                tile.Utilities.Last().Value.SetDeconstructJob();
            }
        }
        else
        {
            Debug.ULogErrorChannel("BuildModeController", "UNIMPLEMENTED BUILD MODE");
        }
    }