move manifest parsing into toolkit (#532)
This commit is contained in:
parent
265ce35fd1
commit
625c538f24
|
@ -9,7 +9,7 @@ using StardewModdingAPI.Framework;
|
||||||
using StardewModdingAPI.Framework.ModData;
|
using StardewModdingAPI.Framework.ModData;
|
||||||
using StardewModdingAPI.Framework.Models;
|
using StardewModdingAPI.Framework.Models;
|
||||||
using StardewModdingAPI.Framework.ModLoading;
|
using StardewModdingAPI.Framework.ModLoading;
|
||||||
using StardewModdingAPI.Framework.Serialisation;
|
using StardewModdingAPI.Toolkit.Serialisation;
|
||||||
|
|
||||||
namespace StardewModdingAPI.Tests.Core
|
namespace StardewModdingAPI.Tests.Core
|
||||||
{
|
{
|
||||||
|
@ -93,8 +93,8 @@ namespace StardewModdingAPI.Tests.Core
|
||||||
Assert.IsNotNull(mod, "The loaded manifest shouldn't be null.");
|
Assert.IsNotNull(mod, "The loaded manifest shouldn't be null.");
|
||||||
Assert.AreEqual(null, mod.DataRecord, "The data record should be null since we didn't provide one.");
|
Assert.AreEqual(null, mod.DataRecord, "The data record should be null since we didn't provide one.");
|
||||||
Assert.AreEqual(modFolder, mod.DirectoryPath, "The directory path doesn't match.");
|
Assert.AreEqual(modFolder, mod.DirectoryPath, "The directory path doesn't match.");
|
||||||
Assert.AreEqual(ModMetadataStatus.Found, mod.Status, "The status doesn't match.");
|
|
||||||
Assert.AreEqual(null, mod.Error, "The error should be null since parsing should have succeeded.");
|
Assert.AreEqual(null, mod.Error, "The error should be null since parsing should have succeeded.");
|
||||||
|
Assert.AreEqual(ModMetadataStatus.Found, mod.Status, "The status doesn't match.");
|
||||||
|
|
||||||
Assert.AreEqual(original[nameof(IManifest.Name)], mod.DisplayName, "The display name should use the manifest name.");
|
Assert.AreEqual(original[nameof(IManifest.Name)], mod.DisplayName, "The display name should use the manifest name.");
|
||||||
Assert.AreEqual(original[nameof(IManifest.Name)], mod.Manifest.Name, "The manifest's name doesn't match.");
|
Assert.AreEqual(original[nameof(IManifest.Name)], mod.Manifest.Name, "The manifest's name doesn't match.");
|
||||||
|
@ -160,7 +160,7 @@ namespace StardewModdingAPI.Tests.Core
|
||||||
{
|
{
|
||||||
// arrange
|
// arrange
|
||||||
Mock<IModMetadata> mock = this.GetMetadata("Mod A", new string[0], allowStatusChange: true);
|
Mock<IModMetadata> mock = this.GetMetadata("Mod A", new string[0], allowStatusChange: true);
|
||||||
mock.Setup(p => p.Manifest).Returns(this.GetManifest(m => m.MinimumApiVersion = new SemanticVersion("1.1")));
|
mock.Setup(p => p.Manifest).Returns(this.GetManifest(minimumApiVersion: "1.1"));
|
||||||
this.SetupMetadataForValidation(mock);
|
this.SetupMetadataForValidation(mock);
|
||||||
|
|
||||||
// act
|
// act
|
||||||
|
@ -174,7 +174,7 @@ namespace StardewModdingAPI.Tests.Core
|
||||||
public void ValidateManifests_MissingEntryDLL_Fails()
|
public void ValidateManifests_MissingEntryDLL_Fails()
|
||||||
{
|
{
|
||||||
// arrange
|
// arrange
|
||||||
Mock<IModMetadata> mock = this.GetMetadata(this.GetManifest("Mod A", "1.0", manifest => manifest.EntryDll = "Missing.dll"), allowStatusChange: true);
|
Mock<IModMetadata> mock = this.GetMetadata(this.GetManifest(id: "Mod A", version: "1.0", entryDll: "Missing.dll"), allowStatusChange: true);
|
||||||
this.SetupMetadataForValidation(mock);
|
this.SetupMetadataForValidation(mock);
|
||||||
|
|
||||||
// act
|
// act
|
||||||
|
@ -189,7 +189,7 @@ namespace StardewModdingAPI.Tests.Core
|
||||||
{
|
{
|
||||||
// arrange
|
// arrange
|
||||||
Mock<IModMetadata> modA = this.GetMetadata("Mod A", new string[0], allowStatusChange: true);
|
Mock<IModMetadata> modA = this.GetMetadata("Mod A", new string[0], allowStatusChange: true);
|
||||||
Mock<IModMetadata> modB = this.GetMetadata(this.GetManifest("Mod A", "1.0", manifest => manifest.Name = "Mod B"), allowStatusChange: true);
|
Mock<IModMetadata> modB = this.GetMetadata(this.GetManifest(id: "Mod A", name: "Mod B", version: "1.0"), allowStatusChange: true);
|
||||||
Mock<IModMetadata> modC = this.GetMetadata("Mod C", new string[0], allowStatusChange: false);
|
Mock<IModMetadata> modC = this.GetMetadata("Mod C", new string[0], allowStatusChange: false);
|
||||||
foreach (Mock<IModMetadata> mod in new[] { modA, modB, modC })
|
foreach (Mock<IModMetadata> mod in new[] { modA, modB, modC })
|
||||||
this.SetupMetadataForValidation(mod);
|
this.SetupMetadataForValidation(mod);
|
||||||
|
@ -398,8 +398,8 @@ namespace StardewModdingAPI.Tests.Core
|
||||||
{
|
{
|
||||||
// arrange
|
// arrange
|
||||||
// A 1.0 ◀── B (need A 1.1)
|
// A 1.0 ◀── B (need A 1.1)
|
||||||
Mock<IModMetadata> modA = this.GetMetadata(this.GetManifest("Mod A", "1.0"));
|
Mock<IModMetadata> modA = this.GetMetadata(this.GetManifest(id: "Mod A", version: "1.0"));
|
||||||
Mock<IModMetadata> modB = this.GetMetadata(this.GetManifest("Mod B", "1.0", new ManifestDependency("Mod A", "1.1")), allowStatusChange: true);
|
Mock<IModMetadata> modB = this.GetMetadata(this.GetManifest(id: "Mod B", version: "1.0", dependencies: new IManifestDependency[] { new ManifestDependency("Mod A", "1.1") }), allowStatusChange: true);
|
||||||
|
|
||||||
// act
|
// act
|
||||||
IModMetadata[] mods = new ModResolver().ProcessDependencies(new[] { modA.Object, modB.Object }, new ModDatabase()).ToArray();
|
IModMetadata[] mods = new ModResolver().ProcessDependencies(new[] { modA.Object, modB.Object }, new ModDatabase()).ToArray();
|
||||||
|
@ -414,8 +414,8 @@ namespace StardewModdingAPI.Tests.Core
|
||||||
{
|
{
|
||||||
// arrange
|
// arrange
|
||||||
// A 1.0 ◀── B (need A 1.0-beta)
|
// A 1.0 ◀── B (need A 1.0-beta)
|
||||||
Mock<IModMetadata> modA = this.GetMetadata(this.GetManifest("Mod A", "1.0"));
|
Mock<IModMetadata> modA = this.GetMetadata(this.GetManifest(id: "Mod A", version: "1.0"));
|
||||||
Mock<IModMetadata> modB = this.GetMetadata(this.GetManifest("Mod B", "1.0", new ManifestDependency("Mod A", "1.0-beta")), allowStatusChange: false);
|
Mock<IModMetadata> modB = this.GetMetadata(this.GetManifest(id: "Mod B", version: "1.0", dependencies: new IManifestDependency[] { new ManifestDependency("Mod A", "1.0-beta") }), allowStatusChange: false);
|
||||||
|
|
||||||
// act
|
// act
|
||||||
IModMetadata[] mods = new ModResolver().ProcessDependencies(new[] { modA.Object, modB.Object }, new ModDatabase()).ToArray();
|
IModMetadata[] mods = new ModResolver().ProcessDependencies(new[] { modA.Object, modB.Object }, new ModDatabase()).ToArray();
|
||||||
|
@ -431,8 +431,8 @@ namespace StardewModdingAPI.Tests.Core
|
||||||
{
|
{
|
||||||
// arrange
|
// arrange
|
||||||
// A ◀── B
|
// A ◀── B
|
||||||
Mock<IModMetadata> modA = this.GetMetadata(this.GetManifest("Mod A", "1.0"));
|
Mock<IModMetadata> modA = this.GetMetadata(this.GetManifest(id: "Mod A", version: "1.0"));
|
||||||
Mock<IModMetadata> modB = this.GetMetadata(this.GetManifest("Mod B", "1.0", new ManifestDependency("Mod A", "1.0", required: false)), allowStatusChange: false);
|
Mock<IModMetadata> modB = this.GetMetadata(this.GetManifest(id: "Mod B", version: "1.0", dependencies: new IManifestDependency[] { new ManifestDependency("Mod A", "1.0", required: false) }), allowStatusChange: false);
|
||||||
|
|
||||||
// act
|
// act
|
||||||
IModMetadata[] mods = new ModResolver().ProcessDependencies(new[] { modB.Object, modA.Object }, new ModDatabase()).ToArray();
|
IModMetadata[] mods = new ModResolver().ProcessDependencies(new[] { modB.Object, modA.Object }, new ModDatabase()).ToArray();
|
||||||
|
@ -448,7 +448,7 @@ namespace StardewModdingAPI.Tests.Core
|
||||||
{
|
{
|
||||||
// arrange
|
// arrange
|
||||||
// A ◀── B where A doesn't exist
|
// A ◀── B where A doesn't exist
|
||||||
Mock<IModMetadata> modB = this.GetMetadata(this.GetManifest("Mod B", "1.0", new ManifestDependency("Mod A", "1.0", required: false)), allowStatusChange: false);
|
Mock<IModMetadata> modB = this.GetMetadata(this.GetManifest(id: "Mod B", version: "1.0", dependencies: new IManifestDependency[] { new ManifestDependency("Mod A", "1.0", required: false) }), allowStatusChange: false);
|
||||||
|
|
||||||
// act
|
// act
|
||||||
IModMetadata[] mods = new ModResolver().ProcessDependencies(new[] { modB.Object }, new ModDatabase()).ToArray();
|
IModMetadata[] mods = new ModResolver().ProcessDependencies(new[] { modB.Object }, new ModDatabase()).ToArray();
|
||||||
|
@ -463,46 +463,26 @@ namespace StardewModdingAPI.Tests.Core
|
||||||
** Private methods
|
** Private methods
|
||||||
*********/
|
*********/
|
||||||
/// <summary>Get a randomised basic manifest.</summary>
|
/// <summary>Get a randomised basic manifest.</summary>
|
||||||
/// <param name="adjust">Adjust the generated manifest.</param>
|
/// <param name="id">The <see cref="IManifest.UniqueID"/> value, or <c>null</c> for a generated value.</param>
|
||||||
private Manifest GetManifest(Action<Manifest> adjust = null)
|
/// <param name="name">The <see cref="IManifest.Name"/> value, or <c>null</c> for a generated value.</param>
|
||||||
|
/// <param name="version">The <see cref="IManifest.Version"/> value, or <c>null</c> for a generated value.</param>
|
||||||
|
/// <param name="entryDll">The <see cref="IManifest.EntryDll"/> value, or <c>null</c> for a generated value.</param>
|
||||||
|
/// <param name="contentPackForID">The <see cref="IManifest.ContentPackFor"/> value.</param>
|
||||||
|
/// <param name="minimumApiVersion">The <see cref="IManifest.MinimumApiVersion"/> value.</param>
|
||||||
|
/// <param name="dependencies">The <see cref="IManifest.Dependencies"/> value.</param>
|
||||||
|
private Manifest GetManifest(string id = null, string name = null, string version = null, string entryDll = null, string contentPackForID = null, string minimumApiVersion = null, IManifestDependency[] dependencies = null)
|
||||||
{
|
{
|
||||||
Manifest manifest = new Manifest
|
return new Manifest(
|
||||||
{
|
uniqueID: id ?? $"{Sample.String()}.{Sample.String()}",
|
||||||
Name = Sample.String(),
|
name: name ?? id ?? Sample.String(),
|
||||||
Author = Sample.String(),
|
author: Sample.String(),
|
||||||
Version = new SemanticVersion(Sample.Int(), Sample.Int(), Sample.Int(), Sample.String()),
|
description: Sample.String(),
|
||||||
Description = Sample.String(),
|
version: version != null ? new SemanticVersion(version) : new SemanticVersion(Sample.Int(), Sample.Int(), Sample.Int(), Sample.String()),
|
||||||
UniqueID = $"{Sample.String()}.{Sample.String()}",
|
entryDll: entryDll ?? $"{Sample.String()}.dll",
|
||||||
EntryDll = $"{Sample.String()}.dll"
|
contentPackFor: contentPackForID != null ? new ManifestContentPackFor(contentPackForID) : null,
|
||||||
};
|
minimumApiVersion: minimumApiVersion != null ? new SemanticVersion(minimumApiVersion) : null,
|
||||||
adjust?.Invoke(manifest);
|
dependencies: dependencies
|
||||||
return manifest;
|
);
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>Get a randomised basic manifest.</summary>
|
|
||||||
/// <param name="uniqueID">The mod's name and unique ID.</param>
|
|
||||||
/// <param name="version">The mod version.</param>
|
|
||||||
/// <param name="adjust">Adjust the generated manifest.</param>
|
|
||||||
/// <param name="dependencies">The dependencies this mod requires.</param>
|
|
||||||
private IManifest GetManifest(string uniqueID, string version, Action<Manifest> adjust, params IManifestDependency[] dependencies)
|
|
||||||
{
|
|
||||||
return this.GetManifest(manifest =>
|
|
||||||
{
|
|
||||||
manifest.Name = uniqueID;
|
|
||||||
manifest.UniqueID = uniqueID;
|
|
||||||
manifest.Version = new SemanticVersion(version);
|
|
||||||
manifest.Dependencies = dependencies;
|
|
||||||
adjust?.Invoke(manifest);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>Get a randomised basic manifest.</summary>
|
|
||||||
/// <param name="uniqueID">The mod's name and unique ID.</param>
|
|
||||||
/// <param name="version">The mod version.</param>
|
|
||||||
/// <param name="dependencies">The dependencies this mod requires.</param>
|
|
||||||
private IManifest GetManifest(string uniqueID, string version, params IManifestDependency[] dependencies)
|
|
||||||
{
|
|
||||||
return this.GetManifest(uniqueID, version, null, dependencies);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Get a randomised basic manifest.</summary>
|
/// <summary>Get a randomised basic manifest.</summary>
|
||||||
|
@ -518,7 +498,7 @@ namespace StardewModdingAPI.Tests.Core
|
||||||
/// <param name="allowStatusChange">Whether the code being tested is allowed to change the mod status.</param>
|
/// <param name="allowStatusChange">Whether the code being tested is allowed to change the mod status.</param>
|
||||||
private Mock<IModMetadata> GetMetadata(string uniqueID, string[] dependencies, bool allowStatusChange = false)
|
private Mock<IModMetadata> GetMetadata(string uniqueID, string[] dependencies, bool allowStatusChange = false)
|
||||||
{
|
{
|
||||||
IManifest manifest = this.GetManifest(uniqueID, "1.0", dependencies?.Select(dependencyID => (IManifestDependency)new ManifestDependency(dependencyID, null)).ToArray());
|
IManifest manifest = this.GetManifest(id: uniqueID, version: "1.0", dependencies: dependencies?.Select(dependencyID => (IManifestDependency)new ManifestDependency(dependencyID, null)).ToArray());
|
||||||
return this.GetMetadata(manifest, allowStatusChange);
|
return this.GetMetadata(manifest, allowStatusChange);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@ using System.Diagnostics.CodeAnalysis;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using StardewModdingAPI.Framework;
|
using StardewModdingAPI.Framework;
|
||||||
|
using StardewModdingAPI.Toolkit.Serialisation.Models;
|
||||||
|
|
||||||
namespace StardewModdingAPI.Tests.Utilities
|
namespace StardewModdingAPI.Tests.Utilities
|
||||||
{
|
{
|
||||||
|
|
|
@ -2,7 +2,7 @@ using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using Microsoft.Xna.Framework.Content;
|
using Microsoft.Xna.Framework.Content;
|
||||||
using Microsoft.Xna.Framework.Graphics;
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
using StardewModdingAPI.Framework.Serialisation;
|
using StardewModdingAPI.Toolkit.Serialisation;
|
||||||
using StardewModdingAPI.Toolkit.Utilities;
|
using StardewModdingAPI.Toolkit.Utilities;
|
||||||
using xTile;
|
using xTile;
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,6 @@ using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using Microsoft.Xna.Framework.Graphics;
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using StardewModdingAPI.Framework.Reflection;
|
using StardewModdingAPI.Framework.Reflection;
|
||||||
using StardewValley;
|
using StardewValley;
|
||||||
|
|
||||||
|
@ -91,20 +90,5 @@ namespace StardewModdingAPI.Framework
|
||||||
// get result
|
// get result
|
||||||
return reflection.GetField<bool>(Game1.spriteBatch, fieldName).GetValue();
|
return reflection.GetField<bool>(Game1.spriteBatch, fieldName).GetValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
/****
|
|
||||||
** Json.NET
|
|
||||||
****/
|
|
||||||
/// <summary>Get a JSON field value from a case-insensitive field name. This will check for an exact match first, then search without case sensitivity.</summary>
|
|
||||||
/// <typeparam name="T">The value type.</typeparam>
|
|
||||||
/// <param name="obj">The JSON object to search.</param>
|
|
||||||
/// <param name="fieldName">The field name.</param>
|
|
||||||
public static T ValueIgnoreCase<T>(this JObject obj, string fieldName)
|
|
||||||
{
|
|
||||||
JToken token = obj.GetValue(fieldName, StringComparison.InvariantCultureIgnoreCase);
|
|
||||||
return token != null
|
|
||||||
? token.Value<T>()
|
|
||||||
: default(T);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@ using System.Linq;
|
||||||
using StardewModdingAPI.Events;
|
using StardewModdingAPI.Events;
|
||||||
using StardewModdingAPI.Framework.Input;
|
using StardewModdingAPI.Framework.Input;
|
||||||
using StardewModdingAPI.Framework.Models;
|
using StardewModdingAPI.Framework.Models;
|
||||||
using StardewModdingAPI.Framework.Serialisation;
|
using StardewModdingAPI.Toolkit.Serialisation;
|
||||||
using StardewModdingAPI.Toolkit.Utilities;
|
using StardewModdingAPI.Toolkit.Utilities;
|
||||||
|
|
||||||
namespace StardewModdingAPI.Framework.ModHelpers
|
namespace StardewModdingAPI.Framework.ModHelpers
|
||||||
|
@ -179,16 +179,14 @@ namespace StardewModdingAPI.Framework.ModHelpers
|
||||||
throw new ArgumentException($"Can't create content pack for directory path '{directoryPath}' because no such directory exists.");
|
throw new ArgumentException($"Can't create content pack for directory path '{directoryPath}' because no such directory exists.");
|
||||||
|
|
||||||
// create manifest
|
// create manifest
|
||||||
IManifest manifest = new Manifest
|
IManifest manifest = new Manifest(
|
||||||
{
|
uniqueID: id,
|
||||||
Name = name,
|
name: name,
|
||||||
Author = author,
|
author: author,
|
||||||
Description = description,
|
description: description,
|
||||||
Version = version,
|
version: version,
|
||||||
UniqueID = id,
|
contentPackFor: new ManifestContentPackFor(this.ModID)
|
||||||
UpdateKeys = new string[0],
|
);
|
||||||
ContentPackFor = new ManifestContentPackFor { UniqueID = this.ModID }
|
|
||||||
};
|
|
||||||
|
|
||||||
// create content pack
|
// create content pack
|
||||||
return this.CreateContentPack(directoryPath, manifest);
|
return this.CreateContentPack(directoryPath, manifest);
|
||||||
|
|
|
@ -3,11 +3,11 @@ using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using StardewModdingAPI.Framework.Exceptions;
|
|
||||||
using StardewModdingAPI.Framework.ModData;
|
using StardewModdingAPI.Framework.ModData;
|
||||||
using StardewModdingAPI.Framework.Models;
|
using StardewModdingAPI.Framework.Models;
|
||||||
using StardewModdingAPI.Framework.Serialisation;
|
using StardewModdingAPI.Toolkit.Serialisation;
|
||||||
using StardewModdingAPI.Toolkit.Utilities;
|
using StardewModdingAPI.Toolkit.Utilities;
|
||||||
|
using ToolkitManifest = StardewModdingAPI.Toolkit.Serialisation.Models.Manifest;
|
||||||
|
|
||||||
namespace StardewModdingAPI.Framework.ModLoading
|
namespace StardewModdingAPI.Framework.ModLoading
|
||||||
{
|
{
|
||||||
|
@ -28,25 +28,28 @@ namespace StardewModdingAPI.Framework.ModLoading
|
||||||
{
|
{
|
||||||
// read file
|
// read file
|
||||||
Manifest manifest = null;
|
Manifest manifest = null;
|
||||||
string path = Path.Combine(modDir.FullName, "manifest.json");
|
|
||||||
string error = null;
|
string error = null;
|
||||||
try
|
|
||||||
{
|
{
|
||||||
manifest = jsonHelper.ReadJsonFile<Manifest>(path);
|
string path = Path.Combine(modDir.FullName, "manifest.json");
|
||||||
if (manifest == null)
|
try
|
||||||
{
|
{
|
||||||
error = File.Exists(path)
|
ToolkitManifest rawManifest = jsonHelper.ReadJsonFile<ToolkitManifest>(path);
|
||||||
? "its manifest is invalid."
|
if (rawManifest == null)
|
||||||
: "it doesn't have a manifest.";
|
{
|
||||||
|
error = File.Exists(path)
|
||||||
|
? "its manifest is invalid."
|
||||||
|
: "it doesn't have a manifest.";
|
||||||
|
}
|
||||||
|
manifest = new Manifest(rawManifest);
|
||||||
|
}
|
||||||
|
catch (SParseException ex)
|
||||||
|
{
|
||||||
|
error = $"parsing its manifest failed: {ex.Message}";
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
error = $"parsing its manifest failed:\n{ex.GetLogSummary()}";
|
||||||
}
|
}
|
||||||
}
|
|
||||||
catch (SParseException ex)
|
|
||||||
{
|
|
||||||
error = $"parsing its manifest failed: {ex.Message}";
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
error = $"parsing its manifest failed:\n{ex.GetLogSummary()}";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// parse internal data record (if any)
|
// parse internal data record (if any)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using StardewModdingAPI.Framework.Serialisation.SmapiConverters;
|
|
||||||
|
|
||||||
namespace StardewModdingAPI.Framework.Models
|
namespace StardewModdingAPI.Framework.Models
|
||||||
{
|
{
|
||||||
|
@ -11,39 +11,87 @@ namespace StardewModdingAPI.Framework.Models
|
||||||
** Accessors
|
** Accessors
|
||||||
*********/
|
*********/
|
||||||
/// <summary>The mod name.</summary>
|
/// <summary>The mod name.</summary>
|
||||||
public string Name { get; set; }
|
public string Name { get; }
|
||||||
|
|
||||||
/// <summary>A brief description of the mod.</summary>
|
/// <summary>A brief description of the mod.</summary>
|
||||||
public string Description { get; set; }
|
public string Description { get; }
|
||||||
|
|
||||||
/// <summary>The mod author's name.</summary>
|
/// <summary>The mod author's name.</summary>
|
||||||
public string Author { get; set; }
|
public string Author { get; }
|
||||||
|
|
||||||
/// <summary>The mod version.</summary>
|
/// <summary>The mod version.</summary>
|
||||||
public ISemanticVersion Version { get; set; }
|
public ISemanticVersion Version { get; }
|
||||||
|
|
||||||
/// <summary>The minimum SMAPI version required by this mod, if any.</summary>
|
/// <summary>The minimum SMAPI version required by this mod, if any.</summary>
|
||||||
public ISemanticVersion MinimumApiVersion { get; set; }
|
public ISemanticVersion MinimumApiVersion { get; }
|
||||||
|
|
||||||
/// <summary>The name of the DLL in the directory that has the <see cref="IMod.Entry"/> method. Mutually exclusive with <see cref="ContentPackFor"/>.</summary>
|
/// <summary>The name of the DLL in the directory that has the <see cref="IMod.Entry"/> method. Mutually exclusive with <see cref="ContentPackFor"/>.</summary>
|
||||||
public string EntryDll { get; set; }
|
public string EntryDll { get; }
|
||||||
|
|
||||||
/// <summary>The mod which will read this as a content pack. Mutually exclusive with <see cref="IManifest.EntryDll"/>.</summary>
|
/// <summary>The mod which will read this as a content pack. Mutually exclusive with <see cref="IManifest.EntryDll"/>.</summary>
|
||||||
[JsonConverter(typeof(ManifestContentPackForConverter))]
|
public IManifestContentPackFor ContentPackFor { get; }
|
||||||
public IManifestContentPackFor ContentPackFor { get; set; }
|
|
||||||
|
|
||||||
/// <summary>The other mods that must be loaded before this mod.</summary>
|
/// <summary>The other mods that must be loaded before this mod.</summary>
|
||||||
[JsonConverter(typeof(ManifestDependencyArrayConverter))]
|
public IManifestDependency[] Dependencies { get; }
|
||||||
public IManifestDependency[] Dependencies { get; set; }
|
|
||||||
|
|
||||||
/// <summary>The namespaced mod IDs to query for updates (like <c>Nexus:541</c>).</summary>
|
/// <summary>The namespaced mod IDs to query for updates (like <c>Nexus:541</c>).</summary>
|
||||||
public string[] UpdateKeys { get; set; }
|
public string[] UpdateKeys { get; set; }
|
||||||
|
|
||||||
/// <summary>The unique mod ID.</summary>
|
/// <summary>The unique mod ID.</summary>
|
||||||
public string UniqueID { get; set; }
|
public string UniqueID { get; }
|
||||||
|
|
||||||
/// <summary>Any manifest fields which didn't match a valid field.</summary>
|
/// <summary>Any manifest fields which didn't match a valid field.</summary>
|
||||||
[JsonExtensionData]
|
[JsonExtensionData]
|
||||||
public IDictionary<string, object> ExtraFields { get; set; }
|
public IDictionary<string, object> ExtraFields { get; }
|
||||||
|
|
||||||
|
|
||||||
|
/*********
|
||||||
|
** Public methods
|
||||||
|
*********/
|
||||||
|
/// <summary>Construct an instance.</summary>
|
||||||
|
/// <param name="manifest">The toolkit manifest.</param>
|
||||||
|
public Manifest(Toolkit.Serialisation.Models.Manifest manifest)
|
||||||
|
: this(
|
||||||
|
uniqueID: manifest.UniqueID,
|
||||||
|
name: manifest.Name,
|
||||||
|
author: manifest.Author,
|
||||||
|
description: manifest.Description,
|
||||||
|
version: manifest.Version != null ? new SemanticVersion(manifest.Version) : null,
|
||||||
|
entryDll: manifest.EntryDll,
|
||||||
|
minimumApiVersion: manifest.MinimumApiVersion != null ? new SemanticVersion(manifest.MinimumApiVersion) : null,
|
||||||
|
contentPackFor: manifest.ContentPackFor != null ? new ManifestContentPackFor(manifest.ContentPackFor) : null,
|
||||||
|
dependencies: manifest.Dependencies?.Select(p => p != null ? (IManifestDependency)new ManifestDependency(p) : null).ToArray(),
|
||||||
|
updateKeys: manifest.UpdateKeys,
|
||||||
|
extraFields: manifest.ExtraFields
|
||||||
|
)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
/// <summary>Construct an instance for a transitional content pack.</summary>
|
||||||
|
/// <param name="uniqueID">The unique mod ID.</param>
|
||||||
|
/// <param name="name">The mod name.</param>
|
||||||
|
/// <param name="author">The mod author's name.</param>
|
||||||
|
/// <param name="description">A brief description of the mod.</param>
|
||||||
|
/// <param name="version">The mod version.</param>
|
||||||
|
/// <param name="entryDll">The name of the DLL in the directory that has the <see cref="IMod.Entry"/> method. Mutually exclusive with <paramref name="contentPackFor"/>.</param>
|
||||||
|
/// <param name="minimumApiVersion">The minimum SMAPI version required by this mod, if any.</param>
|
||||||
|
/// <param name="contentPackFor">The modID which will read this as a content pack. Mutually exclusive with <paramref name="entryDll"/>.</param>
|
||||||
|
/// <param name="dependencies">The other mods that must be loaded before this mod.</param>
|
||||||
|
/// <param name="updateKeys">The namespaced mod IDs to query for updates (like <c>Nexus:541</c>).</param>
|
||||||
|
/// <param name="extraFields">Any manifest fields which didn't match a valid field.</param>
|
||||||
|
public Manifest(string uniqueID, string name, string author, string description, ISemanticVersion version, string entryDll = null, ISemanticVersion minimumApiVersion = null, IManifestContentPackFor contentPackFor = null, IManifestDependency[] dependencies = null, string[] updateKeys = null, IDictionary<string, object> extraFields = null)
|
||||||
|
{
|
||||||
|
this.Name = name;
|
||||||
|
this.Author = author;
|
||||||
|
this.Description = description;
|
||||||
|
this.Version = version;
|
||||||
|
this.UniqueID = uniqueID;
|
||||||
|
this.UpdateKeys = new string[0];
|
||||||
|
this.EntryDll = entryDll;
|
||||||
|
this.ContentPackFor = contentPackFor;
|
||||||
|
this.MinimumApiVersion = minimumApiVersion;
|
||||||
|
this.Dependencies = dependencies ?? new IManifestDependency[0];
|
||||||
|
this.UpdateKeys = updateKeys ?? new string[0];
|
||||||
|
this.ExtraFields = extraFields;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,9 +7,30 @@ namespace StardewModdingAPI.Framework.Models
|
||||||
** Accessors
|
** Accessors
|
||||||
*********/
|
*********/
|
||||||
/// <summary>The unique ID of the mod which can read this content pack.</summary>
|
/// <summary>The unique ID of the mod which can read this content pack.</summary>
|
||||||
public string UniqueID { get; set; }
|
public string UniqueID { get; }
|
||||||
|
|
||||||
/// <summary>The minimum required version (if any).</summary>
|
/// <summary>The minimum required version (if any).</summary>
|
||||||
public ISemanticVersion MinimumVersion { get; set; }
|
public ISemanticVersion MinimumVersion { get; }
|
||||||
|
|
||||||
|
|
||||||
|
/*********
|
||||||
|
** Public methods
|
||||||
|
*********/
|
||||||
|
/// <summary>Construct an instance.</summary>
|
||||||
|
/// <param name="contentPackFor">The toolkit instance.</param>
|
||||||
|
public ManifestContentPackFor(Toolkit.Serialisation.Models.ManifestContentPackFor contentPackFor)
|
||||||
|
{
|
||||||
|
this.UniqueID = contentPackFor.UniqueID;
|
||||||
|
this.MinimumVersion = new SemanticVersion(contentPackFor.MinimumVersion);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Construct an instance.</summary>
|
||||||
|
/// <param name="uniqueID">The unique ID of the mod which can read this content pack.</param>
|
||||||
|
/// <param name="minimumVersion">The minimum required version (if any).</param>
|
||||||
|
public ManifestContentPackFor(string uniqueID, ISemanticVersion minimumVersion = null)
|
||||||
|
{
|
||||||
|
this.UniqueID = uniqueID;
|
||||||
|
this.MinimumVersion = minimumVersion;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,18 +7,23 @@ namespace StardewModdingAPI.Framework.Models
|
||||||
** Accessors
|
** Accessors
|
||||||
*********/
|
*********/
|
||||||
/// <summary>The unique mod ID to require.</summary>
|
/// <summary>The unique mod ID to require.</summary>
|
||||||
public string UniqueID { get; set; }
|
public string UniqueID { get; }
|
||||||
|
|
||||||
/// <summary>The minimum required version (if any).</summary>
|
/// <summary>The minimum required version (if any).</summary>
|
||||||
public ISemanticVersion MinimumVersion { get; set; }
|
public ISemanticVersion MinimumVersion { get; }
|
||||||
|
|
||||||
/// <summary>Whether the dependency must be installed to use the mod.</summary>
|
/// <summary>Whether the dependency must be installed to use the mod.</summary>
|
||||||
public bool IsRequired { get; set; }
|
public bool IsRequired { get; }
|
||||||
|
|
||||||
|
|
||||||
/*********
|
/*********
|
||||||
** Public methods
|
** Public methods
|
||||||
*********/
|
*********/
|
||||||
|
/// <summary>Construct an instance.</summary>
|
||||||
|
/// <param name="dependency">The toolkit instance.</param>
|
||||||
|
public ManifestDependency(Toolkit.Serialisation.Models.ManifestDependency dependency)
|
||||||
|
: this(dependency.UniqueID, dependency.MinimumVersion?.ToString(), dependency.IsRequired) { }
|
||||||
|
|
||||||
/// <summary>Construct an instance.</summary>
|
/// <summary>Construct an instance.</summary>
|
||||||
/// <param name="uniqueID">The unique mod ID to require.</param>
|
/// <param name="uniqueID">The unique mod ID to require.</param>
|
||||||
/// <param name="minimumVersion">The minimum required version (if any).</param>
|
/// <param name="minimumVersion">The minimum required version (if any).</param>
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
using System;
|
using System;
|
||||||
using Microsoft.Xna.Framework;
|
using Microsoft.Xna.Framework;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
using StardewModdingAPI.Framework.Exceptions;
|
using StardewModdingAPI.Toolkit.Serialisation;
|
||||||
|
using StardewModdingAPI.Toolkit.Serialisation.Converters;
|
||||||
|
|
||||||
namespace StardewModdingAPI.Framework.Serialisation.CrossplatformConverters
|
namespace StardewModdingAPI.Framework.Serialisation
|
||||||
{
|
{
|
||||||
/// <summary>Handles deserialisation of <see cref="Color"/> for crossplatform compatibility.</summary>
|
/// <summary>Handles deserialisation of <see cref="Color"/> for crossplatform compatibility.</summary>
|
||||||
/// <remarks>
|
/// <remarks>
|
|
@ -1,9 +1,10 @@
|
||||||
using System;
|
using System;
|
||||||
using Microsoft.Xna.Framework;
|
using Microsoft.Xna.Framework;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
using StardewModdingAPI.Framework.Exceptions;
|
using StardewModdingAPI.Toolkit.Serialisation;
|
||||||
|
using StardewModdingAPI.Toolkit.Serialisation.Converters;
|
||||||
|
|
||||||
namespace StardewModdingAPI.Framework.Serialisation.CrossplatformConverters
|
namespace StardewModdingAPI.Framework.Serialisation
|
||||||
{
|
{
|
||||||
/// <summary>Handles deserialisation of <see cref="PointConverter"/> for crossplatform compatibility.</summary>
|
/// <summary>Handles deserialisation of <see cref="PointConverter"/> for crossplatform compatibility.</summary>
|
||||||
/// <remarks>
|
/// <remarks>
|
|
@ -2,9 +2,10 @@ using System;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using Microsoft.Xna.Framework;
|
using Microsoft.Xna.Framework;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
using StardewModdingAPI.Framework.Exceptions;
|
using StardewModdingAPI.Toolkit.Serialisation;
|
||||||
|
using StardewModdingAPI.Toolkit.Serialisation.Converters;
|
||||||
|
|
||||||
namespace StardewModdingAPI.Framework.Serialisation.CrossplatformConverters
|
namespace StardewModdingAPI.Framework.Serialisation
|
||||||
{
|
{
|
||||||
/// <summary>Handles deserialisation of <see cref="Rectangle"/> for crossplatform compatibility.</summary>
|
/// <summary>Handles deserialisation of <see cref="Rectangle"/> for crossplatform compatibility.</summary>
|
||||||
/// <remarks>
|
/// <remarks>
|
|
@ -36,7 +36,7 @@ namespace StardewModdingAPI
|
||||||
IManifestDependency[] Dependencies { get; }
|
IManifestDependency[] Dependencies { get; }
|
||||||
|
|
||||||
/// <summary>The namespaced mod IDs to query for updates (like <c>Nexus:541</c>).</summary>
|
/// <summary>The namespaced mod IDs to query for updates (like <c>Nexus:541</c>).</summary>
|
||||||
string[] UpdateKeys { get; set; }
|
string[] UpdateKeys { get; }
|
||||||
|
|
||||||
/// <summary>Any manifest fields which didn't match a valid field.</summary>
|
/// <summary>Any manifest fields which didn't match a valid field.</summary>
|
||||||
IDictionary<string, object> ExtraFields { get; }
|
IDictionary<string, object> ExtraFields { get; }
|
||||||
|
|
|
@ -10,6 +10,7 @@ using System.Runtime.ExceptionServices;
|
||||||
using System.Security;
|
using System.Security;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
using Microsoft.Xna.Framework.Input;
|
||||||
#if SMAPI_FOR_WINDOWS
|
#if SMAPI_FOR_WINDOWS
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
#endif
|
#endif
|
||||||
|
@ -27,8 +28,11 @@ using StardewModdingAPI.Framework.Reflection;
|
||||||
using StardewModdingAPI.Framework.Serialisation;
|
using StardewModdingAPI.Framework.Serialisation;
|
||||||
using StardewModdingAPI.Internal;
|
using StardewModdingAPI.Internal;
|
||||||
using StardewModdingAPI.Toolkit.Framework.Clients.WebApi;
|
using StardewModdingAPI.Toolkit.Framework.Clients.WebApi;
|
||||||
|
using StardewModdingAPI.Toolkit.Serialisation;
|
||||||
|
using StardewModdingAPI.Toolkit.Serialisation.Converters;
|
||||||
using StardewModdingAPI.Toolkit.Utilities;
|
using StardewModdingAPI.Toolkit.Utilities;
|
||||||
using StardewValley;
|
using StardewValley;
|
||||||
|
using Keys = System.Windows.Forms.Keys;
|
||||||
using Monitor = StardewModdingAPI.Framework.Monitor;
|
using Monitor = StardewModdingAPI.Framework.Monitor;
|
||||||
using SObject = StardewValley.Object;
|
using SObject = StardewValley.Object;
|
||||||
using ThreadState = System.Threading.ThreadState;
|
using ThreadState = System.Threading.ThreadState;
|
||||||
|
@ -148,6 +152,18 @@ namespace StardewModdingAPI
|
||||||
};
|
};
|
||||||
this.EventManager = new EventManager(this.Monitor, this.ModRegistry);
|
this.EventManager = new EventManager(this.Monitor, this.ModRegistry);
|
||||||
|
|
||||||
|
// init JSON parser
|
||||||
|
JsonConverter[] converters = {
|
||||||
|
new StringEnumConverter<Buttons>(),
|
||||||
|
new StringEnumConverter<Keys>(),
|
||||||
|
new StringEnumConverter<SButton>(),
|
||||||
|
new ColorConverter(),
|
||||||
|
new PointConverter(),
|
||||||
|
new RectangleConverter()
|
||||||
|
};
|
||||||
|
foreach (JsonConverter converter in converters)
|
||||||
|
this.JsonHelper.JsonSettings.Converters.Add(converter);
|
||||||
|
|
||||||
// hook up events
|
// hook up events
|
||||||
ContentEvents.Init(this.EventManager);
|
ContentEvents.Init(this.EventManager);
|
||||||
ControlEvents.Init(this.EventManager);
|
ControlEvents.Init(this.EventManager);
|
||||||
|
@ -1093,7 +1109,7 @@ namespace StardewModdingAPI
|
||||||
/// <param name="mods">The mods for which to reload translations.</param>
|
/// <param name="mods">The mods for which to reload translations.</param>
|
||||||
private void ReloadTranslations(IEnumerable<IModMetadata> mods)
|
private void ReloadTranslations(IEnumerable<IModMetadata> mods)
|
||||||
{
|
{
|
||||||
JsonHelper jsonHelper = new JsonHelper();
|
JsonHelper jsonHelper = this.JsonHelper;
|
||||||
foreach (IModMetadata metadata in mods)
|
foreach (IModMetadata metadata in mods)
|
||||||
{
|
{
|
||||||
if (metadata.IsContentPack)
|
if (metadata.IsContentPack)
|
||||||
|
|
|
@ -103,6 +103,9 @@
|
||||||
<Compile Include="Framework\ContentManagers\GameContentManager.cs" />
|
<Compile Include="Framework\ContentManagers\GameContentManager.cs" />
|
||||||
<Compile Include="Framework\ContentManagers\IContentManager.cs" />
|
<Compile Include="Framework\ContentManagers\IContentManager.cs" />
|
||||||
<Compile Include="Framework\ContentManagers\ModContentManager.cs" />
|
<Compile Include="Framework\ContentManagers\ModContentManager.cs" />
|
||||||
|
<Compile Include="Framework\Serialisation\ColorConverter.cs" />
|
||||||
|
<Compile Include="Framework\Serialisation\PointConverter.cs" />
|
||||||
|
<Compile Include="Framework\Serialisation\RectangleConverter.cs" />
|
||||||
<Compile Include="Framework\Events\ModEventsBase.cs" />
|
<Compile Include="Framework\Events\ModEventsBase.cs" />
|
||||||
<Compile Include="Framework\Events\EventManager.cs" />
|
<Compile Include="Framework\Events\EventManager.cs" />
|
||||||
<Compile Include="Events\IModEvents.cs" />
|
<Compile Include="Events\IModEvents.cs" />
|
||||||
|
@ -114,16 +117,17 @@
|
||||||
<Compile Include="Framework\Events\ModEvents.cs" />
|
<Compile Include="Framework\Events\ModEvents.cs" />
|
||||||
<Compile Include="Framework\Events\ModInputEvents.cs" />
|
<Compile Include="Framework\Events\ModInputEvents.cs" />
|
||||||
<Compile Include="Framework\Input\GamePadStateBuilder.cs" />
|
<Compile Include="Framework\Input\GamePadStateBuilder.cs" />
|
||||||
|
<Compile Include="Framework\Models\Manifest.cs" />
|
||||||
|
<Compile Include="Framework\Models\ManifestContentPackFor.cs" />
|
||||||
|
<Compile Include="Framework\Models\ManifestDependency.cs" />
|
||||||
<Compile Include="Framework\ModHelpers\InputHelper.cs" />
|
<Compile Include="Framework\ModHelpers\InputHelper.cs" />
|
||||||
<Compile Include="IInputHelper.cs" />
|
<Compile Include="IInputHelper.cs" />
|
||||||
<Compile Include="Framework\Input\SInputState.cs" />
|
<Compile Include="Framework\Input\SInputState.cs" />
|
||||||
<Compile Include="Framework\Input\InputStatus.cs" />
|
<Compile Include="Framework\Input\InputStatus.cs" />
|
||||||
<Compile Include="Framework\LegacyManifestVersion.cs" />
|
|
||||||
<Compile Include="Framework\ModData\ModDatabase.cs" />
|
<Compile Include="Framework\ModData\ModDatabase.cs" />
|
||||||
<Compile Include="Framework\ModData\ModDataField.cs" />
|
<Compile Include="Framework\ModData\ModDataField.cs" />
|
||||||
<Compile Include="Framework\ModData\ModDataFieldKey.cs" />
|
<Compile Include="Framework\ModData\ModDataFieldKey.cs" />
|
||||||
<Compile Include="Framework\ModData\ParsedModDataRecord.cs" />
|
<Compile Include="Framework\ModData\ParsedModDataRecord.cs" />
|
||||||
<Compile Include="Framework\Models\ManifestContentPackFor.cs" />
|
|
||||||
<Compile Include="Framework\Models\SMetadata.cs" />
|
<Compile Include="Framework\Models\SMetadata.cs" />
|
||||||
<Compile Include="Framework\ModHelpers\MultiplayerHelper.cs" />
|
<Compile Include="Framework\ModHelpers\MultiplayerHelper.cs" />
|
||||||
<Compile Include="Framework\ModLoading\Finders\EventFinder.cs" />
|
<Compile Include="Framework\ModLoading\Finders\EventFinder.cs" />
|
||||||
|
@ -151,13 +155,6 @@
|
||||||
<Compile Include="Framework\Reflection\InterfaceProxyBuilder.cs" />
|
<Compile Include="Framework\Reflection\InterfaceProxyBuilder.cs" />
|
||||||
<Compile Include="Framework\Reflection\InterfaceProxyFactory.cs" />
|
<Compile Include="Framework\Reflection\InterfaceProxyFactory.cs" />
|
||||||
<Compile Include="Framework\RewriteFacades\SpriteBatchMethods.cs" />
|
<Compile Include="Framework\RewriteFacades\SpriteBatchMethods.cs" />
|
||||||
<Compile Include="Framework\Serialisation\SmapiConverters\ManifestContentPackForConverter.cs" />
|
|
||||||
<Compile Include="Framework\Serialisation\SmapiConverters\ManifestDependencyArrayConverter.cs" />
|
|
||||||
<Compile Include="Framework\Serialisation\SmapiConverters\SemanticVersionConverter.cs" />
|
|
||||||
<Compile Include="Framework\Serialisation\SimpleReadOnlyConverter.cs" />
|
|
||||||
<Compile Include="Framework\Serialisation\CrossplatformConverters\RectangleConverter.cs" />
|
|
||||||
<Compile Include="Framework\Serialisation\CrossplatformConverters\ColorConverter.cs" />
|
|
||||||
<Compile Include="Framework\Serialisation\CrossplatformConverters\PointConverter.cs" />
|
|
||||||
<Compile Include="Framework\SMultiplayer.cs" />
|
<Compile Include="Framework\SMultiplayer.cs" />
|
||||||
<Compile Include="Framework\StateTracking\Comparers\EquatableComparer.cs" />
|
<Compile Include="Framework\StateTracking\Comparers\EquatableComparer.cs" />
|
||||||
<Compile Include="Framework\StateTracking\Comparers\ObjectReferenceComparer.cs" />
|
<Compile Include="Framework\StateTracking\Comparers\ObjectReferenceComparer.cs" />
|
||||||
|
@ -235,16 +232,12 @@
|
||||||
<Compile Include="Context.cs" />
|
<Compile Include="Context.cs" />
|
||||||
<Compile Include="Framework\Logging\ConsoleInterceptionManager.cs" />
|
<Compile Include="Framework\Logging\ConsoleInterceptionManager.cs" />
|
||||||
<Compile Include="Framework\Logging\InterceptingTextWriter.cs" />
|
<Compile Include="Framework\Logging\InterceptingTextWriter.cs" />
|
||||||
<Compile Include="Framework\Models\ManifestDependency.cs" />
|
|
||||||
<Compile Include="Framework\ModData\ModStatus.cs" />
|
<Compile Include="Framework\ModData\ModStatus.cs" />
|
||||||
<Compile Include="Framework\Models\SConfig.cs" />
|
<Compile Include="Framework\Models\SConfig.cs" />
|
||||||
<Compile Include="Framework\ModLoading\ModMetadata.cs" />
|
<Compile Include="Framework\ModLoading\ModMetadata.cs" />
|
||||||
<Compile Include="Framework\Reflection\ReflectedProperty.cs" />
|
<Compile Include="Framework\Reflection\ReflectedProperty.cs" />
|
||||||
<Compile Include="Framework\RequestExitDelegate.cs" />
|
<Compile Include="Framework\RequestExitDelegate.cs" />
|
||||||
<Compile Include="Framework\ContentCoordinator.cs" />
|
<Compile Include="Framework\ContentCoordinator.cs" />
|
||||||
<Compile Include="Framework\Exceptions\SParseException.cs" />
|
|
||||||
<Compile Include="Framework\Serialisation\JsonHelper.cs" />
|
|
||||||
<Compile Include="Framework\Serialisation\SmapiConverters\StringEnumConverter.cs" />
|
|
||||||
<Compile Include="IAssetEditor.cs" />
|
<Compile Include="IAssetEditor.cs" />
|
||||||
<Compile Include="IAssetInfo.cs" />
|
<Compile Include="IAssetInfo.cs" />
|
||||||
<Compile Include="IAssetLoader.cs" />
|
<Compile Include="IAssetLoader.cs" />
|
||||||
|
@ -283,7 +276,6 @@
|
||||||
<Compile Include="Events\ChangeType.cs" />
|
<Compile Include="Events\ChangeType.cs" />
|
||||||
<Compile Include="Events\ItemStackChange.cs" />
|
<Compile Include="Events\ItemStackChange.cs" />
|
||||||
<Compile Include="Framework\Monitor.cs" />
|
<Compile Include="Framework\Monitor.cs" />
|
||||||
<Compile Include="Framework\Models\Manifest.cs" />
|
|
||||||
<Compile Include="Metadata\InstructionMetadata.cs" />
|
<Compile Include="Metadata\InstructionMetadata.cs" />
|
||||||
<Compile Include="Mod.cs" />
|
<Compile Include="Mod.cs" />
|
||||||
<Compile Include="PatchMode.cs" />
|
<Compile Include="PatchMode.cs" />
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
using System;
|
using System;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using StardewModdingAPI.Framework.Models;
|
using StardewModdingAPI.Toolkit.Serialisation.Models;
|
||||||
|
|
||||||
namespace StardewModdingAPI.Framework.Serialisation.SmapiConverters
|
namespace StardewModdingAPI.Toolkit.Serialisation.Converters
|
||||||
{
|
{
|
||||||
/// <summary>Handles deserialisation of <see cref="IManifestContentPackFor"/> arrays.</summary>
|
/// <summary>Handles deserialisation of <see cref="ManifestContentPackFor"/> arrays.</summary>
|
||||||
internal class ManifestContentPackForConverter : JsonConverter
|
public class ManifestContentPackForConverter : JsonConverter
|
||||||
{
|
{
|
||||||
/*********
|
/*********
|
||||||
** Accessors
|
** Accessors
|
||||||
|
@ -21,7 +21,7 @@ namespace StardewModdingAPI.Framework.Serialisation.SmapiConverters
|
||||||
/// <param name="objectType">The object type.</param>
|
/// <param name="objectType">The object type.</param>
|
||||||
public override bool CanConvert(Type objectType)
|
public override bool CanConvert(Type objectType)
|
||||||
{
|
{
|
||||||
return objectType == typeof(IManifestContentPackFor[]);
|
return objectType == typeof(ManifestContentPackFor[]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,11 +2,11 @@ using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
using StardewModdingAPI.Framework.Models;
|
using StardewModdingAPI.Toolkit.Serialisation.Models;
|
||||||
|
|
||||||
namespace StardewModdingAPI.Framework.Serialisation.SmapiConverters
|
namespace StardewModdingAPI.Toolkit.Serialisation.Converters
|
||||||
{
|
{
|
||||||
/// <summary>Handles deserialisation of <see cref="IManifestDependency"/> arrays.</summary>
|
/// <summary>Handles deserialisation of <see cref="ManifestDependency"/> arrays.</summary>
|
||||||
internal class ManifestDependencyArrayConverter : JsonConverter
|
internal class ManifestDependencyArrayConverter : JsonConverter
|
||||||
{
|
{
|
||||||
/*********
|
/*********
|
||||||
|
@ -23,7 +23,7 @@ namespace StardewModdingAPI.Framework.Serialisation.SmapiConverters
|
||||||
/// <param name="objectType">The object type.</param>
|
/// <param name="objectType">The object type.</param>
|
||||||
public override bool CanConvert(Type objectType)
|
public override bool CanConvert(Type objectType)
|
||||||
{
|
{
|
||||||
return objectType == typeof(IManifestDependency[]);
|
return objectType == typeof(ManifestDependency[]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -37,12 +37,12 @@ namespace StardewModdingAPI.Framework.Serialisation.SmapiConverters
|
||||||
/// <param name="serializer">The calling serializer.</param>
|
/// <param name="serializer">The calling serializer.</param>
|
||||||
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
|
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
|
||||||
{
|
{
|
||||||
List<IManifestDependency> result = new List<IManifestDependency>();
|
List<ManifestDependency> result = new List<ManifestDependency>();
|
||||||
foreach (JObject obj in JArray.Load(reader).Children<JObject>())
|
foreach (JObject obj in JArray.Load(reader).Children<JObject>())
|
||||||
{
|
{
|
||||||
string uniqueID = obj.ValueIgnoreCase<string>(nameof(IManifestDependency.UniqueID));
|
string uniqueID = obj.ValueIgnoreCase<string>(nameof(ManifestDependency.UniqueID));
|
||||||
string minVersion = obj.ValueIgnoreCase<string>(nameof(IManifestDependency.MinimumVersion));
|
string minVersion = obj.ValueIgnoreCase<string>(nameof(ManifestDependency.MinimumVersion));
|
||||||
bool required = obj.ValueIgnoreCase<bool?>(nameof(IManifestDependency.IsRequired)) ?? true;
|
bool required = obj.ValueIgnoreCase<bool?>(nameof(ManifestDependency.IsRequired)) ?? true;
|
||||||
result.Add(new ManifestDependency(uniqueID, minVersion, required));
|
result.Add(new ManifestDependency(uniqueID, minVersion, required));
|
||||||
}
|
}
|
||||||
return result.ToArray();
|
return result.ToArray();
|
|
@ -1,10 +1,10 @@
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
using StardewModdingAPI.Framework.Exceptions;
|
using StardewModdingAPI.Toolkit.Serialisation.Models;
|
||||||
|
|
||||||
namespace StardewModdingAPI.Framework.Serialisation.SmapiConverters
|
namespace StardewModdingAPI.Toolkit.Serialisation.Converters
|
||||||
{
|
{
|
||||||
/// <summary>Handles deserialisation of <see cref="SemanticVersion"/>.</summary>
|
/// <summary>Handles deserialisation of <see cref="SemanticVersion"/>.</summary>
|
||||||
internal class SemanticVersionConverter : SimpleReadOnlyConverter<ISemanticVersion>
|
internal class SemanticVersionConverter : SimpleReadOnlyConverter<SemanticVersion>
|
||||||
{
|
{
|
||||||
/*********
|
/*********
|
||||||
** Protected methods
|
** Protected methods
|
||||||
|
@ -12,25 +12,25 @@ namespace StardewModdingAPI.Framework.Serialisation.SmapiConverters
|
||||||
/// <summary>Read a JSON object.</summary>
|
/// <summary>Read a JSON object.</summary>
|
||||||
/// <param name="obj">The JSON object to read.</param>
|
/// <param name="obj">The JSON object to read.</param>
|
||||||
/// <param name="path">The path to the current JSON node.</param>
|
/// <param name="path">The path to the current JSON node.</param>
|
||||||
protected override ISemanticVersion ReadObject(JObject obj, string path)
|
protected override SemanticVersion ReadObject(JObject obj, string path)
|
||||||
{
|
{
|
||||||
int major = obj.ValueIgnoreCase<int>(nameof(ISemanticVersion.MajorVersion));
|
int major = obj.ValueIgnoreCase<int>("MajorVersion");
|
||||||
int minor = obj.ValueIgnoreCase<int>(nameof(ISemanticVersion.MinorVersion));
|
int minor = obj.ValueIgnoreCase<int>("MinorVersion");
|
||||||
int patch = obj.ValueIgnoreCase<int>(nameof(ISemanticVersion.PatchVersion));
|
int patch = obj.ValueIgnoreCase<int>("PatchVersion");
|
||||||
string build = obj.ValueIgnoreCase<string>(nameof(ISemanticVersion.Build));
|
string build = obj.ValueIgnoreCase<string>("Build");
|
||||||
return new LegacyManifestVersion(major, minor, patch, build);
|
return new LegacyManifestVersion(major, minor, patch, build);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Read a JSON string.</summary>
|
/// <summary>Read a JSON string.</summary>
|
||||||
/// <param name="str">The JSON string value.</param>
|
/// <param name="str">The JSON string value.</param>
|
||||||
/// <param name="path">The path to the current JSON node.</param>
|
/// <param name="path">The path to the current JSON node.</param>
|
||||||
protected override ISemanticVersion ReadString(string str, string path)
|
protected override SemanticVersion ReadString(string str, string path)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(str))
|
if (string.IsNullOrWhiteSpace(str))
|
||||||
return null;
|
return null;
|
||||||
if (!SemanticVersion.TryParse(str, out ISemanticVersion version))
|
if (!SemanticVersion.TryParse(str, out ISemanticVersion version))
|
||||||
throw new SParseException($"Can't parse semantic version from invalid value '{str}', should be formatted like 1.2, 1.2.30, or 1.2.30-beta (path: {path}).");
|
throw new SParseException($"Can't parse semantic version from invalid value '{str}', should be formatted like 1.2, 1.2.30, or 1.2.30-beta (path: {path}).");
|
||||||
return version;
|
return (SemanticVersion)version;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,9 +1,8 @@
|
||||||
using System;
|
using System;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
using StardewModdingAPI.Framework.Exceptions;
|
|
||||||
|
|
||||||
namespace StardewModdingAPI.Framework.Serialisation
|
namespace StardewModdingAPI.Toolkit.Serialisation.Converters
|
||||||
{
|
{
|
||||||
/// <summary>The base implementation for simplified converters which deserialise <typeparamref name="T"/> without overriding serialisation.</summary>
|
/// <summary>The base implementation for simplified converters which deserialise <typeparamref name="T"/> without overriding serialisation.</summary>
|
||||||
/// <typeparam name="T">The type to deserialise.</typeparam>
|
/// <typeparam name="T">The type to deserialise.</typeparam>
|
|
@ -1,7 +1,7 @@
|
||||||
using System;
|
using System;
|
||||||
using Newtonsoft.Json.Converters;
|
using Newtonsoft.Json.Converters;
|
||||||
|
|
||||||
namespace StardewModdingAPI.Framework.Serialisation.SmapiConverters
|
namespace StardewModdingAPI.Toolkit.Serialisation.Converters
|
||||||
{
|
{
|
||||||
/// <summary>A variant of <see cref="StringEnumConverter"/> which only converts a specified enum.</summary>
|
/// <summary>A variant of <see cref="StringEnumConverter"/> which only converts a specified enum.</summary>
|
||||||
/// <typeparam name="T">The enum type.</typeparam>
|
/// <typeparam name="T">The enum type.</typeparam>
|
|
@ -0,0 +1,21 @@
|
||||||
|
using System;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
|
||||||
|
namespace StardewModdingAPI.Toolkit.Serialisation
|
||||||
|
{
|
||||||
|
/// <summary>Provides extension methods for parsing JSON.</summary>
|
||||||
|
public static class JsonExtensions
|
||||||
|
{
|
||||||
|
/// <summary>Get a JSON field value from a case-insensitive field name. This will check for an exact match first, then search without case sensitivity.</summary>
|
||||||
|
/// <typeparam name="T">The value type.</typeparam>
|
||||||
|
/// <param name="obj">The JSON object to search.</param>
|
||||||
|
/// <param name="fieldName">The field name.</param>
|
||||||
|
public static T ValueIgnoreCase<T>(this JObject obj, string fieldName)
|
||||||
|
{
|
||||||
|
JToken token = obj.GetValue(fieldName, StringComparison.InvariantCultureIgnoreCase);
|
||||||
|
return token != null
|
||||||
|
? token.Value<T>()
|
||||||
|
: default(T);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,39 +1,23 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using Microsoft.Xna.Framework.Input;
|
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using StardewModdingAPI.Framework.Serialisation.CrossplatformConverters;
|
using StardewModdingAPI.Toolkit.Serialisation.Converters;
|
||||||
using StardewModdingAPI.Framework.Serialisation.SmapiConverters;
|
|
||||||
|
|
||||||
namespace StardewModdingAPI.Framework.Serialisation
|
namespace StardewModdingAPI.Toolkit.Serialisation
|
||||||
{
|
{
|
||||||
/// <summary>Encapsulates SMAPI's JSON file parsing.</summary>
|
/// <summary>Encapsulates SMAPI's JSON file parsing.</summary>
|
||||||
internal class JsonHelper
|
public class JsonHelper
|
||||||
{
|
{
|
||||||
/*********
|
/*********
|
||||||
** Accessors
|
** Accessors
|
||||||
*********/
|
*********/
|
||||||
/// <summary>The JSON settings to use when serialising and deserialising files.</summary>
|
/// <summary>The JSON settings to use when serialising and deserialising files.</summary>
|
||||||
private readonly JsonSerializerSettings JsonSettings = new JsonSerializerSettings
|
public JsonSerializerSettings JsonSettings { get; } = new JsonSerializerSettings
|
||||||
{
|
{
|
||||||
Formatting = Formatting.Indented,
|
Formatting = Formatting.Indented,
|
||||||
ObjectCreationHandling = ObjectCreationHandling.Replace, // avoid issue where default ICollection<T> values are duplicated each time the config is loaded
|
ObjectCreationHandling = ObjectCreationHandling.Replace, // avoid issue where default ICollection<T> values are duplicated each time the config is loaded
|
||||||
Converters = new List<JsonConverter>
|
Converters = new List<JsonConverter> { new SemanticVersionConverter() }
|
||||||
{
|
|
||||||
// SMAPI types
|
|
||||||
new SemanticVersionConverter(),
|
|
||||||
|
|
||||||
// enums
|
|
||||||
new StringEnumConverter<Buttons>(),
|
|
||||||
new StringEnumConverter<Keys>(),
|
|
||||||
new StringEnumConverter<SButton>(),
|
|
||||||
|
|
||||||
// crossplatform compatibility
|
|
||||||
new ColorConverter(),
|
|
||||||
new PointConverter(),
|
|
||||||
new RectangleConverter()
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
namespace StardewModdingAPI.Framework
|
namespace StardewModdingAPI.Toolkit.Serialisation.Models
|
||||||
{
|
{
|
||||||
/// <summary>An implementation of <see cref="ISemanticVersion"/> that hamdles the legacy <see cref="IManifest"/> version format.</summary>
|
/// <summary>An implementation of <see cref="ISemanticVersion"/> that hamdles the legacy <see cref="Manifest"/> version format.</summary>
|
||||||
internal class LegacyManifestVersion : SemanticVersion
|
public class LegacyManifestVersion : SemanticVersion
|
||||||
{
|
{
|
||||||
/*********
|
/*********
|
||||||
** Public methods
|
** Public methods
|
|
@ -0,0 +1,49 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using StardewModdingAPI.Toolkit.Serialisation.Converters;
|
||||||
|
|
||||||
|
namespace StardewModdingAPI.Toolkit.Serialisation.Models
|
||||||
|
{
|
||||||
|
/// <summary>A manifest which describes a mod for SMAPI.</summary>
|
||||||
|
public class Manifest
|
||||||
|
{
|
||||||
|
/*********
|
||||||
|
** Accessors
|
||||||
|
*********/
|
||||||
|
/// <summary>The mod name.</summary>
|
||||||
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
/// <summary>A brief description of the mod.</summary>
|
||||||
|
public string Description { get; set; }
|
||||||
|
|
||||||
|
/// <summary>The mod author's name.</summary>
|
||||||
|
public string Author { get; set; }
|
||||||
|
|
||||||
|
/// <summary>The mod version.</summary>
|
||||||
|
public SemanticVersion Version { get; set; }
|
||||||
|
|
||||||
|
/// <summary>The minimum SMAPI version required by this mod, if any.</summary>
|
||||||
|
public SemanticVersion MinimumApiVersion { get; set; }
|
||||||
|
|
||||||
|
/// <summary>The name of the DLL in the directory that has the <c>Entry</c> method. Mutually exclusive with <see cref="ContentPackFor"/>.</summary>
|
||||||
|
public string EntryDll { get; set; }
|
||||||
|
|
||||||
|
/// <summary>The mod which will read this as a content pack. Mutually exclusive with <see cref="Manifest.EntryDll"/>.</summary>
|
||||||
|
[JsonConverter(typeof(ManifestContentPackForConverter))]
|
||||||
|
public ManifestContentPackFor ContentPackFor { get; set; }
|
||||||
|
|
||||||
|
/// <summary>The other mods that must be loaded before this mod.</summary>
|
||||||
|
[JsonConverter(typeof(ManifestDependencyArrayConverter))]
|
||||||
|
public ManifestDependency[] Dependencies { get; set; }
|
||||||
|
|
||||||
|
/// <summary>The namespaced mod IDs to query for updates (like <c>Nexus:541</c>).</summary>
|
||||||
|
public string[] UpdateKeys { get; set; }
|
||||||
|
|
||||||
|
/// <summary>The unique mod ID.</summary>
|
||||||
|
public string UniqueID { get; set; }
|
||||||
|
|
||||||
|
/// <summary>Any manifest fields which didn't match a valid field.</summary>
|
||||||
|
[JsonExtensionData]
|
||||||
|
public IDictionary<string, object> ExtraFields { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
namespace StardewModdingAPI.Toolkit.Serialisation.Models
|
||||||
|
{
|
||||||
|
/// <summary>Indicates which mod can read the content pack represented by the containing manifest.</summary>
|
||||||
|
public class ManifestContentPackFor
|
||||||
|
{
|
||||||
|
/*********
|
||||||
|
** Accessors
|
||||||
|
*********/
|
||||||
|
/// <summary>The unique ID of the mod which can read this content pack.</summary>
|
||||||
|
public string UniqueID { get; set; }
|
||||||
|
|
||||||
|
/// <summary>The minimum required version (if any).</summary>
|
||||||
|
public SemanticVersion MinimumVersion { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
namespace StardewModdingAPI.Toolkit.Serialisation.Models
|
||||||
|
{
|
||||||
|
/// <summary>A mod dependency listed in a mod manifest.</summary>
|
||||||
|
public class ManifestDependency
|
||||||
|
{
|
||||||
|
/*********
|
||||||
|
** Accessors
|
||||||
|
*********/
|
||||||
|
/// <summary>The unique mod ID to require.</summary>
|
||||||
|
public string UniqueID { get; set; }
|
||||||
|
|
||||||
|
/// <summary>The minimum required version (if any).</summary>
|
||||||
|
public SemanticVersion MinimumVersion { get; set; }
|
||||||
|
|
||||||
|
/// <summary>Whether the dependency must be installed to use the mod.</summary>
|
||||||
|
public bool IsRequired { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
/*********
|
||||||
|
** Public methods
|
||||||
|
*********/
|
||||||
|
/// <summary>Construct an instance.</summary>
|
||||||
|
/// <param name="uniqueID">The unique mod ID to require.</param>
|
||||||
|
/// <param name="minimumVersion">The minimum required version (if any).</param>
|
||||||
|
/// <param name="required">Whether the dependency must be installed to use the mod.</param>
|
||||||
|
public ManifestDependency(string uniqueID, string minimumVersion, bool required = true)
|
||||||
|
{
|
||||||
|
this.UniqueID = uniqueID;
|
||||||
|
this.MinimumVersion = !string.IsNullOrWhiteSpace(minimumVersion)
|
||||||
|
? new SemanticVersion(minimumVersion)
|
||||||
|
: null;
|
||||||
|
this.IsRequired = required;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace StardewModdingAPI.Framework.Exceptions
|
namespace StardewModdingAPI.Toolkit.Serialisation
|
||||||
{
|
{
|
||||||
/// <summary>A format exception which provides a user-facing error message.</summary>
|
/// <summary>A format exception which provides a user-facing error message.</summary>
|
||||||
internal class SParseException : FormatException
|
internal class SParseException : FormatException
|
Loading…
Reference in New Issue