diff --git a/CmlLib/CmlLib.csproj b/CmlLib/CmlLib.csproj index 2dd041f..7094de8 100644 --- a/CmlLib/CmlLib.csproj +++ b/CmlLib/CmlLib.csproj @@ -1,10 +1,10 @@ - + - netcoreapp3.1;net462;net5.0 + net462;netstandard2.0 8.0 enable - 3.3.2 + 3.3.3 Minecraft Launcher Library for .NET Support all version, forge, optifine @@ -19,13 +19,19 @@ Support all version, forge, optifine AlphaBs CmlLib.Core + + + + + + all - + all runtime; build; native; contentfiles; analyzers; buildtransitive @@ -33,8 +39,8 @@ Support all version, forge, optifine all - - + + diff --git a/CmlLib/Core/Auth/MLogin.cs b/CmlLib/Core/Auth/MLogin.cs index 65d385e..f866114 100644 --- a/CmlLib/Core/Auth/MLogin.cs +++ b/CmlLib/Core/Auth/MLogin.cs @@ -109,6 +109,7 @@ private MLoginResponse parseSession(string json, string? clientToken) AccessToken = job["accessToken"]?.ToString(), UUID = profile["id"]?.ToString(), Username = profile["name"]?.ToString(), + UserType = "Mojang", ClientToken = clientToken }; diff --git a/CmlLib/Core/Auth/MSession.cs b/CmlLib/Core/Auth/MSession.cs index 841dee0..874bf69 100644 --- a/CmlLib/Core/Auth/MSession.cs +++ b/CmlLib/Core/Auth/MSession.cs @@ -6,10 +6,10 @@ public class MSession { public MSession() { } - public MSession(string? username, string? accesstoken, string? uuid) + public MSession(string? username, string? accessToken, string? uuid) { Username = username; - AccessToken = accesstoken; + AccessToken = accessToken; UUID = uuid; } @@ -21,6 +21,8 @@ public MSession(string? username, string? accesstoken, string? uuid) public string? UUID { get; set; } [JsonProperty("clientToken")] public string? ClientToken { get; set; } + + public string? UserType { get; set; } public bool CheckIsValid() { @@ -35,7 +37,8 @@ public static MSession GetOfflineSession(string username) { Username = username, AccessToken = "access_token", - UUID = "user_uuid", + UUID = "user_uuid", + UserType = "Mojang", ClientToken = null }; } diff --git a/CmlLib/Core/Downloader/DownloadFileChangedEventArgs.cs b/CmlLib/Core/Downloader/DownloadFileChangedEventArgs.cs index dbc6287..69afa3f 100644 --- a/CmlLib/Core/Downloader/DownloadFileChangedEventArgs.cs +++ b/CmlLib/Core/Downloader/DownloadFileChangedEventArgs.cs @@ -8,15 +8,18 @@ public enum MFile { Runtime, Library, Resource, Minecraft, Others } public class DownloadFileChangedEventArgs : EventArgs { - public DownloadFileChangedEventArgs(MFile kind, object source, string? filename, int total, int progressed) + public DownloadFileChangedEventArgs(MFile type, object source, string? filename, int total, int progressed) { - FileKind = kind; + FileKind = type; + FileType = type; FileName = filename; TotalFileCount = total; ProgressedFileCount = progressed; Source = source; } + // FileType and FileKind is exactly same. + public MFile FileType { get; private set; } public MFile FileKind { get; private set; } public string? FileName { get; private set; } public int TotalFileCount { get; private set; } diff --git a/CmlLib/Core/Launcher/MLaunch.cs b/CmlLib/Core/Launcher/MLaunch.cs index 959f77f..8d0ceb9 100644 --- a/CmlLib/Core/Launcher/MLaunch.cs +++ b/CmlLib/Core/Launcher/MLaunch.cs @@ -12,7 +12,7 @@ public class MLaunch { private const int DefaultServerPort = 25565; - public static readonly string SupportVersion = "1.16.6"; + public static readonly string SupportVersion = "1.17.1"; public readonly static string[] DefaultJavaParameter = { "-XX:+UnlockExperimentalVMOptions", @@ -21,6 +21,7 @@ public class MLaunch "-XX:G1ReservePercent=20", "-XX:MaxGCPauseMillis=50", "-XX:G1HeapRegionSize=16M" + // "-Xss1M" }; public MLaunch(MLaunchOption option) @@ -48,33 +49,8 @@ public Process GetProcess() return mc; } - [MethodTimer.Time] - public string[] CreateArg() + private string createClassPath(MVersion version) { - MVersion version = LaunchOption.GetStartVersion(); - - var args = new List(); - - // Common JVM Arguments - if (LaunchOption.JVMArguments != null) - args.AddRange(LaunchOption.JVMArguments); - else - { - args.AddRange(DefaultJavaParameter); - - if (LaunchOption.MaximumRamMb > 0) - args.Add("-Xmx" + LaunchOption.MaximumRamMb + "m"); - - if (LaunchOption.MinimumRamMb > 0) - args.Add("-Xms" + LaunchOption.MinimumRamMb + "m"); - } - - if (!string.IsNullOrEmpty(LaunchOption.DockName)) - args.Add("-Xdock:name=" + handleEmpty(LaunchOption.DockName)); - if (!string.IsNullOrEmpty(LaunchOption.DockIcon)) - args.Add("-Xdock:icon=" + handleEmpty(LaunchOption.DockIcon)); - - // Version-specific JVM Arguments var classpath = new List(version.Libraries?.Length ?? 1); if (version.Libraries != null) @@ -89,34 +65,36 @@ public string[] CreateArg() classpath.Add(minecraftPath.GetVersionJarPath(version.Jar)); var classpathStr = IOUtil.CombinePath(classpath.ToArray()); + return classpathStr; + } + private string createNativePath(MVersion version) + { var native = new MNative(minecraftPath, version); native.CleanNatives(); var nativePath = native.ExtractNatives(); + return nativePath; + } - var jvmdict = new Dictionary + [MethodTimer.Time] + public string[] CreateArg() + { + MVersion version = LaunchOption.GetStartVersion(); + var args = new List(); + + var classpath = createClassPath(version); + var nativePath = createNativePath(version); + var session = LaunchOption.GetSession(); + + var argDict = new Dictionary { + { "library_directory", minecraftPath.Library }, { "natives_directory", nativePath }, { "launcher_name", useNotNull(LaunchOption.GameLauncherName, "minecraft-launcher") }, { "launcher_version", useNotNull(LaunchOption.GameLauncherVersion, "2") }, - { "classpath", classpathStr } - }; - - if (version.JvmArguments != null) - args.AddRange(Mapper.MapInterpolation(version.JvmArguments, jvmdict)); - else - { - args.Add("-Djava.library.path=" + handleEmpty(nativePath)); - args.Add("-cp " + classpathStr); - } - - if (!string.IsNullOrEmpty(version.MainClass)) - args.Add(version.MainClass); - - // Game Arguments - MSession session = LaunchOption.GetSession(); - var gameDict = new Dictionary - { + { "classpath_separator", Path.PathSeparator.ToString() }, + { "classpath", classpath }, + { "auth_player_name" , session.Username }, { "version_name" , version.Id }, { "game_directory" , minecraftPath.BasePath }, @@ -125,18 +103,55 @@ public string[] CreateArg() { "auth_uuid" , session.UUID }, { "auth_access_token", session.AccessToken }, { "user_properties" , "{}" }, - { "user_type" , "Mojang" }, + { "user_type" , session.UserType ?? "Mojang" }, { "game_assets" , minecraftPath.GetAssetLegacyPath(version.AssetId ?? "legacy") }, { "auth_session" , session.AccessToken }, { "version_type" , useNotNull(LaunchOption.VersionType, version.TypeStr) } }; + // JVM argument + + // version-specific jvm arguments + if (version.JvmArguments != null) + args.AddRange(Mapper.MapInterpolation(version.JvmArguments, argDict)); + + // default jvm arguments + if (LaunchOption.JVMArguments != null) + args.AddRange(LaunchOption.JVMArguments); + else + { + if (LaunchOption.MaximumRamMb > 0) + args.Add("-Xmx" + LaunchOption.MaximumRamMb + "m"); + + if (LaunchOption.MinimumRamMb > 0) + args.Add("-Xms" + LaunchOption.MinimumRamMb + "m"); + + args.AddRange(DefaultJavaParameter); + } + + if (version.JvmArguments == null) + { + args.Add("-Djava.library.path=" + handleEmpty(nativePath)); + args.Add("-cp " + classpath); + } + + // for macOS + if (!string.IsNullOrEmpty(LaunchOption.DockName)) + args.Add("-Xdock:name=" + handleEmpty(LaunchOption.DockName)); + if (!string.IsNullOrEmpty(LaunchOption.DockIcon)) + args.Add("-Xdock:icon=" + handleEmpty(LaunchOption.DockIcon)); + + // main class + if (!string.IsNullOrEmpty(version.MainClass)) + args.Add(version.MainClass); + + // game arguments if (version.GameArguments != null) - args.AddRange(Mapper.MapInterpolation(version.GameArguments, gameDict)); + args.AddRange(Mapper.MapInterpolation(version.GameArguments, argDict)); else if (!string.IsNullOrEmpty(version.MinecraftArguments)) - args.AddRange(Mapper.MapInterpolation(version.MinecraftArguments.Split(' '), gameDict)); + args.AddRange(Mapper.MapInterpolation(version.MinecraftArguments.Split(' '), argDict)); - // Options + // options if (!string.IsNullOrEmpty(LaunchOption.ServerIp)) { args.Add("--server " + handleEmpty(LaunchOption.ServerIp)); diff --git a/CmlLib/Core/Launcher/MNative.cs b/CmlLib/Core/Launcher/MNative.cs index 6b08cbe..ab6247d 100644 --- a/CmlLib/Core/Launcher/MNative.cs +++ b/CmlLib/Core/Launcher/MNative.cs @@ -1,4 +1,6 @@ -using CmlLib.Core.Version; +using System; +using System.Diagnostics; +using CmlLib.Core.Version; using CmlLib.Utils; using System.IO; @@ -25,22 +27,16 @@ public string ExtractNatives() foreach (var item in version.Libraries) { - try + // do not ignore exception + if (item.IsRequire && item.IsNative && !string.IsNullOrEmpty(item.Path)) { - if (item.IsRequire && item.IsNative && !string.IsNullOrEmpty(item.Path)) + string zPath = Path.Combine(gamePath.Library, item.Path); + if (File.Exists(zPath)) { - string zPath = Path.Combine(gamePath.Library, item.Path); - if (File.Exists(zPath)) - { - var z = new SharpZip(zPath); - z.Unzip(path); - } + var z = new SharpZip(zPath); + z.Unzip(path); } } - catch - { - // ignore invalid native library file - } } return path; diff --git a/CmlLib/Core/MRule.cs b/CmlLib/Core/MRule.cs index b751954..e413186 100644 --- a/CmlLib/Core/MRule.cs +++ b/CmlLib/Core/MRule.cs @@ -25,15 +25,8 @@ static MRule() private static string getOSName() { - // Environment.OSVersion.Platform does not work in NET Core -#if NETCOREAPP - if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) - return OSX; - else if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) - return Windows; - else - return Linux; -#elif NETFRAMEWORK + // RuntimeInformation does not work in .NET Framework +#if NETFRAMEWORK var osType = Environment.OSVersion.Platform; if (osType == PlatformID.MacOSX) @@ -42,6 +35,13 @@ private static string getOSName() return Linux; else return Windows; +#else + if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) + return OSX; + else if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + return Windows; + else + return Linux; #endif } diff --git a/CmlLib/Core/Mapper.cs b/CmlLib/Core/Mapper.cs index 3026c95..d4bc6d2 100644 --- a/CmlLib/Core/Mapper.cs +++ b/CmlLib/Core/Mapper.cs @@ -7,7 +7,7 @@ namespace CmlLib.Core { public static class Mapper { - private static Regex argBracket = new Regex(@"\$?\{(.*?)}"); + private static readonly Regex argBracket = new Regex(@"\$?\{(.*?)}"); public static string[] Map(string[] arg, Dictionary dicts, string prepath) { @@ -51,33 +51,24 @@ public static string[] MapPathString(string[] arg, string prepath) public static string Interpolation(string str, Dictionary dicts) { - var sb = new StringBuilder(str); - - var offset = 0; - var m = argBracket.Matches(str); - foreach (Match? item in m) + str = argBracket.Replace(str, new MatchEvaluator((match => { - if (item == null || item.Groups.Count < 2) - continue; - - var outGroup = item.Groups[0]; - - string key = item.Groups[1].Value; - string? value; + if (match.Groups.Count < 2) + return match.Value; - if (dicts.TryGetValue(key, out value)) + var key = match.Groups[1].Value; + if (dicts.TryGetValue(key, out string? value)) { if (value == null) - value = ""; - - replaceByPos(sb, value, outGroup.Index + offset, outGroup.Length); + value = ""; - if (outGroup.Length != value.Length) - offset = value.Length - outGroup.Length; + return value; } - } - return sb.ToString(); + return match.Value; + }))); + + return str; } public static string ToFullPath(string str, string prepath) diff --git a/CmlLib/Core/Version/MVersion.cs b/CmlLib/Core/Version/MVersion.cs index 497e648..b6396ef 100644 --- a/CmlLib/Core/Version/MVersion.cs +++ b/CmlLib/Core/Version/MVersion.cs @@ -70,7 +70,7 @@ public void InheritFrom(MVersion parentVersion) if (nc(JavaVersion)) JavaVersion = parentVersion.JavaVersion; - Jar = parentVersion.Jar; + //Jar = parentVersion.Jar; // Combine @@ -78,6 +78,7 @@ public void InheritFrom(MVersion parentVersion) { if (Libraries != null) Libraries = Libraries.Concat(parentVersion.Libraries).ToArray(); + //Libraries = parentVersion.Libraries.Concat(Libraries).ToArray(); else Libraries = parentVersion.Libraries; } @@ -85,7 +86,8 @@ public void InheritFrom(MVersion parentVersion) if (parentVersion.GameArguments != null) { if (GameArguments != null) - GameArguments = GameArguments.Concat(parentVersion.GameArguments).ToArray(); + //GameArguments = GameArguments.Concat(parentVersion.GameArguments).ToArray(); + GameArguments = parentVersion.GameArguments.Concat(GameArguments).ToArray(); else GameArguments = parentVersion.GameArguments; } @@ -93,7 +95,8 @@ public void InheritFrom(MVersion parentVersion) if (parentVersion.JvmArguments != null) { if (JvmArguments != null) - JvmArguments = JvmArguments.Concat(parentVersion.JvmArguments).ToArray(); + //JvmArguments = JvmArguments.Concat(parentVersion.JvmArguments).ToArray(); + JvmArguments = parentVersion.JvmArguments.Concat(JvmArguments).ToArray(); else JvmArguments = parentVersion.JvmArguments; } diff --git a/CmlLib/Core/Version/MVersionParser.cs b/CmlLib/Core/Version/MVersionParser.cs index f86b86b..6cf1170 100644 --- a/CmlLib/Core/Version/MVersionParser.cs +++ b/CmlLib/Core/Version/MVersionParser.cs @@ -93,7 +93,9 @@ public static MVersion ParseFromJson(string json) version.IsInherited = true; version.ParentVersionId = job["inheritsFrom"]?.ToString(); } - else + + version.Jar = job["jar"]?.ToString(); + if (string.IsNullOrEmpty(version.Jar)) version.Jar = version.Id; return version; diff --git a/CmlLib/Utils/IOUtil.cs b/CmlLib/Utils/IOUtil.cs index ef62007..ad27b40 100644 --- a/CmlLib/Utils/IOUtil.cs +++ b/CmlLib/Utils/IOUtil.cs @@ -175,52 +175,34 @@ public static StreamWriter AsyncStreamWriter(string path, Encoding encoding, boo return new StreamWriter(stream, encoding); } - // In .NET Framework 4.6.2, There is no File.ReadFileTextAsync. so I copied it from .NET Core source code + // In .NET Standard 2.0, There is no File.ReadFileTextAsync. so I copied it from .NET Core source code public static async Task ReadFileAsync(string path) { using var reader = AsyncStreamReader(path, Encoding.UTF8); var content = await reader.ReadToEndAsync() .ConfigureAwait(false); // **MUST be awaited in this scope** - await disposeStreamAsync(reader.BaseStream).ConfigureAwait(false); + await reader.BaseStream.FlushAsync().ConfigureAwait(false); return content; } - - // In .NET Framework 4.6.2, There is no File.WriteFileTextAsync. so I copied it from .NET Core source code + + // In .NET Standard 2.0, There is no File.WriteFileTextAsync. so I copied it from .NET Core source code public static async Task WriteFileAsync(string path, string content) { // UTF8 with BOM might not be recognized by minecraft. not tested var encoder = new UTF8Encoding(false); - var writer = AsyncStreamWriter(path, encoder, false); + using var writer = AsyncStreamWriter(path, encoder, false); await writer.WriteAsync(content).ConfigureAwait(false); // **MUST be awaited in this scope** - -#if NETFRAMEWORK - writer.Dispose(); -#elif NETCOREAPP - await writer.DisposeAsync().ConfigureAwait(false); -#endif + await writer.FlushAsync().ConfigureAwait(false); } public static async Task CopyFileAsync(string sourceFile, string destinationFile) { - var sourceStream = AsyncReadStream(sourceFile); - var destinationStream = AsyncWriteStream(destinationFile, false); + using var sourceStream = AsyncReadStream(sourceFile); + using var destinationStream = AsyncWriteStream(destinationFile, false); await sourceStream.CopyToAsync(destinationStream).ConfigureAwait(false); + await destinationStream.FlushAsync().ConfigureAwait(false); - - await disposeStreamAsync(sourceStream).ConfigureAwait(false); - await disposeStreamAsync(destinationStream).ConfigureAwait(false); - } - - private static Task disposeStreamAsync(Stream stream) - { - // .NET Framework does not support DisposeAsync -#if NETFRAMEWORK - stream.Dispose(); - return Task.CompletedTask; -#elif NETCOREAPP - return stream.DisposeAsync().AsTask(); -#endif } #endregion diff --git a/CmlLibCoreSample/CmlLibCoreSample.csproj b/CmlLibCoreSample/CmlLibCoreSample.csproj index fe782b4..e77fc62 100644 --- a/CmlLibCoreSample/CmlLibCoreSample.csproj +++ b/CmlLibCoreSample/CmlLibCoreSample.csproj @@ -2,7 +2,7 @@ Exe - netcoreapp3.1 + net5.0 diff --git a/CmlLibWinFormSample/App.config b/CmlLibWinFormSample/App.config index 8d23437..ecdcf8a 100644 --- a/CmlLibWinFormSample/App.config +++ b/CmlLibWinFormSample/App.config @@ -1,6 +1,6 @@ - + diff --git a/CmlLibWinFormSample/CmlLibWinFormSample.csproj b/CmlLibWinFormSample/CmlLibWinFormSample.csproj index 6886ec4..3464e0d 100644 --- a/CmlLibWinFormSample/CmlLibWinFormSample.csproj +++ b/CmlLibWinFormSample/CmlLibWinFormSample.csproj @@ -8,10 +8,11 @@ WinExe CmlLibWinFormSample CmlLibWinFormSample - v4.6.2 + v4.7.2 512 true + PackageReference AnyCPU @@ -32,6 +33,9 @@ prompt 4 + + + diff --git a/release.ps1 b/release.ps1 index 873a7e3..555d2b1 100644 --- a/release.ps1 +++ b/release.ps1 @@ -1,9 +1,7 @@ -if ($args.Length -gt 0) -{ - $ver=$args[0] +if ($args.Length -gt 0) { + $ver = $args[0] } -else -{ +else { $ver = Read-Host 'version' } @@ -14,9 +12,8 @@ mkdir .\release\SampleCoreLauncher$ver mkdir .\release\SampleWinformLauncher$ver Copy-Item .\CmlLib\bin\Release\* -Destination .\release\CmlLib.Core.$ver -Recurse -Get-ChildItem .\release\CmlLib.Core.$ver -Recurse -File | Where {($_.Extension -ne ".dll")} | Remove-Item -Copy-Item -Path .\CmlLibCoreSample\bin\Release\netcoreapp3.1\* -Destination .\release\SampleCoreLauncher$ver -Copy-Item .\CmlLibWinFormSample\bin\Release\* -Destination .\release\SampleWinformLauncher$ver -Include *.exe,*.dll,*.pdb,*.config +Get-ChildItem .\release\CmlLib.Core.$ver -Recurse -File | Where-Object { ($_.Extension -ne ".dll") } | Remove-Item +Copy-Item .\CmlLibWinFormSample\bin\Release\* -Destination .\release\SampleWinformLauncher$ver -Include *.exe, *.dll, *.pdb, *.config Compress-Archive -Path .\release\CmlLib.Core.$ver -DestinationPath .\release\CmlLib.Core.$ver.zip Compress-Archive -Path .\release\SampleCoreLauncher$ver -DestinationPath .\release\SampleCoreLauncher$ver.zip