diff --git a/Plain Craft Launcher 2/Application.xaml.vb b/Plain Craft Launcher 2/Application.xaml.vb
index cb4d0301..4791caf3 100644
--- a/Plain Craft Launcher 2/Application.xaml.vb
+++ b/Plain Craft Launcher 2/Application.xaml.vb
@@ -210,8 +210,8 @@ Public Class Application
If AssemblyImazenWebp Is Nothing Then
Log("[Start] 加载 DLL:Imazen.WebP")
AssemblyImazenWebp = Assembly.Load(GetResources("Imazen_WebP"))
- SetDllDirectory(PathTemp)
- File.WriteAllBytes(PathTemp & "libwebp.dll", GetResources("libwebp64"))
+ SetDllDirectory(GetPureAsciiDir())
+ File.WriteAllBytes(GetPureAsciiDir() & "\libwebp.dll", GetResources("libwebp64"))
End If
Return AssemblyImazenWebp
End SyncLock
diff --git a/Plain Craft Launcher 2/FormMain.xaml.vb b/Plain Craft Launcher 2/FormMain.xaml.vb
index a1f9b156..929d7621 100644
--- a/Plain Craft Launcher 2/FormMain.xaml.vb
+++ b/Plain Craft Launcher 2/FormMain.xaml.vb
@@ -10,6 +10,19 @@ Public Class FormMain
Dim FeatureList As New List(Of KeyValuePair(Of Integer, String))
'统计更新日志条目
#If BETA Then
+ If LastVersion < 340 Then 'Release 2.8.8
+ If LastVersion = 338 Then FeatureList.Add(New KeyValuePair(Of Integer, String)(1, "修复数个与新正版登录相关的严重 Bug"))
+ FeatureCount += 3
+ BugCount += 7
+ End If
+ If LastVersion < 338 Then 'Release 2.8.7
+ FeatureList.Add(New KeyValuePair(Of Integer, String)(4, "使用新的正版登录方式,以提高安全性"))
+ FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "优化安装整合包、检索 Mod 的稳定性"))
+ FeatureList.Add(New KeyValuePair(Of Integer, String)(1, "修复无法加载部分 Mod 的图标的 Bug"))
+ FeatureList.Add(New KeyValuePair(Of Integer, String)(1, "修复在 Mod 管理页面删除 Mod 导致报错的 Bug"))
+ FeatureCount += 11
+ BugCount += 21
+ End If
If LastVersion < 336 Then 'Release 2.8.6
FeatureList.Add(New KeyValuePair(Of Integer, String)(4, "下载 Mod 时会使用 MCIM 国内镜像源"))
FeatureList.Add(New KeyValuePair(Of Integer, String)(4, "Mod 管理页面允许筛选可更新/启用/禁用的 Mod"))
@@ -134,6 +147,11 @@ Public Class FormMain
'3:BUG+ IMP* FEAT-
'2:BUG* IMP-
'1:BUG-
+ If LastVersion < 339 Then 'Snapshot 2.8.8
+ If LastVersion = 337 Then FeatureList.Add(New KeyValuePair(Of Integer, String)(1, "修复数个与新正版登录相关的严重 Bug"))
+ FeatureCount += 3
+ BugCount += 7
+ End If
If LastVersion < 337 Then 'Snapshot 2.8.7
FeatureList.Add(New KeyValuePair(Of Integer, String)(4, "使用新的正版登录方式,以提高安全性"))
FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "优化安装整合包、检索 Mod 的稳定性"))
@@ -721,7 +739,7 @@ Public Class FormMain
Exit Sub
ElseIf e.Key = Key.Escape Then
Dim Msg As Object = PanMsg.Children(0)
- If TypeOf Msg Is MyMsgText AndAlso Msg.Btn3.Visibility = Visibility.Visible Then
+ If TypeOf Msg IsNot MyMsgInput AndAlso TypeOf Msg IsNot MyMsgSelect AndAlso Msg.Btn3.Visibility = Visibility.Visible Then
Msg.Btn3_Click()
ElseIf Msg.Btn2.Visibility = Visibility.Visible Then
Msg.Btn2_Click()
diff --git a/Plain Craft Launcher 2/Modules/Base/ModBase.vb b/Plain Craft Launcher 2/Modules/Base/ModBase.vb
index 9da1b3f9..96fe4b7d 100644
--- a/Plain Craft Launcher 2/Modules/Base/ModBase.vb
+++ b/Plain Craft Launcher 2/Modules/Base/ModBase.vb
@@ -12,13 +12,13 @@ Public Module ModBase
#Region "声明"
'下列版本信息由更新器自动修改
- Public Const VersionBaseName As String = "2.8.7" '不含分支前缀的显示用版本名
- Public Const VersionStandardCode As String = "2.8.7." & VersionBranchCode '标准格式的四段式版本号
+ Public Const VersionBaseName As String = "2.8.8" '不含分支前缀的显示用版本名
+ Public Const VersionStandardCode As String = "2.8.8." & VersionBranchCode '标准格式的四段式版本号
Public Const CommitHash As String = "" 'Commit Hash,由 GitHub Workflow 自动替换
#If BETA Then
- Public Const VersionCode As Integer = 336 'Release
+ Public Const VersionCode As Integer = 340 'Release
#Else
- Public Const VersionCode As Integer = 337 'Snapshot
+ Public Const VersionCode As Integer = 339 'Snapshot
#End If
'自动生成的版本信息
Public Const VersionDisplayName As String = VersionBranchName & " " & VersionBaseName
@@ -1840,6 +1840,13 @@ RetryDir:
#Region "系统"
+ '''
+ ''' 指示接取到这个异常的函数进行重试。
+ '''
+ Public Class RetryException
+ Inherits Exception
+ End Class
+
'''
''' 当前程序是否拥有管理员权限。
'''
@@ -2430,6 +2437,14 @@ Retry:
Return rect.Contains(bounds.TopLeft) OrElse rect.Contains(bounds.BottomRight)
End Function
+ '''
+ ''' 控件是否受到 TextTrimming 属性影响,导致内容被截取。
+ '''
+ Public Function IsTextTrimmed(Control As TextBlock) As Boolean
+ Control.Measure(New Size(Double.MaxValue, Double.MaxValue))
+ Return Control.DesiredSize.Width > Control.ActualWidth
+ End Function
+
#End Region
#Region "Debug"
diff --git a/Plain Craft Launcher 2/Modules/Base/ModLoader.vb b/Plain Craft Launcher 2/Modules/Base/ModLoader.vb
index 0e71e588..e824443d 100644
--- a/Plain Craft Launcher 2/Modules/Base/ModLoader.vb
+++ b/Plain Craft Launcher 2/Modules/Base/ModLoader.vb
@@ -288,15 +288,13 @@
End SyncLock
End Try
'检验输入以确定情况
- If (Not IsForceRestart) AndAlso '不要求强行重启
- ((Input IsNot Nothing AndAlso Input.Equals(Me.Input)) OrElse (Input Is Nothing AndAlso Me.Input Is Nothing)) AndAlso '输入相同
- (State = LoadState.Loading OrElse State = LoadState.Finished) AndAlso '正在加载或已加载成功
+ If IsForceRestart Then Return True '强制要求重启
+ If ((Input Is Nothing) <> (Me.Input Is Nothing)) OrElse (Input IsNot Nothing AndAlso Not Input.Equals(Me.Input)) Then Return True '输入不同
+ If (State = LoadState.Loading OrElse State = LoadState.Finished) AndAlso '正在加载或已结束
(IgnoreReloadTimeout OrElse ReloadTimeout = -1 OrElse LastFinishedTime = 0 OrElse GetTimeTick() - LastFinishedTime < ReloadTimeout) Then '没有超时
- '如果输入相同且未出错则不重试
- Return False
+ Return False '则不重试
Else
- '需要开始
- Return True
+ Return True '需要开始
End If
End Function
Public Overrides Sub Start(Optional Input As Object = Nothing, Optional IsForceRestart As Boolean = False)
@@ -317,7 +315,7 @@
Sub()
Try
IsForceRestarting = IsForceRestart
- If ModeDebug Then Log("[Loader] 加载线程 " & Name & " (" & Thread.CurrentThread.ManagedThreadId & ") 已启动")
+ If ModeDebug Then Log("[Loader] 加载线程 " & Name & " (" & Thread.CurrentThread.ManagedThreadId & ") 已" & If(IsForceRestarting, "强制", "") & "启动")
LoadDelegate(Me)
If IsAborted Then
Log("[Loader] 加载线程 " & Name & " (" & Thread.CurrentThread.ManagedThreadId & ") 已中断但线程正常运行至结束,输出被弃用(最新线程:" & If(LastRunningThread Is Nothing, -1, LastRunningThread.ManagedThreadId) & ")", LogLevel.Developer)
@@ -441,12 +439,13 @@
Exit Sub
End If
End SyncLock
- RunInThread(Sub()
- '中断加载器
- For Each Loader In Loaders
- Loader.Abort()
- Next
- End Sub)
+ RunInThread(
+ Sub()
+ '中断加载器
+ For Each Loader In Loaders
+ Loader.Abort()
+ Next
+ End Sub)
End Sub
'''
@@ -485,7 +484,7 @@
Private Sub Update()
If State = LoadState.Finished OrElse State = LoadState.Failed OrElse State = LoadState.Aborted Then Exit Sub
Dim IsFinished As Boolean = True
- Dim Ignore As Boolean = False
+ Dim Blocked As Boolean = False
Dim Input As Object = Me.Input
For Each Loader In Loaders
Select Case Loader.State
@@ -493,28 +492,30 @@
'检查是否需要重启
If Loader.GetType.Name.StartsWithF("LoaderTask") Then '类型名后面带有泛型,必须用 StartsWith
If CType(Loader, Object).ShouldStart(If(Input IsNot Nothing AndAlso Loader.GetType.GenericTypeArguments.First Is Input.GetType, Input, Nothing), IgnoreReloadTimeout:=True) Then
- If ModeDebug Then Log("[Loader] 由于输入条件变更,重启已完成的加载器 " & Loader.Name)
+ Log("[Loader] 由于输入条件变更,重启已完成的加载器 " & Loader.Name)
GoTo Restart
End If
'更新下一个加载器的输入
Input = CType(Loader, Object).Output
End If
+ '如果不让继续启动,且已有加载器正在加载中,就不继续启动
+ If Loader.Block AndAlso Not IsFinished Then Blocked = True
Case LoadState.Loading
'检查是否需要重启
If Loader.GetType.Name.StartsWithF("LoaderTask") Then
If CType(Loader, Object).ShouldStart(If(Input IsNot Nothing AndAlso Loader.GetType.GenericTypeArguments.First Is Input.GetType, Input, Nothing), IgnoreReloadTimeout:=True) Then
- If ModeDebug Then Log("[Loader] 由于输入条件变更,重启进行中的加载器 " & Loader.Name, LogLevel.Developer)
+ Log("[Loader] 由于输入条件变更,重启进行中的加载器 " & Loader.Name, LogLevel.Developer)
GoTo Restart
End If
End If
'已经有正在加载中的了,不需要再启动了
IsFinished = False
- Ignore = True
+ Blocked = True
Case Else
Restart:
'未启动,则启动加载器
IsFinished = False
- If Ignore Then Continue For
+ If Blocked Then Continue For
If Input IsNot Nothing Then
'若输入类型与下一个加载器相同才继续
Dim LoaderType As String = Loader.GetType.Name
@@ -528,8 +529,8 @@ Restart:
Else
Loader.Start(IsForceRestart:=IsForceRestarting)
End If
- '如果不让继续启动,那就不启动呗
- If Loader.Block Then Ignore = True
+ '阻止继续
+ If Loader.Block Then Blocked = True
End Select
Next
If IsFinished Then
diff --git a/Plain Craft Launcher 2/Modules/Base/ModNet.vb b/Plain Craft Launcher 2/Modules/Base/ModNet.vb
index 9fa91361..ea13ad88 100644
--- a/Plain Craft Launcher 2/Modules/Base/ModNet.vb
+++ b/Plain Craft Launcher 2/Modules/Base/ModNet.vb
@@ -140,7 +140,7 @@ Retry:
'''
''' 网页的 Url。
''' 网页的编码,通常为 UTF-8。
- Public Function NetGetCodeByRequestMulty(Url As String, Optional Encode As Encoding = Nothing, Optional Accept As String = "", Optional IsJson As Boolean = False)
+ Public Function NetGetCodeByRequestMultiple(Url As String, Optional Encode As Encoding = Nothing, Optional Accept As String = "", Optional IsJson As Boolean = False)
Dim Threads As New List(Of Thread)
Dim RequestResult = Nothing
Dim RequestEx As Exception = Nothing
@@ -329,7 +329,7 @@ Retry:
'''
''' 同时发送多个网络请求并要求返回内容。
'''
- Public Function NetRequestMulty(Url As String, Method As String, Data As Object, ContentType As String, Optional RequestCount As Integer = 4, Optional Headers As Dictionary(Of String, String) = Nothing, Optional MakeLog As Boolean = True)
+ Public Function NetRequestMultiple(Url As String, Method As String, Data As Object, ContentType As String, Optional RequestCount As Integer = 4, Optional Headers As Dictionary(Of String, String) = Nothing, Optional MakeLog As Boolean = True)
Dim Threads As New List(Of Thread)
Dim RequestResult = Nothing
Dim RequestEx As Exception = Nothing
@@ -701,8 +701,7 @@ RequestFinished:
'''
''' 所属的文件列表任务。
'''
- Public Tasks As New Concurrent.ConcurrentBag(Of LoaderDownload)
-
+ Public Tasks As New SynchronizedCollection(Of LoaderDownload)
'''
''' 所有下载源。
'''
@@ -1232,7 +1231,7 @@ SourceBreak:
'根据情况判断,是否在多线程下禁用下载源(连续错误过多,或不支持断点续传)
If ex.Message.Contains("该下载源不支持") OrElse ex.Message.Contains("未能解析") OrElse ex.Message.Contains("(404)") OrElse
ex.Message.Contains("(502)") OrElse ex.Message.Contains("无返回数据") OrElse ex.Message.Contains("空间不足") OrElse ex.Message.Contains("获取到的分段大小不一致") OrElse
- ((ex.Message.Contains("(403)") OrElse ex.Message.Contains("(429)")) AndAlso Not Info.Source.Url.ContainsF("bmclapi")) OrElse 'BMCLAPI 的部分源在高频率请求下会返回 403、429,所以不应因此禁用下载源
+ (ex.Message.Contains("(403)") AndAlso Not Info.Source.Url.ContainsF("bmclapi")) OrElse 'BMCLAPI 的部分源在高频率请求下会返回 403,所以不应因此禁用下载源
(Info.Source.FailCount >= MathClamp(NetTaskThreadLimit, 5, 30) AndAlso DownloadDone < 1) OrElse
Info.Source.FailCount > NetTaskThreadLimit + 2 Then
Dim IsThisFail As Boolean = False
@@ -1403,7 +1402,7 @@ Retry:
'''
Public Sub Abort(CausedByTask As LoaderDownload)
'从特定任务中移除,如果它还属于其他任务,则继续下载
- Tasks.TryTake(CausedByTask)
+ Tasks.Remove(CausedByTask)
If Tasks.Any Then Exit Sub
'确认中断
SyncLock LockState
diff --git a/Plain Craft Launcher 2/Modules/Minecraft/ModDownload.vb b/Plain Craft Launcher 2/Modules/Minecraft/ModDownload.vb
index 50f77a3e..5cbf8e25 100644
--- a/Plain Craft Launcher 2/Modules/Minecraft/ModDownload.vb
+++ b/Plain Craft Launcher 2/Modules/Minecraft/ModDownload.vb
@@ -99,7 +99,7 @@
Task.Output = New List(Of NetFile) From {BackAssetsFile}
'检查是否需要更新:每天只更新一次
If File.Exists(RealAddress) AndAlso Math.Abs((File.GetLastWriteTime(RealAddress).Date - Now.Date).TotalDays) < 1 Then
- Log("[Download] 无需更新资源文件索引")
+ Log("[Download] 无需更新资源文件索引,取消")
Task.Abort()
End If
End Sub))
@@ -1089,7 +1089,7 @@
Dim Urls As New List(Of KeyValuePair(Of String, Integer))
If McimUrl <> Url Then
Select Case Setup.Get("ToolDownloadMod")
- 'UNDONE: 受 #4811 影响
+ 'UNDONE: 在 MCIM 源稳定后回调
Case 0
If ModeDebug Then
Urls.Add(New KeyValuePair(Of String, Integer)(McimUrl, 10))
@@ -1138,7 +1138,7 @@
Dim Urls As New List(Of KeyValuePair(Of String, Integer))
If McimUrl <> Url Then
Select Case Setup.Get("ToolDownloadMod")
- 'UNDONE: 受 #4811 影响
+ 'UNDONE: 在 MCIM 源稳定后回调
Case 0
If ModeDebug Then
Urls.Add(New KeyValuePair(Of String, Integer)(McimUrl, 10))
diff --git a/Plain Craft Launcher 2/Modules/Minecraft/ModLaunch.vb b/Plain Craft Launcher 2/Modules/Minecraft/ModLaunch.vb
index 452816c8..123d56d8 100644
--- a/Plain Craft Launcher 2/Modules/Minecraft/ModLaunch.vb
+++ b/Plain Craft Launcher 2/Modules/Minecraft/ModLaunch.vb
@@ -106,7 +106,7 @@ Public Module ModLaunch
'构造主加载器
Dim Loaders As New List(Of LoaderBase) From {
New LoaderTask(Of Integer, Integer)("获取 Java", AddressOf McLaunchJava) With {.ProgressWeight = 4, .Block = False},
- McLoginLoader,
+ McLoginLoader, '.ProgressWeight = 15, .Block = False
New LoaderCombo(Of String)("补全文件", DlClientFix(McVersionCurrent, False, AssetsIndexExistsBehaviour.DownloadInBackground)) With {.ProgressWeight = 15, .Show = False},
New LoaderTask(Of String, List(Of McLibToken))("获取启动参数", AddressOf McLaunchArgumentMain) With {.ProgressWeight = 2},
New LoaderTask(Of List(Of McLibToken), Integer)("解压文件", AddressOf McLaunchNatives) With {.ProgressWeight = 2},
@@ -529,8 +529,8 @@ Relogin:
OAuthTokens = MsLoginStep1New(Data)
Else
'有 RefreshToken
- OAuthTokens = MsLoginStep1Refresh(Input.OAuthRefreshToken) '要求重新打开登录网页认证
- If OAuthTokens(0) = "Relogin" Then GoTo Relogin
+ OAuthTokens = MsLoginStep1Refresh(Input.OAuthRefreshToken)
+ If OAuthTokens(0) = "Relogin" Then GoTo Relogin '要求重新打开登录网页认证
End If
If Data.IsAborted Then Throw New ThreadInterruptedException
Data.Progress = 0.25
@@ -838,9 +838,10 @@ LoginFinish:
'参考:https://learn.microsoft.com/zh-cn/entra/identity-platform/v2-oauth2-device-code
'初始请求
+Retry:
McLaunchLog("开始微软登录步骤 1/6(原始登录)")
- Dim PrepareJson As JObject = GetJson(NetRequestMulty("https://login.microsoftonline.com/consumers/oauth2/v2.0/devicecode", "POST",
- $"client_id={OAuthClientId}&tenant=/consumers&scope=XboxLive.signin%20offline_access", "application/x-www-form-urlencoded", 2))
+ Dim PrepareJson As JObject = GetJson(NetRequestRetry("https://login.microsoftonline.com/consumers/oauth2/v2.0/devicecode", "POST",
+ $"client_id={OAuthClientId}&tenant=/consumers&scope=XboxLive.signin%20offline_access", "application/x-www-form-urlencoded"))
McLaunchLog("网页登录地址:" & PrepareJson("verification_uri").ToString)
'弹窗
@@ -849,24 +850,31 @@ LoginFinish:
While Converter.Result Is Nothing
Thread.Sleep(100)
End While
- If TypeOf Converter.Result Is Exception Then
+ If TypeOf Converter.Result Is RetryException Then
+ If MyMsgBox($"请在登录时选择 {vbLQ}其他登录方法{vbRQ},然后选择 {vbLQ}使用我的密码{vbRQ}。{vbCrLf}如果没有该选项,请选择 {vbLQ}设置密码{vbRQ},设置完毕后再登录。",
+ "需要使用密码登录", "重新登录", "设置密码", "取消",
+ Button2Action:=Sub() OpenWebsite("https://account.live.com/password/Change")) = 1 Then
+ GoTo Retry
+ Else
+ Throw New Exception("$$")
+ End If
+ ElseIf TypeOf Converter.Result Is Exception Then
Throw CType(Converter.Result, Exception)
Else
Return Converter.Result
End If
End Function
-
'微软登录步骤 1,刷新登录:从 OAuth Code 或 OAuth RefreshToken 获取 {OAuth AccessToken, OAuth RefreshToken}
Private Function MsLoginStep1Refresh(Code As String) As String()
McLaunchLog("开始微软登录步骤 1/6(刷新登录)")
Dim Result As String
Try
- Result = NetRequestMulty("https://login.live.com/oauth20_token.srf", "POST",
+ Result = NetRequestMultiple("https://login.live.com/oauth20_token.srf", "POST",
$"client_id={OAuthClientId}&refresh_token={Uri.EscapeDataString(Code)}&grant_type=refresh_token&scope=XboxLive.signin%20offline_access",
"application/x-www-form-urlencoded", 2)
Catch ex As Exception
- If ex.Message.Contains("must sign in again") OrElse ex.Message.Contains("invalid_grant") Then '#269
+ If ex.Message.Contains("must sign in again") OrElse (ex.Message.Contains("refresh_token") AndAlso ex.Message.Contains("is not valid")) Then '#269
Return {"Relogin", ""}
Else
Throw
@@ -878,7 +886,6 @@ LoginFinish:
Dim RefreshToken As String = ResultJson("refresh_token").ToString
Return {AccessToken, RefreshToken}
End Function
-
'微软登录步骤 2:从 OAuth AccessToken 获取 XBLToken
Private Function MsLoginStep2(AccessToken As String) As String
McLaunchLog("开始微软登录步骤 2/6")
@@ -891,8 +898,8 @@ LoginFinish:
},
""RelyingParty"": ""http://auth.xboxlive.com"",
""TokenType"": ""JWT""
- }" 'TODO: 新版登录改为 ""RpsTicket"": ""d=" & AccessToken & """
- Dim Result As String = NetRequestMulty("https://user.auth.xboxlive.com/user/authenticate", "POST", Request, "application/json", 3)
+ }"
+ Dim Result As String = NetRequestMultiple("https://user.auth.xboxlive.com/user/authenticate", "POST", Request, "application/json", 3)
Dim ResultJson As JObject = GetJson(Result)
Dim XBLToken As String = ResultJson("Token").ToString
@@ -914,7 +921,7 @@ LoginFinish:
}"
Dim Result As String
Try
- Result = NetRequestMulty("https://xsts.auth.xboxlive.com/xsts/authorize", "POST", Request, "application/json", 3)
+ Result = NetRequestMultiple("https://xsts.auth.xboxlive.com/xsts/authorize", "POST", Request, "application/json", 3)
Catch ex As Net.WebException
'参考 https://github.com/PrismarineJS/prismarine-auth/blob/master/src/common/Constants.js
If ex.Message.Contains("2148916227") Then
@@ -957,7 +964,7 @@ LoginFinish:
Dim Request As String = New JObject(New JProperty("identityToken", $"XBL3.0 x={Tokens(1)};{Tokens(0)}")).ToString(0)
Dim Result As String
Try
- Result = NetRequestMulty("https://api.minecraftservices.com/authentication/login_with_xbox", "POST", Request, "application/json", 2)
+ Result = NetRequestRetry("https://api.minecraftservices.com/authentication/login_with_xbox", "POST", Request, "application/json")
Catch ex As Net.WebException
Dim Message As String = GetExceptionSummary(ex)
If Message.Contains("(429)") Then
@@ -979,7 +986,7 @@ LoginFinish:
Private Sub MsLoginStep5(AccessToken As String)
McLaunchLog("开始微软登录步骤 5/6")
- Dim Result As String = NetRequestMulty("https://api.minecraftservices.com/entitlements/mcstore", "GET", "", "application/json", 2, New Dictionary(Of String, String) From {{"Authorization", "Bearer " & AccessToken}})
+ Dim Result As String = NetRequestMultiple("https://api.minecraftservices.com/entitlements/mcstore", "GET", "", "application/json", 2, New Dictionary(Of String, String) From {{"Authorization", "Bearer " & AccessToken}})
Try
Dim ResultJson As JObject = GetJson(Result)
If Not (ResultJson.ContainsKey("items") AndAlso ResultJson("items").Any) Then
@@ -1000,7 +1007,7 @@ LoginFinish:
Dim Result As String
Try
- Result = NetRequestMulty("https://api.minecraftservices.com/minecraft/profile", "GET", "", "application/json", 2, New Dictionary(Of String, String) From {{"Authorization", "Bearer " & AccessToken}})
+ Result = NetRequestMultiple("https://api.minecraftservices.com/minecraft/profile", "GET", "", "application/json", 2, New Dictionary(Of String, String) From {{"Authorization", "Bearer " & AccessToken}})
Catch ex As Net.WebException
Dim Message As String = GetExceptionSummary(ex)
If Message.Contains("(429)") Then
@@ -1255,7 +1262,7 @@ LoginFinish:
''' 释放 Java Wrapper 并返回完整文件路径。
'''
Public Function ExtractJavaWrapper() As String
- Dim BaseDir As String = GetJavaWrapperDir()
+ Dim BaseDir As String = GetPureASCIIDir()
Dim WrapperPath As String = BaseDir & "\JavaWrapper.jar"
Log("[Java] 选定的 Java Wrapper 路径:" & WrapperPath)
SyncLock ExtractJavaWrapperLock '避免 OptiFine 和 Forge 安装时同时释放 Java Wrapper 导致冲突
@@ -1287,9 +1294,10 @@ LoginFinish:
Private ExtractJavaWrapperLock As New Object
'''
- ''' 获取 Java Wrapper 所在的文件夹,不以 \ 结尾。
+ ''' 获取一个可用于临时存放文件的,不含任何特殊字符的文件夹路径。
+ ''' 返回值不以 \ 结尾。
'''
- Public Function GetJavaWrapperDir() As String
+ Public Function GetPureASCIIDir() As String
If (Path & "PCL").IsASCII() Then
Return Path & "PCL"
ElseIf PathAppdata.IsASCII() Then
@@ -1410,7 +1418,7 @@ LoginFinish:
'添加 Java Wrapper 作为主 Jar
If McLaunchJavaSelected.VersionCode >= 9 Then DataList.Add("--add-exports cpw.mods.bootstraplauncher/cpw.mods.bootstraplauncher=ALL-UNNAMED")
- DataList.Add("-Doolloo.jlw.tmpdir=""" & GetJavaWrapperDir() & """")
+ DataList.Add("-Doolloo.jlw.tmpdir=""" & GetPureASCIIDir() & """")
DataList.Add("-jar """ & ExtractJavaWrapper() & """")
'添加 MainClass
@@ -1477,7 +1485,7 @@ NextVersion:
'添加 Java Wrapper 作为主 Jar
If McLaunchJavaSelected.VersionCode >= 9 Then DataList.Add("--add-exports cpw.mods.bootstraplauncher/cpw.mods.bootstraplauncher=ALL-UNNAMED")
- DataList.Add("-Doolloo.jlw.tmpdir=""" & GetJavaWrapperDir() & """")
+ DataList.Add("-Doolloo.jlw.tmpdir=""" & GetPureASCIIDir() & """")
DataList.Add("-jar """ & ExtractJavaWrapper() & """")
'将 "-XXX" 与后面 "XXX" 合并到一起
diff --git a/Plain Craft Launcher 2/Modules/Minecraft/MyLocalModItem.xaml.vb b/Plain Craft Launcher 2/Modules/Minecraft/MyLocalModItem.xaml.vb
index 59720a6f..316d5e3f 100644
--- a/Plain Craft Launcher 2/Modules/Minecraft/MyLocalModItem.xaml.vb
+++ b/Plain Craft Launcher 2/Modules/Minecraft/MyLocalModItem.xaml.vb
@@ -539,7 +539,7 @@ RetryStart:
'压缩 Subtitle
ColumnSubtitle.Width = New GridLength(1, GridUnitType.Star)
ColumnExtend.Width = New GridLength(0, GridUnitType.Pixel)
- ElseIf Not ColumnExtend.Width.IsStar AndAlso ColumnSubtitle.ActualWidth > LabSubtitle.ActualWidth + 10 Then
+ ElseIf Not ColumnExtend.Width.IsStar AndAlso Not LabSubtitle.IsTextTrimmed Then
'向右展开 Subtitle
ColumnSubtitle.Width = GridLength.Auto
ColumnExtend.Width = New GridLength(1, GridUnitType.Star)
diff --git a/Plain Craft Launcher 2/Modules/ModMusic.vb b/Plain Craft Launcher 2/Modules/ModMusic.vb
index cc1ace63..52a87a85 100644
--- a/Plain Craft Launcher 2/Modules/ModMusic.vb
+++ b/Plain Craft Launcher 2/Modules/ModMusic.vb
@@ -280,7 +280,7 @@
'当前音乐已播放结束,继续下一曲
If CurrentWave.PlaybackState = NAudio.Wave.PlaybackState.Stopped AndAlso MusicAllList.Any Then MusicStartPlay(DequeueNextMusicAddress)
Catch ex As Exception
- Log("[Music] 播放音乐失败的文件完整路径:" & MusicCurrent)
+ Log(ex, "播放音乐出现内部错误(" & MusicCurrent & ")", LogLevel.Developer)
If TypeOf ex Is NAudio.MmException AndAlso (ex.Message.Contains("NoDriver") OrElse ex.Message.Contains("BadDeviceId")) Then
Hint("由于音频设备变更,音乐播放功能在重启 PCL 后才能恢复!", HintType.Critical)
Thread.Sleep(1000000000)
diff --git a/Plain Craft Launcher 2/My Project/AssemblyInfo.vb b/Plain Craft Launcher 2/My Project/AssemblyInfo.vb
index 58f2f1b5..59171f6c 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/ModDownloadLib.vb b/Plain Craft Launcher 2/Pages/PageDownload/ModDownloadLib.vb
index e048a69d..2f6019fa 100644
--- a/Plain Craft Launcher 2/Pages/PageDownload/ModDownloadLib.vb
+++ b/Plain Craft Launcher 2/Pages/PageDownload/ModDownloadLib.vb
@@ -359,7 +359,7 @@ Public Module ModDownloadLib
'添加 Java Wrapper 作为主 Jar
Dim Arguments As String
If UseJavaWrapper Then
- Arguments = $"-Doolloo.jlw.tmpdir=""{GetJavaWrapperDir()}"" -Duser.home=""{BaseMcFolderHome}"" -cp ""{Target}"" -jar ""{ExtractJavaWrapper()}"" optifine.Installer"
+ Arguments = $"-Doolloo.jlw.tmpdir=""{GetPureASCIIDir()}"" -Duser.home=""{BaseMcFolderHome}"" -cp ""{Target}"" -jar ""{ExtractJavaWrapper()}"" optifine.Installer"
Else
Arguments = $"-Duser.home=""{BaseMcFolderHome}"" -cp ""{Target}"" optifine.Installer"
End If
@@ -1026,7 +1026,7 @@ Retry:
'添加 Java Wrapper 作为主 Jar
Dim Arguments As String
If UseJavaWrapper Then
- Arguments = $"-Doolloo.jlw.tmpdir=""{GetJavaWrapperDir()}"" -cp ""{PathTemp}Cache\forge_installer.jar;{Target}"" -jar ""{ExtractJavaWrapper()}"" com.bangbang93.ForgeInstaller ""{McFolder}"
+ Arguments = $"-Doolloo.jlw.tmpdir=""{GetPureASCIIDir()}"" -cp ""{PathTemp}Cache\forge_installer.jar;{Target}"" -jar ""{ExtractJavaWrapper()}"" com.bangbang93.ForgeInstaller ""{McFolder}"
Else
Arguments = $"-cp ""{PathTemp}Cache\forge_installer.jar;{Target}"" com.bangbang93.ForgeInstaller ""{McFolder}"
End If
diff --git a/Plain Craft Launcher 2/Pages/PageLaunch/FormLoginOAuth.xaml b/Plain Craft Launcher 2/Pages/PageLaunch/FormLoginOAuth.xaml
deleted file mode 100644
index 10e9c84e..00000000
--- a/Plain Craft Launcher 2/Pages/PageLaunch/FormLoginOAuth.xaml
+++ /dev/null
@@ -1,28 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/Plain Craft Launcher 2/Pages/PageLaunch/FormLoginOAuth.xaml.vb b/Plain Craft Launcher 2/Pages/PageLaunch/FormLoginOAuth.xaml.vb
deleted file mode 100644
index 35cd8479..00000000
--- a/Plain Craft Launcher 2/Pages/PageLaunch/FormLoginOAuth.xaml.vb
+++ /dev/null
@@ -1,100 +0,0 @@
-Imports System.Windows.Navigation
-
-Public Class FormLoginOAuth
-
- Public Event OnLoginSuccess(code As String)
- Public Event OnLoginCanceled(IsSwitch As Boolean)
-
- '跳转事件
- Private IsLoginSuccessed As Boolean = False
- Private IsSwitch As Boolean = False
- Private Sub Browser_Navigating(sender As WebBrowser, e As NavigatingCancelEventArgs) Handles Browser1.Navigating, Browser2.Navigating, Browser3.Navigating
- Dim Url As String = e.Uri.AbsoluteUri
- If ModeDebug Then Log("[Login] 登录浏览器 " & sender.Tag & " 导向:" & Url)
- If Url.Contains("code=") Then
- Dim Code As String = RegexSeek(Url, "(?<=code\=)[^&]+")
- Log("[Login] 抓取到 OAuth 返回码:" & Code)
- IsLoginSuccessed = True
- RaiseEvent OnLoginSuccess(Code)
- ElseIf Url.Contains("github.") Then
- Hint("PCL 不支持使用 GitHub 登录微软账号!", HintType.Critical)
- Close()
- End If
- End Sub
-
- '已导航事件
- Private IsFirstLoaded As Boolean = False
- Private IsFirstLoadedLock As New Object
- Private Sub Browser_Navigated(sender As WebBrowser, e As NavigationEventArgs) Handles Browser1.Navigated, Browser2.Navigated, Browser3.Navigated
- SyncLock IsFirstLoadedLock
- If IsFirstLoaded Then Exit Sub
- IsFirstLoaded = True
- End SyncLock
- RunInThread(Sub()
- Thread.Sleep(1000)
- RunInUi(Sub()
- sender.Visibility = Visibility.Visible
- PanLoading.Visibility = Visibility.Collapsed
- Log("[Login] 已将登录窗口切换至浏览器")
- End Sub)
- End Sub)
- End Sub
-
- '窗体的进出事件
- Public Shared LoginUrl1 As String = "https://login.microsoftonline.com/consumers/oauth2/v2.0/authorize?prompt=login&client_id=00000000402b5328&response_type=code&scope=service%3A%3Auser.auth.xboxlive.com%3A%3AMBI_SSL&redirect_uri=https:%2F%2Flogin.live.com%2Foauth20_desktop.srf"
- Public Shared LoginUrl2 As String = "https://login.live.com/oauth20_authorize.srf?prompt=login&client_id=00000000402b5328&response_type=code&scope=service%3A%3Auser.auth.xboxlive.com%3A%3AMBI_SSL&redirect_uri=https:%2F%2Flogin.live.com%2Foauth20_desktop.srf"
- Private Sub FrmLoginOAuth_Loaded(sender As Object, e As RoutedEventArgs) Handles Me.Loaded
- Browser1.Navigate(LoginUrl1)
- RunInThread(Sub()
- '估计是由于时间戳原因,同时导航会导致误报密码失败
- Thread.Sleep(2500)
- RunInUi(Sub()
- Try '防止在 Dispose 之后调用
- If Not IsFirstLoaded Then Browser2.Navigate(LoginUrl1)
- Catch
- End Try
- End Sub)
- Thread.Sleep(2500)
- RunInUi(Sub()
- Try
- If Not IsFirstLoaded Then Browser3.Navigate(LoginUrl2)
- Catch
- End Try
- End Sub)
- End Sub)
- End Sub
- Private Sub FormLoginOAuth_Closed() Handles Me.Closed
- RunInThread(Sub()
- Thread.Sleep(1000) '释放会卡一下,所以稍等一下……
- RunInUiWait(Sub()
- Try
- Browser1.Dispose()
- Catch ex As Exception
- Log(ex, "释放微软登录浏览器 1 失败")
- End Try
- End Sub)
- Thread.Sleep(200)
- RunInUiWait(Sub()
- Try
- Browser2.Dispose()
- Catch ex As Exception
- Log(ex, "释放微软登录浏览器 2 失败")
- End Try
- End Sub)
- Thread.Sleep(200)
- RunInUiWait(Sub()
- Try
- Browser3.Dispose()
- Catch ex As Exception
- Log(ex, "释放微软登录浏览器 3 失败")
- End Try
- End Sub)
- End Sub)
- If Not IsLoginSuccessed Then RaiseEvent OnLoginCanceled(IsSwitch)
- FrmMain.Focus()
- End Sub
- Private Sub HintSwitch_Click() Handles HintSwitch.Click
- IsSwitch = True
- Close()
- End Sub
-End Class
diff --git a/Plain Craft Launcher 2/Pages/PageLaunch/MyMsgLogin.xaml.vb b/Plain Craft Launcher 2/Pages/PageLaunch/MyMsgLogin.xaml.vb
index b1f280a8..8fd9c7e6 100644
--- a/Plain Craft Launcher 2/Pages/PageLaunch/MyMsgLogin.xaml.vb
+++ b/Plain Craft Launcher 2/Pages/PageLaunch/MyMsgLogin.xaml.vb
@@ -56,6 +56,9 @@
}, "MyMsgBox " & Uuid)
End Sub
+ '实现回车和 Esc 的接口(#4857)
+ Public Sub Btn1_Click() Handles Btn1.Click
+ End Sub
Public Sub Btn3_Click() Handles Btn3.Click
Finished(New ThreadInterruptedException)
End Sub
@@ -93,7 +96,7 @@
End Sub
Private Sub WorkThread()
- Thread.Sleep(4000)
+ Thread.Sleep(3000)
If MyConverter.IsExited Then Exit Sub
OpenWebsite(Website)
ClipboardSet(UserCode)
@@ -122,12 +125,15 @@
ElseIf ex.Message.Contains("expired_token") Then
Finished(New Exception("$登录用时太长啦,重新试试吧!"))
Return
+ ElseIf ex.Message.Contains("AADSTS70000") Then '可能不能判 “invalid_grant”,见 #269
+ Finished(New RetryException)
+ Return
ElseIf ex.Message.Contains("authorization_pending") Then
- Thread.Sleep(1000)
+ Thread.Sleep(2000)
ElseIf UnknownFailureCount <= 2 Then
UnknownFailureCount += 1
Log(ex, $"登录轮询第 {UnknownFailureCount} 次失败")
- Thread.Sleep(1000)
+ Thread.Sleep(2000)
Else
Finished(New Exception("登录轮询失败", ex))
Return
diff --git a/Plain Craft Launcher 2/Pages/PageLaunch/PageLaunchRight.xaml.vb b/Plain Craft Launcher 2/Pages/PageLaunch/PageLaunchRight.xaml.vb
index 4e765b5e..5cad11cb 100644
--- a/Plain Craft Launcher 2/Pages/PageLaunch/PageLaunchRight.xaml.vb
+++ b/Plain Craft Launcher 2/Pages/PageLaunch/PageLaunchRight.xaml.vb
@@ -110,6 +110,10 @@ Download:
Log("[Page] 主页预设:主页市场")
Url = "https://homepage-market.pages.dev/Custom.xaml"
GoTo Download
+ Case 8
+ Log("[Page] 主页预设:更新日志")
+ Url = "https://updatehomepage.pages.dev/UpdateHomepage.xaml"
+ GoTo Download
End Select
End Select
RunInUi(Sub() LoadContent(Content))
@@ -136,7 +140,7 @@ Download:
Dim NeedDownload As Boolean = True
Try
Version = NetGetCodeByRequestOnce(VersionAddress, Timeout:=10000)
- If Version.Length > 100 Then Throw New Exception($"获取的自定义主页版本过长({Version.Length} 字符)")
+ If Version.Length > 1000 Then Throw New Exception($"获取的自定义主页版本过长({Version.Length} 字符)")
Dim CurrentVersion As String = Setup.Get("CacheSavedPageVersion")
If Version <> "" AndAlso CurrentVersion <> "" AndAlso Version = CurrentVersion Then
Log($"[Page] 当前缓存的自定义主页已为最新,当前版本:{Version},检查源:{VersionAddress}")
diff --git a/Plain Craft Launcher 2/Pages/PageOther/PageOtherAbout.xaml b/Plain Craft Launcher 2/Pages/PageOther/PageOtherAbout.xaml
index 389328d4..951a5dc3 100644
--- a/Plain Craft Launcher 2/Pages/PageOther/PageOtherAbout.xaml
+++ b/Plain Craft Launcher 2/Pages/PageOther/PageOtherAbout.xaml
@@ -104,82 +104,108 @@
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -266,18 +292,18 @@
-
-
-
-
-
-
-
+
+
-
+
+
+
+
diff --git a/Plain Craft Launcher 2/Pages/PageSetup/PageSetupUI.xaml b/Plain Craft Launcher 2/Pages/PageSetup/PageSetupUI.xaml
index 9f289c3c..aeb3ae4e 100644
--- a/Plain Craft Launcher 2/Pages/PageSetup/PageSetupUI.xaml
+++ b/Plain Craft Launcher 2/Pages/PageSetup/PageSetupUI.xaml
@@ -244,6 +244,7 @@
+
diff --git a/Plain Craft Launcher 2/Pages/PageVersion/PageVersionMod.xaml.vb b/Plain Craft Launcher 2/Pages/PageVersion/PageVersionMod.xaml.vb
index a722e08d..372b6a7a 100644
--- a/Plain Craft Launcher 2/Pages/PageVersion/PageVersionMod.xaml.vb
+++ b/Plain Craft Launcher 2/Pages/PageVersion/PageVersionMod.xaml.vb
@@ -470,6 +470,11 @@
Dim IndexOfLoader As Integer = McModLoader.Output.IndexOf(ModEntity)
McModLoader.Output.RemoveAt(IndexOfLoader)
McModLoader.Output.Insert(IndexOfLoader, NewModEntity)
+ If SearchResult IsNot Nothing Then
+ Dim IndexOfResult As Integer = SearchResult.IndexOf(ModEntity)
+ SearchResult.Remove(ModEntity)
+ SearchResult.Insert(IndexOfResult, NewModEntity)
+ End If
'更改 UI 中的列表
Dim NewItem As MyLocalModItem = McModListItem(NewModEntity)
ModItems(ModEntity.RawFileName) = NewItem
@@ -574,7 +579,14 @@
'结果提示
Select Case Loader.State
Case LoadState.Finished
- Hint(If(FinishedFileNames.Count > 1, $"已成功更新 {FinishedFileNames.Count} 个 Mod!", $"已成功更新:{FinishedFileNames.Single}"), HintType.Finish)
+ Select Case FinishedFileNames.Count
+ Case 0 '一般是由于 Mod 文件被占用,然后玩家主动取消
+ Log($"[Mod] 没有 Mod 被成功更新")
+ Case 1
+ Hint($"已成功更新 {FinishedFileNames.Single}!", HintType.Finish)
+ Case Else
+ Hint($"已成功更新 {FinishedFileNames.Count} 个 Mod!", HintType.Finish)
+ End Select
Case LoadState.Failed
Hint("Mod 更新失败:" & GetExceptionSummary(Loader.Error), HintType.Critical)
Case LoadState.Aborted
diff --git a/Plain Craft Launcher 2/Plain Craft Launcher 2.vbproj b/Plain Craft Launcher 2/Plain Craft Launcher 2.vbproj
index cd678c40..9c81af07 100644
--- a/Plain Craft Launcher 2/Plain Craft Launcher 2.vbproj
+++ b/Plain Craft Launcher 2/Plain Craft Launcher 2.vbproj
@@ -256,9 +256,6 @@
PageDownloadPack.xaml
-
- FormLoginOAuth.xaml
-
MyMsgLogin.xaml
@@ -514,10 +511,6 @@
Designer
MSBuild:Compile
-
- Designer
- MSBuild:Compile
-
MSBuild:Compile
Designer
diff --git a/Plain Craft Launcher 2/Resources/Help.zip b/Plain Craft Launcher 2/Resources/Help.zip
index a49d41f9..8db1d47a 100644
Binary files a/Plain Craft Launcher 2/Resources/Help.zip and b/Plain Craft Launcher 2/Resources/Help.zip differ
diff --git "a/\346\234\200\346\226\260\346\255\243\345\274\217\347\211\210.zip" "b/\346\234\200\346\226\260\346\255\243\345\274\217\347\211\210.zip"
index 144de9a9..0e58940f 100644
Binary files "a/\346\234\200\346\226\260\346\255\243\345\274\217\347\211\210.zip" and "b/\346\234\200\346\226\260\346\255\243\345\274\217\347\211\210.zip" differ