remove oldest deprecated code (#231)

Since Stardew Valley 1.2 breaks most mods anyway, this commits removes the oldest deprecations and fixes the issues that are easiest for mods to update. See documentation for details.
This commit is contained in:
Jesse Plamondon-Willard 2017-02-07 20:50:41 -05:00
parent 99d0450b2c
commit 95a93a05b3
21 changed files with 102 additions and 828 deletions

View File

@ -1,5 +1,15 @@
# Release notes
## 1.9
See [log](https://github.com/Pathoschild/SMAPI/compare/1.8...1.9).
For players:
* Updated for Stardew Valley 1.2.
For mod developers:
* Many deprecated APIs have been removed; see [deprecation guide](http://canimod.com/guides/updating-a-smapi-mod)
for more information.
## 1.8
See [log](https://github.com/Pathoschild/SMAPI/compare/1.7...1.8).

View File

@ -67,15 +67,6 @@ namespace StardewModdingAPI
/****
** SMAPI
****/
/// <summary>Parse a command string and invoke it if valid.</summary>
/// <param name="input">The command to run, including the command name and any arguments.</param>
[Obsolete("Use the overload which passes in your mod's monitor")]
public static void CallCommand(string input)
{
Program.DeprecationManager.Warn($"an old version of {nameof(Command)}.{nameof(Command.CallCommand)}", "1.1", DeprecationLevel.Notice);
Command.CallCommand(input, Program.GetLegacyMonitorForMod());
}
/// <summary>Parse a command string and invoke it if valid.</summary>
/// <param name="input">The command to run, including the command name and any arguments.</param>
/// <param name="monitor">Encapsulates monitoring and logging.</param>

View File

@ -26,11 +26,7 @@ namespace StardewModdingAPI
** Accessors
*********/
/// <summary>SMAPI's current semantic version.</summary>
[Obsolete("Use " + nameof(Constants) + "." + nameof(ApiVersion))]
public static readonly Version Version = (Version)Constants.ApiVersion;
/// <summary>SMAPI's current semantic version.</summary>
public static ISemanticVersion ApiVersion => new Version(1, 8, 0, null, suppressDeprecationWarning: true);
public static ISemanticVersion ApiVersion => new SemanticVersion(1, 8, 0, null);
/// <summary>The minimum supported version of Stardew Valley.</summary>
public const string MinimumGameVersion = "1.1";

View File

@ -1,59 +0,0 @@
using System;
using System.Collections.Generic;
using StardewModdingAPI.Framework;
using StardewValley;
namespace StardewModdingAPI.Entities
{
/// <summary>Static class for integrating with the player.</summary>
[Obsolete("This API was never officially documented and will be removed soon.")]
public class SPlayer
{
/*********
** Accessors
*********/
/// <summary>Obsolete.</summary>
[Obsolete("Use " + nameof(Game1) + "." + nameof(Game1.getAllFarmers) + " instead")]
public static List<Farmer> AllFarmers
{
get
{
Program.DeprecationManager.Warn(nameof(SPlayer), "1.0", DeprecationLevel.Info);
return Game1.getAllFarmers();
}
}
/// <summary>Obsolete.</summary>
[Obsolete("Use " + nameof(Game1) + "." + nameof(Game1.player) + " instead")]
public static Farmer CurrentFarmer
{
get
{
Program.DeprecationManager.Warn(nameof(SPlayer), "1.0", DeprecationLevel.Info);
return Game1.player;
}
}
/// <summary>Obsolete.</summary>
[Obsolete("Use " + nameof(Game1) + "." + nameof(Game1.player) + " instead")]
public static Farmer Player
{
get
{
Program.DeprecationManager.Warn(nameof(SPlayer), "1.0", DeprecationLevel.Info);
return Game1.player;
}
}
/// <summary>Obsolete.</summary>
[Obsolete("Use " + nameof(Game1) + "." + nameof(Game1.player) + "." + nameof(Farmer.currentLocation) + " instead")]
public static GameLocation CurrentFarmerLocation
{
get
{
Program.DeprecationManager.Warn(nameof(SPlayer), "1.0", DeprecationLevel.Info);
return Game1.player.currentLocation;
}
}
}
}

View File

@ -1,4 +1,4 @@
namespace StardewModdingAPI.Inheritance
namespace StardewModdingAPI.Events
{
/// <summary>Indicates how an inventory item changed.</summary>
public enum ChangeType

View File

@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using StardewModdingAPI.Inheritance;
using StardewValley;
namespace StardewModdingAPI.Events

View File

@ -15,7 +15,7 @@ namespace StardewModdingAPI.Events
/// <summary>Raised after the game window is resized.</summary>
public static event EventHandler Resize;
/// <summary>Raised when drawing debug information to the screen (when <see cref="StardewModdingAPI.Inheritance.SGame.Debug"/> is true). This is called after the sprite batch is begun. If you just want to add debug info, use <see cref="StardewModdingAPI.Inheritance.SGame.DebugMessageQueue" /> in your update loop.</summary>
/// <summary>Raised when drawing debug information to the screen (when <see cref="SGame.Debug"/> is true). This is called after the sprite batch is begun. If you just want to add debug info, use <see cref="SGame.DebugMessageQueue" /> in your update loop.</summary>
public static event EventHandler DrawDebug;
/// <summary>Obsolete.</summary>

View File

@ -1,6 +1,6 @@
using StardewValley;
using StardewValley;
namespace StardewModdingAPI.Inheritance
namespace StardewModdingAPI.Events
{
/// <summary>Represents an inventory slot that changed.</summary>
public class ItemStackChange

View File

@ -2,7 +2,6 @@
using System.Collections.Generic;
using System.Linq;
using StardewModdingAPI.Framework;
using StardewModdingAPI.Inheritance;
using StardewValley;
namespace StardewModdingAPI.Events

View File

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

View File

@ -7,7 +7,6 @@ using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using StardewModdingAPI.Events;
using StardewModdingAPI.Framework;
using StardewValley;
using StardewValley.BellsAndWhistles;
using StardewValley.Locations;
@ -16,10 +15,10 @@ using StardewValley.Tools;
using xTile.Dimensions;
using Rectangle = Microsoft.Xna.Framework.Rectangle;
namespace StardewModdingAPI.Inheritance
namespace StardewModdingAPI.Framework
{
/// <summary>SMAPI's extension of the game's core <see cref="Game1"/>, used to inject events.</summary>
public class SGame : Game1
internal class SGame : Game1
{
/*********
** Properties

View File

@ -0,0 +1,51 @@
using System;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace StardewModdingAPI.Framework.Serialisation
{
/// <summary>Overrides how SMAPI reads and writes <see cref="ISemanticVersion"/>.</summary>
internal class SemanticVersionConverter : JsonConverter
{
/*********
** Accessors
*********/
/// <summary>Whether this converter can write JSON.</summary>
public override bool CanWrite => false;
/*********
** Public methods
*********/
/// <summary>Get whether this instance can convert the specified object type.</summary>
/// <param name="objectType">The object type.</param>
public override bool CanConvert(Type objectType)
{
return objectType == typeof(ISemanticVersion);
}
/// <summary>Reads the JSON representation of the object.</summary>
/// <param name="reader">The JSON reader.</param>
/// <param name="objectType">The object type.</param>
/// <param name="existingValue">The object being read.</param>
/// <param name="serializer">The calling serializer.</param>
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
JObject obj = JObject.Load(reader);
int major = obj.Value<int>("MajorVersion");
int minor = obj.Value<int>("MinorVersion");
int patch = obj.Value<int>("PatchVersion");
string build = obj.Value<string>("Build");
return new SemanticVersion(major, minor, patch, build);
}
/// <summary>Writes the JSON representation of the object.</summary>
/// <param name="writer">The JSON writer.</param>
/// <param name="value">The value.</param>
/// <param name="serializer">The calling serializer.</param>
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new InvalidOperationException("This converter does not write JSON.");
}
}
}

View File

@ -1,249 +0,0 @@
using System;
using System.Xml.Serialization;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using StardewModdingAPI.Framework;
using StardewValley;
using Object = StardewValley.Object;
#pragma warning disable 1591
namespace StardewModdingAPI.Inheritance
{
/// <summary>Provides access to the game's <see cref="Object"/> internals.</summary>
[Obsolete("This class is deprecated and will be removed in a future version.")]
public class SObject : Object
{
/*********
** Accessors
*********/
public string Description { get; set; }
public Texture2D Texture { get; set; }
public string CategoryName { get; set; }
public Color CategoryColour { get; set; }
public bool IsPassable { get; set; }
public bool IsPlaceable { get; set; }
public bool HasBeenRegistered { get; set; }
public int RegisteredId { get; set; }
public int MaxStackSize { get; set; }
public bool WallMounted { get; set; }
public Vector2 DrawPosition { get; set; }
public bool FlaggedForPickup { get; set; }
[XmlIgnore]
public Vector2 CurrentMouse { get; protected set; }
[XmlIgnore]
public Vector2 PlacedAt { get; protected set; }
public override int Stack
{
get { return this.stack; }
set { this.stack = value; }
}
/*********
** Public methods
*********/
public SObject()
{
Program.DeprecationManager.Warn(nameof(SObject), "0.39.3", DeprecationLevel.PendingRemoval);
this.name = "Modded Item Name";
this.Description = "Modded Item Description";
this.CategoryName = "Modded Item Category";
this.Category = 4163;
this.CategoryColour = Color.White;
this.IsPassable = false;
this.IsPlaceable = false;
this.boundingBox = new Rectangle(0, 0, 64, 64);
this.MaxStackSize = 999;
this.type = "interactive";
}
public override string Name
{
get { return this.name; }
set { this.name = value; }
}
public override string getDescription()
{
return this.Description;
}
public override void draw(SpriteBatch spriteBatch, int x, int y, float alpha = 1)
{
if (this.Texture != null)
{
spriteBatch.Draw(this.Texture, Game1.GlobalToLocal(Game1.viewport, new Vector2(x * Game1.tileSize + Game1.tileSize / 2 + (this.shakeTimer > 0 ? Game1.random.Next(-1, 2) : 0), y * Game1.tileSize + Game1.tileSize / 2 + (this.shakeTimer > 0 ? Game1.random.Next(-1, 2) : 0))), Game1.currentLocation.getSourceRectForObject(this.ParentSheetIndex), Color.White * alpha, 0f, new Vector2(8f, 8f), this.scale.Y > 1f ? this.getScale().Y : Game1.pixelZoom, this.flipped ? SpriteEffects.FlipHorizontally : SpriteEffects.None, (this.isPassable() ? this.getBoundingBox(new Vector2(x, y)).Top : this.getBoundingBox(new Vector2(x, y)).Bottom) / 10000f);
}
}
public new void drawAsProp(SpriteBatch b)
{
}
public override void drawInMenu(SpriteBatch spriteBatch, Vector2 location, float scaleSize, float transparency, float layerDepth, bool drawStackNumber)
{
if (this.isRecipe)
{
transparency = 0.5f;
scaleSize *= 0.75f;
}
if (this.Texture != null)
{
var targSize = (int) (64 * scaleSize * 0.9f);
var midX = (int) (location.X + 32);
var midY = (int) (location.Y + 32);
var targX = midX - targSize / 2;
var targY = midY - targSize / 2;
spriteBatch.Draw(this.Texture, new Rectangle(targX, targY, targSize, targSize), null, new Color(255, 255, 255, transparency), 0, Vector2.Zero, SpriteEffects.None, layerDepth);
}
if (drawStackNumber)
{
var _scale = 0.5f + scaleSize;
Game1.drawWithBorder(this.stack.ToString(), Color.Black, Color.White, location + new Vector2(Game1.tileSize - Game1.tinyFont.MeasureString(string.Concat(this.stack.ToString())).X * _scale, Game1.tileSize - (float) ((double) Game1.tinyFont.MeasureString(string.Concat(this.stack.ToString())).Y * 3.0f / 4.0f) * _scale), 0.0f, _scale, 1f, true);
}
}
public override void drawWhenHeld(SpriteBatch spriteBatch, Vector2 objectPosition, Farmer f)
{
if (this.Texture != null)
{
var targSize = 64;
var midX = (int) (objectPosition.X + 32);
var midY = (int) (objectPosition.Y + 32);
var targX = midX - targSize / 2;
var targY = midY - targSize / 2;
spriteBatch.Draw(this.Texture, new Rectangle(targX, targY, targSize, targSize), null, Color.White, 0, Vector2.Zero, SpriteEffects.None, (f.getStandingY() + 2) / 10000f);
}
}
public override Color getCategoryColor()
{
return this.CategoryColour;
}
public override string getCategoryName()
{
if (string.IsNullOrEmpty(this.CategoryName))
return "Modded Item";
return this.CategoryName;
}
public override bool isPassable()
{
return this.IsPassable;
}
public override bool isPlaceable()
{
return this.IsPlaceable;
}
public override int maximumStackSize()
{
return this.MaxStackSize;
}
public SObject Clone()
{
var toRet = new SObject
{
Name = this.Name,
CategoryName = this.CategoryName,
Description = this.Description,
Texture = this.Texture,
IsPassable = this.IsPassable,
IsPlaceable = this.IsPlaceable,
quality = this.quality,
scale = this.scale,
isSpawnedObject = this.isSpawnedObject,
isRecipe = this.isRecipe,
questItem = this.questItem,
stack = 1,
HasBeenRegistered = this.HasBeenRegistered,
RegisteredId = this.RegisteredId
};
return toRet;
}
public override Item getOne()
{
return this.Clone();
}
public override void actionWhenBeingHeld(Farmer who)
{
var x = Game1.oldMouseState.X + Game1.viewport.X;
var y = Game1.oldMouseState.Y + Game1.viewport.Y;
x = x / Game1.tileSize;
y = y / Game1.tileSize;
this.CurrentMouse = new Vector2(x, y);
//Program.LogDebug(canBePlacedHere(Game1.currentLocation, CurrentMouse));
base.actionWhenBeingHeld(who);
}
public override bool canBePlacedHere(GameLocation l, Vector2 tile)
{
//Program.LogDebug(CurrentMouse.ToString().Replace("{", "").Replace("}", ""));
if (!l.objects.ContainsKey(tile))
return true;
return false;
}
public override bool placementAction(GameLocation location, int x, int y, Farmer who = null)
{
if (Game1.didPlayerJustRightClick())
return false;
x = x / Game1.tileSize;
y = y / Game1.tileSize;
var key = new Vector2(x, y);
if (!this.canBePlacedHere(location, key))
return false;
var s = this.Clone();
s.PlacedAt = key;
s.boundingBox = new Rectangle(x / Game1.tileSize * Game1.tileSize, y / Game1.tileSize * Game1.tileSize, this.boundingBox.Width, this.boundingBox.Height);
location.objects.Add(key, s);
return true;
}
public override void actionOnPlayerEntry()
{
//base.actionOnPlayerEntry();
}
public override void drawPlacementBounds(SpriteBatch spriteBatch, GameLocation location)
{
if (this.canBePlacedHere(location, this.CurrentMouse))
{
var targSize = Game1.tileSize;
var x = Game1.oldMouseState.X + Game1.viewport.X;
var y = Game1.oldMouseState.Y + Game1.viewport.Y;
spriteBatch.Draw(Game1.mouseCursors, new Vector2(x / Game1.tileSize * Game1.tileSize - Game1.viewport.X, y / Game1.tileSize * Game1.tileSize - Game1.viewport.Y), new Rectangle(Utility.playerCanPlaceItemHere(location, this, x, y, Game1.player) ? 194 : 210, 388, 16, 16), Color.White, 0.0f, Vector2.Zero, Game1.pixelZoom, SpriteEffects.None, 0.01f);
}
}
}
}

View File

@ -1,66 +0,0 @@
using System;
using StardewModdingAPI.Framework;
namespace StardewModdingAPI
{
/// <summary>A log writer which queues messages for output, and periodically flushes them to the console and log file.</summary>
/// <remarks>Only one instance should be created.</remarks>
[Obsolete("This class is internal and should not be referenced outside SMAPI. It will no longer be exposed in a future version.")]
public class LogWriter
{
/*********
** Properties
*********/
/// <summary>Manages reading and writing to the log file.</summary>
private readonly LogFileManager LogFile;
/*********
** Public methods
*********/
/// <summary>Construct an instance.</summary>
/// <param name="logFile">Manages reading and writing to the log file.</param>
internal LogWriter(LogFileManager logFile)
{
this.WarnDeprecated();
this.LogFile = logFile;
}
/// <summary>Queue a message for output.</summary>
/// <param name="message">The message to log.</param>
public void WriteToLog(string message)
{
this.WarnDeprecated();
this.WriteToLog(new LogInfo(message));
}
/// <summary>Queue a message for output.</summary>
/// <param name="message">The message to log.</param>
public void WriteToLog(LogInfo message)
{
this.WarnDeprecated();
string output = $"[{message.LogTime}] {message.Message}";
if (message.PrintConsole)
{
if (Monitor.ConsoleSupportsColor)
{
Console.ForegroundColor = message.Colour;
Console.WriteLine(message);
Console.ResetColor();
}
else
Console.WriteLine(message);
}
this.LogFile.WriteLine(output);
}
/*********
** Private methods
*********/
/// <summary>Raise a deprecation warning.</summary>
private void WarnDeprecated()
{
Program.DeprecationManager.Warn($"the {nameof(LogWriter)} class", "1.0", DeprecationLevel.PendingRemoval);
}
}
}

View File

@ -1,23 +1,11 @@
using System;
using Newtonsoft.Json;
using StardewModdingAPI.Framework.Serialisation;
namespace StardewModdingAPI
{
/// <summary>Wraps <see cref="Manifest"/> so it can implement <see cref="IManifest"/> without breaking backwards compatibility.</summary>
[Obsolete("Use " + nameof(IManifest) + " or " + nameof(Mod) + "." + nameof(Mod.ModManifest) + " instead")]
internal class ManifestImpl : Manifest, IManifest
{
/// <summary>The mod version.</summary>
[JsonProperty("Version", ObjectCreationHandling = ObjectCreationHandling.Auto/* avoids issue where Json.NET can't determine concrete type for interface */)]
public new ISemanticVersion Version
{
get { return base.Version; }
set { base.Version = (Version)value; }
}
}
/// <summary>A manifest which describes a mod for SMAPI.</summary>
public class Manifest
public class Manifest : IManifest
{
/*********
** Accessors
@ -32,7 +20,8 @@ namespace StardewModdingAPI
public string Author { get; set; }
/// <summary>The mod version.</summary>
public Version Version { get; set; } = new Version(0, 0, 0, "", suppressDeprecationWarning: true);
[JsonConverter(typeof(SemanticVersionConverter))]
public ISemanticVersion Version { get; set; }
/// <summary>The minimum SMAPI version required by this mod, if any.</summary>
public string MinimumApiVersion { get; set; }
@ -43,26 +32,6 @@ namespace StardewModdingAPI
/// <summary>The unique mod ID.</summary>
public string UniqueID { get; set; }
/****
** Obsolete
****/
/// <summary>Whether the manifest defined the deprecated <see cref="Authour"/> field.</summary>
[JsonIgnore]
internal bool UsedAuthourField { get; private set; }
/// <summary>Obsolete.</summary>
[Obsolete("Use " + nameof(Manifest) + "." + nameof(Manifest.Author) + ".")]
public virtual string Authour
{
get { return this.Author; }
set
{
this.UsedAuthourField = true;
this.Author = value;
}
}
/// <summary>Whether the mod uses per-save config files.</summary>
[Obsolete("Use " + nameof(Mod) + "." + nameof(Mod.Helper) + "." + nameof(IModHelper.ReadConfig) + " instead")]
public bool PerSaveConfigs { get; set; }

View File

@ -23,17 +23,6 @@ namespace StardewModdingAPI
/// <summary>Writes messages to the console and log file.</summary>
public IMonitor Monitor { get; internal set; }
/// <summary>The mod's manifest.</summary>
[Obsolete("Use " + nameof(Mod) + "." + nameof(ModManifest))]
public Manifest Manifest
{
get
{
Program.DeprecationManager.Warn($"{nameof(Mod)}.{nameof(Manifest)}", "1.5", DeprecationLevel.Notice);
return (Manifest)this.ModManifest;
}
}
/// <summary>The mod's manifest.</summary>
public IManifest ModManifest { get; internal set; }
@ -85,11 +74,6 @@ namespace StardewModdingAPI
[Obsolete("This overload is obsolete since SMAPI 1.0.")]
public virtual void Entry(params object[] objects) { }
/// <summary>The mod entry point, called after the mod is first loaded.</summary>
/// <param name="helper">Provides simplified APIs for writing mods.</param>
[Obsolete("This overload is obsolete since SMAPI 1.1.")]
public virtual void Entry(ModHelper helper) { }
/// <summary>The mod entry point, called after the mod is first loaded.</summary>
/// <param name="helper">Provides simplified APIs for writing mods.</param>
public virtual void Entry(IModHelper helper) { }
@ -105,7 +89,7 @@ namespace StardewModdingAPI
Program.DeprecationManager.Warn($"{nameof(Mod)}.{nameof(Mod.PerSaveConfigFolder)}", "1.0", DeprecationLevel.Notice);
Program.DeprecationManager.MarkWarned($"{nameof(Mod)}.{nameof(Mod.PathOnDisk)}", "1.0"); // avoid redundant warnings
if (!((Manifest)this.Manifest).PerSaveConfigs)
if (!((Manifest)this.ModManifest).PerSaveConfigs)
{
this.Monitor.Log("Tried to fetch the per-save config folder, but this mod isn't configured to use per-save config files.", LogLevel.Error);
return "";

View File

@ -14,14 +14,13 @@ using StardewModdingAPI.AssemblyRewriters;
using StardewModdingAPI.Events;
using StardewModdingAPI.Framework;
using StardewModdingAPI.Framework.Models;
using StardewModdingAPI.Inheritance;
using StardewValley;
using Monitor = StardewModdingAPI.Framework.Monitor;
namespace StardewModdingAPI
{
/// <summary>The main entry point for SMAPI, responsible for hooking into and launching the game.</summary>
public class Program
internal class Program
{
/*********
** Properties
@ -52,31 +51,27 @@ namespace StardewModdingAPI
/// <summary>Tracks whether the game should exit immediately and any pending initialisation should be cancelled.</summary>
private static readonly CancellationTokenSource CancellationTokenSource = new CancellationTokenSource();
/// <summary>Whether the game is currently running.</summary>
private static bool ready;
/// <summary>The underlying game assembly.</summary>
private static Assembly StardewAssembly;
/// <summary>The underlying <see cref="StardewValley.Program"/> type.</summary>
private static Type StardewProgramType;
/// <summary>The field containing game's main instance.</summary>
private static FieldInfo StardewGameInfo;
/*********
** Accessors
*********/
/// <summary>The number of mods currently loaded by SMAPI.</summary>
public static int ModsLoaded;
/// <summary>The underlying game instance.</summary>
public static SGame gamePtr;
internal static SGame gamePtr;
/// <summary>Whether the game is currently running.</summary>
public static bool ready;
/// <summary>The underlying game assembly.</summary>
public static Assembly StardewAssembly;
/// <summary>The underlying <see cref="StardewValley.Program"/> type.</summary>
public static Type StardewProgramType;
/// <summary>The field containing game's main instance.</summary>
public static FieldInfo StardewGameInfo;
// ReSharper disable once PossibleNullReferenceException
/// <summary>The game's build type (i.e. GOG vs Steam).</summary>
public static int BuildType => (int)Program.StardewProgramType.GetField("buildType", BindingFlags.Public | BindingFlags.Static).GetValue(null);
/// <summary>The number of mods currently loaded by SMAPI.</summary>
internal static int ModsLoaded;
/// <summary>Tracks the installed mods.</summary>
internal static readonly ModRegistry ModRegistry = new ModRegistry();
@ -358,7 +353,7 @@ namespace StardewModdingAPI
string errorPrefix = $"Couldn't load mod for manifest '{manifestPath}'";
// read manifest
ManifestImpl manifest;
Manifest manifest;
try
{
// read manifest text
@ -370,7 +365,7 @@ namespace StardewModdingAPI
}
// deserialise manifest
manifest = helper.ReadJsonFile<ManifestImpl>("manifest.json");
manifest = helper.ReadJsonFile<Manifest>("manifest.json");
if (manifest == null)
{
Program.Monitor.Log($"{errorPrefix}: the manifest file does not exist.", LogLevel.Error);
@ -381,10 +376,6 @@ namespace StardewModdingAPI
Program.Monitor.Log($"{errorPrefix}: manifest doesn't specify an entry DLL.", LogLevel.Error);
continue;
}
// log deprecated fields
if (manifest.UsedAuthourField)
deprecationWarnings.Add(() => Program.DeprecationManager.Warn(manifest.Name, $"{nameof(Manifest)}.{nameof(Manifest.Authour)}", "1.0", DeprecationLevel.Notice));
}
catch (Exception ex)
{
@ -424,7 +415,7 @@ namespace StardewModdingAPI
}
catch (FormatException ex) when (ex.Message.Contains("not a valid semantic version"))
{
Program.Monitor.Log($"{errorPrefix}: the mod specified an invalid minimum SMAPI version '{manifest.MinimumApiVersion}'. This should be a semantic version number like {Constants.Version}.", LogLevel.Error);
Program.Monitor.Log($"{errorPrefix}: the mod specified an invalid minimum SMAPI version '{manifest.MinimumApiVersion}'. This should be a semantic version number like {Constants.ApiVersion}.", LogLevel.Error);
continue;
}
}
@ -528,14 +519,11 @@ namespace StardewModdingAPI
{
// call entry methods
mod.Entry(); // deprecated since 1.0
mod.Entry((ModHelper)mod.Helper); // deprecated since 1.1
mod.Entry(mod.Helper);
// raise deprecation warning for old Entry() methods
if (Program.DeprecationManager.IsVirtualMethodImplemented(mod.GetType(), typeof(Mod), nameof(Mod.Entry), new[] { typeof(object[]) }))
Program.DeprecationManager.Warn(mod.ModManifest.Name, $"{nameof(Mod)}.{nameof(Mod.Entry)}(object[]) instead of {nameof(Mod)}.{nameof(Mod.Entry)}({nameof(IModHelper)})", "1.0", DeprecationLevel.Notice);
if (Program.DeprecationManager.IsVirtualMethodImplemented(mod.GetType(), typeof(Mod), nameof(Mod.Entry), new[] { typeof(ModHelper) }))
Program.DeprecationManager.Warn(mod.ModManifest.Name, $"{nameof(Mod)}.{nameof(Mod.Entry)}({nameof(ModHelper)}) instead of {nameof(Mod)}.{nameof(Mod.Entry)}({nameof(IModHelper)})", "1.1", DeprecationLevel.PendingRemoval);
}
catch (Exception ex)
{

View File

@ -13,28 +13,21 @@ namespace StardewModdingAPI
/// <remarks>Derived from https://github.com/maxhauser/semver.</remarks>
private static readonly Regex Regex = new Regex(@"^(?<major>\d+)(\.(?<minor>\d+))?(\.(?<patch>\d+))?(?<build>.*)$", RegexOptions.CultureInvariant | RegexOptions.ExplicitCapture);
/// <summary>The backing field for <see cref="Build"/>.</summary>
private string _build;
/*********
** Accessors
*********/
/// <summary>The major version incremented for major API changes.</summary>
public int MajorVersion { get; set; }
public int MajorVersion { get; }
/// <summary>The minor version incremented for backwards-compatible changes.</summary>
public int MinorVersion { get; set; }
public int MinorVersion { get; }
/// <summary>The patch version for backwards-compatible bug fixes.</summary>
public int PatchVersion { get; set; }
public int PatchVersion { get; }
/// <summary>An optional build tag.</summary>
public string Build
{
get { return this._build; }
set { this._build = this.GetNormalisedTag(value); }
}
public string Build { get; }
/*********
@ -50,7 +43,7 @@ namespace StardewModdingAPI
this.MajorVersion = major;
this.MinorVersion = minor;
this.PatchVersion = patch;
this.Build = build;
this.Build = this.GetNormalisedTag(build);
}
/// <summary>Construct an instance.</summary>
@ -65,7 +58,7 @@ namespace StardewModdingAPI
this.MajorVersion = int.Parse(match.Groups["major"].Value);
this.MinorVersion = match.Groups["minor"].Success ? int.Parse(match.Groups["minor"].Value) : 0;
this.PatchVersion = match.Groups["patch"].Success ? int.Parse(match.Groups["patch"].Value) : 0;
this.Build = match.Groups["build"].Success ? match.Groups["build"].Value : null;
this.Build = match.Groups["build"].Success ? this.GetNormalisedTag(match.Groups["build"].Value) : null;
}
/// <summary>Get an integer indicating whether this version precedes (less than 0), supercedes (more than 0), or is equivalent to (0) the specified version.</summary>

View File

@ -123,7 +123,6 @@
<Compile Include="Command.cs" />
<Compile Include="Config.cs" />
<Compile Include="Constants.cs" />
<Compile Include="Entities\SPlayer.cs" />
<Compile Include="Events\ControlEvents.cs" />
<Compile Include="Events\EventArgsCommand.cs" />
<Compile Include="Events\EventArgsClickableMenuChanged.cs" />
@ -150,6 +149,7 @@
<Compile Include="Events\GraphicsEvents.cs" />
<Compile Include="Framework\AssemblyDefinitionResolver.cs" />
<Compile Include="Framework\AssemblyParseResult.cs" />
<Compile Include="Framework\Serialisation\SemanticVersionConverter.cs" />
<Compile Include="IModRegistry.cs" />
<Compile Include="Events\LocationEvents.cs" />
<Compile Include="Events\MenuEvents.cs" />
@ -157,7 +157,6 @@
<Compile Include="Events\PlayerEvents.cs" />
<Compile Include="Events\SaveEvents.cs" />
<Compile Include="Events\TimeEvents.cs" />
<Compile Include="Extensions.cs" />
<Compile Include="Framework\DeprecationLevel.cs" />
<Compile Include="Framework\DeprecationManager.cs" />
<Compile Include="Framework\InternalExtensions.cs" />
@ -178,24 +177,21 @@
<Compile Include="Framework\Models\GitRelease.cs" />
<Compile Include="Framework\Models\UserSettings.cs" />
<Compile Include="IMonitor.cs" />
<Compile Include="Inheritance\ChangeType.cs" />
<Compile Include="Inheritance\ItemStackChange.cs" />
<Compile Include="Inheritance\SObject.cs" />
<Compile Include="Events\ChangeType.cs" />
<Compile Include="Events\ItemStackChange.cs" />
<Compile Include="Log.cs" />
<Compile Include="Framework\Monitor.cs" />
<Compile Include="LogInfo.cs" />
<Compile Include="LogWriter.cs" />
<Compile Include="Manifest.cs" />
<Compile Include="Mod.cs" />
<Compile Include="ModHelper.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Inheritance\SGame.cs" />
<Compile Include="Framework\SGame.cs" />
<Compile Include="IPrivateField.cs" />
<Compile Include="IPrivateMethod.cs" />
<Compile Include="IReflectionHelper.cs" />
<Compile Include="SemanticVersion.cs" />
<Compile Include="Version.cs" />
</ItemGroup>
<ItemGroup>
<None Include="App.config">

View File

@ -1,121 +0,0 @@
using System;
using Newtonsoft.Json;
using StardewModdingAPI.Framework;
namespace StardewModdingAPI
{
/// <summary>A semantic version with an optional release tag.</summary>
[Obsolete("Use " + nameof(SemanticVersion) + " or " + nameof(Manifest) + "." + nameof(Manifest.Version) + " instead")]
public struct Version : ISemanticVersion
{
/*********
** Accessors
*********/
/// <summary>The major version incremented for major API changes.</summary>
public int MajorVersion { get; set; }
/// <summary>The minor version incremented for backwards-compatible changes.</summary>
public int MinorVersion { get; set; }
/// <summary>The patch version for backwards-compatible bug fixes.</summary>
public int PatchVersion { get; set; }
/// <summary>An optional build tag.</summary>
public string Build { get; set; }
/// <summary>Obsolete.</summary>
[JsonIgnore]
[Obsolete("Use " + nameof(Version) + "." + nameof(Version.ToString) + " instead.")]
public string VersionString
{
get
{
Program.DeprecationManager.Warn($"{nameof(Version)}.{nameof(Version.VersionString)}", "1.0", DeprecationLevel.Info);
return this.GetSemanticVersion().ToString();
}
}
/*********
** Public methods
*********/
/// <summary>Construct an instance.</summary>
/// <param name="major">The major version incremented for major API changes.</param>
/// <param name="minor">The minor version incremented for backwards-compatible changes.</param>
/// <param name="patch">The patch version for backwards-compatible bug fixes.</param>
/// <param name="build">An optional build tag.</param>
public Version(int major, int minor, int patch, string build)
: this(major, minor, patch, build, suppressDeprecationWarning: false)
{ }
/// <summary>Get an integer indicating whether this version precedes (less than 0), supercedes (more than 0), or is equivalent to (0) the specified version.</summary>
/// <param name="other">The version to compare with this instance.</param>
public int CompareTo(Version other)
{
return this.GetSemanticVersion().CompareTo(other);
}
/// <summary>Get whether this version is newer than the specified version.</summary>
/// <param name="other">The version to compare with this instance.</param>
[Obsolete("Use " + nameof(ISemanticVersion) + "." + nameof(ISemanticVersion.IsNewerThan) + " instead")]
public bool IsNewerThan(Version other)
{
return this.GetSemanticVersion().IsNewerThan(other);
}
/// <summary>Compares the current instance with another object of the same type and returns an integer that indicates whether the current instance precedes, follows, or occurs in the same position in the sort order as the other object. </summary>
/// <returns>A value that indicates the relative order of the objects being compared. The return value has these meanings: Value Meaning Less than zero This instance precedes <paramref name="other" /> in the sort order. Zero This instance occurs in the same position in the sort order as <paramref name="other" />. Greater than zero This instance follows <paramref name="other" /> in the sort order. </returns>
/// <param name="other">An object to compare with this instance. </param>
int IComparable<ISemanticVersion>.CompareTo(ISemanticVersion other)
{
return this.GetSemanticVersion().CompareTo(other);
}
/// <summary>Get whether this version is older than the specified version.</summary>
/// <param name="other">The version to compare with this instance.</param>
bool ISemanticVersion.IsOlderThan(ISemanticVersion other)
{
return this.GetSemanticVersion().IsOlderThan(other);
}
/// <summary>Get whether this version is newer than the specified version.</summary>
/// <param name="other">The version to compare with this instance.</param>
bool ISemanticVersion.IsNewerThan(ISemanticVersion other)
{
return this.GetSemanticVersion().IsNewerThan(other);
}
/// <summary>Get a string representation of the version.</summary>
public override string ToString()
{
return this.GetSemanticVersion().ToString();
}
/*********
** Private methods
*********/
/// <summary>Construct an instance.</summary>
/// <param name="major">The major version incremented for major API changes.</param>
/// <param name="minor">The minor version incremented for backwards-compatible changes.</param>
/// <param name="patch">The patch version for backwards-compatible bug fixes.</param>
/// <param name="build">An optional build tag.</param>
/// <param name="suppressDeprecationWarning">Whether to suppress the deprecation warning.</param>
internal Version(int major, int minor, int patch, string build, bool suppressDeprecationWarning)
{
if (!suppressDeprecationWarning)
Program.DeprecationManager.Warn($"{nameof(Version)}", "1.5", DeprecationLevel.Notice);
this.MajorVersion = major;
this.MinorVersion = minor;
this.PatchVersion = patch;
this.Build = build;
}
/// <summary>Get the equivalent semantic version.</summary>
/// <remarks>This is a hack so the struct can wrap <see cref="SemanticVersion"/> without a mutable backing field, which would cause a <see cref="StackOverflowException"/> due to recreating the struct value on each change.</remarks>
private SemanticVersion GetSemanticVersion()
{
return new SemanticVersion(this.MajorVersion, this.MinorVersion, this.PatchVersion, this.Build);
}
}
}

View File

@ -81,9 +81,6 @@ namespace TrainerMod
Command.RegisterCommand("save", "Saves the game? Doesn't seem to work. | save").CommandFired += this.HandleSave;
Command.RegisterCommand("load", "Shows the load screen | load").CommandFired += this.HandleLoad;
Command.RegisterCommand("exit", "Closes the game | exit").CommandFired += this.HandleExit;
Command.RegisterCommand("stop", "Closes the game | stop").CommandFired += this.HandleExit;
Command.RegisterCommand("player_setname", "Sets the player's name | player_setname <object> <value>", new[] { "(player, pet, farm)<object> (String)<value> The target name" }).CommandFired += this.HandlePlayerSetName;
Command.RegisterCommand("player_setmoney", "Sets the player's money | player_setmoney <value>|inf", new[] { "(Int32)<value> The target money" }).CommandFired += this.HandlePlayerSetMoney;
Command.RegisterCommand("player_setstamina", "Sets the player's stamina | player_setstamina <value>|inf", new[] { "(Int32)<value> The target stamina" }).CommandFired += this.HandlePlayerSetStamina;
@ -142,15 +139,6 @@ namespace TrainerMod
Game1.activeClickableMenu = new LoadGameMenu();
}
/// <summary>The event raised when the 'exit' command is triggered.</summary>
/// <param name="sender">The event sender.</param>
/// <param name="e">The event arguments.</param>
private void HandleExit(object sender, EventArgsCommand e)
{
Program.gamePtr.Exit();
Environment.Exit(0);
}
/// <summary>The event raised when the 'player_setName' command is triggered.</summary>
/// <param name="sender">The event sender.</param>
/// <param name="e">The event arguments.</param>