Example #1
0
        private void ServerRemote_SelectRecipe(IStaticWorldObject worldObject, Recipe recipe)
        {
            var character = ServerRemoteContext.Character;

            if (worldObject is null ||
                worldObject.ProtoWorldObject != this ||
                !this.SharedCanInteract(character, worldObject, writeToLog: true))
            {
                // player is too far from the world object or world object is destroyed
                return;
            }

            if (!recipe.SharedIsTechUnlocked(character))
            {
                throw new Exception("Cannot select locked recipe: " + recipe);
            }

            var statePrivate       = GetPrivateState(worldObject);
            var manufacturingState = statePrivate.ManufacturingState;

            ManufacturingMechanic.SelectRecipe(
                recipe,
                worldObject,
                manufacturingState,
                this.ManufacturingConfig);

            // reset fuel container hash - to ensure the fuel will refresh as soon as possible
            if (statePrivate.FuelBurningState is not null)
            {
                statePrivate.FuelBurningState.ContainerFuelLastStateHash = 0;
            }
        }
Example #2
0
        public static void UpdateWithManufacturing(
            IStaticWorldObject worldObject,
            LiquidContainerState liquidContainerState,
            LiquidContainerConfig liquidContainerConfig,
            ManufacturingState manufacturingState,
            ManufacturingConfig manufacturingConfig,
            double deltaTime,
            bool isProduceLiquid,
            bool forceUpdateRecipe = false)
        {
            ManufacturingMechanic.UpdateRecipeOnly(
                worldObject,
                manufacturingState,
                manufacturingConfig,
                force: forceUpdateRecipe);

            var isUseRequested = manufacturingState.HasActiveRecipe;

            UpdateWithoutManufacturing(
                liquidContainerState,
                liquidContainerConfig,
                deltaTime,
                isProduceLiquid,
                isUseRequested,
                out var wasUsed);

            if (wasUsed)
            {
                ManufacturingMechanic.UpdateCraftingQueueOnly(
                    manufacturingState,
                    deltaTime);
            }
        }
        protected override void ServerUpdate(ServerUpdateData data)
        {
            var privateState       = data.PrivateState;
            var manufacturingState = privateState.ManufacturingState;
            var worldObject        = data.GameObject;

            // update active recipe
            ManufacturingMechanic.UpdateRecipeOnly(
                worldObject,
                manufacturingState,
                this.ManufacturingConfig);

            var hasActiveRecipe = manufacturingState.HasActiveRecipe;

            bool isActive;
            var  fuelBurningState = privateState.FuelBurningState;

            if (fuelBurningState == null)
            {
                // no fuel burning state - always active
                isActive = true;
            }
            else
            {
                // progress fuel burning
                FuelBurningMechanic.Update(
                    worldObject,
                    fuelBurningState,
                    privateState.FuelBurningByproductsQueue,
                    this.ManufacturingConfig,
                    data.DeltaTime,
                    isNeedFuelNow: hasActiveRecipe &&
                    !manufacturingState.CraftingQueue.IsContainerOutputFull);

                // active only when fuel is burning
                isActive = fuelBurningState.FuelUseTimeRemainsSeconds > 0;
            }

            data.PublicState.IsManufacturingActive = isActive;

            if (isActive &&
                hasActiveRecipe)
            {
                // progress crafting
                ManufacturingMechanic.UpdateCraftingQueueOnly(
                    manufacturingState,
                    data.DeltaTime);

                // it's important to synchronize this property here
                // (because rollback might happen due to unable to spawn output items and container hash will be changed)
                // TODO: this is hack and we need a better way to track whether the container was actually changed or a better way to update the last state hash.
                manufacturingState.ContainerOutputLastStateHash
                    = manufacturingState.CraftingQueue.ContainerOutputLastStateHash;
            }
        }
Example #4
0
        public static void UpdateWithManufacturing(
            IStaticWorldObject worldObject,
            LiquidContainerState liquidContainerState,
            LiquidContainerConfig liquidContainerConfig,
            ManufacturingState manufacturingState,
            ManufacturingConfig manufacturingConfig,
            double deltaTime,
            bool isProduceLiquid,
            bool forceUpdateRecipe = false)
        {
            ManufacturingMechanic.UpdateRecipeOnly(
                worldObject,
                manufacturingState,
                manufacturingConfig,
                force: forceUpdateRecipe);

            var isUseRequested = manufacturingState.HasActiveRecipe;

            var wasFull = liquidContainerState.Amount >= liquidContainerConfig.Capacity;

            UpdateWithoutManufacturing(
                liquidContainerState,
                liquidContainerConfig,
                deltaTime,
                isProduceLiquid,
                isUseRequested,
                out var wasUsed);

            if (!wasFull &&
                liquidContainerState.Amount >= liquidContainerConfig.Capacity)
            {
                /* Note: This is a special workaround for oil pump.
                 * The problem with it is that it becomes inactive (IsActive set to false) for single server update
                 * once the full capacity is reached. With this workaround we're forcing it to refresh the recipe
                 * that will in turn update the crafting queue and produce the output without interruption. */

                // became full, update the recipe
                ManufacturingMechanic.UpdateRecipeOnly(
                    worldObject,
                    manufacturingState,
                    manufacturingConfig,
                    force: forceUpdateRecipe);

                // force crafting system update
                wasUsed = true;
            }

            if (wasUsed)
            {
                ManufacturingMechanic.UpdateCraftingQueueOnly(
                    manufacturingState,
                    deltaTime);
            }
        }
Example #5
0
        protected override void ServerUpdate(ServerUpdateData data)
        {
            var privateState         = data.PrivateState;
            var publicState          = data.PublicState;
            var liquidContainerState = privateState.LiquidState;

            var isFull = liquidContainerState.Amount >= this.LiquidContainerConfig.Capacity;

            ManufacturingMechanic.UpdateRecipeOnly(
                data.GameObject,
                privateState.ManufacturingState,
                this.ManufacturingConfig,
                force: !isFull);

            ManufacturingMechanic.UpdateCraftingQueueOnly(
                privateState.ManufacturingState,
                deltaTime: data.DeltaTime);

            // refill liquid
            LiquidContainerSystem.UpdateWithoutManufacturing(
                liquidContainerState,
                this.LiquidContainerConfig,
                data.DeltaTime,
                isProduceLiquid: false,
                wasUsed: out _,
                isUseRequested: publicState.IsActive,
                resetAmountToZeroWhenNotEnoughToUse: true);

            var isActive = publicState.ElectricityProducerState == ElectricityProducerState.PowerOnActive &&
                           privateState.LiquidState.Amount > 0;
            var fuelBurningState = privateState.FuelBurningState;

            if (fuelBurningState is not null)
            {
                // progress fuel burning
                FuelBurningMechanic.Update(
                    data.GameObject,
                    fuelBurningState,
                    privateState.FuelBurningByproductsQueue,
                    this.ManufacturingConfig,
                    data.DeltaTime,
                    byproductsQueueRate: 1,
                    isNeedFuelNow: publicState.ElectricityProducerState == ElectricityProducerState.PowerOnActive &&
                    privateState.LiquidState.Amount > 0);

                // active only when fuel is burning
                isActive = fuelBurningState.FuelUseTimeRemainsSeconds > 0;
            }

            publicState.IsActive = isActive;
        }
        protected override void ServerUpdate(ServerUpdateData data)
        {
            base.ServerUpdate(data);

            var worldObject        = data.GameObject;
            var privateState       = data.PrivateState;
            var manufacturingState = privateState.ManufacturingState;

            // fill the water storage via the manufacturing mechanic
            ManufacturingMechanic.Update(
                worldObject,
                manufacturingState,
                this.manufacturingConfig,
                data.DeltaTime);

            if (privateState.NextWateringTime == double.MaxValue)
            {
                return;
            }

            if (data.PublicState.ElectricityConsumerState == ElectricityConsumerState.PowerOff)
            {
                privateState.NextWateringTime = double.MaxValue;
                return;
            }

            if (Server.Game.FrameTime < privateState.NextWateringTime)
            {
                return;
            }

            // time to water!
            if (data.PublicState.ElectricityConsumerState != ElectricityConsumerState.PowerOnActive)
            {
                // but the structure is idle - postpone till the next interval
                privateState.NextWateringTime = Server.Game.FrameTime + WateringIntervalSeconds;
                return;
            }

            this.ServerTryWaterNow(worldObject);
        }
Example #7
0
        protected override void ServerUpdate(ServerUpdateData data)
        {
            var privateState       = data.PrivateState;
            var manufacturingState = privateState.ManufacturingState;
            var worldObject        = data.GameObject;

            // update active recipe
            ManufacturingMechanic.UpdateRecipeOnly(
                worldObject,
                manufacturingState,
                this.ManufacturingConfig);

            var hasActiveRecipe = manufacturingState.HasActiveRecipe;

            var isActive         = false;
            var fuelBurningState = privateState.FuelBurningState;

            if (fuelBurningState is null)
            {
                // no fuel burning state
                if (this.ElectricityConsumptionPerSecondWhenActive <= 0)
                {
                    // no fuel burning and no electricity consumption - always active
                    isActive = true;
                }
                else
                {
                    // Consuming electricity.
                    // Active only if electricity state is on and has active recipe.
                    var publicState = data.PublicState;
                    if (publicState.ElectricityConsumerState == ElectricityConsumerState.PowerOnActive)
                    {
                        isActive = hasActiveRecipe &&
                                   !manufacturingState.CraftingQueue.IsContainerOutputFull;
                    }
                }
            }
            else
            {
                // progress fuel burning
                FuelBurningMechanic.Update(
                    worldObject,
                    fuelBurningState,
                    privateState.FuelBurningByproductsQueue,
                    this.ManufacturingConfig,
                    deltaTime: data.DeltaTime,
                    byproductsQueueRate: StructureConstants.ManufacturingSpeedMultiplier,
                    isNeedFuelNow: hasActiveRecipe &&
                    !manufacturingState.CraftingQueue.IsContainerOutputFull);

                // active only when fuel is burning
                isActive = fuelBurningState.FuelUseTimeRemainsSeconds > 0;
            }

            data.PublicState.IsActive = isActive;

            if (isActive &&
                hasActiveRecipe)
            {
                // progress crafting
                ManufacturingMechanic.UpdateCraftingQueueOnly(
                    manufacturingState,
                    deltaTime: data.DeltaTime
                    * StructureConstants.ManufacturingSpeedMultiplier
                    * this.ManufacturingSpeedMultiplier);

                // it's important to synchronize this property here
                // (because rollback might happen due to unable to spawn output items and container hash will be changed)
                // TODO: this is hack and we need a better way to track whether the container was actually changed or a better way to update the last state hash.
                manufacturingState.ContainerOutputLastStateHash
                    = manufacturingState.CraftingQueue.ContainerOutputLastStateHash;
            }
        }
Example #8
0
        protected override void ServerUpdate(ServerUpdateData data)
        {
            var worldObject  = data.GameObject;
            var deltaTime    = data.DeltaTime;
            var privateState = data.PrivateState;
            var manufacturingStateRawPetroleum = data.PrivateState.ManufacturingState;
            var manufacturingStateGasoline     = data.PrivateState.ManufacturingStateGasoline;
            var manufacturingStateMineralOil   = data.PrivateState.ManufacturingStateMineralOil;
            var liquidStateRawPetroleum        = privateState.LiquidStateRawPetroleum;
            var liquidStateGasoline            = privateState.LiquidStateGasoline;
            var liquidStateMineralOil          = privateState.LiquidStateMineralOil;

            // Force update all recipes:
            // it will auto-detect and verify current recipes for every crafting queue.
            var isLiquidStatesChanged = privateState.IsLiquidStatesChanged;

            ManufacturingMechanic.UpdateRecipeOnly(
                worldObject,
                manufacturingStateRawPetroleum,
                this.ManufacturingConfig,
                force: isLiquidStatesChanged);

            ManufacturingMechanic.UpdateRecipeOnly(
                worldObject,
                manufacturingStateGasoline,
                this.ManufacturingConfigGasoline,
                force: isLiquidStatesChanged);

            ManufacturingMechanic.UpdateRecipeOnly(
                worldObject,
                manufacturingStateMineralOil,
                this.ManufacturingConfigMineralOil,
                force: isLiquidStatesChanged);

            privateState.IsLiquidStatesChanged = false;

            // Update fuel state:
            // need fuel when any of the output liquids capacity are not full
            // or any of the manufacturing states has active recipe.
            var isOutputLiquidCapacityFull
                = liquidStateGasoline.Amount >= this.LiquidConfigGasoline.Capacity ||
                  liquidStateMineralOil.Amount >= this.LiquidConfigMineralOil.Capacity;

            var isNeedElectricityNow = !isOutputLiquidCapacityFull &&
                                       liquidStateRawPetroleum.Amount > 0;

            // Consuming electricity.
            // Active only if electricity state is on and has active recipe.
            var isActive    = false;
            var publicState = data.PublicState;

            if (publicState.ElectricityConsumerState == ElectricityConsumerState.PowerOnActive)
            {
                isActive = isNeedElectricityNow;
            }

            // set IsActive flag in public state - this is used to play sound and animation on client
            data.PublicState.IsActive = isActive;

            // Update crafting queue for raw petroleum:
            // on complete it will consume petroleum canister (if available), increase oil level, produce empty canister.
            ManufacturingMechanic.UpdateCraftingQueueOnly(manufacturingStateRawPetroleum, deltaTime);

            if (isActive) // process liquids (consume raw petroleum and produce gasoline and mineral oil)
            {
                // apply extraction rate multiplier (it applies to oil refinery production rate)
                var deltaTimeLiquidProcessing = deltaTime;
                deltaTimeLiquidProcessing *= RateManufacturingSpeedMultiplier.SharedValue;

                // active, we can "transfer" liquids and progress crafting queues for output liquids
                // try transfer ("use") raw petroleum bar
                LiquidContainerSystem.UpdateWithoutManufacturing(
                    liquidStateRawPetroleum,
                    this.LiquidConfigRawPetroleum,
                    deltaTimeLiquidProcessing,
                    // petroleum is not produced via this system (it's produced on recipe completion)
                    isProduceLiquid: false,
                    // use petroleum liquid if other capacities are not full
                    isUseRequested: !isOutputLiquidCapacityFull,
                    wasUsed: out var wasUsedPetroleum,
                    resetAmountToZeroWhenNotEnoughToUse: true);

                if (wasUsedPetroleum)
                {
                    // increase gasoline level (if possible)
                    LiquidContainerSystem.UpdateWithoutManufacturing(
                        liquidStateGasoline,
                        this.LiquidConfigGasoline,
                        deltaTimeLiquidProcessing,
                        isProduceLiquid: true,
                        isUseRequested: false,
                        wasUsed: out _);

                    // increase mineral oil level (if possible)
                    LiquidContainerSystem.UpdateWithoutManufacturing(
                        liquidStateMineralOil,
                        this.LiquidConfigMineralOil,
                        deltaTimeLiquidProcessing,
                        isProduceLiquid: true,
                        isUseRequested: false,
                        wasUsed: out _);

                    // this flag is required to force recipes checking on next iteration
                    privateState.IsLiquidStatesChanged = true;
                }
            }

            // progress crafting queues for output liquids (craft canisters with according liquids)
            ManufacturingMechanic.UpdateCraftingQueueOnly(manufacturingStateGasoline, deltaTime);
            ManufacturingMechanic.UpdateCraftingQueueOnly(manufacturingStateMineralOil, deltaTime);
        }
Example #9
0
        protected override void ServerUpdate(ServerUpdateData data)
        {
            var privateState         = data.PrivateState;
            var publicState          = data.PublicState;
            var liquidContainerState = privateState.LiquidState;

            var isFull = liquidContainerState.Amount >= this.LiquidContainerConfig.Capacity;

            ManufacturingMechanic.UpdateRecipeOnly(
                data.GameObject,
                privateState.ManufacturingState,
                this.ManufacturingConfig,
                force: !isFull);

            ManufacturingMechanic.UpdateCraftingQueueOnly(
                privateState.ManufacturingState,
                deltaTime: data.DeltaTime);

            // refill liquid
            LiquidContainerSystem.UpdateWithoutManufacturing(
                liquidContainerState,
                this.LiquidContainerConfig,
                data.DeltaTime,
                isProduceLiquid: false,
                wasUsed: out _,
                isUseRequested: privateState.CurrentTemperature >= SteamTemperatureGenerationStart,
                resetAmountToZeroWhenNotEnoughToUse: true);

            var isActive         = privateState.LiquidState.Amount > 0;
            var fuelBurningState = privateState.FuelBurningState;

            if (fuelBurningState != null)
            {
                // progress fuel burning
                FuelBurningMechanic.Update(
                    data.GameObject,
                    fuelBurningState,
                    privateState.FuelBurningByproductsQueue,
                    this.ManufacturingConfig,
                    data.DeltaTime * FuelBurningSpeedMultiplier,
                    byproductsQueueRate: 1,
                    isNeedFuelNow: publicState.ElectricityProducerState == ElectricityProducerState.PowerOnActive &&
                    privateState.LiquidState.Amount > 0);

                // active only when fuel is burning
                isActive = fuelBurningState.FuelUseTimeRemainsSeconds > 0;
            }

            publicState.IsActive = isActive;

            // update the temperature
            var temperature = privateState.CurrentTemperature;

            var delta = isActive
                            ? (float)(SteamTemperatureIncreasePerSecond * data.DeltaTime)
                            : -(float)(SteamTemperatureDecreasePerSecond * data.DeltaTime);

            // apply some variance in temperature gain
            delta *= RandomHelper.Range(0.8f, 1.2f);

            temperature += delta;

            privateState.CurrentTemperature = MathHelper.Clamp(temperature,
                                                               SteamTemperatureMin,
                                                               SteamTemperatureMax);
        }
Example #10
0
        protected override void ServerUpdate(ServerUpdateData data)
        {
            var worldObject      = data.GameObject;
            var deltaTime        = data.DeltaTime;
            var privateState     = data.PrivateState;
            var fuelBurningState = privateState.FuelBurningState;
            var manufacturingStateRawPetroleum        = data.PrivateState.ManufacturingState;
            var manufacturingStateProcessedGasoline   = data.PrivateState.ManufacturingStateGasoline;
            var manufacturingStateProcessedMineralOil = data.PrivateState.ManufacturingStateMineralOil;
            var liquidStateRawPetroleum        = privateState.LiquidStateRawPetroleum;
            var liquidStateProcessedGasoline   = privateState.LiquidStateGasoline;
            var liquidStateProcessedMineralOil = privateState.LiquidStateMineralOil;

            // Force update all recipes:
            // it will auto-detect and verify current recipes for every crafting queue.
            var isLiquidStatesChanged = privateState.IsLiquidStatesChanged;

            ManufacturingMechanic.UpdateRecipeOnly(
                worldObject,
                manufacturingStateRawPetroleum,
                this.ManufacturingConfig,
                force: isLiquidStatesChanged);

            ManufacturingMechanic.UpdateRecipeOnly(
                worldObject,
                manufacturingStateProcessedGasoline,
                this.ManufacturingConfigGasoline,
                force: isLiquidStatesChanged);

            ManufacturingMechanic.UpdateRecipeOnly(
                worldObject,
                manufacturingStateProcessedMineralOil,
                this.ManufacturingConfigMineralOil,
                force: isLiquidStatesChanged);

            privateState.IsLiquidStatesChanged = false;

            // Update fuel state:
            // need fuel when processed liquids capacities are not full
            // or any of the manufacturing states has active recipe.
            var isLiquidsCapacitiesFull = liquidStateProcessedGasoline.Amount
                                          >= this.LiquidConfigGasoline.Capacity &&
                                          liquidStateProcessedMineralOil.Amount
                                          >= this.LiquidConfigMineralOil.Capacity;

            var isNeedFuelNow = (!isLiquidsCapacitiesFull && liquidStateRawPetroleum.Amount > 0) ||
                                manufacturingStateProcessedGasoline.HasActiveRecipe ||
                                manufacturingStateProcessedMineralOil.HasActiveRecipe;

            // update fuel burning progress
            FuelBurningMechanic.Update(
                worldObject,
                fuelBurningState,
                privateState.FuelBurningByproductsQueue,
                this.ManufacturingConfig,
                data.DeltaTime,
                isNeedFuelNow,
                forceRefreshFuel: isLiquidStatesChanged);

            var isFuelBurning = fuelBurningState.FuelUseTimeRemainsSeconds > 0;

            // set IsActive flag in public state - this is used to play sound and animation on client
            data.PublicState.IsManufacturingActive = isFuelBurning;

            // Update crafting queue for raw petroleum:
            // on complete it will consume petroleum canister (if available), increase oil level, produce empty canister.
            ManufacturingMechanic.UpdateCraftingQueueOnly(manufacturingStateRawPetroleum, deltaTime);

            if (!isFuelBurning)
            {
                // cannot progress while fuel is not burning
                return;
            }

            // fuel is burning, we can "transfer" liquids and progress crafting queues for processed liquids
            // try transfer ("use") raw petroleum bar
            LiquidContainerSystem.UpdateWithoutManufacturing(
                liquidStateRawPetroleum,
                this.LiquidConfigRawPetroleum,
                deltaTime,
                // petroleum is not produced via this system (it's produced on recipe completion)
                isProduceLiquid: false,
                // use petroleum liquid if other capacities are not full
                isUseRequested: !isLiquidsCapacitiesFull,
                wasUsed: out var wasUsedPetroleum,
                resetAmountToZeroWhenNotEnoughToUse: true);

            if (wasUsedPetroleum)
            {
                // increase gasoline level (if possible)
                LiquidContainerSystem.UpdateWithoutManufacturing(
                    liquidStateProcessedGasoline,
                    this.LiquidConfigGasoline,
                    deltaTime,
                    isProduceLiquid: true,
                    isUseRequested: false,
                    wasUsed: out _);

                // increase mineral oil level (if possible)
                LiquidContainerSystem.UpdateWithoutManufacturing(
                    liquidStateProcessedMineralOil,
                    this.LiquidConfigMineralOil,
                    deltaTime,
                    isProduceLiquid: true,
                    isUseRequested: false,
                    wasUsed: out _);

                // this flag is required to force recipes checking on next iteration
                privateState.IsLiquidStatesChanged = true;
            }

            // progress crafting queues for processed liquids (craft canisters with according liquids)
            ManufacturingMechanic.UpdateCraftingQueueOnly(manufacturingStateProcessedGasoline, deltaTime);
            ManufacturingMechanic.UpdateCraftingQueueOnly(manufacturingStateProcessedMineralOil, deltaTime);
        }