/// <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(); }