diff --git a/WorkshopToolCommon/Constants.cs b/WorkshopToolCommon/Constants.cs index 0e9d0b6..6c18b87 100644 --- a/WorkshopToolCommon/Constants.cs +++ b/WorkshopToolCommon/Constants.cs @@ -2,7 +2,7 @@ { public static class Constants { - public const string Version = "0.6.0.*"; + public const string Version = "0.6.1.*"; #if SE public const string SEWT_Prefix = "[_SEWT_]"; #else diff --git a/WorkshopToolCommon/GameBase.cs b/WorkshopToolCommon/GameBase.cs index 089cb83..1fcc83e 100644 --- a/WorkshopToolCommon/GameBase.cs +++ b/WorkshopToolCommon/GameBase.cs @@ -84,7 +84,7 @@ public virtual int InitGame(string[] args) options.Worlds == null && options.Collections == null) { - if (!options.ClearSteamCloud) + if (!options.ClearSteamCloud && !options.ListDLCs) { System.Console.WriteLine(CommandLine.Text.HelpText.AutoBuild(options).ToString()); return Cleanup(1); @@ -114,7 +114,7 @@ public virtual int InitGame(string[] args) options.Upload = false; } - + MySandboxGame.Log.WriteLineAndConsole($"{AppName} {Assembly.GetExecutingAssembly().GetName().Version}"); ParameterInfo[] parameters; @@ -147,6 +147,8 @@ public virtual int InitGame(string[] args) Task = DownloadMods(options); else if (options.ClearSteamCloud) Task = ClearSteamCloud(options.DeleteSteamCloudFiles, options.Force); + else if (options.ListDLCs) + Task = System.Threading.Tasks.Task.Factory.StartNew(()=> { ListDLCs(); return true; }); else Task = UploadMods(options); @@ -421,7 +423,7 @@ static bool ProcessItemsUpload(WorkshopType type, List paths, Options op tags = tags[0].Split(',', ';'); } - var mod = new Uploader(type, pathname, tags, options.ExcludeExtensions, options.Compile, options.DryRun, options.Development, options.Visibility, options.Force, options.Thumbnail); + var mod = new Uploader(type, pathname, tags, options.ExcludeExtensions, options.IgnorePaths, options.Compile, options.DryRun, options.Development, options.Visibility, options.Force, options.Thumbnail, options.DLCs); if (options.UpdateOnly && mod.ModId == 0) { MySandboxGame.Log.WriteLineAndConsole(string.Format("--update-only passed, skipping: {0}", mod.Title)); @@ -665,6 +667,15 @@ static List GetGlobbedPaths(string[] paths) } #endregion Pathing + private void ListDLCs() + { + MySandboxGame.Log.WriteLineAndConsole("Valid DLC:"); + foreach (var dlc in Sandbox.Game.MyDLCs.DLCs.Values) + { + MySandboxGame.Log.WriteLineAndConsole($"Name: {dlc.Name}, ID: {dlc.AppId}"); + } + } + static string[] CombineCollectionWithList(WorkshopType type, List items, string[] existingitems) { var tempList = new List(); diff --git a/WorkshopToolCommon/Options.cs b/WorkshopToolCommon/Options.cs index 85235e1..fb0eb7b 100644 --- a/WorkshopToolCommon/Options.cs +++ b/WorkshopToolCommon/Options.cs @@ -5,6 +5,8 @@ namespace Phoenix.WorkshopTool { public sealed class Options { + private const string OptionSet = "MainFunctions"; + [Option("visibility", DefaultValue = null, HelpText = "Sets mod visibility (for new only). Accepted values: Public, FriendsOnly, Private")] public MyPublishedFileVisibility? Visibility { get; set; } @@ -17,10 +19,10 @@ public sealed class Options [Option('d', "dry-run", DefaultValue = false, HelpText = "Only run a test, do not actually upload. Useful with --compile")] public bool DryRun { get; set; } - [Option("download", DefaultValue = false, HelpText = "Download mods")] + [Option("download", DefaultValue = false, HelpText = "Download mods", MutuallyExclusiveSet = OptionSet)] public bool Download { get; set; } - [Option("upload", DefaultValue = false, HelpText = "Upload and publish mods")] + [Option("upload", DefaultValue = false, HelpText = "Upload and publish mods", MutuallyExclusiveSet = OptionSet)] public bool Upload { get; set; } [Option('e', "extract", DefaultValue = false, HelpText = "Extract downloaded mods (valid for download only)")] @@ -29,13 +31,16 @@ public sealed class Options [Option('u', "update-only", DefaultValue = false, HelpText = "Only update existing mods (don't upload new)")] public bool UpdateOnly { get; set; } - [OptionArray('x', "exclude", HelpText = "List of extensions to exclude from archiving for upload")] + [OptionArray('x', "exclude", HelpText = "List of extensions to exclude from upload")] public string[] ExcludeExtensions { get; set; } + [OptionArray("ignore", HelpText = "List of paths to exclude from upload")] + public string[] IgnorePaths { get; set; } + [Option('f', "force", DefaultValue = false, HelpText = "Force operation. USE WITH CAUTION! (not valid everywhere)")] public bool Force { get; set; } - [OptionArray('m', "mods", HelpText = "List of directories of mods to upload; or Workshop ID of mods to download (when in download mode). Use quotes if spaces.")] + [OptionArray('m', "mods", HelpText = "List of directories of mods to upload; or Workshop ID of mods to download (when in download mode), use quotes if spaces")] public string[] ModPaths { get; set; } [OptionArray('b', "blueprints", HelpText = "List of directories of blueprints to upload; or Workshop ID of blueprints to download (when in download mode)")] @@ -60,10 +65,20 @@ public sealed class Options [Option("thumb", HelpText = "Thumbnail to upload (doesn't re-upload mod)")] public string Thumbnail { get; set; } - [Option("clearsteamcloud", DefaultValue = false, HelpText = "Clear Steam Cloud (WARNING!). THIS WILL DELETE YOUR STEAM CLOUD FOR SE! Use with --force to actually delete.")] + [Option("clearsteamcloud", DefaultValue = false, HelpText = "Clear Steam Cloud (WARNING!). THIS WILL DELETE YOUR STEAM CLOUD FOR SE! Use with --force to actually delete.", MutuallyExclusiveSet = OptionSet)] public bool ClearSteamCloud { get; set; } - [OptionArray("deletecloudfile", HelpText = "Delete individual file or files from the Steam Cloud.")] + [OptionArray("deletecloudfile", HelpText = "Delete individual file or files from the Steam Cloud")] public string[] DeleteSteamCloudFiles { get; set; } + +#if SE + [Option("listdlc", HelpText = "List available DLCs", MutuallyExclusiveSet = OptionSet)] +#endif + public bool ListDLCs { get; set; } + +#if SE + [OptionArray("dlc", HelpText = "Add DLC dependency to mod, accepts numeric ID or name")] +#endif + public string[] DLCs { get; set; } } } diff --git a/WorkshopToolCommon/Uploader.cs b/WorkshopToolCommon/Uploader.cs index daec261..3ed7325 100644 --- a/WorkshopToolCommon/Uploader.cs +++ b/WorkshopToolCommon/Uploader.cs @@ -36,6 +36,7 @@ class Uploader : IMod static MySteamService MySteam { get => (MySteamService)MyServiceManager.Instance.GetService(); } readonly HashSet m_ignoredExtensions = new HashSet(); readonly HashSet m_ignoredPaths = new HashSet(); + uint[] m_dlcs; string m_modPath; bool m_compile; bool m_dryrun; @@ -52,10 +53,11 @@ class Uploader : IMod private static PublishItemBlocking _publishMethod; private static LoadScripts _compileMethod; - private delegate ulong PublishItemBlocking(string localFolder, string publishedTitle, string publishedDescription, ulong? workshopId, MyPublishedFileVisibility visibility, string[] tags, HashSet ignoredExtensions = null, HashSet ignoredPaths = null); #if SE + private delegate ulong PublishItemBlocking(string localFolder, string publishedTitle, string publishedDescription, ulong? workshopId, MyPublishedFileVisibility visibility, string[] tags, HashSet ignoredExtensions = null, HashSet ignoredPaths = null, uint[] requiredDLCs = null); private delegate void LoadScripts(string path, MyModContext mod = null); #else + private delegate ulong PublishItemBlocking(string localFolder, string publishedTitle, string publishedDescription, ulong? workshopId, MyPublishedFileVisibility visibility, string[] tags, HashSet ignoredExtensions = null, HashSet ignoredPaths = null); private delegate void LoadScripts(MyModContext mod = null); #endif @@ -63,7 +65,7 @@ class Uploader : IMod public ulong ModId { get { return m_modId; } } public string ModPath { get { return m_modPath; } } - public Uploader(WorkshopType type, string path, string[] tags = null, string[] ignoredExtensions = null, bool compile = false, bool dryrun = false, bool development = false, MyPublishedFileVisibility? visibility = null, bool force = false, string previewFilename = null) + public Uploader(WorkshopType type, string path, string[] tags = null, string[] ignoredExtensions = null, string[] ignoredPaths = null, bool compile = false, bool dryrun = false, bool development = false, MyPublishedFileVisibility? visibility = null, bool force = false, string previewFilename = null, string[] dlcs = null) { m_modPath = path; m_modId = MyWorkshop.GetWorkshopIdFromLocalMod(m_modPath); @@ -79,6 +81,9 @@ public Uploader(WorkshopType type, string path, string[] tags = null, string[] i m_isDev = development; m_force = force; m_previewFilename = previewFilename; +#if SE + m_dlcs = MapDLCStringsToInts(dlcs); +#endif if( tags != null ) m_tags = tags; @@ -106,9 +111,38 @@ public Uploader(WorkshopType type, string path, string[] tags = null, string[] i ignoredExtensions.ForEach(s => m_ignoredExtensions.Add(s)); } + if (ignoredPaths != null) + { + ignoredPaths.ForEach(s => m_ignoredPaths.Add(s)); + } + SetupReflection(); } +#if SE + private uint[] MapDLCStringsToInts(string[] stringdlcs) + { + var dlcs = new HashSet(); + foreach (var dlc in stringdlcs) + { + uint value; + if (uint.TryParse(dlc, out value)) + { + dlcs.Add(value); + } + else + { + Sandbox.Game.MyDLCs.MyDLC dlcvalue; + if (Sandbox.Game.MyDLCs.TryGetDLC(dlc, out dlcvalue)) + dlcs.Add(dlcvalue.AppId); + else + MySandboxGame.Log.WriteLineAndConsole($"Invalid DLC specified: {dlc}"); + } + } + return dlcs.ToArray(); + } +#endif + private void SetupReflection() { if (m_compile && m_type == WorkshopType.Mod) @@ -281,6 +315,9 @@ public bool Publish() // Process Tags ProcessTags(); + if(m_dlcs?.Length > 0) + MySandboxGame.Log.WriteLineAndConsole(string.Format("Setting DLC requirement: {0}", string.Join(", ", m_dlcs))); + if (m_dryrun) { MySandboxGame.Log.WriteLineAndConsole("DRY-RUN; Publish skipped"); @@ -289,7 +326,7 @@ public bool Publish() { if (_publishMethod != null) { - m_modId = _publishMethod(m_modPath, m_title, null, m_modId, m_visibility ?? MyPublishedFileVisibility.Public, m_tags, m_ignoredExtensions, m_ignoredPaths); + m_modId = _publishMethod(m_modPath, m_title, null, m_modId, m_visibility ?? MyPublishedFileVisibility.Public, m_tags, m_ignoredExtensions, m_ignoredPaths, m_dlcs); } else { @@ -339,6 +376,7 @@ bool FillPropertiesFromPublished() if (m_visibility == null) m_visibility = results[0].Visibility; + m_dlcs = results[0].DLCs.ToArray(); MyDebug.AssertDebug(owner == MySteam.UserId); if (owner != MySteam.UserId) @@ -510,6 +548,7 @@ public bool UpdatePreviewFileOrTags() publisher.Visibility = m_visibility ?? MyPublishedFileVisibility.Private; publisher.Thumbnail = m_previewFilename; publisher.Tags = new List(m_tags); + publisher.DLCs = new HashSet(m_dlcs); AutoResetEvent resetEvent = new AutoResetEvent(false); try @@ -528,6 +567,9 @@ public bool UpdatePreviewFileOrTags() resetEvent.Set(); }); + if (m_dlcs?.Length > 0) + MySandboxGame.Log.WriteLineAndConsole(string.Format("Setting DLC requirement: {0}", string.Join(", ", m_dlcs))); + publisher.Publish(); if (!resetEvent.WaitOne())