private static string GetSortValue(SObject Instance, SortingProperty Property) { switch (Property) { case SortingProperty.Name: return(Instance.DisplayName); case SortingProperty.Id: return(Instance.ParentSheetIndex.ToString("D4")); case SortingProperty.Category: return(string.Format("{0} {1}", Instance.getCategoryName(), Instance.getCategorySortValue().ToString("D3"))); case SortingProperty.SingleValue: return(ItemBag.GetSingleItemPrice(Instance).ToString("D6")); default: throw new NotImplementedException(string.Format("Unimplemented {0} '{1}' in {2}.{3}", nameof(SortingProperty), Property, nameof(CommandHandler), nameof(GetSortValue))); } }
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(); }
public void Draw(SpriteBatch b) { if (IsEmptyMenu) { return; } //b.Draw(TextureHelpers.GetSolidColorTexture(Game1.graphics.GraphicsDevice, Color.Orange), Bounds, Color.White); // Draw column headers for (int i = 0; i < ColumnHeaderBounds.Count; i++) { Rectangle Destination = ColumnHeaderBounds[i]; b.Draw(Game1.menuTexture, Destination, new Rectangle(64, 896, 64, 64), Color.White); Rectangle IconDestination = new Rectangle(Destination.X + Destination.Width / 4, Destination.Y + Destination.Height / 4, Destination.Width / 2, Destination.Height / 2); ColumnType Type = (ColumnType)(i % ColumnsPerGroup); if (Type == ColumnType.RowValue) { //Could also use Game1.mouseCursors with SourceSprite = new Rectangle(280, 411, 16, 16); b.Draw(GoldIconTexture, IconDestination, GoldIconSourceRect, Color.White); } else { Rectangle SourceRect = ItemBag.QualityIconTexturePositions[ConvertColumnTypeToObjectQuality(Type)]; b.Draw(Game1.mouseCursors, IconDestination, SourceRect, Color.White); } } // Draw cells foreach (var KVP in SlotBounds) { int ItemId = KVP.Key; foreach (var KVP2 in KVP.Value) { ColumnType ColumnType = KVP2.Key; Rectangle Destination = KVP2.Value; b.Draw(Game1.menuTexture, Destination, new Rectangle(128, 128, 64, 64), Color.White); // Draw a thin yellow border if mouse is hovering this slot bool IsHovered = Destination == HoveredSlot; if (IsHovered) { Color HighlightColor = Color.Yellow; Texture2D Highlight = TextureHelpers.GetSolidColorTexture(Game1.graphics.GraphicsDevice, HighlightColor); b.Draw(Highlight, Destination, Color.White * 0.25f); int BorderThickness = Destination.Width / 16; DrawHelpers.DrawBorder(b, Destination, BorderThickness, HighlightColor); } if (ColumnType != ColumnType.RowValue) { ObjectQuality Quality = ConvertColumnTypeToObjectQuality(ColumnType); Object CurrentItem = Placeholders[ItemId][Quality]; float IconScale = IsHovered ? 1.25f : 1.0f; Color Overlay = CurrentItem.Stack == 0 ? Color.White * 0.30f : Color.White; DrawHelpers.DrawItem(b, Destination, CurrentItem, CurrentItem.Stack > 0, true, IconScale, 1.0f, Overlay, CurrentItem.Stack >= Bag.MaxStackSize ? Color.Red : Color.White); OnItemSlotRendered?.Invoke(this, new ItemSlotRenderedEventArgs(b, Destination, CurrentItem, IsHovered)); } else { // Sum up the value of all different qualities of this item int SummedValue = Placeholders[ItemId].Values.Sum(x => x.Stack * ItemBag.GetSingleItemPrice(x)); int NumDigits = DrawHelpers.GetNumDigits(SummedValue); // Compute width/height of the number float ValueScale; int ValueWidth, ValueHeight, CurrentIteration = 0; do { ValueScale = (2.7f - CurrentIteration * 0.1f) * Destination.Width / (float)BagInventoryMenu.DefaultInventoryIconSize; ValueWidth = (int)DrawHelpers.MeasureNumber(SummedValue, ValueScale); ValueHeight = (int)(DrawHelpers.TinyDigitBaseHeight * ValueScale); CurrentIteration++; } while (ValueWidth > Destination.Width * 1.04); // * 1.04 to let the value extend very slightly outside the bounds of the slot // Draw the number in the center of the slot Vector2 TopLeftPosition = new Vector2(Destination.X + (Destination.Width - ValueWidth) / 2 + 1, Destination.Y + (Destination.Height - ValueHeight) / 2); Color ValueColor = GetValueColor(SummedValue); Utility.drawTinyDigits(SummedValue, b, TopLeftPosition, ValueScale, 0f, ValueColor); } } } }
public void DrawToolTips(SpriteBatch b) { if (IsEmptyMenu) { return; } // Draw tooltip over hovered item if (HoveredSlot.HasValue) { // Get the hovered Item Id and ColumnType int? ItemId = null; ColumnType?Column = null; foreach (var KVP in SlotBounds) { foreach (var KVP2 in KVP.Value) { if (KVP2.Value == HoveredSlot.Value) { ItemId = KVP.Key; Column = KVP2.Key; break; } } if (ItemId.HasValue && Column.HasValue) { break; } } if (ItemId.HasValue && Column.HasValue) { if (Column == ColumnType.RowValue) { List <Object> Items = Placeholders[ItemId.Value].Values.ToList(); List <int> Quantities = Items.Select(x => x.Stack).ToList(); List <int> SingleValues = Items.Select(x => ItemBag.GetSingleItemPrice(x)).ToList(); List <int> MultipliedValues = Items.Select(x => x.Stack * ItemBag.GetSingleItemPrice(x)).ToList(); // Compute how many digits each column needs so that we can align each number properly by making each number take up the maximum size of other numbers in the same column int SingleValueColumnDigits = SingleValues.Max(x => DrawHelpers.GetNumDigits(x)); int QuantityColumnDigits = Quantities.Max(x => DrawHelpers.GetNumDigits(x)); int MultipliedValueColumnDigits = MultipliedValues.Max(x => DrawHelpers.GetNumDigits(x)); float DigitScale = 3.0f; float SingleValueColumnWidth = SingleValueColumnDigits * DigitScale * DrawHelpers.TinyDigitBaseWidth; float QuantityColumnWidth = QuantityColumnDigits * DigitScale * DrawHelpers.TinyDigitBaseWidth; float MultipliedValueColumnWidth = MultipliedValueColumnDigits * DigitScale * DrawHelpers.TinyDigitBaseWidth; // Compute how big the tooltip needs to be int Margin = 32; int LineHeight = 28; int HorizontalSeparatorHeight = 6; int SeparatorMargin = 4; float PlusCharacterWidth = Game1.tinyFont.MeasureString("+").X; float MultiplyCharacterWidth = Game1.tinyFont.MeasureString("*").X; float EqualsCharacterWidth = Game1.tinyFont.MeasureString("=").X; float SpaceWidth = 7f; int TotalWidth = (int)(Margin + PlusCharacterWidth + SpaceWidth + SingleValueColumnWidth + SpaceWidth + MultiplyCharacterWidth + SpaceWidth + QuantityColumnWidth + SpaceWidth + EqualsCharacterWidth + SpaceWidth + MultipliedValueColumnWidth + Margin); int TotalHeight = (int)(Margin + Items.Count * LineHeight + SeparatorMargin + HorizontalSeparatorHeight + SeparatorMargin + LineHeight + Margin); // Ensure tooltip is fully visible on screen Rectangle ToolTipLocation = new Rectangle(HoveredSlot.Value.Right, HoveredSlot.Value.Top, TotalWidth, TotalHeight); if (ToolTipLocation.Right > Game1.viewport.Size.Width) { ToolTipLocation = new Rectangle(HoveredSlot.Value.Left - TotalWidth, HoveredSlot.Value.Top, TotalWidth, TotalHeight); } // Draw background DrawHelpers.DrawBox(b, ToolTipLocation); // Draw each row of values int ShadowOffset = 2; int CurrentYPosition = ToolTipLocation.Y + Margin; for (int i = 0; i < Items.Count; i++) { float CurrentXPosition = ToolTipLocation.X + Margin; if (i != 0) { DrawHelpers.DrawStringWithShadow(b, Game1.tinyFont, "+", CurrentXPosition, CurrentYPosition, Color.White, Color.Black, ShadowOffset, ShadowOffset); } CurrentXPosition += PlusCharacterWidth + SpaceWidth; Utility.drawTinyDigits(SingleValues[i], b, new Vector2(CurrentXPosition + SingleValueColumnWidth - DrawHelpers.MeasureNumber(SingleValues[i], DigitScale), CurrentYPosition), DigitScale, 1.0f, Color.White); CurrentXPosition += SingleValueColumnWidth + SpaceWidth; DrawHelpers.DrawStringWithShadow(b, Game1.tinyFont, "*", CurrentXPosition, CurrentYPosition + LineHeight / 4, Color.White, Color.Black, ShadowOffset, ShadowOffset); CurrentXPosition += MultiplyCharacterWidth + SpaceWidth; Utility.drawTinyDigits(Quantities[i], b, new Vector2(CurrentXPosition + QuantityColumnWidth - DrawHelpers.MeasureNumber(Quantities[i], DigitScale), CurrentYPosition), DigitScale, 1.0f, Color.White); CurrentXPosition += QuantityColumnWidth + SpaceWidth; DrawHelpers.DrawStringWithShadow(b, Game1.tinyFont, "=", CurrentXPosition, CurrentYPosition - LineHeight / 6, Color.White, Color.Black, ShadowOffset, ShadowOffset); CurrentXPosition += EqualsCharacterWidth + SpaceWidth; Utility.drawTinyDigits(MultipliedValues[i], b, new Vector2(CurrentXPosition + MultipliedValueColumnWidth - DrawHelpers.MeasureNumber(MultipliedValues[i], DigitScale), CurrentYPosition), DigitScale, 1.0f, Color.White); CurrentYPosition += LineHeight; } // Draw separator CurrentYPosition += SeparatorMargin; DrawHelpers.DrawHorizontalSeparator(b, ToolTipLocation.X + Margin, CurrentYPosition, TotalWidth - Margin * 2, HorizontalSeparatorHeight); CurrentYPosition += HorizontalSeparatorHeight + SeparatorMargin; // Draw total value int SummedValue = MultipliedValues.Sum(); float SummedValueWidth = DrawHelpers.MeasureNumber(SummedValue, DigitScale) + GoldIconSourceRect.Width * 2f + 8; Vector2 SummedValuePosition = new Vector2(ToolTipLocation.X + ((ToolTipLocation.Width - SummedValueWidth) / 2), CurrentYPosition + 6); Rectangle IconDestination = new Rectangle((int)SummedValuePosition.X, (int)(SummedValuePosition.Y + (DrawHelpers.TinyDigitBaseHeight * DigitScale - GoldIconSourceRect.Height * 2) / 2), GoldIconSourceRect.Width * 2, GoldIconSourceRect.Height * 2); b.Draw(GoldIconTexture, IconDestination, GoldIconSourceRect, Color.White); Utility.drawTinyDigits(SummedValue, b, new Vector2(SummedValuePosition.X + GoldIconSourceRect.Width * 2f + 8, SummedValuePosition.Y), DigitScale, 1.0f, GetValueColor(SummedValue)); } else { Object HoveredItem = Placeholders[ItemId.Value][ConvertColumnTypeToObjectQuality(Column.Value)]; Rectangle Location; if (IsNavigatingWithGamepad) { Location = HoveredSlot.Value; //new Rectangle(HoveredSlot.Value.Right, HoveredSlot.Value.Bottom, 1, 1); } else { Location = new Rectangle(Game1.getMouseX() - 8, Game1.getMouseY() + 36, 8 + 36, 1); } DrawHelpers.DrawToolTipInfo(b, Location, HoveredItem, true, true, true, true, true, true, Bag.MaxStackSize); } } } }
internal static void OnGameLaunched() { IModHelper Helper = ItemBagsMod.ModInstance.Helper; #if NEVER //DEBUG try { // Retrieve the item Ids of various new items added by update 1.5 List <string> NewItemNames = new List <string>() { "Bug Steak", "Banana Pudding", "Ginger", "Ginger Ale", "Ginger Beer", "Mango Sticky Rice", "PiƱa Colada", "Poi", "Taro Root", "Tropical Curry", "Squid Ink Ravioli", "Deluxe Fertilizer", "Deluxe Retaining Soil", "Hyper Speed-Gro", "Bone Fragment", "Fossilized Skull", "Fossilized Spine", "Fossilized Tail", "Fossilized Leg", "Fossilized Ribs", "Snake Skull", "Snake Vertebrae", "Cinder Shard", "Dragon Tooth", "Tiger Slime Egg", "Fairy Dust", "Golden Walnut", "Magma Cap", "Monster Musk", "Mummified Bat", "Mummified Frog", "Ostrich Egg", "Qi Gem", "Qi Seasoning", "Radioactive Ore", "Radioactive Bar", "Taro Tuber", "Mushroom Tree Seed", "Magic Bait", "Stingray", "Lionfish", "Blue Discus", "Glacierfish Jr.", "Legend II", "Ms. Angler", "Radioactive Carp", "Son of Crimsonfish", "Cookout Kit", "Coffee Maker", "Mahogany Seed", "Heavy Tapper", "Mango Sapling", "Mango", "Banana Sapling", "Banana", "Farm Computer", "Mini-Shipping Bin", "Warp Totem: Island", "Bone Mill", "Mini-Obelisk", "Ostrich Incubator", "Geode Crusher", "Pineapple Seeds", "Pineapple", "Dark Sign", "Deconstructor", "Hopper", "Solar Panel", "Fiber Seeds" }; //Game1.objectInformation.GroupBy(x => x.Value).Select(x => x.First()).OrderBy(x => x.Value).ToDictionary(x => x.Value, x => x.Key); Dictionary <string, int> AllItems = new Dictionary <string, int>(); foreach (var item in Game1.objectInformation) { AllItems[item.Value.Split('/').First()] = item.Key; } foreach (var item in Game1.bigCraftablesInformation) { AllItems[item.Value.Split('/').First()] = item.Key; } AllItems = AllItems.OrderBy(x => x.Key).ToDictionary(x => x.Key, x => x.Value); List <string> NotFound = new List <string>(); List <string> Result = new List <string>(); Dictionary <string, int> NewItems = new Dictionary <string, int>(); foreach (string Name in NewItemNames.OrderBy(x => x)) { if (!AllItems.TryGetValue(Name, out int Id)) { NotFound.Add(Name); } else { NewItems.Add(Name, Id); Object Instance = new Object(Id, 1); bool HasQualities = CategoriesWithQualities.Contains(Instance.Category); bool IsStackable = Instance.maximumStackSize() > 1; string Category = Instance.getCategoryName(); if (string.IsNullOrEmpty(Category)) { Category = Instance.Category.ToString(); } Result.Add(string.Format("{0} ({1}, {2}, {3}) (Quality={4})", Name, Id, Category, ItemBag.GetSingleItemPrice(Instance), HasQualities.ToString())); } } string NewItemInfo = string.Join("\n", Result); } catch (Exception) { } #endif // Load modded items from JsonAssets the moment it finishes registering items if (Helper.ModRegistry.IsLoaded(ItemBagsMod.JAUniqueId)) { IJsonAssetsAPI API = Helper.ModRegistry.GetApi <IJsonAssetsAPI>(ItemBagsMod.JAUniqueId); if (API != null) { API.IdsFixed += (sender, e) => { OnJsonAssetsIdsFixed(API, ItemBagsMod.BagConfig); }; } } }