1
0
龙腾猫跃 11 сар өмнө
parent
commit
efd480f06c
24 өөрчлөгдсөн 1028 нэмэгдсэн , 428 устгасан
  1. 27 3
      Plain Craft Launcher 2/FormMain.xaml.vb
  2. BIN
      Plain Craft Launcher 2/Images/Heads/EasyTier.png
  3. 48 4
      Plain Craft Launcher 2/Modules/Base/ModBase.vb
  4. 2 2
      Plain Craft Launcher 2/Modules/Base/ModLoader.vb
  5. 50 33
      Plain Craft Launcher 2/Modules/Base/ModNet.vb
  6. 1 6
      Plain Craft Launcher 2/Modules/Base/ModValidate.vb
  7. 9 2
      Plain Craft Launcher 2/Modules/Minecraft/ModDownload.vb
  8. 12 0
      Plain Craft Launcher 2/Modules/ModEvent.vb
  9. 2 2
      Plain Craft Launcher 2/My Project/AssemblyInfo.vb
  10. 1 1
      Plain Craft Launcher 2/Pages/PageDownload/Comp/PageComp.xaml
  11. 2 1
      Plain Craft Launcher 2/Pages/PageDownload/ModDownloadLib.vb
  12. 3 0
      Plain Craft Launcher 2/Pages/PageLaunch/PageLaunchRight.xaml.vb
  13. 1 1
      Plain Craft Launcher 2/Pages/PageLaunch/PageLoginMsSkin.xaml.vb
  14. 4 4
      Plain Craft Launcher 2/Pages/PageLink/PageLinkMain.xaml
  15. 255 140
      Plain Craft Launcher 2/Pages/PageLink/PageLinkMain.xaml.vb
  16. 573 216
      Plain Craft Launcher 2/Pages/PageOther/PageOtherAbout.xaml
  17. 2 1
      Plain Craft Launcher 2/Pages/PageSetup/ModSetup.vb
  18. 2 2
      Plain Craft Launcher 2/Pages/PageSetup/PageSetupLaunch.xaml
  19. 25 4
      Plain Craft Launcher 2/Pages/PageSetup/PageSetupLink.xaml
  20. 4 2
      Plain Craft Launcher 2/Pages/PageSetup/PageSetupLink.xaml.vb
  21. 1 0
      Plain Craft Launcher 2/Pages/PageSetup/PageSetupUI.xaml
  22. 1 3
      Plain Craft Launcher 2/Pages/PageSpeedLeft.xaml.vb
  23. 3 1
      Plain Craft Launcher 2/Plain Craft Launcher 2.vbproj
  24. BIN
      Plain Craft Launcher 2/Resources/Help.zip

+ 27 - 3
Plain Craft Launcher 2/FormMain.xaml.vb

@@ -113,6 +113,17 @@ Public Class FormMain
         '3:BUG+ IMP* FEAT-
         '2:BUG* IMP-
         '1:BUG-
+        If LastVersion < 374 Then 'Snapshot 2.11.1
+            If LastVersion >= 373 Then
+                FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "优化:使用离线登录也可以直接加入联机房间了"))
+                FeatureList.Add(New KeyValuePair(Of Integer, String)(3, "优化:会从所有共享节点中自动选择负载最低的进行中继连接"))
+                FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "优化:若复制了邀请码,则可以直接快速加入房间"))
+                FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "优化:关闭 PCL 时总是会提示是否退出联机,防止在关闭 PCL 时无意地关闭或退出了房间"))
+                FeatureList.Add(New KeyValuePair(Of Integer, String)(2, "新增:允许自定义要连接的节点"))
+            End If
+            FeatureCount += 9
+            BugCount += 7
+        End If
         If LastVersion < 373 Then 'Snapshot 2.11.0
             FeatureList.Add(New KeyValuePair(Of Integer, String)(5, "新增:联机功能!"))
             FeatureCount += 7
@@ -587,9 +598,7 @@ Public Class FormMain
             End Sub, "强行停止下载任务")
         End If
         '关闭联机?
-        If FrmLinkMain IsNot Nothing Then
-            If FrmLinkMain.TryExit(SendWarning) Then Return
-        End If
+        If FrmLinkMain?.TryExit(Not SendWarning, True) Then Return
         '关闭
         RunInUiWait(
         Sub()
@@ -765,6 +774,21 @@ Public Class FormMain
         Catch ex As Exception
             Log(ex, "切回窗口时出错", LogLevel.Feedback)
         End Try
+        '读取剪贴板,自动加入联机房间
+        If PageLinkMain.LinkState <> PageLinkMain.LinkStates.Waiting Then Return '已启动联机
+        Dim Code = ClipboardGetText() : If Code Is Nothing Then Return '剪贴板无文本
+        If Setup.Get("LinkLastAutoJoinInviteCode") = Code Then Return
+        If PageLinkMain.ValidateCodeFormat(Code) IsNot Nothing Then Return '不是邀请码
+        Setup.Set("LinkLastAutoJoinInviteCode", Code)
+        RunInThread(
+        Sub()
+            If MyMsgBox("嘿,是否使用复制的邀请码加入房间?", "加入联机房间", "加入", "取消") = 2 Then Return '防止弹窗阻碍主线程,所以必须放在工作线程
+            RunInUi(
+            Sub()
+                PageLinkMain.Join(Code)
+                ClipboardSet(Nothing, False)
+            End Sub)
+        End Sub)
     End Sub
 
     '文件拖放

BIN
Plain Craft Launcher 2/Images/Heads/EasyTier.png


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

@@ -5,6 +5,7 @@ Imports System.Runtime.CompilerServices
 Imports System.Security.Cryptography
 Imports System.Security.Principal
 Imports System.Text.RegularExpressions
+Imports System.Threading.Tasks
 Imports System.Xaml
 Imports Newtonsoft.Json
 
@@ -13,13 +14,13 @@ Public Module ModBase
 #Region "声明"
 
     '下列版本信息由更新器自动修改
-    Public Const VersionBaseName As String = "2.11.0" '不含分支前缀的显示用版本名
-    Public Const VersionStandardCode As String = "2.11.0." & VersionBranchCode '标准格式的四段式版本号
+    Public Const VersionBaseName As String = "2.11.1" '不含分支前缀的显示用版本名
+    Public Const VersionStandardCode As String = "2.11.1." & VersionBranchCode '标准格式的四段式版本号
     Public Const CommitHash As String = "" 'Commit Hash,由 GitHub Workflow 自动替换
 #If BETA Then
     Public Const VersionCode As Integer = 372 'Release
 #Else
-    Public Const VersionCode As Integer = 373 'Snapshot
+    Public Const VersionCode As Integer = 374 'Snapshot
 #End If
     '自动生成的版本信息
     Public Const VersionDisplayName As String = VersionBranchName & " " & VersionBaseName
@@ -1727,6 +1728,7 @@ RetryDir:
     ''' </summary>
     <Extension> <MethodImpl(MethodImplOptions.AggressiveInlining)>
     Public Function StartsWithF(Str As String, Prefix As String, Optional IgnoreCase As Boolean = False) As Boolean
+        If Str Is Nothing Then Return False
         Return Str.StartsWith(Prefix, If(IgnoreCase, StringComparison.OrdinalIgnoreCase, StringComparison.Ordinal))
     End Function
     ''' <summary>
@@ -1734,6 +1736,7 @@ RetryDir:
     ''' </summary>
     <Extension> <MethodImpl(MethodImplOptions.AggressiveInlining)>
     Public Function EndsWithF(Str As String, Suffix As String, Optional IgnoreCase As Boolean = False) As Boolean
+        If Str Is Nothing Then Return False
         Return Str.EndsWith(Suffix, If(IgnoreCase, StringComparison.OrdinalIgnoreCase, StringComparison.Ordinal))
     End Function
     ''' <summary>
@@ -1741,6 +1744,7 @@ RetryDir:
     ''' </summary>
     <Extension> <MethodImpl(MethodImplOptions.AggressiveInlining)>
     Public Function ContainsF(Str As String, SubStr As String, Optional IgnoreCase As Boolean = False) As Boolean
+        If Str Is Nothing Then Return False
         Return Str.IndexOf(SubStr, If(IgnoreCase, StringComparison.OrdinalIgnoreCase, StringComparison.Ordinal)) >= 0
     End Function
     ''' <summary>
@@ -1777,6 +1781,7 @@ RetryDir:
     ''' 如果输入有误,返回 0。
     ''' </summary>
     Public Function Val(Str As Object) As Double
+        If Str Is Nothing Then Return 0
         Try
             Return If(TypeOf Str Is String AndAlso Str = "&", 0, Conversion.Val(Str))
         Catch
@@ -2147,6 +2152,29 @@ RetryDir:
         Return result
     End Function
 
+    ''' <summary>
+    ''' 为 Task 设置超时,在超时时抛出 TimeoutException。
+    ''' </summary>
+    <Extension> Public Function GetResultWithTimeout(Of T)(TargetTask As Task(Of T), TokenSource As CancellationTokenSource, TimeoutMs As Integer) As T
+        Dim DelayTask = Task.Delay(TimeoutMs)
+        If Task.WhenAny(TargetTask, DelayTask).GetAwaiter().GetResult() Is DelayTask Then
+            TokenSource.Cancel()
+            Throw New TimeoutException($"任务超时({TimeoutMs} ms)")
+        End If
+        Return TargetTask.GetAwaiter().GetResult()
+    End Function
+    ''' <summary>
+    ''' 为 Task 设置超时,在超时时抛出 TimeoutException。
+    ''' </summary>
+    <Extension> Public Sub GetResultWithTimeout(TargetTask As Task, TokenSource As CancellationTokenSource, TimeoutMs As Integer)
+        Dim DelayTask = Task.Delay(TimeoutMs)
+        If Task.WhenAny(TargetTask, DelayTask).GetAwaiter().GetResult() Is DelayTask Then
+            TokenSource.Cancel()
+            Throw New TimeoutException($"任务超时({TimeoutMs} ms)")
+        End If
+        TargetTask.GetAwaiter().GetResult()
+    End Sub
+
     ''' <summary>
     ''' 可用于临时存放文件的,不含任何特殊字符的文件夹路径,以“\”结尾。
     ''' </summary>
@@ -2586,7 +2614,7 @@ Retry:
                 RunInUi(
                 Sub()
                     My.Computer.Clipboard.Clear()
-                    My.Computer.Clipboard.SetText(Text)
+                    If Not String.IsNullOrEmpty(Text) Then My.Computer.Clipboard.SetText(Text)
                 End Sub)
             Catch ex As Exception
                 RetryCount += 1
@@ -2600,6 +2628,21 @@ Retry:
             If ShowSuccessHint Then Hint("已成功复制!", HintType.Green)
         End Sub)
     End Sub
+    ''' <summary>
+    ''' 获取剪贴板文本。将在 UI 线程运行,且不会抛出异常。
+    ''' </summary>
+    Public Function ClipboardGetText() As String
+        Dim Result As String = Nothing
+        RunInUiWait(
+        Sub()
+            Try
+                If My.Computer.Clipboard.ContainsText() Then Result = My.Computer.Clipboard.GetText()
+            Catch ex As Exception
+                Log(ex, "获取剪贴板文本失败")
+            End Try
+        End Sub)
+        Return Result
+    End Function
 
     ''' <summary>
     ''' 以 Byte() 形式获取程序中的资源。
@@ -3079,6 +3122,7 @@ Retry:
     Public Sub Telemetry([Event] As String, ParamArray Datas As String())
         If Not Setup.Get("SystemSystemTelemetry") Then Return '用户关闭了遥测
         If Not ClsBaseUrl.StartsWithF("http") Then Return '开源版没有设置遥测地址
+        If VersionBranchName = "Debug" Then Return '开发版本不上传遥测
         RunInNewThread(
         Sub()
             Try

+ 2 - 2
Plain Craft Launcher 2/Modules/Base/ModLoader.vb

@@ -344,12 +344,12 @@
             LastRunningThread.Start() '不能使用 RunInNewThread,否则在函数返回前线程就会运行完,导致误判 IsAborted
         End Sub
         Public Overrides Sub Failed(ex As Exception)
+            [Error] = ex
             SyncLock LockState
                 If IsAborted OrElse State >= LoadState.Finished Then Return
                 State = LoadState.Failed
             End SyncLock
             Log(ex, $"加载线程 {Name} ({Thread.CurrentThread.ManagedThreadId}) 出错,已完成 {Math.Round(Progress * 100)}%", LogLevel.Developer)
-            [Error] = ex
             TriggerThreadAbort()
         End Sub
         Public Overrides Sub Abort()
@@ -464,11 +464,11 @@
             End Sub)
         End Sub
         Public Overrides Sub Failed(Ex As Exception)
+            [Error] = Ex '先设置错误再调整状态,防止父加载器获取不到异常
             SyncLock LockState
                 If State >= LoadState.Finished Then Return
                 State = LoadState.Failed
             End SyncLock
-            [Error] = Ex
             For Each Loader In Loaders
                 Loader.Abort()
             Next

+ 50 - 33
Plain Craft Launcher 2/Modules/Base/ModNet.vb

@@ -262,11 +262,11 @@ RequestFinished:
                     })
                 End If
             End SyncLock
-            Response = RequestClient.SendAsync(Request, HttpCompletionOption.ResponseHeadersRead, CancelToken.Token).GetAwaiter().GetResult()
+            Response = RequestClient.SendAsync(Request, HttpCompletionOption.ResponseHeadersRead, CancelToken.Token).GetResultWithTimeout(CancelToken, Timeout)
             Dim ResponseStream = Response.Content.ReadAsStreamAsync().GetAwaiter().GetResult()
             Dim ResponseBytes As Byte()
             Using Stream As New MemoryStream
-                ResponseStream.CopyToAsync(Stream, 81920, CancelToken.Token).GetAwaiter().GetResult()
+                ResponseStream.CopyToAsync(Stream, 81920, CancelToken.Token).GetResultWithTimeout(CancelToken, Timeout)
                 ResponseBytes = Stream.ToArray()
             End Using
             '输出
@@ -286,7 +286,7 @@ RequestFinished:
             Throw
         Catch ex As Exception
             RecordIPReliability(HostIp, -1)
-            If TypeOf ex Is OperationCanceledException Then 'CancellationToken 超时
+            If TypeOf ex Is OperationCanceledException OrElse TypeOf ex Is TimeoutException Then 'CancellationToken 超时
                 Throw New WebException($"连接服务器超时,请稍后再试,或使用 VPN 改善网络环境({Method}, {Url},IP:{HostIp})", WebExceptionStatus.Timeout)
             ElseIf ex.IsNetworkRelated Then
                 Throw New WebException($"网络请求失败,请稍后再试,或使用 VPN 改善网络环境({Method}, {Url},IP:{HostIp})", WebExceptionStatus.Timeout)
@@ -992,7 +992,7 @@ StartThread:
                 HostIp = DNSLookup(HttpRequest, CancelToken) 'DNS 预解析
                 If Not Th.IsFirstThread Then HttpRequest.Headers.Range = New RangeHeaderValue(Th.DownloadStart, Nothing)
                 Dim ContentLength As Long = 0
-                Response = ThreadClient.SendAsync(HttpRequest, HttpCompletionOption.ResponseHeadersRead, CancelToken.Token).GetAwaiter().GetResult()
+                Response = ThreadClient.SendAsync(HttpRequest, HttpCompletionOption.ResponseHeadersRead, CancelToken.Token).GetResultWithTimeout(CancelToken, Timeout)
                 If Not Response.IsSuccessStatusCode Then Throw New Exception($"错误码 {Response.StatusCode} ({CInt(Response.StatusCode)}),{Th.Source.Url}") '状态码检查
                 If State = NetState.Error Then GoTo SourceBreak '快速中断
                 If ModeDebug AndAlso Response.RequestMessage.RequestUri.ToString <> Th.Source.Url Then Log($"[Download] {LocalName}:重定向至 {Response.RequestMessage.RequestUri}")
@@ -1063,7 +1063,7 @@ NotSupportRange:
                 ResponseStream = Response.Content.ReadAsStreamAsync().GetAwaiter().GetResult()
                 If Setup.Get("SystemDebugDelay") Then Threading.Thread.Sleep(RandomInteger(50, 3000))
                 Dim ResponseBytes As Byte() = New Byte(16384) {}
-                HttpDataCount = ReadWithTimeout(ResponseStream, ResponseBytes, 0, 16384, Timeout)
+                HttpDataCount = ResponseStream.ReadAsync(ResponseBytes, 0, 16384, CancelToken.Token).GetResultWithTimeout(CancelToken, Timeout)
                 While (IsUnknownSize OrElse Th.DownloadUndone > 0) AndAlso '判断是否下载完成
                             HttpDataCount > 0 AndAlso Not IsProgramEnded AndAlso State < NetState.Merge AndAlso (Not Th.Source.IsFailed OrElse Th.Source.SingleThread = Th)
                     '限速
@@ -1113,7 +1113,7 @@ NotSupportRange:
                         '无数据,且已超时
                         Throw New TimeoutException("操作超时,无数据。")
                     End If
-                    HttpDataCount = ReadWithTimeout(ResponseStream, ResponseBytes, 0, 16384, Timeout)
+                    HttpDataCount = ResponseStream.ReadAsync(ResponseBytes, 0, 16384, CancelToken.Token).GetResultWithTimeout(CancelToken, Timeout)
                 End While
 SourceBreak:
                 If State = NetState.Error OrElse (Th.Source.IsFailed AndAlso Th.Source.SingleThread <> Th) OrElse (Th.DownloadUndone > 0 AndAlso Not IsUnknownSize) Then
@@ -1130,7 +1130,8 @@ SourceBreak:
                     RecordIPReliability(HostIp, 0.5)
                 End If
             Catch ex As Exception
-                Log($"[Download] {LocalName}:出错,{If(TypeOf ex Is OperationCanceledException, $"已超时({Timeout}ms)", ex.GetDetail())},IP:{HostIp}")
+                Log($"[Download] {LocalName}:出错,{If(TypeOf ex Is OperationCanceledException OrElse TypeOf ex Is TimeoutException,
+                    $"已超时({Timeout}ms)", ex.GetDetail())},IP:{HostIp}")
                 RecordIPReliability(HostIp, -0.7)
                 SourceFail(Th, ex, False)
             Finally
@@ -1650,15 +1651,15 @@ Retry:
                 If State >= LoadState.Finished Then Return
                 If ExList Is Nothing OrElse Not ExList.Any() Then ExList = New List(Of Exception) From {New Exception("未知错误!")}
                 '寻找有效的错误信息
-                Dim UsefulExs = ExList.Where(Function(e) TypeOf e IsNot OperationCanceledException AndAlso TypeOf e IsNot ThreadInterruptedException).ToList
+                Dim UsefulExs = ExList.Where(Function(e) TypeOf e IsNot OperationCanceledException AndAlso TypeOf e IsNot TimeoutException AndAlso TypeOf e IsNot ThreadInterruptedException).ToList
                 [Error] = If(UsefulExs.FirstOrDefault, ExList.FirstOrDefault)
                 '获取实际失败的文件
                 For Each File In Files
                     If File.State <> NetState.Error Then Continue For
+                    If File.Sources.All(Function(s) TypeOf s.Ex Is OperationCanceledException OrElse TypeOf s.Ex Is TimeoutException OrElse TypeOf s.Ex Is ThreadInterruptedException) Then Continue For
                     Dim Detail As String = Join(File.Sources.Select(Function(s) $"{If(s.Ex Is Nothing, "无错误信息。", s.Ex.GetBrief())}({s.Url})"), vbCrLf)
                     [Error] = New Exception("文件下载失败:" & File.LocalPath & vbCrLf &
-                                            "各下载源的错误如下:" & vbCrLf & Detail,
-                                            [Error])
+                                            "各下载源的错误如下:" & vbCrLf & Detail, [Error])
                     '上报
                     Telemetry("文件下载失败",
                               "FileName", File.LocalName,
@@ -1951,6 +1952,45 @@ Retry:
         Return False
     End Function
 
+#End Region
+
+#Region "端口"
+
+    ''' <summary>
+    ''' 随机获取单个可用的端口。
+    ''' </summary>
+    Public Function FindFreePort() As Integer
+        Dim Listener As New TcpListener(IPAddress.Loopback, 0)
+        Listener.Start()
+        Dim port As Integer = CType(Listener.LocalEndpoint, IPEndPoint).Port
+        Listener.Stop()
+        Return port
+    End Function
+
+    ''' <summary>
+    ''' 获取当前已被占用的端口列表。
+    ''' </summary>
+    Public Function GetUsedPorts() As List(Of Integer)
+        Dim IPProperties = NetworkInformation.IPGlobalProperties.GetIPGlobalProperties()
+        Dim UsedPorts As New List(Of Integer)
+        UsedPorts.AddRange(IPProperties.GetActiveTcpListeners().Select(Function(ep) ep.Port))
+        UsedPorts.AddRange(IPProperties.GetActiveUdpListeners().Select(Function(ep) ep.Port))
+        UsedPorts.AddRange(IPProperties.GetActiveTcpConnections().Select(Function(conn) conn.LocalEndPoint.Port))
+        Return UsedPorts.Distinct().ToList()
+    End Function
+
+    ''' <summary>
+    ''' 寻找数个连续编号的可用端口。
+    ''' </summary>
+    Public Function FindFreePorts(ConsecutiveCount As Integer, ParamArray ExtraBlackLists As Integer()) As List(Of Integer)
+        Dim UsedPorts = GetUsedPorts().Concat(ExtraBlackLists)
+        For port = 12000 To 65000 - ConsecutiveCount
+            Dim Range = Enumerable.Range(port, ConsecutiveCount)
+            If Not Range.Any(Function(p) UsedPorts.Contains(p)) Then Return Range.ToList
+        Next
+        Throw New Exception("未能找到可用的端口!")
+    End Function
+
 #End Region
 
     ''' <summary>
@@ -1985,27 +2025,4 @@ Retry:
         }.Any(Function(k) Detail.ContainsF(k, True))
     End Function
 
-    ''' <summary>
-    ''' 随机获取一个可用的端口。
-    ''' </summary>
-    Public Function GetAvailablePort() As Integer
-        Dim Listener As New TcpListener(IPAddress.Loopback, 0)
-        Listener.Start()
-        Dim port As Integer = CType(Listener.LocalEndpoint, IPEndPoint).Port
-        Listener.Stop()
-        Return port
-    End Function
-
-    ''' <summary>
-    ''' 带有 Timeout 的读取 Stream 方法。
-    ''' </summary>
-    Private Function ReadWithTimeout(TargetStream As Stream, Buffer() As Byte, Offset As Integer, Count As Integer, ReadTimeoutMs As Integer) As Integer
-        Dim ReadTask = TargetStream.ReadAsync(Buffer, Offset, Count)
-        Dim DelayTask = Task.Delay(ReadTimeoutMs)
-        If Task.WhenAny(ReadTask, DelayTask).GetAwaiter().GetResult() Is DelayTask Then
-            Throw New TimeoutException($"读取数据超时({ReadTimeoutMs} ms)")
-        End If
-        Return ReadTask.GetAwaiter().GetResult()
-    End Function
-
 End Module

+ 1 - 6
Plain Craft Launcher 2/Modules/Base/ModValidate.vb

@@ -114,12 +114,7 @@ Public Class ValidateInteger
     End Sub
     Public Overrides Function Validate(Str As String) As String
         Dim Valed As Integer
-        If Not Integer.TryParse(Str, Valed) Then 
-            Return "请输入一个整数!"
-        End If
-        If Not RegexCheck(Str, "^(-?0|-?[1-9]\d*)$") Then 
-            Return "请输入一个不带有前导零的整数!"
-        End If
+        If Not Integer.TryParse(Str, Valed) Then Return "请输入一个整数!"
         If Str.Length > 9 Then Return "请输入一个大小合理的数字!"
         If Valed > Max Then Return "不可超过 " & Max & "!"
         If Valed < Min Then Return "不可低于 " & Min & "!"

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

@@ -73,8 +73,10 @@
             Sub(Task As LoaderTask(Of String, List(Of NetFile)))
                 Try
                     Dim IndexFile = DlClientAssetIndexGet(Version)
-                    Dim IndexFileInfo As New FileInfo(IndexFile.LocalPath)
-                    If AssetsIndexBehaviour <> AssetsIndexExistsBehaviour.AlwaysDownload AndAlso IndexFile.Check.Check(IndexFile.LocalPath) Is Nothing Then
+                    If IndexFile Is Nothing Then
+                        Task.Output = New List(Of NetFile)
+                        Log("[Download] 未找到版本 " & Version.Name & " 的合适的资源索引下载地址,游戏 assets 可能缺失", LogLevel.Debug)
+                    ElseIf AssetsIndexBehaviour <> AssetsIndexExistsBehaviour.AlwaysDownload AndAlso IndexFile.Check.Check(IndexFile.LocalPath) Is Nothing Then
                         Task.Output = New List(Of NetFile)
                     Else
                         Task.Output = New List(Of NetFile) From {IndexFile}
@@ -93,6 +95,11 @@
                 LoadersAssetsUpdate.Add(New LoaderTask(Of String, List(Of NetFile))("后台分析资源文件索引地址",
                 Sub(Task As LoaderTask(Of String, List(Of NetFile)))
                     Dim BackAssetsFile As NetFile = DlClientAssetIndexGet(Version)
+                    If BackAssetsFile Is Nothing Then
+                        Log("[Download] 未找到版本 " & Version.Name & " 的合适的资源索引下载地址,游戏 assets 可能缺失", LogLevel.Debug)
+                        Task.Abort()
+                        Throw New ThreadInterruptedException
+                    End If
                     RealAddress = BackAssetsFile.LocalPath
                     TempAddress = PathTemp & "Cache\" & BackAssetsFile.LocalName
                     BackAssetsFile.LocalPath = TempAddress

+ 12 - 0
Plain Craft Launcher 2/Modules/ModEvent.vb

@@ -141,6 +141,7 @@ Public Class CustomEvent
         写入设置
         修改变量
         写入变量
+        加入房间
     End Enum
 
     ''' <summary>
@@ -283,6 +284,17 @@ Public Class CustomEvent
                     WriteReg("CustomEvent" & Args(0), Args(1))
                     If Args.Length = 2 Then Hint($"已写入变量:{Args(0)} → {Args(1)}", HintType.Green)
 
+                Case EventType.加入房间
+                    RunInUi(
+                    Sub()
+                        If String.IsNullOrWhiteSpace(Arg) Then
+                            PageLinkMain.Join()
+                        Else
+                            If Not EventSafetyConfirm("即将加入第三方联机房间。") Then Return
+                            PageLinkMain.Join(Arg)
+                        End If
+                    End Sub)
+
                 Case Else
                     MyMsgBox("未知的事件类型:" & Type & vbCrLf & "请检查事件类型填写是否正确,或者 PCL 是否为最新版本。", "事件执行失败")
             End Select

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

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

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

@@ -34,7 +34,7 @@
                     <TextBlock VerticalAlignment="Center" Grid.Row="2" HorizontalAlignment="Left" Text="版本" Margin="0,0,18,0" />
                     <local:MyComboBox x:Name="TextSearchVersion" Grid.Row="2" Grid.Column="1" Grid.ColumnSpan="2" IsEditable="True" MaxDropDownHeight="320">
                         <local:MyComboBoxItem Content="全部 (也可自行输入)" IsSelected="True" />
-                        <local:MyComboBoxItem Content="1.21.8" />
+                        <local:MyComboBoxItem Content="1.21.10" />
                         <local:MyComboBoxItem Content="1.21.1" />
                         <local:MyComboBoxItem Content="1.20.6" />
                         <local:MyComboBoxItem Content="1.20.1" />

+ 2 - 1
Plain Craft Launcher 2/Pages/PageDownload/ModDownloadLib.vb

@@ -99,7 +99,8 @@ Public Module ModDownloadLib
         Sub(Task As LoaderTask(Of String, List(Of NetFile)))
             Try
                 Dim Version As New McVersion(VersionFolder)
-                Task.Output = New List(Of NetFile) From {DlClientAssetIndexGet(Version)}
+                Dim AssetIndex = DlClientAssetIndexGet(Version)
+                Task.Output = If(AssetIndex Is Nothing, New List(Of NetFile), New List(Of NetFile) From {AssetIndex})
             Catch ex As Exception
                 Throw New Exception("分析资源文件索引地址失败", ex)
             End Try

+ 3 - 0
Plain Craft Launcher 2/Pages/PageLaunch/PageLaunchRight.xaml.vb

@@ -104,6 +104,9 @@ Public Class PageLaunchRight
                     Case 12
                         Log("[Page] 主页预设:PCL GitHub 仪表盘")
                         Url = "https://ddf.pcl-community.org/Custom.xaml"
+                    Case 13
+                        Log("[Page] 主页预设:PCL 更新摘要")
+                        Url = "https://raw.gitcode.com/ENC_Euphony/PCL-AI-Summary-HomePage/raw/master/Custom.xaml"
                 End Select
         End Select
         '联网下载

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

@@ -121,7 +121,7 @@ Retry:
                 Next
                 Throw New Exception("未知错误(" & Result & ")")
             Catch ex As Exception
-                If TypeOf ex Is OperationCanceledException Then
+                If TypeOf ex Is OperationCanceledException OrElse TypeOf ex Is TimeoutException Then
                     Hint("更改皮肤失败:连接皮肤服务器超时,请稍后再试,或使用 VPN 改善网络环境", HintType.Red)
                 Else
                     Log(ex, "更改皮肤失败", LogLevel.Hint)

+ 4 - 4
Plain Craft Launcher 2/Pages/PageLink/PageLinkMain.xaml

@@ -152,7 +152,7 @@
                         <TextBlock x:Name="LabFinishDesc" Grid.Column="3" Grid.ColumnSpan="3" Grid.Row="2" Margin="1,9,10,10" 
                                    Text="描述文本。"
                                    FontSize="14" LineHeight="19" MaxWidth="400" TextWrapping="Wrap" Foreground="{StaticResource ColorBrushGray2}" />
-                        <local:MyButton x:Name="BtnFinishCopy" Grid.Column="4" Grid.Row="3" Margin="0,0,15,0" Text="复制" Padding="13,8" ColorType="Highlight" />
+                        <local:MyButton x:Name="BtnFinishCopy" Grid.Column="4" Grid.Row="3" Margin="0,0,15,0" Text="复制邀请码" Padding="13,8" ColorType="Highlight" />
                         <local:MyButton x:Name="BtnFinishExit" Grid.Column="5" Grid.Row="3" Text="退出" Padding="13,8" />
                     </Grid>
                 </local:MyCard>
@@ -186,12 +186,12 @@
                                 Data="m365,295.3c-15.1-3.6-36.5-1.8-39.6,17.5-1.2,12.4,0,107-.5,119.7.8,16.8-5.2,42.4,16.8,47.1,14.3,3.3,34.5,1.9,38.7-15.4,2.6-1.4.1-142.4,1-148.3-.7-10.9-6.2-17.8-16.4-20.6ZM234.1,311.6c-3.2-16.7-20-18.6-34.4-17.2-9.8.4-17.2,6.2-20,15.4-4.4,47.8-.2,97.3-1.6,144.8,0,16,9.8,26.6,24.6,26.1,14.4,1.4,29.1-2.9,31.7-19,2.2-8.8.8-63.9,1.1-74.1-1-25.3,2.1-50.6-1.5-75.9ZM521.4,300.6c-5.4-6.2-15.9-7.1-24.6-6.4-11.9-1-23,6.6-24.7,18.7-2.2,24.1-2,124-.2,148.1,2.6,19.7,24.1,22.4,40.1,18.4,11.9-2.4,16.6-15.2,16.3-27.1,0-33.6.1-69.3,0-103.1-1.2-15.1,4.2-37-6.9-48.5ZM708.8,194.2c.7-34.5-26.8-63.7-61.5-63.4-22.1-.1-52.4,0-75.6,0-13.4,1.1-8.7-12.1-9.6-20.9-1.6-30.6,7.5-67.2-17.5-90.9-11.7-11.9-27.4-18.4-44.3-18.4-64.8,0-129.7,0-194.5,0-37.7,1.4-76.5-3.1-113.8,2.2-48.1,14.7-46.7,55.3-45.4,97.3,0,8,.1,16.1,0,24.1.2,7-7.3,6.8-12.2,6.6-16,0-32,0-48,0-24.4-.7-51.3-1-68.6,18.4C5.8,161.2,0,176.1,0,194.7c0,0,0,350.9,0,350.9,0,22.9,5.5,41.7,16.8,57.5,19.2,27,45.9,40.7,79.5,40.7,37.4,0,77.4.1,129.9.1,42.5,0,85,0,127.5,0,11.2-1.3,273.6,2.4,278-1.8,46.1-9.1,77.1-46.8,77.1-93.8,0-117.8,0-237.9,0-354.1Zm-71-5.3c7.6.2,9.2,1.9,9.3,9.7,0,0,0,347.3,0,347.3,0,3.2.2,6.5-.3,9.9-2.8,19.3-18.9,32.3-38.5,31.9-4.5.4-508.9-.4-513.5,0-3.2,0-6.5.1-9.9-.4-19-2.9-31.8-17.8-31.8-37.1,0-117.9,0-233.9,0-350.9,0-9,2.3-10.3,10.9-10.3,0,0,131.2,0,131.2,0,1.6,0,3,0,4.5,0,0-1.5,0-2.7,0-4.3,0,0,0-115.7,0-115.7.1-8.3,1.9-10.1,10.3-10.1h280.3c8.3,0,10.1,1.8,10.1,10.3v114.1c0,1.9,0,3.7,0,5.6" />
                             <TextBlock x:Name="LabFinishPort" IsHitTestVisible="False" Text="12345" VerticalAlignment="Center" Foreground="{StaticResource ColorBrushGray1}" Margin="0,0.5,13,0" />
                         </StackPanel>
-                        <!--<StackPanel x:Name="BtnFinishIp" Orientation="Horizontal" Background="{StaticResource ColorBrushSemiTransparent}"
-                                    ToolTip="服务器 IP ( 点击复制 )" ToolTipService.Placement="Center" ToolTipService.InitialShowDelay="50" ToolTipService.VerticalOffset="40" ToolTipService.HorizontalOffset="4">
+                        <StackPanel x:Name="BtnFinishIp" Orientation="Horizontal" Background="{StaticResource ColorBrushSemiTransparent}"
+                                    ToolTip="服务器 IP(点击复制)" ToolTipService.Placement="Center" ToolTipService.InitialShowDelay="50" ToolTipService.VerticalOffset="40" ToolTipService.HorizontalOffset="4">
                             <Path IsHitTestVisible="False" Height="17" Width="17" Stretch="Uniform" Fill="{StaticResource ColorBrushGray4}" Margin="11,0,7,0"
                                 Data="m346.4,692.8c-92.5,0-179.5-36-244.9-101.5C36,525.9,0,438.9,0,346.4S36,166.9,101.5,101.5C166.9,36,253.9,0,346.4,0s179.5,36,244.9,101.5c65.4,65.4,101.5,152.4,101.5,244.9s-36,179.5-101.5,244.9c-65.4,65.4-152.4,101.5-244.9,101.5Zm0-645.1c-164.7,0-298.7,134-298.7,298.7s134,298.7,298.7,298.7,298.7-134,298.7-298.7S511.1,47.7,346.4,47.7Zm13.8,473.4c-14.5,0-28.2-9.8-28.2-24.2V207.9c0-14.5,11.8-26.2,26.2-26.2h78.9c57.9,0,105.1,47.1,105.1,105.1s-47.1,105.1-105.1,105.1h-52.6v105.1c0,14.5-9.8,24.2-24.2,24.2Zm24.2-181.7h52.6c29,0,52.6-23.6,52.6-52.6s-20-49.2-46.5-52.3h-.4s-5.3-.4-5.3-.4h-53v105.2Zm-158.8,181.7c-14.5,0-28.2-9.8-28.2-24.2V207.9c0-14.5,11.8-26.2,26.2-26.2s26.2,11.8,26.2,26.2v289c0,14.5-9.8,24.2-24.2,24.2Z" />
                             <TextBlock x:Name="LabFinishIp" IsHitTestVisible="False" Text="6.0.0.1:12345" VerticalAlignment="Center" Foreground="{StaticResource ColorBrushGray1}" Margin="0,0.5,13,0" />
-                        </StackPanel>-->
+                        </StackPanel>
                     </StackPanel>
                 </local:MyCard>
             </Grid>

+ 255 - 140
Plain Craft Launcher 2/Pages/PageLink/PageLinkMain.xaml.vb

@@ -1,4 +1,6 @@
-Public Class PageLinkMain
+Imports System.Net.Sockets
+
+Public Class PageLinkMain
 
     '===============================
     '  状态机与前端页面
@@ -6,33 +8,33 @@
 
 #Region "状态管理"
 
-    Private Enum States
+    Public Enum LinkStates
         Waiting
         Loading
         Failed
         Finished
     End Enum
-    Private State As States = States.Waiting
+    Public Shared LinkState As LinkStates = LinkStates.Waiting
 
     ''' <summary>
     ''' 切换到指定的状态。
     ''' </summary>
-    Private Sub ChangeState(NewState As States)
-        If State = NewState Then Return
-        Dim OldState = State
-        State = NewState
+    Private Sub ChangeState(NewState As LinkStates)
+        If LinkState = NewState Then Return
+        Dim OldState = LinkState
+        LinkState = NewState
         Log($"[Link] 主状态由 {GetStringFromEnum(OldState)} 变更为 {GetStringFromEnum(NewState)}")
         '触发状态切换
         RunInUi(
         Sub()
             Select Case NewState
-                Case States.Waiting
+                Case LinkStates.Waiting
                     SwitchToWaiting(OldState)
-                Case States.Loading
+                Case LinkStates.Loading
                     SwitchToLoading(OldState)
-                Case States.Failed
+                Case LinkStates.Failed
                     SwitchToFailed(OldState)
-                Case States.Finished
+                Case LinkStates.Finished
                     SwitchToFinished(OldState)
             End Select
         End Sub)
@@ -45,18 +47,18 @@
         Sub(Loader As LoaderBase, NewState As LoadState, OldState As LoadState)
             Select Case NewState
                 Case LoadState.Finished
-                    ChangeState(States.Finished)
+                    ChangeState(LinkStates.Finished)
                 Case LoadState.Failed
                     Telemetry("联机失败", "Exception", FilterUserName(Loader.Error.GetDetail, "*"))
-                    ChangeState(States.Failed)
+                    ChangeState(LinkStates.Failed)
             End Select
         End Sub
     End Sub
 
     '页面动画兼容
     Private Sub UpdatePanelVisibility() Handles Me.PageEnter
-        FrmLinkMain.PanSelect.Visibility = If(State = States.Waiting, Visibility.Visible, Visibility.Collapsed)
-        FrmLinkMain.PanFinish.Visibility = If(State = States.Finished, Visibility.Visible, Visibility.Collapsed)
+        FrmLinkMain.PanSelect.Visibility = If(LinkState = LinkStates.Waiting, Visibility.Visible, Visibility.Collapsed)
+        FrmLinkMain.PanFinish.Visibility = If(LinkState = LinkStates.Finished, Visibility.Visible, Visibility.Collapsed)
     End Sub
 
 #End Region
@@ -64,7 +66,7 @@
 #Region "初始页面 (Waiting)"
 
     '由任意状态切换到 Waiting
-    Private Sub SwitchToWaiting(OldState As States)
+    Private Sub SwitchToWaiting(OldState As LinkStates)
         '加载器与进程状态
         LinkLoader.Abort()
         SyncLock LinkLoader.LockState
@@ -72,7 +74,7 @@
         End SyncLock
         ProcessStop()
         '页面切换
-        If OldState <> States.Finished Then
+        If OldState <> LinkStates.Finished Then
             '从完成页面退出时,PageOnContentExit 结束会触发 PageEnter 事件,这会调用 UpdatePanelVisibility
             '如果在现在提前调用了,会丢失完成页面的退出动画
             UpdatePanelVisibility()
@@ -87,7 +89,7 @@
     '创建
     Private Sub Create_MouseLeftButtonUp() Handles PanSelectCreate.MouseLeftButtonUp
         '输入端口号
-        Dim Port As String = MyMsgBoxInput("输入端口", $"在单人游戏的暂停菜单选择 {vbLQ}对局域网开放{vbRQ},然后输入端口数字。{vbCrLf}其实也可以输入其他游戏的端口……",
+        Dim Port As String = MyMsgBoxInput("输入端口", $"在单人游戏的暂停菜单选择 {vbLQ}对局域网开放{vbRQ},然后输入端口数字。{vbCrLf}甚至可以输入其他游戏的端口……嗯……",
             ValidateRules:=New ObjectModel.Collection(Of Validate) From {New ValidateInteger(1024, 65535)},
             HintText:="端口号")
         If Port Is Nothing Then Return
@@ -106,50 +108,31 @@
         NetworkSecret = GenerateRandomCode()
         Log($"[Link] 尝试创建房间,网络名 {NetworkName},网络密码 {NetworkSecret},端口 {ServerPort}")
         '启动
-        ChangeState(States.Loading)
+        ChangeState(LinkStates.Loading)
     End Sub
 
     '加入
-    Private LastCode As String = Nothing
-    Private Sub Join_MouseLeftButtonUp() Handles PanSelectJoin.MouseLeftButtonUp
-        '输入邀请码
+    Private Shared LastCode As String = Nothing
+    ''' <summary>
+    ''' 输入邀请码,切换到联机页并立即加入房间。
+    ''' </summary>
+    Public Shared Sub Join() Handles PanSelectJoin.MouseLeftButtonUp
         Dim Code As String = MyMsgBoxInput("输入邀请码", "输入房主发给你的邀请码。",
-                                           HintText:=If(String.IsNullOrEmpty(LastCode), "", "使用上一次的邀请码:" & LastCode))
+            HintText:=If(String.IsNullOrEmpty(LastCode), "", "使用上一次的邀请码:" & LastCode))
         If Not String.IsNullOrEmpty(LastCode) AndAlso Code IsNot Nothing AndAlso Code = "" Then Code = LastCode
+        If Code Is Nothing Then Return
+        Join(Code)
+    End Sub
+    Public Sub JoinInternal(Code As String)
         If Code Is Nothing Then Return
         '基础格式校验
         Code = Code.Between("【", "】").Between("[", "]") '从完整消息中提取
         Code = Code.ToUpper.Replace("O", "0").Replace("I", "1") '输入修正
-        If Not (Code.Length >= 14 AndAlso Code(0) = "P"c AndAlso Code(5) = "-"c AndAlso Code(11) = "-"c) Then
-            If Code.StartsWithF("U/") Then 'HMCL
-                Hint("请让房主使用 PCL 创建房间!", HintType.Red)
-            ElseIf Code.Length = 10 Then 'PCL CE
-                Hint("请让房主使用非社区版的 PCL 创建房间!", HintType.Red)
-            ElseIf Code.StartsWithF("P") Then '远古版 PCL
-                Hint("你的 PCL 版本与房主的 PCL 版本不一致,或输入的邀请码有误!", HintType.Red)
-            Else
-                Hint("邀请码有误,请让房主使用 PCL 创建房间!", HintType.Red)
-            End If
+        Dim ValidateResult = ValidateCodeFormat(Code)
+        If ValidateResult IsNot Nothing Then
+            Hint(ValidateResult, HintType.Red)
             Return
         End If
-        '离线登录警告
-        If McLoginLoader.State = LoadState.Finished AndAlso McLoginLoader.Output.Type = "Legacy" AndAlso Not Setup.Get("LinkOfflineHint") Then
-            Dim Solution As String
-            If McVersionCurrent IsNot Nothing AndAlso McVersionCurrent.Version.McVersion >= New Version(1, 21, 5) Then
-                Solution = $"请换用正版登录,或是让房主安装 {vbLQ}更高级联机设置{vbRQ} Mod 并禁用正版验证。"
-            ElseIf McVersionCurrent IsNot Nothing AndAlso McVersionCurrent.Version.McVersion >= New Version(1, 12, 0) Then
-                Solution = $"请换用正版登录,或是让房主安装 {vbLQ}自定义局域网联机{vbRQ} Mod 并关闭在线模式。"
-            Else
-                Solution = $"请换用正版登录,或是让房主用服务端开服,关闭 online-mode,然后在创建房间时输入服务端的端口号。"
-            End If
-            Select Case MyMsgBox($"如果不用正版登录可能会进不了服,显示 {vbLQ}无效会话{vbRQ}。" & vbCrLf & Solution,
-                                 "离线登录警告", "继续", "继续且不再提示", "取消", IsWarn:=True)
-                Case 2
-                    Setup.Set("LinkOfflineHint", True)
-                Case 3
-                    Return
-            End Select
-        End If
         '基础信息
         IsServerSide = False
         ServerPort = RadixConvert(Code.Substring(1, 4), 16, 10)
@@ -158,7 +141,45 @@
         Log($"[Link] 尝试加入房间,网络名 {NetworkName},网络密码 {NetworkSecret},端口 {ServerPort}")
         '启动
         LastCode = Code
-        ChangeState(States.Loading)
+        ChangeState(LinkStates.Loading)
+    End Sub
+    Public Shared Function ValidateCodeFormat(Code As String) As String
+        If Code Is Nothing Then Return "邀请码为空!"
+        Code = Code.Between("【", "】").Between("[", "]") '从完整消息中提取
+        Code = Code.ToUpper.Replace("O", "0").Replace("I", "1") '输入修正
+        If Not (Code.Length >= 14 AndAlso Code(0) = "P"c AndAlso Code(5) = "-"c AndAlso Code(11) = "-"c) Then
+            If Code.StartsWithF("U/") Then 'HMCL
+                Return "请让房主使用 PCL 创建房间!"
+            ElseIf Code.Length = 10 Then 'PCL CE
+                Return "请让房主使用非社区版的 PCL 创建房间!"
+            Else
+                Return "邀请码有误,请让房主使用 PCL 创建房间!"
+            End If
+        End If
+        Return Nothing
+    End Function
+
+    '自动加入
+
+    ''' <summary>
+    ''' 切换到联机页并立即加入指定房间。
+    ''' </summary>
+    Public Shared Sub Join(Code As String)
+        If LinkState <> LinkStates.Waiting Then
+            Hint("你已经在联机房间中了!", HintType.Red)
+        ElseIf FrmMain.PageCurrent = FormMain.PageType.Link Then
+            FrmLinkMain.JoinInternal(Code)
+        Else
+            AutoJoinCode = Code
+            FrmMain.PageChange(FormMain.PageType.Link, FormMain.PageSubType.LinkMain)
+        End If
+    End Sub
+    '在进入页面时自动尝试加入房间
+    Private Shared AutoJoinCode As String = Nothing
+    Private Sub PanSelectJoin_Loaded() Handles PanSelectJoin.Loaded
+        If AutoJoinCode Is Nothing Then Return
+        If LinkState = LinkStates.Waiting Then JoinInternal(AutoJoinCode)
+        AutoJoinCode = Nothing
     End Sub
 
 #End Region
@@ -166,7 +187,7 @@
 #Region "加载页面 (Loading | Failed)"
 
     '由 Waiting 或 Failed 状态切换到 Loading
-    Private Sub SwitchToLoading(OldState As States)
+    Private Sub SwitchToLoading(OldState As LinkStates)
         '清理变量
         Peers = Nothing
         FailCount = 0
@@ -180,7 +201,7 @@
     End Sub
 
     '由 Loading 状态切换到 Failed
-    Private Sub SwitchToFailed(OldState As States)
+    Private Sub SwitchToFailed(OldState As LinkStates)
         '加载器与进程状态
         LinkLoader.Abort()
         ProcessStop()
@@ -217,12 +238,12 @@
 
     '取消加载
     Private Sub BtnLoadCancel_Click() Handles BtnLoadCancel.Click
-        ChangeState(States.Waiting)
+        ChangeState(LinkStates.Waiting)
     End Sub
 
     '点击重试
     Private Sub CardLoad_MouseLeftButtonUp() Handles CardLoad.MouseLeftButtonUp
-        ChangeState(States.Loading)
+        ChangeState(LinkStates.Loading)
     End Sub
 
     '进度条
@@ -252,7 +273,7 @@
 #Region "完成页面 (Finished)"
 
     '由 Loading 状态切换到 Finished
-    Private Sub SwitchToFinished(OldState As States)
+    Private Sub SwitchToFinished(OldState As LinkStates)
         '由于只可能从加载器的完成事件触发,不需要管加载器
         UpdatePanelVisibility() '页面的实际切换会由 Loader 调用 MyPageRight 来触发
 
@@ -260,26 +281,27 @@
         If IsServerSide Then
             LabFinishTitle.Text = "已创建房间"
             LabFinishDesc.Text = $"把邀请码发给朋友,让大家加入房间吧!{vbCrLf}邀请码:{NetworkName}-{NetworkSecret}"
-            BtnFinishCopy.Text = "复制邀请码"
             BtnFinishExit.Text = "关闭"
+            BtnFinishCopy.Visibility = Visibility.Visible
+            Copy() '立即复制邀请码
             '下边栏
-            BtnFinishPing.ToolTip = "网络延迟"
-            LineFinishPort.Visibility = Visibility.Visible
             BtnFinishPort.Visibility = Visibility.Visible
             LabFinishPort.Visibility = Visibility.Visible
+            BtnFinishIp.Visibility = Visibility.Collapsed
+            LabFinishIp.Visibility = Visibility.Collapsed
             LabFinishPort.Text = ServerPort
         Else
             LabFinishTitle.Text = "已加入房间"
-            LabFinishDesc.Text = $"在多人游戏中选择直接连接,粘贴地址即可加入游戏!{vbCrLf}服务器地址:{ClientAddress}" '"如果提示无效会话,不要退出联机房间,重新启动游戏即可!"
-            BtnFinishCopy.Text = "复制地址"
+            LabFinishDesc.Text = $"在多人游戏页面的最下方就能找到联机房间!{vbCrLf}注意:使用离线登录时不要手动输入 IP!"
             BtnFinishExit.Text = "离开"
+            BtnFinishCopy.Visibility = Visibility.Collapsed
             '下边栏
-            BtnFinishPing.ToolTip = "与房主的延迟"
-            LineFinishPort.Visibility = Visibility.Collapsed
             BtnFinishPort.Visibility = Visibility.Collapsed
             LabFinishPort.Visibility = Visibility.Collapsed
+            LabFinishIp.Text = ClientAddress
+            BtnFinishIp.Visibility = Visibility.Visible
+            LabFinishIp.Visibility = Visibility.Visible
         End If
-        Copy() '复制信息
         Update() '立即刷新
     End Sub
 
@@ -289,30 +311,37 @@
 
     '退出
     Private Sub BtnFinishExit_Click() Handles BtnFinishExit.Click
-        TryExit(True)
+        TryExit(False, False)
     End Sub
     ''' <summary>
     ''' 退出联机。
     ''' 返回是否弹出了警告窗口并且玩家选择了取消。
     ''' </summary>
-    Public Function TryExit(SendWarning As Boolean) As Boolean
-        If State = States.Waiting OrElse State = States.Failed Then Return False
-        If IsServerSide AndAlso PeopleCount > 1 Then
-            If MyMsgBox("你确定要关闭联机房间吗?" & vbCrLf & "所有玩家都需要重新输入邀请码才可加入游戏!", "关闭房间", "确定", "取消", IsWarn:=True) = 2 Then Return True
+    Public Function TryExit(Slient As Boolean, Closing As Boolean) As Boolean
+        If LinkState = LinkStates.Waiting OrElse LinkState = LinkStates.Failed Then Return False
+        If Not Slient Then
+            If IsServerSide AndAlso PeopleCount > 1 Then
+                If MyMsgBox("你确定要关闭联机房间吗?" & vbCrLf & "所有玩家都需要重新输入邀请码才可加入游戏!", "退出联机", "确定", "取消", IsWarn:=True) = 2 Then Return True
+            ElseIf Closing Then
+                If MyMsgBox(If(IsServerSide, "你确定要关闭联机房间吗?", "你确定要离开联机房间吗?"), "退出联机", "确定", "取消") = 2 Then Return True
+            End If
         End If
-        ChangeState(States.Waiting)
+        ChangeState(LinkStates.Waiting)
         Return False
     End Function
 
-    '复制
+    '复制邀请码
     Private Sub Copy() Handles BtnFinishCopy.Click
-        If IsServerSide Then
-            ClipboardSet($"在 PCL 启动器中输入邀请码【{NetworkName}-{NetworkSecret}】,即可加入联机房间!", False)
-            Hint("已复制邀请码!", HintType.Green)
-        Else
-            ClipboardSet(ClientAddress, False)
-            Hint("已复制服务器地址!", HintType.Green)
-        End If
+        Dim CodeText As String = $"在 PCL 启动器中输入邀请码【{NetworkName}-{NetworkSecret}】,即可加入联机房间!"
+        ClipboardSet(CodeText, False)
+        Setup.Set("LinkLastAutoJoinInviteCode", CodeText)
+        Hint("已复制邀请码!", HintType.Green)
+    End Sub
+
+    '复制 IP
+    Private Sub BtnFinishIp_MouseLeftButtonUp(sender As Object, e As MouseButtonEventArgs) Handles BtnFinishIp.MouseLeftButtonUp
+        ClipboardSet(ClientAddress, False)
+        Hint("已复制服务器地址!", HintType.Green)
     End Sub
 
 #End Region
@@ -334,6 +363,14 @@
     ''' </summary>
     Private ServerPort As Integer
     ''' <summary>
+    ''' 客户端映射后的端口号。
+    ''' </summary>
+    Private ClientPort As Integer
+    ''' <summary>
+    ''' RPC 端口号。
+    ''' </summary>
+    Private RPCPort As Integer
+    ''' <summary>
     ''' 在客户端映射后的地址。
     ''' 除非已作为客户端启动 EasyTier,否则一直为 Nothing。
     ''' </summary>
@@ -414,7 +451,7 @@
             '解压
             Dim ExtractPath As String = RequestTaskTempFolder()
             ExtractFile(PathEasyTier & "EasyTier.zip", ExtractPath,
-                ProgressIncrementHandler:=Sub(Progress) Task.Progress += Progress * 0.06)
+                ProgressIncrementHandler:=Sub(Progress) Task.Progress += Progress * 0.05)
             Dim ExtractedPath As String = New DirectoryInfo(ExtractPath).EnumerateDirectories.FirstOrDefault?.FullName
             Log("[Link] 联机模块解压时的临时路径:" & ExtractedPath)
             CopyDirectory(ExtractedPath, PathEasyTier)
@@ -427,28 +464,42 @@
             File.Delete(PathEasyTier & "EasyTier.zip")
             Setup.Set("LinkEasyTierVersion", ServerVersion)
         End If
-        Task.Progress = 0.1
-        '获取启动参数
+        Task.Progress = 0.07
+        '获取节点列表
+        Dim Peers As List(Of String)
+        Dim CustomPeers As String = Setup.Get("LinkCustomPeer")
+        If String.IsNullOrWhiteSpace(CustomPeers) Then
+            Peers = GetOnlinePeers()
+        Else
+            Peers = CustomPeers.Split(",,".ToCharArray).Select(Function(p) p.Trim).Where(Function(p) Not String.IsNullOrEmpty(p)).ToList()
+            Log("[Link] 使用自定义节点")
+        End If
+        Task.Progress = 0.13
+        '获取空闲端口
         UpdateLoadingPage("正在启动联机模块……", "启动联机模块")
+        Dim FreePorts = FindFreePorts(5, ServerPort)
+        ClientPort = FreePorts(0)
+        RPCPort = FreePorts(1)
+        Dim ListenersPort As Integer = FreePorts(2) '它会占用【当前、当前 +1、当前 +2】共三个端口
+        '获取启动参数
         Dim Arguments As String = ServerConfig("Link")("Argument")
-        Arguments += $" --network-name={NetworkName} --network-secret={NetworkSecret}"
+        Arguments += $" --network-name={NetworkName} --network-secret={NetworkSecret} --listeners {ListenersPort} --rpc-portal {RPCPort}"
         HostName = If(IsServerSide, "Server-", "Client-") & RadixConvert(Math.Abs(Identify.GetHashCode), 10, 36)
         If IsServerSide Then
             Arguments += $" -i 10.114.114.114 --hostname={HostName} --tcp-whitelist={ServerPort} --udp-whitelist={ServerPort}"
         Else
             Arguments += $" -d --hostname={HostName} --tcp-whitelist=0 --udp-whitelist=0"
             '端口转发
-            Dim Port As Integer = GetAvailablePort()
-            ClientAddress = $"localhost:{Port}"
-            Arguments += $" --port-forward tcp://[{IPAddress.IPv6Loopback}]:{Port}/10.114.114.114:{ServerPort}"
-            Arguments += $" --port-forward udp://[{IPAddress.IPv6Loopback}]:{Port}/10.114.114.114:{ServerPort}"
-            Arguments += $" --port-forward tcp://{IPAddress.Loopback}:{Port}/10.114.114.114:{ServerPort}"
-            Arguments += $" --port-forward udp://{IPAddress.Loopback}:{Port}/10.114.114.114:{ServerPort}"
+            ClientAddress = $"localhost:{ClientPort}"
+            Arguments += $" --port-forward tcp://[{IPAddress.IPv6Loopback}]:{ClientPort}/10.114.114.114:{ServerPort}"
+            Arguments += $" --port-forward udp://[{IPAddress.IPv6Loopback}]:{ClientPort}/10.114.114.114:{ServerPort}"
+            Arguments += $" --port-forward tcp://{IPAddress.Loopback}:{ClientPort}/10.114.114.114:{ServerPort}"
+            Arguments += $" --port-forward udp://{IPAddress.Loopback}:{ClientPort}/10.114.114.114:{ServerPort}"
         End If
-        For Each Peer As String In ServerConfig("Link")("Peers")
+        For Each Peer As String In Peers
             Arguments += $" -p=""{Peer}"""
         Next
-        If Not Setup.Get("LinkShareMode") Then Arguments += " --private-mode true"
+        Arguments += " --private-mode true" '老好人模式现在莫得用:If Not Setup.Get("LinkShareMode") Then
         '启动进程
         ProcessStart(Arguments)
         Task.Progress = 0.15
@@ -482,9 +533,9 @@
             '超时判定
             If LastProgress <> Task.Progress Then
                 TimeoutCounter = 0
-            ElseIf TimeoutCounter < 20 Then
+            ElseIf TimeoutCounter < 30 * 2 Then
                 TimeoutCounter += 1
-            Else '进度停滞超过 10s
+            Else '进度停滞超过 30s
                 Select Case PeerCount
                     Case -1 'CLI 无返回
                         Panic("无法启动联机模块", "近期日志:" & vbCrLf & LogHistory.Join(vbCrLf))
@@ -497,6 +548,49 @@
         Loop Until Task.IsAborted
         If Task.IsAborted Then Throw New ThreadInterruptedException
     End Sub
+    ''' <summary>
+    ''' 从在线配置和 API 获取节点列表。
+    ''' </summary>
+    Private Function GetOnlinePeers() As List(Of String)
+        Dim Peers As List(Of String) = ServerConfig("Link")("Peers").Select(Function(p) p.ToString).ToList()
+        Try
+            '从 API 获取节点列表
+            Dim BlackList As List(Of String) = ServerConfig("Link")("PeersBlackList").Select(Function(p) p.ToString).ToList() '黑名单
+            Dim CentralNodes As New List(Of String)
+            Dim RandomNodes As New List(Of Tuple(Of String, Double))
+            For Each Node As JObject In CType(GetJson(NetRequestByClientRetry("https://uptime.easytier.cn/api/nodes?page=1&per_page=200")), JObject)("data")("items")
+                '状态检查
+                If Node("protocol").ToString <> "tcp" Then Continue For
+                If Node("current_health_status").ToString <> "healthy" Then Continue For
+                If Not Node("is_active").ToObject(Of Boolean) Then Continue For
+                If Not Node("is_approved").ToObject(Of Boolean) Then Continue For
+                Dim Tags = Node("tags").Select(Function(t) t.ToString).ToList
+                If Not Tags.Contains("国内") Then Continue For
+                If Tags.Contains("即将下线") Then Continue For
+                Dim Address As String = Node("address").ToString
+                If BlackList.Contains(Address) Then Continue For
+                '添加节点
+                If Tags.Contains("MC") Then
+                    CentralNodes.Add(Address)
+                Else
+                    If Not Node("allow_relay").ToObject(Of Boolean) Then Continue For
+                    If Node("usage_percentage").ToObject(Of Double) = 0 Then Continue For '或许节点有问题才导致是 0 负载
+                    RandomNodes.Add(New Tuple(Of String, Double)(
+                        Address,
+                        Node("usage_percentage").ToObject(Of Double) * (103 - Node("health_percentage_24h").ToObject(Of Double)))) '负载,越低越好
+                End If
+            Next
+            RandomNodes = RandomNodes.OrderBy(Function(n) n.Item2).ToList()
+            Log($"[Link] 获取到 {CentralNodes.Count} 个中心节点,{RandomNodes.Count} 个随机节点")
+            '选择节点
+            Dim RandomCount As Integer = ServerConfig("Link")("RandomPeer").ToObject(Of Integer)
+            If RandomNodes.Count < RandomCount Then Throw New Exception($"可用的随机节点数量不足,需要 {RandomCount} 个,实际 {RandomNodes.Count} 个")
+            Peers = CentralNodes.Concat(RandomNodes.Take(RandomCount).Select(Function(n) n.Item1)).ToList()
+        Catch ex As Exception
+            Log(ex, "获取节点列表失败,联机质量可能受到影响", LogLevel.Hint)
+        End Try
+        Return Peers
+    End Function
 
 #End Region
 
@@ -544,26 +638,14 @@
     ''' 出现意外错误,给出错误信息并结束联机。
     ''' </summary>
     Private Sub Panic(Brief As String, Detail As String)
-        If State = States.Loading Then
+        If LinkState = LinkStates.Loading Then
             FailReason = Brief
             LinkLoader.Failed(New Exception(Detail))
         Else
             MyMsgBox(Detail, "联机出错:" & Brief, IsWarn:=True)
-            ChangeState(States.Waiting)
+            ChangeState(LinkStates.Waiting)
             Telemetry("联机失败", "Exception", FilterUserName(Brief & ":" & Detail, "*"))
         End If
-        '收集到的 CLI 错误:
-
-        'Error: Timeout : deadline has elapsed
-        'Caused by
-        '    deadline has elapsed
-
-        'Error: failed to get peer manager client
-        'Caused by
-        '    0:  rust tun error failed to connect to server: Url {scheme:  "tcp", cannot_be_a_base: false, username: "", password: None, host: Some(Domain("127.0.0.1")), port: Some(15888), path: "", query: None, fragment: None }
-        '    1:  failed to connect to server: Url {scheme:  "tcp", cannot_be_a_base: false, username: "", password: None, host: Some(Domain("127.0.0.1")), port: Some(15888), path: "", query: None, fragment: None }
-        '    2:  IO error
-        '    3:  由于目标计算机积极拒绝, 无法连接。 (os error 10061)
     End Sub
 
     ''' <summary>
@@ -656,32 +738,33 @@
         ''' 名称。
         ''' </summary>
         Public ReadOnly Name As String
+        ''' <summary>
+        ''' 连接方式。
+        ''' </summary>
+        Public ReadOnly Cost As String
 
         ''' <summary>
-        ''' 从 CLI 给出的信息行分析对应的数据。
+        ''' 从 CLI 给出的信息分析对应的数据。
         ''' </summary>
-        Public Sub New(Info As String)
-            '具体每个部分的索引见 GetPeerData()
-            Dim Parts = Info.Split("|").Select(Function(s) If(s.All(Function(c) c = " "c), s, s.Trim)).Where(Function(s) s <> "").ToList
-            If Parts.Count <> 10 Then Throw New Exception($"信息列数有误")
-            '延迟
-            Ping = If(Parts(3) = "-", 0, Parts(3))
+        Public Sub New(Info As JObject)
             '类别
-            Dim PeerName = Parts(1)
+            Dim PeerName = Info("hostname").ToString
             If PeerName = HostName Then
                 Type = Types.Self
             ElseIf PeerName.StartsWithF("Client") Then
                 Type = Types.Client
-            ElseIf Parts(0).StartsWithF("10.114.114.114") Then '只允许这个 IP 作为房主,避免网络被多个房主搞炸的情况
+            ElseIf Info("ipv4") = "10.114.114.114" Then '只允许这个 IP 作为房主,避免网络被多个房主搞炸的情况
                 Type = Types.Server
             Else
                 Type = Types.Misc
             End If
-            '主机名
+            '基础信息
+            Ping = If(Info("lat_ms").ToString = "-", 0, Info("lat_ms").ToString)
             Name = PeerName
+            Cost = Info("cost")
         End Sub
         Public Overrides Function ToString() As String
-            Return $"{Type} - {Name} - Ping {Ping:0.0}ms"
+            Return $"{Type} - {Name} - Ping {Ping:0.0}ms [{Cost}]"
         End Function
     End Class
 
@@ -705,12 +788,12 @@
         '| 10.114.114.114/24 | Server-J6P6IW         | p2p      | 5.63    | 0.0% | 1.65 kB | 1.64 kB | udp    | PortRestricted | 2.4.5-4c4d172e |
         '| 10.114.114.114/24 | Server-J6PHIW (连接中) | relay(2) | 1000.00 | 0.0% | 0 B     | 0 B     |        | PortRestricted | 2.4.5-4c4d172e |
         Try
-            Dim CliResult = StartProcessAndGetOutput(PathEasyTier & "联机模块 CLI.exe", "peer", 2000, Encoding:=Encoding.UTF8, PrintLog:=False)
+            Dim CliResult = StartProcessAndGetOutput(PathEasyTier & "联机模块 CLI.exe", $"-o json -p 127.0.0.1:{RPCPort} peer", 2000, Encoding:=Encoding.UTF8, PrintLog:=False)
             '解析
-            If Not CliResult.Contains("lat(ms)") Then Throw New Exception("CLI 调用失败:" & vbCrLf & CliResult)
-            If GetUuid() Mod If(ModeDebug, 4, 30) = 0 Then Log("[EasyTier] CLI 输出抽样:" & vbCrLf & CliResult)
+            If Not CliResult.Contains("lat_ms") Then Throw New Exception("CLI 调用失败:" & vbCrLf & CliResult)
+            If GetUuid() Mod If(ModeDebug, 23, 103) = 0 Then Log("[EasyTier] CLI 输出抽样:" & vbCrLf & CliResult)
             Dim NewPeers As New List(Of Peer)
-            For Each Line In CliResult.Split(vbCrLf.ToCharArray, StringSplitOptions.RemoveEmptyEntries).Skip(2)
+            For Each Line As JObject In CType(GetJson(CliResult), JArray).Skip(1)
                 Try
                     Dim Peer = New Peer(Line)
                     If Peer.Type = Peer.Types.Self Then Continue For '自己
@@ -724,7 +807,7 @@
             FailCount = 0
         Catch ex As Exception
             Log(ex, "获取节点信息失败")
-            If State = States.Finished Then
+            If LinkState = LinkStates.Finished Then
                 FailCount += 1
                 If FailCount >= 4 Then Panic("获取节点信息失败", ex.Message)
             End If
@@ -741,18 +824,26 @@
     ''' 0 代表尚不可用。
     ''' </summary>
     Private Function GetPeerPing() As Double
-        If Peers Is Nothing Then Return 0
-        Dim PingTargets As IEnumerable(Of Peer)
+        Dim Peer = GetTargetPeer()
+        If Peer Is Nothing Then Return 0
+        Return Peer.Ping
+    End Function
+    ''' <summary>
+    ''' 服务端会返回所有节点中 Ping 的那一个,客户端会返回服务端。
+    ''' 若没有则为 Nothing。
+    ''' </summary>
+    Private Function GetTargetPeer() As Peer
+        If Peers Is Nothing Then Return Nothing
+        Dim Targets As IEnumerable(Of Peer)
         If IsServerSide Then
-            PingTargets = Peers
-        Else
-            PingTargets = Peers.Where(Function(p) p.Type = Peer.Types.Server)
-        End If
-        If Not PingTargets.Any Then
-            Return 0
+            Targets = Peers.Where(Function(p) p.Ping > 0)
         Else
-            Return Math.Max(1, PingTargets.Select(Function(p) p.Ping).Min())
+            Targets = Peers.Where(Function(p) p.Type = Peer.Types.Server AndAlso p.Ping > 0)
         End If
+        If Not Targets.Any Then Return Nothing
+        '返回 Ping 大于 0 且最低的那个
+        Dim MinPing = Targets.Min(Function(p) p.Ping)
+        Return Targets.First(Function(p) p.Ping = MinPing)
     End Function
 
     ''' <summary>
@@ -768,7 +859,7 @@
 
 #End Region
 
-#Region "定时状态更新"
+#Region "定时任务"
 
     '启动
     Private IsTimerStarted As Boolean = False
@@ -781,13 +872,13 @@
                 Try
                     Thread.Sleep(200)
                     Counter += 200
-                    '每 4 秒执行一次
-                    If Counter >= 4000 Then
+                    '每秒执行一次
+                    If Counter >= 1000 Then
                         Counter = 0
                         Update()
                     End If
                     '每 200ms 更新进度条
-                    If State = States.Loading Then RunInUi(AddressOf UpdateProgressBar)
+                    If LinkState = LinkStates.Loading Then RunInUi(AddressOf UpdateProgressBar)
                 Catch ex As Exception
                     Log(ex, "联机模块主时钟出错", LogLevel.Feedback)
                     Thread.Sleep(10000)
@@ -796,9 +887,10 @@
         End Sub, "Link Timer")
     End Sub
 
-    '每 4 秒或进入页面时更新一次信息
+    '每秒或进入页面时触发
+    Private BroadcastSocket As New Socket(SocketType.Dgram, ProtocolType.Udp)
     Private Sub Update() Handles Me.Loaded
-        If State <> States.Finished Then Return
+        If LinkState <> LinkStates.Finished Then Return
         '重新获取信息
         SyncLock RefreshPeerLoader.LockState
             If RefreshPeerLoader.State <> LoadState.Loading Then RefreshPeerLoader.Start(IsForceRestart:=True)
@@ -808,13 +900,25 @@
             RunInUi(
             Sub()
                 Dim Ping As Double = GetPeerPing()
+                Dim RelayLayer As Integer = If(GetTargetPeer().Cost.RegexSeek("(?<=relay\()\d+") Is Nothing,
+                    0, Val(GetTargetPeer().Cost.RegexSeek("(?<=relay\()\d+")) - 1)
+                '更新 Ping 显示
                 If Ping Mod 500 = 0 OrElse $"{Ping:0.0}" = "1.0" OrElse FailCount > 0 Then
                     LabFinishPing.Text = "连接中"
                     AniStop("Link Logo Rotation")
                 Else
-                    LabFinishPing.Text = If(Ping >= 10, $"{Ping:0} ms", $"{Ping:0.0} ms")
+                    LabFinishPing.Text =
+                        If(RelayLayer > 0, If(RelayLayer > 1, $"中继 {RelayLayer} · ", "中继 · "), "") & '使用中继连接时显示 “中继” 前缀
+                        If(Ping >= 10, $"{Ping:0} ms", $"{Ping:0.0} ms")
                     AniStart(AaRotateTransform(ImgFinishLogo, 500, 5000), "Link Logo Rotation") 'Logo 旋转动画
                 End If
+                '更新 Ping 的 Tooltip 显示
+                Dim Tooltip As String = If(IsServerSide, "网络延迟", "与房主的延迟")
+                If RelayLayer Then Tooltip &= If(IsServerSide,
+                    $"(你的网络环境较差,正经过 {RelayLayer} 层中继,可能会有点卡)",
+                    $"(你或者房主的网络环境较差,正经过 {RelayLayer} 层中继,可能会有点卡)")
+                BtnFinishPing.ToolTip = Tooltip
+                '更新人数显示
                 LabFinishPlayer.Text = PeopleCount & "  人"
             End Sub)
         End If
@@ -827,9 +931,20 @@
         End If
         If Not IsServerSide AndAlso Not Peers.Any(Function(p) p.Type = Peer.Types.Server) Then
             MyMsgBox("房主已离开房间!", "联机结束")
-            ChangeState(States.Waiting)
+            ChangeState(LinkStates.Waiting)
             Return
         End If
+        '广播联机房间端口
+        If Not IsServerSide Then
+            Try
+                BroadcastSocket.SendTo(
+                    Encoding.UTF8.GetBytes($"[MOTD]PCL 联机房间[/MOTD][AD]{ClientPort}[/AD]"),
+                    SocketFlags.None,
+                    New IPEndPoint(IPAddress.Loopback, 4445))
+            Catch ex As Exception
+                Log(ex, "广播联机房间端口失败")
+            End Try
+        End If
     End Sub
     ''' <summary>
     ''' 检查联机模块是否崩溃。

+ 573 - 216
Plain Craft Launcher 2/Pages/PageOther/PageOtherAbout.xaml

@@ -46,6 +46,7 @@
                         <RowDefinition Height="45" />
                         <RowDefinition Height="45" />
                         <RowDefinition Height="45" />
+                        <RowDefinition Height="45" />
                     </Grid.RowDefinitions>
                     <Grid.ColumnDefinitions>
                         <ColumnDefinition Width="40" />
@@ -58,11 +59,13 @@
                     <local:MyButton Text="打开百科" Grid.Row="1" Grid.Column="2" Height="35" local:CustomEventService.EventType="打开网页" local:CustomEventService.EventData="https://www.mcmod.cn" />
                     <local:MyListItem Title="z0z0r4" Margin="-5,0,0,0" IsHitTestVisible="False" Grid.ColumnSpan="2" Info="提供了 MCIM 社区资源镜像源和帮助库图床!" Grid.Row="2" Grid.Column="1" />
                     <local:MyButton Text="MCIM 主页" Grid.Row="2" Grid.Column="2" Height="35" local:CustomEventService.EventType="打开网页" local:CustomEventService.EventData="https://github.com/mcmod-info-mirror" />
-                    <local:MyListItem Title="00ll00" Margin="-5,0,0,0" IsHitTestVisible="False" Grid.ColumnSpan="2" Info="提供了 Java Launch Wrapper 和一些重要服务支持!" Grid.Row="3" Grid.Column="1" />
-                    <local:MyListItem Title="Patrick" Margin="-5,0,0,0" IsHitTestVisible="False" Grid.ColumnSpan="2" Info="设计并制作了 PCL 图标,让我从做图标的水深火热中得到了解脱……" Grid.Row="4" Grid.Column="1" />
-                    <local:MyListItem Title="Hao_Tian" Margin="-5,0,0,0" IsHitTestVisible="False" Grid.ColumnSpan="2" Info="在内测中找出了一大堆没人想得到的诡异 Bug,有非同寻常的 Bug 体质" Grid.Row="5" Grid.Column="1" />
-                    <local:MyListItem Title="Minecraft 中文论坛" Margin="-5,0,15,0" IsHitTestVisible="False" Info="虽然已经关站了,但感谢此前提供了 MCBBS 镜像源……" Grid.Row="6" Grid.Column="1" />
-                    <local:MyListItem Title="PCL 内群的各位" Margin="-5,0,0,0" IsHitTestVisible="False" Grid.ColumnSpan="2" Info="感谢内群的沙雕网友们这么久以来对我和 PCL 的支持与鼓励!" Grid.Row="7" Grid.Column="1" />
+                    <local:MyListItem Title="EasyTier" Margin="-5,0,0,0" IsHitTestVisible="False" Grid.ColumnSpan="2" Info="提供了联机模块!" Grid.Row="3" Grid.Column="1" />
+                    <local:MyButton Text="GitHub 页面" Grid.Row="3" Grid.Column="2" Height="35" local:CustomEventService.EventType="打开网页" local:CustomEventService.EventData="https://github.com/EasyTier/EasyTier" />
+                    <local:MyListItem Title="00ll00" Margin="-5,0,0,0" IsHitTestVisible="False" Grid.ColumnSpan="2" Info="提供了 Java Launch Wrapper 和一些重要服务支持!" Grid.Row="4" Grid.Column="1" />
+                    <local:MyListItem Title="Patrick" Margin="-5,0,0,0" IsHitTestVisible="False" Grid.ColumnSpan="2" Info="设计并制作了 PCL 图标,让我从做图标的水深火热中得到了解脱……" Grid.Row="5" Grid.Column="1" />
+                    <local:MyListItem Title="Hao_Tian" Margin="-5,0,0,0" IsHitTestVisible="False" Grid.ColumnSpan="2" Info="在内测中找出了一大堆没人想得到的诡异 Bug,有非同寻常的 Bug 体质" Grid.Row="6" Grid.Column="1" />
+                    <local:MyListItem Title="Minecraft 中文论坛" Margin="-5,0,15,0" IsHitTestVisible="False" Info="虽然已经关站了,但感谢此前提供了 MCBBS 镜像源……" Grid.Row="7" Grid.Column="1" />
+                    <local:MyListItem Title="PCL 内群的各位" Margin="-5,0,0,0" IsHitTestVisible="False" Grid.ColumnSpan="2" Info="感谢内群的沙雕网友们这么久以来对我和 PCL 的支持与鼓励!" Grid.Row="8" Grid.Column="1" />
                     <Image Source="/Plain Craft Launcher 2;component/Images/Heads/bangbang93.png" Grid.Row="0" Margin="3">
                         <Image.Clip>
                             <EllipseGeometry Center="17 17" RadiusX="17" RadiusY="17" />
@@ -78,27 +81,32 @@
                             <EllipseGeometry Center="17 17" RadiusX="17" RadiusY="17" />
                         </Image.Clip>
                     </Image>
-                    <Image Source="/Plain Craft Launcher 2;component/Images/Heads/00ll00.png" Grid.Row="3" Margin="3">
+                    <Image Source="/Plain Craft Launcher 2;component/Images/Heads/EasyTier.png" Grid.Row="3" Margin="3">
+                        <Image.Clip>
+                            <EllipseGeometry Center="17 17" RadiusX="17" RadiusY="17" />
+                        </Image.Clip>
+                    </Image>
+                    <Image Source="/Plain Craft Launcher 2;component/Images/Heads/00ll00.png" Grid.Row="4" Margin="3">
                         <Image.Clip>
                             <EllipseGeometry Center="17 17" RadiusX="17" RadiusY="17" />
                         </Image.Clip>
                     </Image>
-                    <Image Source="/Plain Craft Launcher 2;component/Images/Heads/Patrick.png" Grid.Row="4" Margin="3">
+                    <Image Source="/Plain Craft Launcher 2;component/Images/Heads/Patrick.png" Grid.Row="5" Margin="3">
                         <Image.Clip>
                             <EllipseGeometry Center="17 17" RadiusX="17" RadiusY="17" />
                         </Image.Clip>
                     </Image>
-                    <Image Source="/Plain Craft Launcher 2;component/Images/Heads/Hao_Tian.jpg" Grid.Row="5" Margin="3">
+                    <Image Source="/Plain Craft Launcher 2;component/Images/Heads/Hao_Tian.jpg" Grid.Row="6" Margin="3">
                         <Image.Clip>
                             <EllipseGeometry Center="17 17" RadiusX="17" RadiusY="17" />
                         </Image.Clip>
                     </Image>
-                    <Image Source="/Plain Craft Launcher 2;component/Images/Heads/MCBBS.png" Grid.Row="6" Margin="3">
+                    <Image Source="/Plain Craft Launcher 2;component/Images/Heads/MCBBS.png" Grid.Row="7" Margin="3">
                         <Image.Clip>
                             <EllipseGeometry Center="17 17" RadiusX="17" RadiusY="17" />
                         </Image.Clip>
                     </Image>
-                    <Image Source="/Plain Craft Launcher 2;component/Images/Heads/PCL2.png" Grid.Row="7" Margin="3">
+                    <Image Source="/Plain Craft Launcher 2;component/Images/Heads/PCL2.png" Grid.Row="8" Margin="3">
                         <Image.Clip>
                             <EllipseGeometry Center="17 17" RadiusX="17" RadiusY="17" />
                         </Image.Clip>
@@ -107,217 +115,566 @@
             </local:MyCard>
             <local:MyCard Margin="0,0,0,15" Title="赞助者">
                 <StackPanel Margin="25,40,10,20">
-                    <TextBlock HorizontalAlignment="Left" Text="以下是 2025 年 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="lecoe" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="QIUQI" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="Aquadtr" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="stb" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="mco" />
-                        <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="Le Play" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="烨神" />
-                        <TextBlock Width="240" Margin="0,1.5" Text="Kamazi_Yuka5201" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="滚动的拉布拉多" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="王牟" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="Lazarus" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="幻觉" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="凌天" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="lIIIllIIllIIl" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="Zsol" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="榴莲" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="Night Voyager" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="JOHNJIANG" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="柒月" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="不温柔先森" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="Freewind" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="纯萧子" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="扇" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="Amturester" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="maigm" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="JO23" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="JCNB" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="星尘" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="姜桐桐233" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="AkaneRyoba" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="南山必胜客" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="57" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="咸菜萝卜煲" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="shawnlong" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="DDNGSZX1" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="KaguraZaka" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="谶纛" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="666" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="betwangzai" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="卑微小林" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="fjvg" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="TH-x" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="Q" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="清鸢" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="P·咕·D·咕咕·F" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="顾木" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="LAZY" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="沙发上的沙发" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="有熊子来" />
-                        <TextBlock Width="240" Margin="0,1.5" Text="月下誓约,予爱以心" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="超级白给马" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="fwlqpalzmd" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="安执妄dying" />
-                        <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="zz" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="爱炫鱼的猫" />
+                    <TextBlock HorizontalAlignment="Left" Text="以下是 2025 年 10 月的高级赞助者们!感谢各位对 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="Albus" />
+                        <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="apoooooo" />
+                        <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="Ding" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="yi9999" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="muo" />
+                        <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="L." />
+                        <TextBlock Width="120" Margin="0,1.5" Text="??????????)?" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="温雅" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="MingChuYa" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="S????? . ?" />
+                        <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="MCMIAO" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="熠惊" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="emm" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="十月." />
+                        <TextBlock Width="120" Margin="0,1.5" Text="Mark_ShaoYang" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="左" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="Crocoldilopolis" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="!" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="风息" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="by烟火" />
+                        <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="巫元dry" />
+                        <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="SmileRm" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="光" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="SquareBlock" />
+                        <TextBlock Width="240" Margin="0,1.5" Text="失去梦想的GGbond" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="Kuni" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="Herr" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="周清风" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="kirito" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="Tt" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="柳絮随风行" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="trav" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="Danielisdoge" />
+                        <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="zero" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="许愿流星雨" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="YiHuwuyue" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="CenturionSC" />
+                        <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="Caryee" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="蓝涯" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="柒拾叁" />
+                        <TextBlock Width="240" 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="CT" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="酋长想去欧洲" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="MOYO_" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="四季的猫." />
+                        <TextBlock Width="120" Margin="0,1.5" Text="Jcey" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="Nefelibata." />
+                        <TextBlock Width="120" Margin="0,1.5" Text="领域星" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="cnp" />
+                        <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="wax" />
+                        <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="Freezinker" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="鱼丸" />
+                        <TextBlock Width="240" Margin="0,1.5" Text="NORMAL_MAN36" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="阿希佩尔" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="kikimmo" />
+                        <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="江上tipsy" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="句号" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="Master" />
+                        <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="NOBODY112" />
+                        <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="EasyOrange" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="MATH算珠" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="暮光Ts" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="洛秋" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="瑾" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="Tenno" />
+                        <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="Rei" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="lxh123123123" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="瓷" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="yyc我稀饭你" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="似水请客" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="冬季の信物" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="Y先生" />
+                        <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="ZJD" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="别吵我在法考" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="WLan" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="457ssu" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="liu" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="贤" />
                         <TextBlock Width="120" Margin="0,1.5" Text="玄月" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="BRfake" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="Lucien_Liu" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="煎bingo子" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="dailiweier" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="korfr" />
+                        <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="XINA-33" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="Temmie" />
+                        <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="LightingPriest" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="sxdxm" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="GYWTT" />
+                        <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="sul" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="静心涵养" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="均就均吧" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="Tuski_Velpro" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="望江寒" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="我该要E了" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="lxx" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="MX丶" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="乘风9527" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="修狗不是狗" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="奇怪的深渊增加了" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="森森1025" />
+                        <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="她面有愠色" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="shengli" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="哈基鸭" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="苏言`" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="cc的毅" />
+                        <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="LBDLXLZT" />
+                        <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="qiji_SaMa" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="是我小白鸭~" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="Yylinmu" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="zzz" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="遨菡" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="欧欧欧" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="Freezing" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="潜汐" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="waaiu" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="小劫" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="Lemon0904" />
+                        <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="JiuJiu" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="阋yee" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="qsiwsi" />
+                        <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="ZYX" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="玦" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="浬江河" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="ZERO" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="猫猫qwq" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="shark" />
+                        <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="TTT" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="赵云撤" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="岩壑之崩" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="Fox Hound" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="Alon.E." />
+                        <TextBlock Width="120" Margin="0,1.5" Text="湺" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="陳拾憶" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="kwzddz" />
+                        <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="Q7" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="阿卡找你玩" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="月月" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="POCKY" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="橙子饱宝" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="空城风雨" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="Carlmu" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="日雨云曇" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="Caerphilly" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="Andy Wang" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="Kepler" />
+                        <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="夜Ylz" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="不知道唉kk" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="墨染星云间" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="-Trespassin." />
+                        <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="慕可OvO" />
+                        <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="MOMOHAN" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="希瓦大陆_Hitable" />
+                        <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="okufir" />
+                        <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="Kakiko" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="摩卡茉莉" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="长忆安思" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="Solomon" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="博麗靈夢" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="CMMing" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="择日再起床" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="逆黑C" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="星恒" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="销" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="XingLing2333" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="Lesonmol" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="a" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="格拉索夫司机" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="LDG" />
+                        <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="JadePolarise" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="不爱吃饭的Hog" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="莉莉大饺子" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="yu" />
+                        <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="LordyTheQDuck" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="衔纸人" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="粉色妖精小姐?" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="kongfan" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="白杨之下" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="Eme.b" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="熊猫" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="颜5236" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="KK" />
+                        <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="Escape Star" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="LSEN志恒" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="Azqs7109" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="艾雅法拉的狗" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="????????" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="LOWN" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="cuu7878" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="RemixQQ" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="CANYUEX" />
+                        <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="wujijuan" />
+                        <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="qq1967131327" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="sence4910" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="HilkK" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="ZThengao" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="玖镜Sama" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="Glx?" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="派大星" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="河边鸺葵" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="SoftSui" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="徐家胤" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="至夏" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="溯洄SWZM" />
+                        <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="XLMX" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="雲墨丶雪风" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="每天都是上上签" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="Bright" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="UFO君" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="z001" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="琥色" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="MaxQi" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="姜淼淼" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="Chenluoxcly" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="南宫墨白" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="白晓" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="ChengYhy" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="陆壹" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="Agoni" />
+                        <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="imsunxinhao" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="在我嘴里种水稻" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="浮世三千" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="blue sky" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="wujiayi" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="XIAOXI" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="景天鸽" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="24598" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="世谈茶楼" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="jwl" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="Saki" />
+                        <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="neltharion" />
+                        <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="lalailoveyou" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="EternalSinDusk" />
+                        <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="BIOKL" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="你先别急" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="MuMAA" />
+                        <TextBlock Width="240" Margin="0,1.5" Text="擻齺獼豳鏚嬼嬭鼬乸鑽麣覊" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="风眠" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="hgmzyyy" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="Danc1n9" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="doodo" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="FrostNova" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="mc" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="柒" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="迷途" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="XU." />
+                        <TextBlock Width="120" Margin="0,1.5" Text="八云源" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="qbn5" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="许诺霓虹" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="X-ran" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="微风" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="阿米诺斯" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="玄纪2006" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="666" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="恋某人-柏然" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="The_Crispy" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="电脑and病毒哥" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="W" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="jys" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="lonelife" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="离断幽" />
                         <TextBlock Width="120" Margin="0,1.5" Text="对方正在输入..." />
-                        <TextBlock Width="120" Margin="0,1.5" Text="hakureireimu" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="wwxa2019" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="TAIGA" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="墨玉" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="Jane" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="雪下丨残影" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="未命名3742" />
-                        <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="ATH9" />
-                        <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="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="准江月" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="蓝叶" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="ELUCIDATE" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="兔饼干哈哈" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="Styx誓约" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="V" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="月芸柔" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="灯火鬼魂" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="A" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="项刀关志" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="剑鱼776" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="叶明心" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="Ashlxy" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="小时" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="fisher426" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="老罗" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="带我去跳海" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="Jogycjh" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="F" />
+                        <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="YanTY" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="勿念fmj" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="道瑶" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="JerryGo" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="HAJ_IMI" />
+                        <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="月野" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="烛龙" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="Rock god-Morax" />
                         <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="山有木兮325" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="37号村民" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="白承宣" />
-                        <TextBlock Width="240" 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="NeonSoda" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="UNICORN" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="红石beaker" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="EliasLSK" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="思考人生" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="L" />
-                        <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="FAMS" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="会变身的栖仔" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="baka王" />
-                        <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="Xc_AcE" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="@6#" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="molFish" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="雪见" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="AAALLLAAANNN" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="华氏451" />
-                        <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="八云蓝LIN" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="LittleBlue" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="老梦" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="动漫男主" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="Red_橙子" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="Junmucheng" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="无印" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="窗前露" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="1111111" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="什雨" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="七日 SEVENDAYS" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="Gǔdù" />
-                        <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="240" Margin="0,1.5" Text="小狗很担心你有没有好好喝水" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="hjhmeibao" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="网络白字话事人" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="想要点好运" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="Timmy1950" />
-                        <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="HansOffice" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="466某某某" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="zztzzy" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="辉光离子管" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="联开开" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="XIAOSHUAI" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="KMYLS" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="聽音" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="oPzPo" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="dream" />
+                        <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="HPLY" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="淡然a" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="白玉京" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="Ykir" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="三千" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="溪峡" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="avenqyx" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="xxz" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="tytd" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="yezhi" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="落子不悔" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="chenge886" />
+                        <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="晨099" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="Ado" />
+                        <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="240" Margin="0,1.5" Text="Black_Banana_Cat" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="君染" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="XiaoMingPro" />
+                        <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="123" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="Zik yeung" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="wihz" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="九平" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="liu" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="PickStars" />
-                        <TextBlock Width="240" Margin="0,1.5" Text="我真的事仁济啊(恼)" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="Zikyeung" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="zzz_10728701" />
+                        <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="zzzzzjy" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="南有乔树" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="wsaml" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="韬光养晦" />
                         <TextBlock Width="120" Margin="0,1.5" Text="李白" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="HurgerLiPy" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="Crishen70400" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="孤独" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="夏末彡微凉" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="山本樱桃不是df" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="陶牧馆长" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="一二三四" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="17382073935" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="不知道" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="重庆你周哥" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="熳ai" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="Rainbow Stars" />
-                        <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="一只小孽QAQ" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="五度左右" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="咖喱鱼" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="千叶GG" />
-                        <TextBlock Width="120" Margin="0,1.5" Text="泽木_Zemu" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="xsh" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="ChatCTL" />
+                        <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="240" Margin="0,1.5" Text="没事还有俾斯麦兜底" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="Lewis" />
+                        <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="dedf" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="Adminstrator" />
+                        <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="wuzhi718" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="琳" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="fycn" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="风铃末末?" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="漫游池塘中" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="james" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="jiekun" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="gugugugugu" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="Zomib" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="乱想的名字" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="fish" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="Kfeadow" />
+                        <TextBlock Width="240" Margin="0,1.5" Text="MeltyAcoustAmber" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="Quan_Q" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="旋叶" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="YanXiaXia__" />
+                        <TextBlock Width="120" Margin="0,1.5" Text="崩坏坏sama" />
+                        <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="50MB" />
                     </WrapPanel>
                     <Grid Height="35">
                         <Grid.ColumnDefinitions>

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

@@ -111,8 +111,9 @@
         {"LaunchAdvanceGraphicCard", New SetupEntry(True, Source:=SetupSource.Registry)},
         {"LaunchRamType", New SetupEntry(0)},
         {"LaunchRamCustom", New SetupEntry(15)},
-        {"LinkOfflineHint", New SetupEntry(False, Source:=SetupSource.Registry)},
+        {"LinkLastAutoJoinInviteCode", New SetupEntry("", Source:=SetupSource.Registry)},
         {"LinkShareMode", New SetupEntry(True, Source:=SetupSource.Registry)},
+        {"LinkCustomPeer", New SetupEntry("")},
         {"LinkEasyTierVersion", New SetupEntry(-1, Source:=SetupSource.Registry)},
         {"ToolHelpChinese", New SetupEntry(True, Source:=SetupSource.Registry)},
         {"ToolDownloadThread", New SetupEntry(63, Source:=SetupSource.Registry)},

+ 2 - 2
Plain Craft Launcher 2/Pages/PageSetup/PageSetupLaunch.xaml

@@ -86,14 +86,14 @@
                             </local:MyComboBox>
                             <local:MyTextBox Padding="0,0,5,0" Visibility="Collapsed" Grid.Column="1" Margin="50,0,0,0" x:Name="TextArgumentWindowWidth" Tag="LaunchArgumentWindowWidth" Width="60" HorizontalContentAlignment="Center" Text="854">
                                 <local:MyTextBox.ValidateRules>
-                                    <local:ValidateInteger Min="1" Max="9999" />
+                                    <local:ValidateInteger Min="1" Max="99999" />
                                 </local:MyTextBox.ValidateRules>
                             </local:MyTextBox>
                             <TextBlock x:Name="LabArgumentWindowMiddle" Visibility="Collapsed" Grid.Column="2" Text=" × " VerticalAlignment="Center" FontSize="18" />
                             <local:MyTextBox Padding="0,0,5,0" Visibility="Collapsed" Grid.Column="3" Width="60" HorizontalContentAlignment="Center" x:Name="TextArgumentWindowHeight" Tag="LaunchArgumentWindowHeight" Text="480"
                                           ToolTip="Forge 1.12.2 等个别版本存在 Bug,会导致高度设定无效" ToolTipService.Placement="Right" ToolTipService.HorizontalOffset="5">
                                 <local:MyTextBox.ValidateRules>
-                                    <local:ValidateInteger Min="1" Max="9999" />
+                                    <local:ValidateInteger Min="1" Max="99999" />
                                 </local:MyTextBox.ValidateRules>
                             </local:MyTextBox>
                         </Grid>

+ 25 - 4
Plain Craft Launcher 2/Pages/PageSetup/PageSetupLink.xaml

@@ -6,11 +6,32 @@
     PanScroll="PanBack">
     <local:MyScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled" x:Name="PanBack">
         <StackPanel x:Name="PanMain" Margin="25,10">
-            <local:MyCard Margin="0,15" Title="联机">
-                <StackPanel Margin="25,40,25,20" Orientation="Vertical">
-                    <local:MyCheckBox Text="老好人模式" x:Name="CheckShareMode" Tag="LinkShareMode" Height="22"
+            <local:MyCard Margin="0,15" Title="高级设置" IsSwapped="True" CanSwap="True">
+                <Grid Margin="25,40,25,22">
+                    <Grid.ColumnDefinitions>
+                        <ColumnDefinition Width="Auto" />
+                        <ColumnDefinition Width="1*" />
+                    </Grid.ColumnDefinitions>
+                    <Grid.RowDefinitions>
+                        <RowDefinition Height="28" />
+                        <RowDefinition Height="15" />
+                        <RowDefinition Height="35" />
+                    </Grid.RowDefinitions>
+                    <TextBlock VerticalAlignment="Center" HorizontalAlignment="Left" Text="自定义节点" Margin="0,0,25,0" />
+                    <local:MyTextBox x:Name="TextCustomPeer" Tag="LinkCustomPeer" Grid.Column="1" MaxHeight="28" 
+                        ToolTip="覆盖 PCL 所选择的节点,仅连接此处填写的节点。&#xa;如果你自己搭建了 EasyTier 节点,你可以用这个设置让 PCL 连接它。&#xa;&#xa;使用逗号分隔多个节点,例如:&#xa;tcp://public.easytier.cn:11010,tcp://public2.easytier.cn:54321&#xa;&#xa;房主和加入者必须连接到至少一个相同节点,才能互相连上。" />
+                    <local:MyCheckBox Text="老好人模式" x:Name="CheckShareMode" Grid.Row="1" Tag="LinkShareMode" Height="22" Visibility="Collapsed"
                         ToolTip="启动联机后,用你的网络帮助其他玩家建立连接、降低延迟!&#xa;即使你不开启,开启了这个选项的其他玩家也会帮助你,不过,人人为我,我为人人嘛……" />
-                </StackPanel>
+                    <StackPanel Orientation="Horizontal" Grid.Row="2" Grid.ColumnSpan="2" HorizontalAlignment="Left">
+                        <local:MyButton MinWidth="140" Padding="13,5" Margin="0,0,20,0" HorizontalAlignment="Left"
+                            Text=" 光荣地贡献节点!" ColorType="Highlight"
+                            ToolTip="联机功能全靠社区的各位无私贡献的节点才能存在!&#xa;如果你有空闲的服务器,欢迎搭建一个共享节点,人人为我,我为人人嘛……&#xa;&#xa;你可以在 EasyTier 的【搭建共享节点】文档中查看搭建方式,搭建好后点击这里提交。&#xa;PCL 会自动选取节点进行连接。" 
+                            local:CustomEventService.EventType="打开网页" local:CustomEventService.EventData="https://uptime.easytier.cn/submit" />
+                        <local:MyButton MinWidth="140" Padding="13,5" Margin="0,0,20,0" HorizontalAlignment="Left"
+                            Text="节点状态"
+                            local:CustomEventService.EventType="打开网页" local:CustomEventService.EventData="https://uptime.easytier.cn/" />
+                    </StackPanel>
+                </Grid>
             </local:MyCard>
         </StackPanel>
     </local:MyScrollViewer>

+ 4 - 2
Plain Craft Launcher 2/Pages/PageSetup/PageSetupLink.xaml.vb

@@ -1,4 +1,4 @@
-Class PageSetupLink
+Public Class PageSetupLink
 
     Private Shadows IsLoaded As Boolean = False
 
@@ -18,12 +18,14 @@
     End Sub
     Public Sub Reload()
         CheckShareMode.Checked = Setup.Get("LinkShareMode")
+        TextCustomPeer.Text = Setup.Get("LinkCustomPeer")
     End Sub
 
     '初始化
     Public Sub Reset()
         Try
             Setup.Reset("LinkShareMode")
+            Setup.Reset("LinkCustomPeer")
 
             Log("[Setup] 已初始化联机页设置")
             Hint("已初始化联机页设置!", HintType.Green, False)
@@ -35,7 +37,7 @@
     End Sub
 
     '将控件改变路由到设置改变
-    Private Shared Sub TextBoxChange(sender As MyTextBox, e As Object) 'Handles TextLinkName.ValidatedTextChanged
+    Private Shared Sub TextBoxChange(sender As MyTextBox, e As Object) Handles TextCustomPeer.ValidatedTextChanged
         If AniControlEnabled = 0 Then Setup.Set(sender.Tag, sender.Text)
     End Sub
     Private Shared Sub CheckBoxChange(sender As MyCheckBox, e As Object) Handles CheckShareMode.Change

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

@@ -253,6 +253,7 @@
                             <local:MyComboBoxItem Content="OpenMCIM 仪表盘(作者:SALTWOOD)" Visibility="Collapsed" />
                             <local:MyComboBoxItem Content="杂志主页(作者:CreeperIsASpy)" />
                             <local:MyComboBoxItem Content="PCL GitHub 仪表盘(作者:Deep-Dark-Forest)" />
+                            <local:MyComboBoxItem Content="Minecraft 更新摘要(作者:pynickle,部分由 AI 生成)" />
                         </local:MyComboBox>
                     </Grid>
                 </StackPanel>

+ 1 - 3
Plain Craft Launcher 2/Pages/PageSpeedLeft.xaml.vb

@@ -1,6 +1,4 @@
-Imports System.Threading.Tasks
-
-Public Class PageSpeedLeft
+Public Class PageSpeedLeft
     Private Const WatcherInterval As Integer = 300
 
     '初始化

+ 3 - 1
Plain Craft Launcher 2/Plain Craft Launcher 2.vbproj

@@ -933,6 +933,8 @@
   <ItemGroup>
     <None Include="Resources\System.Net.Http.Formatting.dll" />
   </ItemGroup>
-  <ItemGroup />
+  <ItemGroup>
+    <Resource Include="Images\Heads\EasyTier.png" />
+  </ItemGroup>
   <Import Project="$(MSBuildToolsPath)\Microsoft.VisualBasic.targets" />
 </Project>

BIN
Plain Craft Launcher 2/Resources/Help.zip