diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..083f401 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,72 @@ +# topmost editorconfig +root: true + +########## +## General formatting +## documentation: http://editorconfig.org +########## +[*] +indent_style = space +indent_size = 4 +insert_final_newline = true +trim_trailing_whitespace = true +charset = utf-8 + +[*.{csproj,nuspec,targets}] +indent_size = 2 + +[*.csproj] +insert_final_newline = false + +########## +## C# formatting +## documentation: https://docs.microsoft.com/en-us/visualstudio/ide/editorconfig-code-style-settings-reference +########## +[*.cs] + +#sort 'system' usings first +dotnet_sort_system_directives_first = true + +# use 'this.' qualifier +dotnet_style_qualification_for_field = true:error +dotnet_style_qualification_for_property = true:error +dotnet_style_qualification_for_method = true:error +dotnet_style_qualification_for_event = true:error + +# use language keywords (like int) instead of type (like Int32) +dotnet_style_predefined_type_for_locals_parameters_members = true:error +dotnet_style_predefined_type_for_member_access = true:error + +# don't use 'var' for language keywords +csharp_style_var_for_built_in_types = false:error + +# suggest modern C# features where simpler +dotnet_style_object_initializer = true:suggestion +dotnet_style_collection_initializer = true:suggestion +dotnet_style_coalesce_expression = true:suggestion +dotnet_style_null_propagation = true:suggestion +dotnet_style_explicit_tuple_names = true:suggestion +csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion +csharp_style_pattern_matching_over_as_with_null_check = true:suggestion +csharp_style_conditional_delegate_call = true:suggestion +csharp_prefer_simple_default_expression = true:suggestion + +# prefer method block bodies +csharp_style_expression_bodied_methods = false:suggestion +csharp_style_expression_bodied_constructors = false:suggestion + +# prefer property expression bodies +csharp_style_expression_bodied_properties = true:suggestion +csharp_style_expression_bodied_indexers = true:suggestion +csharp_style_expression_bodied_accessors = true:suggestion + +# prefer inline out variables +csharp_style_inlined_variable_declaration = true:warning + +# avoid superfluous braces +csharp_prefer_braces = false:suggestion + +# set block newline conventions +csharp_new_line_before_open_brace = true +csharp_new_line_before_else = false +csharp_new_line_before_catch = false diff --git a/PrismaticTools.sln b/PrismaticTools.sln index 40856f6..8266680 100644 --- a/PrismaticTools.sln +++ b/PrismaticTools.sln @@ -1,26 +1,28 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.27703.2026 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.28803.202 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PrismaticTools", "PrismaticTools\PrismaticTools.csproj", "{C24166EE-9341-4760-86B3-F89B326F3FC0}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "root", "root", "{7EF5E22B-2A2D-4B4A-9903-6B118B874F64}" + ProjectSection(SolutionItems) = preProject + .editorconfig = .editorconfig + .gitignore = .gitignore + LICENSE = LICENSE + README.md = README.md + EndProjectSection +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PrismaticTools", "PrismaticTools\PrismaticTools.csproj", "{7A6634BD-1FF7-4711-99B6-FD503ED9B5C0}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU - Debug|x86 = Debug|x86 Release|Any CPU = Release|Any CPU - Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {C24166EE-9341-4760-86B3-F89B326F3FC0}.Debug|Any CPU.ActiveCfg = Debug|x86 - {C24166EE-9341-4760-86B3-F89B326F3FC0}.Debug|Any CPU.Build.0 = Debug|x86 - {C24166EE-9341-4760-86B3-F89B326F3FC0}.Debug|x86.ActiveCfg = Debug|x86 - {C24166EE-9341-4760-86B3-F89B326F3FC0}.Debug|x86.Build.0 = Debug|x86 - {C24166EE-9341-4760-86B3-F89B326F3FC0}.Release|Any CPU.ActiveCfg = Release|x86 - {C24166EE-9341-4760-86B3-F89B326F3FC0}.Release|Any CPU.Build.0 = Release|x86 - {C24166EE-9341-4760-86B3-F89B326F3FC0}.Release|x86.ActiveCfg = Release|x86 - {C24166EE-9341-4760-86B3-F89B326F3FC0}.Release|x86.Build.0 = Release|x86 + {7A6634BD-1FF7-4711-99B6-FD503ED9B5C0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7A6634BD-1FF7-4711-99B6-FD503ED9B5C0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7A6634BD-1FF7-4711-99B6-FD503ED9B5C0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7A6634BD-1FF7-4711-99B6-FD503ED9B5C0}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/PrismaticTools.sln.DotSettings b/PrismaticTools.sln.DotSettings new file mode 100644 index 0000000..7cc51a4 --- /dev/null +++ b/PrismaticTools.sln.DotSettings @@ -0,0 +1,3 @@ + + DO_NOT_SHOW + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> \ No newline at end of file diff --git a/PrismaticTools/0Harmony.dll b/PrismaticTools/0Harmony.dll deleted file mode 100644 index 6361942..0000000 Binary files a/PrismaticTools/0Harmony.dll and /dev/null differ diff --git a/PrismaticTools/Assets/old/prismaticBar.png b/PrismaticTools/Assets/old/prismaticBar.png deleted file mode 100644 index b5ec38a..0000000 Binary files a/PrismaticTools/Assets/old/prismaticBar.png and /dev/null differ diff --git a/PrismaticTools/Assets/old/prismaticSprinkler.png b/PrismaticTools/Assets/old/prismaticSprinkler.png deleted file mode 100644 index f016887..0000000 Binary files a/PrismaticTools/Assets/old/prismaticSprinkler.png and /dev/null differ diff --git a/PrismaticTools/Assets/old/prismaticTools.png b/PrismaticTools/Assets/old/prismaticTools.png deleted file mode 100644 index 42c88a0..0000000 Binary files a/PrismaticTools/Assets/old/prismaticTools.png and /dev/null differ diff --git a/PrismaticTools/Assets/old/tools.png b/PrismaticTools/Assets/old/tools.png deleted file mode 100644 index 5718ba6..0000000 Binary files a/PrismaticTools/Assets/old/tools.png and /dev/null differ diff --git a/PrismaticTools/Assets/tools.png b/PrismaticTools/Assets/tools.png deleted file mode 100644 index 991cdc2..0000000 Binary files a/PrismaticTools/Assets/tools.png and /dev/null differ diff --git a/PrismaticTools/Framework/AssetEditor.cs b/PrismaticTools/Framework/AssetEditor.cs index 79611c5..ef3e577 100644 --- a/PrismaticTools/Framework/AssetEditor.cs +++ b/PrismaticTools/Framework/AssetEditor.cs @@ -1,63 +1,76 @@ -using Microsoft.Xna.Framework; +using System.Collections.Generic; +using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using StardewModdingAPI; -using StardewValley; -using System.Collections.Generic; +using StardewModdingAPI.Events; namespace PrismaticTools.Framework { - public class AssetEditor : IAssetEditor { + public class AssetEditor { + private string barName => ModEntry.ModHelper.Translation.Get("prismaticBar.name"); + private string barDesc => ModEntry.ModHelper.Translation.Get("prismaticBar.description"); + private string sprinklerName => ModEntry.ModHelper.Translation.Get("prismaticSprinkler.name"); + private string sprinklerDesc => ModEntry.ModHelper.Translation.Get("prismaticSprinkler.description"); - private string barName = ModEntry.ModHelper.Translation.Get("prismaticBar.name"); - private string barDesc = ModEntry.ModHelper.Translation.Get("prismaticBar.description"); - private string sprinklerName = ModEntry.ModHelper.Translation.Get("prismaticSprinkler.name"); - private string sprinklerDesc = ModEntry.ModHelper.Translation.Get("prismaticSprinkler.description"); + public void OnAssetRequested(AssetRequestedEventArgs e) { + // new item sprites + if (e.NameWithoutLocale.IsEquivalentTo("Maps/springobjects")) { + e.Edit(asset => { + var editor = asset.AsImage(); - public bool CanEdit(IAssetInfo asset) { - bool canEdit = - asset.AssetNameEquals("Maps/springobjects") - || asset.AssetNameEquals("Data/ObjectInformation") - || asset.AssetNameEquals("Data/CraftingRecipes") - || asset.AssetNameEquals("TileSheets/tools"); - return canEdit; - } + Texture2D bar = ModEntry.ModHelper.ModContent.Load("assets/prismaticBar.png"); + Texture2D sprinkler = ModEntry.ModHelper.ModContent.Load("assets/prismaticSprinkler.png"); + + editor.ExtendImage(minWidth: editor.Data.Width, minHeight: 1200 / 24 * 16); + editor.PatchImage(bar, targetArea: this.GetRectangle(PrismaticBarItem.INDEX)); + editor.PatchImage(sprinkler, targetArea: this.GetRectangle(PrismaticSprinklerItem.INDEX)); + }); + } + + // new item data + else if (e.NameWithoutLocale.IsEquivalentTo("Data/ObjectInformation")) { + e.Edit(asset => { + var data = asset.AsDictionary().Data; - public void Edit(IAssetData asset) { + data.Add(PrismaticBarItem.INDEX, $"{this.barName}/{PrismaticBarItem.PRICE}/{PrismaticBarItem.EDIBILITY}/{PrismaticBarItem.TYPE} {PrismaticBarItem.CATEGORY}/{this.barName}/{this.barDesc}"); + data.Add(PrismaticSprinklerItem.INDEX, $"{this.sprinklerName}/{PrismaticSprinklerItem.PRICE}/{PrismaticSprinklerItem.EDIBILITY}/{PrismaticSprinklerItem.TYPE} {PrismaticSprinklerItem.CATEGORY}/{this.sprinklerName}/{this.sprinklerDesc}"); + }); + } + + // new recipes + else if (e.NameWithoutLocale.IsEquivalentTo("Data/CraftingRecipes")) { + e.Edit(asset => { + var data = asset.AsDictionary().Data; + + // somehow the Dictionary maintains ordering, so reconstruct it with new sprinkler recipe immediately after prismatic + Dictionary newDict = new(); + foreach (string key in data.Keys) { + newDict.Add(key, data[key]); + if (key.Equals("Iridium Sprinkler")) { + if (asset.Locale != "en") + newDict.Add("Prismatic Sprinkler", $"{PrismaticBarItem.INDEX} 2 787 2/Home/{PrismaticSprinklerItem.INDEX}/false/Farming {PrismaticSprinklerItem.CRAFTING_LEVEL}/{this.sprinklerName}"); + else + newDict.Add("Prismatic Sprinkler", $"{PrismaticBarItem.INDEX} 2 787 2/Home/{PrismaticSprinklerItem.INDEX}/false/Farming {PrismaticSprinklerItem.CRAFTING_LEVEL}"); + } + } - if (asset.AssetNameEquals("Maps/springobjects")) { - Texture2D bar = ModEntry.ModHelper.Content.Load("Assets/prismaticBar.png", ContentSource.ModFolder); - Texture2D sprinkler = ModEntry.ModHelper.Content.Load("Assets/prismaticSprinkler.png", ContentSource.ModFolder); - Texture2D old = asset.AsImage().Data; - asset.ReplaceWith(new Texture2D(Game1.graphics.GraphicsDevice, old.Width, System.Math.Max(old.Height, 1200 / 24 * 16))); - asset.AsImage().PatchImage(old); - asset.AsImage().PatchImage(bar, targetArea: Rektangle(PrismaticBarItem.INDEX)); - asset.AsImage().PatchImage(sprinkler, targetArea: Rektangle(PrismaticSprinklerItem.INDEX)); - } else if (asset.AssetNameEquals("Data/ObjectInformation")) { - asset.AsDictionary().Data.Add(PrismaticBarItem.INDEX, $"{barName}/{PrismaticBarItem.PRICE}/{PrismaticBarItem.EDIBILITY}/{PrismaticBarItem.TYPE} {PrismaticBarItem.CATEGORY}/{barName}/{barDesc}"); - asset.AsDictionary().Data.Add(PrismaticSprinklerItem.INDEX, $"{sprinklerName}/{PrismaticSprinklerItem.PRICE}/{PrismaticSprinklerItem.EDIBILITY}/{PrismaticSprinklerItem.TYPE} {PrismaticSprinklerItem.CATEGORY}/{sprinklerName}/{sprinklerDesc}"); - } else if (asset.AssetNameEquals("Data/CraftingRecipes")) { - IAssetDataForDictionary oldDict = asset.AsDictionary(); - Dictionary newDict = new Dictionary(); - // somehow the Dictionary maintains ordering, so reconstruct it with new sprinkler recipe immediately after prismatic - foreach (string key in oldDict.Data.Keys) { - newDict.Add(key, oldDict.Data[key]); - if (key.Equals("Iridium Sprinkler")) { - if (asset.Locale != "en") - newDict.Add("Prismatic Sprinkler", $"{PrismaticBarItem.INDEX} 2 787 2/Home/{PrismaticSprinklerItem.INDEX}/false/Farming {PrismaticSprinklerItem.CRAFTING_LEVEL}/{sprinklerName}"); - else - newDict.Add("Prismatic Sprinkler", $"{PrismaticBarItem.INDEX} 2 787 2/Home/{PrismaticSprinklerItem.INDEX}/false/Farming {PrismaticSprinklerItem.CRAFTING_LEVEL}"); + data.Clear(); + foreach (string key in newDict.Keys) { + data.Add(key, newDict[key]); } - } - asset.AsDictionary().Data.Clear(); - foreach (string key in newDict.Keys) { - asset.AsDictionary().Data.Add(key, newDict[key]); - } - } else if (asset.AssetNameEquals("TileSheets\\tools")) { - asset.AsImage().PatchImage(ModEntry.toolsTexture, null, null, PatchMode.Overlay); + }); + } + + // tool sprites + else if (e.NameWithoutLocale.IsEquivalentTo("TileSheets/tools")) { + e.Edit(asset => { + var editor = asset.AsImage(); + editor.PatchImage(ModEntry.ToolsTexture, patchMode: PatchMode.Overlay); + }); } } - public Rectangle Rektangle(int id) { + public Rectangle GetRectangle(int id) { int x = (id % 24) * 16; int y = (id / 24) * 16; return new Rectangle(x, y, 16, 16); diff --git a/PrismaticTools/Framework/Blacksmith.cs b/PrismaticTools/Framework/Blacksmith.cs index 15f8656..4a6a9de 100644 --- a/PrismaticTools/Framework/Blacksmith.cs +++ b/PrismaticTools/Framework/Blacksmith.cs @@ -1,25 +1,24 @@ -using Microsoft.Xna.Framework.Graphics; +using System.Collections.Generic; using StardewModdingAPI.Events; using StardewValley; using StardewValley.Menus; using StardewValley.Tools; -using System.Collections.Generic; namespace PrismaticTools.Framework { - class BlacksmithInitializer { - - private static int UpgradeCost = ModEntry.Config.PrismaticToolCost; - private static int NumBars = 3; + internal class BlacksmithInitializer { + private static readonly int UpgradeCost = ModEntry.Config.PrismaticToolCost; - public static void Init() { - MenuEvents.MenuChanged += MenuEvents_MenuChanged1; + public static void Init(IModEvents events) { + events.Display.MenuChanged += OnMenuChanged; } - private static void MenuEvents_MenuChanged1(object sender, EventArgsClickableMenuChanged e) { - if (!(e.NewMenu is ShopMenu)) { + /// Raised after a game menu is opened, closed, or replaced. + /// The event sender. + /// The event arguments. + private static void OnMenuChanged(object sender, MenuChangedEventArgs e) { + if (!(e.NewMenu is ShopMenu menu)) { return; } - ShopMenu menu = e.NewMenu as ShopMenu; List categories = ModEntry.ModHelper.Reflection.GetField>(menu, "categoriesToSellHere").GetValue(); if (!categories.Contains(Object.GemCategory) || !categories.Contains(Object.mineralsCategory) || !categories.Contains(Object.metalResources)) { return; @@ -32,28 +31,28 @@ private static void MenuEvents_MenuChanged1(object sender, EventArgsClickableMen Tool toolFromName4 = who.getToolFromName("Hoe"); Tool tool; - List forSale = ModEntry.ModHelper.Reflection.GetField>(menu, "forSale").GetValue(); - Dictionary stock = ModEntry.ModHelper.Reflection.GetField>(menu, "itemPriceAndStock").GetValue(); + List forSale = menu.forSale; + Dictionary stock = menu.itemPriceAndStock; if (toolFromName1 != null && toolFromName1.UpgradeLevel == 4) { tool = new Axe { UpgradeLevel = 5 }; forSale.Add(tool); - stock.Add(tool, new int[3] { UpgradeCost, 1, PrismaticBarItem.INDEX }); + stock.Add(tool, new[] { UpgradeCost, 1, PrismaticBarItem.INDEX }); } if (toolFromName2 != null && toolFromName2.UpgradeLevel == 4) { tool = new WateringCan { UpgradeLevel = 5 }; forSale.Add(tool); - stock.Add(tool, new int[3] { UpgradeCost, 1, PrismaticBarItem.INDEX }); + stock.Add(tool, new[] { UpgradeCost, 1, PrismaticBarItem.INDEX }); } if (toolFromName3 != null && toolFromName3.UpgradeLevel == 4) { tool = new Pickaxe { UpgradeLevel = 5 }; forSale.Add(tool); - stock.Add(tool, new int[3] { UpgradeCost, 1, PrismaticBarItem.INDEX }); + stock.Add(tool, new[] { UpgradeCost, 1, PrismaticBarItem.INDEX }); } if (toolFromName4 != null && toolFromName4.UpgradeLevel == 4) { tool = new Hoe { UpgradeLevel = 5 }; forSale.Add(tool); - stock.Add(tool, new int[3] { UpgradeCost, 1, PrismaticBarItem.INDEX }); + stock.Add(tool, new[] { UpgradeCost, 1, PrismaticBarItem.INDEX }); } } } diff --git a/PrismaticTools/Framework/Furnace.cs b/PrismaticTools/Framework/Furnace.cs deleted file mode 100644 index 3f525c3..0000000 --- a/PrismaticTools/Framework/Furnace.cs +++ /dev/null @@ -1,75 +0,0 @@ -using Harmony; -using Microsoft.Xna.Framework; -using StardewValley; - -namespace PrismaticTools.Framework { - [HarmonyPatch(typeof(Farmer), "getTallyOfObject")] - internal class PrismaticGetTallyOfObject { - static public void Postfix(ref int __result, int index, bool bigCraftable) { - if (index == 382 && !bigCraftable) { - if (__result <= 0) { - __result = 666666; - return; - } - } - } - } - - [HarmonyPatch(typeof(Object), "performObjectDropInAction")] - internal class PrismaticPerformObjectDropInAction { - - static public bool Prefix(ref Object __instance, ref bool __result, ref Item dropInItem, bool probe, Farmer who) { - if (!(dropInItem is Object)) - return false; - Object object1 = dropInItem as Object; - - if (object1.ParentSheetIndex != 74) { - return true; - } - - if (__instance.name.Equals("Furnace")) { - if (who.IsLocalPlayer && who.getTallyOfObject(382, false) == 666666) { - if (!probe && who.IsLocalPlayer) - Game1.showRedMessage(Game1.content.LoadString("Strings\\StringsFromCSFiles:Object.cs.12772")); - return false; - } - if (__instance.heldObject.Value == null && !probe) { - __instance.heldObject.Value = new Object(PrismaticBarItem.INDEX, 5, false, -1, 0); - __instance.MinutesUntilReady = 2400; - who.currentLocation.playSound("furnace"); - __instance.initializeLightSource(__instance.TileLocation, false); - __instance.showNextIndex.Value = true; - - Multiplayer multiplayer = ModEntry.ModHelper.Reflection.GetField(typeof(Game1), "multiplayer").GetValue(); - multiplayer.broadcastSprites(who.currentLocation, new TemporaryAnimatedSprite[1] { - new TemporaryAnimatedSprite(30, __instance.TileLocation * 64f + new Vector2(0.0f, -16f), Color.White, 4, false, 50f, 10, 64, (float) (((double) __instance.TileLocation.Y + 1.0) * 64.0 / 10000.0 + 9.99999974737875E-05), -1, 0) { - alphaFade = 0.005f - } - }); - for (int index = who.Items.Count - 1; index >= 0; --index) { - if (who.Items[index] is Object && (who.Items[index] as Object).ParentSheetIndex == 382) { - --who.Items[index].Stack; - if (who.Items[index].Stack <= 0) { - who.Items[index] = (Item)null; - break; - } - break; - } - } - object1.Stack -= 1; - __result = object1.Stack <= 0; - return false; - } - if (__instance.heldObject.Value == null & probe) { - if (object1.ParentSheetIndex == 74) { - __instance.heldObject.Value = new Object(); - __result = true; - return false; - } - } - } - __result = false; - return false; - } - } -} \ No newline at end of file diff --git a/PrismaticTools/Framework/PrismaticAPI.cs b/PrismaticTools/Framework/PrismaticAPI.cs index 83e2a37..dc4abcc 100644 --- a/PrismaticTools/Framework/PrismaticAPI.cs +++ b/PrismaticTools/Framework/PrismaticAPI.cs @@ -1,5 +1,5 @@ -using Microsoft.Xna.Framework; using System.Collections.Generic; +using Microsoft.Xna.Framework; namespace PrismaticTools.Framework { public class PrismaticAPI { @@ -9,10 +9,9 @@ public class PrismaticAPI { public bool ArePrismaticSprinklersScarecrows { get; } = ModEntry.Config.UseSprinklersAsScarecrows; public IEnumerable GetSprinklerCoverage(Vector2 origin) { - for (int x = -SprinklerRange; x <= SprinklerRange; x++) { - for (int y = -SprinklerRange; y <= SprinklerRange; y++) { + for (int x = -this.SprinklerRange; x <= this.SprinklerRange; x++) { + for (int y = -this.SprinklerRange; y <= this.SprinklerRange; y++) yield return new Vector2(x, y) + origin; - } } } } diff --git a/PrismaticTools/Framework/PrismaticItems.cs b/PrismaticTools/Framework/PrismaticItems.cs index cec1db7..657ad14 100644 --- a/PrismaticTools/Framework/PrismaticItems.cs +++ b/PrismaticTools/Framework/PrismaticItems.cs @@ -1,24 +1,17 @@ -using StardewValley; +using StardewValley; namespace PrismaticTools.Framework { - - public class PrismaticSprinklerItem { + public class PrismaticSprinklerItem { public const int INDEX = 1113; - public const int OLD_INDEX = 813; - public const string NAME = "Prismatic Sprinkler"; public const int PRICE = 2000; public const int EDIBILITY = -300; public const string TYPE = "Crafting"; public const int CATEGORY = Object.CraftingCategory; - public const string DESCRIPTION = "Waters the 48 adjacent tiles every morning."; public const int CRAFTING_LEVEL = 9; } public class PrismaticBarItem : Object { public const int INDEX = 1112; - public const int OLD_INDEX = 812; - public const string NAME = "Prismatic Bar"; - public const string DESCRIPTION = "A mystical ingot forged from legend itself."; public const int PRICE = 2500; public const string TYPE = "Basic"; public const int CATEGORY = metalResources; diff --git a/PrismaticTools/Framework/PrismaticPatches.cs b/PrismaticTools/Framework/PrismaticPatches.cs new file mode 100644 index 0000000..87c4cbc --- /dev/null +++ b/PrismaticTools/Framework/PrismaticPatches.cs @@ -0,0 +1,249 @@ +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using Microsoft.Xna.Framework; +using Netcode; +using StardewValley; +using StardewValley.TerrainFeatures; +using StardewValley.Tools; +using SObject = StardewValley.Object; + +namespace PrismaticTools.Framework { + [SuppressMessage("ReSharper", "InconsistentNaming")] + internal static class PrismaticPatches { + /********* + ** Public methods + *********/ + /**** + ** Furnace patches + ****/ + public static void Farmer_GetTallyOfObject(ref int __result, int index, bool bigCraftable) { + if (index == 382 && !bigCraftable && __result <= 0) + __result = 666666; + } + + public static bool Object_PerformObjectDropInAction(ref SObject __instance, ref bool __result, ref Item dropInItem, bool probe, Farmer who) { + if (!(dropInItem is SObject object1)) + return false; + + if (object1.ParentSheetIndex != 74) + return true; + + if (__instance.name.Equals("Furnace")) { + if (who.IsLocalPlayer && who.getTallyOfObject(382, false) == 666666) { + if (!probe && who.IsLocalPlayer) + Game1.showRedMessage(Game1.content.LoadString("Strings\\StringsFromCSFiles:Object.cs.12772")); + return false; + } + if (__instance.heldObject.Value == null && !probe) { + __instance.heldObject.Value = new SObject(PrismaticBarItem.INDEX, 5); + __instance.MinutesUntilReady = 2400; + who.currentLocation.playSound("furnace"); + __instance.initializeLightSource(__instance.TileLocation); + __instance.showNextIndex.Value = true; + + Multiplayer multiplayer = ModEntry.ModHelper.Reflection.GetField(typeof(Game1), "multiplayer").GetValue(); + multiplayer.broadcastSprites(who.currentLocation, new TemporaryAnimatedSprite(30, __instance.TileLocation * 64f + new Vector2(0.0f, -16f), Color.White, 4, false, 50f, 10, 64, (float)((__instance.TileLocation.Y + 1.0) * 64.0 / 10000.0 + 9.99999974737875E-05)) { + alphaFade = 0.005f + }); + for (int index = who.Items.Count - 1; index >= 0; --index) { + if (who.Items[index] is SObject obj && obj.ParentSheetIndex == 382) { + --who.Items[index].Stack; + if (who.Items[index].Stack <= 0) { + who.Items[index] = null; + break; + } + break; + } + } + object1.Stack -= 1; + __result = object1.Stack <= 0; + return false; + } + if (__instance.heldObject.Value == null & probe) { + if (object1.ParentSheetIndex == 74) { + __instance.heldObject.Value = new SObject(); + __result = true; + return false; + } + } + } + __result = false; + return false; + } + + /**** + ** Sprinkler patches + ****/ + public static bool Farm_AddCrows(ref Farm __instance) { + int num1 = 0; + foreach (KeyValuePair pair in __instance.terrainFeatures.Pairs) { + if (pair.Value is HoeDirt dirt && dirt.crop != null) + ++num1; + } + List vector2List = new List(); + foreach (KeyValuePair pair in __instance.objects.Pairs) { + if (pair.Value.Name.Contains("arecrow")) { + vector2List.Add(pair.Key); + } + } + int num2 = System.Math.Min(4, num1 / 16); + for (int index1 = 0; index1 < num2; ++index1) { + if (Game1.random.NextDouble() < 1.0) { + for (int index2 = 0; index2 < 10; ++index2) { + Vector2 key = __instance.terrainFeatures.Pairs.ElementAt(Game1.random.Next(__instance.terrainFeatures.Count())).Key; + if (__instance.terrainFeatures[key] is HoeDirt dirt && dirt.crop?.currentPhase.Value > 1) { + bool flag = false; + foreach (Vector2 index3 in vector2List) { + if (Vector2.Distance(index3, key) < 9.0) { + flag = true; + ++__instance.objects[index3].SpecialVariable; + break; + } + } + if (!flag) + dirt.crop = null; + break; + } + } + } + } + return false; + } + + public static void After_Object_IsSprinkler(ref SObject __instance, ref bool __result) { + if (__instance.ParentSheetIndex == PrismaticSprinklerItem.INDEX) + __result = true; + } + + public static void After_Object_GetBaseRadiusForSprinkler(ref SObject __instance, ref int __result) { + if (__instance.ParentSheetIndex == PrismaticSprinklerItem.INDEX) + __result = ModEntry.Config.SprinklerRange; + } + + public static bool Object_UpdatingWhenCurrentLocation(ref SObject __instance, GameTime time, GameLocation environment) { + var obj = __instance; + + // enable sprinkler scarecrow/light + if (obj.ParentSheetIndex == PrismaticSprinklerItem.INDEX) + TryEnablePrismaticSprinkler(environment, obj.TileLocation, obj); + + return true; + } + + public static bool Object_OnPlacing(ref SObject __instance, GameLocation location, int x, int y) { + var obj = __instance; + + // enable sprinkler scarecrow/light + if (obj.ParentSheetIndex == PrismaticSprinklerItem.INDEX) + TryEnablePrismaticSprinkler(location, new Vector2(x, y), obj); + + return true; + } + + /**** + ** Tool patches + ****/ + public static void Tree_PerformToolAction(ref Tree __instance, Tool t, int explosion) { + if (t is Axe axe && axe.UpgradeLevel == 5 && explosion <= 0 && ModEntry.ModHelper.Reflection.GetField(__instance, "health").GetValue() > -99f) { + __instance.health.Value = 0.0f; + } + } + + public static void FruitTree_PerformToolAction(ref FruitTree __instance, Tool t, int explosion) { + if (t is Axe axe && axe.UpgradeLevel == 5 && explosion <= 0 && ModEntry.ModHelper.Reflection.GetField(__instance, "health").GetValue() > -99f) { + __instance.health.Value = 0.0f; + } + } + + public static void Pickaxe_DoFunction(ref Pickaxe __instance, GameLocation location, int x, int y, int power, Farmer who) { + if (__instance.UpgradeLevel == 5) { + if (location.Objects.TryGetValue(new Vector2(x / 64, y / 64), out SObject obj)) { + if (obj.Name == "Stone") { + obj.MinutesUntilReady = 0; + } + } + } + } + + public static void ResourceClump_PerformToolAction(ref ResourceClump __instance, Tool t, int damage, Vector2 tileLocation, GameLocation location) { + if (t is Axe && t.UpgradeLevel == 5 && (__instance.parentSheetIndex.Value == 600 || __instance.parentSheetIndex.Value == 602)) { + __instance.health.Value = 0; + } + } + + public static void Tool_TilesAffected_Postfix(ref List __result, Vector2 tileLocation, int power, Farmer who) { + if (power >= 6) { + __result.Clear(); + Vector2 direction; + Vector2 orth; + int radius = ModEntry.Config.PrismaticToolWidth; + int length = ModEntry.Config.PrismaticToolLength; + switch (who.FacingDirection) { + case 0: direction = new Vector2(0, -1); orth = new Vector2(1, 0); break; + case 1: direction = new Vector2(1, 0); orth = new Vector2(0, 1); break; + case 2: direction = new Vector2(0, 1); orth = new Vector2(-1, 0); break; + case 3: direction = new Vector2(-1, 0); orth = new Vector2(0, -1); break; + default: direction = Vector2.Zero; orth = Vector2.Zero; break; + } + for (int i = 0; i < length; i++) { + __result.Add(direction * i + tileLocation); + for (int j = 1; j <= radius; j++) { + __result.Add(direction * i + orth * j + tileLocation); + __result.Add(direction * i + orth * -j + tileLocation); + } + } + } + } + + public static bool Tool_Name(Tool __instance, ref string __result) { + if (__instance.UpgradeLevel == 5) { + + switch (__instance.BaseName) { + case "Axe": __result = ModEntry.ModHelper.Translation.Get("prismaticAxe"); break; + case "Pickaxe": __result = ModEntry.ModHelper.Translation.Get("prismaticPickaxe"); break; + case "Watering Can": __result = ModEntry.ModHelper.Translation.Get("prismaticWatercan"); break; + case "Hoe": __result = ModEntry.ModHelper.Translation.Get("prismaticHoe"); break; + } + //__result = "Prismatic " + __instance.BaseName; + //__result = ModEntry.ModHelper.Translation.Get("prismatic.prefix") + " " + Game1.content.LoadString("Strings\\StringsFromCSFiles:Axe.cs.1"); + return false; + } + return true; + } + + public static bool Tool_DisplayName(Tool __instance, ref string __result) { + if (__instance.UpgradeLevel == 5) { + __result = __instance.Name; + return false; + } + return true; + } + + + /********* + ** Private methods + *********/ + /// Try to add the light source for a prismatic sprinkler, if applicable. + /// The location containing the sprinkler. + /// The sprinkler's tile coordinate within the location. + /// The object to check. + private static void TryEnablePrismaticSprinkler(GameLocation location, Vector2 tile, SObject obj) { + if (obj.ParentSheetIndex != PrismaticSprinklerItem.INDEX) + return; + + // set name + obj.Name = ModEntry.Config.UseSprinklersAsScarecrows + ? "Prismatic Scarecrow Sprinkler" + : "Prismatic Sprinkler"; + + // add light source + if (ModEntry.Config.UseSprinklersAsLamps) { + int id = (int)tile.X * 4000 + (int)tile.Y; + if (!location.sharedLights.ContainsKey(id)) { + obj.lightSource = new LightSource(4, tile * Game1.tileSize, 2.0f, Color.Black, id); + location.sharedLights.Add(id, obj.lightSource); + } + } + } + } +} diff --git a/PrismaticTools/Framework/Sprinkler.cs b/PrismaticTools/Framework/Sprinkler.cs deleted file mode 100644 index 3e520b0..0000000 --- a/PrismaticTools/Framework/Sprinkler.cs +++ /dev/null @@ -1,142 +0,0 @@ -using Microsoft.Xna.Framework; -using StardewValley; -using StardewValley.TerrainFeatures; -using StardewModdingAPI.Events; -using System.Collections.Generic; -using System.Linq; -using Harmony; -using System.Reflection.Emit; - -namespace PrismaticTools.Framework { - - // searches map for any currently placed prismatic sprinklers and: - // - waters adjacent tiles - // - enables light sources - // - optionally makes them act as scarecrows - public static class SprinklerInitializer { - - public static void Init() { - TimeEvents.AfterDayStarted += TimeEvents_AfterDayStarted; - SaveEvents.AfterLoad += SaveEvents_AfterLoad; - LocationEvents.ObjectsChanged += LocationEvents_ObjectsChanged; - } - - private static void SaveEvents_AfterLoad(object sender, System.EventArgs e) { - if (ModEntry.Config.UseSprinklersAsScarecrows) { - foreach (GameLocation location in Game1.locations) { - foreach (Object obj in location.Objects.Values) { - if (obj.ParentSheetIndex == PrismaticSprinklerItem.INDEX) { - obj.Name = "Prismatic Scarecrow Sprinkler"; - } - } - } - } - - // set light source - if (!ModEntry.Config.UseSprinklersAsLamps) { - return; - } - Object sprinkler; - foreach (GameLocation location in Game1.locations) { - if (location is GameLocation) { - foreach (KeyValuePair pair in location.objects.Pairs) { - if (location.objects[pair.Key].ParentSheetIndex == PrismaticSprinklerItem.INDEX) { - sprinkler = location.objects[pair.Key]; - int id = (int)sprinkler.TileLocation.X * 4000 + (int)sprinkler.TileLocation.Y; - sprinkler.lightSource = new LightSource(4, new Vector2((sprinkler.boundingBox.X + 32), (sprinkler.boundingBox.Y + 32)), 2.0f, Color.Black, id); - location.sharedLights.Add(sprinkler.lightSource.Clone()); - } - } - } - } - } - - private static void LocationEvents_ObjectsChanged(object sender, EventArgsLocationObjectsChanged e) { - // adds lightsources to newly placed sprinkler - if (!ModEntry.Config.UseSprinklersAsLamps) { - return; - } - foreach (KeyValuePair pair in e.Added) { - Object obj = pair.Value; - if (obj.ParentSheetIndex == PrismaticSprinklerItem.INDEX) { - int id = (int)obj.TileLocation.X * 4000 + (int)obj.TileLocation.Y; - obj.lightSource = new LightSource(4, new Vector2((obj.boundingBox.X + 32), (obj.boundingBox.Y + 32)), 2.0f, Color.Black, id); - obj.Name = "Prismatic Scarecrow Sprinkler"; - Game1.currentLocation.sharedLights.Add(obj.lightSource.Clone()); - } - } - } - - private static void TimeEvents_AfterDayStarted(object sender, System.EventArgs e) { - foreach (GameLocation location in Game1.locations) { - foreach (Object obj in location.Objects.Values) { - if (obj.ParentSheetIndex == PrismaticSprinklerItem.INDEX) { - - // add water spray animation - location.TemporarySprites.Add(new TemporaryAnimatedSprite("TileSheets\\animations", new Rectangle(0, 2176, 320, 320), 60f, 4, 100, obj.TileLocation * 64 + new Vector2(-192, -208), false, false) { - color = Color.White * 0.4f, - scale = 7f / 5f, - delayBeforeAnimationStart = 0, - id = obj.TileLocation.X * 4000f + obj.TileLocation.Y - }); - - if (location is Farm || location.IsGreenhouse) { - for (int index1 = (int)obj.TileLocation.X - ModEntry.Config.SprinklerRange; index1 <= obj.TileLocation.X + ModEntry.Config.SprinklerRange; ++index1) { - for (int index2 = (int)obj.TileLocation.Y - ModEntry.Config.SprinklerRange; index2 <= obj.TileLocation.Y + ModEntry.Config.SprinklerRange; ++index2) { - Vector2 key = new Vector2(index1, index2); - - // water dirt - if (location.terrainFeatures.ContainsKey(key) && location.terrainFeatures[key] is HoeDirt) { - (location.terrainFeatures[key] as HoeDirt).state.Value = 1; - } - } - } - } - } - } - } - } - - [HarmonyPatch(typeof(Farm), "addCrows")] - internal class PrismaticAddCrows { - static public bool Prefix(ref Farm __instance) { - int num1 = 0; - foreach (KeyValuePair pair in __instance.terrainFeatures.Pairs) { - if (pair.Value is HoeDirt && (pair.Value as HoeDirt).crop != null) - ++num1; - } - List vector2List = new List(); - foreach (KeyValuePair pair in __instance.objects.Pairs) { - if (pair.Value.Name.Contains("arecrow")) { - vector2List.Add(pair.Key); - } - } - int num2 = System.Math.Min(4, num1 / 16); - for (int index1 = 0; index1 < num2; ++index1) { - if (Game1.random.NextDouble() < 1.0) { - for (int index2 = 0; index2 < 10; ++index2) { - Vector2 key = __instance.terrainFeatures.Pairs.ElementAt(Game1.random.Next(__instance.terrainFeatures.Count())).Key; - if (__instance.terrainFeatures[key] is HoeDirt && (__instance.terrainFeatures[key] as HoeDirt).crop != null && ((__instance.terrainFeatures[key] as HoeDirt).crop.currentPhase.Value) > 1) { - bool flag = false; - foreach (Vector2 index3 in vector2List) { - if ((double)Vector2.Distance(index3, key) < 9.0) { - flag = true; - ++__instance.objects[index3].SpecialVariable; - break; - } - } - if (!flag) { - (__instance.terrainFeatures[key] as HoeDirt).crop = (Crop)null; - break; - } - break; - } - } - } - } - return false; - } - } - } -} - diff --git a/PrismaticTools/Framework/Tools.cs b/PrismaticTools/Framework/Tools.cs deleted file mode 100644 index 2f8e3b8..0000000 --- a/PrismaticTools/Framework/Tools.cs +++ /dev/null @@ -1,108 +0,0 @@ -using Harmony; -using System.Collections.Generic; -using StardewValley; -using Microsoft.Xna.Framework; - -using StardewValley.TerrainFeatures; -using Netcode; -using StardewValley.Tools; - -namespace PrismaticTools.Framework { - - [HarmonyPatch(typeof(Tree), "performToolAction")] - internal class PrismaticPerformToolActionTree { - static void Prefix(ref Tree __instance, Tool t, int explosion) { - if (t is Axe && (t as Axe).UpgradeLevel == 5 && explosion <= 0 && ModEntry.ModHelper.Reflection.GetField(__instance, "health").GetValue() > -99f) { - __instance.health.Value = 0.0f; - } - } - } - - [HarmonyPatch(typeof(FruitTree), "performToolAction")] - internal class PrismaticPerformToolActionFruitTree { - static void Prefix(ref FruitTree __instance, Tool t, int explosion) { - if (t is Axe && (t as Axe).UpgradeLevel == 5 && explosion <= 0 && ModEntry.ModHelper.Reflection.GetField(__instance, "health").GetValue() > -99f) { - __instance.health.Value = 0.0f; - } - } - } - - [HarmonyPatch(typeof(Pickaxe), "DoFunction")] - internal class PrimaticDoFunction { - static void Prefix(ref Pickaxe __instance, GameLocation location, int x, int y, int power, Farmer who) { - if (__instance.UpgradeLevel == 5) { - if (location.Objects.TryGetValue(new Vector2(x/64, y/64), out Object obj)) { - if (obj.Name == "Stone") { - obj.MinutesUntilReady = 0; - } - } - } - } - } - - [HarmonyPatch(typeof(ResourceClump), "performToolAction")] - internal class PrismaticPerformToolActionResourceClump { - static void Prefix(ref ResourceClump __instance, Tool t, int damage, Vector2 tileLocation, GameLocation location) { - if (t is Axe && t.UpgradeLevel == 5 && (__instance.parentSheetIndex.Value == 600 || __instance.parentSheetIndex.Value == 602)) { - __instance.health.Value = 0; - } - } - } - - [HarmonyPatch(typeof(Tool), "tilesAffected")] - internal class PrismaticTilesAffected { - static void Postfix(ref List __result, Vector2 tileLocation, int power, Farmer who) { - if (power >= 6) { - __result.Clear(); - Vector2 direction; - Vector2 orth; - int radius = ModEntry.Config.PrismaticToolWidth; - int length = ModEntry.Config.PrismaticToolLength; - switch (who.FacingDirection) { - case 0: direction = new Vector2(0, -1); orth = new Vector2(1, 0); break; - case 1: direction = new Vector2(1, 0); orth = new Vector2(0, 1); break; - case 2: direction = new Vector2(0, 1); orth = new Vector2(-1, 0); break; - case 3: direction = new Vector2(-1, 0); orth = new Vector2(0, -1); break; - default: direction = new Vector2(0, 0); orth = new Vector2(0, 0); break; - } - for (int i = 0; i < length; i++) { - __result.Add(direction * i + tileLocation); - for (int j = 1; j <= radius; j++) { - __result.Add(direction * i + orth * j + tileLocation); - __result.Add(direction * i + orth * -j + tileLocation); - } - } - } - } - } - - [HarmonyPatch(typeof(Tool), "get_Name")] - internal class PrismaticGetName { - public static bool Prefix(Tool __instance, ref string __result) { - if (__instance.UpgradeLevel == 5) { - - switch (__instance.BaseName) { - case "Axe": __result = ModEntry.ModHelper.Translation.Get("prismaticAxe"); break; - case "Pickaxe": __result = ModEntry.ModHelper.Translation.Get("prismaticPickaxe"); break; - case "Watering Can": __result = ModEntry.ModHelper.Translation.Get("prismaticWatercan"); break; - case "Hoe": __result = ModEntry.ModHelper.Translation.Get("prismaticHoe"); break; - } - //__result = "Prismatic " + __instance.BaseName; - //__result = ModEntry.ModHelper.Translation.Get("prismatic.prefix") + " " + Game1.content.LoadString("Strings\\StringsFromCSFiles:Axe.cs.1"); - return false; - } - return true; - } - } - - [HarmonyPatch(typeof(Tool), "get_DisplayName")] - internal static class CobaltDisplayNameHook { - public static bool Prefix(Tool __instance, ref string __result) { - if (__instance.UpgradeLevel == 5) { - __result = __instance.Name; - return false; - } - return true; - } - } -} diff --git a/PrismaticTools/ModConfig.cs b/PrismaticTools/ModConfig.cs index 6affd87..6f7efbb 100644 --- a/PrismaticTools/ModConfig.cs +++ b/PrismaticTools/ModConfig.cs @@ -1,20 +1,10 @@ - namespace PrismaticTools.Framework { public class ModConfig { - public bool UseSprinklersAsScarecrows { get; set; } - public bool UseSprinklersAsLamps { get; set; } - public int SprinklerRange { get; set; } - public int PrismaticToolLength { get; set; } - public int PrismaticToolWidth { get; set; } - public int PrismaticToolCost { get; set; } - - public ModConfig() { - UseSprinklersAsScarecrows = true; - UseSprinklersAsLamps = true; - SprinklerRange = 3; - PrismaticToolLength = 7; - PrismaticToolWidth = 2; - PrismaticToolCost = 100000; - } + public bool UseSprinklersAsScarecrows { get; set; } = true; + public bool UseSprinklersAsLamps { get; set; } = true; + public int SprinklerRange { get; set; } = 3; + public int PrismaticToolLength { get; set; } = 7; + public int PrismaticToolWidth { get; set; } = 2; + public int PrismaticToolCost { get; set; } = 100000; } } diff --git a/PrismaticTools/ModEntry.cs b/PrismaticTools/ModEntry.cs index 658c927..1eb9ff9 100644 --- a/PrismaticTools/ModEntry.cs +++ b/PrismaticTools/ModEntry.cs @@ -1,73 +1,136 @@ -using Microsoft.Xna.Framework; +using System.Collections.Generic; +using HarmonyLib; +using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; -using System.Reflection; - -using Harmony; -using StardewValley; +using PrismaticTools.Framework; using StardewModdingAPI; using StardewModdingAPI.Events; - -using PrismaticTools.Framework; -using System.Collections.Generic; -using StardewValley.Objects; -using StardewValley.Locations; +using StardewValley; +using StardewValley.TerrainFeatures; using StardewValley.Tools; namespace PrismaticTools { - public class ModEntry : Mod { - - public static IMonitor mon; public static IModHelper ModHelper; public static ModConfig Config; + public static Texture2D ToolsTexture; - public static Texture2D toolsTexture; - private int colorCycleIndex = 0; - private List colors = new List(); + private int colorCycleIndex; + private readonly List colors = new List(); + private AssetEditor AssetEditor; public override void Entry(IModHelper helper) { - mon = Monitor; ModHelper = helper; + this.AssetEditor = new AssetEditor(); - Config = Helper.ReadConfig(); + Config = this.Helper.ReadConfig(); - toolsTexture = ModHelper.Content.Load("Assets/tools.png", ContentSource.ModFolder); + ToolsTexture = ModHelper.ModContent.Load("assets/tools.png"); - helper.ConsoleCommands.Add("ptools", "Upgrade all tools to prismatic", UpgradeTools); + helper.ConsoleCommands.Add("ptools", "Upgrade all tools to prismatic", this.UpgradeTools); - SaveEvents.AfterLoad += SaveEvents_AfterLoad; - PlayerEvents.InventoryChanged += PlayerEvents_InventoryChanged; - GameEvents.EighthUpdateTick += GameEvents_EighthUpdateTick; + helper.Events.GameLoop.SaveLoaded += this.OnSaveLoaded; + helper.Events.GameLoop.UpdateTicked += this.OnUpdateTicked; + helper.Events.Player.InventoryChanged += this.OnInventoryChanged; + helper.Events.Content.AssetRequested += this.OnAssetRequested; - helper.Content.AssetEditors.Add(new AssetEditor()); - SprinklerInitializer.Init(); - BlacksmithInitializer.Init(); + BlacksmithInitializer.Init(helper.Events); - InitColors(); + this.InitColors(); - var harmony = HarmonyInstance.Create("stokastic.PrismaticTools"); - harmony.PatchAll(Assembly.GetExecutingAssembly()); + var harmony = new Harmony("stokastic.PrismaticTools"); + this.ApplyPatches(harmony); } - private void GameEvents_EighthUpdateTick(object sender, System.EventArgs e) { + private void ApplyPatches(Harmony harmony) { + // furnaces + harmony.Patch( + original: AccessTools.Method(typeof(Farmer), nameof(Farmer.getTallyOfObject)), + prefix: new HarmonyMethod(typeof(PrismaticPatches), nameof(PrismaticPatches.Farmer_GetTallyOfObject)) + ); + harmony.Patch( + original: AccessTools.Method(typeof(Object), nameof(Object.performObjectDropInAction)), + prefix: new HarmonyMethod(typeof(PrismaticPatches), nameof(PrismaticPatches.Object_PerformObjectDropInAction)) + ); + + // sprinklers + harmony.Patch( + original: AccessTools.Method(typeof(Farm), nameof(Farm.addCrows)), + prefix: new HarmonyMethod(typeof(PrismaticPatches), nameof(PrismaticPatches.Farm_AddCrows)) + ); + harmony.Patch( + original: AccessTools.Method(typeof(Object), nameof(Object.IsSprinkler)), + postfix: new HarmonyMethod(typeof(PrismaticPatches), nameof(PrismaticPatches.After_Object_IsSprinkler)) + ); + harmony.Patch( + original: AccessTools.Method(typeof(Object), nameof(Object.GetBaseRadiusForSprinkler)), + postfix: new HarmonyMethod(typeof(PrismaticPatches), nameof(PrismaticPatches.After_Object_GetBaseRadiusForSprinkler)) + ); + harmony.Patch( + original: AccessTools.Method(typeof(Object), nameof(Object.updateWhenCurrentLocation)), + prefix: new HarmonyMethod(typeof(PrismaticPatches), nameof(PrismaticPatches.Object_UpdatingWhenCurrentLocation)) + ); + harmony.Patch( + original: AccessTools.Method(typeof(Object), nameof(Object.placementAction)), + prefix: new HarmonyMethod(typeof(PrismaticPatches), nameof(PrismaticPatches.Object_OnPlacing)) + ); + + // tools + harmony.Patch( + original: AccessTools.Method(typeof(Tree), nameof(Tree.performToolAction)), + prefix: new HarmonyMethod(typeof(PrismaticPatches), nameof(PrismaticPatches.Tree_PerformToolAction)) + ); + harmony.Patch( + original: AccessTools.Method(typeof(FruitTree), nameof(FruitTree.performToolAction)), + prefix: new HarmonyMethod(typeof(PrismaticPatches), nameof(PrismaticPatches.FruitTree_PerformToolAction)) + ); + harmony.Patch( + original: AccessTools.Method(typeof(Pickaxe), nameof(Pickaxe.DoFunction)), + prefix: new HarmonyMethod(typeof(PrismaticPatches), nameof(PrismaticPatches.Pickaxe_DoFunction)) + ); + harmony.Patch( + original: AccessTools.Method(typeof(ResourceClump), nameof(ResourceClump.performToolAction)), + prefix: new HarmonyMethod(typeof(PrismaticPatches), nameof(PrismaticPatches.ResourceClump_PerformToolAction)) + ); + harmony.Patch( + original: AccessTools.Method(typeof(Tool), "tilesAffected"), + postfix: new HarmonyMethod(typeof(PrismaticPatches), nameof(PrismaticPatches.Tool_TilesAffected_Postfix)) + ); + harmony.Patch( + original: AccessTools.Property(typeof(Tool), nameof(Tool.Name)).GetMethod, + prefix: new HarmonyMethod(typeof(PrismaticPatches), nameof(PrismaticPatches.Tool_Name)) + ); + harmony.Patch( + original: AccessTools.Property(typeof(Tool), nameof(Tool.DisplayName)).GetMethod, + prefix: new HarmonyMethod(typeof(PrismaticPatches), nameof(PrismaticPatches.Tool_DisplayName)) + ); + } + + /// Raised after the game state is updated (≈60 times per second). + /// The event sender. + /// The event arguments. + private void OnUpdateTicked(object sender, UpdateTickedEventArgs e) { + if (!e.IsMultipleOf(8)) + return; + Farmer farmer = Game1.player; Item item; try { item = farmer.Items[farmer.CurrentToolIndex]; - } catch (System.ArgumentOutOfRangeException) { + } catch (System.ArgumentOutOfRangeException) { return; } - if (item == null || !(item is Object) || !((item as Object).ParentSheetIndex == PrismaticBarItem.INDEX)) { + if (!(item is Object obj) || obj.ParentSheetIndex != PrismaticBarItem.INDEX) { return; } - for (int i=0; iAdds light sources to prismatic bar and sprinkler items in inventory. private void AddLightsToInventoryItems() { if (!Config.UseSprinklersAsLamps) { return; } foreach (Item item in Game1.player.Items) { - if (item is Object) { - if (item.ParentSheetIndex == PrismaticSprinklerItem.INDEX) { - (item as Object).lightSource = new LightSource(LightSource.cauldronLight, new Vector2(0, 0), 2.0f, new Color(0.0f, 0.0f, 0.0f)); - } else if (item.ParentSheetIndex == PrismaticBarItem.INDEX) { - (item as Object).lightSource = new LightSource(LightSource.cauldronLight, new Vector2(0, 0), 1.0f, colors[colorCycleIndex]); + if (item is Object obj) { + if (obj.ParentSheetIndex == PrismaticSprinklerItem.INDEX) { + obj.lightSource = new LightSource(LightSource.cauldronLight, Vector2.Zero, 2.0f, new Color(0.0f, 0.0f, 0.0f)); + } else if (obj.ParentSheetIndex == PrismaticBarItem.INDEX) { + obj.lightSource = new LightSource(LightSource.cauldronLight, Vector2.Zero, 1.0f, this.colors[this.colorCycleIndex]); } } } } - private void PlayerEvents_InventoryChanged(object sender, EventArgsInventoryChanged e) { - AddLightsToInventoryItems(); + /// Set scarecrow mode for sprinkler items. + private void SetScarecrowModeForAllSprinklers() { + foreach (GameLocation location in Game1.locations) { + foreach (Object obj in location.Objects.Values) { + if (obj.ParentSheetIndex == PrismaticSprinklerItem.INDEX) { + obj.Name = Config.UseSprinklersAsScarecrows + ? "Prismatic Scarecrow Sprinkler" + : "Prismatic Sprinkler"; + } + } + } } - private void SaveEvents_AfterLoad(object sender, System.EventArgs e) { + /// Raised after items are added or removed to a player's inventory. + /// The event sender. + /// The event arguments. + private void OnInventoryChanged(object sender, InventoryChangedEventArgs e) { + if (e.IsLocalPlayer) + this.AddLightsToInventoryItems(); + } + + /// Raised after the player loads a save slot and the world is initialised. + /// The event sender. + /// The event arguments. + private void OnSaveLoaded(object sender, SaveLoadedEventArgs e) { // force add sprinkler recipe for people who were level 10 before installing mod if (Game1.player.FarmingLevel >= PrismaticSprinklerItem.CRAFTING_LEVEL) { try { @@ -110,73 +193,21 @@ private void SaveEvents_AfterLoad(object sender, System.EventArgs e) { } catch { } } - IndexCompatibilityFix(); - AddLightsToInventoryItems(); + this.AddLightsToInventoryItems(); + this.SetScarecrowModeForAllSprinklers(); } - // used to resolve asset conflicts with other mods - private void IndexCompatibilityFix() { - var watch = System.Diagnostics.Stopwatch.StartNew(); - foreach (GameLocation location in Game1.locations) { - if (location is FarmHouse) { - // check fridge - if ((location as FarmHouse).fridge.Value != null) { - foreach (Item item in (location as FarmHouse).fridge.Value.items) { - if (item == null) { - continue; - } - if (item.Name.Contains("Prismatic")) { - SwapIndex(item); - } - } - } - } - foreach (Object obj in location.Objects.Values) { - // check chests, signposts, furnaces, and placed sprinklers - if (obj == null) { - continue; - } - - if (obj is Chest) { - foreach (Item item in (obj as Chest).items) { - if (item.Name.Contains("Prismatic")) { - SwapIndex(item); - } - } - } else if (obj is Sign) { - SwapIndex((obj as Sign).displayItem.Value); - } else if (obj.bigCraftable.Value && obj.name.Equals("Furnace")) { - if (obj.heldObject.Value != null) { - SwapIndex((obj.heldObject.Value)); - } - } else if (obj.ParentSheetIndex == PrismaticBarItem.OLD_INDEX || obj.ParentSheetIndex == PrismaticSprinklerItem.OLD_INDEX) { - SwapIndex(obj); - } - } - } - - foreach (Item item in Game1.player.Items) { - if (item != null && item.Name.Contains("Prismatic")) { - SwapIndex(item); - } - } - watch.Stop(); - Monitor.Log($"IndexCompatibility exec time: {watch.ElapsedMilliseconds} ms", LogLevel.Trace); - } - - private void SwapIndex(Item item) { - if (item.ParentSheetIndex == PrismaticBarItem.OLD_INDEX) { - item.ParentSheetIndex = PrismaticBarItem.INDEX; - } - if (item.ParentSheetIndex == PrismaticSprinklerItem.OLD_INDEX) { - item.ParentSheetIndex = PrismaticSprinklerItem.INDEX; - } + /// Raised when an asset is being requested from the content pipeline. + /// The event sender. + /// The event arguments. + private void OnAssetRequested(object sender, AssetRequestedEventArgs e) { + this.AssetEditor.OnAssetRequested(e); } private void InitColors() { int n = 24; - for(int i=0; i - - + - Debug - AnyCPU - {C24166EE-9341-4760-86B3-F89B326F3FC0} - Library - Properties - PrismaticTools - PrismaticTools - v4.5 - 512 - - + 1.7.1 + net5.0 + + true - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - true - bin\x86\Debug\ - DEBUG;TRACE - full - x86 - prompt - MinimumRecommendedRules.ruleset - - - bin\x86\Release\ - TRACE - true - none - x86 - prompt - MinimumRecommendedRules.ruleset - false - - - - - - - .\0Harmony.dll - - - - - - - - - - - - - - - - - - - - - - - - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - - - - + - - Always - - - Always - - - Always - - - Always - - - PreserveNewest - + - - - - - This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - \ No newline at end of file + diff --git a/PrismaticTools/Properties/AssemblyInfo.cs b/PrismaticTools/Properties/AssemblyInfo.cs deleted file mode 100644 index 078602c..0000000 --- a/PrismaticTools/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("PrismaticTools")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("PrismaticTools")] -[assembly: AssemblyCopyright("Copyright © 2018")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("c24166ee-9341-4760-86b3-f89b326f3fc0")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/PrismaticTools/Assets/prismaticBar.png b/PrismaticTools/assets/prismaticBar.png similarity index 100% rename from PrismaticTools/Assets/prismaticBar.png rename to PrismaticTools/assets/prismaticBar.png diff --git a/PrismaticTools/Assets/prismaticSprinkler.png b/PrismaticTools/assets/prismaticSprinkler.png similarity index 100% rename from PrismaticTools/Assets/prismaticSprinkler.png rename to PrismaticTools/assets/prismaticSprinkler.png diff --git a/PrismaticTools/Assets/prismaticTools.png b/PrismaticTools/assets/prismaticTools.png similarity index 100% rename from PrismaticTools/Assets/prismaticTools.png rename to PrismaticTools/assets/prismaticTools.png diff --git a/PrismaticTools/assets/tools.png b/PrismaticTools/assets/tools.png new file mode 100644 index 0000000..8142b81 Binary files /dev/null and b/PrismaticTools/assets/tools.png differ diff --git a/PrismaticTools/i18n/de.json b/PrismaticTools/i18n/de.json index 50be3e0..8197c9d 100644 --- a/PrismaticTools/i18n/de.json +++ b/PrismaticTools/i18n/de.json @@ -1,11 +1,11 @@ -{ - "prismatic.prefix": "Prismatische", - "prismaticBar.name": "Prismatischer Barren", - "prismaticBar.description": "Ein mystischer Barren, der aus der Legende selbst geschmiedet wurde.", - "prismaticHoe": "Prismatische Hacke", - "prismaticWatercan": "Prismatische Gießkanne", - "prismaticPickaxe": "Prismatische Spitzhacke", - "prismaticAxe": "Prismatische Axt", - "prismaticSprinkler.name": "Prismatischer Sprinkler", - "prismaticSprinkler.description": "Bewässert jeden Morgen 48 Felder um sich herum.", -} \ No newline at end of file +{ + "prismatic.prefix": "Prismatische", + "prismaticBar.name": "Prismatischer Barren", + "prismaticBar.description": "Ein mystischer Barren, der aus der Legende selbst geschmiedet wurde.", + "prismaticHoe": "Prismatische Hacke", + "prismaticWatercan": "Prismatische Gießkanne", + "prismaticPickaxe": "Prismatische Spitzhacke", + "prismaticAxe": "Prismatische Axt", + "prismaticSprinkler.name": "Prismatischer Sprinkler", + "prismaticSprinkler.description": "Bewässert jeden Morgen 48 Felder um sich herum.", +} diff --git a/PrismaticTools/i18n/default.json b/PrismaticTools/i18n/default.json index 2bd55da..f17c5d2 100644 --- a/PrismaticTools/i18n/default.json +++ b/PrismaticTools/i18n/default.json @@ -1,11 +1,11 @@ -{ - "prismatic.prefix": "Prismatic", - "prismaticBar.name": "Prismatic Bar", - "prismaticBar.description": "A mystical ingot forged from legend itself.", - "prismaticHoe": "Prismatic Hoe", - "prismaticWatercan": "Prismatic Watering Can", - "prismaticPickaxe": "Prismatic Pickaxe", - "prismaticAxe": "Prismatic Axe", - "prismaticSprinkler.name": "Prismatic Sprinkler", - "prismaticSprinkler.description": "Waters the 48 adjacenet tiles every morning.", -} \ No newline at end of file +{ + "prismatic.prefix": "Prismatic", + "prismaticBar.name": "Prismatic Bar", + "prismaticBar.description": "A mystical ingot forged from legend itself.", + "prismaticHoe": "Prismatic Hoe", + "prismaticWatercan": "Prismatic Watering Can", + "prismaticPickaxe": "Prismatic Pickaxe", + "prismaticAxe": "Prismatic Axe", + "prismaticSprinkler.name": "Prismatic Sprinkler", + "prismaticSprinkler.description": "Waters the 48 adjacenet tiles every morning.", +} diff --git a/PrismaticTools/i18n/ko.json b/PrismaticTools/i18n/ko.json new file mode 100644 index 0000000..7bfe2a2 --- /dev/null +++ b/PrismaticTools/i18n/ko.json @@ -0,0 +1,11 @@ +{ + "prismatic.prefix": "무지갯빛", + "prismaticBar.name": "무지갯빛 주괴", + "prismaticBar.description": "전설 그 자체를 주조해 만들어진 신비로운 금속 주괴.", + "prismaticHoe": "무지갯빛 괭이", + "prismaticWatercan": "무지갯빛 물뿌리개", + "prismaticPickaxe": "무지갯빛 곡괭이", + "prismaticAxe": "무지갯빛 도끼", + "prismaticSprinkler.name": "무지갯빛 스프링클러", + "prismaticSprinkler.description": "매일 아침마다 인근 48개의 타일에 물을 줍니다." +} diff --git a/PrismaticTools/i18n/zh.json b/PrismaticTools/i18n/zh.json index 1d69964..02589c4 100644 --- a/PrismaticTools/i18n/zh.json +++ b/PrismaticTools/i18n/zh.json @@ -1,11 +1,11 @@ -{ - "prismatic.prefix": "五彩", - "prismaticBar.name": "五彩锭", - "prismaticBar.description": "一个神秘的铸锭,传说是由五彩碎片锻造而成的。", - "prismaticHoe": "五彩锄头", - "prismaticWatercan": "五彩水壶", - "prismaticPickaxe": "五彩镐", - "prismaticAxe": "五彩斧", - "prismaticSprinkler.name": "五彩洒水器", - "prismaticSprinkler.description": "每天早晨自动给附近的48块地浇水。", -} \ No newline at end of file +{ + "prismatic.prefix": "五彩", + "prismaticBar.name": "五彩锭", + "prismaticBar.description": "一个神秘的铸锭,传说是由五彩碎片锻造而成的。", + "prismaticHoe": "五彩锄头", + "prismaticWatercan": "五彩水壶", + "prismaticPickaxe": "五彩镐", + "prismaticAxe": "五彩斧", + "prismaticSprinkler.name": "五彩洒水器", + "prismaticSprinkler.description": "每天早晨自动给附近的48块地浇水。", +} diff --git a/PrismaticTools/manifest.json b/PrismaticTools/manifest.json index 02cbf0e..7094089 100644 --- a/PrismaticTools/manifest.json +++ b/PrismaticTools/manifest.json @@ -1,10 +1,9 @@ -{ - "Name": "PrismaticTools", - "Author": "stokastic", - "Version": "1.7.0", - "Description": "Adds prismatic tools and sprinklers to the game.", - "UniqueID": "stokastic.PrismaticTools", - "EntryDll": "PrismaticTools.dll", - "MinimumApiVersion": "2.7", - "UpdateKeys": [ "Nexus:2428" ] -} \ No newline at end of file +{ + "Name": "Prismatic Tools", + "Author": "stokastic", + "Version": "1.7.1", + "Description": "Adds prismatic tools and sprinklers to the game.", + "UniqueID": "stokastic.PrismaticTools", + "EntryDll": "PrismaticTools.dll", + "UpdateKeys": [ "Nexus:2428" ] +} diff --git a/PrismaticTools/packages.config b/PrismaticTools/packages.config deleted file mode 100644 index d798813..0000000 --- a/PrismaticTools/packages.config +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file