diff options
-rw-r--r-- | src/StardewModdingAPI/Constants.cs | 14 | ||||
-rw-r--r-- | src/StardewModdingAPI/Extensions.cs | 78 | ||||
-rw-r--r-- | src/StardewModdingAPI/Inheritance/SGame.cs | 51 | ||||
-rw-r--r-- | src/StardewModdingAPI/Log.cs | 6 | ||||
-rw-r--r-- | src/StardewModdingAPI/Program.cs | 4 | ||||
-rw-r--r-- | src/StardewModdingAPI/StardewModdingAPI.csproj | 1 | ||||
-rw-r--r-- | src/TrainerMod/Framework/Extensions.cs | 22 | ||||
-rw-r--r-- | src/TrainerMod/TrainerMod.cs | 67 | ||||
-rw-r--r-- | src/TrainerMod/TrainerMod.csproj | 3 |
9 files changed, 120 insertions, 126 deletions
diff --git a/src/StardewModdingAPI/Constants.cs b/src/StardewModdingAPI/Constants.cs index d023be3c..e5752dfd 100644 --- a/src/StardewModdingAPI/Constants.cs +++ b/src/StardewModdingAPI/Constants.cs @@ -1,5 +1,6 @@ using System; using System.IO; +using System.Linq; using System.Reflection; using StardewValley; @@ -12,7 +13,7 @@ namespace StardewModdingAPI ** Properties *********/ /// <summary>The directory name containing the current save's data (if a save is loaded).</summary> - private static string RawSaveFolderName => Constants.PlayerNull ? string.Empty : $"{Game1.player.name.RemoveNumerics()}_{Game1.uniqueIDForThisGame}"; + private static string RawSaveFolderName => Constants.PlayerNull ? string.Empty : Constants.GetSaveFolderName(); /// <summary>The directory path containing the current save's data (if a save is loaded).</summary> private static string RawSavePath => Constants.PlayerNull ? string.Empty : Path.Combine(Constants.SavesPath, Constants.RawSaveFolderName); @@ -56,5 +57,16 @@ namespace StardewModdingAPI /// <summary>The file path to the error log where the latest output should be saved.</summary> public static string LogPath => Path.Combine(Constants.LogDir, "MODDED_ProgramLog.Log_LATEST.txt"); + + + /********* + ** Private field + *********/ + /// <summary>Get the name of a save directory for the current player.</summary> + private static string GetSaveFolderName() + { + string prefix = new string(Game1.player.name.Where(char.IsLetterOrDigit).ToArray()); + return $"{prefix}_{Game1.uniqueIDForThisGame}"; + } } }
\ No newline at end of file diff --git a/src/StardewModdingAPI/Extensions.cs b/src/StardewModdingAPI/Extensions.cs deleted file mode 100644 index 9a8c55f4..00000000 --- a/src/StardewModdingAPI/Extensions.cs +++ /dev/null @@ -1,78 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; -using Microsoft.Xna.Framework.Input; - -namespace StardewModdingAPI -{ - public static class Extensions - { - public static Random Random = new Random(); - - public static bool IsKeyDown(this Keys key) - { - return Keyboard.GetState().IsKeyDown(key); - } - - public static string ToSingular<T>(this IEnumerable<T> ienum, string split = ", ") // where T : class - { - //Apparently Keys[] won't split normally :l - if (typeof(T) == typeof(Keys)) - { - return string.Join(split, ienum.ToArray()); - } - return string.Join(split, ienum); - } - - public static bool IsInt32(this object o) - { - int i; - return int.TryParse(o.ToString(), out i); - } - - public static int AsInt32(this object o) - { - return int.Parse(o.ToString()); - } - - public static int GetHash(this IEnumerable enumerable) - { - var hash = 0; - foreach (var v in enumerable) - { - hash ^= v.GetHashCode(); - } - return hash; - } - - public static FieldInfo GetBaseFieldInfo(this Type t, string name) - { - return t.GetField(name, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Static); - } - - public static T GetBaseFieldValue<T>(this Type t, object o, string name) where T : class - { - return t.GetBaseFieldInfo(name).GetValue(o) as T; - } - - public static void SetBaseFieldValue<T>(this Type t, object o, string name, object newValue) where T : class - { - t.GetBaseFieldInfo(name).SetValue(o, newValue as T); - } - - public static string RemoveNumerics(this string st) - { - var s = st; - foreach (var c in s) - { - if (!char.IsLetterOrDigit(c)) - { - s = s.Replace(c.ToString(), ""); - } - } - return s; - } - } -}
\ No newline at end of file diff --git a/src/StardewModdingAPI/Inheritance/SGame.cs b/src/StardewModdingAPI/Inheritance/SGame.cs index 74a3d5d5..bd6a3491 100644 --- a/src/StardewModdingAPI/Inheritance/SGame.cs +++ b/src/StardewModdingAPI/Inheritance/SGame.cs @@ -1,4 +1,5 @@ using System; +using System.Collections; using System.Collections.Generic; using System.Linq; using System.Reflection; @@ -134,15 +135,15 @@ namespace StardewModdingAPI.Inheritance /// <summary>The game's current render target.</summary> public RenderTarget2D Screen { - get { return typeof(Game1).GetBaseFieldValue<RenderTarget2D>(Program.gamePtr, "screen"); } - set { typeof(Game1).SetBaseFieldValue<RenderTarget2D>(this, "screen", value); } + get { return this.GetBaseFieldValue<RenderTarget2D>("screen"); } + set { this.SetBaseFieldValue<RenderTarget2D>("screen", value); } } /// <summary>The game's current background color.</summary> public Color BgColour { - get { return (Color)typeof(Game1).GetBaseFieldValue<object>(Program.gamePtr, "bgColor"); } - set { typeof(Game1).SetBaseFieldValue<object>(this, "bgColor", value); } + get { return (Color)this.GetBaseFieldValue<object>("bgColor"); } + set { this.SetBaseFieldValue<object>("bgColor", value); } } /// <summary>The current game instance.</summary> @@ -879,10 +880,10 @@ namespace StardewModdingAPI.Inheritance } // raise location list changed - if (Game1.locations.GetHash() != this.PreviousGameLocations) + if (this.GetHash(Game1.locations) != this.PreviousGameLocations) { LocationEvents.InvokeLocationsChanged(Game1.locations); - this.PreviousGameLocations = Game1.locations.GetHash(); + this.PreviousGameLocations = this.GetHash(Game1.locations); } // raise current location changed @@ -944,7 +945,7 @@ namespace StardewModdingAPI.Inheritance } // raise current location's object list changed - int? objectHash = Game1.currentLocation?.objects?.GetHash(); + int? objectHash = Game1.currentLocation?.objects != null ? this.GetHash(Game1.currentLocation.objects) : (int?)null; if (objectHash != null && this.PreviousLocationObjects != objectHash) { LocationEvents.InvokeOnNewLocationObject(Game1.currentLocation.objects); @@ -1032,5 +1033,39 @@ namespace StardewModdingAPI.Inheritance } } } + + /// <summary>Get a hash value for an enumeration.</summary> + /// <param name="enumerable">The enumeration of items to hash.</param> + private int GetHash(IEnumerable enumerable) + { + var hash = 0; + foreach (var v in enumerable) + hash ^= v.GetHashCode(); + return hash; + } + + /// <summary>Get reflection metadata for a private <see cref="Game1"/> field.</summary> + /// <param name="name">The field name.</param> + private FieldInfo GetBaseFieldInfo(string name) + { + return typeof(Game1).GetField(name, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Static); + } + + /// <summary>Get the value of a private <see cref="Game1"/> field.</summary> + /// <typeparam name="TValue">The expected value type.</typeparam> + /// <param name="name">The field name.</param> + private TValue GetBaseFieldValue<TValue>(string name) where TValue : class + { + return this.GetBaseFieldInfo(name).GetValue(Program.gamePtr) as TValue; + } + + /// <summary>Set the value of a private <see cref="Game1"/> field.</summary> + /// <typeparam name="TValue">The expected value type.</typeparam> + /// <param name="name">The field name.</param> + /// <param name="value">The value to set.</param> + public void SetBaseFieldValue<TValue>(string name, object value) where TValue : class + { + this.GetBaseFieldInfo(name).SetValue(Program.gamePtr, value as TValue); + } } -}
\ No newline at end of file +} diff --git a/src/StardewModdingAPI/Log.cs b/src/StardewModdingAPI/Log.cs index 15c4ce55..abf6e36a 100644 --- a/src/StardewModdingAPI/Log.cs +++ b/src/StardewModdingAPI/Log.cs @@ -7,6 +7,9 @@ namespace StardewModdingAPI { public static class Log { + /// <summary>A pseudorandom number generator used to generate log files.</summary> + private static readonly Random Random = new Random(); + private static readonly LogWriter _writer; static Log() @@ -38,9 +41,8 @@ namespace StardewModdingAPI public static void Application_ThreadException(object sender, ThreadExceptionEventArgs e) { Console.WriteLine("A thread exception has been caught"); - File.WriteAllText(Path.Combine(Constants.LogDir, $"MODDED_ErrorLog.Log_{Extensions.Random.Next(100000000, 999999999)}.txt"), e.Exception.ToString()); + File.WriteAllText(Path.Combine(Constants.LogDir, $"MODDED_ErrorLog.Log_{Log.Random.Next(100000000, 999999999)}.txt"), e.Exception.ToString()); } - #endregion #region Sync Logging diff --git a/src/StardewModdingAPI/Program.cs b/src/StardewModdingAPI/Program.cs index 3bfaee0d..1d4c6dcc 100644 --- a/src/StardewModdingAPI/Program.cs +++ b/src/StardewModdingAPI/Program.cs @@ -363,11 +363,11 @@ namespace StardewModdingAPI Log.AsyncR("The command specified could not be found"); else { - Log.AsyncY(fnd.CommandArgs.Length > 0 ? $"{fnd.CommandName}: {fnd.CommandDesc} - {fnd.CommandArgs.ToSingular()}" : $"{fnd.CommandName}: {fnd.CommandDesc}"); + Log.AsyncY(fnd.CommandArgs.Length > 0 ? $"{fnd.CommandName}: {fnd.CommandDesc} - {string.Join(", ", fnd.CommandArgs)}" : $"{fnd.CommandName}: {fnd.CommandDesc}"); } } else - Log.AsyncY("Commands: " + Command.RegisteredCommands.Select(x => x.CommandName).ToSingular()); + Log.AsyncY("Commands: " + string.Join(", ", Command.RegisteredCommands.Select(x => x.CommandName))); } } } diff --git a/src/StardewModdingAPI/StardewModdingAPI.csproj b/src/StardewModdingAPI/StardewModdingAPI.csproj index cf8c58cb..ddab8734 100644 --- a/src/StardewModdingAPI/StardewModdingAPI.csproj +++ b/src/StardewModdingAPI/StardewModdingAPI.csproj @@ -193,7 +193,6 @@ <Compile Include="Events\MineEvents.cs" /> <Compile Include="Events\PlayerEvents.cs" /> <Compile Include="Events\TimeEvents.cs" /> - <Compile Include="Extensions.cs" /> <Compile Include="Framework\UpdateHelper.cs" /> <Compile Include="Framework\GitRelease.cs" /> <Compile Include="Inheritance\ChangeType.cs" /> diff --git a/src/TrainerMod/Framework/Extensions.cs b/src/TrainerMod/Framework/Extensions.cs new file mode 100644 index 00000000..30019748 --- /dev/null +++ b/src/TrainerMod/Framework/Extensions.cs @@ -0,0 +1,22 @@ +namespace TrainerMod.Framework +{ + /// <summary>Provides extension methods on primitive types.</summary> + public static class Extensions + { + /// <summary>Get whether an object is a number.</summary> + /// <param name="value">The object value.</param> + public static bool IsInt(this object value) + { + int i; + return int.TryParse(value.ToString(), out i); + } + + /// <summary>Parse an object into a number.</summary> + /// <param name="value">The object value.</param> + /// <exception cref="System.FormatException">The value is not a valid number.</exception> + public static int ToInt(this object value) + { + return int.Parse(value.ToString()); + } + } +} diff --git a/src/TrainerMod/TrainerMod.cs b/src/TrainerMod/TrainerMod.cs index 224e70ad..8c521d95 100644 --- a/src/TrainerMod/TrainerMod.cs +++ b/src/TrainerMod/TrainerMod.cs @@ -8,6 +8,7 @@ using StardewValley; using StardewValley.Menus; using StardewValley.Objects; using StardewValley.Tools; +using TrainerMod.Framework; using Object = StardewValley.Object; namespace TrainerMod @@ -272,9 +273,9 @@ namespace TrainerMod { if (e.Command.CalledArgs.Length > 0) { - if (e.Command.CalledArgs[0].IsInt32()) + if (e.Command.CalledArgs[0].IsInt()) { - Game1.player.addedSpeed = e.Command.CalledArgs[0].AsInt32(); + Game1.player.addedSpeed = e.Command.CalledArgs[0].ToInt(); Log.Async($"Set {Game1.player.Name}'s added speed to {Game1.player.addedSpeed}"); } else @@ -297,9 +298,9 @@ namespace TrainerMod if (objs.Contains(obj)) { var cs = e.Command.CalledArgs[1].Split(new[] {','}, 3); - if (cs[0].IsInt32() && cs[1].IsInt32() && cs[2].IsInt32()) + if (cs[0].IsInt() && cs[1].IsInt() && cs[2].IsInt()) { - var c = new Color(cs[0].AsInt32(), cs[1].AsInt32(), cs[2].AsInt32()); + var c = new Color(cs[0].ToInt(), cs[1].ToInt(), cs[2].ToInt()); switch (obj) { case "hair": @@ -337,9 +338,9 @@ namespace TrainerMod var objs = "hair,shirt,skin,acc,shoe,swim,gender".Split(','); if (objs.Contains(obj)) { - if (e.Command.CalledArgs[1].IsInt32()) + if (e.Command.CalledArgs[1].IsInt()) { - var i = e.Command.CalledArgs[1].AsInt32(); + var i = e.Command.CalledArgs[1].ToInt(); switch (obj) { case "hair": @@ -395,11 +396,11 @@ namespace TrainerMod { if (e.Command.CalledArgs.Length > 0) { - if (e.Command.CalledArgs[0].IsInt32()) + if (e.Command.CalledArgs[0].IsInt()) { - if (e.Command.CalledArgs[0].AsInt32() == 0 || e.Command.CalledArgs[0].AsInt32() == 1) + if (e.Command.CalledArgs[0].ToInt() == 0 || e.Command.CalledArgs[0].ToInt() == 1) { - freezeTime = e.Command.CalledArgs[0].AsInt32() == 1; + freezeTime = e.Command.CalledArgs[0].ToInt() == 1; frozenTime = freezeTime ? Game1.timeOfDay : 0; Log.AsyncY("Time is now " + (freezeTime ? "frozen" : "thawed")); } @@ -423,11 +424,11 @@ namespace TrainerMod { if (e.Command.CalledArgs.Length > 0) { - if (e.Command.CalledArgs[0].IsInt32()) + if (e.Command.CalledArgs[0].IsInt()) { - if (e.Command.CalledArgs[0].AsInt32() <= 2600 && e.Command.CalledArgs[0].AsInt32() >= 600) + if (e.Command.CalledArgs[0].ToInt() <= 2600 && e.Command.CalledArgs[0].ToInt() >= 600) { - Game1.timeOfDay = e.Command.CalledArgs[0].AsInt32(); + Game1.timeOfDay = e.Command.CalledArgs[0].ToInt(); frozenTime = freezeTime ? Game1.timeOfDay : 0; Log.AsyncY("Time set to: " + Game1.timeOfDay); } @@ -451,11 +452,11 @@ namespace TrainerMod { if (e.Command.CalledArgs.Length > 0) { - if (e.Command.CalledArgs[0].IsInt32()) + if (e.Command.CalledArgs[0].IsInt()) { - if (e.Command.CalledArgs[0].AsInt32() <= 28 && e.Command.CalledArgs[0].AsInt32() > 0) + if (e.Command.CalledArgs[0].ToInt() <= 28 && e.Command.CalledArgs[0].ToInt() > 0) { - Game1.dayOfMonth = e.Command.CalledArgs[0].AsInt32(); + Game1.dayOfMonth = e.Command.CalledArgs[0].ToInt(); } else { @@ -505,9 +506,9 @@ namespace TrainerMod else { infHealth = false; - if (e.Command.CalledArgs[0].IsInt32()) + if (e.Command.CalledArgs[0].IsInt()) { - Game1.player.health = e.Command.CalledArgs[0].AsInt32(); + Game1.player.health = e.Command.CalledArgs[0].ToInt(); } else { @@ -525,9 +526,9 @@ namespace TrainerMod { if (e.Command.CalledArgs.Length > 0) { - if (e.Command.CalledArgs[0].IsInt32()) + if (e.Command.CalledArgs[0].IsInt()) { - Game1.player.maxHealth = e.Command.CalledArgs[0].AsInt32(); + Game1.player.maxHealth = e.Command.CalledArgs[0].ToInt(); } else { @@ -544,9 +545,9 @@ namespace TrainerMod { if (e.Command.CalledArgs.Length > 0) { - if (e.Command.CalledArgs[0].IsInt32()) + if (e.Command.CalledArgs[0].IsInt()) { - Game1.player.immunity = e.Command.CalledArgs[0].AsInt32(); + Game1.player.immunity = e.Command.CalledArgs[0].ToInt(); } else { @@ -563,16 +564,16 @@ namespace TrainerMod { if (e.Command.CalledArgs.Length > 0) { - if (e.Command.CalledArgs[0].IsInt32()) + if (e.Command.CalledArgs[0].IsInt()) { var count = 1; var quality = 0; if (e.Command.CalledArgs.Length > 1) { Console.WriteLine(e.Command.CalledArgs[1]); - if (e.Command.CalledArgs[1].IsInt32()) + if (e.Command.CalledArgs[1].IsInt()) { - count = e.Command.CalledArgs[1].AsInt32(); + count = e.Command.CalledArgs[1].ToInt(); } else { @@ -582,9 +583,9 @@ namespace TrainerMod if (e.Command.CalledArgs.Length > 2) { - if (e.Command.CalledArgs[2].IsInt32()) + if (e.Command.CalledArgs[2].IsInt()) { - quality = e.Command.CalledArgs[2].AsInt32(); + quality = e.Command.CalledArgs[2].ToInt(); } else { @@ -594,7 +595,7 @@ namespace TrainerMod } } - var o = new Object(e.Command.CalledArgs[0].AsInt32(), count) {quality = quality}; + var o = new Object(e.Command.CalledArgs[0].ToInt(), count) {quality = quality}; Game1.player.addItemByMenuIfNecessary(o); } @@ -613,9 +614,9 @@ namespace TrainerMod { if (e.Command.CalledArgs.Length > 0) { - if (e.Command.CalledArgs[0].IsInt32()) + if (e.Command.CalledArgs[0].IsInt()) { - var toAdd = new MeleeWeapon(e.Command.CalledArgs[0].AsInt32()); + var toAdd = new MeleeWeapon(e.Command.CalledArgs[0].ToInt()); Game1.player.addItemByMenuIfNecessary(toAdd); Log.Async($"Given {toAdd.Name} to {Game1.player.Name}"); } @@ -634,9 +635,9 @@ namespace TrainerMod { if (e.Command.CalledArgs.Length > 0) { - if (e.Command.CalledArgs[0].IsInt32()) + if (e.Command.CalledArgs[0].IsInt()) { - var toAdd = new Ring(e.Command.CalledArgs[0].AsInt32()); + var toAdd = new Ring(e.Command.CalledArgs[0].ToInt()); Game1.player.addItemByMenuIfNecessary(toAdd); Log.Async($"Given {toAdd.Name} to {Game1.player.Name}"); } @@ -702,9 +703,9 @@ namespace TrainerMod { if (e.Command.CalledArgs.Length > 0) { - if (e.Command.CalledArgs[0].IsInt32()) + if (e.Command.CalledArgs[0].IsInt()) { - Game1.enterMine(true, e.Command.CalledArgs[0].AsInt32(), ""); + Game1.enterMine(true, e.Command.CalledArgs[0].ToInt(), ""); } else { diff --git a/src/TrainerMod/TrainerMod.csproj b/src/TrainerMod/TrainerMod.csproj index 9bc2c5ab..4b940780 100644 --- a/src/TrainerMod/TrainerMod.csproj +++ b/src/TrainerMod/TrainerMod.csproj @@ -1,4 +1,4 @@ -<?xml version="1.0" encoding="utf-8"?> +<?xml version="1.0" encoding="utf-8"?> <Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> <PropertyGroup> @@ -98,6 +98,7 @@ <Reference Include="System.Xml" /> </ItemGroup> <ItemGroup> + <Compile Include="Framework\Extensions.cs" /> <Compile Include="TrainerMod.cs" /> <Compile Include="Properties\AssemblyInfo.cs" /> </ItemGroup> |