diff options
Diffstat (limited to 'src/SMAPI.ModBuildConfig/Framework/ModFileManager.cs')
-rw-r--r-- | src/SMAPI.ModBuildConfig/Framework/ModFileManager.cs | 124 |
1 files changed, 98 insertions, 26 deletions
diff --git a/src/SMAPI.ModBuildConfig/Framework/ModFileManager.cs b/src/SMAPI.ModBuildConfig/Framework/ModFileManager.cs index fbb91193..ad4ffdf9 100644 --- a/src/SMAPI.ModBuildConfig/Framework/ModFileManager.cs +++ b/src/SMAPI.ModBuildConfig/Framework/ModFileManager.cs @@ -21,6 +21,45 @@ namespace StardewModdingAPI.ModBuildConfig.Framework /// <summary>The files that are part of the package.</summary> private readonly IDictionary<string, FileInfo> Files; + /// <summary>The file extensions used by assembly files.</summary> + private readonly ISet<string> AssemblyFileExtensions = new HashSet<string>(StringComparer.OrdinalIgnoreCase) + { + ".dll", + ".exe", + ".pdb", + ".xml" + }; + + /// <summary>The DLLs which match the <see cref="ExtraAssemblyTypes.Game"/> type.</summary> + private readonly ISet<string> GameDllNames = new HashSet<string> + { + // SMAPI + "0Harmony", + "Mono.Cecil", + "Mono.Cecil.Mdb", + "Mono.Cecil.Pdb", + "MonoMod.Common", + "Newtonsoft.Json", + "StardewModdingAPI", + "SMAPI.Toolkit", + "SMAPI.Toolkit.CoreInterfaces", + "TMXTile", + + // game + framework + "BmFont", + "FAudio-CS", + "GalaxyCSharp", + "GalaxyCSharpGlue", + "Lidgren.Network", + "MonoGame.Framework", + "SkiaSharp", + "Stardew Valley", + "StardewValley.GameData", + "Steamworks.NET", + "TextCopy", + "xTile" + }; + /********* ** Public methods @@ -30,9 +69,11 @@ namespace StardewModdingAPI.ModBuildConfig.Framework /// <param name="targetDir">The folder containing the build output.</param> /// <param name="ignoreFilePaths">The custom relative file paths provided by the user to ignore.</param> /// <param name="ignoreFilePatterns">Custom regex patterns matching files to ignore when deploying or zipping the mod.</param> + /// <param name="bundleAssemblyTypes">The extra assembly types which should be bundled with the mod.</param> + /// <param name="modDllName">The name (without extension or path) for the current mod's DLL.</param> /// <param name="validateRequiredModFiles">Whether to validate that required mod files like the manifest are present.</param> /// <exception cref="UserErrorException">The mod package isn't valid.</exception> - public ModFileManager(string projectDir, string targetDir, string[] ignoreFilePaths, Regex[] ignoreFilePatterns, bool validateRequiredModFiles) + public ModFileManager(string projectDir, string targetDir, string[] ignoreFilePaths, Regex[] ignoreFilePatterns, ExtraAssemblyTypes bundleAssemblyTypes, string modDllName, bool validateRequiredModFiles) { this.Files = new Dictionary<string, FileInfo>(StringComparer.OrdinalIgnoreCase); @@ -48,7 +89,7 @@ namespace StardewModdingAPI.ModBuildConfig.Framework string relativePath = entry.Item1; FileInfo file = entry.Item2; - if (!this.ShouldIgnore(file, relativePath, ignoreFilePaths, ignoreFilePatterns)) + if (!this.ShouldIgnore(file, relativePath, ignoreFilePaths, ignoreFilePatterns, bundleAssemblyTypes, modDllName)) this.Files[relativePath] = file; } @@ -152,39 +193,70 @@ namespace StardewModdingAPI.ModBuildConfig.Framework /// <param name="relativePath">The file's relative path in the package.</param> /// <param name="ignoreFilePaths">The custom relative file paths provided by the user to ignore.</param> /// <param name="ignoreFilePatterns">Custom regex patterns matching files to ignore when deploying or zipping the mod.</param> - private bool ShouldIgnore(FileInfo file, string relativePath, string[] ignoreFilePaths, Regex[] ignoreFilePatterns) + /// <param name="bundleAssemblyTypes">The extra assembly types which should be bundled with the mod.</param> + /// <param name="modDllName">The name (without extension or path) for the current mod's DLL.</param> + private bool ShouldIgnore(FileInfo file, string relativePath, string[] ignoreFilePaths, Regex[] ignoreFilePatterns, ExtraAssemblyTypes bundleAssemblyTypes, string modDllName) { - bool IsAssemblyFile(string baseName) + // apply custom patterns + if (ignoreFilePaths.Any(p => p == relativePath) || ignoreFilePatterns.Any(p => p.IsMatch(relativePath))) + return true; + + // ignore unneeded files + { + bool shouldIgnore = + // release zips + this.EqualsInvariant(file.Extension, ".zip") + + // *.deps.json (only SMAPI's top-level one is used) + || file.Name.EndsWith(".deps.json") + + // code analysis files + || file.Name.EndsWith(".CodeAnalysisLog.xml", StringComparison.OrdinalIgnoreCase) + || file.Name.EndsWith(".lastcodeanalysissucceeded", StringComparison.OrdinalIgnoreCase) + + // translation class builder (not used at runtime) + || ( + file.Name.StartsWith("Pathoschild.Stardew.ModTranslationClassBuilder") + && this.AssemblyFileExtensions.Contains(file.Extension) + ) + + // OS metadata files + || this.EqualsInvariant(file.Name, ".DS_Store") + || this.EqualsInvariant(file.Name, "Thumbs.db"); + if (shouldIgnore) + return true; + } + + // check for bundled assembly types + // When bundleAssemblyTypes is set, *all* dependencies are copied into the build output but only those which match the given assembly types should be bundled. + if (bundleAssemblyTypes != ExtraAssemblyTypes.None) { - return - this.EqualsInvariant(file.Name, $"{baseName}.dll") - || this.EqualsInvariant(file.Name, $"{baseName}.pdb") - || this.EqualsInvariant(file.Name, $"{baseName}.xnb"); + var type = this.GetExtraAssemblyType(file, modDllName); + if (type != ExtraAssemblyTypes.None && !bundleAssemblyTypes.HasFlag(type)) + return true; } - return - // release zips - this.EqualsInvariant(file.Extension, ".zip") + return false; + } - // unneeded *.deps.json (only SMAPI's top-level one is used) - || file.Name.EndsWith(".deps.json") + /// <summary>Get the extra assembly type for a file, assuming that the user specified one or more extra types to bundle.</summary> + /// <param name="file">The file to check.</param> + /// <param name="modDllName">The name (without extension or path) for the current mod's DLL.</param> + private ExtraAssemblyTypes GetExtraAssemblyType(FileInfo file, string modDllName) + { + string baseName = Path.GetFileNameWithoutExtension(file.Name); + string extension = file.Extension; - // dependencies bundled with SMAPI - || IsAssemblyFile("0Harmony") - || IsAssemblyFile("Newtonsoft.Json") - || IsAssemblyFile("Pathoschild.Stardew.ModTranslationClassBuilder") // not used at runtime + if (baseName == modDllName || !this.AssemblyFileExtensions.Contains(extension)) + return ExtraAssemblyTypes.None; - // code analysis files - || file.Name.EndsWith(".CodeAnalysisLog.xml", StringComparison.OrdinalIgnoreCase) - || file.Name.EndsWith(".lastcodeanalysissucceeded", StringComparison.OrdinalIgnoreCase) + if (this.GameDllNames.Contains(baseName)) + return ExtraAssemblyTypes.Game; - // OS metadata files - || this.EqualsInvariant(file.Name, ".DS_Store") - || this.EqualsInvariant(file.Name, "Thumbs.db") + if (baseName.StartsWith("System.", StringComparison.OrdinalIgnoreCase) || baseName.StartsWith("Microsoft.", StringComparison.OrdinalIgnoreCase)) + return ExtraAssemblyTypes.System; - // custom ignore patterns - || ignoreFilePaths.Any(p => p == relativePath) - || ignoreFilePatterns.Any(p => p.IsMatch(relativePath)); + return ExtraAssemblyTypes.ThirdParty; } /// <summary>Get whether a string is equal to another case-insensitively.</summary> |