remove extensions from public interface, refactor & document
This commit is contained in:
parent
ab3fffde0a
commit
78e8a6a4a0
|
@ -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}";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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" />
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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>
|
||||
|
|
Loading…
Reference in New Issue