using System; using System.Collections.Generic; using StardewModdingAPI.Framework; namespace StardewModdingAPI.Events { /// Events raised when the game loads content. public static class ContentEvents { /********* ** Properties *********/ /// Tracks the installed mods. private static ModRegistry ModRegistry; /// Encapsulates monitoring and logging. private static IMonitor Monitor; /// The mods using the experimental API for which a warning has been raised. private static readonly HashSet WarnedMods = new HashSet(); /********* ** Events *********/ /// Raised after the content language changes. public static event EventHandler> AfterLocaleChanged; /// Raised when an XNB file is being read into the cache. Mods can change the data here before it's cached. #if EXPERIMENTAL public #else internal #endif static event EventHandler AfterAssetLoaded; /********* ** Internal methods *********/ /// Injects types required for backwards compatibility. /// Tracks the installed mods. /// Encapsulates monitoring and logging. internal static void Shim(ModRegistry modRegistry, IMonitor monitor) { ContentEvents.ModRegistry = modRegistry; ContentEvents.Monitor = monitor; } /// Raise an event. /// Encapsulates monitoring and logging. /// The previous locale. /// The current locale. internal static void InvokeAfterLocaleChanged(IMonitor monitor, string oldLocale, string newLocale) { monitor.SafelyRaiseGenericEvent($"{nameof(ContentEvents)}.{nameof(ContentEvents.AfterLocaleChanged)}", ContentEvents.AfterLocaleChanged?.GetInvocationList(), null, new EventArgsValueChanged(oldLocale, newLocale)); } /// Raise an event. /// Encapsulates monitoring and logging. /// Encapsulates access and changes to content being read from a data file. internal static void InvokeAfterAssetLoaded(IMonitor monitor, IContentEventHelper contentHelper) { if (ContentEvents.AfterAssetLoaded != null) { Delegate[] handlers = ContentEvents.AfterAssetLoaded.GetInvocationList(); ContentEvents.RaiseDeprecationWarning(handlers); monitor.SafelyRaiseGenericEvent($"{nameof(ContentEvents)}.{nameof(ContentEvents.AfterAssetLoaded)}", handlers, null, contentHelper); } } /********* ** Private methods *********/ /// Raise a 'experimental API' warning for each mod using the content API. /// The event handlers. private static void RaiseDeprecationWarning(Delegate[] handlers) { foreach (Delegate handler in handlers) { string modName = ContentEvents.ModRegistry.GetModFrom(handler) ?? "An unknown mod"; if (!ContentEvents.WarnedMods.Contains(modName)) { ContentEvents.WarnedMods.Add(modName); ContentEvents.Monitor.Log($"{modName} used the undocumented and experimental content API, which may change or be removed without warning.", LogLevel.Warn); } } } } }