龙腾猫跃 3 سال پیش
والد
کامیت
7cf61bc7cd
31فایلهای تغییر یافته به همراه657 افزوده شده و 349 حذف شده
  1. 19 11
      Plain Craft Launcher 2/Controls/MyTextBox.vb
  2. 4 4
      Plain Craft Launcher 2/FormMain.xaml
  3. 16 1
      Plain Craft Launcher 2/FormMain.xaml.vb
  4. 92 45
      Plain Craft Launcher 2/Modules/Base/ModBase.vb
  5. 125 38
      Plain Craft Launcher 2/Modules/Minecraft/ModComp.vb
  6. 5 5
      Plain Craft Launcher 2/Modules/Minecraft/ModCrash.vb
  7. 2 3
      Plain Craft Launcher 2/Modules/Minecraft/ModDownload.vb
  8. 4 2
      Plain Craft Launcher 2/Modules/Minecraft/ModLaunch.vb
  9. 66 39
      Plain Craft Launcher 2/Modules/Minecraft/ModMinecraft.vb
  10. 61 24
      Plain Craft Launcher 2/Modules/Minecraft/MyCompItem.xaml
  11. 6 0
      Plain Craft Launcher 2/Modules/ModEvent.vb
  12. 2 2
      Plain Craft Launcher 2/My Project/AssemblyInfo.vb
  13. 1 1
      Plain Craft Launcher 2/Pages/PageDownload/PageDownloadCompDetail.xaml
  14. 1 1
      Plain Craft Launcher 2/Pages/PageDownload/PageDownloadCompDetail.xaml.vb
  15. 4 4
      Plain Craft Launcher 2/Pages/PageDownload/PageDownloadInstall.xaml
  16. 1 1
      Plain Craft Launcher 2/Pages/PageDownload/PageDownloadInstall.xaml.vb
  17. 2 0
      Plain Craft Launcher 2/Pages/PageDownload/PageDownloadLeft.xaml.vb
  18. 1 4
      Plain Craft Launcher 2/Pages/PageDownload/PageDownloadMod.xaml
  19. 1 1
      Plain Craft Launcher 2/Pages/PageDownload/PageDownloadMod.xaml.vb
  20. 0 3
      Plain Craft Launcher 2/Pages/PageDownload/PageDownloadPack.xaml
  21. 1 1
      Plain Craft Launcher 2/Pages/PageDownload/PageDownloadPack.xaml.vb
  22. 1 5
      Plain Craft Launcher 2/Pages/PageLaunch/PageLaunchLeft.xaml.vb
  23. 1 1
      Plain Craft Launcher 2/Pages/PageLink/PageLinkHiper.xaml.vb
  24. 2 1
      Plain Craft Launcher 2/Pages/PageSetup/PageSetupLaunch.xaml
  25. 1 1
      Plain Craft Launcher 2/Pages/PageSetup/PageSetupLaunch.xaml.vb
  26. 9 1
      Plain Craft Launcher 2/Pages/PageSetup/PageSetupSystem.xaml
  27. 11 1
      Plain Craft Launcher 2/Pages/PageSetup/PageSetupSystem.xaml.vb
  28. 2 1
      Plain Craft Launcher 2/Pages/PageVersion/PageVersionSetup.xaml
  29. 1 1
      Plain Craft Launcher 2/Pages/PageVersion/PageVersionSetup.xaml.vb
  30. 215 147
      Plain Craft Launcher 2/Resources/Custom.xaml
  31. BIN
      Plain Craft Launcher 2/Resources/Help.zip

+ 19 - 11
Plain Craft Launcher 2/Controls/MyTextBox.vb

@@ -86,15 +86,15 @@
             ValidateResult = ValidateRule.Validate(Text)
             If IsNothing(ValidateResult) OrElse Not ValidateResult = "" Then Exit For
         Next
-        Dim NewResult As Boolean = ValidateResult = ""
+        Dim IsSuccessful As Boolean = ValidateResult = ""
         '根据结果改变样式
-        If ShownValidateResult <> If(NewResult, 0, 1) Then
+        If ShownValidateResult <> If(IsSuccessful, ValidateState.Success, ValidateState.FailedAndShowDetail) Then
             If IsLoaded AndAlso labWrong IsNot Nothing Then
-                ChangeValidateResult(NewResult, True)
+                ChangeValidateResult(IsSuccessful, True)
             Else
                 RunInNewThread(Sub()
                                    Thread.Sleep(30)
-                                   RunInUi(Sub() ChangeValidateResult(NewResult, False))
+                                   RunInUi(Sub() ChangeValidateResult(IsSuccessful, False))
                                End Sub, "DelayedValidate Change")
             End If
         End If
@@ -126,12 +126,12 @@
         IsTextChanged = False
         ChangeValidateResult(ValidateResult = "", True)
     End Sub
-    Private ShownValidateResult As Integer = -1
-    Private Sub ChangeValidateResult(NewResult As Boolean, IsLoaded As Boolean)
+    Private ShownValidateResult As ValidateState = ValidateState.NotInited
+    Private Sub ChangeValidateResult(IsSuccessful As Boolean, IsLoaded As Boolean)
         If IsLoaded AndAlso AniControlEnabled = 0 AndAlso labWrong IsNot Nothing Then
-            If NewResult OrElse Not IsTextChanged Then
+            If IsSuccessful OrElse Not IsTextChanged Then
                 '变为正确
-                ShownValidateResult = 0
+                ShownValidateResult = If(IsSuccessful, ValidateState.Success, ValidateState.FailedButTextNotChanged)
                 AniStart({
                          AaOpacity(labWrong, -labWrong.Opacity, 150),
                          AaHeight(labWrong, -labWrong.Height, 150,, New AniEaseOutFluent),
@@ -139,7 +139,7 @@
                     }, "MyTextBox Validate " & Uuid)
             ElseIf ShowValidateResult Then
                 '变为错误
-                ShownValidateResult = 1
+                ShownValidateResult = ValidateState.FailedAndShowDetail
                 labWrong.Visibility = Visibility.Visible
                 AniStart({
                          AaOpacity(labWrong, 1 - labWrong.Opacity, 170),
@@ -147,14 +147,22 @@
                     }, "MyTextBox Validate " & Uuid)
             Else
                 '变为错误,但不显示文本
-                ShownValidateResult = 2
+                ShownValidateResult = ValidateState.FailedAndHideDetail
             End If
         Else
-            ShownValidateResult = 3
+            ShownValidateResult = ValidateState.NotLoaded
         End If
         RefreshColor()
         RaiseEvent ValidateChanged(Me, New EventArgs)
     End Sub
+    Private Enum ValidateState
+        NotInited
+        Success
+        FailedButTextNotChanged
+        FailedAndShowDetail
+        FailedAndHideDetail
+        NotLoaded
+    End Enum
 
     '提示文本
 

+ 4 - 4
Plain Craft Launcher 2/FormMain.xaml

@@ -4,7 +4,7 @@
         xmlns:local="clr-namespace:PCL"
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"
         x:Name="WindMain" x:Class="FormMain" Style="{StaticResource MyWindow}"
-        AllowDrop="True" Topmost="True" Title="Plain Craft Launcher 2 " AllowsTransparency="True" MinHeight="470" MinWidth="780" ScrollViewer.VerticalScrollBarVisibility="Disabled" Icon="/Plain Craft Launcher 2;component/Images/icon.ico" WindowStyle="None" ResizeMode="CanMinimize" Background="{x:Null}" d:DesignWidth="870" d:DesignHeight="520" Width="850" Height="500" RenderTransformOrigin="0.5,0.5">
+        AllowDrop="True" Topmost="True" Title="Plain Craft Launcher 2 " AllowsTransparency="True" MinHeight="470" MinWidth="810" ScrollViewer.VerticalScrollBarVisibility="Disabled" Icon="/Plain Craft Launcher 2;component/Images/icon.ico" WindowStyle="None" ResizeMode="CanMinimize" Background="{x:Null}" d:DesignWidth="870" d:DesignHeight="520" Width="850" Height="500" RenderTransformOrigin="0.5,0.5">
     <Window.TaskbarItemInfo>
         <TaskbarItemInfo ThumbnailClipMargin="{Binding Margin, ElementName=PanForm}" />
     </Window.TaskbarItemInfo>
@@ -119,13 +119,13 @@
                             <local:MyRadioButton x:Name="BtnTitleSelect0" Text="{DynamicResource LangTitleHome}" Tag="0" Margin="5,0" Checked="True" Padding="2,0"
                                              LogoScale="0.95" Logo="M985.403 552.96C985.403 812.702 773.041 1024 512 1024S38.597 812.702 38.597 552.96c0-158.208 79.163-304.955 211.771-392.625 31.074-20.52 72.94-11.973 93.46 19.101s12.012 72.94-19.062 93.46c-94.681 62.622-151.237 167.306-151.237 280.064 0 185.344 151.788 336.108 338.471 336.108S850.471 738.304 850.471 552.96c0-114.649-57.974-220.278-155.096-282.585-31.35-20.125-40.448-61.833-20.362-93.184s61.794-40.448 93.184-20.4c135.995 87.236 217.206 235.362 217.206 396.169zM512 560.128c37.258 0 67.466-30.208 67.466-67.466V67.466C579.466 30.208 549.258 0 512 0s-67.466 30.208-67.466 67.466v425.196c0 37.258 30.208 67.466 67.466 67.466z" />
                             <local:MyRadioButton x:Name="BtnTitleSelect1" Text="{DynamicResource LangTitleDownload}" Tag="1" Margin="5,0" Padding="2,0"
-                                             LogoScale="0.9" Logo="M955.076923 610.461538h-59.076923c-15.753846 0-29.538462 13.784615-29.538462 29.538462v196.923077c0 15.753846-13.784615 29.538462-29.538461 29.538461h-649.846154c-15.753846 0-29.538462-13.784615-29.538461-29.538461v-196.923077c0-15.753846-13.784615-29.538462-29.538462-29.538462h-59.076923c-15.753846 0-29.538462 13.784615-29.538462 29.538462V905.846154c0 43.323077 35.446154 78.769231 78.769231 78.769231h787.692308c43.323077 0 78.769231-35.446154 78.769231-78.769231V640c0-15.753846-13.784615-29.538462-29.538462-29.538462zM492.307692 740.430769c11.815385 11.815385 29.538462 11.815385 41.353846 0l265.846154-265.846154c11.815385-11.815385 11.815385-29.538462 0-41.353846l-41.353846-41.353846c-11.815385-11.815385-29.538462-11.815385-41.353846 0l-110.276923 110.276923c-11.815385 11.815385-33.476923 3.938462-33.476923-13.784615V68.923077C571.076923 53.169231 555.323077 39.384615 541.538462 39.384615h-59.076924c-15.753846 0-29.538462 13.784615-29.538461 29.538462v417.476923c0 17.723077-21.661538 25.6-33.476923 13.784615l-110.276923-110.276923c-11.815385-11.815385-29.538462-11.815385-41.353846 0L226.461538 433.230769c-11.815385 11.815385-11.815385 29.538462 0 41.353846L492.307692 740.430769z" />
+                                             LogoScale="0.9" Logo="M955 610h-59c-15 0-29 13-29 29v196c0 15-13 29-29 29h-649c-15 0-29-13-29-29v-196c0-15-13-29-29-29h-59c-15 0-29 13-29 29V905c0 43 35 78 78 78h787c43 0 78-35 78-78V640c0-15-13-29-29-29zM492 740c11 11 29 11 41 0l265-265c11-11 11-29 0-41l-41-41c-11-11-29-11-41 0l-110 110c-11 11-33 3-33-13V68C571 53 555 39 541 39h-59c-15 0-29 13-29 29v417c0 17-21 25-33 13l-110-110c-11-11-29-11-41 0L226 433c-11 11-11 29 0 41L492 740z" />
                             <local:MyRadioButton x:Name="BtnTitleSelect2" Text="联机" Tag="2" Margin="5,0" Padding="2,0"
                                              LogoScale="1.05" Logo="M512 817c-48.601 0-88-39.399-88-88s39.399-88 88-88 88 39.399 88 88-39.399 88-88 88zM237.671 565.74C308.335 474.58 397.369 429 504.774 429c118.433 0 214.225 55.421 287.377 166.264l-53.407 30.369c-13.84 7.87-31.362 4.367-41.114-8.219-50.291-64.911-114.577-97.367-192.856-97.367-86.851 0-156.835 40.318-209.95 120.953l-47.995-28.02c-15.263-8.91-20.412-28.507-11.502-43.77a32 32 0 0 1 2.344-3.47zM107.691 419.47C205.24 278.491 337.805 208 505.379 208c178.77 0 317.694 80.224 416.772 240.672l-56.54 31.73c-13.686 7.68-30.922 4.303-40.697-7.975C735.581 360.213 629.07 303.009 505.38 300.815 373.997 298.485 261.637 362.88 168.3 494l-50.116-28.505c-15.362-8.738-20.732-28.275-11.994-43.637a32 32 0 0 1 1.5-2.387z"/>
                             <local:MyRadioButton x:Name="BtnTitleSelect3" Text="{DynamicResource LangTitleSetup}" Tag="3" Margin="5,0" Padding="2,0"
                                              LogoScale="1.1" Logo="M940.4 463.7L773.3 174.2c-17.3-30-49.2-48.4-83.8-48.4H340.2c-34.6 0-66.5 18.5-83.8 48.4L89.2 463.7c-17.3 30-17.3 66.9 0 96.8L256.4 850c17.3 30 49.2 48.4 83.8 48.4h349.2c34.6 0 66.5-18.5 83.8-48.4l167.2-289.5c17.3-29.9 17.3-66.8 0-96.8z m-94.6 96.8L725.9 768.1c-17.3 30-49.2 48.4-83.8 48.4H387.5c-34.6 0-66.5-18.5-83.8-48.4L183.9 560.5c-17.3-30-17.3-66.9 0-96.8l119.8-207.5c17.3-30 49.2-48.4 83.8-48.4h254.6c34.6 0 66.5 18.5 83.8 48.4l119.8 207.5c17.3 30 17.3 66.9 0.1 96.8z M522.3 321.2c-2.5-0.1-5-0.2-7.5-0.2-119.9 0-214 110.3-186.3 235 15.8 70.9 71.5 126.6 142.4 142.4 17.5 3.9 34.7 5.4 51.4 4.7 102.1-3.9 183.6-87.9 183.6-191 0.1-103-81.5-187-183.6-190.9z m68.6 269.1c-18.5 18-43 28.9-68.6 30.7l-6 0.3c-30.2 0.4-58.6-11.4-79.7-33-19.5-20.1-30.7-47-30.9-75-0.3-29.6 11.1-57.4 32-78.3 20.6-20.6 48-32 77.2-32 2.5 0 5 0.1 7.5 0.3 26.7 1.8 51.5 13.2 70.5 32.5 19.6 20 30.8 46.9 31.2 74.9 0.2 30.2-11.5 58.6-33.2 79.6z"/>
                             <local:MyRadioButton x:Name="BtnTitleSelect4" Text="{DynamicResource LangTitleOther}" Tag="4" Margin="5,0" Padding="2,0"
-                                             LogoScale="0.93" Logo="M364.145778 0h-273.066667C40.846222 0 0 40.846222 0 91.022222v273.066667C0 414.264889 40.846222 455.111111 91.136 455.111111h273.066667C414.321778 455.111111 455.111111 414.264889 455.111111 364.032V91.022222C455.111111 40.846222 414.321778 0 364.145778 0zM341.333333 341.333333H113.777778V113.777778h227.555555v227.555555zM933.034667 0h-273.066667C609.792 0 568.888889 40.846222 568.888889 91.022222v273.066667c0 50.176 40.903111 91.022222 91.136 91.022222h273.066667C983.210667 455.111111 1024 414.264889 1024 364.032V91.022222c0-50.176-40.789333-91.022222-90.965333-91.022222zM910.222222 341.333333h-227.555555V113.777778h227.555555v227.555555zM364.145778 568.888889h-273.066667C40.846222 568.888889 0 609.735111 0 659.911111v273.066667c0 50.176 40.846222 91.022222 91.136 91.022222h273.066667C414.321778 1024 455.111111 983.153778 455.111111 932.920889v-273.066667C455.111111 609.735111 414.321778 568.888889 364.145778 568.888889zM341.333333 910.222222H113.777778v-227.555555h227.555555v227.555555zM933.034667 568.888889h-273.066667c-50.176 0-91.079111 40.846222-91.079111 91.022222v273.066667c0 50.176 40.903111 91.022222 91.136 91.022222h273.066667c50.119111 0 90.908444-40.846222 90.908444-91.079111v-273.066667c0-50.119111-40.789333-90.965333-90.965333-90.965333zM910.222222 910.222222h-227.555555v-227.555555h227.555555v227.555555z"/>
+                                             LogoScale="0.93" Logo="M364 0h-273C40 0 0 40 0 91v273C0 414 40 455 91 455h273C414 455 455 414 455 364V91C455 40 414 0 364 0zM341 341H113V113h227v227zM933 0h-273C609 0 568 40 568 91v273c0 50 40 91 91 91h273C983 455 1024 414 1024 364V91c0-50-40-91-90-91zM910 341h-227V113h227v227zM364 568h-273C40 568 0 609 0 659v273c0 50 40 91 91 91h273C414 1024 455 983 455 932v-273C455 609 414 568 364 568zM341 910H113v-227h227v227zM933 568h-273c-50 0-91 40-91 91v273c0 50 40 91 91 91h273c50 0 90-40 90-91v-273c0-50-40-90-90-90zM910 910h-227v-227h227v227z"/>
                         </StackPanel>
                     </Grid>
                     <Grid x:Name="PanTitleInner" Visibility="Collapsed" Margin="-16,0,0,0" Opacity="0" HorizontalAlignment="Left" Width="{Binding ActualWidth, ElementName=PanTitle, Mode=OneWay}">
@@ -168,7 +168,7 @@
                     <local:MyExtraButton x:Name="BtnExtraBack" HorizontalAlignment="Right" VerticalAlignment="Center" ToolTip="返回顶部" Visibility="Collapsed"
                                        Logo="M858.496 188.9024 173.1072 188.9024c-30.2848 0-54.8352-24.5504-54.8352-54.8352L118.272 106.6496c0-30.2848 24.5504-54.8352 54.8352-54.8352l685.3888 0c30.2848 0 54.8352 24.5504 54.8352 54.8352l0 27.4176C913.3312 164.352 888.7808 188.9024 858.496 188.9024L858.496 188.9024zM150.6048 550.8608c0 0 300.0064-240.3584 303.0272-243.328 13.9776-13.5936 31.1808-21.8624 48.8192-24.7552 1.7152-0.3072 3.4304-0.5888 5.1456-0.768 2.7392-0.3072 5.4528-0.3584 8.192-0.3328 2.7392-0.0256 5.4272 0.0256 8.1664 0.3328 1.7408 0.1792 3.4304 0.4864 5.1456 0.768 17.664 2.8928 34.8672 11.1616 48.8192 24.7552 3.0464 2.944 303.0016 243.328 303.0016 243.328 32.384 31.5136 29.6192 63.9744-2.7392 95.5136-32.3328 31.5392-75.648 2.9696-108.0064-28.544l-185.8816-147.1232 0 485.8368c0 30.3104-24.5248 54.8608-54.8352 54.8608l-27.392 0c-30.2848 0-54.8352-24.5504-54.8352-54.8608L447.232 470.7072l-185.8304 147.0976c-32.3584 31.5392-75.6992 60.1344-108.032 28.5696C121.0368 614.8352 118.272 582.3744 150.6048 550.8608L150.6048 550.8608zM150.6048 550.8608" />
                     <local:MyExtraButton x:Name="BtnExtraDownload" HorizontalAlignment="Right" VerticalAlignment="Center" ToolTip="下载管理" Visibility="Collapsed"
-                                       Logo="M955.076923 610.461538h-59.076923c-15.753846 0-29.538462 13.784615-29.538462 29.538462v196.923077c0 15.753846-13.784615 29.538462-29.538461 29.538461h-649.846154c-15.753846 0-29.538462-13.784615-29.538461-29.538461v-196.923077c0-15.753846-13.784615-29.538462-29.538462-29.538462h-59.076923c-15.753846 0-29.538462 13.784615-29.538462 29.538462V905.846154c0 43.323077 35.446154 78.769231 78.769231 78.769231h787.692308c43.323077 0 78.769231-35.446154 78.769231-78.769231V640c0-15.753846-13.784615-29.538462-29.538462-29.538462zM492.307692 740.430769c11.815385 11.815385 29.538462 11.815385 41.353846 0l265.846154-265.846154c11.815385-11.815385 11.815385-29.538462 0-41.353846l-41.353846-41.353846c-11.815385-11.815385-29.538462-11.815385-41.353846 0l-110.276923 110.276923c-11.815385 11.815385-33.476923 3.938462-33.476923-13.784615V68.923077C571.076923 53.169231 555.323077 39.384615 541.538462 39.384615h-59.076924c-15.753846 0-29.538462 13.784615-29.538461 29.538462v417.476923c0 17.723077-21.661538 25.6-33.476923 13.784615l-110.276923-110.276923c-11.815385-11.815385-29.538462-11.815385-41.353846 0L226.461538 433.230769c-11.815385 11.815385-11.815385 29.538462 0 41.353846L492.307692 740.430769z" />
+                                       Logo="M955 610h-59c-15 0-29 13-29 29v196c0 15-13 29-29 29h-649c-15 0-29-13-29-29v-196c0-15-13-29-29-29h-59c-15 0-29 13-29 29V905c0 43 35 78 78 78h787c43 0 78-35 78-78V640c0-15-13-29-29-29zM492 740c11 11 29 11 41 0l265-265c11-11 11-29 0-41l-41-41c-11-11-29-11-41 0l-110 110c-11 11-33 3-33-13V68C571 53 555 39 541 39h-59c-15 0-29 13-29 29v417c0 17-21 25-33 13l-110-110c-11-11-29-11-41 0L226 433c-11 11-11 29 0 41L492 740z" />
                     <local:MyExtraButton x:Name="BtnExtraApril" HorizontalAlignment="Right" VerticalAlignment="Center" ToolTip="投降" Visibility="Collapsed"
                                        Logo="M124.96 32c-28.64 0-60.064 23.2-60.064 51.904v856.192c0 28.576 30.688 51.904 59.296 51.904s60.064-23.328 60.064-51.904V83.904C184.256 55.2 153.536 32 124.96 32z m616.352 71.264c-168.416 0-168.416-69.024-336.8-69.024-97.216 0-172.256 45.344-172.256 45.344l-0.736 516.736s75.776-45.28 172.96-45.28c168.416 0 168.416 69.024 336.8 69.024 105.344 0 211.168-55.328 211.168-55.328V48.064c0.032 0-105.792 55.2-211.136 55.2z m0 0" />
                     <local:MyExtraButton x:Name="BtnExtraShutdown" HorizontalAlignment="Right" VerticalAlignment="Center" ToolTip="关闭 Minecraft" Visibility="Collapsed"

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

@@ -10,10 +10,19 @@ Public Class FormMain
         Dim FeatureList As New List(Of KeyValuePair(Of Integer, String))
         '统计更新日志条目
 #If BETA Then
+        If LastVersion < 286 Then 'Release 2.5.2
+            FeatureList.Add(New KeyValuePair(Of Integer, String)(5, "支持搜索、安装 Modrinth 的 Mod 与整合包"))
+            FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "资源搜索页面支持翻页"))
+            FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "在全局启动设置中添加了 启动前执行命令 选项"))
+            FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "重做资源下载的资源项界面"))
+            FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "在选择下载 Fabric 时会自动选择 Fabric API"))
+            FeatureCount += 35
+            BugCount += 36
+        End If
         If LastVersion < 281 Then 'Release 2.4.9
+            If LastVersion = 279 Then FeatureList.Add(New KeyValuePair(Of Integer, String)(1, "修复进入 Mod、整合包下载页时报错的 Bug"))
             FeatureCount += 1
             BugCount += 5
-            If LastVersion = 279 Then FeatureList.Add(New KeyValuePair(Of Integer, String)(1, "修复进入 Mod、整合包下载页时报错的 Bug"))
         End If
         If LastVersion < 279 Then 'Release 2.4.8
             FeatureCount += 1
@@ -126,6 +135,12 @@ Public Class FormMain
         '3:BUG+ IMP* FEAT-
         '2:BUG* IMP-
         '1:BUG-
+        If LastVersion < 285 Then 'Snapshot 2.5.2
+            FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "重做资源下载的资源项界面"))
+            If LastVersion = 284 Then FeatureList.Add(New KeyValuePair(Of Integer, String)(1, "修复打开部分帮助报错的 Bug"))
+            FeatureCount += 8
+            BugCount += 8
+        End If
         If LastVersion < 284 Then 'Snapshot 2.5.1
             If LastVersion >= 275 Then FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "在全局启动设置中添加了 启动前执行命令 选项"))
             FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "在选择下载 Fabric 时会自动选择 Fabric API"))

+ 92 - 45
Plain Craft Launcher 2/Modules/Base/ModBase.vb

@@ -1,5 +1,6 @@
 Imports System.IO.Compression
 Imports System.Management
+Imports System.Runtime.CompilerServices
 Imports System.Security.Cryptography
 Imports System.Security.Principal
 Imports System.Windows.Markup
@@ -10,12 +11,12 @@ Public Module ModBase
 #Region "声明"
 
     '下列版本信息由更新器自动修改
-    Public Const VersionBaseName As String = "2.5.1" '不含分支前缀的显示用版本名
-    Public Const VersionStandardCode As String = "2.5.1." & VersionBranchCode '标准格式的四段式版本号
+    Public Const VersionBaseName As String = "2.5.2" '不含分支前缀的显示用版本名
+    Public Const VersionStandardCode As String = "2.5.2." & VersionBranchCode '标准格式的四段式版本号
 #If BETA Then
-    Public Const VersionCode As Integer = 281 'Release
+    Public Const VersionCode As Integer = 286 'Release
 #Else
-    Public Const VersionCode As Integer = 284 'Snapshot
+    Public Const VersionCode As Integer = 285 'Snapshot
 #End If
     '自动生成的版本信息
     Public Const VersionDisplayName As String = VersionBranchName & " " & VersionBaseName
@@ -1487,15 +1488,29 @@ Re:
     ''' <summary>
     ''' 连接字符串。
     ''' </summary>
-    Public Function Join(List As ICollection, Split As String) As String
+    <Extension> Public Function Join(List As IEnumerable, Split As String) As String
         Dim Builder As New StringBuilder
-        Dim LastCount As Integer = List.Count - 1
-        For i = 0 To LastCount
-            If List(i) IsNot Nothing Then Builder.Append(List(i))
-            If i <> LastCount Then Builder.Append(Split)
+        Dim IsFirst As Boolean = True
+        For Each Element In List
+            If IsFirst Then
+                IsFirst = False
+            Else
+                Builder.Append(Split)
+            End If
+            If Element IsNot Nothing Then Builder.Append(Element)
         Next
         Return Builder.ToString
     End Function
+    ''' <summary>
+    ''' 分割字符串。
+    ''' </summary>
+    <Extension> Public Function Split(FullStr As String, SplitStr As String) As String()
+        If SplitStr.Length = 1 Then
+            Return FullStr.Split(SplitStr(0))
+        Else
+            Return FullStr.Split({SplitStr}, StringSplitOptions.None)
+        End If
+    End Function
 
     ''' <summary>
     ''' 获取字符串哈希值。
@@ -1785,46 +1800,71 @@ NextElement:
     ''' <summary>
     ''' 将时间间隔转换为类似“5 分 10 秒前”的易于阅读的形式。
     ''' </summary>
-    Public Function GetTimeSpanString(Span As TimeSpan) As String
+    Public Function GetTimeSpanString(Span As TimeSpan, IsShortForm As Boolean) As String
         Dim EndFix = If(Span.TotalMilliseconds > 0, "后", "前")
         If Span.TotalMilliseconds < 0 Then Span = -Span
         Dim TotalMonthes = Math.Floor(Span.Days / 30)
-        If TotalMonthes >= 61 Then
-            '5+ 年,“5 年”
-            GetTimeSpanString = Math.Floor(TotalMonthes / 12) & " 年"
-        ElseIf TotalMonthes >= 12 Then
-            '12~60 月,“1 年 2 个月”
-            GetTimeSpanString = Math.Floor(TotalMonthes / 12) & " 年" & If((TotalMonthes Mod 12) > 0, " " & (TotalMonthes Mod 12) & " 个月", "")
-        ElseIf TotalMonthes >= 4 Then
-            '4~11 月,“5 月”
-            GetTimeSpanString = TotalMonthes & " 月"
-        ElseIf TotalMonthes >= 1 Then
-            '1~4 月,“2 月 13 天”
-            GetTimeSpanString = TotalMonthes & " 月" & If((Span.Days Mod 30) > 0, " " & (Span.Days Mod 30) & " 天", "")
-        ElseIf Span.TotalDays >= 4 Then
-            '4~30 天,“23 天”
-            GetTimeSpanString = Span.Days & " 天"
-        ElseIf Span.TotalDays >= 1 Then
-            '1~3 天,“2 天 20 小时”
-            GetTimeSpanString = Span.Days & " 天" & If(Span.Hours > 0, " " & Span.Hours & " 小时", "")
-        ElseIf Span.TotalHours >= 10 Then
-            '10 小时 ~ 1 天,“15 小时”
-            GetTimeSpanString = Span.Hours & " 小时"
-        ElseIf Span.TotalHours >= 1 Then
-            '1~10 小时,“1 小时 20 分钟”
-            GetTimeSpanString = Span.Hours & " 小时" & If(Span.Minutes > 0, " " & Span.Minutes & " 分钟", "")
-        ElseIf Span.TotalMinutes >= 10 Then
-            '10 分钟 ~ 1 小时,“49 分钟”
-            GetTimeSpanString = Span.Minutes & " 分钟"
-        ElseIf Span.TotalMinutes >= 1 Then
-            '1~10 分钟,“9 分 23 秒”
-            GetTimeSpanString = Span.Minutes & " 分" & If(Span.Seconds > 0, " " & Span.Seconds & " 秒", "")
-        ElseIf Span.TotalSeconds >= 1 Then
-            '1 秒 ~ 1 分钟,“23 秒”
-            GetTimeSpanString = Span.Seconds & " 秒"
+        If IsShortForm Then
+            If TotalMonthes >= 12 Then
+                '1+ 年,“3 年”
+                GetTimeSpanString = Math.Floor(TotalMonthes / 12) & " 年"
+            ElseIf TotalMonthes >= 2 Then
+                '2~11 月,“5 个月”
+                GetTimeSpanString = TotalMonthes & " 个月"
+            ElseIf Span.TotalDays >= 2 Then
+                '2 天 ~ 2 月,“23 天”
+                GetTimeSpanString = Span.Days & " 天"
+            ElseIf Span.TotalHours >= 1 Then
+                '1 小时 ~ 2 天,“15 小时”
+                GetTimeSpanString = Span.Hours & " 小时"
+            ElseIf Span.TotalMinutes >= 1 Then
+                '1 分钟 ~ 1 小时,“49 分钟”
+                GetTimeSpanString = Span.Minutes & " 分钟"
+            ElseIf Span.TotalSeconds >= 1 Then
+                '1 秒 ~ 1 分钟,“23 秒”
+                GetTimeSpanString = Span.Seconds & " 秒"
+            Else
+                '不到 1 秒
+                GetTimeSpanString = "1 秒"
+            End If
         Else
-            '不到 1 秒
-            GetTimeSpanString = "1 秒"
+            If TotalMonthes >= 61 Then
+                '5+ 年,“5 年”
+                GetTimeSpanString = Math.Floor(TotalMonthes / 12) & " 年"
+            ElseIf TotalMonthes >= 12 Then
+                '12~60 月,“1 年 2 个月”
+                GetTimeSpanString = Math.Floor(TotalMonthes / 12) & " 年" & If((TotalMonthes Mod 12) > 0, " " & (TotalMonthes Mod 12) & " 个月", "")
+            ElseIf TotalMonthes >= 4 Then
+                '4~11 月,“5 月”
+                GetTimeSpanString = TotalMonthes & " 月"
+            ElseIf TotalMonthes >= 1 Then
+                '1~4 月,“2 月 13 天”
+                GetTimeSpanString = TotalMonthes & " 月" & If((Span.Days Mod 30) > 0, " " & (Span.Days Mod 30) & " 天", "")
+            ElseIf Span.TotalDays >= 4 Then
+                '4~30 天,“23 天”
+                GetTimeSpanString = Span.Days & " 天"
+            ElseIf Span.TotalDays >= 1 Then
+                '1~3 天,“2 天 20 小时”
+                GetTimeSpanString = Span.Days & " 天" & If(Span.Hours > 0, " " & Span.Hours & " 小时", "")
+            ElseIf Span.TotalHours >= 10 Then
+                '10 小时 ~ 1 天,“15 小时”
+                GetTimeSpanString = Span.Hours & " 小时"
+            ElseIf Span.TotalHours >= 1 Then
+                '1~10 小时,“1 小时 20 分钟”
+                GetTimeSpanString = Span.Hours & " 小时" & If(Span.Minutes > 0, " " & Span.Minutes & " 分钟", "")
+            ElseIf Span.TotalMinutes >= 10 Then
+                '10 分钟 ~ 1 小时,“49 分钟”
+                GetTimeSpanString = Span.Minutes & " 分钟"
+            ElseIf Span.TotalMinutes >= 1 Then
+                '1~10 分钟,“9 分 23 秒”
+                GetTimeSpanString = Span.Minutes & " 分" & If(Span.Seconds > 0, " " & Span.Seconds & " 秒", "")
+            ElseIf Span.TotalSeconds >= 1 Then
+                '1 秒 ~ 1 分钟,“23 秒”
+                GetTimeSpanString = Span.Seconds & " 秒"
+            Else
+                '不到 1 秒
+                GetTimeSpanString = "1 秒"
+            End If
         End If
         GetTimeSpanString += EndFix
     End Function
@@ -1998,6 +2038,13 @@ NextElement:
     End Function
     Public Delegate Function CompareThreadStart(Of T)(Left As T, Right As T) As Boolean
 
+    ''' <summary>
+    ''' 返回列表的浅表副本。
+    ''' </summary>
+    <Extension> Public Function Clone(Of T)(list As IList(Of T)) As IList(Of T)
+        Return New List(Of T)(list)
+    End Function
+
     ''' <summary>
     ''' 获取程序启动参数。
     ''' </summary>

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

@@ -257,14 +257,14 @@
                         Case 406 : Tags.Add("世界元素")
                         Case 407 : Tags.Add("生物群系")
                         Case 410 : Tags.Add("维度")
-                        Case 408 : Tags.Add("矿物和资源")
+                        Case 408 : Tags.Add("矿物/资源")
                         Case 409 : Tags.Add("天然结构")
                         Case 412 : Tags.Add("科技")
-                        Case 415 : Tags.Add("管道与物流")
+                        Case 415 : Tags.Add("管道/物流")
                         Case 4843 : Tags.Add("自动化")
                         Case 417 : Tags.Add("能源")
                         Case 4558 : Tags.Add("红石")
-                        Case 436 : Tags.Add("食物与烹饪")
+                        Case 436 : Tags.Add("食物/烹饪")
                         Case 416 : Tags.Add("农业")
                         Case 414 : Tags.Add("运输")
                         Case 420 : Tags.Add("仓储")
@@ -274,7 +274,7 @@
                         Case 411 : Tags.Add("生物")
                         Case 434 : Tags.Add("装备")
                         Case 423 : Tags.Add("信息显示")
-                        Case 435 : Tags.Add("多人")
+                        Case 435 : Tags.Add("服务器")
                         Case 5191 : Tags.Add("改良")
                         Case 421 : Tags.Add("支持库")
                         '整合包
@@ -292,8 +292,8 @@
                         Case 5128 : Tags.Add("原版改良")
                         Case 4487 : Tags.Add("FTB")
                         Case 4480 : Tags.Add("基于地图")
-                        Case 4481 : Tags.Add("轻量整合")
-                        Case 4482 : Tags.Add("大型整合")
+                        Case 4481 : Tags.Add("轻量")
+                        Case 4482 : Tags.Add("大型")
                             'FUTURE: Res
                     End Select
                 Next
@@ -321,7 +321,7 @@
                 Website = $"https://modrinth.com/{Data("project_type")}/{Slug}"
                 'GameVersions
                 GameVersions = If(CType(Data("versions"), JArray), New JArray).
-                                   Select(Function(v) v.ToString).Where(Function(v) v.Contains("1.")).
+                                   Select(Function(v) v.ToString).Where(Function(v) v.StartsWith("1.")).
                                    Select(Of Integer)(Function(v) Val(v.Split(".")(1).Split("-").First)).Where(Function(v) v > 0).
                                    Distinct.OrderByDescending(Function(v) v).ToList
                 'Type
@@ -342,7 +342,7 @@
                         'Mod
                         Case "worldgen" : Tags.Add("世界元素")
                         Case "technology" : Tags.Add("科技")
-                        Case "food" : Tags.Add("食物与烹饪")
+                        Case "food" : Tags.Add("食物/烹饪")
                         Case "game-mechanics" : Tags.Add("游戏机制")
                         Case "transportation" : Tags.Add("运输")
                         Case "storage" : Tags.Add("仓储")
@@ -352,7 +352,7 @@
                         Case "mobs" : Tags.Add("生物")
                         Case "equipment" : Tags.Add("装备")
                         Case "optimization" : Tags.Add("性能优化")
-                        Case "social" : Tags.Add("多人")
+                        Case "social" : Tags.Add("服务器")
                         Case "utility" : Tags.Add("改良")
                         Case "library" : Tags.Add("支持库")
                         '整合包
@@ -365,7 +365,7 @@
                         Case "magic" : Tags.Add("魔法")
                         Case "adventure" : Tags.Add("冒险")
                         Case "kitchen-sink" : Tags.Add("烹饪")
-                        Case "lightweight" : Tags.Add("轻量整合")
+                        Case "lightweight" : Tags.Add("轻量")
                             'FUTURE: Res
                     End Select
                 Next
@@ -409,17 +409,93 @@
                         SpaVersions.Add("1." & StartVersion & "~1." & EndVersion)
                     End If
                 Next
-                GameVersionDescription = "[" & Join(SpaVersions, ", ") & "] "
+                GameVersionDescription = SpaVersions.Join(", ")
             End If
             '实例化 UI
             Dim NewItem As New MyCompItem With {.Tag = Me}
-            NewItem.LabTitle.Text = TranslatedName
+            '标题
+            Dim FinalName As String = TranslatedName.Split(" | ").First.Split(" - ").First.Split(" (").First.Split(" [").First
+            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
+NoExName:
+                CType(NewItem.LabTitleRaw.Parent, StackPanel).Children.Remove(NewItem.LabTitleRaw)
+            Else
+                Dim ExName As String = ""
+                For Each Ex In ExNameList
+                    '去除 “Forge/Fabric” 一类的无意义提示
+                    If Ex.Length < 19 AndAlso Ex.ToLower.Contains("fabric") AndAlso Ex.ToLower.Contains("forge") Then Continue For
+                    '将 “Forge” 等提示改为 “Forge 版”
+                    If (Ex.ToLower.Contains("forge") OrElse Ex.ToLower.Contains("fabric") OrElse Ex.ToLower.Contains("quilt")) AndAlso
+                       Not Ex.Contains("版") AndAlso Ex.Length < 19 Then Ex = Ex.Replace("Edition", "").Trim & " 版"
+                    ExName &= "  |  " & Ex.Trim
+                Next
+                If ExName = "" Then GoTo NoExName
+                NewItem.LabTitleRaw.Text = ExName
+            End If
+            'Tag
+            For Each TagText In Tags
+                Dim NewTag = GetObjectFromXML(
+                "<Border xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation""
+                         Background=""#11000000"" Padding=""3,1"" CornerRadius=""3"" Margin=""0,0,3,0"" 
+                         SnapsToDevicePixels=""True"" UseLayoutRounding=""False"">
+                   <TextBlock Text=""" & TagText & """ Foreground=""#868686"" FontSize=""11"" />
+                </Border>")
+                NewItem.PanTags.Children.Add(NewTag)
+            Next
+            '下边栏
+            If Not ShowMcVersionDesc AndAlso Not ShowLoaderDesc Then
+                '全部隐藏
+                CType(NewItem.PathVersion.Parent, Grid).Children.Remove(NewItem.PathVersion)
+                CType(NewItem.LabVersion.Parent, Grid).Children.Remove(NewItem.LabVersion)
+                NewItem.ColumnVersionMargin.Width = New GridLength(0)
+            ElseIf ShowMcVersionDesc AndAlso ShowMcVersionDesc Then
+                '全部显示
+                Dim ModLoaderDesc As String = If(ModLoaders.Count > 0 AndAlso ModLoaders.Count < 3 AndAlso
+                        Not (Type = CompType.Mod AndAlso Setup.Get("ToolDownloadIgnoreQuilt") AndAlso ModLoaders.Contains(CompModLoaderType.Forge) AndAlso ModLoaders.Contains(CompModLoaderType.Fabric)),
+                        ModLoaders.Join(" / ") & " ", "")
+                Dim VersionDesc As String = If(GameVersionDescription = "1.7+", "全版本", GameVersionDescription)
+                NewItem.LabVersion.Text = ModLoaderDesc & VersionDesc
+            ElseIf ShowMcVersionDesc Then
+                '仅显示版本
+                NewItem.LabVersion.Text = If(GameVersionDescription = "1.7+", "全版本", GameVersionDescription)
+            Else
+                '仅显示 Mod 加载器
+                Select Case ModLoaders.Count
+                    Case 0
+                        NewItem.LabVersion.Text = "未知"
+                    Case 1
+                        NewItem.LabVersion.Text = If(Type = CompType.Mod, "仅 ", "") & ModLoaders(0).ToString
+                    Case 2
+                        If Type = CompType.Mod Then
+                            NewItem.LabVersion.Text =
+                                If(Not (Setup.Get("ToolDownloadIgnoreQuilt") AndAlso
+                                ModLoaders.Contains(CompModLoaderType.Forge) AndAlso ModLoaders.Contains(CompModLoaderType.Fabric)),
+                                ModLoaders.Join(" / "), "任意")
+                        Else
+                            NewItem.LabVersion.Text = ModLoaders.Join(" / ")
+                        End If
+                    Case 3
+                        If Type = CompType.Mod Then
+                            NewItem.LabVersion.Text = "任意"
+                        Else
+                            NewItem.LabVersion.Text = ModLoaders.Join(" / ")
+                        End If
+                End Select
+            End If
             NewItem.LabInfo.Text = Description.Replace(vbCr, "").Replace(vbLf, "")
-            NewItem.LabLeft.Text = (If(ModLoaders.Count > 0 AndAlso ShowLoaderDesc, "[" & Join(ModLoaders.Select(Function(m) GetStringFromEnum(m)).ToList, "/") & "] ", "") &
-                                   If(ShowMcVersionDesc, GameVersionDescription, "")).Replace("] [", " ") &
-                                   If(FromCurseForge, "[CurseForge] ", "[Modrinth] ") &
-                                   Join(Tags, ",") &
-                                   If(LastUpdate IsNot Nothing, " (" & GetTimeSpanString(LastUpdate - Date.Now) & "更新)", "")
+            NewItem.LabSource.Text = If(FromCurseForge, "CurseForge", "Modrinth")
+            If LastUpdate IsNot Nothing Then
+                NewItem.LabTime.Text = GetTimeSpanString(LastUpdate - Date.Now, True)
+            End If
+            NewItem.LabDownload.Text =
+                If(DownloadCount > 100000000, Math.Round(DownloadCount / 100000000, 2) & " 亿",
+                    If(DownloadCount > 100000, Math.Floor(DownloadCount / 10000) & " 万", DownloadCount))
+            '其他
             If LogoUrl Is Nothing Then
                 NewItem.Logo = "pack://application:,,,/images/Icons/NoIcon.png"
             Else
@@ -551,7 +627,7 @@
             If Tag.StartsWith("/") Then Storage.CurseForgeTotal = 0
             If Storage.CurseForgeTotal > -1 AndAlso Storage.CurseForgeTotal <= Storage.CurseForgeOffset Then Return Nothing
             '应用筛选参数
-            Dim Address As String = $"https://api.curseforge.com/v1/mods/search?gameId=432&sortField=Featured&sortOrder=desc&pageSize={CompPageSize}"
+            Dim Address As String = $"https://api.curseforge.com/v1/mods/search?gameId=432&sortField=2&sortOrder=desc&pageSize={CompPageSize}"
             Select Case Type
                 Case CompType.Mod
                     Address += "&classId=6"
@@ -633,13 +709,18 @@
     ''' 根据搜索请求获取一系列的工程列表。需要基于加载器运行。
     ''' </summary>
     Public Sub CompProjectsGet(Task As LoaderTask(Of CompProjectRequest, Integer))
+        Dim Storage = Task.Input.Storage '避免多线程问题
 
         If Task.Input.Storage.Results.Count >= Task.Input.TargetResultCount Then
             Log($"[Comp] 已有 {Task.Input.Storage.Results.Count} 个结果,多于所需的 {Task.Input.TargetResultCount} 个结果,结束处理")
             Exit Sub
         ElseIf Not Task.Input.CanContinue Then
-            Log($"[Comp] 已有 {Task.Input.Storage.Results.Count} 个结果,少于所需的 {Task.Input.TargetResultCount} 个结果,但无法继续获取,结束处理")
-            Exit Sub
+            If Task.Input.Storage.Results.Count = 0 Then
+                Throw New Exception("没有符合条件的结果")
+            Else
+                Log($"[Comp] 已有 {Task.Input.Storage.Results.Count} 个结果,少于所需的 {Task.Input.TargetResultCount} 个结果,但无法继续获取,结束处理")
+                Exit Sub
+            End If
         End If
 
 #Region "拒绝 1.13- Quilt(这个版本根本没有 Quilt)"
@@ -658,9 +739,8 @@
         Log("[Comp] 工程列表搜索原始文本:" & RawFilter)
 
         '中文请求关键字处理
-        Dim IsChineseSearch As Boolean = RegexCheck(RawFilter, "[\u4e00-\u9fbb]")
-        If IsChineseSearch AndAlso Not String.IsNullOrEmpty(RawFilter) Then
-            If Task.Input.Type <> CompType.Mod Then Throw New Exception($"{If(Task.Input.Type = CompType.ModPack, "整合包", "资源包")}搜索仅支持英文")
+        Dim IsChineseSearch As Boolean = RegexCheck(RawFilter, "[\u4e00-\u9fbb]") AndAlso Not String.IsNullOrEmpty(RawFilter)
+        If IsChineseSearch AndAlso Task.Input.Type = CompType.Mod Then
             '构造搜索请求
             Dim SearchEntries As New List(Of SearchEntry(Of CompDatabaseEntry))
             For Each Entry In CompDatabase
@@ -680,7 +760,7 @@
                 If Not SearchResults(i).AbsoluteRight AndAlso i >= Math.Min(2, SearchResults.Count - 1) Then Exit For '把 3 个结果拼合以提高准确度
                 If SearchResults(i).Item.CurseForgeSlug IsNot Nothing Then SearchResult += SearchResults(i).Item.CurseForgeSlug.Replace("-", " ") & " "
                 If SearchResults(i).Item.ModrinthSlug IsNot Nothing Then SearchResult += SearchResults(i).Item.ModrinthSlug.Replace("-", " ") & " "
-                SearchResult += SearchResults(i).Item.ChineseName.Replace(" (", "|").Split("|").Last.TrimEnd(") ").Replace(" - ", "§").Split("§").First.
+                SearchResult += SearchResults(i).Item.ChineseName.Split(" (").Last.TrimEnd(") ").Split(" - ").First.
                     Replace(":", "").Replace("(", "").Replace(")", "").ToLower & " "
             Next
             Log("[Comp] 中文搜索原始关键词:" & SearchResult, LogLevel.Developer)
@@ -728,13 +808,13 @@
         Dim RealResults As New List(Of CompProject)
 Retry:
         Dim RawResults As New List(Of CompProject)
+        Dim [Error] As Exception = Nothing
 
 #Region "从 CurseForge 和 Modrinth 获取结果列表,存储于 RawResults"
 
         Dim CurseForgeThread As Thread = Nothing
         Dim ModrinthThread As Thread = Nothing
         Dim ResultsLock As New Object
-        Dim [Error] As Exception = Nothing
 
         Try
 
@@ -756,11 +836,12 @@ Retry:
                             SyncLock ResultsLock
                                 RawResults.AddRange(ProjectList)
                             End SyncLock
-                            Task.Input.Storage.CurseForgeOffset += ProjectList.Count
-                            Task.Input.Storage.CurseForgeTotal = RequestResult("pagination")("totalCount").ToObject(Of Integer)
-                            Log($"[Comp] 从 CurseForge 获取到了 {ProjectList.Count} 个工程(已获取 {Task.Input.Storage.CurseForgeOffset} 个,共 {Task.Input.Storage.CurseForgeTotal} 个)")
+                            Storage.CurseForgeOffset += ProjectList.Count
+                            Storage.CurseForgeTotal = RequestResult("pagination")("totalCount").ToObject(Of Integer)
+                            Log($"[Comp] 从 CurseForge 获取到了 {ProjectList.Count} 个工程(已获取 {Storage.CurseForgeOffset} 个,共 {Storage.CurseForgeTotal} 个)")
                         Catch ex As Exception
                             Log(ex, "从 CurseForge 获取工程列表失败")
+                            Storage.CurseForgeTotal = Storage.CurseForgeOffset
                             [Error] = ex
                         End Try
                     End Sub, "CurseForge Project Request")
@@ -783,11 +864,12 @@ Retry:
                             SyncLock ResultsLock
                                 RawResults.AddRange(ProjectList)
                             End SyncLock
-                            Task.Input.Storage.ModrinthOffset += ProjectList.Count
-                            Task.Input.Storage.ModrinthTotal = RequestResult("total_hits").ToObject(Of Integer)
-                            Log($"[Comp] 从 Modrinth 获取到了 {ProjectList.Count} 个工程(已获取 {Task.Input.Storage.ModrinthOffset} 个,共 {Task.Input.Storage.ModrinthTotal} 个)")
+                            Storage.ModrinthOffset += ProjectList.Count
+                            Storage.ModrinthTotal = RequestResult("total_hits").ToObject(Of Integer)
+                            Log($"[Comp] 从 Modrinth 获取到了 {ProjectList.Count} 个工程(已获取 {Storage.ModrinthOffset} 个,共 {Storage.ModrinthTotal} 个)")
                         Catch ex As Exception
                             Log(ex, "从 Modrinth 获取工程列表失败")
+                            Storage.ModrinthTotal = Storage.ModrinthOffset
                             [Error] = ex
                         End Try
                     End Sub, "Modrinth Project Request")
@@ -797,13 +879,18 @@ Retry:
             If CurseForgeThread IsNot Nothing Then CurseForgeThread.Join()
             If Task.IsAborted Then Exit Sub '会自动触发 Finally
             If ModrinthThread IsNot Nothing Then ModrinthThread.Join()
+            If Task.IsAborted Then Exit Sub
 
             '确认存在结果
             If RawResults.Count = 0 Then
                 If [Error] IsNot Nothing Then
                     Throw [Error]
                 Else
-                    Throw New Exception("没有符合条件的结果")
+                    If IsChineseSearch AndAlso Task.Input.Type <> CompType.Mod Then
+                        Throw New Exception($"{If(Task.Input.Type = CompType.ModPack, "整合包", "资源包")}搜索仅支持英文")
+                    Else
+                        Throw New Exception("没有符合条件的结果")
+                    End If
                 End If
             End If
 
@@ -823,7 +910,7 @@ Retry:
         RawResults = Distinct(RawResults, Function(a, b) a.IsLike(b))
         '已有内容去重
         RawResults = RawResults.Where(Function(r) Not RealResults.Any(Function(b) r.IsLike(b)) AndAlso
-                                                  Not Task.Input.Storage.Results.Any(Function(b) r.IsLike(b))).ToList
+                                                  Not Storage.Results.Any(Function(b) r.IsLike(b))).ToList
         '加入列表
         RealResults.AddRange(RawResults)
         Log($"[Comp] 去重后累计新增结果 {RealResults.Count} 个")
@@ -832,8 +919,8 @@ Retry:
 
 #Region "检查结果数量,如果不足且可继续,会继续加载下一页"
 
-        If RealResults.Count + Task.Input.Storage.Results.Count < Task.Input.TargetResultCount Then
-            Log($"[Comp] 总结果数需求最少 {Task.Input.TargetResultCount} 个,仅获得了 {RealResults.Count + Task.Input.Storage.Results.Count} 个")
+        If RealResults.Count + Storage.Results.Count < Task.Input.TargetResultCount Then
+            Log($"[Comp] 总结果数需求最少 {Task.Input.TargetResultCount} 个,仅获得了 {RealResults.Count + Storage.Results.Count} 个")
             If Task.Input.CanContinue Then
                 Log("[Comp] 将继续尝试加载下一页")
                 GoTo Retry
@@ -869,7 +956,7 @@ Retry:
             Next
         End If
         '根据排序分得出结果并添加
-        Task.Input.Storage.Results.AddRange(
+        Storage.Results.AddRange(
             Sort(Scores.ToList, Function(a, b) a.Value > b.Value).Select(Function(r) r.Key).ToList)
 
 #End Region
@@ -1094,7 +1181,7 @@ Retry:
             If DownloadCount > 0 Then 'CurseForge 的下载次数经常错误地返回 0
                 Info += If(DownloadCount > 100000, Math.Round(DownloadCount / 10000) & " 万次下载,", DownloadCount & " 次下载,")
             End If
-            Info += GetTimeSpanString(ReleaseDate - Date.Now) & "更新"
+            Info += GetTimeSpanString(ReleaseDate - Date.Now, False) & "更新"
             Info += If(Status = CompFileStatus.Release, "", "," & StatusDescription)
 
             '建立控件
@@ -1224,7 +1311,7 @@ Retry:
         Stack.Children.Add(New TextBlock With {.Text = "前置 Mod", .FontSize = 14, .HorizontalAlignment = HorizontalAlignment.Left, .Margin = New Thickness(6, 2, 0, 5)})
         '添加前置 Mod 列表
         For Each Dep In Deps
-            Dim Item = CompProjectCache(Dep).ToCompItem(False, True, AddressOf FrmDownloadMod.ProjectClick)
+            Dim Item = CompProjectCache(Dep).ToCompItem(True, True, AddressOf FrmDownloadMod.ProjectClick)
             Stack.Children.Add(Item)
         Next
         '添加结尾间隔

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

@@ -86,9 +86,9 @@
         For Each FilePath In RightLogs
             Try
                 If FilePath.Contains("crash-") Then
-                    AnalyzeRawFiles.Add(New KeyValuePair(Of String, String())(FilePath, ReadFile(FilePath).Replace(vbCrLf, vbCr).Replace(vbLf, vbCr).Split(vbCr)))
+                    AnalyzeRawFiles.Add(New KeyValuePair(Of String, String())(FilePath, ReadFile(FilePath).Split(vbCrLf.ToCharArray)))
                 Else
-                    AnalyzeRawFiles.Add(New KeyValuePair(Of String, String())(FilePath, ReadFile(FilePath, Encoding.UTF8).Replace(vbCrLf, vbCr).Replace(vbLf, vbCr).Split(vbCr)))
+                    AnalyzeRawFiles.Add(New KeyValuePair(Of String, String())(FilePath, ReadFile(FilePath, Encoding.UTF8).Split(vbCrLf.ToCharArray)))
                 End If
             Catch ex As Exception
                 Log(ex, "读取可能的崩溃日志文件失败(" & FilePath & ")")
@@ -133,9 +133,9 @@
                 Dim Ext As String = TargetFile.Extension.ToLower
                 If Ext = ".log" OrElse Ext = ".txt" Then
                     If TargetFile.Name.StartsWith("crash-") Then
-                        AnalyzeRawFiles.Add(New KeyValuePair(Of String, String())(TargetFile.FullName, ReadFile(TargetFile.FullName).Replace(vbCrLf, vbCr).Replace(vbLf, vbCr).Split(vbCr)))
+                        AnalyzeRawFiles.Add(New KeyValuePair(Of String, String())(TargetFile.FullName, ReadFile(TargetFile.FullName).Split(vbCrLf.ToCharArray)))
                     Else
-                        AnalyzeRawFiles.Add(New KeyValuePair(Of String, String())(TargetFile.FullName, ReadFile(TargetFile.FullName, Encoding.UTF8).Replace(vbCrLf, vbCr).Replace(vbLf, vbCr).Split(vbCr)))
+                        AnalyzeRawFiles.Add(New KeyValuePair(Of String, String())(TargetFile.FullName, ReadFile(TargetFile.FullName, Encoding.UTF8).Split(vbCrLf.ToCharArray)))
                     End If
                 End If
             Catch ex As Exception
@@ -377,7 +377,7 @@
             '来源崩溃日志的分析
             If LogCrash IsNot Nothing Then
                 Log("[Crash] 开始进行崩溃日志堆栈分析")
-                Dim StackLogs As String = LogCrash.Replace("System Details", "¨").Split("¨").First
+                Dim StackLogs As String = LogCrash.Split("System Details").First
                 Dim Keywords = AnalyzeStackKeyword(StackLogs)
                 If Keywords.Count > 0 Then
                     Dim Names = AnalyzeModName(Keywords)

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

@@ -622,7 +622,7 @@
         Dim Versions As New List(Of DlForgeVersionEntry)
         Try
             '分割版本信息
-            Dim VersionCodes = Mid(Result, 1, Result.LastIndexOf("</table>")).Replace("<td class=""download-version", "¨").Split("¨")
+            Dim VersionCodes = Mid(Result, 1, Result.LastIndexOf("</table>")).Split("<td class=""download-version")
             '获取所有版本信息
             For i = 1 To VersionCodes.Count - 1
                 Dim VersionCode = VersionCodes(i)
@@ -632,8 +632,7 @@
                     Dim IsRecommended As Boolean = VersionCode.Contains("fa promo-recommended")
                     Dim Inherit As String = Loader.Input
                     '分支获取
-                    Dim Branch As String = RegexSeek(VersionCode, "(?<=Branch:</strong>[\s]*)[^<]+")
-                    Branch = RegexSeek(If(Branch, ""), "[^\s]+")
+                    Dim Branch As String = RegexSeek(VersionCode, $"(?<=-{Name}-)[^-""]+(?=-[a-z]+.[a-z]{{3}})")
                     If String.IsNullOrWhiteSpace(Branch) Then Branch = Nothing
                     If Name = "11.15.1.2318" OrElse Name = "11.15.1.1902" OrElse Name = "11.15.1.1890" Then Branch = "1.8.9"
                     If Branch Is Nothing AndAlso Inherit = "1.7.10" AndAlso Name.Split(".")(3) >= 1300 Then Branch = "1.7.10"

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

@@ -1830,14 +1830,16 @@ NextVersion:
                         Else
                             PackFormat = 9
                         End If
-                    Case 19, 99 '99 是快照版
+                    Case 19
                         If McVersionCurrent.Version.McCodeSub <= 3 Then
                             PackFormat = 10
                         Else
                             PackFormat = 12
                         End If
-                    Case Else
+                    Case 20, 99 '99 是快照版
                         PackFormat = 13
+                    Case Else
+                        PackFormat = 14
                         'https://minecraft.fandom.com/zh/wiki/数据包#数据包版本
                 End Select
                 McLaunchLog("正在构建自定义皮肤资源包,格式为:" & PackFormat)

+ 66 - 39
Plain Craft Launcher 2/Modules/Minecraft/ModMinecraft.vb

@@ -441,10 +441,51 @@ Wait:
                 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")
+                Log("[Java] 检查后找到 " & TargetJavaList.Count & " 个特定的 Java")
             End If
 
 RetryGet:
@@ -477,38 +518,7 @@ RetryGet:
                 GoTo RetryGet
             End If
 
-#Region "检查用户指定的 Java"
-
-            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
+#Region "检查用户指定的 Java 是否可用"
 
             '确保指定的 Java 可用
             If UserJava Is Nothing Then GoTo ExitUserJavaCheck
@@ -569,7 +579,7 @@ ExitUserJavaCheck:
                 If TargetJavaList.Contains(Java) Then
                     '直接使用指定的 Java
                     AllowedJavaList = New List(Of JavaEntry) From {Java}
-                    Log("[Java] 优先使用特定目录下的 Java:" & Java.ToString)
+                    Log("[Java] 优先使用特定的 Java:" & Java.ToString)
                     GoTo UserPass
                 End If
             Next
@@ -2569,9 +2579,26 @@ NextVersion:
         '统一通行证文件
         If Setup.Get("VersionServerLogin", Version:=Version) = 3 Then
             Dim TargetFile = PathAppdata & "nide8auth.jar"
-            Dim Checker As New FileChecker(MinSize:=173000)
-            If (IsSetupSkip AndAlso File.Exists(TargetFile)) OrElse Checker.Check(TargetFile) IsNot Nothing Then
-                Result.Add(New NetFile({"https://login.mc-user.com:233/index/jar"}, TargetFile, Checker))
+            If Not (IsSetupSkip AndAlso File.Exists(TargetFile)) Then
+                Dim DownloadInfo As JObject = Nothing
+                '获取下载信息
+                Try
+                    Log("[Minecraft] 开始获取统一通行证下载信息")
+                    '测试链接:https://auth.mc-user.com:233/00000000000000000000000000000000/
+                    DownloadInfo = GetJson(NetGetCodeByDownload({
+                        "https://auth.mc-user.com:233/" & Setup.Get("VersionServerNide", Version:=Version)}, IsJson:=True))
+                Catch ex As Exception
+                    Log(ex, "获取统一通行证下载信息失败")
+                End Try
+                '校验文件
+                If DownloadInfo IsNot Nothing Then
+                    Dim Checker As New FileChecker(Hash:=DownloadInfo("jarHash").ToString)
+                    If (IsSetupSkip AndAlso File.Exists(TargetFile)) OrElse Checker.Check(TargetFile) IsNot Nothing Then
+                        '开始下载
+                        Log("[Minecraft] 统一通行证需要更新:Hash - " & Checker.Hash, LogLevel.Developer)
+                        Result.Add(New NetFile({"https://login.mc-user.com:233/index/jar"}, TargetFile, Checker))
+                    End If
+                End If
             End If
         End If
         'Authlib-Injector 文件
@@ -2593,7 +2620,7 @@ NextVersion:
                     If (IsSetupSkip AndAlso File.Exists(TargetFile)) OrElse Checker.Check(TargetFile) IsNot Nothing Then
                         '开始下载
                         Dim DownloadAddress As String = DownloadInfo("download_url")
-                        Log("[Minecraft] Authlib-Injector 需要更新:" & DownloadAddress)
+                        Log("[Minecraft] Authlib-Injector 需要更新:" & DownloadAddress, LogLevel.Developer)
                         Result.Add(New NetFile({
                                 DownloadAddress.Replace("bmclapi2.bangbang93.com", "download.mcbbs.net"), DownloadAddress
                             }, TargetFile, New FileChecker(Hash:=DownloadInfo("checksums")("sha256").ToString)))
@@ -3756,7 +3783,7 @@ VersionFindFail:
             If Version Is Nothing Then Exit Sub
             Dim Time As Date = Version("releaseTime")
             Dim MsgBoxText As String = $"新版本:{VersionName}{vbCrLf}" &
-                If((Date.Now - Time).TotalDays > 1, "更新时间:" & Time.ToString, "更新于:" & GetTimeSpanString(Time - Date.Now))
+                If((Date.Now - Time).TotalDays > 1, "更新时间:" & Time.ToString, "更新于:" & GetTimeSpanString(Time - Date.Now, False))
             Dim MsgResult = MyMsgBox(MsgBoxText, "Minecraft 更新提示", "确定", "下载", If((Date.Now - Time).TotalHours > 3, "更新日志", ""),
                 Button3Action:=Sub() McUpdateLogShow(Version))
             '弹窗结果

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

@@ -1,45 +1,82 @@
 <Grid x:Class="MyCompItem"
              xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
              xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
-             x:Name="PanBack" Height="59"
+             x:Name="PanBack" Height="64"
              RenderTransformOrigin="0.5,0.5" Background="{StaticResource ColorBrushSemiTransparent}" SnapsToDevicePixels="True">
     <Grid.ColumnDefinitions>
         <ColumnDefinition Width="7" />
+        <ColumnDefinition Width="50" />
+        <ColumnDefinition Width="8" />
         <ColumnDefinition Width="Auto" />
-        <ColumnDefinition Width="9" />
-        <ColumnDefinition Width="1*"/>
-        <ColumnDefinition Width="Auto"/>
-        <ColumnDefinition Width="7" />
+        <ColumnDefinition Width="1*" />
     </Grid.ColumnDefinitions>
     <Grid.RowDefinitions>
         <RowDefinition Height="1*" />
         <RowDefinition Height="17" />
-        <RowDefinition Height="14" />
-        <RowDefinition Height="14" />
-        <RowDefinition Height="1*" />
+        <RowDefinition Height="18" />
+        <RowDefinition Height="16" />
+        <RowDefinition Height="1.1*" />
     </Grid.RowDefinitions>
-    <!--<Rectangle Height="45" Width="45" RadiusX="4" RadiusY="4" Fill="White" Grid.Column="1" Grid.Row="1" IsHitTestVisible="False" SnapsToDevicePixels="True" UseLayoutRounding="False" Grid.RowSpan="3" />-->
-    <Border Height="45" Width="45" Grid.Column="1" Grid.Row="1" IsHitTestVisible="False" SnapsToDevicePixels="True" UseLayoutRounding="True" Grid.RowSpan="3">
+    <!-- Logo -->
+    <Border Grid.Column="1" Grid.Row="1" Grid.RowSpan="3" IsHitTestVisible="False" SnapsToDevicePixels="True" UseLayoutRounding="True" 
+                                HorizontalAlignment="Right" VerticalAlignment="Center" Width="50" Height="50">
         <Border.Clip>
-            <RectangleGeometry Rect="0,0,45,45" RadiusX="6" RadiusY="6" />
+            <RectangleGeometry Rect="0,0,50,50" RadiusX="6" RadiusY="6" />
         </Border.Clip>
         <Image x:Name="PathLogo" RenderOptions.BitmapScalingMode="HighQuality" />
     </Border>
-    <TextBlock x:Name="LabTitle" Grid.Row="1" Grid.Column="3" Grid.ColumnSpan="2" IsHitTestVisible="False" SnapsToDevicePixels="False" UseLayoutRounding="False" 
-               Margin="0,0,0,1" HorizontalAlignment="Left" VerticalAlignment="Center" TextTrimming="CharacterEllipsis" 
-               FontSize="14" Foreground="{StaticResource ColorBrush1}" />
-    <TextBlock x:Name="LabLeft" Grid.Row="2" Grid.Column="3" IsHitTestVisible="False" SnapsToDevicePixels="False" UseLayoutRounding="False" 
-               HorizontalAlignment="Left" VerticalAlignment="Center" TextTrimming="CharacterEllipsis"
-               FontSize="12" Foreground="{StaticResource ColorBrushGray3}" />
-    <!--<TextBlock x:Name="LabRight" Grid.Row="2" Grid.Column="4" IsHitTestVisible="False" SnapsToDevicePixels="False" UseLayoutRounding="False" 
-               HorizontalAlignment="Right" VerticalAlignment="Center" TextTrimming="CharacterEllipsis" 
-               FontSize="12" Foreground="{StaticResource ColorBrushGray3}" />-->
-    <TextBlock x:Name="LabInfo" Grid.Row="3" Grid.Column="3" Grid.ColumnSpan="2" IsHitTestVisible="True" SnapsToDevicePixels="False" UseLayoutRounding="False" 
-               HorizontalAlignment="Left" VerticalAlignment="Center" TextTrimming="CharacterEllipsis" 
-               FontSize="12" Foreground="{StaticResource ColorBrushGray3}"
-               ToolTipService.InitialShowDelay="80" ToolTipService.Placement="Relative" ToolTipService.PlacementRectangle="-8,-6,500,10000">
+    <!-- 标题 -->
+    <StackPanel Grid.Column="3" Grid.ColumnSpan="2" Grid.Row="1" VerticalAlignment="Bottom" Margin="0,1,0,0" Orientation="Horizontal" 
+                IsHitTestVisible="False" SnapsToDevicePixels="False" UseLayoutRounding="False">
+        <TextBlock x:Name="LabTitle" TextTrimming="WordEllipsis" FontSize="14" Foreground="{DynamicResource ColorBrush1}" />
+        <TextBlock x:Name="LabTitleRaw" TextTrimming="WordEllipsis" FontSize="12" Foreground="{StaticResource ColorBrushGray1}" Opacity="0.4" VerticalAlignment="Bottom" />
+    </StackPanel>
+    <!-- Tag 与 详情 -->
+    <StackPanel x:Name="PanTags" Grid.Row="2" Grid.Column="3" Orientation="Horizontal" VerticalAlignment="Bottom" Margin="-1,0,0,0">
+        <!--<Border Background="{DynamicResource ColorBrush6}" Padding="3,1" CornerRadius="3" Margin="0,0,4,0" SnapsToDevicePixels="True" UseLayoutRounding="False">
+            <TextBlock Text="科技" Foreground="{DynamicResource ColorBrush2}" FontSize="11" />
+        </Border>-->
+    </StackPanel>
+    <TextBlock x:Name="LabInfo" Grid.Row="2" Grid.Column="4" VerticalAlignment="Bottom" Margin="1,0,3,0.5"
+               TextTrimming="CharacterEllipsis" FontSize="12" Foreground="{StaticResource ColorBrushGray3}"
+               IsHitTestVisible="True" SnapsToDevicePixels="False" UseLayoutRounding="False" 
+               ToolTipService.InitialShowDelay="150" ToolTipService.Placement="Relative" ToolTipService.PlacementRectangle="-8,-6,500,10000">
         <TextBlock.ToolTip>
             <ToolTip x:Name="ToolTipInfo" Style="{StaticResource ExtendTextToolTip}" />
         </TextBlock.ToolTip>
     </TextBlock>
+    <!-- 下边栏 -->
+    <Grid Grid.Row="3" Grid.Column="3" Grid.ColumnSpan="2" VerticalAlignment="Bottom"
+          IsHitTestVisible="False" SnapsToDevicePixels="False" UseLayoutRounding="False">
+        <Grid.ColumnDefinitions>
+            <ColumnDefinition Width="Auto" />
+            <ColumnDefinition Width="Auto" SharedSizeGroup="CompItemVersion" />
+            <ColumnDefinition Width="0.7*" x:Name="ColumnVersionMargin" />
+            
+            <ColumnDefinition Width="Auto" />
+            <ColumnDefinition Width="55" />
+            <ColumnDefinition Width="1*" />
+
+            <ColumnDefinition Width="Auto" />
+            <ColumnDefinition Width="Auto" MinWidth="57" SharedSizeGroup="CompItemTime" />
+            <ColumnDefinition Width="1*" />
+
+            <ColumnDefinition Width="Auto" />
+            <ColumnDefinition Width="Auto" SharedSizeGroup="CompItemSource" />
+            <ColumnDefinition Width="1.7*" />
+        </Grid.ColumnDefinitions>
+        <Path x:Name="PathVersion" Grid.Column="0" Fill="{StaticResource ColorBrushGray3}" Stretch="Uniform" Height="11"
+              Data="M940.4 463.7L773.3 174.2c-17.3-30-49.2-48.4-83.8-48.4H340.2c-34.6 0-66.5 18.5-83.8 48.4L89.2 463.7c-17.3 30-17.3 66.9 0 96.8L256.4 850c17.3 30 49.2 48.4 83.8 48.4h349.2c34.6 0 66.5-18.5 83.8-48.4l167.2-289.5c17.3-29.9 17.3-66.8 0-96.8z m-94.6 96.8L725.9 768.1c-17.3 30-49.2 48.4-83.8 48.4H387.5c-34.6 0-66.5-18.5-83.8-48.4L183.9 560.5c-17.3-30-17.3-66.9 0-96.8l119.8-207.5c17.3-30 49.2-48.4 83.8-48.4h254.6c34.6 0 66.5 18.5 83.8 48.4l119.8 207.5c17.3 30 17.3 66.9 0.1 96.8z M522.3 321.2c-2.5-0.1-5-0.2-7.5-0.2-119.9 0-214 110.3-186.3 235 15.8 70.9 71.5 126.6 142.4 142.4 17.5 3.9 34.7 5.4 51.4 4.7 102.1-3.9 183.6-87.9 183.6-191 0.1-103-81.5-187-183.6-190.9z m68.6 269.1c-18.5 18-43 28.9-68.6 30.7l-6 0.3c-30.2 0.4-58.6-11.4-79.7-33-19.5-20.1-30.7-47-30.9-75-0.3-29.6 11.1-57.4 32-78.3 20.6-20.6 48-32 77.2-32 2.5 0 5 0.1 7.5 0.3 26.7 1.8 51.5 13.2 70.5 32.5 19.6 20 30.8 46.9 31.2 74.9 0.2 30.2-11.5 58.6-33.2 79.6z" />
+        <TextBlock x:Name="LabVersion" Grid.Column="1" Margin="4,0,2,0" VerticalAlignment="Center" Foreground="{StaticResource ColorBrushGray3}" FontSize="12" 
+                   TextTrimming="WordEllipsis" />
+        <Path x:Name="PathDownload" Grid.Column="3" Fill="{StaticResource ColorBrushGray4}" Stretch="Uniform" Height="10.5"
+              Data="M955 610h-59c-15 0-29 13-29 29v196c0 15-13 29-29 29h-649c-15 0-29-13-29-29v-196c0-15-13-29-29-29h-59c-15 0-29 13-29 29V905c0 43 35 78 78 78h787c43 0 78-35 78-78V640c0-15-13-29-29-29zM492 740c11 11 29 11 41 0l265-265c11-11 11-29 0-41l-41-41c-11-11-29-11-41 0l-110 110c-11 11-33 3-33-13V68C571 53 555 39 541 39h-59c-15 0-29 13-29 29v417c0 17-21 25-33 13l-110-110c-11-11-29-11-41 0L226 433c-11 11-11 29 0 41L492 740z" />
+        <TextBlock x:Name="LabDownload" Grid.Column="4" Margin="5,0,2,0" VerticalAlignment="Center" Foreground="{StaticResource ColorBrushGray4}" FontSize="12" />
+        <Path x:Name="PathTime" Grid.Column="6" Fill="{StaticResource ColorBrushGray4}" Stretch="Uniform" Height="11.5" Margin="0,0,1,0"
+              Data="M810 403l-39 39c-10 10-28 10-39 0l-162-162v412c0 15-12 28-28 28h-56c-15 0-28-12-28-28v-412l-162 162c-10 10-28 10-39 0l-39-39c-10-10-10-28 0-39l278-278c10-10 28-10 39 0l278 278c10 10 10 28-0 39zM568 946h-112v-112h112v112z" />
+        <TextBlock x:Name="LabTime" Grid.Column="7" Margin="5,0,2,0" VerticalAlignment="Center" Foreground="{StaticResource ColorBrushGray4}" FontSize="12" />
+        <Path x:Name="PathSource" Grid.Column="9" Fill="{StaticResource ColorBrushGray4}" Stretch="Uniform" Height="11.5"
+              Data="M511 143c-203 0-369 165-369 369 0 203 165 369 369 369s369-165 369-369c0-203-165-369-369-369z m0 673c-29 0-68-59-89-159l178 0c-20 100-59 159-89 159z m-98-224c-2-24-3-51-3-79 0-29 1-57 4-83l197 0c2 25 4 53 4 83 0 28-1 54-3 79l-198-0z m98-383c29 0 67 58 88 156l-177-0c20-98 59-155 88-155z m164 221l128 0c7 26 11 54 11 82 0 27-3 54-10 80l-129-0c2-26 3-52 3-79 0-28-1-56-4-83z m101-64l-110-0c-7-37-16-72-28-102-4-11-9-22-15-33 66 25 121 74 155 135z m-376-135c-5 10-10 21-15 33-12 30-21 64-28 102l-110-0c34-60 89-109 154-134z m-181 199l128 0c-2 27-3 54-3 83 0 27 1 53 3 79l-127-0v6c-8-27-12-55-12-85-0-29 3-57 11-83z m24 227l112 0c7 38 16 74 29 105 4 11 9 22 15 33-67-26-122-76-156-139zM621 795c5-10 10-21 15-33 12-30 22-66 29-105l111 0c-34 62-89 111-156 137z" />
+        <TextBlock x:Name="LabSource" Grid.Column="10" Margin="5,0,2,0" VerticalAlignment="Center" Foreground="{StaticResource ColorBrushGray4}" FontSize="12" />
+    </Grid>
 </Grid>

+ 6 - 0
Plain Craft Launcher 2/Modules/ModEvent.vb

@@ -58,6 +58,12 @@
                 Case "刷新帮助"
                     PageOtherLeft.RefreshHelp()
 
+                Case "今日人品"
+                    PageOtherTest.Jrrp()
+
+                Case "清理垃圾"
+                    PageOtherTest.RubbishClear()
+
                 Case "弹出窗口"
                     MyMsgBox(Data(1).Replace("\n", vbCrLf), Data(0).Replace("\n", vbCrLf))
 

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

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

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

@@ -12,7 +12,7 @@
                 <RowDefinition Height="Auto" />
             </Grid.RowDefinitions>
             <local:MyCard Margin="0,0,0,25" x:Name="CardIntro">
-                <StackPanel Margin="22,22,22,19" x:Name="PanIntro">
+                <StackPanel Margin="22,18,22,19" x:Name="PanIntro">
                     <StackPanel Orientation="Horizontal" Height="35">
                         <local:MyButton x:Name="BtnIntroWeb"   MinWidth="140" Text="转到 CurseForge" Padding="13,0" Margin="0,0,20,0" HorizontalAlignment="Left" ColorType="Highlight" />
                         <local:MyButton x:Name="BtnIntroWiki"  MinWidth="140" Text="转到 MC 百科" Padding="13,0" Margin="0,0,20,0" HorizontalAlignment="Left" />

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

@@ -273,7 +273,7 @@
                 End If
                 '获取基本信息
                 Dim ChineseName As String = If(Project.TranslatedName = Project.RawName, "",
-                    Project.TranslatedName.Replace(" (", "Å").Split("Å").First.Replace("\", "\").Replace("/", "/").Replace("|", "|").Replace(":", ":").Replace("<", "<").Replace(">", ">").Replace("*", "*").Replace("?", "?").Replace("""", "").Replace(": ", ":"))
+                    Project.TranslatedName.Split(" (").First.Replace("\", "\").Replace("/", "/").Replace("|", "|").Replace(":", ":").Replace("<", "<").Replace(">", ">").Replace("*", "*").Replace("?", "?").Replace("""", "").Replace(": ", ":"))
                 Dim FileName As String
                 Select Case Setup.Get("ToolDownloadTranslate")
                     Case 0

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

@@ -7,11 +7,11 @@
     <Grid>
         <local:MyScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled" x:Name="PanBack">
             <Grid Margin="25,10,25,25">
-                <VirtualizingStackPanel Grid.Row="1" VirtualizingStackPanel.IsVirtualizing="True" VirtualizingStackPanel.VirtualizationMode="Recycling" Name="PanMinecraft" Grid.IsSharedSizeScope="True">
-                    <VirtualizingStackPanel.RenderTransform>
+                <StackPanel Grid.Row="1" Name="PanMinecraft" Grid.IsSharedSizeScope="True">
+                    <StackPanel.RenderTransform>
                         <TranslateTransform />
-                    </VirtualizingStackPanel.RenderTransform>
-                </VirtualizingStackPanel>
+                    </StackPanel.RenderTransform>
+                </StackPanel>
                 <StackPanel Grid.Row="1" x:Name="PanSelect" Visibility="Collapsed" Opacity="0" IsHitTestVisible="False">
                     <StackPanel.RenderTransform>
                         <TranslateTransform X="40" />

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

@@ -1079,7 +1079,7 @@
 
 #Region "安装"
 
-    Private Sub TextSelectName_KeyUp(sender As Object, e As KeyEventArgs) Handles TextSelectName.KeyUp
+    Private Sub TextSelectName_KeyDown(sender As Object, e As KeyEventArgs) Handles TextSelectName.KeyDown
         If e.Key = Key.Enter AndAlso BtnSelectStart.IsEnabled Then BtnSelectStart_Click()
     End Sub
     Private Sub BtnSelectStart_Click() Handles BtnSelectStart.Click

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

@@ -98,10 +98,12 @@
                 ItemInstall.Checked = True
             Case FormMain.PageSubType.DownloadMod
                 PageDownloadMod.Storage = New CompProjectStorage
+                PageDownloadMod.Page = 0
                 If FrmDownloadMod IsNot Nothing Then FrmDownloadMod.PageLoaderRestart()
                 ItemMod.Checked = True
             Case FormMain.PageSubType.DownloadPack
                 PageDownloadPack.Storage = New CompProjectStorage
+                PageDownloadPack.Page = 0
                 If FrmDownloadPack IsNot Nothing Then FrmDownloadPack.PageLoaderRestart()
                 ItemPack.Checked = True
             Case FormMain.PageSubType.DownloadClient

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

@@ -49,7 +49,7 @@
                             <local:MyComboBoxItem Content="装备与工具" Tag="434/equipment" />
                             <local:MyComboBoxItem Content="性能优化" Tag="/optimization" />
                             <local:MyComboBoxItem Content="信息显示" Tag="423/" />
-                            <local:MyComboBoxItem Content="多人" Tag="435/social" />
+                            <local:MyComboBoxItem Content="服务器" Tag="435/social" />
                             <local:MyComboBoxItem Content="改良" Tag="5191/utility" />
                             <local:MyComboBoxItem Content="支持库" Tag="421/library" />
                         </local:MyComboBox>
@@ -73,9 +73,6 @@
                             <local:MyComboBoxItem Content="1.9.4" />
                             <local:MyComboBoxItem Content="1.8.9" />
                             <local:MyComboBoxItem Content="1.7.10" />
-                            <local:MyComboBoxItem Content="1.7.2" />
-                            <local:MyComboBoxItem Content="1.6.4" />
-                            <local:MyComboBoxItem Content="1.5.2" />
                         </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" />

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

@@ -104,7 +104,7 @@
         If Loader.ShouldStart(LoaderInput()) Then Storage = New CompProjectStorage '避免连续搜索两次使得 CompProjectStorage 引用丢失(#1311)
         Loader.Start()
     End Sub
-    Private Sub TextSearchName_KeyUp(sender As Object, e As KeyEventArgs) Handles TextSearchName.KeyUp, TextSearchVersion.KeyUp
+    Private Sub EnterTrigger(sender As Object, e As KeyEventArgs) Handles TextSearchName.KeyDown, TextSearchVersion.KeyDown
         If e.Key = Key.Enter Then StartNewSearch()
     End Sub
 

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

@@ -65,9 +65,6 @@
                             <local:MyComboBoxItem Content="1.9.4" />
                             <local:MyComboBoxItem Content="1.8.9" />
                             <local:MyComboBoxItem Content="1.7.10" />
-                            <local:MyComboBoxItem Content="1.7.2" />
-                            <local:MyComboBoxItem Content="1.6.4" />
-                            <local:MyComboBoxItem Content="1.5.2" />
                         </local:MyComboBox>
                     </Grid>
                     <Grid Margin="0,4,0,6" Height="35">

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

@@ -106,7 +106,7 @@
         If Loader.ShouldStart(LoaderInput()) Then Storage = New CompProjectStorage '避免连续搜索两次使得 CompProjectStorage 引用丢失(#1311)
         Loader.Start()
     End Sub
-    Private Sub TextSearchName_KeyUp(sender As Object, e As KeyEventArgs) Handles TextSearchName.KeyUp, TextSearchVersion.KeyUp
+    Private Sub EnterTrigger(sender As Object, e As KeyEventArgs) Handles TextSearchName.KeyDown, TextSearchVersion.KeyDown
         If e.Key = Key.Enter Then StartNewSearch()
     End Sub
 

+ 1 - 5
Plain Craft Launcher 2/Pages/PageLaunch/PageLaunchLeft.xaml.vb

@@ -746,11 +746,7 @@ ExitRefresh:
         '获取 “你知道吗” 提示
         Dim Hint As String = PageOtherTest.GetRandomHint()
         Try
-            Dim RawHints = Array.FindAll(
-                ReadFile(Path & "PCL\hints.txt").Replace(vbLf, "").Split(vbCr),
-                Function(Input As String) As Boolean
-                    Return Not String.IsNullOrWhiteSpace(Input)
-                End Function)
+            Dim RawHints = ReadFile(Path & "PCL\hints.txt").Split(vbCrLf.ToCharArray).Where(Function(s) Not String.IsNullOrWhiteSpace(s)).ToList
             If RawHints.Count > 0 Then Hint = RandomOne(RawHints)
         Catch ex As Exception
             Log(ex, "获取自定义 你知道吗 提示失败", LogLevel.Hint)

+ 1 - 1
Plain Craft Launcher 2/Pages/PageLink/PageLinkHiper.xaml.vb

@@ -688,7 +688,7 @@ FinishMcbFileCheck:
     Private Sub TextCert_ValidateChanged(sender As Object, e As EventArgs) Handles TextCert.ValidateChanged
         BtnCertDone.IsEnabled = TextCert.ValidateResult = ""
     End Sub
-    Private Sub TextCert_KeyUp(sender As Object, e As KeyEventArgs) Handles TextCert.KeyUp
+    Private Sub TextCert_KeyDown(sender As Object, e As KeyEventArgs) Handles TextCert.KeyDown
         If e.Key = Key.Enter AndAlso BtnCertDone.IsEnabled Then BtnCertDone_Click() '允许回车确认
     End Sub
 

+ 2 - 1
Plain Craft Launcher 2/Pages/PageSetup/PageSetupLaunch.xaml

@@ -145,7 +145,8 @@
                             </local:MyTextBox>
                         </Grid>
                         <TextBlock VerticalAlignment="Center" Grid.Row="12" HorizontalAlignment="Left" Text="游戏 Java" Margin="0,0,25,0" />
-                        <local:MyComboBox x:Name="ComboArgumentJava" Grid.ColumnSpan="2" Grid.Row="12" Grid.Column="1" ToolTip="若将 Java 放在游戏文件夹或 PCL 文件夹,在进行自动选择时 PCL 会尽量优先选择它">
+                        <local:MyComboBox x:Name="ComboArgumentJava" Grid.ColumnSpan="2" Grid.Row="12" Grid.Column="1" MaxDropDownHeight="240"
+                                          ToolTip="若将 Java 放在游戏文件夹或 PCL 文件夹,在进行自动选择时 PCL 会尽量优先选择它">
                             <ComboBoxItem Content="加载中……" IsSelected="True" />
                             <!--<local:MyComboBoxItem Content="Java 8 (1.8.0_171),64 位:C:\Program Files (x86)\Common Files\Oracle\Java\javapath\javaw.exe" ToolTipService.Placement="Right" ToolTipService.HorizontalOffset="5" IsSelected="True" ToolTip="C:\Program Files (x86)\Common Files\Oracle\Java\javapath\javaw.exe" />-->
                         </local:MyComboBox>

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

@@ -431,7 +431,7 @@ PreFin:
         Dim SelectedItem As MyComboBoxItem = Nothing
         Dim SelectedBySetup As String = Setup.Get("LaunchArgumentJavaSelect")
         Try
-            For Each Java In JavaList
+            For Each Java In Sort(JavaList.Clone(), Function(l, r) l.VersionCode < r.VersionCode)
                 Dim ListItem = New MyComboBoxItem With {.Content = Java.ToString, .ToolTip = Java.PathFolder, .Tag = Java}
                 ToolTipService.SetPlacement(ListItem, Primitives.PlacementMode.Right)
                 ToolTipService.SetHorizontalOffset(ListItem, 5)

+ 9 - 1
Plain Craft Launcher 2/Pages/PageSetup/PageSetupSystem.xaml

@@ -25,6 +25,7 @@
                             <RowDefinition Height="Auto" />
                             <RowDefinition Height="Auto" />
                             <RowDefinition Height="Auto" />
+                            <RowDefinition Height="Auto" />
                         </Grid.RowDefinitions>
                         <TextBlock VerticalAlignment="Center" HorizontalAlignment="Left" Text="版本列表获取" Margin="0,0,25,0" />
                         <local:MyComboBox x:Name="ComboDownloadVersion" Grid.ColumnSpan="2" Tag="ToolDownloadVersion" Grid.Column="1">
@@ -50,6 +51,9 @@
                         <local:MyCheckBox Margin="0,2,0,4" Text="安装整合包时保留原始压缩包" Grid.Row="7" Height="22" Grid.ColumnSpan="2"
                                           x:Name="CheckDownloadKeepModpack" Tag="ToolDownloadKeepModpack" 
                                           ToolTip="安装整合包时,在版本文件夹下保留用于安装的原始整合包压缩包文件" />
+                        <local:MyCheckBox Margin="0,2,0,4" Text="简化 Mod 加载器需求(忽略 Quilt)" Grid.Row="8" Height="22" Grid.ColumnSpan="2"
+                                          x:Name="CheckDownloadIgnoreQuilt" Tag="ToolDownloadIgnoreQuilt" 
+                                          ToolTip="当 Mod 支持 Forge、Fabric 但不支持 Quilt 时,不显示它的 Mod 加载器需求。&#xa;例如,关闭时 JEI 会显示需要 Forge / Fabric 1.8+,开启后 JEI 仅显示需要 1.8+。" />
                     </Grid>
                 </StackPanel>
             </local:MyCard>
@@ -111,8 +115,12 @@
                     <Grid Height="35" Grid.Row="6" Grid.ColumnSpan="5" Margin="0,5,0,0">
                         <Grid.ColumnDefinitions>
                             <ColumnDefinition Width="Auto" SharedSizeGroup="Button" />
+                            <ColumnDefinition Width="Auto" SharedSizeGroup="Button" />
+                            <ColumnDefinition Width="Auto" SharedSizeGroup="Button" />
                         </Grid.ColumnDefinitions>
-                        <local:MyButton x:Name="BtnSystemUpdate" MinWidth="140" Text="检查更新" Padding="13,0" Margin="0,0,20,0" />
+                        <local:MyButton Grid.Column="0" x:Name="BtnSystemUpdate" MinWidth="140" Text="检查更新" Padding="13,0" Margin="0,0,20,0" />
+                        <local:MyButton Grid.Column="1" x:Name="BtnSystemIdentify" MinWidth="140" Text="复制识别码" Padding="13,0" Margin="0,0,20,0" />
+                        <local:MyButton Grid.Column="2" x:Name="BtnSystemUnlock" MinWidth="140" Text="输入解锁码" Padding="13,0" Margin="0,0,20,0" />
                     </Grid>
                 </Grid>
             </local:MyCard>

+ 11 - 1
Plain Craft Launcher 2/Pages/PageSetup/PageSetupSystem.xaml.vb

@@ -57,6 +57,7 @@
         ComboDownloadVersion.SelectedIndex = Setup.Get("ToolDownloadVersion")
         ComboDownloadTranslate.SelectedIndex = Setup.Get("ToolDownloadTranslate")
         CheckDownloadKeepModpack.Checked = Setup.Get("ToolDownloadKeepModpack")
+        CheckDownloadIgnoreQuilt.Checked = Setup.Get("ToolDownloadIgnoreQuilt")
 
         'Minecraft 更新提示
         CheckUpdateRelease.Checked = Setup.Get("ToolUpdateRelease")
@@ -86,6 +87,7 @@
             Setup.Reset("ToolDownloadVersion")
             Setup.Reset("ToolDownloadTranslate")
             Setup.Reset("ToolDownloadKeepModpack")
+            Setup.Reset("ToolDownloadIgnoreQuilt")
             Setup.Reset("ToolUpdateRelease")
             Setup.Reset("ToolUpdateSnapshot")
             Setup.Reset("ToolHelpChinese")
@@ -107,7 +109,7 @@
     End Sub
 
     '将控件改变路由到设置改变
-    Private Shared Sub CheckBoxChange(sender As MyCheckBox, e As Object) Handles CheckDebugMode.Change, CheckDebugDelay.Change, CheckDebugSkipCopy.Change, CheckUpdateRelease.Change, CheckUpdateSnapshot.Change, CheckHelpChinese.Change, CheckDownloadKeepModpack.Change
+    Private Shared Sub CheckBoxChange(sender As MyCheckBox, e As Object) Handles CheckDebugMode.Change, CheckDebugDelay.Change, CheckDebugSkipCopy.Change, CheckUpdateRelease.Change, CheckUpdateSnapshot.Change, CheckHelpChinese.Change, CheckDownloadKeepModpack.Change, CheckDownloadIgnoreQuilt.Change
         If AniControlEnabled = 0 Then Setup.Set(sender.Tag, sender.Checked)
     End Sub
     Private Shared Sub SliderChange(sender As MySlider, e As Object) Handles SliderDebugAnim.Change, SliderDownloadThread.Change, SliderDownloadSpeed.Change
@@ -149,6 +151,14 @@
         End If
     End Sub
 
+    '识别码/解锁码替代入口
+    Private Sub BtnSystemIdentify_Click(sender As Object, e As MouseButtonEventArgs) Handles BtnSystemIdentify.Click
+        PageOtherAbout.CopyUniqueAddress()
+    End Sub
+    Private Sub BtnSystemUnlock_Click(sender As Object, e As MouseButtonEventArgs) Handles BtnSystemUnlock.Click
+        PageOtherAbout.DonateCodeInput()
+    End Sub
+
     '调试模式
     Private Sub CheckDebugMode_Change() Handles CheckDebugMode.Change
         If AniControlEnabled = 0 Then Hint("部分调试信息将在刷新或启动器重启后切换显示!",, False)

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

@@ -47,7 +47,8 @@
                             <local:MyComboBoxItem Content="关闭" ToolTip="与其余未开启隔离的版本均使用同一档案,存档、Mod 等均为公用。&#xa;若存在不同版本的 Forge 或 Fabric,可能会由于 Mod 与版本冲突导致未知问题。" />
                         </local:MyComboBox>
                         <TextBlock VerticalAlignment="Center" Grid.Row="6" HorizontalAlignment="Left" Text="游戏 Java" Margin="0,0,25,0" />
-                        <local:MyComboBox x:Name="ComboArgumentJava" Grid.ColumnSpan="2" Grid.Row="6" Grid.Column="1" ToolTip="若将 Java 放在游戏文件夹或 PCL 文件夹,在进行自动选择时 PCL 会尽量优先选择它">
+                        <local:MyComboBox x:Name="ComboArgumentJava" Grid.ColumnSpan="2" Grid.Row="6" Grid.Column="1" MaxDropDownHeight="240"
+                                          ToolTip="若将 Java 放在游戏文件夹或 PCL 文件夹,在进行自动选择时 PCL 会尽量优先选择它">
                             <ComboBoxItem Content="加载中……" IsSelected="True" />
                             <!--<local:MyComboBoxItem Content="Java 8 (1.8.0_171),64 位:C:\Program Files (x86)\Common Files\Oracle\Java\javapath\javaw.exe" ToolTipService.Placement="Right" ToolTipService.HorizontalOffset="5" IsSelected="True" ToolTip="C:\Program Files (x86)\Common Files\Oracle\Java\javapath\javaw.exe" />-->
                         </local:MyComboBox>

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

@@ -417,7 +417,7 @@ PreFin:
         Dim SelectedItem As MyComboBoxItem = Nothing
         Dim SelectedBySetup As String = Setup.Get("VersionArgumentJavaSelect", Version:=PageVersionLeft.Version)
         Try
-            For Each Java In JavaList
+            For Each Java In Sort(JavaList.Clone(), Function(l, r) l.VersionCode < r.VersionCode)
                 Dim ListItem = New MyComboBoxItem With {.Content = Java.ToString, .ToolTip = Java.PathFolder, .Tag = Java}
                 ToolTipService.SetPlacement(ListItem, Primitives.PlacementMode.Right)
                 ToolTipService.SetHorizontalOffset(ListItem, 5)

+ 215 - 147
Plain Craft Launcher 2/Resources/Custom.xaml

@@ -1,199 +1,251 @@
-
-<!-- 这是 PCL 的主页自定义文件。你可以通过修改这个文件来自定义 PCL 主页:添加文本、打开网页、启动游戏,等等。
+<!-- 这是 PCL 的主页自定义文件。你可以通过修改这个文件来自定义 PCL 主页:添加文本、打开网页、启动游戏,等等。
      如果你倒腾这个文件把 PCL 玩炸了,把这个文件直接删除就行了。
-     如果你懂得 WPF 的布局文件编写,你甚至可以做出不少的新玩意儿…… -->
-    
-<local:MyCard Title="基础教学 1:纯文本">
+     下列内容均基于 WPF 框架。你可以在继续之前先尝试自学 XAML 与 WPF 的基础,这能让你更轻松地理解下列内容。
+     你也可以使用 Ctrl + F 快速查找。例如,若需要改变文本颜色,则搜索 “颜色” 即可。 -->
+
+<local:MyCard Title="纯文本" Margin="0,0,0,15" CanSwap="True" IsSwaped="True">
     <StackPanel Margin="25,40,23,15">
-        <TextBlock Margin="0,0,0,4"
-                   Text="每个 local:MyCard 代表一张卡片,你可以添加、删除格式类似的 MyCard 来添加多个卡片。每个 TextBlock 代表一段文本,你可以在 Text 中书写任何你想写的内容。你也可以自行添加更多的 TextBlock。" />
-        <TextBlock Margin="0,0,0,4" Foreground="#8C7721"
-                   Text="你可以通过添加、删除属性修改样式,例如上面的 Foreground 会修改字体颜色。" />
-        <TextBlock Margin="20,5,20,0" FontSize="11"
-                   Text="它还有许多可以调整的属性:Margin 调整边距,FontSize 调整字号,TextWrapping 则是启用自动换行。" />
+        <TextBlock TextWrapping="Wrap" Margin="0,0,0,4"
+                    Text="每个 local:MyCard 代表一张卡片,你可以添加、删除格式类似的 MyCard 来添加多个卡片。每个 TextBlock 代表一段文本,你可以在 Text 属性中书写任何你想写的内容,也可以自行添加更多的 TextBlock。" />
+        <TextBlock TextWrapping="Wrap" Margin="0,0,0,4" FontSize="11"
+                    Text="你可以通过添加、删除属性修改样式,例如上一行的 FontSize 就会将字号改为 11 号。" />
+        <TextBlock TextWrapping="Wrap" Margin="20,5,20,0" Foreground="#8C7721"
+                    Text="它还有许多可以调整的属性:上一行的 Margin 调整了边距,Foreground 则会让文字变色。" />
     </StackPanel>
 </local:MyCard>
-    
-<local:MyCard Title="基础教学 2:卡片属性、提示条" Margin="0,0,0,15" CanSwap="True" IsSwaped="True">
+
+<local:MyCard Title="卡片、提示条" Margin="0,0,0,15" CanSwap="True" IsSwaped="True">
     <StackPanel Margin="25,40,23,15">
         <local:MyHint Text="local:MyHint 代表提示条,它默认是警告样式。" />
         <local:MyHint Margin="0,8,0,2" IsWarn="False"
-                   Text="将提示条的 IsWarn 属性改为 False 即可改为提示样式。&#xa;使用左边的那堆字符可以在任意地方手动换行,如果需要使用等号、引号等特殊字符,可以自行百度 XAML 转义字符。" />
-        <TextBlock Margin="0,6,0,0"
-                   Text="卡片(local:MyCard)的 Title 属性决定了它的标题。&#xa;为卡片添加 CanSwap 属性让它可以被折叠,True 代表是,False 代表否。在此基础上,再使用 IsSwaped 属性调整它是否默认被折叠。" />
+                    Text="将提示条的 IsWarn 属性改为 False 即可改为提示样式。&#xA;使用左边的那堆字符可以在任意地方手动换行,如果需要使用等号、引号等特殊字符,可以自行百度 XAML 转义字符。" />
+        <TextBlock TextWrapping="Wrap" Margin="0,6,0,0"
+                    Text="卡片(local:MyCard)的 Title 属性决定了它的标题。&#xA;为卡片添加 CanSwap 属性让它可以被折叠,True 代表是,False 代表否。在此基础上,再使用 IsSwaped 属性调整它是否默认被折叠。" />
     </StackPanel>
 </local:MyCard>
-    
-<local:MyCard Title="基础教学 3:长宽属性、图片">
+
+<local:MyCard Title="长宽属性、图片" Margin="0,0,0,15" CanSwap="True" IsSwaped="True">
     <StackPanel Margin="25,40,23,15">
-        <TextBlock Margin="0,0,0,4" Width="320" HorizontalAlignment="Right"
-                   Text="任意项目都可以添加 Width 与 Height 控制宽高,此外通过 HorizontalAlignment 来控制对齐:Center 代表居中,Right 代表居右。例如这段文本就被居右了。" />
-        <TextBlock Margin="0,0,0,6"
-                   Text="Image 代表图片,你需要在它的 Source 属性中填写一个网址或文件路径,它会从该处获取图片并显示。你通常也需要用 Height 限制它的高度。" />
+        <TextBlock TextWrapping="Wrap" Margin="0,0,0,4" Width="320" HorizontalAlignment="Right"
+                    Text="任意项目都可以添加 Width 与 Height 属性来控制宽高。HorizontalAlignment 属性可以控制对齐:Center 代表居中,Right 代表居右,例如这段文本就被居右了。" />
+        <TextBlock TextWrapping="Wrap" Margin="0,0,0,6"
+                    Text="Image 代表图片,你需要在它的 Source 属性中填写一个网址或文件路径,它会从该处获取图片并显示。通常需要使用 Height 限制它的高度。" />
         <Image Height="50" HorizontalAlignment="Center" Source="https://www.mcbbs.net/template/mcbbs/image/logo_sc.png" />
     </StackPanel>
 </local:MyCard>
-    
-<local:MyCard Title="按钮教学 1:基础">
+
+<local:MyCard Title="按钮" Margin="0,0,0,15" CanSwap="True" IsSwaped="True">
     <StackPanel Margin="25,40,23,15">
-        <TextBlock Margin="0,0,0,4"
-                   Text="你可以通过添加 local:MyButton 来新建一个按钮。你需要通过上一张卡片中提到的宽高属性来限定它的尺寸与位置,通过 Padding 属性控制它的内边距。" />
-        <TextBlock Margin="0,0,0,10"
-                   Text="按钮可以做到很多事,例如将 EventType 属性改为 打开网页,然后在 EventData 属性中写入网址,即可通过点击按钮打开网页。" />
-        <local:MyButton Width="140" Height="35" HorizontalAlignment="Left" Padding="13,0,13,0"
-                   Text="打开 MCBBS" EventType="打开网页" EventData="https://www.mcbbs.net/" />
-        <TextBlock Margin="0,10,0,10"
-                   Text="或者将 EventType 属性改为 弹出窗口,然后在 EventData 属性中写入弹窗的标题与内容……" />
-        <local:MyButton Width="140" Height="35" HorizontalAlignment="Left" Padding="13,0,13,0"
-                   Text="显示一个弹窗" EventType="弹出窗口" EventData="这是标题|标题与内容以竖线间隔。\n你也可以直接在其中换行。" />
+        <TextBlock TextWrapping="Wrap" Margin="0,0,0,4"
+                    Text="添加 local:MyButton 即可新建一个按钮。你需要限定它的尺寸与位置,并通过 Padding 属性进一步控制它的内边距。" />
+        <local:MyButton Margin="0,4,0,10" Height="35" HorizontalAlignment="Left" Padding="25,0,25,0"
+                    Text="这是一个按钮!一个按钮!" />
+        <TextBlock TextWrapping="Wrap" Margin="0,0,0,4"
+                    Text="你可以修改 ColorType 属性来调整按钮配色:Highlight 代表当前主题色,Red 代表红色。ToolTip 属性还可以让你在鼠标悬浮在上面的时候显示提示文本。" />
+        <local:MyButton Margin="0,4,0,10" Width="250" Height="35" ColorType="Highlight"
+                    Text="把鼠标停在这里别动……" ToolTip="……就能看到这句话!" />
+        <TextBlock TextWrapping="Wrap" Margin="0,0,0,4"
+                    Text="local:MyTextButton 是没有边框的 “纯文本按钮”,其作用与 local:MyButton 一致。" />
+        <local:MyTextButton Margin="0,8,0,10" HorizontalAlignment="Center"
+                    Text="一个精简版的文本按钮" />
+        <TextBlock TextWrapping="Wrap" Margin="0,0,0,4"
+                    Text="按钮可以做到很多事,具体将在 “事件” 部分介绍。" />
     </StackPanel>
 </local:MyCard>
-    
-<local:MyCard Title="按钮教学 2:属性">
+
+<local:MyCard Title="事件 1:打开网页、弹出窗口" Margin="0,0,0,15" CanSwap="True" IsSwaped="True">
     <StackPanel Margin="25,40,23,15">
-        <TextBlock TextWrapping="Wrap"
-                   Text="你可以修改 ColorType 属性来调整按钮配色,Highlight 代表当前主题色,Red 代表红色。ToolTip 属性还可以让你在鼠标悬浮在上面的时候显示提示文本。" />
-        <local:MyButton Margin="0,8,0,10" Width="250" Height="35" ColorType="Highlight"
-                   Text="打开 Wiki(按钮是主题色)" EventType="打开网页" EventData="https://minecraft-zh.gamepedia.com/Minecraft_Wiki" ToolTip="点击打开 Minecraft Wiki!" />
-        <TextBlock TextWrapping="Wrap"
-                   Text="local:MyTextButton 是没有边框的文本按钮,你同样可以设置 EventType 与 EventData 让它具有特定功能。" />
+        <TextBlock TextWrapping="Wrap" Margin="0,0,0,10"
+                    Text="将按钮的 EventType 属性设为 打开网页,然后在 EventData 属性中写入网址,即可通过点击按钮打开网页。" />
+        <local:MyButton Width="140" Height="35" HorizontalAlignment="Left" Padding="13,0,13,0"
+                    Text="打开 MCBBS" EventType="打开网页" EventData="https://www.mcbbs.net/" />
+        <TextBlock TextWrapping="Wrap" Margin="0,10,0,10"
+                    Text="或者将 EventType 属性改为 弹出窗口,然后在 EventData 属性中写入弹窗的标题与内容……" />
+        <local:MyButton Width="140" Height="35" HorizontalAlignment="Left" Padding="13,0,13,0"
+                    Text="显示一个弹窗" EventType="弹出窗口" EventData="这是标题|标题与内容以竖线间隔。\n你也可以直接在其中换行。" />
+        <TextBlock TextWrapping="Wrap" Margin="0,10,0,0"
+                    Text="local:MyTextButton 同样可以设置 EventType 与 EventData 让它具有特定功能。" />
         <local:MyTextButton Margin="0,8,0,0" HorizontalAlignment="Center"
-                   Text="点击打开知乎" EventType="打开网页" EventData="https://www.zhihu.com/" />
+                    Text="点击打开知乎" EventType="打开网页" EventData="https://www.zhihu.com/" />
     </StackPanel>
 </local:MyCard>
-    
-<local:MyCard Title="按钮教学 3:启动游戏">
+
+<local:MyCard Title="事件 2:启动游戏" Margin="0,0,0,15" CanSwap="True" IsSwaped="True">
     <StackPanel Margin="25,40,23,15">
-        <TextBlock TextWrapping="Wrap"
-                 Text="EventType 改为启动游戏,EventData 改为游戏版本,即可点击启动特定版本的游戏。如果当前游戏文件夹没有该版本则无法启动。" />
-        <local:MyButton Margin="0,8,0,10" Width="250" Height="35"
-                 Text="启动 Minecraft 1.12.2" EventType="启动游戏" EventData="1.12.2" />
-        <TextBlock TextWrapping="Wrap"
-                 Text="在 EventData 后面添加一条竖线(|),然后写服务器 IP,即可在启动该版本的同时自动进入服务器。按 Shift + 回车键上方的键就能打出来竖线了。" />
-        <local:MyButton Margin="0,8,0,0" Width="250" Height="35"
-                 Text="使用 1.12.2 进入 Hypixel" EventType="启动游戏" EventData="1.12.2|mc.hypixel.net" ToolTip="服务器 IP:mc.hypixel.net" />
+        <TextBlock TextWrapping="Wrap" Margin="0,0,0,4"
+                    Text="将 EventType 设置为 启动游戏,EventData 设置为具体的游戏版本,即可通过点击按钮启动游戏。如果当前游戏文件夹没有该版本,则无法启动。" />
+        <local:MyButton Margin="0,4,0,10" Width="250" Height="35"
+                    Text="启动 Minecraft 1.12.2" EventType="启动游戏" EventData="1.12.2" />
+        <TextBlock TextWrapping="Wrap" Margin="0,0,0,4"
+                    Text="在 EventData 后面添加一条竖线(|),竖线后填写服务器 IP,即可在启动该版本的同时自动进入服务器。" />
+        <local:MyButton Margin="0,4,0,0" Width="250" Height="35"
+                    Text="启动 1.12.2 并进入 Hypixel" EventType="启动游戏" EventData="1.12.2|mc.hypixel.net" ToolTip="服务器 IP:mc.hypixel.net" />
     </StackPanel>
 </local:MyCard>
-    
-<local:MyCard Title="按钮教学 4:打开文件">
+
+<local:MyCard Title="事件 3:打开文件" Margin="0,0,0,15" CanSwap="True" IsSwaped="True">
     <StackPanel Margin="25,40,23,15">
-        <TextBlock TextWrapping="Wrap"
-                   Text="EventType 为打开文件,EventData 为文件路径,即可点击打开特定文件或启动程序。" />
-        <local:MyButton Margin="0,8,0,8" Width="200" Height="35"
-                   Text="打开记事本" EventType="打开文件" EventData="notepad.exe" />
-        <TextBlock Margin="0,4,0,0"
-                   Text="如果能在 PCL 文件夹中找到该文件,则会优先打开 PCL 文件夹中的文件。当然,你可以使用例如 C:\ 开头的绝对路径。" />
-        <TextBlock TextWrapping="Wrap"
-                   Text="此外,PCL 会将文件中的花括号 path 替换为 PCL 可执行文件所在文件夹({path}),可以用于执行特定程序或加载图片。" />
-        <local:MyButton Margin="0,8,0,8" Width="200" Height="35"
-                   Text="打开 PCL 日志" EventType="打开文件" EventData="Log1.txt" ToolTip="PCL 的日志文件就在 PCL 文件夹内,且名为 Log1.txt" />
-        <TextBlock Margin="0,4,0,0"
-                   Text="就像为游戏指定服务器 IP 一样,你也可以在 EventData 的竖线后为程序添加启动参数。" />
-        <local:MyButton Margin="0,8,0,0" Width="200" Height="35"
-                   Text="定位游戏启动脚本" EventType="打开文件" EventData="explorer.exe|/select,LatestLaunch.bat" ToolTip="PCL 会将上一次启动 MC 的脚本保存在 PCL 文件夹内,且名为 LatestLaunch.bat。&#xa;点击按钮会打开文件管理器,并且借助参数要求它选中这个文件。" />
+        <TextBlock TextWrapping="Wrap" Margin="0,0,0,4"
+                    Text="将 EventType 设置为 打开文件,EventData 设置为文件路径,即可点击打开特定文件或启动程序。" />
+        <local:MyButton Margin="0,4,0,8" Width="200" Height="35"
+                    Text="打开记事本" EventType="打开文件" EventData="notepad.exe" />
+        <TextBlock TextWrapping="Wrap" Margin="0,4,0,0"
+                    Text="如果能在 PCL 文件夹中找到该文件,则会优先打开 PCL 文件夹中的文件。当然,你可以使用例如 C:\ 开头的绝对路径。" />
+        <TextBlock TextWrapping="Wrap" Margin="0,0,0,4"
+                    Text="此外,PCL2 会将文件中的花括号 path 替换为 PCL 可执行文件所在文件夹({path}),可以用于执行特定程序或加载图片。" />
+        <local:MyButton Margin="0,4,0,10" Width="200" Height="35"
+                    Text="打开 PCL 日志" EventType="打开文件" EventData="Log1.txt" ToolTip="PCL2 的日志文件就在 PCL 文件夹内,且名为 Log1.txt" />
+        <TextBlock TextWrapping="Wrap" Margin="0,0,0,4"
+                    Text="就像为游戏指定服务器 IP 一样,你也可以在 EventData 的竖线后为程序添加启动参数。" />
+        <local:MyButton Margin="0,4,0,0" Width="200" Height="35"
+                    Text="定位游戏启动脚本" EventType="打开文件" EventData="explorer.exe|/select,LatestLaunch.bat" ToolTip="PCL2 会将上一次启动 MC 的脚本保存在 PCL 文件夹内,且名为 LatestLaunch.bat。&#xA;点击按钮会打开文件管理器,并且借助参数要求它选中这个文件。" />
     </StackPanel>
 </local:MyCard>
-    
-<local:MyCard Title="按钮教学 5:其他命令">
+
+<local:MyCard Title="事件 4:其他事件类型" Margin="0,0,0,15" CanSwap="True" IsSwaped="True">
     <StackPanel Margin="25,40,23,15">
-        <TextBlock Margin="0,0,0,4"
-                   Text="EventType 为复制文本,会将 EventData 中的内容复制到剪贴板。" />
-        <TextBlock Margin="0,0,0,4"
-                   Text="EventType 为刷新主页,即可点击重新加载主页。如果你使用联网方式下载主页文件,你可以通过这一方式更新主页内容。它无需指定 EventData。" />
-        <TextBlock TextWrapping="Wrap"
-                   Text="EventType 为下载文件,会在点击时要求选择文件保存位置,并且下载 EventData 的链接中的文件。" />
-        <local:MyButton Margin="0,8,0,0" Width="250" Height="35"
-                   Text="下载 MCBBS 的 Logo" EventType="下载文件" EventData="https://www.mcbbs.net/template/mcbbs/image/logo_sc.png" />
+        <TextBlock TextWrapping="Wrap" Margin="0,4,0,6" FontWeight="Bold"
+                    Text="EventType 共有以下种类:" />
+        <TextBlock TextWrapping="Wrap" Margin="0,0,0,4"
+                    Text="· 打开网页、启动游戏、打开文件:已在上方的卡片中介绍" />
+        <TextBlock TextWrapping="Wrap" Margin="0,0,0,4"
+                    Text="· 今日人品、清理垃圾:触发百宝箱中的对应功能" />
+        <TextBlock TextWrapping="Wrap" Margin="0,0,0,4"
+                    Text="· 复制文本:将 EventData 中的内容复制到剪贴板" />
+        <TextBlock TextWrapping="Wrap" Margin="0,0,0,4"
+                    Text="· 刷新主页:点击重新加载主页。如果主页文件为联网更新,这会重新下载主页内容" />
+        <TextBlock TextWrapping="Wrap" Margin="0,0,0,4"
+                    Text="· 下载文件:在点击时要求选择文件保存位置,并且下载 EventData 的链接中的文件" />
+        <local:MyButton Margin="0,5,0,6" Width="250" Height="35"
+                    Text="下载 MCBBS 的 Logo" EventType="下载文件" EventData="https://www.mcbbs.net/template/mcbbs/image/logo_sc.png" />
+        <TextBlock TextWrapping="Wrap" Margin="0,4,0,0"
+                    Text="· 打开帮助:跳转到 EventData 对应的帮助文件(输入相对 Help 文件夹的路径)"/>
+        <local:MyButton Margin="0,5,0,6" Width="250" Height="35"
+                    Text="打开自定义帮助页面" EventType="打开帮助" EventData="帮助/自定义帮助.json"/>
     </StackPanel>
 </local:MyCard>
-    
-<local:MyCard Title="高级:复杂按钮布局" CanSwap="True" IsSwaped="True">
+
+<local:MyCard Title="横向布局 1:StackPanel" Margin="0,0,0,15" CanSwap="True" IsSwaped="True">
     <StackPanel Margin="25,40,23,15">
-        <local:MyHint Margin="0,0,0,7" IsWarn="False"
-                   Text="下面的按钮列举了全部 6 种 EventType 作为示例。" />
-        <TextBlock Margin="0,0,0,4"
-                   Text="你需要用到 StackPanel 在一横行里塞下多个按钮,你可以仅在这个教学卡片的基础上稍作调整,来实现自己的按钮布局。" />
-        <TextBlock Margin="0,0,0,10"
-                   Text="如果你要实现更复杂的布局,你必须使用 Grid 等控件。多百度吧……谷歌也行。" />
+        <TextBlock TextWrapping="Wrap" Margin="0,0,0,10"
+                    Text="你需要使用 StackPanel 在一行里塞下多个按钮。你可以仅在这个教学卡片的基础上稍作调整,来实现自己的按钮布局。" />
         <!-- 这是第一行 -->
         <StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
             <local:MyButton Margin="0,0,10,0" Width="140" Height="35" HorizontalAlignment="Left" Padding="13,0,13,0" ColorType="Highlight"
-                   Text="打开 B 站" EventType="打开网页" EventData="https://www.bilibili.com/" />
+                        Text="打开 B 站" EventType="打开网页" EventData="https://www.bilibili.com/" />
             <local:MyButton Margin="0,0,10,0" Width="140" Height="35" HorizontalAlignment="Left" Padding="13,0,13,0"
-                   Text="进入 Hypixel" EventType="启动游戏" EventData="1.16.3|mc.hypixel.net" ToolTip="使用 Minecraft 1.16.3 进入 Hypixel" />
+                        Text="进入 Hypixel" EventType="启动游戏" EventData="1.16.3|mc.hypixel.net" ToolTip="使用 Minecraft 1.16.3 进入 Hypixel" />
             <local:MyButton Margin="0,0,10,0" Width="140" Height="35" HorizontalAlignment="Left" Padding="13,0,13,0"
-                   Text="打开画图" EventType="打开文件" EventData="mspaint.exe" />
+                        Text="打开画图" EventType="打开文件" EventData="mspaint.exe" />
         </StackPanel>
         <!-- 这是第二行 -->
         <StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Margin="0,10,0,0">
             <local:MyButton Margin="0,0,10,0" Width="140" Height="35" HorizontalAlignment="Left" Padding="13,0,13,0" ColorType="Red"
-                   Text="复制召唤命令" EventType="复制文本" EventData="/execute as @a at @s run summon Creeper ~ ~2 ~" ToolTip="这条 Minecraft 命令会在每个玩家头顶召唤一只苦力怕!" />
+                        Text="复制召唤命令" EventType="复制文本" EventData="/execute as @a at @s run summon Creeper ~ ~2 ~" ToolTip="这条 Minecraft 命令会在每个玩家头顶召唤一只苦力怕!" />
             <local:MyButton Margin="0,0,10,0" Width="140" Height="35" HorizontalAlignment="Left" Padding="13,0,13,0"
-                   Text="刷新主页" EventType="刷新主页" ToolTip="这通常用于联网更新主页时刷新信息,对本地文件没啥用" />
+                        Text="今日人品" EventType="今日人品" />
             <local:MyButton Margin="0,0,10,0" Width="140" Height="35" HorizontalAlignment="Left" Padding="13,0,13,0"
-                   Text="下载作者的头像" EventType="下载文件" EventData="https://www.mcbbs.net/uc_server/data/avatar/000/14/51/06_avatar_small.jpg?ts=1471402592" />
+                        Text="下载作者的头像" EventType="下载文件" EventData="https://www.mcbbs.net/uc_server/data/avatar/000/14/51/06_avatar_small.jpg?ts=1471402592" />
         </StackPanel>
     </StackPanel>
 </local:MyCard>
 
-<local:MyCard Title="高级:全局动态资源绑定" CanSwap="True" IsSwaped="True">
+<local:MyCard Title="横向布局 2:Grid" Margin="0,0,0,15" CanSwap="True" IsSwaped="True">
+    <StackPanel Margin="25,40,23,15">
+        <TextBlock TextWrapping="Wrap" Margin="0,0,0,4"
+                    Text="如果要实现更复杂的布局,则必须使用 Grid。Grid 可以让按钮们自动适应窗口宽度:随意拉伸 PCL 窗口,按钮大小会自动改变。" />
+        <TextBlock TextWrapping="Wrap" Margin="0,0,0,10"
+                    Text="你可以上网查找 “WPF Grid” 的相关教程,这里仅给出一个例子,不作详细介绍。你可以仅在这个教学卡片的基础上稍作调整,来实现自己的按钮布局。" />
+        <Grid>
+            <Grid.ColumnDefinitions>
+                <ColumnDefinition Width="1*" />
+                <ColumnDefinition Width="1.6*" />
+                <!-- 这个按钮的宽度是其他按钮的 1.6 倍 -->
+                <ColumnDefinition Width="1*" />
+                <!-- 如果不打 *,则会占用固定的宽度 -->
+            </Grid.ColumnDefinitions>
+            <!-- 为按钮添加 Grid.Column 属性,删除 Width 与 HorizontalAlignment 属性 -->
+            <local:MyButton Grid.Column="0" Margin="0,0,10,0" Height="35" ColorType="Highlight"
+                        Text="打开 B 站" EventType="打开网页" EventData="https://www.bilibili.com/" />
+            <local:MyButton Grid.Column="1" Margin="0,0,10,0" Height="35" 
+                        Text="进入 Hypixel" EventType="启动游戏" EventData="1.16.3|mc.hypixel.net" ToolTip="使用 Minecraft 1.16.3 进入 Hypixel" />
+            <local:MyButton Grid.Column="2" Margin="0,0,10,0" Height="35" 
+                        Text="打开画图" EventType="打开文件" EventData="mspaint.exe" />
+        </Grid>
+    </StackPanel>
+</local:MyCard>
+
+<local:MyCard Title="列表项 1:基础" Margin="0,0,0,15" CanSwap="True" IsSwaped="True">
     <StackPanel Margin="25,40,23,15">
-        <TextBlock TextWrapping="Wrap" LineHeight="17" Margin="0,0,0,15"
-                   Text="你可以使用全局动态资源绑定的方式来给你的控件赋予全局主题色。" />
-        <TextBlock TextWrapping="Wrap"
-                   Text="你好世界!" Foreground="{DynamicResource ColorBrush1}"/>
-        <TextBlock TextWrapping="Wrap"
-                   Text="你好世界!" Foreground="{DynamicResource ColorBrush3}"/>
-        <TextBlock TextWrapping="Wrap"
-                   Text="你好世界!" Foreground="{DynamicResource ColorBrush5}"/>
-        <TextBlock TextWrapping="Wrap" LineHeight="17" Margin="0,15,0,15"
-                   Text="除了字体颜色的前景色,你也可以用于背景色、边框等绝大部分的颜色参数,参考如下复杂例子。" />
-        <Border Background="{DynamicResource ColorBrush5}" BorderBrush="{DynamicResource ColorBrush2}"
-                   CornerRadius="3" HorizontalAlignment="Stretch" BorderThickness="1" Height="27px" Opacity="0.7">
-            <Grid>
-                <Path Fill="{DynamicResource ColorBrush1}" Stretch="Fill" Width="15" Height="15" HorizontalAlignment="Left" Margin="10,0,0,0"
-                        Data="M256 8C119.043 8 8 119.083 8 256c0 136.997 111.043 248 248 248s248-111.003 248-248C504 119.083 392.957 8 256 8zm0 110c23.196 0 42 18.804 42 42s-18.804 42-42 42-42-18.804-42-42 18.804-42 42-42zm56 254c0 6.627-5.373 12-12 12h-88c-6.627 0-12-5.373-12-12v-24c0-6.627 5.373-12 12-12h12v-64h-12c-6.627 0-12-5.373-12-12v-24c0-6.627 5.373-12 12-12h64c6.627 0 12 5.373 12 12v100h12c6.627 0 12 5.373 12 12v24z"></Path>
-                <TextBlock Foreground="{DynamicResource ColorBrush1}" Margin="35,5,0,0" Text="仿造的同步主题色的信息条。" />
-            </Grid>
-        </Border>
+        <TextBlock TextWrapping="Wrap" Margin="0,0,0,4"
+                    Text="你也可以使用列表项 “local:MyListItem” 来替代按钮,其使用方式与按钮类似。" />
+        <local:MyListItem  Margin="-5,2,-5,8"
+		            Logo="https://www.baidu.com/favicon.ico" Title="百度" Info="百度一下,你就知道!" 
+		            EventType="打开网页" EventData="https://www.baidu.com/" Type="Clickable" />
+        <TextBlock TextWrapping="Wrap" Margin="0,0,0,4"
+                    Text="Logo 属性为列表项的图标,指定的可以是链接也可以是文件路径;Title 是大标题,Info 是可选的小标题(详细信息);Type 如果省略,该列表项则单纯只展示信息,仅当 Type 为 Clickable 才能触发点击效果。"/>
+        <local:MyListItem Margin="-5,2,-5,8"
+                    Logo="pack://application:,,,/images/Blocks/Grass.png"
+		            EventType="打开帮助" EventData="帮助/自定义帮助.json" Type="Clickable" />
+        <TextBlock TextWrapping="Wrap" Margin="0,0,0,4"
+                    Text="EventType、EventData 与按钮几乎一致,唯一不同的是,列表项不支持联网加载帮助文件。" />
     </StackPanel>
 </local:MyCard>
 
-<local:MyCard Title="高级:预置图片和列表项" CanSwap="True" IsSwaped="True">
+<local:MyCard Title="列表项 2:内置图片" Margin="0,0,0,15" CanSwap="True" IsSwaped="True">
     <StackPanel Margin="25,40,23,15">
-        <TextBlock TextWrapping="Wrap" LineHeight="17"
-                   Text="PCL 中包含一些预置的方块与物品图片,可以直接使用。"/>
-        <StackPanel Orientation="Horizontal">
-            <Image Width="30" Height="30" Margin="15,15,0,15" Source="pack://application:,,,/images/Blocks/CommandBlock.png"/>
+        <TextBlock TextWrapping="Wrap" Margin="0,0,0,4"
+                    Text="PCL 内置了一些 Minecraft 方块与物品图片,可以直接使用。"/>
+        <StackPanel Orientation="Horizontal" Margin="10,8,0,15" Height="30">
+            <Image Width="30" Margin="5,0,0,0" Source="pack://application:,,,/images/Blocks/CommandBlock.png"/>
             <!-- 命令方块 -->
-            <Image Width="30" Height="30" Margin="5,15,0,15" Source="pack://application:,,,/images/Blocks/Cobblestone.png"/>
+            <Image Width="30" Margin="5,0,0,0" Source="pack://application:,,,/images/Blocks/Cobblestone.png"/>
             <!-- 圆石 -->
-            <Image Width="30" Height="30" Margin="5,15,0,15" Source="pack://application:,,,/images/Blocks/GoldBlock.png"/>
+            <Image Width="30" Margin="5,0,0,0" Source="pack://application:,,,/images/Blocks/GoldBlock.png"/>
             <!-- 金块 -->
-            <Image Width="30" Height="30" Margin="5,15,0,15" Source="pack://application:,,,/images/Blocks/Grass.png"/>
+            <Image Width="30" Margin="5,0,0,0" Source="pack://application:,,,/images/Blocks/Grass.png"/>
             <!-- 草方块 -->
-            <Image Width="30" Height="30" Margin="5,15,0,15" Source="pack://application:,,,/images/Blocks/GrassPath.png"/>
+            <Image Width="30" Margin="5,0,0,0" Source="pack://application:,,,/images/Blocks/GrassPath.png"/>
             <!-- 草径 -->
-            <Image Width="30" Height="30" Margin="5,15,0,15" Source="pack://application:,,,/images/Blocks/Anvil.png"/>
-            <!-- 铁砧(zhen) -->
-            <Image Width="30" Height="30" Margin="5,15,0,15" Source="pack://application:,,,/images/Blocks/RedstoneBlock.png"/>
+            <Image Width="30" Margin="5,0,0,0" Source="pack://application:,,,/images/Blocks/Anvil.png"/>
+            <!-- 铁砧 -->
+            <Image Width="30" Margin="5,0,0,0" Source="pack://application:,,,/images/Blocks/RedstoneBlock.png"/>
             <!-- 红石块 -->
-            <Image Width="30" Height="30" Margin="5,15,0,15" Source="pack://application:,,,/images/Blocks/RedstoneLampOn.png"/>
+            <Image Width="30" Margin="5,0,0,0" Source="pack://application:,,,/images/Blocks/RedstoneLampOn.png"/>
             <!-- 红石灯(亮) -->
-            <Image Width="30" Height="30" Margin="5,15,0,15" Source="pack://application:,,,/images/Blocks/RedstoneLampOff.png"/>
+            <Image Width="30" Margin="5,0,0,0" Source="pack://application:,,,/images/Blocks/RedstoneLampOff.png"/>
             <!-- 红石灯(灭) -->
-            <Image Width="30" Height="30" Margin="5,15,0,15" Source="pack://application:,,,/images/Blocks/Egg.png"/>
+            <Image Width="30" Margin="5,0,0,0" Source="pack://application:,,,/images/Blocks/Egg.png"/>
             <!-- 鸡蛋 -->
-            <Image Width="30" Height="30" Margin="5,15,0,15" Source="pack://application:,,,/images/Blocks/Fabric.png"/>
+            <Image Width="30" Margin="5,0,0,0" Source="pack://application:,,,/images/Blocks/Fabric.png"/>
             <!-- 布料(Fabric 图标) -->
         </StackPanel>
-        <TextBlock TextWrapping="Wrap" LineHeight="17"
-                   Text="在需要更详细的列出内容时,你可以使用列表项来替代按钮。在列表项中,点击操作的使用方式与按钮相同。"/>
-        <local:MyListItem Margin="-5,15,-5,0" 
-		                  Logo="https://www.baidu.com/favicon.ico" Title="百度" Info="百度一下,你就知道!" 
-		                  EventType="打开网页" EventData="https://www.baidu.com/" Type="Clickable" />
+        <TextBlock TextWrapping="Wrap" Margin="0,0,0,4"
+                    Text="使用时,将上方对应行的 Source 复制到 MyListItem 的 Logo 属性处即可。"/>
         <local:MyListItem Margin="-5,0,-5,8"
-		                  EventType="打开帮助" EventData="帮助/自定义帮助.json" Type="Clickable" />
+            Logo="pack://application:,,,/images/Blocks/CommandBlock.png"
+            Title="清理垃圾" Info="使用内置的命令方块图片作为 Logo" EventType="清理垃圾" Type="Clickable" />
+    </StackPanel>
+</local:MyCard>
+
+<local:MyCard Title="主题色" Margin="0,0,0,15" CanSwap="True" IsSwaped="True">
+    <StackPanel Margin="25,40,23,15">
+        <TextBlock TextWrapping="Wrap" Margin="0,0,0,15"
+                    Text="你可以用类似 {DynamicResource ColorBrush5} 的格式使用 PCL 当前的主题颜色,修改末尾的数字编号以改变颜色浓度。" />
+        <StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Margin="8,4">
+            <TextBlock TextWrapping="Wrap" Text=" 浓度 1 " Margin="5,0" Background="{DynamicResource ColorBrush1}" Foreground="#FFFFFF" />
+            <TextBlock TextWrapping="Wrap" Text=" 浓度 2 " Margin="5,0" Background="{DynamicResource ColorBrush2}" Foreground="#FFFFFF" />
+            <TextBlock TextWrapping="Wrap" Text=" 浓度 3 " Margin="5,0" Background="{DynamicResource ColorBrush3}" Foreground="#FFFFFF" />
+            <TextBlock TextWrapping="Wrap" Text=" 浓度 4 " Margin="5,0" Background="{DynamicResource ColorBrush4}" Foreground="#FFFFFF" />
+        </StackPanel>
+        <StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Margin="8,4">
+            <TextBlock TextWrapping="Wrap" Text=" 浓度 5 " Margin="5,0" Background="{DynamicResource ColorBrush5}" />
+            <TextBlock TextWrapping="Wrap" Text=" 浓度 6 " Margin="5,0" Background="{DynamicResource ColorBrush6}" />
+            <TextBlock TextWrapping="Wrap" Text=" 浓度 7 " Margin="5,0" Background="{DynamicResource ColorBrush7}" />
+            <TextBlock TextWrapping="Wrap" Text=" 浓度 8 " Margin="5,0" Background="{DynamicResource ColorBrush8}" />
+        </StackPanel>
+        <TextBlock TextWrapping="Wrap" Margin="0,15,0,8" Foreground="{DynamicResource ColorBrush2}" Background="{DynamicResource ColorBrush6}"
+                    Text="除了字体颜色,你也可以将主题色用于背景色、边框颜色等颜色参数。例如这行字的颜色为浓度 2,背景为浓度 6。" />
     </StackPanel>
 </local:MyCard>
 
@@ -202,36 +254,52 @@
 全部通用的属性:
  - Width、Height:设置宽度与高度
  - ToolTip:设置鼠标指向时的提示文本
- - Foreground:调整前景颜色(十六进制字符串,例如 #FF010203 代表 ARGB 中的 255,1,2,3。前两位代表不透明度,FF 为全不透明,00 为全透明)
- - Background:调整背景颜色(使用类似 Background="{DynamicResource ColorBrush5}" 的格式以调用 PCL 当前的主题颜色,修改末尾的数字编号以改变颜色浓度)
+ - Background:调整背景颜色(十六进制字符串,例如 #FF010203 代表 ARGB 中的 255,1,2,3。前两位代表不透明度,FF 为全不透明,00 为全透明)
  - Margin:调整外边距(格式为 左,上,右,下。例如 Margin="0,0,0,2" 即为 2 单位的下边距)
- - HorizontalAlignment:设置对齐方式(Left、Center、Right)
 
 TextBlock(纯文本):
  - Text:设置显示的文本(如果要使用引号等特殊字符,自行百度 XAML 转义)
  - TextWrapping:开启自动换行
  - FontSize:设置字号
- 
+ - FontWeight:设置为 Bold 时,文字加粗
+ - Foreground:调整前景颜色(十六进制字符串,例如 #FF010203 代表 ARGB 中的 255,1,2,3。前两位代表不透明度,FF 为全不透明,00 为全透明)
+ - HorizontalAlignment:设置对齐方式(Left、Center、Right)
+
 Image(图片):
  - Source:要显示的图片的网址
+ - Foreground:调整前景颜色(十六进制字符串,例如 #FF010203 代表 ARGB 中的 255,1,2,3。前两位代表不透明度,FF 为全不透明,00 为全透明)
+ - HorizontalAlignment:设置对齐方式(Left、Center、Right)
+
+local:MyCard(卡片):
+ - Title:设置显示的标题文本
+ - CanSwap:这张卡片是否可以折叠,True 为是,False 为否
+ - IsSwaped:这张卡片是否默认折叠,要求 CanSwap 必须为 True
+ - Foreground:调整前景颜色(十六进制字符串,例如 #FF010203 代表 ARGB 中的 255,1,2,3。前两位代表不透明度,FF 为全不透明,00 为全透明)
+ - HorizontalAlignment:设置对齐方式(Left、Center、Right)(使用时,CanSwap 属性需为 False)
 
 local:MyHint(提示条):
- - Text:设置显示的文本(&#xa; 代表换行)
+ - Text:设置显示的文本(&#xA; 代表换行)
  - IsWarn:设置为 True 代表警告样式,False 代表提示样式
- 
+ - Foreground:调整前景颜色(十六进制字符串,例如 #FF010203 代表 ARGB 中的 255,1,2,3。前两位代表不透明度,FF 为全不透明,00 为全透明)
+ - HorizontalAlignment:设置对齐方式(Left、Center、Right)
+
 local:MyButton(按钮):
  - Text:设置显示的文本
  - Padding:设置内边距,格式与 Margin 一致
  - ColorType:设置颜色主题(Highlight 为当前启动器的主题颜色,Red 为红色,默认为黑色)
  - EventType、EventData:触发特定事件
- 
+ - HorizontalAlignment:设置对齐方式(Left、Center、Right)
+
 local:MyTextButton(文本按钮):
  - Text:设置显示的文本
  - EventType、EventData:触发特定事件
- 
-local:MyCard(卡片):
- - Title:设置显示的标题文本
- - CanSwap:这张卡片是否可以折叠,True 为是,False 为否
- - IsSwaped:这张卡片是否默认折叠,要求 CanSwap 必须为 True
+ - Foreground:调整前景颜色(十六进制字符串,例如 #FF010203 代表 ARGB 中的 255,1,2,3。前两位代表不透明度,FF 为全不透明,00 为全透明)
+ - HorizontalAlignment:设置对齐方式(Left、Center、Right)
+
+local:MyListItem(列表项):
+ - Logo:列表项的图标(所指定的可以是链接也可以是文件路径)
+ - Title:列表项的大标题
+ - Info:列表项的详细信息,它将会以灰色显示在大标题下方
+ - Type:若留空仅单纯展示信息,设置为 Clickable 触发相应活动
 
--->
+-->

BIN
Plain Craft Launcher 2/Resources/Help.zip