using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Reflection; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Input; using StardewModdingAPI.Framework; namespace StardewModdingAPI { /// Provides general utility extensions. public static class Extensions { /********* ** Properties *********/ /// The backing field for . private static readonly Random _random = new Random(); /********* ** Accessors *********/ /// A pseudo-random number generator. public static Random Random { get { Program.DeprecationManager.Warn($"{nameof(Extensions)}.{nameof(Extensions.Random)}", "1.0", DeprecationLevel.Info); return Extensions._random; } } /********* ** Public methods *********/ /// Get whether the given key is currently being pressed. /// The key to check. public static bool IsKeyDown(this Keys key) { Program.DeprecationManager.Warn($"{nameof(Extensions)}.{nameof(Extensions.IsKeyDown)}", "1.0", DeprecationLevel.Info); return Keyboard.GetState().IsKeyDown(key); } /// Get a random color. public static Color RandomColour() { Program.DeprecationManager.Warn($"{nameof(Extensions)}.{nameof(Extensions.RandomColour)}", "1.0", DeprecationLevel.Info); return new Color(Extensions.Random.Next(0, 255), Extensions.Random.Next(0, 255), Extensions.Random.Next(0, 255)); } /// Concatenate an enumeration into a delimiter-separated string. /// The values to concatenate. /// The value separator. [Obsolete("The usage of ToSingular has changed. Please update your call to use ToSingular")] public static string ToSingular(this IEnumerable ienum, string split = ", ") { Program.DeprecationManager.Warn($"{nameof(Extensions)}.{nameof(Extensions.ToSingular)}", "1.0", DeprecationLevel.PendingRemoval); return ""; } /// Concatenate an enumeration into a delimiter-separated string. /// The enumerated value type. /// The values to concatenate. /// The value separator. public static string ToSingular(this IEnumerable ienum, string split = ", ") { Program.DeprecationManager.Warn($"{nameof(Extensions)}.{nameof(Extensions.ToSingular)}", "1.0", DeprecationLevel.Info); //Apparently Keys[] won't split normally :l if (typeof(T) == typeof(Keys)) { return string.Join(split, ienum.ToArray()); } return string.Join(split, ienum); } /// Get whether the value can be parsed as a number. /// The value. public static bool IsInt32(this object o) { Program.DeprecationManager.Warn($"{nameof(Extensions)}.{nameof(Extensions.IsInt32)}", "1.0", DeprecationLevel.Info); int i; return int.TryParse(o.ToString(), out i); } /// Get the numeric representation of a value. /// The value. public static int AsInt32(this object o) { Program.DeprecationManager.Warn($"{nameof(Extensions)}.{nameof(Extensions.AsInt32)}", "1.0", DeprecationLevel.Info); return int.Parse(o.ToString()); } /// Get whether the value can be parsed as a boolean. /// The value. public static bool IsBool(this object o) { Program.DeprecationManager.Warn($"{nameof(Extensions)}.{nameof(Extensions.IsBool)}", "1.0", DeprecationLevel.Info); bool b; return bool.TryParse(o.ToString(), out b); } /// Get the boolean representation of a value. /// The value. public static bool AsBool(this object o) { Program.DeprecationManager.Warn($"{nameof(Extensions)}.{nameof(Extensions.AsBool)}", "1.0", DeprecationLevel.Info); return bool.Parse(o.ToString()); } /// Get a list hash calculated from the hashes of the values it contains. /// The values to hash. public static int GetHash(this IEnumerable enumerable) { Program.DeprecationManager.Warn($"{nameof(Extensions)}.{nameof(Extensions.GetHash)}", "1.0", DeprecationLevel.Info); var hash = 0; foreach (var v in enumerable) hash ^= v.GetHashCode(); return hash; } /// Cast a value to the given type. This returns null if the value can't be cast. /// The type to which to cast. /// The value. public static T Cast(this object o) where T : class { Program.DeprecationManager.Warn($"{nameof(Extensions)}.{nameof(Extensions.Cast)}", "1.0", DeprecationLevel.Info); return o as T; } /// Get all private types on an object. /// The object to scan. public static FieldInfo[] GetPrivateFields(this object o) { Program.DeprecationManager.Warn($"{nameof(Extensions)}.{nameof(Extensions.GetPrivateFields)}", "1.0", DeprecationLevel.Info); return o.GetType().GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Static); } /// Get metadata for a private field. /// The type to scan. /// The name of the field to find. public static FieldInfo GetBaseFieldInfo(this Type t, string name) { Program.DeprecationManager.Warn($"{nameof(Extensions)}.{nameof(Extensions.GetBaseFieldValue)}", "1.0", DeprecationLevel.Info); return t.GetField(name, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Static); } /// Get the value of a private field. /// The type to scan. /// The instance for which to get a value. /// The name of the field to find. public static T GetBaseFieldValue(this Type t, object o, string name) where T : class { Program.DeprecationManager.Warn($"{nameof(Extensions)}.{nameof(Extensions.GetBaseFieldValue)}", "1.0", DeprecationLevel.Info); return t.GetBaseFieldInfo(name).GetValue(o) as T; } /// Set the value of a private field. /// The type to scan. /// The instance for which to set a value. /// The name of the field to find. /// The value to set. public static void SetBaseFieldValue(this Type t, object o, string name, object newValue) where T : class { Program.DeprecationManager.Warn($"{nameof(Extensions)}.{nameof(Extensions.SetBaseFieldValue)}", "1.0", DeprecationLevel.Info); t.GetBaseFieldInfo(name).SetValue(o, newValue as T); } /// Get a copy of the string with only alphanumeric characters. (Numbers are not removed, despite the name.) /// The string to copy. public static string RemoveNumerics(this string st) { Program.DeprecationManager.Warn($"{nameof(Extensions)}.{nameof(Extensions.RemoveNumerics)}", "1.0", DeprecationLevel.Info); var s = st; foreach (var c in s) { if (!char.IsLetterOrDigit(c)) s = s.Replace(c.ToString(), ""); } return s; } } }