From 9c1617c9ee51a0f6b93242fe8fc789336957460c Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Wed, 11 Apr 2018 21:15:16 -0400 Subject: drop support for Stardew Valley 1.2 (#453) --- src/SMAPI/Framework/ModHelpers/ReflectionHelper.cs | 116 --------------------- 1 file changed, 116 deletions(-) (limited to 'src/SMAPI/Framework/ModHelpers') diff --git a/src/SMAPI/Framework/ModHelpers/ReflectionHelper.cs b/src/SMAPI/Framework/ModHelpers/ReflectionHelper.cs index e5bf47f6..648d6742 100644 --- a/src/SMAPI/Framework/ModHelpers/ReflectionHelper.cs +++ b/src/SMAPI/Framework/ModHelpers/ReflectionHelper.cs @@ -107,122 +107,6 @@ namespace StardewModdingAPI.Framework.ModHelpers ); } -#if !STARDEW_VALLEY_1_3 - /**** - ** Obsolete - ****/ - /// Get a private instance field. - /// The field type. - /// The object which has the field. - /// The field name. - /// Whether to throw an exception if the private field is not found. - /// Returns the field wrapper, or null if the field doesn't exist and is false. - [Obsolete] - public IPrivateField GetPrivateField(object obj, string name, bool required = true) - { - this.DeprecationManager.Warn($"{nameof(IReflectionHelper)}.GetPrivate*", "2.3", DeprecationLevel.Notice); - return (IPrivateField)this.GetField(obj, name, required); - } - - /// Get a private static field. - /// The field type. - /// The type which has the field. - /// The field name. - /// Whether to throw an exception if the private field is not found. - [Obsolete] - public IPrivateField GetPrivateField(Type type, string name, bool required = true) - { - this.DeprecationManager.Warn($"{nameof(IReflectionHelper)}.GetPrivate*", "2.3", DeprecationLevel.Notice); - return (IPrivateField)this.GetField(type, name, required); - } - - /// Get a private instance property. - /// The property type. - /// The object which has the property. - /// The property name. - /// Whether to throw an exception if the private property is not found. - [Obsolete] - public IPrivateProperty GetPrivateProperty(object obj, string name, bool required = true) - { - this.DeprecationManager.Warn($"{nameof(IReflectionHelper)}.GetPrivate*", "2.3", DeprecationLevel.Notice); - return (IPrivateProperty)this.GetProperty(obj, name, required); - } - - /// Get a private static property. - /// The property type. - /// The type which has the property. - /// The property name. - /// Whether to throw an exception if the private property is not found. - [Obsolete] - public IPrivateProperty GetPrivateProperty(Type type, string name, bool required = true) - { - this.DeprecationManager.Warn($"{nameof(IReflectionHelper)}.GetPrivate*", "2.3", DeprecationLevel.Notice); - return (IPrivateProperty)this.GetProperty(type, name, required); - } - - /// Get the value of a private instance field. - /// The field type. - /// The object which has the field. - /// The field name. - /// Whether to throw an exception if the private field is not found. - /// Returns the field value, or the default value for if the field wasn't found and is false. - /// - /// This is a shortcut for followed by . - /// When is false, this will return the default value if reflection fails. If you need to check whether the field exists, use instead. - /// - [Obsolete] - public TValue GetPrivateValue(object obj, string name, bool required = true) - { - this.DeprecationManager.Warn($"{nameof(IReflectionHelper)}.GetPrivate*", "2.3", DeprecationLevel.Notice); - IPrivateField field = (IPrivateField)this.GetField(obj, name, required); - return field != null - ? field.GetValue() - : default(TValue); - } - - /// Get the value of a private static field. - /// The field type. - /// The type which has the field. - /// The field name. - /// Whether to throw an exception if the private field is not found. - /// Returns the field value, or the default value for if the field wasn't found and is false. - /// - /// This is a shortcut for followed by . - /// When is false, this will return the default value if reflection fails. If you need to check whether the field exists, use instead. - /// - [Obsolete] - public TValue GetPrivateValue(Type type, string name, bool required = true) - { - this.DeprecationManager.Warn($"{nameof(IReflectionHelper)}.GetPrivate*", "2.3", DeprecationLevel.Notice); - IPrivateField field = (IPrivateField)this.GetField(type, name, required); - return field != null - ? field.GetValue() - : default(TValue); - } - - /// Get a private instance method. - /// The object which has the method. - /// The field name. - /// Whether to throw an exception if the private field is not found. - [Obsolete] - public IPrivateMethod GetPrivateMethod(object obj, string name, bool required = true) - { - this.DeprecationManager.Warn($"{nameof(IReflectionHelper)}.GetPrivate*", "2.3", DeprecationLevel.Notice); - return (IPrivateMethod)this.GetMethod(obj, name, required); - } - - /// Get a private static method. - /// The type which has the method. - /// The field name. - /// Whether to throw an exception if the private field is not found. - [Obsolete] - public IPrivateMethod GetPrivateMethod(Type type, string name, bool required = true) - { - this.DeprecationManager.Warn($"{nameof(IReflectionHelper)}.GetPrivate*", "2.3", DeprecationLevel.Notice); - return (IPrivateMethod)this.GetMethod(type, name, required); - } -#endif - /********* ** Private methods -- cgit From b346d28d3858b79c6c4cde55faac34ecdedeaff1 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Thu, 19 Apr 2018 20:35:16 -0400 Subject: fix GetApi interface validation errors not naming interface --- src/SMAPI/Framework/ModHelpers/ModRegistryHelper.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/SMAPI/Framework/ModHelpers') diff --git a/src/SMAPI/Framework/ModHelpers/ModRegistryHelper.cs b/src/SMAPI/Framework/ModHelpers/ModRegistryHelper.cs index e579a830..008a80f5 100644 --- a/src/SMAPI/Framework/ModHelpers/ModRegistryHelper.cs +++ b/src/SMAPI/Framework/ModHelpers/ModRegistryHelper.cs @@ -82,12 +82,12 @@ namespace StardewModdingAPI.Framework.ModHelpers } if (!typeof(TInterface).IsInterface) { - this.Monitor.Log("Tried to map a mod-provided API to a class; must be a public interface.", LogLevel.Error); + this.Monitor.Log($"Tried to map a mod-provided API to class '{typeof(TInterface).FullName}'; must be a public interface.", LogLevel.Error); return null; } if (!typeof(TInterface).IsPublic) { - this.Monitor.Log("Tried to map a mod-provided API to a non-public interface; must be a public interface.", LogLevel.Error); + this.Monitor.Log($"Tried to map a mod-provided API to non-public interface '{typeof(TInterface).FullName}'; must be a public interface.", LogLevel.Error); return null; } -- cgit From a625e9bed71c6398a18ec0f5d41d7f8135660efd Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Sat, 28 Apr 2018 13:30:24 -0400 Subject: add initial multiplayer API (#480) --- src/SMAPI/Framework/ModHelpers/ModHelper.cs | 6 ++++- .../Framework/ModHelpers/MultiplayerHelper.cs | 31 ++++++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 src/SMAPI/Framework/ModHelpers/MultiplayerHelper.cs (limited to 'src/SMAPI/Framework/ModHelpers') diff --git a/src/SMAPI/Framework/ModHelpers/ModHelper.cs b/src/SMAPI/Framework/ModHelpers/ModHelper.cs index b5758d21..1f37a1be 100644 --- a/src/SMAPI/Framework/ModHelpers/ModHelper.cs +++ b/src/SMAPI/Framework/ModHelpers/ModHelper.cs @@ -45,6 +45,9 @@ namespace StardewModdingAPI.Framework.ModHelpers /// An API for managing console commands. public ICommandHelper ConsoleCommands { get; } + /// Provides multiplayer utilities. + public IMultiplayerHelper Multiplayer { get; } + /// An API for reading translations stored in the mod's i18n folder, with one file per locale (like en.json) containing a flat key => value structure. Translations are fetched with locale fallback, so missing translations are filled in from broader locales (like pt-BR.json < pt.json < default.json). public ITranslationHelper Translation { get; } @@ -66,7 +69,7 @@ namespace StardewModdingAPI.Framework.ModHelpers /// Manages deprecation warnings. /// An argument is null or empty. /// The path does not exist on disk. - public ModHelper(string modID, string modDirectory, JsonHelper jsonHelper, IContentHelper contentHelper, ICommandHelper commandHelper, IModRegistry modRegistry, IReflectionHelper reflectionHelper, ITranslationHelper translationHelper, IEnumerable contentPacks, Func createContentPack, DeprecationManager deprecationManager) + public ModHelper(string modID, string modDirectory, JsonHelper jsonHelper, IContentHelper contentHelper, ICommandHelper commandHelper, IModRegistry modRegistry, IReflectionHelper reflectionHelper, IMultiplayerHelper multiplayer, ITranslationHelper translationHelper, IEnumerable contentPacks, Func createContentPack, DeprecationManager deprecationManager) : base(modID) { // validate directory @@ -82,6 +85,7 @@ namespace StardewModdingAPI.Framework.ModHelpers this.ModRegistry = modRegistry ?? throw new ArgumentNullException(nameof(modRegistry)); this.ConsoleCommands = commandHelper ?? throw new ArgumentNullException(nameof(commandHelper)); this.Reflection = reflectionHelper ?? throw new ArgumentNullException(nameof(reflectionHelper)); + this.Multiplayer = multiplayer ?? throw new ArgumentNullException(nameof(multiplayer)); this.Translation = translationHelper ?? throw new ArgumentNullException(nameof(translationHelper)); this.ContentPacks = contentPacks.ToArray(); this.CreateContentPack = createContentPack; diff --git a/src/SMAPI/Framework/ModHelpers/MultiplayerHelper.cs b/src/SMAPI/Framework/ModHelpers/MultiplayerHelper.cs new file mode 100644 index 00000000..7a8da1d0 --- /dev/null +++ b/src/SMAPI/Framework/ModHelpers/MultiplayerHelper.cs @@ -0,0 +1,31 @@ +namespace StardewModdingAPI.Framework.ModHelpers +{ + /// Provides multiplayer utilities. + internal class MultiplayerHelper : BaseHelper, IMultiplayerHelper + { + /********* + ** Properties + *********/ + /// SMAPI's core multiplayer utility. + private readonly SMultiplayer Multiplayer; + + + /********* + ** Public methods + *********/ + /// Construct an instance. + /// The unique ID of the relevant mod. + /// SMAPI's core multiplayer utility. + public MultiplayerHelper(string modID, SMultiplayer multiplayer) + : base(modID) + { + this.Multiplayer = multiplayer; + } + + /// Get a new multiplayer ID. + public long GetNewID() + { + return this.Multiplayer.getNewID(); + } + } +} -- cgit From 418ff99ea3b4d06432182b147d0637cce5eb0bae Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Sun, 6 May 2018 21:00:35 -0400 Subject: add GetActiveLocations to multiplayer API (#480) --- src/SMAPI/Framework/ModHelpers/MultiplayerHelper.cs | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'src/SMAPI/Framework/ModHelpers') diff --git a/src/SMAPI/Framework/ModHelpers/MultiplayerHelper.cs b/src/SMAPI/Framework/ModHelpers/MultiplayerHelper.cs index 7a8da1d0..c449a51b 100644 --- a/src/SMAPI/Framework/ModHelpers/MultiplayerHelper.cs +++ b/src/SMAPI/Framework/ModHelpers/MultiplayerHelper.cs @@ -1,3 +1,6 @@ +using System.Collections.Generic; +using StardewValley; + namespace StardewModdingAPI.Framework.ModHelpers { /// Provides multiplayer utilities. @@ -22,6 +25,12 @@ namespace StardewModdingAPI.Framework.ModHelpers this.Multiplayer = multiplayer; } + /// Get the locations which are being actively synced from the host. + public IEnumerable GetActiveLocations() + { + return this.Multiplayer.activeLocations(); + } + /// Get a new multiplayer ID. public long GetNewID() { -- cgit From 61b023916eb92237b3b10b30b77792139de1097d Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Wed, 9 May 2018 23:58:58 -0400 Subject: rewrite content logic to decentralise cache (#488) This is necessary due to changes in Stardew Valley 1.3, which now changes loaded assets and expects those changes to be persisted but not propagated to other content managers. --- src/SMAPI/Framework/ModHelpers/ContentHelper.cs | 38 ++++++++++++------------- 1 file changed, 19 insertions(+), 19 deletions(-) (limited to 'src/SMAPI/Framework/ModHelpers') diff --git a/src/SMAPI/Framework/ModHelpers/ContentHelper.cs b/src/SMAPI/Framework/ModHelpers/ContentHelper.cs index c7d4c39e..4a71f7e7 100644 --- a/src/SMAPI/Framework/ModHelpers/ContentHelper.cs +++ b/src/SMAPI/Framework/ModHelpers/ContentHelper.cs @@ -23,10 +23,10 @@ namespace StardewModdingAPI.Framework.ModHelpers ** Properties *********/ /// SMAPI's core content logic. - private readonly ContentCore ContentCore; + private readonly ContentCoordinator ContentCore; /// The content manager for this mod. - private readonly ContentManagerShim ContentManager; + private readonly SContentManager ContentManager; /// The absolute path to the mod folder. private readonly string ModFolderPath; @@ -42,10 +42,10 @@ namespace StardewModdingAPI.Framework.ModHelpers ** Accessors *********/ /// The game's current locale code (like pt-BR). - public string CurrentLocale => this.ContentCore.GetLocale(); + public string CurrentLocale => this.ContentManager.GetLocale(); /// The game's current locale as an enum value. - public LocalizedContentManager.LanguageCode CurrentLocaleConstant => this.ContentCore.Language; + public LocalizedContentManager.LanguageCode CurrentLocaleConstant => this.ContentManager.Language; /// The observable implementation of . internal ObservableCollection ObservableAssetEditors { get; } = new ObservableCollection(); @@ -70,7 +70,7 @@ namespace StardewModdingAPI.Framework.ModHelpers /// The unique ID of the relevant mod. /// The friendly mod name for use in errors. /// Encapsulates monitoring and logging. - public ContentHelper(ContentCore contentCore, ContentManagerShim contentManager, string modFolderPath, string modID, string modName, IMonitor monitor) + public ContentHelper(ContentCoordinator contentCore, SContentManager contentManager, string modFolderPath, string modID, string modName, IMonitor monitor) : base(modID) { this.ContentCore = contentCore; @@ -96,7 +96,7 @@ namespace StardewModdingAPI.Framework.ModHelpers switch (source) { case ContentSource.GameContent: - return this.ContentManager.Load(key); + return this.ContentCore.MainContentManager.Load(key); case ContentSource.ModFolder: // get file @@ -105,10 +105,10 @@ namespace StardewModdingAPI.Framework.ModHelpers throw GetContentError($"there's no matching file at path '{file.FullName}'."); // get asset path - string assetName = this.ContentCore.GetAssetNameFromFilePath(file.FullName); + string assetName = this.ContentManager.GetAssetNameFromFilePath(file.FullName, ContentSource.ModFolder); // try cache - if (this.ContentCore.IsLoaded(assetName)) + if (this.ContentManager.IsLoaded(assetName)) return this.ContentManager.Load(assetName); // fix map tilesheets @@ -146,7 +146,7 @@ namespace StardewModdingAPI.Framework.ModHelpers [Pure] public string NormaliseAssetName(string assetName) { - return this.ContentCore.NormaliseAssetName(assetName); + return this.ContentManager.NormaliseAssetName(assetName); } /// Get the underlying key in the game's content cache for an asset. This can be used to load custom map tilesheets, but should be avoided when you can use the content API instead. This does not validate whether the asset exists. @@ -158,11 +158,11 @@ namespace StardewModdingAPI.Framework.ModHelpers switch (source) { case ContentSource.GameContent: - return this.ContentCore.NormaliseAssetName(key); + return this.ContentManager.NormaliseAssetName(key); case ContentSource.ModFolder: FileInfo file = this.GetModFile(key); - return this.ContentCore.NormaliseAssetName(this.ContentCore.GetAssetNameFromFilePath(file.FullName)); + return this.ContentManager.NormaliseAssetName(this.ContentManager.GetAssetNameFromFilePath(file.FullName, ContentSource.GameContent)); default: throw new NotSupportedException($"Unknown content source '{source}'."); @@ -177,7 +177,7 @@ namespace StardewModdingAPI.Framework.ModHelpers { string actualKey = this.GetActualAssetKey(key, ContentSource.GameContent); this.Monitor.Log($"Requested cache invalidation for '{actualKey}'.", LogLevel.Trace); - return this.ContentCore.InvalidateCache(asset => asset.AssetNameEquals(actualKey)); + return this.ContentCore.InvalidateCache(asset => asset.AssetNameEquals(actualKey)).Any(); } /// Remove all assets of the given type from the cache so they're reloaded on the next request. This can be a very expensive operation and should only be used in very specific cases. This will reload core game assets if needed, but references to the former assets will still show the previous content. @@ -186,7 +186,7 @@ namespace StardewModdingAPI.Framework.ModHelpers public bool InvalidateCache() { this.Monitor.Log($"Requested cache invalidation for all assets of type {typeof(T)}. This is an expensive operation and should be avoided if possible.", LogLevel.Trace); - return this.ContentCore.InvalidateCache((key, type) => typeof(T).IsAssignableFrom(type)); + return this.ContentCore.InvalidateCache((key, type) => typeof(T).IsAssignableFrom(type)).Any(); } /// Remove matching assets from the content cache so they're reloaded on the next request. This will reload core game assets if needed, but references to the former asset will still show the previous content. @@ -195,7 +195,7 @@ namespace StardewModdingAPI.Framework.ModHelpers public bool InvalidateCache(Func predicate) { this.Monitor.Log("Requested cache invalidation for all assets matching a predicate.", LogLevel.Trace); - return this.ContentCore.InvalidateCache(predicate); + return this.ContentCore.InvalidateCache(predicate).Any(); } /********* @@ -207,7 +207,7 @@ namespace StardewModdingAPI.Framework.ModHelpers [SuppressMessage("ReSharper", "ParameterOnlyUsedForPreconditionCheck.Local", Justification = "Parameter is only used for assertion checks by design.")] private void AssertValidAssetKeyFormat(string key) { - this.ContentCore.AssertValidAssetKeyFormat(key); + this.ContentManager.AssertValidAssetKeyFormat(key); if (Path.IsPathRooted(key)) throw new ArgumentException("The asset key must not be an absolute path."); } @@ -235,7 +235,7 @@ namespace StardewModdingAPI.Framework.ModHelpers // get map info if (!map.TileSheets.Any()) return; - mapKey = this.ContentCore.NormaliseAssetName(mapKey); // Mono's Path.GetDirectoryName doesn't handle Windows dir separators + mapKey = this.ContentManager.NormaliseAssetName(mapKey); // Mono's Path.GetDirectoryName doesn't handle Windows dir separators string relativeMapFolder = Path.GetDirectoryName(mapKey) ?? ""; // folder path containing the map, relative to the mod folder // fix tilesheets @@ -251,7 +251,7 @@ namespace StardewModdingAPI.Framework.ModHelpers string seasonalImageSource = null; if (Game1.currentSeason != null) { - string filename = Path.GetFileName(imageSource); + string filename = Path.GetFileName(imageSource) ?? throw new InvalidOperationException($"The '{imageSource}' tilesheet couldn't be loaded: filename is unexpectedly null."); bool hasSeasonalPrefix = filename.StartsWith("spring_", StringComparison.CurrentCultureIgnoreCase) || filename.StartsWith("summer_", StringComparison.CurrentCultureIgnoreCase) @@ -341,7 +341,7 @@ namespace StardewModdingAPI.Framework.ModHelpers private FileInfo GetModFile(string path) { // try exact match - path = Path.Combine(this.ModFolderPath, this.ContentCore.NormalisePathSeparators(path)); + path = Path.Combine(this.ModFolderPath, this.ContentManager.NormalisePathSeparators(path)); FileInfo file = new FileInfo(path); // try with default extension @@ -360,7 +360,7 @@ namespace StardewModdingAPI.Framework.ModHelpers private FileInfo GetContentFolderFile(string key) { // get file path - string path = Path.Combine(this.ContentCore.FullRootDirectory, key); + string path = Path.Combine(this.ContentManager.FullRootDirectory, key); if (!path.EndsWith(".xnb")) path += ".xnb"; -- cgit From 75dfa884d99a778e694d2712ff70efac5e26725f Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Thu, 10 May 2018 00:53:19 -0400 Subject: fix documentation warnings --- src/SMAPI/Framework/ModHelpers/ModHelper.cs | 1 + 1 file changed, 1 insertion(+) (limited to 'src/SMAPI/Framework/ModHelpers') diff --git a/src/SMAPI/Framework/ModHelpers/ModHelper.cs b/src/SMAPI/Framework/ModHelpers/ModHelper.cs index 1f37a1be..26fe7198 100644 --- a/src/SMAPI/Framework/ModHelpers/ModHelper.cs +++ b/src/SMAPI/Framework/ModHelpers/ModHelper.cs @@ -63,6 +63,7 @@ namespace StardewModdingAPI.Framework.ModHelpers /// An API for managing console commands. /// an API for fetching metadata about loaded mods. /// An API for accessing private game code. + /// Provides multiplayer utilities. /// An API for reading translations stored in the mod's i18n folder. /// The content packs loaded for this mod. /// Create a transitional content pack. -- cgit From bd04d46dd1d66b30d4f21575bbbd2e541eabcef3 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Tue, 22 May 2018 22:53:44 -0400 Subject: refactor content API to fix load errors with decentralised cache (#524) --- src/SMAPI/Framework/ModHelpers/ContentHelper.cs | 66 ++++++++++++++----------- 1 file changed, 38 insertions(+), 28 deletions(-) (limited to 'src/SMAPI/Framework/ModHelpers') diff --git a/src/SMAPI/Framework/ModHelpers/ContentHelper.cs b/src/SMAPI/Framework/ModHelpers/ContentHelper.cs index 4a71f7e7..ce26c980 100644 --- a/src/SMAPI/Framework/ModHelpers/ContentHelper.cs +++ b/src/SMAPI/Framework/ModHelpers/ContentHelper.cs @@ -7,6 +7,7 @@ using System.IO; using System.Linq; using Microsoft.Xna.Framework.Content; using Microsoft.Xna.Framework.Graphics; +using StardewModdingAPI.Framework.ContentManagers; using StardewModdingAPI.Framework.Exceptions; using StardewModdingAPI.Framework.Utilities; using StardewValley; @@ -25,8 +26,11 @@ namespace StardewModdingAPI.Framework.ModHelpers /// SMAPI's core content logic. private readonly ContentCoordinator ContentCore; - /// The content manager for this mod. - private readonly SContentManager ContentManager; + /// A content manager for this mod which manages files from the game's Content folder. + private readonly IContentManager GameContentManager; + + /// A content manager for this mod which manages files from the mod's folder. + private readonly IContentManager ModContentManager; /// The absolute path to the mod folder. private readonly string ModFolderPath; @@ -42,10 +46,10 @@ namespace StardewModdingAPI.Framework.ModHelpers ** Accessors *********/ /// The game's current locale code (like pt-BR). - public string CurrentLocale => this.ContentManager.GetLocale(); + public string CurrentLocale => this.GameContentManager.GetLocale(); /// The game's current locale as an enum value. - public LocalizedContentManager.LanguageCode CurrentLocaleConstant => this.ContentManager.Language; + public LocalizedContentManager.LanguageCode CurrentLocaleConstant => this.GameContentManager.Language; /// The observable implementation of . internal ObservableCollection ObservableAssetEditors { get; } = new ObservableCollection(); @@ -65,16 +69,16 @@ namespace StardewModdingAPI.Framework.ModHelpers *********/ /// Construct an instance. /// SMAPI's core content logic. - /// The content manager for this mod. /// The absolute path to the mod folder. /// The unique ID of the relevant mod. /// The friendly mod name for use in errors. /// Encapsulates monitoring and logging. - public ContentHelper(ContentCoordinator contentCore, SContentManager contentManager, string modFolderPath, string modID, string modName, IMonitor monitor) + public ContentHelper(ContentCoordinator contentCore, string modFolderPath, string modID, string modName, IMonitor monitor) : base(modID) { this.ContentCore = contentCore; - this.ContentManager = contentManager; + this.GameContentManager = contentCore.CreateGameContentManager(this.ContentCore.GetManagedAssetPrefix(modID) + ".content"); + this.ModContentManager = contentCore.CreateModContentManager(this.ContentCore.GetManagedAssetPrefix(modID), rootDirectory: modFolderPath); this.ModFolderPath = modFolderPath; this.ModName = modName; this.Monitor = monitor; @@ -92,24 +96,22 @@ namespace StardewModdingAPI.Framework.ModHelpers try { - this.AssertValidAssetKeyFormat(key); + this.AssertAndNormaliseAssetName(key); switch (source) { case ContentSource.GameContent: - return this.ContentCore.MainContentManager.Load(key); + return this.GameContentManager.Load(key); case ContentSource.ModFolder: // get file FileInfo file = this.GetModFile(key); if (!file.Exists) throw GetContentError($"there's no matching file at path '{file.FullName}'."); - - // get asset path - string assetName = this.ContentManager.GetAssetNameFromFilePath(file.FullName, ContentSource.ModFolder); + string internalKey = this.GetInternalModAssetKey(file); // try cache - if (this.ContentManager.IsLoaded(assetName)) - return this.ContentManager.Load(assetName); + if (this.ModContentManager.IsLoaded(internalKey)) + return this.ModContentManager.Load(internalKey); // fix map tilesheets if (file.Extension.ToLower() == ".tbin") @@ -121,15 +123,15 @@ namespace StardewModdingAPI.Framework.ModHelpers // fetch & cache FormatManager formatManager = FormatManager.Instance; Map map = formatManager.LoadMap(file.FullName); - this.FixCustomTilesheetPaths(map, key); + this.FixCustomTilesheetPaths(map, relativeMapPath: key); // inject map - this.ContentManager.Inject(assetName, map); + this.ModContentManager.Inject(internalKey, map); return (T)(object)map; } // load through content manager - return this.ContentManager.Load(assetName); + return this.ModContentManager.Load(internalKey); default: throw GetContentError($"unknown content source '{source}'."); @@ -146,7 +148,7 @@ namespace StardewModdingAPI.Framework.ModHelpers [Pure] public string NormaliseAssetName(string assetName) { - return this.ContentManager.NormaliseAssetName(assetName); + return this.ModContentManager.AssertAndNormaliseAssetName(assetName); } /// Get the underlying key in the game's content cache for an asset. This can be used to load custom map tilesheets, but should be avoided when you can use the content API instead. This does not validate whether the asset exists. @@ -158,11 +160,11 @@ namespace StardewModdingAPI.Framework.ModHelpers switch (source) { case ContentSource.GameContent: - return this.ContentManager.NormaliseAssetName(key); + return this.GameContentManager.AssertAndNormaliseAssetName(key); case ContentSource.ModFolder: FileInfo file = this.GetModFile(key); - return this.ContentManager.NormaliseAssetName(this.ContentManager.GetAssetNameFromFilePath(file.FullName, ContentSource.GameContent)); + return this.GetInternalModAssetKey(file); default: throw new NotSupportedException($"Unknown content source '{source}'."); @@ -205,16 +207,24 @@ namespace StardewModdingAPI.Framework.ModHelpers /// The asset key to check. /// The asset key is empty or contains invalid characters. [SuppressMessage("ReSharper", "ParameterOnlyUsedForPreconditionCheck.Local", Justification = "Parameter is only used for assertion checks by design.")] - private void AssertValidAssetKeyFormat(string key) + private void AssertAndNormaliseAssetName(string key) { - this.ContentManager.AssertValidAssetKeyFormat(key); + this.ModContentManager.AssertAndNormaliseAssetName(key); if (Path.IsPathRooted(key)) throw new ArgumentException("The asset key must not be an absolute path."); } + /// Get the internal key in the content cache for a mod asset. + /// The asset file. + private string GetInternalModAssetKey(FileInfo modFile) + { + string relativePath = PathUtilities.GetRelativePath(this.ModFolderPath, modFile.FullName); + return Path.Combine(this.ModContentManager.Name, relativePath); + } + /// Fix custom map tilesheet paths so they can be found by the content manager. /// The map whose tilesheets to fix. - /// The map asset key within the mod folder. + /// The relative map path within the mod folder. /// A map tilesheet couldn't be resolved. /// /// The game's logic for tilesheets in is a bit specialised. It boils @@ -230,13 +240,13 @@ namespace StardewModdingAPI.Framework.ModHelpers /// /// While that doesn't exactly match the game logic, it's close enough that it's unlikely to make a difference. /// - private void FixCustomTilesheetPaths(Map map, string mapKey) + private void FixCustomTilesheetPaths(Map map, string relativeMapPath) { // get map info if (!map.TileSheets.Any()) return; - mapKey = this.ContentManager.NormaliseAssetName(mapKey); // Mono's Path.GetDirectoryName doesn't handle Windows dir separators - string relativeMapFolder = Path.GetDirectoryName(mapKey) ?? ""; // folder path containing the map, relative to the mod folder + relativeMapPath = this.ModContentManager.AssertAndNormaliseAssetName(relativeMapPath); // Mono's Path.GetDirectoryName doesn't handle Windows dir separators + string relativeMapFolder = Path.GetDirectoryName(relativeMapPath) ?? ""; // folder path containing the map, relative to the mod folder // fix tilesheets foreach (TileSheet tilesheet in map.TileSheets) @@ -341,7 +351,7 @@ namespace StardewModdingAPI.Framework.ModHelpers private FileInfo GetModFile(string path) { // try exact match - path = Path.Combine(this.ModFolderPath, this.ContentManager.NormalisePathSeparators(path)); + path = Path.Combine(this.ModFolderPath, this.ModContentManager.NormalisePathSeparators(path)); FileInfo file = new FileInfo(path); // try with default extension @@ -360,7 +370,7 @@ namespace StardewModdingAPI.Framework.ModHelpers private FileInfo GetContentFolderFile(string key) { // get file path - string path = Path.Combine(this.ContentManager.FullRootDirectory, key); + string path = Path.Combine(this.GameContentManager.FullRootDirectory, key); if (!path.EndsWith(".xnb")) path += ".xnb"; -- cgit From 69b17f1db87d9aeb5dd6d6f9c81ac9ac62f2a6d3 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Fri, 25 May 2018 02:06:28 -0400 Subject: move PathUtilities into toolkit (#532) --- src/SMAPI/Framework/ModHelpers/ContentHelper.cs | 2 +- src/SMAPI/Framework/ModHelpers/ModHelper.cs | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'src/SMAPI/Framework/ModHelpers') diff --git a/src/SMAPI/Framework/ModHelpers/ContentHelper.cs b/src/SMAPI/Framework/ModHelpers/ContentHelper.cs index ce26c980..671dc21e 100644 --- a/src/SMAPI/Framework/ModHelpers/ContentHelper.cs +++ b/src/SMAPI/Framework/ModHelpers/ContentHelper.cs @@ -9,7 +9,7 @@ using Microsoft.Xna.Framework.Content; using Microsoft.Xna.Framework.Graphics; using StardewModdingAPI.Framework.ContentManagers; using StardewModdingAPI.Framework.Exceptions; -using StardewModdingAPI.Framework.Utilities; +using StardewModdingAPI.Toolkit.Utilities; using StardewValley; using xTile; using xTile.Format; diff --git a/src/SMAPI/Framework/ModHelpers/ModHelper.cs b/src/SMAPI/Framework/ModHelpers/ModHelper.cs index 26fe7198..61d2075c 100644 --- a/src/SMAPI/Framework/ModHelpers/ModHelper.cs +++ b/src/SMAPI/Framework/ModHelpers/ModHelper.cs @@ -4,7 +4,7 @@ using System.IO; using System.Linq; using StardewModdingAPI.Framework.Models; using StardewModdingAPI.Framework.Serialisation; -using StardewModdingAPI.Framework.Utilities; +using StardewModdingAPI.Toolkit.Utilities; namespace StardewModdingAPI.Framework.ModHelpers { @@ -157,13 +157,13 @@ namespace StardewModdingAPI.Framework.ModHelpers this.DeprecationManager.Warn($"{nameof(IModHelper)}.{nameof(IModHelper.CreateTransitionalContentPack)}", "2.5", DeprecationLevel.Notice); // validate - if(string.IsNullOrWhiteSpace(directoryPath)) + if (string.IsNullOrWhiteSpace(directoryPath)) throw new ArgumentNullException(nameof(directoryPath)); - if(string.IsNullOrWhiteSpace(id)) + if (string.IsNullOrWhiteSpace(id)) throw new ArgumentNullException(nameof(id)); - if(string.IsNullOrWhiteSpace(name)) + if (string.IsNullOrWhiteSpace(name)) throw new ArgumentNullException(nameof(name)); - if(!Directory.Exists(directoryPath)) + if (!Directory.Exists(directoryPath)) throw new ArgumentException($"Can't create content pack for directory path '{directoryPath}' because no such directory exists."); // create manifest -- cgit From 558fb8a865b638cf5536856e7dcab44823feeaf3 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Thu, 31 May 2018 22:47:56 -0400 Subject: move location events into new event system (#310) --- src/SMAPI/Framework/ModHelpers/ModHelper.cs | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) (limited to 'src/SMAPI/Framework/ModHelpers') diff --git a/src/SMAPI/Framework/ModHelpers/ModHelper.cs b/src/SMAPI/Framework/ModHelpers/ModHelper.cs index 26fe7198..92cb9d94 100644 --- a/src/SMAPI/Framework/ModHelpers/ModHelper.cs +++ b/src/SMAPI/Framework/ModHelpers/ModHelper.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.IO; using System.Linq; +using StardewModdingAPI.Events; using StardewModdingAPI.Framework.Models; using StardewModdingAPI.Framework.Serialisation; using StardewModdingAPI.Framework.Utilities; @@ -33,6 +34,9 @@ namespace StardewModdingAPI.Framework.ModHelpers /// The full path to the mod's folder. public string DirectoryPath { get; } + /// Manages access to events raised by SMAPI, which let your mod react when something happens in the game. + public IModEvents Events { get; } + /// An API for loading content assets. public IContentHelper Content { get; } @@ -59,6 +63,7 @@ namespace StardewModdingAPI.Framework.ModHelpers /// The mod's unique ID. /// The full path to the mod's folder. /// Encapsulate SMAPI's JSON parsing. + /// Manages access to events raised by SMAPI. /// An API for loading content assets. /// An API for managing console commands. /// an API for fetching metadata about loaded mods. @@ -70,7 +75,7 @@ namespace StardewModdingAPI.Framework.ModHelpers /// Manages deprecation warnings. /// An argument is null or empty. /// The path does not exist on disk. - public ModHelper(string modID, string modDirectory, JsonHelper jsonHelper, IContentHelper contentHelper, ICommandHelper commandHelper, IModRegistry modRegistry, IReflectionHelper reflectionHelper, IMultiplayerHelper multiplayer, ITranslationHelper translationHelper, IEnumerable contentPacks, Func createContentPack, DeprecationManager deprecationManager) + public ModHelper(string modID, string modDirectory, JsonHelper jsonHelper, IModEvents events, IContentHelper contentHelper, ICommandHelper commandHelper, IModRegistry modRegistry, IReflectionHelper reflectionHelper, IMultiplayerHelper multiplayer, ITranslationHelper translationHelper, IEnumerable contentPacks, Func createContentPack, DeprecationManager deprecationManager) : base(modID) { // validate directory @@ -91,6 +96,7 @@ namespace StardewModdingAPI.Framework.ModHelpers this.ContentPacks = contentPacks.ToArray(); this.CreateContentPack = createContentPack; this.DeprecationManager = deprecationManager; + this.Events = events; } /**** @@ -157,13 +163,13 @@ namespace StardewModdingAPI.Framework.ModHelpers this.DeprecationManager.Warn($"{nameof(IModHelper)}.{nameof(IModHelper.CreateTransitionalContentPack)}", "2.5", DeprecationLevel.Notice); // validate - if(string.IsNullOrWhiteSpace(directoryPath)) + if (string.IsNullOrWhiteSpace(directoryPath)) throw new ArgumentNullException(nameof(directoryPath)); - if(string.IsNullOrWhiteSpace(id)) + if (string.IsNullOrWhiteSpace(id)) throw new ArgumentNullException(nameof(id)); - if(string.IsNullOrWhiteSpace(name)) + if (string.IsNullOrWhiteSpace(name)) throw new ArgumentNullException(nameof(name)); - if(!Directory.Exists(directoryPath)) + if (!Directory.Exists(directoryPath)) throw new ArgumentException($"Can't create content pack for directory path '{directoryPath}' because no such directory exists."); // create manifest -- cgit From d41fe6ff88b569f991f219c5f348d3688fba956f Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Sat, 2 Jun 2018 16:00:16 -0400 Subject: add input API --- src/SMAPI/Framework/ModHelpers/InputHelper.cs | 54 +++++++++++++++++++++++++++ src/SMAPI/Framework/ModHelpers/ModHelper.cs | 8 +++- 2 files changed, 61 insertions(+), 1 deletion(-) create mode 100644 src/SMAPI/Framework/ModHelpers/InputHelper.cs (limited to 'src/SMAPI/Framework/ModHelpers') diff --git a/src/SMAPI/Framework/ModHelpers/InputHelper.cs b/src/SMAPI/Framework/ModHelpers/InputHelper.cs new file mode 100644 index 00000000..f4cd12b6 --- /dev/null +++ b/src/SMAPI/Framework/ModHelpers/InputHelper.cs @@ -0,0 +1,54 @@ +using StardewModdingAPI.Framework.Input; + +namespace StardewModdingAPI.Framework.ModHelpers +{ + /// Provides an API for checking and changing input state. + internal class InputHelper : BaseHelper, IInputHelper + { + /********* + ** Accessors + *********/ + /// Manages the game's input state. + private readonly SInputState InputState; + + + /********* + ** Public methods + *********/ + /// Construct an instance. + /// The unique ID of the relevant mod. + /// Manages the game's input state. + public InputHelper(string modID, SInputState inputState) + : base(modID) + { + this.InputState = inputState; + } + + /// Get the current cursor position. + public ICursorPosition GetCursorPosition() + { + return this.InputState.CursorPosition; + } + + /// Get whether a button is currently pressed. + /// The button. + public bool IsDown(SButton button) + { + return this.InputState.IsDown(button); + } + + /// Get whether a button is currently suppressed, so the game won't see it. + /// The button. + public bool IsSuppressed(SButton button) + { + return this.InputState.SuppressButtons.Contains(button); + } + + /// Prevent the game from handling a button press. This doesn't prevent other mods from receiving the event. + /// The button to suppress. + public void Suppress(SButton button) + { + this.InputState.SuppressButtons.Add(button); + } + } +} diff --git a/src/SMAPI/Framework/ModHelpers/ModHelper.cs b/src/SMAPI/Framework/ModHelpers/ModHelper.cs index 92cb9d94..1e07dafa 100644 --- a/src/SMAPI/Framework/ModHelpers/ModHelper.cs +++ b/src/SMAPI/Framework/ModHelpers/ModHelper.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; using StardewModdingAPI.Events; +using StardewModdingAPI.Framework.Input; using StardewModdingAPI.Framework.Models; using StardewModdingAPI.Framework.Serialisation; using StardewModdingAPI.Framework.Utilities; @@ -40,6 +41,9 @@ namespace StardewModdingAPI.Framework.ModHelpers /// An API for loading content assets. public IContentHelper Content { get; } + /// An API for checking and changing input state. + public IInputHelper Input { get; } + /// An API for accessing private game code. public IReflectionHelper Reflection { get; } @@ -63,6 +67,7 @@ namespace StardewModdingAPI.Framework.ModHelpers /// The mod's unique ID. /// The full path to the mod's folder. /// Encapsulate SMAPI's JSON parsing. + /// Manages the game's input state. /// Manages access to events raised by SMAPI. /// An API for loading content assets. /// An API for managing console commands. @@ -75,7 +80,7 @@ namespace StardewModdingAPI.Framework.ModHelpers /// Manages deprecation warnings. /// An argument is null or empty. /// The path does not exist on disk. - public ModHelper(string modID, string modDirectory, JsonHelper jsonHelper, IModEvents events, IContentHelper contentHelper, ICommandHelper commandHelper, IModRegistry modRegistry, IReflectionHelper reflectionHelper, IMultiplayerHelper multiplayer, ITranslationHelper translationHelper, IEnumerable contentPacks, Func createContentPack, DeprecationManager deprecationManager) + public ModHelper(string modID, string modDirectory, JsonHelper jsonHelper, SInputState inputState, IModEvents events, IContentHelper contentHelper, ICommandHelper commandHelper, IModRegistry modRegistry, IReflectionHelper reflectionHelper, IMultiplayerHelper multiplayer, ITranslationHelper translationHelper, IEnumerable contentPacks, Func createContentPack, DeprecationManager deprecationManager) : base(modID) { // validate directory @@ -88,6 +93,7 @@ namespace StardewModdingAPI.Framework.ModHelpers this.DirectoryPath = modDirectory; this.JsonHelper = jsonHelper ?? throw new ArgumentNullException(nameof(jsonHelper)); this.Content = contentHelper ?? throw new ArgumentNullException(nameof(contentHelper)); + this.Input = new InputHelper(modID, inputState); this.ModRegistry = modRegistry ?? throw new ArgumentNullException(nameof(modRegistry)); this.ConsoleCommands = commandHelper ?? throw new ArgumentNullException(nameof(commandHelper)); this.Reflection = reflectionHelper ?? throw new ArgumentNullException(nameof(reflectionHelper)); -- cgit From 625c538f244519700f3942b2b2969845db9a99b0 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Tue, 5 Jun 2018 20:22:46 -0400 Subject: move manifest parsing into toolkit (#532) --- src/SMAPI/Framework/ModHelpers/ModHelper.cs | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) (limited to 'src/SMAPI/Framework/ModHelpers') diff --git a/src/SMAPI/Framework/ModHelpers/ModHelper.cs b/src/SMAPI/Framework/ModHelpers/ModHelper.cs index e8726938..18904857 100644 --- a/src/SMAPI/Framework/ModHelpers/ModHelper.cs +++ b/src/SMAPI/Framework/ModHelpers/ModHelper.cs @@ -5,7 +5,7 @@ using System.Linq; using StardewModdingAPI.Events; using StardewModdingAPI.Framework.Input; using StardewModdingAPI.Framework.Models; -using StardewModdingAPI.Framework.Serialisation; +using StardewModdingAPI.Toolkit.Serialisation; using StardewModdingAPI.Toolkit.Utilities; 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."); // create manifest - IManifest manifest = new Manifest - { - Name = name, - Author = author, - Description = description, - Version = version, - UniqueID = id, - UpdateKeys = new string[0], - ContentPackFor = new ManifestContentPackFor { UniqueID = this.ModID } - }; + IManifest manifest = new Manifest( + uniqueID: id, + name: name, + author: author, + description: description, + version: version, + contentPackFor: new ManifestContentPackFor(this.ModID) + ); // create content pack return this.CreateContentPack(directoryPath, manifest); -- cgit From b08e27d13a1f0c82656df95212fc40588b3b5314 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Sun, 24 Jun 2018 21:51:51 -0400 Subject: merge IManifest interfaces into new project (#532) --- src/SMAPI/Framework/ModHelpers/ModHelper.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/SMAPI/Framework/ModHelpers') diff --git a/src/SMAPI/Framework/ModHelpers/ModHelper.cs b/src/SMAPI/Framework/ModHelpers/ModHelper.cs index 18904857..d9498e83 100644 --- a/src/SMAPI/Framework/ModHelpers/ModHelper.cs +++ b/src/SMAPI/Framework/ModHelpers/ModHelper.cs @@ -4,8 +4,8 @@ using System.IO; using System.Linq; using StardewModdingAPI.Events; using StardewModdingAPI.Framework.Input; -using StardewModdingAPI.Framework.Models; using StardewModdingAPI.Toolkit.Serialisation; +using StardewModdingAPI.Toolkit.Serialisation.Models; using StardewModdingAPI.Toolkit.Utilities; namespace StardewModdingAPI.Framework.ModHelpers @@ -185,7 +185,7 @@ namespace StardewModdingAPI.Framework.ModHelpers author: author, description: description, version: version, - contentPackFor: new ManifestContentPackFor(this.ModID) + contentPackFor: this.ModID ); // create content pack -- cgit