龙腾猫跃 преди 2 години
родител
ревизия
76bf3c40d0

+ 2 - 2
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

+ 19 - 1
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()

+ 19 - 4
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 "系统"
 
+    ''' <summary>
+    ''' 指示接取到这个异常的函数进行重试。
+    ''' </summary>
+    Public Class RetryException
+        Inherits Exception
+    End Class
+
     ''' <summary>
     ''' 当前程序是否拥有管理员权限。
     ''' </summary>
@@ -2430,6 +2437,14 @@ Retry:
         Return rect.Contains(bounds.TopLeft) OrElse rect.Contains(bounds.BottomRight)
     End Function
 
+    ''' <summary>
+    ''' 控件是否受到 TextTrimming 属性影响,导致内容被截取。
+    ''' </summary>
+    <Extension> 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"

+ 22 - 21
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
 
         ''' <summary>
@@ -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

+ 5 - 6
Plain Craft Launcher 2/Modules/Base/ModNet.vb

@@ -140,7 +140,7 @@ Retry:
     ''' </summary>
     ''' <param name="Url">网页的 Url。</param>
     ''' <param name="Encode">网页的编码,通常为 UTF-8。</param>
-    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:
     ''' <summary>
     ''' 同时发送多个网络请求并要求返回内容。
     ''' </summary>
-    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:
         ''' <summary>
         ''' 所属的文件列表任务。
         ''' </summary>
-        Public Tasks As New Concurrent.ConcurrentBag(Of LoaderDownload)
-
+        Public Tasks As New SynchronizedCollection(Of LoaderDownload)
         ''' <summary>
         ''' 所有下载源。
         ''' </summary>
@@ -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:
         ''' </summary>
         Public Sub Abort(CausedByTask As LoaderDownload)
             '从特定任务中移除,如果它还属于其他任务,则继续下载
-            Tasks.TryTake(CausedByTask)
+            Tasks.Remove(CausedByTask)
             If Tasks.Any Then Exit Sub
             '确认中断
             SyncLock LockState

+ 3 - 3
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))

+ 29 - 21
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 并返回完整文件路径。
     ''' </summary>
     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
 
     ''' <summary>
-    ''' 获取 Java Wrapper 所在的文件夹,不以 \ 结尾。
+    ''' 获取一个可用于临时存放文件的,不含任何特殊字符的文件夹路径。
+    ''' 返回值不以 \ 结尾。
     ''' </summary>
-    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" 合并到一起

+ 1 - 1
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)

+ 1 - 1
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)

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

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

+ 2 - 2
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

+ 0 - 28
Plain Craft Launcher 2/Pages/PageLaunch/FormLoginOAuth.xaml

@@ -1,28 +0,0 @@
-<Window x:Class="FormLoginOAuth"
-        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
-        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
-        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
-        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
-        xmlns:local="clr-namespace:PCL"
-        mc:Ignorable="d"
-        Height="720" Width="580" MinHeight="720" MinWidth="580" ResizeMode="CanResize" WindowStartupLocation="CenterScreen" Title="Microsoft 账户登录">
-    <Grid>
-        <Grid.Background>
-            <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
-                <GradientStop Color="White" Offset="0"/>
-                <GradientStop Color="{DynamicResource ColorObject8}" Offset="1"/>
-            </LinearGradientBrush>
-        </Grid.Background>
-        <StackPanel x:Name="PanLoading" Orientation="Vertical" VerticalAlignment="Center" HorizontalAlignment="Center">
-            <local:MyLoading x:Name="Loading" Text="正在加载登录页面" HorizontalAlignment="Center" />
-            <TextBlock Text="如果网络环境不佳,加载可能非常缓慢甚至一直加载不出来" Margin="0,25,0,0"
-                       HorizontalAlignment="Center" Foreground="{DynamicResource ColorBrush1}" Opacity="0.7" />
-            <TextBlock Text="此时请尝试使用 VPN 或加速器,然后重试"
-                       HorizontalAlignment="Center" Foreground="{DynamicResource ColorBrush1}" Opacity="0.7" />
-        </StackPanel>
-        <WebBrowser x:Name="Browser1" Visibility="Collapsed" Tag="1" Margin="0,0,0,25" />
-        <WebBrowser x:Name="Browser2" Visibility="Collapsed" Tag="2" Margin="0,0,0,25" />
-        <WebBrowser x:Name="Browser3" Visibility="Collapsed" Tag="3" Margin="0,0,0,25" />
-        <local:MyTextButton Text="如果遇到问题,可以点击这里使用系统浏览器登录" HorizontalAlignment="Center" VerticalAlignment="Bottom" Margin="0,0,0,5" x:Name="HintSwitch" />
-    </Grid>
-</Window>

+ 0 - 100
Plain Craft Launcher 2/Pages/PageLaunch/FormLoginOAuth.xaml.vb

@@ -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

+ 9 - 3
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

+ 5 - 1
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}")

+ 109 - 83
Plain Craft Launcher 2/Pages/PageOther/PageOtherAbout.xaml

@@ -104,82 +104,108 @@
             </local:MyCard>
             <local:MyCard Margin="0,0,0,15" Title="赞助者">
                 <StackPanel Margin="25,40,10,20">
-                    <TextBlock HorizontalAlignment="Left" Text="以下是 2024 年 8 月的高级赞助者们!感谢各位对 PCL 和伟大的咕咕咕事业的支持!" Margin="0,0,25,5.5" TextTrimming="None" TextWrapping="WrapWithOverflow" />
+                    <TextBlock HorizontalAlignment="Left" Text="以下是 2024 年 9 月的高级赞助者们!感谢各位对 PCL 和伟大的咕咕咕事业的支持!" Margin="0,0,25,5.5" TextTrimming="None" TextWrapping="WrapWithOverflow" />
                     <WrapPanel Margin="0,0,0,10">
-                        <TextBlock Width="120" Margin="0,1.5" Text="没用的元元" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="鸮不是号鸟" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="兮兮要次糖糖" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="wxzsghh114514" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="地了排子" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="阿宅cheli" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="笑脸114514" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="小麦A" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="未名小七TAO" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="雪冥" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="氟西汀" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="阿巴阿巴" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="侦探hj" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="666" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="萬帆WanFan" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="swayst" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="yuchen" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="鲸落猫南北" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="念池鱼思故渊" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="No_1died" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="Error02" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="橙子皮" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="丨丨丨丨" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="零崽" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="叁無" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="火星上行走的柠檬精" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="北极椰子" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="流玉髓" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="咕咕" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="小鹏1098" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="风雪" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="梦幻の小店" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="nhrnick" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="天天的周末" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="雪梨" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="Z_ebra" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="acmzyh" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="yuyyyu" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="看看" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="墨霜夜" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="皇势力" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="曦予千山" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="Lv50.疾旋鼬" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="雪暮" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="铁树" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="ZHypocrite" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="花卉" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="hmmmfffll" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="夕阳下的余光" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="扶风°" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="唠叨的土豆" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="ulifx" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="DXX" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="小曲" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="0飞霜墨染0" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="Aminos1337" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="死亡旋风大魔王" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="风见翎" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="水阔鱼" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="无名氏" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="绘梨衣のGodzilla" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="521HERTZ" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="momotsuki" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="浩东流" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="破片南瓜" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="playalone" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="木丶九九" />
                         <TextBlock Width="120" Margin="0,1.5" Text="闫雁" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="不知道叫啥" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="隔壁家老张" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="DZY" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="Hugh" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="Jto" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="JO极名字" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="啊猫" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="章九连" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="zeq_killjsj" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="重庆你周哥" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="我是桶子哥" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="chenxingyin" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="koimiaori" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="Awfrlu+" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="古河渚上花" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="THE END" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="哎呀菜菜子" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="AptS:1547" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="安麓" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="彘彘彘彘彘彘" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="通大小学弟" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="Ender__sun" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="此生浮" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="皮皮恒" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="charlesmin" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="snow" />
-
+                        <TextBlock Width="120" Margin="0,1.5" Text="雨季丶看花落丬" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="greenClemente" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="nfd" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="求阙" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="苏苏" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="冰魄凝华Iris" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="TNT" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="jokeresin" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="冻冻莓" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="木吉" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="寰辰" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="大智" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="晚吟" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="e_2" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="墨辞" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="CongYiXu1259" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="绀香十九" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="花十一" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="摸摸鱼" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="不想起名" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="Corazon" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="断幕" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="wuying" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="隐”" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="华子" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="Hikari" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="小辉joyb_" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="bluck" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="风人过" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="锦锋" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="初辟鸿蒙" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="YLF零度" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="ADB114514" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="晓乐" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="Raze" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="jj" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="社÷老登" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="仝圮" />
+                        <TextBlock Width="240" Margin="0,1.5" Text="FSL Launcher - 小黄菌" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="华燃王小灭" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="Charlotte_Caius" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="木了丰" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="-夜-光-" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="蓝色骷髅" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="易游" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="祈绫参_UPE" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="卖梦的人" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="rking" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="柠果籽" />
+                        <TextBlock Width="240" Margin="0,1.5" Text="真我 · 人之律者爱莉希雅" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="KevinREL" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="LEIBI" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="GNFDF" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="朱重八" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="TONYAF" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="Reshiram???" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="克罗44" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="社恐的波奇酱" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="Xylophone233" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="陌上如玉" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="lili66" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="小派呀" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="日想" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="墨处择" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="刘畅" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="做好事不留名的好心人" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="好将军" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="为生活而拼搏" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="韬光养晦" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="知芍" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="awa" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="CaTy" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="zhifeiwen" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="磁爆步兵" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="双开门冰箱AK15" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="泠羽" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="lupeihao" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="木子" />
                     </WrapPanel>
                     <Grid Height="35">
                         <Grid.ColumnDefinitions>
@@ -266,18 +292,18 @@
                     <local:MyButton Grid.Row="9" Grid.Column="3" MinWidth="140" Text="查看许可文档" Padding="13,0" Margin="0,7,20,18" HorizontalAlignment="Left"
                                     EventType="打开网页" EventData="https://iconmonstr.com/license/" />
                     
-                    <TextBlock Grid.Row="10" Grid.Column="0" Text="Iconfont" TextWrapping="Wrap" FontWeight="Bold" />
-                    <TextBlock Grid.Row="10" Grid.Column="2" Grid.ColumnSpan="2" Text="Copyright © ALIMAMA MUX, powered by alimama THX." TextWrapping="Wrap" />
-                    <local:MyButton Grid.Row="11" Grid.Column="2" MinWidth="140" Text="查看原网站" Padding="13,0" Margin="0,7,20,18" HorizontalAlignment="Left"
-                                    EventType="打开网页" EventData="https://www.iconfont.cn/" />
-
-                    <TextBlock Grid.Row="12" Grid.Column="0" Text="libwebp wrapper for .NET" TextWrapping="Wrap" FontWeight="Bold" />
-                    <TextBlock Grid.Row="12" Grid.Column="2" Grid.ColumnSpan="2" Text="Copyright © 2012 Imazen&#xa;Licensed under the MIT License." TextWrapping="Wrap" />
-                    <local:MyButton Grid.Row="13" Grid.Column="2" MinWidth="140" Text="查看来源网站" Padding="13,0" Margin="0,7,20,18" HorizontalAlignment="Left"
+                    <TextBlock Grid.Row="10" Grid.Column="0" Text="libwebp wrapper for .NET" TextWrapping="Wrap" FontWeight="Bold" />
+                    <TextBlock Grid.Row="10" Grid.Column="2" Grid.ColumnSpan="2" Text="Copyright © 2012 Imazen&#xa;Licensed under the MIT License." TextWrapping="Wrap" />
+                    <local:MyButton Grid.Row="11" Grid.Column="2" MinWidth="140" Text="查看来源网站" Padding="13,0" Margin="0,7,20,18" HorizontalAlignment="Left"
                                     EventType="打开网页" EventData="https://github.com/imazen/libwebp-net" />
-                    <local:MyButton Grid.Row="13" Grid.Column="3" MinWidth="140" Text="查看许可文档" Padding="13,0" Margin="0,7,20,18" HorizontalAlignment="Left"
+                    <local:MyButton Grid.Row="11" Grid.Column="3" MinWidth="140" Text="查看许可文档" Padding="13,0" Margin="0,7,20,18" HorizontalAlignment="Left"
                                     EventType="打开网页" EventData="https://github.com/imazen/libwebp-net/blob/master/LICENSE.txt" />
 
+                    <TextBlock Grid.Row="12" Grid.Column="0" Text="Iconfont" TextWrapping="Wrap" FontWeight="Bold" />
+                    <TextBlock Grid.Row="12" Grid.Column="2" Grid.ColumnSpan="2" Text="Copyright © ALIMAMA MUX, powered by alimama THX." TextWrapping="Wrap" />
+                    <local:MyButton Grid.Row="13" Grid.Column="2" MinWidth="140" Text="查看原网站" Padding="13,0" Margin="0,7,20,18" HorizontalAlignment="Left"
+                                    EventType="打开网页" EventData="https://www.iconfont.cn/" />
+
                 </Grid>
             </local:MyCard>
         </StackPanel>

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

@@ -244,6 +244,7 @@
                             <local:MyComboBoxItem Content="Minecraft 皮肤推荐(作者:wkea)" />
                             <local:MyComboBoxItem Content="OpenBMCLAPI 仪表盘 Lite(作者:Silverteal、Mxmilu666)" />
                             <local:MyComboBoxItem Content="PCL 主页市场(作者:凌云)" />
+                            <local:MyComboBoxItem Content="PCL 更新日志(作者:Joker2184)" />
                         </local:MyComboBox>
                     </Grid>
                 </StackPanel>

+ 13 - 1
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

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

@@ -256,9 +256,6 @@
     <Compile Include="Pages\PageDownload\PageDownloadPack.xaml.vb">
       <DependentUpon>PageDownloadPack.xaml</DependentUpon>
     </Compile>
-    <Compile Include="Pages\PageLaunch\FormLoginOAuth.xaml.vb">
-      <DependentUpon>FormLoginOAuth.xaml</DependentUpon>
-    </Compile>
     <Compile Include="Pages\PageLaunch\MyMsgLogin.xaml.vb">
       <DependentUpon>MyMsgLogin.xaml</DependentUpon>
     </Compile>
@@ -514,10 +511,6 @@
       <SubType>Designer</SubType>
       <Generator>MSBuild:Compile</Generator>
     </Page>
-    <Page Include="Pages\PageLaunch\FormLoginOAuth.xaml">
-      <SubType>Designer</SubType>
-      <Generator>MSBuild:Compile</Generator>
-    </Page>
     <Page Include="Pages\PageLaunch\MyMsgLogin.xaml">
       <Generator>MSBuild:Compile</Generator>
       <SubType>Designer</SubType>

BIN
Plain Craft Launcher 2/Resources/Help.zip


BIN
最新正式版.zip