using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Revitalize.Framework.Menus.MenuComponents;
using Revitalize.Framework.Objects.Machines;
using StardewValley;
using StardewValley.Menus;
using StardustCore.UIUtilities;
using StardustCore.UIUtilities.MenuComponents.ComponentsV2.Buttons;
namespace Revitalize.Framework.Menus
{
///
/// A simple menu for displaying craftable objects.
///
public class CraftingMenuV1 : IClickableMenuExtended
{
///
/// All the different pages for crafting.
///
public Dictionary CraftingTabs;
///
/// All of the actual buttons to display for crafting.
///
public Dictionary> craftingItemsToDisplay;
///
/// The inventory to tke items from.
///
public IList- fromInventory;
///
/// The inventory to put items into.
///
public IList
- toInventory;
///
/// The current page index for the current tab.
///
public int currentPageIndex;
///
/// The name of the current tab.
///
public string currentTab;
///
/// The background color for the menu.
///
public Color backgroundColor;
///
/// The x offset for the menu so that tabs can be interacted with properly.
///
public int xOffset = 72;
///
/// Teh hover text to display.
///
public string hoverText;
///
/// How many crafting recipes to display at a time.
///
public int amountOfRecipesToShow = 9;
///
/// Is this menu the player's?
///
public bool playerInventory;
///
/// The crafting info menu that displays when a recipe is clicked.
///
public CraftingInformationPage craftingInfo;
///
/// The previous page button.
///
public AnimatedButton leftButton;
///
/// The next page button.
///
public AnimatedButton rightButton;
///
/// The search box used for looking for specific items.
///
public StardewValley.Menus.TextBox searchBox;
private Machine machine;
///
/// The maximum amount of pages to display.
///
private int maxPages
{
get
{
if (string.IsNullOrEmpty(this.currentTab)) return 0;
List searchSelection;
if (string.IsNullOrEmpty(this.searchBox.Text) == false)
{
searchSelection = this.craftingItemsToDisplay[this.currentTab].FindAll(i => i.displayItem.item.DisplayName.ToLowerInvariant().Contains(this.searchBox.Text.ToLowerInvariant()));
}
else
{
searchSelection = this.craftingItemsToDisplay[this.currentTab];
}
return (int)(Math.Ceiling((double)(searchSelection.Count / this.amountOfRecipesToShow)));
}
}
public CraftingMenuV1() : base()
{
}
///
/// Constructor to be used when the inventory is the player's
///
///
///
///
///
///
///
public CraftingMenuV1(int X, int Y, int Width, int Height, Color BackgroundColor, IList
- Inventory) : base(X, Y, Width, Height, false)
{
this.backgroundColor = BackgroundColor;
this.CraftingTabs = new Dictionary();
this.craftingItemsToDisplay = new Dictionary>();
this.currentPageIndex = 0;
this.fromInventory = Inventory;
this.toInventory = Inventory;
this.playerInventory = true;
this.initializeButtons();
}
///
/// Constructor to be used when inventory destination is the same and not the player.
///
///
///
///
///
///
///
public CraftingMenuV1(int X, int Y, int Width, int Height, Color BackgroundColor, ref IList
- Inventory) : base(X, Y, Width, Height, false)
{
this.backgroundColor = BackgroundColor;
this.CraftingTabs = new Dictionary();
this.craftingItemsToDisplay = new Dictionary>();
this.currentPageIndex = 0;
this.fromInventory = Inventory;
this.toInventory = Inventory;
this.initializeButtons();
}
///
/// Inventory constructor to be used when the input and output inventories are different.
///
///
///
///
///
///
///
///
public CraftingMenuV1(int X, int Y, int Width, int Height, Color BackgroundColor, ref IList
- FromInventory, ref IList
- ToInventory,Machine Machine) : base(X, Y, Width, Height, false)
{
this.backgroundColor = BackgroundColor;
this.CraftingTabs = new Dictionary();
this.craftingItemsToDisplay = new Dictionary>();
this.currentPageIndex = 0;
this.fromInventory = FromInventory;
this.toInventory = ToInventory;
this.initializeButtons();
this.machine = Machine;
this.playerInventory = false;
}
///
/// Fix the display of menu elements when the menu is resized.
///
///
///
public override void gameWindowSizeChanged(Rectangle oldBounds, Rectangle newBounds)
{
base.gameWindowSizeChanged(oldBounds, newBounds);
if (this.craftingInfo != null)
{
this.craftingInfo.gameWindowSizeChanged(oldBounds, newBounds);
}
}
///
/// Initialize the buttons for the menu.
///
private void initializeButtons()
{
this.leftButton = new AnimatedButton(new StardustCore.Animations.AnimatedSprite("Left Button", new Vector2(this.xPositionOnScreen, this.yPositionOnScreen), new StardustCore.Animations.AnimationManager(TextureManager.GetExtendedTexture(ModCore.Manifest, "InventoryMenu", "PreviousPageButton"), new StardustCore.Animations.Animation(0, 0, 32, 32)), Color.White), new Rectangle(0, 0, 32, 32), 2f);
this.rightButton = new AnimatedButton(new StardustCore.Animations.AnimatedSprite("Right Button", new Vector2(this.xPositionOnScreen + this.width, this.yPositionOnScreen), new StardustCore.Animations.AnimationManager(TextureManager.GetExtendedTexture(ModCore.Manifest, "InventoryMenu", "NextPageButton"), new StardustCore.Animations.Animation(0, 0, 32, 32)), Color.White), new Rectangle(0, 0, 32, 32), 2f);
this.searchBox = new TextBox((Texture2D)null, (Texture2D)null, Game1.dialogueFont, Game1.textColor);
this.searchBox.X = this.xPositionOnScreen + this.width + 96;
this.searchBox.Y = this.yPositionOnScreen;
this.searchBox.Width = 256;
this.searchBox.Height = 192;
Game1.keyboardDispatcher.Subscriber = (IKeyboardSubscriber)this.searchBox;
this.searchBox.Selected = false;
}
///
/// What happens when the menu receives a key press.
///
///
public override void receiveKeyPress(Keys key)
{
if (this.searchBox.Selected && key != Keys.Escape)
{
return;
}
else
{
base.receiveKeyPress(key);
}
}
///
/// Sorts all of the recipes for the menu.
///
public void sortRecipes()
{
foreach (KeyValuePair> pair in this.craftingItemsToDisplay)
{
List copy = pair.Value.ToList();
pair.Value.Clear();
copy = copy.OrderBy(x => x.displayItem.item.DisplayName).ToList();
foreach (CraftingRecipeButton b in copy)
{
this.addInCraftingRecipe(b, pair.Key);
}
}
}
///
/// Adds in a new tab for the crafting recipe menu.
///
///
///
public void addInCraftingPageTab(string name, AnimatedButton Button)
{
int count = this.CraftingTabs.Count;
if (this.CraftingTabs.ContainsKey(name))
{
return;
}
else
{
Vector2 newPos = new Vector2(100 + (48), this.yPositionOnScreen + (24 * 4) * (count + 1));
Button.Position = newPos;
this.CraftingTabs.Add(name, Button);
this.craftingItemsToDisplay.Add(name, new List());
}
}
///
/// Adds in a crafting recipe to the crafting menu.
///
///
///
public void addInCraftingRecipe(CraftingRecipeButton Button, string WhichTab)
{
if (this.craftingItemsToDisplay.ContainsKey(WhichTab))
{
int count = this.craftingItemsToDisplay[WhichTab].Count % this.amountOfRecipesToShow;
Vector2 newPos = new Vector2(this.xPositionOnScreen + (128), (this.yPositionOnScreen + 64) + (64 * (count + 1)));
Button.displayItem.Position = newPos;
this.craftingItemsToDisplay[WhichTab].Add(Button);
}
else
{
throw new Exception("Tab: " + WhichTab + " doesn't exist!");
}
}
///
/// What happens when you hover over a menu element.
///
///
///
public override void performHoverAction(int x, int y)
{
bool hovered = false;
foreach (KeyValuePair pair in this.CraftingTabs)
{
if (pair.Value.containsPoint(x, y))
{
this.hoverText = pair.Key;
hovered = true;
}
}
//get range of buttons to show
if (string.IsNullOrEmpty(this.currentTab) == false)
{
List buttonsToDraw = this.getRecipeButtonsToDisplay();
foreach (CraftingRecipeButton button in buttonsToDraw)
{
if (button.containsPoint(x, y))
{
this.hoverText = button.recipe.outputName;
hovered = true;
}
}
}
if (hovered == false)
{
this.hoverText = "";
}
}
///
/// What happens when the meu receives a left click.
///
///
///
///
public override void receiveLeftClick(int x, int y, bool playSound = true)
{
if (this.leftButton.containsPoint(x, y))
{
if (this.currentPageIndex <= 0) this.currentPageIndex = 0;
else
{
this.currentPageIndex--;
Game1.playSound("shwip");
}
}
if (this.rightButton.containsPoint(x, y))
{
if (this.currentPageIndex < this.maxPages)
{
this.currentPageIndex++;
Game1.playSound("shwip");
}
}
Rectangle r = new Rectangle(this.searchBox.X, this.searchBox.Y, this.searchBox.Width, this.searchBox.Height / 2);
if (r.Contains(x, y))
{
this.searchBox.Update();
this.searchBox.SelectMe();
}
else
{
this.searchBox.Selected = false;
}
foreach (KeyValuePair pair in this.CraftingTabs)
{
if (pair.Value.containsPoint(x, y))
{
this.currentTab = pair.Key;
this.currentPageIndex = 0;
return;
}
}
//get range of buttons to show
if (string.IsNullOrEmpty(this.currentTab) == false)
{
List buttonsToDraw = this.getRecipeButtonsToDisplay();
foreach (CraftingRecipeButton button in buttonsToDraw)
{
if (button.containsPoint(x, y))
{
//button.craftItem(this.fromInventory, this.toInventory);
if (this.playerInventory)
{
this.fromInventory = Game1.player.Items;
}
this.craftingInfo = new CraftingInformationPage(this.xPositionOnScreen + this.width + this.xOffset, this.yPositionOnScreen, 400, this.height, this.backgroundColor, button, ref this.fromInventory,ref this.toInventory,this.playerInventory,this.machine);
Game1.soundBank.PlayCue("coin");
if (this.playerInventory)
{
Game1.player.Items = this.toInventory;
return;
}
//ModCore.log("Button has been clicked!");
return;
}
}
}
//ModCore.log("Menu has been clicked");
if (this.craftingInfo != null)
{
this.craftingInfo.receiveLeftClick(x, y);
if (this.craftingInfo.doesMenuContainPoint(x, y)) return;
}
this.craftingInfo = null;
}
///
/// Draws the menu to the screen.
///
///
public override void draw(SpriteBatch b)
{
this.drawDialogueBoxBackground(this.xPositionOnScreen + this.xOffset, this.yPositionOnScreen, this.width, this.height, this.backgroundColor);
if (this.currentPageIndex > this.maxPages) this.currentPageIndex = 0;
this.leftButton.draw(b);
//Draw page numbers here.
//b.DrawString(Game1.smallFont,"Page: "+this.currentPageIndex.ToString()/)
b.DrawString(Game1.dialogueFont, ("Page: " + (this.currentPageIndex + 1) + " / " + (this.maxPages + 1)).ToString(), new Vector2(this.xPositionOnScreen + 128, this.yPositionOnScreen+32), Color.White);
this.rightButton.draw(b);
this.searchBox.Draw(b, true);
//this.drawDialogueBoxBackground();
foreach (KeyValuePair pair in this.CraftingTabs)
{
pair.Value.draw(b);
}
if (string.IsNullOrEmpty(this.currentTab))
{
if (string.IsNullOrEmpty(this.hoverText) == false)
{
IClickableMenuExtended.drawHoverText(b, this.hoverText, Game1.dialogueFont);
}
this.drawMouse(b);
return;
}
List buttonsToDraw = this.getRecipeButtonsToDisplay();
foreach (CraftingRecipeButton button in buttonsToDraw)
{
if (button.recipe.CanCraft(this.fromInventory))
{
button.draw(b);
}
else
{
button.draw(b, .25f);
}
b.DrawString(Game1.smallFont, button.displayItem.item.DisplayName, button.displayItem.Position + new Vector2(64, 0), Color.Brown);
}
if (this.craftingInfo != null)
{
this.craftingInfo.draw(b);
}
if (string.IsNullOrEmpty(this.hoverText) == false)
{
IClickableMenuExtended.drawHoverText(b, this.hoverText, Game1.dialogueFont);
}
this.drawMouse(b);
}
///
/// Gets all of the crafting buttons to display.
///
///
private List getRecipeButtonsToDisplay()
{
List searchSelection;
if (string.IsNullOrEmpty(this.searchBox.Text) == false)
{
searchSelection = this.craftingItemsToDisplay[this.currentTab].FindAll(i => i.displayItem.item.DisplayName.ToLowerInvariant().Contains(this.searchBox.Text.ToLowerInvariant()));
}
else
{
searchSelection = this.craftingItemsToDisplay[this.currentTab];
}
searchSelection = this.searchSort(searchSelection);
int amount = searchSelection.Count / this.amountOfRecipesToShow;
int min = this.currentPageIndex == amount ? searchSelection.Count % this.amountOfRecipesToShow : this.amountOfRecipesToShow;
List buttonsToDraw = searchSelection.GetRange(this.currentPageIndex * this.amountOfRecipesToShow, min);
return buttonsToDraw;
}
///
/// Repositions crafting buttons based on the current sort context.
///
///
///
private List searchSort(List Unsorted)
{
List copy = Unsorted.ToList();
//copy = copy.OrderBy(x => x.displayItem.item.DisplayName).ToList(); //Sort the recipes again. Probably unnecessary.
//Do sorting;
for (int i = 0; i < Unsorted.Count; i++)
{
int count = i % this.amountOfRecipesToShow;
copy[i].displayItem.Position = new Vector2(this.xPositionOnScreen + (128), (this.yPositionOnScreen + 64) + (64 * (count + 1)));
}
return copy;
}
}
}