Skip to content

Commit

Permalink
1.0.2-b:
Browse files Browse the repository at this point in the history
Fix check for watering objects on-placement in rain to use local weather rather than global weather.
Add trace logging to crafting page harmony patches re: missing recipe issues.
Flatten HarmonyPatch.Patch behaviour towards modular solution.
  • Loading branch information
b-b-blueberry committed Sep 4, 2021
1 parent 005d2dc commit 73e6742
Show file tree
Hide file tree
Showing 2 changed files with 92 additions and 42 deletions.
131 changes: 90 additions & 41 deletions RaisedGardenBeds/HarmonyPatches.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,44 +3,82 @@
using StardewValley;
using StardewValley.Menus;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;

namespace RaisedGardenBeds
{
public static class HarmonyPatches
{
internal class PatchTemplate
{
public readonly HarmonyPatchType type;
public readonly MethodInfo original;
public readonly string patch;
public readonly HarmonyMethod method;

public PatchTemplate(HarmonyPatchType type, MethodInfo original, string patch = null, HarmonyMethod method = null)
{
this.type = type;
this.original = original;
this.patch = patch ?? method.methodName;
this.method = method ?? new HarmonyMethod(
methodType: typeof(HarmonyPatches),
methodName: patch);
}
}

internal static void Patch(string id)
{
Harmony harmony = new Harmony(id);

Log.T(typeof(HarmonyPatches).GetMethods().Take(typeof(HarmonyPatches).GetMethods().Count() - 4).Select(mi => mi.Name)
.Aggregate("Applying Harmony patches:", (str, s) => $"{str}{Environment.NewLine}{s}"));

// Utility
harmony.Patch(
original: AccessTools.Method(typeof(Utility), "isThereAnObjectHereWhichAcceptsThisItem"),
prefix: new HarmonyMethod(typeof(HarmonyPatches), nameof(Utility_IsThereAnObjectHereWhichAcceptsThisItem_Prefix)));
harmony.Patch(
original: AccessTools.Method(typeof(Utility), "isViableSeedSpot"),
prefix: new HarmonyMethod(typeof(HarmonyPatches), nameof(Utility_IsViableSeedSpot_Prefix)));

// Object
harmony.Patch(
original: AccessTools.Method(typeof(StardewValley.Object), "ApplySprinkler"),
prefix: new HarmonyMethod(typeof(HarmonyPatches), nameof(Object_ApplySprinkler_Prefix)));

// GameLocation
harmony.Patch(
original: AccessTools.Method(typeof(GameLocation), "isTileOccupiedForPlacement"),
postfix: new HarmonyMethod(typeof(HarmonyPatches), nameof(GameLocation_IsTileOccupiedForPlacement_Postfix)));

// Crafting
harmony.Patch(
original: AccessTools.Method(typeof(CraftingPage), "layoutRecipes"),
postfix: new HarmonyMethod(typeof(HarmonyPatches), nameof(CraftingPage_LayoutRecipes_Postfix)));
harmony.Patch(
original: AccessTools.Method(typeof(CraftingPage), "clickCraftingRecipe"),
prefix: new HarmonyMethod(typeof(HarmonyPatches), nameof(CraftingPage_ClickCraftingRecipe_Prefix)));
List<PatchTemplate> patches = new List<PatchTemplate>
{
// Utility
new PatchTemplate(
type: HarmonyPatchType.Prefix,
original: AccessTools.Method(typeof(StardewValley.Utility), "isThereAnObjectHereWhichAcceptsThisItem"),
patch: nameof(HarmonyPatches.Utility_IsThereAnObjectHereWhichAcceptsThisItem_Prefix)),
new PatchTemplate(
type: HarmonyPatchType.Prefix,
original: AccessTools.Method(typeof(StardewValley.Utility), "isViableSeedSpot"),
patch: nameof(HarmonyPatches.Utility_IsViableSeedSpot_Prefix)),

// Object
new PatchTemplate(
type: HarmonyPatchType.Prefix,
original: AccessTools.Method(typeof(StardewValley.Object), "ApplySprinkler"),
patch: nameof(HarmonyPatches.Object_ApplySprinkler_Prefix)),

// GameLocation
new PatchTemplate(
type: HarmonyPatchType.Postfix,
original: AccessTools.Method(typeof(StardewValley.GameLocation), "isTileOccupiedForPlacement"),
patch: nameof(HarmonyPatches.GameLocation_IsTileOccupiedForPlacement_Postfix)),

// CraftingPage
new PatchTemplate(
type: HarmonyPatchType.Postfix,
original: AccessTools.Method(typeof(StardewValley.Menus.CraftingPage), "layoutRecipes"),
patch: nameof(HarmonyPatches.CraftingPage_LayoutRecipes_Postfix)),
new PatchTemplate(
type: HarmonyPatchType.Prefix,
original: AccessTools.Method(typeof(StardewValley.Menus.CraftingPage), "clickCraftingRecipe"),
patch: nameof(HarmonyPatches.CraftingPage_ClickCraftingRecipe_Prefix)),
};

Log.T(patches.Aggregate("Applying Harmony patches:", (str, p) => $"{str}{Environment.NewLine}{p.patch}"));

foreach (PatchTemplate patch in patches)
{
harmony.Patch(
original: patch.original,
prefix: patch.type == HarmonyPatchType.Prefix ? patch.method : null,
postfix: patch.type == HarmonyPatchType.Postfix ? patch.method : null,
transpiler: patch.type == HarmonyPatchType.Transpiler ? patch.method : null,
finalizer: patch.type == HarmonyPatchType.Finalizer ? patch.method : null);
}
}

private static void ErrorHandler(Exception e)
Expand Down Expand Up @@ -156,22 +194,29 @@ public static void GameLocation_IsTileOccupiedForPlacement_Postfix(
public static void CraftingPage_LayoutRecipes_Postfix(
CraftingPage __instance)
{
__instance.pagesOfCraftingRecipes
.ForEach(dict => dict
int unlockedCount = Game1.player.craftingRecipes.Keys.Count(c => c.StartsWith(OutdoorPot.GenericName));
int[] matchesPerDict = new int[__instance.pagesOfCraftingRecipes.Count];
int i = 0;
foreach (Dictionary<ClickableTextureComponent, CraftingRecipe> dict in __instance.pagesOfCraftingRecipes)
{
List<KeyValuePair<ClickableTextureComponent, CraftingRecipe>> matches = dict
.Where(pair => pair.Value.name.StartsWith(OutdoorPot.GenericName))
.ToList()
.ForEach(pair =>
{
string variantKey = OutdoorPot.GetVariantKeyFromName(name: pair.Value.name);
.ToList();
matches.ForEach(pair =>
{
string variantKey = OutdoorPot.GetVariantKeyFromName(name: pair.Value.name);

// Sprite
pair.Key.texture = ModEntry.Sprites[ModEntry.ItemDefinitions[variantKey].SpriteKey];
pair.Key.sourceRect = OutdoorPot.GetSpriteSourceRectangle(spriteIndex: ModEntry.ItemDefinitions[variantKey].SpriteIndex);
// Sprite
pair.Key.texture = ModEntry.Sprites[ModEntry.ItemDefinitions[variantKey].SpriteKey];
pair.Key.sourceRect = OutdoorPot.GetSpriteSourceRectangle(spriteIndex: ModEntry.ItemDefinitions[variantKey].SpriteIndex);

// Strings
pair.Value.DisplayName = OutdoorPot.GetDisplayNameFromName(pair.Value.name);
pair.Value.description = OutdoorPot.GetRawDescription();
}));
// Strings
pair.Value.DisplayName = OutdoorPot.GetDisplayNameFromName(pair.Value.name);
pair.Value.description = OutdoorPot.GetRawDescription();
});
matchesPerDict[i++] = matches.Count();
}
Log.T($"Found {string.Join("/", matchesPerDict)} garden beds in crafting menu pages ({unlockedCount} unlocked).");
}

/// <summary>
Expand Down Expand Up @@ -200,7 +245,9 @@ public static bool CraftingPage_ClickCraftingRecipe_Prefix(
// Behaviours as from base method
recipe.consumeIngredients(null);
if (playSound)
{
Game1.playSound("coin");
}
if (___heldItem == null)
{
___heldItem = item;
Expand All @@ -210,7 +257,9 @@ public static bool CraftingPage_ClickCraftingRecipe_Prefix(
___heldItem.addToStack(item);
}
if (Game1.player.craftingRecipes.ContainsKey(recipe.name))
{
Game1.player.craftingRecipes[recipe.name] += recipe.numberProducedPerCraft;
}
Game1.stats.checkForCraftingAchievements();
if (Game1.options.gamepadControls && ___heldItem != null && Game1.player.couldInventoryAcceptThisItem(___heldItem))
{
Expand Down
3 changes: 2 additions & 1 deletion RaisedGardenBeds/OutdoorPot.cs
Original file line number Diff line number Diff line change
Expand Up @@ -185,8 +185,9 @@ public OutdoorPot(string variantKey, Vector2 tileLocation)

// IndoorPot (Vector2) : Object (Vector2, int, bool)
this.hoeDirt.Value = new HoeDirt();
if (Game1.isRaining && Game1.currentLocation.IsOutdoors)
if (Game1.currentLocation != null && Game1.currentLocation.IsOutdoors && Game1.IsRainingHere(Game1.currentLocation))
{
// Water the garden bed on-placement if outdoors and raining
this.hoeDirt.Value.state.Value = 1;
}
this.showNextIndex.Value = this.hoeDirt.Value.state.Value == 1;
Expand Down

0 comments on commit 73e6742

Please sign in to comment.