Exemple #1
0
 public override void ServerOnDestroy(IStaticWorldObject gameObject)
 {
     base.ServerOnDestroy(gameObject);
     LandClaimSystem.ServerOnObjectLandClaimDestroyed(gameObject);
 }
Exemple #2
0
        /// <summary>
        /// Enqueue crafting selected recipe.
        /// </summary>
        /// <param name="craftingQueue">Crafting queue instance.</param>
        /// <param name="recipeEntry">Recipe instance.</param>
        /// <param name="countToCraft">Count to craft - must be greater than zero.</param>
        public static void ServerStartCrafting(
            [CanBeNull] IStaticWorldObject station,
            [CanBeNull] ICharacter character,
            [NotNull] CraftingQueue craftingQueue,
            [NotNull] RecipeWithSkin recipeEntry,
            ushort countToCraft,
            ushort?maxQueueSize = null)
        {
            if (station is null &&
                character is null)
            {
                throw new NullReferenceException("Character AND station cannot be null simultaneously");
            }

            if (countToCraft == 0)
            {
                throw new Exception("Are you really want to craft zero items?");
            }

            var isAdminMode = character is not null &&
                              CreativeModeSystem.SharedIsInCreativeMode(character);

            if (!isAdminMode &&
                recipeEntry.Recipe.RecipeType != RecipeType.ManufacturingByproduct &&
                !recipeEntry.Recipe.CanBeCrafted(character,
                                                 station,
                                                 craftingQueue,
                                                 countToCraft: recipeEntry.Recipe.RecipeType == RecipeType.Manufacturing
                                                                 ? (ushort)1
                                                                 : countToCraft))
            {
                Logger.Error($"Recipe cannot be crafted - check failed: {recipeEntry} at {station}.", character);
                return;
            }

            var queueCount = craftingQueue.QueueItems.Count;

            if (queueCount > 0)
            {
                foreach (var existingQueueItem in craftingQueue.QueueItems)
                {
                    if (!existingQueueItem.CanCombineWith(recipeEntry))
                    {
                        continue;
                    }

                    // try to increase the count to craft
                    var lastQueueItemCountBefore = existingQueueItem.CountToCraftRemains;

                    var maxCountToCraft       = ushort.MaxValue;
                    var isManufacturingRecipe = recipeEntry.Recipe.RecipeType != RecipeType.Hand &&
                                                recipeEntry.Recipe.RecipeType != RecipeType.StationCrafting;

                    if (!isManufacturingRecipe)
                    {
                        maxCountToCraft = recipeEntry.Recipe.OutputItems.Items[0].ProtoItem.MaxItemsPerStack;
                    }

                    var originalRequestedCountToCraft = countToCraft;
                    var lastQueueItemCountNew         =
                        (ushort)Math.Min(maxCountToCraft, lastQueueItemCountBefore + countToCraft);
                    var canAddCount = lastQueueItemCountNew - lastQueueItemCountBefore;

                    if (canAddCount > 0)
                    {
                        existingQueueItem.CountToCraftRemains = lastQueueItemCountNew;
                        Logger.Info(
                            $"Recipe count extended for crafting: {recipeEntry} at {station}: from x{lastQueueItemCountBefore} to x{countToCraft}",
                            character);

                        ServerDestroyInputItems(craftingQueue,
                                                recipeEntry.Recipe,
                                                countToCraft: (ushort)canAddCount,
                                                isAdminMode);

                        if (isManufacturingRecipe)
                        {
                            return;
                        }

                        var remainingCountToCraft = originalRequestedCountToCraft
                                                    - canAddCount;
                        if (remainingCountToCraft <= 0)
                        {
                            // the last queue item took all the requested items count to craft
                            return;
                        }

                        // last queue item cannot accomodate all the requested count to craft
                        // let's try to add to previous queue item or a new queue item
                        countToCraft = (ushort)remainingCountToCraft;
                    }
                }
            }

            if (maxQueueSize.HasValue &&
                craftingQueue.QueueItems.Count >= maxQueueSize.Value)
            {
                Logger.Info(
                    $"Recipe cannot be queue for crafting due to max queue size limitation: {recipeEntry} at {station} with max queue size {maxQueueSize.Value}.",
                    character);
                return;
            }

            var queueItem = new CraftingQueueItem(recipeEntry, countToCraft, craftingQueue.ServerLastQueueItemLocalId++);

            ServerDestroyInputItems(craftingQueue,
                                    recipeEntry.Recipe,
                                    countToCraft: queueItem.CountToCraftRemains,
                                    isAdminMode);

            craftingQueue.QueueItems.Add(queueItem);
            if (craftingQueue.QueueItems.Count == 1)
            {
                // the added recipe is first in queue - so we will craft it right now
                craftingQueue.SetDurationFromCurrentRecipe();
            }

            Logger.Info($"Recipe queued for crafting: {recipeEntry} at {station}.", character);
        }
 IObjectElectricityStructurePrivateState IProtoObjectElectricityConsumer.GetPrivateState(
     IStaticWorldObject worldObject)
 {
     return(GetPrivateState(worldObject));
 }
        public override float StructurePointsMax => 0; // non-damageable

        public override void ServerApplyDecay(IStaticWorldObject worldObject, double deltaTime)
        {
            // cannot decay
        }
Exemple #5
0
 public virtual double ServerGetDamageToTree(IStaticWorldObject targetObject)
 {
     return(this.DamageToTree);
 }
 public DestroyWallRequest(IStaticWorldObject wallObject, bool isForce)
 {
     this.WallObject = wallObject;
     this.IsForce    = isForce;
 }
 public ObjectMulchboxPrivateState GetMulchboxPrivateState(IStaticWorldObject objectMulchbox)
 {
     return(GetPrivateState(objectMulchbox));
 }
Exemple #8
0
 void IInteractableProtoStaticWorldObject.ServerOnMenuClosed(ICharacter who, IStaticWorldObject worldObject)
 {
 }
 protected virtual IReadOnlyDropItemsList ServerGetLootDroplist(IStaticWorldObject worldObject)
 {
     return(this.LootDroplist);
 }
Exemple #10
0
        BaseUserControlWithWindow IInteractableProtoStaticWorldObject.ClientOpenUI(IStaticWorldObject worldObject)
        {
            var privateState = GetPrivateState(worldObject);

            return(this.ClientOpenUI(worldObject, privateState));
        }
Exemple #11
0
 void IInteractableProtoStaticWorldObject.ServerOnClientInteract(ICharacter who, IStaticWorldObject worldObject)
 {
 }
Exemple #12
0
 protected override bool TestObject(IStaticWorldObject staticWorldObject)
 {
     return(staticWorldObject.ProtoGameObject is IProtoObjectGatherable protoGatherable &&
            protoGatherable.SharedIsCanGather(staticWorldObject) &&
            protoGatherable.SharedCanInteract(CurrentCharacter, staticWorldObject, false));
 }
Exemple #13
0
 protected override void ServerOnLiquidAmountChanged(IStaticWorldObject objectManufacturer)
 {
     // do nothing
 }
Exemple #14
0
 protected override LiquidContainerState GetLiquidState(IStaticWorldObject objectManufacturer)
 {
     return(ProtoObjectWell.GetPrivateState(objectManufacturer)
            .LiquidStateWater);
 }
Exemple #15
0
 public override bool SharedCanInteract(ICharacter character, IStaticWorldObject worldObject, bool writeToLog)
 {
     return(this.SharedIsInsideCharacterInteractionArea(character,
                                                        worldObject,
                                                        writeToLog));
 }
Exemple #16
0
 protected virtual BaseUserControlWithWindow ClientOpenUI(
     IStaticWorldObject worldObject,
     PrivateState privateState)
 {
     return(WindowTrashCan.Show(privateState));
 }
Exemple #17
0
        public ViewModelManufacturingState(
            IStaticWorldObject worldObjectManufacturer,
            ManufacturingState manufacturingState,
            ManufacturingConfig manufacturingConfig)
        {
            this.worldObjectManufacturer = worldObjectManufacturer;
            this.ManufacturingState      = manufacturingState;
            this.ManufacturingConfig     = manufacturingConfig;

            this.ContainerInput  = (IClientItemsContainer)manufacturingState.ContainerInput;
            this.ContainerOutput = (IClientItemsContainer)manufacturingState.ContainerOutput;

            this.CommandBrowseRecipes           = new ActionCommand(this.ExecuteCommandBrowseRecipes);
            this.CommandCloseRecipesBrowser     = new ActionCommand(this.CloseRecipesBrowser);
            this.CommandSelectRecipeFromBrowser =
                new ActionCommandWithParameter(this.ExecuteCommandSelectRecipeFromBrowser);
            this.CommandApplyBestMatchingRecipe = new ActionCommand(this.ExecuteCommandApplyBestMatchingRecipe);

            this.VisibilityRecipesSelection = manufacturingConfig.IsAutoSelectRecipe
                                                  ? Visibility.Collapsed
                                                  : Visibility.Visible;

            this.SelectedRecipe = manufacturingState.SelectedRecipe;
            //this.BestMatchingRecipe = manufacturingState.BestMatchingRecipe;

            this.RefreshCraftingProgressPercents();

            this.ManufacturingState.ClientSubscribe(
                _ => _.SelectedRecipe,
                recipe => this.SelectedRecipe = recipe,
                this);

            //this.ManufacturingState.ClientSubscribe(
            //    _ => _.BestMatchingRecipe,
            //    recipe => this.BestMatchingRecipe = recipe,
            //    this);

            this.ManufacturingState.CraftingQueue.ClientSubscribe(
                _ => _.IsContainerOutputFull,
                _ => this.NotifyPropertyChanged(nameof(this.IsContainerOutputFull)),
                this);

            this.craftingQueue = this.ManufacturingState.CraftingQueue.QueueItems;
            this.craftingQueue.ClientAnyModification
                += this.CraftingQueueAnyModificationHandler;

            this.ManufacturingState.CraftingQueue.ClientSubscribe(
                _ => _.TimeRemainsToComplete,
                time => this.RefreshCraftingProgressPercents(),
                this);

            // register containers exchange
            var character = Client.Characters.CurrentPlayerCharacter;

            ClientContainersExchangeManager.Register(
                this,
                this.ManufacturingState.ContainerOutput,
                allowedTargets: new[]
            {
                character.SharedGetPlayerContainerInventory(),
                character.SharedGetPlayerContainerHotbar()
            });

            ClientContainersExchangeManager.Register(
                this,
                this.ManufacturingState.ContainerInput,
                allowedTargets: new[]
            {
                character.SharedGetPlayerContainerInventory(),
                character.SharedGetPlayerContainerHotbar()
            });

            this.ContainerInput.StateHashChanged += this.ContainerInputStateChangedHandler;

            this.RefreshIsInputMatchSelectedRecipe();
            this.RefreshBestMatchingRecipe();
        }
        /// <summary>
        /// Bomberman-style explosion penetrating the walls in a cross.
        /// </summary>
        public static void ServerProcessExplosionBomberman(
            Vector2D positionEpicenter,
            IPhysicsSpace physicsSpace,
            int damageDistanceFullDamage,
            int damageDistanceMax,
            double damageDistanceDynamicObjectsOnly,
            WeaponFinalCache weaponFinalCache,
            Func <double, double> callbackCalculateDamageCoefByDistanceForStaticObjects,
            Func <double, double> callbackCalculateDamageCoefByDistanceForDynamicObjects)
        {
            var protoObjectExplosive = weaponFinalCache.ProtoObjectExplosive;

            Api.Assert(protoObjectExplosive != null,
                       "Weapon final cache should contain the exploded object");

            Api.Assert(damageDistanceMax >= damageDistanceFullDamage,
                       $"{nameof(damageDistanceMax)} must be >= {nameof(damageDistanceFullDamage)}");

            var world          = Api.Server.World;
            var damagedObjects = new HashSet <IWorldObject>();

            ProcessExplosionDirection(-1, 0); // left
            ProcessExplosionDirection(0, 1);  // top
            ProcessExplosionDirection(1, 0);  // right
            ProcessExplosionDirection(0, -1); // bottom

            ServerProcessExplosionCircle(positionEpicenter,
                                         physicsSpace,
                                         damageDistanceDynamicObjectsOnly,
                                         weaponFinalCache,
                                         damageOnlyDynamicObjects: true,
                                         callbackCalculateDamageCoefByDistance:
                                         callbackCalculateDamageCoefByDistanceForDynamicObjects);

            void ProcessExplosionDirection(int xOffset, int yOffset)
            {
                var fromPosition = positionEpicenter.ToVector2Ushort();

                for (var offsetIndex = 1; offsetIndex <= damageDistanceMax; offsetIndex++)
                {
                    var tile = world.GetTile(fromPosition.X + offsetIndex * xOffset,
                                             fromPosition.Y + offsetIndex * yOffset,
                                             logOutOfBounds: false);

                    if (!tile.IsValidTile ||
                        tile.IsCliff)
                    {
                        return;
                    }

                    var tileStaticObjects            = tile.StaticObjects;
                    IStaticWorldObject damagedObject = null;
                    foreach (var staticWorldObject in tileStaticObjects)
                    {
                        if (staticWorldObject.ProtoGameObject is IProtoObjectWall ||
                            staticWorldObject.ProtoGameObject is IProtoObjectDoor)
                        {
                            // damage only walls and doors
                            damagedObject = staticWorldObject;
                            break;
                        }
                    }

                    if (damagedObject == null)
                    {
                        // no wall or door there
                        if (offsetIndex > damageDistanceFullDamage)
                        {
                            // stop damage propagation
                            return;
                        }

                        continue;
                    }

                    if (!damagedObjects.Add(damagedObject))
                    {
                        // the object is already damaged
                        // (from another direction which might be theoretically possible in some future cases)
                        continue;
                    }

                    var distanceToDamagedObject = offsetIndex;
                    var damageMultiplier        =
                        callbackCalculateDamageCoefByDistanceForStaticObjects(distanceToDamagedObject);
                    damageMultiplier = MathHelper.Clamp(damageMultiplier, 0, 1);

                    var damageableProto = (IDamageableProtoWorldObject)damagedObject.ProtoGameObject;
                    damageableProto.SharedOnDamage(
                        weaponFinalCache,
                        damagedObject,
                        damageMultiplier,
                        out _,
                        out _);
                }
            }
        }
 protected override void ClientDeinitializeStructure(IStaticWorldObject gameObject)
 {
     base.ClientDeinitializeStructure(gameObject);
     this.clientBlendHelper.Update(gameObject.OccupiedTile);
 }
Exemple #20
0
 public override string ClientGetTitle(IStaticWorldObject worldObject)
 {
     return(this.Name);
 }
 protected override ITextureResource ClientGetTextureResource(
     IStaticWorldObject gameObject,
     StaticObjectPublicState publicState)
 {
     return(this.DefaultTexture);
 }
Exemple #22
0
 public virtual void ServerOnBuilt(IStaticWorldObject structure, ICharacter byCharacter)
 {
 }
 public override bool SharedCanInteract(ICharacter character, IStaticWorldObject worldObject, bool writeToLog)
 {
     return(false);
 }
Exemple #24
0
 public virtual float SharedGetStructurePointsMax(IStaticWorldObject worldObject)
 => this.StructurePointsMax;
Exemple #25
0
 public override bool SharedIsCanGather(IStaticWorldObject staticWorldObject)
 {
     return(GetPublicState(staticWorldObject).HasHarvest);
 }
Exemple #26
0
 protected virtual void ClientDeinitializeStructure(IStaticWorldObject gameObject)
 {
 }
Exemple #27
0
        private static void TeleportToBed(ICharacter character, IStaticWorldObject bedObject)
        {
            var bedPosition = bedObject.TilePosition.ToVector2D()
                              + bedObject.ProtoStaticWorldObject.Layout.Center;

            var neighborTiles = bedObject.OccupiedTiles
                                .SelectMany(t => t.EightNeighborTiles)
                                .Concat(bedObject.OccupiedTiles)
                                .Distinct()
                                .ToList();

            neighborTiles.Shuffle();

            var bedTileHeight = bedObject.OccupiedTile.Height;

            neighborTiles.SortBy(t => t.Position.ToVector2D()
                                 .DistanceSquaredTo(bedPosition));
            var physicsSpace = Server.World.GetPhysicsSpace();

            foreach (var neighborTile in neighborTiles)
            {
                if (neighborTile.Height != bedTileHeight)
                {
                    continue;
                }

                var spawnPosition = neighborTile.Position.ToVector2D() + (0.5, 0.5);
                using (var objectsNearby = physicsSpace.TestCircle(
                           spawnPosition,
                           radius: 0.5,
                           collisionGroup: CollisionGroups.Default))
                {
                    if (objectsNearby.Count > 0)
                    {
                        // invalid tile - obstacles
                        continue;
                    }
                }

                if (!LandClaimSystem.SharedIsPositionInsideOwnedOrFreeArea(neighborTile.Position,
                                                                           character,
                                                                           requireFactionPermission: false))
                {
                    // invalid tile - it's claimed by another player
                    continue;
                }

                // valid tile found - respawn here
                // ensure the character has quit the current vehicle
                VehicleSystem.ServerCharacterExitCurrentVehicle(character, force: true);
                if (PlayerCharacter.GetPublicState(character).CurrentVehicle is not null)
                {
                    Logger.Important($"{character} cannot be teleported to bed as it cannot exit the current vehicle");
                    return;
                }

                Server.World.SetPosition(character, spawnPosition);
                Logger.Important($"{character} teleported to bed {bedObject}");
                return;
            }

            Logger.Important($"{character} cannot be teleported to bed {bedObject}");
        }
Exemple #28
0
 public void Setup(IStaticWorldObject worldObjectMeteorite)
 {
     this.lastWorldObjectMeteorite = worldObjectMeteorite;
     this.RefreshViewModel();
 }
 IObjectElectricityConsumerPublicState IProtoObjectElectricityConsumer.GetPublicState(
     IStaticWorldObject worldObject)
 {
     return(GetPublicState(worldObject));
 }
Exemple #30
0
 public sealed override void ServerOnBuilt(IStaticWorldObject structure, ICharacter byCharacter)
 {
     base.ServerOnBuilt(structure, byCharacter);
     LandClaimSystem.ServerOnObjectLandClaimBuilt(byCharacter, structure);
 }