From 3b8de89309dfc1e3306dd70746d599f431b5768a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BE=99=E8=85=BE=E7=8C=AB=E8=B7=83?= <1043137532@qq.com> Date: Tue, 12 Sep 2023 00:55:44 +0800 Subject: [PATCH] 2.6.8 --- Plain Craft Launcher 2/Application.xaml | 4 +- Plain Craft Launcher 2/Application.xaml.vb | 8 + Plain Craft Launcher 2/Controls/MyCard.vb | 4 - .../Controls/MyExtraButton.xaml | 4 +- .../Controls/MyExtraButton.xaml.vb | 4 +- Plain Craft Launcher 2/Controls/MyPageLeft.vb | 48 +-- .../Controls/MyScrollViewer.vb | 6 +- Plain Craft Launcher 2/FormMain.xaml.vb | 24 ++ .../Modules/Base/ModBase.vb | 44 ++- .../Modules/Base/ModLoader.vb | 23 +- .../Modules/Base/MyBitmap.vb | 40 +-- .../Modules/Minecraft/ModComp.vb | 13 +- .../Modules/Minecraft/ModCrash.vb | 255 ++++++++------ .../Modules/Minecraft/ModLaunch.vb | 30 +- .../Modules/Minecraft/ModModpack.vb | 32 +- Plain Craft Launcher 2/Modules/ModMusic.vb | 4 +- .../My Project/AssemblyInfo.vb | 4 +- .../Pages/PageDownload/ModDownloadLib.vb | 182 +++++----- .../PageDownload/PageDownloadInstall.xaml.vb | 4 +- .../Pages/PageLaunch/MySkin.xaml.vb | 4 +- .../Pages/PageLaunch/PageLaunchLeft.xaml.vb | 9 +- .../Pages/PageLink/PageLinkIoi.xaml.vb | 2 +- .../PageOther/PageOtherHelpDetail.xaml.vb | 2 +- .../Pages/PageSelectRight.xaml.vb | 1 + .../Pages/PageSetup/PageSetupSystem.xaml | 2 +- .../Pages/PageSpeedLeft.xaml.vb | 1 - Plain Craft Launcher 2/Resources/Custom.xaml | 312 +++++++++++------- Plain Craft Launcher 2/Resources/Help.zip | Bin 74683 -> 76759 bytes 28 files changed, 615 insertions(+), 451 deletions(-) diff --git a/Plain Craft Launcher 2/Application.xaml b/Plain Craft Launcher 2/Application.xaml index 8fc582a..7a25967 100644 --- a/Plain Craft Launcher 2/Application.xaml +++ b/Plain Craft Launcher 2/Application.xaml @@ -133,7 +133,7 @@ - + @@ -147,7 +147,7 @@ - + diff --git a/Plain Craft Launcher 2/Application.xaml.vb b/Plain Craft Launcher 2/Application.xaml.vb index 05e70a1..a0ffcef 100644 --- a/Plain Craft Launcher 2/Application.xaml.vb +++ b/Plain Craft Launcher 2/Application.xaml.vb @@ -247,4 +247,12 @@ Public Class Application End Select End Sub + Public Shared ShowingTooltips As New List(Of Border) + Private Sub TooltipLoaded(sender As Border, e As EventArgs) + ShowingTooltips.Add(sender) + End Sub + Private Sub TooltipUnloaded(sender As Border, e As RoutedEventArgs) + ShowingTooltips.Remove(sender) + End Sub + End Class diff --git a/Plain Craft Launcher 2/Controls/MyCard.vb b/Plain Craft Launcher 2/Controls/MyCard.vb index f938186..db2fe82 100644 --- a/Plain Craft Launcher 2/Controls/MyCard.vb +++ b/Plain Craft Launcher 2/Controls/MyCard.vb @@ -41,10 +41,6 @@ End Sub Private IsLoad As Boolean = False Private Sub MyCard_Loaded() Handles Me.Loaded - '卡片的进入时动画已被页面通用切换动画替代 - 'If LoadAnimation AndAlso IsLoad Then - ' StartHeightAnimation(Math.Min(50, ActualHeight), ActualHeight - Math.Min(50, ActualHeight), True) - 'End If If IsLoad Then Exit Sub '初次加载限定 If Not Title = "" AndAlso IsNothing(MainTextBlock) Then diff --git a/Plain Craft Launcher 2/Controls/MyExtraButton.xaml b/Plain Craft Launcher 2/Controls/MyExtraButton.xaml index a5b796f..f8a0d88 100644 --- a/Plain Craft Launcher 2/Controls/MyExtraButton.xaml +++ b/Plain Craft Launcher 2/Controls/MyExtraButton.xaml @@ -16,9 +16,9 @@ - + - + diff --git a/Plain Craft Launcher 2/Controls/MyExtraButton.xaml.vb b/Plain Craft Launcher 2/Controls/MyExtraButton.xaml.vb index a31e0d0..d6da198 100644 --- a/Plain Craft Launcher 2/Controls/MyExtraButton.xaml.vb +++ b/Plain Craft Launcher 2/Controls/MyExtraButton.xaml.vb @@ -17,7 +17,7 @@ PanProgress.Visibility = Visibility.Collapsed Else PanProgress.Visibility = Visibility.Visible - RectProgress.Rect = New Rect(0, 0, 40, 40 * (1 - value)) + RectProgress.Rect = New Rect(0, 40 * (1 - value), 40, 40 * value) End If End Set End Property @@ -179,7 +179,7 @@ AniStop("MyExtraButton Color " & Uuid) If IsMouseOver Then - PanColor.SetResourceReference(BackgroundProperty, "ColorBrush2") + PanColor.SetResourceReference(BackgroundProperty, "ColorBrush4") Else PanColor.SetResourceReference(BackgroundProperty, "ColorBrush3") End If diff --git a/Plain Craft Launcher 2/Controls/MyPageLeft.vb b/Plain Craft Launcher 2/Controls/MyPageLeft.vb index c43e56e..b09897b 100644 --- a/Plain Craft Launcher 2/Controls/MyPageLeft.vb +++ b/Plain Craft Launcher 2/Controls/MyPageLeft.vb @@ -29,21 +29,28 @@ '逐个进入动画 Dim AniList As New List(Of AniData) Dim Id As Integer = 0, Delay As Integer = 0 - Dim Controls = GetAllAnimControls() - For Each Element As FrameworkElement In Controls - Element.Opacity = 0 - Element.RenderTransform = New TranslateTransform(-25, 0) - AniList.Add(AaOpacity(Element, If(TypeOf Element Is TextBlock, 0.6, 1), 200, Delay, New AniEaseOutFluent(AniEasePower.Weak))) - AniList.Add(AaTranslateX(Element, 5, 200, Delay, New AniEaseOutFluent)) - AniList.Add(AaTranslateX(Element, 20, 300, Delay, New AniEaseOutBack(AniEasePower.Weak))) - If TypeOf Element Is MyListItem Then - AniList.Add(AaCode(Sub() - CType(Element, MyListItem).IsMouseOverAnimationEnabled = True - CType(Element, MyListItem).RefreshColor(Me, New EventArgs) - End Sub, Delay + 280)) + For Each Element As FrameworkElement In GetAllAnimControls(True) + If Element.Visibility = Visibility.Collapsed Then + '还原之前的隐藏动画可能导致的改变(#2436) + Element.Opacity = 1 + Element.RenderTransform = New TranslateTransform(0, 0) + If TypeOf Element Is MyListItem Then CType(Element, MyListItem).IsMouseOverAnimationEnabled = True + Else + Element.Opacity = 0 + Element.RenderTransform = New TranslateTransform(-25, 0) + If TypeOf Element Is MyListItem Then CType(Element, MyListItem).IsMouseOverAnimationEnabled = False + AniList.Add(AaOpacity(Element, If(TypeOf Element Is TextBlock, 0.6, 1), 200, Delay, New AniEaseOutFluent(AniEasePower.Weak))) + AniList.Add(AaTranslateX(Element, 5, 200, Delay, New AniEaseOutFluent)) + AniList.Add(AaTranslateX(Element, 20, 300, Delay, New AniEaseOutBack(AniEasePower.Weak))) + If TypeOf Element Is MyListItem Then + AniList.Add(AaCode(Sub() + CType(Element, MyListItem).IsMouseOverAnimationEnabled = True + CType(Element, MyListItem).RefreshColor(Me, New EventArgs) + End Sub, Delay + 280)) + End If + Delay += Math.Max(8, 20 - Id) * 2.5 + Id += 1 End If - Delay += Math.Max(8, 20 - Id) * 2.5 - Id += 1 Next AniStart(AniList, "PageLeft PageChange " & Uuid) End If @@ -74,23 +81,22 @@ End Sub '遍历获取所有需要生成动画的控件 - Private Function GetAllAnimControls() As List(Of FrameworkElement) + Private Function GetAllAnimControls(Optional IgnoreInvisibility As Boolean = False) As List(Of FrameworkElement) Dim AllControls As New List(Of FrameworkElement) - GetAllAnimControls(AnimatedControl, AllControls) + GetAllAnimControls(AnimatedControl, AllControls, IgnoreInvisibility) Return AllControls End Function - Private Sub GetAllAnimControls(Element As FrameworkElement, ByRef AllControls As List(Of FrameworkElement)) - If Element.Visibility = Visibility.Collapsed Then Exit Sub + Private Sub GetAllAnimControls(Element As FrameworkElement, ByRef AllControls As List(Of FrameworkElement), IgnoreInvisibility As Boolean) + If Not IgnoreInvisibility AndAlso Element.Visibility = Visibility.Collapsed Then Exit Sub If TypeOf Element Is MyTextButton Then AllControls.Add(Element) ElseIf TypeOf Element Is MyListItem Then - CType(Element, MyListItem).IsMouseOverAnimationEnabled = False AllControls.Add(Element) ElseIf TypeOf Element Is ContentControl Then - GetAllAnimControls(CType(Element, ContentControl).Content, AllControls) + GetAllAnimControls(CType(Element, ContentControl).Content, AllControls, IgnoreInvisibility) ElseIf TypeOf Element Is Panel Then For Each Element2 As FrameworkElement In CType(Element, Panel).Children - GetAllAnimControls(Element2, AllControls) + GetAllAnimControls(Element2, AllControls, IgnoreInvisibility) Next Else AllControls.Add(Element) diff --git a/Plain Craft Launcher 2/Controls/MyScrollViewer.vb b/Plain Craft Launcher 2/Controls/MyScrollViewer.vb index 666d9fa..1187052 100644 --- a/Plain Craft Launcher 2/Controls/MyScrollViewer.vb +++ b/Plain Craft Launcher 2/Controls/MyScrollViewer.vb @@ -15,8 +15,12 @@ '如果当前是在对有滚动条的下拉框或文本框执行,则不接管操作 Exit Sub End If - PerformVerticalOffsetDelta(-e.Delta) e.Handled = True + PerformVerticalOffsetDelta(-e.Delta) + '关闭 Tooltip (#2552) + For Each TooltipBorder In Application.ShowingTooltips + AniStart(AaOpacity(TooltipBorder, -1, 100), $"Hide Tooltip {GetUuid()}") + Next End Sub Public Sub PerformVerticalOffsetDelta(Delta As Double) AniStart(AaDouble(Sub(AnimDelta As Double) diff --git a/Plain Craft Launcher 2/FormMain.xaml.vb b/Plain Craft Launcher 2/FormMain.xaml.vb index bd16da5..37908b8 100644 --- a/Plain Craft Launcher 2/FormMain.xaml.vb +++ b/Plain Craft Launcher 2/FormMain.xaml.vb @@ -10,6 +10,11 @@ Public Class FormMain Dim FeatureList As New List(Of KeyValuePair(Of Integer, String)) '统计更新日志条目 #If BETA Then + If LastVersion < 304 Then 'Release 2.6.8 + FeatureList.Add(New KeyValuePair(Of Integer, String)(1, "修复开始或结束游戏时可能报错的 Bug")) + FeatureCount += 20 + BugCount += 25 + End If If LastVersion < 302 Then 'Release 2.6.7 FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "再次修复网络条件差时可能无法下载 MC 的 Bug")) BugCount += 1 @@ -128,6 +133,11 @@ Public Class FormMain '3:BUG+ IMP* FEAT- '2:BUG* IMP- '1:BUG- + If LastVersion < 305 Then 'Snapshot 2.6.8 + FeatureList.Add(New KeyValuePair(Of Integer, String)(1, "修复开始或结束游戏时可能报错的 Bug")) + FeatureCount += 20 + BugCount += 25 + End If If LastVersion < 303 Then 'Snapshot 2.6.7 FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "再次修复网络条件差时可能无法下载 MC 的 Bug")) BugCount += 1 @@ -331,6 +341,7 @@ Public Class FormMain End Sub '窗口加载 + Private Declare Auto Function ChangeWindowMessageFilterEx Lib "user32.dll" (ByVal hwnd As IntPtr, ByVal message As UInt32, ByVal action As UInt32, ByVal changeInfo As UInt32) As Boolean Private IsWindowLoadFinished As Boolean = False ''' ''' 是否为联机提权后自动重启。 @@ -442,6 +453,7 @@ Public Class FormMain TimerMainStartRun() '加载池 RunInNewThread(Sub() + 'EULA 提示 If Not Setup.Get("SystemEula") Then Select Case MyMsgBox("在使用 PCL 前,请同意 PCL 的用户协议与免责声明。", "协议授权", "同意", "拒绝", "查看用户协议与免责声明", Button3Action:=Sub() OpenWebsite("https://shimo.im/docs/rGrd8pY8xWkt6ryW")) @@ -451,6 +463,7 @@ Public Class FormMain EndProgram(False) End Select End If + '启动加载器池 Try JavaListInit() '延后到同意协议后再执行,避免在初次启动时进行进程操作 Thread.Sleep(200) @@ -460,11 +473,22 @@ Public Class FormMain Catch ex As Exception Log(ex, "初始化加载池运行失败", LogLevel.Feedback) End Try + '清理自动更新文件 Try If File.Exists(Path & "PCL\Plain Craft Launcher 2.exe") Then File.Delete(Path & "PCL\Plain Craft Launcher 2.exe") Catch ex As Exception Log(ex, "清理自动更新文件失败") End Try + '开启管理员权限下的文件拖拽(#2531) + Try + If IsAdmin() Then + Log("[System] PCL 正以管理员权限运行") + ChangeWindowMessageFilterEx(Handle, &H233, 1, Nothing) + ChangeWindowMessageFilterEx(Handle, &H49, 1, Nothing) + End If + Catch ex As Exception + Log(ex, "开启管理员权限下的文件拖拽失败") + End Try End Sub, "Start Loader", ThreadPriority.Lowest) Log("[Start] 第三阶段加载用时:" & GetTimeTick() - ApplicationStartTick & " ms") diff --git a/Plain Craft Launcher 2/Modules/Base/ModBase.vb b/Plain Craft Launcher 2/Modules/Base/ModBase.vb index b7f340b..e19f368 100644 --- a/Plain Craft Launcher 2/Modules/Base/ModBase.vb +++ b/Plain Craft Launcher 2/Modules/Base/ModBase.vb @@ -11,12 +11,12 @@ Public Module ModBase #Region "声明" '下列版本信息由更新器自动修改 - Public Const VersionBaseName As String = "2.6.7" '不含分支前缀的显示用版本名 - Public Const VersionStandardCode As String = "2.6.7." & VersionBranchCode '标准格式的四段式版本号 + Public Const VersionBaseName As String = "2.6.8" '不含分支前缀的显示用版本名 + Public Const VersionStandardCode As String = "2.6.8." & VersionBranchCode '标准格式的四段式版本号 #If BETA Then - Public Const VersionCode As Integer = 302 'Release + Public Const VersionCode As Integer = 304 'Release #Else - Public Const VersionCode As Integer = 303 'Snapshot + Public Const VersionCode As Integer = 305 'Snapshot #End If '自动生成的版本信息 Public Const VersionDisplayName As String = VersionBranchName & " " & VersionBaseName @@ -1242,23 +1242,7 @@ Re: Public Function ExtractFile(CompressFilePath As String, DestDirectory As String, Optional Encode As Encoding = Nothing) As Boolean Try Directory.CreateDirectory(DestDirectory) - If CompressFilePath.EndsWith(".zip") OrElse CompressFilePath.EndsWith(".jar") OrElse CompressFilePath.EndsWith(".mrpack") Then - '以 zip 方式解压 - Using stream As New FileStream(CompressFilePath, FileMode.Open) - Using archive As New ZipArchive(stream, ZipArchiveMode.Read, False, If(Encode, Encoding.GetEncoding("GB18030"))) - For Each entry As ZipArchiveEntry In archive.Entries - Dim destinationPath As String = IO.Path.Combine(DestDirectory, entry.FullName) - If destinationPath.EndsWith("\") OrElse destinationPath.EndsWith("/") Then - Directory.CreateDirectory(destinationPath) - Else - If File.Exists(destinationPath) Then File.Delete(destinationPath) - entry.ExtractToFile(destinationPath, True) - End If - Next - End Using - End Using - Return True - ElseIf CompressFilePath.EndsWith(".gz") Then + If CompressFilePath.EndsWith(".gz") Then '以 gz 方式解压 Dim stream As New GZipStream(New FileStream(CompressFilePath, FileMode.Open, FileAccess.ReadWrite), CompressionMode.Decompress) Dim decompressedFile As New FileStream(DestDirectory & GetFileNameFromPath(CompressFilePath).ToLower.Replace(".tar", "").Replace(".gz", ""), FileMode.OpenOrCreate, FileAccess.Write) @@ -1271,7 +1255,19 @@ Re: stream.Close() Return True Else - Return False + '以 zip 方式解压 + Using Archive = ZipFile.Open(CompressFilePath, ZipArchiveMode.Read, If(Encode, Encoding.GetEncoding("GB18030"))) + For Each Entry As ZipArchiveEntry In Archive.Entries + Dim DestinationPath As String = IO.Path.Combine(DestDirectory, Entry.FullName) + If DestinationPath.EndsWith("\") OrElse DestinationPath.EndsWith("/") Then + Continue For '不创建空文件夹 + Else + Directory.CreateDirectory(GetPathFromFullPath(DestinationPath)) + Entry.ExtractToFile(DestinationPath, True) + End If + Next + End Using + Return True End If Catch ex As Exception Log(ex, "尝试解压文件失败") @@ -1301,7 +1297,7 @@ Re: Next Temp = Directory.GetDirectories(Path) For Each str As String In Temp - DeleteDirectory(str) + DeleteDirectory(str, IgnoreIssue) Next Try Directory.Delete(Path, True) @@ -1578,7 +1574,7 @@ Re: ''' 为字符串进行 XML 转义。 ''' Public Function EscapeXML(Str As String) As String - Return Str.Replace("&", "&").Replace("<", "<").Replace(">", ">").Replace("'", "'").Replace("""", """) + Return Str.Replace("&", "&").Replace("<", "<").Replace(">", ">").Replace("'", "'").Replace("""", """).Replace(vbCrLf, " ") End Function '正则 diff --git a/Plain Craft Launcher 2/Modules/Base/ModLoader.vb b/Plain Craft Launcher 2/Modules/Base/ModLoader.vb index 0d8deed..6a173c1 100644 --- a/Plain Craft Launcher 2/Modules/Base/ModLoader.vb +++ b/Plain Craft Launcher 2/Modules/Base/ModLoader.vb @@ -437,10 +437,6 @@ For Each Loader In Loaders Loader.Abort() Next - '从列表删除 - SyncLock LoaderTaskbarLock - If LoaderTaskbar.Contains(Me) Then LoaderTaskbar.Remove(Me) - End SyncLock End Sub) End Sub @@ -571,6 +567,7 @@ Restart: If FrmSpeedLeft IsNot Nothing Then FrmSpeedLeft.TaskRemove(Loader) SyncLock LoaderTaskbarLock LoaderTaskbar.Add(Loader) + Log($"[Taskbar] {Loader.Name} 已加入任务列表") End SyncLock End Sub Public Sub LoaderTaskbarProgressRefresh() @@ -585,16 +582,13 @@ Restart: If Loader.Show AndAlso Loader.State = LoadState.Loading Then IsAllDownloadTaskCompleted = False Next '若单个任务已中止或全部任务已完成,则刷新并移除 - Dim RemovedTask As New List(Of LoaderBase) - For i = 0 To LoaderTaskbar.Count - 1 - If (IsAllDownloadTaskCompleted OrElse LoaderTaskbar(i).State = LoadState.Aborted) AndAlso LoaderTaskbar(i).Show Then - If FrmSpeedLeft IsNot Nothing Then FrmSpeedLeft.TaskRefresh(LoaderTaskbar(i)) - RemovedTask.Add(LoaderTaskbar(i)) + For Each Task In LoaderTaskbar.ToList() + If (IsAllDownloadTaskCompleted OrElse Task.State = LoadState.Aborted OrElse Task.State = LoadState.Waiting) AndAlso Task.Show Then + If FrmSpeedLeft IsNot Nothing Then FrmSpeedLeft.TaskRefresh(Task) + LoaderTaskbar.Remove(Task) + Log($"[Taskbar] {Task.Name} 已移出任务列表") End If Next - For Each Task In RemovedTask - LoaderTaskbar.Remove(Task) - Next End SyncLock '更新平滑后的进度 If NewProgress <= 0 OrElse NewProgress >= 1 OrElse LoaderTaskbarProgress > NewProgress Then @@ -625,8 +619,9 @@ Restart: Try Dim Total As Double = 0, Count As Integer = 0 SyncLock LoaderTaskbarLock - For i = 0 To LoaderTaskbar.Count - 1 - Total += LoaderTaskbar(i).Progress + For Each Task In LoaderTaskbar.ToList + If Not Task.Show Then Continue For + Total += Task.Progress Count += 1 '避免多线程影响导致计数出错 Next End SyncLock diff --git a/Plain Craft Launcher 2/Modules/Base/MyBitmap.vb b/Plain Craft Launcher 2/Modules/Base/MyBitmap.vb index 02da732..1c25959 100644 --- a/Plain Craft Launcher 2/Modules/Base/MyBitmap.vb +++ b/Plain Craft Launcher 2/Modules/Base/MyBitmap.vb @@ -28,7 +28,7 @@ Public Class MyBitmap Public Shared Widening Operator CType(Image As MyBitmap) As ImageSource Dim Bitmap = Image.Pic Dim rect = New System.Drawing.Rectangle(0, 0, Bitmap.Width, Bitmap.Height) - Dim bitmapData = Bitmap.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite, System.Drawing.Imaging.PixelFormat.Format32bppArgb) + Dim bitmapData = Bitmap.LockBits(rect, ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb) Try Dim size = rect.Width * rect.Height * 4 Return BitmapSource.Create(Bitmap.Width, Bitmap.Height, Bitmap.HorizontalResolution, Bitmap.VerticalResolution, PixelFormats.Bgra32, Nothing, bitmapData.Scan0, size, bitmapData.Stride) @@ -104,45 +104,27 @@ Public Class MyBitmap End Using End Sub - ''' - ''' 获取旋转的图片,这个方法不会导致原对象改变且会返回一个新的对象。图片长宽必须相等。 - ''' - ''' 旋转角度(单位为角度)。 - Public Function Rotation(angle As Double) As System.Drawing.Bitmap - Dim img As System.Drawing.Image = Me.Pic - Dim bitSize As Single = img.Width - Dim bmp As New System.Drawing.Bitmap(CInt(bitSize), CInt(bitSize), img.PixelFormat) - bmp.SetResolution(img.HorizontalResolution, img.VerticalResolution) - Using g As System.Drawing.Graphics = System.Drawing.Graphics.FromImage(bmp) - g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor - g.TranslateTransform(bitSize / 2, bitSize / 2) - g.RotateTransform(angle) - g.TranslateTransform(-bitSize / 2, -bitSize / 2) - g.DrawImage(img, New System.Drawing.Rectangle(0, 0, img.Width, img.Width)) - End Using - Return bmp - End Function - ''' ''' 获取裁切的图片,这个方法不会导致原对象改变且会返回一个新的对象。 ''' - Public Function Clip(rect As System.Drawing.Rectangle) As System.Drawing.Bitmap - Dim img As System.Drawing.Image = Pic - Dim bmp As New System.Drawing.Bitmap(rect.Width, rect.Height, img.PixelFormat) - bmp.SetResolution(img.HorizontalResolution, img.VerticalResolution) + Public Function Clip(X As Integer, Y As Integer, Width As Integer, Height As Integer) As MyBitmap + Dim bmp As New System.Drawing.Bitmap(Width, Height, Pic.PixelFormat) + bmp.SetResolution(Pic.HorizontalResolution, Pic.VerticalResolution) Using g As System.Drawing.Graphics = System.Drawing.Graphics.FromImage(bmp) g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor - g.DrawImageUnscaled(img, rect.X, rect.Y) + g.TranslateTransform(-X, -Y) + g.DrawImage(Pic, New System.Drawing.Rectangle(0, 0, Pic.Width, Pic.Height)) End Using Return bmp End Function ''' - ''' 获取左右翻转的图片,这个方法不会导致原对象改变。 + ''' 获取旋转或翻转后的图片,这个方法不会导致原对象改变且会返回一个新的对象。 ''' - Public Function LeftRightFilp() As System.Drawing.Bitmap + Public Function RotateFlip(Type As System.Drawing.RotateFlipType) As MyBitmap Dim bmp As New System.Drawing.Bitmap(Pic) - bmp.RotateFlip(System.Drawing.RotateFlipType.RotateNoneFlipX) + bmp.SetResolution(Pic.HorizontalResolution, Pic.VerticalResolution) + bmp.RotateFlip(Type) Return bmp End Function @@ -152,7 +134,7 @@ Public Class MyBitmap Public Sub Save(FilePath As String) Dim encoder As BitmapEncoder = New PngBitmapEncoder() encoder.Frames.Add(BitmapFrame.Create(Me)) - Using fileStream = New System.IO.FileStream(FilePath, FileMode.Create) + Using fileStream As New FileStream(FilePath, FileMode.Create) encoder.Save(fileStream) End Using End Sub diff --git a/Plain Craft Launcher 2/Modules/Minecraft/ModComp.vb b/Plain Craft Launcher 2/Modules/Minecraft/ModComp.vb index 251d059..409aee8 100644 --- a/Plain Craft Launcher 2/Modules/Minecraft/ModComp.vb +++ b/Plain Craft Launcher 2/Modules/Minecraft/ModComp.vb @@ -434,7 +434,7 @@ Dim NormalNameList = New List(Of String) For Each Name In NameLists Dim LowerName As String = Name.ToLower - If Name.ToUpper = Name Then + If Name.ToUpper = Name AndAlso Name <> "FPS" AndAlso Name <> "HUD" Then '缩写 ExNameList.Add(Name) ElseIf (LowerName.Contains("forge") OrElse LowerName.Contains("fabric") OrElse LowerName.Contains("quilt")) AndAlso @@ -487,8 +487,10 @@ NoExName: '将 “Forge” 等提示改为 “Forge 版” If (Ex.ToLower.Contains("forge") OrElse Ex.ToLower.Contains("fabric") OrElse Ex.ToLower.Contains("quilt")) AndAlso Not Ex.Contains("版") AndAlso Ex.ToLower.Replace("forge", "").Replace("fabric", "").Replace("quilt", "").Length <= 3 Then - Ex = Ex.Replace("Edition", "").Trim.Capitalize & " 版" + Ex = Ex.Replace("Edition", "").Replace("edition", "").Trim.Capitalize & " 版" End If + '将 “forge” 等词语的首字母大写 + Ex = Ex.Replace("forge", "Forge").Replace("neo", "Neo").Replace("fabric", "Fabric").Replace("quilt", "Quilt") ExName &= " | " & Ex.Trim Next If ExName = "" Then GoTo NoExName @@ -933,7 +935,10 @@ Retry: Next '更新结果 SyncLock ResultsLock - RawResults.AddRange(ProjectList) + For Each Project In ProjectList + If Task.Input.Type = CompType.Mod AndAlso Not Project.ModLoaders.Any() Then Continue For '过滤插件(#2458) + RawResults.Add(Project) + Next End SyncLock Storage.ModrinthOffset += ProjectList.Count Storage.ModrinthTotal = RequestResult("total_hits").ToObject(Of Integer) @@ -988,7 +993,7 @@ Retry: Not Storage.Results.Any(Function(b) r.IsLike(b))).ToList '加入列表 RealResults.AddRange(RawResults) - Log($"[Comp] 去重后累计新增结果 {RealResults.Count} 个") + Log($"[Comp] 去重、筛选后累计新增结果 {RealResults.Count} 个") #End Region diff --git a/Plain Craft Launcher 2/Modules/Minecraft/ModCrash.vb b/Plain Craft Launcher 2/Modules/Minecraft/ModCrash.vb index 9b5ac13..03672de 100644 --- a/Plain Craft Launcher 2/Modules/Minecraft/ModCrash.vb +++ b/Plain Craft Launcher 2/Modules/Minecraft/ModCrash.vb @@ -127,7 +127,7 @@ End Try '导入其中的日志文件 - For Each TargetFile As FileInfo In New DirectoryInfo(TempFolder & "Temp\").EnumerateFiles + For Each TargetFile As FileInfo In New DirectoryInfo(TempFolder & "Temp\").EnumerateFiles.ToList() Try If Not TargetFile.Exists OrElse TargetFile.Length = 0 Then Continue For Dim Ext As String = TargetFile.Extension.ToLower @@ -137,6 +137,8 @@ Else AnalyzeRawFiles.Add(New KeyValuePair(Of String, String())(TargetFile.FullName, ReadFile(TargetFile.FullName, Encoding.UTF8).Split(vbCrLf.ToCharArray))) End If + Else + File.Delete(TargetFile.FullName) End If Catch ex As Exception Log(ex, "导入单个日志文件失败") @@ -235,6 +237,7 @@ End If Case AnalyzeFileType.MinecraftLog LogMc = "" + LogMcDebug = "" '创建文件名词典 Dim FileNameDict As New Dictionary(Of String, KeyValuePair(Of String, String())) For Each SelectedFile In SelectedFiles @@ -272,11 +275,21 @@ Exit For End If Next + '查找 Debug Log + For Each FileName As String In {"debug.log", "debug log.txt"} + If FileNameDict.ContainsKey(FileName) Then + Dim CurrentLog = FileNameDict(FileName) + LogMcDebug += GetHeadTailLines(CurrentLog.Value, 1000, 0) + Log("[Crash] 导入分析:" & CurrentLog.Key & ",作为 Minecraft Debug 日志") + Exit For + End If + Next '检查错误 If LogMc = "" Then LogMc = Nothing Throw New Exception("无法找到匹配的 Minecraft Log") End If + If LogMcDebug = "" Then LogMcDebug = Nothing Case AnalyzeFileType.ExtraLog '全部丢过去 For Each SelectedFile In SelectedFiles @@ -294,7 +307,7 @@ If ResultCount = 0 Then Log("[Crash] 步骤 2:准备日志文本完成,没有任何可供分析的日志") Else - Log(("[Crash] 步骤 2:准备日志文本完成,找到" & If(LogMc Is Nothing, "", "游戏日志、") & If(LogHs Is Nothing, "", "虚拟机日志、") & If(LogCrash Is Nothing, "", "崩溃日志、")).TrimEnd("、") & "用作分析") + Log(("[Crash] 步骤 2:准备日志文本完成,找到" & If(LogMc Is Nothing, "", "游戏日志、") & If(LogMcDebug Is Nothing, "", "游戏 Debug 日志、") & If(LogHs Is Nothing, "", "虚拟机日志、") & If(LogCrash Is Nothing, "", "崩溃日志、")).TrimEnd("、") & "用作分析") End If Return ResultCount @@ -315,7 +328,7 @@ End Function '3:根据文本分析崩溃原因 - Private LogMc As String = Nothing, LogHs As String = Nothing, LogCrash As String = Nothing + Private LogMc As String = Nothing, LogMcDebug As String = Nothing, LogHs As String = Nothing, LogCrash As String = Nothing Private LogAll As String '可能导致崩溃的原因与附加信息 Private CrashReasons As New Dictionary(Of CrashReason, List(Of String)) @@ -324,6 +337,7 @@ ''' Private Enum CrashReason Mod文件被解压 + MixinBootstrap缺失 内存不足 使用JDK 显卡不支持OpenGL @@ -344,9 +358,8 @@ ModMixin失败 Mod加载器报错 Mod初始化失败 - 崩溃日志堆栈分析发现关键字 - 崩溃日志堆栈分析发现Mod名称 - MC日志堆栈分析发现关键字 + 堆栈分析发现关键字 + 堆栈分析发现Mod名称 OptiFine导致无法加载世界 'https://www.minecraftforum.net/forums/support/java-edition-support/3051132-exception-ticking-world 特定方块导致崩溃 特定实体导致崩溃 @@ -372,7 +385,6 @@ ''' Public Sub Analyze(Optional Version As McVersion = Nothing) Log("[Crash] 步骤 3:分析崩溃原因") - LogAll = (If(LogMc, "") & If(LogHs, "") & If(LogCrash, "")).ToLower '1. 精准日志匹配,中/高优先级 AnalyzeCrit1() @@ -381,37 +393,41 @@ If CrashReasons.Count > 0 Then GoTo Done '2. 堆栈分析 - If LogAll.Contains("forge") OrElse LogAll.Contains("fabric") OrElse LogAll.Contains("liteloader") Then - '来源崩溃日志的分析 + LogAll = (If(LogMc, "") & If(LogMcDebug, "") & If(LogHs, "") & If(LogCrash, "")) + If LogAll.Contains("orge") OrElse LogAll.Contains("abric") OrElse LogAll.Contains("uilt") OrElse LogAll.Contains("iteloader") Then + Dim Keywords As New List(Of String) + '崩溃日志 If LogCrash IsNot Nothing Then Log("[Crash] 开始进行崩溃日志堆栈分析") Dim StackLogs As String = LogCrash.Split("System Details").First - Dim Keywords = AnalyzeStackKeyword(StackLogs) - If Keywords.Count > 0 Then - Dim Names = AnalyzeModName(Keywords) - If Names Is Nothing Then - AppendReason(CrashReason.崩溃日志堆栈分析发现关键字, Keywords) - Else - AppendReason(CrashReason.崩溃日志堆栈分析发现Mod名称, Names) - End If - GoTo Done - End If + Keywords.AddRange(AnalyzeStackKeyword(StackLogs)) End If - '来自 Minecraft 日志的分析 + 'Minecraft 日志 If LogMc IsNot Nothing Then Dim Fatals = RegexSearch(LogMc, "/FATAL] [\w\W]+?(?=[\n]+\[)") Log("[Crash] 开始进行 Minecraft 日志堆栈分析,发现 " & Fatals.Count & " 个报错项") If Fatals.Count > 0 Then - Dim Keywords As New List(Of String) For Each Fatal In Fatals Keywords.AddRange(AnalyzeStackKeyword(Fatal)) Next - If Keywords.Count > 0 Then - AppendReason(CrashReason.MC日志堆栈分析发现关键字, Keywords.Distinct.ToList) - GoTo Done - End If End If End If + '虚拟机日志 + If LogHs IsNot Nothing Then + Log("[Crash] 开始进行虚拟机堆栈分析") + Dim StackLogs As String = LogHs.Split("Registers:").First.Split("T H R E A D").Last + Keywords.AddRange(AnalyzeStackKeyword(StackLogs)) + End If + 'Mod 名称分析 + If Keywords.Count > 0 Then + Dim Names = AnalyzeModName(Keywords) + If Names Is Nothing Then + AppendReason(CrashReason.堆栈分析发现关键字, Keywords) + Else + AppendReason(CrashReason.堆栈分析发现Mod名称, Names) + End If + GoTo Done + End If Else Log("[Crash] 可能并未安装 Mod,不进行堆栈分析") End If @@ -565,22 +581,6 @@ Done: '游戏日志分析 If LogMc IsNot Nothing Then - 'Mixin 崩溃 - If LogMc.Contains("Mixin prepare failed ") OrElse LogMc.Contains("Mixin apply failed ") OrElse LogMc.Contains("MixinApplyError") OrElse - LogMc.Contains("mixin.injection.throwables.") OrElse LogMc.Contains(".mixins.json] FAILED during )") Then - Dim ModId As String = RegexSeek(LogMc, "(?<=in )[^./ ]+(?=.mixins.json.+failed injection check)") - If ModId Is Nothing Then ModId = RegexSeek(LogMc, "(?<=in mixins.)[^./ ]+(?=.json.+failed injection check)") - If ModId Is Nothing Then ModId = RegexSeek(LogMc, "(?<= failed .+ in )[^./ ]+(?=.mixins.json)") - If ModId Is Nothing Then ModId = RegexSeek(LogMc, "(?<= failed .+ in mixins.)[^./ ]+(?=.json)") - If ModId Is Nothing Then ModId = RegexSeek(LogMc, "(?<= in config \[)[^./ ]+(?=.mixins.json\] FAILED during )") - If ModId Is Nothing Then ModId = RegexSeek(LogMc, "(?<= in config \[mixins.)[^./ ]+(?=.json\] FAILED during )") - If ModId Is Nothing Then ModId = RegexSeek(LogMc, "(?<=from mod )[^./ ]+(?=\] from)") - If ModId Is Nothing Then ModId = RegexSeek(LogMc, "(?<=for mod )[^./ ]+(?= failed)") - '兜底名称判断 - If ModId Is Nothing Then ModId = RegexSeek(LogMc, "[^./ \]]+(?=.mixins.json") - If ModId Is Nothing Then ModId = RegexSeek(LogMc, "(?<=mixins.)[^./ \]]+(?=.json") - AppendReason(CrashReason.ModMixin失败, TryAnalyzeModName(If(ModId, "").TrimEnd((vbCrLf & " ").ToCharArray))) - End If '常规信息 If LogMc.Contains("An exception was thrown, the game will display an error screen and halt.") Then AppendReason(CrashReason.Forge报错, RegexSeek(LogMc, "(?<=the game will display an error screen and halt.[\n\r]+[^\n]+?Exception: )[\s\S]+?(?=\n\tat)")?.Trim(vbCrLf)) If LogMc.Contains("A potential solution has been determined:") Then AppendReason(CrashReason.Fabric报错并给出解决方案, Join(RegexSearch(If(RegexSeek(LogMc, "(?<=A potential solution has been determined:\n)((\t)+ - [^\n]+\n)+"), ""), "(?<=(\t)+)[^\n]+"), vbLf)) @@ -594,6 +594,24 @@ Done: '游戏日志分析 If LogMc IsNot Nothing Then + 'Mixin 崩溃 + If LogMc.Contains("Mixin prepare failed ") OrElse LogMc.Contains("Mixin apply failed ") OrElse LogMc.Contains("MixinApplyError") OrElse + LogMc.Contains("mixin.injection.throwables.") OrElse LogMc.Contains(".mixins.json] FAILED during )") Then + Dim ModId As String = RegexSeek(LogMc, "(?<=in )[^./ ]+(?=.mixins.json.+failed injection check)") + If ModId Is Nothing Then ModId = RegexSeek(LogMc, "(?<=in mixins.)[^./ ]+(?=.json.+failed injection check)") + If ModId Is Nothing Then ModId = RegexSeek(LogMc, "(?<= failed .+ in )[^./ ]+(?=.mixins.json)") + If ModId Is Nothing Then ModId = RegexSeek(LogMc, "(?<= failed .+ in mixins.)[^./ ]+(?=.json)") + If ModId Is Nothing Then ModId = RegexSeek(LogMc, "(?<= failed mixins.)[^./ ]+(?=.json:)") + If ModId Is Nothing Then ModId = RegexSeek(LogMc, "(?<= in config \[)[^./ ]+(?=.mixins.json\] FAILED during )") + If ModId Is Nothing Then ModId = RegexSeek(LogMc, "(?<= in config \[mixins.)[^./ ]+(?=.json\] FAILED during )") + If ModId Is Nothing Then ModId = RegexSeek(LogMc, "(?<=from mod )[^./ ]+(?=\] from)") + If ModId Is Nothing Then ModId = RegexSeek(LogMc, "(?<=for mod )[^./ ]+(?= failed)") + '兜底名称判断 + If ModId Is Nothing Then ModId = RegexSeek(LogMc, "[^./ \]]+(?=.mixins.json)") + If ModId Is Nothing Then ModId = RegexSeek(LogMc, "(?<=mixins.)[^./ \]]+(?=.json)") + AppendReason(CrashReason.ModMixin失败, TryAnalyzeModName(If(ModId, "").TrimEnd((vbCrLf & " ").ToCharArray))) + End If + '极短的程序输出 If Not (LogMc.Contains("at net.") OrElse LogMc.Contains("INFO]")) AndAlso LogHs Is Nothing AndAlso LogCrash Is Nothing AndAlso LogMc.Length < 100 Then AppendReason(CrashReason.极短的程序输出, LogMc) End If @@ -667,7 +685,7 @@ NextStack: End Function ''' - ''' 根据 Mod 关键词与详细信息(崩溃报告第二部分)与,获取实际的 Mod 名称。 + ''' 根据 Mod 关键词尝试获取实际的 Mod 名称。 ''' 若失败则返回 Nothing。 ''' Private Function AnalyzeModName(Keywords As List(Of String)) As List(Of String) @@ -682,60 +700,95 @@ NextStack: Next Keywords = RealKeywords - '获取崩溃报告对应部分 - If LogCrash Is Nothing Then Return Nothing - If Not LogCrash.Contains("A detailed walkthrough of the error") Then Return Nothing - Dim Details As String = LogCrash.Replace("A detailed walkthrough of the error", "¨") - Dim IsFabricDetail As Boolean = Details.Contains("Fabric Mods") '是否为 Fabric 信息格式 - If IsFabricDetail Then - Details = Details.Replace("Fabric Mods", "¨") - Log("[Crash] 检测到 Fabric Mod 信息格式") - End If - Details = Details.Split("¨").Last - - '[Forge] 获取所有包含 .jar 的行 - '[Fabric] 获取所有包含 Mod 信息的行 - Dim ModNameLines As New List(Of String) - For Each Line In Details.Split(vbLf) - If Line.ToLower.Contains(".jar") OrElse - (IsFabricDetail AndAlso Line.StartsWith(vbTab & vbTab) AndAlso Not RegexCheck(Line, "\t\tfabric[\w-]*: Fabric")) Then ModNameLines.Add(Line) - Next - Log("[Crash] 找到 " & ModNameLines.Count & " 个可能的 Mod 项目行") - - '获取 Mod ID 与关键词的匹配行 - Dim HintLines As New List(Of String) - For Each KeyWord As String In Keywords - For Each ModString As String In ModNameLines - Dim RealModString As String = ModString.ToLower.Replace("_", "") - If Not RealModString.Contains(KeyWord.ToLower.Replace("_", "")) Then Continue For - If RealModString.Contains("minecraft.jar") OrElse RealModString.Contains(" forge-") OrElse RealModString.Contains(" mixin-") Then Continue For - HintLines.Add(ModString.Trim(vbCrLf.ToCharArray)) - Exit For - Next - Next - HintLines = HintLines.Distinct.ToList - Log("[Crash] 找到 " & HintLines.Count & " 个可能的崩溃 Mod 匹配行") - For Each ModName As String In HintLines - Log("[Crash] - " & ModName) - Next - - '从 Mod 匹配行中提取 .jar 文件的名称 - For Each Line As String In HintLines - Dim Name As String + '从崩溃报告获取 Mod 信息 + If LogCrash IsNot Nothing AndAlso LogCrash.Contains("A detailed walkthrough of the error") Then + Dim Details As String = LogCrash.Replace("A detailed walkthrough of the error", "¨") + Dim IsFabricDetail As Boolean = Details.Contains("Fabric Mods") '是否为 Fabric 信息格式 If IsFabricDetail Then - Name = RegexSeek(Line, "(?<=: )[^\n]+(?= [^\n]+)") - Else - Name = RegexSeek(Line, "(?<=\()[^\t]+.jar(?=\))|(?<=(\t\t)|(\| ))[^\t\|]+.jar", RegularExpressions.RegexOptions.IgnoreCase) + Details = Details.Replace("Fabric Mods", "¨") + Log("[Crash] 崩溃报告中检测到 Fabric Mod 信息格式") End If - If Name IsNot Nothing Then ModFileNames.Add(Name) - Next - ModFileNames = ModFileNames.Distinct.ToList - Log("[Crash] 找到 " & ModFileNames.Count & " 个可能的崩溃 Mod 文件名") - For Each ModFileName As String In ModFileNames - Log("[Crash] - " & ModFileName) - Next + Details = Details.Split("¨").Last - Return If(ModFileNames.Count = 0, Nothing, ModFileNames) + '[Forge] 获取所有包含 .jar 的行 + '[Fabric] 获取所有包含 Mod 信息的行 + Dim ModNameLines As New List(Of String) + For Each Line In Details.Split(vbLf) + If Line.ToLower.Contains(".jar") OrElse + (IsFabricDetail AndAlso Line.StartsWith(vbTab & vbTab) AndAlso Not RegexCheck(Line, "\t\tfabric[\w-]*: Fabric")) Then ModNameLines.Add(Line) + Next + Log("[Crash] 崩溃报告中找到 " & ModNameLines.Count & " 个可能的 Mod 项目行") + + '获取 Mod ID 与关键词的匹配行 + Dim HintLines As New List(Of String) + For Each KeyWord As String In Keywords + For Each ModString As String In ModNameLines + Dim RealModString As String = ModString.ToLower.Replace("_", "") + If Not RealModString.Contains(KeyWord.ToLower.Replace("_", "")) Then Continue For + If RealModString.Contains("minecraft.jar") OrElse RealModString.Contains(" forge-") OrElse RealModString.Contains(" mixin-") Then Continue For + HintLines.Add(ModString.Trim(vbCrLf.ToCharArray)) + Exit For + Next + Next + HintLines = HintLines.Distinct.ToList + Log("[Crash] 崩溃报告中找到 " & HintLines.Count & " 个可能的崩溃 Mod 匹配行") + For Each ModLine As String In HintLines + Log("[Crash] - " & ModLine) + Next + + '从 Mod 匹配行中提取 .jar 文件的名称 + For Each Line As String In HintLines + Dim Name As String + If IsFabricDetail Then + Name = RegexSeek(Line, "(?<=: )[^\n]+(?= [^\n]+)") + Else + Name = RegexSeek(Line, "(?<=\()[^\t]+.jar(?=\))|(?<=(\t\t)|(\| ))[^\t\|]+.jar", RegularExpressions.RegexOptions.IgnoreCase) + End If + If Name IsNot Nothing Then ModFileNames.Add(Name) + Next + + End If + + '从 debug.log 获取 Mod 信息 + If LogMcDebug IsNot Nothing Then + + 'Forge: Found valid mod file YungsBetterStrongholds-1.20-Forge-4.0.1.jar with {betterstrongholds} mods - versions {1.20-Forge-4.0.1} + Dim ModNameLines As List(Of String) = RegexSearch(LogMcDebug, "(?<=valid mod file ).*", RegularExpressions.RegexOptions.Multiline) + Log("[Crash] Debug 信息中找到 " & ModNameLines.Count & " 个可能的 Mod 项目行") + + '获取 Mod ID 与关键词的匹配行 + Dim HintLines As New List(Of String) + For Each KeyWord As String In Keywords + For Each ModString As String In ModNameLines + If ModString.Contains($"{{{KeyWord}}}") Then HintLines.Add(ModString) + Next + Next + HintLines = HintLines.Distinct.ToList + Log("[Crash] Debug 信息中找到 " & HintLines.Count & " 个可能的崩溃 Mod 匹配行") + For Each ModLine As String In HintLines + Log("[Crash] - " & ModLine) + Next + + '从 Mod 匹配行中提取 .jar 文件的名称 + For Each Line As String In HintLines + Dim Name As String + Name = RegexSeek(Line, ".*(?= with)") + If Name IsNot Nothing Then ModFileNames.Add(Name) + Next + + End If + + '输出 + ModFileNames = ModFileNames.Distinct.ToList + If ModFileNames.Count = 0 Then + Return Nothing + Else + Log("[Crash] 找到 " & ModFileNames.Count & " 个可能的崩溃 Mod 文件名") + For Each ModFileName As String In ModFileNames + Log("[Crash] - " & ModFileName) + Next + Return ModFileNames + End If End Function ''' ''' 尝试获取 Mod 名称,若失败则返回原关键字。 @@ -841,26 +894,26 @@ NextStack: Case CrashReason.Mod名称包含特殊字符 Results.Add("由于有 Mod 的名称包含特殊字符,导致游戏崩溃。\n请尝试修改 Mod 文件名,让它只包含英文字母、数字、减号(-)、下划线(_)和小数点,然后再启动游戏。") Case CrashReason.MixinBootstrap缺失 - Results.Add("由于缺失 MixinBootstrap,导致游戏崩溃。\n请尝试安装 MixinBootstrap 解决。若安装后崩溃,尝试在该文件名前添加英文“!”后再试") + Results.Add("由于缺失 MixinBootstrap,导致游戏崩溃。\n请尝试安装 MixinBootstrap。若安装后依然崩溃,可以尝试在文件名前添加英文感叹号。") Case CrashReason.使用32位Java导致JVM无法分配足够多的内存 If Environment.Is64BitOperatingSystem Then Results.Add("你似乎正在使用 32 位 Java,这会导致 Minecraft 无法使用所需的内存,进而造成崩溃。\n\n请在启动设置的 Java 选择一项中改用 64 位的 Java 再启动游戏,然后再启动游戏。\n如果你没有安装 64 位的 Java,你可以从网络中下载、安装一个。") Else Results.Add("你正在使用 32 位的操作系统,这会导致 Minecraft 无法使用所需的内存,进而造成崩溃。\n\n你或许只能重装 64 位的操作系统来解决此问题。\n如果你的电脑内存在 2GB 以内,那或许只能换台电脑了……\h") End If - Case CrashReason.崩溃日志堆栈分析发现关键字, CrashReason.MC日志堆栈分析发现关键字 - If Additional.Count = 1 Then - Results.Add("你的游戏遇到了一些问题,这可能是某些 Mod 所引起的,PCL 找到了一个可疑的关键词:" & Additional.First & "。\n\n如果你知道它对应的 Mod,那么有可能就是它引起的错误,你也可以查看错误报告获取详情。\h") - Else - Results.Add("你的游戏遇到了一些问题,这可能是某些 Mod 所引起的,PCL 找到了以下可疑的关键词:\n - " & Join(Additional, ", ") & "\n\n如果你知道这些关键词对应的 Mod,那么有可能就是它引起的错误,你也可以查看错误报告获取详情。\h") - End If Case CrashReason.Mod缺少前置或MC版本错误 If Additional.Count > 0 Then Results.Add("由于未满足 Mod 的依赖项,导致游戏退出。\n未满足的依赖项:\n - " & Join(Additional, "\n - ") & "\n\n请根据上述信息进行对应处理,如果看不懂英文可以使用翻译软件。") Else Results.Add("由于未满足 Mod 的依赖项,导致游戏退出。\n请根据错误报告中的日志信息进行对应处理,如果看不懂英文可以使用翻译软件。\h") End If - Case CrashReason.崩溃日志堆栈分析发现Mod名称 + Case CrashReason.堆栈分析发现关键字 + If Additional.Count = 1 Then + Results.Add("你的游戏遇到了一些问题,这可能是某些 Mod 所引起的,PCL 找到了一个可疑的关键词:" & Additional.First & "。\n\n如果你知道它对应的 Mod,那么有可能就是它引起的错误,你也可以查看错误报告获取详情。\h") + Else + Results.Add("你的游戏遇到了一些问题,这可能是某些 Mod 所引起的,PCL 找到了以下可疑的关键词:\n - " & Join(Additional, ", ") & "\n\n如果你知道这些关键词对应的 Mod,那么有可能就是它引起的错误,你也可以查看错误报告获取详情。\h") + End If + Case CrashReason.堆栈分析发现Mod名称 If Additional.Count = 1 Then Results.Add("名为 " & Additional.First & " 的 Mod 可能导致了游戏出错。\n\e\h") Else diff --git a/Plain Craft Launcher 2/Modules/Minecraft/ModLaunch.vb b/Plain Craft Launcher 2/Modules/Minecraft/ModLaunch.vb index 7ca5ca2..a16140e 100644 --- a/Plain Craft Launcher 2/Modules/Minecraft/ModLaunch.vb +++ b/Plain Craft Launcher 2/Modules/Minecraft/ModLaunch.vb @@ -1141,14 +1141,11 @@ SystemBrowser: '1.15:Java 8 - 15 MinVer = New Version(1, 8, 0, 0) : MaxVer = New Version(1, 15, 999, 999) ElseIf VersionSortBoolean(McVersionCurrent.Version.ForgeVersion, "34.0.0") AndAlso VersionSortBoolean("36.2.25", McVersionCurrent.Version.ForgeVersion) Then - '1.16.X,Forge 34.X ~ 36.2.25:最高 Java 8u320 + '1.16,Forge 34.X ~ 36.2.25:最高 Java 8u320 MaxVer = New Version(1, 8, 0, 320) - ElseIf McVersionCurrent.Version.McCodeMain >= 18 AndAlso McVersionCurrent.Version.McCodeMain < 99 AndAlso McVersionCurrent.Version.HasOptiFine Then '#305 - '1.18+:若安装了 OptiFine,最高 Java 18 + ElseIf McVersionCurrent.Version.McCodeMain >= 18 AndAlso McVersionCurrent.Version.McCodeMain < 19 AndAlso McVersionCurrent.Version.HasOptiFine Then '#305 + '1.18:若安装了 OptiFine,最高 Java 18 MaxVer = New Version(1, 18, 999, 999) - ElseIf McVersionCurrent.Version.McCodeMain >= 19 AndAlso McVersionCurrent.Version.McCodeMain < 99 Then - '1.19+:最高 Java 19 - MaxVer = New Version(1, 19, 999, 999) End If End If @@ -1753,6 +1750,15 @@ NextVersion: '更新 options.txt Dim SetupFileAddress As String = McVersionCurrent.PathIndie & "options.txt" + If Not File.Exists(SetupFileAddress) Then + 'Yosbr Mod 兼容(#2385):https://www.curseforge.com/minecraft/mc-mods/yosbr + Dim YosbrFileAddress As String = McVersionCurrent.PathIndie & "config\yosbr\options.txt" + If File.Exists(YosbrFileAddress) Then + McLaunchLog("将修改 Yosbr Mod 中的 options.txt") + SetupFileAddress = YosbrFileAddress + WriteIni(SetupFileAddress, "lang", "none") '忽略默认语言 + End If + End If Try '语言 '1.0- :没有语言选项 @@ -1773,11 +1779,11 @@ NextVersion: WriteIni(SetupFileAddress, "lang", RequiredLang) McLaunchLog($"已将语言从 {CurrentLang} 修改为 {RequiredLang}") End If - '如果是初次设置,一并修改 forceUnicodeFont - If Setup.Get("ToolHelpChinese") AndAlso (CurrentLang = "none" OrElse Not Directory.Exists(McVersionCurrent.PathIndie & "saves")) Then - WriteIni(SetupFileAddress, "forceUnicodeFont", "true") - McLaunchLog("已开启 forceUnicodeFont") - End If + ''如果是初次设置,一并修改 forceUnicodeFont + 'If Setup.Get("ToolHelpChinese") AndAlso (CurrentLang = "none" OrElse Not Directory.Exists(McVersionCurrent.PathIndie & "saves")) Then + ' WriteIni(SetupFileAddress, "forceUnicodeFont", "true") + ' McLaunchLog("已开启 forceUnicodeFont") + 'End If '窗口 Select Case Setup.Get("LaunchArgumentWindowType") Case 0 '全屏 @@ -1861,7 +1867,7 @@ NextVersion: Dim Skin As New MyBitmap(PathAppdata & "CustomSkin.png") If (McVersionCurrent.Version.McCodeMain = 6 OrElse McVersionCurrent.Version.McCodeMain = 7) AndAlso Skin.Pic.Height = 64 Then McLaunchLog("该 Minecraft 版本不支持双层皮肤,已进行裁剪") - Skin = Skin.Clip(New System.Drawing.Rectangle(0, 0, 64, 32)) + Skin = Skin.Clip(0, 0, 64, 32) End If Skin.Save(Path & "PCL\CustomSkin_Cliped.png") '构建压缩文件 diff --git a/Plain Craft Launcher 2/Modules/Minecraft/ModModpack.vb b/Plain Craft Launcher 2/Modules/Minecraft/ModModpack.vb index aeefbe9..8711ed0 100644 --- a/Plain Craft Launcher 2/Modules/Minecraft/ModModpack.vb +++ b/Plain Craft Launcher 2/Modules/Minecraft/ModModpack.vb @@ -1,4 +1,6 @@ -Public Module ModModpack +Imports System.IO.Compression + +Public Module ModModpack '触发整合包安装的外部接口 ''' @@ -109,7 +111,7 @@ '整合包缓存清理 Private IsInstallCacheCleared As Boolean = False Private IsInstallCacheClearing As Boolean = False - Private Sub UnpackFiles(InstallTemp As String, FileAddress As String) + Private Sub UnpackFiles(InstallTemp As String, FileAddress As String, Loader As LoaderBase) '清理缓存文件夹 If Not IsInstallCacheCleared Then IsInstallCacheCleared = True @@ -135,9 +137,8 @@ Try Retry: '完全不知道为啥会出现文件正在被另一进程使用的问题,总之多试试 - Directory.CreateDirectory(InstallTemp) DeleteDirectory(InstallTemp) - Compression.ZipFile.ExtractToDirectory(FileAddress, InstallTemp, Encode) + ExtractFile(FileAddress, InstallTemp, Encode) Catch ex As Exception Log(ex, "第 " & RetryCount & " 次解压尝试失败") If TypeOf ex Is ArgumentException Then @@ -146,6 +147,7 @@ Retry: End If If RetryCount < 5 Then Thread.Sleep(RetryCount * 2000) + If Loader IsNot Nothing AndAlso Loader.LoadingState <> MyLoading.MyLoadingState.Run Then Exit Sub RetryCount += 1 GoTo Retry Else @@ -215,13 +217,15 @@ Retry: If OverrideHome <> "" Then InstallLoaders.Add(New LoaderTask(Of String, Integer)("解压整合包文件", Sub(Task As LoaderTask(Of String, Integer)) - UnpackFiles(InstallTemp, FileAddress) + UnpackFiles(InstallTemp, FileAddress, Task) Task.Progress = 0.5 + Dim OverridePath As String = InstallTemp & ArchiveBaseFolder & OverrideHome '复制结果 - If Directory.Exists(InstallTemp & ArchiveBaseFolder & OverrideHome) Then - CopyDirectory(InstallTemp & ArchiveBaseFolder & OverrideHome, PathMcFolder & "versions\" & VersionName) + If Directory.Exists(OverridePath) Then + CopyDirectory(OverridePath, PathMcFolder & "versions\" & VersionName) + Log($"[ModPack] 整合包 override 复制:{OverridePath} -> {PathMcFolder & "versions\" & VersionName}") Else - Log("[ModPack] 整合包中未找到 override 目录,已跳过") + Log($"[ModPack] 整合包中未找到 override 文件夹:{OverridePath}") End If Task.Progress = 0.9 '开启版本隔离 @@ -393,7 +397,7 @@ Retry: Dim InstallLoaders As New List(Of LoaderBase) InstallLoaders.Add(New LoaderTask(Of String, Integer)("解压整合包文件", Sub(Task As LoaderTask(Of String, Integer)) - UnpackFiles(InstallTemp, FileAddress) + UnpackFiles(InstallTemp, FileAddress, Task) Task.Progress = 0.5 '复制 overrides 文件夹和 client-overrides 文件夹 If Directory.Exists(InstallTemp & ArchiveBaseFolder & "overrides") Then @@ -425,7 +429,7 @@ Retry: End Select End If '添加下载文件 - FileList.Add(New NetFile(File("downloads").Select(Function(t) t.ToString).ToArray, + FileList.Add(New NetFile(File("downloads").Select(Function(t) t.ToString.Replace("://edge.forgecdn", "://media.forgecdn")).ToArray, '修复 #2390 PathMcFolder & "versions\" & VersionName & "\" & File("path").ToString, New FileChecker(ActualSize:=File("fileSize").ToObject(Of Long), Hash:=File("hashes")("sha1").ToString))) Next @@ -520,7 +524,7 @@ Retry: Dim InstallLoaders As New List(Of LoaderBase) InstallLoaders.Add(New LoaderTask(Of String, Integer)("解压整合包文件", Sub(Task As LoaderTask(Of String, Integer)) - UnpackFiles(InstallTemp, FileAddress) + UnpackFiles(InstallTemp, FileAddress, Task) Task.Progress = 0.5 '复制结果 If Directory.Exists(InstallTemp & ArchiveBaseFolder & "minecraft") Then @@ -619,7 +623,7 @@ Retry: Dim InstallLoaders As New List(Of LoaderBase) InstallLoaders.Add(New LoaderTask(Of String, Integer)("解压整合包文件", Sub(Task As LoaderTask(Of String, Integer)) - UnpackFiles(InstallTemp, FileAddress) + UnpackFiles(InstallTemp, FileAddress, Task) Task.Progress = 0.5 '复制结果 If Directory.Exists(InstallTemp & ArchiveBaseFolder & ".minecraft") Then @@ -714,7 +718,7 @@ Retry: Dim InstallLoaders As New List(Of LoaderBase) InstallLoaders.Add(New LoaderTask(Of String, Integer)("解压整合包文件", Sub(Task As LoaderTask(Of String, Integer)) - UnpackFiles(InstallTemp, FileAddress) + UnpackFiles(InstallTemp, FileAddress, Task) Task.Progress = 0.5 '复制结果 If Directory.Exists(InstallTemp & ArchiveBaseFolder & "overrides") Then @@ -805,7 +809,7 @@ Retry: If String.IsNullOrWhiteSpace(NewName) Then Exit Sub '解压 Hint("正在解压压缩包……") - UnpackFiles(TargetFolder, FileAddress) + UnpackFiles(TargetFolder, FileAddress, Nothing) '加入文件夹列表 PageSelectLeft.AddFolder(TargetFolder, NewName, False) Hint("已加入游戏文件夹列表:" & NewName, HintType.Finish) diff --git a/Plain Craft Launcher 2/Modules/ModMusic.vb b/Plain Craft Launcher 2/Modules/ModMusic.vb index ae5a191..1f8f7d7 100644 --- a/Plain Craft Launcher 2/Modules/ModMusic.vb +++ b/Plain Craft Launcher 2/Modules/ModMusic.vb @@ -25,7 +25,7 @@ For Each File In My.Computer.FileSystem.GetFiles(Path & "PCL\Musics\", FileIO.SearchOption.SearchAllSubDirectories, "*.*") '文件夹可能会被加入 .ini 文件夹配置文件、一些乱七八糟的 .jpg 文件啥的 Dim Extend As String = File.Split(".").Last.ToLower - If Not (Extend = "ini" OrElse Extend = "jpg" OrElse Extend = "txt" OrElse Extend = "cfg" OrElse Extend = "lrc" OrElse Extend = "png") Then + If Not (Extend = "ini" OrElse Extend = "jpg" OrElse Extend = "txt" OrElse Extend = "cfg" OrElse Extend = "lrc" OrElse Extend = "db" OrElse Extend = "png") Then MusicAllList.Add(File) End If Next @@ -212,7 +212,7 @@ ''' 继续音乐播放,返回是否成功切换了状态。 ''' Public Function MusicResume() As Boolean - If MusicState = MusicStates.Play Then + If MusicState = MusicStates.Play OrElse Not MusicAllList.Any() Then Return False Else RunInThread(Sub() diff --git a/Plain Craft Launcher 2/My Project/AssemblyInfo.vb b/Plain Craft Launcher 2/My Project/AssemblyInfo.vb index 065e07a..91a059b 100644 --- a/Plain Craft Launcher 2/My Project/AssemblyInfo.vb +++ b/Plain Craft Launcher 2/My Project/AssemblyInfo.vb @@ -51,6 +51,6 @@ Imports System.Runtime.InteropServices ' 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 ' 方法是按如下所示使用“*” - - + + diff --git a/Plain Craft Launcher 2/Pages/PageDownload/ModDownloadLib.vb b/Plain Craft Launcher 2/Pages/PageDownload/ModDownloadLib.vb index 6b50e8f..ffeb4bc 100644 --- a/Plain Craft Launcher 2/Pages/PageDownload/ModDownloadLib.vb +++ b/Plain Craft Launcher 2/Pages/PageDownload/ModDownloadLib.vb @@ -196,7 +196,7 @@ Public Module ModDownloadLib Else NewItem.Info = Entry("lore").ToString End If - If Entry("url").ToString.Contains("pcl") Then NewItem.Info = "[PCL 特别提供] " & NewItem.Info + If Entry("url").ToString.Contains("pcl") Then NewItem.Info = "[PCL 特供下载] " & NewItem.Info AddHandler NewItem.Click, OnClick '建立菜单 If IsSaveOnly Then @@ -299,8 +299,8 @@ Public Module ModDownloadLib WikiName = "Java版Infdev_20100618" ElseIf Id = "c0.30_01c" OrElse Id = "c0.30_survival" OrElse Id.Contains("生存测试") Then WikiName = "Java版Classic_0.30(生存模式)" - ElseIf Id = "c0.31" Then - WikiName = "Java版Indev_0.31(2010年1月30日)" + ElseIf Id.StartsWith("c0.31") Then + WikiName = "Java版Indev_0.31_20100130" ElseIf Id.StartsWith("c") Then WikiName = "Java版" & Id.Replace("c", "Classic_") ElseIf Id.StartsWith("rd-") Then @@ -382,7 +382,7 @@ Public Module ModDownloadLib Log(ex, "开始 OptiFine 下载失败", LogLevel.Feedback) End Try End Sub - Private Sub McDownloadOptiFineInstall(BaseMcFolderHome As String, Target As String, Task As LoaderTask(Of List(Of NetFile), Boolean)) + Private Sub McDownloadOptiFineInstall(BaseMcFolderHome As String, Target As String, Task As LoaderTask(Of List(Of NetFile), Boolean), UseJavaWrapper As Boolean) '选择 Java Dim Java = JavaSelect("已取消安装。", New Version(1, 8, 0, 0)) If Java Is Nothing Then @@ -399,7 +399,12 @@ Public Module ModDownloadLib If Java Is Nothing Then Throw New Exception("由于未找到 Java,已取消安装。") End If '添加 Java Wrapper 作为主 Jar - Dim Arguments = "-Doolloo.jlw.tmpdir=""" & GetJavaWrapperDir() & """ -Duser.home=""" & BaseMcFolderHome & """ -cp """ & Target & """ -jar """ & ExtractJavaWrapper() & """ optifine.Installer" + Dim Arguments As String + If UseJavaWrapper Then + Arguments = $"-Doolloo.jlw.tmpdir=""{GetJavaWrapperDir()}"" -Duser.home=""{BaseMcFolderHome}"" -cp ""{Target}"" -jar ""{ExtractJavaWrapper()}"" optifine.Installer" + Else + Arguments = $"-Duser.home=""{BaseMcFolderHome}"" -cp ""{Target}"" optifine.Installer" + End If If Java.VersionCode >= 9 Then Arguments = "--add-exports cpw.mods.bootstraplauncher/cpw.mods.bootstraplauncher=ALL-UNNAMED " & Arguments '开始启动 SyncLock InstallSyncLock @@ -504,67 +509,66 @@ Public Module ModDownloadLib '获取下载地址 Loaders.Add(New LoaderTask(Of String, List(Of NetFile))("获取 OptiFine 主文件下载地址", - Sub(Task As LoaderTask(Of String, List(Of NetFile))) - '启动依赖版本的下载 - If ClientDownloadLoader Is Nothing Then - If IsCustomFolder Then Throw New Exception("如果没有指定原版下载器,则不能指定 MC 安装文件夹") - ClientDownloadLoader = McDownloadClient(NetPreDownloadBehaviour.ExitWhileExistsOrDownloading, DownloadInfo.Inherit) - End If - Task.Progress = 0.1 - Dim Sources As New List(Of String) - 'BMCLAPI 源 - If DownloadInfo.IsPreview Then - Sources.Add("https://download.mcbbs.net/optifine/" & DownloadInfo.Inherit & "/HD_U_" & DownloadInfo.NameDisplay.Replace(DownloadInfo.Inherit & " ", "").Replace(" ", "/")) - Sources.Add("https://bmclapi2.bangbang93.com/optifine/" & DownloadInfo.Inherit & "/HD_U_" & DownloadInfo.NameDisplay.Replace(DownloadInfo.Inherit & " ", "").Replace(" ", "/")) - Else - Sources.Add("https://download.mcbbs.net/optifine/" & DownloadInfo.Inherit & "/HD_U/" & DownloadInfo.NameDisplay.Replace(DownloadInfo.Inherit & " ", "")) - Sources.Add("https://bmclapi2.bangbang93.com/optifine/" & DownloadInfo.Inherit & "/HD_U/" & DownloadInfo.NameDisplay.Replace(DownloadInfo.Inherit & " ", "")) - End If - '官方源 - Dim PageData As String - Try - PageData = NetGetCodeByClient("https://optifine.net/adloadx?f=" & DownloadInfo.NameFile, New UTF8Encoding(False), 15000, "text/html") - Task.Progress = 0.8 - Sources.Add("https://optifine.net/" & RegexSearch(PageData, "downloadx\?f=[^""']+")(0)) - Log("[Download] OptiFine " & DownloadInfo.NameDisplay & " 官方下载地址:" & Sources(0)) - Catch ex As Exception - Log(ex, "获取 OptiFine " & DownloadInfo.NameDisplay & " 官方下载地址失败") - End Try - Task.Progress = 0.9 - 'OptiFine 中文镜像源 - Sources.Add("https://optifine.cn/download/" & DownloadInfo.NameFile) - '构造文件请求 - Task.Output = New List(Of NetFile) From {New NetFile(Sources.ToArray, Target, New FileChecker(MinSize:=64 * 1024))} - End Sub) With {.ProgressWeight = 8}) + Sub(Task As LoaderTask(Of String, List(Of NetFile))) + '启动依赖版本的下载 + If ClientDownloadLoader Is Nothing Then + If IsCustomFolder Then Throw New Exception("如果没有指定原版下载器,则不能指定 MC 安装文件夹") + ClientDownloadLoader = McDownloadClient(NetPreDownloadBehaviour.ExitWhileExistsOrDownloading, DownloadInfo.Inherit) + End If + Task.Progress = 0.1 + Dim Sources As New List(Of String) + 'BMCLAPI 源 + If DownloadInfo.IsPreview Then + Sources.Add("https://download.mcbbs.net/optifine/" & DownloadInfo.Inherit & "/HD_U_" & DownloadInfo.NameDisplay.Replace(DownloadInfo.Inherit & " ", "").Replace(" ", "/")) + Sources.Add("https://bmclapi2.bangbang93.com/optifine/" & DownloadInfo.Inherit & "/HD_U_" & DownloadInfo.NameDisplay.Replace(DownloadInfo.Inherit & " ", "").Replace(" ", "/")) + Else + Sources.Add("https://download.mcbbs.net/optifine/" & DownloadInfo.Inherit & "/HD_U/" & DownloadInfo.NameDisplay.Replace(DownloadInfo.Inherit & " ", "")) + Sources.Add("https://bmclapi2.bangbang93.com/optifine/" & DownloadInfo.Inherit & "/HD_U/" & DownloadInfo.NameDisplay.Replace(DownloadInfo.Inherit & " ", "")) + End If + '官方源 + Dim PageData As String + Try + PageData = NetGetCodeByClient("https://optifine.net/adloadx?f=" & DownloadInfo.NameFile, New UTF8Encoding(False), 15000, "text/html") + Task.Progress = 0.8 + Sources.Add("https://optifine.net/" & RegexSearch(PageData, "downloadx\?f=[^""']+")(0)) + Log("[Download] OptiFine " & DownloadInfo.NameDisplay & " 官方下载地址:" & Sources(0)) + Catch ex As Exception + Log(ex, "获取 OptiFine " & DownloadInfo.NameDisplay & " 官方下载地址失败") + End Try + 'OptiFine 中文镜像源 + Sources.Add("https://optifine.cn/download/" & DownloadInfo.NameFile) + '构造文件请求 + Task.Output = New List(Of NetFile) From {New NetFile(Sources.ToArray, Target, New FileChecker(MinSize:=64 * 1024))} + End Sub) With {.ProgressWeight = 8}) Loaders.Add(New LoaderDownload("下载 OptiFine 主文件", New List(Of NetFile)) With {.ProgressWeight = 8}) Loaders.Add(New LoaderTask(Of List(Of NetFile), Boolean)("等待原版下载", - Sub(Task As LoaderTask(Of List(Of NetFile), Boolean)) - '等待原版文件下载完成 - If ClientDownloadLoader Is Nothing Then Exit Sub - Dim TargetLoaders As List(Of LoaderBase) = - ClientDownloadLoader.GetLoaderList.Where(Function(l) l.Name = McDownloadClientLibName OrElse l.Name = McDownloadClientJsonName). - Where(Function(l) l.State <> LoadState.Finished).ToList - If TargetLoaders.Count > 0 Then Log("[Download] OptiFine 安装正在等待原版文件下载完成") - Do While TargetLoaders.Count > 0 AndAlso Not Task.IsAborted - TargetLoaders = TargetLoaders.Where(Function(l) l.State <> LoadState.Finished).ToList - Thread.Sleep(50) - Loop - If Task.IsAborted Then Exit Sub - '拷贝原版文件 - If Not IsCustomFolder Then Exit Sub - SyncLock VanillaSyncLock - Dim ClientName As String = GetFolderNameFromPath(ClientFolder) - Directory.CreateDirectory(McFolder & "versions\" & DownloadInfo.Inherit) - If Not File.Exists(McFolder & "versions\" & DownloadInfo.Inherit & "\" & DownloadInfo.Inherit & ".json") Then - CopyFile(ClientFolder & ClientName & ".json", + Sub(Task As LoaderTask(Of List(Of NetFile), Boolean)) + '等待原版文件下载完成 + If ClientDownloadLoader Is Nothing Then Exit Sub + Dim TargetLoaders As List(Of LoaderBase) = + ClientDownloadLoader.GetLoaderList.Where(Function(l) l.Name = McDownloadClientLibName OrElse l.Name = McDownloadClientJsonName). + Where(Function(l) l.State <> LoadState.Finished).ToList + If TargetLoaders.Count > 0 Then Log("[Download] OptiFine 安装正在等待原版文件下载完成") + Do While TargetLoaders.Count > 0 AndAlso Not Task.IsAborted + TargetLoaders = TargetLoaders.Where(Function(l) l.State <> LoadState.Finished).ToList + Thread.Sleep(50) + Loop + If Task.IsAborted Then Exit Sub + '拷贝原版文件 + If Not IsCustomFolder Then Exit Sub + SyncLock VanillaSyncLock + Dim ClientName As String = GetFolderNameFromPath(ClientFolder) + Directory.CreateDirectory(McFolder & "versions\" & DownloadInfo.Inherit) + If Not File.Exists(McFolder & "versions\" & DownloadInfo.Inherit & "\" & DownloadInfo.Inherit & ".json") Then + CopyFile(ClientFolder & ClientName & ".json", McFolder & "versions\" & DownloadInfo.Inherit & "\" & DownloadInfo.Inherit & ".json") - End If - If Not File.Exists(McFolder & "versions\" & DownloadInfo.Inherit & "\" & DownloadInfo.Inherit & ".jar") Then - CopyFile(ClientFolder & ClientName & ".jar", + End If + If Not File.Exists(McFolder & "versions\" & DownloadInfo.Inherit & "\" & DownloadInfo.Inherit & ".jar") Then + CopyFile(ClientFolder & ClientName & ".jar", McFolder & "versions\" & DownloadInfo.Inherit & "\" & DownloadInfo.Inherit & ".jar") - End If - End SyncLock - End Sub) With {.ProgressWeight = 0.1, .Show = False}) + End If + End SyncLock + End Sub) With {.ProgressWeight = 0.1, .Show = False}) '安装(新旧方式均需要原版 Jar 和 Json) If IsNewVersion Then @@ -586,7 +590,19 @@ Public Module ModDownloadLib BaseMcFolder & "versions\" & DownloadInfo.Inherit & "\" & DownloadInfo.Inherit & ".jar") Task.Progress = 0.06 '进行安装 - McDownloadOptiFineInstall(BaseMcFolderHome, Target, Task) + Dim UseJavaWrapper As Boolean = True +Retry: + Try + McDownloadOptiFineInstall(BaseMcFolderHome, Target, Task, UseJavaWrapper) + Catch ex As Exception + If UseJavaWrapper Then + Log(ex, "使用 JavaWrapper 安装 OptiFine 失败,将不使用 JavaWrapper 并重试") + UseJavaWrapper = False + GoTo Retry + Else + Throw New Exception("运行 OptiFine 安装器失败", ex) + End If + End Try Task.Progress = 0.96 '复制文件 File.Delete(BaseMcFolder & "launcher_profiles.json") @@ -596,7 +612,7 @@ Public Module ModDownloadLib File.Delete(Target) DeleteDirectory(BaseMcFolderHome) Catch ex As Exception - Throw New Exception("安装新版 OptiFine 版本失败", ex) + Throw New Exception("安装 OptiFine(方式 A)失败", ex) End Try End Sub) With {.ProgressWeight = 8}) Else @@ -645,7 +661,7 @@ Public Module ModDownloadLib End If WriteFile(VersionFolder & Id & ".json", Json) Catch ex As Exception - Throw New Exception("安装旧版 OptiFine 版本失败", ex) + Throw New Exception("安装 OptiFine(方式 B)失败", ex) End Try End Sub) With {.ProgressWeight = 1}) End If @@ -1110,7 +1126,7 @@ Public Module ModDownloadLib End Try End Sub - Private Sub ForgeInjector(Target As String, Task As LoaderTask(Of Boolean, Boolean), McFolder As String) + Private Sub ForgeInjector(Target As String, Task As LoaderTask(Of Boolean, Boolean), McFolder As String, UseJavaWrapper As Boolean) '选择 Java Dim Java = JavaSelect("已取消安装。", New Version(1, 8, 0, 0)) If Java Is Nothing Then @@ -1127,7 +1143,12 @@ Public Module ModDownloadLib If Java Is Nothing Then Throw New Exception("由于未找到 Java,已取消安装。") End If '添加 Java Wrapper 作为主 Jar - Dim Arguments = "-Doolloo.jlw.tmpdir=""" & GetJavaWrapperDir() & """ -cp """ & PathTemp & "Cache\forge_installer.jar;" & Target & """ -jar """ & ExtractJavaWrapper() & """ com.bangbang93.ForgeInstaller """ & McFolder + Dim Arguments As String + If UseJavaWrapper Then + Arguments = $"-Doolloo.jlw.tmpdir=""{GetJavaWrapperDir()}"" -cp ""{PathTemp}Cache\forge_installer.jar;{Target}"" -jar ""{ExtractJavaWrapper()}"" com.bangbang93.ForgeInstaller ""{McFolder}" + Else + Arguments = $"-cp ""{PathTemp}Cache\forge_installer.jar;{Target}"" com.bangbang93.ForgeInstaller ""{McFolder}" + End If If Java.VersionCode >= 9 Then Arguments = "--add-exports cpw.mods.bootstraplauncher/cpw.mods.bootstraplauncher=ALL-UNNAMED " & Arguments '开始启动 SyncLock InstallSyncLock @@ -1415,12 +1436,25 @@ Public Module ModDownloadLib '释放 launcher_installer.json McFolderLauncherProfilesJsonCreate(McFolder) Task.Progress = 0.05 - '释放 Forge 注入器 - WriteFile(PathTemp & "Cache\forge_installer.jar", GetResources("ForgeInstaller")) - Task.Progress = 0.06 - '运行注入器 - ForgeInjector(InstallerAddress, Task, McFolder) - Task.Progress = 0.97 + '运行 Forge 安装器 + Dim UseJavaWrapper As Boolean = True +Retry: + Try + '释放 Forge 注入器 + WriteFile(PathTemp & "Cache\forge_installer.jar", GetResources("ForgeInstaller")) + Task.Progress = 0.06 + '运行注入器 + ForgeInjector(InstallerAddress, Task, McFolder, UseJavaWrapper) + Task.Progress = 0.97 + Catch ex As Exception + If UseJavaWrapper Then + Log(ex, "使用 JavaWrapper 安装 Forge 失败,将不使用 JavaWrapper 并重试") + UseJavaWrapper = False + GoTo Retry + Else + Throw New Exception("运行 Forge 安装器失败", ex) + End If + End Try '拷贝新增的版本 Json Dim DeltaList = New DirectoryInfo(McFolder & "versions\").EnumerateDirectories.SkipWhile(Function(Info As DirectoryInfo) As Boolean Return OldList.Contains(Info.FullName) @@ -1470,7 +1504,7 @@ Public Module ModDownloadLib Task.Progress = 0.6 '解压支持库文件 Installer.Dispose() - ZipFile.ExtractToDirectory(InstallerAddress, InstallerAddress & "_unrar\") + ExtractFile(InstallerAddress, InstallerAddress & "_unrar\") CopyDirectory(InstallerAddress & "_unrar\maven\", McFolder & "libraries\") DeleteDirectory(InstallerAddress & "_unrar\") Else diff --git a/Plain Craft Launcher 2/Pages/PageDownload/PageDownloadInstall.xaml.vb b/Plain Craft Launcher 2/Pages/PageDownload/PageDownloadInstall.xaml.vb index 01e94ba..0138f2d 100644 --- a/Plain Craft Launcher 2/Pages/PageDownload/PageDownloadInstall.xaml.vb +++ b/Plain Craft Launcher 2/Pages/PageDownload/PageDownloadInstall.xaml.vb @@ -848,7 +848,7 @@ If LoadFabric.State.LoadingState = MyLoading.MyLoadingState.Run Then Return "正在获取版本列表……" If LoadFabric.State.LoadingState = MyLoading.MyLoadingState.Error Then Return "获取版本列表失败:" & CType(LoadFabric.State, Object).Error.Message For Each Version As JObject In DlFabricListLoader.Output.Value("game") - If Version("version").ToString = SelectedMinecraftId.Replace("∞", "infinite") Then + If Version("version").ToString = SelectedMinecraftId.Replace("∞", "infinite").Replace("Combat Test 7c", "1.16_combat-3") Then If SelectedForge IsNot Nothing Then Return "与 Forge 不兼容" 'If SelectedOptiFine IsNot Nothing Then Return "与 OptiFine 不兼容" Return Nothing @@ -908,7 +908,7 @@ Public Shared Function IsSuitableFabricApi(DisplayName As String, MinecraftVersion As String) As Boolean Try If DisplayName Is Nothing OrElse MinecraftVersion Is Nothing Then Return False - DisplayName = DisplayName.ToLower : MinecraftVersion = MinecraftVersion.ToLower + DisplayName = DisplayName.ToLower : MinecraftVersion = MinecraftVersion.Replace("∞", "infinite").Replace("Combat Test 7c", "1.16_combat-3").ToLower If DisplayName.StartsWith("[" & MinecraftVersion & "]") Then Return True If Not DisplayName.Contains("/") OrElse Not DisplayName.Contains("]") Then Return False '直接的判断(例如 1.18.1/22w03a) diff --git a/Plain Craft Launcher 2/Pages/PageLaunch/MySkin.xaml.vb b/Plain Craft Launcher 2/Pages/PageLaunch/MySkin.xaml.vb index 5f1849a..e26a226 100644 --- a/Plain Craft Launcher 2/Pages/PageLaunch/MySkin.xaml.vb +++ b/Plain Craft Launcher 2/Pages/PageLaunch/MySkin.xaml.vb @@ -104,7 +104,7 @@ (Image.Pic.GetPixel(1, 1) <> Image.Pic.GetPixel(Scale * 41, Scale * 9) AndAlso '或是头部颜色和透明区均不一样 Image.Pic.GetPixel(Image.Pic.Width - 1, Image.Pic.Height - 1) <> Image.Pic.GetPixel(Scale * 41, Scale * 9) AndAlso Image.Pic.GetPixel(Image.Pic.Width - 2, Image.Pic.Height / 2 - 2) <> Image.Pic.GetPixel(Scale * 41, Scale * 9)) Then - ImgFore.Source = New CroppedBitmap(Image, New Int32Rect(Scale * 40, Scale * 8, Scale * 8, Scale * 8)) + ImgFore.Source = Image.Clip(Scale * 40, Scale * 8, Scale * 8, Scale * 8) Else ImgFore.Source = Nothing End If @@ -112,7 +112,7 @@ ImgFore.Source = Nothing End If '脸层 - ImgBack.Source = New CroppedBitmap(Image, New Int32Rect(Scale * 8, Scale * 8, Scale * 8, Scale * 8)) + ImgBack.Source = Image.Clip(Scale * 8, Scale * 8, Scale * 8, Scale * 8) Log("[Skin] 载入头像成功:" & Loader.Name) Catch ex As Exception Log(ex, "载入头像失败(" & If(Address, "null") & "," & Loader.Name & ")", LogLevel.Hint) diff --git a/Plain Craft Launcher 2/Pages/PageLaunch/PageLaunchLeft.xaml.vb b/Plain Craft Launcher 2/Pages/PageLaunch/PageLaunchLeft.xaml.vb index 0a1cbb3..ce9c4a9 100644 --- a/Plain Craft Launcher 2/Pages/PageLaunch/PageLaunchLeft.xaml.vb +++ b/Plain Craft Launcher 2/Pages/PageLaunch/PageLaunchLeft.xaml.vb @@ -673,14 +673,7 @@ ExitRefresh: McLaunchProcess = Nothing McLaunchWatcher = Nothing '获取 “你知道吗” 提示 - Dim Hint As String = PageOtherTest.GetRandomHint() - Try - Dim RawHints = ReadFile(Path & "PCL\hints.txt").Split(vbCrLf.ToCharArray).Where(Function(s) Not String.IsNullOrWhiteSpace(s)).ToList - If RawHints.Count > 0 Then Hint = RandomOne(RawHints) - Catch ex As Exception - Log(ex, "获取自定义 你知道吗 提示失败", LogLevel.Hint) - End Try - LabLaunchingHint.Text = Hint + LabLaunchingHint.Text = PageOtherTest.GetRandomHint() End Sub Private ShowProgress As Double = 0 ''' diff --git a/Plain Craft Launcher 2/Pages/PageLink/PageLinkIoi.xaml.vb b/Plain Craft Launcher 2/Pages/PageLink/PageLinkIoi.xaml.vb index 85ee5c3..8d7a317 100644 --- a/Plain Craft Launcher 2/Pages/PageLink/PageLinkIoi.xaml.vb +++ b/Plain Craft Launcher 2/Pages/PageLink/PageLinkIoi.xaml.vb @@ -133,7 +133,7 @@ StartDownload: Log("[IOI] 解压联机模块以完成下载") If File.Exists(PathTemp & "ioi.exe") Then File.Delete(PathTemp & "ioi.exe") If File.Exists(PathIoi) Then File.Delete(PathIoi) - Compression.ZipFile.ExtractToDirectory(PathTemp & "联机模块.zip", PathTemp) + ExtractFile(PathTemp & "联机模块.zip", PathTemp) File.Delete(PathTemp & "联机模块.zip") CopyFile(PathTemp & "ioi.exe", PathIoi) File.Delete(PathTemp & "ioi.exe") diff --git a/Plain Craft Launcher 2/Pages/PageOther/PageOtherHelpDetail.xaml.vb b/Plain Craft Launcher 2/Pages/PageOther/PageOtherHelpDetail.xaml.vb index 203bd0f..79aecfd 100644 --- a/Plain Craft Launcher 2/Pages/PageOther/PageOtherHelpDetail.xaml.vb +++ b/Plain Craft Launcher 2/Pages/PageOther/PageOtherHelpDetail.xaml.vb @@ -14,7 +14,7 @@ If String.IsNullOrEmpty(Entry.XamlContent) Then Throw New Exception("帮助 xaml 文件为空") Me.Entry = Entry PanCustom.Children.Clear() - FileContent = FileContent.Replace("{path}", Path) + FileContent = HelpArgumentReplace(FileContent) PanCustom.Children.Add(GetObjectFromXML(FileContent)) Return True Catch ex As Exception diff --git a/Plain Craft Launcher 2/Pages/PageSelectRight.xaml.vb b/Plain Craft Launcher 2/Pages/PageSelectRight.xaml.vb index ea70ccd..215b136 100644 --- a/Plain Craft Launcher 2/Pages/PageSelectRight.xaml.vb +++ b/Plain Craft Launcher 2/Pages/PageSelectRight.xaml.vb @@ -219,6 +219,7 @@ If(IsHintIndie, vbCrLf & "由于该版本开启了版本隔离,删除版本时该版本对应的存档、资源包、Mod 等文件也将被一并删除!", ""), "版本删除确认", , "取消",, True) Case 1 + IniClearCache(Version.Path & "PCL\Setup.ini") If IsShiftPressed Then DeleteDirectory(Version.Path) Hint("版本 " & Version.Name & " 已永久删除!", HintType.Finish) diff --git a/Plain Craft Launcher 2/Pages/PageSetup/PageSetupSystem.xaml b/Plain Craft Launcher 2/Pages/PageSetup/PageSetupSystem.xaml index 16966f9..d188d32 100644 --- a/Plain Craft Launcher 2/Pages/PageSetup/PageSetupSystem.xaml +++ b/Plain Craft Launcher 2/Pages/PageSetup/PageSetupSystem.xaml @@ -74,7 +74,7 @@ - + diff --git a/Plain Craft Launcher 2/Pages/PageSpeedLeft.xaml.vb b/Plain Craft Launcher 2/Pages/PageSpeedLeft.xaml.vb index b3874fe..3e961fd 100644 --- a/Plain Craft Launcher 2/Pages/PageSpeedLeft.xaml.vb +++ b/Plain Craft Launcher 2/Pages/PageSpeedLeft.xaml.vb @@ -195,7 +195,6 @@ AniDispose(sender, False) AniDispose(Card, True, Sub() If FrmSpeedRight.PanMain.Children.Count = 0 AndAlso FrmMain.PageCurrent = FormMain.PageType.DownloadManager Then FrmMain.PageBack()) RightCards.Remove(Loader.Name) - LoaderTaskbar.Remove(Loader) Log($"[Watcher] 关闭下载管理卡片:{Loader.Name}") RunInThread(Sub() Loader.Abort()) End Sub diff --git a/Plain Craft Launcher 2/Resources/Custom.xaml b/Plain Craft Launcher 2/Resources/Custom.xaml index 1dcaf68..3502147 100644 --- a/Plain Craft Launcher 2/Resources/Custom.xaml +++ b/Plain Craft Launcher 2/Resources/Custom.xaml @@ -4,102 +4,102 @@ 你也可以使用 Ctrl + F 快速查找。例如,若需要改变文本颜色,则搜索 “颜色” 即可。 --> - + - + - - - + + - + - + - - + + - + - - - - + - + - - - - + - + - - - + - + - - - - + + - - + + @@ -133,128 +133,176 @@ - - - + + - - - + + - - - - - - + + + - - - - - - - - - - - - - - - - - - - - - - - - + + - + - - - + - + - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + - - + - + - + - - + + - - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file +local:MyIconTextButton(带图标的按钮): + - Text:设置显示的文本 + - Logo:设置显示的图标 + - LogoScale:设置图标的缩放,默认为 1 + - ColorType:设置颜色主题(Highlight 为当前启动器的主题颜色,默认为黑色) + - EventType、EventData:触发特定事件 + +local:MyIconButton(图标按钮): + - Logo:设置显示的图标 + - LogoScale:设置图标的缩放,默认为 1 + - Theme:设置颜色主题,Color(默认)为当前启动器的主题颜色,也可设置为 White、Black、Red + - EventType、EventData:触发特定事件 + +--> diff --git a/Plain Craft Launcher 2/Resources/Help.zip b/Plain Craft Launcher 2/Resources/Help.zip index 481cadecb8a08482dbf235f8c0559895bdd8dded..bd5a837759d36c1ca6e35c09399851ca94d3988e 100644 GIT binary patch delta 42279 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 JO9^OE{{vIg{`UX? delta 40004 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 F_g{5DerW&z