龙腾猫跃 3 anni fa
parent
commit
f4448eddf4
28 ha cambiato i file con 1166 aggiunte e 1092 eliminazioni
  1. 2 0
      Plain Craft Launcher 2/Controls/MyCard.vb
  2. 5 0
      Plain Craft Launcher 2/Controls/MyExtraButton.xaml
  3. 18 0
      Plain Craft Launcher 2/Controls/MyExtraButton.xaml.vb
  4. 7 104
      Plain Craft Launcher 2/FormMain.xaml.vb
  5. 7 3
      Plain Craft Launcher 2/Modules/Base/ModBase.vb
  6. 1 0
      Plain Craft Launcher 2/Modules/Base/ModLoader.vb
  7. 38 12
      Plain Craft Launcher 2/Modules/Minecraft/ModComp.vb
  8. 4 0
      Plain Craft Launcher 2/Modules/Minecraft/ModCrash.vb
  9. 747 0
      Plain Craft Launcher 2/Modules/Minecraft/ModJava.vb
  10. 48 29
      Plain Craft Launcher 2/Modules/Minecraft/ModLaunch.vb
  11. 19 713
      Plain Craft Launcher 2/Modules/Minecraft/ModMinecraft.vb
  12. 12 2
      Plain Craft Launcher 2/Modules/Minecraft/ModWatcher.vb
  13. 6 6
      Plain Craft Launcher 2/Modules/Minecraft/MyCompItem.xaml
  14. 4 1
      Plain Craft Launcher 2/Modules/ModMusic.vb
  15. 2 2
      Plain Craft Launcher 2/My Project/AssemblyInfo.vb
  16. 22 4
      Plain Craft Launcher 2/Pages/PageDownload/ModDownloadLib.vb
  17. 1 1
      Plain Craft Launcher 2/Pages/PageDownload/PageDownloadClient.xaml.vb
  18. 1 3
      Plain Craft Launcher 2/Pages/PageDownload/PageDownloadInstall.xaml
  19. 5 5
      Plain Craft Launcher 2/Pages/PageDownload/PageDownloadInstall.xaml.vb
  20. 40 34
      Plain Craft Launcher 2/Pages/PageDownload/PageDownloadMod.xaml
  21. 2 1
      Plain Craft Launcher 2/Pages/PageDownload/PageDownloadMod.xaml.vb
  22. 34 28
      Plain Craft Launcher 2/Pages/PageDownload/PageDownloadPack.xaml
  23. 3 2
      Plain Craft Launcher 2/Pages/PageDownload/PageDownloadPack.xaml.vb
  24. 6 10
      Plain Craft Launcher 2/Pages/PageSetup/PageSetupLaunch.xaml.vb
  25. 2 2
      Plain Craft Launcher 2/Pages/PageVersion/PageVersionSetup.xaml.vb
  26. 1 0
      Plain Craft Launcher 2/Plain Craft Launcher 2.vbproj
  27. 0 1
      Plain Craft Launcher 2/Resources/Custom.xaml
  28. 129 129
      Plain Craft Launcher 2/Resources/ModData.txt

+ 2 - 0
Plain Craft Launcher 2/Controls/MyCard.vb

@@ -155,6 +155,8 @@
                     Stack.Children.Add(LiteLoaderDownloadListItem(Data, AddressOf LiteLoaderSave_Click, True))
                     Stack.Children.Add(LiteLoaderDownloadListItem(Data, AddressOf LiteLoaderSave_Click, True))
                 Case 11
                 Case 11
                     Stack.Children.Add(CType(Data, HelpEntry).ToListItem)
                     Stack.Children.Add(CType(Data, HelpEntry).ToListItem)
+                Case 12
+                    Stack.Children.Add(FabricDownloadListItem(CType(Data, JObject), AddressOf FrmDownloadInstall.Fabric_Selected))
                 Case Else
                 Case Else
                     Log("未知的虚拟化种类:" & Type, LogLevel.Feedback)
                     Log("未知的虚拟化种类:" & Type, LogLevel.Feedback)
             End Select
             End Select

+ 5 - 0
Plain Craft Launcher 2/Controls/MyExtraButton.xaml

@@ -16,6 +16,11 @@
                 <DropShadowEffect ShadowDepth="0" BlurRadius="10" Opacity="0.2" />
                 <DropShadowEffect ShadowDepth="0" BlurRadius="10" Opacity="0.2" />
             </Border.Effect>
             </Border.Effect>
         </Border>
         </Border>
+        <Border x:Name="PanProgress" CornerRadius="1000" BorderThickness="0.001" Background="#2AFFFFFF" ClipToBounds="True" Visibility="Collapsed">
+            <Border.Clip>
+                <RectangleGeometry x:Name="RectProgress" Rect="0,0,40,25" />
+            </Border.Clip>
+        </Border>
         <Path x:Name="Path" Stretch="Uniform" Margin="12" Fill="{DynamicResource ColorBrush8}" RenderTransformOrigin="0.5,0.5">
         <Path x:Name="Path" Stretch="Uniform" Margin="12" Fill="{DynamicResource ColorBrush8}" RenderTransformOrigin="0.5,0.5">
             <Path.RenderTransform>
             <Path.RenderTransform>
                 <ScaleTransform />
                 <ScaleTransform />

+ 18 - 0
Plain Craft Launcher 2/Controls/MyExtraButton.xaml.vb

@@ -4,6 +4,24 @@
     Public Event Click(sender As Object, e As MouseButtonEventArgs) '自定义事件
     Public Event Click(sender As Object, e As MouseButtonEventArgs) '自定义事件
     Public Event RightClick(sender As Object, e As MouseButtonEventArgs)
     Public Event RightClick(sender As Object, e As MouseButtonEventArgs)
 
 
+    '进度条
+    Private _Progress As Double = 0
+    Public Property Progress As Double
+        Get
+            Return _Progress
+        End Get
+        Set(value As Double)
+            If _Progress = value Then Exit Property
+            _Progress = value
+            If value < 0.0001 Then
+                PanProgress.Visibility = Visibility.Collapsed
+            Else
+                PanProgress.Visibility = Visibility.Visible
+                RectProgress.Rect = New Rect(0, 0, 40, 40 * (1 - value))
+            End If
+        End Set
+    End Property
+
     '自定义属性
     '自定义属性
     Public Uuid As Integer = GetUuid()
     Public Uuid As Integer = GetUuid()
     Private _Logo As String = ""
     Private _Logo As String = ""

+ 7 - 104
Plain Craft Launcher 2/FormMain.xaml.vb

@@ -89,52 +89,19 @@ Public Class FormMain
             FeatureCount += 8
             FeatureCount += 8
             BugCount += 33
             BugCount += 33
         End If
         End If
-        If LastVersion < 246 Then 'Release 2.2.9
-            FeatureList.Add(New KeyValuePair(Of Integer, String)(4, "Mod 下载支持筛选 Forge Mod 与 Fabric Mod"))
-            FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "Mod、整合包下载的综合优化"))
-            FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "修复使用离线登录进入 Forge 的存档可能导致游戏崩溃"))
-            FeatureCount += 13
-            BugCount += 11
-        End If
-        If LastVersion < 242 Then 'Release 2.2.7
-            FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "修复 MC 所包含的一个严重安全漏洞"))
-            If LastVersion >= 236 Then FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "修复可能无法更改登录信息的 Bug"))
-        End If
-        If LastVersion < 238 Then 'Release 2.2.6
-            If LastVersion = 236 Then FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "修复无法使用联机模块的 Bug"))
-            FeatureCount += 1
-            BugCount += 2
-        End If
-        If LastVersion < 236 Then 'Release 2.2.5
-            FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "网络状态检测支持检测 Windows 防火墙与网络延迟"))
-            FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "重制右侧页面的切换动画,卡片与提示条将逐个进入退出,并具有独特的位移动画"))
-            FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "添加 MC 1.18 中要求 Java 17 的检测与提醒"))
-            FeatureList.Add(New KeyValuePair(Of Integer, String)(1, "优化页面切换、下载的性能"))
-            FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "允许拖拽按钮设置第三方登录"))
-            FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "修复无法下载新版本的 Forge 的 Bug"))
-            FeatureCount += 25
-            BugCount += 22
-        End If
-        If LastVersion < 233 Then 'Release 2.2.3
-            FeatureList.Add(New KeyValuePair(Of Integer, String)(4, "微软账号支持更换皮肤与披风"))
-            FeatureList.Add(New KeyValuePair(Of Integer, String)(4, "支持拖拽整合包文件到 PCL 进行快捷安装"))
-            FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "Mod 下载支持显示对应的 MC 版本与 Mod 加载器,且可以跳转到 MCBBS 介绍页"))
-            FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "支持安装 1.17 OptiFine + Forge"))
-            FeatureList.Add(New KeyValuePair(Of Integer, String)(1, "使用 Mojang 账号登录将会显示迁移提醒"))
-            FeatureCount += 12
-            BugCount += 26
-        End If
-        If LastVersion < 231 Then 'Release 2.2.1, Also 229
-            FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "添加 1.18 实验性快照 5 的特供下载,且支持列表的联网更新"))
-            FeatureCount += 11
-            BugCount += 3
-        End If
 #Else
 #Else
         '5:          FEAT+
         '5:          FEAT+
         '4:     IMP+ FEAT*
         '4:     IMP+ FEAT*
         '3:BUG+ IMP* FEAT-
         '3:BUG+ IMP* FEAT-
         '2:BUG* IMP-
         '2:BUG* IMP-
         '1:BUG-
         '1:BUG-
+        If LastVersion < 287 Then 'Snapshot 2.5.3
+            FeatureList.Add(New KeyValuePair(Of Integer, String)(4, "在缺少 Java 时会自动下载所需的 Java"))
+            FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "添加 CurseForge / Modrinth 来源筛选"))
+            FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "为下载管理和音乐播放按钮添加进度条"))
+            FeatureCount += 8
+            BugCount += 8
+        End If
         If LastVersion < 285 Then 'Snapshot 2.5.2
         If LastVersion < 285 Then 'Snapshot 2.5.2
             FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "重做资源下载的资源项界面"))
             FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "重做资源下载的资源项界面"))
             If LastVersion = 284 Then FeatureList.Add(New KeyValuePair(Of Integer, String)(1, "修复打开部分帮助报错的 Bug"))
             If LastVersion = 284 Then FeatureList.Add(New KeyValuePair(Of Integer, String)(1, "修复打开部分帮助报错的 Bug"))
@@ -260,70 +227,6 @@ Public Class FormMain
             FeatureCount += 2
             FeatureCount += 2
             BugCount += 16
             BugCount += 16
         End If
         End If
-        If LastVersion < 249 Then 'Snapshot 2.2.10
-            If LastVersion = 247 Then FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "修复无法使用中文搜索 Mod 的 Bug"))
-            FeatureCount += 6
-            BugCount += 17
-        End If
-        If LastVersion < 247 Then 'Snapshot 2.2.9
-            FeatureList.Add(New KeyValuePair(Of Integer, String)(4, "Mod 下载支持筛选 Forge Mod 与 Fabric Mod"))
-            FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "Mod、整合包下载的综合优化"))
-            FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "修复使用离线登录进入 Forge 的存档可能导致游戏崩溃"))
-            FeatureCount += 8
-            BugCount += 4
-        End If
-        If LastVersion < 245 Then 'Snapshot 2.2.8
-            FeatureCount += 5
-            BugCount += 7
-        End If
-        If LastVersion < 243 Then 'Snapshot 2.2.7
-            FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "修复 MC 所包含的一个严重安全漏洞"))
-            If LastVersion >= 236 Then FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "修复可能无法更改登录信息的 Bug"))
-        End If
-        If LastVersion < 239 Then 'Snapshot 2.2.6
-            If LastVersion >= 235 Then FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "修复自动更新由于路径错误失败的 Bug"))
-            If LastVersion = 237 Then FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "修复无法使用联机模块的 Bug"))
-            FeatureCount += 1
-            BugCount += 1
-        End If
-        If LastVersion < 237 Then 'Snapshot 2.2.5
-            FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "允许拖拽按钮设置第三方登录"))
-            If LastVersion = 235 Then FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "修复在启动游戏时有可能卡死的 Bug"))
-            FeatureCount += 2
-            BugCount += 3
-        End If
-        If LastVersion < 235 Then 'Snapshot 2.2.4
-            FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "网络状态检测支持检测 Windows 防火墙与网络延迟"))
-            FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "重制右侧页面的切换动画,卡片与提示条将逐个进入退出,并具有独特的位移动画"))
-            FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "添加 MC 1.18 中要求 Java 17 的检测与提醒"))
-            FeatureList.Add(New KeyValuePair(Of Integer, String)(1, "优化页面切换、下载的性能"))
-            FeatureCount += 23
-            BugCount += 19
-        End If
-        If LastVersion < 234 Then 'Snapshot 2.2.3
-            FeatureList.Add(New KeyValuePair(Of Integer, String)(4, "支持拖拽整合包文件到 PCL 进行快捷安装"))
-            FeatureList.Add(New KeyValuePair(Of Integer, String)(4, "支持安装 1.17 OptiFine + Forge"))
-            FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "Mod 详情页面支持跳转 MCBBS 介绍页"))
-            FeatureCount += 10
-            BugCount += 17
-        End If
-        If LastVersion < 232 Then 'Snapshot 2.2.2
-            FeatureList.Add(New KeyValuePair(Of Integer, String)(4, "微软账号支持更换皮肤与披风"))
-            FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "支持显示 Mod 与整合包对应的 MC 版本与 Mod 加载器名称"))
-            FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "使用 Mojang 账号登录将会显示迁移提醒"))
-            FeatureCount += 2
-            BugCount += 9
-        End If
-        If LastVersion < 230 Then 'Snapshot 2.2.1, Also 228
-            FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "添加 1.18 实验性快照 5 的特供下载,且支持列表的联网更新"))
-            FeatureList.Add(New KeyValuePair(Of Integer, String)(1, "修复 Win7 上 IOI 联机导致日志文件极大,占用硬盘空间的 Bug"))
-            FeatureCount += 12
-            BugCount += 4
-        End If
-        If LastVersion < 227 Then 'Snapshot 2.2.0
-            FeatureCount += 2
-            BugCount += 2
-        End If
 #End If
 #End If
         '整理更新日志文本
         '整理更新日志文本
         Dim ContentList As New List(Of String)
         Dim ContentList As New List(Of String)

+ 7 - 3
Plain Craft Launcher 2/Modules/Base/ModBase.vb

@@ -11,10 +11,10 @@ Public Module ModBase
 #Region "声明"
 #Region "声明"
 
 
     '下列版本信息由更新器自动修改
     '下列版本信息由更新器自动修改
-    Public Const VersionBaseName As String = "2.5.2" '不含分支前缀的显示用版本名
-    Public Const VersionStandardCode As String = "2.5.2." & VersionBranchCode '标准格式的四段式版本号
+    Public Const VersionBaseName As String = "2.5.3" '不含分支前缀的显示用版本名
+    Public Const VersionStandardCode As String = "2.5.3." & VersionBranchCode '标准格式的四段式版本号
 #If BETA Then
 #If BETA Then
-    Public Const VersionCode As Integer = 286 'Release
+    Public Const VersionCode As Integer = 287 'Release
 #Else
 #Else
     Public Const VersionCode As Integer = 285 'Snapshot
     Public Const VersionCode As Integer = 285 'Snapshot
 #End If
 #End If
@@ -1360,6 +1360,8 @@ Re:
             CommonReason = "PCL 的权限不足。请尝试右键 PCL,选择以管理员身份运行。"
             CommonReason = "PCL 的权限不足。请尝试右键 PCL,选择以管理员身份运行。"
         ElseIf TypeOf InnerEx Is OutOfMemoryException Then
         ElseIf TypeOf InnerEx Is OutOfMemoryException Then
             CommonReason = "你的电脑运行内存不足,导致 PCL 无法继续运行。请在关闭一部分不需要的程序后再试。"
             CommonReason = "你的电脑运行内存不足,导致 PCL 无法继续运行。请在关闭一部分不需要的程序后再试。"
+        ElseIf TypeOf InnerEx Is Runtime.InteropServices.COMException Then
+            CommonReason = "由于操作系统或显卡存在问题,导致出现错误。请尝试重启 PCL。"
         ElseIf {"远程主机强迫关闭了", "远程方已关闭传输流", "未能解析此远程名称", "由于目标计算机积极拒绝",
         ElseIf {"远程主机强迫关闭了", "远程方已关闭传输流", "未能解析此远程名称", "由于目标计算机积极拒绝",
                 "操作已超时", "操作超时", "服务器超时", "连接超时"}.Any(Function(s) Desc.Contains(s)) Then
                 "操作已超时", "操作超时", "服务器超时", "连接超时"}.Any(Function(s) Desc.Contains(s)) Then
             CommonReason = "你的网络环境不佳,导致难以连接到服务器。请检查网络,多重试几次,或尝试使用 VPN。"
             CommonReason = "你的网络环境不佳,导致难以连接到服务器。请检查网络,多重试几次,或尝试使用 VPN。"
@@ -1406,6 +1408,8 @@ Re:
             CommonReason = "PCL 的权限不足。请尝试右键 PCL,选择以管理员身份运行。"
             CommonReason = "PCL 的权限不足。请尝试右键 PCL,选择以管理员身份运行。"
         ElseIf TypeOf InnerEx Is OutOfMemoryException Then
         ElseIf TypeOf InnerEx Is OutOfMemoryException Then
             CommonReason = "你的电脑运行内存不足,导致 PCL 无法继续运行。请在关闭一部分不需要的程序后再试。"
             CommonReason = "你的电脑运行内存不足,导致 PCL 无法继续运行。请在关闭一部分不需要的程序后再试。"
+        ElseIf TypeOf InnerEx Is Runtime.InteropServices.COMException Then
+            CommonReason = "由于操作系统或显卡存在问题,导致出现错误。请尝试重启 PCL。"
         ElseIf {"远程主机强迫关闭了", "远程方已关闭传输流", "未能解析此远程名称", "由于目标计算机积极拒绝",
         ElseIf {"远程主机强迫关闭了", "远程方已关闭传输流", "未能解析此远程名称", "由于目标计算机积极拒绝",
                 "操作已超时", "操作超时", "服务器超时", "连接超时"}.Any(Function(s) Desc.Contains(s)) Then
                 "操作已超时", "操作超时", "服务器超时", "连接超时"}.Any(Function(s) Desc.Contains(s)) Then
             CommonReason = "你的网络环境不佳,导致难以连接到服务器。请检查网络,多重试几次,或尝试使用 VPN。"
             CommonReason = "你的网络环境不佳,导致难以连接到服务器。请检查网络,多重试几次,或尝试使用 VPN。"

+ 1 - 0
Plain Craft Launcher 2/Modules/Base/ModLoader.vb

@@ -602,6 +602,7 @@ Restart:
             Else
             Else
                 LoaderTaskbarProgress = LoaderTaskbarProgress * 0.9 + NewProgress * 0.1
                 LoaderTaskbarProgress = LoaderTaskbarProgress * 0.9 + NewProgress * 0.1
             End If
             End If
+            RunInUi(Sub() FrmMain.BtnExtraDownload.Progress = LoaderTaskbarProgress)
             '更新任务栏信息
             '更新任务栏信息
             If LoaderTaskbar.Count = 0 OrElse LoaderTaskbarProgress = 1 Then
             If LoaderTaskbar.Count = 0 OrElse LoaderTaskbarProgress = 1 Then
                 NewState = Shell.TaskbarItemProgressState.None
                 NewState = Shell.TaskbarItemProgressState.None

+ 38 - 12
Plain Craft Launcher 2/Modules/Minecraft/ModComp.vb

@@ -21,6 +21,11 @@
         Fabric = 4
         Fabric = 4
         Quilt = 5
         Quilt = 5
     End Enum
     End Enum
+    <Flags> Public Enum CompSourceType
+        CurseForge = 1
+        Modrinth = 2
+        Any = CurseForge Or Modrinth
+    End Enum
 
 
 #Region "CompDatabase | Mod 数据库"
 #Region "CompDatabase | Mod 数据库"
 
 
@@ -383,7 +388,7 @@
             '获取版本描述
             '获取版本描述
             Dim GameVersionDescription As String
             Dim GameVersionDescription As String
             If GameVersions Is Nothing OrElse GameVersions.Count = 0 Then
             If GameVersions Is Nothing OrElse GameVersions.Count = 0 Then
-                GameVersionDescription = ""
+                GameVersionDescription = "未知"
             Else
             Else
                 Dim SpaVersions As New List(Of String)
                 Dim SpaVersions As New List(Of String)
                 For i = 0 To GameVersions.Count - 1
                 For i = 0 To GameVersions.Count - 1
@@ -414,20 +419,24 @@
             '实例化 UI
             '实例化 UI
             Dim NewItem As New MyCompItem With {.Tag = Me}
             Dim NewItem As New MyCompItem With {.Tag = Me}
             '标题
             '标题
-            Dim FinalName As String = TranslatedName.Split(" | ").First.Split(" - ").First.Split(" (").First.Split(" [").First
+            Dim FinalName As String = TranslatedName.Split(" | ").First.Split(" - ").First.Split("(").First.Split("[").First
+            Dim ExNameList As List(Of String) = TranslatedName.Split({" | ", " - ", "(", ")", "[", "]", "{", "}"}, StringSplitOptions.RemoveEmptyEntries).
+                Select(Function(s) s.Trim(" /".ToCharArray)).Where(Function(w) Not String.IsNullOrEmpty(w)).ToList
+            ExNameList.RemoveAt(0)
+            If TranslatedName = RawName AndAlso '没有中文翻译
+               Not ExNameList.Any(Function(s) s.Contains("orge") OrElse s.Contains("abric") OrElse s.Contains("uilt")) AndAlso '不是标注 XX 版
+               Not (ExNameList.Count = 1 AndAlso ExNameList.First.ToUpper <> ExNameList.First) Then '不是缩写
+                FinalName = RawName '使用原名
+                ExNameList.Clear()
+            End If
             NewItem.LabTitle.Text = FinalName
             NewItem.LabTitle.Text = FinalName
-            Dim ExNameList As New List(Of String)
-            If TranslatedName.Contains(" (") Then ExNameList.Add(TranslatedName.Split(" (").Last.Split(")").First)
-            If TranslatedName.Contains(" [") Then ExNameList.Add(TranslatedName.Split(" [").Last.Split("]").First)
-            If TranslatedName.Contains(" - ") Then ExNameList.Add(TranslatedName.Split(" - ").Last.Split(" | ").First.Split(" (").First.Split(" [").First)
-            If TranslatedName.Contains(" | ") Then ExNameList.Add(TranslatedName.Split(" | ").Last.Split(" - ").First.Split(" (").First.Split(" [").First)
             If ExNameList.Count = 0 Then
             If ExNameList.Count = 0 Then
 NoExName:
 NoExName:
                 CType(NewItem.LabTitleRaw.Parent, StackPanel).Children.Remove(NewItem.LabTitleRaw)
                 CType(NewItem.LabTitleRaw.Parent, StackPanel).Children.Remove(NewItem.LabTitleRaw)
             Else
             Else
                 Dim ExName As String = ""
                 Dim ExName As String = ""
                 For Each Ex In ExNameList
                 For Each Ex In ExNameList
-                    '去除 “Forge/Fabric” 一类的无意义提示
+                    '去除 “Forge/Fabric” 这一无意义提示
                     If Ex.Length < 19 AndAlso Ex.ToLower.Contains("fabric") AndAlso Ex.ToLower.Contains("forge") Then Continue For
                     If Ex.Length < 19 AndAlso Ex.ToLower.Contains("fabric") AndAlso Ex.ToLower.Contains("forge") Then Continue For
                     '将 “Forge” 等提示改为 “Forge 版”
                     '将 “Forge” 等提示改为 “Forge 版”
                     If (Ex.ToLower.Contains("forge") OrElse Ex.ToLower.Contains("fabric") OrElse Ex.ToLower.Contains("quilt")) AndAlso
                     If (Ex.ToLower.Contains("forge") OrElse Ex.ToLower.Contains("fabric") OrElse Ex.ToLower.Contains("quilt")) AndAlso
@@ -452,7 +461,9 @@ NoExName:
                 '全部隐藏
                 '全部隐藏
                 CType(NewItem.PathVersion.Parent, Grid).Children.Remove(NewItem.PathVersion)
                 CType(NewItem.PathVersion.Parent, Grid).Children.Remove(NewItem.PathVersion)
                 CType(NewItem.LabVersion.Parent, Grid).Children.Remove(NewItem.LabVersion)
                 CType(NewItem.LabVersion.Parent, Grid).Children.Remove(NewItem.LabVersion)
-                NewItem.ColumnVersionMargin.Width = New GridLength(0)
+                NewItem.ColumnVersion1.Width = New GridLength(0)
+                NewItem.ColumnVersion2.MaxWidth = 0
+                NewItem.ColumnVersion3.Width = New GridLength(0)
             ElseIf ShowMcVersionDesc AndAlso ShowMcVersionDesc Then
             ElseIf ShowMcVersionDesc AndAlso ShowMcVersionDesc Then
                 '全部显示
                 '全部显示
                 Dim ModLoaderDesc As String = If(ModLoaders.Count > 0 AndAlso ModLoaders.Count < 3 AndAlso
                 Dim ModLoaderDesc As String = If(ModLoaders.Count > 0 AndAlso ModLoaders.Count < 3 AndAlso
@@ -491,6 +502,11 @@ NoExName:
             NewItem.LabSource.Text = If(FromCurseForge, "CurseForge", "Modrinth")
             NewItem.LabSource.Text = If(FromCurseForge, "CurseForge", "Modrinth")
             If LastUpdate IsNot Nothing Then
             If LastUpdate IsNot Nothing Then
                 NewItem.LabTime.Text = GetTimeSpanString(LastUpdate - Date.Now, True)
                 NewItem.LabTime.Text = GetTimeSpanString(LastUpdate - Date.Now, True)
+            Else
+                NewItem.LabTime.Visibility = Visibility.Collapsed
+                NewItem.ColumnTime1.Width = New GridLength(0)
+                NewItem.ColumnTime2.Width = New GridLength(0)
+                NewItem.ColumnTime3.Width = New GridLength(0)
             End If
             End If
             NewItem.LabDownload.Text =
             NewItem.LabDownload.Text =
                 If(DownloadCount > 100000000, Math.Round(DownloadCount / 100000000, 2) & " 亿",
                 If(DownloadCount > 100000000, Math.Round(DownloadCount / 100000000, 2) & " 亿",
@@ -610,6 +626,10 @@ NoExName:
         ''' </summary>
         ''' </summary>
         Public SearchText As String = Nothing
         Public SearchText As String = Nothing
         ''' <summary>
         ''' <summary>
+        ''' 允许的来源。
+        ''' </summary>
+        Public Source As CompSourceType = CompSourceType.Any
+        ''' <summary>
         ''' 构造函数。
         ''' 构造函数。
         ''' </summary>
         ''' </summary>
         Public Sub New(Type As CompType, Storage As CompProjectStorage, TargetResultCount As Integer)
         Public Sub New(Type As CompType, Storage As CompProjectStorage, TargetResultCount As Integer)
@@ -624,6 +644,7 @@ NoExName:
         ''' 获取对应的 CurseForge API 请求链接。若返回 Nothing 则为不进行 CurseForge 请求。
         ''' 获取对应的 CurseForge API 请求链接。若返回 Nothing 则为不进行 CurseForge 请求。
         ''' </summary>
         ''' </summary>
         Public Function GetCurseForgeAddress() As String
         Public Function GetCurseForgeAddress() As String
+            If Not Source.HasFlag(CompSourceType.CurseForge) Then Return Nothing
             If Tag.StartsWith("/") Then Storage.CurseForgeTotal = 0
             If Tag.StartsWith("/") Then Storage.CurseForgeTotal = 0
             If Storage.CurseForgeTotal > -1 AndAlso Storage.CurseForgeTotal <= Storage.CurseForgeOffset Then Return Nothing
             If Storage.CurseForgeTotal > -1 AndAlso Storage.CurseForgeTotal <= Storage.CurseForgeOffset Then Return Nothing
             '应用筛选参数
             '应用筛选参数
@@ -647,6 +668,7 @@ NoExName:
         ''' 获取对应的 Modrinth API 请求链接。若返回 Nothing 则为不进行 Modrinth 请求。
         ''' 获取对应的 Modrinth API 请求链接。若返回 Nothing 则为不进行 Modrinth 请求。
         ''' </summary>
         ''' </summary>
         Public Function GetModrinthAddress() As String
         Public Function GetModrinthAddress() As String
+            If Not Source.HasFlag(CompSourceType.Modrinth) Then Return Nothing
             If Tag.EndsWith("/") Then Storage.ModrinthTotal = 0
             If Tag.EndsWith("/") Then Storage.ModrinthTotal = 0
             If Storage.ModrinthTotal > -1 AndAlso Storage.ModrinthTotal <= Storage.ModrinthOffset Then Return Nothing
             If Storage.ModrinthTotal > -1 AndAlso Storage.ModrinthTotal <= Storage.ModrinthOffset Then Return Nothing
             '应用筛选参数
             '应用筛选参数
@@ -668,7 +690,7 @@ NoExName:
             Dim request = TryCast(obj, CompProjectRequest)
             Dim request = TryCast(obj, CompProjectRequest)
             Return request IsNot Nothing AndAlso
             Return request IsNot Nothing AndAlso
                 Type = request.Type AndAlso TargetResultCount = request.TargetResultCount AndAlso
                 Type = request.Type AndAlso TargetResultCount = request.TargetResultCount AndAlso
-                Tag = request.Tag AndAlso ModLoader = request.ModLoader AndAlso
+                Tag = request.Tag AndAlso ModLoader = request.ModLoader AndAlso Source = request.Source AndAlso
                 GameVersion = request.GameVersion AndAlso SearchText = request.SearchText
                 GameVersion = request.GameVersion AndAlso SearchText = request.SearchText
         End Function
         End Function
         Public Shared Operator =(left As CompProjectRequest, right As CompProjectRequest) As Boolean
         Public Shared Operator =(left As CompProjectRequest, right As CompProjectRequest) As Boolean
@@ -888,6 +910,10 @@ Retry:
                 Else
                 Else
                     If IsChineseSearch AndAlso Task.Input.Type <> CompType.Mod Then
                     If IsChineseSearch AndAlso Task.Input.Type <> CompType.Mod Then
                         Throw New Exception($"{If(Task.Input.Type = CompType.ModPack, "整合包", "资源包")}搜索仅支持英文")
                         Throw New Exception($"{If(Task.Input.Type = CompType.ModPack, "整合包", "资源包")}搜索仅支持英文")
+                    ElseIf Task.Input.Source = CompSourceType.CurseForge AndAlso Task.Input.Tag.StartsWith("/") Then
+                        Throw New Exception("CurseForge 不兼容所选的类型")
+                    ElseIf Task.Input.Source = CompSourceType.Modrinth AndAlso Task.Input.Tag.EndsWith("/") Then
+                        Throw New Exception("Modrinth 不兼容所选的类型")
                     Else
                     Else
                         Throw New Exception("没有符合条件的结果")
                         Throw New Exception("没有符合条件的结果")
                     End If
                     End If
@@ -1127,7 +1153,7 @@ Retry:
                 '可能为空
                 '可能为空
                 If CType(Data("files"), JArray).Count > 0 Then
                 If CType(Data("files"), JArray).Count > 0 Then
                     FileName = Data("files")(0)("filename")
                     FileName = Data("files")(0)("filename")
-                    DownloadAddress = {Data("files")(0)("url").ToString.Replace(FileName, Net.WebUtility.UrlEncode(FileName))}
+                    DownloadAddress = {Data("files")(0)("url").ToString.Replace(FileName, FileName)}
                 End If
                 End If
                 'Dependencies
                 'Dependencies
                 If Type = CompType.Mod Then
                 If Type = CompType.Mod Then
@@ -1311,7 +1337,7 @@ Retry:
         Stack.Children.Add(New TextBlock With {.Text = "前置 Mod", .FontSize = 14, .HorizontalAlignment = HorizontalAlignment.Left, .Margin = New Thickness(6, 2, 0, 5)})
         Stack.Children.Add(New TextBlock With {.Text = "前置 Mod", .FontSize = 14, .HorizontalAlignment = HorizontalAlignment.Left, .Margin = New Thickness(6, 2, 0, 5)})
         '添加前置 Mod 列表
         '添加前置 Mod 列表
         For Each Dep In Deps
         For Each Dep In Deps
-            Dim Item = CompProjectCache(Dep).ToCompItem(True, True, AddressOf FrmDownloadMod.ProjectClick)
+            Dim Item = CompProjectCache(Dep).ToCompItem(False, False, AddressOf FrmDownloadMod.ProjectClick)
             Stack.Children.Add(Item)
             Stack.Children.Add(Item)
         Next
         Next
         '添加结尾间隔
         '添加结尾间隔

+ 4 - 0
Plain Craft Launcher 2/Modules/Minecraft/ModCrash.vb

@@ -330,6 +330,7 @@
         使用OpenJ9
         使用OpenJ9
         Java版本过高
         Java版本过高
         Java版本不兼容
         Java版本不兼容
+        Mod名称包含特殊字符
         显卡驱动不支持导致无法设置像素格式
         显卡驱动不支持导致无法设置像素格式
         极短的程序输出
         极短的程序输出
         Intel驱动不兼容导致EXCEPTION_ACCESS_VIOLATION 'https://bugs.mojang.com/browse/MC-32606
         Intel驱动不兼容导致EXCEPTION_ACCESS_VIOLATION 'https://bugs.mojang.com/browse/MC-32606
@@ -482,6 +483,7 @@ Done:
             If LogMc.Contains("Maybe try a lower resolution resourcepack?") Then AppendReason(CrashReason.材质过大或显卡配置不足)
             If LogMc.Contains("Maybe try a lower resolution resourcepack?") Then AppendReason(CrashReason.材质过大或显卡配置不足)
             If LogMc.Contains("java.lang.NoSuchMethodError: net.minecraft.world.server.ChunkManager$ProxyTicketManager.shouldForceTicks(J)Z") AndAlso LogMc.Contains("OptiFine") Then AppendReason(CrashReason.OptiFine导致无法加载世界)
             If LogMc.Contains("java.lang.NoSuchMethodError: net.minecraft.world.server.ChunkManager$ProxyTicketManager.shouldForceTicks(J)Z") AndAlso LogMc.Contains("OptiFine") Then AppendReason(CrashReason.OptiFine导致无法加载世界)
             If LogMc.Contains("Unsupported class file major version") Then AppendReason(CrashReason.Java版本不兼容)
             If LogMc.Contains("Unsupported class file major version") Then AppendReason(CrashReason.Java版本不兼容)
+            If LogMc.Contains("Invalid module name: '' is not a Java identifier") Then AppendReason(CrashReason.Mod名称包含特殊字符)
             If LogMc.Contains("java.lang.UnsupportedClassVersionError: net/fabricmc/loader/impl/launch/knot/KnotClient : Unsupported major.minor version") Then AppendReason(CrashReason.Java版本不兼容)
             If LogMc.Contains("java.lang.UnsupportedClassVersionError: net/fabricmc/loader/impl/launch/knot/KnotClient : Unsupported major.minor version") Then AppendReason(CrashReason.Java版本不兼容)
             If LogMc.Contains("Could not reserve enough space") Then
             If LogMc.Contains("Could not reserve enough space") Then
                 If LogMc.Contains("for 1048576KB object heap") Then
                 If LogMc.Contains("for 1048576KB object heap") Then
@@ -799,6 +801,8 @@ NextStack:
                     Results.Add("游戏似乎因为你所使用的 Java 版本过高而崩溃了。\n请在启动设置的 Java 选择一项中改用较低版本的 Java,然后再启动游戏。\n如果没有,可以从网络中下载、安装一个。")
                     Results.Add("游戏似乎因为你所使用的 Java 版本过高而崩溃了。\n请在启动设置的 Java 选择一项中改用较低版本的 Java,然后再启动游戏。\n如果没有,可以从网络中下载、安装一个。")
                 Case CrashReason.Java版本不兼容
                 Case CrashReason.Java版本不兼容
                     Results.Add("游戏不兼容你当前使用的 Java。\n如果没有合适的 Java,可以从网络中下载、安装一个。")
                     Results.Add("游戏不兼容你当前使用的 Java。\n如果没有合适的 Java,可以从网络中下载、安装一个。")
+                Case CrashReason.Mod名称包含特殊字符
+                    Results.Add("由于有 Mod 的名称包含特殊字符,导致游戏崩溃。\n请尝试修改 Mod 文件名,让它只包含英文字母、数字、减号(-)、下划线(_)和小数点,然后再启动游戏。")
                 Case CrashReason.使用32位Java导致JVM无法分配足够多的内存
                 Case CrashReason.使用32位Java导致JVM无法分配足够多的内存
                     If Environment.Is64BitOperatingSystem Then
                     If Environment.Is64BitOperatingSystem Then
                         Results.Add("你似乎正在使用 32 位 Java,这会导致 Minecraft 无法使用 1GB 以上的内存,进而造成崩溃。\n\n请在启动设置的 Java 选择一项中改用 64 位的 Java 再启动游戏,然后再启动游戏。\n如果你没有安装 64 位的 Java,你可以从网络中下载、安装一个。")
                         Results.Add("你似乎正在使用 32 位 Java,这会导致 Minecraft 无法使用 1GB 以上的内存,进而造成崩溃。\n\n请在启动设置的 Java 选择一项中改用 64 位的 Java 再启动游戏,然后再启动游戏。\n如果你没有安装 64 位的 Java,你可以从网络中下载、安装一个。")

+ 747 - 0
Plain Craft Launcher 2/Modules/Minecraft/ModJava.vb

@@ -0,0 +1,747 @@
+Public Module ModJava
+    Public JavaListCacheVersion As Integer = 4
+
+    ''' <summary>
+    ''' 目前所有可用的 Java。
+    ''' </summary>
+    Public JavaList As New List(Of JavaEntry)
+
+    Public Class JavaEntry
+
+        '路径
+        ''' <summary>
+        ''' Java.exe 文件的完整路径。
+        ''' </summary>
+        Public ReadOnly Property PathJava As String
+            Get
+                Return PathFolder & "java.exe"
+            End Get
+        End Property
+        ''' <summary>
+        ''' Javaw.exe 文件的完整路径。
+        ''' </summary>
+        Public ReadOnly Property PathJavaw As String
+            Get
+                Return PathFolder & "javaw.exe"
+            End Get
+        End Property
+        ''' <summary>
+        ''' Javaw.exe 文件所在文件夹的路径,以 \ 结尾。
+        ''' </summary>
+        Public PathFolder As String
+        ''' <summary>
+        ''' 是否为用户手动导入的 Java。
+        ''' </summary>
+        Public IsUserImport As Boolean
+
+        '版本信息
+        ''' <summary>
+        ''' Java 的详细版本。若不足 4 位会在前方补 1,例如 1.16.0.1。
+        ''' 其大版本号为 Minor。
+        ''' </summary>
+        Public Version As Version
+        ''' <summary>
+        ''' Java 的大版本号。
+        ''' </summary>
+        Public ReadOnly Property VersionCode As Integer
+            Get
+                Return Version.Minor
+            End Get
+        End Property
+        ''' <summary>
+        ''' 是否为 Java Runtime Environment。
+        ''' </summary>
+        Public IsJre As Boolean
+        ''' <summary>
+        ''' 是否为 64 位 Java。
+        ''' </summary>
+        Public Is64Bit As Boolean
+        ''' <summary>
+        ''' 是否已设置环境变量。
+        ''' </summary>
+        Public ReadOnly Property HasEnvironment As Boolean
+            Get
+                If PathFolder Is Nothing OrElse PathEnv Is Nothing Then Return False
+                Return PathEnv.Replace("\", "").Replace("/", "").ToLower.Contains(PathFolder.Replace("\", "").ToLower)
+            End Get
+        End Property
+
+        '序列化
+        Public Function ToJson() As JObject
+            Return New JObject({New JProperty("Path", PathFolder), New JProperty("VersionString", Version.ToString), New JProperty("IsJre", IsJre), New JProperty("Is64Bit", Is64Bit), New JProperty("IsUserImport", IsUserImport)})
+        End Function
+        Public Shared Function FromJson(Data As JObject) As JavaEntry
+            Return New JavaEntry(Data("Path"), Data("IsUserImport")) With {.Version = New Version(Data("VersionString")), .IsJre = Data("IsJre"), .Is64Bit = Data("Is64Bit")}
+        End Function
+        ''' <summary>
+        ''' 转化为用户友好的字符串输出。
+        ''' </summary>
+        Public Overrides Function ToString() As String
+            Dim VersionString = Version.ToString
+            If VersionString.StartsWith("1.") Then VersionString = Mid(VersionString, 3)
+            Return If(IsJre, "JRE ", "JDK ") & VersionCode & " (" & VersionString & ")," & If(Is64Bit, "64", "32") & " 位" & If(IsUserImport, ",手动导入", "") & ":" & PathFolder
+        End Function
+
+        '构造
+        ''' <summary>
+        ''' 输入 javaw.exe 文件所在文件夹的路径,不限制结尾。
+        ''' </summary>
+        Public Sub New(Folder As String, IsUserImport As Boolean)
+            If Not Folder.EndsWith("\") Then Folder += "\"
+            PathFolder = Folder.Replace("/", "\")
+            Me.IsUserImport = IsUserImport
+        End Sub
+
+        '方法
+        Private IsChecked As Boolean = False
+        ''' <summary>
+        ''' 检查并获取 Java 详细信息。在 Java 存在异常时抛出错误。
+        ''' </summary>
+        Public Sub Check()
+            If IsChecked Then Exit Sub
+            Dim Output As String = Nothing
+            Try
+                '确定文件存在
+                If Not File.Exists(PathJavaw) Then
+                    Throw New FileNotFoundException("未找到 javaw.exe 文件", PathJavaw)
+                End If
+                If Not File.Exists(PathFolder & "java.exe") Then
+                    Throw New FileNotFoundException("未找到 java.exe 文件", PathFolder & "java.exe")
+                End If
+                IsJre = Not File.Exists(PathFolder & "javac.exe")
+                '运行 -version
+                Output = ShellAndGetOutput(PathFolder & "java.exe", "-version", 15000).ToLower
+                If Output = "" Then Throw New Exception("尝试运行该 Java 失败")
+                If ModeDebug Then Log("[Java] Java 检查输出:" & PathFolder & "java.exe" & vbCrLf & Output)
+                '获取详细信息
+                Dim VersionString = If(RegexSeek(Output, "(?<=version "")[^""]+"), If(RegexSeek(Output, "(?<=openjdk )[0-9]+"), "")).Replace("_", ".").Split("-").First
+                Do While VersionString.Split(".").Count < 4
+                    If VersionString.StartsWith("1.") Then
+                        VersionString = VersionString & ".0"
+                    Else
+                        VersionString = "1." & VersionString
+                    End If
+                Loop
+                Version = New Version(VersionString)
+                If Version.Minor = 0 Then
+                    Log("[Java] 疑似 X.0.X.X 格式版本号:" & Version.ToString)
+                    Version = New Version(1, Version.Major, Version.Build, Version.Revision)
+                End If
+                Is64Bit = Output.Contains("64-bit")
+                If Version.Minor <= 4 OrElse Version.Minor >= 25 Then Throw New Exception("分析详细信息失败,获取的版本为 " & Version.ToString)
+                '无论如何不允许使用 JRE 16,它完全是炸的,安 OptiFine、Forge 和启动 MC 都会炸
+                If IsJre AndAlso VersionCode = 16 Then Throw New Exception("由于 JRE 16 对 Minecraft 的兼容性很差,因此不再允许使用")
+            Catch ex As Exception
+                Log("[Java] 检查失败的 Java 输出:" & PathFolder & "java.exe" & vbCrLf & If(Output, "无程序输出"))
+                Throw New Exception("检查 Java 失败(" & If(PathJavaw, "Nothing") & ")", ex)
+            End Try
+            IsChecked = True
+        End Sub
+
+    End Class
+
+    ''' <summary>
+    ''' Path 环境变量。
+    ''' </summary>
+    Private ReadOnly Property PathEnv As String
+        Get
+            If _PathEnv Is Nothing Then _PathEnv = If(Environment.GetEnvironmentVariable("Path"), "")
+            Return _PathEnv
+        End Get
+    End Property
+    Private _PathEnv As String = Nothing
+
+    ''' <summary>
+    ''' JAVA_HOME 环境变量。
+    ''' </summary>
+    Private ReadOnly Property PathJavaHome As String
+        Get
+            If _PathJavaHome Is Nothing Then _PathJavaHome = If(Environment.GetEnvironmentVariable("JAVA_HOME"), "")
+            Return _PathJavaHome
+        End Get
+    End Property
+    Private _PathJavaHome As String = Nothing
+
+    ''' <summary>
+    ''' 初始化 Java 列表,但除非没有 Java,否则不进行检查。
+    ''' </summary>
+    Public Sub JavaListInit()
+        JavaList = New List(Of JavaEntry)
+        Try
+            If Setup.Get("CacheJavaListVersion") < JavaListCacheVersion Then
+                '不使用缓存
+                Log("[Java] 要求 Java 列表缓存更新")
+                Setup.Set("CacheJavaListVersion", JavaListCacheVersion)
+            Else
+                '使用缓存
+                For Each JsonEntry In GetJson(Setup.Get("LaunchArgumentJavaAll"))
+                    JavaList.Add(JavaEntry.FromJson(JsonEntry))
+                Next
+            End If
+            If JavaList.Count = 0 Then
+                Log("[Java] 初始化未找到可用的 Java,将自动触发搜索", LogLevel.Developer)
+                JavaSearchLoader.Start(0)
+            Else
+                Log("[Java] 缓存中有 " & JavaList.Count & " 个可用的 Java")
+            End If
+        Catch ex As Exception
+            Log(ex, "初始化 Java 列表失败", LogLevel.Feedback)
+            Setup.Set("LaunchArgumentJavaAll", "[]")
+        End Try
+    End Sub
+    ''' <summary>
+    ''' 根据要求返回最适合的 Java,若找不到则返回 Nothing。
+    ''' 最小与最大版本在与输入相同时也会通过。
+    ''' 必须在工作线程调用。
+    ''' </summary>
+    Public Function JavaSelect(CancelException As String, Optional MinVersion As Version = Nothing, Optional MaxVersion As Version = Nothing,
+                               Optional RelatedVersion As McVersion = Nothing) As JavaEntry
+        Try
+            Dim AllowedJavaList As New List(Of JavaEntry)
+
+            '添加特定的 Java
+            Dim JavaPreList As New Dictionary(Of String, Boolean)
+            If PathMcFolder.Split("\").Count > 3 Then JavaSearchFolder(GetPathFromFullPath(PathMcFolder), JavaPreList, False, True) 'Minecraft 文件夹的父文件夹(如果不是根目录的话)
+            JavaSearchFolder(PathMcFolder, JavaPreList, False, True) 'Minecraft 文件夹
+            If RelatedVersion IsNot Nothing Then JavaSearchFolder(RelatedVersion.Path, JavaPreList, False, True) '所选版本文件夹
+            Dim TargetJavaList As New List(Of JavaEntry)
+            For Each Entry In JavaPreList
+                TargetJavaList.Add(New JavaEntry(Entry.Key, Entry.Value))
+            Next
+
+#Region "添加用户指定的 Java,储存到 UserJava 中"
+
+            Dim UserJava As JavaEntry = Nothing
+
+            '获取版本独立设置中指定的 Java
+            If RelatedVersion IsNot Nothing AndAlso Setup.Get("VersionArgumentJavaSelect", Version:=RelatedVersion).ToString.StartsWith("{") Then
+                Try
+                    UserJava = JavaEntry.FromJson(GetJson(Setup.Get("VersionArgumentJavaSelect", Version:=RelatedVersion)))
+                    '确保版本独立设置中指定的 Java 在 Java 列表中(#978)
+                    If Not JavaList.Any(Function(j) j.PathFolder = UserJava.PathFolder) Then
+                        UserJava = Nothing
+                        Setup.Reset("VersionArgumentJavaSelect", Version:=RelatedVersion)
+                        Log("版本独立设置中指定的 Java 不在主 Java 列表中,此设置已重置", LogLevel.Debug)
+                        Exit Try
+                    End If
+                Catch ex As Exception
+                    UserJava = Nothing
+                    Setup.Reset("VersionArgumentJavaSelect", Version:=RelatedVersion)
+                    Log(ex, "版本独立设置中指定的 Java 已无法使用,此设置已重置", LogLevel.Hint)
+                End Try
+            End If
+
+            '获取全局设置中指定的 Java
+            If UserJava Is Nothing AndAlso Setup.Get("LaunchArgumentJavaSelect") <> "" Then
+                Try
+                    UserJava = JavaEntry.FromJson(GetJson(Setup.Get("LaunchArgumentJavaSelect")))
+                Catch ex As Exception
+                    UserJava = Nothing
+                    Setup.Reset("LaunchArgumentJavaSelect")
+                    Log(ex, "设置中指定的 Java 已无法使用,此设置已重置", LogLevel.Hint)
+                End Try
+            End If
+
+            '添加到特定 Java 列表
+            If UserJava IsNot Nothing Then
+                Log($"[Java] 用户指定的 Java:{UserJava}")
+                TargetJavaList.Add(UserJava)
+            End If
+
+#End Region
+
+            '检查特定的 Java
+            If TargetJavaList.Count > 0 Then
+                TargetJavaList = JavaCheckList(TargetJavaList)
+                Log("[Java] 检查后找到 " & TargetJavaList.Count & " 个特定的 Java")
+            End If
+
+RetryGet:
+            '等待进行中的搜索结束
+            If JavaSearchLoader.State <> LoadState.Finished AndAlso JavaSearchLoader.State <> LoadState.Waiting Then JavaSearchLoader.WaitForExit()
+            Select Case JavaSearchLoader.State
+                Case LoadState.Failed
+                    Throw JavaSearchLoader.Error
+                Case LoadState.Aborted
+                    Throw New ThreadInterruptedException("Java 搜索加载器已中断")
+            End Select
+
+            '生成完整的 Java 列表
+            Dim AllJavaList As New List(Of JavaEntry)
+            AllJavaList.AddRange(TargetJavaList)
+            AllJavaList.AddRange(JavaList)
+
+            '根据选定条件进行过滤
+            For Each Java In AllJavaList
+                If MinVersion IsNot Nothing AndAlso Java.Version < MinVersion Then Continue For
+                If MaxVersion IsNot Nothing AndAlso Java.Version > MaxVersion Then Continue For
+                If Java.Is64Bit AndAlso Is32BitSystem Then Continue For
+                AllowedJavaList.Add(Java)
+            Next
+
+            '若未找到适合的 Java,尝试触发搜索
+            If AllowedJavaList.Count = 0 AndAlso JavaSearchLoader.State = LoadState.Waiting Then
+                Log("[Java] 未找到满足条件的 Java,尝试进行搜索")
+                JavaSearchLoader.Start(IsForceRestart:=True)
+                GoTo RetryGet
+            End If
+
+#Region "检查用户指定的 Java 是否可用"
+
+            '确保指定的 Java 可用
+            If UserJava Is Nothing Then GoTo ExitUserJavaCheck
+            If AllowedJavaList.Any(Function(j) j.PathFolder = UserJava.PathFolder) Then
+                Log("[Java] 使用用户指定的 Java:" & UserJava.PathFolder)
+                AllowedJavaList = New List(Of JavaEntry) From {UserJava}
+                GoTo UserPass
+            End If
+
+            '指定的 Java 不可用,弹窗要求选择
+            Log("[Java] 发现用户指定的不兼容 Java:" & UserJava.ToString)
+            For Each Java In AllowedJavaList
+                Log($"[Java] 实际可用的 Java:{Java.ToString}")
+            Next
+            Dim Requirement As String = ""
+            Dim ShowRevision As Boolean = False
+            If (MinVersion Is Nothing OrElse MinVersion.Minor = 0) AndAlso (MaxVersion IsNot Nothing AndAlso MaxVersion.Minor < 999) Then
+                ShowRevision = MaxVersion.MinorRevision < 999
+                Requirement = "最高兼容到 Java " & MaxVersion.Minor & If(ShowRevision, "." & MaxVersion.MajorRevision & "." & MaxVersion.MinorRevision, "")
+            ElseIf (MinVersion IsNot Nothing AndAlso MinVersion.Minor > 0) AndAlso (MaxVersion Is Nothing OrElse MaxVersion.Minor >= 999) Then
+                ShowRevision = MinVersion.MinorRevision > 0 OrElse MinVersion.MajorRevision > 0
+                Requirement = "至少需要 Java " & MinVersion.Minor & If(ShowRevision, "." & MinVersion.MajorRevision & "." & MinVersion.MinorRevision, "")
+            ElseIf (MinVersion IsNot Nothing AndAlso MinVersion.Minor > 0) AndAlso (MaxVersion IsNot Nothing AndAlso MaxVersion.Minor < 999) Then
+                ShowRevision = MinVersion.MinorRevision > 0 OrElse MinVersion.MajorRevision > 0 OrElse MaxVersion.MinorRevision < 999
+                Dim Left As String = MinVersion.Minor & If(ShowRevision, "." & MinVersion.MajorRevision & "." & MinVersion.MinorRevision, "")
+                Dim Right As String = MaxVersion.Minor & If(ShowRevision, "." & MaxVersion.MajorRevision & "." & MaxVersion.MinorRevision, "")
+                Requirement = "需要 Java " & If(Left = Right, Left, Left & " ~ " & Right)
+            End If
+            Dim JavaCurrent As String = UserJava.VersionCode & If(ShowRevision, "." & UserJava.Version.MajorRevision & "." & UserJava.Version.MinorRevision, "")
+            If Setup.Get("LaunchAdvanceJava") Then
+                '直接跳过弹窗
+                Hint("设置中指定了使用 Java " & JavaCurrent & ",但当前版本" & Requirement & ",这可能会导致游戏崩溃!", HintType.Critical)
+                AllowedJavaList = New List(Of JavaEntry) From {UserJava}
+            Else
+                Select Case MyMsgBox("你在设置中手动指定了使用 Java " & JavaCurrent & ",但当前" & Requirement & "。" & vbCrLf &
+                            "如果强制使用该 Java,可能导致游戏崩溃。" & vbCrLf &
+                            "你也可以将 游戏 Java 设置修改为 自动选择合适的 Java。" & vbCrLf &
+                            vbCrLf &
+                            " - 指定的 Java:" & UserJava.ToString,
+                            "Java 兼容性警告", "让 PCL 自动选择", "强制使用该 Java", "取消")
+                    Case 1 '让 PCL 自动选择
+                    Case 2 '强制使用指定的 Java
+                        Log("[Java] 已强制使用用户指定的不兼容 Java")
+                        AllowedJavaList = New List(Of JavaEntry) From {UserJava}
+                    Case 3 '取消启动
+                        Throw New Exception(CancelException)
+                End Select
+            End If
+
+ExitUserJavaCheck:
+#End Region
+
+            '若依然未找到适合的 Java,直接返回
+            If AllowedJavaList.Count = 0 Then Return Nothing
+
+            '优先使用特定目录下的 Java
+            For Each Java In AllowedJavaList
+                If TargetJavaList.Contains(Java) Then
+                    '直接使用指定的 Java
+                    AllowedJavaList = New List(Of JavaEntry) From {Java}
+                    Log("[Java] 优先使用特定的 Java:" & Java.ToString)
+                    GoTo UserPass
+                End If
+            Next
+UserPass:
+
+            '对适合的 Java 进行排序
+            AllowedJavaList = Sort(AllowedJavaList, AddressOf JavaSorter)
+
+            '检查选定的 Java,若测试失败则尝试进行搜索
+            Dim SelectedJava = AllowedJavaList.First
+            Try
+                SelectedJava.Check()
+            Catch ex As ThreadInterruptedException
+                Throw
+            Catch ex As Exception
+                Log(ex, "找到的 Java 已无法使用,尝试进行搜索")
+                AllowedJavaList = New List(Of JavaEntry)
+                JavaSearchLoader.Start(IsForceRestart:=True)
+                GoTo RetryGet
+            End Try
+
+            '返回
+            Log("[Java] 选定的 Java:" & SelectedJava.ToString)
+            Return SelectedJava
+
+        Catch ex As ThreadInterruptedException
+            Log(ex, "查找符合条件的 Java 时出现加载器中断")
+            Return Nothing
+        Catch ex As Exception
+            If ex.Message = "$$" Then Throw ex
+            Log(ex, "查找符合条件的 Java 失败", LogLevel.Feedback)
+            Return Nothing
+        End Try
+    End Function
+    ''' <summary>
+    ''' 是否强制指定了 64 位 Java。如果没有强制指定,返回是否安装了 64 位 Java。
+    ''' </summary>
+    Public Function JavaIs64Bit(Optional RelatedVersion As McVersion = Nothing) As Boolean
+        Try
+            '检查强制指定
+            Dim UserSetup As String = Setup.Get("LaunchArgumentJavaSelect")
+            If RelatedVersion IsNot Nothing Then
+                Dim UserSetupVersion As String = Setup.Get("VersionArgumentJavaSelect", Version:=RelatedVersion)
+                If UserSetupVersion <> "使用全局设置" Then UserSetup = UserSetupVersion
+            End If
+            If UserSetup <> "" Then
+                Dim UserJava As JavaEntry = Nothing
+                Try
+                    UserJava = JavaEntry.FromJson(GetJson(UserSetup))
+                Catch ex As Exception
+                    Log(ex, "版本指定的 Java 信息已损坏,已重置版本设置中指定的 Java")
+                    Setup.Set("VersionArgumentJavaSelect", "使用全局设置", Version:=RelatedVersion)
+                    GoTo NoUserJava
+                End Try
+                For Each Java In JavaList
+                    If Java.PathFolder = UserJava.PathFolder Then Return UserJava.Is64Bit
+                Next
+            End If
+NoUserJava:
+            '检查列表
+            For Each Java In JavaList
+                If Java.Is64Bit Then Return True
+            Next
+            Return False
+        Catch ex As Exception
+            Log(ex, "检查 Java 类别时出错", LogLevel.Feedback)
+            Setup.Set("LaunchArgumentJavaSelect", "")
+            Return True
+        End Try
+    End Function
+    ''' <summary>
+    ''' 将 Java 按照适用性排序。
+    ''' </summary>
+    Public Function JavaSorter(Left As JavaEntry, Right As JavaEntry) As Boolean
+        '1. 尽量在当前文件夹或当前 Minecraft 文件夹
+        Dim ProgramPathParent As String, MinecraftPathParent As String = ""
+        ProgramPathParent = If(New DirectoryInfo(Path).Parent, New DirectoryInfo(Path)).FullName
+        If PathMcFolder <> "" Then MinecraftPathParent = If(New DirectoryInfo(PathMcFolder).Parent, New DirectoryInfo(PathMcFolder)).FullName
+        If Left.PathFolder.StartsWith(ProgramPathParent) AndAlso Not Right.PathFolder.StartsWith(ProgramPathParent) Then Return True
+        If Not Left.PathFolder.StartsWith(ProgramPathParent) AndAlso Right.PathFolder.StartsWith(ProgramPathParent) Then Return False
+        If PathMcFolder <> "" Then
+            If Left.PathFolder.StartsWith(MinecraftPathParent) AndAlso Not Right.PathFolder.StartsWith(MinecraftPathParent) Then Return True
+            If Not Left.PathFolder.StartsWith(MinecraftPathParent) AndAlso Right.PathFolder.StartsWith(MinecraftPathParent) Then Return False
+        End If
+        '2. 尽量使用 64 位
+        If Left.Is64Bit AndAlso Not Right.Is64Bit Then Return True
+        If Not Left.Is64Bit AndAlso Right.Is64Bit Then Return False
+        '3. 尽量不使用 JDK
+        If Left.IsJre AndAlso Not Right.IsJre Then Return True
+        If Not Left.IsJre AndAlso Right.IsJre Then Return False
+        '4. Java 大版本
+        If Left.VersionCode <> Right.VersionCode Then
+            '                             Java  7   8   9  10  11  12 13 14 15  16  17  18  19  20...
+            Dim Weight = {0, 1, 2, 3, 4, 5, 6, 14, 29, 10, 11, 12, 13, 9, 8, 7, 15, 31, 30, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28}
+            Return Weight.ElementAtOrDefault(Left.VersionCode) >= Weight.ElementAtOrDefault(Right.VersionCode)
+        End If
+        '5. 最次级版本号更接近 51
+        Return Math.Abs(Left.Version.Revision - 51) <= Math.Abs(Right.Version.Revision - 51)
+    End Function
+
+#Region "搜索"
+
+    ''' <summary>
+    ''' 模糊搜索并获取所有可用的 Java,并在结束后更新设置页面显示。输出将直接写入 JavaList。
+    ''' </summary>
+    Public JavaSearchLoader As New LoaderTask(Of Integer, Integer)("查找 Java", AddressOf JavaSearchLoaderSub) With {.ProgressWeight = 2}
+    Private Sub JavaSearchLoaderSub(Loader As LoaderTask(Of Integer, Integer))
+        If FrmSetupLaunch IsNot Nothing Then
+            RunInUiWait(Sub()
+                            FrmSetupLaunch.ComboArgumentJava.Items.Clear()
+                            FrmSetupLaunch.ComboArgumentJava.Items.Add(New ComboBoxItem With {.Content = "加载中……", .IsSelected = True})
+                        End Sub)
+        End If
+        If FrmVersionSetup IsNot Nothing Then
+            RunInUiWait(Sub()
+                            FrmVersionSetup.ComboArgumentJava.Items.Clear()
+                            FrmVersionSetup.ComboArgumentJava.Items.Add(New ComboBoxItem With {.Content = "加载中……", .IsSelected = True})
+                        End Sub)
+        End If
+
+        Try
+
+            '可能包含 Java 的文件夹列表,以 “\” 结尾,且仅包含 “\”
+            'Key:文件夹地址
+            'Value: 是否为玩家手动导入
+            Dim JavaPreList As New Dictionary(Of String, Boolean)
+
+#Region "模糊查找可能可用的 Java"
+
+            '查找环境变量中的 Java
+            For Each PathInEnv As String In Split((PathEnv & ";" & PathJavaHome).Replace("\\", "\").Replace("/", "\"), ";")
+                PathInEnv = PathInEnv.Trim(" """.ToCharArray())
+                If PathInEnv = "" Then Continue For
+                If Not PathInEnv.EndsWith("\") Then PathInEnv += "\"
+                '粗略检查有效性
+                If File.Exists(PathInEnv & "javaw.exe") Then JavaPreList(PathInEnv) = False
+            Next
+            '查找磁盘中的 Java
+            For Each Disk As DriveInfo In DriveInfo.GetDrives()
+                JavaSearchFolder(Disk.Name, JavaPreList, False)
+            Next
+            '查找 APPDATA 文件夹中的 Java
+            JavaSearchFolder(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) & "\", JavaPreList, False)
+            JavaSearchFolder(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) & "\", JavaPreList, False)
+            '查找启动器目录中的 Java
+            JavaSearchFolder(Path, JavaPreList, False, IsFullSearch:=True)
+            '查找所选 Minecraft 文件夹中的 Java
+            If Not String.IsNullOrWhiteSpace(PathMcFolder) AndAlso Path <> PathMcFolder Then
+                JavaSearchFolder(PathMcFolder, JavaPreList, False, IsFullSearch:=True)
+            End If
+
+            '若不全为符号链接,则清除符号链接的地址
+            Dim JavaWithoutReparse As New Dictionary(Of String, Boolean)
+            For Each Pair In JavaPreList
+                Dim Folder As String = Pair.Key.Replace("\\", "\").Replace("/", "\")
+                Dim Info As FileSystemInfo = New FileInfo(Folder & "javaw.exe")
+                Do
+                    If Info.Attributes.HasFlag(FileAttributes.ReparsePoint) Then
+                        Log("[Java] 位于 " & Folder & " 的 Java 包含符号链接")
+                        Continue For
+                    End If
+                    Info = If(TypeOf Info Is FileInfo, CType(Info, FileInfo).Directory, CType(Info, DirectoryInfo).Parent)
+                Loop While Info IsNot Nothing
+                Log("[Java] 位于 " & Folder & " 的 Java 不含符号链接")
+                JavaWithoutReparse.Add(Pair.Key, Pair.Value)
+            Next
+            If JavaWithoutReparse.Count > 0 Then JavaPreList = JavaWithoutReparse
+
+            '若不全为特殊引用,则清除特殊引用的地址
+            Dim JavaWithoutInherit As New Dictionary(Of String, Boolean)
+            For Each Pair In JavaPreList
+                If Pair.Key.Contains("javapath_target_") OrElse Pair.Key.Contains("javatmp") Then
+                    Log("[Java] 位于 " & Pair.Key & " 的 Java 包含特殊引用")
+                    Continue For
+                End If
+                Log("[Java] 位于 " & Pair.Key & " 的 Java 不含特殊引用")
+                JavaWithoutInherit.Add(Pair.Key, Pair.Value)
+            Next
+            If JavaWithoutInherit.Count > 0 Then JavaPreList = JavaWithoutInherit
+
+#End Region
+
+#Region "添加玩家手动导入的 Java"
+
+            Dim ImportedJava As String = Setup.Get("LaunchArgumentJavaAll")
+            Try
+                For Each JavaJsonObject In GetJson(ImportedJava)
+                    Dim Entry = JavaEntry.FromJson(JavaJsonObject)
+                    If Entry.IsUserImport Then JavaPreList(Entry.PathFolder) = True
+                Next
+            Catch ex As Exception
+                Log(ex, "Java 列表已损坏", LogLevel.Feedback)
+                Setup.Set("LaunchArgumentJavaAll", "[]")
+            End Try
+
+#End Region
+
+            '确保可用并获取详细信息,转入正式列表
+            Dim NewJavaList As New List(Of JavaEntry)
+            For Each Entry In Distinct(JavaPreList.ToList, Function(a, b) a.Key.ToLower = b.Key.ToLower) '#794
+                NewJavaList.Add(New JavaEntry(Entry.Key, Entry.Value))
+            Next
+            NewJavaList = Sort(JavaCheckList(NewJavaList), AddressOf JavaSorter)
+
+            '修改设置项
+            Dim AllList As New JArray
+            For Each Java In NewJavaList
+                AllList.Add(Java.ToJson)
+            Next
+            Setup.Set("LaunchArgumentJavaAll", AllList.ToString(Newtonsoft.Json.Formatting.None))
+            JavaList = NewJavaList
+
+        Catch ex As Exception
+            Log(ex, "搜索 Java 时出错", LogLevel.Feedback)
+            JavaList = New List(Of JavaEntry)
+        End Try
+
+        Log("[Java] Java 搜索完成,发现 " & JavaList.Count & " 个 Java")
+        If FrmSetupLaunch IsNot Nothing Then RunInUi(Sub() FrmSetupLaunch.RefreshJavaComboBox())
+        If FrmVersionSetup IsNot Nothing Then RunInUi(Sub() FrmVersionSetup.RefreshJavaComboBox())
+    End Sub
+
+    ''' <summary>
+    ''' 多线程检查列表中的所有 Java 项。
+    ''' </summary>
+    Private Function JavaCheckList(JavaEntries As List(Of JavaEntry)) As List(Of JavaEntry)
+        Log("[Java] 开始确认列表 Java 状态,共 " & JavaEntries.Count & " 项")
+        JavaCheckList = New List(Of JavaEntry)
+        Dim ListLock As New Object
+
+        '启动检查线程
+        Dim CheckThreads As New List(Of Thread)
+        For Each Entry In JavaEntries
+            Dim CheckThread As New Thread(Sub()
+                                              Try
+                                                  Entry.Check()
+                                                  Log("[Java] " & Entry.ToString)
+                                                  SyncLock ListLock
+                                                      JavaCheckList.Add(Entry)
+                                                  End SyncLock
+                                              Catch ex As Exception
+                                                  If Entry.IsUserImport Then
+                                                      Log(ex, "位于 " & Entry.PathFolder & " 的 Java 存在异常,将被自动移除", LogLevel.Hint)
+                                                  Else
+                                                      Log(ex, "位于 " & Entry.PathFolder & " 的 Java 存在异常")
+                                                  End If
+                                              End Try
+                                          End Sub)
+            CheckThreads.Add(CheckThread)
+            CheckThread.Start()
+        Next
+
+        '等待构造线程完成
+Wait:
+        Thread.Sleep(10)
+        For Each CheckThread In CheckThreads
+            If CheckThread.IsAlive Then GoTo Wait
+        Next
+    End Function
+    ''' <summary>
+    ''' 模糊搜索指定文件夹下的 Java,并只进行粗略的检查。这不会搜索全部路径。
+    ''' </summary>
+    ''' <param name="OriginalPath">开始搜索的起始路径,不限制结尾。</param>
+    ''' <param name="IsFullSearch">搜索当前文件夹下的全部文件夹(此参数不会传递到子文件夹)。</param>
+    Private Sub JavaSearchFolder(OriginalPath As String, ByRef Results As Dictionary(Of String, Boolean), Source As Boolean, Optional IsFullSearch As Boolean = False)
+        Try
+            Log("[Java] 开始" & If(IsFullSearch, "完全", "部分") & "遍历查找:" & OriginalPath)
+            JavaSearchFolder(New DirectoryInfo(OriginalPath), Results, Source, IsFullSearch)
+        Catch ex As UnauthorizedAccessException
+            Log("[Java] 遍历查找 Java 时遭遇无权限的文件夹:" & OriginalPath)
+        Catch ex As Exception
+            Log(ex, "遍历查找 Java 时出错(" & OriginalPath & ")")
+        End Try
+    End Sub
+    ''' <summary>
+    ''' 模糊搜索指定文件夹下的 Java,并只进行粗略的检查。这不会搜索全部路径。
+    ''' </summary>
+    ''' <param name="OriginalPath">开始搜索的起始路径,不限制结尾。</param>
+    ''' <param name="IsFullSearch">搜索当前文件夹下的全部文件夹(此参数不会传递到子文件夹)。</param>
+    Private Sub JavaSearchFolder(OriginalPath As DirectoryInfo, ByRef Results As Dictionary(Of String, Boolean), Source As Boolean, Optional IsFullSearch As Boolean = False)
+        Try
+            '确认目录存在
+            If Not OriginalPath.Exists Then Exit Sub
+            Dim Path As String = OriginalPath.FullName.Replace("\\", "\")
+            If Not Path.EndsWith("\") Then Path += "\"
+            '若该目录有 Java,则加入结果
+            If File.Exists(Path & "javaw.exe") Then Results(Path) = Source
+            '查找其下的所有文件夹
+            For Each FolderInfo As DirectoryInfo In OriginalPath.EnumerateDirectories
+                If FolderInfo.Attributes.HasFlag(FileAttributes.ReparsePoint) Then Continue For '跳过符号链接
+                Dim SearchEntry = GetFolderNameFromPath(FolderInfo.Name).ToLower '用于搜索的字符串
+                If IsFullSearch OrElse
+                        FolderInfo.Parent.Name.ToLower = "users" OrElse
+                        SearchEntry.Contains("java") OrElse SearchEntry.Contains("jdk") OrElse SearchEntry.Contains("env") OrElse
+                        SearchEntry.Contains("环境") OrElse SearchEntry.Contains("run") OrElse SearchEntry.Contains("软件") OrElse
+                        SearchEntry.Contains("jre") OrElse SearchEntry = "bin" OrElse SearchEntry.Contains("mc") OrElse
+                        SearchEntry.Contains("software") OrElse SearchEntry.Contains("cache") OrElse SearchEntry.Contains("temp") OrElse
+                        SearchEntry.Contains("corretto") OrElse SearchEntry.Contains("roaming") OrElse SearchEntry.Contains("users") OrElse
+                        SearchEntry.Contains("craft") OrElse SearchEntry.Contains("program") OrElse SearchEntry.Contains("世界") OrElse
+                        SearchEntry.Contains("net") OrElse SearchEntry.Contains("游戏") OrElse SearchEntry.Contains("oracle") OrElse
+                        SearchEntry.Contains("game") OrElse SearchEntry.Contains("file") OrElse SearchEntry.Contains("data") OrElse
+                        SearchEntry.Contains("jvm") OrElse SearchEntry.Contains("服务") OrElse SearchEntry.Contains("server") OrElse
+                        SearchEntry.Contains("客户") OrElse SearchEntry.Contains("client") OrElse SearchEntry.Contains("整合") OrElse
+                        SearchEntry.Contains("应用") OrElse SearchEntry.Contains("运行") OrElse SearchEntry.Contains("前置") OrElse
+                        SearchEntry.Contains("mojang") OrElse SearchEntry.Contains("官启") OrElse SearchEntry.Contains("新建文件夹") OrElse
+                        SearchEntry.Contains("eclipse") OrElse SearchEntry.Contains("microsoft") OrElse SearchEntry.Contains("hotspot") OrElse
+                        SearchEntry.Contains("runtime") OrElse SearchEntry.Contains("x86") OrElse SearchEntry.Contains("x64") OrElse
+                        SearchEntry.Contains("forge") OrElse SearchEntry.Contains("原版") OrElse SearchEntry.Contains("optifine") OrElse
+                        SearchEntry.Contains("官方") OrElse SearchEntry.Contains("启动") OrElse SearchEntry.Contains("hmcl") OrElse
+                        SearchEntry.Contains("mod") OrElse SearchEntry.Contains("高清") OrElse SearchEntry.Contains("download") OrElse
+                        SearchEntry.Contains("launch") OrElse SearchEntry.Contains("程序") OrElse SearchEntry.Contains("path") OrElse
+                        SearchEntry.Contains("version") OrElse SearchEntry.Contains("baka") OrElse SearchEntry.Contains("pcl") OrElse
+                        SearchEntry.Contains("local") OrElse SearchEntry.Contains("packages") OrElse SearchEntry.Contains("4297127D64EC6") OrElse '官启文件夹
+                        SearchEntry.Contains("国服") OrElse SearchEntry.Contains("网易") OrElse SearchEntry.Contains("ext") OrElse '网易 Java 文件夹名
+                        SearchEntry.Contains("netease") OrElse SearchEntry.Contains("1.") OrElse SearchEntry.Contains("启动") Then
+                    JavaSearchFolder(FolderInfo, Results, Source)
+                End If
+            Next
+        Catch ex As UnauthorizedAccessException
+            Log("[Java] 遍历查找 Java 时遭遇无权限的文件夹:" & OriginalPath.FullName)
+        Catch ex As Exception
+            Log(ex, "遍历查找 Java 时出错(" & OriginalPath.FullName & ")")
+        End Try
+    End Sub
+
+#End Region
+
+#Region "下载"
+
+    ''' <summary>
+    ''' 提示 Java 缺失,并弹窗确认是否自动下载。返回玩家选择是否下载。
+    ''' 支持下载 Java 8、14、17,输入其他 VersionCode 会要求玩家自行下载。
+    ''' </summary>
+    Public Function JavaDownloadConfirm(VersionCode As String) As Boolean
+        If VersionCode = 8 OrElse VersionCode = 14 OrElse VersionCode = 17 Then
+            Return MyMsgBox($"PCL 未找到 Java {VersionCode},是否需要 PCL 自动下载?" & vbCrLf &
+                            $"如果你已经安装了 Java {VersionCode},请在 设置 → 启动选项 → 游戏 Java 中手动导入。",
+                            "未找到 Java", "自动下载", "取消") = 1
+        Else
+            MyMsgBox($"PCL 未找到 Java {VersionCode}。" & vbCrLf &
+                     $"请自行搜索并安装 Java {VersionCode},安装后在 设置 → 启动选项 → 游戏 Java 中重新搜索或导入。",
+                     "未找到 Java")
+            Return False
+        End If
+    End Function
+
+    ''' <summary>
+    ''' 获取下载 Java 8/14/17 的加载器。需要开启 IsForceRestart 以正常刷新 Java 列表。
+    ''' </summary>
+    Public Function JavaFixLoaders(Version As Integer) As LoaderCombo(Of Integer)
+        Return New LoaderCombo(Of Integer)($"下载 Java {Version}", {
+            New LoaderTask(Of Integer, List(Of NetFile))("获取 Java 下载信息", AddressOf JavaFileList) With {.ProgressWeight = 2},
+            New LoaderDownload("下载 Java 文件", New List(Of NetFile)) With {.ProgressWeight = 10},
+            JavaSearchLoader
+        })
+    End Function
+    Private Sub JavaFileList(Loader As LoaderTask(Of Integer, List(Of NetFile)))
+        Log("[Java] 开始获取 Java 下载信息")
+        Dim IndexFileStr As String = NetGetCodeByDownload(
+            {"https://download.mcbbs.net/v1/products/java-runtime/2ec0cc96c44e5a76b9c8b7c39df7210883d12871/all.json",
+             "https://bmclapi2.bangbang93.com/v1/products/java-runtime/2ec0cc96c44e5a76b9c8b7c39df7210883d12871/all.json",
+             "https://piston-meta.mojang.com/v1/products/java-runtime/2ec0cc96c44e5a76b9c8b7c39df7210883d12871/all.json"},
+        IsJson:=True)
+        '获取下载地址
+        Dim MainEntry As JObject = CType(GetJson(IndexFileStr), JObject)($"windows-x{If(Is32BitSystem, "86", "64")}")
+        Dim Entries = MainEntry.Children.Reverse. '选择最靠后的一项(最新)
+            SelectMany(Function(e As JProperty) CType(e.Value, JArray).Select(Function(v) New KeyValuePair(Of String, JObject)(e.Name, v)))
+        Dim TargetEntry = Entries.First(Function(t) t.Value("version")("name").ToString.StartsWith(Loader.Input))
+        Dim Address As String = TargetEntry.Value("manifest")("url")
+        Log($"[Java] 准备下载 Java {TargetEntry.Value("version")("name")}({TargetEntry.Key}):{Address}")
+        '获取文件列表
+        Dim ListFileStr As String = NetGetCodeByDownload(
+            {Address.Replace("piston-meta.mojang.com", "download.mcbbs.net"),
+             Address.Replace("piston-meta.mojang.com", "bmclapi2.bangbang93.com"),
+             Address},
+        IsJson:=True)
+        Dim BaseDir As String = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) & "\.minecraft\runtime\" & TargetEntry.Key & "\"
+        Dim Results As New List(Of NetFile)
+        For Each File As JProperty In CType(GetJson(ListFileStr), JObject)("files")
+            If CType(File.Value, JObject)("downloads")?("raw") Is Nothing Then Continue For
+            Dim Info As JObject = CType(File.Value, JObject)("downloads")("raw")
+            Dim Checker As New FileChecker(ActualSize:=Info("size"), Hash:=Info("sha1"))
+            If Checker.Check(BaseDir & File.Name) Is Nothing Then Continue For '跳过已存在的文件
+            Dim Url As String = Info("url")
+            Results.Add(New NetFile(
+                            {Url.Replace("piston-data.mojang.com", "download.mcbbs.net"),
+                             Url.Replace("piston-data.mojang.com", "bmclapi2.bangbang93.com"),
+                             Url},
+                        BaseDir & File.Name, Checker))
+        Next
+        Loader.Output = Results
+        Log($"[Java] 需要下载 {Results.Count} 个文件,目标文件夹:{BaseDir}")
+    End Sub
+
+#End Region
+
+End Module

+ 48 - 29
Plain Craft Launcher 2/Modules/Minecraft/ModLaunch.vb

@@ -102,9 +102,7 @@ Public Module ModLaunch
         Try
         Try
             '构造主加载器
             '构造主加载器
             Dim LaunchLoader As New LoaderCombo(Of Object)("Minecraft 启动", {
             Dim LaunchLoader As New LoaderCombo(Of Object)("Minecraft 启动", {
-                New LoaderCombo(Of Integer)("Java 处理", {
-                    New LoaderTask(Of Integer, List(Of NetFile))("Java 验证", AddressOf McLaunchJavaValidate) With {.ProgressWeight = 2}
-                }) With {.ProgressWeight = 2, .Show = False, .Block = False},
+                New LoaderTask(Of Integer, Integer)("获取 Java", AddressOf McLaunchJava) With {.ProgressWeight = 4, .Block = False, .Show = False},
                 McLoginLoader,
                 McLoginLoader,
                 New LoaderCombo(Of String)("补全文件", DlClientFix(McVersionCurrent, False, AssetsIndexExistsBehaviour.DownloadInBackground, True)) With {.ProgressWeight = 15, .Show = False, .Block = True},
                 New LoaderCombo(Of String)("补全文件", DlClientFix(McVersionCurrent, False, AssetsIndexExistsBehaviour.DownloadInBackground, True)) With {.ProgressWeight = 15, .Show = False, .Block = True},
                 New LoaderTask(Of String, List(Of McLibToken))("获取启动参数", AddressOf McLaunchArgumentMain) With {.ProgressWeight = 2},
                 New LoaderTask(Of String, List(Of McLibToken))("获取启动参数", AddressOf McLaunchArgumentMain) With {.ProgressWeight = 2},
@@ -1131,7 +1129,7 @@ SystemBrowser:
 #Region "Java 处理"
 #Region "Java 处理"
 
 
     Private McLaunchJavaSelected As JavaEntry = Nothing
     Private McLaunchJavaSelected As JavaEntry = Nothing
-    Private Sub McLaunchJavaValidate(Task As LoaderTask(Of Integer, List(Of NetFile)))
+    Private Sub McLaunchJava(Task As LoaderTask(Of Integer, Integer))
         Dim MinVer As New Version(0, 0, 0, 0), MaxVer As New Version(999, 999, 999, 999)
         Dim MinVer As New Version(0, 0, 0, 0), MaxVer As New Version(999, 999, 999, 999)
 
 
         'MC 大版本检测
         'MC 大版本检测
@@ -1188,11 +1186,11 @@ 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 - 19
-                MinVer = New Version(1, 8, 0, 0) : MaxVer = New Version(1, 19, 999, 999)
+                '1.15 - 1.16:Java 8+
+                MinVer = New Version(1, 8, 0, 0)
             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 - 19
-                MinVer = New Version(1, 17, 0, 0) : MaxVer = New Version(1, 19, 999, 999)
+                '1.18+:Java 17+
+                MinVer = New Version(1, 17, 0, 0)
             End If
             End If
         End If
         End If
 
 
@@ -1213,21 +1211,37 @@ SystemBrowser:
 
 
         '无合适的 Java
         '无合适的 Java
         If Task.IsAborted Then Exit Sub '中断加载会导致 JavaSelect 异常地返回空值,误判找不到 Java
         If Task.IsAborted Then Exit Sub '中断加载会导致 JavaSelect 异常地返回空值,误判找不到 Java
-        McLaunchLog("无合适的 Java,取消启动")
-        If MinVer >= New Version(1, 17, 0, 0) Then
-            '缺少 Java 17
-            JavaMissing(17)
-        ElseIf MinVer >= New Version(1, 16, 0, 0) Then
-            '缺少 Java 16
-            JavaMissing(16)
+        McLaunchLog("无合适的 Java,需要确认是否自动下载")
+        Dim JavaCode As String
+        If MinVer >= New Version(1, 16, 0, 0) Then
+            JavaCode = 17
         ElseIf MaxVer < New Version(1, 8, 0, 0) Then
         ElseIf MaxVer < New Version(1, 8, 0, 0) Then
-            '缺少 Java 7
-            JavaMissing(7)
+            JavaCode = 7
+        ElseIf MinVer > New Version(1, 8, 0, 52) Then
+            '缺少 Java 8 较新版(统一通行证)
+            JavaCode = "8u101"
         Else
         Else
-            '缺少 Java 8 较新版
-            JavaMissing(8)
+            JavaCode = 8
+        End If
+        If Not JavaDownloadConfirm(JavaCode) Then Throw New Exception("$$")
+
+        '开始自动下载
+        Dim JavaLoader = JavaFixLoaders(JavaCode)
+        JavaLoader.Start(JavaCode, IsForceRestart:=True)
+        Do While JavaLoader.State = LoadState.Loading AndAlso Not Task.IsAborted
+            Task.Progress = JavaLoader.Progress
+            Thread.Sleep(10)
+        Loop
+
+        '检查下载结果
+        McLaunchJavaSelected = JavaSelect("$$", MinVer, MaxVer, McVersionCurrent)
+        If Task.IsAborted Then Exit Sub
+        If McLaunchJavaSelected IsNot Nothing Then
+            McLaunchLog("选择的 Java:" & McLaunchJavaSelected.ToString)
+        Else
+            Hint("没有可用的 Java,已取消启动!", HintType.Critical)
+            Throw New Exception("$$")
         End If
         End If
-        Throw New Exception("$$")
 
 
     End Sub
     End Sub
 
 
@@ -1304,16 +1318,21 @@ SystemBrowser:
         '进服
         '进服
         Dim Server As String = If(String.IsNullOrEmpty(McLaunchLoader.Input.ServerIp), Setup.Get("VersionServerEnter", McVersionCurrent), McLaunchLoader.Input.ServerIp)
         Dim Server As String = If(String.IsNullOrEmpty(McLaunchLoader.Input.ServerIp), Setup.Get("VersionServerEnter", McVersionCurrent), McLaunchLoader.Input.ServerIp)
         If Server.Length > 0 Then
         If Server.Length > 0 Then
-            If Server.Contains(":") Then
-                '包含端口号
-                Arguments += " --server " & Server.Split(":")(0) & " --port " & Server.Split(":")(1)
+            If McVersionCurrent.ReleaseTime > New Date(2023, 4, 4) Then
+                'QuickPlay
+                Arguments += $" --quickPlayMultiplayer ""{Server}"""
             Else
             Else
-                '不包含端口号
-                Arguments += " --server " & Server & " --port 25565"
-            End If
-            'OptiFine 警告
-            If McVersionCurrent.Version.HasOptiFine Then
-                Hint("OptiFine 与自动进入服务器可能不兼容,有概率导致材质丢失甚至游戏崩溃!", HintType.Critical)
+                '老版本
+                If Server.Contains(":") Then
+                    '包含端口号
+                    Arguments += " --server " & Server.Split(":")(0) & " --port " & Server.Split(":")(1)
+                Else
+                    '不包含端口号
+                    Arguments += " --server " & Server & " --port 25565"
+                End If
+                If McVersionCurrent.Version.HasOptiFine Then 'OptiFine 警告
+                    Hint("OptiFine 与自动进入服务器可能不兼容,有概率导致材质丢失甚至游戏崩溃!", HintType.Critical)
+                End If
             End If
             End If
         End If
         End If
         '自定义
         '自定义

+ 19 - 713
Plain Craft Launcher 2/Modules/Minecraft/ModMinecraft.vb

@@ -2,718 +2,6 @@
 
 
 Public Module ModMinecraft
 Public Module ModMinecraft
 
 
-#Region "Java"
-
-    '列表初始化
-
-    Public JavaListCacheVersion As Integer = 3
-    ''' <summary>
-    ''' 目前所有可用的 Java。
-    ''' </summary>
-    Public JavaList As New List(Of JavaEntry)
-    ''' <summary>
-    ''' 初始化 Java 列表,但除非没有 Java,否则不进行检查。
-    ''' </summary>
-    Public Sub JavaListInit()
-        JavaList = New List(Of JavaEntry)
-        Try
-            If Setup.Get("CacheJavaListVersion") < JavaListCacheVersion Then
-                '不使用缓存
-                Log("[Java] 要求 Java 列表缓存更新")
-                Setup.Set("CacheJavaListVersion", JavaListCacheVersion)
-            Else
-                '使用缓存
-                For Each JsonEntry In GetJson(Setup.Get("LaunchArgumentJavaAll"))
-                    JavaList.Add(JavaEntry.FromJson(JsonEntry))
-                Next
-            End If
-            If JavaList.Count = 0 Then
-                Log("[Java] 初始化未找到可用的 Java,将自动触发搜索", LogLevel.Developer)
-                JavaSearchLoader.Start(0)
-            Else
-                Log("[Java] 缓存中有 " & JavaList.Count & " 个可用的 Java")
-            End If
-        Catch ex As Exception
-            Log(ex, "初始化 Java 列表失败", LogLevel.Feedback)
-            Setup.Set("LaunchArgumentJavaAll", "[]")
-        End Try
-    End Sub
-
-    '基础环境
-
-    ''' <summary>
-    ''' Path 环境变量。
-    ''' </summary>
-    Private ReadOnly Property PathEnv As String
-        Get
-            If _PathEnv Is Nothing Then _PathEnv = If(Environment.GetEnvironmentVariable("Path"), "")
-            Return _PathEnv
-        End Get
-    End Property
-    Private _PathEnv As String = Nothing
-
-    ''' <summary>
-    ''' JAVA_HOME 环境变量。
-    ''' </summary>
-    Private ReadOnly Property PathJavaHome As String
-        Get
-            If _PathJavaHome Is Nothing Then _PathJavaHome = If(Environment.GetEnvironmentVariable("JAVA_HOME"), "")
-            Return _PathJavaHome
-        End Get
-    End Property
-    Private _PathJavaHome As String = Nothing
-
-    Public Class JavaEntry
-
-        '路径
-        ''' <summary>
-        ''' Java.exe 文件的完整路径。
-        ''' </summary>
-        Public ReadOnly Property PathJava As String
-            Get
-                Return PathFolder & "java.exe"
-            End Get
-        End Property
-        ''' <summary>
-        ''' Javaw.exe 文件的完整路径。
-        ''' </summary>
-        Public ReadOnly Property PathJavaw As String
-            Get
-                Return PathFolder & "javaw.exe"
-            End Get
-        End Property
-        ''' <summary>
-        ''' Javaw.exe 文件所在文件夹的路径,以 \ 结尾。
-        ''' </summary>
-        Public PathFolder As String
-        ''' <summary>
-        ''' 是否为用户手动导入的 Java。
-        ''' </summary>
-        Public IsUserImport As Boolean
-
-        '版本信息
-        ''' <summary>
-        ''' Java 的详细版本。若不足 4 位会在前方补 1,例如 1.16.0.1。
-        ''' 其大版本号为 Minor。
-        ''' </summary>
-        Public Version As Version
-        ''' <summary>
-        ''' Java 的大版本号。
-        ''' </summary>
-        Public ReadOnly Property VersionCode As Integer
-            Get
-                Return Version.Minor
-            End Get
-        End Property
-        ''' <summary>
-        ''' 是否为 Java Runtime Environment。
-        ''' </summary>
-        Public IsJre As Boolean
-        ''' <summary>
-        ''' 是否为 64 位 Java。
-        ''' </summary>
-        Public Is64Bit As Boolean
-        ''' <summary>
-        ''' 是否已设置环境变量。
-        ''' </summary>
-        Public ReadOnly Property HasEnvironment As Boolean
-            Get
-                If PathFolder Is Nothing OrElse PathEnv Is Nothing Then Return False
-                Return PathEnv.Replace("\", "").Replace("/", "").ToLower.Contains(PathFolder.Replace("\", "").ToLower)
-            End Get
-        End Property
-
-        '序列化
-        Public Function ToJson() As JObject
-            Return New JObject({New JProperty("Path", PathFolder), New JProperty("VersionString", Version.ToString), New JProperty("IsJre", IsJre), New JProperty("Is64Bit", Is64Bit), New JProperty("IsUserImport", IsUserImport)})
-        End Function
-        Public Shared Function FromJson(Data As JObject) As JavaEntry
-            Return New JavaEntry(Data("Path"), Data("IsUserImport")) With {.Version = New Version(Data("VersionString")), .IsJre = Data("IsJre"), .Is64Bit = Data("Is64Bit")}
-        End Function
-        ''' <summary>
-        ''' 转化为用户友好的字符串输出。
-        ''' </summary>
-        Public Overrides Function ToString() As String
-            Dim VersionString = Version.ToString
-            If VersionString.StartsWith("1.") Then VersionString = Mid(VersionString, 3)
-            Return If(IsJre, "JRE ", "JDK ") & VersionCode & " (" & VersionString & ")," & If(Is64Bit, "64", "32") & " 位" & If(IsUserImport, ",手动导入", "") & ":" & PathFolder
-        End Function
-
-        '构造
-        ''' <summary>
-        ''' 输入 javaw.exe 文件所在文件夹的路径,不限制结尾。
-        ''' </summary>
-        Public Sub New(Folder As String, IsUserImport As Boolean)
-            If Not Folder.EndsWith("\") Then Folder += "\"
-            PathFolder = Folder.Replace("/", "\")
-            Me.IsUserImport = IsUserImport
-        End Sub
-
-        '方法
-        Private IsChecked As Boolean = False
-        ''' <summary>
-        ''' 检查并获取 Java 详细信息。在 Java 存在异常时抛出错误。
-        ''' </summary>
-        Public Sub Check()
-            If IsChecked Then Exit Sub
-            Dim Output As String = Nothing
-            Try
-                '确定文件存在
-                If Not File.Exists(PathJavaw) Then
-                    Throw New FileNotFoundException("未找到 javaw.exe 文件", PathJavaw)
-                End If
-                If Not File.Exists(PathFolder & "java.exe") Then
-                    Throw New FileNotFoundException("未找到 java.exe 文件", PathFolder & "java.exe")
-                End If
-                IsJre = Not File.Exists(PathFolder & "javac.exe")
-                '运行 -version
-                Output = ShellAndGetOutput(PathFolder & "java.exe", "-version", 15000).ToLower
-                If Output = "" Then Throw New Exception("尝试运行该 Java 失败")
-                If ModeDebug Then Log("[Java] Java 检查输出:" & PathFolder & "java.exe" & vbCrLf & Output)
-                '获取详细信息
-                Dim VersionString = If(RegexSeek(Output, "(?<=version "")[^""]+"), If(RegexSeek(Output, "(?<=openjdk )[0-9]+"), "")).Replace("_", ".").Split("-").First
-                Do While VersionString.Split(".").Count < 4
-                    If VersionString.StartsWith("1.") Then
-                        VersionString = VersionString & ".0"
-                    Else
-                        VersionString = "1." & VersionString
-                    End If
-                Loop
-                Version = New Version(VersionString)
-                If Version.Minor = 0 Then
-                    Log("[Java] 疑似 X.0.X.X 格式版本号:" & Version.ToString)
-                    Version = New Version(1, Version.Major, Version.Build, Version.Revision)
-                End If
-                Is64Bit = Output.Contains("64-bit")
-                If Version.Minor <= 4 OrElse Version.Minor >= 25 Then Throw New Exception("分析详细信息失败,获取的版本为 " & Version.ToString)
-                '无论如何不允许使用 JRE 16,它完全是炸的,安 OptiFine、Forge 和启动 MC 都会炸
-                If IsJre AndAlso VersionCode = 16 Then Throw New Exception("由于 JRE 16 对 Minecraft 的兼容性很差,因此不再允许使用")
-            Catch ex As Exception
-                Log("[Java] 检查失败的 Java 输出:" & PathFolder & "java.exe" & vbCrLf & If(Output, "无程序输出"))
-                Throw New Exception("检查 Java 失败(" & If(PathJavaw, "Nothing") & ")", ex)
-            End Try
-            IsChecked = True
-        End Sub
-
-    End Class
-
-    '搜索
-
-    ''' <summary>
-    ''' 模糊搜索并获取所有可用的 Java,并在结束后更新设置页面显示。输出将直接写入 JavaList。
-    ''' </summary>
-    Public JavaSearchLoader As New LoaderTask(Of Integer, Integer)("Java Search Loader", AddressOf JavaSearchLoaderSub)
-    Private Sub JavaSearchLoaderSub(Loader As LoaderTask(Of Integer, Integer))
-        If FrmSetupLaunch IsNot Nothing Then
-            RunInUiWait(Sub()
-                            FrmSetupLaunch.ComboArgumentJava.Items.Clear()
-                            FrmSetupLaunch.ComboArgumentJava.Items.Add(New ComboBoxItem With {.Content = "加载中……", .IsSelected = True})
-                        End Sub)
-        End If
-        If FrmVersionSetup IsNot Nothing Then
-            RunInUiWait(Sub()
-                            FrmVersionSetup.ComboArgumentJava.Items.Clear()
-                            FrmVersionSetup.ComboArgumentJava.Items.Add(New ComboBoxItem With {.Content = "加载中……", .IsSelected = True})
-                        End Sub)
-        End If
-
-        Try
-
-            '可能包含 Java 的文件夹列表,以 “\” 结尾,且仅包含 “\”
-            'Key:文件夹地址
-            'Value: 是否为玩家手动导入
-            Dim JavaPreList As New Dictionary(Of String, Boolean)
-
-#Region "模糊查找可能可用的 Java"
-
-            '查找环境变量中的 Java
-            For Each PathInEnv As String In Split((PathEnv & ";" & PathJavaHome).Replace("\\", "\").Replace("/", "\"), ";")
-                PathInEnv = PathInEnv.Trim(" """.ToCharArray())
-                If PathInEnv = "" Then Continue For
-                If Not PathInEnv.EndsWith("\") Then PathInEnv += "\"
-                '粗略检查有效性
-                If File.Exists(PathInEnv & "javaw.exe") Then JavaPreList(PathInEnv) = False
-            Next
-            '查找磁盘中的 Java
-            For Each Disk As DriveInfo In DriveInfo.GetDrives()
-                JavaSearchFolder(Disk.Name, JavaPreList, False)
-            Next
-            '查找 APPDATA 文件夹中的 Java
-            JavaSearchFolder(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) & "\", JavaPreList, False)
-            '查找启动器目录中的 Java
-            JavaSearchFolder(Path, JavaPreList, False, IsFullSearch:=True)
-            '查找所选 Minecraft 文件夹中的 Java
-            If Not String.IsNullOrWhiteSpace(PathMcFolder) AndAlso Path <> PathMcFolder Then
-                JavaSearchFolder(PathMcFolder, JavaPreList, False, IsFullSearch:=True)
-            End If
-
-            '若不全为符号链接,则清除符号链接的地址
-            Dim JavaWithoutReparse As New Dictionary(Of String, Boolean)
-            For Each Pair In JavaPreList
-                Dim Folder As String = Pair.Key.Replace("\\", "\").Replace("/", "\")
-                Dim Info As FileSystemInfo = New FileInfo(Folder & "javaw.exe")
-                Do
-                    If Info.Attributes.HasFlag(FileAttributes.ReparsePoint) Then
-                        Log("[Java] 位于 " & Folder & " 的 Java 包含符号链接")
-                        Continue For
-                    End If
-                    Info = If(TypeOf Info Is FileInfo, CType(Info, FileInfo).Directory, CType(Info, DirectoryInfo).Parent)
-                Loop While Info IsNot Nothing
-                Log("[Java] 位于 " & Folder & " 的 Java 不含符号链接")
-                JavaWithoutReparse.Add(Pair.Key, Pair.Value)
-            Next
-            If JavaWithoutReparse.Count > 0 Then JavaPreList = JavaWithoutReparse
-
-            '若不全为特殊引用,则清除特殊引用的地址
-            Dim JavaWithoutInherit As New Dictionary(Of String, Boolean)
-            For Each Pair In JavaPreList
-                If Pair.Key.Contains("javapath_target_") OrElse Pair.Key.Contains("javatmp") Then
-                    Log("[Java] 位于 " & Pair.Key & " 的 Java 包含特殊引用")
-                    Continue For
-                End If
-                Log("[Java] 位于 " & Pair.Key & " 的 Java 不含特殊引用")
-                JavaWithoutInherit.Add(Pair.Key, Pair.Value)
-            Next
-            If JavaWithoutInherit.Count > 0 Then JavaPreList = JavaWithoutInherit
-
-#End Region
-
-#Region "添加玩家手动导入的 Java"
-
-            Dim ImportedJava As String = Setup.Get("LaunchArgumentJavaAll")
-            Try
-                For Each JavaJsonObject In GetJson(ImportedJava)
-                    Dim Entry = JavaEntry.FromJson(JavaJsonObject)
-                    If Entry.IsUserImport Then JavaPreList(Entry.PathFolder) = True
-                Next
-            Catch ex As Exception
-                Log(ex, "Java 列表已损坏", LogLevel.Feedback)
-                Setup.Set("LaunchArgumentJavaAll", "[]")
-            End Try
-
-#End Region
-
-            '确保可用并获取详细信息,转入正式列表
-            Dim NewJavaList As New List(Of JavaEntry)
-            For Each Entry In Distinct(JavaPreList.ToList, Function(a, b) a.Key.ToLower = b.Key.ToLower) '#794
-                NewJavaList.Add(New JavaEntry(Entry.Key, Entry.Value))
-            Next
-            NewJavaList = Sort(JavaCheckList(NewJavaList), AddressOf JavaSorter)
-
-            '修改设置项
-            Dim AllList As New JArray
-            For Each Java In NewJavaList
-                AllList.Add(Java.ToJson)
-            Next
-            Setup.Set("LaunchArgumentJavaAll", AllList.ToString(Newtonsoft.Json.Formatting.None))
-            JavaList = NewJavaList
-
-        Catch ex As Exception
-            Log(ex, "搜索 Java 时出错", LogLevel.Feedback)
-            JavaList = New List(Of JavaEntry)
-        End Try
-
-        Log("[Java] Java 搜索完成,发现 " & JavaList.Count & " 个 Java")
-        If FrmSetupLaunch IsNot Nothing Then RunInUi(Sub() FrmSetupLaunch.RefreshJavaComboBox())
-        If FrmVersionSetup IsNot Nothing Then RunInUi(Sub() FrmVersionSetup.RefreshJavaComboBox())
-    End Sub
-
-    ''' <summary>
-    ''' 多线程检查列表中的所有 Java 项。
-    ''' </summary>
-    Private Function JavaCheckList(JavaEntries As List(Of JavaEntry)) As List(Of JavaEntry)
-        Log("[Java] 开始确认列表 Java 状态,共 " & JavaEntries.Count & " 项")
-        JavaCheckList = New List(Of JavaEntry)
-        Dim ListLock As New Object
-
-        '启动检查线程
-        Dim CheckThreads As New List(Of Thread)
-        For Each Entry In JavaEntries
-            Dim CheckThread As New Thread(Sub()
-                                              Try
-                                                  Entry.Check()
-                                                  Log("[Java] " & Entry.ToString)
-                                                  SyncLock ListLock
-                                                      JavaCheckList.Add(Entry)
-                                                  End SyncLock
-                                              Catch ex As Exception
-                                                  If Entry.IsUserImport Then
-                                                      Log(ex, "位于 " & Entry.PathFolder & " 的 Java 存在异常,将被自动移除", LogLevel.Hint)
-                                                  Else
-                                                      Log(ex, "位于 " & Entry.PathFolder & " 的 Java 存在异常")
-                                                  End If
-                                              End Try
-                                          End Sub)
-            CheckThreads.Add(CheckThread)
-            CheckThread.Start()
-        Next
-
-        '等待构造线程完成
-Wait:
-        Thread.Sleep(10)
-        For Each CheckThread In CheckThreads
-            If CheckThread.IsAlive Then GoTo Wait
-        Next
-    End Function
-    ''' <summary>
-    ''' 模糊搜索指定文件夹下的 Java,并只进行粗略的检查。这不会搜索全部路径。
-    ''' </summary>
-    ''' <param name="OriginalPath">开始搜索的起始路径,不限制结尾。</param>
-    ''' <param name="IsFullSearch">搜索当前文件夹下的全部文件夹(此参数不会传递到子文件夹)。</param>
-    Private Sub JavaSearchFolder(OriginalPath As String, ByRef Results As Dictionary(Of String, Boolean), Source As Boolean, Optional IsFullSearch As Boolean = False)
-        Try
-            Log("[Java] 开始" & If(IsFullSearch, "完全", "部分") & "遍历查找:" & OriginalPath)
-            JavaSearchFolder(New DirectoryInfo(OriginalPath), Results, Source, IsFullSearch)
-        Catch ex As UnauthorizedAccessException
-            Log("[Java] 遍历查找 Java 时遭遇无权限的文件夹:" & OriginalPath)
-        Catch ex As Exception
-            Log(ex, "遍历查找 Java 时出错(" & OriginalPath & ")")
-        End Try
-    End Sub
-    ''' <summary>
-    ''' 模糊搜索指定文件夹下的 Java,并只进行粗略的检查。这不会搜索全部路径。
-    ''' </summary>
-    ''' <param name="OriginalPath">开始搜索的起始路径,不限制结尾。</param>
-    ''' <param name="IsFullSearch">搜索当前文件夹下的全部文件夹(此参数不会传递到子文件夹)。</param>
-    Private Sub JavaSearchFolder(OriginalPath As DirectoryInfo, ByRef Results As Dictionary(Of String, Boolean), Source As Boolean, Optional IsFullSearch As Boolean = False)
-        Try
-            '确认目录存在
-            If Not OriginalPath.Exists Then Exit Sub
-            Dim Path As String = OriginalPath.FullName.Replace("\\", "\")
-            If Not Path.EndsWith("\") Then Path += "\"
-            '若该目录有 Java,则加入结果
-            If File.Exists(Path & "javaw.exe") Then Results(Path) = Source
-            '查找其下的所有文件夹
-            For Each FolderInfo As DirectoryInfo In OriginalPath.EnumerateDirectories
-                If FolderInfo.Attributes.HasFlag(FileAttributes.ReparsePoint) Then Continue For '跳过符号链接
-                Dim SearchEntry = GetFolderNameFromPath(FolderInfo.Name).ToLower '用于搜索的字符串
-                If IsFullSearch OrElse
-                        FolderInfo.Parent.Name.ToLower = "users" OrElse
-                        SearchEntry.Contains("java") OrElse SearchEntry.Contains("jdk") OrElse SearchEntry.Contains("env") OrElse
-                        SearchEntry.Contains("环境") OrElse SearchEntry.Contains("run") OrElse SearchEntry.Contains("软件") OrElse
-                        SearchEntry.Contains("jre") OrElse SearchEntry = "bin" OrElse SearchEntry.Contains("mc") OrElse
-                        SearchEntry.Contains("software") OrElse SearchEntry.Contains("cache") OrElse SearchEntry.Contains("temp") OrElse
-                        SearchEntry.Contains("corretto") OrElse SearchEntry.Contains("roaming") OrElse SearchEntry.Contains("users") OrElse
-                        SearchEntry.Contains("craft") OrElse SearchEntry.Contains("program") OrElse SearchEntry.Contains("世界") OrElse
-                        SearchEntry.Contains("net") OrElse SearchEntry.Contains("游戏") OrElse SearchEntry.Contains("oracle") OrElse
-                        SearchEntry.Contains("game") OrElse SearchEntry.Contains("file") OrElse SearchEntry.Contains("data") OrElse
-                        SearchEntry.Contains("jvm") OrElse SearchEntry.Contains("服务") OrElse SearchEntry.Contains("server") OrElse
-                        SearchEntry.Contains("客户") OrElse SearchEntry.Contains("client") OrElse SearchEntry.Contains("整合") OrElse
-                        SearchEntry.Contains("应用") OrElse SearchEntry.Contains("运行") OrElse SearchEntry.Contains("前置") OrElse
-                        SearchEntry.Contains("mojang") OrElse SearchEntry.Contains("官启") OrElse SearchEntry.Contains("新建文件夹") OrElse
-                        SearchEntry.Contains("eclipse") OrElse SearchEntry.Contains("microsoft") OrElse SearchEntry.Contains("hotspot") OrElse
-                        SearchEntry.Contains("runtime") OrElse SearchEntry.Contains("x86") OrElse SearchEntry.Contains("x64") OrElse
-                        SearchEntry.Contains("forge") OrElse SearchEntry.Contains("原版") OrElse SearchEntry.Contains("optifine") OrElse
-                        SearchEntry.Contains("官方") OrElse SearchEntry.Contains("启动") OrElse SearchEntry.Contains("hmcl") OrElse
-                        SearchEntry.Contains("mod") OrElse SearchEntry.Contains("高清") OrElse SearchEntry.Contains("download") OrElse
-                        SearchEntry.Contains("launch") OrElse SearchEntry.Contains("程序") OrElse SearchEntry.Contains("path") OrElse
-                        SearchEntry.Contains("国服") OrElse SearchEntry.Contains("网易") OrElse SearchEntry.Contains("ext") OrElse '网易 Java 文件夹名
-                        SearchEntry.Contains("netease") OrElse SearchEntry.Contains("1.") OrElse SearchEntry.Contains("启动") Then
-                    JavaSearchFolder(FolderInfo, Results, Source)
-                End If
-            Next
-        Catch ex As UnauthorizedAccessException
-            Log("[Java] 遍历查找 Java 时遭遇无权限的文件夹:" & OriginalPath.FullName)
-        Catch ex As Exception
-            Log(ex, "遍历查找 Java 时出错(" & OriginalPath.FullName & ")")
-        End Try
-    End Sub
-
-    '获取
-
-    ''' <summary>
-    ''' 根据要求返回最适合的 Java,若找不到则返回 Nothing。
-    ''' 最小与最大版本在与输入相同时也会通过。
-    ''' 必须在工作线程调用。
-    ''' </summary>
-    Public Function JavaSelect(CancelException As String, Optional MinVersion As Version = Nothing, Optional MaxVersion As Version = Nothing,
-                               Optional RelatedVersion As McVersion = Nothing) As JavaEntry
-        Try
-            Dim AllowedJavaList As New List(Of JavaEntry)
-
-            '添加特定的 Java
-            Dim JavaPreList As New Dictionary(Of String, Boolean)
-            If PathMcFolder.Split("\").Count > 3 Then JavaSearchFolder(GetPathFromFullPath(PathMcFolder), JavaPreList, False, True) 'Minecraft 文件夹的父文件夹(如果不是根目录的话)
-            JavaSearchFolder(PathMcFolder, JavaPreList, False, True) 'Minecraft 文件夹
-            If RelatedVersion IsNot Nothing Then JavaSearchFolder(RelatedVersion.Path, JavaPreList, False, True) '所选版本文件夹
-            Dim TargetJavaList As New List(Of JavaEntry)
-            For Each Entry In JavaPreList
-                TargetJavaList.Add(New JavaEntry(Entry.Key, Entry.Value))
-            Next
-
-#Region "添加用户指定的 Java,储存到 UserJava 中"
-
-            Dim UserJava As JavaEntry = Nothing
-
-            '获取版本独立设置中指定的 Java
-            If RelatedVersion IsNot Nothing AndAlso Setup.Get("VersionArgumentJavaSelect", Version:=RelatedVersion).ToString.StartsWith("{") Then
-                Try
-                    UserJava = JavaEntry.FromJson(GetJson(Setup.Get("VersionArgumentJavaSelect", Version:=RelatedVersion)))
-                    '确保版本独立设置中指定的 Java 在 Java 列表中(#978)
-                    If Not JavaList.Any(Function(j) j.PathFolder = UserJava.PathFolder) Then
-                        UserJava = Nothing
-                        Setup.Reset("VersionArgumentJavaSelect", Version:=RelatedVersion)
-                        Log("版本独立设置中指定的 Java 不在主 Java 列表中,此设置已重置", LogLevel.Debug)
-                        Exit Try
-                    End If
-                Catch ex As Exception
-                    UserJava = Nothing
-                    Setup.Reset("VersionArgumentJavaSelect", Version:=RelatedVersion)
-                    Log(ex, "版本独立设置中指定的 Java 已无法使用,此设置已重置", LogLevel.Hint)
-                End Try
-            End If
-
-            '获取全局设置中指定的 Java
-            If UserJava Is Nothing AndAlso Setup.Get("LaunchArgumentJavaSelect") <> "" Then
-                Try
-                    UserJava = JavaEntry.FromJson(GetJson(Setup.Get("LaunchArgumentJavaSelect")))
-                Catch ex As Exception
-                    UserJava = Nothing
-                    Setup.Reset("LaunchArgumentJavaSelect")
-                    Log(ex, "设置中指定的 Java 已无法使用,此设置已重置", LogLevel.Hint)
-                End Try
-            End If
-
-            '添加到特定 Java 列表
-            If UserJava IsNot Nothing Then
-                Log($"[Java] 用户指定的 Java:{UserJava}")
-                TargetJavaList.Add(UserJava)
-            End If
-
-#End Region
-
-            '检查特定的 Java
-            If TargetJavaList.Count > 0 Then
-                TargetJavaList = JavaCheckList(TargetJavaList)
-                Log("[Java] 检查后找到 " & TargetJavaList.Count & " 个特定的 Java")
-            End If
-
-RetryGet:
-            '等待进行中的搜索结束
-            If JavaSearchLoader.State <> LoadState.Finished AndAlso JavaSearchLoader.State <> LoadState.Waiting Then JavaSearchLoader.WaitForExit()
-            Select Case JavaSearchLoader.State
-                Case LoadState.Failed
-                    Throw JavaSearchLoader.Error
-                Case LoadState.Aborted
-                    Throw New ThreadInterruptedException("Java 搜索加载器已中断")
-            End Select
-
-            '生成完整的 Java 列表
-            Dim AllJavaList As New List(Of JavaEntry)
-            AllJavaList.AddRange(TargetJavaList)
-            AllJavaList.AddRange(JavaList)
-
-            '根据选定条件进行过滤
-            For Each Java In AllJavaList
-                If MinVersion IsNot Nothing AndAlso Java.Version < MinVersion Then Continue For
-                If MaxVersion IsNot Nothing AndAlso Java.Version > MaxVersion Then Continue For
-                If Java.Is64Bit AndAlso Is32BitSystem Then Continue For
-                AllowedJavaList.Add(Java)
-            Next
-
-            '若未找到适合的 Java,尝试触发搜索
-            If AllowedJavaList.Count = 0 AndAlso JavaSearchLoader.State = LoadState.Waiting Then
-                Log("[Java] 未找到满足条件的 Java,尝试进行搜索")
-                JavaSearchLoader.Start()
-                GoTo RetryGet
-            End If
-
-#Region "检查用户指定的 Java 是否可用"
-
-            '确保指定的 Java 可用
-            If UserJava Is Nothing Then GoTo ExitUserJavaCheck
-            If AllowedJavaList.Any(Function(j) j.PathFolder = UserJava.PathFolder) Then
-                Log("[Java] 使用用户指定的 Java:" & UserJava.PathFolder)
-                AllowedJavaList = New List(Of JavaEntry) From {UserJava}
-                GoTo UserPass
-            End If
-
-            '指定的 Java 不可用,弹窗要求选择
-            Log("[Java] 发现用户指定的不兼容 Java:" & UserJava.ToString)
-            For Each Java In AllowedJavaList
-                Log($"[Java] 实际可用的 Java:{Java.ToString}")
-            Next
-            Dim Requirement As String = ""
-            Dim ShowRevision As Boolean = False
-            If (MinVersion Is Nothing OrElse MinVersion.Minor = 0) AndAlso (MaxVersion IsNot Nothing AndAlso MaxVersion.Minor < 999) Then
-                ShowRevision = MaxVersion.MinorRevision < 999
-                Requirement = "最高兼容到 Java " & MaxVersion.Minor & If(ShowRevision, "." & MaxVersion.MajorRevision & "." & MaxVersion.MinorRevision, "")
-            ElseIf (MinVersion IsNot Nothing AndAlso MinVersion.Minor > 0) AndAlso (MaxVersion Is Nothing OrElse MaxVersion.Minor >= 999) Then
-                ShowRevision = MinVersion.MinorRevision > 0 OrElse MinVersion.MajorRevision > 0
-                Requirement = "至少需要 Java " & MinVersion.Minor & If(ShowRevision, "." & MinVersion.MajorRevision & "." & MinVersion.MinorRevision, "")
-            ElseIf (MinVersion IsNot Nothing AndAlso MinVersion.Minor > 0) AndAlso (MaxVersion IsNot Nothing AndAlso MaxVersion.Minor < 999) Then
-                ShowRevision = MinVersion.MinorRevision > 0 OrElse MinVersion.MajorRevision > 0 OrElse MaxVersion.MinorRevision < 999
-                Dim Left As String = MinVersion.Minor & If(ShowRevision, "." & MinVersion.MajorRevision & "." & MinVersion.MinorRevision, "")
-                Dim Right As String = MaxVersion.Minor & If(ShowRevision, "." & MaxVersion.MajorRevision & "." & MaxVersion.MinorRevision, "")
-                Requirement = "需要 Java " & If(Left = Right, Left, Left & " ~ " & Right)
-            End If
-            Dim JavaCurrent As String = UserJava.VersionCode & If(ShowRevision, "." & UserJava.Version.MajorRevision & "." & UserJava.Version.MinorRevision, "")
-            If Setup.Get("LaunchAdvanceJava") Then
-                '直接跳过弹窗
-                Hint("设置中指定了使用 Java " & JavaCurrent & ",但当前版本" & Requirement & ",这可能会导致游戏崩溃!", HintType.Critical)
-                AllowedJavaList = New List(Of JavaEntry) From {UserJava}
-            Else
-                Select Case MyMsgBox("你在设置中手动指定了使用 Java " & JavaCurrent & ",但当前" & Requirement & "。" & vbCrLf &
-                            "如果强制使用该 Java,可能导致游戏崩溃。" & vbCrLf &
-                            "你也可以将 游戏 Java 设置修改为 自动选择合适的 Java。" & vbCrLf &
-                            vbCrLf &
-                            " - 指定的 Java:" & UserJava.ToString,
-                            "Java 兼容性警告", "让 PCL 自动选择", "强制使用该 Java", "取消")
-                    Case 1 '让 PCL 自动选择
-                    Case 2 '强制使用指定的 Java
-                        Log("[Java] 已强制使用用户指定的不兼容 Java")
-                        AllowedJavaList = New List(Of JavaEntry) From {UserJava}
-                    Case 3 '取消启动
-                        Throw New Exception(CancelException)
-                End Select
-            End If
-
-ExitUserJavaCheck:
-#End Region
-
-            '若依然未找到适合的 Java,直接返回
-            If AllowedJavaList.Count = 0 Then Return Nothing
-
-            '优先使用特定目录下的 Java
-            For Each Java In AllowedJavaList
-                If TargetJavaList.Contains(Java) Then
-                    '直接使用指定的 Java
-                    AllowedJavaList = New List(Of JavaEntry) From {Java}
-                    Log("[Java] 优先使用特定的 Java:" & Java.ToString)
-                    GoTo UserPass
-                End If
-            Next
-UserPass:
-
-            '对适合的 Java 进行排序
-            AllowedJavaList = Sort(AllowedJavaList, AddressOf JavaSorter)
-
-            '检查选定的 Java,若测试失败则尝试进行搜索
-            Dim SelectedJava = AllowedJavaList.First
-            Try
-                SelectedJava.Check()
-            Catch ex As ThreadInterruptedException
-                Throw
-            Catch ex As Exception
-                Log(ex, "找到的 Java 已无法使用,尝试进行搜索")
-                AllowedJavaList = New List(Of JavaEntry)
-                JavaSearchLoader.Start(IsForceRestart:=True)
-                GoTo RetryGet
-            End Try
-
-            '返回
-            Log("[Java] 选定的 Java:" & SelectedJava.ToString)
-            Return SelectedJava
-
-        Catch ex As ThreadInterruptedException
-            Log(ex, "查找符合条件的 Java 时出现加载器中断")
-            Return Nothing
-        Catch ex As Exception
-            If ex.Message = "$$" Then Throw ex
-            Log(ex, "查找符合条件的 Java 失败", LogLevel.Feedback)
-            Return Nothing
-        End Try
-    End Function
-    ''' <summary>
-    ''' 返回是否安装了 64 位 Java,或在强制指定的时候是否指定 64 位 Java。
-    ''' </summary>
-    Public Function JavaUse64Bit(Optional RelatedVersion As McVersion = Nothing) As Boolean
-        Try
-            '检查强制指定
-            Dim UserSetup As String = Setup.Get("LaunchArgumentJavaSelect")
-            If RelatedVersion IsNot Nothing Then
-                Dim UserSetupVersion As String = Setup.Get("VersionArgumentJavaSelect", Version:=RelatedVersion)
-                If UserSetupVersion <> "使用全局设置" Then UserSetup = UserSetupVersion
-            End If
-            If UserSetup <> "" Then
-                Dim UserJava As JavaEntry = Nothing
-                Try
-                    UserJava = JavaEntry.FromJson(GetJson(UserSetup))
-                Catch ex As Exception
-                    Log(ex, "版本指定的 Java 信息已损坏,已重置版本设置中指定的 Java")
-                    Setup.Set("VersionArgumentJavaSelect", "使用全局设置", Version:=RelatedVersion)
-                    GoTo NoUserJava
-                End Try
-                For Each Java In JavaList
-                    If Java.PathFolder = UserJava.PathFolder Then Return UserJava.Is64Bit
-                Next
-            End If
-NoUserJava:
-            '检查列表
-            For Each Java In JavaList
-                If Java.Is64Bit Then Return True
-            Next
-            Return False
-        Catch ex As Exception
-            Log(ex, "检查 Java 类别时出错", LogLevel.Feedback)
-            Setup.Set("LaunchArgumentJavaSelect", "")
-            Return True
-        End Try
-    End Function
-    ''' <summary>
-    ''' 用于 Java 排序的函数。
-    ''' </summary>
-    Public Function JavaSorter(Left As JavaEntry, Right As JavaEntry) As Boolean
-        '1. 尽量在当前文件夹或当前 Minecraft 文件夹
-        Dim ProgramPathParent As String, MinecraftPathParent As String = ""
-        ProgramPathParent = If(New DirectoryInfo(Path).Parent, New DirectoryInfo(Path)).FullName
-        If PathMcFolder <> "" Then MinecraftPathParent = If(New DirectoryInfo(PathMcFolder).Parent, New DirectoryInfo(PathMcFolder)).FullName
-        If Left.PathFolder.StartsWith(ProgramPathParent) AndAlso Not Right.PathFolder.StartsWith(ProgramPathParent) Then Return True
-        If Not Left.PathFolder.StartsWith(ProgramPathParent) AndAlso Right.PathFolder.StartsWith(ProgramPathParent) Then Return False
-        If PathMcFolder <> "" Then
-            If Left.PathFolder.StartsWith(MinecraftPathParent) AndAlso Not Right.PathFolder.StartsWith(MinecraftPathParent) Then Return True
-            If Not Left.PathFolder.StartsWith(MinecraftPathParent) AndAlso Right.PathFolder.StartsWith(MinecraftPathParent) Then Return False
-        End If
-        '2. 尽量使用 64 位
-        If Left.Is64Bit AndAlso Not Right.Is64Bit Then Return True
-        If Not Left.Is64Bit AndAlso Right.Is64Bit Then Return False
-        '3. 尽量不使用 JDK
-        If Left.IsJre AndAlso Not Right.IsJre Then Return True
-        If Not Left.IsJre AndAlso Right.IsJre Then Return False
-        '4. Java 大版本
-        If Left.VersionCode <> Right.VersionCode Then
-            '                             Java  7   8   9  10  11  12 13 14 15  16  17  18  19  20...
-            Dim Weight = {0, 1, 2, 3, 4, 5, 6, 14, 29, 10, 11, 12, 13, 9, 8, 7, 15, 31, 30, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28}
-            Return Weight.ElementAtOrDefault(Left.VersionCode) >= Weight.ElementAtOrDefault(Right.VersionCode)
-        End If
-        '5. 最次级版本号更接近 51
-        Return Math.Abs(Left.Version.Revision - 51) <= Math.Abs(Right.Version.Revision - 51)
-    End Function
-
-    '缺失
-    ''' <summary>
-    ''' 提示 Java 缺失并跳转下载。支持 Java 7、8、16、17。
-    ''' </summary>
-    Public Sub JavaMissing(VersionCode As Integer)
-        Select Case VersionCode
-            Case 7
-                MyMsgBox("PCL 未找到 Java 7。" & vbCrLf &
-                         "请自行百度安装 Java 7,安装后在 PCL 的 设置 → 启动设置 → 游戏 Java 中通过搜索或导入,确保安装的 Java 已列入 Java 列表。",
-                         "未找到 Java")
-            Case 8 '291
-                If Is32BitSystem Then
-                    OpenWebsite("https://wwa.lanzoui.com/i7RyXq0jbub")
-                Else
-                    OpenWebsite("https://wwa.lanzoui.com/i2UyMq0jaqb")
-                End If
-                MyMsgBox("PCL 未找到版本适宜的 Java 8。" & vbCrLf &
-                         "请在打开的网页中下载安装包并安装,安装后在 PCL 的 设置 → 启动设置 → 游戏 Java 中通过搜索或导入,确保安装的 Java 已列入 Java 列表。",
-                         "未找到 Java")
-            Case 16, 17
-                If Is32BitSystem Then
-                    MyMsgBox("该版本的 MC 已不支持 32 位操作系统。你必须增加内存并重装为 64 位系统才能继续。", "系统兼容性提示")
-                Else
-                    OpenWebsite("https://www.oracle.com/java/technologies/downloads/#java17")
-                    MyMsgBox("PCL 未找到 Java 17。" & vbCrLf &
-                             "请在打开的网页中选择 x64 Installer,下载并安装。" & vbCrLf &
-                             "安装后在 PCL 的 设置 → 启动设置 → 游戏 Java 中通过搜索或导入,确保安装的 Java 已列入 Java 列表。",
-                             "未找到 Java")
-                End If
-        End Select
-    End Sub
-
-#End Region
-
 #Region "文件夹"
 #Region "文件夹"
 
 
     ''' <summary>
     ''' <summary>
@@ -1701,6 +989,8 @@ ExitDataLoad:
             Return "我们从地下室的废墟里找到了这个开发于 1994 年的杰作!"
             Return "我们从地下室的废墟里找到了这个开发于 1994 年的杰作!"
         ElseIf Name = "22w13oneblockatatime" Then
         ElseIf Name = "22w13oneblockatatime" Then
             Return "一次一个方块更新!迎接全新的挖掘、合成与骑乘玩法吧!"
             Return "一次一个方块更新!迎接全新的挖掘、合成与骑乘玩法吧!"
+        ElseIf Name = "23w13a_or_b" Then
+            Return "研究表明玩家喜欢作出选择——越多越好!"
         Else
         Else
             Return ""
             Return ""
         End If
         End If
@@ -2265,6 +1555,19 @@ NextVersion:
         Dim c = Integer.Parse(Uuid(23), Globalization.NumberStyles.AllowHexSpecifier)
         Dim c = Integer.Parse(Uuid(23), Globalization.NumberStyles.AllowHexSpecifier)
         Dim d = Integer.Parse(Uuid(31), Globalization.NumberStyles.AllowHexSpecifier)
         Dim d = Integer.Parse(Uuid(31), Globalization.NumberStyles.AllowHexSpecifier)
         Return If((a Xor b Xor c Xor d) Mod 2, "Alex", "Steve")
         Return If((a Xor b Xor c Xor d) Mod 2, "Alex", "Steve")
+        'Math.floorMod(uuid.hashCode(), 18)
+
+        'Public Function hashCode(ByVal str As String) As Integer
+        'Dim hash As Integer = 0
+        'Dim n As Integer = str.Length
+        'If n = 0 Then
+        '    Return hash
+        'End If
+        'For i As Integer = 0 To n - 1
+        '    hash = hash + Asc(str(i)) * (1 << (n - i - 1))
+        'Next
+        'Return hash
+        'End Function
     End Function
     End Function
 
 
 #End Region
 #End Region
@@ -2366,7 +1669,10 @@ NextVersion:
                 End If
                 End If
             End If
             End If
             If Not IsNothing(Rule("features")) Then '标签
             If Not IsNothing(Rule("features")) Then '标签
-                IsRightRule = IsRightRule AndAlso IsNothing(Rule("features")("is_demo_user")) '只反选是否为 Demo 用户
+                IsRightRule = IsRightRule AndAlso IsNothing(Rule("features")("is_demo_user")) '反选是否为 Demo 用户
+                If CType(Rule("features"), JObject).Children.Any(Function(j As JProperty) j.Name.StartsWith("is_quick_play")) Then
+                    IsRightRule = False '不开 Quick Play,让玩家自己加去
+                End If
             End If
             End If
 
 
             '反选确认
             '反选确认

+ 12 - 2
Plain Craft Launcher 2/Modules/Minecraft/ModWatcher.vb

@@ -95,7 +95,7 @@
                                        TimerLog()
                                        TimerLog()
                                        '设置窗口标题
                                        '设置窗口标题
                                        For i = 1 To 3
                                        For i = 1 To 3
-                                           If IsWindowFinished AndAlso WindowTitle <> "" AndAlso State = MinecraftState.Running AndAlso Not GameProcess.HasExited Then
+                                           If IsWindowFinished AndAlso IsWindowAppeared AndAlso WindowTitle <> "" AndAlso State = MinecraftState.Running AndAlso Not GameProcess.HasExited Then
                                                Dim RealTitle As String = WindowTitle.Replace("{time}", Date.Now.ToShortTimeString)
                                                Dim RealTitle As String = WindowTitle.Replace("{time}", Date.Now.ToShortTimeString)
                                                SetWindowText(WindowHandle, RealTitle.ToCharArray)
                                                SetWindowText(WindowHandle, RealTitle.ToCharArray)
                                            End If
                                            End If
@@ -248,6 +248,9 @@
 
 
         '窗口检查
         '窗口检查
         Private IsWindowAppeared As Boolean = False
         Private IsWindowAppeared As Boolean = False
+        ''' <summary>
+        ''' 窗口检查是否已经完成。这不一定代表着找到了窗口(如果没有找到,IsWindowAppeared 仍为 False)。
+        ''' </summary>
         Private IsWindowFinished As Boolean = False
         Private IsWindowFinished As Boolean = False
         Private WindowHandle As IntPtr
         Private WindowHandle As IntPtr
         Private Sub TimerWindow()
         Private Sub TimerWindow()
@@ -255,7 +258,14 @@
                 If GameProcess.HasExited Then Exit Sub
                 If GameProcess.HasExited Then Exit Sub
                 If IsWindowFinished Then Exit Sub
                 If IsWindowFinished Then Exit Sub
                 '获取全部窗口,检查是否有新增的
                 '获取全部窗口,检查是否有新增的
-                Dim MinecraftWindow = TryGetMinecraftWindow()
+                Dim MinecraftWindow As KeyValuePair(Of IntPtr, String)? = Nothing
+                Try
+                    MinecraftWindow = TryGetMinecraftWindow()
+                Catch ex As ComponentModel.Win32Exception
+                    '拒绝访问(#1062)
+                    Log(ex, "由于反作弊或安全软件拦截,PCL 无法操作游戏窗口", LogLevel.Hint)
+                    IsWindowFinished = True
+                End Try
                 If MinecraftWindow Is Nothing Then Exit Sub
                 If MinecraftWindow Is Nothing Then Exit Sub
                 Dim MinecraftWindowName = MinecraftWindow.Value.Value, MinecraftWindowHandle = MinecraftWindow.Value.Key
                 Dim MinecraftWindowName = MinecraftWindow.Value.Value, MinecraftWindowHandle = MinecraftWindow.Value.Key
                 '已找到窗口
                 '已找到窗口

+ 6 - 6
Plain Craft Launcher 2/Modules/Minecraft/MyCompItem.xaml

@@ -49,17 +49,17 @@
     <Grid Grid.Row="3" Grid.Column="3" Grid.ColumnSpan="2" VerticalAlignment="Bottom"
     <Grid Grid.Row="3" Grid.Column="3" Grid.ColumnSpan="2" VerticalAlignment="Bottom"
           IsHitTestVisible="False" SnapsToDevicePixels="False" UseLayoutRounding="False">
           IsHitTestVisible="False" SnapsToDevicePixels="False" UseLayoutRounding="False">
         <Grid.ColumnDefinitions>
         <Grid.ColumnDefinitions>
-            <ColumnDefinition Width="Auto" />
-            <ColumnDefinition Width="Auto" SharedSizeGroup="CompItemVersion" />
-            <ColumnDefinition Width="0.7*" x:Name="ColumnVersionMargin" />
+            <ColumnDefinition x:Name="ColumnVersion1" Width="Auto" />
+            <ColumnDefinition x:Name="ColumnVersion2" Width="Auto" SharedSizeGroup="CompItemVersion" />
+            <ColumnDefinition x:Name="ColumnVersion3" Width="0.7*" />
             
             
             <ColumnDefinition Width="Auto" />
             <ColumnDefinition Width="Auto" />
             <ColumnDefinition Width="55" />
             <ColumnDefinition Width="55" />
             <ColumnDefinition Width="1*" />
             <ColumnDefinition Width="1*" />
 
 
-            <ColumnDefinition Width="Auto" />
-            <ColumnDefinition Width="Auto" MinWidth="57" SharedSizeGroup="CompItemTime" />
-            <ColumnDefinition Width="1*" />
+            <ColumnDefinition x:Name="ColumnTime1"  Width="Auto" />
+            <ColumnDefinition x:Name="ColumnTime2" Width="Auto" MinWidth="57" SharedSizeGroup="CompItemTime" />
+            <ColumnDefinition x:Name="ColumnTime3" Width="1*" />
 
 
             <ColumnDefinition Width="Auto" />
             <ColumnDefinition Width="Auto" />
             <ColumnDefinition Width="Auto" SharedSizeGroup="CompItemSource" />
             <ColumnDefinition Width="Auto" SharedSizeGroup="CompItemSource" />

+ 4 - 1
Plain Craft Launcher 2/Modules/ModMusic.vb

@@ -259,7 +259,10 @@
                     PreviousVolume = Setup.Get("UiMusicVolume")
                     PreviousVolume = Setup.Get("UiMusicVolume")
                     CurrentWave.Volume = PreviousVolume / 1000
                     CurrentWave.Volume = PreviousVolume / 1000
                 End If
                 End If
-                Thread.Sleep(50)
+                '更新进度条
+                Dim Percent = Reader.CurrentTime.TotalMilliseconds / Reader.TotalTime.TotalMilliseconds
+                RunInUi(Sub() FrmMain.BtnExtraMusic.Progress = Percent)
+                Thread.Sleep(100)
             End While
             End While
             '当前音乐已播放结束,继续下一曲
             '当前音乐已播放结束,继续下一曲
             If CurrentWave.PlaybackState = NAudio.Wave.PlaybackState.Stopped AndAlso MusicAllList.Count > 0 Then MusicStartPlay(DequeueNextMusicAddress)
             If CurrentWave.PlaybackState = NAudio.Wave.PlaybackState.Stopped AndAlso MusicAllList.Count > 0 Then MusicStartPlay(DequeueNextMusicAddress)

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

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

+ 22 - 4
Plain Craft Launcher 2/Pages/PageDownload/ModDownloadLib.vb

@@ -382,8 +382,17 @@ Public Module ModDownloadLib
         '选择 Java
         '选择 Java
         Dim Java = JavaSelect("已取消安装。", New Version(1, 8, 0, 0))
         Dim Java = JavaSelect("已取消安装。", New Version(1, 8, 0, 0))
         If Java Is Nothing Then
         If Java Is Nothing Then
-            JavaMissing(17)
-            Throw New Exception("未找到用于安装 OptiFine 的 Java")
+            If Not JavaDownloadConfirm(17) Then Throw New Exception("由于未找到 Java,已取消安装。")
+            '开始自动下载
+            Dim JavaLoader = JavaFixLoaders(17)
+            JavaLoader.Start(17, IsForceRestart:=True)
+            Do While JavaLoader.State = LoadState.Loading AndAlso Not Task.IsAborted
+                Thread.Sleep(10)
+            Loop
+            '检查下载结果
+            Java = JavaSelect("已取消安装。", New Version(1, 8, 0, 0))
+            If Task.IsAborted Then Exit Sub
+            If Java Is Nothing Then Throw New Exception("由于未找到 Java,已取消安装。")
         End If
         End If
         '添加 Java Wrapper 作为主 Jar
         '添加 Java Wrapper 作为主 Jar
         Dim Arguments = "-Doolloo.jlw.tmpdir=""" & GetJavaWrapperDir() & """ -Duser.home=""" & BaseMcFolderHome & """ -cp """ & Target & """ -jar """ & ExtractJavaWrapper() & """ optifine.Installer"
         Dim Arguments = "-Doolloo.jlw.tmpdir=""" & GetJavaWrapperDir() & """ -Duser.home=""" & BaseMcFolderHome & """ -cp """ & Target & """ -jar """ & ExtractJavaWrapper() & """ optifine.Installer"
@@ -1099,8 +1108,17 @@ Public Module ModDownloadLib
         '选择 Java
         '选择 Java
         Dim Java = JavaSelect("已取消安装。", New Version(1, 8, 0, 0))
         Dim Java = JavaSelect("已取消安装。", New Version(1, 8, 0, 0))
         If Java Is Nothing Then
         If Java Is Nothing Then
-            JavaMissing(17)
-            Throw New Exception("未找到用于安装 Forge 的 Java")
+            If Not JavaDownloadConfirm(17) Then Throw New Exception("由于未找到 Java,已取消安装。")
+            '开始自动下载
+            Dim JavaLoader = JavaFixLoaders(17)
+            JavaLoader.Start(17, IsForceRestart:=True)
+            Do While JavaLoader.State = LoadState.Loading AndAlso Not Task.IsAborted
+                Thread.Sleep(10)
+            Loop
+            '检查下载结果
+            Java = JavaSelect("已取消安装。", New Version(1, 8, 0, 0))
+            If Task.IsAborted Then Exit Sub
+            If Java Is Nothing Then Throw New Exception("由于未找到 Java,已取消安装。")
         End If
         End If
         '添加 Java Wrapper 作为主 Jar
         '添加 Java Wrapper 作为主 Jar
         Dim Arguments = "-Doolloo.jlw.tmpdir=""" & GetJavaWrapperDir() & """ -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

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

@@ -39,7 +39,7 @@
                                 Version("id") = "20w14∞"
                                 Version("id") = "20w14∞"
                                 Version("type") = "special"
                                 Version("type") = "special"
                                 Version.Add("lore", GetMcFoolName(Version("id")))
                                 Version.Add("lore", GetMcFoolName(Version("id")))
-                            Case "3d shareware v1.34", "1.rv-pre1", "15w14a", "2.0", "22w13oneblockatatime"
+                            Case "3d shareware v1.34", "1.rv-pre1", "15w14a", "2.0", "22w13oneblockatatime", "23w13a_or_b"
                                 Type = "愚人节版"
                                 Type = "愚人节版"
                                 Version("type") = "special"
                                 Version("type") = "special"
                                 Version.Add("lore", GetMcFoolName(Version("id")))
                                 Version.Add("lore", GetMcFoolName(Version("id")))

+ 1 - 3
Plain Craft Launcher 2/Pages/PageDownload/PageDownloadInstall.xaml

@@ -100,9 +100,7 @@
                         </Grid>
                         </Grid>
                     </local:MyCard>
                     </local:MyCard>
                     <local:MyCard Title="Fabric" Height="40" Margin="0,15,0,0" x:Name="CardFabric" IsSwaped="True" CanSwap="True" SwapLogoRight="True">
                     <local:MyCard Title="Fabric" Height="40" Margin="0,15,0,0" x:Name="CardFabric" IsSwaped="True" CanSwap="True" SwapLogoRight="True">
-                        <StackPanel Margin="20,40,18,15" VerticalAlignment="Top">
-                            <StackPanel Name="PanFabric" />
-                        </StackPanel>
+                        <StackPanel Margin="20,40,18,15" VerticalAlignment="Top" Name="PanFabric" />
                         <Grid x:Name="PanFabricInfo" Height="18" Margin="175,11,15,0" VerticalAlignment="Top" Tag="True">
                         <Grid x:Name="PanFabricInfo" Height="18" Margin="175,11,15,0" VerticalAlignment="Top" Tag="True">
                             <Grid.RenderTransform>
                             <Grid.RenderTransform>
                                 <TranslateTransform />
                                 <TranslateTransform />

+ 5 - 5
Plain Craft Launcher 2/Pages/PageDownload/PageDownloadInstall.xaml.vb

@@ -522,7 +522,7 @@
                                 Version("id") = "20w14∞"
                                 Version("id") = "20w14∞"
                                 Version("type") = "special"
                                 Version("type") = "special"
                                 Version.Add("lore", GetMcFoolName(Version("id")))
                                 Version.Add("lore", GetMcFoolName(Version("id")))
-                            Case "3d shareware v1.34", "1.rv-pre1", "15w14a", "2.0", "22w13oneblockatatime"
+                            Case "3d shareware v1.34", "1.rv-pre1", "15w14a", "2.0", "22w13oneblockatatime", "23w13a_or_b"
                                 Type = "愚人节版"
                                 Type = "愚人节版"
                                 Version("type") = "special"
                                 Version("type") = "special"
                                 Version.Add("lore", GetMcFoolName(Version("id")))
                                 Version.Add("lore", GetMcFoolName(Version("id")))
@@ -859,16 +859,16 @@
             If Versions.Count = 0 Then Exit Sub
             If Versions.Count = 0 Then Exit Sub
             '可视化
             '可视化
             PanFabric.Children.Clear()
             PanFabric.Children.Clear()
-            For Each Version In Versions
-                PanFabric.Children.Add(FabricDownloadListItem(Version, AddressOf Fabric_Selected))
-            Next
+            PanFabric.Tag = Versions
+            CardFabric.SwapControl = PanFabric
+            CardFabric.SwapType = 12
         Catch ex As Exception
         Catch ex As Exception
             Log(ex, "可视化 Fabric 安装版本列表出错", LogLevel.Feedback)
             Log(ex, "可视化 Fabric 安装版本列表出错", LogLevel.Feedback)
         End Try
         End Try
     End Sub
     End Sub
 
 
     '选择与清除
     '选择与清除
-    Private Sub Fabric_Selected(sender As MyListItem, e As EventArgs)
+    Public Sub Fabric_Selected(sender As MyListItem, e As EventArgs)
         SelectedFabric = sender.Tag("version").ToString
         SelectedFabric = sender.Tag("version").ToString
         FabricApi_Loaded()
         FabricApi_Loaded()
         OptiFabric_Loaded()
         OptiFabric_Loaded()

+ 40 - 34
Plain Craft Launcher 2/Pages/PageDownload/PageDownloadMod.xaml

@@ -10,22 +10,55 @@
                 <StackPanel Margin="25,40,25,15">
                 <StackPanel Margin="25,40,25,15">
                     <Grid Margin="0,0,0,11" HorizontalAlignment="Stretch">
                     <Grid Margin="0,0,0,11" HorizontalAlignment="Stretch">
                         <Grid.ColumnDefinitions>
                         <Grid.ColumnDefinitions>
-                            <ColumnDefinition Width="Auto" />
-                            <ColumnDefinition Width="1*" />
-                            <ColumnDefinition Width="70" />
                             <ColumnDefinition Width="Auto" />
                             <ColumnDefinition Width="Auto" />
                             <ColumnDefinition Width="1.3*" />
                             <ColumnDefinition Width="1.3*" />
                             <ColumnDefinition Width="1.2*" />
                             <ColumnDefinition Width="1.2*" />
+                            <ColumnDefinition Width="50" />
+                            <ColumnDefinition Width="Auto" />
+                            <ColumnDefinition Width="1*" />
                         </Grid.ColumnDefinitions>
                         </Grid.ColumnDefinitions>
                         <Grid.RowDefinitions>
                         <Grid.RowDefinitions>
                             <RowDefinition Height="28" />
                             <RowDefinition Height="28" />
                             <RowDefinition Height="9" />
                             <RowDefinition Height="9" />
                             <RowDefinition Height="28" />
                             <RowDefinition Height="28" />
                         </Grid.RowDefinitions>
                         </Grid.RowDefinitions>
-                        <TextBlock VerticalAlignment="Center" HorizontalAlignment="Left" Text="名称" Margin="0,0,25,0" />
-                        <local:MyTextBox x:Name="TextSearchName" Grid.Column="1" Grid.ColumnSpan="10" />
-                        <TextBlock VerticalAlignment="Center" Grid.Row="2" HorizontalAlignment="Left" Text="类型" Margin="0,0,25,0" />
-                        <local:MyComboBox x:Name="ComboSearchTag" Grid.Column="1" Grid.Row="2" MaxDropDownHeight="320">
+                        <TextBlock VerticalAlignment="Center" HorizontalAlignment="Left" Text="名称" Margin="0,0,18,0" />
+                        <local:MyTextBox x:Name="TextSearchName" Grid.Column="1" Grid.ColumnSpan="2" />
+                        <TextBlock VerticalAlignment="Center" Grid.Column="4" HorizontalAlignment="Left" Text="来源" Margin="0,0,18,0" />
+                        <local:MyComboBox x:Name="ComboSearchSource" Grid.Column="5">
+                            <local:MyComboBoxItem Content="全部" Tag="3" IsSelected="True" />
+                            <local:MyComboBoxItem Content="CurseForge" Tag="1" />
+                            <local:MyComboBoxItem Content="Modrinth" Tag="2" />
+                        </local:MyComboBox>
+                        <TextBlock VerticalAlignment="Center" Grid.Row="2" HorizontalAlignment="Left" Text="版本" Margin="0,0,18,0" />
+                        <local:MyComboBox x:Name="TextSearchVersion" Grid.Row="2" Grid.Column="1" Grid.ColumnSpan="2" IsEditable="True" MaxDropDownHeight="320">
+                            <local:MyComboBoxItem Content="全部 (也可自行输入)" IsSelected="True" />
+                            <local:MyComboBoxItem Content="1.19.4" />
+                            <local:MyComboBoxItem Content="1.19.3" />
+                            <local:MyComboBoxItem Content="1.19.2" />
+                            <local:MyComboBoxItem Content="1.19.1" />
+                            <local:MyComboBoxItem Content="1.19" />
+                            <local:MyComboBoxItem Content="1.18.2" />
+                            <local:MyComboBoxItem Content="1.17.1" />
+                            <local:MyComboBoxItem Content="1.16.5" />
+                            <local:MyComboBoxItem Content="1.15.2" />
+                            <local:MyComboBoxItem Content="1.14.4" />
+                            <local:MyComboBoxItem Content="1.13.2" />
+                            <local:MyComboBoxItem Content="1.12.2" />
+                            <local:MyComboBoxItem Content="1.11.2" />
+                            <local:MyComboBoxItem Content="1.10.2" />
+                            <local:MyComboBoxItem Content="1.9.4" />
+                            <local:MyComboBoxItem Content="1.8.9" />
+                            <local:MyComboBoxItem Content="1.7.10" />
+                        </local:MyComboBox>
+                        <local:MyComboBox x:Name="ComboSearchLoader" Visibility="Collapsed" Grid.Row="2" Grid.Column="2" MaxDropDownHeight="320" Margin="10,0,0,0">
+                            <local:MyComboBoxItem Content="任意 Mod 加载器" IsSelected="True" Tag="0" />
+                            <local:MyComboBoxItem Content="Forge" Tag="1" />
+                            <local:MyComboBoxItem Content="Fabric" Tag="4" />
+                            <local:MyComboBoxItem Content="Quilt" Tag="5" />
+                        </local:MyComboBox>
+                        <TextBlock VerticalAlignment="Center" Grid.Column="4" Grid.Row="2" HorizontalAlignment="Left" Text="类型" Margin="0,0,18,0" />
+                        <local:MyComboBox x:Name="ComboSearchTag" Grid.Column="5" Grid.Row="2" MaxDropDownHeight="320">
                             <local:MyComboBoxItem Content="全部" Tag="" IsSelected="True" />
                             <local:MyComboBoxItem Content="全部" Tag="" IsSelected="True" />
                             <local:MyComboBoxItem Content="世界元素" Tag="406/worldgen" />
                             <local:MyComboBoxItem Content="世界元素" Tag="406/worldgen" />
                             <local:MyComboBoxItem Content="生物群系" Tag="407/" Margin="15,0,0,0" />
                             <local:MyComboBoxItem Content="生物群系" Tag="407/" Margin="15,0,0,0" />
@@ -53,33 +86,6 @@
                             <local:MyComboBoxItem Content="改良" Tag="5191/utility" />
                             <local:MyComboBoxItem Content="改良" Tag="5191/utility" />
                             <local:MyComboBoxItem Content="支持库" Tag="421/library" />
                             <local:MyComboBoxItem Content="支持库" Tag="421/library" />
                         </local:MyComboBox>
                         </local:MyComboBox>
-                        <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">
-                            <local:MyComboBoxItem Content="全部 (也可自行输入)" IsSelected="True" />
-                            <local:MyComboBoxItem Content="1.19.4" />
-                            <local:MyComboBoxItem Content="1.19.3" />
-                            <local:MyComboBoxItem Content="1.19.2" />
-                            <local:MyComboBoxItem Content="1.19.1" />
-                            <local:MyComboBoxItem Content="1.19" />
-                            <local:MyComboBoxItem Content="1.18.2" />
-                            <local:MyComboBoxItem Content="1.17.1" />
-                            <local:MyComboBoxItem Content="1.16.5" />
-                            <local:MyComboBoxItem Content="1.15.2" />
-                            <local:MyComboBoxItem Content="1.14.4" />
-                            <local:MyComboBoxItem Content="1.13.2" />
-                            <local:MyComboBoxItem Content="1.12.2" />
-                            <local:MyComboBoxItem Content="1.11.2" />
-                            <local:MyComboBoxItem Content="1.10.2" />
-                            <local:MyComboBoxItem Content="1.9.4" />
-                            <local:MyComboBoxItem Content="1.8.9" />
-                            <local:MyComboBoxItem Content="1.7.10" />
-                        </local:MyComboBox>
-                        <local:MyComboBox x:Name="ComboSearchLoader" Visibility="Collapsed" Grid.Row="2" Grid.Column="5" MaxDropDownHeight="320" Margin="10,0,0,0">
-                            <local:MyComboBoxItem Content="任意 Mod 加载器" IsSelected="True" Tag="0" />
-                            <local:MyComboBoxItem Content="Forge" Tag="1" />
-                            <local:MyComboBoxItem Content="Fabric" Tag="4" />
-                            <local:MyComboBoxItem Content="Quilt" Tag="5" />
-                        </local:MyComboBox>
                     </Grid>
                     </Grid>
                     <Grid Margin="0,4,0,6" Height="35">
                     <Grid Margin="0,4,0,6" Height="35">
                         <Grid.ColumnDefinitions>
                         <Grid.ColumnDefinitions>

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

@@ -12,13 +12,14 @@
     End Sub
     End Sub
     Private Shared Function LoaderInput() As CompProjectRequest
     Private Shared Function LoaderInput() As CompProjectRequest
         Dim Request As New CompProjectRequest(CompType.Mod, Storage, (Page + 1) * PageSize)
         Dim Request As New CompProjectRequest(CompType.Mod, Storage, (Page + 1) * PageSize)
-        If FrmDownloadMod IsNot Nothing AndAlso FrmDownloadMod.IsLoaded Then
+        If FrmDownloadMod IsNot Nothing Then
             With Request
             With Request
                 .SearchText = FrmDownloadMod.TextSearchName.Text
                 .SearchText = FrmDownloadMod.TextSearchName.Text
                 .GameVersion = If(FrmDownloadMod.TextSearchVersion.Text = "全部 (也可自行输入)", Nothing,
                 .GameVersion = If(FrmDownloadMod.TextSearchVersion.Text = "全部 (也可自行输入)", Nothing,
                     If(FrmDownloadMod.TextSearchVersion.Text.Contains(".") OrElse FrmDownloadMod.TextSearchVersion.Text.Contains("w"), FrmDownloadMod.TextSearchVersion.Text, Nothing))
                     If(FrmDownloadMod.TextSearchVersion.Text.Contains(".") OrElse FrmDownloadMod.TextSearchVersion.Text.Contains("w"), FrmDownloadMod.TextSearchVersion.Text, Nothing))
                 .Tag = FrmDownloadMod.ComboSearchTag.SelectedItem.Tag
                 .Tag = FrmDownloadMod.ComboSearchTag.SelectedItem.Tag
                 .ModLoader = Val(FrmDownloadMod.ComboSearchLoader.SelectedItem.Tag)
                 .ModLoader = Val(FrmDownloadMod.ComboSearchLoader.SelectedItem.Tag)
+                .Source = CType(Val(FrmDownloadMod.ComboSearchSource.SelectedItem.Tag), CompSourceType)
             End With
             End With
         End If
         End If
         Return Request
         Return Request

+ 34 - 28
Plain Craft Launcher 2/Pages/PageDownload/PageDownloadPack.xaml

@@ -10,43 +10,27 @@
                 <StackPanel Margin="25,40,25,15">
                 <StackPanel Margin="25,40,25,15">
                     <Grid Margin="0,0,0,11" HorizontalAlignment="Stretch">
                     <Grid Margin="0,0,0,11" HorizontalAlignment="Stretch">
                         <Grid.ColumnDefinitions>
                         <Grid.ColumnDefinitions>
-                            <ColumnDefinition Width="Auto" />
-                            <ColumnDefinition Width="1*" />
-                            <ColumnDefinition Width="70" />
                             <ColumnDefinition Width="Auto" />
                             <ColumnDefinition Width="Auto" />
                             <ColumnDefinition Width="2.5*" />
                             <ColumnDefinition Width="2.5*" />
+                            <ColumnDefinition Width="50" />
+                            <ColumnDefinition Width="Auto" />
+                            <ColumnDefinition Width="1*" />
                         </Grid.ColumnDefinitions>
                         </Grid.ColumnDefinitions>
                         <Grid.RowDefinitions>
                         <Grid.RowDefinitions>
                             <RowDefinition Height="28" />
                             <RowDefinition Height="28" />
                             <RowDefinition Height="9" />
                             <RowDefinition Height="9" />
                             <RowDefinition Height="28" />
                             <RowDefinition Height="28" />
                         </Grid.RowDefinitions>
                         </Grid.RowDefinitions>
-                        <TextBlock VerticalAlignment="Center" HorizontalAlignment="Left" Text="名称" Margin="0,0,25,0" />
-                        <local:MyTextBox x:Name="TextSearchName" Grid.Column="1" Grid.ColumnSpan="10" HintText="仅支持使用英文搜索" />
-                        <TextBlock VerticalAlignment="Center" Grid.Row="2" HorizontalAlignment="Left" Text="类型" Margin="0,0,25,0" />
-                        <local:MyComboBox x:Name="ComboSearchTag" Grid.Column="1" Grid.Row="2" MaxDropDownHeight="320">
-                            <local:MyComboBoxItem Tag="" Content="全部" IsSelected="True" />
-                            <local:MyComboBoxItem Tag="4484/" Content="多人" />
-                            <local:MyComboBoxItem Tag="/optimization" Content="性能优化" />
-                            <local:MyComboBoxItem Tag="4479/challenging" Content="硬核" />
-                            <local:MyComboBoxItem Tag="4483/combat" Content="战斗" />
-                            <local:MyComboBoxItem Tag="4478/quests" Content="任务" />
-                            <local:MyComboBoxItem Tag="4472/technology" Content="科技" />
-                            <local:MyComboBoxItem Tag="4473/magic" Content="魔法" />
-                            <local:MyComboBoxItem Tag="4475/adventure" Content="冒险" />
-                            <local:MyComboBoxItem Tag="/kitchen-sink" Content="烹饪" />
-                            <local:MyComboBoxItem Tag="4476/" Content="探索" />
-                            <local:MyComboBoxItem Tag="4477/" Content="小游戏" />
-                            <local:MyComboBoxItem Tag="4471/" Content="科幻" />
-                            <local:MyComboBoxItem Tag="4736/" Content="空岛" />
-                            <local:MyComboBoxItem Tag="5128/" Content="原版改良" />
-                            <local:MyComboBoxItem Tag="4487/" Content="FTB" ToolTip="该整合包由 FTB 官方发布" />
-                            <local:MyComboBoxItem Tag="4480/" Content="基于地图" />
-                            <local:MyComboBoxItem Tag="4481/lightweight" Content="轻量整合" />
-                            <local:MyComboBoxItem Tag="4482/" Content="大型整合" />
+                        <TextBlock VerticalAlignment="Center" HorizontalAlignment="Left" Text="名称" Margin="0,0,18,0" />
+                        <local:MyTextBox x:Name="TextSearchName" Grid.Column="1" />
+                        <TextBlock VerticalAlignment="Center" Grid.Column="3" HorizontalAlignment="Left" Text="来源" Margin="0,0,18,0" />
+                        <local:MyComboBox x:Name="ComboSearchSource" Grid.Column="4">
+                            <local:MyComboBoxItem Content="全部" Tag="3" IsSelected="True" />
+                            <local:MyComboBoxItem Content="CurseForge" Tag="1" />
+                            <local:MyComboBoxItem Content="Modrinth" Tag="2" />
                         </local:MyComboBox>
                         </local:MyComboBox>
-                        <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">
+                        <TextBlock VerticalAlignment="Center" Grid.Row="2" HorizontalAlignment="Left" Text="版本" Margin="0,0,18,0" />
+                        <local:MyComboBox x:Name="TextSearchVersion" Grid.Row="2" Grid.Column="1" IsEditable="True" MaxDropDownHeight="320">
                             <local:MyComboBoxItem Content="全部 (也可自行输入)" IsSelected="True" />
                             <local:MyComboBoxItem Content="全部 (也可自行输入)" IsSelected="True" />
                             <local:MyComboBoxItem Content="1.19.4" />
                             <local:MyComboBoxItem Content="1.19.4" />
                             <local:MyComboBoxItem Content="1.19.3" />
                             <local:MyComboBoxItem Content="1.19.3" />
@@ -66,6 +50,28 @@
                             <local:MyComboBoxItem Content="1.8.9" />
                             <local:MyComboBoxItem Content="1.8.9" />
                             <local:MyComboBoxItem Content="1.7.10" />
                             <local:MyComboBoxItem Content="1.7.10" />
                         </local:MyComboBox>
                         </local:MyComboBox>
+                        <TextBlock VerticalAlignment="Center" Grid.Row="2" Grid.Column="3" HorizontalAlignment="Left" Text="类型" Margin="0,0,18,0" />
+                        <local:MyComboBox x:Name="ComboSearchTag" Grid.Column="4" Grid.Row="2" MaxDropDownHeight="320">
+                            <local:MyComboBoxItem Tag="" Content="全部" IsSelected="True" />
+                            <local:MyComboBoxItem Tag="4484/" Content="多人" />
+                            <local:MyComboBoxItem Tag="/optimization" Content="性能优化" />
+                            <local:MyComboBoxItem Tag="4479/challenging" Content="硬核" />
+                            <local:MyComboBoxItem Tag="4483/combat" Content="战斗" />
+                            <local:MyComboBoxItem Tag="4478/quests" Content="任务" />
+                            <local:MyComboBoxItem Tag="4472/technology" Content="科技" />
+                            <local:MyComboBoxItem Tag="4473/magic" Content="魔法" />
+                            <local:MyComboBoxItem Tag="4475/adventure" Content="冒险" />
+                            <local:MyComboBoxItem Tag="/kitchen-sink" Content="烹饪" />
+                            <local:MyComboBoxItem Tag="4476/" Content="探索" />
+                            <local:MyComboBoxItem Tag="4477/" Content="小游戏" />
+                            <local:MyComboBoxItem Tag="4471/" Content="科幻" />
+                            <local:MyComboBoxItem Tag="4736/" Content="空岛" />
+                            <local:MyComboBoxItem Tag="5128/" Content="原版改良" />
+                            <local:MyComboBoxItem Tag="4487/" Content="FTB" ToolTip="该整合包由 FTB 官方发布" />
+                            <local:MyComboBoxItem Tag="4480/" Content="基于地图" />
+                            <local:MyComboBoxItem Tag="4481/lightweight" Content="轻量整合" />
+                            <local:MyComboBoxItem Tag="4482/" Content="大型整合" />
+                        </local:MyComboBox>
                     </Grid>
                     </Grid>
                     <Grid Margin="0,4,0,6" Height="35">
                     <Grid Margin="0,4,0,6" Height="35">
                         <Grid.ColumnDefinitions>
                         <Grid.ColumnDefinitions>

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

@@ -6,18 +6,19 @@
     Public Shared Loader As New LoaderTask(Of CompProjectRequest, Integer)("CompProject ModPack", AddressOf CompProjectsGet, AddressOf LoaderInput) With {.ReloadTimeout = 60 * 1000}
     Public Shared Loader As New LoaderTask(Of CompProjectRequest, Integer)("CompProject ModPack", AddressOf CompProjectsGet, AddressOf LoaderInput) With {.ReloadTimeout = 60 * 1000}
     Public Shared Storage As New CompProjectStorage
     Public Shared Storage As New CompProjectStorage
     Public Shared Page As Integer = 0
     Public Shared Page As Integer = 0
-    Private Sub PageDownloadMod_Inited(sender As Object, e As EventArgs) Handles Me.Initialized
+    Private Sub PageDownloadPack_Inited(sender As Object, e As EventArgs) Handles Me.Initialized
         PageLoaderInit(Load, PanLoad, PanContent, PanAlways, Loader, AddressOf Load_OnFinish, AddressOf LoaderInput)
         PageLoaderInit(Load, PanLoad, PanContent, PanAlways, Loader, AddressOf Load_OnFinish, AddressOf LoaderInput)
         McVersionHighest = Math.Max(McVersionHighest, Integer.Parse(CType(TextSearchVersion.Items(1), MyComboBoxItem).Content.ToString.Split(".")(1)))
         McVersionHighest = Math.Max(McVersionHighest, Integer.Parse(CType(TextSearchVersion.Items(1), MyComboBoxItem).Content.ToString.Split(".")(1)))
     End Sub
     End Sub
     Private Shared Function LoaderInput() As CompProjectRequest
     Private Shared Function LoaderInput() As CompProjectRequest
         Dim Request As New CompProjectRequest(CompType.ModPack, Storage, (Page + 1) * PageSize)
         Dim Request As New CompProjectRequest(CompType.ModPack, Storage, (Page + 1) * PageSize)
-        If FrmDownloadPack IsNot Nothing AndAlso FrmDownloadPack.IsLoaded Then
+        If FrmDownloadPack IsNot Nothing Then
             With Request
             With Request
                 .SearchText = FrmDownloadPack.TextSearchName.Text
                 .SearchText = FrmDownloadPack.TextSearchName.Text
                 .GameVersion = If(FrmDownloadPack.TextSearchVersion.Text = "全部 (也可自行输入)", Nothing,
                 .GameVersion = If(FrmDownloadPack.TextSearchVersion.Text = "全部 (也可自行输入)", Nothing,
                     If(FrmDownloadPack.TextSearchVersion.Text.Contains(".") OrElse FrmDownloadPack.TextSearchVersion.Text.Contains("w"), FrmDownloadPack.TextSearchVersion.Text, Nothing))
                     If(FrmDownloadPack.TextSearchVersion.Text.Contains(".") OrElse FrmDownloadPack.TextSearchVersion.Text.Contains("w"), FrmDownloadPack.TextSearchVersion.Text, Nothing))
                 .Tag = FrmDownloadPack.ComboSearchTag.SelectedItem.Tag
                 .Tag = FrmDownloadPack.ComboSearchTag.SelectedItem.Tag
+                .Source = CType(Val(FrmDownloadPack.ComboSearchSource.SelectedItem.Tag), CompSourceType)
             End With
             End With
         End If
         End If
         Return Request
         Return Request

+ 6 - 10
Plain Craft Launcher 2/Pages/PageSetup/PageSetupLaunch.xaml.vb

@@ -214,7 +214,7 @@
                           If(RamGame <> RamGameActual, " (可用 " & If(RamGameActual = Math.Floor(RamGameActual), RamGameActual & ".0", RamGameActual) & " GB)", "")
                           If(RamGame <> RamGameActual, " (可用 " & If(RamGameActual = Math.Floor(RamGameActual), RamGameActual & ".0", RamGameActual) & " GB)", "")
         LabRamUsed.Text = If(RamUsed = Math.Floor(RamUsed), RamUsed & ".0", RamUsed) & " GB"
         LabRamUsed.Text = If(RamUsed = Math.Floor(RamUsed), RamUsed & ".0", RamUsed) & " GB"
         LabRamTotal.Text = " / " & If(RamTotal = Math.Floor(RamTotal), RamTotal & ".0", RamTotal) & " GB"
         LabRamTotal.Text = " / " & If(RamTotal = Math.Floor(RamTotal), RamTotal & ".0", RamTotal) & " GB"
-        LabRamWarn.Visibility = If(RamGame = 1 AndAlso Not JavaUse64Bit() AndAlso Not Is32BitSystem, Visibility.Visible, Visibility.Collapsed)
+        LabRamWarn.Visibility = If(RamGame = 1 AndAlso Not JavaIs64Bit() AndAlso Not Is32BitSystem, Visibility.Visible, Visibility.Collapsed)
         If ShowAnim Then
         If ShowAnim Then
             '宽度动画
             '宽度动画
             AniStart({
             AniStart({
@@ -413,7 +413,7 @@ PreFin:
             End If
             End If
         End If
         End If
         '若使用 32 位 Java,则限制为 1G
         '若使用 32 位 Java,则限制为 1G
-        If Not JavaUse64Bit(If(UseVersionJavaSetup, Version, Nothing)) Then RamGive = Math.Min(1, RamGive)
+        If Not JavaIs64Bit(If(UseVersionJavaSetup, Version, Nothing)) Then RamGive = Math.Min(1, RamGive)
         Return RamGive
         Return RamGive
     End Function
     End Function
 
 
@@ -487,18 +487,14 @@ PreFin:
             Exit Sub
             Exit Sub
         End If
         End If
         '选择 Java
         '选择 Java
-        Dim JavaSelected As String = SelectFile("javaw.exe|javaw.exe", "选择 javaw.exe 文件")
+        Dim JavaSelected As String = SelectFile("javaw.exe|javaw.exe", "选择 bin 文件夹中的 javaw.exe 文件")
         If JavaSelected = "" Then Exit Sub
         If JavaSelected = "" Then Exit Sub
-        If Not JavaSelected.ToLower.EndsWith("javaw.exe") Then
-            Hint("请选择 bin 文件夹中的 javaw.exe 文件!", HintType.Critical)
-            Exit Sub
-        End If
         JavaSelected = GetPathFromFullPath(JavaSelected)
         JavaSelected = GetPathFromFullPath(JavaSelected)
         Try
         Try
             '验证 Java 可用
             '验证 Java 可用
             Dim NewEntry As New JavaEntry(JavaSelected, True)
             Dim NewEntry As New JavaEntry(JavaSelected, True)
             NewEntry.Check()
             NewEntry.Check()
-            '加入列表并改变选择
+            '加入列表
             Dim JavaNewList As New JArray From {NewEntry.ToJson}
             Dim JavaNewList As New JArray From {NewEntry.ToJson}
             For Each JsonEntry In GetJson(Setup.Get("LaunchArgumentJavaAll"))
             For Each JsonEntry In GetJson(Setup.Get("LaunchArgumentJavaAll"))
                 Dim Entry = JavaEntry.FromJson(JsonEntry)
                 Dim Entry = JavaEntry.FromJson(JsonEntry)
@@ -506,9 +502,9 @@ PreFin:
                 JavaNewList.Add(JsonEntry)
                 JavaNewList.Add(JsonEntry)
             Next
             Next
             Setup.Set("LaunchArgumentJavaAll", JavaNewList.ToString(Newtonsoft.Json.Formatting.None))
             Setup.Set("LaunchArgumentJavaAll", JavaNewList.ToString(Newtonsoft.Json.Formatting.None))
-            Setup.Set("LaunchArgumentJavaSelect", NewEntry.ToJson.ToString(Newtonsoft.Json.Formatting.None)) '加载器会优先选择设置中的 Java
             '重新加载列表
             '重新加载列表
             JavaSearchLoader.Start(IsForceRestart:=True)
             JavaSearchLoader.Start(IsForceRestart:=True)
+            Hint("已将该 Java 加入 Java 列表!", HintType.Finish)
         Catch ex As Exception
         Catch ex As Exception
             Log(ex, "该 Java 存在异常,无法使用", LogLevel.Msgbox, "异常的 Java")
             Log(ex, "该 Java 存在异常,无法使用", LogLevel.Msgbox, "异常的 Java")
             Exit Sub
             Exit Sub
@@ -522,7 +518,7 @@ PreFin:
         End If
         End If
         RunInThread(Sub()
         RunInThread(Sub()
                         Hint("正在搜索 Java!")
                         Hint("正在搜索 Java!")
-                        JavaSearchLoader.WaitForExit(GetUuid)
+                        JavaSearchLoader.WaitForExit(IsForceRestart:=True)
                         If JavaList.Count = 0 Then
                         If JavaList.Count = 0 Then
                             Hint("未找到可用的 Java!", HintType.Critical)
                             Hint("未找到可用的 Java!", HintType.Critical)
                         Else
                         Else

+ 2 - 2
Plain Craft Launcher 2/Pages/PageVersion/PageVersionSetup.xaml.vb

@@ -164,7 +164,7 @@
                           If(RamGame <> RamGameActual, " (可用 " & If(RamGameActual = Math.Floor(RamGameActual), RamGameActual & ".0", RamGameActual) & " GB)", "")
                           If(RamGame <> RamGameActual, " (可用 " & If(RamGameActual = Math.Floor(RamGameActual), RamGameActual & ".0", RamGameActual) & " GB)", "")
         LabRamUsed.Text = If(RamUsed = Math.Floor(RamUsed), RamUsed & ".0", RamUsed) & " GB"
         LabRamUsed.Text = If(RamUsed = Math.Floor(RamUsed), RamUsed & ".0", RamUsed) & " GB"
         LabRamTotal.Text = " / " & If(RamTotal = Math.Floor(RamTotal), RamTotal & ".0", RamTotal) & " GB"
         LabRamTotal.Text = " / " & If(RamTotal = Math.Floor(RamTotal), RamTotal & ".0", RamTotal) & " GB"
-        LabRamWarn.Visibility = If(RamGame = 1 AndAlso Not JavaUse64Bit(PageVersionLeft.Version) AndAlso Not Is32BitSystem, Visibility.Visible, Visibility.Collapsed)
+        LabRamWarn.Visibility = If(RamGame = 1 AndAlso Not JavaIs64Bit(PageVersionLeft.Version) AndAlso Not Is32BitSystem, Visibility.Visible, Visibility.Collapsed)
         If ShowAnim Then
         If ShowAnim Then
             '宽度动画
             '宽度动画
             AniStart({
             AniStart({
@@ -349,7 +349,7 @@ PreFin:
             End If
             End If
         End If
         End If
         '若使用 32 位 Java,则限制为 1G
         '若使用 32 位 Java,则限制为 1G
-        If Not JavaUse64Bit(PageVersionLeft.Version) Then RamGive = Math.Min(1, RamGive)
+        If Not JavaIs64Bit(PageVersionLeft.Version) Then RamGive = Math.Min(1, RamGive)
         Return RamGive
         Return RamGive
     End Function
     End Function
 
 

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

@@ -183,6 +183,7 @@
     <Compile Include="Controls\MyPageRight.vb" />
     <Compile Include="Controls\MyPageRight.vb" />
     <Compile Include="Controls\MyPageLeft.vb" />
     <Compile Include="Controls\MyPageLeft.vb" />
     <Compile Include="Modules\Minecraft\ModComp.vb" />
     <Compile Include="Modules\Minecraft\ModComp.vb" />
+    <Compile Include="Modules\Minecraft\ModJava.vb" />
     <Compile Include="Modules\Minecraft\ModModpack.vb" />
     <Compile Include="Modules\Minecraft\ModModpack.vb" />
     <Compile Include="Modules\ModEvent.vb" />
     <Compile Include="Modules\ModEvent.vb" />
     <Compile Include="Controls\MyExtraButton.xaml.vb">
     <Compile Include="Controls\MyExtraButton.xaml.vb">

+ 0 - 1
Plain Craft Launcher 2/Resources/Custom.xaml

@@ -280,7 +280,6 @@ local:MyCard(卡片):
 local:MyHint(提示条):
 local:MyHint(提示条):
  - Text:设置显示的文本(&#xA; 代表换行)
  - Text:设置显示的文本(&#xA; 代表换行)
  - IsWarn:设置为 True 代表警告样式,False 代表提示样式
  - IsWarn:设置为 True 代表警告样式,False 代表提示样式
- - Foreground:调整前景颜色(十六进制字符串,例如 #FF010203 代表 ARGB 中的 255,1,2,3。前两位代表不透明度,FF 为全不透明,00 为全透明)
  - HorizontalAlignment:设置对齐方式(Left、Center、Right)
  - HorizontalAlignment:设置对齐方式(Left、Center、Right)
 
 
 local:MyButton(按钮):
 local:MyButton(按钮):

File diff suppressed because it is too large
+ 129 - 129
Plain Craft Launcher 2/Resources/ModData.txt


Some files were not shown because too many files changed in this diff