Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
252207c
migrate to new NuGet package reference format
Pathoschild Nov 23, 2018
e544fa0
update mod build config package
Pathoschild Nov 23, 2018
66dce3f
simplify project file using the new mod build config package features
Pathoschild Nov 23, 2018
a338e67
migrate to Harmony NuGet package
Pathoschild Nov 23, 2018
fa4b47e
bump versions for release, tweak manifest name
Pathoschild Nov 23, 2018
b46d9ed
rework Harmony patching for crossplatform compatibility
Pathoschild Nov 27, 2018
5abe726
update for SMAPI 3.0
Pathoschild Jan 9, 2019
3ece888
update for Stardew Valley 1.3.33
Pathoschild Jan 9, 2019
89194ba
fix sprinkler light feature
Pathoschild Jan 10, 2019
47d15a3
fix null reference exceptions in some cases
Pathoschild Jan 19, 2019
9ed0fe6
fix 'key has already been added' error in some cases
Pathoschild Jan 19, 2019
5fb070a
remove old migration
Pathoschild May 25, 2019
001a739
add editorconfig to keep formatting consistent, minor code formatting
Pathoschild May 25, 2019
cd88183
add Korean translations
Pathoschild May 25, 2019
e8fa0f6
remove unused fields
Pathoschild May 25, 2019
9ea2133
minor cleanup
Pathoschild May 25, 2019
62f43f7
replace location scanning with object patches for compatibility with …
Pathoschild May 25, 2019
e30943b
fix sprinklers not un-scarecrowed when option is disabled
Pathoschild May 25, 2019
5c0d1dc
update mod build package & migrate to new .csproj format
Pathoschild Jul 1, 2019
d22e5fa
remove unused assets/old files
Pathoschild Jul 4, 2019
0e1baf5
Update for SMAPI 3.0
Seawolf87 Nov 28, 2019
89b9988
fix platform targets
Pathoschild Dec 31, 2020
faaae56
restore original code style for consistency
Pathoschild Dec 31, 2020
29f2bab
Merge pull request #3 from Seawolf87/develop
Pathoschild Dec 31, 2020
21e6f77
update sprinkler patches for Stardew Valley 1.5
Pathoschild Dec 31, 2020
76ad8b5
bump API version for Stardew Valley 1.5
Pathoschild Dec 31, 2020
59dfde9
update for Stardew Valley 1.5.5
Pathoschild May 7, 2022
31c3e95
update for recent SMAPI releases
Pathoschild May 7, 2022
f22660e
fix non-prismatic sprites overwritten by edits
Pathoschild May 7, 2022
040a476
fix Prismatic Tools translations not updated when player switches lan…
Pathoschild May 7, 2022
6c408d7
reduce repetition in asset editor
Pathoschild May 7, 2022
08d397f
use SMAPI's ExtendImage instead of manually replacing it
Pathoschild May 7, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 72 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -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
28 changes: 15 additions & 13 deletions PrismaticTools.sln
Original file line number Diff line number Diff line change
@@ -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
Expand Down
3 changes: 3 additions & 0 deletions PrismaticTools.sln.DotSettings
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ArrangeThisQualifier/@EntryIndexedValue">DO_NOT_SHOW</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateInstanceFields/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String></wpf:ResourceDictionary>
Binary file removed PrismaticTools/0Harmony.dll
Binary file not shown.
Binary file removed PrismaticTools/Assets/old/prismaticBar.png
Binary file not shown.
Binary file removed PrismaticTools/Assets/old/prismaticSprinkler.png
Binary file not shown.
Binary file removed PrismaticTools/Assets/old/prismaticTools.png
Binary file not shown.
Binary file removed PrismaticTools/Assets/old/tools.png
Binary file not shown.
Binary file removed PrismaticTools/Assets/tools.png
Binary file not shown.
107 changes: 60 additions & 47 deletions PrismaticTools/Framework/AssetEditor.cs
Original file line number Diff line number Diff line change
@@ -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<T>(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<Texture2D>("assets/prismaticBar.png");
Texture2D sprinkler = ModEntry.ModHelper.ModContent.Load<Texture2D>("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<int, string>().Data;

public void Edit<T>(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<string, string>().Data;

// somehow the Dictionary maintains ordering, so reconstruct it with new sprinkler recipe immediately after prismatic
Dictionary<string, string> 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<Texture2D>("Assets/prismaticBar.png", ContentSource.ModFolder);
Texture2D sprinkler = ModEntry.ModHelper.Content.Load<Texture2D>("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<int, string>().Data.Add(PrismaticBarItem.INDEX, $"{barName}/{PrismaticBarItem.PRICE}/{PrismaticBarItem.EDIBILITY}/{PrismaticBarItem.TYPE} {PrismaticBarItem.CATEGORY}/{barName}/{barDesc}");
asset.AsDictionary<int, string>().Data.Add(PrismaticSprinklerItem.INDEX, $"{sprinklerName}/{PrismaticSprinklerItem.PRICE}/{PrismaticSprinklerItem.EDIBILITY}/{PrismaticSprinklerItem.TYPE} {PrismaticSprinklerItem.CATEGORY}/{sprinklerName}/{sprinklerDesc}");
} else if (asset.AssetNameEquals("Data/CraftingRecipes")) {
IAssetDataForDictionary<string, string> oldDict = asset.AsDictionary<string, string>();
Dictionary<string, string> newDict = new Dictionary<string, string>();
// 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<string, string>().Data.Clear();
foreach (string key in newDict.Keys) {
asset.AsDictionary<string, string>().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);
Expand Down
33 changes: 16 additions & 17 deletions PrismaticTools/Framework/Blacksmith.cs
Original file line number Diff line number Diff line change
@@ -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)) {
/// <summary>Raised after a game menu is opened, closed, or replaced.</summary>
/// <param name="sender">The event sender.</param>
/// <param name="e">The event arguments.</param>
private static void OnMenuChanged(object sender, MenuChangedEventArgs e) {
if (!(e.NewMenu is ShopMenu menu)) {
return;
}
ShopMenu menu = e.NewMenu as ShopMenu;
List<int> categories = ModEntry.ModHelper.Reflection.GetField<List<int>>(menu, "categoriesToSellHere").GetValue();
if (!categories.Contains(Object.GemCategory) || !categories.Contains(Object.mineralsCategory) || !categories.Contains(Object.metalResources)) {
return;
Expand All @@ -32,28 +31,28 @@ private static void MenuEvents_MenuChanged1(object sender, EventArgsClickableMen
Tool toolFromName4 = who.getToolFromName("Hoe");
Tool tool;

List<Item> forSale = ModEntry.ModHelper.Reflection.GetField<List<Item>>(menu, "forSale").GetValue();
Dictionary<Item, int[]> stock = ModEntry.ModHelper.Reflection.GetField<Dictionary<Item, int[]>>(menu, "itemPriceAndStock").GetValue();
List<ISalable> forSale = menu.forSale;
Dictionary<ISalable, int[]> 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 });
}
}
}
Expand Down
Loading