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; /// Get the mod metadata for a content pack, if it's a valid content pack for the mod. private readonly Func GetOnBehalfOf; /********* ** Accessors *********/ /// The name of the asset being requested. public IAssetName Name { get; } /// The with any locale codes stripped. /// For example, if contains a locale like Data/Bundles.fr-FR, this will be the name without locale like Data/Bundles. If the name has no locale, this field is equivalent. public IAssetName NameWithoutLocale { get; } /// The requested data type. public Type DataType { 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. /// The requested data type. /// The with any locale codes stripped. /// Get the mod metadata for a content pack, if it's a valid content pack for the mod. internal AssetRequestedEventArgs(IModMetadata mod, IAssetName name, IAssetName nameWithoutLocale, Type dataType, Func getOnBehalfOf) { this.Mod = mod; this.Name = name; this.NameWithoutLocale = nameWithoutLocale; this.DataType = dataType; this.GetOnBehalfOf = getOnBehalfOf; } /// 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. /// If there are multiple loads that apply to the same asset, the priority with which this one should be applied. /// The content pack ID on whose behalf you're applying the change. This is only valid for content packs for your mod. /// /// 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 use the parameter to decide what happens. 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, AssetLoadPriority priority, string? onBehalfOf = null) { this.LoadOperations.Add( new AssetLoadOperation( mod: this.Mod, priority: priority, onBehalfOf: this.GetOnBehalfOf(this.Mod, onBehalfOf, "load assets"), getData: _ => 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. /// If there are multiple loads that apply to the same asset, the priority with which this one should be applied. /// /// 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, AssetLoadPriority priority) where TAsset : notnull { this.LoadOperations.Add( new AssetLoadOperation( mod: this.Mod, priority: priority, onBehalfOf: null, _ => this.Mod.Mod!.Helper.ModContent.Load(relativePath) ) ); } /// Edit the asset after it's loaded. /// Apply changes to the asset. /// If there are multiple edits that apply to the same asset, the priority with which this one should be applied. /// The content pack ID on whose behalf you're applying the change. This is only valid for content packs for your mod. /// /// 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, AssetEditPriority priority = AssetEditPriority.Default, string? onBehalfOf = null) { this.EditOperations.Add( new AssetEditOperation( mod: this.Mod, priority: priority, onBehalfOf: this.GetOnBehalfOf(this.Mod, onBehalfOf, "edit assets"), apply ) ); } } }