Exemple #1
0
        private static bool SharedValidateQueueIsNotFull(
            ICharacter character,
            RecipeWithSkin recipeEntry,
            ushort countToCraft,
            ushort maxCraftingQueueEntriesCount)
        {
            var characterServerState = PlayerCharacter.GetPrivateState(character);
            var craftingQueueItems   = characterServerState.CraftingQueue.QueueItems;

            if (craftingQueueItems.Count + 1 <= maxCraftingQueueEntriesCount)
            {
                // allow to add the recipe
                return(true);
            }

            foreach (var scheduledQueueItem in craftingQueueItems)
            {
                var macCountToCraft = recipeEntry.Recipe.OutputItems.Items[0].ProtoItem.MaxItemsPerStack;
                if (scheduledQueueItem.CanCombineWith(recipeEntry) &&
                    (int)scheduledQueueItem.CountToCraftRemains + (int)countToCraft <= macCountToCraft)
                {
                    // allow to increase already queued recipe's count
                    return(true);
                }
            }

            Logger.Info("Crafting queue is full", character);

            if (IsClient)
            {
                ClientShowNotificationCraftingQueueIsFull();
            }

            return(false);
        }
Exemple #2
0
        public bool CanCombineWith(RecipeWithSkin recipeEntry)
        {
            if (recipeEntry.Recipe != this.RecipeEntry.Recipe ||
                recipeEntry.ProtoItemSkinOverride is not null ||
                this.RecipeEntry.ProtoItemSkinOverride is not null)
            {
                return(false);
            }

            foreach (var outputItem in this.RecipeEntry.Recipe.OutputItems.Items)
            {
                if (!outputItem.ProtoItem.IsStackable)
                {
                    return(false);
                }
            }

            return(true);
        }
Exemple #3
0
        public static async Task ClientStartCrafting(RecipeWithSkin recipeEntry, ushort countToCraft)
        {
            recipeEntry.Validate();

            if (recipeEntry.ProtoItemSkinOverride is IProtoItemWithSkinData protoItemSkin)
            {
                if (!Client.Microtransactions.IsSkinOwned((ushort)protoItemSkin.SkinId))
                {
                    throw new Exception("The skin is not owned: " + protoItemSkin);
                }
            }

            if (SharedValidateQueueIsNotFull(Client.Characters.CurrentPlayerCharacter,
                                             recipeEntry,
                                             countToCraft,
                                             maxCraftingQueueEntriesCount:
                                             ClientCurrentMaxCraftingQueueEntriesCount))
            {
                await Instance.CallServer(_ => _.ServerRemote_CraftRecipe(recipeEntry, countToCraft));
            }
        }
Exemple #4
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);
        }
Exemple #5
0
 public CraftingQueueItem(RecipeWithSkin recipeEntry, ushort countToCraft, ushort localId)
 {
     this.RecipeEntry         = recipeEntry;
     this.CountToCraftRemains = countToCraft;
     this.LocalId             = localId;
 }
Exemple #6
0
        public bool ServerRemote_CraftRecipe(RecipeWithSkin recipeEntry, ushort countToCraft)
        {
            recipeEntry.Validate();
            var character            = ServerRemoteContext.Character;
            var characterServerState = PlayerCharacter.GetPrivateState(character);

            if (recipeEntry.ProtoItemSkinOverride is IProtoItemWithSkinData protoItemSkin)
            {
                if (!Server.Items.IsSkinOwned(character, (ushort)protoItemSkin.SkinId))
                {
                    throw new Exception("The skin is not owned: " + protoItemSkin + " for " + character);
                }
            }

            IStaticWorldObject station;
            var craftingQueue = characterServerState.CraftingQueue;

            switch (recipeEntry.Recipe)
            {
            case Recipe.RecipeForHandCrafting:
                // simply craft by character
                station = null;
                break;

            case Recipe.RecipeForStationCrafting recipeForStation:
                station = SharedFindNearbyStationOfTypes(recipeForStation.StationTypes, character);
                if (station is null)
                {
                    Logger.Error(
                        $"No crafting stations of types {recipeForStation.StationTypes.GetJoinedString()} found nearby character {character} at position {character.Position}");
                    return(false);
                }

                break;

            default:
                throw new Exception("Incorrect recipe for in-hand or station crafting: " + recipeEntry);
            }

            // extra check (it's also done in the recipe itself)
            if (!recipeEntry.Recipe.SharedIsTechUnlocked(character))
            {
                // locked recipe
                return(false);
            }

            var maxCraftingQueueEntriesCount = SharedGetMaxCraftingQueueEntriesCount(character);

            if (recipeEntry.Recipe.OutputItems.Items[0].ProtoItem.IsStackable)
            {
                // stackable items
                if (!SharedValidateQueueIsNotFull(character, recipeEntry, countToCraft, maxCraftingQueueEntriesCount))
                {
                    return(false);
                }

                CraftingMechanics.ServerStartCrafting(station,
                                                      character,
                                                      craftingQueue,
                                                      recipeEntry,
                                                      countToCraft,
                                                      maxQueueSize: maxCraftingQueueEntriesCount);
            }
            else
            {
                // non-stackable items
                countToCraft = MathHelper.Clamp(countToCraft,
                                                min: (ushort)1,
                                                max: maxCraftingQueueEntriesCount);
                for (var i = 0; i < countToCraft; i++)
                {
                    if (!SharedValidateQueueIsNotFull(character,
                                                      recipeEntry,
                                                      countToCraft: 1,
                                                      maxCraftingQueueEntriesCount))
                    {
                        return(false);
                    }

                    CraftingMechanics.ServerStartCrafting(station,
                                                          character,
                                                          craftingQueue,
                                                          recipeEntry,
                                                          countToCraft: 1,
                                                          maxQueueSize: maxCraftingQueueEntriesCount);
                }
            }

            return(true);
        }