Beispiel #1
0
        private void UpdateQuantities()
        {
            //  Initialize all quantities back to zero
            foreach (Object Placeholder in Placeholders.SelectMany(x => x.Value.Values))
            {
                Placeholder.Stack = 0;
            }

            //  Set quantities of the placeholder items to match the corresponding amount of the item currently stored in the bag
            foreach (Object Item in Bag.Contents)
            {
                if (Placeholders.TryGetValue(Item.ParentSheetIndex, out Dictionary <ObjectQuality, Object> Group))
                {
                    ObjectQuality Quality = (ObjectQuality)Item.Quality;
                    if (Group.TryGetValue(Quality, out Object Placeholder))
                    {
                        ItemBag.ForceSetQuantity(Placeholder, Item.Stack);

                        if (Placeholder.Price != Item.Price)
                        {
#if DEBUG
                            string WarningMsg = string.Format("Warning - GroupedLayout placeholder item '{0}' does not have a matching price to the corresponding item in the bag."
                                                              + " Placeholder.Price={1}, BagItem.Price={2}", Placeholder.DisplayName, Placeholder.Price, Item.Price);
                            ItemBagsMod.ModInstance.Monitor.Log(WarningMsg, LogLevel.Warn);
#endif
                            Placeholder.Price = Item.Price;
                        }
                    }
                }
            }
        }
Beispiel #2
0
        public Object ToObject()
        {
            if (IsBigCraftable)
            {
                Object Item = new Object(Vector2.Zero, Id, false)
                {
                    Price = this.Price
                };                                                                        // It seems like some modded items don't have their price set properly if not explicitly specified
                ItemBag.ForceSetQuantity(Item, this.Quantity);
                return(Item);
            }
            else
            {
                Object Item = new Object(Id, Quantity, false, Price <= 0 ? -1 : Price, Quality);
                if (!string.IsNullOrEmpty(Name))
                {
                    Item.Name = Name;
                }

                if (this.HoneyType != null)
                {
                    Item.honeyType.Value = (Object.HoneyType) this.HoneyType.Value;
                }
                if (this.PreserveType != null)
                {
                    Item.preserve.Value = (Object.PreserveType) this.PreserveType.Value;
                }
                if (this.PreservedId != int.MinValue)
                {
                    Item.preservedParentSheetIndex.Value = this.PreservedId;
                }

#if DEBUG
                if (Item.Price <= 0 && Item.Price != this.Price)
                {
                    string WarningMsg = string.Format("Warning - Item '{0}' did not have its price set to a non-zero value after being created. Expected Price = {1}, Actual Price = {2}",
                                                      Item.DisplayName, this.Price, Item.Price);
                    ItemBagsMod.ModInstance.Monitor.Log(WarningMsg, StardewModdingAPI.LogLevel.Warn);
                }
#endif

                //  Sanity check in case Stack > 999 and StardewValley is updated to set the Object.Stack in its constructor instead of Object.stack
                //  (Object.Stack has a setter that restricts maximum value to the range 0-999, while Object.stack (the backing Net field) does not)
                if (Item.Stack != Quantity)
                {
                    ItemBag.ForceSetQuantity(Item, Quantity);
                }

                return(Item);
            }
        }
Beispiel #3
0
        private void UpdateQuantities()
        {
            //  Initialize all quantities back to zero
            foreach (Object Placeholder in PlaceholderItems)
            {
                Placeholder.Stack = 0;
            }

            //  Set quantities of the placeholder items to match the corresponding amount of the item currently stored in the bag
            foreach (Object Item in Bag.Contents)
            {
                Object Placeholder = PlaceholderItems.FirstOrDefault(x => ItemBag.AreItemsEquivalent(x, Item, false, true));
                if (Placeholder != null)
                {
                    ItemBag.ForceSetQuantity(Placeholder, Item.Stack);
                }
            }
        }
        private static void OnCraftingPageDeactivated()
        {
            try
            {
                //  If the player had the CraftingPage of the GameMenu opened, they may have crafted items using materials that were inside their bags,
                //  so we must Resynchronize the bag contents in multiplayer
                if (BagsInUse != null && BagsInUse.Any())
                {
                    //  Recombine item Stacks that were split to avoid having > 999
                    if (SplitStacks != null && SplitStacks.Any())
                    {
                        foreach (KeyValuePair <Object, List <Object> > KVP in SplitStacks)
                        {
                            int NewQuantity = KVP.Value.Sum(x => x.Stack);
                            ItemBag.ForceSetQuantity(KVP.Key, NewQuantity);
                        }
                    }

                    foreach (ItemBag Bag in BagsInUse)
                    {
                        if (Bag is OmniBag OB)
                        {
                            foreach (ItemBag NestedBag in OB.NestedBags)
                            {
                                NestedBag.Contents.RemoveAll(x => x == null || x.Stack <= 0);
                            }
                        }
                        else
                        {
                            Bag.Contents.RemoveAll(x => x == null || x.Stack <= 0);
                        }

                        Bag.Resync();
                    }
                }
            }
            finally
            {
                BagsInUse   = null;
                SplitStacks = null;
            }
        }
        /// <summary>Initializes extra data for the Crafting Page so it can search for and use materials within bags in your inventory.</summary>
        private static void OnCraftingPageActivated(CraftingPage CraftingMenu)
        {
            //  Allow the CraftingPage to search for and use items inside of bags
            bool           AllowUsingBundleBagItemsForCrafting = false;
            List <ItemBag> BagsInInventory = Game1.player.Items.Where(x => x != null && x is ItemBag).Cast <ItemBag>().ToList();

            if (BagsInInventory.Any())
            {
                BagsInUse = new HashSet <ItemBag>(BagsInInventory);

                //  Get the "_materialContainers" protected field that defines additional item containers to search for when using up materials during crafting
                IReflectedField <List <Chest> > ReflectionResult = Helper.Reflection.GetField <List <Chest> >(CraftingMenu, "_materialContainers", true);
                List <Chest> MaterialContainers = ReflectionResult.GetValue();
                if (MaterialContainers == null)
                {
                    MaterialContainers = new List <Chest>();
                    ReflectionResult.SetValue(MaterialContainers);
                }

                //  Create a temporary chest from the items of each bag, and add the chest to _materialContainers
                foreach (ItemBag IB in BagsInInventory.Where(x => AllowUsingBundleBagItemsForCrafting || !(x is BundleBag)))
                {
                    //  Note that if the item inside the bag has Stack > 999, it must be split up into chunks with Stacks <= 999
                    //  Because the Game truncates the actual stack down to 999 anytime it modifies a stack value
                    if (IB is OmniBag OB)
                    {
                        foreach (ItemBag NestedBag in OB.NestedBags.Where(x => AllowUsingBundleBagItemsForCrafting || !(x is BundleBag)))
                        {
                            List <Item> TemporaryChestContents = new List <Item>();

                            foreach (Object Item in NestedBag.Contents)
                            {
                                if (Item.Stack > 999)
                                {
                                    if (SplitStacks == null)
                                    {
                                        SplitStacks = new Dictionary <Object, List <Object> >();
                                    }

                                    List <Object> Chunks = new List <Object>();

                                    int TotalStack     = Item.Stack;
                                    int DistributedAmt = 0;
                                    while (DistributedAmt < TotalStack)
                                    {
                                        int    CurrentStackAmt = Math.Min(999, TotalStack - DistributedAmt);
                                        Object Chunk           = ItemBag.CreateCopy(Item);
                                        ItemBag.ForceSetQuantity(Chunk, CurrentStackAmt);
                                        DistributedAmt += CurrentStackAmt;
                                        Chunks.Add(Chunk);
                                    }

                                    SplitStacks.Add(Item, Chunks);
                                    TemporaryChestContents.AddRange(Chunks);
                                }
                                else
                                {
                                    TemporaryChestContents.Add(Item);
                                }
                            }

                            Chest TempChest = new Chest(0, TemporaryChestContents, Vector2.Zero, false, 0);
                            MaterialContainers.Add(TempChest);
                        }
                    }
                    else
                    {
                        List <Item> TemporaryChestContents = new List <Item>();

                        foreach (Object Item in IB.Contents)
                        {
                            if (Item.Stack > 999)
                            {
                                if (SplitStacks == null)
                                {
                                    SplitStacks = new Dictionary <Object, List <Object> >();
                                }

                                List <Object> Chunks = new List <Object>();

                                int TotalStack     = Item.Stack;
                                int DistributedAmt = 0;
                                while (DistributedAmt < TotalStack)
                                {
                                    int    CurrentStackAmt = Math.Min(999, TotalStack - DistributedAmt);
                                    Object Chunk           = ItemBag.CreateCopy(Item);
                                    ItemBag.ForceSetQuantity(Chunk, CurrentStackAmt);
                                    DistributedAmt += CurrentStackAmt;
                                    Chunks.Add(Chunk);
                                }

                                SplitStacks.Add(Item, Chunks);
                                TemporaryChestContents.AddRange(Chunks);
                            }
                            else
                            {
                                TemporaryChestContents.Add(Item);
                            }
                        }

                        Chest TempChest = new Chest(0, TemporaryChestContents, Vector2.Zero, false, 0);
                        MaterialContainers.Add(TempChest);
                    }
                }
            }
        }
        public void InitializePlaceholders()
        {
            List <Object> Temp = new List <Object>();

            IEnumerable <Object> SortedContents;

            switch (Rucksack.SortProperty)
            {
            case SortingProperty.Time:
                SortedContents = Rucksack.Contents;
                break;

            case SortingProperty.Name:
                SortedContents = Rucksack.Contents.OrderBy(x => x.DisplayName);
                break;

            case SortingProperty.Id:
                SortedContents = Rucksack.Contents.OrderBy(x => x.bigCraftable.Value).ThenBy(x => x.ParentSheetIndex);
                break;

            case SortingProperty.Category:
                //SortedContents = Rucksack.Contents.OrderBy(x => x.getCategorySortValue());
                SortedContents = Rucksack.Contents.OrderBy(x => x.getCategoryName());
                break;

            case SortingProperty.Quantity:
                SortedContents = Rucksack.Contents.OrderBy(x => x.Stack);
                break;

            case SortingProperty.SingleValue:
                SortedContents = Rucksack.Contents.OrderBy(x => ItemBag.GetSingleItemPrice(x));
                break;

            case SortingProperty.StackValue:
                SortedContents = Rucksack.Contents.OrderBy(x => ItemBag.GetSingleItemPrice(x) * x.Stack);
                break;

            case SortingProperty.Similarity:
                //Possible TODO: Maybe SortingProperty.Similarity shouldn't exist - maybe it should just be a "bool GroupBeforeSorting"
                //that only groups by ItemId (and maybe also sorts by Quality after). Then the grouping can be applied to any of the other sorting properties.
                //So it could just be a togglebutton to turn on/off like the Autofill Toggle

                SortedContents = Rucksack.Contents
                                 .OrderBy(Item => Item.getCategoryName()).GroupBy(Item => Item.getCategoryName()) // First sort and group by CategoryName
                                 .SelectMany(
                    CategoryGroup =>
                    CategoryGroup.GroupBy(Item => Item.ParentSheetIndex)             // Then Group by item Id
                    .SelectMany(IdGroup => IdGroup.OrderBy(y => y.Quality))          // Then sort by Quality
                    );
                break;

            default: throw new NotImplementedException(string.Format("Unexpected SortingProperty: {0}", Rucksack.SortProperty.ToString()));
            }
            if (Rucksack.SortOrder == SortingOrder.Descending)
            {
                SortedContents = SortedContents.Reverse();
            }

            //Possible TODO Add filtering?
            //For EX: if you only wanted to show Fish,
            //SortedContents = SortedContents.Where(x => x.Category == <WhateverTheIdIsForFishCategory>);

            TempVisualFeedback = new Dictionary <Object, DateTime>();
            foreach (Object Item in SortedContents)
            {
                bool WasRecentlyModified = Bag.RecentlyModified.TryGetValue(Item, out DateTime ModifiedTime);

                int NumSlots     = (Item.Stack - 1) / Rucksack.MaxStackSize + 1;
                int RemainingQty = Item.Stack;
                for (int i = 0; i < NumSlots; i++)
                {
                    Object Copy = ItemBag.CreateCopy(Item);
                    ItemBag.ForceSetQuantity(Copy, Math.Min(RemainingQty, Rucksack.MaxStackSize));
                    Temp.Add(Copy);
                    RemainingQty -= Copy.Stack;

                    if (WasRecentlyModified)
                    {
                        TempVisualFeedback.Add(Copy, ModifiedTime);
                    }
                }
            }

            this.PlaceholderItems = Temp.AsReadOnly();
        }