Moved crafting page patch

master
Mohammad Shoaib Khan 2023-02-24 14:43:19 +05:30
parent 9d7c2c36ec
commit f851806947
No known key found for this signature in database
GPG Key ID: D8040D966320B620
4 changed files with 252 additions and 238 deletions

View File

@ -80,7 +80,7 @@ namespace stardew_access
harmony.Patch( harmony.Patch(
original: AccessTools.Method(typeof(CraftingPage), nameof(CraftingPage.draw), new Type[] { typeof(SpriteBatch) }), original: AccessTools.Method(typeof(CraftingPage), nameof(CraftingPage.draw), new Type[] { typeof(SpriteBatch) }),
postfix: new HarmonyMethod(typeof(GameMenuPatches), nameof(GameMenuPatches.CraftingPagePatch)) postfix: new HarmonyMethod(typeof(CraftingPagePatch), nameof(CraftingPagePatch.DrawPatch))
); );
harmony.Patch( harmony.Patch(

View File

@ -9,13 +9,10 @@ namespace stardew_access.Patches
{ {
internal static string hoveredItemQueryKey = ""; internal static string hoveredItemQueryKey = "";
internal static string gameMenuQueryKey = ""; internal static string gameMenuQueryKey = "";
internal static string craftingPageQueryKey = "";
internal static string inventoryPageQueryKey = ""; internal static string inventoryPageQueryKey = "";
internal static string exitPageQueryKey = ""; internal static string exitPageQueryKey = "";
internal static string optionsPageQueryKey = ""; internal static string optionsPageQueryKey = "";
internal static string profilePageQuery = ""; internal static string profilePageQuery = "";
internal static int currentSelectedCraftingRecipe = -1;
internal static bool isSelectingRecipe = false;
internal static void GameMenuPatch(GameMenu __instance) internal static void GameMenuPatch(GameMenu __instance)
{ {
@ -48,237 +45,6 @@ namespace stardew_access.Patches
} }
} }
internal static void CraftingPagePatch(CraftingPage __instance, CraftingRecipe ___hoverRecipe, int ___currentCraftingPage)
{
try
{
int x = Game1.getMouseX(true), y = Game1.getMouseY(true); // Mouse x and y position
if (MainClass.Config.SnapToFirstInventorySlotKey.JustPressed() && __instance.inventory.inventory.Count > 0)
{
// snap to first inventory slot
__instance.setCurrentlySnappedComponentTo(__instance.inventory.inventory[0].myID);
__instance.inventory.inventory[0].snapMouseCursorToCenter();
currentSelectedCraftingRecipe = -1;
}
else if (MainClass.Config.SnapToFirstSecondaryInventorySlotKey.JustPressed() && __instance.pagesOfCraftingRecipes[___currentCraftingPage].Count > 0)
{
// snap to first crafting recipe
__instance.setCurrentlySnappedComponentTo(__instance.pagesOfCraftingRecipes[___currentCraftingPage].ElementAt(0).Key.myID);
__instance.pagesOfCraftingRecipes[___currentCraftingPage].ElementAt(0).Key.snapMouseCursorToCenter();
currentSelectedCraftingRecipe = 0;
}
else if (MainClass.Config.CraftingMenuCycleThroughRecipiesKey.JustPressed() && !isSelectingRecipe)
{
isSelectingRecipe = true;
CycleThroughRecipies(__instance.pagesOfCraftingRecipes, ___currentCraftingPage, __instance);
Task.Delay(200).ContinueWith(_ => { isSelectingRecipe = false; });
}
#region Narrate buttons in the menu
if (__instance.upButton != null && __instance.upButton.containsPoint(x, y))
{
string toSpeak = "Previous Recipe List";
if (craftingPageQueryKey != toSpeak)
{
craftingPageQueryKey = toSpeak;
hoveredItemQueryKey = "";
MainClass.ScreenReader.Say(toSpeak, true);
}
return;
}
if (__instance.downButton != null && __instance.downButton.containsPoint(x, y))
{
string toSpeak = "Next Recipe List";
if (craftingPageQueryKey != toSpeak)
{
craftingPageQueryKey = toSpeak;
hoveredItemQueryKey = "";
MainClass.ScreenReader.Say(toSpeak, true);
}
return;
}
if (__instance.trashCan.containsPoint(x, y))
{
string toSpeak = "Trash Can";
if (craftingPageQueryKey != toSpeak)
{
craftingPageQueryKey = toSpeak;
hoveredItemQueryKey = "";
MainClass.ScreenReader.Say(toSpeak, true);
}
return;
}
if (__instance.dropItemInvisibleButton.containsPoint(x, y))
{
string toSpeak = "Drop Item";
if (craftingPageQueryKey != toSpeak)
{
craftingPageQueryKey = toSpeak;
hoveredItemQueryKey = "";
MainClass.ScreenReader.Say(toSpeak, true);
Game1.playSound("drop_item");
}
return;
}
#endregion
#region Narrate hovered recipe
if (___hoverRecipe != null)
{
string name = ___hoverRecipe.DisplayName;
int numberOfProduce = ___hoverRecipe.numberProducedPerCraft;
string description = "";
string ingredients = "";
string buffs = "";
string craftable = "";
description = $"Description:\n{___hoverRecipe.description}";
craftable = ___hoverRecipe.doesFarmerHaveIngredientsInInventory(getContainerContents(__instance._materialContainers)) ? "Craftable" : "Not Craftable";
#region Crafting ingredients
ingredients = "Ingredients:\n";
for (int i = 0; i < ___hoverRecipe.recipeList.Count; i++)
{
int recipeCount = ___hoverRecipe.recipeList.ElementAt(i).Value;
int recipeItem = ___hoverRecipe.recipeList.ElementAt(i).Key;
string recipeName = ___hoverRecipe.getNameFromIndex(recipeItem);
ingredients += $" ,{recipeCount} {recipeName}";
}
#endregion
#region Health & stamina and buff items (effects like +1 walking speed)
Item producesItem = ___hoverRecipe.createItem();
if (producesItem is StardewValley.Object producesItemObject)
{
if (producesItemObject.Edibility != -300)
{
int stamina_recovery = producesItemObject.staminaRecoveredOnConsumption();
buffs += $"{stamina_recovery} Energy";
if (stamina_recovery >= 0)
{
int health_recovery = producesItemObject.healthRecoveredOnConsumption();
buffs += $"\n{health_recovery} Health";
}
}
// These variables are taken from the game's code itself (IClickableMenu.cs -> 1016 line)
bool edibleItem = producesItem != null && (int)producesItemObject.Edibility != -300;
string[]? buffIconsToDisplay = (producesItem != null && edibleItem && Game1.objectInformation[producesItemObject.ParentSheetIndex].Split('/').Length > 7)
? producesItem.ModifyItemBuffs(Game1.objectInformation[producesItemObject.ParentSheetIndex].Split('/')[7].Split(' '))
: null;
if (buffIconsToDisplay != null)
{
for (int j = 0; j < buffIconsToDisplay.Length; j++)
{
string buffName = ((Convert.ToInt32(buffIconsToDisplay[j]) > 0) ? "+" : "") + buffIconsToDisplay[j] + " ";
if (j <= 11)
{
buffName = Game1.content.LoadString("Strings\\UI:ItemHover_Buff" + j, buffName);
}
try
{
int count = int.Parse(buffName.Substring(0, buffName.IndexOf(' ')));
if (count != 0)
buffs += $"{buffName}\n";
}
catch (Exception) { }
}
buffs = $"Buffs and boosts:\n {buffs}";
}
}
#endregion
string toSpeak = $"{numberOfProduce} {name}, {craftable}, \n\t{ingredients}, \n\t{description} \n\t{buffs}";
if (craftingPageQueryKey != toSpeak)
{
craftingPageQueryKey = toSpeak;
gameMenuQueryKey = "";
hoveredItemQueryKey = "";
MainClass.ScreenReader.Say(toSpeak, true);
}
return;
}
else
{
var isRecipeInFocus = false;
foreach (var item in __instance.pagesOfCraftingRecipes[___currentCraftingPage])
{
if (item.Key.containsPoint(x, y))
{
isRecipeInFocus = true;
break;
}
}
if (isRecipeInFocus)
{
string query = $"unknown recipe:{__instance.getCurrentlySnappedComponent().myID}";
if (craftingPageQueryKey != query)
{
craftingPageQueryKey = query;
gameMenuQueryKey = "";
hoveredItemQueryKey = "";
MainClass.ScreenReader.Say("unknown recipe", true);
}
return;
}
}
#endregion
#region Narrate hovered item
if (InventoryUtils.narrateHoveredSlot(__instance.inventory, __instance.inventory.inventory, __instance.inventory.actualInventory, x, y))
{
gameMenuQueryKey = "";
craftingPageQueryKey = "";
return;
}
#endregion
}
catch (Exception e)
{
MainClass.ErrorLog($"Unable to narrate Text:\n{e.Message}\n{e.StackTrace}");
}
}
private static void CycleThroughRecipies(List<Dictionary<ClickableTextureComponent, CraftingRecipe>> pagesOfCraftingRecipes, int ___currentCraftingPage, CraftingPage __instance)
{
currentSelectedCraftingRecipe++;
if (currentSelectedCraftingRecipe < 0 || currentSelectedCraftingRecipe >= pagesOfCraftingRecipes[0].Count)
currentSelectedCraftingRecipe = 0;
__instance.setCurrentlySnappedComponentTo(pagesOfCraftingRecipes[___currentCraftingPage].ElementAt(currentSelectedCraftingRecipe).Key.myID);
pagesOfCraftingRecipes[___currentCraftingPage].ElementAt(currentSelectedCraftingRecipe).Key.snapMouseCursorToCenter();
// Skip if recipe is not unlocked/unknown
if (pagesOfCraftingRecipes[___currentCraftingPage].ElementAt(currentSelectedCraftingRecipe).Key.hoverText.Equals("ghosted"))
CycleThroughRecipies(pagesOfCraftingRecipes, ___currentCraftingPage, __instance);
}
// This method is used to get the inventory items to check if the player has enough ingredients for a recipe
// Taken from CraftingPage.cs -> 169 line
internal static IList<Item>? getContainerContents(List<Chest> materialContainers)
{
if (materialContainers == null)
{
return null;
}
List<Item> items = new List<Item>();
for (int i = 0; i < materialContainers.Count; i++)
{
items.AddRange(materialContainers[i].items);
}
return items;
}
internal static void InventoryPagePatch(InventoryPage __instance) internal static void InventoryPagePatch(InventoryPage __instance)
{ {
try try

View File

@ -0,0 +1,250 @@
using StardewValley;
using StardewValley.Menus;
using StardewValley.Objects;
namespace stardew_access.Patches
{
internal class CraftingPagePatch
{
internal static string hoveredItemQueryKey = "";
internal static string craftingPageQueryKey = "";
internal static int currentSelectedCraftingRecipe = -1;
internal static bool isSelectingRecipe = false;
internal static void DrawPatch(CraftingPage __instance, CraftingRecipe ___hoverRecipe, int ___currentCraftingPage)
{
try
{
int x = Game1.getMouseX(true), y = Game1.getMouseY(true); // Mouse x and y position
if (MainClass.Config.SnapToFirstInventorySlotKey.JustPressed() && __instance.inventory.inventory.Count > 0)
{
// snap to first inventory slot
__instance.setCurrentlySnappedComponentTo(__instance.inventory.inventory[0].myID);
__instance.inventory.inventory[0].snapMouseCursorToCenter();
currentSelectedCraftingRecipe = -1;
}
else if (MainClass.Config.SnapToFirstSecondaryInventorySlotKey.JustPressed() && __instance.pagesOfCraftingRecipes[___currentCraftingPage].Count > 0)
{
// snap to first crafting recipe
__instance.setCurrentlySnappedComponentTo(__instance.pagesOfCraftingRecipes[___currentCraftingPage].ElementAt(0).Key.myID);
__instance.pagesOfCraftingRecipes[___currentCraftingPage].ElementAt(0).Key.snapMouseCursorToCenter();
currentSelectedCraftingRecipe = 0;
}
else if (MainClass.Config.CraftingMenuCycleThroughRecipiesKey.JustPressed() && !isSelectingRecipe)
{
isSelectingRecipe = true;
CycleThroughRecipies(__instance.pagesOfCraftingRecipes, ___currentCraftingPage, __instance);
Task.Delay(200).ContinueWith(_ => { isSelectingRecipe = false; });
}
#region Narrate buttons in the menu
if (__instance.upButton != null && __instance.upButton.containsPoint(x, y))
{
string toSpeak = "Previous Recipe List";
if (craftingPageQueryKey != toSpeak)
{
craftingPageQueryKey = toSpeak;
hoveredItemQueryKey = "";
MainClass.ScreenReader.Say(toSpeak, true);
}
return;
}
if (__instance.downButton != null && __instance.downButton.containsPoint(x, y))
{
string toSpeak = "Next Recipe List";
if (craftingPageQueryKey != toSpeak)
{
craftingPageQueryKey = toSpeak;
hoveredItemQueryKey = "";
MainClass.ScreenReader.Say(toSpeak, true);
}
return;
}
if (__instance.trashCan.containsPoint(x, y))
{
string toSpeak = "Trash Can";
if (craftingPageQueryKey != toSpeak)
{
craftingPageQueryKey = toSpeak;
hoveredItemQueryKey = "";
MainClass.ScreenReader.Say(toSpeak, true);
}
return;
}
if (__instance.dropItemInvisibleButton.containsPoint(x, y))
{
string toSpeak = "Drop Item";
if (craftingPageQueryKey != toSpeak)
{
craftingPageQueryKey = toSpeak;
hoveredItemQueryKey = "";
MainClass.ScreenReader.Say(toSpeak, true);
Game1.playSound("drop_item");
}
return;
}
#endregion
#region Narrate hovered recipe
if (___hoverRecipe != null)
{
string name = ___hoverRecipe.DisplayName;
int numberOfProduce = ___hoverRecipe.numberProducedPerCraft;
string description = "";
string ingredients = "";
string buffs = "";
string craftable = "";
description = $"Description:\n{___hoverRecipe.description}";
craftable = ___hoverRecipe.doesFarmerHaveIngredientsInInventory(getContainerContents(__instance._materialContainers)) ? "Craftable" : "Not Craftable";
#region Crafting ingredients
ingredients = "Ingredients:\n";
for (int i = 0; i < ___hoverRecipe.recipeList.Count; i++)
{
int recipeCount = ___hoverRecipe.recipeList.ElementAt(i).Value;
int recipeItem = ___hoverRecipe.recipeList.ElementAt(i).Key;
string recipeName = ___hoverRecipe.getNameFromIndex(recipeItem);
ingredients += $" ,{recipeCount} {recipeName}";
}
#endregion
#region Health & stamina and buff items (effects like +1 walking speed)
Item producesItem = ___hoverRecipe.createItem();
if (producesItem is StardewValley.Object producesItemObject)
{
if (producesItemObject.Edibility != -300)
{
int stamina_recovery = producesItemObject.staminaRecoveredOnConsumption();
buffs += $"{stamina_recovery} Energy";
if (stamina_recovery >= 0)
{
int health_recovery = producesItemObject.healthRecoveredOnConsumption();
buffs += $"\n{health_recovery} Health";
}
}
// These variables are taken from the game's code itself (IClickableMenu.cs -> 1016 line)
bool edibleItem = producesItem != null && (int)producesItemObject.Edibility != -300;
string[]? buffIconsToDisplay = (producesItem != null && edibleItem && Game1.objectInformation[producesItemObject.ParentSheetIndex].Split('/').Length > 7)
? producesItem.ModifyItemBuffs(Game1.objectInformation[producesItemObject.ParentSheetIndex].Split('/')[7].Split(' '))
: null;
if (buffIconsToDisplay != null)
{
for (int j = 0; j < buffIconsToDisplay.Length; j++)
{
string buffName = ((Convert.ToInt32(buffIconsToDisplay[j]) > 0) ? "+" : "") + buffIconsToDisplay[j] + " ";
if (j <= 11)
{
buffName = Game1.content.LoadString("Strings\\UI:ItemHover_Buff" + j, buffName);
}
try
{
int count = int.Parse(buffName.Substring(0, buffName.IndexOf(' ')));
if (count != 0)
buffs += $"{buffName}\n";
}
catch (Exception) { }
}
buffs = $"Buffs and boosts:\n {buffs}";
}
}
#endregion
string toSpeak = $"{numberOfProduce} {name}, {craftable}, \n\t{ingredients}, \n\t{description} \n\t{buffs}";
if (craftingPageQueryKey != toSpeak)
{
craftingPageQueryKey = toSpeak;
hoveredItemQueryKey = "";
MainClass.ScreenReader.Say(toSpeak, true);
}
return;
}
else
{
var isRecipeInFocus = false;
foreach (var item in __instance.pagesOfCraftingRecipes[___currentCraftingPage])
{
if (item.Key.containsPoint(x, y))
{
isRecipeInFocus = true;
break;
}
}
if (isRecipeInFocus)
{
string query = $"unknown recipe:{__instance.getCurrentlySnappedComponent().myID}";
if (craftingPageQueryKey != query)
{
craftingPageQueryKey = query;
hoveredItemQueryKey = "";
MainClass.ScreenReader.Say("unknown recipe", true);
}
return;
}
}
#endregion
#region Narrate hovered item
if (InventoryUtils.narrateHoveredSlot(__instance.inventory, __instance.inventory.inventory, __instance.inventory.actualInventory, x, y))
{
craftingPageQueryKey = "";
return;
}
#endregion
}
catch (Exception e)
{
MainClass.ErrorLog($"Unable to narrate Text:\n{e.Message}\n{e.StackTrace}");
}
}
private static void CycleThroughRecipies(List<Dictionary<ClickableTextureComponent, CraftingRecipe>> pagesOfCraftingRecipes, int ___currentCraftingPage, CraftingPage __instance)
{
currentSelectedCraftingRecipe++;
if (currentSelectedCraftingRecipe < 0 || currentSelectedCraftingRecipe >= pagesOfCraftingRecipes[0].Count)
currentSelectedCraftingRecipe = 0;
__instance.setCurrentlySnappedComponentTo(pagesOfCraftingRecipes[___currentCraftingPage].ElementAt(currentSelectedCraftingRecipe).Key.myID);
pagesOfCraftingRecipes[___currentCraftingPage].ElementAt(currentSelectedCraftingRecipe).Key.snapMouseCursorToCenter();
// Skip if recipe is not unlocked/unknown
if (pagesOfCraftingRecipes[___currentCraftingPage].ElementAt(currentSelectedCraftingRecipe).Key.hoverText.Equals("ghosted"))
CycleThroughRecipies(pagesOfCraftingRecipes, ___currentCraftingPage, __instance);
}
// This method is used to get the inventory items to check if the player has enough ingredients for a recipe
// Taken from CraftingPage.cs -> 169 line
internal static IList<Item>? getContainerContents(List<Chest> materialContainers)
{
if (materialContainers == null)
{
return null;
}
List<Item> items = new List<Item>();
for (int i = 0; i < materialContainers.Count; i++)
{
items.AddRange(materialContainers[i].items);
}
return items;
}
internal static void Cleanup()
{
hoveredItemQueryKey = "";
craftingPageQueryKey = "";
currentSelectedCraftingRecipe = -1;
isSelectingRecipe = false;
}
}
}

View File

@ -34,13 +34,11 @@ namespace stardew_access.Patches
else if (menu is GameMenu) else if (menu is GameMenu)
{ {
GameMenuPatches.gameMenuQueryKey = ""; GameMenuPatches.gameMenuQueryKey = "";
GameMenuPatches.craftingPageQueryKey = "";
GameMenuPatches.inventoryPageQueryKey = ""; GameMenuPatches.inventoryPageQueryKey = "";
GameMenuPatches.exitPageQueryKey = ""; GameMenuPatches.exitPageQueryKey = "";
GameMenuPatches.optionsPageQueryKey = ""; GameMenuPatches.optionsPageQueryKey = "";
SocialPagePatch.Cleanup(); SocialPagePatch.Cleanup();
GameMenuPatches.currentSelectedCraftingRecipe = -1; CraftingPagePatch.Cleanup();
GameMenuPatches.isSelectingRecipe = false;
} }
else if (menu is JunimoNoteMenu) else if (menu is JunimoNoteMenu)
{ {