Пример #1
0
        public void TryAdd(ProtoItemWithCountFractional entry)
        {
            if (!(entry.ProtoItem is IProtoItemFood protoItemFood))
            {
                return;
            }

            this.FoodRestore    += protoItemFood.FoodRestore * entry.Count;
            this.HealthRestore  += protoItemFood.HealthRestore * entry.Count;
            this.StaminaRestore += protoItemFood.StaminaRestore * entry.Count;
            this.WaterRestore   += protoItemFood.WaterRestore * entry.Count;
        }
Пример #2
0
        private static void AddListEntry(
            List <ProtoItemWithCountFractional> list,
            ProtoItemWithCountFractional entry)
        {
            for (var index = 0; index < list.Count; index++)
            {
                var existingEntry = list[index];
                if (!ReferenceEquals(existingEntry.ProtoItem, entry.ProtoItem))
                {
                    continue;
                }

                // entry found - combine them
                list[index] = new ProtoItemWithCountFractional(entry.ProtoItem,
                                                               entry.Count + existingEntry.Count);
                return;
            }

            // entry not found - add new entry
            list.Add(entry);
        }
Пример #3
0
 public ViewModelRequiredItemControl(ProtoItemWithCountFractional protoItemWithCount)
 {
     this.ProtoItemWithCount = protoItemWithCount;
 }
Пример #4
0
        public ViewModelRecipeBreakdown(Recipe recipe)
        {
            var inputItems          = new List <ProtoItemWithCountFractional>();
            var outputItems         = new List <ProtoItemWithCountFractional>();
            var outputItemsExtras   = new List <ProtoItemWithCountFractional>();
            var intermediateRecipes = new List <ViewModelIntermediateRecipe>();
            var inputNutrition      = new NutritionValueInfo();
            var outputNutrition     = new NutritionValueInfo();

            var multiplier = 1 / (double)recipe.OutputItems.Items[0].Count;
            var isOriginalRecipeManufacturing = recipe.RecipeType == RecipeType.Manufacturing ||
                                                recipe.RecipeType == RecipeType.ManufacturingByproduct;

            var    originalRecipeDurationPerItem = recipe.OriginalDuration * multiplier;
            double specificDurationCrafting,
                   specificDurationManufacturing;

            if (isOriginalRecipeManufacturing)
            {
                specificDurationCrafting      = 0;
                specificDurationManufacturing = originalRecipeDurationPerItem;
            }
            else
            {
                specificDurationCrafting      = originalRecipeDurationPerItem;
                specificDurationManufacturing = 0;
            }

            var timeSb = new StringBuilder()
                         .AppendLine($"{recipe.Name} — per single item:")
                         .AppendLine();
            var recursiveErrorsSb = new StringBuilder();
            var tag = isOriginalRecipeManufacturing ? "[manufacture]" : "[craft]";

            timeSb.AppendLine($"{tag} {originalRecipeDurationPerItem:0.##}s — x{multiplier:0.##} {recipe.Name}");

            foreach (var outputItem in recipe.OutputItems.Items)
            {
                var entry = new ProtoItemWithCountFractional(outputItem.ProtoItem,
                                                             outputItem.Count * multiplier);
                outputItems.Add(entry);
                outputNutrition.TryAdd(entry);
            }

            ProcessInputRecursive(recipe, multiplier, depth: 0);

            inputItems.Sort(ListOrderComparison);
            outputItems.Sort(ListOrderComparison);
            outputItemsExtras.Sort(ListOrderComparison);

            this.InputItems          = inputItems;
            this.OutputItems         = outputItems;
            this.OutputItemsExtras   = outputItemsExtras;
            this.IntermediateRecipes = intermediateRecipes;

            this.InputTotalNutritionValue  = inputNutrition;
            this.OutputTotalNutritionValue = outputNutrition;

            this.RecipesDurationTotalText = ClientTimeFormatHelper.FormatTimeDuration(
                specificDurationCrafting,
                roundSeconds: false)
                                            + " + "
                                            + ClientTimeFormatHelper.FormatTimeDuration(
                specificDurationManufacturing,
                roundSeconds: false);

            timeSb.AppendLine()
            .AppendLine($"Total duration: {this.RecipesDurationTotalText} (crafting + manufacturing)");
            this.recipeTimeCalculation = timeSb.ToString().Trim('\r', '\n');

            this.RecursiveErrors = recursiveErrorsSb.Length > 0
                                       ? "Nested recipes recursion detected."
                                   + Environment.NewLine
                                   + "Recursion was broken when looking for recipes for these item(s):"
                                   + Environment.NewLine
                                   + recursiveErrorsSb
                                   + Environment.NewLine
                                   + "Intermediate recipes list:"
                                   + string.Join("",
                                                 this.IntermediateRecipes.Select(
                                                     r => Environment.NewLine
                                                     + "* "
                                                     + r.ViewModelCraftingRecipe.Title))
                                   + Environment.NewLine
                                   + Environment.NewLine
                                   + $"Please edit {nameof(BasicItems)} or {nameof(RecipesHelper.BlacklistRecipes)} lists in {nameof(ViewModelRecipeBreakdown)}.cs (Editor.mpk)"
                                       : null;

            void ProcessInputRecursive(Recipe outerRecipe, double outerMultiplier, int depth)
            {
                foreach (var inputItem in outerRecipe.InputItems)
                {
                    if (BasicItems.Contains(inputItem.ProtoItem.GetType()))
                    {
                        // don't lookup recipe
                        var entry = new ProtoItemWithCountFractional(inputItem.ProtoItem,
                                                                     inputItem.Count * outerMultiplier);
                        AddListEntry(inputItems, entry);
                        inputNutrition.TryAdd(entry);
                        continue;
                    }

                    var inputItemRecipe = RecipesHelper.FindFirstRecipe(inputItem.ProtoItem);
                    if (inputItemRecipe == null)
                    {
                        // no recipe
                        var entry = new ProtoItemWithCountFractional(inputItem.ProtoItem,
                                                                     inputItem.Count * outerMultiplier);
                        AddListEntry(inputItems, entry);
                        inputNutrition.TryAdd(entry);
                        continue;
                    }

                    if (depth > 20)
                    {
                        // recursion went too deep, stop here
                        recursiveErrorsSb.AppendLine("* " + inputItem.ProtoItem.Name);
                        return;
                    }

                    // expand recipe
                    var recipeMultiplier = inputItem.Count / (double)inputItemRecipe.OutputItems.Items[0].Count;
                    AddIntermediateRecipe(intermediateRecipes,
                                          inputItemRecipe,
                                          recipeMultiplier * outerMultiplier);

                    ProcessInputRecursive(inputItemRecipe,
                                          recipeMultiplier * outerMultiplier,
                                          depth: depth + 1);

                    var isManufacturing = inputItemRecipe.RecipeType == RecipeType.Manufacturing ||
                                          inputItemRecipe.RecipeType == RecipeType.ManufacturingByproduct;
                    var inputItemRecipeDuration = inputItemRecipe.OriginalDuration
                                                  * recipeMultiplier
                                                  * outerMultiplier;

                    if (isManufacturing)
                    {
                        specificDurationManufacturing += inputItemRecipeDuration;
                    }
                    else
                    {
                        specificDurationCrafting += inputItemRecipeDuration;
                    }

                    var tag = isManufacturing ? "[manufacture]" : "[craft]";
                    timeSb.AppendLine(
                        $"{tag} {ClientTimeFormatHelper.FormatTimeDuration(inputItemRecipeDuration, roundSeconds: true)} — x{recipeMultiplier * outerMultiplier:0.##} {inputItemRecipe.Name} (for {outerRecipe.Name})");

                    foreach (var outputItem in inputItemRecipe.OutputItems.Items)
                    {
                        if (outputItem.ProtoItem == inputItem.ProtoItem)
                        {
                            continue;
                        }

                        var entry = new ProtoItemWithCountFractional(outputItem.ProtoItem,
                                                                     outputItem.Count
                                                                     * recipeMultiplier
                                                                     * outerMultiplier);
                        AddListEntry(outputItemsExtras, entry);
                        outputNutrition.TryAdd(entry);
                    }
                }
            }
        }
Пример #5
0
 private static int ListOrderComparison(ProtoItemWithCountFractional x, ProtoItemWithCountFractional y)
 {
     return(string.Compare(x.ProtoItem.Id, y.ProtoItem.Id, StringComparison.Ordinal));
 }