From 8a5ca535198fecf0a0e6714eef180e883b5eba61 Mon Sep 17 00:00:00 2001 From: Harrison Deng Date: Wed, 18 May 2022 22:06:39 -0500 Subject: [PATCH] Set up options and arguments for install command. --- .vscode/launch.json | 26 ++++++++ .vscode/settings.json | 5 ++ .vscode/tasks.json | 41 ++++++++++++ MCCFMD/Commands/Install.cs | 55 ++++++++++++++++ MCCFMD/MCCFMD.csproj | 8 ++- MCCFMD/Program.cs | 23 ++++++- MCCFMD/Serialization/ManifestConverter.cs | 77 +++++++++++++++++++++++ MCCFMD/Serialization/ManifestGames.cs | 4 ++ MCCFMD/Serialization/Modpack/File.cs | 9 +++ MCCFMD/Serialization/Modpack/Game.cs | 12 ++++ MCCFMD/Serialization/Modpack/Manifest.cs | 19 ++++++ MCCFMD/Serialization/Modpack/ModLoader.cs | 8 +++ MCCFMD/Serialization/ProfileReader.cs | 7 +++ 13 files changed, 290 insertions(+), 4 deletions(-) create mode 100644 .vscode/launch.json create mode 100644 .vscode/settings.json create mode 100644 .vscode/tasks.json create mode 100644 MCCFMD/Commands/Install.cs create mode 100644 MCCFMD/Serialization/ManifestConverter.cs create mode 100644 MCCFMD/Serialization/ManifestGames.cs create mode 100644 MCCFMD/Serialization/Modpack/File.cs create mode 100644 MCCFMD/Serialization/Modpack/Game.cs create mode 100644 MCCFMD/Serialization/Modpack/Manifest.cs create mode 100644 MCCFMD/Serialization/Modpack/ModLoader.cs create mode 100644 MCCFMD/Serialization/ProfileReader.cs diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..05438c7 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,26 @@ +{ + "version": "0.2.0", + "configurations": [ + { + // Use IntelliSense to find out which attributes exist for C# debugging + // Use hover for the description of the existing attributes + // For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md + "name": ".NET Core Launch (console)", + "type": "coreclr", + "request": "launch", + "preLaunchTask": "build", + // If you have changed target frameworks, make sure to update the program path. + "program": "${workspaceFolder}/MCCFMD/bin/Debug/net6.0/MCCFMD.dll", + "args": [], + "cwd": "${workspaceFolder}/MCCFMD", + // For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console + "console": "internalConsole", + "stopAtEntry": false + }, + { + "name": ".NET Core Attach", + "type": "coreclr", + "request": "attach" + } + ] +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..5f7a336 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "cSpell.words": [ + "MCCFMD" + ] +} \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..c68aa27 --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,41 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "build", + "command": "dotnet", + "type": "process", + "args": [ + "build", + "${workspaceFolder}/MCCFMD/MCCFMD.csproj", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary" + ], + "problemMatcher": "$msCompile" + }, + { + "label": "publish", + "command": "dotnet", + "type": "process", + "args": [ + "publish", + "${workspaceFolder}/MCCFMD/MCCFMD.csproj", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary" + ], + "problemMatcher": "$msCompile" + }, + { + "label": "watch", + "command": "dotnet", + "type": "process", + "args": [ + "watch", + "run", + "--project", + "${workspaceFolder}/MCCFMD/MCCFMD.csproj" + ], + "problemMatcher": "$msCompile" + } + ] +} \ No newline at end of file diff --git a/MCCFMD/Commands/Install.cs b/MCCFMD/Commands/Install.cs new file mode 100644 index 0000000..6cf65ce --- /dev/null +++ b/MCCFMD/Commands/Install.cs @@ -0,0 +1,55 @@ +using System.Collections; +using System.Collections.Generic; +using System.IO; +using System.CommandLine; +using System.Threading.Tasks; + +namespace MCCFMD.Commands +{ + public class Install : Command + { + const string NAME = "install"; + const string DESC = "Install the profile described by the manifest."; + public Install(DirectoryInfo workspaceDir) : base(NAME, DESC) + { + Argument profileFile = new Argument("profile", "The .zip file describing the profile to install."); + Add(profileFile); + + Option destination = new Option("--destination", "Where to install the profile."); + destination.AddAlias("-d"); + Add(destination); + + Option server = new Option("--server", "Install server files."); + server.AddAlias("-s"); + Add(server); + + Option client = new Option("--client", "Install files in local client."); + client.AddAlias("-c"); + Add(client); + + Option fileExclude = new Option("--exclude-file", "Excludes files with IDs listed in a given file."); + fileExclude.AddAlias("-E"); + Add(fileExclude); + + Option fileInclude = new Option("--include-file", "Includes files with IDs listed in a given file."); + fileInclude.AddAlias("-I"); + Add(fileInclude); + + Option> excludeIds = new Option> + ("--exclude-id", "Excludes the files with the given IDs."); + excludeIds.AllowMultipleArgumentsPerToken = true; + excludeIds.AddAlias("-e"); + Add(excludeIds); + + Option> includeIds = new Option>("--include-id", "Include the files with the given IDs"); + includeIds.AllowMultipleArgumentsPerToken = true; + includeIds.AddAlias("-i"); + Add(includeIds); + + this.SetHandler(async (FileInfo profileFile, DirectoryInfo? dest, bool server, bool client, FileInfo? fileExclude, FileInfo? fileInclude, IEnumerable excludeIds, IEnumerable includeIds) => + { + + }, profileFile, destination, client, fileExclude, fileInclude, excludeIds, includeIds); + } + } +} \ No newline at end of file diff --git a/MCCFMD/MCCFMD.csproj b/MCCFMD/MCCFMD.csproj index 40c60dd..ad37455 100644 --- a/MCCFMD/MCCFMD.csproj +++ b/MCCFMD/MCCFMD.csproj @@ -3,8 +3,12 @@ Exe net6.0 - enable + false enable - + + + + + \ No newline at end of file diff --git a/MCCFMD/Program.cs b/MCCFMD/Program.cs index 83fa4f4..48a3824 100644 --- a/MCCFMD/Program.cs +++ b/MCCFMD/Program.cs @@ -1,2 +1,21 @@ -// See https://aka.ms/new-console-template for more information -Console.WriteLine("Hello, World!"); +using System.IO; +using System; +using System.CommandLine; +using System.Threading.Tasks; +using MCCFMD.Commands; + +namespace MCCFMD +{ + internal class Program + { + // See: https://docs.microsoft.com/en-us/dotnet/core/tutorials/top-level-templates + static async Task Main(string[] args) + { + DirectoryInfo workspace = new DirectoryInfo(Path.Combine(Path.GetTempPath(), Path.GetRandomFileName())); + Directory.CreateDirectory(workspace.FullName); + RootCommand rootCmd = new RootCommand("CLI utility for creating, editing, and installing Curseforge profiles."); + rootCmd.Add(new Install(workspace)); + return await rootCmd.InvokeAsync(args); + } + } +} \ No newline at end of file diff --git a/MCCFMD/Serialization/ManifestConverter.cs b/MCCFMD/Serialization/ManifestConverter.cs new file mode 100644 index 0000000..bbc4f09 --- /dev/null +++ b/MCCFMD/Serialization/ManifestConverter.cs @@ -0,0 +1,77 @@ +using System.Collections.Generic; +using System.Reflection; +using System.Linq; +using System; +using System.Text.Json; +using System.Text.Json.Serialization; +using MCCFMD.Serialization.Modpack; + +namespace MCCFMD.Serialization +{ + public class ManifestConverter : JsonConverter + { + PropertyInfo[] manifestProperties; + Type manifestType; + + public ManifestConverter() + { + manifestType = typeof(Manifest); + manifestProperties = manifestType.GetProperties(); + } + public override Manifest Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + string[] propertyNames = new string[manifestProperties.Length]; + for (int i = 0; i < propertyNames.Length; i++) propertyNames[i] = manifestProperties[i].Name; + Manifest result = new Manifest(); + HashSet pendingProperties = new HashSet(propertyNames); + while (reader.Read()) + { + if (reader.TokenType == JsonTokenType.EndObject) + { + if (pendingProperties.Count != 0) + { + throw new JsonException("Manifest is missing data. Will not proceed."); + } + return result; + } + + if (reader.TokenType == JsonTokenType.PropertyName) + { + string propertyName = reader.GetString() ?? throw new JsonException(); + if (propertyNames.Contains(propertyName)) + { + PropertyInfo property = manifestProperties[Array.IndexOf(propertyNames, propertyName)]; + pendingProperties.Remove(propertyName); + property.SetValue(result, JsonSerializer.Deserialize(ref reader, property.PropertyType, options)); + } + else if (Enum.GetNames(typeof(ManifestGames)).Contains(propertyName, StringComparer.CurrentCultureIgnoreCase)) + { + Game game = JsonSerializer.Deserialize(ref reader); + game.gameType = Enum.Parse(propertyName, true); + result.game = game; + } + } + else + { + throw new JsonException(); + } + } + throw new JsonException(); // Reached end of stream and did not find ending token. + } + + public override void Write(Utf8JsonWriter writer, Manifest value, JsonSerializerOptions options) + { + writer.WriteStartObject(); + writer.WritePropertyName(value.game.gameType.ToString().ToLower()); + JsonSerializer.Serialize(writer, value.game, typeof(Game), options); + for (int i = 0; i < manifestProperties.Length; i++) + { + PropertyInfo property = manifestProperties[i]; + writer.WritePropertyName(property.Name); + JsonSerializer.Serialize(writer, property.GetValue(value), property.PropertyType, options); + } + + writer.WriteEndObject(); + } + } +} \ No newline at end of file diff --git a/MCCFMD/Serialization/ManifestGames.cs b/MCCFMD/Serialization/ManifestGames.cs new file mode 100644 index 0000000..a80540f --- /dev/null +++ b/MCCFMD/Serialization/ManifestGames.cs @@ -0,0 +1,4 @@ +public enum ManifestGames +{ + Minecraft +} \ No newline at end of file diff --git a/MCCFMD/Serialization/Modpack/File.cs b/MCCFMD/Serialization/Modpack/File.cs new file mode 100644 index 0000000..745a51c --- /dev/null +++ b/MCCFMD/Serialization/Modpack/File.cs @@ -0,0 +1,9 @@ +namespace MCCFMD.Serialization.Modpack +{ + public struct File + { + public string ProjectId { get; set; } + public string FileId { get; set; } + public bool Required { get; set; } + } +} \ No newline at end of file diff --git a/MCCFMD/Serialization/Modpack/Game.cs b/MCCFMD/Serialization/Modpack/Game.cs new file mode 100644 index 0000000..ef1e7fd --- /dev/null +++ b/MCCFMD/Serialization/Modpack/Game.cs @@ -0,0 +1,12 @@ +using System.Collections.Generic; +using System.Text.Json.Serialization; +namespace MCCFMD.Serialization.Modpack +{ + public struct Game + { + [JsonIgnore] + public ManifestGames gameType; + public string Version { get; set; } + public IList ModLoaders { get; set; } + } +} \ No newline at end of file diff --git a/MCCFMD/Serialization/Modpack/Manifest.cs b/MCCFMD/Serialization/Modpack/Manifest.cs new file mode 100644 index 0000000..2fa6863 --- /dev/null +++ b/MCCFMD/Serialization/Modpack/Manifest.cs @@ -0,0 +1,19 @@ +using System.Collections.Generic; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace MCCFMD.Serialization.Modpack +{ + public struct Manifest + { + [JsonIgnore] + public Game game; + public string ManifestType { get; set; } + public int ManifestVersion { get; set; } + public string Name { get; set; } + public string Version { get; set; } + public string Author { get; set; } + public IList Files { get; set; } + public string Overrides { get; set; } + } +} \ No newline at end of file diff --git a/MCCFMD/Serialization/Modpack/ModLoader.cs b/MCCFMD/Serialization/Modpack/ModLoader.cs new file mode 100644 index 0000000..379648d --- /dev/null +++ b/MCCFMD/Serialization/Modpack/ModLoader.cs @@ -0,0 +1,8 @@ +namespace MCCFMD.Serialization.Modpack +{ + public struct ModLoader + { + public string Id { get; set; } + public bool Primary { get; set; } + } +} \ No newline at end of file diff --git a/MCCFMD/Serialization/ProfileReader.cs b/MCCFMD/Serialization/ProfileReader.cs new file mode 100644 index 0000000..e684fbe --- /dev/null +++ b/MCCFMD/Serialization/ProfileReader.cs @@ -0,0 +1,7 @@ +namespace MCCFMD.Serialization +{ + internal class ProfileReader + { + + } +} \ No newline at end of file