This commit is contained in:
龙腾猫跃
2026-07-02 23:24:29 +08:00
parent 124e3be6bf
commit c6d0457946
193 changed files with 3112 additions and 3747 deletions
@@ -1,4 +1,4 @@
<local:MyPageRight
<local:MyPageRight
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:PCL" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
@@ -37,8 +37,7 @@
<local:MyIconButton Grid.Column="5" Grid.Row="1" x:Name="BtnLoadCancel" Height="25" Width="25"
VerticalAlignment="Top" Margin="0,-13,-13,0"
Theme="Black" Opacity="0.3"
ToolTip="取消" ToolTipService.Placement="Right" ToolTipService.InitialShowDelay="100"
ToolTipService.VerticalOffset="-2" ToolTipService.HorizontalOffset="0"
ToolTip="取消" ToolTipService.InitialShowDelay="100"
LogoScale="0.72" Logo="F1 M2,0 L0,2 8,10 0,18 2,20 10,12 18,20 20,18 12,10 20,2 18,0 10,8 2,0Z" />
<Grid Height="12" VerticalAlignment="Bottom" Grid.ColumnSpan="100" Grid.RowSpan="100" Margin="0,0,0,-0.6">
<Grid.ColumnDefinitions>
@@ -164,7 +163,7 @@
<local:MyCard Grid.Row="4" HorizontalAlignment="Center" VerticalAlignment="Center" CornerRadius="8">
<StackPanel Orientation="Horizontal" Margin="3,0">
<StackPanel x:Name="BtnFinishPing" Orientation="Horizontal" Background="{StaticResource ColorBrushSemiTransparent}"
ToolTip="延迟" ToolTipService.Placement="Center" ToolTipService.InitialShowDelay="50" ToolTipService.VerticalOffset="40" ToolTipService.HorizontalOffset="4">
ToolTip="延迟" ToolTipService.InitialShowDelay="50">
<Path IsHitTestVisible="False" Height="14" Width="14" Stretch="Uniform" Fill="#9C9C9C" Margin="13,0,8,0"
Data="M60.9 966.2A60.3 60.3 0 0 1 0.8 906.1v-90.1a60.3 60.3 0 0 1 60.1-60.1 60.3 60.3 0 0 1 60.1 60.1v90.1a60.2 60.2 0 0 1-60.1 60.1z m300.6 0a60.3 60.3 0 0 1-60.1-60.1V665.6a60.3 60.3 0 0 1 60.1-60.1 60.3 60.3 0 0 1 60.1 60.1v240.5a60.2 60.2 0 0 1-60.1 60.1z m300.6 0a60.3 60.3 0 0 1-60.1-60.1V425.1a60.3 60.3 0 0 1 60.1-60.1 60.3 60.3 0 0 1 60.1 60.1v481.0a60.3 60.3 0 0 1-60.1 60.1z m300.6 0a60.3 60.3 0 0 1-60.1-60.1V124.5a60.3 60.3 0 0 1 60.1-60.1 60.3 60.3 0 0 1 60.1 60.1v781.6a60.3 60.3 0 0 1-60.1 60.1z" />
<TextBlock x:Name="LabFinishPing" IsHitTestVisible="False" Text="15 ms" VerticalAlignment="Center" Foreground="{StaticResource ColorBrushGray1}" Margin="0,0.5,13,0" />
@@ -175,7 +174,7 @@
</TextBlock.RenderTransform>
</TextBlock>
<StackPanel x:Name="BtnFinishPlayer" Orientation="Horizontal" Background="{StaticResource ColorBrushSemiTransparent}"
ToolTip="房间内人数" ToolTipService.Placement="Center" ToolTipService.InitialShowDelay="50" ToolTipService.VerticalOffset="40" ToolTipService.HorizontalOffset="4">
ToolTip="房间内人数" ToolTipService.InitialShowDelay="50">
<Path IsHitTestVisible="False" Height="18" Width="18" Stretch="Uniform" Fill="{StaticResource ColorBrushGray4}" Margin="13,0,8,0"
Data="m843.3,478.4c-.1-3.9-.2-7.7-.2-10.8,0-42.8-11.1-84.4-32-120.2-19.6-33.5-47.1-60.7-79.7-79,15-16.8,23.6-39.2,25-65.2,1.3-24.8-3.7-52.1-14.6-79-20.5-50.8-56-86.3-86.3-86.3s-25.1,4.1-37.5,23.5l-.4.7-.2.8c-4.1,16.6,3.9,33.4,20,41.7l.7.4h.8c34.9,5.6,50.6,38.7,53.5,65.3,3.3,30.7-7.8,67.2-40.1,80.1-7.4,1.1-9.9,7.7-11.5,12.1-.6,1.7-1.2,3.3-1.9,4.3l-.7,1v1.2c-3.4,27.8,19.6,39.8,46.3,53.6,41.4,21.4,93,48.1,93.1,144.9v.3c.3,4.3,0,9.9-.1,15.7-.6,17.9-1.4,40.2,10.3,52.4,5.5,5.7,13,8.6,22.5,8.7.7,0,1.4,0,2.1,0h0c8.1,0,14.7-2.6,19.8-7.9,12.7-13.1,11.9-39.4,11.4-58.6Z M204.7,295.9l.5-1.1v-30.1c0-3.9-2.1-6-3.3-7.1-.1-.1-.2-.2-.3-.3v-1.7l-8.9-9.2-.7-.4c-26.3-13.5-42.6-40.8-42.6-71.3s21.8-67.4,55.5-78.1c17-4.5,28.2-22.1,24.5-38.4v-.6c-.1,0-.4-.5-.4-.5-7.5-15.3-21.4-24.7-36.2-24.7s-5.1.3-7.7.8h-.2c-29.8,7.2-56.6,25.5-75.7,51.4-18.9,25.7-29.3,57.8-29.3,90.4s11.1,64.8,32.2,92.1C45.3,303.9,2.5,376.9,0,458.9v57.5s0,.2,0,.2c1.4,15.3,13.1,30.8,32.8,30.8s32.9-12.7,32.9-33.9v-43.3c0-76.2,45.9-139.2,114.3-157.1,10.5-.5,19.5-6.8,24.7-17.3Z M516,286.5c36.8-31.1,58.5-77.4,58.5-125.4C574.4,70.8,507.4,0,421.7,0s-152.7,70.8-152.7,161.2,20.4,95.1,56.4,125.6c-51.7,19.8-96.1,54.8-129,101.5-35.2,50.2-53.9,109.7-53.9,172v33.8c0,16.9,13.7,30.6,30.6,30.6h496.6c16.9,0,30.6-13.7,30.6-30.6v-33.8c0-61.4-19-120.6-54.9-171.3-32.9-46.4-78.6-82.5-129.5-102.4Zm-94.5-225.3c51.3,0,91.5,43.9,91.5,100s-41.9,100-91.5,100-91.5-43.9-91.5-100,40.2-100,91.5-100Zm218,502H203.8v-3.2c0-127,97.8-230.3,218-230.3s217.7,105.4,217.7,230.3v3.2Z" />
<TextBlock x:Name="LabFinishPlayer" IsHitTestVisible="False" Text="2  人" VerticalAlignment="Center" Foreground="{StaticResource ColorBrushGray1}" Margin="0,0.5,13,0" />
@@ -186,13 +185,13 @@
</TextBlock.RenderTransform>
</TextBlock>
<StackPanel x:Name="BtnFinishPort" Orientation="Horizontal" Background="{StaticResource ColorBrushSemiTransparent}"
ToolTip="端口" ToolTipService.Placement="Center" ToolTipService.InitialShowDelay="50" ToolTipService.VerticalOffset="40" ToolTipService.HorizontalOffset="4">
ToolTip="端口" ToolTipService.InitialShowDelay="50">
<Path IsHitTestVisible="False" Height="16" Width="16" Stretch="Uniform" Fill="{StaticResource ColorBrushGray4}" Margin="13,0,7,0"
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">
ToolTip="服务器 IP(点击复制)" ToolTipService.InitialShowDelay="50">
<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" />
@@ -1,5 +1,8 @@
Imports System.Globalization
Imports System.Collections.ObjectModel
Imports System.Globalization
Imports System.Net.Sockets
Imports System.Reflection
Imports PCL
Public Class PageLinkMain
Private Const INVITE_CODE_VERSION As Integer = 2
@@ -70,7 +73,7 @@ Public Class PageLinkMain
'由任意状态切换到 Waiting
Private Sub SwitchToWaiting(OldState As LinkStates)
'加载器与进程状态
LinkLoader.Interrupt()
LinkLoader.Cancel()
SyncLock LinkLoader.LockState
LinkLoader.State = LoadState.Waiting
End SyncLock
@@ -92,7 +95,7 @@ Public Class PageLinkMain
Private Sub Create_MouseLeftButtonUp() Handles PanSelectCreate.MouseLeftButtonUp
'输入端口号
Dim Port As String = MyMsgBoxInput("输入端口", $"在单人游戏的暂停菜单选择 {vbLQ}对局域网开放{vbRQ},然后输入端口数字。{vbCrLf}甚至可以输入其他游戏的端口……嗯……",
ValidateRules:=New ObjectModel.Collection(Of Validate) From {New ValidateInteger(1024, 65535)},
ValidateRules:=New Collection(Of Validate) From {New ValidateInteger(1024, 65535)},
HintText:="端口号")
If Port Is Nothing Then Return
'基础信息
@@ -223,7 +226,7 @@ Public Class PageLinkMain
'由 Loading 状态切换到 Failed
Private Sub SwitchToFailed(OldState As LinkStates)
'加载器与进程状态
LinkLoader.Interrupt()
LinkLoader.Cancel()
ProcessStop()
'UI 更新
UpdateProgressBar(1)
@@ -379,7 +382,7 @@ Public Class PageLinkMain
''' <summary>
''' EasyTier 所在的文件夹路径,以 \ 结尾。
''' </summary>
Private PathEasyTier As String = PathAppdata & "EasyTier\"
Private PathEasyTier As String = Paths.AppDataThenName & "EasyTier\"
''' <summary>
''' 当前是服务端还是客户端。
''' </summary>
@@ -444,11 +447,11 @@ Public Class PageLinkMain
UpdateLoadingPage("正在获取 CPU 架构……", "获取 CPU 架构")
Dim Architecture As String = GetType(String).Assembly.GetName().ProcessorArchitecture
Select Case Architecture
Case Reflection.ProcessorArchitecture.X86
Case ProcessorArchitecture.X86
Architecture = "i686"
Case Reflection.ProcessorArchitecture.Amd64
Case ProcessorArchitecture.Amd64
Architecture = "x86_64"
Case Reflection.ProcessorArchitecture.Arm
Case ProcessorArchitecture.Arm
Architecture = "arm64"
Case Else
Logger.Warn($"CPU 是不支持的 {Architecture} 架构,这可能会导致联机模块无法启动!")
@@ -470,7 +473,7 @@ Public Class PageLinkMain
RequiredFiles.Add(New NetFile(
ServerConfig("Link")("Downloads").Select(Function(UrlEntry) UrlEntry.ToString.Replace("{arch}", Architecture)),
PathEasyTier & "EasyTier.zip",
New FileChecker(MinSize:=1024 * 1024 * 2)))
New FileChecker With {.MinSize = 1024 * 1024 * 2}))
End If
'开始下载
UpdateLoadingPage("正在下载联机模块……", "下载联机模块")
@@ -486,11 +489,9 @@ Public Class PageLinkMain
Dim ExtractPath As String = RequestTaskTempFolder()
FileUtils.ExtractToDirectory(PathEasyTier & "EasyTier.zip", ExtractPath,
progressHandler:=Sub(Percentage) Task.Progress = Percentage * 0.05)
DirectoryUtils.Copy(DirectoryUtils.GetDirectories(ExtractPath).First, PathEasyTier)
DirectoryUtils.Copy(DirectoryUtils.EnumerateDirectories(ExtractPath, True).First, PathEasyTier)
'重命名
FileUtils.Delete(PathEasyTier & "联机模块.exe")
FileUtils.Move(PathEasyTier & "easytier-core.exe", PathEasyTier & "联机模块.exe")
FileUtils.Delete(PathEasyTier & "联机模块 CLI.exe")
FileUtils.Move(PathEasyTier & "easytier-cli.exe", PathEasyTier & "联机模块 CLI.exe")
'清理
FileUtils.Delete(PathEasyTier & "EasyTier.zip")
@@ -583,8 +584,8 @@ Public Class PageLinkMain
Panic("无法连接到房主", $"可能的原因:{vbCrLf}- 你或者房主的网络环境不佳{vbCrLf}- 房主已关闭房间{vbCrLf}- 邀请码输错了")
End Select
End If
Loop Until Task.IsInterrupted
If Task.IsInterrupted Then Throw New ThreadInterruptedException
Loop Until Task.IsCanceled
If Task.IsCanceled Then Throw New OperationCanceledException
'等待连接稳定,最多 5s
If IsServerSide Then Return
UpdateLoadingPage("连接优化中……", "优化连接")
@@ -592,7 +593,7 @@ Public Class PageLinkMain
For i = 1 To 50
Dim Server = GetTargetPeer()
If Server IsNot Nothing AndAlso Not Server.Relay AndAlso Server.Ping < 100 Then Return '结束
If Task.IsInterrupted Then Throw New ThreadInterruptedException
If Task.IsCanceled Then Throw New OperationCanceledException
Thread.Sleep(100)
Next
End Sub
@@ -612,10 +613,10 @@ Public Class PageLinkMain
Dim RawNodes As JObject
Dim IsFallbackRawList As Boolean = False
Try
RawNodes = GetJson(NetRequestByClient("https://uptime.easytier.cn/api/nodes?page=1&per_page=1000", RequireJson:=True))
RawNodes = NetRequestByClient("https://uptime.easytier.cn/api/nodes?page=1&per_page=1000", RequireJson:=True).DeserializeJson()
Catch exx As Exception
Logger.Warn(exx, "从源站获取节点列表失败,将使用 CDN 缓存")
RawNodes = GetJson(NetRequestByClientRetry("https://easytier.meloong.com/?page=1&per_page=1000", RequireJson:=True))
RawNodes = NetRequestByClientRetry("https://easytier.meloong.com/?page=1&per_page=1000", RequireJson:=True).DeserializeJson()
IsFallbackRawList = True
End Try
'分析节点列表
@@ -654,7 +655,7 @@ ForcedPass:
If SelectedDiscoverNode Is Nothing Then
Logger.Warn($"未找到 ID {DiscoverNodeID} 的发现节点")
Panic("房间已过期", "请让房主重新创建房间!")
Throw New ThreadInterruptedException
Throw New OperationCanceledException
End If
End If
If SelectedDiscoverNode Is Nothing Then '使用回退发现节点
@@ -671,9 +672,8 @@ ForcedPass:
If RelayNodes.Count < RelayCount Then Throw New Exception($"可用的中继节点数量不足,需要 {RelayCount} 个,实际 {RelayNodes.Count} 个")
FinalPeers.AddRange(RelayNodes.Take(RelayCount).Select(Function(n) n("address").ToString()))
End If
Catch ex As ThreadInterruptedException
Throw
Catch ex As Exception
ex.ThrowIfCanceled()
Logger.Error(ex, "获取节点列表失败,联机质量可能受到影响", LogBehavior.Toast)
FinalPeers.AddRange(ServerConfig("Link")("Peers").Select(Function(p) p.ToString))
If FinalDiscoverID <= 0 Then
@@ -771,23 +771,22 @@ ForcedPass:
Logger.Info($"正在启动 EasyTier:{Arguments}")
ProcessCore = New Process With {.StartInfo = Info}
Dim LogLineHandler =
Function(sender As Object, e As DataReceivedEventArgs, Handle As AutoResetEvent)
Sub(sender As Object, e As DataReceivedEventArgs, Handle As AutoResetEvent)
Try
If e.Data Is Nothing Then
Handle.[Set]()
Return Nothing
Return
End If
ProcessLogLine(e.Data)
Catch unused As ObjectDisposedException
Catch ex As Exception
Logger.Warn(ex, "读取 EasyTier 信息失败")
End Try
Return Nothing
End Function
End Sub
ProcessOutputHandle = New AutoResetEvent(False)
AddHandler ProcessCore.OutputDataReceived, Function(sender, e) LogLineHandler(sender, e, ProcessOutputHandle)
AddHandler ProcessCore.OutputDataReceived, Sub(sender, e) LogLineHandler(sender, e, ProcessOutputHandle)
ProcessErrorHandle = New AutoResetEvent(False)
AddHandler ProcessCore.ErrorDataReceived, Function(sender, e) LogLineHandler(sender, e, ProcessErrorHandle)
AddHandler ProcessCore.ErrorDataReceived, Sub(sender, e) LogLineHandler(sender, e, ProcessErrorHandle)
ProcessCore.Start()
ProcessCore.BeginOutputReadLine()
ProcessCore.BeginErrorReadLine()
@@ -872,7 +871,7 @@ ForcedPass:
Double.TryParse(Info("lat_ms"), NumberStyles.Any, CultureInfo.InvariantCulture, Ping)
Name = PeerName
Relay = Info("cost").ToString.ContainsIgnoreCase("relay")
NATType = Info("nat_type").ToString.ToEnum(Of NATTypes)
NATType = EnumUtils.FromString(Of NATTypes)(Info("nat_type"))
End Sub
Public Overrides Function ToString() As String
Return $"{Type} - {Name} - Ping {Ping:0.0}ms [中继? {Relay}] - NAT {NATType}"
@@ -914,12 +913,12 @@ ForcedPass:
Private RefreshPeerLoader As New LoaderTask(Of Integer, List(Of Peer))("EasyTier CLI", AddressOf RefreshPeer)
Private Sub RefreshPeer()
Try
Dim CliResult = StartProcessAndGetOutput(PathEasyTier & "联机模块 CLI.exe", $"-o json -p 127.0.0.1:{RPCPort} 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, 23, 103) = 0 Then Logger.Info($"CLI 输出抽样:{vbCrLf}{CliResult}")
Dim NewPeers As New List(Of Peer)
For Each Line As JObject In CType(GetJson(CliResult), JArray)
For Each Line As JObject In CType(CliResult.DeserializeJson(), JArray)
Try
Dim Peer = New Peer(Line)
If Peer.Type = Peer.Types.Self Then