Esempio n. 1
0
        public static void RecycleInventoryForAllRecipes(Inventory inventory, Player player)
        {
            var itemListSnapshot = new List <ItemDrop.ItemData>();

            // copy the inventory, otherwise collection will constantly change causing issues
            itemListSnapshot.AddRange(inventory.GetAllItems());
            var analysisList = new List <RecyclingAnalysisContext>();

            for (var index = 0; index < itemListSnapshot.Count; index++)
            {
                var item            = itemListSnapshot[index];
                var analysisContext = new RecyclingAnalysisContext(item);
                analysisList.Add(analysisContext);
                RecycleOneItemInInventory(analysisContext, inventory, player);
            }

            var stringBuilder = new StringBuilder();

            foreach (var analysisContext in analysisList.Where(analysis => analysis.Impediments.Count > 0))
            {
                stringBuilder.AppendLine($"Could not recycle {Plugin.Localize(analysisContext.Item.m_shared.m_name)} " +
                                         $"for {analysisContext.Impediments.Count} reasons:");
                foreach (var impediment in analysisContext.Impediments)
                {
                    stringBuilder.AppendLine(impediment);
                }
            }

            if (stringBuilder.ToString().Length == 0 || !Plugin.Settings.NotifyOnSalvagingImpediments.Value)
            {
                return;
            }
            MessageHud.instance.ShowMessage(MessageHud.MessageType.Center, stringBuilder.ToString());
        }
Esempio n. 2
0
        private static void DoInventoryChanges(RecyclingAnalysisContext analysisContext, Inventory inventory,
                                               Player player, ItemDrop.ItemData item)
        {
            foreach (var entry in analysisContext.Entries)
            {
                var addedItem = inventory.AddItem(
                    entry.prefab.name, entry.amount, entry.mQuality,
                    entry.mVariant, player.GetPlayerID(), player.GetPlayerName()
                    );
                if (addedItem != null)
                {
                    continue;
                }
                Plugin.Log.LogError(
                    "Inventory refused to add item after valid analysis! Check the error from the inventory for details. Will mark analysis for dumping.");
                analysisContext.ShouldErrorDumpAnalysis = true;
                analysisContext.Impediments.Add(
                    $"Inventory could not add item {Plugin.Localize(item.m_shared.m_name)}");
            }

            if (inventory.RemoveItem(item))
            {
                return;
            }
            Plugin.Log.LogError(
                "Inventory refused to add item after valid analysis! Check the error from the inventory for details. Will mark analysis for dumping.");
            analysisContext.ShouldErrorDumpAnalysis = true;
            analysisContext.Impediments.Add($"Inventory could not remove item {Plugin.Localize(item.m_shared.m_name)}");
        }
Esempio n. 3
0
        private static void AnalyzeMaterialYieldForItem(RecyclingAnalysisContext analysisContext, Recipe recipe)
        {
            var recyclingRate = Plugin.Settings.RecyclingRate.Value;
            var itemData      = analysisContext.Item;

            Plugin.Log.LogDebug($"Gathering recycling result for {itemData.m_shared.m_name}");
            var amountToCraftedRecipeAmountPercentage = itemData.m_stack / (double)recipe.m_amount;

            foreach (var resource in recipe.m_resources)
            {
                var rItemData = resource.m_resItem.m_itemData;
                var preFab    = ObjectDB.instance.m_items.FirstOrDefault(item =>
                                                                         item.GetComponent <ItemDrop>().m_itemData.m_shared.m_name == rItemData.m_shared.m_name);
                if (preFab == null)
                {
                    Plugin.Log.LogWarning(
                        $"Could not find a prefab for {itemData.m_shared.m_name}! Won't be able to spawn items. You might want to report this!");
                    analysisContext.Impediments.Add(
                        $"Could not find item {Localization.instance.Localize(itemData.m_shared.m_name)}({itemData.m_shared.m_name})");
                    continue;
                }

                var finalAmount = CalculateFinalAmount(itemData, resource, amountToCraftedRecipeAmountPercentage,
                                                       recyclingRate);
                analysisContext.Entries.Add(
                    new RecyclingAnalysisContext.RecyclingYieldEntry(preFab, finalAmount, rItemData.m_quality,
                                                                     rItemData.m_variant));
                if (Plugin.Settings.PreventZeroResourceYields.Value && finalAmount == 0)
                {
                    analysisContext.Impediments.Add(
                        $"Recycling would yield 0 of {Localization.instance.Localize(resource.m_resItem.m_itemData.m_shared.m_name)}");
                }
            }
        }
Esempio n. 4
0
        private static void AnalyzeInventoryHasEnoughEmptySlots(RecyclingAnalysisContext analysisContext,
                                                                Inventory inventory,
                                                                ItemDrop.ItemData itemData)
        {
            var emptySlotsAmount = inventory.GetEmptySlots();
            var needsSlots       = analysisContext.Entries.Sum(entry =>
                                                               Math.Ceiling(entry.amount /
                                                                            (double)entry.prefab.GetComponent <ItemDrop>().m_itemData.m_shared.m_maxStackSize));

            if (emptySlotsAmount >= needsSlots)
            {
                return;
            }
            analysisContext.Impediments.Add($"Need {needsSlots} slots but only {emptySlotsAmount} were available");
            Plugin.Log.LogDebug($"Not enough slots to recycle {itemData.m_shared.m_name} " +
                                $"(has {emptySlotsAmount} need {needsSlots})");
        }
Esempio n. 5
0
        private static void RecycleOneItemInInventory(RecyclingAnalysisContext analysisContext, Inventory inventory,
                                                      Player player)
        {
            var item = analysisContext.Item;

            if (!TryFindRecipeForItem(analysisContext, player, item, out var recipe))
            {
                return;
            }

            //todo: optimize two .GetComponent<ItemDrop> calls
            AnalyzeMaterialYieldForItem(analysisContext, recipe);
            AnalyzeInventoryHasEnoughEmptySlots(analysisContext, inventory, item);

            if (analysisContext.Impediments.Count > 0)
            {
                return;
            }
            DoInventoryChanges(analysisContext, inventory, player, item);
        }
Esempio n. 6
0
        private static bool TryFindRecipeForItem(RecyclingAnalysisContext analysisContext, Player player,
                                                 ItemDrop.ItemData item,
                                                 out Recipe recipe)
        {
            var foundRecipes = ObjectDB.instance.m_recipes
                               // some recipes are just weird, so check for null item, data and even shared (somehow it happens)
                               .Where(rec => rec?.m_item?.m_itemData?.m_shared?.m_name == item.m_shared.m_name)
                               .ToList();

            if (foundRecipes.Count == 0)
            {
                Plugin.Log.LogDebug($"Could not find a recipe for {item.m_shared.m_name}");
                recipe = null;
                return(false);
            }

            if (foundRecipes.Count > 1)
            {
                analysisContext.Impediments.Add(
                    $"Found multiple recipes ({foundRecipes.Count}) for {Localization.instance.Localize(item.m_shared.m_name)}");
                recipe = null;
                return(false);
            }

            recipe = foundRecipes.FirstOrDefault();
            if (!player.IsRecipeKnown(recipe.m_item.m_itemData.m_shared.m_name))
            {
                analysisContext.Impediments.Add(
                    $"Recipe for {Localization.instance.Localize(item.m_shared.m_name)} not known.");
                Plugin.Log.LogDebug($"Recipe {recipe.name} not known item ({item.m_shared.m_name})");
                recipe = null;
                return(false);
            }

            return(true);
        }