2.11.1
Some checks failed
Build / Build (Debug) (push) Has been cancelled
Build / Build (Release) (push) Has been cancelled

This commit is contained in:
龙腾猫跃
2025-11-01 11:51:54 +08:00
parent a067271995
commit efd480f06c
24 changed files with 1031 additions and 431 deletions

View File

@@ -113,6 +113,17 @@ Public Class FormMain
'3BUG+ IMP* FEAT-
'2BUG* IMP-
'1BUG-
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
'文件拖放

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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("")>

View File

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

View File

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

View File

@@ -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
'联网下载

View File

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

View File

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

View File

@@ -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
Targets = Peers.Where(Function(p) p.Ping > 0)
Else
PingTargets = Peers.Where(Function(p) p.Type = Peer.Types.Server)
End If
If Not PingTargets.Any Then
Return 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>
''' 检查联机模块是否崩溃。

View File

@@ -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/Patrick.png" Grid.Row="4" Margin="3">
<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/Hao_Tian.jpg" Grid.Row="5" 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/MCBBS.png" Grid.Row="6" 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/PCL2.png" Grid.Row="7" 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="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 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="对方正在输入..." />
<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="杨三海" />
<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="123" />
<TextBlock Width="120" Margin="0,1.5" Text="Zik yeung" />
<TextBlock Width="120" Margin="0,1.5" Text="wihz" />
<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="PickStars" />
<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="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="带我去跳海" />
<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="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="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="李白" />
<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">

View File

@@ -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)},

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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