From 584725bb8e554e314843315facca1fd15868bee4 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Wed, 23 Mar 2022 01:06:11 -0400 Subject: add initial AssetRequested content event (#766) --- src/SMAPI/Events/AssetRequestedEventArgs.cs | 94 +++++++++++++++++++++++++++++ src/SMAPI/Events/IContentEvents.cs | 17 ++++++ src/SMAPI/Events/IModEvents.cs | 3 + 3 files changed, 114 insertions(+) create mode 100644 src/SMAPI/Events/AssetRequestedEventArgs.cs create mode 100644 src/SMAPI/Events/IContentEvents.cs (limited to 'src/SMAPI/Events') diff --git a/src/SMAPI/Events/AssetRequestedEventArgs.cs b/src/SMAPI/Events/AssetRequestedEventArgs.cs new file mode 100644 index 00000000..b17250b0 --- /dev/null +++ b/src/SMAPI/Events/AssetRequestedEventArgs.cs @@ -0,0 +1,94 @@ +using System; +using System.Collections.Generic; +using Microsoft.Xna.Framework.Graphics; +using StardewModdingAPI.Framework; +using StardewModdingAPI.Framework.Content; +using xTile; + +namespace StardewModdingAPI.Events +{ + /// Event arguments for an event. + public class AssetRequestedEventArgs : EventArgs + { + /********* + ** Fields + *********/ + /// The mod handling the event. + private readonly IModMetadata Mod; + + + /********* + ** Accessors + *********/ + /// The name of the asset being requested. + public IAssetName Name { get; } + + /// The load operations requested by the event handler. + internal IList LoadOperations { get; } = new List(); + + /// The edit operations requested by the event handler. + internal IList EditOperations { get; } = new List(); + + + /********* + ** Public methods + *********/ + /// Construct an instance. + /// The mod handling the event. + /// The name of the asset being requested. + internal AssetRequestedEventArgs(IModMetadata mod, IAssetName name) + { + this.Mod = mod; + this.Name = name; + } + + /// Provide the initial instance for the asset, instead of trying to load it from the game's Content folder. + /// Get the initial instance of an asset. + /// + /// Usage notes: + /// + /// The asset doesn't need to exist in the game's Content folder. If any mod loads the asset, the game will see it as an existing asset as if it was in that folder. + /// Each asset can logically only have one initial instance. If multiple loads apply at the same time, SMAPI will raise an error and ignore all of them. If you're making changes to the existing asset instead of replacing it, you should use instead to avoid those limitations and improve mod compatibility. + /// + /// + public void LoadFrom(Func load) + { + this.LoadOperations.Add( + new AssetLoadOperation(this.Mod, _ => load()) + ); + } + + /// Provide the initial instance for the asset from a file in your mod folder, instead of trying to load it from the game's Content folder. + /// The expected data type. The main supported types are , , dictionaries, and lists; other types may be supported by the game's content pipeline. + /// The relative path to the file in your mod folder. + /// + /// Usage notes: + /// + /// The asset doesn't need to exist in the game's Content folder. If any mod loads the asset, the game will see it as an existing asset as if it was in that folder. + /// Each asset can logically only have one initial instance. If multiple loads apply at the same time, SMAPI will raise an error and ignore all of them. If you're making changes to the existing asset instead of replacing it, you should use instead to avoid those limitations and improve mod compatibility. + /// + /// + public void LoadFromModFile(string relativePath) + { + this.LoadOperations.Add( + new AssetLoadOperation(this.Mod, _ => this.Mod.Mod.Helper.Content.Load(relativePath)) + ); + } + + /// Edit the asset after it's loaded. + /// Apply changes to the asset. + /// + /// Usage notes: + /// + /// Editing an asset which doesn't exist has no effect. This is applied after the asset is loaded from the game's Content folder, or from any mod's or . + /// 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). + /// + /// + public void Edit(Action apply) + { + this.EditOperations.Add( + new AssetEditOperation(this.Mod, apply) + ); + } + } +} diff --git a/src/SMAPI/Events/IContentEvents.cs b/src/SMAPI/Events/IContentEvents.cs new file mode 100644 index 00000000..feaf9c0a --- /dev/null +++ b/src/SMAPI/Events/IContentEvents.cs @@ -0,0 +1,17 @@ +using System; +using StardewValley; + +namespace StardewModdingAPI.Events +{ + /// Events related to assets loaded from the content pipeline (including data, maps, and textures). + public interface IContentEvents + { + /// Raised when an asset is being requested from the content pipeline. + /// + /// The asset isn't necessarily being loaded yet (e.g. the game may be checking if it exists). Mods can register the changes they want to apply using methods on the parameter. These will be applied when the asset is actually loaded. + /// + /// If the asset is requested multiple times in the same tick (e.g. once to check if it exists and once to load it), SMAPI might only raise the event once and reuse the cached result. + /// + event EventHandler AssetRequested; + } +} diff --git a/src/SMAPI/Events/IModEvents.cs b/src/SMAPI/Events/IModEvents.cs index 1f892b31..2603961b 100644 --- a/src/SMAPI/Events/IModEvents.cs +++ b/src/SMAPI/Events/IModEvents.cs @@ -3,6 +3,9 @@ namespace StardewModdingAPI.Events /// Manages access to events raised by SMAPI. public interface IModEvents { + /// Events related to assets loaded from the content pipeline (including data, maps, and textures). + IContentEvents Content { get; } + /// Events related to UI and drawing to the screen. IDisplayEvents Display { get; } -- cgit