Explorar el Código

公开更多代码

龙腾猫跃 hace 2 años
padre
commit
c23fecfe14

+ 1 - 7
.gitignore

@@ -343,11 +343,5 @@ healthchecksdb
 
 # ------------------------------------------------------------
 
-# 包含主题解锁、加密解密等部分的代码
-ModSecret.vb
-ModSetup.vb
-PageOtherAbout.*
-PageOtherTest.*
-PageSetupUI.*
-# 开发者工具
+MaskFiles/
 ModDevelop.vb

+ 45 - 0
Plain Craft Launcher 2.sln

@@ -0,0 +1,45 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.2.32616.157
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "Plain Craft Launcher 2", "Plain Craft Launcher 2\Plain Craft Launcher 2.vbproj", "{4499F2D2-18EF-4238-B1F0-7BD547AFF925}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Releaser", "Releaser", "{0FB7B07C-83E1-477E-B05B-C298304748BC}"
+	ProjectSection(SolutionItems) = preProject
+	EndProjectSection
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "解决方案项", "解决方案项", "{E9455DAD-1E69-4848-98A3-528C8DD5517C}"
+	ProjectSection(SolutionItems) = preProject
+	EndProjectSection
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Beta|Any CPU = Beta|Any CPU
+		Debug|Any CPU = Debug|Any CPU
+		Release|Any CPU = Release|Any CPU
+		ReleaseUpdate|Any CPU = ReleaseUpdate|Any CPU
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{4499F2D2-18EF-4238-B1F0-7BD547AFF925}.Beta|Any CPU.ActiveCfg = BETA|Any CPU
+		{4499F2D2-18EF-4238-B1F0-7BD547AFF925}.Beta|Any CPU.Build.0 = BETA|Any CPU
+		{4499F2D2-18EF-4238-B1F0-7BD547AFF925}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{4499F2D2-18EF-4238-B1F0-7BD547AFF925}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{4499F2D2-18EF-4238-B1F0-7BD547AFF925}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{4499F2D2-18EF-4238-B1F0-7BD547AFF925}.Release|Any CPU.Build.0 = Release|Any CPU
+		{4499F2D2-18EF-4238-B1F0-7BD547AFF925}.ReleaseUpdate|Any CPU.ActiveCfg = ReleaseUpdate|Any CPU
+		{4499F2D2-18EF-4238-B1F0-7BD547AFF925}.ReleaseUpdate|Any CPU.Build.0 = ReleaseUpdate|Any CPU
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+	GlobalSection(ExtensibilityGlobals) = postSolution
+		SolutionGuid = {838A572E-025C-4A2B-B682-68732EC0FE76}
+	EndGlobalSection
+	GlobalSection(Performance) = preSolution
+		HasPerformanceSessions = true
+	EndGlobalSection
+	GlobalSection(Performance) = preSolution
+		HasPerformanceSessions = true
+	EndGlobalSection
+EndGlobal

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

@@ -12,7 +12,7 @@ Public Class Application
         Try
             ModDevelop.Start()
         Catch ex As Exception
-            Log(ex, "开发者模式测试出错", LogLevel.Feedback)
+            Log(ex, "开发者模式测试出错", LogLevel.Msgbox)
         End Try
     End Sub
 #End If

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

@@ -595,7 +595,7 @@ Public Module ModBase
         Try
             Dim parentKey As Microsoft.Win32.RegistryKey, softKey As Microsoft.Win32.RegistryKey
             parentKey = My.Computer.Registry.CurrentUser
-            softKey = parentKey.OpenSubKey("Software\PCL", True)
+            softKey = parentKey.OpenSubKey("Software\" & RegFolder, True)
             If softKey Is Nothing Then
                 ReadReg = DefaultValue '不存在则返回默认值
             Else
@@ -616,8 +616,8 @@ Public Module ModBase
         Try
             Dim parentKey As Microsoft.Win32.RegistryKey, softKey As Microsoft.Win32.RegistryKey
             parentKey = My.Computer.Registry.CurrentUser
-            softKey = parentKey.OpenSubKey("Software\PCL", True)
-            If softKey Is Nothing Then softKey = parentKey.CreateSubKey("Software\PCL") '如果不存在就创建  
+            softKey = parentKey.OpenSubKey("Software\" & RegFolder, True)
+            If softKey Is Nothing Then softKey = parentKey.CreateSubKey("Software\" & RegFolder) '如果不存在就创建  
             softKey.SetValue(Key, Value)
         Catch ex As Exception
             Log(ex, "写入注册表出错:" & Key, If(ShowException, LogLevel.Hint, LogLevel.Developer))

+ 0 - 23
Plain Craft Launcher 2/Modules/Base/ModValidate.vb

@@ -355,26 +355,3 @@ Fin:
         Return ""
     End Function
 End Class
-
-''' <summary>
-''' 敏感词过滤。
-''' </summary>
-Public Class ValidateFilter
-    Inherits Validate
-    Private Shared Excepts As String() = SecretDecrypt(SecretSensitiveWordsRaw).Split("|")
-    Public Sub New()
-    End Sub '用于 XAML 初始化
-    Public Overrides Function Validate(Str As String) As String
-        '提取无间隔符的字符串
-        Dim RealStr As String = ""
-        For Each St In If(Str, "").ToLower
-            If String.IsNullOrWhiteSpace(St.ToString) OrElse ("!@#$%^&*()_+-={}[]|\;':"",./<>? ~ ·!¥…()—,。、《》?‘;:【】{}" & vbLQ & vbRQ).ToCharArray.Contains(St) Then Continue For
-            RealStr += St
-        Next
-        '检查
-        For Each Except In Excepts
-            If RealStr.Contains(Except) Then Return "存在敏感内容!"
-        Next
-        Return ""
-    End Function
-End Class

+ 239 - 0
Plain Craft Launcher 2/Modules/ModSecret.vb

@@ -0,0 +1,239 @@
+'由于包含加解密等安全信息,本文件中的部分代码已被删除
+
+Imports System.Net
+Imports System.Reflection
+Imports System.Security.Cryptography
+
+Friend Module ModSecret
+
+#Region "杂项"
+
+    '在开源内容的注册表键与普通内容的注册表键隔离
+    Public Const RegFolder As String = "PCLDebug"
+
+    Friend Sub SecretOnApplicationStart()
+        '提升 UI 线程优先级
+        Thread.CurrentThread.Priority = ThreadPriority.Highest
+        '确保 .NET Framework 版本
+        Try
+            Dim VersionTest As New FormattedText("", Globalization.CultureInfo.CurrentCulture, FlowDirection.LeftToRight, Fonts.SystemTypefaces.First, 96, New MyColor, DPI)
+        Catch ex As UriFormatException '修复 #3555
+            Environment.SetEnvironmentVariable("windir", Environment.GetEnvironmentVariable("SystemRoot"), EnvironmentVariableTarget.User)
+            Dim VersionTest As New FormattedText("", Globalization.CultureInfo.CurrentCulture, FlowDirection.LeftToRight, Fonts.SystemTypefaces.First, 96, New MyColor, DPI)
+        End Try
+        '检测当前文件夹权限
+        Try
+            Directory.CreateDirectory(Path & "PCL")
+        Catch ex As Exception
+            MsgBox($"PCL 无法创建 PCL 文件夹({Path & "PCL"}),请尝试:" & vbCrLf &
+                  "1. 将 PCL 移动到其他文件夹" & If(Path.StartsWithF("C:", True), ",例如 C 盘和桌面以外的其他位置。", "。") & vbCrLf &
+                  "2. 删除当前目录中的 PCL 文件夹,然后再试。" & vbCrLf &
+                  "3. 右键 PCL 选择属性,打开 兼容性 中的 以管理员身份运行此程序。",
+                MsgBoxStyle.Critical, "运行环境错误")
+            Environment.[Exit](Result.Cancel)
+        End Try
+        If Not CheckPermission(Path & "PCL") Then
+            MsgBox("PCL 没有对当前文件夹的写入权限,请尝试:" & vbCrLf &
+                  "1. 将 PCL 移动到其他文件夹" & If(Path.StartsWithF("C:", True), ",例如 C 盘和桌面以外的其他位置。", "。") & vbCrLf &
+                  "2. 删除当前目录中的 PCL 文件夹,然后再试。" & vbCrLf &
+                  "3. 右键 PCL 选择属性,打开 兼容性 中的 以管理员身份运行此程序。",
+                MsgBoxStyle.Critical, "运行环境错误")
+            Environment.[Exit](Result.Cancel)
+        End If
+        '开源版本提示
+        MsgBox($"该版本中不包含以下特性:
+- CurseForge 查询:需要 API Key(你可以申请一个,然后添加到 SecretHeadersSign 方法中)
+- 更新与联网通知:避免滥用隐患
+- 主题切换:这是需要赞助解锁的纪念性质的功能,别让赞助者太伤心啦
+- 百宝箱:开发早期往里面塞了些开发工具,整理起来太麻烦了,干脆噶了", MsgBoxStyle.Information, "开源版本说明")
+    End Sub
+
+    ''' <summary>
+    ''' 获取设备标识码。
+    ''' </summary>
+    Friend Function SecretGetUniqueAddress() As String
+        Return "0000-0000-0000-0000"
+    End Function
+
+    Friend Sub SecretLaunchJvmArgs(ByRef DataList As List(Of String))
+        Dim DataJvmCustom As String = Setup.Get("VersionAdvanceJvm", Version:=McVersionCurrent)
+        DataList.Insert(0, If(DataJvmCustom = "", Setup.Get("LaunchAdvanceJvm"), DataJvmCustom)) '可变 JVM 参数
+        McLaunchLog("当前剩余内存:" & Math.Round(My.Computer.Info.AvailablePhysicalMemory / 1024 / 1024 / 1024 * 10) / 10 & "G")
+        DataList.Add("-Xmn" & Math.Floor(PageVersionSetup.GetRam(McVersionCurrent) * 1024 * 0.15) & "m")
+        DataList.Add("-Xmx" & Math.Floor(PageVersionSetup.GetRam(McVersionCurrent) * 1024) & "m")
+        If Not DataList.Any(Function(d) d.Contains("-Dlog4j2.formatMsgNoLookups=true")) Then DataList.Add("-Dlog4j2.formatMsgNoLookups=true")
+    End Sub
+
+    ''' <summary>
+    ''' 打码字符串中的 AccessToken。
+    ''' </summary>
+    Friend Function SecretFilter(Raw As String, FilterChar As Char) As String
+        '打码 "accessToken " 后的内容
+        If Raw.Contains("accessToken ") Then
+            For Each Token In RegexSearch(Raw, "(?<=accessToken ([^ ]{5}))[^ ]+(?=[^ ]{5})")
+                Raw = Raw.Replace(Token, New String(FilterChar, Token.Count))
+            Next
+        End If
+        '打码当前登录的结果
+        Dim AccessToken As String = McLoginLoader.Output.AccessToken
+        If AccessToken Is Nothing OrElse AccessToken.Length < 10 OrElse Not Raw.ContainsF(AccessToken, True) OrElse
+            McLoginLoader.Output.Uuid = McLoginLoader.Output.AccessToken Then 'UUID 和 AccessToken 一样则不打码
+            Return Raw
+        Else
+            Return Raw.Replace(AccessToken, Left(AccessToken, 5) & New String(FilterChar, AccessToken.Length - 10) & Right(AccessToken, 5))
+        End If
+    End Function
+
+#End Region
+
+#Region "网络鉴权"
+
+    Friend Function SecretCdnSign(UrlWithMark As String)
+        '只处理以 {CDN} 结尾的链接
+        If Not UrlWithMark.EndsWithF("{CDN}") Then Return UrlWithMark
+        Return UrlWithMark.Replace("{CDN}", "").Replace(" ", "%20")
+    End Function
+    ''' <summary>
+    ''' 设置 Headers 的 UA、Referer。
+    ''' </summary>
+    Friend Sub SecretHeadersSign(Url As String, ByRef Client As CookieWebClient, Optional UseBrowserUserAgent As Boolean = False)
+        If ApplicationStartTick < 1 Then Return '禁止在没有运行程序的情况下通过反射调用
+        If UseBrowserUserAgent Then
+            Client.Headers("User-Agent") = "PCL2/" & VersionStandardCode & " Mozilla/5.0 AppleWebKit/537.36 Chrome/63.0.3239.132 Safari/537.36"
+        Else
+            Client.Headers("User-Agent") = "PCL2/" & VersionStandardCode
+        End If
+        Client.Headers("Referer") = "http://" & VersionCode & ".pcl2.server/"
+        '如果你有 CurseForge API Key,请添加到 Headers 中,以恢复对 CurseForge 的访问
+    End Sub
+    ''' <summary>
+    ''' 设置 Headers 的 UA、Referer。
+    ''' </summary>
+    Friend Sub SecretHeadersSign(Url As String, ByRef Request As HttpWebRequest, Optional UseBrowserUserAgent As Boolean = False)
+        If ApplicationStartTick < 1 Then Return '禁止在没有运行程序的情况下通过反射调用
+        If UseBrowserUserAgent Then
+            Request.UserAgent = "PCL2/" & VersionStandardCode & " Mozilla/5.0 AppleWebKit/537.36 Chrome/63.0.3239.132 Safari/537.36"
+        Else
+            Request.UserAgent = "PCL2/" & VersionStandardCode
+        End If
+        Request.Referer = "http://" & VersionCode & ".pcl2.server/"
+        '如果你有 CurseForge API Key,请添加到 Headers 中,以恢复对 CurseForge 的访问
+    End Sub
+
+#End Region
+
+#Region "字符串加解密"
+
+    ''' <summary>
+    ''' 获取八位密钥。
+    ''' </summary>
+    Private Function SecretKeyGet(Key As String) As String
+        Return "00000000"
+    End Function
+    ''' <summary>
+    ''' 加密字符串。
+    ''' </summary>
+    Friend Function SecretEncrypt(SourceString As String, Optional Key As String = "") As String
+        Key = SecretKeyGet(Key)
+        Dim btKey As Byte() = Encoding.UTF8.GetBytes(Key)
+        Dim btIV As Byte() = Encoding.UTF8.GetBytes("87160295")
+        Dim des As New DESCryptoServiceProvider
+        Using MS As New MemoryStream
+            Dim inData As Byte() = Encoding.UTF8.GetBytes(SourceString)
+            Using cs As New CryptoStream(MS, des.CreateEncryptor(btKey, btIV), CryptoStreamMode.Write)
+                cs.Write(inData, 0, inData.Length)
+                cs.FlushFinalBlock()
+                Return Convert.ToBase64String(MS.ToArray())
+            End Using
+        End Using
+    End Function
+    ''' <summary>
+    ''' 解密字符串。
+    ''' </summary>
+    Friend Function SecretDecrypt(SourceString As String, Optional Key As String = "") As String
+        Key = SecretKeyGet(Key)
+        Dim btKey As Byte() = Encoding.UTF8.GetBytes(Key)
+        Dim btIV As Byte() = Encoding.UTF8.GetBytes("87160295")
+        Dim des As New DESCryptoServiceProvider
+        Using MS As New MemoryStream
+            Dim inData As Byte() = Convert.FromBase64String(SourceString)
+            Using cs As New CryptoStream(MS, des.CreateDecryptor(btKey, btIV), CryptoStreamMode.Write)
+                cs.Write(inData, 0, inData.Length)
+                cs.FlushFinalBlock()
+                Return Encoding.UTF8.GetString(MS.ToArray())
+            End Using
+        End Using
+    End Function
+
+#End Region
+
+#Region "主题"
+
+    Public Color1 As New MyColor(52, 61, 74)
+    Public Color2 As New MyColor(11, 91, 203)
+    Public Color3 As New MyColor(19, 112, 243)
+    Public Color4 As New MyColor(72, 144, 245)
+    Public Color5 As New MyColor(150, 192, 249)
+    Public Color6 As New MyColor(213, 230, 253)
+    Public Color7 As New MyColor(222, 236, 253)
+    Public Color8 As New MyColor(234, 242, 254)
+    Public ColorBg0 As New MyColor(150, 192, 249)
+    Public ColorBg1 As New MyColor(190, Color7)
+    Public ColorGray1 As New MyColor(64, 64, 64)
+    Public ColorGray2 As New MyColor(115, 115, 115)
+    Public ColorGray3 As New MyColor(140, 140, 140)
+    Public ColorGray4 As New MyColor(166, 166, 166)
+    Public ColorGray5 As New MyColor(204, 204, 204)
+    Public ColorGray6 As New MyColor(235, 235, 235)
+    Public ColorGray7 As New MyColor(240, 240, 240)
+    Public ColorGray8 As New MyColor(245, 245, 245)
+    Public ColorSemiTransparent As New MyColor(1, Color8)
+
+    Public ThemeNow As Integer = -1
+    Public ColorHue As Integer = 210, ColorSat As Integer = 85, ColorLightAdjust As Integer = 0, ColorHueTopbarDelta As Object = 0
+    Public ThemeDontClick As Integer = 0
+
+    Public Sub ThemeRefresh(Optional NewTheme As Integer = -1)
+        Hint("该版本中不包含主题功能……")
+    End Sub
+    Public Sub ThemeRefreshMain()
+    End Sub
+    Public Sub ThemeCheckAll(EffectSetup As Boolean)
+    End Sub
+    Public Function ThemeCheckOne(Id As Integer) As Boolean
+        Return True
+    End Function
+    Friend Function ThemeUnlock(Id As Integer, Optional ShowDoubleHint As Boolean = True, Optional UnlockHint As String = Nothing) As Boolean
+        Return False
+    End Function
+    Public Function ThemeCheckGold(Optional Code As String = Nothing) As Boolean
+        Return False
+    End Function
+    Public Function DonateCodeInput() As Boolean?
+    End Function
+
+#End Region
+
+#Region "更新"
+
+    Public IsUpdateStarted As Boolean = False
+    Public IsUpdateWaitingRestart As Boolean = False
+    Public Sub UpdateCheckByButton()
+        Hint("该版本中不包含更新功能……")
+    End Sub
+    Public Sub UpdateStart(BaseUrl As String, Slient As Boolean, Optional ReceivedKey As String = Nothing, Optional ForceValidated As Boolean = False)
+    End Sub
+    Public Sub UpdateRestart(TriggerRestartAndByEnd As Boolean)
+    End Sub
+    Public Sub UpdateReplace(ProcessId As Integer, OldFileName As String, NewFileName As String, TriggerRestart As Boolean)
+    End Sub
+
+#End Region
+
+#Region "联网通知"
+
+    Public ServerLoader As New LoaderTask(Of Integer, Integer)("PCL 服务", Sub() Log("[Server] 该版本中不包含更新通知功能……"), Priority:=ThreadPriority.BelowNormal)
+
+#End Region
+
+End Module

+ 0 - 3
Plain Craft Launcher 2/Pages/PageLink/PageLinkIoi.xaml.vb

@@ -149,9 +149,6 @@ Public Class PageLinkIoi
     ''' 检查某个玩家名是否合法。
     ''' </summary>
     Private Shared Function IsPlayerNameValid(Name As String) As Boolean
-        For Each ValidateRule As Validate In {New ValidateNullOrWhiteSpace, New ValidateLength(0, 20), New ValidateFilter}
-            If Not String.IsNullOrEmpty(ValidateRule.Validate(Name)) Then Return False
-        Next
         Return True
     End Function
 

+ 332 - 0
Plain Craft Launcher 2/Pages/PageOther/PageOtherAbout.xaml

@@ -0,0 +1,332 @@
+<local:MyPageRight
+    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+    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:Class="PageOtherAbout"
+    PanScroll="{Binding ElementName=PanBack}" RenderOptions.BitmapScalingMode="LowQuality">
+    <local:MyScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled" x:Name="PanBack">
+        <StackPanel x:Name="PanMain" Margin="25,10" Grid.IsSharedSizeScope="True">
+            <local:MyCard Margin="0,15" Title="关于">
+                <Grid Margin="21,40,21,16">
+                    <Grid.RowDefinitions>
+                        <RowDefinition Height="45" />
+                        <RowDefinition Height="45" />
+                    </Grid.RowDefinitions>
+                    <Grid.ColumnDefinitions>
+                        <ColumnDefinition Width="40" />
+                        <ColumnDefinition />
+                        <ColumnDefinition Width="150" />
+                    </Grid.ColumnDefinitions>
+                    <local:MyListItem IsHitTestVisible="False" Title="龙腾猫跃" Margin="-5,0,15,0" Info="Plain Craft Launcher 的作者!" Grid.Row="0" Grid.Column="1" />
+                    <local:MyListItem IsHitTestVisible="False" Title="Plain Craft Launcher 2" Margin="-5,0,15,0" Info="当前版本:%VERSION%(%VERSIONCODE%.%BRANCH%)" Grid.Row="1" Grid.Column="1" x:Name="ItemAboutPcl" />
+                    <Image Source="/Plain Craft Launcher 2;component/Images/Heads/Logo.png" Grid.Row="1" Margin="3">
+                        <Image.Clip>
+                            <EllipseGeometry Center="17 17" RadiusX="17" RadiusY="17" />
+                        </Image.Clip>
+                    </Image>
+                    <Image Source="/Plain Craft Launcher 2;component/Images/Heads/LTCat.jpg" Grid.Row="0" Margin="3">
+                        <Image.Clip>
+                            <EllipseGeometry Center="17 17" RadiusX="17" RadiusY="17" />
+                        </Image.Clip>
+                    </Image>
+                    <local:MyButton Text="赞助作者" Grid.Column="2" Grid.Row="0" Height="35" EventType="打开网页" EventData="https://afdian.net/a/LTCat" />
+                    <local:MyButton Text="查看源代码" Grid.Column="2" Grid.Row="1" Height="35" EventType="打开网页" EventData="https://github.com/Hex-Dragon/PCL2" />
+                </Grid>
+            </local:MyCard>
+            <local:MyCard Margin="0,0,0,15" Title="特别鸣谢">
+                <Grid Margin="21,40,21,16">
+                    <Grid.RowDefinitions>
+                        <RowDefinition Height="45" />
+                        <RowDefinition Height="45" />
+                        <RowDefinition Height="45" />
+                        <RowDefinition Height="45" />
+                        <RowDefinition Height="45" />
+                        <RowDefinition Height="45" />
+                        <RowDefinition Height="45" />
+                        <RowDefinition Height="45" />
+                    </Grid.RowDefinitions>
+                    <Grid.ColumnDefinitions>
+                        <ColumnDefinition Width="40" />
+                        <ColumnDefinition />
+                        <ColumnDefinition Width="150" />
+                    </Grid.ColumnDefinitions>
+                    <local:MyListItem Title="bangbang93" Margin="-5,0,15,0" IsHitTestVisible="False" Info="提供 BMCLAPI 镜像源和 Forge 安装工具,详见 https://bmclapi.bangbang93.com" Grid.Row="0" Grid.Column="1" />
+                    <local:MyButton x:Name="BtnAboutBmclapi" Text="赞助镜像源" Grid.Row="0" Grid.Column="2" Height="35" />
+                    <local:MyListItem Title="MC 百科" Margin="-5,0,0,0" IsHitTestVisible="False" Grid.ColumnSpan="2" Info="提供了 Mod 名称的中文翻译和更多相关信息!" Grid.Row="1" Grid.Column="1" />
+                    <local:MyButton x:Name="BtnAboutWiki" Text="打开百科" Grid.Row="1" Grid.Column="2" Height="35" />
+                    <local:MyListItem Title="00ll00" Margin="-5,0,0,0" IsHitTestVisible="False" Grid.ColumnSpan="2" Info="提供了 Java Launch Wrapper 和一些重要服务支持!" Grid.Row="2" Grid.Column="1" />
+                    <local:MyListItem Title="DoodleHuang" Margin="-5,0,0,0" IsHitTestVisible="False" Grid.ColumnSpan="2" Info="提供了部分很难找到的 Minecraft 版本与一些技术支持!" Grid.Row="3" Grid.Column="1" />
+                    <local:MyListItem Title="Patrick" Margin="-5,0,0,0" IsHitTestVisible="False" Grid.ColumnSpan="2" Info="设计并制作了 PCL 图标,让我从做图标的水深火热中得到了解脱……" Grid.Row="4" Grid.Column="1" />
+                    <local:MyListItem Title="Hao_Tian" Margin="-5,0,0,0" IsHitTestVisible="False" Grid.ColumnSpan="2" Info="在内测中找出了一大堆没人想得到的诡异 Bug,有非同寻常的 Bug 体质" Grid.Row="5" Grid.Column="1" />
+                    <local:MyListItem Title="Minecraft 中文论坛" Margin="-5,0,15,0" IsHitTestVisible="False" Info="虽然已经关站了,但感谢此前提供了 MCBBS 镜像源……" Grid.Row="6" Grid.Column="1" />
+                    <local:MyListItem Title="PCL 内群的各位" Margin="-5,0,0,0" IsHitTestVisible="False" Grid.ColumnSpan="2" Info="感谢内群的沙雕网友们这么久以来对我和 PCL 的支持与鼓励!" Grid.Row="7" Grid.Column="1" />
+                    <Image Source="/Plain Craft Launcher 2;component/Images/Heads/bangbang93.png" Grid.Row="0" Margin="3">
+                        <Image.Clip>
+                            <EllipseGeometry Center="17 17" RadiusX="17" RadiusY="17" />
+                        </Image.Clip>
+                    </Image>
+                    <Image Source="/Plain Craft Launcher 2;component/Images/Heads/wiki.png" Grid.Row="1" Margin="3">
+                        <Image.Clip>
+                            <EllipseGeometry Center="17 17" RadiusX="17" RadiusY="17" />
+                        </Image.Clip>
+                    </Image>
+                    <Image Source="/Plain Craft Launcher 2;component/Images/Heads/00ll00.png" Grid.Row="2" Margin="3">
+                        <Image.Clip>
+                            <EllipseGeometry Center="17 17" RadiusX="17" RadiusY="17" />
+                        </Image.Clip>
+                    </Image>
+                    <Image Source="/Plain Craft Launcher 2;component/Images/Heads/DoodleHuang.png" Grid.Row="3" Margin="3">
+                        <Image.Clip>
+                            <EllipseGeometry Center="17 17" RadiusX="17" RadiusY="17" />
+                        </Image.Clip>
+                    </Image>
+                    <Image Source="/Plain Craft Launcher 2;component/Images/Heads/Patrick.png" Grid.Row="4" Margin="3">
+                        <Image.Clip>
+                            <EllipseGeometry Center="17 17" RadiusX="17" RadiusY="17" />
+                        </Image.Clip>
+                    </Image>
+                    <Image Source="/Plain Craft Launcher 2;component/Images/Heads/Hao_Tian.jpg" Grid.Row="5" Margin="3">
+                        <Image.Clip>
+                            <EllipseGeometry Center="17 17" RadiusX="17" RadiusY="17" />
+                        </Image.Clip>
+                    </Image>
+                    <Image Source="/Plain Craft Launcher 2;component/Images/Heads/MCBBS.png" Grid.Row="6" Margin="3">
+                        <Image.Clip>
+                            <EllipseGeometry Center="17 17" RadiusX="17" RadiusY="17" />
+                        </Image.Clip>
+                    </Image>
+                    <Image Source="/Plain Craft Launcher 2;component/Images/Heads/PCL2.png" Grid.Row="7" Margin="3">
+                        <Image.Clip>
+                            <EllipseGeometry Center="17 17" RadiusX="17" RadiusY="17" />
+                        </Image.Clip>
+                    </Image>
+                </Grid>
+            </local:MyCard>
+            <local:MyCard Margin="0,0,0,15" Title="赞助者">
+                <StackPanel Margin="25,40,10,20">
+                    <TextBlock HorizontalAlignment="Left" Text="以下是 2024 年 4 月的高级赞助者们!感谢各位对 PCL 和伟大的咕咕咕事业的支持!" Margin="0,0,25,5.5" TextTrimming="None" TextWrapping="WrapWithOverflow" />
+                    <WrapPanel Margin="0,0,0,10">
+                        <TextBlock Width="120" Margin="0,1.5" Text="道士师傅" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="狗群主群狗" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="Alioth陳" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="shyzysa" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="死んだライオン" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="mc沙漠之狐隆帅" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="123456胡杨" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="香蕉风味" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="毛哥" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="leon" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="clnb" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="123" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="lihaoran0313" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="贵友" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="蒸福啦" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="狐狸涩" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="皓垣Faraway" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="冷月溪影" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="狮青椒" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="多金的爸爸" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="陈师傅" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="王舒心" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="Akn123" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="Dfkeit" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="CloudLonngLee" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="别再错过月亮了" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="特别周冠宇" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="臻榛搸殝" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="GT" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="夜也" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="is步行街" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="狮心人面人" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="小刀李" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="空染" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="歪歪的示波器" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="SYF" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="帝王尬笑" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="DarkKCat" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="我将如闪电般归来" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="TSLOLY" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="JackX" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="挽安" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="花衔镜" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="玄言" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="硫酸梅" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="ムーの小雨" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="潘某" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="颐葭" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="Vaincre_VV" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="小明爱睡觉" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="YHLin" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="翁yy" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="午睡不爱睡觉" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="tanglin" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="Quittskii" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="W2erty" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="Chris_Dream" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="sanrenxin" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="BBK" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="京北的洋" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="喵木仔" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="abstudio" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="洛惜惜缘" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="熊心万花镜" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="tianguaren" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="bitlogi" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="彬彬爆" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="超爱小辣椒" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="Kkigoo" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="于书墨" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="御坂1354号" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="t7fihb8" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="44.5GB" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="寰宇第一激推希儿" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="拳打羽酱脚踢军师" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="戌亥ピカ" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="乔巴诺" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="LING-DIAN" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="你太迷人" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="夏目龙羽" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="小烨爱吃尖椒鸡" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="七色的魔法死" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="沫世" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="我的神a啊" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="转角" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="做强做盛.步步升高" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="火箭空降" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="嚯嚯嚯哈哈哈哈" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="醉梦" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="zzyd" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="御影" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="Xephyrs" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="Sovtheia" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="CRANK" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="本太子的作业满天飞" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="超级无敌旋风小猪猪" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="泽希尔·S+" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="erliang_ya" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="明酱酱" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="玐煲粥" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="The_follow" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="王八" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="joker" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="north-cool" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="JJ" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="小石" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="XiaomQ928" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="Fly with You!!" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="海上乘鲸客" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="miku" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="小雯" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="woainad" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="wqaycm" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="白豆" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="Alex" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="大地风暴" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="曾and田某人" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="栀玖夕夏" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="小卌丯" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="旧言" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="?的不行  ?的难受" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="ElliottZChan" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="沐子冷落" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="_Blessing" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="友酒歌" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="鲸以歌" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="花好月圆" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="n3v3r" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="七星灯" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="Theia" />
+
+                    </WrapPanel>
+                    <Grid Height="35">
+                        <Grid.ColumnDefinitions>
+                            <ColumnDefinition Width="Auto" SharedSizeGroup="Button" />
+                            <ColumnDefinition Width="Auto" SharedSizeGroup="Button" />
+                            <ColumnDefinition Width="Auto" SharedSizeGroup="Button" />
+                        </Grid.ColumnDefinitions>
+                        <local:MyButton x:Name="BtnDonateOutput" Grid.Column="0" MinWidth="140" Text="生成解锁码" Padding="13,0" Margin="0,0,20,0" HorizontalAlignment="Left" ColorType="Highlight" Visibility="Collapsed" />
+                        <local:MyButton x:Name="BtnDonateDonate" Grid.Column="0" MinWidth="140" Text="赞助作者" Padding="13,0" Margin="0,0,20,0" HorizontalAlignment="Left" ColorType="Highlight" EventType="打开网页" EventData="https://afdian.net/a/LTCat" />
+                        <local:MyButton x:Name="BtnDonateCopy" Grid.Column="1" MinWidth="140" Text="复制识别码" Padding="13,0" Margin="0,0,20,0" HorizontalAlignment="Left" />
+                        <local:MyButton x:Name="BtnDonateInput" Grid.Column="2" MinWidth="140" Text="输入解锁码" Padding="13,0" Margin="0,0,20,0" HorizontalAlignment="Left" />
+                    </Grid>
+                </StackPanel>
+            </local:MyCard>
+            <local:MyCard Margin="0,0,0,15" Title="法律信息" IsSwaped="True" CanSwap="True">
+                <StackPanel Margin="25,39,23,20">
+                    <TextBlock Text="隐私说明" TextWrapping="Wrap" Margin="0,6,0,4" FontWeight="Bold" />
+                    <TextBlock Margin="0,0,0,2" LineHeight="17" Text="本软件会汇报自己的版本名与版本号,以统计用户数量与各版本的用户数量占比。除此之外,本软件不会上传您的任何信息。&#13;若您能提供未经外部修改的本软件本体上传隐私信息的确凿证据,开发者会向您支付 PCL 开发所获全部净收入。" TextWrapping="Wrap" />
+                    <TextBlock Text="其他信息" TextWrapping="Wrap" Margin="0,12,0,4" FontWeight="Bold" />
+                    <TextBlock Margin="0,0,0,2" LineHeight="17" Text="Copyright © 龙腾猫跃 2016. All Rights Reserved.&#13;计算机软件著作权登记号:2020SR0875133&#13;违法违规行为举报投诉邮箱:[email protected]" TextWrapping="Wrap" />
+                    <StackPanel Orientation="Horizontal" Height="35" HorizontalAlignment="Left" Margin="0,12,0,0">
+                        <local:MyButton Text="用户协议与免责声明" Width="170" Padding="13,0" Margin="0,0,20,0" ColorType="Highlight" EventType="打开网页" EventData="https://shimo.im/docs/rGrd8pY8xWkt6ryW" />
+                        <local:MyButton Text="查看源代码" Width="140" Padding="13,0" EventType="打开网页" EventData="https://github.com/Hex-Dragon/PCL2" />
+                    </StackPanel>
+                </StackPanel>
+            </local:MyCard>
+            <local:MyCard Margin="0,0,0,15" Title="许可与版权声明" IsSwaped="True" CanSwap="True">
+                <Grid Margin="25,42,23,4">
+                    <Grid.ColumnDefinitions>
+                        <ColumnDefinition Width="Auto" />
+                        <ColumnDefinition Width="20" />
+                        <ColumnDefinition Width="Auto" />
+                        <ColumnDefinition />
+                    </Grid.ColumnDefinitions>
+                    <Grid.RowDefinitions>
+                        <RowDefinition Height="Auto" />
+                        <RowDefinition Height="60" />
+                        <RowDefinition Height="Auto" />
+                        <RowDefinition Height="60" />
+                        <RowDefinition Height="Auto" />
+                        <RowDefinition Height="60" />
+                        <RowDefinition Height="Auto" />
+                        <RowDefinition Height="60" />
+                        <RowDefinition Height="Auto" />
+                        <RowDefinition Height="60" />
+                        <RowDefinition Height="Auto" />
+                        <RowDefinition Height="60" />
+                        <RowDefinition Height="Auto" />
+                    </Grid.RowDefinitions>
+                    <TextBlock Grid.Row="0" Grid.Column="0" Text="Java Launch Wrapper" TextWrapping="Wrap" FontWeight="Bold" />
+                    <TextBlock Grid.Row="0" Grid.Column="2" Grid.ColumnSpan="2" Text="Copyright © 2022 00ll00&#xa;Licensed under the MIT License." TextWrapping="Wrap" />
+                    <local:MyButton Grid.Row="1" Grid.Column="2" MinWidth="140" Text="查看来源网站" Padding="13,0" Margin="0,7,20,18" HorizontalAlignment="Left"
+                                    EventType="打开网页" EventData="https://github.com/00ll00/java_launch_wrapper" />
+                    <local:MyButton Grid.Row="1" Grid.Column="3" MinWidth="140" Text="查看许可文档" Padding="13,0" Margin="0,7,20,18" HorizontalAlignment="Left"
+                                    EventType="打开网页" EventData="https://github.com/00ll00/java_launch_wrapper?tab=MIT-1-ov-file#readme" />
+
+                    <TextBlock Grid.Row="2" Grid.Column="0" Text="Newtonsoft.Json" TextWrapping="Wrap" FontWeight="Bold" />
+                    <TextBlock Grid.Row="2" Grid.Column="2" Grid.ColumnSpan="2" Text="Copyright © 2007 James Newton-King&#xa;Licensed under the MIT License." TextWrapping="Wrap" />
+                    <local:MyButton Grid.Row="3" Grid.Column="2" MinWidth="140" Text="查看来源网站" Padding="13,0" Margin="0,7,20,18" HorizontalAlignment="Left"
+                                    EventType="打开网页" EventData="https://www.newtonsoft.com/json" />
+                    <local:MyButton Grid.Row="3" Grid.Column="3" MinWidth="140" Text="查看许可文档" Padding="13,0" Margin="0,7,20,18" HorizontalAlignment="Left"
+                                    EventType="打开网页" EventData="https://opensource.org/licenses/MIT" />
+                    
+                    <TextBlock Grid.Row="4" Grid.Column="0" Text="NAudio" TextWrapping="Wrap" FontWeight="Bold" />
+                    <TextBlock Grid.Row="4" Grid.Column="2" Grid.ColumnSpan="2" Text="Copyright © 2015 Mark Heath ([email protected])&#xa;Licensed under the MIT License." TextWrapping="Wrap" />
+                    <local:MyButton Grid.Row="5" Grid.Column="2" MinWidth="140" Text="查看来源网站" Padding="13,0" Margin="0,7,20,18" HorizontalAlignment="Left"
+                                    EventType="打开网页" EventData="https://github.com/naudio/NAudio" />
+                    <local:MyButton Grid.Row="5" Grid.Column="3" MinWidth="140" Text="查看许可文档" Padding="13,0" Margin="0,7,20,18" HorizontalAlignment="Left" 
+                                    EventType="打开网页" EventData="https://github.com/naudio/NAudio/blob/master/license.txt" />
+                    
+                    <TextBlock Grid.Row="6" Grid.Column="0" Text="Ookii.Dialogs" TextWrapping="Wrap" FontWeight="Bold" />
+                    <TextBlock Grid.Row="6" Grid.Column="2" Grid.ColumnSpan="2" Text="Copyright © 2009 Sven Groot (Ookii.org)" TextWrapping="Wrap" />
+                    <local:MyButton Grid.Row="7" Grid.Column="2" MinWidth="140" Text="查看来源网站" Padding="13,0" Margin="0,7,20,18" HorizontalAlignment="Left"
+                                    EventType="打开网页" EventData="https://www.ookii.org/Software/Dialogs/" />
+                    <local:MyButton Grid.Row="7" Grid.Column="3" MinWidth="140" Text="查看许可文档" Padding="13,0" Margin="0,7,20,18" HorizontalAlignment="Left"
+                                    EventType="打开网页" EventData="https://github.com/caioproiete/ookii-dialogs-wpf/blob/master/LICENSE" />
+                    
+                    <TextBlock Grid.Row="8" Grid.Column="0" Text="Iconmonstr" TextWrapping="Wrap" FontWeight="Bold" />
+                    <TextBlock Grid.Row="8" Grid.Column="2" Grid.ColumnSpan="2" Text="Copyright © 2019 iconmonstr (Alexander Kahlkopf)" TextWrapping="Wrap" />
+                    <local:MyButton Grid.Row="9" Grid.Column="2" MinWidth="140" Text="查看来源网站" Padding="13,0" Margin="0,7,20,18" HorizontalAlignment="Left"
+                                    EventType="打开网页" EventData="https://iconmonstr.com/" />
+                    <local:MyButton Grid.Row="9" Grid.Column="3" MinWidth="140" Text="查看许可文档" Padding="13,0" Margin="0,7,20,18" HorizontalAlignment="Left"
+                                    EventType="打开网页" EventData="https://iconmonstr.com/license/" />
+                    
+                    <TextBlock Grid.Row="10" Grid.Column="0" Text="Iconfont" TextWrapping="Wrap" FontWeight="Bold" />
+                    <TextBlock Grid.Row="10" Grid.Column="2" Grid.ColumnSpan="2" Text="Copyright © ALIMAMA MUX, powered by alimama THX." TextWrapping="Wrap" />
+                    <local:MyButton Grid.Row="11" Grid.Column="2" MinWidth="140" Text="查看原网站" Padding="13,0" Margin="0,7,20,18" HorizontalAlignment="Left"
+                                    EventType="打开网页" EventData="https://www.iconfont.cn/" />
+                </Grid>
+            </local:MyCard>
+        </StackPanel>
+    </local:MyScrollViewer>
+</local:MyPageRight>

+ 40 - 0
Plain Craft Launcher 2/Pages/PageOther/PageOtherAbout.xaml.vb

@@ -0,0 +1,40 @@
+Public Class PageOtherAbout
+
+    Private Shadows IsLoaded As Boolean = False
+    Private Sub PageOtherAbout_Loaded(sender As Object, e As RoutedEventArgs) Handles Me.Loaded
+
+        '重复加载部分
+        PanBack.ScrollToHome()
+
+        '非重复加载部分
+        If IsLoaded Then Exit Sub
+        IsLoaded = True
+
+        ItemAboutPcl.Info = ItemAboutPcl.Info.Replace("%VERSION%", VersionDisplayName).Replace("%VERSIONCODE%", VersionCode).Replace("%BRANCH%", VersionBranchCode)
+#If DEBUG Then
+        BtnDonateDonate.Visibility = Visibility.Collapsed
+        BtnDonateOutput.Visibility = Visibility.Visible
+#End If
+
+    End Sub
+
+    Private Sub BtnAboutBmclapi_Click(sender As Object, e As EventArgs) Handles BtnAboutBmclapi.Click
+        OpenWebsite("https://afdian.net/a/bangbang93")
+    End Sub
+    Private Sub BtnAboutWiki_Click(sender As Object, e As EventArgs) Handles BtnAboutWiki.Click
+        OpenWebsite("https://www.mcmod.cn")
+    End Sub
+    Public Shared Sub CopyUniqueAddress() Handles BtnDonateCopy.Click
+        ClipboardSet(UniqueAddress)
+    End Sub
+    Private Sub DonateCodeInput() Handles BtnDonateInput.Click
+        DonateCodeInput()
+    End Sub
+
+#If DEBUG Then
+    Private Sub BtnDonateOutput_Click(sender As Object, e As EventArgs) Handles BtnDonateOutput.Click
+        DonateCodeGenerate()
+    End Sub
+#End If
+
+End Class

+ 12 - 0
Plain Craft Launcher 2/Pages/PageOther/PageOtherTest.xaml

@@ -0,0 +1,12 @@
+<local:MyPageRight x:Class="PageOtherTest"
+    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
+    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
+    xmlns:local="clr-namespace:PCL"
+    xmlns:sys="clr-namespace:System;assembly=mscorlib"
+    PanScroll="{Binding ElementName=PanBack}">
+    <local:MyScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled" x:Name="PanBack">
+        <TextBlock Text="为便于维护,开源内容中不包含百宝箱功能……" HorizontalAlignment="Center" FontSize="15" Height="30" VerticalAlignment="Center" />
+    </local:MyScrollViewer>
+</local:MyPageRight>

+ 27 - 0
Plain Craft Launcher 2/Pages/PageOther/PageOtherTest.xaml.vb

@@ -0,0 +1,27 @@
+Public Class PageOtherTest
+
+    Public Shared Sub StartCustomDownload(Url As String, FileName As String, Optional Folder As String = Nothing)
+        Hint("为便于维护,开源内容中不包含百宝箱功能……")
+    End Sub
+    Public Shared Sub Jrrp()
+        Hint("为便于维护,开源内容中不包含百宝箱功能……")
+    End Sub
+    Public Shared Sub RubbishClear()
+        Hint("为便于维护,开源内容中不包含百宝箱功能……")
+    End Sub
+    Public Shared Sub MemoryOptimize(ShowHint As Boolean)
+        If ShowHint Then Hint("为便于维护,开源内容中不包含百宝箱功能……")
+    End Sub
+    Public Shared Sub MemoryOptimizeInternal()
+    End Sub
+    Public Shared Function GetRandomCave() As String
+        Return "为便于维护,开源内容中不包含百宝箱功能……"
+    End Function
+    Public Shared Function GetRandomHint() As String
+        Return "为便于维护,开源内容中不包含百宝箱功能……"
+    End Function
+    Public Shared Function GetRandomPresetHint() As String
+        Return "为便于维护,开源内容中不包含百宝箱功能……"
+    End Function
+
+End Class

+ 691 - 0
Plain Craft Launcher 2/Pages/PageSetup/ModSetup.vb

@@ -0,0 +1,691 @@
+Public Class ModSetup
+
+    ''' <summary>
+    ''' 设置的更新号。
+    ''' </summary>
+    Public Const VersionSetup As Integer = 1
+    ''' <summary>
+    ''' 设置列表。
+    ''' </summary>
+    Private ReadOnly SetupDict As New Dictionary(Of String, SetupEntry) From {
+        {"Identify", New SetupEntry("", Source:=SetupSource.Registry)},
+        {"HintDownloadThread", New SetupEntry(False, Source:=SetupSource.Registry)},
+        {"HintNotice", New SetupEntry(0, Source:=SetupSource.Registry)},
+        {"HintDownload", New SetupEntry(0, Source:=SetupSource.Registry)},
+        {"HintInstallBack", New SetupEntry(False, Source:=SetupSource.Registry)},
+        {"HintHide", New SetupEntry(False, Source:=SetupSource.Registry)},
+        {"HintHandInstall", New SetupEntry(False, Source:=SetupSource.Registry)},
+        {"HintBuy", New SetupEntry(False, Source:=SetupSource.Registry)},
+        {"HintClearRubbish", New SetupEntry(0, Source:=SetupSource.Registry)},
+        {"HintUpdateMod", New SetupEntry(False, Source:=SetupSource.Registry)},
+        {"TestSetupReader", New SetupEntry("", Source:=SetupSource.Registry, Encoded:=True)},
+        {"SystemEula", New SetupEntry(False, Source:=SetupSource.Registry)},
+        {"SystemCount", New SetupEntry(0, Source:=SetupSource.Registry, Encoded:=True)},
+        {"SystemLaunchCount", New SetupEntry(0, Source:=SetupSource.Registry, Encoded:=True)},
+        {"SystemLastVersionReg", New SetupEntry(0, Source:=SetupSource.Registry, Encoded:=True)},
+        {"SystemHighestBetaVersionReg", New SetupEntry(0, Source:=SetupSource.Registry, Encoded:=True)},
+        {"SystemHighestAlphaVersionReg", New SetupEntry(0, Source:=SetupSource.Registry, Encoded:=True)},
+        {"SystemSetupVersionReg", New SetupEntry(VersionSetup, Source:=SetupSource.Registry)},
+        {"SystemSetupVersionIni", New SetupEntry(VersionSetup)},
+        {"SystemHelpVersion", New SetupEntry(0, Source:=SetupSource.Registry)},
+        {"SystemDebugMode", New SetupEntry(False, Source:=SetupSource.Registry)},
+        {"SystemDebugAnim", New SetupEntry(9, Source:=SetupSource.Registry)},
+        {"SystemDebugDelay", New SetupEntry(False, Source:=SetupSource.Registry)},
+        {"SystemDebugSkipCopy", New SetupEntry(False, Source:=SetupSource.Registry)},
+        {"SystemSystemCache", New SetupEntry("", Source:=SetupSource.Registry)},
+        {"SystemSystemUpdate", New SetupEntry(0)},
+        {"SystemSystemActivity", New SetupEntry(0)},
+        {"CacheSavedPageUrl", New SetupEntry("", Source:=SetupSource.Registry)},
+        {"CacheSavedPageVersion", New SetupEntry("", Source:=SetupSource.Registry)},
+        {"CacheMsOAuthRefresh", New SetupEntry("", Source:=SetupSource.Registry, Encoded:=True)},
+        {"CacheMsAccess", New SetupEntry("", Source:=SetupSource.Registry, Encoded:=True)},
+        {"CacheMsProfileJson", New SetupEntry("", Source:=SetupSource.Registry, Encoded:=True)},
+        {"CacheMsUuid", New SetupEntry("", Source:=SetupSource.Registry, Encoded:=True)},
+        {"CacheMsName", New SetupEntry("", Source:=SetupSource.Registry, Encoded:=True)},
+        {"CacheNideAccess", New SetupEntry("", Source:=SetupSource.Registry, Encoded:=True)},
+        {"CacheNideClient", New SetupEntry("", Source:=SetupSource.Registry, Encoded:=True)},
+        {"CacheNideUuid", New SetupEntry("", Source:=SetupSource.Registry, Encoded:=True)},
+        {"CacheNideName", New SetupEntry("", Source:=SetupSource.Registry, Encoded:=True)},
+        {"CacheNideUsername", New SetupEntry("", Source:=SetupSource.Registry, Encoded:=True)},
+        {"CacheNidePass", New SetupEntry("", Source:=SetupSource.Registry, Encoded:=True)},
+        {"CacheNideServer", New SetupEntry("", Source:=SetupSource.Registry, Encoded:=True)},
+        {"CacheAuthAccess", New SetupEntry("", Source:=SetupSource.Registry, Encoded:=True)},
+        {"CacheAuthClient", New SetupEntry("", Source:=SetupSource.Registry, Encoded:=True)},
+        {"CacheAuthUuid", New SetupEntry("", Source:=SetupSource.Registry, Encoded:=True)},
+        {"CacheAuthName", New SetupEntry("", Source:=SetupSource.Registry, Encoded:=True)},
+        {"CacheAuthUsername", New SetupEntry("", Source:=SetupSource.Registry, Encoded:=True)},
+        {"CacheAuthPass", New SetupEntry("", Source:=SetupSource.Registry, Encoded:=True)},
+        {"CacheAuthServerServer", New SetupEntry("", Source:=SetupSource.Registry, Encoded:=True)},
+        {"CacheAuthServerName", New SetupEntry("", Source:=SetupSource.Registry, Encoded:=True)},
+        {"CacheAuthServerRegister", New SetupEntry("", Source:=SetupSource.Registry, Encoded:=True)},
+        {"CacheDownloadFolder", New SetupEntry("", Source:=SetupSource.Registry)},
+        {"CacheJavaListVersion", New SetupEntry(0, Source:=SetupSource.Registry)},
+        {"LoginRemember", New SetupEntry(True, Source:=SetupSource.Registry, Encoded:=True)},
+        {"LoginLegacyName", New SetupEntry("", Source:=SetupSource.Registry, Encoded:=True)},
+        {"LoginMsJson", New SetupEntry("{}", Source:=SetupSource.Registry, Encoded:=True)}, '{UserName: OAuthToken, ...}
+        {"LoginNideEmail", New SetupEntry("", Source:=SetupSource.Registry, Encoded:=True)},
+        {"LoginNidePass", New SetupEntry("", Source:=SetupSource.Registry, Encoded:=True)},
+        {"LoginAuthEmail", New SetupEntry("", Source:=SetupSource.Registry, Encoded:=True)},
+        {"LoginAuthPass", New SetupEntry("", Source:=SetupSource.Registry, Encoded:=True)},
+        {"LoginType", New SetupEntry(McLoginType.Legacy, Source:=SetupSource.Registry)},
+        {"LoginPageType", New SetupEntry(0)},
+        {"LaunchSkinID", New SetupEntry("", Source:=SetupSource.Registry)},
+        {"LaunchSkinType", New SetupEntry(0, Source:=SetupSource.Registry)},
+        {"LaunchSkinSlim", New SetupEntry(False, Source:=SetupSource.Registry)},
+        {"LaunchVersionSelect", New SetupEntry("")},
+        {"LaunchFolderSelect", New SetupEntry("")},
+        {"LaunchFolders", New SetupEntry("", Source:=SetupSource.Registry)},
+        {"LaunchArgumentTitle", New SetupEntry("")},
+        {"LaunchArgumentInfo", New SetupEntry("PCL")},
+        {"LaunchArgumentJavaSelect", New SetupEntry("", Source:=SetupSource.Registry)},
+        {"LaunchArgumentJavaAll", New SetupEntry("[]", Source:=SetupSource.Registry)},
+        {"LaunchArgumentIndie", New SetupEntry(0)},
+        {"LaunchArgumentVisible", New SetupEntry(5, Source:=SetupSource.Registry)},
+        {"LaunchArgumentPriority", New SetupEntry(1, Source:=SetupSource.Registry)},
+        {"LaunchArgumentWindowWidth", New SetupEntry(854)},
+        {"LaunchArgumentWindowHeight", New SetupEntry(480)},
+        {"LaunchArgumentWindowType", New SetupEntry(1)},
+        {"LaunchArgumentRam", New SetupEntry(False, Source:=SetupSource.Registry)},
+        {"LaunchAdvanceJvm", New SetupEntry("-XX:+UseG1GC -XX:-UseAdaptiveSizePolicy -XX:-OmitStackTraceInFastThrow -Dfml.ignoreInvalidMinecraftCertificates=True -Dfml.ignorePatchDiscrepancies=True -Dlog4j2.formatMsgNoLookups=true")},
+        {"LaunchAdvanceGame", New SetupEntry("")},
+        {"LaunchAdvanceRun", New SetupEntry("")},
+        {"LaunchAdvanceRunWait", New SetupEntry(True)},
+        {"LaunchAdvanceAssets", New SetupEntry(False)},
+        {"LaunchAdvanceJava", New SetupEntry(False)},
+        {"LaunchRamType", New SetupEntry(0)},
+        {"LaunchRamCustom", New SetupEntry(15)},
+        {"LinkEula", New SetupEntry(False, Source:=SetupSource.Registry)},
+        {"LinkName", New SetupEntry("", Source:=SetupSource.Registry)},
+        {"LinkHiperCertLast", New SetupEntry("", Source:=SetupSource.Registry)},
+        {"LinkHiperCertTime", New SetupEntry("", Source:=SetupSource.Registry)},
+        {"LinkHiperCertWarn", New SetupEntry(True, Source:=SetupSource.Registry)},
+        {"LinkIoiVersion", New SetupEntry(0, Source:=SetupSource.Registry, Encoded:=True)},
+        {"ToolHelpChinese", New SetupEntry(True, Source:=SetupSource.Registry)},
+        {"ToolDownloadThread", New SetupEntry(63, Source:=SetupSource.Registry)},
+        {"ToolDownloadSpeed", New SetupEntry(42, Source:=SetupSource.Registry)},
+        {"ToolDownloadVersion", New SetupEntry(0, Source:=SetupSource.Registry)},
+        {"ToolDownloadTranslate", New SetupEntry(0, Source:=SetupSource.Registry)},
+        {"ToolDownloadKeepModpack", New SetupEntry(False, Source:=SetupSource.Registry)},
+        {"ToolDownloadIgnoreQuilt", New SetupEntry(True, Source:=SetupSource.Registry)},
+        {"ToolDownloadCert", New SetupEntry(True, Source:=SetupSource.Registry)},
+        {"ToolUpdateAlpha", New SetupEntry(0, Source:=SetupSource.Registry, Encoded:=True)},
+        {"ToolUpdateRelease", New SetupEntry(False, Source:=SetupSource.Registry)},
+        {"ToolUpdateSnapshot", New SetupEntry(False, Source:=SetupSource.Registry)},
+        {"ToolUpdateReleaseLast", New SetupEntry("", Source:=SetupSource.Registry)},
+        {"ToolUpdateSnapshotLast", New SetupEntry("", Source:=SetupSource.Registry)},
+        {"UiLauncherTransparent", New SetupEntry(600)}, '避免与 PCL1 设置冲突(UiLauncherOpacity)
+        {"UiLauncherHue", New SetupEntry(180)},
+        {"UiLauncherSat", New SetupEntry(80)},
+        {"UiLauncherDelta", New SetupEntry(90)},
+        {"UiLauncherLight", New SetupEntry(20)},
+        {"UiLauncherTheme", New SetupEntry(0)},
+        {"UiLauncherThemeGold", New SetupEntry("", Source:=SetupSource.Registry, Encoded:=True)},
+        {"UiLauncherThemeHide", New SetupEntry("0|1|2|3|4", Source:=SetupSource.Registry, Encoded:=True)},
+        {"UiLauncherThemeHide2", New SetupEntry("0|1|2|3|4", Source:=SetupSource.Registry, Encoded:=True)},
+        {"UiLauncherLogo", New SetupEntry(True)},
+        {"UiLauncherEmail", New SetupEntry(False)},
+        {"UiBackgroundColorful", New SetupEntry(True)},
+        {"UiBackgroundOpacity", New SetupEntry(1000)},
+        {"UiBackgroundBlur", New SetupEntry(0)},
+        {"UiBackgroundSuit", New SetupEntry(0)},
+        {"UiCustomType", New SetupEntry(0)},
+        {"UiCustomPreset", New SetupEntry(0)},
+        {"UiCustomNet", New SetupEntry("")},
+        {"UiLogoType", New SetupEntry(1)},
+        {"UiLogoText", New SetupEntry("")},
+        {"UiLogoLeft", New SetupEntry(False)},
+        {"UiMusicVolume", New SetupEntry(500)},
+        {"UiMusicStop", New SetupEntry(False)},
+        {"UiMusicStart", New SetupEntry(False)},
+        {"UiMusicRandom", New SetupEntry(True)},
+        {"UiMusicAuto", New SetupEntry(True)},
+        {"UiHiddenPageDownload", New SetupEntry(False)},
+        {"UiHiddenPageLink", New SetupEntry(False)},
+        {"UiHiddenPageSetup", New SetupEntry(False)},
+        {"UiHiddenPageOther", New SetupEntry(False)},
+        {"UiHiddenFunctionSelect", New SetupEntry(False)},
+        {"UiHiddenFunctionHidden", New SetupEntry(False)},
+        {"UiHiddenSetupLaunch", New SetupEntry(False)},
+        {"UiHiddenSetupUi", New SetupEntry(False)},
+        {"UiHiddenSetupLink", New SetupEntry(False)},
+        {"UiHiddenSetupSystem", New SetupEntry(False)},
+        {"UiHiddenOtherHelp", New SetupEntry(False)},
+        {"UiHiddenOtherFeedback", New SetupEntry(False)},
+        {"UiHiddenOtherVote", New SetupEntry(False)},
+        {"UiHiddenOtherAbout", New SetupEntry(False)},
+        {"UiHiddenOtherTest", New SetupEntry(False)},
+        {"VersionAdvanceJvm", New SetupEntry("", Source:=SetupSource.Version)},
+        {"VersionAdvanceGame", New SetupEntry("", Source:=SetupSource.Version)},
+        {"VersionAdvanceAssets", New SetupEntry(0, Source:=SetupSource.Version)},
+        {"VersionAdvanceAssetsV2", New SetupEntry(False, Source:=SetupSource.Version)},
+        {"VersionAdvanceJava", New SetupEntry(False, Source:=SetupSource.Version)},
+        {"VersionAdvanceRun", New SetupEntry("", Source:=SetupSource.Version)},
+        {"VersionAdvanceRunWait", New SetupEntry(True, Source:=SetupSource.Version)},
+        {"VersionRamType", New SetupEntry(2, Source:=SetupSource.Version)},
+        {"VersionRamCustom", New SetupEntry(15, Source:=SetupSource.Version)},
+        {"VersionArgumentTitle", New SetupEntry("", Source:=SetupSource.Version)},
+        {"VersionArgumentInfo", New SetupEntry("", Source:=SetupSource.Version)},
+        {"VersionArgumentIndie", New SetupEntry(-1, Source:=SetupSource.Version)},
+        {"VersionArgumentJavaSelect", New SetupEntry("使用全局设置", Source:=SetupSource.Version)},
+        {"VersionServerEnter", New SetupEntry("", Source:=SetupSource.Version)},
+        {"VersionServerLogin", New SetupEntry(0, Source:=SetupSource.Version)},
+        {"VersionServerNide", New SetupEntry("", Source:=SetupSource.Version)},
+        {"VersionServerAuthRegister", New SetupEntry("", Source:=SetupSource.Version)},
+        {"VersionServerAuthName", New SetupEntry("", Source:=SetupSource.Version)},
+        {"VersionServerAuthServer", New SetupEntry("", Source:=SetupSource.Version)}
+    }
+
+#Region "基础"
+
+    Private Enum SetupSource
+        Normal
+        Registry
+        Version
+    End Enum
+    Private Class SetupEntry
+
+        Public Encoded As Boolean
+        Public DefaultValue
+        Public DefaultValueEncoded
+        Public Value
+        Public Source As SetupSource
+
+        '加载状态:0/未读取  1/已读取未处理  2/已处理
+        Public State As Byte = 0
+        Public Type
+
+        Public Sub New(Value, Optional Source = SetupSource.Normal, Optional Encoded = False)
+            Me.DefaultValue = Value
+            Me.DefaultValueEncoded = If(Encoded, SecretEncrypt(Value, "PCL" & UniqueAddress), Value)
+            Me.Encoded = Encoded
+            Me.Value = Value
+            Me.Source = Source
+            Type = If(Value, New Object).GetType
+        End Sub
+
+    End Class
+
+    ''' <summary>
+    ''' 改变某个设置项的值。
+    ''' </summary>
+    Public Sub [Set](Key As String, Value As Object, Optional ForceReload As Boolean = False, Optional Version As McVersion = Nothing)
+        [Set](Key, Value, SetupDict(Key), ForceReload, Version)
+    End Sub
+    Private Sub [Set](Key As String, Value As Object, E As SetupEntry, ForceReload As Boolean, Version As McVersion)
+        Try
+
+            Value = CTypeDynamic(Value, E.Type)
+            If E.State = 2 Then
+                '如果已应用,且值相同,则无需再次更改
+                If E.Value = Value AndAlso Not ForceReload Then Exit Sub
+            Else
+                '如果未应用,则直接更改并应用
+                If E.Source <> SetupSource.Version Then E.State = 2
+            End If
+            '设置新值
+            E.Value = Value
+            '写入值
+            If E.Encoded Then
+                Try
+                    If Value Is Nothing Then Value = ""
+                    Value = SecretEncrypt(Value, "PCL" & UniqueAddress)
+                Catch ex As Exception
+                    Log(ex, "加密设置失败:" & Key, LogLevel.Developer)
+                End Try
+            End If
+            Select Case E.Source
+                Case SetupSource.Normal
+                    WriteIni("Setup", Key, Value)
+                Case SetupSource.Registry
+                    WriteReg(Key, Value)
+                Case SetupSource.Version
+                    If Version Is Nothing Then
+                        Throw New Exception("更改版本设置 " & Key & " 时未提供目标版本")
+                    Else
+                        WriteIni(Version.Path & "PCL\Setup.ini", Key, Value)
+                    End If
+            End Select
+            '应用
+            '例如 VersionServerLogin 要求在设置之后再引发事件
+            Dim Method As Reflection.MethodInfo = GetType(ModSetup).GetMethod(Key)
+            If Method IsNot Nothing Then Method.Invoke(Me, {Value})
+
+        Catch ex As Exception
+            Log(ex, "设置设置项时出错(" & Key & ", " & Value & ")", LogLevel.Feedback)
+        End Try
+    End Sub
+
+    ''' <summary>
+    ''' 应用某个设置项的值。
+    ''' </summary>
+    Public Function Load(Key As String, Optional ForceReload As Boolean = False, Optional Version As McVersion = Nothing)
+        Return Load(Key, SetupDict(Key), ForceReload, Version)
+    End Function
+    Private Function Load(Key As String, E As SetupEntry, ForceReload As Boolean, Version As McVersion)
+        '如果已经应用过,则什么也不干
+        If E.State = 2 AndAlso Not ForceReload Then Return E.Value
+        '读取,应用并设置状态
+        Read(Key, E, Version)
+        If E.Source <> SetupSource.Version Then E.State = 2
+        Dim Method As Reflection.MethodInfo = GetType(ModSetup).GetMethod(Key)
+        If Method IsNot Nothing Then Method.Invoke(Me, {E.Value})
+        Return E.Value
+    End Function
+
+    ''' <summary>
+    ''' 获取某个设置项的值。
+    ''' </summary>
+    Public Function [Get](Key As String, Optional Version As McVersion = Nothing)
+        If Not SetupDict.ContainsKey(Key) Then Throw New KeyNotFoundException("未找到设置项:" & Key) With {.Source = Key}
+        Return [Get](Key, SetupDict(Key), Version)
+    End Function
+    Private Function [Get](Key As String, E As SetupEntry, Version As McVersion)
+        '获取强制值
+        Dim Force As String = ForceValue(Key)
+        If Force IsNot Nothing Then
+            E.Value = CTypeDynamic(Force, E.Type)
+            E.State = 1
+        End If
+        '如果尚未读取过,则读取
+        If E.State = 0 Then
+            Read(Key, E, Version)
+            If E.Source <> SetupSource.Version Then E.State = 1
+        End If
+        '返回现在的值
+        Return E.Value
+    End Function
+
+    ''' <summary>
+    ''' 初始化某个设置项的值。
+    ''' </summary>
+    Public Sub Reset(Key As String, Optional ForceReload As Boolean = False, Optional Version As McVersion = Nothing)
+        Dim E As SetupEntry = SetupDict(Key)
+        [Set](Key, E.DefaultValue, E, ForceReload, Version)
+    End Sub
+
+    Private Sub Read(Key As String, ByRef E As SetupEntry, Version As McVersion)
+        Try
+            If Not E.State = 0 Then Exit Sub
+            Dim SourceValue As String '先用 String 储存,避免类型转换
+            Select Case E.Source
+                Case SetupSource.Normal
+                    SourceValue = ReadIni("Setup", Key, E.DefaultValueEncoded)
+                Case SetupSource.Registry
+                    SourceValue = ReadReg(Key, E.DefaultValueEncoded)
+                Case Else 'SetupSource.Version
+                    If Version Is Nothing Then
+                        Throw New Exception("读取版本设置 " & Key & " 时未提供目标版本")
+                    Else
+                        SourceValue = ReadIni(Version.Path & "PCL\Setup.ini", Key, E.DefaultValueEncoded)
+                    End If
+            End Select
+            If E.Encoded Then
+                If SourceValue.Equals(E.DefaultValueEncoded) Then
+                    SourceValue = E.DefaultValue
+                Else
+                    Try
+                        SourceValue = SecretDecrypt(SourceValue, "PCL" & UniqueAddress)
+                    Catch ex As Exception
+                        Log(ex, "解密设置失败:" & Key, LogLevel.Developer)
+                        SourceValue = E.DefaultValue
+                        Setup.Set(Key, E.DefaultValue, True)
+                    End Try
+                End If
+            End If
+            E.Value = CTypeDynamic(SourceValue, E.Type)
+        Catch ex As Exception
+            Log(ex, "读取设置失败:" & Key, LogLevel.Hint)
+            E.Value = CTypeDynamic(E.DefaultValue, E.Type)
+        End Try
+    End Sub
+
+    '对部分设置强制赋值
+    Private Function ForceValue(Key As String) As String
+#If BETA Then
+        If Key = "UiLauncherTheme" Then Return "0"
+#End If
+        If Key = "UiHiddenPageLink" Then Return True
+        If Key = "UiHiddenSetupLink" Then Return True
+        Return Nothing
+    End Function
+
+#End Region
+
+#Region "Launch"
+
+    '切换选择
+    Public Sub LaunchVersionSelect(Value As String)
+        Log("[Setup] 当前选择的 Minecraft 版本:" & Value)
+        WriteIni(PathMcFolder & "PCL.ini", "Version", If(IsNothing(McVersionCurrent), "", McVersionCurrent.Name))
+    End Sub
+    Public Sub LaunchFolderSelect(Value As String)
+        Log("[Setup] 当前选择的 Minecraft 文件夹:" & Value.ToString.Replace("$", Path))
+        PathMcFolder = Value.ToString.Replace("$", Path)
+    End Sub
+
+    '游戏内存
+    Public Sub LaunchRamType(Type As Integer)
+        If FrmSetupLaunch Is Nothing Then Exit Sub
+        FrmSetupLaunch.RamType(Type)
+    End Sub
+
+    '离线皮肤
+    Public Sub LaunchSkinType(Value As Integer)
+        RunInUi(Sub()
+                    If Not IsNothing(FrmSetupLaunch) Then
+                        Select Case Value
+                            Case 0, 1, 2 '默认
+                                FrmSetupLaunch.PanSkinID.Visibility = Visibility.Collapsed
+                                FrmSetupLaunch.PanSkinChange.Visibility = Visibility.Collapsed
+                            Case 3 '正版
+                                FrmSetupLaunch.PanSkinID.Visibility = Visibility.Visible
+                                FrmSetupLaunch.PanSkinChange.Visibility = Visibility.Collapsed
+                            Case 4 '自定义
+                                FrmSetupLaunch.PanSkinID.Visibility = Visibility.Collapsed
+                                FrmSetupLaunch.PanSkinChange.Visibility = Visibility.Visible
+                        End Select
+                        FrmSetupLaunch.CardSkin.TriggerForceResize()
+                    End If
+                    PageLaunchLeft.SkinLegacy.Start()
+                End Sub)
+    End Sub
+    Public Sub LaunchSkinID(Value As String)
+        PageLaunchLeft.SkinLegacy.Start()
+    End Sub
+
+#End Region
+
+#Region "Tool"
+
+    Public Sub ToolDownloadThread(Value As Integer)
+        NetTaskThreadLimit = Value + 1
+    End Sub
+    Public Sub ToolDownloadCert(Value As Boolean)
+        Net.ServicePointManager.ServerCertificateValidationCallback =
+            If(Value, Nothing, New Net.Security.RemoteCertificateValidationCallback(Function() True))
+    End Sub
+    Public Sub ToolDownloadSpeed(Value As Integer)
+        If Value <= 14 Then
+            NetTaskSpeedLimitHigh = (Value + 1) * 0.1 * 1024 * 1024L
+        ElseIf Value <= 31 Then
+            NetTaskSpeedLimitHigh = (Value - 11) * 0.5 * 1024 * 1024L
+        ElseIf Value <= 41 Then
+            NetTaskSpeedLimitHigh = (Value - 21) * 1024 * 1024L
+        Else
+            NetTaskSpeedLimitHigh = -1
+        End If
+    End Sub
+
+#End Region
+
+#Region "UI"
+
+    '启动器
+    Public Sub UiLauncherTransparent(Value As Integer)
+        FrmMain.Opacity = Value / 1000 + 0.4
+    End Sub
+#If Not BETA Then
+    Public Sub UiLauncherTheme(Value As Integer)
+        ThemeRefresh(Value)
+    End Sub
+#End If
+    Public Sub UiBackgroundColorful(Value As Boolean)
+        ThemeRefresh()
+    End Sub
+
+    '背景图片
+    Public Sub UiBackgroundOpacity(Value As Integer)
+        FrmMain.ImgBack.Opacity = Value / 1000
+    End Sub
+    Public Sub UiBackgroundBlur(Value As Integer)
+        If Value = 0 Then
+            FrmMain.ImgBack.Effect = Nothing
+        Else
+            FrmMain.ImgBack.Effect = New Effects.BlurEffect With {.Radius = Value + 1}
+        End If
+        FrmMain.ImgBack.Margin = New Thickness(-(Value + 1) / 1.8)
+    End Sub
+    Public Sub UiBackgroundSuit(Value As Integer)
+        If IsNothing(FrmMain.ImgBack.Background) Then Exit Sub
+        Dim Width As Double = CType(FrmMain.ImgBack.Background, ImageBrush).ImageSource.Width
+        Dim Height As Double = CType(FrmMain.ImgBack.Background, ImageBrush).ImageSource.Height
+        If Value = 0 Then
+            '智能:当图片较小时平铺,较大时适应
+            If Width < FrmMain.PanMain.ActualWidth / 2 AndAlso Height < FrmMain.PanMain.ActualHeight / 2 Then
+                Value = 4 '平铺
+            Else
+                Value = 2 '适应
+            End If
+        End If
+        CType(FrmMain.ImgBack.Background, ImageBrush).TileMode = TileMode.None
+        CType(FrmMain.ImgBack.Background, ImageBrush).Viewport = New Rect(0, 0, 1, 1)
+        CType(FrmMain.ImgBack.Background, ImageBrush).ViewportUnits = BrushMappingMode.RelativeToBoundingBox
+        Select Case Value
+            Case 1 '居中
+                FrmMain.ImgBack.HorizontalAlignment = HorizontalAlignment.Center
+                FrmMain.ImgBack.VerticalAlignment = VerticalAlignment.Center
+                CType(FrmMain.ImgBack.Background, ImageBrush).Stretch = Stretch.None
+                FrmMain.ImgBack.Width = CType(FrmMain.ImgBack.Background, ImageBrush).ImageSource.Width
+                FrmMain.ImgBack.Height = CType(FrmMain.ImgBack.Background, ImageBrush).ImageSource.Height
+            Case 2 '适应
+                FrmMain.ImgBack.HorizontalAlignment = HorizontalAlignment.Stretch
+                FrmMain.ImgBack.VerticalAlignment = VerticalAlignment.Stretch
+                CType(FrmMain.ImgBack.Background, ImageBrush).Stretch = Stretch.UniformToFill
+                FrmMain.ImgBack.Width = Double.NaN
+                FrmMain.ImgBack.Height = Double.NaN
+            Case 3 '拉伸
+                FrmMain.ImgBack.HorizontalAlignment = HorizontalAlignment.Stretch
+                FrmMain.ImgBack.VerticalAlignment = VerticalAlignment.Stretch
+                CType(FrmMain.ImgBack.Background, ImageBrush).Stretch = Stretch.Fill
+                FrmMain.ImgBack.Width = Double.NaN
+                FrmMain.ImgBack.Height = Double.NaN
+            Case 4 '平铺
+                FrmMain.ImgBack.HorizontalAlignment = HorizontalAlignment.Stretch
+                FrmMain.ImgBack.VerticalAlignment = VerticalAlignment.Stretch
+                CType(FrmMain.ImgBack.Background, ImageBrush).Stretch = Stretch.None
+                CType(FrmMain.ImgBack.Background, ImageBrush).TileMode = TileMode.Tile
+                CType(FrmMain.ImgBack.Background, ImageBrush).Viewport = New Rect(0, 0, CType(FrmMain.ImgBack.Background, ImageBrush).ImageSource.Width, CType(FrmMain.ImgBack.Background, ImageBrush).ImageSource.Height)
+                CType(FrmMain.ImgBack.Background, ImageBrush).ViewportUnits = BrushMappingMode.Absolute
+                FrmMain.ImgBack.Width = Double.NaN
+                FrmMain.ImgBack.Height = Double.NaN
+            Case 5 '左上
+                FrmMain.ImgBack.HorizontalAlignment = HorizontalAlignment.Left
+                FrmMain.ImgBack.VerticalAlignment = VerticalAlignment.Top
+                CType(FrmMain.ImgBack.Background, ImageBrush).Stretch = Stretch.None
+                FrmMain.ImgBack.Width = CType(FrmMain.ImgBack.Background, ImageBrush).ImageSource.Width
+                FrmMain.ImgBack.Height = CType(FrmMain.ImgBack.Background, ImageBrush).ImageSource.Height
+            Case 6 '右上
+                FrmMain.ImgBack.HorizontalAlignment = HorizontalAlignment.Right
+                FrmMain.ImgBack.VerticalAlignment = VerticalAlignment.Top
+                CType(FrmMain.ImgBack.Background, ImageBrush).Stretch = Stretch.None
+                FrmMain.ImgBack.Width = CType(FrmMain.ImgBack.Background, ImageBrush).ImageSource.Width
+                FrmMain.ImgBack.Height = CType(FrmMain.ImgBack.Background, ImageBrush).ImageSource.Height
+            Case 7 '左下
+                FrmMain.ImgBack.HorizontalAlignment = HorizontalAlignment.Left
+                FrmMain.ImgBack.VerticalAlignment = VerticalAlignment.Bottom
+                CType(FrmMain.ImgBack.Background, ImageBrush).Stretch = Stretch.None
+                FrmMain.ImgBack.Width = CType(FrmMain.ImgBack.Background, ImageBrush).ImageSource.Width
+                FrmMain.ImgBack.Height = CType(FrmMain.ImgBack.Background, ImageBrush).ImageSource.Height
+            Case 8 '右下
+                FrmMain.ImgBack.HorizontalAlignment = HorizontalAlignment.Right
+                FrmMain.ImgBack.VerticalAlignment = VerticalAlignment.Bottom
+                CType(FrmMain.ImgBack.Background, ImageBrush).Stretch = Stretch.None
+                FrmMain.ImgBack.Width = CType(FrmMain.ImgBack.Background, ImageBrush).ImageSource.Width
+                FrmMain.ImgBack.Height = CType(FrmMain.ImgBack.Background, ImageBrush).ImageSource.Height
+        End Select
+    End Sub
+
+    '主页
+    Public Sub UiCustomType(Value As Integer)
+        If FrmSetupUI Is Nothing Then Exit Sub
+        Select Case Value
+            Case 0 '无
+                FrmSetupUI.PanCustomPreset.Visibility = Visibility.Collapsed
+                FrmSetupUI.PanCustomLocal.Visibility = Visibility.Collapsed
+                FrmSetupUI.PanCustomNet.Visibility = Visibility.Collapsed
+                FrmSetupUI.HintCustom.Visibility = Visibility.Collapsed
+            Case 1 '本地
+                FrmSetupUI.PanCustomPreset.Visibility = Visibility.Collapsed
+                FrmSetupUI.PanCustomLocal.Visibility = Visibility.Visible
+                FrmSetupUI.PanCustomNet.Visibility = Visibility.Collapsed
+                FrmSetupUI.HintCustom.Visibility = Visibility.Visible
+                FrmSetupUI.HintCustom.Text = $"从 PCL 文件夹下的 Custom.xaml 读取主页内容。{vbCrLf}你可以手动编辑该文件,向主页添加文本、图片、常用网站、快捷启动等功能。"
+                FrmSetupUI.HintCustom.EventType = ""
+                FrmSetupUI.HintCustom.EventData = ""
+            Case 2 '联网
+                FrmSetupUI.PanCustomPreset.Visibility = Visibility.Collapsed
+                FrmSetupUI.PanCustomLocal.Visibility = Visibility.Collapsed
+                FrmSetupUI.PanCustomNet.Visibility = Visibility.Visible
+                FrmSetupUI.HintCustom.Visibility = Visibility.Visible
+                FrmSetupUI.HintCustom.Text = $"从指定网址联网获取主页内容。服主也可以用于动态更新服务器公告。{vbCrLf}如果你制作了稳定运行的联网主页,可以点击这条提示投稿,若合格即可加入预设!"
+                FrmSetupUI.HintCustom.EventType = "打开网页"
+                FrmSetupUI.HintCustom.EventData = "https://github.com/Hex-Dragon/PCL2/discussions/2528"
+            Case 3 '预设
+                FrmSetupUI.PanCustomPreset.Visibility = Visibility.Visible
+                FrmSetupUI.PanCustomLocal.Visibility = Visibility.Collapsed
+                FrmSetupUI.PanCustomNet.Visibility = Visibility.Collapsed
+                FrmSetupUI.HintCustom.Visibility = Visibility.Collapsed
+        End Select
+        FrmSetupUI.CardCustom.TriggerForceResize()
+    End Sub
+
+    '顶部栏
+    Public Sub UiLogoType(Value As Integer)
+        Select Case Value
+            Case 0 '无
+                FrmMain.ShapeTitleLogo.Visibility = Visibility.Collapsed
+                FrmMain.LabTitleLogo.Visibility = Visibility.Collapsed
+                FrmMain.ImageTitleLogo.Visibility = Visibility.Collapsed
+                If Not IsNothing(FrmSetupUI) Then
+                    FrmSetupUI.CheckLogoLeft.Visibility = Visibility.Visible
+                    FrmSetupUI.PanLogoText.Visibility = Visibility.Collapsed
+                    FrmSetupUI.PanLogoChange.Visibility = Visibility.Collapsed
+                End If
+            Case 1 '默认
+                FrmMain.ShapeTitleLogo.Visibility = Visibility.Visible
+                FrmMain.LabTitleLogo.Visibility = Visibility.Collapsed
+                FrmMain.ImageTitleLogo.Visibility = Visibility.Collapsed
+                If Not IsNothing(FrmSetupUI) Then
+                    FrmSetupUI.CheckLogoLeft.Visibility = Visibility.Collapsed
+                    FrmSetupUI.PanLogoText.Visibility = Visibility.Collapsed
+                    FrmSetupUI.PanLogoChange.Visibility = Visibility.Collapsed
+                End If
+            Case 2 '文本
+                FrmMain.ShapeTitleLogo.Visibility = Visibility.Collapsed
+                FrmMain.LabTitleLogo.Visibility = Visibility.Visible
+                FrmMain.ImageTitleLogo.Visibility = Visibility.Collapsed
+                If Not IsNothing(FrmSetupUI) Then
+                    FrmSetupUI.CheckLogoLeft.Visibility = Visibility.Collapsed
+                    FrmSetupUI.PanLogoText.Visibility = Visibility.Visible
+                    FrmSetupUI.PanLogoChange.Visibility = Visibility.Collapsed
+                End If
+                Setup.Load("UiLogoText", True)
+            Case 3 '图片
+                FrmMain.ShapeTitleLogo.Visibility = Visibility.Collapsed
+                FrmMain.LabTitleLogo.Visibility = Visibility.Collapsed
+                FrmMain.ImageTitleLogo.Visibility = Visibility.Visible
+                If Not IsNothing(FrmSetupUI) Then
+                    FrmSetupUI.CheckLogoLeft.Visibility = Visibility.Collapsed
+                    FrmSetupUI.PanLogoText.Visibility = Visibility.Collapsed
+                    FrmSetupUI.PanLogoChange.Visibility = Visibility.Visible
+                End If
+                Try
+                    FrmMain.ImageTitleLogo.Source = New MyBitmap(Path & "PCL\Logo.png")
+                Catch ex As Exception
+                    FrmMain.ImageTitleLogo.Source = Nothing
+                    Log(ex, "显示标题栏图片失败", LogLevel.Msgbox)
+                End Try
+        End Select
+        Setup.Load("UiLogoLeft", True)
+        If Not IsNothing(FrmSetupUI) Then FrmSetupUI.CardLogo.TriggerForceResize()
+    End Sub
+    Public Sub UiLogoText(Value As String)
+        FrmMain.LabTitleLogo.Text = Value
+    End Sub
+    Public Sub UiLogoLeft(Value As Boolean)
+        FrmMain.PanTitleMain.ColumnDefinitions(0).Width = New GridLength(If(Value AndAlso (Setup.Get("UiLogoType") = 0), 0, 1), GridUnitType.Star)
+    End Sub
+
+    '功能隐藏
+    Public Sub UiHiddenPageLink(Value As Boolean)
+        PageSetupUI.HiddenRefresh()
+    End Sub
+    Public Sub UiHiddenPageDownload(Value As Boolean)
+        PageSetupUI.HiddenRefresh()
+    End Sub
+    Public Sub UiHiddenPageSetup(Value As Boolean)
+        PageSetupUI.HiddenRefresh()
+    End Sub
+    Public Sub UiHiddenPageOther(Value As Boolean)
+        PageSetupUI.HiddenRefresh()
+    End Sub
+    Public Sub UiHiddenFunctionSelect(Value As Boolean)
+        PageSetupUI.HiddenRefresh()
+    End Sub
+    Public Sub UiHiddenFunctionHidden(Value As Boolean)
+        PageSetupUI.HiddenRefresh()
+    End Sub
+    Public Sub UiHiddenSetupLaunch(Value As Boolean)
+        PageSetupUI.HiddenRefresh()
+    End Sub
+    Public Sub UiHiddenSetupUi(Value As Boolean)
+        PageSetupUI.HiddenRefresh()
+    End Sub
+    Public Sub UiHiddenSetupLink(Value As Boolean)
+        PageSetupUI.HiddenRefresh()
+    End Sub
+    Public Sub UiHiddenSetupSystem(Value As Boolean)
+        PageSetupUI.HiddenRefresh()
+    End Sub
+    Public Sub UiHiddenOtherHelp(Value As Boolean)
+        PageSetupUI.HiddenRefresh()
+    End Sub
+    Public Sub UiHiddenOtherFeedback(Value As Boolean)
+        PageSetupUI.HiddenRefresh()
+    End Sub
+    Public Sub UiHiddenOtherVote(Value As Boolean)
+        PageSetupUI.HiddenRefresh()
+    End Sub
+    Public Sub UiHiddenOtherAbout(Value As Boolean)
+        PageSetupUI.HiddenRefresh()
+    End Sub
+    Public Sub UiHiddenOtherTest(Value As Boolean)
+        PageSetupUI.HiddenRefresh()
+    End Sub
+
+
+#End Region
+
+#Region "System"
+
+    '调试选项
+    Public Sub SystemDebugMode(Value As Boolean)
+        ModeDebug = Value
+    End Sub
+    Public Sub SystemDebugAnim(Value As Integer)
+        AniSpeed = If(Value >= 30, 200, MathClamp(Value * 0.1 + 0.1, 0.1, 3))
+    End Sub
+
+#End Region
+
+#Region "Version"
+
+    '游戏内存
+    Public Sub VersionRamType(Type As Integer)
+        If FrmVersionSetup Is Nothing Then Exit Sub
+        FrmVersionSetup.RamType(Type)
+    End Sub
+
+    '服务器
+    Public Sub VersionServerLogin(Type As Integer)
+        If FrmVersionSetup Is Nothing Then Exit Sub
+        '为第三方登录清空缓存以更新描述
+        WriteIni(PathMcFolder & "PCL.ini", "VersionCache", "")
+        If PageVersionLeft.Version Is Nothing Then Exit Sub
+        PageVersionLeft.Version = New McVersion(PageVersionLeft.Version.Name).Load()
+        LoaderFolderRun(McVersionListLoader, PathMcFolder, LoaderFolderRunType.ForceRun, MaxDepth:=1, ExtraPath:="versions\")
+    End Sub
+
+#End Region
+
+End Class

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

@@ -28,7 +28,6 @@
                                 <local:ValidateNullable />
                                 <local:ValidateNullOrWhiteSpace />
                                 <local:ValidateLength Max="20" />
-                                <local:ValidateFilter />
                             </local:MyTextBox.ValidateRules>
                         </local:MyTextBox>
                     </Grid>

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

@@ -156,7 +156,7 @@
         PageOtherAbout.CopyUniqueAddress()
     End Sub
     Private Sub BtnSystemUnlock_Click(sender As Object, e As MouseButtonEventArgs) Handles BtnSystemUnlock.Click
-        PageOtherAbout.DonateCodeInput()
+        DonateCodeInput()
     End Sub
 
     '调试模式

+ 295 - 0
Plain Craft Launcher 2/Pages/PageSetup/PageSetupUI.xaml

@@ -0,0 +1,295 @@
+<local:MyPageRight
+    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+    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:Class="PageSetupUI"
+    PanScroll="{Binding ElementName=PanBack}">
+    <local:MyScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled" x:Name="PanBack">
+        <StackPanel x:Name="PanMain" Margin="25,10">
+            <local:MyCard Margin="0,15" Title="基础" x:Name="CardLauncher">
+                <Grid Margin="25,40,25,17">
+                    <StackPanel>
+                        <Grid Margin="0,0,0,6">
+                            <Grid.ColumnDefinitions>
+                                <ColumnDefinition Width="Auto" SharedSizeGroup="Name1" />
+                                <ColumnDefinition Width="1*" />
+                                <ColumnDefinition Width="30" />
+                                <ColumnDefinition Width="Auto" />
+                                <ColumnDefinition Width="1*" />
+                            </Grid.ColumnDefinitions>
+                            <Grid.RowDefinitions>
+                                <RowDefinition Height="Auto" />
+                                <RowDefinition Height="Auto" />
+                                <RowDefinition Height="Auto" />
+                            </Grid.RowDefinitions>
+                            <TextBlock VerticalAlignment="Center" HorizontalAlignment="Left" Text="不透明度" Margin="0,0,20,0" />
+                            <local:MySlider Grid.ColumnSpan="5" x:Name="SliderLauncherOpacity" Tag="UiLauncherTransparent" MaxValue="600" ValueByKey="10" Grid.Column="1" />
+                            <TextBlock Grid.Row="1" VerticalAlignment="Center" Name="LabLauncherHue" Visibility="Collapsed" HorizontalAlignment="Left" Text="色调" Margin="0,10,20,0" />
+                            <local:MySlider Grid.Row="1" Grid.Column="1" x:Name="SliderLauncherHue" Tag="UiLauncherHue" Visibility="Collapsed" MaxValue="360" ValueByKey="10" Margin="0,10,0,0" />
+                            <TextBlock Grid.Row="2" VerticalAlignment="Center" Name="LabLauncherDelta" Visibility="Collapsed" HorizontalAlignment="Left" Text="色调渐变" Margin="0,10,20,0" />
+                            <local:MySlider Grid.Row="2" Grid.Column="1" x:Name="SliderLauncherDelta" Tag="UiLauncherDelta" Visibility="Collapsed" MaxValue="180" ValueByKey="5" Margin="0,10,0,0" />
+                            <TextBlock Grid.Row="1" Grid.Column="3" VerticalAlignment="Center" Name="LabLauncherSat" Visibility="Collapsed" HorizontalAlignment="Left" Text="饱和度" Margin="0,10,20,0" />
+                            <local:MySlider Grid.Row="1" Grid.Column="4" x:Name="SliderLauncherSat" Tag="UiLauncherSat" Visibility="Collapsed" MaxValue="100" ValueByKey="5" Margin="0,10,0,0" />
+                            <TextBlock Grid.Row="2" Grid.Column="3" VerticalAlignment="Center" Name="LabLauncherLight" Visibility="Collapsed" HorizontalAlignment="Left" Text="亮度" Margin="0,10,20,0" />
+                            <local:MySlider Grid.Row="2" Grid.Column="4" x:Name="SliderLauncherLight" Tag="UiLauncherLight" Visibility="Collapsed" MaxValue="40" ValueByKey="5" Margin="0,10,0,0" />
+                        </Grid>
+                        <Grid x:Name="PanLauncherTheme" Height="90" Margin="0,0,0,7">
+                            <Grid.ColumnDefinitions>
+                                <ColumnDefinition Width="Auto" SharedSizeGroup="Name1" />
+                                <ColumnDefinition />
+                                <ColumnDefinition />
+                                <ColumnDefinition />
+                                <ColumnDefinition />
+                                <ColumnDefinition />
+                            </Grid.ColumnDefinitions>
+                            <Grid.RowDefinitions>
+                                <RowDefinition />
+                                <RowDefinition />
+                                <RowDefinition />
+                            </Grid.RowDefinitions>
+                            <TextBlock VerticalAlignment="Center" HorizontalAlignment="Left" Text="主题" Margin="0,0,20,0" />
+                            <TextBlock VerticalAlignment="Center" HorizontalAlignment="Left" Text="隐藏主题" Margin="0,0,20,0" Grid.Row="1" />
+                            <local:MyRadioBox Grid.Column="1" Grid.Row="0" Text="龙猫蓝" x:Name="RadioLauncherTheme0" Tag="UiLauncherTheme/0" />
+                            <local:MyRadioBox Grid.Column="2" Grid.Row="0" Text="甜柠青" x:Name="RadioLauncherTheme1" Tag="UiLauncherTheme/1" />
+                            <local:MyRadioBox Grid.Column="3" Grid.Row="0" Text="小草绿" x:Name="RadioLauncherTheme2" Tag="UiLauncherTheme/2" />
+                            <local:MyRadioBox Grid.Column="4" Grid.Row="0" Text="菠萝黄" x:Name="RadioLauncherTheme3" Tag="UiLauncherTheme/3" />
+                            <local:MyRadioBox Grid.Column="5" Grid.Row="0" Text="橡木棕" x:Name="RadioLauncherTheme4" Tag="UiLauncherTheme/4" />
+                            <local:MyRadioBox Grid.Column="1" Grid.Row="1" Text="玄素黑" x:Name="RadioLauncherTheme5" Tag="UiLauncherTheme/5" Opacity="0" ToolTip="灰色是个谎言" ToolTipService.Placement="Bottom" />
+                            <local:MyRadioBox Grid.Column="1" Grid.Row="1" Text="???" x:Name="RadioLauncherTheme5Gray" IsEnabled="False" Opacity="1" />
+                            <TextBlock Grid.Column="1" Grid.Row="1" x:Name="LabLauncherTheme5Unlock" Background="{StaticResource ColorBrushSemiTransparent}" ToolTip="灰色是个谎言" ToolTipService.Placement="Bottom" />
+                            <local:MyRadioBox Grid.Column="2" Grid.Row="1" Text="???" x:Name="RadioLauncherTheme12" Tag="UiLauncherTheme/12" IsEnabled="False" ToolTip="滑稽树上滑稽果,滑稽树下你和我,滑稽之日搞事情,欢乐多又多" ToolTipService.ShowOnDisabled="True" ToolTipService.Placement="Bottom" />
+                            <local:MyRadioBox Grid.Column="3" Grid.Row="1" Text="???" x:Name="RadioLauncherTheme6" Tag="UiLauncherTheme/6" IsEnabled="False" ToolTip="99 次重逢的喜悦" ToolTipService.ShowOnDisabled="True" ToolTipService.Placement="Bottom" />
+                            <local:MyRadioBox Grid.Column="4" Grid.Row="1" Text="???" x:Name="RadioLauncherTheme7" Tag="UiLauncherTheme/7" IsEnabled="False" ToolTip="072 101 108 112 032 068 101 118 032 048 046 052 046 052" ToolTipService.ShowOnDisabled="True" ToolTipService.Placement="Bottom" />
+                            <local:MyRadioBox Grid.Column="5" Grid.Row="1" Text="???" x:Name="RadioLauncherTheme13" Tag="UiLauncherTheme/13" IsEnabled="False" ToolTip="这就是传说中的欧皇了吧" ToolTipService.ShowOnDisabled="True" ToolTipService.Placement="Bottom" />
+                            <local:MyRadioBox Grid.Column="1" Grid.Row="2" Text="???" x:Name="RadioLauncherTheme8" Tag="UiLauncherTheme/8" IsEnabled="False" ToolTipService.Placement="Bottom" />
+                            <TextBlock Grid.Column="1" Grid.Row="2" x:Name="LabLauncherTheme8Copy" Background="{StaticResource ColorBrushSemiTransparent}" ToolTipService.Placement="Bottom" />
+                            <local:MyRadioBox Grid.Column="2" Grid.Row="2" Text="???" x:Name="RadioLauncherTheme9" Tag="UiLauncherTheme/9" IsEnabled="False" ToolTipService.Placement="Bottom" />
+                            <TextBlock Grid.Column="2" Grid.Row="2" x:Name="LabLauncherTheme9Copy" Background="{StaticResource ColorBrushSemiTransparent}" ToolTipService.Placement="Bottom" />
+                            <local:MyRadioBox Grid.Column="3" Grid.Row="2" Text="???" x:Name="RadioLauncherTheme10" Tag="UiLauncherTheme/10" IsEnabled="False" ToolTip="进行一次正版登录,支持正版游戏!" ToolTipService.ShowOnDisabled="True" ToolTipService.Placement="Bottom" />
+                            <local:MyRadioBox Grid.Column="4" Grid.Row="2" Text="???" x:Name="RadioLauncherTheme11" Tag="UiLauncherTheme/11" IsEnabled="False" ToolTipService.Placement="Bottom" ToolTip="右键打开解密游戏入口" />
+                            <TextBlock Grid.Column="4" Grid.Row="2" x:Name="LabLauncherTheme11Click" Background="{StaticResource ColorBrushSemiTransparent}" ToolTipService.Placement="Bottom" />
+                            <local:MyRadioBox Grid.Column="5" Grid.Row="2" Text="自定义" x:Name="RadioLauncherTheme14" Tag="UiLauncherTheme/14" IsEnabled="False" ToolTipService.Placement="Bottom" ToolTip="需要解锁五个隐藏主题" ToolTipService.ShowOnDisabled="True" />
+                        </Grid>
+                        <local:MyCheckBox Text="打开启动器时显示 PCL 图标" Margin="-1,0,0,1" Height="22" x:Name="CheckLauncherLogo" Tag="UiLauncherLogo" />
+                    </StackPanel>
+                    <Border Background="#CCCCCCCC" Margin="-5,22,-5,-5" CornerRadius="4" Name="PanLauncherHide" Visibility="Collapsed">
+                        <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
+                            <TextBlock Text="需要小小赞助一下作者,才能修改主题颜色(悲)……" FontSize="15" Margin="0,2,0,0" />
+                            <local:MyButton Height="35" x:Name="BtnLauncherDonate" MinWidth="150" Text="支持作者" Padding="13,0" HorizontalAlignment="Center" Margin="0,9,0,0" ColorType="Highlight" />
+                        </StackPanel>
+                    </Border>
+                </Grid>
+            </local:MyCard>
+            <local:MyCard x:Name="CardBackground" Margin="0,0,0,15" Title="背景图片">
+                <StackPanel Margin="25,40,25,20">
+                    <Grid x:Name="PanBackgroundSuit" Height="28" Margin="0,0,0,10" Visibility="Collapsed">
+                        <Grid.ColumnDefinitions>
+                            <ColumnDefinition Width="Auto" SharedSizeGroup="Name" />
+                            <ColumnDefinition />
+                        </Grid.ColumnDefinitions>
+                        <TextBlock VerticalAlignment="Center" HorizontalAlignment="Left" Text="自适应方式" Margin="0,0,25,0" />
+                        <local:MyComboBox x:Name="ComboBackgroundSuit" Tag="UiBackgroundSuit" Grid.Column="1">
+                            <local:MyComboBoxItem Content="智能" IsSelected="True" ToolTip="当图片较小时选择平铺,较大时选择适应" />
+                            <local:MyComboBoxItem Content="居中" />
+                            <local:MyComboBoxItem Content="适应" ToolTip="拉伸图片并保持长宽比不变,直至填满整个窗口" />
+                            <local:MyComboBoxItem Content="拉伸" ToolTip="拉伸图片使其恰好填满整个窗口,很可能会导致长宽比的改变" />
+                            <local:MyComboBoxItem Content="平铺" />
+                            <local:MyComboBoxItem Content="居于左上" />
+                            <local:MyComboBoxItem Content="居于右上" />
+                            <local:MyComboBoxItem Content="居于左下" />
+                            <local:MyComboBoxItem Content="居于右下" />
+                        </local:MyComboBox>
+                    </Grid>
+                    <Grid x:Name="PanBackgroundOpacity" Height="22" Margin="0,0,0,7" Visibility="Collapsed">
+                        <Grid.ColumnDefinitions>
+                            <ColumnDefinition Width="Auto" SharedSizeGroup="Name" />
+                            <ColumnDefinition />
+                        </Grid.ColumnDefinitions>
+                        <TextBlock VerticalAlignment="Center" HorizontalAlignment="Left" Text="不透明度" Margin="0,0,25,0" />
+                        <local:MySlider x:Name="SliderBackgroundOpacity" Tag="UiBackgroundOpacity" MaxValue="1000" ValueByKey="10" Grid.Column="1" />
+                    </Grid>
+                    <Grid x:Name="PanBackgroundBlur" Height="22" Margin="0,0,0,10" Visibility="Collapsed">
+                        <Grid.ColumnDefinitions>
+                            <ColumnDefinition Width="Auto" SharedSizeGroup="Name" />
+                            <ColumnDefinition />
+                        </Grid.ColumnDefinitions>
+                        <TextBlock VerticalAlignment="Center" HorizontalAlignment="Left" Text="背景模糊" Margin="0,0,25,0" />
+                        <local:MySlider x:Name="SliderBackgroundBlur" Tag="UiBackgroundBlur" MaxValue="40" Grid.Column="1" ToolTip="较强的模糊会导致启动器严重掉帧,请谨慎使用。&#13;不建议在制作整合包时开启模糊,以确保 PCL 在低性能电脑上可以流畅运行。" />
+                    </Grid>
+                    <local:MyCheckBox Text="使用彩色背景" Margin="-1,0,0,8" Height="22" x:Name="CheckBackgroundColorful" Tag="UiBackgroundColorful" />
+                    <Grid Height="35" Margin="0,2,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="BtnBackgroundOpen" MinWidth="140" Text="打开文件夹" Padding="13,0" Margin="0,0,20,0" ToolTip="将背景图片放到该文件夹,PCL 将会在每次打开时随机加载其中的一张图片"/>
+                        <local:MyButton x:Name="BtnBackgroundRefresh" MinWidth="140" Text="刷新背景图片" Padding="13,0" Margin="0,0,20,0" ToolTip="随机加载文件夹内的一张背景图片" Grid.Column="1"/>
+                        <local:MyButton x:Name="BtnBackgroundClear" MinWidth="140" Text="清空背景图片" Visibility="Collapsed" Padding="13,0" Margin="0,0,20,0" ColorType="Red" Grid.Column="2"/>
+                    </Grid>
+                </StackPanel>
+            </local:MyCard>
+            <local:MyCard x:Name="CardMusic" Margin="0,0,0,15" Title="背景音乐">
+                <StackPanel Margin="25,42,25,20">
+                    <Grid x:Name="PanMusicVolume" Visibility="Collapsed" Height="22" Margin="0,0,0,10">
+                        <Grid.ColumnDefinitions>
+                            <ColumnDefinition Width="Auto" SharedSizeGroup="Name" />
+                            <ColumnDefinition />
+                        </Grid.ColumnDefinitions>
+                        <TextBlock VerticalAlignment="Center" HorizontalAlignment="Left" Text="音量" Margin="0,0,25,0" />
+                        <local:MySlider x:Name="SliderMusicVolume" Tag="UiMusicVolume" MaxValue="1000" ValueByKey="10" Grid.Column="1" />
+                    </Grid>
+                    <StackPanel x:Name="PanMusicDetail" Visibility="Collapsed" Margin="-1,0,0,3">
+                        <local:MyCheckBox Text="随机播放" Margin="0,0,0,5" Height="22" x:Name="CheckMusicRandom" Tag="UiMusicRandom" />
+                        <local:MyCheckBox Text="打开启动器自动开始播放" Margin="0,0,0,5" Height="22" x:Name="CheckMusicAuto" Tag="UiMusicAuto" />
+                        <local:MyCheckBox Text="游戏启动后自动开始播放,游戏退出后自动暂停播放" Margin="0,0,0,5" Height="22" x:Name="CheckMusicStart" Tag="UiMusicStart" />
+                        <local:MyCheckBox Text="游戏启动后自动暂停播放,游戏退出后自动开始播放" Margin="0,0,0,5" Height="22" x:Name="CheckMusicStop" Tag="UiMusicStop" />
+                    </StackPanel>
+                    <Grid Height="35">
+                        <Grid.ColumnDefinitions>
+                            <ColumnDefinition Width="Auto" SharedSizeGroup="Button" />
+                            <ColumnDefinition Width="Auto" SharedSizeGroup="Button" />
+                            <ColumnDefinition Width="Auto" SharedSizeGroup="Button" />
+                        </Grid.ColumnDefinitions>
+                        <local:MyButton x:Name="BtnMusicOpen" Text="打开文件夹" MinWidth="140" Padding="13,0" Margin="0,0,20,0" ToolTip="将背景音乐放到该文件夹,PCL 将会播放其中的所有音乐"/>
+                        <local:MyButton x:Name="BtnMusicRefresh" Text="刷新背景音乐" MinWidth="140" Padding="13,0" Margin="0,0,20,0" ToolTip="刷新播放列表,并播放列表中的音乐" Grid.Column="1"/>
+                        <local:MyButton x:Name="BtnMusicClear" Text="清空背景音乐" MinWidth="140" Visibility="Collapsed" Padding="13,0" Margin="0,0,20,0" ColorType="Red" Grid.Column="2"/>
+                    </Grid>
+                </StackPanel>
+            </local:MyCard>
+            <local:MyCard x:Name="CardLogo" Margin="0,0,0,15" Title="标题栏">
+                <StackPanel Margin="25,40,25,15">
+                    <Grid Margin="-1,0,0,0">
+                        <Grid.ColumnDefinitions>
+                            <ColumnDefinition Width="1*" />
+                            <ColumnDefinition Width="1*" />
+                            <ColumnDefinition Width="1*" />
+                            <ColumnDefinition Width="1*" />
+                            <ColumnDefinition Width="0.2*" />
+                        </Grid.ColumnDefinitions>
+                        <local:MyRadioBox Text="无" x:Name="RadioLogoType0" Height="22" Tag="UiLogoType/0" Grid.Column="0" />
+                        <local:MyRadioBox Text="默认" x:Name="RadioLogoType1" Height="22" Tag="UiLogoType/1" Grid.Column="1" />
+                        <local:MyRadioBox Text="文本" x:Name="RadioLogoType2" Height="22" Tag="UiLogoType/2" Grid.Column="2" />
+                        <local:MyRadioBox Text="图片" x:Name="RadioLogoType3" Height="22" Tag="UiLogoType/3" Grid.Column="3" />
+                    </Grid>
+                    <local:MyCheckBox Text="标题栏居左" Margin="-1,8,0,3" Height="22" x:Name="CheckLogoLeft" Tag="UiLogoLeft" Visibility="Collapsed" />
+                    <Grid x:Name="PanLogoText" Margin="0,14,0,5" Visibility="Collapsed">
+                        <Grid.ColumnDefinitions>
+                            <ColumnDefinition Width="Auto" SharedSizeGroup="Name" />
+                            <ColumnDefinition />
+                        </Grid.ColumnDefinitions>
+                        <TextBlock VerticalAlignment="Center" HorizontalAlignment="Left" Text="标题栏文本" Margin="0,0,25,0" />
+                        <local:MyTextBox x:Name="TextLogoText" Tag="UiLogoText" Grid.Column="1" MaxLength="30" />
+                    </Grid>
+                    <Grid x:Name="PanLogoChange" Margin="0,14,0,5" Height="35" Visibility="Collapsed">
+                        <Grid.ColumnDefinitions>
+                            <ColumnDefinition Width="Auto" SharedSizeGroup="Button" />
+                            <ColumnDefinition Width="Auto" SharedSizeGroup="Button" />
+                        </Grid.ColumnDefinitions>
+                        <local:MyButton x:Name="BtnLogoChange" Text="更改图片" MinWidth="140" Padding="13,0" Margin="0,0,20,0" />
+                        <local:MyButton x:Name="BtnLogoDelete" Text="清空图片" MinWidth="140" Padding="13,0" Margin="0,0,20,0" ColorType="Red" Grid.Column="1" />
+                    </Grid>
+                </StackPanel>
+            </local:MyCard>
+            <local:MyCard Margin="0,0,0,15" Title="主页" x:Name="CardCustom">
+                <StackPanel Margin="25,40,25,15">
+                    <Grid Margin="-1,0,0,0">
+                        <Grid.ColumnDefinitions>
+                            <ColumnDefinition Width="1*" />
+                            <ColumnDefinition Width="1*" />
+                            <ColumnDefinition Width="1*" />
+                            <ColumnDefinition Width="1*" />
+                            <ColumnDefinition Width="0.2*" />
+                        </Grid.ColumnDefinitions>
+                        <local:MyRadioBox Text="空白" x:Name="RadioCustomType0" Height="22" Tag="UiCustomType/0" Grid.Column="0" />
+                        <local:MyRadioBox Text="预设" x:Name="RadioCustomType3" Height="22" Tag="UiCustomType/3" Grid.Column="1" />
+                        <local:MyRadioBox Text="读取本地文件" x:Name="RadioCustomType1" Height="22" Tag="UiCustomType/1" Grid.Column="2" />
+                        <local:MyRadioBox Text="联网更新" x:Name="RadioCustomType2" Height="22" Tag="UiCustomType/2" Grid.Column="3" />
+                    </Grid>
+                    <local:MyHint Margin="0,15,0,1" Text="内容见 ModSetup" IsWarn="False" x:Name="HintCustom" />
+                    <Grid Height="35" x:Name="PanCustomLocal" Visibility="Collapsed" Margin="0,10,0,5">
+                        <Grid.ColumnDefinitions>
+                            <ColumnDefinition Width="Auto" SharedSizeGroup="Button" />
+                            <ColumnDefinition Width="Auto" SharedSizeGroup="Button" />
+                            <ColumnDefinition Width="Auto" SharedSizeGroup="Button" />
+                        </Grid.ColumnDefinitions>
+                        <local:MyButton x:Name="BtnCustomRefresh" Grid.Column="0" MinWidth="140" Text="刷新主页" Padding="13,0" Margin="0,0,20,0" HorizontalAlignment="Left" ColorType="Highlight" />
+                        <local:MyButton x:Name="BtnCustomFile" Grid.Column="1" MinWidth="140" Text="生成教学文件" Padding="13,0" Margin="0,0,20,0" HorizontalAlignment="Left" />
+                        <local:MyButton x:Name="BtnCustomTutorial" Grid.Column="2" MinWidth="140" Text="查看教程" Padding="13,0" Margin="0,0,20,0" HorizontalAlignment="Left" />
+                    </Grid>
+                    <Grid x:Name="PanCustomNet" Visibility="Collapsed" Margin="0,10,0,5">
+                        <Grid.ColumnDefinitions>
+                            <ColumnDefinition Width="Auto" SharedSizeGroup="Name" />
+                            <ColumnDefinition />
+                        </Grid.ColumnDefinitions>
+                        <TextBlock VerticalAlignment="Center" HorizontalAlignment="Left" Text="下载地址" Margin="0,0,25,0" />
+                        <local:MyTextBox x:Name="TextCustomNet" Tag="UiCustomNet" Grid.Column="1" MaxHeight="28">
+                            <local:MyTextBox.ValidateRules>
+                                <local:ValidateHttp />
+                            </local:MyTextBox.ValidateRules>
+                        </local:MyTextBox>
+                    </Grid>
+                    <Grid x:Name="PanCustomPreset" Visibility="Collapsed" Margin="0,12,10,5" Height="28">
+                        <Grid.ColumnDefinitions>
+                            <ColumnDefinition Width="Auto" SharedSizeGroup="Name" />
+                            <ColumnDefinition />
+                        </Grid.ColumnDefinitions>
+                        <TextBlock VerticalAlignment="Center" HorizontalAlignment="Left" Text="主页预设" Margin="0,0,25,0" />
+                        <local:MyComboBox x:Name="ComboCustomPreset" Grid.ColumnSpan="2" Tag="UiCustomPreset" Grid.Column="1">
+                            <local:MyComboBoxItem Content="你知道吗?" IsSelected="True" />
+                            <local:MyComboBoxItem Content="回声洞" />
+                            <local:MyComboBoxItem Content="Minecraft 新闻(作者:最亮的信标)" />
+                            <local:MyComboBoxItem Content="简单主页(作者:MFn233)" />
+                            <local:MyComboBoxItem Content="每日整合包推荐(作者:wkea)" />
+                            <local:MyComboBoxItem Content="Minecraft 皮肤推荐(作者:wkea)" />
+                        </local:MyComboBox>
+                    </Grid>
+                </StackPanel>
+            </local:MyCard>
+            <local:MyCard x:Name="CardSwitch" Margin="0,0,0,15" Title="功能隐藏">
+                <StackPanel Margin="25,38,15,15">
+                    <TextBlock Margin="0,1,0,1" Text="你可以隐藏不需要的页面或关闭特定功能。在任意界面按 F12 可以暂时显示被隐藏的功能。" TextWrapping="Wrap" />
+                    <Grid>
+                        <Grid.ColumnDefinitions>
+                            <ColumnDefinition Width="Auto" />
+                            <ColumnDefinition Width="18" />
+                            <ColumnDefinition Width="0.8*" />
+                            <ColumnDefinition Width="0.9*" />
+                            <ColumnDefinition Width="0.8*" />
+                            <ColumnDefinition Width="0.6*" />
+                            <ColumnDefinition Width="1.0*" />
+                        </Grid.ColumnDefinitions>
+                        <Grid.RowDefinitions>
+                            <RowDefinition Height="4" />
+                            <RowDefinition Height="30" />
+                            <RowDefinition Height="30" />
+                            <RowDefinition Height="30" />
+                            <RowDefinition Height="30" />
+                            <RowDefinition Height="Auto" />
+                        </Grid.RowDefinitions>
+                        <TextBlock Grid.Row="1" VerticalAlignment="Center" HorizontalAlignment="Left" Text="主页面" />
+                        <local:MyCheckBox Height="22" VerticalAlignment="Center" Grid.Row="1" Grid.Column="2" Text="下载" x:Name="CheckHiddenPageDownload" Tag="UiHiddenPageDownload" />
+                        <local:MyCheckBox Height="22" VerticalAlignment="Center" Grid.Row="1" Grid.Column="3" Visibility="Collapsed" Text="联机" x:Name="CheckHiddenPageLink" Tag="UiHiddenPageLink" />
+                        <local:MyCheckBox Height="22" VerticalAlignment="Center" Grid.Row="1" Grid.Column="3" Text="设置" x:Name="CheckHiddenPageSetup" Tag="UiHiddenPageSetup" />
+                        <local:MyCheckBox Height="22" VerticalAlignment="Center" Grid.Row="1" Grid.Column="4" Text="更多" x:Name="CheckHiddenPageOther" Tag="UiHiddenPageOther" />
+                        <TextBlock Grid.Row="2" VerticalAlignment="Center" HorizontalAlignment="Left" Text="设置 子页面" />
+                        <local:MyCheckBox Height="22" VerticalAlignment="Center" Grid.Row="2" Grid.Column="2" Text="游戏" x:Name="CheckHiddenSetupLaunch" Tag="UiHiddenSetupLaunch" />
+                        <local:MyCheckBox Height="22" VerticalAlignment="Center" Grid.Row="2" Grid.Column="3" Text="个性化" x:Name="CheckHiddenSetupUI" Tag="UiHiddenSetupUi" />
+                        <local:MyCheckBox Height="22" VerticalAlignment="Center" Grid.Row="2" Grid.Column="4" Text="启动器" x:Name="CheckHiddenSetupSystem" Tag="UiHiddenSetupSystem" />
+                        <local:MyCheckBox Height="22" VerticalAlignment="Center" Grid.Row="2" Grid.Column="5" Text="联机" x:Name="CheckHiddenSetupLink" Tag="UiHiddenSetupLink" Visibility="Collapsed" />
+                        <TextBlock Grid.Row="3" VerticalAlignment="Center" HorizontalAlignment="Left" Text="更多 子页面" />
+                        <local:MyCheckBox Height="22" VerticalAlignment="Center" Grid.Row="3" Grid.Column="2" Text="帮助" x:Name="CheckHiddenOtherHelp" Tag="UiHiddenOtherHelp" />
+                        <local:MyCheckBox Height="22" VerticalAlignment="Center" Grid.Row="3" Grid.Column="3" Text="关于与鸣谢" x:Name="CheckHiddenOtherAbout" Tag="UiHiddenOtherAbout" />
+                        <local:MyCheckBox Height="22" VerticalAlignment="Center" Grid.Row="3" Grid.Column="4" Text="百宝箱" x:Name="CheckHiddenOtherTest" Tag="UiHiddenOtherTest" />
+                        <local:MyCheckBox Height="22" VerticalAlignment="Center" Grid.Row="3" Grid.Column="5" Text="反馈" x:Name="CheckHiddenOtherFeedback" Tag="UiHiddenOtherFeedback" />
+                        <local:MyCheckBox Height="22" VerticalAlignment="Center" Grid.Row="3" Grid.Column="6" Text="新功能投票" x:Name="CheckHiddenOtherVote" Tag="UiHiddenOtherVote" />
+                        <TextBlock Grid.Row="4" VerticalAlignment="Center" HorizontalAlignment="Left" Text="特定功能" />
+                        <local:MyCheckBox Height="22" VerticalAlignment="Center" Grid.Row="4" Grid.Column="2" Text="邮箱隐藏" x:Name="CheckLauncherEmail" Tag="UiLauncherEmail" ToolTip="隐藏第三方登录的账号邮箱显示,并尽量将邮箱打码,以避免隐私泄露。&#xa;此选项的更改将在重启启动器后生效。" />
+                        <local:MyCheckBox Height="22" VerticalAlignment="Center" Grid.Row="4" Grid.Column="3" Text="版本选择" x:Name="CheckHiddenFunctionSelect" Tag="UiHiddenFunctionSelect" />
+                        <local:MyCheckBox Height="22" VerticalAlignment="Center" Grid.Row="4" Grid.Column="4" Text="功能隐藏" x:Name="CheckHiddenFunctionHidden" Tag="UiHiddenFunctionHidden" ToolTip="仅隐藏本选项卡,设置的禁用内容依然有效。&#xa;可以在保留个性化设置页面的情况下避免隐藏设置被修改。" />
+                    </Grid>
+                </StackPanel>
+            </local:MyCard>
+        </StackPanel>
+    </local:MyScrollViewer>
+</local:MyPageRight>

+ 705 - 0
Plain Craft Launcher 2/Pages/PageSetup/PageSetupUI.xaml.vb

@@ -0,0 +1,705 @@
+Public Class PageSetupUI
+
+    Public Shadows IsLoaded As Boolean = False
+
+    Private Sub PageSetupUI_Loaded(sender As Object, e As RoutedEventArgs) Handles Me.Loaded
+
+        '重复加载部分
+        PanBack.ScrollToHome()
+        ThemeCheckAll(True)
+
+        If ThemeDontClick <> 0 Then
+            Dim NewText As String
+            Select Case ThemeDontClick
+                Case 1
+                    NewText = "眼瞎白"
+                Case 2
+                    NewText = "真·滑稽彩"
+                Case Else
+                    NewText = "???"
+            End Select
+            For Each Control In PanLauncherTheme.Children
+                If (TypeOf Control Is MyRadioBox) AndAlso CType(Control, MyRadioBox).IsEnabled Then
+                    CType(Control, MyRadioBox).Text = NewText
+                End If
+            Next
+        End If
+
+        '非重复加载部分
+        If IsLoaded Then Exit Sub
+        IsLoaded = True
+
+        AniControlEnabled += 1
+        SliderLoad()
+        Reload()
+        AniControlEnabled -= 1
+
+#If BETA Then
+        PanLauncherHide.Visibility = Visibility.Visible
+#End If
+
+        '设置解锁
+        If Not RadioLauncherTheme8.IsEnabled Then LabLauncherTheme8Copy.ToolTip = "累积赞助达到 ¥23.33 后,在爱发电私信发送【解锁码】以解锁。" & vbCrLf & "右键打开赞助页面,如果觉得 PCL 做得还不错就支持一下吧 =w=!"
+        RadioLauncherTheme8.ToolTip = "累积赞助达到 ¥23.33 后,在爱发电私信发送【解锁码】以解锁"
+        If Not RadioLauncherTheme9.IsEnabled Then LabLauncherTheme9Copy.ToolTip = "· 反馈一个 Bug,在 Issue 标记为 [已完成] 后回复 Issue 要求解锁(右键打开反馈页面)" & vbCrLf & "· 向帮助库提交 Pull Request,在龙猫合并后解锁"
+        RadioLauncherTheme9.ToolTip = "· 反馈一个 Bug,在反馈标记为 [完成] 后回复 Issue 要求解锁" & vbCrLf & "· 向帮助库提交 Pull Request,在龙猫合并后解锁"
+        '极客蓝的处理在 ThemeCheck 中
+
+    End Sub
+    Public Sub Reload()
+        Try
+
+            '启动器
+            SliderLauncherOpacity.Value = Setup.Get("UiLauncherTransparent")
+            SliderLauncherHue.Value = Setup.Get("UiLauncherHue")
+            SliderLauncherSat.Value = Setup.Get("UiLauncherSat")
+            SliderLauncherDelta.Value = Setup.Get("UiLauncherDelta")
+            SliderLauncherLight.Value = Setup.Get("UiLauncherLight")
+            If Setup.Get("UiLauncherTheme") <= 14 Then CType(FindName("RadioLauncherTheme" & Setup.Get("UiLauncherTheme")), MyRadioBox).Checked = True
+            CheckLauncherLogo.Checked = Setup.Get("UiLauncherLogo")
+            CheckLauncherEmail.Checked = Setup.Get("UiLauncherEmail")
+
+            '背景图片
+            SliderBackgroundOpacity.Value = Setup.Get("UiBackgroundOpacity")
+            SliderBackgroundBlur.Value = Setup.Get("UiBackgroundBlur")
+            ComboBackgroundSuit.SelectedIndex = Setup.Get("UiBackgroundSuit")
+            CheckBackgroundColorful.Checked = Setup.Get("UiBackgroundColorful")
+            BackgroundRefresh(False, False)
+
+            '标题栏
+            CType(FindName("RadioLogoType" & Setup.Get("UiLogoType")), MyRadioBox).Checked = True
+            CheckLogoLeft.Visibility = If(RadioLogoType0.Checked, Visibility.Visible, Visibility.Collapsed)
+            PanLogoText.Visibility = If(RadioLogoType2.Checked, Visibility.Visible, Visibility.Collapsed)
+            PanLogoChange.Visibility = If(RadioLogoType3.Checked, Visibility.Visible, Visibility.Collapsed)
+            TextLogoText.Text = Setup.Get("UiLogoText")
+            CheckLogoLeft.Checked = Setup.Get("UiLogoLeft")
+
+            '背景音乐
+            CheckMusicRandom.Checked = Setup.Get("UiMusicRandom")
+            CheckMusicAuto.Checked = Setup.Get("UiMusicAuto")
+            CheckMusicStop.Checked = Setup.Get("UiMusicStop")
+            CheckMusicStart.Checked = Setup.Get("UiMusicStart")
+            SliderMusicVolume.Value = Setup.Get("UiMusicVolume")
+            MusicRefreshUI()
+
+            '主页
+            ComboCustomPreset.SelectedIndex = Setup.Get("UiCustomPreset")
+            CType(FindName("RadioCustomType" & Setup.Load("UiCustomType")), MyRadioBox).Checked = True
+            TextCustomNet.Text = Setup.Get("UiCustomNet")
+
+            '功能隐藏
+            CheckHiddenPageDownload.Checked = Setup.Get("UiHiddenPageDownload")
+            CheckHiddenPageLink.Checked = Setup.Get("UiHiddenPageLink")
+            CheckHiddenPageSetup.Checked = Setup.Get("UiHiddenPageSetup")
+            CheckHiddenPageOther.Checked = Setup.Get("UiHiddenPageOther")
+            CheckHiddenFunctionSelect.Checked = Setup.Get("UiHiddenFunctionSelect")
+            CheckHiddenFunctionHidden.Checked = Setup.Get("UiHiddenFunctionHidden")
+            CheckHiddenSetupLaunch.Checked = Setup.Get("UiHiddenSetupLaunch")
+            CheckHiddenSetupUI.Checked = Setup.Get("UiHiddenSetupUi")
+            CheckHiddenSetupLink.Checked = Setup.Get("UiHiddenSetupLink")
+            CheckHiddenSetupSystem.Checked = Setup.Get("UiHiddenSetupSystem")
+            CheckHiddenOtherAbout.Checked = Setup.Get("UiHiddenOtherAbout")
+            CheckHiddenOtherFeedback.Checked = Setup.Get("UiHiddenOtherFeedback")
+            CheckHiddenOtherVote.Checked = Setup.Get("UiHiddenOtherVote")
+            CheckHiddenOtherHelp.Checked = Setup.Get("UiHiddenOtherHelp")
+            CheckHiddenOtherTest.Checked = Setup.Get("UiHiddenOtherTest")
+
+        Catch ex As NullReferenceException
+            Log(ex, "个性化设置项存在异常,已被自动重置", LogLevel.Msgbox)
+            Reset()
+        Catch ex As Exception
+            Log(ex, "重载个性化设置时出错", LogLevel.Feedback)
+        End Try
+    End Sub
+
+    '初始化
+    Public Sub Reset()
+        Try
+            Setup.Reset("UiLauncherTransparent")
+            Setup.Reset("UiLauncherTheme")
+            Setup.Reset("UiLauncherLogo")
+            Setup.Reset("UiLauncherHue")
+            Setup.Reset("UiLauncherSat")
+            Setup.Reset("UiLauncherDelta")
+            Setup.Reset("UiLauncherLight")
+            Setup.Reset("UiLauncherEmail")
+            Setup.Reset("UiBackgroundColorful")
+            Setup.Reset("UiBackgroundOpacity")
+            Setup.Reset("UiBackgroundBlur")
+            Setup.Reset("UiBackgroundSuit")
+            Setup.Reset("UiLogoType")
+            Setup.Reset("UiLogoText")
+            Setup.Reset("UiLogoLeft")
+            Setup.Reset("UiMusicVolume")
+            Setup.Reset("UiMusicStop")
+            Setup.Reset("UiMusicStart")
+            Setup.Reset("UiMusicRandom")
+            Setup.Reset("UiMusicAuto")
+            Setup.Reset("UiCustomType")
+            Setup.Reset("UiCustomPreset")
+            Setup.Reset("UiCustomNet")
+            Setup.Reset("UiHiddenPageDownload")
+            Setup.Reset("UiHiddenPageLink")
+            Setup.Reset("UiHiddenPageSetup")
+            Setup.Reset("UiHiddenPageOther")
+            Setup.Reset("UiHiddenFunctionSelect")
+            Setup.Reset("UiHiddenFunctionHidden")
+            Setup.Reset("UiHiddenSetupLaunch")
+            Setup.Reset("UiHiddenSetupUi")
+            Setup.Reset("UiHiddenSetupLink")
+            Setup.Reset("UiHiddenSetupSystem")
+            Setup.Reset("UiHiddenOtherAbout")
+            Setup.Reset("UiHiddenOtherFeedback")
+            Setup.Reset("UiHiddenOtherVote")
+            Setup.Reset("UiHiddenOtherHelp")
+            Setup.Reset("UiHiddenOtherTest")
+
+            Log("[Setup] 已初始化个性化设置!")
+            Hint("已初始化个性化设置", HintType.Finish, False)
+        Catch ex As Exception
+            Log(ex, "初始化个性化设置失败", LogLevel.Msgbox)
+        End Try
+
+        Reload()
+    End Sub
+
+    '将控件改变路由到设置改变
+    Private Shared Sub SliderChange(sender As MySlider, e As Object) Handles SliderBackgroundOpacity.Change, SliderBackgroundBlur.Change, SliderLauncherOpacity.Change, SliderMusicVolume.Change, SliderLauncherHue.Change, SliderLauncherLight.Change, SliderLauncherSat.Change, SliderLauncherDelta.Change
+        If AniControlEnabled = 0 Then Setup.Set(sender.Tag, sender.Value)
+    End Sub
+    Private Shared Sub ComboChange(sender As MyComboBox, e As Object) Handles ComboBackgroundSuit.SelectionChanged, ComboCustomPreset.SelectionChanged
+        If AniControlEnabled = 0 Then Setup.Set(sender.Tag, sender.SelectedIndex)
+    End Sub
+    Private Shared Sub CheckBoxChange(sender As MyCheckBox, e As Object) Handles CheckMusicStop.Change, CheckMusicRandom.Change, CheckMusicAuto.Change, CheckBackgroundColorful.Change, CheckLogoLeft.Change, CheckLauncherLogo.Change, CheckHiddenFunctionHidden.Change, CheckHiddenFunctionSelect.Change, CheckHiddenPageDownload.Change, CheckHiddenPageLink.Change, CheckHiddenPageOther.Change, CheckHiddenPageSetup.Change, CheckHiddenSetupLaunch.Change, CheckHiddenSetupSystem.Change, CheckHiddenSetupLink.Change, CheckHiddenSetupUI.Change, CheckHiddenOtherAbout.Change, CheckHiddenOtherFeedback.Change, CheckHiddenOtherVote.Change, CheckHiddenOtherHelp.Change, CheckHiddenOtherTest.Change, CheckMusicStart.Change, CheckLauncherEmail.Change
+        If AniControlEnabled = 0 Then Setup.Set(sender.Tag, sender.Checked)
+    End Sub
+    Private Shared Sub TextBoxChange(sender As MyTextBox, e As Object) Handles TextLogoText.ValidatedTextChanged, TextCustomNet.ValidatedTextChanged
+        If AniControlEnabled = 0 Then Setup.Set(sender.Tag, sender.Text)
+    End Sub
+    Private Shared Sub RadioBoxChange(sender As MyRadioBox, e As Object) Handles RadioLogoType0.Check, RadioLogoType1.Check, RadioLogoType2.Check, RadioLogoType3.Check, RadioLauncherTheme0.Check, RadioLauncherTheme1.Check, RadioLauncherTheme2.Check, RadioLauncherTheme3.Check, RadioLauncherTheme4.Check, RadioLauncherTheme5.Check, RadioLauncherTheme6.Check, RadioLauncherTheme7.Check, RadioLauncherTheme8.Check, RadioLauncherTheme9.Check, RadioLauncherTheme10.Check, RadioLauncherTheme11.Check, RadioLauncherTheme12.Check, RadioLauncherTheme13.Check, RadioLauncherTheme14.Check, RadioCustomType0.Check, RadioCustomType1.Check, RadioCustomType2.Check, RadioCustomType3.Check
+        If AniControlEnabled = 0 Then Setup.Set(sender.Tag.ToString.Split("/")(0), Val(sender.Tag.ToString.Split("/")(1)))
+    End Sub
+
+    '背景图片
+    Private Sub BtnUIBgOpen_Click(sender As Object, e As EventArgs) Handles BtnBackgroundOpen.Click
+        OpenExplorer("""" & Path & "PCL\Pictures""")
+    End Sub
+    Private Sub BtnBackgroundRefresh_Click(sender As Object, e As EventArgs) Handles BtnBackgroundRefresh.Click
+        BackgroundRefresh(True, True)
+    End Sub
+    Public Sub BackgroundRefreshUI(Show As Boolean, Count As Integer)
+        If IsNothing(PanBackgroundOpacity) Then Exit Sub
+        If Show Then
+            PanBackgroundOpacity.Visibility = Visibility.Visible
+            PanBackgroundBlur.Visibility = Visibility.Visible
+            PanBackgroundSuit.Visibility = Visibility.Visible
+            BtnBackgroundClear.Visibility = Visibility.Visible
+            CardBackground.Title = "背景图片(" & Count & " 张)"
+        Else
+            PanBackgroundOpacity.Visibility = Visibility.Collapsed
+            PanBackgroundBlur.Visibility = Visibility.Collapsed
+            PanBackgroundSuit.Visibility = Visibility.Collapsed
+            BtnBackgroundClear.Visibility = Visibility.Collapsed
+            CardBackground.Title = "背景图片"
+        End If
+        CardBackground.TriggerForceResize()
+    End Sub
+    Private Sub BtnBackgroundClear_Click(sender As Object, e As EventArgs) Handles BtnBackgroundClear.Click
+        If MyMsgBox("即将删除背景图片文件夹中的所有文件。" & vbCrLf & "此操作不可撤销,是否确定?", "警告",, "取消", IsWarn:=True) = 1 Then
+            DeleteDirectory(Path & "PCL\Pictures")
+            BackgroundRefresh(False, True)
+            Hint("背景图片已清空!", HintType.Finish)
+        End If
+    End Sub
+    ''' <summary>
+    ''' 刷新背景图片及设置页 UI。
+    ''' </summary>
+    ''' <param name="IsHint">是否显示刷新提示。</param>
+    ''' <param name="Refresh">是否刷新图片显示。</param>
+    Public Shared Sub BackgroundRefresh(IsHint As Boolean, Refresh As Boolean)
+        Try
+
+            '获取可用的图片文件
+            Directory.CreateDirectory(Path & "PCL\Pictures\")
+            Dim Pic As New List(Of String)
+            For Each File In EnumerateFiles(Path & "PCL\Pictures\")
+                If File.Extension.ToLower <> ".ini" AndAlso File.Extension.ToLower <> ".db" Then '文件夹可能会被加入 .ini 和 thumbs.db
+                    Pic.Add(File.FullName)
+                End If
+            Next
+            '加载
+            If Not Pic.Any() Then
+                If Refresh Then
+                    If FrmMain.ImgBack.Visibility = Visibility.Collapsed Then
+                        If IsHint Then Hint("未检测到可用背景图片!", HintType.Critical)
+                    Else
+                        FrmMain.ImgBack.Visibility = Visibility.Collapsed
+                        If IsHint Then Hint("背景图片已清除!", HintType.Finish)
+                    End If
+                End If
+                If Not IsNothing(FrmSetupUI) Then FrmSetupUI.BackgroundRefreshUI(False, 0)
+            Else
+                If Refresh Then
+                    Dim Address As String = RandomOne(Pic)
+                    Try
+                        Log("[UI] 加载背景图片:" & Address)
+                        FrmMain.ImgBack.Background = New MyBitmap(Address)
+                        Setup.Load("UiBackgroundSuit", True)
+                        FrmMain.ImgBack.Visibility = Visibility.Visible
+                        If IsHint Then Hint("背景图片已刷新:" & GetFileNameFromPath(Address), HintType.Finish, False)
+                    Catch ex As Exception
+                        If ex.Message.Contains("参数无效") Then
+                            Log("刷新背景图片失败,该图片文件可能并非标准格式。" & vbCrLf &
+                                "你可以尝试使用画图打开该文件并重新保存,这会让图片变为标准格式。" & vbCrLf &
+                                "文件:" & Address, LogLevel.Msgbox)
+                        Else
+                            Log(ex, "刷新背景图片失败(" & Address & ")", LogLevel.Msgbox)
+                        End If
+                    End Try
+                End If
+                If Not IsNothing(FrmSetupUI) Then FrmSetupUI.BackgroundRefreshUI(True, Pic.Count)
+            End If
+
+        Catch ex As Exception
+            Log(ex, "刷新背景图片时出现未知错误", LogLevel.Feedback)
+        End Try
+    End Sub
+
+
+    '顶部栏
+    Private Sub BtnLogoChange_Click(sender As Object, e As EventArgs) Handles BtnLogoChange.Click
+        Dim FileName As String = SelectFile("常用图片文件(*.png;*.jpg;*.gif)|*.png;*.jpg;*.gif", "选择图片")
+        If FileName = "" Then Exit Sub
+        Try
+            '拷贝文件
+            File.Delete(Path & "PCL\Logo.png")
+            CopyFile(FileName, Path & "PCL\Logo.png")
+            '设置当前显示
+            FrmMain.ImageTitleLogo.Source = New MyBitmap(Path & "PCL\Logo.png")
+        Catch ex As Exception
+            If ex.Message.Contains("参数无效") Then
+                Log("改变标题栏图片失败,该图片文件可能并非标准格式。" & vbCrLf &
+                    "你可以尝试使用画图打开该文件并重新保存,这会让图片变为标准格式。", LogLevel.Msgbox)
+            Else
+                Log(ex, "设置标题栏图片失败", LogLevel.Msgbox)
+            End If
+            FrmMain.ImageTitleLogo.Source = Nothing
+        End Try
+    End Sub
+    Private Sub RadioLogoType3_Check(sender As Object, e As RouteEventArgs) Handles RadioLogoType3.PreviewCheck
+        If Not (AniControlEnabled = 0 AndAlso e.RaiseByMouse) Then Exit Sub
+Refresh:
+        '已有图片则不再选择
+        If File.Exists(Path & "PCL\Logo.png") Then
+            Try
+                FrmMain.ImageTitleLogo.Source = New MyBitmap(Path & "PCL\Logo.png")
+            Catch ex As Exception
+                If ex.Message.Contains("参数无效") Then
+                    Log("调整标题栏图片失败,该图片文件可能并非标准格式。" & vbCrLf &
+                    "你可以尝试使用画图打开该文件并重新保存,这会让图片变为标准格式。", LogLevel.Msgbox)
+                Else
+                    Log(ex, "调整标题栏图片失败", LogLevel.Msgbox)
+                End If
+                FrmMain.ImageTitleLogo.Source = Nothing
+                e.Handled = True
+                Try
+                    File.Delete(Path & "PCL\Logo.png")
+                Catch exx As Exception
+                    Log(exx, "清理错误的标题栏图片失败", LogLevel.Msgbox)
+                End Try
+            End Try
+            Exit Sub
+        End If
+        '没有图片则要求选择
+        Dim FileName As String = SelectFile("常用图片文件(*.png;*.jpg;*.gif)|*.png;*.jpg;*.gif", "选择图片")
+        If FileName = "" Then
+            FrmMain.ImageTitleLogo.Source = Nothing
+            e.Handled = True
+        Else
+            Try
+                '拷贝文件
+                File.Delete(Path & "PCL\Logo.png")
+                CopyFile(FileName, Path & "PCL\Logo.png")
+                GoTo Refresh
+            Catch ex As Exception
+                Log(ex, "复制标题栏图片失败", LogLevel.Msgbox)
+            End Try
+        End If
+    End Sub
+    Private Sub BtnLogoDelete_Click(sender As Object, e As EventArgs) Handles BtnLogoDelete.Click
+        Try
+            File.Delete(Path & "PCL\Logo.png")
+            RadioLogoType1.SetChecked(True, True, True)
+            Hint("标题栏图片已清空!", HintType.Finish)
+        Catch ex As Exception
+            Log(ex, "清空标题栏图片失败", LogLevel.Msgbox)
+        End Try
+    End Sub
+
+    '背景音乐
+    Private Sub BtnMusicOpen_Click(sender As Object, e As EventArgs) Handles BtnMusicOpen.Click
+        OpenExplorer("""" & Path & "PCL\Musics""")
+    End Sub
+    Private Sub BtnMusicRefresh_Click(sender As Object, e As EventArgs) Handles BtnMusicRefresh.Click
+        MusicRefreshPlay(True)
+    End Sub
+    Public Sub MusicRefreshUI()
+        If PanBackgroundOpacity Is Nothing Then Exit Sub
+        If MusicAllList.Any Then
+            PanMusicVolume.Visibility = Visibility.Visible
+            PanMusicDetail.Visibility = Visibility.Visible
+            BtnMusicClear.Visibility = Visibility.Visible
+            CardMusic.Title = "背景音乐(" & EnumerateFiles(Path & "PCL\Musics\").Count & " 首)"
+        Else
+            PanMusicVolume.Visibility = Visibility.Collapsed
+            PanMusicDetail.Visibility = Visibility.Collapsed
+            BtnMusicClear.Visibility = Visibility.Collapsed
+            CardMusic.Title = "背景音乐"
+        End If
+        CardMusic.TriggerForceResize()
+    End Sub
+    Private Sub BtnMusicClear_Click(sender As Object, e As EventArgs) Handles BtnMusicClear.Click
+        If MyMsgBox("即将删除背景音乐文件夹中的所有文件。" & vbCrLf & "此操作不可撤销,是否确定?", "警告",, "取消", IsWarn:=True) = 1 Then
+            RunInThread(Sub()
+                            Hint("正在删除背景音乐……")
+                            '停止播放音乐
+                            MusicNAudio = Nothing
+                            MusicWaitingList = New List(Of String)
+                            MusicAllList = New List(Of String)
+                            Thread.Sleep(200)
+                            '删除文件
+                            Try
+                                DeleteDirectory(Path & "PCL\Musics")
+                                Hint("背景音乐已删除!", HintType.Finish)
+                            Catch ex As Exception
+                                Log(ex, "删除背景音乐失败", LogLevel.Msgbox)
+                            End Try
+                            Try
+                                Directory.CreateDirectory(Path & "PCL\Musics")
+                                RunInUi(Sub() MusicRefreshPlay(False))
+                            Catch ex As Exception
+                                Log(ex, "重建背景音乐文件夹失败", LogLevel.Msgbox)
+                            End Try
+                        End Sub)
+        End If
+    End Sub
+    Private Sub CheckMusicStart_Change() Handles CheckMusicStart.Change
+        If AniControlEnabled <> 0 Then Exit Sub
+        If CheckMusicStart.Checked Then CheckMusicStop.Checked = False
+    End Sub
+    Private Sub CheckMusicStop_Change() Handles CheckMusicStop.Change
+        If AniControlEnabled <> 0 Then Exit Sub
+        If CheckMusicStop.Checked Then CheckMusicStart.Checked = False
+    End Sub
+
+    '主页
+    Private Sub BtnCustomFile_Click(sender As Object, e As EventArgs) Handles BtnCustomFile.Click
+        Try
+            If File.Exists(Path & "PCL\Custom.xaml") Then
+                If MyMsgBox("当前已存在布局文件,继续生成教学文件将会覆盖现有布局文件!", "覆盖确认", "继续", "取消", IsWarn:=True) = 2 Then Exit Sub
+            End If
+            WriteFile(Path & "PCL\Custom.xaml", GetResources("Custom"))
+            Hint("教学文件已生成!", HintType.Finish)
+            OpenExplorer("/select,""" & Path & "PCL\Custom.xaml""")
+        Catch ex As Exception
+            Log(ex, "生成教学文件失败", LogLevel.Feedback)
+        End Try
+    End Sub
+    Private Sub BtnCustomRefresh_Click() Handles BtnCustomRefresh.Click
+        FrmLaunchRight.ForceRefresh()
+        Hint("已刷新主页!", HintType.Finish)
+    End Sub
+    Private Sub BtnCustomTutorial_Click(sender As Object, e As EventArgs) Handles BtnCustomTutorial.Click
+        MyMsgBox("1. 点击 生成教学文件 按钮,这会在 PCL 文件夹下生成 Custom.xaml 布局文件。" & vbCrLf &
+                 "2. 使用记事本等工具打开这个文件并进行修改,修改完记得保存。" & vbCrLf &
+                 "3. 点击 刷新主页 按钮,查看主页现在长啥样了。" & vbCrLf &
+                 vbCrLf &
+                 "你可以在生成教学文件后直接刷新主页,对照着进行修改,更有助于理解。" & vbCrLf &
+                 "直接将自定义主页文件拖进 PCL 窗口也可以快捷加载。", "主页自定义教程")
+    End Sub
+
+    '主题
+    Private Sub LabLauncherTheme5Unlock_MouseLeftButtonUp(sender As Object, e As MouseButtonEventArgs) Handles LabLauncherTheme5Unlock.MouseLeftButtonUp
+        RadioLauncherTheme5Gray.Opacity -= 0.23
+        RadioLauncherTheme5.Opacity += 0.23
+        AniStart({
+                     AaOpacity(RadioLauncherTheme5Gray, 1, 1000),
+                     AaOpacity(RadioLauncherTheme5, -1, 1000)
+                 }, "ThemeUnlock")
+        If RadioLauncherTheme5Gray.Opacity < 0.08 Then
+            ThemeUnlock(5, UnlockHint:="隐藏主题 玄素黑 已解锁!")
+            AniStop("ThemeUnlock")
+            RadioLauncherTheme5.Checked = True
+        End If
+    End Sub
+    Private Sub LabLauncherTheme11Click_MouseLeftButtonUp() Handles LabLauncherTheme11Click.MouseLeftButtonUp, RadioLauncherTheme11.MouseRightButtonUp
+        If LabLauncherTheme11Click.Visibility = Visibility.Collapsed OrElse LabLauncherTheme11Click.ToolTip.ToString.Contains("点击") Then
+            If MyMsgBox(
+                "1. 不爬取或攻击相关服务或网站,不盗取相关账号,没有谜题可以或需要以此来解决。" & vbCrLf &
+                "2. 不得篡改或损毁相关公开信息,请尽量让它们保持原状。" & vbCrLf &
+                "3. 在你感到迷茫的时候,看看回声洞可能会给你带来惊喜。" & vbCrLf & vbCrLf &
+                "若违规,可能会被从任意相关群中踢出!",
+                "解密游戏的基本规则", "我知道了", "恕我拒绝") = 1 Then
+                MyMsgBox("你需要用自己的智慧来找到下一步的线索……" & vbCrLf &
+                         "初始线索:gnp.dorC61\60\20\0202\moc.x1xa.2s\\:sp" & "T".ToLower & "th", "解密游戏") '防止触发病毒检测规则
+            End If
+        End If
+    End Sub
+    Private Sub LabLauncherTheme8Copy_MouseRightButtonUp() Handles LabLauncherTheme8Copy.MouseRightButtonUp
+        OpenWebsite("https://afdian.net/a/LTCat")
+    End Sub
+    Private Sub LabLauncherTheme9Copy_MouseRightButtonUp() Handles LabLauncherTheme9Copy.MouseRightButtonUp
+        PageOtherLeft.TryFeedback()
+    End Sub
+
+    '主题自定义
+    Private Sub RadioLauncherTheme14_Change(sender As Object, e As RouteEventArgs) Handles RadioLauncherTheme14.Changed
+        If RadioLauncherTheme14.Checked Then
+            If LabLauncherHue.Visibility = Visibility.Visible Then Exit Sub
+            LabLauncherHue.Visibility = Visibility.Visible
+            SliderLauncherHue.Visibility = Visibility.Visible
+            LabLauncherSat.Visibility = Visibility.Visible
+            SliderLauncherSat.Visibility = Visibility.Visible
+            LabLauncherDelta.Visibility = Visibility.Visible
+            SliderLauncherDelta.Visibility = Visibility.Visible
+            LabLauncherLight.Visibility = Visibility.Visible
+            SliderLauncherLight.Visibility = Visibility.Visible
+        Else
+            If LabLauncherHue.Visibility = Visibility.Collapsed Then Exit Sub
+            LabLauncherHue.Visibility = Visibility.Collapsed
+            SliderLauncherHue.Visibility = Visibility.Collapsed
+            LabLauncherSat.Visibility = Visibility.Collapsed
+            SliderLauncherSat.Visibility = Visibility.Collapsed
+            LabLauncherDelta.Visibility = Visibility.Collapsed
+            SliderLauncherDelta.Visibility = Visibility.Collapsed
+            LabLauncherLight.Visibility = Visibility.Collapsed
+            SliderLauncherLight.Visibility = Visibility.Collapsed
+        End If
+        CardLauncher.TriggerForceResize()
+    End Sub
+    Private Sub HSL_Change() Handles SliderLauncherHue.Change, SliderLauncherLight.Change, SliderLauncherSat.Change, SliderLauncherDelta.Change
+        If AniControlEnabled <> 0 OrElse SliderLauncherSat Is Nothing OrElse Not SliderLauncherSat.IsLoaded Then Exit Sub
+        ThemeRefresh()
+    End Sub
+
+#Region "功能隐藏"
+
+    Private Shared _HiddenForceShow As Boolean = False
+    ''' <summary>
+    ''' 是否强制显示被禁用的功能。
+    ''' </summary>
+    Public Shared Property HiddenForceShow As Boolean
+        Get
+            Return _HiddenForceShow
+        End Get
+        Set(value As Boolean)
+            _HiddenForceShow = value
+            HiddenRefresh()
+        End Set
+    End Property
+
+    ''' <summary>
+    ''' 更新功能隐藏带来的显示变化。
+    ''' </summary>
+    Public Shared Sub HiddenRefresh() Handles Me.Loaded
+        If FrmMain.PanTitleSelect Is Nothing OrElse Not FrmMain.PanTitleSelect.IsLoaded Then Exit Sub
+        Try
+            '顶部栏
+            If Not HiddenForceShow AndAlso Setup.Get("UiHiddenPageDownload") AndAlso Setup.Get("UiHiddenPageLink") AndAlso Setup.Get("UiHiddenPageSetup") AndAlso Setup.Get("UiHiddenPageOther") Then
+                '顶部栏已被全部隐藏
+                FrmMain.PanTitleSelect.Visibility = Visibility.Collapsed
+            Else
+                '顶部栏未被全部隐藏
+                FrmMain.PanTitleSelect.Visibility = Visibility.Visible
+                FrmMain.BtnTitleSelect1.Visibility = If(Not HiddenForceShow AndAlso Setup.Get("UiHiddenPageDownload"), Visibility.Collapsed, Visibility.Visible)
+                FrmMain.BtnTitleSelect2.Visibility = Visibility.Collapsed 'If(Not HiddenForceShow AndAlso Setup.Get("UiHiddenPageLink"), Visibility.Collapsed, Visibility.Visible)
+                FrmMain.BtnTitleSelect3.Visibility = If(Not HiddenForceShow AndAlso Setup.Get("UiHiddenPageSetup"), Visibility.Collapsed, Visibility.Visible)
+                FrmMain.BtnTitleSelect4.Visibility = If(Not HiddenForceShow AndAlso Setup.Get("UiHiddenPageOther"), Visibility.Collapsed, Visibility.Visible)
+            End If
+            '功能
+            FrmLaunchLeft.RefreshButtonsUI()
+            If FrmSetupUI IsNot Nothing Then
+                FrmSetupUI.CardSwitch.Visibility = If(Not HiddenForceShow AndAlso Setup.Get("UiHiddenFunctionHidden"), Visibility.Collapsed, Visibility.Visible)
+            End If
+            '设置子页面
+            If FrmSetupLeft IsNot Nothing Then
+                FrmSetupLeft.ItemLaunch.Visibility = If(Not HiddenForceShow AndAlso Setup.Get("UiHiddenSetupLaunch"), Visibility.Collapsed, Visibility.Visible)
+                FrmSetupLeft.ItemUI.Visibility = If(Not HiddenForceShow AndAlso Setup.Get("UiHiddenSetupUi"), Visibility.Collapsed, Visibility.Visible)
+                FrmSetupLeft.ItemLink.Visibility = Visibility.Collapsed 'If(Not HiddenForceShow AndAlso Setup.Get("UiHiddenSetupLink"), Visibility.Collapsed, Visibility.Visible)
+                FrmSetupLeft.ItemSystem.Visibility = If(Not HiddenForceShow AndAlso Setup.Get("UiHiddenSetupSystem"), Visibility.Collapsed, Visibility.Visible)
+                '隐藏左边选择卡
+                Dim AvaliableCount As Integer = 0
+                If Not Setup.Get("UiHiddenSetupLaunch") Then AvaliableCount += 1
+                If Not Setup.Get("UiHiddenSetupUi") Then AvaliableCount += 1
+                If Not Setup.Get("UiHiddenSetupLink") Then AvaliableCount += 1
+                If Not Setup.Get("UiHiddenSetupSystem") Then AvaliableCount += 1
+                FrmSetupLeft.PanItem.Visibility = If(AvaliableCount < 2 AndAlso Not HiddenForceShow, Visibility.Collapsed, Visibility.Visible)
+            End If
+            '更多子页面
+            Dim OtherAvaliableCount As Integer = 0
+            If Not Setup.Get("UiHiddenOtherHelp") Then OtherAvaliableCount += 1
+            If Not Setup.Get("UiHiddenOtherAbout") Then OtherAvaliableCount += 1
+            If Not Setup.Get("UiHiddenOtherTest") Then OtherAvaliableCount += 1
+            If Not Setup.Get("UiHiddenOtherFeedback") Then OtherAvaliableCount += 1
+            If Not Setup.Get("UiHiddenOtherVote") Then OtherAvaliableCount += 1
+            If FrmOtherLeft IsNot Nothing Then
+                FrmOtherLeft.ItemHelp.Visibility = If(Not HiddenForceShow AndAlso Setup.Get("UiHiddenOtherHelp"), Visibility.Collapsed, Visibility.Visible)
+                FrmOtherLeft.ItemFeedback.Visibility = If(Not HiddenForceShow AndAlso Setup.Get("UiHiddenOtherFeedback"), Visibility.Collapsed, Visibility.Visible)
+                FrmOtherLeft.ItemVote.Visibility = If(Not HiddenForceShow AndAlso Setup.Get("UiHiddenOtherVote"), Visibility.Collapsed, Visibility.Visible)
+                FrmOtherLeft.ItemAbout.Visibility = If(Not HiddenForceShow AndAlso Setup.Get("UiHiddenOtherAbout"), Visibility.Collapsed, Visibility.Visible)
+                FrmOtherLeft.ItemTest.Visibility = If(Not HiddenForceShow AndAlso Setup.Get("UiHiddenOtherTest"), Visibility.Collapsed, Visibility.Visible)
+                '隐藏左边选择卡
+                FrmOtherLeft.PanItem.Visibility = If(OtherAvaliableCount < 2 AndAlso Not HiddenForceShow, Visibility.Collapsed, Visibility.Visible)
+            End If
+            If OtherAvaliableCount = 1 AndAlso Not HiddenForceShow Then
+                If Not Setup.Get("UiHiddenOtherHelp") Then
+                    FrmMain.BtnTitleSelect4.Text = "帮助"
+                ElseIf Not Setup.Get("UiHiddenOtherAbout") Then
+                    FrmMain.BtnTitleSelect4.Text = "关于"
+                Else
+                    FrmMain.BtnTitleSelect4.Text = "百宝箱"
+                End If
+            Else
+                FrmMain.BtnTitleSelect4.Text = "更多"
+            End If
+            '各个页面的入口
+            If FrmMain.PageCurrent = FormMain.PageType.VersionSelect Then FrmSelectRight.BtnEmptyDownload_Loaded()
+            If FrmMain.PageCurrent = FormMain.PageType.Launch Then FrmLaunchLeft.RefreshButtonsUI()
+            If FrmMain.PageCurrent = FormMain.PageType.VersionSetup AndAlso FrmVersionModDisabled IsNot Nothing Then FrmVersionModDisabled.BtnDownload_Loaded()
+            '备注
+            If FrmSetupUI IsNot Nothing Then FrmSetupUI.CardSwitch.Title = If(HiddenForceShow, "功能隐藏(已暂时关闭,按 F12 以重新启用)", "功能隐藏")
+        Catch ex As Exception
+            Log(ex, "刷新功能隐藏项目失败", LogLevel.Feedback)
+        End Try
+    End Sub
+
+    'UI 协同改变
+    Private Sub HiddenSetupMain() Handles CheckHiddenPageSetup.Change
+        '设置主页面
+        If CheckHiddenPageSetup.Checked Then
+            '开启
+            CheckHiddenSetupLaunch.Checked = True
+            CheckHiddenSetupSystem.Checked = True
+            CheckHiddenSetupLink.Checked = True
+            CheckHiddenSetupUI.Checked = True
+        Else
+            '关闭
+            If Setup.Get("UiHiddenSetupLaunch") AndAlso Setup.Get("UiHiddenSetupUi") AndAlso Setup.Get("UiHiddenSetupSystem") AndAlso Setup.Get("UiHiddenSetupLink") Then
+                CheckHiddenSetupLaunch.Checked = False
+                CheckHiddenSetupSystem.Checked = False
+                CheckHiddenSetupLink.Checked = False
+                CheckHiddenSetupUI.Checked = False
+            End If
+        End If
+    End Sub
+    Private Sub HiddenSetupSub() Handles CheckHiddenSetupLaunch.Change, CheckHiddenSetupSystem.Change, CheckHiddenSetupLink.Change, CheckHiddenSetupUI.Change
+        '设置子页面
+        If Setup.Get("UiHiddenSetupLaunch") AndAlso Setup.Get("UiHiddenSetupUi") AndAlso Setup.Get("UiHiddenSetupSystem") AndAlso Setup.Get("UiHiddenSetupLink") Then
+            '已被全部隐藏
+            CheckHiddenPageSetup.Checked = True
+        Else
+            '未被全部隐藏
+            CheckHiddenPageSetup.Checked = False
+        End If
+    End Sub
+    Private Sub HiddenOtherMain() Handles CheckHiddenPageOther.Change
+        '更多主页面
+        If CheckHiddenPageOther.Checked Then
+            '开启
+            CheckHiddenOtherAbout.Checked = True
+            CheckHiddenOtherTest.Checked = True
+            CheckHiddenOtherFeedback.Checked = True
+            CheckHiddenOtherVote.Checked = True
+            CheckHiddenOtherHelp.Checked = True
+        Else
+            '关闭
+            If Setup.Get("UiHiddenOtherHelp") AndAlso Setup.Get("UiHiddenOtherAbout") AndAlso Setup.Get("UiHiddenOtherTest") AndAlso
+                Setup.Get("UiHiddenOtherVote") AndAlso Setup.Get("UiHiddenOtherFeedback") Then
+                CheckHiddenOtherAbout.Checked = False
+                CheckHiddenOtherTest.Checked = False
+                CheckHiddenOtherFeedback.Checked = False
+                CheckHiddenOtherVote.Checked = False
+                CheckHiddenOtherHelp.Checked = False
+            End If
+        End If
+    End Sub
+    Private Sub HiddenOtherSub(sender As Object, user As Boolean) Handles CheckHiddenOtherHelp.Change, CheckHiddenOtherAbout.Change, CheckHiddenOtherTest.Change
+        '更多子页面(有具体内容的)
+        If Setup.Get("UiHiddenOtherHelp") AndAlso Setup.Get("UiHiddenOtherAbout") AndAlso Setup.Get("UiHiddenOtherTest") Then
+            '已被全部隐藏
+            CheckHiddenPageOther.Checked = True
+        Else
+            '未被全部隐藏
+            CheckHiddenPageOther.Checked = False
+        End If
+        '修改无具体内容的项
+        If Not user Then Exit Sub
+        If Setup.Get("UiHiddenOtherHelp") AndAlso Setup.Get("UiHiddenOtherAbout") AndAlso Setup.Get("UiHiddenOtherTest") Then
+            CheckHiddenOtherFeedback.Checked = True
+            CheckHiddenOtherVote.Checked = True
+        End If
+    End Sub
+    Private Sub HiddenOtherNet(sender As Object, user As Boolean) Handles CheckHiddenOtherFeedback.Change, CheckHiddenOtherVote.Change
+        '更多子页面(无具体内容的)
+        If Not user Then Exit Sub
+        If Setup.Get("UiHiddenOtherHelp") AndAlso Setup.Get("UiHiddenOtherAbout") AndAlso Setup.Get("UiHiddenOtherTest") AndAlso
+            (Not Setup.Get("UiHiddenOtherFeedback") OrElse Not Setup.Get("UiHiddenOtherVote")) Then
+            CheckHiddenOtherAbout.Checked = False
+            CheckHiddenOtherTest.Checked = False
+            CheckHiddenOtherHelp.Checked = False
+        End If
+    End Sub
+
+    '警告提示
+    Private Sub HiddenHint(sender As Object, user As Boolean) Handles CheckHiddenFunctionHidden.Change, CheckHiddenPageSetup.Change, CheckHiddenSetupUI.Change
+        If AniControlEnabled = 0 AndAlso sender.Checked Then Hint("按 F12 即可暂时关闭功能隐藏设置。千万别忘了,要不然设置就改不回来了……")
+    End Sub
+
+#End Region
+
+    '公开预览版
+    Private Sub BtnLauncherDonate_Click(sender As Object, e As EventArgs) Handles BtnLauncherDonate.Click
+        OpenWebsite("https://afdian.net/a/LTCat")
+    End Sub
+
+    '滑动条
+    Private Sub SliderLoad()
+        SliderMusicVolume.GetHintText = Function(Value As Integer)
+                                            Return Math.Ceiling(Value * 0.1) & "%"
+                                        End Function
+        SliderLauncherOpacity.GetHintText = Function(Value As Integer)
+                                                Return Math.Round(40 + Value * 0.1) & "%"
+                                            End Function
+        SliderLauncherHue.GetHintText = Function(Value As Integer)
+                                            Return Value & "°"
+                                        End Function
+        SliderLauncherSat.GetHintText = Function(Value As Integer)
+                                            Return Value & "%"
+                                        End Function
+        SliderLauncherDelta.GetHintText = Function(Value As Integer)
+                                              If Value > 90 Then
+                                                  Return "+" & (Value - 90)
+                                              ElseIf Value = 90 Then
+                                                  Return 0
+                                              Else
+                                                  Return Value - 90
+                                              End If
+                                          End Function
+        SliderLauncherLight.GetHintText = Function(Value As Integer)
+                                              If Value > 20 Then
+                                                  Return "+" & (Value - 20)
+                                              ElseIf Value = 20 Then
+                                                  Return 0
+                                              Else
+                                                  Return Value - 20
+                                              End If
+                                          End Function
+        SliderBackgroundOpacity.GetHintText = Function(Value As Integer)
+                                                  Return Math.Round(Value * 0.1) & "%"
+                                              End Function
+        SliderBackgroundBlur.GetHintText = Function(Value As Integer)
+                                               Return Value & " 像素"
+                                           End Function
+    End Sub
+
+End Class

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

@@ -185,6 +185,10 @@
     <Compile Include="Controls\MyIconTextButton.xaml.vb">
       <DependentUpon>MyIconTextButton.xaml</DependentUpon>
     </Compile>
+    <None Include="MaskFiles\Plain Craft Launcher 2\Pages\PageOther\PageOtherTest.xaml.vb">
+      <DependentUpon>PageOtherTest.xaml</DependentUpon>
+    </None>
+    <None Include="MaskFiles\Plain Craft Launcher 2\Modules\ModSecret.vb" />
     <Compile Include="Modules\Minecraft\ModComp.vb" />
     <Compile Include="Modules\Minecraft\ModJava.vb" />
     <Compile Include="Modules\Minecraft\ModMod.vb" />
@@ -466,6 +470,10 @@
       <DependentUpon>FormMain.xaml</DependentUpon>
       <SubType>Code</SubType>
     </Compile>
+    <None Include="MaskFiles\Plain Craft Launcher 2\Pages\PageOther\PageOtherTest.xaml">
+      <Generator>MSBuild:Compile</Generator>
+      <SubType>Designer</SubType>
+    </None>
     <Page Include="Modules\Minecraft\MyLocalModItem.xaml">
       <Generator>MSBuild:Compile</Generator>
       <SubType>Designer</SubType>
@@ -916,5 +924,8 @@
   <ItemGroup>
     <Resource Include="Images\Heads\MCBBS.png" />
   </ItemGroup>
+  <ItemGroup>
+    <None Include="MaskFiles\Plain Craft Launcher 2.sln" />
+  </ItemGroup>
   <Import Project="$(MSBuildToolsPath)\Microsoft.VisualBasic.targets" />
 </Project>