龙腾猫跃 7 месяцев назад
Родитель
Сommit
af8be24506

+ 3 - 0
Plain Craft Launcher 2/Controls/MyHint.xaml.vb

@@ -107,11 +107,14 @@ Public Class MyHint
     End Sub
     End Sub
 
 
     '触发点击事件
     '触发点击事件
+    Public Event Click(sender As Object, e As MouseButtonEventArgs)
     Private IsMouseDown As Boolean = False
     Private IsMouseDown As Boolean = False
     Private Sub MyHint_MouseUp(sender As Object, e As MouseButtonEventArgs) Handles Me.MouseLeftButtonUp
     Private Sub MyHint_MouseUp(sender As Object, e As MouseButtonEventArgs) Handles Me.MouseLeftButtonUp
         If Not IsMouseDown Then Return
         If Not IsMouseDown Then Return
         IsMouseDown = False
         IsMouseDown = False
         Log("[Control] 按下提示条" & If(String.IsNullOrEmpty(Name), "", ":" & Name))
         Log("[Control] 按下提示条" & If(String.IsNullOrEmpty(Name), "", ":" & Name))
+        RaiseEvent Click(sender, e)
+        If e.Handled Then Return
         e.Handled = True
         e.Handled = True
         RaiseCustomEvent() '自定义事件
         RaiseCustomEvent() '自定义事件
     End Sub
     End Sub

+ 20 - 0
Plain Craft Launcher 2/FormMain.xaml.vb

@@ -11,6 +11,16 @@ Public Class FormMain
         Dim FeatureList As New List(Of KeyValuePair(Of Integer, String))
         Dim FeatureList As New List(Of KeyValuePair(Of Integer, String))
         '统计更新日志条目
         '统计更新日志条目
 #If BETA Then
 #If BETA Then
+        If LastVersion < 386 Then 'Release 2.12.5
+            FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "修复:无法下载 NeoForge 26.1"))
+            FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "修复:部分关键词搜不到资源,特别是中文 Mod 搜索经常没有结果"))
+            FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "优化:降低游戏的内存占用"))
+            FeatureList.Add(New KeyValuePair(Of Integer, String)(1, "修复:老版本 Windows 无法启动游戏"))
+            FeatureList.Add(New KeyValuePair(Of Integer, String)(1, "修复:连接 Mojang 的服务可能失败,提示错误码 421"))
+            FeatureList.Add(New KeyValuePair(Of Integer, String)(1, "修复:无法访问爱发电"))
+            FeatureCount += 24
+            BugCount += 19
+        End If
         If LastVersion < 383 Then 'Release 2.12.3
         If LastVersion < 383 Then 'Release 2.12.3
             FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "修复:部分关键词搜不到资源,特别是中文 Mod 搜索经常没有结果"))
             FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "修复:部分关键词搜不到资源,特别是中文 Mod 搜索经常没有结果"))
             FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "修复:下载可能完全卡住,或是下载进度反复回退"))
             FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "修复:下载可能完全卡住,或是下载进度反复回退"))
@@ -140,6 +150,16 @@ Public Class FormMain
         '3:BUG+ IMP* FEAT-
         '3:BUG+ IMP* FEAT-
         '2:BUG* IMP-
         '2:BUG* IMP-
         '1:BUG-
         '1:BUG-
+        If LastVersion < 385 Then 'Snapshot 2.12.5
+            FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "修复:无法下载 NeoForge 26.1"))
+            If LastVersion = 384 Then
+                FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "修复:下载可能失败,提示下载管理刷新线程出错"))
+                FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "修复:无法保存选择的 Minecraft 文件夹"))
+                FeatureList.Add(New KeyValuePair(Of Integer, String)(1, "修复:使用中文搜索 Mod 时, 部分结果会忽略筛选条件"))
+            End If
+            FeatureCount += 3
+            BugCount += 6
+        End If
         If LastVersion < 384 Then 'Snapshot 2.12.4
         If LastVersion < 384 Then 'Snapshot 2.12.4
             FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "修复:部分关键词搜不到资源,特别是中文 Mod 搜索经常没有结果"))
             FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "修复:部分关键词搜不到资源,特别是中文 Mod 搜索经常没有结果"))
             FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "优化:降低游戏的内存占用"))
             FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "优化:降低游戏的内存占用"))

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

@@ -14,13 +14,13 @@ Public Module ModBase
 #Region "声明"
 #Region "声明"
 
 
     '下列版本信息由更新器自动修改
     '下列版本信息由更新器自动修改
-    Public Const VersionBaseName As String = "2.12.4" '不含分支前缀的显示用版本名
-    Public Const VersionStandardCode As String = "2.12.4." & VersionBranchCode '标准格式的四段式版本号
+    Public Const VersionBaseName As String = "2.12.5" '不含分支前缀的显示用版本名
+    Public Const VersionStandardCode As String = "2.12.5." & VersionBranchCode '标准格式的四段式版本号
     Public Const CommitHash As String = "" 'Commit Hash,由 GitHub Workflow 自动替换
     Public Const CommitHash As String = "" 'Commit Hash,由 GitHub Workflow 自动替换
 #If BETA Then
 #If BETA Then
     Public Const VersionCode As Integer = 383 'Release
     Public Const VersionCode As Integer = 383 'Release
 #Else
 #Else
-    Public Const VersionCode As Integer = 384 'Snapshot
+    Public Const VersionCode As Integer = 385 'Snapshot
 #End If
 #End If
     '自动生成的版本信息
     '自动生成的版本信息
     Public Const VersionDisplayName As String = VersionBranchName & " " & VersionBaseName
     Public Const VersionDisplayName As String = VersionBranchName & " " & VersionBaseName
@@ -1336,11 +1336,12 @@ Re:
         Dim Files As String()
         Dim Files As String()
         Try
         Try
             Files = Directory.GetFiles(Path)
             Files = Directory.GetFiles(Path)
-        Catch ex As DirectoryNotFoundException '#4549
-            If Not Directory.Exists(Path) Then Return 0 '可能已被其他线程删除
-            Log(ex, $"疑似为孤立符号链接,尝试直接删除({Path})", LogLevel.Developer)
-            Directory.Delete(Path)
-            Return 0
+        Catch ex As DirectoryNotFoundException '#4549,也可能已被其他线程删除
+            If Directory.Exists(Path) Then
+                Log(ex, $"疑似为孤立符号链接,尝试直接删除({Path})", LogLevel.Developer)
+                Directory.Delete(Path)
+            End If
+            Return DeletedCount
         End Try
         End Try
         For Each FilePath As String In Files
         For Each FilePath As String In Files
             Dim RetriedFile As Boolean = False
             Dim RetriedFile As Boolean = False
@@ -1348,6 +1349,8 @@ RetryFile:
             Try
             Try
                 File.Delete(FilePath)
                 File.Delete(FilePath)
                 DeletedCount += 1
                 DeletedCount += 1
+            Catch ex As DirectoryNotFoundException
+                Return DeletedCount
             Catch ex As Exception
             Catch ex As Exception
                 If Not RetriedFile Then
                 If Not RetriedFile Then
                     RetriedFile = True
                     RetriedFile = True

+ 16 - 8
Plain Craft Launcher 2/Modules/Base/ModNet.vb

@@ -182,10 +182,19 @@ RequestFinished:
             Throw New Exception($"预处理下载文件路径失败({LocalPath})", ex)
             Throw New Exception($"预处理下载文件路径失败({LocalPath})", ex)
         End Try
         End Try
         '下载
         '下载
+        Dim RetryCount As Integer = 0
+Retry:
         Try
         Try
             File.WriteAllBytes(LocalPath, SendRequest(Url, HttpMethod.Get, SimulateBrowserHeaders:=SimulateBrowserHeaders))
             File.WriteAllBytes(LocalPath, SendRequest(Url, HttpMethod.Get, SimulateBrowserHeaders:=SimulateBrowserHeaders))
+        Catch ex As ThreadInterruptedException
+            File.Delete(LocalPath)
+            Throw
         Catch ex As Exception
         Catch ex As Exception
             File.Delete(LocalPath)
             File.Delete(LocalPath)
+            If RetryCount < 2 Then
+                RetryCount += 1
+                GoTo Retry
+            End If
             Throw New WebException($"通过网络请求直接下载小文件失败({LocalPath})", ex)
             Throw New WebException($"通过网络请求直接下载小文件失败({LocalPath})", ex)
         End Try
         End Try
     End Sub
     End Sub
@@ -284,6 +293,9 @@ RequestFinished:
             Throw
             Throw
         Catch ex As ResponsedWebException
         Catch ex As ResponsedWebException
             Throw
             Throw
+        Catch ex As FileNotFoundException
+            '由于 CacheCow 读取缓存失败,然后系统调用不存在的 System.Net.Http.Formatting.resources 抛出(#8150)
+            Throw New Exception($"网络请求时读取缓存失败", ex)
         Catch ex As Exception
         Catch ex As Exception
             RecordIPReliability(HostIp, -1)
             RecordIPReliability(HostIp, -1)
             If TypeOf ex Is OperationCanceledException OrElse TypeOf ex Is TimeoutException Then 'CancellationToken 超时
             If TypeOf ex Is OperationCanceledException OrElse TypeOf ex Is TimeoutException Then 'CancellationToken 超时
@@ -416,7 +428,7 @@ RequestFinished:
     Public ReadOnly Property NetTaskSpeedLimitHigh As Long
     Public ReadOnly Property NetTaskSpeedLimitHigh As Long
         Get
         Get
             If _NetTaskSpeedLimitHigh Is Nothing Then
             If _NetTaskSpeedLimitHigh Is Nothing Then
-                Dim Setting = PCL.Settings.Get("ToolDownloadSpeed")
+                Dim Setting As Integer = Settings.Get("ToolDownloadSpeed")
                 If Setting <= 14 Then
                 If Setting <= 14 Then
                     _NetTaskSpeedLimitHigh = (Setting + 1) * 0.1 * 1024 * 1024L
                     _NetTaskSpeedLimitHigh = (Setting + 1) * 0.1 * 1024 * 1024L
                 ElseIf Setting <= 31 Then
                 ElseIf Setting <= 31 Then
@@ -1959,13 +1971,9 @@ Retry:
     ''' 是否有正在进行中、需要在下载管理页面显示的下载任务?
     ''' 是否有正在进行中、需要在下载管理页面显示的下载任务?
     ''' </summary>
     ''' </summary>
     Public Function HasDownloadingTask(Optional IgnoreCustomDownload As Boolean = False) As Boolean
     Public Function HasDownloadingTask(Optional IgnoreCustomDownload As Boolean = False) As Boolean
-        For Each Task In LoaderTaskbar.ToList()
-            If (Task.Show AndAlso Task.State = LoadState.Loading) AndAlso
-               (Not IgnoreCustomDownload OrElse Not Task.Name.ToString.Contains("自定义下载")) Then
-                Return True
-            End If
-        Next
-        Return False
+        Return LoaderTaskbar.Any(
+        Function(Task) Task.Show AndAlso Task.State = LoadState.Loading AndAlso
+                       (Not IgnoreCustomDownload OrElse Not Task.Name.ToString.Contains("自定义下载")))
     End Function
     End Function
 
 
 #End Region
 #End Region

+ 81 - 71
Plain Craft Launcher 2/Modules/Minecraft/ModComp.vb

@@ -1,35 +1,38 @@
 Public Module ModComp
 Public Module ModComp
 
 
-    Public Enum CompType
-        ''' <summary>
-        ''' 允许任意种类,或种类未知。
-        ''' </summary>
-        Any = -1
+    <Flags> Public Enum CompType
         ''' <summary> 
         ''' <summary> 
         ''' Mod。
         ''' Mod。
         ''' </summary>
         ''' </summary>
-        [Mod] = 0
+        [Mod] = 1
         ''' <summary>
         ''' <summary>
         ''' 整合包。
         ''' 整合包。
         ''' </summary>
         ''' </summary>
-        ModPack = 1
+        ModPack = 2
         ''' <summary>
         ''' <summary>
         ''' 资源包。
         ''' 资源包。
         ''' </summary>
         ''' </summary>
-        ResourcePack = 2
+        ResourcePack = 4
         ''' <summary>
         ''' <summary>
         ''' 光影包。
         ''' 光影包。
         ''' </summary>
         ''' </summary>
-        Shader = 3
+        Shader = 8
         ''' <summary>
         ''' <summary>
-        ''' CurseForge:数据包。
-        ''' Modrinth:数据包,或数据包与 Mod 的混合。
+        ''' 数据包。
         ''' </summary>
         ''' </summary>
-        DataPack = 4
+        DataPack = 16
         ''' <summary>
         ''' <summary>
         ''' 服务端插件。
         ''' 服务端插件。
         ''' </summary>
         ''' </summary>
-        Plugin = 5
+        Plugin = 32
+        ''' <summary>
+        ''' 同时包含数据包以及 Mod。
+        ''' </summary>
+        ModOrDataPack = [Mod] Or DataPack
+        ''' <summary>
+        ''' 允许任意种类,或种类未知。
+        ''' </summary>
+        Any = [Mod] Or ModPack Or ResourcePack Or Shader Or DataPack Or Plugin
     End Enum
     End Enum
     Public Enum CompModLoaderType
     Public Enum CompModLoaderType
         'https://docs.curseforge.com/?http#tocS_ModLoaderType
         'https://docs.curseforge.com/?http#tocS_ModLoaderType
@@ -132,10 +135,10 @@
         ''' </summary>
         ''' </summary>
         Public ReadOnly FromCurseForge As Boolean
         Public ReadOnly FromCurseForge As Boolean
         ''' <summary>
         ''' <summary>
-        ''' 工程的种类。
-        ''' 由于 Modrinth 混合使用 Mod 和数据包,结果不一定准确。
+        ''' 工程中包含的文件种类。
+        ''' 若为 Modrinth 工程,可能为 Mod 或 数据包。
         ''' </summary>
         ''' </summary>
-        Public ReadOnly Type As CompType
+        Public ReadOnly Types As CompType
         ''' <summary>
         ''' <summary>
         ''' 工程的短名。例如 technical-enchant。
         ''' 工程的短名。例如 technical-enchant。
         ''' </summary>
         ''' </summary>
@@ -191,6 +194,12 @@
         ''' 例如:261(26.1.x)、180(1.18.x)。
         ''' 例如:261(26.1.x)、180(1.18.x)。
         ''' </summary>
         ''' </summary>
         Public ReadOnly Drops As List(Of Integer)
         Public ReadOnly Drops As List(Of Integer)
+        ''' <summary>
+        ''' Modrinth API 返回的原始版本列表。
+        ''' 仅用于 Modrinth 工程的二次筛选,不会被缓存,不会被预处理。
+        ''' 若非从 Modrinth 获取则为 Nothing。
+        ''' </summary>
+        Public ReadOnly UnsafeGameVersions As List(Of String)
 
 
         '数据库信息
         '数据库信息
 
 
@@ -203,7 +212,7 @@
             Get
             Get
                 If Not LoadedDatabase Then
                 If Not LoadedDatabase Then
                     LoadedDatabase = True
                     LoadedDatabase = True
-                    If Type = CompType.Mod OrElse Type = CompType.DataPack Then
+                    If Types.HasFlag(CompType.Mod) OrElse Types.HasFlag(CompType.DataPack) Then
                         _DatabaseEntry = CompDatabase.FirstOrDefault(Function(c) If(FromCurseForge, c.CurseForgeSlug, c.ModrinthSlug) = Slug)
                         _DatabaseEntry = CompDatabase.FirstOrDefault(Function(c) If(FromCurseForge, c.CurseForgeSlug, c.ModrinthSlug) = Slug)
                     End If
                     End If
                 End If
                 End If
@@ -240,7 +249,7 @@
             If Data.ContainsKey("Tags") Then
             If Data.ContainsKey("Tags") Then
 #Region "CompJson"
 #Region "CompJson"
                 FromCurseForge = Data("DataSource") = "CurseForge"
                 FromCurseForge = Data("DataSource") = "CurseForge"
-                Type = Data("Type").ToObject(Of Integer)
+                Types = Data("Types").ToObject(Of Integer)
                 Slug = Data("Slug")
                 Slug = Data("Slug")
                 Id = Data("Id")
                 Id = Data("Id")
                 If Data.ContainsKey("CurseForgeFileIds") Then CurseForgeFileIds = CType(Data("CurseForgeFileIds"), JArray).Select(Function(t) t.ToObject(Of Integer)).ToList
                 If Data.ContainsKey("CurseForgeFileIds") Then CurseForgeFileIds = CType(Data("CurseForgeFileIds"), JArray).Select(Function(t) t.ToObject(Of Integer)).ToList
@@ -284,23 +293,23 @@
                     If LogoUrl = "" Then LogoUrl = Nothing
                     If LogoUrl = "" Then LogoUrl = Nothing
                     'Type
                     'Type
                     If Website.Contains("/mc-mods/") OrElse Website.Contains("/mod/") Then
                     If Website.Contains("/mc-mods/") OrElse Website.Contains("/mod/") Then
-                        Type = CompType.Mod
+                        Types = CompType.Mod
                     ElseIf Website.Contains("/modpacks/") Then
                     ElseIf Website.Contains("/modpacks/") Then
-                        Type = CompType.ModPack
+                        Types = CompType.ModPack
                     ElseIf Website.Contains("/resourcepacks/") Then
                     ElseIf Website.Contains("/resourcepacks/") Then
-                        Type = CompType.ResourcePack
+                        Types = CompType.ResourcePack
                     ElseIf Website.Contains("/texture-packs/") Then
                     ElseIf Website.Contains("/texture-packs/") Then
-                        Type = CompType.ResourcePack
+                        Types = CompType.ResourcePack
                     ElseIf Website.Contains("/shaders/") Then
                     ElseIf Website.Contains("/shaders/") Then
-                        Type = CompType.Shader
+                        Types = CompType.Shader
                     Else
                     Else
-                        Type = CompType.DataPack
+                        Types = CompType.DataPack
                     End If
                     End If
                     'FileIndexes / VanillaMajorVersions / ModLoaders
                     'FileIndexes / VanillaMajorVersions / ModLoaders
                     ModLoaders = New List(Of CompModLoaderType)
                     ModLoaders = New List(Of CompModLoaderType)
                     Dim Files As New List(Of KeyValuePair(Of Integer, List(Of String))) 'FileId, GameVersions
                     Dim Files As New List(Of KeyValuePair(Of Integer, List(Of String))) 'FileId, GameVersions
                     For Each File In If(Data("latestFiles"), New JArray)
                     For Each File In If(Data("latestFiles"), New JArray)
-                        Dim NewFile As New CompFile(File, Type)
+                        Dim NewFile As New CompFile(File, Types)
                         If Not NewFile.Available Then Continue For
                         If Not NewFile.Available Then Continue For
                         ModLoaders.AddRange(NewFile.ModLoaders)
                         ModLoaders.AddRange(NewFile.ModLoaders)
                         Dim GameVersions = File("gameVersions").ToObject(Of List(Of String))
                         Dim GameVersions = File("gameVersions").ToObject(Of List(Of String))
@@ -408,14 +417,14 @@
                     Website = $"https://modrinth.com/{Data("project_type")}/{Slug}"
                     Website = $"https://modrinth.com/{Data("project_type")}/{Slug}"
                     'GameVersions
                     'GameVersions
                     '搜索结果的键为 versions,获取特定工程的键为 game_versions
                     '搜索结果的键为 versions,获取特定工程的键为 game_versions
-                    Drops = If(CType(If(Data("game_versions"), Data("versions")), JArray), New JArray).
-                        Select(Function(v) McVersion.VersionToDrop(v)).Where(Function(v) v > 0).Distinct.OrderByDescending(Function(v) v).ToList
+                    UnsafeGameVersions = If(CType(If(Data("game_versions"), Data("versions")), JArray), New JArray).Select(Function(v) v.ToString).Distinct.ToList
+                    Drops = UnsafeGameVersions.Select(Function(v) McVersion.VersionToDrop(v)).Where(Function(v) v > 0).Distinct.OrderByDescending(Function(v) v).ToList
                     'Type
                     'Type
                     Select Case Data("project_type").ToString
                     Select Case Data("project_type").ToString
-                        Case "modpack" : Type = CompType.ModPack
-                        Case "resourcepack" : Type = CompType.ResourcePack
-                        Case "shader" : Type = CompType.Shader
-                        Case Else : Type = CompType.Mod 'Modrinth 将数据包标为 Mod
+                        Case "modpack" : Types = CompType.ModPack
+                        Case "resourcepack" : Types = CompType.ResourcePack
+                        Case "shader" : Types = CompType.Shader
+                        Case Else : Types = CompType.Mod 'Modrinth 将数据包标为 Mod,但 categories 字段里有 datapack
                     End Select
                     End Select
                     'Tags & ModLoaders
                     'Tags & ModLoaders
                     Tags = New List(Of String)
                     Tags = New List(Of String)
@@ -437,7 +446,7 @@
                             Case "fabric" : ModLoaders.Add(CompModLoaderType.Fabric)
                             Case "fabric" : ModLoaders.Add(CompModLoaderType.Fabric)
                             Case "quilt" : ModLoaders.Add(CompModLoaderType.Quilt)
                             Case "quilt" : ModLoaders.Add(CompModLoaderType.Quilt)
                             Case "neoforge" : ModLoaders.Add(CompModLoaderType.NeoForge)
                             Case "neoforge" : ModLoaders.Add(CompModLoaderType.NeoForge)
-                            Case "datapack" : Type = CompType.DataPack '若包含数据包版本,则优先标为 DataPack
+                            Case "datapack" : Types = CompType.DataPack
                             '共用
                             '共用
                             Case "technology" : Tags.Add("科技")
                             Case "technology" : Tags.Add("科技")
                             Case "magic" : Tags.Add("魔法")
                             Case "magic" : Tags.Add("魔法")
@@ -452,9 +461,9 @@
                             Case "game-mechanics" : Tags.Add("游戏机制")
                             Case "game-mechanics" : Tags.Add("游戏机制")
                             Case "transportation" : Tags.Add("运输")
                             Case "transportation" : Tags.Add("运输")
                             Case "storage" : Tags.Add("仓储")
                             Case "storage" : Tags.Add("仓储")
-                            Case "decoration" : If Type <> CompType.ResourcePack Then Tags.Add("装饰")
-                            Case "mobs" : If Type <> CompType.ResourcePack Then Tags.Add("生物")
-                            Case "equipment" : If Type <> CompType.ResourcePack Then Tags.Add("装备")
+                            Case "decoration" : If Types <> CompType.ResourcePack Then Tags.Add("装饰")
+                            Case "mobs" : If Types <> CompType.ResourcePack Then Tags.Add("生物")
+                            Case "equipment" : If Types <> CompType.ResourcePack Then Tags.Add("装备")
                             Case "social" : Tags.Add("服务器")
                             Case "social" : Tags.Add("服务器")
                             Case "library" : Tags.Add("支持库")
                             Case "library" : Tags.Add("支持库")
                             '整合包
                             '整合包
@@ -504,6 +513,7 @@
                             Case "vanilla" : Tags.Add("原版可用")
                             Case "vanilla" : Tags.Add("原版可用")
                         End Select
                         End Select
                     Next
                     Next
+                    If Types = CompType.DataPack AndAlso ModLoaders.Any Then Types = CompType.DataPack Or CompType.Mod
 #End Region
 #End Region
                 End If
                 End If
                 If Not Tags.Any() Then Tags.Add("其他")
                 If Not Tags.Any() Then Tags.Add("其他")
@@ -519,7 +529,7 @@
         Public Function ToJson() As JObject
         Public Function ToJson() As JObject
             Dim Json As New JObject
             Dim Json As New JObject
             Json("DataSource") = If(FromCurseForge, "CurseForge", "Modrinth")
             Json("DataSource") = If(FromCurseForge, "CurseForge", "Modrinth")
-            Json("Type") = CInt(Type)
+            Json("Types") = CInt(Types)
             Json("Slug") = Slug
             Json("Slug") = Slug
             Json("Id") = Id
             Json("Id") = Id
             If CurseForgeFileIds IsNot Nothing Then Json("CurseForgeFileIds") = New JArray(CurseForgeFileIds)
             If CurseForgeFileIds IsNot Nothing Then Json("CurseForgeFileIds") = New JArray(CurseForgeFileIds)
@@ -549,7 +559,7 @@
                 For i = 0 To Drops.Count - 1 '版本号一定为降序
                 For i = 0 To Drops.Count - 1 '版本号一定为降序
                     '获取当前连续的版本号段
                     '获取当前连续的版本号段
                     Dim StartDrop As Integer = Drops(i), EndDrop As Integer = Drops(i)
                     Dim StartDrop As Integer = Drops(i), EndDrop As Integer = Drops(i)
-                    If StartDrop < 100 Then '如果支持新版本,则不显示 1.9-
+                    If StartDrop < 120 Then '如果支持新版本,则不显示 1.11-
                         If Segments.Any() AndAlso Not IsOld Then
                         If Segments.Any() AndAlso Not IsOld Then
                             Exit For
                             Exit For
                         Else
                         Else
@@ -567,14 +577,14 @@
                     If StartDrop = EndDrop Then
                     If StartDrop = EndDrop Then
                         Segments.Add(StartName)
                         Segments.Add(StartName)
                     ElseIf AllDrops IsNot Nothing AndAlso StartDrop >= AllDrops.First Then
                     ElseIf AllDrops IsNot Nothing AndAlso StartDrop >= AllDrops.First Then
-                        If EndDrop < 100 Then
+                        If EndDrop < 120 Then
                             Segments.Clear()
                             Segments.Clear()
                             Segments.Add("全版本")
                             Segments.Add("全版本")
                             Exit For
                             Exit For
                         Else
                         Else
                             Segments.Add(EndName & "+")
                             Segments.Add(EndName & "+")
                         End If
                         End If
-                    ElseIf EndDrop < 100 Then
+                    ElseIf EndDrop < 120 Then
                         Segments.Add(StartName & "-")
                         Segments.Add(StartName & "-")
                         Exit For
                         Exit For
                     ElseIf AllDrops Is Nothing OrElse AllDrops.IndexOf(EndDrop) - AllDrops.IndexOf(StartDrop) = 1 Then
                     ElseIf AllDrops Is Nothing OrElse AllDrops.IndexOf(EndDrop) - AllDrops.IndexOf(StartDrop) = 1 Then
@@ -762,7 +772,7 @@ NoSubtitle:
             'Mod 加载器一致
             'Mod 加载器一致
             If ModLoaders.Count <> Project.ModLoaders.Count OrElse ModLoaders.Except(Project.ModLoaders).Any() Then Return False
             If ModLoaders.Count <> Project.ModLoaders.Count OrElse ModLoaders.Except(Project.ModLoaders).Any() Then Return False
             '若不为光影,则要求 MC 版本一致
             '若不为光影,则要求 MC 版本一致
-            If Type <> CompType.Shader AndAlso (Drops.Count <> Project.Drops.Count OrElse Drops.Except(Project.Drops).Any()) Then Return False
+            If Types <> CompType.Shader AndAlso (Drops.Count <> Project.Drops.Count OrElse Drops.Except(Project.Drops).Any()) Then Return False
             '最近更新时间差距在一周以内
             '最近更新时间差距在一周以内
             If Math.Abs((LastUpdate - Project.LastUpdate).TotalDays) > 7 Then Return False
             If Math.Abs((LastUpdate - Project.LastUpdate).TotalDays) > 7 Then Return False
             'MCMOD 翻译名 / 原名 / 描述文本 / Slug 的英文部分相同
             'MCMOD 翻译名 / 原名 / 描述文本 / Slug 的英文部分相同
@@ -813,8 +823,8 @@ NoSubtitle:
         ''' </summary>
         ''' </summary>
         Public ReadOnly Property CanContinue As Boolean
         Public ReadOnly Property CanContinue As Boolean
             Get
             Get
-                If Tag.StartsWithF("/") OrElse Not Source.HasFlag(CompSourceType.CurseForge) Then Storage.CurseForgeTotal = 0
-                If Tag.EndsWithF("/") OrElse Not Source.HasFlag(CompSourceType.Modrinth) Then Storage.ModrinthTotal = 0
+                If Tag.StartsWithF("/") OrElse Not Sources.HasFlag(CompSourceType.CurseForge) Then Storage.CurseForgeTotal = 0
+                If Tag.EndsWithF("/") OrElse Not Sources.HasFlag(CompSourceType.Modrinth) Then Storage.ModrinthTotal = 0
                 If Storage.CurseForgeTotal = -1 OrElse Storage.ModrinthTotal = -1 Then Return True
                 If Storage.CurseForgeTotal = -1 OrElse Storage.ModrinthTotal = -1 Then Return True
                 Return Storage.CurseForgeOffset < Storage.CurseForgeTotal OrElse Storage.ModrinthOffset < Storage.ModrinthTotal
                 Return Storage.CurseForgeOffset < Storage.CurseForgeTotal OrElse Storage.ModrinthOffset < Storage.ModrinthTotal
             End Get
             End Get
@@ -845,7 +855,7 @@ NoSubtitle:
         ''' <summary>
         ''' <summary>
         ''' 允许的来源。
         ''' 允许的来源。
         ''' </summary>
         ''' </summary>
-        Public Source As CompSourceType = CompSourceType.Any
+        Public Sources As CompSourceType = CompSourceType.Any
         Public Sub New(Type As CompType, Storage As CompProjectStorage, TargetResultCount As Integer)
         Public Sub New(Type As CompType, Storage As CompProjectStorage, TargetResultCount As Integer)
             Me.Type = Type
             Me.Type = Type
             Me.Storage = Storage
             Me.Storage = Storage
@@ -904,7 +914,7 @@ NoSubtitle:
             Dim request = TryCast(obj, CompProjectRequest)
             Dim request = TryCast(obj, CompProjectRequest)
             Return request IsNot Nothing AndAlso
             Return request IsNot Nothing AndAlso
                 Type = request.Type AndAlso TargetResultCount = request.TargetResultCount AndAlso
                 Type = request.Type AndAlso TargetResultCount = request.TargetResultCount AndAlso
-                Tag = request.Tag AndAlso ModLoader = request.ModLoader AndAlso Source = request.Source AndAlso
+                Tag = request.Tag AndAlso ModLoader = request.ModLoader AndAlso Sources = request.Sources AndAlso
                 GameVersion = request.GameVersion AndAlso SearchText = request.SearchText
                 GameVersion = request.GameVersion AndAlso SearchText = request.SearchText
         End Function
         End Function
         Public Shared Operator =(left As CompProjectRequest, right As CompProjectRequest) As Boolean
         Public Shared Operator =(left As CompProjectRequest, right As CompProjectRequest) As Boolean
@@ -914,7 +924,7 @@ NoSubtitle:
             Return Not left = right
             Return Not left = right
         End Operator
         End Operator
         Public Overrides Function GetHashCode() As Integer
         Public Overrides Function GetHashCode() As Integer
-            Return (Type, Tag, ModLoader, GameVersion, SearchText, Source).GetHashCode()
+            Return (Type, Tag, ModLoader, GameVersion, SearchText, Sources).GetHashCode()
         End Function
         End Function
 
 
     End Class
     End Class
@@ -1019,7 +1029,7 @@ NoSubtitle:
                 Return Candidates
                 Return Candidates
             End Function
             End Function
             'CurseForge
             'CurseForge
-            If Request.Source.HasFlag(CompSourceType.CurseForge) Then
+            If Request.Sources.HasFlag(CompSourceType.CurseForge) Then
                 '数据库搜索
                 '数据库搜索
                 Static CurseForgeSearchEntries As List(Of SearchEntry(Of CompDatabaseEntry)) =
                 Static CurseForgeSearchEntries As List(Of SearchEntry(Of CompDatabaseEntry)) =
                 CompDatabase.Where(Function(Entry) Entry.CurseForgeSlug IsNot Nothing).Select(
                 CompDatabase.Where(Function(Entry) Entry.CurseForgeSlug IsNot Nothing).Select(
@@ -1043,7 +1053,7 @@ NoSubtitle:
                 End If
                 End If
             End If
             End If
             'Modrinth
             'Modrinth
-            If Request.Source.HasFlag(CompSourceType.Modrinth) Then
+            If Request.Sources.HasFlag(CompSourceType.Modrinth) Then
                 '数据库搜索
                 '数据库搜索
                 Static ModrinthSearchEntries As List(Of SearchEntry(Of CompDatabaseEntry)) =
                 Static ModrinthSearchEntries As List(Of SearchEntry(Of CompDatabaseEntry)) =
                 CompDatabase.Where(Function(Entry) Entry.ModrinthSlug IsNot Nothing).Select(
                 CompDatabase.Where(Function(Entry) Entry.ModrinthSlug IsNot Nothing).Select(
@@ -1094,7 +1104,7 @@ NextPage:
         Try
         Try
 
 
             'CurseForge 搜索
             'CurseForge 搜索
-            If Request.Source.HasFlag(CompSourceType.CurseForge) AndAlso
+            If Request.Sources.HasFlag(CompSourceType.CurseForge) AndAlso
                Not (Storage.CurseForgeTotal > -1 AndAlso Storage.CurseForgeTotal <= Storage.CurseForgeOffset) AndAlso '剩余的未显示的搜索结果不足
                Not (Storage.CurseForgeTotal > -1 AndAlso Storage.CurseForgeTotal <= Storage.CurseForgeOffset) AndAlso '剩余的未显示的搜索结果不足
                (Not IsChineseSearch OrElse (IsChineseSearch AndAlso Not String.IsNullOrEmpty(CurseForgeAltSearchText))) Then '如果是中文搜索,就只在有对应搜索关键词的时候才继续
                (Not IsChineseSearch OrElse (IsChineseSearch AndAlso Not String.IsNullOrEmpty(CurseForgeAltSearchText))) Then '如果是中文搜索,就只在有对应搜索关键词的时候才继续
                 WorkThreads.Add(RunInNewThread(
                 WorkThreads.Add(RunInNewThread(
@@ -1125,7 +1135,7 @@ NextPage:
             End If
             End If
 
 
             'Modrinth 搜索
             'Modrinth 搜索
-            If Request.Source.HasFlag(CompSourceType.Modrinth) AndAlso
+            If Request.Sources.HasFlag(CompSourceType.Modrinth) AndAlso
                Not (Storage.ModrinthTotal > -1 AndAlso Storage.ModrinthTotal <= Storage.ModrinthOffset) AndAlso '剩余的未显示的搜索结果不足
                Not (Storage.ModrinthTotal > -1 AndAlso Storage.ModrinthTotal <= Storage.ModrinthOffset) AndAlso '剩余的未显示的搜索结果不足
                (Not IsChineseSearch OrElse (IsChineseSearch AndAlso Not String.IsNullOrEmpty(ModrinthAltSearchText))) Then '如果是中文搜索,就只在有对应搜索关键词的时候才继续
                (Not IsChineseSearch OrElse (IsChineseSearch AndAlso Not String.IsNullOrEmpty(ModrinthAltSearchText))) Then '如果是中文搜索,就只在有对应搜索关键词的时候才继续
                 WorkThreads.Add(RunInNewThread(
                 WorkThreads.Add(RunInNewThread(
@@ -1153,7 +1163,7 @@ NextPage:
             End If
             End If
 
 
             'Modrinth 直接获取工程
             'Modrinth 直接获取工程
-            If Request.Source.HasFlag(CompSourceType.Modrinth) AndAlso
+            If Request.Sources.HasFlag(CompSourceType.Modrinth) AndAlso
                Not (Storage.ModrinthTotal > -1 AndAlso Storage.ModrinthTotal <= Storage.ModrinthOffset) AndAlso '剩余的未显示的搜索结果不足
                Not (Storage.ModrinthTotal > -1 AndAlso Storage.ModrinthTotal <= Storage.ModrinthOffset) AndAlso '剩余的未显示的搜索结果不足
                ModrinthSlugs.Any Then '有直接获取的 Slug
                ModrinthSlugs.Any Then '有直接获取的 Slug
                 WorkThreads.Add(RunInNewThread(
                 WorkThreads.Add(RunInNewThread(
@@ -1163,7 +1173,16 @@ NextPage:
                         Log("[Comp] 开始 Modrinth 直接获取:" & ModrinthUrl)
                         Log("[Comp] 开始 Modrinth 直接获取:" & ModrinthUrl)
                         Dim ProjectList As New List(Of CompProject)
                         Dim ProjectList As New List(Of CompProject)
                         For Each JsonEntry As JObject In DlModRequest(ModrinthUrl)
                         For Each JsonEntry As JObject In DlModRequest(ModrinthUrl)
-                            ProjectList.Add(New CompProject(JsonEntry))
+                            Dim Project As New CompProject(JsonEntry)
+                            '应用筛选
+                            If Request.Type <> CompType.Any AndAlso Not Project.Types.HasFlag(Request.Type) Then Continue For
+                            If Not String.IsNullOrEmpty(Request.Tag) AndAlso
+                                Not JsonEntry("categories").Any(Function(c) c.ToString = Request.Tag.AfterLast("/")) Then Continue For 'Project.Tags 已经转换成中文了,只能从 json 判
+                            If Request.ModLoader <> CompModLoaderType.Any AndAlso Not IgnoreModLoaderFilter AndAlso
+                                Not Project.ModLoaders.Any(Function(m) m = Request.ModLoader) Then Continue For
+                            If Not String.IsNullOrEmpty(Request.GameVersion) AndAlso
+                                Not Project.UnsafeGameVersions.Any(Function(d) d = Request.GameVersion) Then Continue For
+                            ProjectList.Add(Project)
                         Next
                         Next
                         '更新结果
                         '更新结果
                         ProjectList.ForEach(Sub(p) RawResults.Add(p))
                         ProjectList.ForEach(Sub(p) RawResults.Add(p))
@@ -1196,9 +1215,9 @@ NextPage:
                 Else
                 Else
                     If IsChineseSearch AndAlso Not (Request.Type = CompType.Mod OrElse Request.Type = CompType.DataPack) Then
                     If IsChineseSearch AndAlso Not (Request.Type = CompType.Mod OrElse Request.Type = CompType.DataPack) Then
                         Throw New Exception(MSG_NO_CHINESE_SEARCH_RESULT)
                         Throw New Exception(MSG_NO_CHINESE_SEARCH_RESULT)
-                    ElseIf Request.Source = CompSourceType.CurseForge AndAlso Request.Tag.StartsWithF("/") Then
+                    ElseIf Request.Sources = CompSourceType.CurseForge AndAlso Request.Tag.StartsWithF("/") Then
                         Throw New Exception("CurseForge 不兼容所选的类型")
                         Throw New Exception("CurseForge 不兼容所选的类型")
-                    ElseIf Request.Source = CompSourceType.Modrinth AndAlso Request.Tag.EndsWithF("/") Then
+                    ElseIf Request.Sources = CompSourceType.Modrinth AndAlso Request.Tag.EndsWithF("/") Then
                         Throw New Exception("Modrinth 不兼容所选的类型")
                         Throw New Exception("Modrinth 不兼容所选的类型")
                     Else
                     Else
                         Throw New Exception("没有搜索结果")
                         Throw New Exception("没有搜索结果")
@@ -1418,7 +1437,7 @@ NextPage:
         '实例化
         '实例化
 
 
         ''' <summary>
         ''' <summary>
-        ''' 从文件 Json 中初始化实例。若出错会抛出异常。
+        ''' 从 json 中初始化实例。若出错会抛出异常。
         ''' </summary>
         ''' </summary>
         Public Sub New(Data As JObject, DefaultType As CompType)
         Public Sub New(Data As JObject, DefaultType As CompType)
             Type = DefaultType
             Type = DefaultType
@@ -1505,25 +1524,16 @@ NextPage:
                         Size = File("size")
                         Size = File("size")
                         Hash = File("hashes")("sha1")
                         Hash = File("hashes")("sha1")
                     End If
                     End If
-                    'ModLoaders
+                    'Loaders
                     '结果可能混杂着 Mod、数据包和服务端插件
                     '结果可能混杂着 Mod、数据包和服务端插件
                     Dim RawLoaders As List(Of String) = Data("loaders").Select(Function(v) v.ToString).ToList
                     Dim RawLoaders As List(Of String) = Data("loaders").Select(Function(v) v.ToString).ToList
                     ModLoaders = New List(Of CompModLoaderType)
                     ModLoaders = New List(Of CompModLoaderType)
-                    If Type = CompType.Mod Then '以尽量宽容的方式检测加载器,以免同时兼容两种的项被删除
-                        If RawLoaders.Intersect({"bukkit", "folia", "paper", "purpur", "spigot"}).Any() Then Type = CompType.Plugin 'Veinminer Enchantment 同时支持服务端与 Fabric
-                        If RawLoaders.Contains("datapack") Then Type = CompType.DataPack
-                        If RawLoaders.Contains("forge") Then ModLoaders.Add(CompModLoaderType.Forge) : Type = CompType.Mod
-                        If RawLoaders.Contains("neoforge") Then ModLoaders.Add(CompModLoaderType.NeoForge) : Type = CompType.Mod
-                        If RawLoaders.Contains("fabric") Then ModLoaders.Add(CompModLoaderType.Fabric) : Type = CompType.Mod
-                        If RawLoaders.Contains("quilt") Then ModLoaders.Add(CompModLoaderType.Quilt) : Type = CompType.Mod
-                    ElseIf Type = CompType.DataPack Then
-                        If RawLoaders.Intersect({"bukkit", "folia", "paper", "purpur", "spigot"}).Any() Then Type = CompType.Plugin
-                        If RawLoaders.Contains("forge") Then ModLoaders.Add(CompModLoaderType.Forge) : Type = CompType.Mod
-                        If RawLoaders.Contains("neoforge") Then ModLoaders.Add(CompModLoaderType.NeoForge) : Type = CompType.Mod
-                        If RawLoaders.Contains("fabric") Then ModLoaders.Add(CompModLoaderType.Fabric) : Type = CompType.Mod
-                        If RawLoaders.Contains("quilt") Then ModLoaders.Add(CompModLoaderType.Quilt) : Type = CompType.Mod
-                        If RawLoaders.Contains("datapack") Then Type = CompType.DataPack
-                    End If
+                    If RawLoaders.Intersect({"bukkit", "folia", "paper", "purpur", "spigot"}).Any() Then Type = CompType.Plugin 'Veinminer Enchantment 同时支持服务端与 Fabric
+                    If RawLoaders.Contains("datapack") Then Type = CompType.DataPack
+                    If RawLoaders.Contains("forge") Then ModLoaders.Add(CompModLoaderType.Forge) : Type = CompType.Mod
+                    If RawLoaders.Contains("neoforge") Then ModLoaders.Add(CompModLoaderType.NeoForge) : Type = CompType.Mod
+                    If RawLoaders.Contains("fabric") Then ModLoaders.Add(CompModLoaderType.Fabric) : Type = CompType.Mod
+                    If RawLoaders.Contains("quilt") Then ModLoaders.Add(CompModLoaderType.Quilt) : Type = CompType.Mod
                     'Dependencies
                     'Dependencies
                     If Data.ContainsKey("dependencies") Then
                     If Data.ContainsKey("dependencies") Then
                         RawDependencies = Data("dependencies").
                         RawDependencies = Data("dependencies").
@@ -1694,7 +1704,7 @@ NextPage:
                 'Modrinth
                 'Modrinth
                 ResultJsonArray = DlModRequest($"https://api.modrinth.com/v2/project/{ProjectId}/version?include_changelog=false")
                 ResultJsonArray = DlModRequest($"https://api.modrinth.com/v2/project/{ProjectId}/version?include_changelog=false")
             End If
             End If
-            CompFilesCache(ProjectId) = ResultJsonArray.Select(Function(a) New CompFile(a, TargetProject.Type)).
+            CompFilesCache(ProjectId) = ResultJsonArray.Select(Function(a) New CompFile(a, TargetProject.Types)).
                 Where(Function(a) a.Available).ToList.
                 Where(Function(a) a.Available).ToList.
                 Distinct(Function(a, b) a.Id = b.Id) 'CurseForge 可能会重复返回相同项(#1330)
                 Distinct(Function(a, b) a.Id = b.Id) 'CurseForge 可能会重复返回相同项(#1330)
         End If
         End If

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

@@ -858,10 +858,11 @@
                 VersionName = ApiName
                 VersionName = ApiName
                 Version = New Version(ApiName.BeforeFirst("-"))
                 Version = New Version(ApiName.BeforeFirst("-"))
                 If Version.Major >= 24 Then
                 If Version.Major >= 24 Then
-                    Inherit = Version.Major & "." & Version.Minor
+                    Inherit = $"{Version.Major}.{Version.Minor}.{Version.Build}"
                 Else
                 Else
-                    Inherit = "1." & Version.Major & If(Version.Minor > 0, "." & Version.Minor, "")
+                    Inherit = $"1.{Version.Major}.{Version.Minor}"
                 End If
                 End If
+                If Inherit.EndsWithF(".0") Then Inherit = Left(Inherit, Inherit.Length - 2)
                 If VersionName.Contains("+") Then Inherit &= "-" & VersionName.AfterFirst("+")
                 If VersionName.Contains("+") Then Inherit &= "-" & VersionName.AfterFirst("+")
             End If
             End If
         End Sub
         End Sub

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

@@ -1446,9 +1446,10 @@ NextInstance:
             Args = Args.Where(Function(a) Not RegexCheck(a,
             Args = Args.Where(Function(a) Not RegexCheck(a,
                 "( )*-XX:[+-]?(Use\w+GC|ZGenerational|UseCompactObjectHeaders|G1\w+Percent|G1\w+Size|(Max|Min)(GCPauseMillis|HeapFreeRatio))")).ToList
                 "( )*-XX:[+-]?(Use\w+GC|ZGenerational|UseCompactObjectHeaders|G1\w+Percent|G1\w+Size|(Max|Min)(GCPauseMillis|HeapFreeRatio))")).ToList
             '添加 GC 参数
             '添加 GC 参数
+            Args.Add("-XX:+UnlockExperimentalVMOptions")
+            If McLaunchJavaSelected.MajorVersion >= 24 AndAlso McLaunchJavaSelected.Is64Bit Then Args.Add("-XX:+UseCompactObjectHeaders")
             If UseG1GC AndAlso SetupType = 4 Then
             If UseG1GC AndAlso SetupType = 4 Then
                 '优化的 G1GC
                 '优化的 G1GC
-                Args.Add("-XX:+UnlockExperimentalVMOptions")
                 Args.Add("-XX:+UseG1GC")
                 Args.Add("-XX:+UseG1GC")
                 Args.Add("-XX:G1NewSizePercent=20")
                 Args.Add("-XX:G1NewSizePercent=20")
                 Args.Add("-XX:G1ReservePercent=20")
                 Args.Add("-XX:G1ReservePercent=20")
@@ -1459,10 +1460,8 @@ NextInstance:
                 If McLaunchJavaSelected.MajorVersion = 8 Then Args.Add("-XX:+ParallelRefProcEnabled")
                 If McLaunchJavaSelected.MajorVersion = 8 Then Args.Add("-XX:+ParallelRefProcEnabled")
                 If McLaunchJavaSelected.MajorVersion >= 12 Then Args.Add("-XX:MinHeapFreeRatio=25") '需要比 G1NewSizePercent 大一点
                 If McLaunchJavaSelected.MajorVersion >= 12 Then Args.Add("-XX:MinHeapFreeRatio=25") '需要比 G1NewSizePercent 大一点
                 If McLaunchJavaSelected.MajorVersion >= 12 Then Args.Add("-XX:MaxHeapFreeRatio=40") '需要比 MinHeapFreeRatio 大一些
                 If McLaunchJavaSelected.MajorVersion >= 12 Then Args.Add("-XX:MaxHeapFreeRatio=40") '需要比 MinHeapFreeRatio 大一些
-                If McLaunchJavaSelected.MajorVersion >= 24 AndAlso McLaunchJavaSelected.Is64Bit Then Args.Add("-XX:+UseCompactObjectHeaders")
             ElseIf UseG1GC Then
             ElseIf UseG1GC Then
                 'Mojang G1GC
                 'Mojang G1GC
-                Args.Add("-XX:+UnlockExperimentalVMOptions")
                 Args.Add("-XX:+UseG1GC")
                 Args.Add("-XX:+UseG1GC")
                 Args.Add("-XX:G1NewSizePercent=20")
                 Args.Add("-XX:G1NewSizePercent=20")
                 Args.Add("-XX:G1ReservePercent=20")
                 Args.Add("-XX:G1ReservePercent=20")

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

@@ -1119,7 +1119,7 @@ ExitDataLoad:
         Public Shared Function IsFormatFit(Version As String) As Boolean
         Public Shared Function IsFormatFit(Version As String) As Boolean
             If Version Is Nothing Then Return False
             If Version Is Nothing Then Return False
             If RegexCheck(Version, "^1\.\d") Then Return True
             If RegexCheck(Version, "^1\.\d") Then Return True
-            If Val(RegexSeek(Version, "^[2-9]\d\.\d+")) > 25 Then Return True
+            If Val(RegexSeek(Version, "^[2-9]\d\.\d+")) >= 26 Then Return True
             Return False
             Return False
         End Function
         End Function
         ''' <summary>
         ''' <summary>

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

@@ -1,7 +1,7 @@
 Imports System.IO.Compression
 Imports System.IO.Compression
 
 
 Public Module ModMod
 Public Module ModMod
-    Private Const LocalModCacheVersion As Integer = 12
+    Private Const LocalModCacheVersion As Integer = 13
 
 
     Public Class McMod
     Public Class McMod
 
 

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

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

+ 8 - 8
Plain Craft Launcher 2/Pages/PageDownload/Comp/MyCompItem.xaml.vb

@@ -94,36 +94,36 @@
         End If
         End If
         '打开详情页
         '打开详情页
         Dim TargetType As CompType
         Dim TargetType As CompType
-        Dim TargetVersion As String = Nothing
+        Dim TargetInstance As String = Nothing
         Dim TargetLoader As CompModLoaderType = CompModLoaderType.Any
         Dim TargetLoader As CompModLoaderType = CompModLoaderType.Any
         If FrmMain.PageCurrent.Page = FormMain.PageType.Download Then
         If FrmMain.PageCurrent.Page = FormMain.PageType.Download Then
             '从下载页进入
             '从下载页进入
             Select Case FrmMain.PageCurrentSub
             Select Case FrmMain.PageCurrentSub
                 Case FormMain.PageSubType.DownloadMod
                 Case FormMain.PageSubType.DownloadMod
                     TargetType = CompType.Mod
                     TargetType = CompType.Mod
-                    TargetVersion = FrmDownloadMod.Content.Loader.Input.GameVersion
+                    TargetInstance = FrmDownloadMod.Content.Loader.Input.GameVersion
                     TargetLoader = FrmDownloadMod.Content.Loader.Input.ModLoader
                     TargetLoader = FrmDownloadMod.Content.Loader.Input.ModLoader
                 Case FormMain.PageSubType.DownloadPack
                 Case FormMain.PageSubType.DownloadPack
                     TargetType = CompType.ModPack
                     TargetType = CompType.ModPack
-                    TargetVersion = FrmDownloadPack.Content.Loader.Input.GameVersion
+                    TargetInstance = FrmDownloadPack.Content.Loader.Input.GameVersion
                 Case FormMain.PageSubType.DownloadDataPack
                 Case FormMain.PageSubType.DownloadDataPack
                     TargetType = CompType.DataPack
                     TargetType = CompType.DataPack
-                    TargetVersion = FrmDownloadDataPack.Content.Loader.Input.GameVersion
+                    TargetInstance = FrmDownloadDataPack.Content.Loader.Input.GameVersion
                 Case FormMain.PageSubType.DownloadResourcePack
                 Case FormMain.PageSubType.DownloadResourcePack
                     TargetType = CompType.ResourcePack
                     TargetType = CompType.ResourcePack
-                    TargetVersion = FrmDownloadResourcePack.Content.Loader.Input.GameVersion
+                    TargetInstance = FrmDownloadResourcePack.Content.Loader.Input.GameVersion
                 Case FormMain.PageSubType.DownloadShader
                 Case FormMain.PageSubType.DownloadShader
                     TargetType = CompType.Shader
                     TargetType = CompType.Shader
-                    TargetVersion = FrmDownloadShader.Content.Loader.Input.GameVersion
+                    TargetInstance = FrmDownloadShader.Content.Loader.Input.GameVersion
             End Select
             End Select
         Else
         Else
             '从详情页进入(查看前置)
             '从详情页进入(查看前置)
             TargetType = CompType.Any '允许任意类别
             TargetType = CompType.Any '允许任意类别
-            TargetVersion = FrmMain.PageCurrent.Additional(2)
+            TargetInstance = FrmMain.PageCurrent.Additional(2)
             TargetLoader = FrmMain.PageCurrent.Additional(3)
             TargetLoader = FrmMain.PageCurrent.Additional(3)
         End If
         End If
         FrmMain.PageChange(New FormMain.PageStackData With {.Page = FormMain.PageType.CompDetail,
         FrmMain.PageChange(New FormMain.PageStackData With {.Page = FormMain.PageType.CompDetail,
-                           .Additional = {sender.Tag, New List(Of String), TargetVersion, TargetLoader, TargetType}})
+                           .Additional = {sender.Tag, New List(Of String), TargetInstance, TargetLoader, TargetType}})
     End Sub
     End Sub
 
 
     '鼠标点击判定
     '鼠标点击判定

+ 4 - 3
Plain Craft Launcher 2/Pages/PageDownload/Comp/PageComp.xaml

@@ -34,15 +34,16 @@
                     <TextBlock VerticalAlignment="Center" Grid.Row="2" HorizontalAlignment="Left" Text="版本" Margin="0,0,18,0" />
                     <TextBlock VerticalAlignment="Center" Grid.Row="2" HorizontalAlignment="Left" Text="版本" Margin="0,0,18,0" />
                     <local:MyComboBox x:Name="TextSearchVersion" Grid.Row="2" Grid.Column="1" Grid.ColumnSpan="2" IsEditable="True">
                     <local:MyComboBox x:Name="TextSearchVersion" Grid.Row="2" Grid.Column="1" Grid.ColumnSpan="2" IsEditable="True">
                         <local:MyComboBoxItem Content="全部 (也可自行输入)" IsSelected="True" />
                         <local:MyComboBoxItem Content="全部 (也可自行输入)" IsSelected="True" />
+                        <local:MyComboBoxItem Content="26.1" />
                         <local:MyComboBoxItem Content="1.21.11" />
                         <local:MyComboBoxItem Content="1.21.11" />
+                        <local:MyComboBoxItem Content="1.21.8" />
+                        <local:MyComboBoxItem Content="1.21.4" />
                         <local:MyComboBoxItem Content="1.21.1" />
                         <local:MyComboBoxItem Content="1.21.1" />
-                        <local:MyComboBoxItem Content="1.20.6" />
                         <local:MyComboBoxItem Content="1.20.1" />
                         <local:MyComboBoxItem Content="1.20.1" />
-                        <local:MyComboBoxItem Content="1.19.4" />
+                        <local:MyComboBoxItem Content="1.19.2" />
                         <local:MyComboBoxItem Content="1.18.2" />
                         <local:MyComboBoxItem Content="1.18.2" />
                         <local:MyComboBoxItem Content="1.16.5" />
                         <local:MyComboBoxItem Content="1.16.5" />
                         <local:MyComboBoxItem Content="1.12.2" />
                         <local:MyComboBoxItem Content="1.12.2" />
-                        <local:MyComboBoxItem Content="1.8.9" />
                         <local:MyComboBoxItem Content="1.7.10" />
                         <local:MyComboBoxItem Content="1.7.10" />
                     </local:MyComboBox>
                     </local:MyComboBox>
                     <local:MyComboBox x:Name="ComboSearchLoader" Visibility="Collapsed" Grid.Row="2" Grid.Column="2" Margin="10,0,0,0">
                     <local:MyComboBox x:Name="ComboSearchLoader" Visibility="Collapsed" Grid.Row="2" Grid.Column="2" Margin="10,0,0,0">

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

@@ -127,7 +127,7 @@ Public Class PageComp
             .GameVersion = GameVersion
             .GameVersion = GameVersion
             .Tag = ComboSearchTag.SelectedItem.Tag
             .Tag = ComboSearchTag.SelectedItem.Tag
             .ModLoader = If(PageType = CompType.Mod, Val(ComboSearchLoader.SelectedItem.Tag), CompModLoaderType.Any)
             .ModLoader = If(PageType = CompType.Mod, Val(ComboSearchLoader.SelectedItem.Tag), CompModLoaderType.Any)
-            .Source = CType(Val(ComboSearchSource.SelectedItem.Tag), CompSourceType)
+            .Sources = CType(Val(ComboSearchSource.SelectedItem.Tag), CompSourceType)
         End With
         End With
         Return Request
         Return Request
     End Function
     End Function

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

@@ -20,6 +20,7 @@
                 </StackPanel>
                 </StackPanel>
             </local:MyCard>
             </local:MyCard>
             <StackPanel Grid.Row="1" Grid.RowSpan="2" Name="PanMain" Grid.IsSharedSizeScope="True">
             <StackPanel Grid.Row="1" Grid.RowSpan="2" Name="PanMain" Grid.IsSharedSizeScope="True">
+                <local:MyHint x:Name="HintAlternative" Theme="Blue" Margin="0,0,0,15" />
                 <local:MyCard Margin="0,0,0,15" x:Name="CardFilter">
                 <local:MyCard Margin="0,0,0,15" x:Name="CardFilter">
                     <StackPanel x:Name="PanFilter" Margin="10,10,0,10" Orientation="Horizontal" VerticalAlignment="Top" HorizontalAlignment="Left" />
                     <StackPanel x:Name="PanFilter" Margin="10,10,0,10" Orientation="Horizontal" VerticalAlignment="Top" HorizontalAlignment="Left" />
                 </local:MyCard>
                 </local:MyCard>

+ 23 - 7
Plain Craft Launcher 2/Pages/PageDownload/Comp/PageDownloadCompDetail.xaml.vb

@@ -21,14 +21,15 @@
         Project = FrmMain.PageCurrent.Additional(0)
         Project = FrmMain.PageCurrent.Additional(0)
         TargetInstance = FrmMain.PageCurrent.Additional(2)
         TargetInstance = FrmMain.PageCurrent.Additional(2)
         TargetLoader = FrmMain.PageCurrent.Additional(3)
         TargetLoader = FrmMain.PageCurrent.Additional(3)
-        PageType = FrmMain.PageCurrent.Additional(4)
+        TargetType = FrmMain.PageCurrent.Additional(4)
     End Sub
     End Sub
     Private Project As CompProject
     Private Project As CompProject
     Private TargetInstance As String, TargetLoader As CompModLoaderType
     Private TargetInstance As String, TargetLoader As CompModLoaderType
     ''' <summary>
     ''' <summary>
-    ''' 当前页面应展示的内容类别。可能为 Any。
+    ''' 当前页面应展示的内容类别。
+    ''' 若当前页面是在查看前置时进入,则也可能为 Any。
     ''' </summary>
     ''' </summary>
-    Private PageType As CompType
+    Private TargetType As CompType
     '自动重试
     '自动重试
     Private Sub Load_State(sender As Object, state As MyLoading.MyLoadingState, oldState As MyLoading.MyLoadingState) Handles Load.StateChanged
     Private Sub Load_State(sender As Object, state As MyLoading.MyLoadingState, oldState As MyLoading.MyLoadingState) Handles Load.StateChanged
         Select Case CompFileLoader.State
         Select Case CompFileLoader.State
@@ -74,13 +75,13 @@
     '筛选类型相同的结果(Modrinth 会返回 Mod、服务端插件、数据包混合的列表)
     '筛选类型相同的结果(Modrinth 会返回 Mod、服务端插件、数据包混合的列表)
     Private Function GetResults() As List(Of CompFile)
     Private Function GetResults() As List(Of CompFile)
         Dim Results As List(Of CompFile) = CompFileLoader.Output
         Dim Results As List(Of CompFile) = CompFileLoader.Output
-        Select Case PageType
+        Select Case TargetType
             Case CompType.Any
             Case CompType.Any
                 Results = Results.Where(Function(r) r.Type <> CompType.Plugin).ToList
                 Results = Results.Where(Function(r) r.Type <> CompType.Plugin).ToList
             Case CompType.Shader, CompType.ResourcePack
             Case CompType.Shader, CompType.ResourcePack
                 '不筛选光影和资源包,否则原版光影会因为是资源包格式而被过滤(#6473)
                 '不筛选光影和资源包,否则原版光影会因为是资源包格式而被过滤(#6473)
             Case Else
             Case Else
-                Results = Results.Where(Function(r) r.Type = PageType).ToList
+                Results = Results.Where(Function(r) r.Type = TargetType).ToList
         End Select
         End Select
         Return Results
         Return Results
     End Function
     End Function
@@ -204,7 +205,7 @@ GroupDone:
                 If Not Pair.Value.Any() Then Continue For
                 If Not Pair.Value.Any() Then Continue For
                 If Pair.Key = TargetCardName.Replace("(所选版本)", "") Then Continue For
                 If Pair.Key = TargetCardName.Replace("(所选版本)", "") Then Continue For
                 '增加卡片
                 '增加卡片
-                Dim NewCard As New MyCard With {.Title = Pair.Key, .Margin = New Thickness(0, 0, 0, 15), .SwapType = If(PageType = CompType.ModPack, 9, 8)} '9 是安装,8 是另存为
+                Dim NewCard As New MyCard With {.Title = Pair.Key, .Margin = New Thickness(0, 0, 0, 15), .SwapType = If(TargetType = CompType.ModPack, 9, 8)} '9 是安装,8 是另存为
                 Dim NewStack As New StackPanel With {.Margin = New Thickness(20, MyCard.SwapedHeight, 18, 0), .VerticalAlignment = VerticalAlignment.Top, .RenderTransform = New TranslateTransform(0, 0), .Tag = Pair.Value}
                 Dim NewStack As New StackPanel With {.Margin = New Thickness(20, MyCard.SwapedHeight, 18, 0), .VerticalAlignment = VerticalAlignment.Top, .RenderTransform = New TranslateTransform(0, 0), .Tag = Pair.Value}
                 NewCard.Children.Add(NewStack)
                 NewCard.Children.Add(NewStack)
                 NewCard.SwapControl = NewStack
                 NewCard.SwapControl = NewStack
@@ -213,7 +214,7 @@ GroupDone:
                 If Pair.Key = TargetCardName OrElse
                 If Pair.Key = TargetCardName OrElse
                    (FrmMain.PageCurrent.Additional IsNot Nothing AndAlso '#2761
                    (FrmMain.PageCurrent.Additional IsNot Nothing AndAlso '#2761
                    CType(FrmMain.PageCurrent.Additional(1), List(Of String)).Contains(NewCard.Title)) Then
                    CType(FrmMain.PageCurrent.Additional(1), List(Of String)).Contains(NewCard.Title)) Then
-                    MyCard.StackInstall(NewStack, If(PageType = CompType.ModPack, 9, 8), Pair.Key) '9 是安装,8 是另存为
+                    MyCard.StackInstall(NewStack, If(TargetType = CompType.ModPack, 9, 8), Pair.Key) '9 是安装,8 是另存为
                 Else
                 Else
                     NewCard.IsSwapped = True
                     NewCard.IsSwapped = True
                 End If
                 End If
@@ -226,6 +227,14 @@ GroupDone:
             If PanResults.Children.Count = 1 Then
             If PanResults.Children.Count = 1 Then
                 CType(PanResults.Children(0), MyCard).IsSwapped = False
                 CType(PanResults.Children(0), MyCard).IsSwapped = False
             End If
             End If
+            '替代提示
+            If Project.Types = CompType.ModOrDataPack AndAlso (TargetType = CompType.Mod OrElse TargetType = CompType.DataPack) Then
+                HintAlternative.Visibility = Visibility.Visible
+                HintAlternative.Text = If(TargetType = CompType.Mod,
+                    "以下是该项目的 Mod 版本。点击这里查看其数据包版本。", "以下是该项目的数据包版本。点击这里查看其 Mod 版本。")
+            Else
+                HintAlternative.Visibility = Visibility.Collapsed
+            End If
         Catch ex As Exception
         Catch ex As Exception
             Log(ex, "可视化工程下载列表出错", LogLevel.Feedback)
             Log(ex, "可视化工程下载列表出错", LogLevel.Feedback)
         End Try
         End Try
@@ -494,4 +503,11 @@ GroupDone:
         ClipboardSet(CompItem.LabTitle.Text & CompItem.LabTitleRaw.Text)
         ClipboardSet(CompItem.LabTitle.Text & CompItem.LabTitleRaw.Text)
     End Sub
     End Sub
 
 
+    'Mod / 数据包 互相跳转
+    Private Sub HintAlternative_Click() Handles HintAlternative.Click
+        TargetType = If(TargetType = CompType.Mod, CompType.DataPack, CompType.Mod)
+        FrmMain.PageCurrent.Additional(4) = TargetType '加载器会从这里重新拿数据
+        PageLoaderRestart(IsForceRestart:=True)
+    End Sub
+
 End Class
 End Class

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

@@ -47,7 +47,7 @@
     Private Sub BtnEdit_Click(sender As Object, e As EventArgs) Handles BtnEdit.Click
     Private Sub BtnEdit_Click(sender As Object, e As EventArgs) Handles BtnEdit.Click
         If McLoginLoader.State = LoadState.Loading Then
         If McLoginLoader.State = LoadState.Loading Then
             Log("[Launch] 要求更换角色,但登录加载器繁忙", LogLevel.Debug)
             Log("[Launch] 要求更换角色,但登录加载器繁忙", LogLevel.Debug)
-            If CType(McLoginLoader.Input, McLoginServer).ForceReselectProfile Then
+            If TypeOf McLoginLoader.Input Is McLoginServer AndAlso CType(McLoginLoader.Input, McLoginServer).ForceReselectProfile Then
                 Hint("正在尝试更换,请稍候!")
                 Hint("正在尝试更换,请稍候!")
             Else
             Else
                 Hint("正在登录中,请稍后再更换角色!", HintType.Red)
                 Hint("正在登录中,请稍后再更换角色!", HintType.Red)

+ 47 - 42
Plain Craft Launcher 2/Pages/PageLaunch/PageLoginMsSkin.xaml.vb

@@ -85,51 +85,56 @@
         Hint("正在更改皮肤……")
         Hint("正在更改皮肤……")
         IsChanging = True
         IsChanging = True
         '开始实际获取
         '开始实际获取
-        RunInNewThread(
-        Sub()
-            Try
+        RunInNewThread(Sub() EditSkin(SkinInfo), "Ms Skin Upload")
+    End Sub
+    Private Sub EditSkin(SkinInfo As McSkinInfo)
 Retry:
 Retry:
-                Do While McLoginMsLoader.State = LoadState.Loading '等待登录结束
-                    Thread.Sleep(10)
-                Loop
-                If McLoginMsLoader.State = LoadState.Failed Then Throw New Exception("登录失败", McLoginMsLoader.Error)
-                Dim AccessToken As String = Settings.Get("CacheMsV2Access")
-                Dim Uuid As String = Settings.Get("CacheMsV2Uuid")
-                Dim Result As String = NetRequestByClientRetry("https://api.minecraftservices.com/minecraft/profile/skins", HttpMethod.Post,
-                    Content:=New Net.Http.MultipartFormDataContent From {
-                        {New Net.Http.StringContent(If(SkinInfo.IsSlim, "slim", "classic")), "variant"},
-                        {New Net.Http.ByteArrayContent(ReadFileBytes(SkinInfo.LocalFile)), "file", GetFileNameFromPath(SkinInfo.LocalFile)}
-                    },
-                    Headers:={{"Authorization", "Bearer " & AccessToken}, {"Accept", "*/*"}, {"User-Agent", "MojangSharp/0.1"}})
-                If Result.Contains("request requires user authentication") Then
-                    Hint("正在登录,将在登录完成后继续更改皮肤……")
-                    McLoginMsLoader.Start(GetLoginData(), IsForceRestart:=True)
-                    GoTo Retry
-                ElseIf Result.Contains("""error""") Then
-                    Hint("更改皮肤失败:" & GetJson(Result)("error").ToString, HintType.Red)
+        Try
+            Do While McLoginMsLoader.State = LoadState.Loading '等待登录结束
+                Thread.Sleep(10)
+            Loop
+            If McLoginMsLoader.State = LoadState.Failed Then Throw New Exception("登录失败", McLoginMsLoader.Error)
+            Dim AccessToken As String = Settings.Get("CacheMsV2Access")
+            Dim Uuid As String = Settings.Get("CacheMsV2Uuid")
+            Dim Result As String = NetRequestByClientRetry("https://api.minecraftservices.com/minecraft/profile/skins", HttpMethod.Post,
+                Content:=New Net.Http.MultipartFormDataContent From {
+                    {New Net.Http.StringContent(If(SkinInfo.IsSlim, "slim", "classic")), "variant"},
+                    {New Net.Http.ByteArrayContent(ReadFileBytes(SkinInfo.LocalFile)), "file", GetFileNameFromPath(SkinInfo.LocalFile)}
+                },
+                Headers:={{"Authorization", "Bearer " & AccessToken}, {"Accept", "*/*"}, {"User-Agent", "MojangSharp/0.1"}})
+            If Result.Contains("request requires user authentication") Then
+                Hint("正在重新登录,将在登录后自动更改皮肤……")
+                McLoginMsLoader.Start(GetLoginData(), IsForceRestart:=True)
+                GoTo Retry
+            ElseIf Result.Contains("""error""") Then
+                Hint("更改皮肤失败:" & GetJson(Result)("error").ToString, HintType.Red)
+                Return
+            End If
+            '获取新皮肤地址
+            Log("[Skin] 皮肤修改返回值:" & vbCrLf & Result)
+            Dim ResultJson As JObject = GetJson(Result)
+            If ResultJson.ContainsKey("errorMessage") Then Throw New Exception(ResultJson("errorMessage").ToString) '#5309
+            For Each Skin As JObject In ResultJson("skins")
+                If Skin("state").ToString = "ACTIVE" Then
+                    MySkin.ReloadCache(Skin("url"))
                     Return
                     Return
                 End If
                 End If
-                '获取新皮肤地址
-                Log("[Skin] 皮肤修改返回值:" & vbCrLf & Result)
-                Dim ResultJson As JObject = GetJson(Result)
-                If ResultJson.ContainsKey("errorMessage") Then Throw New Exception(ResultJson("errorMessage").ToString) '#5309
-                For Each Skin As JObject In ResultJson("skins")
-                    If Skin("state").ToString = "ACTIVE" Then
-                        MySkin.ReloadCache(Skin("url"))
-                        Return
-                    End If
-                Next
-                Throw New Exception("未知错误(" & Result & ")")
-            Catch ex As Exception
-                If TypeOf ex Is OperationCanceledException OrElse TypeOf ex Is TimeoutException Then
-                    Hint("更改皮肤失败:连接皮肤服务器超时,请稍后再试,或使用 VPN 改善网络环境", HintType.Red)
-                Else
-                    Log(ex, "更改皮肤失败", LogLevel.Hint)
-                End If
-            Finally
-                IsChanging = False
-            End Try
-        End Sub, "Ms Skin Upload")
+            Next
+            Throw New Exception("未知错误(" & Result & ")")
+        Catch ex As Exception
+            If TypeOf ex Is OperationCanceledException OrElse TypeOf ex Is TimeoutException Then
+                Hint("更改皮肤失败:连接皮肤服务器超时,请稍后再试,或使用 VPN 改善网络环境", HintType.Red)
+            ElseIf TypeOf ex Is ResponsedWebException AndAlso CType(ex, ResponsedWebException).StatusCode = HttpStatusCode.Unauthorized Then
+                Log(ex, "更改皮肤时遭遇 401 错误", LogLevel.Developer)
+                Hint("正在重新登录,将在登录后自动更改皮肤……")
+                McLoginMsLoader.Start(GetLoginData(), IsForceRestart:=True)
+                GoTo Retry
+            Else
+                Log(ex, "更改皮肤失败", LogLevel.Hint)
+            End If
+        Finally
+            IsChanging = False
+        End Try
     End Sub
     End Sub
 
 
     '保存皮肤
     '保存皮肤

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

@@ -186,6 +186,8 @@
                         <TextBlock Margin="0,1.5,6,0" Text="ZYL" />
                         <TextBlock Margin="0,1.5,6,0" Text="ZYL" />
                         <TextBlock Margin="0,1.5,6,0" Text="qixi" />
                         <TextBlock Margin="0,1.5,6,0" Text="qixi" />
                         <TextBlock Margin="0,1.5,6,0" Text="555" />
                         <TextBlock Margin="0,1.5,6,0" Text="555" />
+                        <TextBlock Margin="0,1.5,6,0" Text="轩₩" />
+                        <TextBlock Margin="0,1.5,6,0" Text="zzw" />
                         <TextBlock Margin="0,1.5,6,0" Text="JJJT" />
                         <TextBlock Margin="0,1.5,6,0" Text="JJJT" />
                         <TextBlock Margin="0,1.5,6,0" Text="Rou" />
                         <TextBlock Margin="0,1.5,6,0" Text="Rou" />
                         <TextBlock Margin="0,1.5,6,0" Text="wyb" />
                         <TextBlock Margin="0,1.5,6,0" Text="wyb" />
@@ -202,6 +204,7 @@
                         <TextBlock Margin="0,1.5,6,0" Text="xsqs" />
                         <TextBlock Margin="0,1.5,6,0" Text="xsqs" />
                         <TextBlock Margin="0,1.5,6,0" Text="啊?" />
                         <TextBlock Margin="0,1.5,6,0" Text="啊?" />
                         <TextBlock Margin="0,1.5,6,0" Text="空青" />
                         <TextBlock Margin="0,1.5,6,0" Text="空青" />
+                        <TextBlock Margin="0,1.5,6,0" Text="奇才" />
                         <TextBlock Margin="0,1.5,6,0" Text="无风" />
                         <TextBlock Margin="0,1.5,6,0" Text="无风" />
                         <TextBlock Margin="0,1.5,6,0" Text="听雨" />
                         <TextBlock Margin="0,1.5,6,0" Text="听雨" />
                         <TextBlock Margin="0,1.5,6,0" Text="方格" />
                         <TextBlock Margin="0,1.5,6,0" Text="方格" />
@@ -315,6 +318,9 @@
                         <TextBlock Margin="0,1.5,6,0" Text="笨挽" />
                         <TextBlock Margin="0,1.5,6,0" Text="笨挽" />
                         <TextBlock Margin="0,1.5,6,0" Text="悦木" />
                         <TextBlock Margin="0,1.5,6,0" Text="悦木" />
                         <TextBlock Margin="0,1.5,6,0" Text="林霖" />
                         <TextBlock Margin="0,1.5,6,0" Text="林霖" />
+                        <TextBlock Margin="0,1.5,6,0" Text="谷雨" />
+                        <TextBlock Margin="0,1.5,6,0" Text="辞七" />
+                        <TextBlock Margin="0,1.5,6,0" Text="血狐" />
                         <TextBlock Margin="0,1.5,6,0" Text="Alex" />
                         <TextBlock Margin="0,1.5,6,0" Text="Alex" />
                         <TextBlock Margin="0,1.5,6,0" Text="JIUZ" />
                         <TextBlock Margin="0,1.5,6,0" Text="JIUZ" />
                         <TextBlock Margin="0,1.5,6,0" Text="hina" />
                         <TextBlock Margin="0,1.5,6,0" Text="hina" />
@@ -365,6 +371,7 @@
                         <TextBlock Margin="0,1.5,6,0" Text="KSfall" />
                         <TextBlock Margin="0,1.5,6,0" Text="KSfall" />
                         <TextBlock Margin="0,1.5,6,0" Text="司马Q" />
                         <TextBlock Margin="0,1.5,6,0" Text="司马Q" />
                         <TextBlock Margin="0,1.5,6,0" Text="FedEx" />
                         <TextBlock Margin="0,1.5,6,0" Text="FedEx" />
+                        <TextBlock Margin="0,1.5,6,0" Text="&amp;#39;" />
                         <TextBlock Margin="0,1.5,6,0" Text="0NaCl" />
                         <TextBlock Margin="0,1.5,6,0" Text="0NaCl" />
                         <TextBlock Margin="0,1.5,6,0" Text="pisces" />
                         <TextBlock Margin="0,1.5,6,0" Text="pisces" />
                         <TextBlock Margin="0,1.5,6,0" Text="ZDHK" />
                         <TextBlock Margin="0,1.5,6,0" Text="ZDHK" />
@@ -381,6 +388,8 @@
                         <TextBlock Margin="0,1.5,6,0" Text="伊蕾娜" />
                         <TextBlock Margin="0,1.5,6,0" Text="伊蕾娜" />
                         <TextBlock Margin="0,1.5,6,0" Text="竹节虫" />
                         <TextBlock Margin="0,1.5,6,0" Text="竹节虫" />
                         <TextBlock Margin="0,1.5,6,0" Text="狼崽子" />
                         <TextBlock Margin="0,1.5,6,0" Text="狼崽子" />
+                        <TextBlock Margin="0,1.5,6,0" Text="栀熙阳" />
+                        <TextBlock Margin="0,1.5,6,0" Text="晚雾鹤" />
                         <TextBlock Margin="0,1.5,6,0" Text="刘杰世" />
                         <TextBlock Margin="0,1.5,6,0" Text="刘杰世" />
                         <TextBlock Margin="0,1.5,6,0" Text="汐阶屿" />
                         <TextBlock Margin="0,1.5,6,0" Text="汐阶屿" />
                         <TextBlock Margin="0,1.5,6,0" Text="ーーー" />
                         <TextBlock Margin="0,1.5,6,0" Text="ーーー" />
@@ -394,6 +403,7 @@
                         <TextBlock Margin="0,1.5,6,0" Text="ximou" />
                         <TextBlock Margin="0,1.5,6,0" Text="ximou" />
                         <TextBlock Margin="0,1.5,6,0" Text="小萌新" />
                         <TextBlock Margin="0,1.5,6,0" Text="小萌新" />
                         <TextBlock Margin="0,1.5,6,0" Text="寒凌川" />
                         <TextBlock Margin="0,1.5,6,0" Text="寒凌川" />
+                        <TextBlock Margin="0,1.5,6,0" Text="江漪焺" />
                         <TextBlock Margin="0,1.5,6,0" Text="沨旻泽" />
                         <TextBlock Margin="0,1.5,6,0" Text="沨旻泽" />
                         <TextBlock Margin="0,1.5,6,0" Text="李睿洋" />
                         <TextBlock Margin="0,1.5,6,0" Text="李睿洋" />
                         <TextBlock Margin="0,1.5,6,0" Text="Frutaa" />
                         <TextBlock Margin="0,1.5,6,0" Text="Frutaa" />
@@ -451,22 +461,29 @@
                         <TextBlock Margin="0,1.5,6,0" Text="白清河" />
                         <TextBlock Margin="0,1.5,6,0" Text="白清河" />
                         <TextBlock Margin="0,1.5,6,0" Text="晚江诗" />
                         <TextBlock Margin="0,1.5,6,0" Text="晚江诗" />
                         <TextBlock Margin="0,1.5,6,0" Text="諸星洋" />
                         <TextBlock Margin="0,1.5,6,0" Text="諸星洋" />
+                        <TextBlock Margin="0,1.5,6,0" Text="哦哦哦" />
+                        <TextBlock Margin="0,1.5,6,0" Text="咕谷谷" />
+                        <TextBlock Margin="0,1.5,6,0" Text="长白山" />
                         <TextBlock Margin="0,1.5,6,0" Text="UN_41" />
                         <TextBlock Margin="0,1.5,6,0" Text="UN_41" />
                         <TextBlock Margin="0,1.5,6,0" Text="bguae" />
                         <TextBlock Margin="0,1.5,6,0" Text="bguae" />
                         <TextBlock Margin="0,1.5,6,0" Text="yoyal8" />
                         <TextBlock Margin="0,1.5,6,0" Text="yoyal8" />
                         <TextBlock Margin="0,1.5,6,0" Text="hjsa30" />
                         <TextBlock Margin="0,1.5,6,0" Text="hjsa30" />
                         <TextBlock Margin="0,1.5,6,0" Text="Chpoy" />
                         <TextBlock Margin="0,1.5,6,0" Text="Chpoy" />
+                        <TextBlock Margin="0,1.5,6,0" Text="Zh11h" />
                         <TextBlock Margin="0,1.5,6,0" Text="Ander." />
                         <TextBlock Margin="0,1.5,6,0" Text="Ander." />
                         <TextBlock Margin="0,1.5,6,0" Text="aKALA" />
                         <TextBlock Margin="0,1.5,6,0" Text="aKALA" />
                         <TextBlock Margin="0,1.5,6,0" Text="muzsh" />
                         <TextBlock Margin="0,1.5,6,0" Text="muzsh" />
                         <TextBlock Margin="0,1.5,6,0" Text="gyj120" />
                         <TextBlock Margin="0,1.5,6,0" Text="gyj120" />
+                        <TextBlock Margin="0,1.5,6,0" Text="Young" />
                         <TextBlock Margin="0,1.5,6,0" Text="IC1805" />
                         <TextBlock Margin="0,1.5,6,0" Text="IC1805" />
                         <TextBlock Margin="0,1.5,6,0" Text="凌·秋烨" />
                         <TextBlock Margin="0,1.5,6,0" Text="凌·秋烨" />
                         <TextBlock Margin="0,1.5,6,0" Text="logical" />
                         <TextBlock Margin="0,1.5,6,0" Text="logical" />
                         <TextBlock Margin="0,1.5,6,0" Text="bit...bit" />
                         <TextBlock Margin="0,1.5,6,0" Text="bit...bit" />
+                        <TextBlock Margin="0,1.5,6,0" Text="wujian" />
                         <TextBlock Margin="0,1.5,6,0" Text="N0rdiK" />
                         <TextBlock Margin="0,1.5,6,0" Text="N0rdiK" />
                         <TextBlock Margin="0,1.5,6,0" Text="Sphinx" />
                         <TextBlock Margin="0,1.5,6,0" Text="Sphinx" />
                         <TextBlock Margin="0,1.5,6,0" Text="kimma" />
                         <TextBlock Margin="0,1.5,6,0" Text="kimma" />
+                        <TextBlock Margin="0,1.5,6,0" Text="Jupiter" />
                         <TextBlock Margin="0,1.5,6,0" Text="techzjc" />
                         <TextBlock Margin="0,1.5,6,0" Text="techzjc" />
                         <TextBlock Margin="0,1.5,6,0" Text="Keiskei" />
                         <TextBlock Margin="0,1.5,6,0" Text="Keiskei" />
                         <TextBlock Margin="0,1.5,6,0" Text="EMO龚" />
                         <TextBlock Margin="0,1.5,6,0" Text="EMO龚" />
@@ -500,6 +517,7 @@
                         <TextBlock Margin="0,1.5,6,0" Text="Decade" />
                         <TextBlock Margin="0,1.5,6,0" Text="Decade" />
                         <TextBlock Margin="0,1.5,6,0" Text="laobide" />
                         <TextBlock Margin="0,1.5,6,0" Text="laobide" />
                         <TextBlock Margin="0,1.5,6,0" Text="ccb大神" />
                         <TextBlock Margin="0,1.5,6,0" Text="ccb大神" />
+                        <TextBlock Margin="0,1.5,6,0" Text="plastick" />
                         <TextBlock Margin="0,1.5,6,0" Text="chicken" />
                         <TextBlock Margin="0,1.5,6,0" Text="chicken" />
                         <TextBlock Margin="0,1.5,6,0" Text="阿毛mjy" />
                         <TextBlock Margin="0,1.5,6,0" Text="阿毛mjy" />
                         <TextBlock Margin="0,1.5,6,0" Text="CRF1SH" />
                         <TextBlock Margin="0,1.5,6,0" Text="CRF1SH" />
@@ -508,6 +526,7 @@
                         <TextBlock Margin="0,1.5,6,0" Text="-Guard-" />
                         <TextBlock Margin="0,1.5,6,0" Text="-Guard-" />
                         <TextBlock Margin="0,1.5,6,0" Text="Stridder" />
                         <TextBlock Margin="0,1.5,6,0" Text="Stridder" />
                         <TextBlock Margin="0,1.5,6,0" Text="猫yi巴草" />
                         <TextBlock Margin="0,1.5,6,0" Text="猫yi巴草" />
+                        <TextBlock Margin="0,1.5,6,0" Text="秦爅QIN" />
                         <TextBlock Margin="0,1.5,6,0" Text="Lennyes" />
                         <TextBlock Margin="0,1.5,6,0" Text="Lennyes" />
                         <TextBlock Margin="0,1.5,6,0" Text="Aspirike" />
                         <TextBlock Margin="0,1.5,6,0" Text="Aspirike" />
                         <TextBlock Margin="0,1.5,6,0" Text="Paprosa" />
                         <TextBlock Margin="0,1.5,6,0" Text="Paprosa" />
@@ -536,6 +555,7 @@
                         <TextBlock Margin="0,1.5,6,0" Text="氮气炸锅" />
                         <TextBlock Margin="0,1.5,6,0" Text="氮气炸锅" />
                         <TextBlock Margin="0,1.5,6,0" Text="小小小马" />
                         <TextBlock Margin="0,1.5,6,0" Text="小小小马" />
                         <TextBlock Margin="0,1.5,6,0" Text="爱莉希雅" />
                         <TextBlock Margin="0,1.5,6,0" Text="爱莉希雅" />
+                        <TextBlock Margin="0,1.5,6,0" Text="未梦领来" />
                         <TextBlock Margin="0,1.5,6,0" Text="容我三思" />
                         <TextBlock Margin="0,1.5,6,0" Text="容我三思" />
                         <TextBlock Margin="0,1.5,6,0" Text="正经云泽" />
                         <TextBlock Margin="0,1.5,6,0" Text="正经云泽" />
                         <TextBlock Margin="0,1.5,6,0" Text="不会起名" />
                         <TextBlock Margin="0,1.5,6,0" Text="不会起名" />
@@ -634,6 +654,7 @@
                         <TextBlock Margin="0,1.5,6,0" Text="THOPING" />
                         <TextBlock Margin="0,1.5,6,0" Text="THOPING" />
                         <TextBlock Margin="0,1.5,6,0" Text="EXcloudZ" />
                         <TextBlock Margin="0,1.5,6,0" Text="EXcloudZ" />
                         <TextBlock Margin="0,1.5,6,0" Text="想rua狐狸" />
                         <TextBlock Margin="0,1.5,6,0" Text="想rua狐狸" />
+                        <TextBlock Margin="0,1.5,6,0" Text="AmorSick" />
                         <TextBlock Margin="0,1.5,6,0" Text="Leisurelyz" />
                         <TextBlock Margin="0,1.5,6,0" Text="Leisurelyz" />
                         <TextBlock Margin="0,1.5,6,0" Text="white白鸽" />
                         <TextBlock Margin="0,1.5,6,0" Text="white白鸽" />
                         <TextBlock Margin="0,1.5,6,0" Text="有用的小B" />
                         <TextBlock Margin="0,1.5,6,0" Text="有用的小B" />
@@ -707,9 +728,13 @@
                         <TextBlock Margin="0,1.5,6,0" Text="帕秋莉~go" />
                         <TextBlock Margin="0,1.5,6,0" Text="帕秋莉~go" />
                         <TextBlock Margin="0,1.5,6,0" Text="玉玉小南娘" />
                         <TextBlock Margin="0,1.5,6,0" Text="玉玉小南娘" />
                         <TextBlock Margin="0,1.5,6,0" Text="欣喜的掌声" />
                         <TextBlock Margin="0,1.5,6,0" Text="欣喜的掌声" />
+                        <TextBlock Margin="0,1.5,6,0" Text="小云爱中国" />
+                        <TextBlock Margin="0,1.5,6,0" Text="内存漫游者" />
+                        <TextBlock Margin="0,1.5,6,0" Text="压力暴大了" />
                         <TextBlock Margin="0,1.5,6,0" Text="Myst-FOEY" />
                         <TextBlock Margin="0,1.5,6,0" Text="Myst-FOEY" />
                         <TextBlock Margin="0,1.5,6,0" Text="qaz155808" />
                         <TextBlock Margin="0,1.5,6,0" Text="qaz155808" />
                         <TextBlock Margin="0,1.5,6,0" Text="289775340" />
                         <TextBlock Margin="0,1.5,6,0" Text="289775340" />
+                        <TextBlock Margin="0,1.5,6,0" Text="baicai1339" />
                         <TextBlock Margin="0,1.5,6,0" Text="Executarea" />
                         <TextBlock Margin="0,1.5,6,0" Text="Executarea" />
                         <TextBlock Margin="0,1.5,6,0" Text="rosewhisky" />
                         <TextBlock Margin="0,1.5,6,0" Text="rosewhisky" />
                         <TextBlock Margin="0,1.5,6,0" Text="mreaaaaay" />
                         <TextBlock Margin="0,1.5,6,0" Text="mreaaaaay" />
@@ -732,6 +757,7 @@
                         <TextBlock Margin="0,1.5,6,0" Text="DeathHunk" />
                         <TextBlock Margin="0,1.5,6,0" Text="DeathHunk" />
                         <TextBlock Margin="0,1.5,6,0" Text="时时雨Sama" />
                         <TextBlock Margin="0,1.5,6,0" Text="时时雨Sama" />
                         <TextBlock Margin="0,1.5,6,0" Text="永远的Elysia" />
                         <TextBlock Margin="0,1.5,6,0" Text="永远的Elysia" />
+                        <TextBlock Margin="0,1.5,6,0" Text="Frankie_233" />
                         <TextBlock Margin="0,1.5,6,0" Text="2127864647" />
                         <TextBlock Margin="0,1.5,6,0" Text="2127864647" />
                         <TextBlock Margin="0,1.5,6,0" Text="Hashtag233" />
                         <TextBlock Margin="0,1.5,6,0" Text="Hashtag233" />
                         <TextBlock Margin="0,1.5,6,0" Text="yu🐟 ζ°)))彡" />
                         <TextBlock Margin="0,1.5,6,0" Text="yu🐟 ζ°)))彡" />
@@ -768,6 +794,7 @@
                         <TextBlock Margin="0,1.5,6,0" Text="酱汁饼大可爱" />
                         <TextBlock Margin="0,1.5,6,0" Text="酱汁饼大可爱" />
                         <TextBlock Margin="0,1.5,6,0" Text="下水道的鼠鼠" />
                         <TextBlock Margin="0,1.5,6,0" Text="下水道的鼠鼠" />
                         <TextBlock Margin="0,1.5,6,0" Text="萨卡兹大蟑螂" />
                         <TextBlock Margin="0,1.5,6,0" Text="萨卡兹大蟑螂" />
+                        <TextBlock Margin="0,1.5,6,0" Text="吃麦片的老鼠" />
                         <TextBlock Margin="0,1.5,6,0" Text="小石潭记qwq" />
                         <TextBlock Margin="0,1.5,6,0" Text="小石潭记qwq" />
                         <TextBlock Margin="0,1.5,6,0" Text="centuryplant" />
                         <TextBlock Margin="0,1.5,6,0" Text="centuryplant" />
                         <TextBlock Margin="0,1.5,6,0" Text="Suber_agiley" />
                         <TextBlock Margin="0,1.5,6,0" Text="Suber_agiley" />
@@ -786,6 +813,7 @@
                         <TextBlock Margin="0,1.5,6,0" Text="guduzihaoge" />
                         <TextBlock Margin="0,1.5,6,0" Text="guduzihaoge" />
                         <TextBlock Margin="0,1.5,6,0" Text="minecraft风竹" />
                         <TextBlock Margin="0,1.5,6,0" Text="minecraft风竹" />
                         <TextBlock Margin="0,1.5,6,0" Text="huangweijian" />
                         <TextBlock Margin="0,1.5,6,0" Text="huangweijian" />
+                        <TextBlock Margin="0,1.5,6,0" Text="Tincyclopedia" />
                         <TextBlock Margin="0,1.5,6,0" Text="Kecdl_Chacha" />
                         <TextBlock Margin="0,1.5,6,0" Text="Kecdl_Chacha" />
                         <TextBlock Margin="0,1.5,6,0" Text="CrimsonCloud" />
                         <TextBlock Margin="0,1.5,6,0" Text="CrimsonCloud" />
                         <TextBlock Margin="0,1.5,6,0" Text="minecraftac11" />
                         <TextBlock Margin="0,1.5,6,0" Text="minecraftac11" />

+ 29 - 21
Plain Craft Launcher 2/Pages/PageSetup/Settings.vb

@@ -211,7 +211,6 @@
         ''' 该设置的值的实际类型。
         ''' 该设置的值的实际类型。
         ''' </summary>
         ''' </summary>
         Public Type As Type
         Public Type As Type
-
         Public Sub New(Key As String, Value As Object, Optional Source As Sources = Sources.Normal, Optional Encrypted As Boolean = False, Optional OnChanged As Action(Of Object) = Nothing)
         Public Sub New(Key As String, Value As Object, Optional Source As Sources = Sources.Normal, Optional Encrypted As Boolean = False, Optional OnChanged As Action(Of Object) = Nothing)
             Try
             Try
                 Me.Key = Key
                 Me.Key = Key
@@ -224,22 +223,13 @@
                 Log(ex, "初始化设置项失败", LogLevel.Feedback) '#5095 的 fallback
                 Log(ex, "初始化设置项失败", LogLevel.Feedback) '#5095 的 fallback
             End Try
             End Try
         End Sub
         End Sub
-    End Class
 
 
-    ''' <summary>
-    ''' 改变某个设置项的值。
-    ''' </summary>
-    Public Shared Sub [Set](Key As String, Value As Object, Optional Instance As McInstance = Nothing)
-        Dim Entry As Setting = Nothing
-        If Not Entries.TryGetValue(Key, Entry) Then Throw New KeyNotFoundException("未找到设置项:" & Key)
-        Try
-            '判断是否一致
-            If Entry.Value Is Nothing Then [Get](Key, Instance)
-            Value = CTypeDynamic(Value, Entry.Type)
-            If Entry.Value = Value Then Return
-            '设置新值
-            Entry.Value = Value
-            If Entry.Encrypted Then
+        ''' <summary>
+        ''' 立即将当前的 Value 写入对应的注册表或文件。
+        ''' </summary>
+        Public Sub Save(Optional Instance As McInstance = Nothing)
+            Dim Value As String = Me.Value
+            If Encrypted Then
                 Try
                 Try
                     If Value Is Nothing Then Value = ""
                     If Value Is Nothing Then Value = ""
                     Value = SecretEncrypt(Value, "PCL" & Identify)
                     Value = SecretEncrypt(Value, "PCL" & Identify)
@@ -247,17 +237,34 @@
                     Log(ex, "加密设置失败:" & Key, LogLevel.Developer)
                     Log(ex, "加密设置失败:" & Key, LogLevel.Developer)
                 End Try
                 End Try
             End If
             End If
-            Select Case Entry.Source
+            Select Case Source
                 Case Sources.Normal
                 Case Sources.Normal
                     WriteIni("Setup", Key, Value)
                     WriteIni("Setup", Key, Value)
                 Case Sources.Registry
                 Case Sources.Registry
                     WriteReg(Key, Value)
                     WriteReg(Key, Value)
                 Case Sources.Instance
                 Case Sources.Instance
-                    If Instance Is Nothing Then Throw New Exception($"更改版本设置 {Key} 时未提供目标版本")
+                    If Instance Is Nothing Then Throw New Exception($"保存版本独立设置 {Key} 时未提供目标版本")
                     WriteIni(Instance.PathVersion & "PCL\Setup.ini", Key, Value)
                     WriteIni(Instance.PathVersion & "PCL\Setup.ini", Key, Value)
             End Select
             End Select
-            '触发改变事件(必须在写入之后,以保证 VersionServerLogin 之类的在事件中读取到的是最新的值)
-            If Entry.OnChanged IsNot Nothing Then Entry.OnChanged.Invoke(Value)
+        End Sub
+    End Class
+
+    ''' <summary>
+    ''' 改变某个设置项的值。
+    ''' </summary>
+    Public Shared Sub [Set](Key As String, Value As Object, Optional Instance As McInstance = Nothing)
+        Dim Entry As Setting = Nothing
+        If Not Entries.TryGetValue(Key, Entry) Then Throw New KeyNotFoundException("未找到设置项:" & Key)
+        Try
+            '判断是否一致
+            If Entry.Value Is Nothing Then [Get](Key, Instance)
+            Value = CTypeDynamic(Value, Entry.Type)
+            If Entry.Value = Value Then Return
+            '设置新值
+            Entry.Value = Value
+            Entry.Save(Instance)
+            '触发改变事件(必须在保存之后,以保证 VersionServerLogin 之类的在事件中读取到的是最新的值)
+            If Entry.OnChanged IsNot Nothing Then Entry.OnChanged.Invoke(Entry.Value)
         Catch ex As Exception
         Catch ex As Exception
             Log(ex, "设置设置项时出错(" & Key & ", " & Value & ")", LogLevel.Feedback)
             Log(ex, "设置设置项时出错(" & Key & ", " & Value & ")", LogLevel.Feedback)
         End Try
         End Try
@@ -315,7 +322,8 @@
                     Catch ex As Exception
                     Catch ex As Exception
                         Log(ex, "解密设置失败:" & Key, LogLevel.Developer)
                         Log(ex, "解密设置失败:" & Key, LogLevel.Developer)
                         GotValue = Entry.DefaultValue
                         GotValue = Entry.DefaultValue
-                        [Set](Key, Entry.DefaultValue)
+                        Entry.Value = Entry.DefaultValue
+                        Entry.Save(Instance)
                     End Try
                     End Try
                 End If
                 End If
             End If
             End If