コード例 #1
0
 protected virtual void ServerUpdateInstalledImplant(ServerUpdateData data)
 {
 }
コード例 #2
0
 protected override void ServerUpdate(ServerUpdateData data)
 {
     this.ServerTryConsumeInputItem(data.PrivateState);
     base.ServerUpdate(data);
 }
コード例 #3
0
        protected override void ServerUpdate(ServerUpdateData data)
        {
            var worldObject           = data.GameObject;
            var privateState          = data.PrivateState;
            var objectDepletedDeposit =
                ObjectDepletedDeposit.SharedGetDepletedDepositWorldObject(worldObject.OccupiedTile);
            var objectDeposit = this.SharedGetDepositWorldObject(worldObject.OccupiedTile);

            var fuelBurningState = privateState.FuelBurningState;

            if (objectDepletedDeposit is not null)
            {
                // this is a depleted deposit - stop extraction
                data.PublicState.IsActive = false;
                privateState.LiquidContainerState.Amount = 0;
                if (fuelBurningState is not null)
                {
                    fuelBurningState.FuelUseTimeRemainsSeconds = 0;
                }

                return;
            }

            var isActive = false;
            var isFull   = privateState.LiquidContainerState.Amount >= this.LiquidContainerConfig.Capacity;

            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 = !isFull;
                    }
                }
            }
            else
            {
                // Please note: fuel is used only to produce oil.
                // Fuel is not used for "petroleum canister" crafting.
                FuelBurningMechanic.Update(
                    worldObject,
                    fuelBurningState,
                    byproductsCraftQueue: null,
                    this.ManufacturingConfig,
                    data.DeltaTime * FuelBurningSpeedMultiplier,
                    byproductsQueueRate: 1,
                    isNeedFuelNow: !isFull);

                var isFuelBurning = fuelBurningState.FuelUseTimeRemainsSeconds > 0;
                isActive = isFuelBurning;
            }

            data.PublicState.IsActive = isActive;

            LiquidContainerSystem.UpdateWithManufacturing(
                worldObject,
                data.PrivateState.LiquidContainerState,
                this.LiquidContainerConfig,
                data.PrivateState.ManufacturingState,
                this.ManufacturingConfig,
                data.DeltaTime * SharedGetSpeedMultiplier(objectDeposit),
                // the pump produce petroleum only when active
                isProduceLiquid: data.PublicState.IsActive,
                forceUpdateRecipe: true);
        }
コード例 #4
0
 protected override void ServerUpdate(ServerUpdateData data)
 {
     //var character = data.GameObject;
     //this.SharedApplyInput(character, data.PrivateState);
 }
コード例 #5
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 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 any of the output liquids capacity are not full
            // or any of the manufacturing states has active recipe.
            var isOutputLiquidCapacityFull
                = liquidStateProcessedGasoline.Amount >= this.LiquidConfigGasoline.Capacity ||
                  liquidStateProcessedMineralOil.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 *= StructureConstants.ManufacturingSpeedMultiplier;

                // active, we can "transfer" liquids and progress crafting queues for processed 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(
                        liquidStateProcessedGasoline,
                        this.LiquidConfigGasoline,
                        deltaTimeLiquidProcessing,
                        isProduceLiquid: true,
                        isUseRequested: false,
                        wasUsed: out _);

                    // increase mineral oil level (if possible)
                    LiquidContainerSystem.UpdateWithoutManufacturing(
                        liquidStateProcessedMineralOil,
                        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 processed liquids (craft canisters with according liquids)
            ManufacturingMechanic.UpdateCraftingQueueOnly(manufacturingStateProcessedGasoline, deltaTime);
            ManufacturingMechanic.UpdateCraftingQueueOnly(manufacturingStateProcessedMineralOil, deltaTime);
        }
コード例 #6
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);
        }
コード例 #7
0
        protected override void ServerUpdate(ServerUpdateData data)
        {
            var worldObject = data.GameObject;
            var publicState = data.PublicState;

            var itemsContainer = publicState.ItemsContainer;
            var hasItems       = itemsContainer.OccupiedSlotsCount > 0;
            var isTimedOut     = false;

            if (hasItems)
            {
                var timeNow = Server.Game.FrameTime;
                if (publicState.ItemsContainerLastHash
                    != publicState.ItemsContainer.StateHash)
                {
                    // items container updated - try to extend the timeout
                    publicState.DestroyAtTime = Math.Max(publicState.DestroyAtTime,
                                                         timeNow + AutoDestroyTimeoutSeconds);
                    publicState.ItemsContainerLastHash = publicState.ItemsContainer.StateHash;
                }
                else
                {
                    // there are items - check timeout
                    isTimedOut = timeNow >= publicState.DestroyAtTime;
                    if (isTimedOut)
                    {
                        // should destroy because timed out
                        if (Server.World.IsObservedByAnyPlayer(worldObject))
                        {
                            // cannot destroy - there are players observing it
                            isTimedOut = false;
                            publicState.DestroyAtTime = timeNow + AutoDestroyPostponeSeconds;
                        }
                    }
                }

                if (!isTimedOut)
                {
                    return;
                }
            }

            // don't have items or timeout reached
            Logger.Important(
                "Destroying ground container at "
                + worldObject.TilePosition
                + (isTimedOut ? " - timed out" : " - contains no items"));

            if (data.PrivateState.ServerLastInteractCharacter != null)
            {
                // notify other players that the ground items were picked up
                using (var scopedBy = Api.Shared.GetTempList <ICharacter>())
                {
                    Server.World.GetScopedByPlayers(worldObject, scopedBy);
                    scopedBy.Remove(data.PrivateState.ServerLastInteractCharacter);
                    this.CallClient(scopedBy, _ => _.ClientRemote_OtherPlayerPickedUp(worldObject.TilePosition));
                }
            }

            // actually destroy it
            publicState.ItemsContainer = null;
            Server.World.DestroyObject(worldObject);
        }
コード例 #8
0
            public override double ServerUpdateIntervalSeconds => 0; // every frame

            protected override void ServerUpdate(ServerUpdateData data)
            {
                Instance.ServerUpdate();
            }
コード例 #9
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 == 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.PowerOn)
                    {
                        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;
            }
        }
コード例 #10
0
 protected virtual void ServerUpdateMob(ServerUpdateData data)
 {
 }
コード例 #11
0
        protected override void ServerUpdate(ServerUpdateData data)
        {
            base.ServerUpdate(data);

            var objectDrone  = data.GameObject;
            var privateState = data.PrivateState;
            var publicState  = data.PublicState;

            if (privateState.AssociatedItem is null)
            {
                // incorrectly configured drone
                Server.World.DestroyObject(objectDrone);
                return;
            }

            if (privateState.IsDespawned)
            {
                return;
            }

            UpdateWeaponCooldown();

            Vector2D destinationCoordinate;
            var      characterOwner = privateState.CharacterOwner;

            var hasMiningTargets = publicState.TargetObjectPosition.HasValue;

            if (hasMiningTargets &&
                !(CharacterDroneControlSystem.SharedIsValidDroneOperationDistance(objectDrone.TilePosition,
                                                                                  characterOwner.TilePosition) &&
                  objectDrone.Tile.Height == characterOwner.Tile.Height))
            {
                Logger.Info("The drone is beyond operation distance or has different tile height and will be recalled: "
                            + objectDrone);
                CharacterDroneControlSystem.ServerRecallDrone(objectDrone);
                hasMiningTargets = false;
            }

            if (hasMiningTargets)
            {
                // go to the next waypoint
                destinationCoordinate = publicState.TargetDronePosition
                                        ?? publicState.TargetObjectPosition.Value.ToVector2D();

                if (!CharacterDroneControlSystem.ServerIsMiningAllowed(
                        publicState.TargetObjectPosition.Value,
                        objectDrone))
                {
                    // cannot mine as it's already mined by another drone
                    publicState.ResetTargetPosition();
                    return;
                }
            }
            else
            {
                // should return to the player to despawn
                if (characterOwner is null ||
                    characterOwner.GetPublicState <ICharacterPublicState>().IsDead ||
                    CharacterDroneControlSystem.SharedIsBeyondDroneAbandonDistance(
                        objectDrone.TilePosition,
                        characterOwner.TilePosition))
                {
                    CharacterDroneControlSystem.ServerDeactivateDrone(objectDrone);
                    return;
                }

                destinationCoordinate = characterOwner.Position;
            }

            RefreshMovement(isToMineral: hasMiningTargets,
                            destinationCoordinate,
                            out var isDestinationReached);
            if (!isDestinationReached)
            {
                return;
            }

            if (hasMiningTargets)
            {
                PerformMining();
            }
            else
            {
                // we were going to the player and reached its location, despawn
                ServerOnDroneReturnedToPlayer(objectDrone);
            }

            void RefreshMovement(
                bool isToMineral,
                Vector2D toPosition,
                out bool isDestinationReached)
            {
                var positionDelta       = toPosition - objectDrone.Position;
                var positionDeltaLength = positionDelta.Length;

                double targetVelocity;

                if (positionDeltaLength
                    > (isToMineral
                           ? DistanceThresholdToMineral
                           : DistanceThresholdToPlayer))
                {
                    // fly towards that object
                    targetVelocity       = this.StatMoveSpeed;
                    isDestinationReached = false;

                    // reduce speed when too close to the target
                    var distanceCoef = positionDeltaLength / (0.5 * targetVelocity);
                    if (distanceCoef < 1)
                    {
                        targetVelocity *= Math.Pow(distanceCoef, 0.5);
                        // ensure it cannot drop lower than 5% of the original move speed
                        targetVelocity = Math.Max(0.05 * this.StatMoveSpeed, targetVelocity);
                    }
                }
                else
                {
                    isDestinationReached = true;

                    // stop
                    if (Server.World.GetDynamicObjectMoveSpeed(objectDrone) == 0)
                    {
                        // already stopped
                        return;
                    }

                    targetVelocity = 0;
                }

                var movementDirectionNormalized = positionDelta.Normalized;
                var moveAcceleration            = movementDirectionNormalized * this.PhysicsBodyAccelerationCoef * targetVelocity;

                Server.World.SetDynamicObjectMoveSpeed(objectDrone, targetVelocity);

                Server.World.SetDynamicObjectPhysicsMovement(objectDrone,
                                                             moveAcceleration,
                                                             targetVelocity: targetVelocity);
                objectDrone.PhysicsBody.Friction = this.PhysicsBodyFriction;
            }

            void PerformMining()
            {
                var targetObject = CharacterDroneControlSystem.SharedGetCompatibleTarget(
                    characterOwner,
                    publicState.TargetObjectPosition.Value,
                    out _,
                    out _);

                if (targetObject is null ||
                    !WorldObjectClaimSystem.SharedIsAllowInteraction(characterOwner,
                                                                     targetObject,
                                                                     showClientNotification: false))
                {
                    // nothing to mine there, or finished mining, or cannot mine
                    CharacterDroneControlSystem.ServerUnregisterCurrentMining(
                        publicState.TargetObjectPosition.Value,
                        objectDrone);

                    publicState.ResetTargetPosition();
                    return;
                }

                if (privateState.WeaponCooldownSecondsRemains > 0)
                {
                    return;
                }

                if (!CharacterDroneControlSystem.ServerTryRegisterCurrentMining(
                        publicState.TargetObjectPosition.Value,
                        objectDrone))
                {
                    // cannot mine as it's already mined by another drone
                    publicState.ResetTargetPosition();
                    return;
                }

                publicState.IsMining = true;

                var protoMiningTool = this.ProtoItemMiningTool;

                privateState.WeaponCooldownSecondsRemains +=
                    Api.Shared.RoundDurationByServerFrameDuration(protoMiningTool.FireInterval);

                var characterFinalStatsCache = characterOwner.SharedGetFinalStatsCache();

                var weaponFinalCache = privateState.WeaponFinalCache;

                if (weaponFinalCache is null ||
                    !privateState.LastCharacterOwnerFinalStatsCache.CustomEquals(characterFinalStatsCache))
                {
                    weaponFinalCache = ServerCreateWeaponFinalCacheForDrone(characterOwner,
                                                                            protoMiningTool,
                                                                            objectDrone);

                    privateState.WeaponFinalCache = weaponFinalCache;
                    privateState.LastCharacterOwnerFinalStatsCache = characterFinalStatsCache;
                }

                var protoWorldObject = (IDamageableProtoWorldObject)targetObject.ProtoGameObject;

                protoWorldObject.SharedOnDamage(
                    weaponFinalCache,
                    targetObject,
                    damagePreMultiplier: 1,
                    damagePostMultiplier: 1,
                    obstacleBlockDamageCoef: out _,
                    damageApplied: out var damageApplied);

                // reduce drone durability on 1 unit (reflected as HP when it's a world object)
                // but ensure the new HP cannot drop to exact 0 (to prevent destruction while mining)
                var newHP = publicState.StructurePointsCurrent
                            - 1 * LazyProtoItemDrone.Value.DurabilityToStructurePointsConversionCoefficient;

                publicState.StructurePointsCurrent = Math.Max(float.Epsilon, (float)newHP);

                if (damageApplied <= 0)
                {
                    // cannot mine there for whatever reason, recall the drone
                    publicState.ResetTargetPosition();
                }

                this.ServerSendMiningSoundCue(objectDrone, characterOwner);
            }

            void UpdateWeaponCooldown()
            {
                if (privateState.WeaponCooldownSecondsRemains <= 0)
                {
                    return;
                }

                // process weapon cooldown
                var deltaTime = data.DeltaTime;

                if (deltaTime > 0.4)
                {
                    // too large delta time probably due to a frame skip
                    deltaTime = 0.4;
                }

                if (privateState.WeaponCooldownSecondsRemains > 0)
                {
                    privateState.WeaponCooldownSecondsRemains -= deltaTime;
                    if (privateState.WeaponCooldownSecondsRemains < -0.2)
                    {
                        // clamp the remaining cooldown in case of a frame skip
                        privateState.WeaponCooldownSecondsRemains = -0.2;
                    }
                }
            }
        }
コード例 #12
0
        /// <summary>
        /// Return metadata for updates
        /// </summary>
        /// <param name="request">The request; contains IDs for updates to retrieve metadata for</param>
        /// <returns>Update metadata for requested updates</returns>
        public Task <ServerUpdateData> GetUpdateDataAsync(GetUpdateDataRequest request)
        {
            var response = new ServerUpdateData();

            // Make sure the request is not larger than the config says
            var updateRequestCount = request.GetUpdateData.updateIds.Count();

            if (updateRequestCount > ServiceConfiguration.MaxNumberOfUpdatesPerRequest)
            {
                return(null);
            }

            var returnUpdatesList = new List <ServerSyncUpdateData>();
            var returnFilesList   = new List <ServerSyncUrlData>();

            foreach (var rawIdentity in request.GetUpdateData.updateIds)
            {
                var updateIdentity = new Identity(rawIdentity);

                // Find the update; it can be either category or update
                Update update;
                if (!FilteredUpdates.TryGetValue(updateIdentity, out update))
                {
                    if ((update = Categories.First(c => c.Identity.Equals(updateIdentity))) == null)
                    {
                        throw new Exception("Update not found");
                    }
                }

                if (update.HasFiles)
                {
                    // if update contains files, we must also gather file information
                    foreach (var updateFile in update.Files)
                    {
                        returnFilesList.Add(
                            new ServerSyncUrlData()
                        {
                            FileDigest = Convert.FromBase64String(updateFile.Digests[0].DigestBase64),
                            MUUrl      = updateFile.Urls[0].MuUrl,
                            UssUrl     = $"Content/{updateFile.GetContentDirectoryName()}/{updateFile.FileName}"
                        });
                    }
                }

                var rawUpdateData = new ServerSyncUpdateData();
                rawUpdateData.Id = rawIdentity;

                using (var metadataReader = new StreamReader(MetadataSource.GetUpdateMetadataStream(update.Identity)))
                {
                    rawUpdateData.XmlUpdateBlob = metadataReader.ReadToEnd();
                }

                returnUpdatesList.Add(rawUpdateData);
            }

            response.updates = returnUpdatesList.ToArray();

            // Deduplicate list of files
            response.fileUrls = returnFilesList.GroupBy(f => f.MUUrl).Select(k => k.First()).ToArray();

            return(Task.FromResult(response));
        }
コード例 #13
0
        protected override void ServerUpdate(ServerUpdateData data)
        {
            var item         = data.GameObject;
            var privateState = data.PrivateState;

            var character = item.Container.OwnerAsCharacter;

            if (!IsItemSelectedByPlayer(character, item))
            {
                // not a selected player item
                this.ServerSetUpdateRate(item, isRare: true);
                return;
            }

            privateState.ServerTimeToPing -= data.DeltaTime;
            if (privateState.ServerTimeToPing > 0)
            {
                return;
            }

            privateState.ServerTimeToPing = ServerScanInterval;

            if (!CharacterEnergySystem.ServerDeductEnergyCharge(
                    character,
                    requiredEnergyAmount: this.EnergyConsumptionPerSecond * ServerScanInterval))

            {
                // no power
                this.CallClient(character, _ => _.ClientRemote_NoPower());
                return;
            }

            ItemDurabilitySystem.ServerModifyDurability(
                item,
                delta: -(int)Math.Round(this.DurabilityDecreasePerSecond * ServerScanInterval));

            if (item.IsDestroyed)
            {
                // zero durability reached
                return;
            }

            // update signal strength
            using var tempSignalStrength = Api.Shared.GetTempList <byte>();
            this.ServerCalculateStrengthToTheClosestPragmiumSpires(character,
                                                                   tempSignalStrength.AsList(),
                                                                   MaxNumberOfPongsPerScan);

            var previousSignalStrength = -1;

            foreach (var signalStrength in tempSignalStrength.AsList())
            {
                if (signalStrength == previousSignalStrength)
                {
                    // don't send multiple pongs for the signals of the same strength
                    continue;
                }

                previousSignalStrength = signalStrength;

                var serverTimeToPong = SharedCalculateTimeToPong(signalStrength);
                ServerTimersSystem.AddAction(
                    serverTimeToPong,
                    () =>
                {
                    var currentCharacter = item.Container.OwnerAsCharacter;
                    if (IsItemSelectedByPlayer(currentCharacter, item))
                    {
                        this.CallClient(currentCharacter,
                                        _ => _.ClientRemote_OnSignal(item,
                                                                     PragmiumSensorSignalKind.Pong));
                    }
                });

                //Logger.Dev(string.Format("Pragmium scanner signal: {0} strength. Time to send pong: {1} ms.",
                //                         signalStrength,
                //                         (int)(serverTimeToPong * 1000)));
            }

            this.CallClient(character, _ => _.ClientRemote_OnSignal(item, PragmiumSensorSignalKind.Ping));

            bool IsItemSelectedByPlayer(ICharacter c, IItem i)
            => c is not null &&
            ReferenceEquals(i, c.SharedGetPlayerSelectedHotbarItem());
        }
コード例 #14
0
 protected override void ServerUpdate(ServerUpdateData data)
 {
     ItemFreshnessSystem.ServerUpdateFreshness(data.GameObject, data.DeltaTime);
 }
コード例 #15
0
 protected sealed override void ServerUpdate(ServerUpdateData data)
 {
 }
コード例 #16
0
ファイル: PowerGrid.cs プロジェクト: jashking/CryoFall
 protected override void ServerUpdate(ServerUpdateData data)
 {
     PowerGridSystem.ServerUpdateGrid(data.GameObject,
                                      data.PublicState,
                                      data.DeltaTime);
 }
コード例 #17
0
        protected override void ServerUpdateMob(ServerUpdateData data)
        {
            var character   = data.GameObject;
            var publicState = data.PublicState;

            if (publicState.IsDead)
            {
                return;
            }

            var privateState        = data.PrivateState;
            var lastTargetCharacter = privateState.CurrentTargetCharacter;
            var deltaTime           = data.DeltaTime;

            // Regenerate the health points a bit on every frame
            // if there was no damage dealt to boss recently.
            // Please note: the difficulty coefficient doesn't apply there
            // as the boss HP doesn't change with difficulty - only damage
            // to it is modified by the difficulty coefficient.
            if (Server.Game.FrameTime
                >= privateState.LastDamageTime + RegenerationDelaySeconds)
            {
                publicState.CurrentStats.ServerSetHealthCurrent(
                    (float)(publicState.CurrentStats.HealthCurrent
                            + HealthRegenerationPerSecond * deltaTime));
            }

            var weaponList = this.ServerSelectWeaponsList(privateState,
                                                          deltaTime,
                                                          out var isSwitchingToNovaAttack);

            ServerCharacterAiHelper.ProcessBossAi(
                character,
                weaponList,
                distanceEnemyTooClose: 7.5,
                distanceEnemyTooFar: 15.5,
                movementDirection: out var movementDirection,
                rotationAngleRad: out var rotationAngleRad);

            if (movementDirection != default &&
                !ServerCanMoveInDirection(character.TilePosition.ToVector2D(),
                                          movementDirection,
                                          privateState.HoldPosition.ToVector2D()))
            {
                // cannot move in desired direction - too far from the position to hold
                movementDirection = default;
            }

            this.ServerSetMobInput(character, movementDirection, rotationAngleRad);

            if (lastTargetCharacter is null &&
                privateState.CurrentTargetCharacter != null
                // is the last attack happened not too recently?
                && privateState.TimeToNextNovaAttack < NovaAttackInterval.Max - 8)
            {
                //Logger.Dev("Boss acquired target! Will use a nova attack in the next 2-4 seconds!");
                privateState.TimeToNextNovaAttack = RandomHelper.Next(2, 4);
            }

            if (isSwitchingToNovaAttack)
            {
                privateState.WeaponState.SharedSetInputIsFiring(false);
            }
        }
コード例 #18
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);
        }
コード例 #19
0
 protected override void ServerUpdate(ServerUpdateData data)
 {
     base.ServerUpdate(data);
     TradingStationsSystem.ServerUpdate(data.GameObject);
 }
コード例 #20
0
 protected override void ServerUpdate(ServerUpdateData data)
 {
     base.ServerUpdate(data);
     data.PublicState.LiquidType = data.PrivateState.LiquidType;
 }
コード例 #21
0
 protected override void ServerUpdate(ServerUpdateData data)
 {
     FoodSpoilageSystem.ServerUpdateFoodFreshness(data.GameObject, data.DeltaTime);
 }