diff --git a/Plain Craft Launcher 2/Controls/MyHint.xaml.vb b/Plain Craft Launcher 2/Controls/MyHint.xaml.vb
index b78df17..9724691 100644
--- a/Plain Craft Launcher 2/Controls/MyHint.xaml.vb
+++ b/Plain Craft Launcher 2/Controls/MyHint.xaml.vb
@@ -107,11 +107,14 @@ Public Class MyHint
End Sub
'触发点击事件
+ Public Event Click(sender As Object, e As MouseButtonEventArgs)
Private IsMouseDown As Boolean = False
Private Sub MyHint_MouseUp(sender As Object, e As MouseButtonEventArgs) Handles Me.MouseLeftButtonUp
If Not IsMouseDown Then Return
IsMouseDown = False
Log("[Control] 按下提示条" & If(String.IsNullOrEmpty(Name), "", ":" & Name))
+ RaiseEvent Click(sender, e)
+ If e.Handled Then Return
e.Handled = True
RaiseCustomEvent() '自定义事件
End Sub
diff --git a/Plain Craft Launcher 2/FormMain.xaml.vb b/Plain Craft Launcher 2/FormMain.xaml.vb
index efd8885..46862eb 100644
--- a/Plain Craft Launcher 2/FormMain.xaml.vb
+++ b/Plain Craft Launcher 2/FormMain.xaml.vb
@@ -11,6 +11,16 @@ Public Class FormMain
Dim FeatureList As New List(Of KeyValuePair(Of Integer, String))
'统计更新日志条目
#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
FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "修复:部分关键词搜不到资源,特别是中文 Mod 搜索经常没有结果"))
FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "修复:下载可能完全卡住,或是下载进度反复回退"))
@@ -140,6 +150,16 @@ Public Class FormMain
'3:BUG+ IMP* FEAT-
'2:BUG* IMP-
'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
FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "修复:部分关键词搜不到资源,特别是中文 Mod 搜索经常没有结果"))
FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "优化:降低游戏的内存占用"))
diff --git a/Plain Craft Launcher 2/Modules/Base/ModBase.vb b/Plain Craft Launcher 2/Modules/Base/ModBase.vb
index c83e8e5..6665adb 100644
--- a/Plain Craft Launcher 2/Modules/Base/ModBase.vb
+++ b/Plain Craft Launcher 2/Modules/Base/ModBase.vb
@@ -14,13 +14,13 @@ Public Module ModBase
#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 自动替换
#If BETA Then
Public Const VersionCode As Integer = 383 'Release
#Else
- Public Const VersionCode As Integer = 384 'Snapshot
+ Public Const VersionCode As Integer = 385 'Snapshot
#End If
'自动生成的版本信息
Public Const VersionDisplayName As String = VersionBranchName & " " & VersionBaseName
@@ -1336,11 +1336,12 @@ Re:
Dim Files As String()
Try
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
For Each FilePath As String In Files
Dim RetriedFile As Boolean = False
@@ -1348,6 +1349,8 @@ RetryFile:
Try
File.Delete(FilePath)
DeletedCount += 1
+ Catch ex As DirectoryNotFoundException
+ Return DeletedCount
Catch ex As Exception
If Not RetriedFile Then
RetriedFile = True
diff --git a/Plain Craft Launcher 2/Modules/Base/ModNet.vb b/Plain Craft Launcher 2/Modules/Base/ModNet.vb
index d6c89c4..a5e1131 100644
--- a/Plain Craft Launcher 2/Modules/Base/ModNet.vb
+++ b/Plain Craft Launcher 2/Modules/Base/ModNet.vb
@@ -182,10 +182,19 @@ RequestFinished:
Throw New Exception($"预处理下载文件路径失败({LocalPath})", ex)
End Try
'下载
+ Dim RetryCount As Integer = 0
+Retry:
Try
File.WriteAllBytes(LocalPath, SendRequest(Url, HttpMethod.Get, SimulateBrowserHeaders:=SimulateBrowserHeaders))
+ Catch ex As ThreadInterruptedException
+ File.Delete(LocalPath)
+ Throw
Catch ex As Exception
File.Delete(LocalPath)
+ If RetryCount < 2 Then
+ RetryCount += 1
+ GoTo Retry
+ End If
Throw New WebException($"通过网络请求直接下载小文件失败({LocalPath})", ex)
End Try
End Sub
@@ -284,6 +293,9 @@ RequestFinished:
Throw
Catch ex As ResponsedWebException
Throw
+ Catch ex As FileNotFoundException
+ '由于 CacheCow 读取缓存失败,然后系统调用不存在的 System.Net.Http.Formatting.resources 抛出(#8150)
+ Throw New Exception($"网络请求时读取缓存失败", ex)
Catch ex As Exception
RecordIPReliability(HostIp, -1)
If TypeOf ex Is OperationCanceledException OrElse TypeOf ex Is TimeoutException Then 'CancellationToken 超时
@@ -416,7 +428,7 @@ RequestFinished:
Public ReadOnly Property NetTaskSpeedLimitHigh As Long
Get
If _NetTaskSpeedLimitHigh Is Nothing Then
- Dim Setting = PCL.Settings.Get("ToolDownloadSpeed")
+ Dim Setting As Integer = Settings.Get("ToolDownloadSpeed")
If Setting <= 14 Then
_NetTaskSpeedLimitHigh = (Setting + 1) * 0.1 * 1024 * 1024L
ElseIf Setting <= 31 Then
@@ -1959,13 +1971,9 @@ Retry:
''' 是否有正在进行中、需要在下载管理页面显示的下载任务?
'''
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 Region
diff --git a/Plain Craft Launcher 2/Modules/Minecraft/ModComp.vb b/Plain Craft Launcher 2/Modules/Minecraft/ModComp.vb
index b7143a2..37aaa81 100644
--- a/Plain Craft Launcher 2/Modules/Minecraft/ModComp.vb
+++ b/Plain Craft Launcher 2/Modules/Minecraft/ModComp.vb
@@ -1,35 +1,38 @@
Public Module ModComp
- Public Enum CompType
- '''
- ''' 允许任意种类,或种类未知。
- '''
- Any = -1
+ Public Enum CompType
'''
''' Mod。
'''
- [Mod] = 0
+ [Mod] = 1
'''
''' 整合包。
'''
- ModPack = 1
+ ModPack = 2
'''
''' 资源包。
'''
- ResourcePack = 2
+ ResourcePack = 4
'''
''' 光影包。
'''
- Shader = 3
+ Shader = 8
'''
- ''' CurseForge:数据包。
- ''' Modrinth:数据包,或数据包与 Mod 的混合。
+ ''' 数据包。
'''
- DataPack = 4
+ DataPack = 16
'''
''' 服务端插件。
'''
- Plugin = 5
+ Plugin = 32
+ '''
+ ''' 同时包含数据包以及 Mod。
+ '''
+ ModOrDataPack = [Mod] Or DataPack
+ '''
+ ''' 允许任意种类,或种类未知。
+ '''
+ Any = [Mod] Or ModPack Or ResourcePack Or Shader Or DataPack Or Plugin
End Enum
Public Enum CompModLoaderType
'https://docs.curseforge.com/?http#tocS_ModLoaderType
@@ -132,10 +135,10 @@
'''
Public ReadOnly FromCurseForge As Boolean
'''
- ''' 工程的种类。
- ''' 由于 Modrinth 混合使用 Mod 和数据包,结果不一定准确。
+ ''' 工程中包含的文件种类。
+ ''' 若为 Modrinth 工程,可能为 Mod 或 数据包。
'''
- Public ReadOnly Type As CompType
+ Public ReadOnly Types As CompType
'''
''' 工程的短名。例如 technical-enchant。
'''
@@ -191,6 +194,12 @@
''' 例如:261(26.1.x)、180(1.18.x)。
'''
Public ReadOnly Drops As List(Of Integer)
+ '''
+ ''' Modrinth API 返回的原始版本列表。
+ ''' 仅用于 Modrinth 工程的二次筛选,不会被缓存,不会被预处理。
+ ''' 若非从 Modrinth 获取则为 Nothing。
+ '''
+ Public ReadOnly UnsafeGameVersions As List(Of String)
'数据库信息
@@ -203,7 +212,7 @@
Get
If Not LoadedDatabase Then
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)
End If
End If
@@ -240,7 +249,7 @@
If Data.ContainsKey("Tags") Then
#Region "CompJson"
FromCurseForge = Data("DataSource") = "CurseForge"
- Type = Data("Type").ToObject(Of Integer)
+ Types = Data("Types").ToObject(Of Integer)
Slug = Data("Slug")
Id = Data("Id")
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
'Type
If Website.Contains("/mc-mods/") OrElse Website.Contains("/mod/") Then
- Type = CompType.Mod
+ Types = CompType.Mod
ElseIf Website.Contains("/modpacks/") Then
- Type = CompType.ModPack
+ Types = CompType.ModPack
ElseIf Website.Contains("/resourcepacks/") Then
- Type = CompType.ResourcePack
+ Types = CompType.ResourcePack
ElseIf Website.Contains("/texture-packs/") Then
- Type = CompType.ResourcePack
+ Types = CompType.ResourcePack
ElseIf Website.Contains("/shaders/") Then
- Type = CompType.Shader
+ Types = CompType.Shader
Else
- Type = CompType.DataPack
+ Types = CompType.DataPack
End If
'FileIndexes / VanillaMajorVersions / ModLoaders
ModLoaders = New List(Of CompModLoaderType)
Dim Files As New List(Of KeyValuePair(Of Integer, List(Of String))) 'FileId, GameVersions
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
ModLoaders.AddRange(NewFile.ModLoaders)
Dim GameVersions = File("gameVersions").ToObject(Of List(Of String))
@@ -408,14 +417,14 @@
Website = $"https://modrinth.com/{Data("project_type")}/{Slug}"
'GameVersions
'搜索结果的键为 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
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
'Tags & ModLoaders
Tags = New List(Of String)
@@ -437,7 +446,7 @@
Case "fabric" : ModLoaders.Add(CompModLoaderType.Fabric)
Case "quilt" : ModLoaders.Add(CompModLoaderType.Quilt)
Case "neoforge" : ModLoaders.Add(CompModLoaderType.NeoForge)
- Case "datapack" : Type = CompType.DataPack '若包含数据包版本,则优先标为 DataPack
+ Case "datapack" : Types = CompType.DataPack
'共用
Case "technology" : Tags.Add("科技")
Case "magic" : Tags.Add("魔法")
@@ -452,9 +461,9 @@
Case "game-mechanics" : Tags.Add("游戏机制")
Case "transportation" : 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 "library" : Tags.Add("支持库")
'整合包
@@ -504,6 +513,7 @@
Case "vanilla" : Tags.Add("原版可用")
End Select
Next
+ If Types = CompType.DataPack AndAlso ModLoaders.Any Then Types = CompType.DataPack Or CompType.Mod
#End Region
End If
If Not Tags.Any() Then Tags.Add("其他")
@@ -519,7 +529,7 @@
Public Function ToJson() As JObject
Dim Json As New JObject
Json("DataSource") = If(FromCurseForge, "CurseForge", "Modrinth")
- Json("Type") = CInt(Type)
+ Json("Types") = CInt(Types)
Json("Slug") = Slug
Json("Id") = Id
If CurseForgeFileIds IsNot Nothing Then Json("CurseForgeFileIds") = New JArray(CurseForgeFileIds)
@@ -549,7 +559,7 @@
For i = 0 To Drops.Count - 1 '版本号一定为降序
'获取当前连续的版本号段
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
Exit For
Else
@@ -567,14 +577,14 @@
If StartDrop = EndDrop Then
Segments.Add(StartName)
ElseIf AllDrops IsNot Nothing AndAlso StartDrop >= AllDrops.First Then
- If EndDrop < 100 Then
+ If EndDrop < 120 Then
Segments.Clear()
Segments.Add("全版本")
Exit For
Else
Segments.Add(EndName & "+")
End If
- ElseIf EndDrop < 100 Then
+ ElseIf EndDrop < 120 Then
Segments.Add(StartName & "-")
Exit For
ElseIf AllDrops Is Nothing OrElse AllDrops.IndexOf(EndDrop) - AllDrops.IndexOf(StartDrop) = 1 Then
@@ -762,7 +772,7 @@ NoSubtitle:
'Mod 加载器一致
If ModLoaders.Count <> Project.ModLoaders.Count OrElse ModLoaders.Except(Project.ModLoaders).Any() Then Return False
'若不为光影,则要求 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
'MCMOD 翻译名 / 原名 / 描述文本 / Slug 的英文部分相同
@@ -813,8 +823,8 @@ NoSubtitle:
'''
Public ReadOnly Property CanContinue As Boolean
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
Return Storage.CurseForgeOffset < Storage.CurseForgeTotal OrElse Storage.ModrinthOffset < Storage.ModrinthTotal
End Get
@@ -845,7 +855,7 @@ NoSubtitle:
'''
''' 允许的来源。
'''
- Public Source As CompSourceType = CompSourceType.Any
+ Public Sources As CompSourceType = CompSourceType.Any
Public Sub New(Type As CompType, Storage As CompProjectStorage, TargetResultCount As Integer)
Me.Type = Type
Me.Storage = Storage
@@ -904,7 +914,7 @@ NoSubtitle:
Dim request = TryCast(obj, CompProjectRequest)
Return request IsNot Nothing 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
End Function
Public Shared Operator =(left As CompProjectRequest, right As CompProjectRequest) As Boolean
@@ -914,7 +924,7 @@ NoSubtitle:
Return Not left = right
End Operator
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 Class
@@ -1019,7 +1029,7 @@ NoSubtitle:
Return Candidates
End Function
'CurseForge
- If Request.Source.HasFlag(CompSourceType.CurseForge) Then
+ If Request.Sources.HasFlag(CompSourceType.CurseForge) Then
'数据库搜索
Static CurseForgeSearchEntries As List(Of SearchEntry(Of CompDatabaseEntry)) =
CompDatabase.Where(Function(Entry) Entry.CurseForgeSlug IsNot Nothing).Select(
@@ -1043,7 +1053,7 @@ NoSubtitle:
End If
End If
'Modrinth
- If Request.Source.HasFlag(CompSourceType.Modrinth) Then
+ If Request.Sources.HasFlag(CompSourceType.Modrinth) Then
'数据库搜索
Static ModrinthSearchEntries As List(Of SearchEntry(Of CompDatabaseEntry)) =
CompDatabase.Where(Function(Entry) Entry.ModrinthSlug IsNot Nothing).Select(
@@ -1094,7 +1104,7 @@ NextPage:
Try
'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 IsChineseSearch OrElse (IsChineseSearch AndAlso Not String.IsNullOrEmpty(CurseForgeAltSearchText))) Then '如果是中文搜索,就只在有对应搜索关键词的时候才继续
WorkThreads.Add(RunInNewThread(
@@ -1125,7 +1135,7 @@ NextPage:
End If
'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 IsChineseSearch OrElse (IsChineseSearch AndAlso Not String.IsNullOrEmpty(ModrinthAltSearchText))) Then '如果是中文搜索,就只在有对应搜索关键词的时候才继续
WorkThreads.Add(RunInNewThread(
@@ -1153,7 +1163,7 @@ NextPage:
End If
'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 '剩余的未显示的搜索结果不足
ModrinthSlugs.Any Then '有直接获取的 Slug
WorkThreads.Add(RunInNewThread(
@@ -1163,7 +1173,16 @@ NextPage:
Log("[Comp] 开始 Modrinth 直接获取:" & ModrinthUrl)
Dim ProjectList As New List(Of CompProject)
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
'更新结果
ProjectList.ForEach(Sub(p) RawResults.Add(p))
@@ -1196,9 +1215,9 @@ NextPage:
Else
If IsChineseSearch AndAlso Not (Request.Type = CompType.Mod OrElse Request.Type = CompType.DataPack) Then
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 不兼容所选的类型")
- ElseIf Request.Source = CompSourceType.Modrinth AndAlso Request.Tag.EndsWithF("/") Then
+ ElseIf Request.Sources = CompSourceType.Modrinth AndAlso Request.Tag.EndsWithF("/") Then
Throw New Exception("Modrinth 不兼容所选的类型")
Else
Throw New Exception("没有搜索结果")
@@ -1418,7 +1437,7 @@ NextPage:
'实例化
'''
- ''' 从文件 Json 中初始化实例。若出错会抛出异常。
+ ''' 从 json 中初始化实例。若出错会抛出异常。
'''
Public Sub New(Data As JObject, DefaultType As CompType)
Type = DefaultType
@@ -1505,25 +1524,16 @@ NextPage:
Size = File("size")
Hash = File("hashes")("sha1")
End If
- 'ModLoaders
+ 'Loaders
'结果可能混杂着 Mod、数据包和服务端插件
Dim RawLoaders As List(Of String) = Data("loaders").Select(Function(v) v.ToString).ToList
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
If Data.ContainsKey("dependencies") Then
RawDependencies = Data("dependencies").
@@ -1694,7 +1704,7 @@ NextPage:
'Modrinth
ResultJsonArray = DlModRequest($"https://api.modrinth.com/v2/project/{ProjectId}/version?include_changelog=false")
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.
Distinct(Function(a, b) a.Id = b.Id) 'CurseForge 可能会重复返回相同项(#1330)
End If
diff --git a/Plain Craft Launcher 2/Modules/Minecraft/ModDownload.vb b/Plain Craft Launcher 2/Modules/Minecraft/ModDownload.vb
index f535386..b9d9458 100644
--- a/Plain Craft Launcher 2/Modules/Minecraft/ModDownload.vb
+++ b/Plain Craft Launcher 2/Modules/Minecraft/ModDownload.vb
@@ -858,10 +858,11 @@
VersionName = ApiName
Version = New Version(ApiName.BeforeFirst("-"))
If Version.Major >= 24 Then
- Inherit = Version.Major & "." & Version.Minor
+ Inherit = $"{Version.Major}.{Version.Minor}.{Version.Build}"
Else
- Inherit = "1." & Version.Major & If(Version.Minor > 0, "." & Version.Minor, "")
+ Inherit = $"1.{Version.Major}.{Version.Minor}"
End If
+ If Inherit.EndsWithF(".0") Then Inherit = Left(Inherit, Inherit.Length - 2)
If VersionName.Contains("+") Then Inherit &= "-" & VersionName.AfterFirst("+")
End If
End Sub
diff --git a/Plain Craft Launcher 2/Modules/Minecraft/ModLaunch.vb b/Plain Craft Launcher 2/Modules/Minecraft/ModLaunch.vb
index 5672ca1..6722894 100644
--- a/Plain Craft Launcher 2/Modules/Minecraft/ModLaunch.vb
+++ b/Plain Craft Launcher 2/Modules/Minecraft/ModLaunch.vb
@@ -1446,9 +1446,10 @@ NextInstance:
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
'添加 GC 参数
+ Args.Add("-XX:+UnlockExperimentalVMOptions")
+ If McLaunchJavaSelected.MajorVersion >= 24 AndAlso McLaunchJavaSelected.Is64Bit Then Args.Add("-XX:+UseCompactObjectHeaders")
If UseG1GC AndAlso SetupType = 4 Then
'优化的 G1GC
- Args.Add("-XX:+UnlockExperimentalVMOptions")
Args.Add("-XX:+UseG1GC")
Args.Add("-XX:G1NewSizePercent=20")
Args.Add("-XX:G1ReservePercent=20")
@@ -1459,10 +1460,8 @@ NextInstance:
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:MaxHeapFreeRatio=40") '需要比 MinHeapFreeRatio 大一些
- If McLaunchJavaSelected.MajorVersion >= 24 AndAlso McLaunchJavaSelected.Is64Bit Then Args.Add("-XX:+UseCompactObjectHeaders")
ElseIf UseG1GC Then
'Mojang G1GC
- Args.Add("-XX:+UnlockExperimentalVMOptions")
Args.Add("-XX:+UseG1GC")
Args.Add("-XX:G1NewSizePercent=20")
Args.Add("-XX:G1ReservePercent=20")
diff --git a/Plain Craft Launcher 2/Modules/Minecraft/ModMinecraft.vb b/Plain Craft Launcher 2/Modules/Minecraft/ModMinecraft.vb
index 923652c..ad7ebd4 100644
--- a/Plain Craft Launcher 2/Modules/Minecraft/ModMinecraft.vb
+++ b/Plain Craft Launcher 2/Modules/Minecraft/ModMinecraft.vb
@@ -1119,7 +1119,7 @@ ExitDataLoad:
Public Shared Function IsFormatFit(Version As String) As Boolean
If Version Is Nothing Then Return False
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
End Function
'''
diff --git a/Plain Craft Launcher 2/Modules/Minecraft/ModMod.vb b/Plain Craft Launcher 2/Modules/Minecraft/ModMod.vb
index 2bbecff..4b53985 100644
--- a/Plain Craft Launcher 2/Modules/Minecraft/ModMod.vb
+++ b/Plain Craft Launcher 2/Modules/Minecraft/ModMod.vb
@@ -1,7 +1,7 @@
Imports System.IO.Compression
Public Module ModMod
- Private Const LocalModCacheVersion As Integer = 12
+ Private Const LocalModCacheVersion As Integer = 13
Public Class McMod
diff --git a/Plain Craft Launcher 2/My Project/AssemblyInfo.vb b/Plain Craft Launcher 2/My Project/AssemblyInfo.vb
index e0765ad..bf8a58b 100644
--- a/Plain Craft Launcher 2/My Project/AssemblyInfo.vb
+++ b/Plain Craft Launcher 2/My Project/AssemblyInfo.vb
@@ -51,6 +51,6 @@ Imports System.Runtime.InteropServices
' 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号
' 方法是按如下所示使用“*”
-
-
+
+
diff --git a/Plain Craft Launcher 2/Pages/PageDownload/Comp/MyCompItem.xaml.vb b/Plain Craft Launcher 2/Pages/PageDownload/Comp/MyCompItem.xaml.vb
index 0a36182..6843a0b 100644
--- a/Plain Craft Launcher 2/Pages/PageDownload/Comp/MyCompItem.xaml.vb
+++ b/Plain Craft Launcher 2/Pages/PageDownload/Comp/MyCompItem.xaml.vb
@@ -94,36 +94,36 @@
End If
'打开详情页
Dim TargetType As CompType
- Dim TargetVersion As String = Nothing
+ Dim TargetInstance As String = Nothing
Dim TargetLoader As CompModLoaderType = CompModLoaderType.Any
If FrmMain.PageCurrent.Page = FormMain.PageType.Download Then
'从下载页进入
Select Case FrmMain.PageCurrentSub
Case FormMain.PageSubType.DownloadMod
TargetType = CompType.Mod
- TargetVersion = FrmDownloadMod.Content.Loader.Input.GameVersion
+ TargetInstance = FrmDownloadMod.Content.Loader.Input.GameVersion
TargetLoader = FrmDownloadMod.Content.Loader.Input.ModLoader
Case FormMain.PageSubType.DownloadPack
TargetType = CompType.ModPack
- TargetVersion = FrmDownloadPack.Content.Loader.Input.GameVersion
+ TargetInstance = FrmDownloadPack.Content.Loader.Input.GameVersion
Case FormMain.PageSubType.DownloadDataPack
TargetType = CompType.DataPack
- TargetVersion = FrmDownloadDataPack.Content.Loader.Input.GameVersion
+ TargetInstance = FrmDownloadDataPack.Content.Loader.Input.GameVersion
Case FormMain.PageSubType.DownloadResourcePack
TargetType = CompType.ResourcePack
- TargetVersion = FrmDownloadResourcePack.Content.Loader.Input.GameVersion
+ TargetInstance = FrmDownloadResourcePack.Content.Loader.Input.GameVersion
Case FormMain.PageSubType.DownloadShader
TargetType = CompType.Shader
- TargetVersion = FrmDownloadShader.Content.Loader.Input.GameVersion
+ TargetInstance = FrmDownloadShader.Content.Loader.Input.GameVersion
End Select
Else
'从详情页进入(查看前置)
TargetType = CompType.Any '允许任意类别
- TargetVersion = FrmMain.PageCurrent.Additional(2)
+ TargetInstance = FrmMain.PageCurrent.Additional(2)
TargetLoader = FrmMain.PageCurrent.Additional(3)
End If
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
'鼠标点击判定
diff --git a/Plain Craft Launcher 2/Pages/PageDownload/Comp/PageComp.xaml b/Plain Craft Launcher 2/Pages/PageDownload/Comp/PageComp.xaml
index b451f64..d669f8d 100644
--- a/Plain Craft Launcher 2/Pages/PageDownload/Comp/PageComp.xaml
+++ b/Plain Craft Launcher 2/Pages/PageDownload/Comp/PageComp.xaml
@@ -34,15 +34,16 @@
+
+
+
-
-
+
-
diff --git a/Plain Craft Launcher 2/Pages/PageDownload/Comp/PageComp.xaml.vb b/Plain Craft Launcher 2/Pages/PageDownload/Comp/PageComp.xaml.vb
index 746cdad..9df5bb3 100644
--- a/Plain Craft Launcher 2/Pages/PageDownload/Comp/PageComp.xaml.vb
+++ b/Plain Craft Launcher 2/Pages/PageDownload/Comp/PageComp.xaml.vb
@@ -127,7 +127,7 @@ Public Class PageComp
.GameVersion = GameVersion
.Tag = ComboSearchTag.SelectedItem.Tag
.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
Return Request
End Function
diff --git a/Plain Craft Launcher 2/Pages/PageDownload/Comp/PageDownloadCompDetail.xaml b/Plain Craft Launcher 2/Pages/PageDownload/Comp/PageDownloadCompDetail.xaml
index eb4a37c..f95e25d 100644
--- a/Plain Craft Launcher 2/Pages/PageDownload/Comp/PageDownloadCompDetail.xaml
+++ b/Plain Craft Launcher 2/Pages/PageDownload/Comp/PageDownloadCompDetail.xaml
@@ -20,6 +20,7 @@
+
diff --git a/Plain Craft Launcher 2/Pages/PageDownload/Comp/PageDownloadCompDetail.xaml.vb b/Plain Craft Launcher 2/Pages/PageDownload/Comp/PageDownloadCompDetail.xaml.vb
index 32bb750..6d6dc54 100644
--- a/Plain Craft Launcher 2/Pages/PageDownload/Comp/PageDownloadCompDetail.xaml.vb
+++ b/Plain Craft Launcher 2/Pages/PageDownload/Comp/PageDownloadCompDetail.xaml.vb
@@ -21,14 +21,15 @@
Project = FrmMain.PageCurrent.Additional(0)
TargetInstance = FrmMain.PageCurrent.Additional(2)
TargetLoader = FrmMain.PageCurrent.Additional(3)
- PageType = FrmMain.PageCurrent.Additional(4)
+ TargetType = FrmMain.PageCurrent.Additional(4)
End Sub
Private Project As CompProject
Private TargetInstance As String, TargetLoader As CompModLoaderType
'''
- ''' 当前页面应展示的内容类别。可能为 Any。
+ ''' 当前页面应展示的内容类别。
+ ''' 若当前页面是在查看前置时进入,则也可能为 Any。
'''
- 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
Select Case CompFileLoader.State
@@ -74,13 +75,13 @@
'筛选类型相同的结果(Modrinth 会返回 Mod、服务端插件、数据包混合的列表)
Private Function GetResults() As List(Of CompFile)
Dim Results As List(Of CompFile) = CompFileLoader.Output
- Select Case PageType
+ Select Case TargetType
Case CompType.Any
Results = Results.Where(Function(r) r.Type <> CompType.Plugin).ToList
Case CompType.Shader, CompType.ResourcePack
'不筛选光影和资源包,否则原版光影会因为是资源包格式而被过滤(#6473)
Case Else
- Results = Results.Where(Function(r) r.Type = PageType).ToList
+ Results = Results.Where(Function(r) r.Type = TargetType).ToList
End Select
Return Results
End Function
@@ -204,7 +205,7 @@ GroupDone:
If Not Pair.Value.Any() 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}
NewCard.Children.Add(NewStack)
NewCard.SwapControl = NewStack
@@ -213,7 +214,7 @@ GroupDone:
If Pair.Key = TargetCardName OrElse
(FrmMain.PageCurrent.Additional IsNot Nothing AndAlso '#2761
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
NewCard.IsSwapped = True
End If
@@ -226,6 +227,14 @@ GroupDone:
If PanResults.Children.Count = 1 Then
CType(PanResults.Children(0), MyCard).IsSwapped = False
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
Log(ex, "可视化工程下载列表出错", LogLevel.Feedback)
End Try
@@ -494,4 +503,11 @@ GroupDone:
ClipboardSet(CompItem.LabTitle.Text & CompItem.LabTitleRaw.Text)
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
diff --git a/Plain Craft Launcher 2/Pages/PageLaunch/PageLoginAuthSkin.xaml.vb b/Plain Craft Launcher 2/Pages/PageLaunch/PageLoginAuthSkin.xaml.vb
index 6eba85a..22b8ac7 100644
--- a/Plain Craft Launcher 2/Pages/PageLaunch/PageLoginAuthSkin.xaml.vb
+++ b/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
If McLoginLoader.State = LoadState.Loading Then
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("正在尝试更换,请稍候!")
Else
Hint("正在登录中,请稍后再更换角色!", HintType.Red)
diff --git a/Plain Craft Launcher 2/Pages/PageLaunch/PageLoginMsSkin.xaml.vb b/Plain Craft Launcher 2/Pages/PageLaunch/PageLoginMsSkin.xaml.vb
index 65c39b0..269afb6 100644
--- a/Plain Craft Launcher 2/Pages/PageLaunch/PageLoginMsSkin.xaml.vb
+++ b/Plain Craft Launcher 2/Pages/PageLaunch/PageLoginMsSkin.xaml.vb
@@ -85,51 +85,56 @@
Hint("正在更改皮肤……")
IsChanging = True
'开始实际获取
- RunInNewThread(
- Sub()
- Try
+ RunInNewThread(Sub() EditSkin(SkinInfo), "Ms Skin Upload")
+ End Sub
+ Private Sub EditSkin(SkinInfo As McSkinInfo)
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
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
'保存皮肤
diff --git a/Plain Craft Launcher 2/Pages/PageOther/PageOtherAbout.xaml b/Plain Craft Launcher 2/Pages/PageOther/PageOtherAbout.xaml
index a19759d..56a215d 100644
--- a/Plain Craft Launcher 2/Pages/PageOther/PageOtherAbout.xaml
+++ b/Plain Craft Launcher 2/Pages/PageOther/PageOtherAbout.xaml
@@ -186,6 +186,8 @@
+
+
@@ -202,6 +204,7 @@
+
@@ -315,6 +318,9 @@
+
+
+
@@ -365,6 +371,7 @@
+
@@ -381,6 +388,8 @@
+
+
@@ -394,6 +403,7 @@
+
@@ -451,22 +461,29 @@
+
+
+
+
+
+
+
@@ -500,6 +517,7 @@
+
@@ -508,6 +526,7 @@
+
@@ -536,6 +555,7 @@
+
@@ -634,6 +654,7 @@
+
@@ -707,9 +728,13 @@
+
+
+
+
@@ -732,6 +757,7 @@
+
@@ -768,6 +794,7 @@
+
@@ -786,6 +813,7 @@
+
diff --git a/Plain Craft Launcher 2/Pages/PageSetup/Settings.vb b/Plain Craft Launcher 2/Pages/PageSetup/Settings.vb
index 06839f5..1e477cd 100644
--- a/Plain Craft Launcher 2/Pages/PageSetup/Settings.vb
+++ b/Plain Craft Launcher 2/Pages/PageSetup/Settings.vb
@@ -211,7 +211,6 @@
''' 该设置的值的实际类型。
'''
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)
Try
Me.Key = Key
@@ -224,6 +223,30 @@
Log(ex, "初始化设置项失败", LogLevel.Feedback) '#5095 的 fallback
End Try
End Sub
+
+ '''
+ ''' 立即将当前的 Value 写入对应的注册表或文件。
+ '''
+ Public Sub Save(Optional Instance As McInstance = Nothing)
+ Dim Value As String = Me.Value
+ If Encrypted Then
+ Try
+ If Value Is Nothing Then Value = ""
+ Value = SecretEncrypt(Value, "PCL" & Identify)
+ Catch ex As Exception
+ Log(ex, "加密设置失败:" & Key, LogLevel.Developer)
+ End Try
+ End If
+ Select Case Source
+ Case Sources.Normal
+ WriteIni("Setup", Key, Value)
+ Case Sources.Registry
+ WriteReg(Key, Value)
+ Case Sources.Instance
+ If Instance Is Nothing Then Throw New Exception($"保存版本独立设置 {Key} 时未提供目标版本")
+ WriteIni(Instance.PathVersion & "PCL\Setup.ini", Key, Value)
+ End Select
+ End Sub
End Class
'''
@@ -239,25 +262,9 @@
If Entry.Value = Value Then Return
'设置新值
Entry.Value = Value
- If Entry.Encrypted Then
- Try
- If Value Is Nothing Then Value = ""
- Value = SecretEncrypt(Value, "PCL" & Identify)
- Catch ex As Exception
- Log(ex, "加密设置失败:" & Key, LogLevel.Developer)
- End Try
- End If
- Select Case Entry.Source
- Case Sources.Normal
- WriteIni("Setup", Key, Value)
- Case Sources.Registry
- WriteReg(Key, Value)
- Case Sources.Instance
- If Instance Is Nothing Then Throw New Exception($"更改版本设置 {Key} 时未提供目标版本")
- WriteIni(Instance.PathVersion & "PCL\Setup.ini", Key, Value)
- End Select
- '触发改变事件(必须在写入之后,以保证 VersionServerLogin 之类的在事件中读取到的是最新的值)
- If Entry.OnChanged IsNot Nothing Then Entry.OnChanged.Invoke(Value)
+ Entry.Save(Instance)
+ '触发改变事件(必须在保存之后,以保证 VersionServerLogin 之类的在事件中读取到的是最新的值)
+ If Entry.OnChanged IsNot Nothing Then Entry.OnChanged.Invoke(Entry.Value)
Catch ex As Exception
Log(ex, "设置设置项时出错(" & Key & ", " & Value & ")", LogLevel.Feedback)
End Try
@@ -315,7 +322,8 @@
Catch ex As Exception
Log(ex, "解密设置失败:" & Key, LogLevel.Developer)
GotValue = Entry.DefaultValue
- [Set](Key, Entry.DefaultValue)
+ Entry.Value = Entry.DefaultValue
+ Entry.Save(Instance)
End Try
End If
End If