龙腾猫跃 3 лет назад
Родитель
Сommit
5fb5a3b963

+ 0 - 1
Plain Craft Launcher 2/Application.xaml.vb

@@ -15,7 +15,6 @@ Public Class Application
             Log(ex, "开发者模式测试出错", LogLevel.Feedback)
             Log(ex, "开发者模式测试出错", LogLevel.Feedback)
         End Try
         End Try
     End Sub
     End Sub
-
 #End If
 #End If
 
 
     '开始
     '开始

+ 11 - 3
Plain Craft Launcher 2/Controls/MyCard.vb

@@ -287,9 +287,9 @@
 End Class
 End Class
 Partial Public Module ModAnimation
 Partial Public Module ModAnimation
     Public Sub AniDispose(Control As MyCard, RemoveFromChildren As Boolean, Optional CallBack As ParameterizedThreadStart = Nothing)
     Public Sub AniDispose(Control As MyCard, RemoveFromChildren As Boolean, Optional CallBack As ParameterizedThreadStart = Nothing)
-        If Not Control.IsHitTestVisible Then Exit Sub
-        Control.IsHitTestVisible = False
-        AniStart({
+        If Control.IsHitTestVisible Then
+            Control.IsHitTestVisible = False
+            AniStart({
                      AaScaleTransform(Control, -0.08, 200,, New AniEaseInFluent),
                      AaScaleTransform(Control, -0.08, 200,, New AniEaseInFluent),
                      AaOpacity(Control, -1, 200,, New AniEaseOutFluent),
                      AaOpacity(Control, -1, 200,, New AniEaseOutFluent),
                      AaHeight(Control, -Control.ActualHeight, 150, 100, New AniEaseOutFluent),
                      AaHeight(Control, -Control.ActualHeight, 150, 100, New AniEaseOutFluent),
@@ -302,5 +302,13 @@ Partial Public Module ModAnimation
                                 If CallBack IsNot Nothing Then CallBack(Control)
                                 If CallBack IsNot Nothing Then CallBack(Control)
                             End Sub,, True)
                             End Sub,, True)
             }, "MyCard Dispose " & Control.Uuid)
             }, "MyCard Dispose " & Control.Uuid)
+        Else
+            If RemoveFromChildren Then
+                CType(Control.Parent, Object).Children.Remove(Control)
+            Else
+                Control.Visibility = Visibility.Collapsed
+            End If
+            If CallBack IsNot Nothing Then CallBack(Control)
+        End If
     End Sub
     End Sub
 End Module
 End Module

+ 13 - 1
Plain Craft Launcher 2/FormMain.xaml.vb

@@ -10,6 +10,12 @@ Public Class FormMain
         Dim FeatureList As New List(Of KeyValuePair(Of Integer, String))
         Dim FeatureList As New List(Of KeyValuePair(Of Integer, String))
         '统计更新日志条目
         '统计更新日志条目
 #If BETA Then
 #If BETA Then
+        If LastVersion < 270 Then 'Release 2.4.3
+            FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "优化 Mod、整合包下载的版本检查与显示"))
+            If LastVersion <= 267 Then FeatureList.Add(New KeyValuePair(Of Integer, String)(1, "修复无法安装 LiteLoader 的 Bug"))
+            FeatureCount += 6
+            BugCount += 15
+        End If
         If LastVersion < 268 Then 'Release 2.4.2
         If LastVersion < 268 Then 'Release 2.4.2
             FeatureList.Add(New KeyValuePair(Of Integer, String)(5, "暂时关闭了联机功能"))
             FeatureList.Add(New KeyValuePair(Of Integer, String)(5, "暂时关闭了联机功能"))
             FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "游戏崩溃的弹窗添加了直接查看日志的选项"))
             FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "游戏崩溃的弹窗添加了直接查看日志的选项"))
@@ -100,6 +106,12 @@ Public Class FormMain
         '3:BUG+ IMP* FEAT-
         '3:BUG+ IMP* FEAT-
         '2:BUG* IMP-
         '2:BUG* IMP-
         '1:BUG-
         '1:BUG-
+        If LastVersion < 271 Then 'Snapshot 2.4.3
+            FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "优化 Mod、整合包下载的版本检查与显示"))
+            If LastVersion <= 267 Then FeatureList.Add(New KeyValuePair(Of Integer, String)(1, "修复无法安装 LiteLoader 的 Bug"))
+            FeatureCount += 6
+            BugCount += 15
+        End If
         If LastVersion < 269 Then 'Snapshot 2.4.2
         If LastVersion < 269 Then 'Snapshot 2.4.2
             If LastVersion = 267 Then FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "修复无法下载 CurseForge 整合包的 Bug"))
             If LastVersion = 267 Then FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "修复无法下载 CurseForge 整合包的 Bug"))
             FeatureCount += 2
             FeatureCount += 2
@@ -1136,7 +1148,7 @@ Install:
         If MyMsgBox("由于联机提供商要求新联机强制付费,且高度商业化,PCL 将暂时关闭联机功能,不再使用该联机模块。" & vbCrLf &
         If MyMsgBox("由于联机提供商要求新联机强制付费,且高度商业化,PCL 将暂时关闭联机功能,不再使用该联机模块。" & vbCrLf &
                     "PCL、HMCL、BakaXL 将合作开发新的跨启动器联机功能,在开发结束后将同步开放,请各位多多理解。",
                     "PCL、HMCL、BakaXL 将合作开发新的跨启动器联机功能,在开发结束后将同步开放,请各位多多理解。",
                     "联机功能已暂时关闭", "查看详情", "确定") = 1 Then
                     "联机功能已暂时关闭", "查看详情", "确定") = 1 Then
-            OpenWebsite("https://www.bilibili.com/read/cv19553725")
+            OpenWebsite("https://www.bilibili.com/read/cv19845645")
         End If
         End If
         e.Handled = True
         e.Handled = True
     End Sub
     End Sub

+ 6 - 4
Plain Craft Launcher 2/Modules/Base/ModBase.vb

@@ -10,12 +10,12 @@ Public Module ModBase
 #Region "声明"
 #Region "声明"
 
 
     '下列版本信息由更新器自动修改
     '下列版本信息由更新器自动修改
-    Public Const VersionBaseName As String = "2.4.2" '不含分支前缀的显示用版本名
-    Public Const VersionStandardCode As String = "2.4.2." & VersionBranchCode '标准格式的四段式版本号
+    Public Const VersionBaseName As String = "2.4.3" '不含分支前缀的显示用版本名
+    Public Const VersionStandardCode As String = "2.4.3." & VersionBranchCode '标准格式的四段式版本号
 #If BETA Then
 #If BETA Then
-    Public Const VersionCode As Integer = 268 'Release
+    Public Const VersionCode As Integer = 270 'Release
 #Else
 #Else
-    Public Const VersionCode As Integer = 269 'Snapshot
+    Public Const VersionCode As Integer = 271 'Snapshot
 #End If
 #End If
     '自动生成的版本信息
     '自动生成的版本信息
     Public Const VersionDisplayName As String = VersionBranchName & " " & VersionBaseName
     Public Const VersionDisplayName As String = VersionBranchName & " " & VersionBaseName
@@ -771,6 +771,8 @@ Public Module ModBase
             '还原文件路径
             '还原文件路径
             If Not FromPath.Contains(":\") Then FromPath = Path & FromPath
             If Not FromPath.Contains(":\") Then FromPath = Path & FromPath
             If Not ToPath.Contains(":\") Then ToPath = Path & ToPath
             If Not ToPath.Contains(":\") Then ToPath = Path & ToPath
+            '如果复制同一个文件则跳过
+            If FromPath = ToPath Then Exit Sub
             '读取文件内容
             '读取文件内容
             Dim FileBytes As Byte()
             Dim FileBytes As Byte()
             Using ReadStream As New FileStream(FromPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite) '支持读取使用中的文件
             Using ReadStream As New FileStream(FromPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite) '支持读取使用中的文件

+ 42 - 32
Plain Craft Launcher 2/Modules/Minecraft/ModDownload.vb

@@ -221,6 +221,7 @@
                 McDownloadClientUpdateHint(Version, Json)
                 McDownloadClientUpdateHint(Version, Json)
                 IsNewClientVersionHinted = True
                 IsNewClientVersionHinted = True
             End If
             End If
+            McVersionHighest = Version.Split(".")(1)
             Setup.Set("ToolUpdateReleaseLast", Version)
             Setup.Set("ToolUpdateReleaseLast", Version)
             '解析更新提示(Snapshot)
             '解析更新提示(Snapshot)
             Version = Json("latest")("snapshot")
             Version = Json("latest")("snapshot")
@@ -772,7 +773,7 @@
         ''' </summary>
         ''' </summary>
         Public IsLegacy As Boolean
         Public IsLegacy As Boolean
         ''' <summary>
         ''' <summary>
-        ''' 发布时间,格式为“yyyy/mm/dd HH:mm:ss”。
+        ''' 发布时间,格式为“yyyy/mm/dd HH:mm”。
         ''' </summary>
         ''' </summary>
         Public ReleaseTime As String
         Public ReleaseTime As String
         ''' <summary>
         ''' <summary>
@@ -1090,33 +1091,27 @@
             DateUpdate = Data("dateModified")
             DateUpdate = Data("dateModified")
             DownloadCount = Data("downloadCount")
             DownloadCount = Data("downloadCount")
             IsModPack = Not Website.Contains("/mc-mods/")
             IsModPack = Not Website.Contains("/mc-mods/")
-            '获取常见文件
+            '获取 Mod Loader 列表
+            ModLoaders = New List(Of String)
             For Each File In If(Data("latestFiles"), {})
             For Each File In If(Data("latestFiles"), {})
                 Dim NewFile As New DlCfFile(File, IsModPack)
                 Dim NewFile As New DlCfFile(File, IsModPack)
                 If Not NewFile.IsAvailable Then Continue For
                 If Not NewFile.IsAvailable Then Continue For
+                ModLoaders.AddRange(NewFile.ModLoaders)
             Next
             Next
-            '获取游戏版本、Mod Loader
+            ModLoaders = ModLoaders.Distinct.ToList
+            '用一个偷懒的方式让 Forge 排在 Fabric 的前面
+            ModLoaders = ModLoaders.Select(Function(s) s.Replace("Forge", "Aorge")).ToList()
+            ModLoaders.Sort()
+            ModLoaders = ModLoaders.Select(Function(s) s.Replace("Aorge", "Forge")).ToList()
+            '获取游戏版本
             Dim GameVersions As New List(Of Integer)
             Dim GameVersions As New List(Of Integer)
-            ModLoaders = New List(Of String)
             For Each File In If(Data("latestFilesIndexes"), {})
             For Each File In If(Data("latestFilesIndexes"), {})
                 Dim Version As String = File("gameVersion")
                 Dim Version As String = File("gameVersion")
                 If Not Version.Contains("1.") Then Continue For
                 If Not Version.Contains("1.") Then Continue For
                 GameVersions.Add(Version.Split(".")(1).Split("-").First)
                 GameVersions.Add(Version.Split(".")(1).Split("-").First)
-                Select Case If(File("modLoader"), "0").ToString
-                    Case 1
-                        ModLoaders.Add("Forge")
-                    Case 2
-                        ModLoaders.Add("Cauldron")
-                    Case 3
-                        ModLoaders.Add("LiteLoader")
-                    Case 4
-                        ModLoaders.Add("Fabric")
-                End Select
                 FileIndexes.Add(File("fileId"))
                 FileIndexes.Add(File("fileId"))
             Next
             Next
             GameVersions = Sort(GameVersions.Distinct.ToList, AddressOf VersionSortBoolean)
             GameVersions = Sort(GameVersions.Distinct.ToList, AddressOf VersionSortBoolean)
-            ModLoaders = ModLoaders.Distinct.ToList
-            ModLoaders.Sort()
             If GameVersions.Count = 0 Then
             If GameVersions.Count = 0 Then
                 GameVersionDesc = ""
                 GameVersionDesc = ""
             Else
             Else
@@ -1133,8 +1128,15 @@
                     Next
                     Next
                     If StartVersion = EndVersion Then
                     If StartVersion = EndVersion Then
                         SpaVersions.Add("1." & StartVersion)
                         SpaVersions.Add("1." & StartVersion)
+                    ElseIf StartVersion >= McVersionHighest Then
+                        SpaVersions.Add("1." & EndVersion & "+")
+                    ElseIf EndVersion <= 7 Then
+                        SpaVersions.Add("1." & StartVersion & "-")
+                        Exit For
+                    ElseIf StartVersion - EndVersion = 1 Then
+                        SpaVersions.Add("1." & StartVersion & ", 1." & EndVersion)
                     Else
                     Else
-                        SpaVersions.Add("1." & StartVersion & "-1." & EndVersion)
+                        SpaVersions.Add("1." & StartVersion & "~1." & EndVersion)
                     End If
                     End If
                 Next
                 Next
                 GameVersionDesc = "[" & Join(SpaVersions, ", ") & "] "
                 GameVersionDesc = "[" & Join(SpaVersions, ", ") & "] "
@@ -1211,12 +1213,11 @@
             Dim NewItem As New MyCfItem With {.Tag = Me}
             Dim NewItem As New MyCfItem With {.Tag = Me}
             NewItem.LabTitle.Text = ChineseName
             NewItem.LabTitle.Text = ChineseName
             NewItem.LabInfo.Text = Description.Replace(vbCr, "").Replace(vbLf, "")
             NewItem.LabInfo.Text = Description.Replace(vbCr, "").Replace(vbLf, "")
-            NewItem.LabLeft.Text = If(ModLoaders.Count > 0 AndAlso ShowLoaderDesc, "[" & Join(ModLoaders, " & ") & "] ", "") &
-                                   If(ShowVersionDesc, GameVersionDesc, "") &
+            NewItem.LabLeft.Text = (If(ModLoaders.Count > 0 AndAlso ShowLoaderDesc, "[" & Join(ModLoaders, "/") & "] ", "") &
+                                   If(ShowVersionDesc, GameVersionDesc, "")).Replace("] [", " ") &
                                    Join(CategoryDesc, ",") & " (" &
                                    Join(CategoryDesc, ",") & " (" &
-                                   GetTimeSpanString(DateUpdate - Date.Now) & "更新" &
-                                   If(DownloadCount > 0,
-                                        "," & If(DownloadCount > 100000, Math.Round(DownloadCount / 10000) & " 万次下载", DownloadCount & " 次下载"), "") & ")"
+                                   GetTimeSpanString(DateUpdate - Date.Now) & "更新," &
+                                   If(DownloadCount > 100000, Math.Round(DownloadCount / 10000) & " 万次下载", DownloadCount & " 次下载") & ")"
             If Thumb Is Nothing Then
             If Thumb Is Nothing Then
                 NewItem.Logo = "pack://application:,,,/images/Icons/NoIcon.png"
                 NewItem.Logo = "pack://application:,,,/images/Icons/NoIcon.png"
             Else
             Else
@@ -1279,7 +1280,7 @@
             Dim SearchResult As String = ""
             Dim SearchResult As String = ""
             For i = 0 To SearchResults.Count - 1
             For i = 0 To SearchResults.Count - 1
                 If Not SearchResults(i).AbsoluteRight AndAlso i >= Math.Min(2, SearchResults.Count - 1) Then Exit For '把 3 个结果拼合以提高准确度
                 If Not SearchResults(i).AbsoluteRight AndAlso i >= Math.Min(2, SearchResults.Count - 1) Then Exit For '把 3 个结果拼合以提高准确度
-                SearchResult += SearchResults(i).Item.Replace(" (", "|").Split("|").Last.TrimEnd(")") & " "
+                SearchResult += SearchResults(i).Item.Replace(" - ", "§").Split("§").First.Replace(" (", "|").Split("|").Last.TrimEnd(")") & " "
             Next
             Next
             Log("[Download] CurseForge 工程列表中文搜索原始关键词:" & SearchResult, LogLevel.Developer)
             Log("[Download] CurseForge 工程列表中文搜索原始关键词:" & SearchResult, LogLevel.Developer)
             '去除常见连接词
             '去除常见连接词
@@ -1432,6 +1433,7 @@
         Public DisplayName As String
         Public DisplayName As String
         Public [Date] As Date
         Public [Date] As Date
         Public GameVersion As String()
         Public GameVersion As String()
+        Public ModLoaders As New List(Of String)
         Public ReleaseType As Integer
         Public ReleaseType As Integer
         Public FileName As String
         Public FileName As String
         Public DownloadCount As Integer
         Public DownloadCount As Integer
@@ -1481,11 +1483,13 @@
                     End If
                     End If
                 Next
                 Next
             End If
             End If
-            '获取游戏版本
+            '获取游戏版本与 Mod 加载器列表
             Dim Versions As New List(Of String)
             Dim Versions As New List(Of String)
-            For Each Version In Data("gameVersions")
-                If Version.ToString.StartsWith("1.") OrElse Version.ToString.Contains("w") Then
-                    Versions.Add(Version.ToString.Trim.ToLower)
+            For Each Version In Data("gameVersions").Select(Function(t) t.ToString.Trim.ToLower)
+                If Version.StartsWith("1.") OrElse Version.Contains("w") Then
+                    Versions.Add(Version)
+                ElseIf Version = "forge" OrElse Version = "fabric" OrElse Version = "quilt" OrElse Version = "rift" Then
+                    ModLoaders.Add(Version.First.ToString.ToUpper & Version.Substring(1))
                 End If
                 End If
             Next
             Next
             If Versions.Count > 1 Then
             If Versions.Count > 1 Then
@@ -1493,11 +1497,13 @@
                 If IsModPack Then GameVersion = {GameVersion(0)}
                 If IsModPack Then GameVersion = {GameVersion(0)}
             ElseIf Versions.Count = 1 Then
             ElseIf Versions.Count = 1 Then
                 GameVersion = Versions.ToArray
                 GameVersion = Versions.ToArray
-                'ElseIf Data("gameVersion").Count = 1 AndAlso Not Data("gameVersion")(0).ToString.Contains("1.") Then
-                '    GameVersion = {"1.16.4"}
             Else
             Else
                 GameVersion = {"未知版本"}
                 GameVersion = {"未知版本"}
             End If
             End If
+            '用一个偷懒的方式让 Forge 排在 Fabric 的前面
+            ModLoaders = ModLoaders.Select(Function(s) s.Replace("Forge", "Aorge")).ToList()
+            ModLoaders.Sort()
+            ModLoaders = ModLoaders.Select(Function(s) s.Replace("Aorge", "Forge")).ToList()
         End Sub
         End Sub
 
 
         ''' <summary>
         ''' <summary>
@@ -1513,10 +1519,14 @@
             '获取描述信息
             '获取描述信息
             Dim Info As String = ""
             Dim Info As String = ""
             If Not IsModPack Then
             If Not IsModPack Then
-                Info += "适用于 " & Join(GameVersion, "、").Replace("-snapshot", " 快照") &
-                          If(ModeDebug AndAlso Dependencies.Count > 0, "," & Dependencies.Count & " 个前置,", ",")
+                Info += If(ModLoaders.Count > 0, Join(ModLoaders, "/"), "") &
+                        If(GameVersion.Count > 1, If(ModLoaders.Count > 0, " ", "") & Join(GameVersion, "、").Replace("-snapshot", " 快照"), "")
+                If Info <> "" Then Info = "适用于 " & Info & ","
+                Info += If(ModeDebug AndAlso Dependencies.Count > 0, Dependencies.Count & " 个前置 Mod,", "")
             End If
             End If
-            Info += If(DownloadCount > 0, If(DownloadCount > 100000, Math.Round(DownloadCount / 10000) & " 万次下载,", DownloadCount & " 次下载,"), "")
+            'If DownloadCount > 0 Then 'DownloadCount 目前的返回内容完全不正确,经常是 0,干脆不显示了
+            '    Info += If(DownloadCount > 100000, Math.Round(DownloadCount / 10000) & " 万次下载,", DownloadCount & " 次下载,")
+            'End If
             Info += GetTimeSpanString([Date] - Date.Now) & "更新"
             Info += GetTimeSpanString([Date] - Date.Now) & "更新"
             Info += If(ReleaseType <> 1, "," & ReleaseTypeString, "")
             Info += If(ReleaseType <> 1, "," & ReleaseTypeString, "")
 
 

+ 35 - 17
Plain Craft Launcher 2/Modules/Minecraft/ModLaunch.vb

@@ -1078,19 +1078,30 @@ SystemBrowser:
             MaxVer = New Version(1, 12, 999, 999)
             MaxVer = New Version(1, 12, 999, 999)
         End If
         End If
 
 
+        'OptiFine 检测
+        If McVersionCurrent.Version.HasOptiFine Then
+            If McVersionCurrent.Version.McCodeMain <= 7 AndAlso McVersionCurrent.Version.McCodeMain > 0 Then
+                '<1.7:至多 Java 8(Java 9 - 10 未测试)
+                MaxVer = New Version(1, 8, 999, 999)
+            ElseIf McVersionCurrent.Version.McCodeMain >= 8 AndAlso McVersionCurrent.Version.McCodeMain <= 11 Then
+                '1.8 - 1.11:必须恰好 Java 8(Java 9 - 10 未测试)
+                MinVer = New Version(1, 8, 0, 0) : MaxVer = New Version(1, 8, 999, 999)
+            End If
+        End If
+
         'Forge 检测
         'Forge 检测
         If McVersionCurrent.Version.HasForge Then
         If McVersionCurrent.Version.HasForge Then
             If McVersionCurrent.Version.McName = "1.7.2" Then
             If McVersionCurrent.Version.McName = "1.7.2" Then
                 '1.7.2:必须 Java 7
                 '1.7.2:必须 Java 7
                 MinVer = New Version(1, 7, 0, 0) : MaxVer = New Version(1, 7, 999, 999)
                 MinVer = New Version(1, 7, 0, 0) : MaxVer = New Version(1, 7, 999, 999)
             ElseIf McVersionCurrent.Version.McCodeMain <= 12 AndAlso McVersionCurrent.Version.McCodeMain > 0 AndAlso VersionSortBoolean("14.23.5.2855", McVersionCurrent.Version.ForgeVersion) Then
             ElseIf McVersionCurrent.Version.McCodeMain <= 12 AndAlso McVersionCurrent.Version.McCodeMain > 0 AndAlso VersionSortBoolean("14.23.5.2855", McVersionCurrent.Version.ForgeVersion) Then
-                '1.12,Forge 14.23.5.2855 及更低:Java 8
+                '<1.12,Forge 14.23.5.2855 及更低:Java 8
                 MaxVer = New Version(1, 8, 999, 999)
                 MaxVer = New Version(1, 8, 999, 999)
             ElseIf McVersionCurrent.Version.McCodeMain <= 14 AndAlso McVersionCurrent.Version.McCodeMain > 0 AndAlso VersionSortBoolean("28.2.23", McVersionCurrent.Version.ForgeVersion) Then
             ElseIf McVersionCurrent.Version.McCodeMain <= 14 AndAlso McVersionCurrent.Version.McCodeMain > 0 AndAlso VersionSortBoolean("28.2.23", McVersionCurrent.Version.ForgeVersion) Then
                 '1.13 - 1.14,Forge 28.2.23 及更低:Java 8 - 10
                 '1.13 - 1.14,Forge 28.2.23 及更低:Java 8 - 10
                 MinVer = New Version(1, 8, 0, 0) : MaxVer = New Version(1, 10, 999, 999)
                 MinVer = New Version(1, 8, 0, 0) : MaxVer = New Version(1, 10, 999, 999)
-            ElseIf McVersionCurrent.Version.McCodeMain <= 16 AndAlso McVersionCurrent.Version.McCodeMain > 0 Then
-                '1.15 - 1.16:Java 8 - 15
+            ElseIf McVersionCurrent.Version.McCodeMain <= 15 AndAlso McVersionCurrent.Version.McCodeMain > 0 Then
+                '1.15:Java 8 - 15
                 MinVer = New Version(1, 8, 0, 0) : MaxVer = New Version(1, 15, 999, 999)
                 MinVer = New Version(1, 8, 0, 0) : MaxVer = New Version(1, 15, 999, 999)
             ElseIf McVersionCurrent.Version.McCodeMain >= 18 AndAlso McVersionCurrent.Version.McCodeMain < 99 AndAlso McVersionCurrent.Version.HasOptiFine Then '#305
             ElseIf McVersionCurrent.Version.McCodeMain >= 18 AndAlso McVersionCurrent.Version.McCodeMain < 99 AndAlso McVersionCurrent.Version.HasOptiFine Then '#305
                 '1.18+:若安装了 OptiFine,最高 Java 18
                 '1.18+:若安装了 OptiFine,最高 Java 18
@@ -1101,8 +1112,8 @@ SystemBrowser:
         'Fabric 检测
         'Fabric 检测
         If McVersionCurrent.Version.HasFabric Then
         If McVersionCurrent.Version.HasFabric Then
             If McVersionCurrent.Version.McCodeMain >= 15 AndAlso McVersionCurrent.Version.McCodeMain <= 16 AndAlso McVersionCurrent.Version.McCodeMain <> -1 Then
             If McVersionCurrent.Version.McCodeMain >= 15 AndAlso McVersionCurrent.Version.McCodeMain <= 16 AndAlso McVersionCurrent.Version.McCodeMain <> -1 Then
-                '1.15 - 1.16:Java 8 - 15
-                MinVer = New Version(1, 8, 0, 0) : MaxVer = New Version(1, 15, 999, 999)
+                '1.15 - 1.16:Java 8 - 18
+                MinVer = New Version(1, 8, 0, 0) : MaxVer = New Version(1, 18, 999, 999)
             ElseIf McVersionCurrent.Version.McCodeMain >= 18 AndAlso McVersionCurrent.Version.McCodeMain < 99 Then
             ElseIf McVersionCurrent.Version.McCodeMain >= 18 AndAlso McVersionCurrent.Version.McCodeMain < 99 Then
                 '1.18+:Java 17 - 18
                 '1.18+:Java 17 - 18
                 MinVer = New Version(1, 17, 0, 0) : MaxVer = New Version(1, 18, 999, 999)
                 MinVer = New Version(1, 17, 0, 0) : MaxVer = New Version(1, 18, 999, 999)
@@ -1150,22 +1161,29 @@ SystemBrowser:
     Private McLaunchArgument As String
     Private McLaunchArgument As String
 
 
     ''' <summary>
     ''' <summary>
-    ''' 释放 Java Wrapper 并返回文件路径。
+    ''' 释放 Java Wrapper 并返回完整文件路径。
     ''' </summary>
     ''' </summary>
     Public Function ExtractJavaWrapper() As String
     Public Function ExtractJavaWrapper() As String
-        Dim WrapperPath As String = PathAppdata & "JavaWrapper.jar"
+        Dim WrapperPath As String = GetJavaWrapperDir() & "\JavaWrapper.jar"
+        If Not File.Exists(WrapperPath) OrElse New FileInfo(WrapperPath).Length <> 16818 Then
+            WriteFile(WrapperPath, GetResources("JavaWrapper"))
+            Log("[Java] 已自动释放 Java Wrapper:" & WrapperPath)
+        End If
+        Return WrapperPath
+    End Function
+    ''' <summary>
+    ''' 获取 Java Wrapper 所在的文件夹,不以 \ 结尾。
+    ''' </summary>
+    Public Function GetJavaWrapperDir() As String
+        Dim WrapperPath As String = PathAppdata.TrimEnd("\")
         If Encoding.UTF8.GetByteCount(WrapperPath) <> WrapperPath.Length Then
         If Encoding.UTF8.GetByteCount(WrapperPath) <> WrapperPath.Length Then
             Log("[Java] AppData 路径中包含非 ASCII 字符,换用 Temp 目录")
             Log("[Java] AppData 路径中包含非 ASCII 字符,换用 Temp 目录")
-            WrapperPath = PathTemp & "JavaWrapper.jar"
+            WrapperPath = PathTemp.TrimEnd("\")
             If Encoding.UTF8.GetByteCount(PathTemp) <> PathTemp.Length Then
             If Encoding.UTF8.GetByteCount(PathTemp) <> PathTemp.Length Then
                 Log("[Java] Temp 路径中包含非 ASCII 字符,换用 C 盘根目录")
                 Log("[Java] Temp 路径中包含非 ASCII 字符,换用 C 盘根目录")
-                WrapperPath = "C:\PCL\JavaWrapper.jar"
+                WrapperPath = "C:\PCL"
             End If
             End If
         End If
         End If
-        If Not File.Exists(WrapperPath) OrElse New FileInfo(WrapperPath).Length > 20 * 1024 Then
-            WriteFile(WrapperPath, GetResources("JavaWrapper"))
-            Log("[Java] 已自动释放 Java Wrapper:" & WrapperPath)
-        End If
         Return WrapperPath
         Return WrapperPath
     End Function
     End Function
 
 
@@ -1185,7 +1203,7 @@ SystemBrowser:
             McLaunchLog("旧版 JVM 参数获取成功:")
             McLaunchLog("旧版 JVM 参数获取成功:")
             McLaunchLog(Arguments)
             McLaunchLog(Arguments)
         End If
         End If
-        If McVersionCurrent.JsonObject("minecraftArguments") IsNot Nothing Then
+        If Not String.IsNullOrEmpty(McVersionCurrent.JsonObject("minecraftArguments")) Then '有的版本是空字符串
             McLaunchLog("获取旧版 Game 参数")
             McLaunchLog("获取旧版 Game 参数")
             Arguments += " " & McLaunchArgumentsGameOld(McVersionCurrent)
             Arguments += " " & McLaunchArgumentsGameOld(McVersionCurrent)
             McLaunchLog("旧版 Game 参数获取成功")
             McLaunchLog("旧版 Game 参数获取成功")
@@ -1270,6 +1288,7 @@ SystemBrowser:
 
 
         '添加 Java Wrapper 作为主 Jar
         '添加 Java Wrapper 作为主 Jar
         If McLaunchJavaSelected.VersionCode >= 9 Then DataList.Add("--add-exports cpw.mods.bootstraplauncher/cpw.mods.bootstraplauncher=ALL-UNNAMED")
         If McLaunchJavaSelected.VersionCode >= 9 Then DataList.Add("--add-exports cpw.mods.bootstraplauncher/cpw.mods.bootstraplauncher=ALL-UNNAMED")
+        DataList.Insert(0, "-Doolloo.jlw.tmpdir=""" & GetJavaWrapperDir() & """")
         DataList.Add("-jar """ & ExtractJavaWrapper() & """")
         DataList.Add("-jar """ & ExtractJavaWrapper() & """")
 
 
         '添加 MainClass
         '添加 MainClass
@@ -1336,6 +1355,7 @@ NextVersion:
 
 
         '添加 Java Wrapper 作为主 Jar
         '添加 Java Wrapper 作为主 Jar
         If McLaunchJavaSelected.VersionCode >= 9 Then DataList.Add("--add-exports cpw.mods.bootstraplauncher/cpw.mods.bootstraplauncher=ALL-UNNAMED")
         If McLaunchJavaSelected.VersionCode >= 9 Then DataList.Add("--add-exports cpw.mods.bootstraplauncher/cpw.mods.bootstraplauncher=ALL-UNNAMED")
+        DataList.Insert(0, "-Doolloo.jlw.tmpdir=""" & GetJavaWrapperDir() & """")
         DataList.Add("-jar """ & ExtractJavaWrapper() & """")
         DataList.Add("-jar """ & ExtractJavaWrapper() & """")
 
 
         '将 "-XXX" 与后面 "XXX" 合并到一起
         '将 "-XXX" 与后面 "XXX" 合并到一起
@@ -1502,9 +1522,7 @@ NextVersion:
         GameArguments.Add("${assets_index_name}", McAssetsGetIndexName(Version))
         GameArguments.Add("${assets_index_name}", McAssetsGetIndexName(Version))
 
 
         '支持库参数
         '支持库参数
-        'Dim LibList As List(Of McLibToken) = McLibListGet(Version,
-        '    Not (Version.Version.HasForge AndAlso Version.Version.McCodeMain >= 17)) '包含版本 Jar 的条件是不为 1.17+ 的 Forge
-        Dim LibList As List(Of McLibToken) = McLibListGet(Version, True) '如果在 1.19.x Forge 不包含版本 Jar 会导致 #188
+        Dim LibList As List(Of McLibToken) = McLibListGet(Version, True)
         Loader.Output = LibList
         Loader.Output = LibList
         Dim CpStrings As New List(Of String)
         Dim CpStrings As New List(Of String)
         Dim OptiFineCp As String = Nothing
         Dim OptiFineCp As String = Nothing

+ 13 - 5
Plain Craft Launcher 2/Modules/Minecraft/ModMinecraft.vb

@@ -2327,13 +2327,16 @@ NextVersion:
             Dim RealVersion As McVersion
             Dim RealVersion As McVersion
             Dim RequiredJar As String = Version.JsonObject("jar")?.ToString
             Dim RequiredJar As String = Version.JsonObject("jar")?.ToString
             If Version.IsHmclFormatJson OrElse RequiredJar Is Nothing Then
             If Version.IsHmclFormatJson OrElse RequiredJar Is Nothing Then
+                'HMCL 项直接使用自身的 Jar
                 '根据 Inherit 获取最深层版本
                 '根据 Inherit 获取最深层版本
-                '此外,HMCL 项直接使用自身的 Jar
                 Dim OriginalVersion As McVersion = Version
                 Dim OriginalVersion As McVersion = Version
-                Do Until OriginalVersion.InheritVersion = ""
-                    If OriginalVersion.InheritVersion = OriginalVersion.Name Then Exit Do
-                    OriginalVersion = New McVersion(PathMcFolder & "versions\" & OriginalVersion.InheritVersion & "\")
-                Loop
+                '1.17+ 的 Forge 不寻找 Inherit
+                If Not (Version.Version.HasForge AndAlso Version.Version.McCodeMain >= 17) Then
+                    Do Until OriginalVersion.InheritVersion = ""
+                        If OriginalVersion.InheritVersion = OriginalVersion.Name Then Exit Do
+                        OriginalVersion = New McVersion(PathMcFolder & "versions\" & OriginalVersion.InheritVersion & "\")
+                    Loop
+                End If
                 '需要新建对象,否则后面的 Check 会导致 McVersionCurrent 的 State 变回 Original
                 '需要新建对象,否则后面的 Check 会导致 McVersionCurrent 的 State 变回 Original
                 '复现:启动一个 Snapshot 版本
                 '复现:启动一个 Snapshot 版本
                 RealVersion = New McVersion(OriginalVersion.Path)
                 RealVersion = New McVersion(OriginalVersion.Path)
@@ -2380,6 +2383,11 @@ NextVersion:
         '转换为 LibToken
         '转换为 LibToken
         For Each Library As JObject In AllLibs.Children
         For Each Library As JObject In AllLibs.Children
 
 
+            '清理 null 项(BakaXL 会把没有的项序列化为 null,但会被 Newtonsoft 转换为 JValue,导致 Is Nothing = false;这导致了 #409)
+            For i = Library.Properties.Count - 1 To 0 Step -1
+                If Library.Properties(i).Value.Type = JTokenType.Null Then Library.Remove(Library.Properties(i).Name)
+            Next
+
             '检查是否需要(Rules)
             '检查是否需要(Rules)
             If Not McJsonRuleCheck(Library("rules")) Then Continue For
             If Not McJsonRuleCheck(Library("rules")) Then Continue For
 
 

+ 5 - 1
Plain Craft Launcher 2/Modules/Minecraft/ModModpack.vb

@@ -241,8 +241,12 @@ Retry:
                 For Each ModJson In Task.Input
                 For Each ModJson In Task.Input
                     '跳过重复的 Mod(疑似 CurseForge Bug)
                     '跳过重复的 Mod(疑似 CurseForge Bug)
                     If FileList.ContainsKey(ModJson("id").ToObject(Of Integer)) Then Continue For
                     If FileList.ContainsKey(ModJson("id").ToObject(Of Integer)) Then Continue For
+                    '根据 modules 判断是资源包还是 Mod
+                    Dim ModuleNames = CType(ModJson("modules"), JArray).Select(Function(l) l("name").ToString).ToList
+                    Dim IsResourcePack As Boolean = Not ModuleNames.Contains("META-INF") AndAlso ModuleNames.Contains("pack.mcmeta")
                     '实际的添加
                     '实际的添加
-                    FileList.Add(ModJson("id"), New DlCfFile(ModJson, False).GetDownloadFile(PathMcFolder & "versions\" & VersionName & "\mods\", False))
+                    FileList.Add(ModJson("id"), New DlCfFile(ModJson, False).GetDownloadFile(
+                                 PathMcFolder & "versions\" & VersionName & "\" & If(IsResourcePack, "resourcepacks", "mods") & "\", False))
                     Task.Progress += 1 / (1 + ModFileList.Count)
                     Task.Progress += 1 / (1 + ModFileList.Count)
                 Next
                 Next
                 Task.Output = FileList.Values.ToList
                 Task.Output = FileList.Values.ToList

+ 2 - 2
Plain Craft Launcher 2/My Project/AssemblyInfo.vb

@@ -51,6 +51,6 @@ Imports System.Runtime.InteropServices
 ' 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号
 ' 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号
 ' 方法是按如下所示使用“*”
 ' 方法是按如下所示使用“*”
 
 
-<Assembly: AssemblyVersion("2.4.2.0")>
-<Assembly: AssemblyFileVersion("2.4.2.0")>
+<Assembly: AssemblyVersion("2.4.3.0")>
+<Assembly: AssemblyFileVersion("2.4.3.0")>
 <Assembly: NeutralResourcesLanguage("")>
 <Assembly: NeutralResourcesLanguage("")>

+ 52 - 44
Plain Craft Launcher 2/Pages/PageDownload/ModDownloadLib.vb

@@ -1,8 +1,15 @@
 Imports System.IO.Compression
 Imports System.IO.Compression
 
 
 Public Module ModDownloadLib
 Public Module ModDownloadLib
-    '如果 OptiFine 与 Forge 同时开始安装,就会导致 Forge 安装失败
+
+    ''' <summary>
+    ''' 如果 OptiFine 与 Forge 同时开始安装,就会导致 Forge 安装失败,所以在这里添加一个锁。
+    ''' </summary>
     Private InstallSyncLock As New Object
     Private InstallSyncLock As New Object
+    ''' <summary>
+    ''' 最高的 Minecraft 大版本号,-1 代表尚未获取。
+    ''' </summary>
+    Public McVersionHighest As Integer = -1
 
 
 #Region "Minecraft 下载"
 #Region "Minecraft 下载"
 
 
@@ -114,7 +121,7 @@ Public Module ModDownloadLib
                                                                 Task.Output = New List(Of NetFile) From {New NetFile(DlSourceLauncherOrMetaGet(JsonAddress), VersionFolder & VersionName & ".json")}
                                                                 Task.Output = New List(Of NetFile) From {New NetFile(DlSourceLauncherOrMetaGet(JsonAddress), VersionFolder & VersionName & ".json")}
                                                             End Sub) With {.ProgressWeight = 2, .Show = False})
                                                             End Sub) With {.ProgressWeight = 2, .Show = False})
         End If
         End If
-        Loaders.Add(New LoaderDownload("下载原版 Json 文件", New List(Of NetFile) From {
+        Loaders.Add(New LoaderDownload(McDownloadClientJsonName, New List(Of NetFile) From {
                 New NetFile(DlSourceLauncherOrMetaGet(If(JsonUrl, "")), VersionFolder & VersionName & ".json", New FileChecker(CanUseExistsFile:=False, IsJson:=True))
                 New NetFile(DlSourceLauncherOrMetaGet(If(JsonUrl, "")), VersionFolder & VersionName & ".json", New FileChecker(CanUseExistsFile:=False, IsJson:=True))
             }) With {.ProgressWeight = 3})
             }) With {.ProgressWeight = 3})
 
 
@@ -159,6 +166,7 @@ Public Module ModDownloadLib
 
 
     End Function
     End Function
     Private Const McDownloadClientLibName As String = "下载原版支持库文件"
     Private Const McDownloadClientLibName As String = "下载原版支持库文件"
+    Private Const McDownloadClientJsonName As String = "下载原版 Json 文件"
 
 
 #End Region
 #End Region
 
 
@@ -378,7 +386,7 @@ Public Module ModDownloadLib
             Throw New Exception("未找到用于安装 OptiFine 的 Java")
             Throw New Exception("未找到用于安装 OptiFine 的 Java")
         End If
         End If
         '添加 Java Wrapper 作为主 Jar
         '添加 Java Wrapper 作为主 Jar
-        Dim Arguments = "-Duser.home=""" & BaseMcFolderHome & """ -cp """ & Target & """ -jar """ & ExtractJavaWrapper() & """ optifine.Installer"
+        Dim Arguments = "-Doolloo.jlw.tmpdir=""" & GetJavaWrapperDir() & """ -Duser.home=""" & BaseMcFolderHome & """ -cp """ & Target & """ -jar """ & ExtractJavaWrapper() & """ optifine.Installer"
         If Java.VersionCode >= 9 Then Arguments = "--add-exports cpw.mods.bootstraplauncher/cpw.mods.bootstraplauncher=ALL-UNNAMED " & Arguments
         If Java.VersionCode >= 9 Then Arguments = "--add-exports cpw.mods.bootstraplauncher/cpw.mods.bootstraplauncher=ALL-UNNAMED " & Arguments
         '开始启动
         '开始启动
         SyncLock InstallSyncLock
         SyncLock InstallSyncLock
@@ -518,27 +526,28 @@ Public Module ModDownloadLib
         Loaders.Add(New LoaderDownload("下载 OptiFine 主文件", New List(Of NetFile)) With {.ProgressWeight = 8})
         Loaders.Add(New LoaderDownload("下载 OptiFine 主文件", New List(Of NetFile)) With {.ProgressWeight = 8})
         Loaders.Add(New LoaderTask(Of List(Of NetFile), Boolean)("等待原版下载",
         Loaders.Add(New LoaderTask(Of List(Of NetFile), Boolean)("等待原版下载",
                                                                          Sub(Task As LoaderTask(Of List(Of NetFile), Boolean))
                                                                          Sub(Task As LoaderTask(Of List(Of NetFile), Boolean))
-                                                                             '是否已经存在原版文件
-                                                                             If ClientDownloadLoader Is Nothing Then Exit Sub
                                                                              '等待原版文件下载完成
                                                                              '等待原版文件下载完成
-                                                                             For Each Loader In ClientDownloadLoader.GetLoaderList
-                                                                                 If Loader.Name <> McDownloadClientLibName Then Continue For
-                                                                                 If Loader.State = LoadState.Loading Then
-                                                                                     Log("[Download] OptiFine 安装正在等待原版文件下载完成")
-                                                                                     Loader.WaitForExit()
-                                                                                 End If
-                                                                                 Exit For
-                                                                             Next
+                                                                             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 IsCustomFolder Then
-                                                                                 Dim ClientName As String = New DirectoryInfo(ClientDownloadLoader.Input).Name
-                                                                                 Directory.CreateDirectory(McFolder & "versions\" & DownloadInfo.Inherit)
-                                                                                 If Not File.Exists(McFolder & "versions\" & DownloadInfo.Inherit & "\" & DownloadInfo.Inherit & ".json") Then
-                                                                                     CopyFile(ClientDownloadLoader.Input & ClientName & ".json", McFolder & "versions\" & DownloadInfo.Inherit & "\" & DownloadInfo.Inherit & ".json")
-                                                                                 End If
-                                                                                 If Not File.Exists(McFolder & "versions\" & DownloadInfo.Inherit & "\" & DownloadInfo.Inherit & ".jar") Then
-                                                                                     CopyFile(ClientDownloadLoader.Input & ClientName & ".jar", McFolder & "versions\" & DownloadInfo.Inherit & "\" & DownloadInfo.Inherit & ".jar")
-                                                                                 End If
+                                                                             If Not IsCustomFolder Then Exit Sub
+                                                                             Dim ClientName As String = New DirectoryInfo(ClientDownloadLoader.Input).Name
+                                                                             Directory.CreateDirectory(McFolder & "versions\" & DownloadInfo.Inherit)
+                                                                             If Not File.Exists(McFolder & "versions\" & DownloadInfo.Inherit & "\" & DownloadInfo.Inherit & ".json") Then
+                                                                                 CopyFile(ClientDownloadLoader.Input & ClientName & ".json",
+                                                                                          McFolder & "versions\" & DownloadInfo.Inherit & "\" & DownloadInfo.Inherit & ".json")
+                                                                             End If
+                                                                             If Not File.Exists(McFolder & "versions\" & DownloadInfo.Inherit & "\" & DownloadInfo.Inherit & ".jar") Then
+                                                                                 CopyFile(ClientDownloadLoader.Input & ClientName & ".jar",
+                                                                                          McFolder & "versions\" & DownloadInfo.Inherit & "\" & DownloadInfo.Inherit & ".jar")
                                                                              End If
                                                                              End If
                                                                          End Sub) With {.ProgressWeight = 0.1, .Show = False})
                                                                          End Sub) With {.ProgressWeight = 0.1, .Show = False})
 
 
@@ -876,8 +885,8 @@ Public Module ModDownloadLib
                                                                     '构造版本 Json
                                                                     '构造版本 Json
                                                                     Dim VersionJson As New JObject
                                                                     Dim VersionJson As New JObject
                                                                     VersionJson.Add("id", VersionName)
                                                                     VersionJson.Add("id", VersionName)
-                                                                    VersionJson.Add("time", DateTime.ParseExact(DownloadInfo.ReleaseTime, "yyyy/MM/dd HH:mm:ss", Globalization.CultureInfo.CurrentCulture))
-                                                                    VersionJson.Add("releaseTime", DateTime.ParseExact(DownloadInfo.ReleaseTime, "yyyy/MM/dd HH:mm:ss", Globalization.CultureInfo.CurrentCulture))
+                                                                    VersionJson.Add("time", Date.ParseExact(DownloadInfo.ReleaseTime, "yyyy/MM/dd HH:mm", Globalization.CultureInfo.CurrentCulture))
+                                                                    VersionJson.Add("releaseTime", Date.ParseExact(DownloadInfo.ReleaseTime, "yyyy/MM/dd HH:mm", Globalization.CultureInfo.CurrentCulture))
                                                                     VersionJson.Add("type", "release")
                                                                     VersionJson.Add("type", "release")
                                                                     VersionJson.Add("arguments", GetJson("{""game"":[""--tweakClass"",""" & DownloadInfo.JsonToken("tweakClass").ToString & """]}"))
                                                                     VersionJson.Add("arguments", GetJson("{""game"":[""--tweakClass"",""" & DownloadInfo.JsonToken("tweakClass").ToString & """]}"))
                                                                     VersionJson.Add("libraries", DownloadInfo.JsonToken("libraries"))
                                                                     VersionJson.Add("libraries", DownloadInfo.JsonToken("libraries"))
@@ -1094,7 +1103,7 @@ Public Module ModDownloadLib
             Throw New Exception("未找到用于安装 Forge 的 Java")
             Throw New Exception("未找到用于安装 Forge 的 Java")
         End If
         End If
         '添加 Java Wrapper 作为主 Jar
         '添加 Java Wrapper 作为主 Jar
-        Dim Arguments = "-cp """ & PathTemp & "Cache\forge_installer.jar;" & Target & """ -jar """ & ExtractJavaWrapper() & """  com.bangbang93.ForgeInstaller """ & McFolder
+        Dim Arguments = "-Doolloo.jlw.tmpdir=""" & GetJavaWrapperDir() & """ -cp """ & PathTemp & "Cache\forge_installer.jar;" & Target & """ -jar """ & ExtractJavaWrapper() & """  com.bangbang93.ForgeInstaller """ & McFolder
         If Java.VersionCode >= 9 Then Arguments = "--add-exports cpw.mods.bootstraplauncher/cpw.mods.bootstraplauncher=ALL-UNNAMED " & Arguments
         If Java.VersionCode >= 9 Then Arguments = "--add-exports cpw.mods.bootstraplauncher/cpw.mods.bootstraplauncher=ALL-UNNAMED " & Arguments
         '开始启动
         '开始启动
         SyncLock InstallSyncLock
         SyncLock InstallSyncLock
@@ -1329,27 +1338,26 @@ Public Module ModDownloadLib
                                                                              End If
                                                                              End If
 #End Region
 #End Region
 #Region "原版文件"
 #Region "原版文件"
-                                                                             '是否已经存在原版文件
-                                                                             If ClientDownloadLoader Is Nothing Then Exit Sub
                                                                              '等待原版文件下载完成
                                                                              '等待原版文件下载完成
-                                                                             For Each Loader In ClientDownloadLoader.GetLoaderList
-                                                                                 If Loader.Name <> McDownloadClientLibName Then Continue For
-                                                                                 If Loader.State = LoadState.Loading Then
-                                                                                     Log("[Download] Forge 安装正在等待原版文件下载完成")
-                                                                                     Loader.WaitForExit()
-                                                                                 End If
-                                                                                 Exit For
-                                                                             Next
+                                                                             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] Forge 安装正在等待原版文件下载完成")
+                                                                             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 IsCustomFolder Then
-                                                                                 Dim ClientName As String = New DirectoryInfo(ClientDownloadLoader.Input).Name
-                                                                                 Directory.CreateDirectory(McFolder & "versions\" & Inherit)
-                                                                                 If Not File.Exists(McFolder & "versions\" & Inherit & "\" & Inherit & ".json") Then
-                                                                                     CopyFile(ClientDownloadLoader.Input & ClientName & ".json", McFolder & "versions\" & Inherit & "\" & Inherit & ".json")
-                                                                                 End If
-                                                                                 If Not File.Exists(McFolder & "versions\" & Inherit & "\" & Inherit & ".jar") Then
-                                                                                     CopyFile(ClientDownloadLoader.Input & ClientName & ".jar", McFolder & "versions\" & Inherit & "\" & Inherit & ".jar")
-                                                                                 End If
+                                                                             If Not IsCustomFolder Then Exit Sub
+                                                                             Dim ClientName As String = New DirectoryInfo(ClientDownloadLoader.Input).Name
+                                                                             Directory.CreateDirectory(McFolder & "versions\" & Inherit)
+                                                                             If Not File.Exists(McFolder & "versions\" & Inherit & "\" & Inherit & ".json") Then
+                                                                                 CopyFile(ClientDownloadLoader.Input & ClientName & ".json", McFolder & "versions\" & Inherit & "\" & Inherit & ".json")
+                                                                             End If
+                                                                             If Not File.Exists(McFolder & "versions\" & Inherit & "\" & Inherit & ".jar") Then
+                                                                                 CopyFile(ClientDownloadLoader.Input & ClientName & ".jar", McFolder & "versions\" & Inherit & "\" & Inherit & ".jar")
                                                                              End If
                                                                              End If
 #End Region
 #End Region
                                                                          End Sub) With {.ProgressWeight = 0.1, .Show = False})
                                                                          End Sub) With {.ProgressWeight = 0.1, .Show = False})

+ 113 - 52
Plain Craft Launcher 2/Pages/PageDownload/PageDownloadCfDetail.xaml.vb

@@ -192,63 +192,124 @@
         End Try
         End Try
     End Sub
     End Sub
     'Mod 下载;整合包另存为
     'Mod 下载;整合包另存为
-    Public Shared DownloadFolder = Nothing '仅在本次缓存的下载文件夹
+    Public Shared CachedFolder As String = Nothing '仅在本次缓存的下载文件夹
     Public Sub Save_Click(sender As Object, e As EventArgs)
     Public Sub Save_Click(sender As Object, e As EventArgs)
-        Try
-            Dim Desc As String = If(Project.IsModPack, "整合包", "Mod ")
-
-            '确认默认保存位置
-            Dim DefaultFolder As String = Nothing
-            If Not Project.IsModPack Then
-                DefaultFolder = DownloadFolder
-                If McVersionCurrent IsNot Nothing Then
-                    If Not McVersionCurrent.IsLoaded Then McVersionCurrent.Load()
-                    If McVersionCurrent.Modable Then
+        Dim File As DlCfFile = If(TypeOf sender Is MyListItem, sender, sender.Parent).Tag
+        RunInNewThread(
+        Sub()
+            Try
+                Dim Desc As String = If(Project.IsModPack, "整合包", "Mod ")
+                '确认默认保存位置
+                Dim DefaultFolder As String = Nothing
+                If Not Project.IsModPack Then
+                    '获取 Mod 所需的加载器种类
+                    Dim AllowForge As Boolean? = Nothing, AllowFabric As Boolean? = Nothing 'FUTURE: Quilt 支持
+                    If File.ModLoaders.Count > 0 Then '从文件中获取
+                        AllowForge = False : AllowFabric = False
+                        For Each LoaderType In File.ModLoaders
+                            If LoaderType = "Forge" Then AllowForge = True
+                            If LoaderType = "Fabric" Then AllowFabric = True
+                        Next
+                    ElseIf Project.ModLoaders.Count > 0 Then '从工程中获取
+                        AllowForge = False : AllowFabric = False
+                        For Each LoaderType In Project.ModLoaders
+                            If LoaderType = "Forge" Then AllowForge = True
+                            If LoaderType = "Fabric" Then AllowFabric = True
+                        Next
+                    End If
+                    If AllowForge IsNot Nothing AndAlso Not AllowForge AndAlso
+                       AllowFabric IsNot Nothing AndAlso Not AllowFabric Then
+                        AllowForge = Nothing : AllowFabric = Nothing
+                    End If
+                    Log("[Download] 允许 Forge:" & If(AllowForge, "未知") & ",允许 Fabric:" & If(AllowFabric, "未知"))
+                    '判断某个版本是否符合要求
+                    Dim IsVersionSuitable As Func(Of McVersion, Boolean) =
+                            Function(Version)
+                                If Not Version.IsLoaded Then Version.Load()
+                                If Not Version.Modable Then Return False
+                                If File.GameVersion.Any(Function(v) v.Contains(".")) AndAlso
+                                   Not File.GameVersion.Any(Function(v) v.Contains(".") AndAlso v.Split(".")(1) = Version.Version.McCodeMain) Then Return False
+                                If AllowForge Is Nothing OrElse AllowFabric Is Nothing Then Return True
+                                If AllowForge AndAlso Version.Version.HasForge Then Return True
+                                If AllowFabric AndAlso Version.Version.HasFabric Then Return True
+                                Return False
+                            End Function
+                    '获取 Mod 默认下载位置
+                    If CachedFolder IsNot Nothing Then
+                        DefaultFolder = CachedFolder
+                        Log("[Download] 使用上次下载时的文件夹作为默认下载位置")
+                    ElseIf McVersionCurrent IsNot Nothing AndAlso IsVersionSuitable(McVersionCurrent) Then
                         DefaultFolder = McVersionCurrent.PathIndie & "mods\"
                         DefaultFolder = McVersionCurrent.PathIndie & "mods\"
                         Directory.CreateDirectory(DefaultFolder)
                         Directory.CreateDirectory(DefaultFolder)
+                        Log("[Download] 使用当前版本的 mods 文件夹作为默认下载位置(" & McVersionCurrent.Name & ")")
+                    Else
+                        Dim NeedLoad As Boolean = McVersionListLoader.State <> LoadState.Finished
+                        If NeedLoad Then
+                            Hint("正在查找适合的游戏版本……")
+                            LoaderFolderRun(McVersionListLoader, PathMcFolder, LoaderFolderRunType.ForceRun, MaxDepth:=1, ExtraPath:="versions\", WaitForExit:=True)
+                        End If
+                        Dim SuitableVersions As New List(Of McVersion)
+                        For Each Version As McVersion In McVersionList.Values.SelectMany(Function(l) l)
+                            If IsVersionSuitable(Version) Then SuitableVersions.Add(Version)
+                        Next
+                        If SuitableVersions.Count = 0 Then
+                            DefaultFolder = PathMcFolder
+                            If NeedLoad Then
+                                Hint("当前 MC 文件夹中未找到适合这个 Mod 的游戏版本")
+                            Else
+                                Log("[Download] 由于当前版本不兼容,使用当前的 MC 文件夹作为默认下载位置")
+                            End If
+                        Else '选择 Mod 数量最多的版本
+                            Dim SelectedVersion = SuitableVersions.OrderBy(Function(v)
+                                                                               Dim Info As New DirectoryInfo(v.PathIndie & "mods\")
+                                                                               Return If(Info.Exists, Info.GetFiles().Length, -1)
+                                                                           End Function).LastOrDefault()
+                            DefaultFolder = SelectedVersion.PathIndie & "mods\"
+                            Directory.CreateDirectory(DefaultFolder)
+                            Log("[Download] 使用适合的游戏版本作为默认下载位置(" & SelectedVersion.Name & ")")
+                        End If
                     End If
                     End If
                 End If
                 End If
-                If String.IsNullOrEmpty(DefaultFolder) Then DefaultFolder = Nothing
-            End If
-
-            '获取基本信息
-            Dim File As DlCfFile = If(TypeOf sender Is MyListItem, sender, sender.Parent).Tag
-            Dim ChineseName As String = If(Project.ChineseName = Project.Name, "",
-                Project.ChineseName.Replace(" (", "Å").Split("Å").First.Replace("\", "\").Replace("/", "/").Replace("|", "|").Replace(":", ":").Replace("<", "<").Replace(">", ">").Replace("*", "*").Replace("?", "?").Replace("""", "").Replace(": ", ":"))
-            Dim FileName As String
-            Select Case Setup.Get("ToolDownloadTranslate")
-                Case 0
-                    FileName = If(ChineseName = "", "", "[" & ChineseName & "] ") & File.FileName
-                Case 1
-                    FileName = If(ChineseName = "", "", ChineseName & "-") & File.FileName
-                Case 2
-                    FileName = File.FileName & If(ChineseName = "", "", "-" & ChineseName)
-                Case Else
-                    FileName = File.FileName
-            End Select
-            Dim Target As String
-            If File.FileName.EndsWith(".litemod") Then
-                Target = SelectAs("选择保存位置", FileName, Desc & "文件|" & If(Project.IsModPack, "*.zip", "*.litemod"), DefaultFolder)
-            Else
-                Target = SelectAs("选择保存位置", FileName, Desc & "文件|" & If(Project.IsModPack, "*.zip", "*.jar"), DefaultFolder)
-            End If
-            If Not Target.Contains("\") Then Exit Sub
-            Dim LoaderName As String = Desc & "下载:" & File.DisplayName & " "
-            If Target <> DefaultFolder AndAlso Not Project.IsModPack Then DownloadFolder = GetPathFromFullPath(Target)
-
-            '构造步骤加载器
-            Dim Loaders As New List(Of LoaderBase)
-            Loaders.Add(New LoaderDownload("下载文件", New List(Of NetFile) From {File.GetDownloadFile(Target, True)}) With {.ProgressWeight = 6, .Block = True})
-
-            '启动
-            Dim Loader As New LoaderCombo(Of Integer)(LoaderName, Loaders) With {.OnStateChanged = AddressOf DownloadStateSave}
-            Loader.Start(1)
-            LoaderTaskbarAdd(Loader)
-            FrmMain.BtnExtraDownload.ShowRefresh()
-            FrmMain.BtnExtraDownload.Ribble()
-        Catch ex As Exception
-            Log(ex, "保存 CurseForge 文件失败", LogLevel.Feedback)
-        End Try
+                '获取基本信息
+                Dim ChineseName As String = If(Project.ChineseName = Project.Name, "",
+                        Project.ChineseName.Replace(" (", "Å").Split("Å").First.Replace("\", "\").Replace("/", "/").Replace("|", "|").Replace(":", ":").Replace("<", "<").Replace(">", ">").Replace("*", "*").Replace("?", "?").Replace("""", "").Replace(": ", ":"))
+                Dim FileName As String
+                Select Case Setup.Get("ToolDownloadTranslate")
+                    Case 0
+                        FileName = If(ChineseName = "", "", "[" & ChineseName & "] ") & File.FileName
+                    Case 1
+                        FileName = If(ChineseName = "", "", ChineseName & "-") & File.FileName
+                    Case 2
+                        FileName = File.FileName & If(ChineseName = "", "", "-" & ChineseName)
+                    Case Else
+                        FileName = File.FileName
+                End Select
+                RunInUi(
+                Sub()
+                    '弹窗要求选择保存位置
+                    Dim Target As String
+                    If File.FileName.EndsWith(".litemod") Then
+                        Target = SelectAs("选择保存位置", FileName, Desc & "文件|" & If(Project.IsModPack, "*.zip", "*.litemod"), DefaultFolder)
+                    Else
+                        Target = SelectAs("选择保存位置", FileName, Desc & "文件|" & If(Project.IsModPack, "*.zip", "*.jar"), DefaultFolder)
+                    End If
+                    If Not Target.Contains("\") Then Exit Sub
+                    '构造步骤加载器
+                    Dim LoaderName As String = Desc & "下载:" & File.DisplayName & " "
+                    If Target <> DefaultFolder AndAlso Not Project.IsModPack Then CachedFolder = GetPathFromFullPath(Target)
+                    Dim Loaders As New List(Of LoaderBase)
+                    Loaders.Add(New LoaderDownload("下载文件", New List(Of NetFile) From {File.GetDownloadFile(Target, True)}) With {.ProgressWeight = 6, .Block = True})
+                    '启动
+                    Dim Loader As New LoaderCombo(Of Integer)(LoaderName, Loaders) With {.OnStateChanged = AddressOf DownloadStateSave}
+                    Loader.Start(1)
+                    LoaderTaskbarAdd(Loader)
+                    FrmMain.BtnExtraDownload.ShowRefresh()
+                    FrmMain.BtnExtraDownload.Ribble()
+                End Sub)
+            Catch ex As Exception
+                Log(ex, "保存 CurseForge 文件失败", LogLevel.Feedback)
+            End Try
+        End Sub, "Download CFDetail Save")
     End Sub
     End Sub
 
 
     Private Sub BtnIntroCf_Click(sender As Object, e As EventArgs) Handles BtnIntroCf.Click
     Private Sub BtnIntroCf_Click(sender As Object, e As EventArgs) Handles BtnIntroCf.Click

+ 3 - 13
Plain Craft Launcher 2/Pages/PageDownload/PageDownloadMod.xaml

@@ -51,28 +51,17 @@
                         <TextBlock VerticalAlignment="Center" Grid.Row="2" Grid.Column="3" HorizontalAlignment="Left" Text="版本" Margin="0,0,25,0" />
                         <TextBlock VerticalAlignment="Center" Grid.Row="2" Grid.Column="3" HorizontalAlignment="Left" Text="版本" Margin="0,0,25,0" />
                         <local:MyComboBox x:Name="TextSearchVersion" Grid.Row="2" Grid.Column="4" Grid.ColumnSpan="2" IsEditable="True" MaxDropDownHeight="320" HintText="全部 (也可自行输入)">
                         <local:MyComboBox x:Name="TextSearchVersion" Grid.Row="2" Grid.Column="4" Grid.ColumnSpan="2" IsEditable="True" MaxDropDownHeight="320" HintText="全部 (也可自行输入)">
                             <local:MyComboBoxItem Content="" IsSelected="True" />
                             <local:MyComboBoxItem Content="" IsSelected="True" />
+                            <local:MyComboBoxItem Content="1.19.3" />
                             <local:MyComboBoxItem Content="1.19.2" />
                             <local:MyComboBoxItem Content="1.19.2" />
                             <local:MyComboBoxItem Content="1.19.1" />
                             <local:MyComboBoxItem Content="1.19.1" />
                             <local:MyComboBoxItem Content="1.19" />
                             <local:MyComboBoxItem Content="1.19" />
                             <local:MyComboBoxItem Content="1.18.2" />
                             <local:MyComboBoxItem Content="1.18.2" />
-                            <local:MyComboBoxItem Content="1.18.1" />
-                            <local:MyComboBoxItem Content="1.18" />
                             <local:MyComboBoxItem Content="1.17.1" />
                             <local:MyComboBoxItem Content="1.17.1" />
-                            <local:MyComboBoxItem Content="1.17" />
                             <local:MyComboBoxItem Content="1.16.5" />
                             <local:MyComboBoxItem Content="1.16.5" />
-                            <local:MyComboBoxItem Content="1.16.4" />
-                            <local:MyComboBoxItem Content="1.16.3" />
-                            <local:MyComboBoxItem Content="1.16.2" />
-                            <local:MyComboBoxItem Content="1.16.1" />
-                            <local:MyComboBoxItem Content="1.16" />
                             <local:MyComboBoxItem Content="1.15.2" />
                             <local:MyComboBoxItem Content="1.15.2" />
-                            <local:MyComboBoxItem Content="1.15" />
                             <local:MyComboBoxItem Content="1.14.4" />
                             <local:MyComboBoxItem Content="1.14.4" />
-                            <local:MyComboBoxItem Content="1.14" />
                             <local:MyComboBoxItem Content="1.13.2" />
                             <local:MyComboBoxItem Content="1.13.2" />
-                            <local:MyComboBoxItem Content="1.13" />
                             <local:MyComboBoxItem Content="1.12.2" />
                             <local:MyComboBoxItem Content="1.12.2" />
-                            <local:MyComboBoxItem Content="1.12" />
                             <local:MyComboBoxItem Content="1.11.2" />
                             <local:MyComboBoxItem Content="1.11.2" />
                             <local:MyComboBoxItem Content="1.10.2" />
                             <local:MyComboBoxItem Content="1.10.2" />
                             <local:MyComboBoxItem Content="1.9.4" />
                             <local:MyComboBoxItem Content="1.9.4" />
@@ -83,9 +72,10 @@
                             <local:MyComboBoxItem Content="1.5.2" />
                             <local:MyComboBoxItem Content="1.5.2" />
                         </local:MyComboBox>
                         </local:MyComboBox>
                         <local:MyComboBox x:Name="ComboSearchLoader" Visibility="Collapsed" Grid.Row="2" Grid.Column="5" MaxDropDownHeight="320" Margin="10,0,0,0">
                         <local:MyComboBox x:Name="ComboSearchLoader" Visibility="Collapsed" Grid.Row="2" Grid.Column="5" MaxDropDownHeight="320" Margin="10,0,0,0">
-                            <local:MyComboBoxItem Content="Forge 或 Fabric" IsSelected="True" Tag="0" />
+                            <local:MyComboBoxItem Content="任意 Mod 加载器" IsSelected="True" Tag="0" />
                             <local:MyComboBoxItem Content="Forge" Tag="1" />
                             <local:MyComboBoxItem Content="Forge" Tag="1" />
                             <local:MyComboBoxItem Content="Fabric" Tag="4" />
                             <local:MyComboBoxItem Content="Fabric" Tag="4" />
+                            <local:MyComboBoxItem Content="Quilt" Tag="5" />
                         </local:MyComboBox>
                         </local:MyComboBox>
                     </Grid>
                     </Grid>
                     <Grid Margin="0,4,0,6" Height="35">
                     <Grid Margin="0,4,0,6" Height="35">

+ 1 - 0
Plain Craft Launcher 2/Pages/PageDownload/PageDownloadMod.xaml.vb

@@ -3,6 +3,7 @@
     '初始化加载器信息
     '初始化加载器信息
     Private Sub PageDownloadMod_Inited(sender As Object, e As EventArgs) Handles Me.Initialized
     Private Sub PageDownloadMod_Inited(sender As Object, e As EventArgs) Handles Me.Initialized
         PageLoaderInit(Load, PanLoad, CardProjects, PanAlways, Loader, AddressOf Load_OnFinish, AddressOf LoaderInput)
         PageLoaderInit(Load, PanLoad, CardProjects, PanAlways, Loader, AddressOf Load_OnFinish, AddressOf LoaderInput)
+        McVersionHighest = Math.Max(McVersionHighest, Integer.Parse(CType(TextSearchVersion.Items(1), MyComboBoxItem).Content.ToString.Split(".")(1)))
     End Sub
     End Sub
     Public Shared Loader As New LoaderTask(Of DlCfProjectRequest, DlCfProjectResult)("DlCfProject Mod", AddressOf DlCfProjectSub, AddressOf LoaderInput) With {.ReloadTimeout = 60 * 1000}
     Public Shared Loader As New LoaderTask(Of DlCfProjectRequest, DlCfProjectResult)("DlCfProject Mod", AddressOf DlCfProjectSub, AddressOf LoaderInput) With {.ReloadTimeout = 60 * 1000}
     Private Shared Function LoaderInput() As DlCfProjectRequest
     Private Shared Function LoaderInput() As DlCfProjectRequest

+ 1 - 22
Plain Craft Launcher 2/Pages/PageDownload/PageDownloadPack.xaml

@@ -47,42 +47,21 @@
                         <TextBlock VerticalAlignment="Center" Grid.Row="2" Grid.Column="3" HorizontalAlignment="Left" Text="版本" Margin="0,0,25,0" />
                         <TextBlock VerticalAlignment="Center" Grid.Row="2" Grid.Column="3" HorizontalAlignment="Left" Text="版本" Margin="0,0,25,0" />
                         <local:MyComboBox x:Name="TextSearchVersion" Grid.Row="2" Grid.Column="4" IsEditable="True" MaxDropDownHeight="320" HintText="全部 (也可自行输入)">
                         <local:MyComboBox x:Name="TextSearchVersion" Grid.Row="2" Grid.Column="4" IsEditable="True" MaxDropDownHeight="320" HintText="全部 (也可自行输入)">
                             <local:MyComboBoxItem Content="" IsSelected="True" />
                             <local:MyComboBoxItem Content="" IsSelected="True" />
+                            <local:MyComboBoxItem Content="1.19.3" />
                             <local:MyComboBoxItem Content="1.19.2" />
                             <local:MyComboBoxItem Content="1.19.2" />
                             <local:MyComboBoxItem Content="1.19.1" />
                             <local:MyComboBoxItem Content="1.19.1" />
                             <local:MyComboBoxItem Content="1.19" />
                             <local:MyComboBoxItem Content="1.19" />
                             <local:MyComboBoxItem Content="1.18.2" />
                             <local:MyComboBoxItem Content="1.18.2" />
-                            <local:MyComboBoxItem Content="1.18.1" />
-                            <local:MyComboBoxItem Content="1.18" />
                             <local:MyComboBoxItem Content="1.17.1" />
                             <local:MyComboBoxItem Content="1.17.1" />
-                            <local:MyComboBoxItem Content="1.17" />
                             <local:MyComboBoxItem Content="1.16.5" />
                             <local:MyComboBoxItem Content="1.16.5" />
-                            <local:MyComboBoxItem Content="1.16.4" />
-                            <local:MyComboBoxItem Content="1.16.3" />
-                            <local:MyComboBoxItem Content="1.16.2" />
-                            <local:MyComboBoxItem Content="1.16.1" />
-                            <local:MyComboBoxItem Content="1.16" />
                             <local:MyComboBoxItem Content="1.15.2" />
                             <local:MyComboBoxItem Content="1.15.2" />
-                            <local:MyComboBoxItem Content="1.15.1" />
-                            <local:MyComboBoxItem Content="1.15" />
                             <local:MyComboBoxItem Content="1.14.4" />
                             <local:MyComboBoxItem Content="1.14.4" />
-                            <local:MyComboBoxItem Content="1.14.3" />
-                            <local:MyComboBoxItem Content="1.14.2" />
-                            <local:MyComboBoxItem Content="1.14.1" />
-                            <local:MyComboBoxItem Content="1.14" />
                             <local:MyComboBoxItem Content="1.13.2" />
                             <local:MyComboBoxItem Content="1.13.2" />
-                            <local:MyComboBoxItem Content="1.13.1" />
-                            <local:MyComboBoxItem Content="1.13" />
                             <local:MyComboBoxItem Content="1.12.2" />
                             <local:MyComboBoxItem Content="1.12.2" />
-                            <local:MyComboBoxItem Content="1.12.1" />
-                            <local:MyComboBoxItem Content="1.12" />
                             <local:MyComboBoxItem Content="1.11.2" />
                             <local:MyComboBoxItem Content="1.11.2" />
-                            <local:MyComboBoxItem Content="1.11" />
                             <local:MyComboBoxItem Content="1.10.2" />
                             <local:MyComboBoxItem Content="1.10.2" />
-                            <local:MyComboBoxItem Content="1.10" />
                             <local:MyComboBoxItem Content="1.9.4" />
                             <local:MyComboBoxItem Content="1.9.4" />
-                            <local:MyComboBoxItem Content="1.9" />
                             <local:MyComboBoxItem Content="1.8.9" />
                             <local:MyComboBoxItem Content="1.8.9" />
-                            <local:MyComboBoxItem Content="1.8" />
                             <local:MyComboBoxItem Content="1.7.10" />
                             <local:MyComboBoxItem Content="1.7.10" />
                             <local:MyComboBoxItem Content="1.7.2" />
                             <local:MyComboBoxItem Content="1.7.2" />
                             <local:MyComboBoxItem Content="1.6.4" />
                             <local:MyComboBoxItem Content="1.6.4" />

+ 1 - 0
Plain Craft Launcher 2/Pages/PageDownload/PageDownloadPack.xaml.vb

@@ -3,6 +3,7 @@
     '初始化加载器信息
     '初始化加载器信息
     Private Sub PageDownloadMod_Inited(sender As Object, e As EventArgs) Handles Me.Initialized
     Private Sub PageDownloadMod_Inited(sender As Object, e As EventArgs) Handles Me.Initialized
         PageLoaderInit(Load, PanLoad, CardProjects, PanAlways, Loader, AddressOf Load_OnFinish, AddressOf LoaderInput)
         PageLoaderInit(Load, PanLoad, CardProjects, PanAlways, Loader, AddressOf Load_OnFinish, AddressOf LoaderInput)
+        McVersionHighest = Math.Max(McVersionHighest, Integer.Parse(CType(TextSearchVersion.Items(1), MyComboBoxItem).Content.ToString.Split(".")(1)))
     End Sub
     End Sub
     Public Shared Loader As New LoaderTask(Of DlCfProjectRequest, DlCfProjectResult)("DlCfProject ModPack", AddressOf DlCfProjectSub, AddressOf LoaderInput) With {.ReloadTimeout = 60 * 1000}
     Public Shared Loader As New LoaderTask(Of DlCfProjectRequest, DlCfProjectResult)("DlCfProject ModPack", AddressOf DlCfProjectSub, AddressOf LoaderInput) With {.ReloadTimeout = 60 * 1000}
     Private Shared Function LoaderInput() As DlCfProjectRequest
     Private Shared Function LoaderInput() As DlCfProjectRequest

+ 15 - 11
Plain Craft Launcher 2/Pages/PageLaunch/MySkin.xaml.vb

@@ -83,12 +83,21 @@
             '加载
             '加载
             Dim Image As New MyBitmap(Address)
             Dim Image As New MyBitmap(Address)
             ImgBack.Tag = Address
             ImgBack.Tag = Address
+            '大小检查
+            Dim Scale As Integer = Image.Pic.Width / 64
+            If Image.Pic.Width < 32 OrElse Image.Pic.Height < 32 Then
+                ImgFore.Source = Nothing : ImgBack.Source = Nothing
+                Throw New Exception("图片大小不足,长为 " & Image.Pic.Height & ",宽为 " & Image.Pic.Width)
+            End If
             '头发层(附加层)
             '头发层(附加层)
             If Image.Pic.Width >= 64 AndAlso Image.Pic.Height >= 32 Then
             If Image.Pic.Width >= 64 AndAlso Image.Pic.Height >= 32 Then
-                '如果图片中有透明像素,或是头部颜色和透明区均不一样,则加载附加层
-                If (Image.Pic.GetPixel(1, 1).A = 0 OrElse Image.Pic.GetPixel(Image.Pic.Width - 1, Image.Pic.Height - 1).A = 0 OrElse Image.Pic.GetPixel(Image.Pic.Width - 2, 2).A = 0) OrElse
-                   (Image.Pic.GetPixel(1, 1) <> Image.Pic.GetPixel(41, 9) AndAlso Image.Pic.GetPixel(Image.Pic.Width - 1, Image.Pic.Height - 1) <> Image.Pic.GetPixel(41, 9) AndAlso Image.Pic.GetPixel(Image.Pic.Width - 2, 2) <> Image.Pic.GetPixel(41, 9)) Then
-                    ImgFore.Source = New CroppedBitmap(Image, New Int32Rect(40, 8, 8, 8))
+                If (Image.Pic.GetPixel(1, 1).A = 0 OrElse '如果图片中有任何透明像素(避免纯色白底)
+                    Image.Pic.GetPixel(Image.Pic.Width - 1, Image.Pic.Height - 1).A = 0 OrElse
+                    Image.Pic.GetPixel(Image.Pic.Width - 2, Image.Pic.Height / 2 - 2).A = 0) OrElse
+                   (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))
                 Else
                 Else
                     ImgFore.Source = Nothing
                     ImgFore.Source = Nothing
                 End If
                 End If
@@ -96,13 +105,8 @@
                 ImgFore.Source = Nothing
                 ImgFore.Source = Nothing
             End If
             End If
             '脸层
             '脸层
-            If Image.Pic.Width >= 32 AndAlso Image.Pic.Height >= 32 Then
-                ImgBack.Source = New CroppedBitmap(Image, New Int32Rect(8, 8, 8, 8))
-                Log("[Skin] 载入头像成功:" & Loader.Name)
-            Else
-                ImgBack.Source = Nothing
-                Throw New Exception("图片大小不足,长为 " & Image.Pic.Height & ",宽为 " & Image.Pic.Width)
-            End If
+            ImgBack.Source = New CroppedBitmap(Image, New Int32Rect(Scale * 8, Scale * 8, Scale * 8, Scale * 8))
+            Log("[Skin] 载入头像成功:" & Loader.Name)
         Catch ex As Exception
         Catch ex As Exception
             Log(ex, "载入头像失败(" & If(Address, "null") & "," & Loader.Name & ")", LogLevel.Hint)
             Log(ex, "载入头像失败(" & If(Address, "null") & "," & Loader.Name & ")", LogLevel.Hint)
         End Try
         End Try

+ 0 - 1
Plain Craft Launcher 2/Pages/PageOther/PageOtherLeft.xaml

@@ -18,7 +18,6 @@
         <local:MyListItem x:Name="ItemFeedback" IsScaleAnimationEnabled="False" Type="Clickable" Tag="3" PaddingRight="35" Height="36" VerticalAlignment="Top" Title="反馈"
         <local:MyListItem x:Name="ItemFeedback" IsScaleAnimationEnabled="False" Type="Clickable" Tag="3" PaddingRight="35" Height="36" VerticalAlignment="Top" Title="反馈"
                           LogoScale="0.9" Logo="M613.717333 64.426667l3.413334 3.242666 331.861333 331.861334a85.333333 85.333333 0 0 1 3.2 117.269333l-3.2 3.413333L573.162667 896H960a21.333333 21.333333 0 0 1 21.333333 21.333333v42.666667a21.333333 21.333333 0 0 1-21.333333 21.333333H64a21.333333 21.333333 0 0 1-21.333333-21.333333v-42.666667a21.333333 21.333333 0 0 1 21.333333-21.333333h295.338667L74.069333 610.709333a85.333333 85.333333 0 0 1-3.221333-117.269333l3.2-3.413333 422.4-422.357334a85.333333 85.333333 0 0 1 117.269333-3.221333z m-20.629333 99.882666l-21.418667 321.493334a85.333333 85.333333 0 0 1-74.944 79.04l-4.522666 0.426666-321.493334 21.44 295.552 295.530667 422.4-422.378667L593.066667 164.309333z m-86.442667 13.824L184.533333 500.266667l301.994667-20.117334 20.117333-301.994666z" />
                           LogoScale="0.9" Logo="M613.717333 64.426667l3.413334 3.242666 331.861333 331.861334a85.333333 85.333333 0 0 1 3.2 117.269333l-3.2 3.413333L573.162667 896H960a21.333333 21.333333 0 0 1 21.333333 21.333333v42.666667a21.333333 21.333333 0 0 1-21.333333 21.333333H64a21.333333 21.333333 0 0 1-21.333333-21.333333v-42.666667a21.333333 21.333333 0 0 1 21.333333-21.333333h295.338667L74.069333 610.709333a85.333333 85.333333 0 0 1-3.221333-117.269333l3.2-3.413333 422.4-422.357334a85.333333 85.333333 0 0 1 117.269333-3.221333z m-20.629333 99.882666l-21.418667 321.493334a85.333333 85.333333 0 0 1-74.944 79.04l-4.522666 0.426666-321.493334 21.44 295.552 295.530667 422.4-422.378667L593.066667 164.309333z m-86.442667 13.824L184.533333 500.266667l301.994667-20.117334 20.117333-301.994666z" />
         <local:MyListItem x:Name="ItemVote" IsScaleAnimationEnabled="False" Type="Clickable" Tag="4" PaddingRight="35" Height="36" VerticalAlignment="Top" Title="新功能投票"
         <local:MyListItem x:Name="ItemVote" IsScaleAnimationEnabled="False" Type="Clickable" Tag="4" PaddingRight="35" Height="36" VerticalAlignment="Top" Title="新功能投票"
-                          EventType="打开网页" EventData="https://github.com/Hex-Dragon/PCL2/discussions/categories/%E5%8A%9F%E8%83%BD%E6%8A%95%E7%A5%A8"
                           LogoScale="0.92" Logo="M979 1024H45c-24.9 0-45-20.1-45-45s20.1-45 45-45h934c24.9 0 45 20.1 45 45s-20.1 45-45 45zM135 887C60.6 887 0 826.4 0 752V334c0-74.4 60.6-135 135-135s135 60.6 135 135v418c0 74.4-60.6 135-135 135z m0-598c-24.8 0-45 20.2-45 45v418c0 24.8 20.2 45 45 45s45-20.2 45-45V334c0-24.8-20.2-45-45-45zM512 887c-74.4 0-135-60.6-135-135V532c0-74.4 60.6-135 135-135s135 60.6 135 135v220c0 74.4-60.6 135-135 135z m0-400c-24.8 0-45 20.2-45 45v220c0 24.8 20.2 45 45 45s45-20.2 45-45V532c0-24.8-20.2-45-45-45zM889 887c-74.4 0-135-60.6-135-135V135C754 60.6 814.6 0 889 0s135 60.6 135 135v617c0 74.4-60.6 135-135 135z m0-797c-24.8 0-45 20.2-45 45v617c0 24.8 20.2 45 45 45s45-20.2 45-45V135c0-24.8-20.2-45-45-45z" />
                           LogoScale="0.92" Logo="M979 1024H45c-24.9 0-45-20.1-45-45s20.1-45 45-45h934c24.9 0 45 20.1 45 45s-20.1 45-45 45zM135 887C60.6 887 0 826.4 0 752V334c0-74.4 60.6-135 135-135s135 60.6 135 135v418c0 74.4-60.6 135-135 135z m0-598c-24.8 0-45 20.2-45 45v418c0 24.8 20.2 45 45 45s45-20.2 45-45V334c0-24.8-20.2-45-45-45zM512 887c-74.4 0-135-60.6-135-135V532c0-74.4 60.6-135 135-135s135 60.6 135 135v220c0 74.4-60.6 135-135 135z m0-400c-24.8 0-45 20.2-45 45v220c0 24.8 20.2 45 45 45s45-20.2 45-45V532c0-24.8-20.2-45-45-45zM889 887c-74.4 0-135-60.6-135-135V135C754 60.6 814.6 0 889 0s135 60.6 135 135v617c0 74.4-60.6 135-135 135z m0-797c-24.8 0-45 20.2-45 45v617c0 24.8 20.2 45 45 45s45-20.2 45-45V135c0-24.8-20.2-45-45-45z" />
     </StackPanel>
     </StackPanel>
 </local:MyPageLeft>
 </local:MyPageLeft>

+ 10 - 2
Plain Craft Launcher 2/Pages/PageOther/PageOtherLeft.xaml.vb

@@ -122,9 +122,17 @@
         FrmOtherHelp.SearchBox.Text = ""
         FrmOtherHelp.SearchBox.Text = ""
     End Sub
     End Sub
 
 
-    '打开反馈
+    '打开网页
     Public Shared Sub TryFeedback() Handles ItemFeedback.Click
     Public Shared Sub TryFeedback() Handles ItemFeedback.Click
-        If CanFeedback(True) Then Feedback(True, False)
+        If Not CanFeedback(True) Then Exit Sub
+        If MyMsgBox("是否要打开反馈列表网页?" & vbCrLf & "如果无法打开该网页,请尝试使用加速器或 VPN。",
+                    "提醒", "打开", "取消") = 2 Then Exit Sub
+        Feedback(True, False)
+    End Sub
+    Public Shared Sub TryVote() Handles ItemVote.Click
+        If MyMsgBox("是否要打开新功能投票网页?" & vbCrLf & "如果无法打开该网页,请尝试使用加速器或 VPN。",
+                    "提醒", "打开", "取消") = 2 Then Exit Sub
+        OpenWebsite("https://github.com/Hex-Dragon/PCL2/discussions/categories/%E5%8A%9F%E8%83%BD%E6%8A%95%E7%A5%A8?discussions_q=category%3A%E5%8A%9F%E8%83%BD%E6%8A%95%E7%A5%A8+sort%3Adate_created")
     End Sub
     End Sub
 
 
 End Class
 End Class

+ 9 - 0
Plain Craft Launcher 2/Plain Craft Launcher 2.vbproj

@@ -899,5 +899,14 @@
   <ItemGroup>
   <ItemGroup>
     <Resource Include="Resources\ModData.txt" />
     <Resource Include="Resources\ModData.txt" />
   </ItemGroup>
   </ItemGroup>
+  <ItemGroup>
+    <Resource Include="Images\Skins\Ari.png" />
+    <Resource Include="Images\Skins\Efe.png" />
+    <Resource Include="Images\Skins\Kai.png" />
+    <Resource Include="Images\Skins\Makena.png" />
+    <Resource Include="Images\Skins\Noor.png" />
+    <Resource Include="Images\Skins\Sunny.png" />
+    <Resource Include="Images\Skins\Zuri.png" />
+  </ItemGroup>
   <Import Project="$(MSBuildToolsPath)\Microsoft.VisualBasic.targets" />
   <Import Project="$(MSBuildToolsPath)\Microsoft.VisualBasic.targets" />
 </Project>
 </Project>

BIN
Plain Craft Launcher 2/Resources/Help.zip


BIN
Plain Craft Launcher 2/Resources/java-wrapper.jar