add asset edit priority (#766)

This commit is contained in:
Jesse Plamondon-Willard 2022-03-26 01:43:40 -04:00
parent e40907ab8b
commit ad8912047b
No known key found for this signature in database
GPG Key ID: CF8B1456B3E29F49
6 changed files with 33 additions and 5 deletions

View File

@ -13,7 +13,7 @@
* For mod authors: * For mod authors:
* Added [content events](https://stardewvalleywiki.com/Modding:Modder_Guide/APIs/Events#Content), which will replace `IAssetEditor` and `IAssetLoader` in SMAPI 4.0.0. * Added [content events](https://stardewvalleywiki.com/Modding:Modder_Guide/APIs/Events#Content), which will replace `IAssetEditor` and `IAssetLoader` in SMAPI 4.0.0.
_These include new features not supported by the old API, like load conflict resolution and content pack labels. They also support new cases like easily detecting when an asset has been changed._ _These include new features not supported by the old API like load conflict resolution, edit priority, and content pack labels. They also support new cases like easily detecting when an asset has been changed._
* Overhauled [mod-provided APIs](https://stardewvalleywiki.com/Modding:Modder_Guide/APIs/Integrations#Mod-provided_APIs) (thanks to Shockah!). * Overhauled [mod-provided APIs](https://stardewvalleywiki.com/Modding:Modder_Guide/APIs/Integrations#Mod-provided_APIs) (thanks to Shockah!).
_This adds support for many previously-unsupported cases: proxied interfaces in return values or input arguments, proxied enums if their values match, generic methods, and more._ _This adds support for many previously-unsupported cases: proxied interfaces in return values or input arguments, proxied enums if their values match, generic methods, and more._
* Added `Constants.ContentPath`. * Added `Constants.ContentPath`.

View File

@ -0,0 +1,16 @@
namespace StardewModdingAPI.Events
{
/// <summary>The priority for an asset edit when multiple apply for the same asset.</summary>
/// <remarks>You can also specify arbitrary intermediate values, like <c>AssetLoadPriority.Low + 5</c>.</remarks>
public enum AssetEditPriority
{
/// <summary>This edit should be applied before (i.e. 'under') <see cref="Default"/> edits.</summary>
Early = -1000,
/// <summary>The default priority.</summary>
Default = 0,
/// <summary>This edit should be applied after (i.e. 'on top of') <see cref="Default"/> edits.</summary>
Late = 1000
}
}

View File

@ -100,6 +100,7 @@ namespace StardewModdingAPI.Events
/// <summary>Edit the asset after it's loaded.</summary> /// <summary>Edit the asset after it's loaded.</summary>
/// <param name="apply">Apply changes to the asset.</param> /// <param name="apply">Apply changes to the asset.</param>
/// <param name="priority">If there are multiple edits that apply to the same asset, the priority with which this one should be applied.</param>
/// <param name="onBehalfOf">The content pack ID on whose behalf you're applying the change. This is only valid for content packs for your mod.</param> /// <param name="onBehalfOf">The content pack ID on whose behalf you're applying the change. This is only valid for content packs for your mod.</param>
/// <remarks> /// <remarks>
/// Usage notes: /// Usage notes:
@ -108,11 +109,12 @@ namespace StardewModdingAPI.Events
/// <item>You can apply any number of edits to the asset. Each edit will be applied on top of the previous one (i.e. it'll see the merged asset from all previous edits as its input).</item> /// <item>You can apply any number of edits to the asset. Each edit will be applied on top of the previous one (i.e. it'll see the merged asset from all previous edits as its input).</item>
/// </list> /// </list>
/// </remarks> /// </remarks>
public void Edit(Action<IAssetData> apply, string onBehalfOf = null) public void Edit(Action<IAssetData> apply, AssetEditPriority priority = AssetEditPriority.Default, string onBehalfOf = null)
{ {
this.EditOperations.Add( this.EditOperations.Add(
new AssetEditOperation( new AssetEditOperation(
mod: this.Mod, mod: this.Mod,
priority: priority,
onBehalfOf: this.GetOnBehalfOf(this.Mod, onBehalfOf, "edit assets"), onBehalfOf: this.GetOnBehalfOf(this.Mod, onBehalfOf, "edit assets"),
apply apply
) )

View File

@ -1,4 +1,5 @@
using System; using System;
using StardewModdingAPI.Events;
namespace StardewModdingAPI.Framework.Content namespace StardewModdingAPI.Framework.Content
{ {
@ -11,6 +12,9 @@ namespace StardewModdingAPI.Framework.Content
/// <summary>The mod applying the edit.</summary> /// <summary>The mod applying the edit.</summary>
public IModMetadata Mod { get; } public IModMetadata Mod { get; }
/// <summary>If there are multiple edits that apply to the same asset, the priority with which this one should be applied.</summary>
public AssetEditPriority Priority { get; }
/// <summary>The content pack on whose behalf the edit is being applied, if any.</summary> /// <summary>The content pack on whose behalf the edit is being applied, if any.</summary>
public IModMetadata OnBehalfOf { get; } public IModMetadata OnBehalfOf { get; }
@ -23,11 +27,13 @@ namespace StardewModdingAPI.Framework.Content
*********/ *********/
/// <summary>Construct an instance.</summary> /// <summary>Construct an instance.</summary>
/// <param name="mod">The mod applying the edit.</param> /// <param name="mod">The mod applying the edit.</param>
/// <param name="priority">If there are multiple edits that apply to the same asset, the priority with which this one should be applied.</param>
/// <param name="onBehalfOf">The content pack on whose behalf the edit is being applied, if any.</param> /// <param name="onBehalfOf">The content pack on whose behalf the edit is being applied, if any.</param>
/// <param name="applyEdit">Apply the edit to an asset.</param> /// <param name="applyEdit">Apply the edit to an asset.</param>
public AssetEditOperation(IModMetadata mod, IModMetadata onBehalfOf, Action<IAssetData> applyEdit) public AssetEditOperation(IModMetadata mod, AssetEditPriority priority, IModMetadata onBehalfOf, Action<IAssetData> applyEdit)
{ {
this.Mod = mod; this.Mod = mod;
this.Priority = priority;
this.OnBehalfOf = onBehalfOf; this.OnBehalfOf = onBehalfOf;
this.ApplyEdit = applyEdit; this.ApplyEdit = applyEdit;
} }

View File

@ -640,6 +640,7 @@ namespace StardewModdingAPI.Framework
{ {
new AssetEditOperation( new AssetEditOperation(
mod: editor.Mod, mod: editor.Mod,
priority: AssetEditPriority.Default,
onBehalfOf: null, onBehalfOf: null,
applyEdit: assetData => editor.Data.Edit<T>(assetData) applyEdit: assetData => editor.Data.Edit<T>(assetData)
) )

View File

@ -82,9 +82,12 @@ namespace StardewModdingAPI.Framework.ContentManagers
AssetLoadOperation[] loaders = this.GetLoaders<object>(info).ToArray(); AssetLoadOperation[] loaders = this.GetLoaders<object>(info).ToArray();
if (!this.AssertMaxOneRequiredLoader(info, loaders, out string error)) if (!this.AssertMaxOneRequiredLoader(info, loaders, out string error))
{
this.Monitor.Log(error, LogLevel.Warn); this.Monitor.Log(error, LogLevel.Warn);
return false;
}
return loaders.Length == 1; return loaders.Any();
} }
/// <inheritdoc /> /// <inheritdoc />
@ -334,7 +337,7 @@ namespace StardewModdingAPI.Framework.ContentManagers
} }
// edit asset // edit asset
AssetEditOperation[] editors = this.GetEditors<T>(info).ToArray(); AssetEditOperation[] editors = this.GetEditors<T>(info).OrderBy(p => p.Priority).ToArray();
foreach (AssetEditOperation editor in editors) foreach (AssetEditOperation editor in editors)
{ {
IModMetadata mod = editor.Mod; IModMetadata mod = editor.Mod;