2.6.14
This commit is contained in:
@@ -1,204 +1,10 @@
|
||||
Imports System.Net
|
||||
Imports System.Net.Sockets
|
||||
Imports System.Net.Sockets
|
||||
|
||||
Public Class PageLinkIoi
|
||||
Public Const RequestVersion As Integer = 4
|
||||
Public Const IoiVersion As Integer = 10 '由于已关闭更新渠道,在提升 IoiVersion 时必须提升 RequestVersion
|
||||
Public Shared PathIoi As String = PathAppdata & "联机模块\IOI 联机模块.exe"
|
||||
|
||||
#Region "初始化"
|
||||
|
||||
'页面初始化
|
||||
Private IsLoad As Boolean = False
|
||||
Private Sub MeLoaded() Handles Me.Loaded
|
||||
FormMain.EndProgramForce(Result.Aborted)
|
||||
|
||||
'重复加载部分
|
||||
PanBack.ScrollToHome()
|
||||
RefreshUi()
|
||||
|
||||
'非重复加载部分
|
||||
If IsLoad Then Exit Sub
|
||||
IsLoad = True
|
||||
|
||||
'更新线程
|
||||
RunInNewThread(Sub()
|
||||
Do While True
|
||||
Thread.Sleep(200)
|
||||
If FrmMain.PageCurrent.Page = FormMain.PageType.Link AndAlso FrmMain.PageCurrentSub = FormMain.PageSubType.LinkIoi Then RunInUiWait(Sub() FrmLinkIoi.RefreshUi())
|
||||
RefreshWorker()
|
||||
Loop
|
||||
End Sub, "Link Timer")
|
||||
|
||||
End Sub
|
||||
|
||||
'加载器初始化与左边栏处理
|
||||
Private Sub LoaderInit() Handles Me.Initialized
|
||||
PageLoaderInit(Load, PanLoad, PanBack, PanAlways, InitLoader, Sub()
|
||||
End Sub)
|
||||
End Sub
|
||||
|
||||
'初始化加载器与步骤
|
||||
Public Shared WithEvents InitLoader As New LoaderCombo(Of Integer)("联机模块初始化", {
|
||||
New LoaderTask(Of Integer, Integer)("端口检查", AddressOf InitPortCheck) With {.ProgressWeight = 1},
|
||||
New LoaderTask(Of Integer, Integer)("启动请求核心", AddressOf StartSocketListener) With {.ProgressWeight = 1},
|
||||
New LoaderTask(Of Integer, List(Of NetFile))("初次启动尝试", AddressOf InitFirst) With {.ProgressWeight = 4},
|
||||
New LoaderDownload("下载更新文件", New List(Of NetFile)) With {.ProgressWeight = 6},
|
||||
New LoaderTask(Of List(Of NetFile), Boolean)("二次启动尝试", AddressOf InitSecond) With {.ProgressWeight = 3},
|
||||
New LoaderTask(Of Boolean, Boolean)("创建请求核心房间", AddressOf InitRequest) With {.ProgressWeight = 2}
|
||||
})
|
||||
'判断端口是否被占用
|
||||
Private Shared Sub InitPortCheck()
|
||||
'检查协议
|
||||
If Not Setup.Get("LinkEula") Then
|
||||
Reopen:
|
||||
Select Case MyMsgBox("PCL 的联机服务由速聚授权提供。" & vbCrLf & "在使用前,你需要同意速聚的用户服务协议和隐私政策。", "协议授权", "同意", "拒绝", "查看用户服务协议和隐私政策")
|
||||
Case 1
|
||||
Setup.Set("LinkEula", True)
|
||||
Case 2
|
||||
Throw New Exception("你拒绝了用户服务协议……")
|
||||
Case 3
|
||||
OpenWebsite("https://mp.weixin.qq.com/mp/appmsgalbum?__biz=MzkxMTMyODk3Mg==&action=getalbum&album_id=2585385685407514625&scene=173&from_msgid=2247483720&from_itemidx=1&count=3&nolastread=1#wechat_redirect")
|
||||
GoTo Reopen
|
||||
End Select
|
||||
End If
|
||||
'先掐死
|
||||
IoiStop(True)
|
||||
'检查端口
|
||||
Dim HasConflict As Boolean = False
|
||||
For Each Port In Net.NetworkInformation.IPGlobalProperties.GetIPGlobalProperties().GetActiveTcpListeners()
|
||||
If Port.Port <> 55555 AndAlso Port.Port <> 55557 Then Continue For
|
||||
Log("[IOI] 发现端口 " & Port.Port & " 被占用")
|
||||
HasConflict = True
|
||||
Next
|
||||
If Not HasConflict Then Exit Sub
|
||||
'对应的报错
|
||||
For Each Line As String In ShellAndGetOutput("netstat", "-ano", 30000).Split({vbCrLf}, StringSplitOptions.RemoveEmptyEntries)
|
||||
If Not (Line.Contains("127.0.0.1:55555") OrElse Line.Contains("127.0.0.1:55557")) Then Continue For
|
||||
Dim ProcessName As String
|
||||
Try
|
||||
ProcessName = Process.GetProcessById(Line.Split(" ").Last).ProcessName
|
||||
Catch ex As Exception
|
||||
Log(ex, "获取占用端口的进程信息失败,假定进程已结束")
|
||||
Continue For
|
||||
End Try
|
||||
If ProcessName = "联机模块" Then
|
||||
Throw New Exception("由于一个已知问题,请在重启电脑后再尝试使用联机功能")
|
||||
ElseIf ProcessName = "Idle" Then
|
||||
'不知道为啥反正又没占用了
|
||||
Log("[IOI] 未发现占用此端口的程序,继续执行")
|
||||
Else
|
||||
Throw New Exception("端口被程序 " & ProcessName & " 占用,无法启动联机模块,请在任务管理器关闭此程序后再试")
|
||||
End If
|
||||
Next
|
||||
End Sub
|
||||
'下载更新前尝试启动
|
||||
Private Shared Sub InitFirst(Task As LoaderTask(Of Integer, List(Of NetFile)))
|
||||
'初次启动尝试
|
||||
If IoiVersion <> Setup.Get("LinkIoiVersion") Then
|
||||
Log("[IOI] 设置版本强制要求联机模块更新")
|
||||
Setup.Set("LinkIoiVersion", IoiVersion)
|
||||
ElseIf File.Exists(PathIoi) Then
|
||||
Task.Progress = 0.2
|
||||
CheckFirewall()
|
||||
If IoiStart() Then
|
||||
'已完成启动与初始化
|
||||
Task.Output = New List(Of NetFile)
|
||||
Exit Sub
|
||||
Else
|
||||
'需要更新
|
||||
IoiStop(True)
|
||||
File.Delete(PathIoi)
|
||||
GoTo StartDownload
|
||||
End If
|
||||
'如果抛出异常则直接使加载器失败
|
||||
End If
|
||||
'开始下载
|
||||
StartDownload:
|
||||
Task.Progress = 0.8
|
||||
Log("[IOI] 需要下载联机模块")
|
||||
If File.Exists(PathTemp & "联机模块.zip") Then File.Delete(PathTemp & "联机模块.zip")
|
||||
Task.Output = New List(Of NetFile) From {New NetFile(
|
||||
{"https://gitcode.net/to/cato_bin/-/raw/master/ioi_v2_x" & If(Is32BitSystem, 32, 64) & ".zip",
|
||||
"http://mirror.hiper.cn.s2.the.bb/ioi_v2_x" & If(Is32BitSystem, 32, 64) & ".zip",
|
||||
"http://mirror.hiper.cn.s3.the.bb:175/ioi_v2_x" & If(Is32BitSystem, 32, 64) & ".zip",
|
||||
"https://pcl2-server-1253424809.file.myqcloud.com/link/ioi_v2_x" & If(Is32BitSystem, 32, 64) & ".zip{CDN}"},
|
||||
PathTemp & "联机模块.zip")}
|
||||
End Sub
|
||||
'下载更新后尝试启动
|
||||
Private Shared Sub InitSecond(Task As LoaderTask(Of List(Of NetFile), Boolean))
|
||||
'若首次尝试已经成功,则直接跳过
|
||||
If IoiState = LoadState.Finished Then Exit Sub
|
||||
'解压更新包
|
||||
Log("[IOI] 解压联机模块以完成下载")
|
||||
If File.Exists(PathTemp & "ioi.exe") Then File.Delete(PathTemp & "ioi.exe")
|
||||
If File.Exists(PathIoi) Then File.Delete(PathIoi)
|
||||
ExtractFile(PathTemp & "联机模块.zip", PathTemp)
|
||||
File.Delete(PathTemp & "联机模块.zip")
|
||||
CopyFile(PathTemp & "ioi.exe", PathIoi)
|
||||
File.Delete(PathTemp & "ioi.exe")
|
||||
Task.Progress = 0.4
|
||||
'再次尝试启动
|
||||
CheckFirewall()
|
||||
If IoiStart() Then Exit Sub
|
||||
IoiStop(True)
|
||||
Throw New Exception("联机模块初始化失败")
|
||||
End Sub
|
||||
'在 IOI 启动后建立 55557 房间
|
||||
Private Shared Sub InitRequest()
|
||||
Try
|
||||
Dim Result As JObject = GetJson(NetRequestOnce("http://127.0.0.1:55555/api/port?proto=tcp&port=55557" & "&password=" & IoiPassword, "PUT", "", "", 100000))
|
||||
If Result("msg") IsNot Nothing Then Throw New InvalidOperationException(Result("msg").ToString)
|
||||
Catch ex As InvalidOperationException
|
||||
'API 返回的错误
|
||||
Log("创建请求核心房间失败:" & ex.Message, LogLevel.Msgbox)
|
||||
Catch ex As Exception
|
||||
'常规错误
|
||||
Log(ex, "创建请求核心房间失败", LogLevel.Msgbox)
|
||||
End Try
|
||||
End Sub
|
||||
|
||||
'检查防火墙权限,并添加对应的权限
|
||||
Private Shared Sub CheckFirewall()
|
||||
Try
|
||||
Log("[IOI] Windows 防火墙:检测开始")
|
||||
If Not PageLinkLeft.FirewallIsBlock(PathIoi) Then Exit Try
|
||||
If PageLinkLeft.FirewallPolicy.CurrentProfile.ExceptionsNotAllowed Then
|
||||
'禁止白名单
|
||||
MyMsgBox("由于 Windows 防火墙阻止了所有传入连接,PCL 无法获取防火墙通行权限。" & vbCrLf &
|
||||
"联机会有很大概率失败,就算连上了,延迟也会变高……" & vbCrLf & vbCrLf &
|
||||
"请先关闭 Windows 防火墙中的 " & vbLQ & "阻止所有传入连接" & vbRQ & " 选项,然后重启 PCL。", "遭到防火墙拦截")
|
||||
ElseIf IsAdmin() Then
|
||||
'有管理员权限
|
||||
Log("[IOI] Windows 防火墙:尝试添加防火墙通行权限")
|
||||
Try
|
||||
PageLinkLeft.FirewallAddAuthorized("Plain Craft Launcher 启动器(IOI 联机模块)", PathIoi)
|
||||
Catch ex As Exception
|
||||
Log(ex, "无法将联机模块添加至防火墙白名单,可能导致联机失败", LogLevel.Msgbox)
|
||||
End Try
|
||||
Else
|
||||
'无管理员权限
|
||||
If MyMsgBox("由于你开启了 Windows 防火墙,PCL 需要获取防火墙通行权限。" & vbCrLf & vbCrLf &
|
||||
"若继续,PCL 将尝试以管理员权限重新启动。" & vbCrLf &
|
||||
"若拒绝,联机模块可能会被防火墙拦截,联机会有很大概率失败。", "需要管理员权限", "继续", "拒绝") = 1 Then
|
||||
Log("[IOI] Windows 防火墙:尝试提升权限")
|
||||
If RunAsAdmin("--link ioi") Then
|
||||
FrmMain.EndProgram(False) '已重新运行
|
||||
Else
|
||||
Hint("获取管理员权限失败,请尝试右键 PCL,选择 " & vbLQ & "以管理员身份运行" & vbRQ & ",然后再进入联机页面!", HintType.Critical)
|
||||
End If
|
||||
Else
|
||||
Hint("在没有防火墙权限的情况下尝试联机,很可能会导致联机失败!", HintType.Critical)
|
||||
End If
|
||||
End If
|
||||
Log("[IOI] Windows 防火墙:无防火墙通行权限")
|
||||
Catch ex As Exception
|
||||
Log(ex, "无法检测防火墙状态,可能导致联机失败", LogLevel.Msgbox)
|
||||
End Try
|
||||
End Sub
|
||||
|
||||
#End Region
|
||||
|
||||
#Region "进程管理"
|
||||
|
||||
Private Shared IoiId As String, IoiPassword As String
|
||||
@@ -209,38 +15,7 @@ StartDownload:
|
||||
''' 若 Ioi 正在运行,则结束 Ioi 进程,同时初始化状态数据。返回是否关闭了对应进程。
|
||||
''' </summary>
|
||||
Public Shared Function IoiStop(SleepWhenKilled As Boolean) As Boolean
|
||||
IoiStop = False
|
||||
'发送断开信息
|
||||
Try
|
||||
If IoiProcess IsNot Nothing AndAlso Not IoiProcess.HasExited Then
|
||||
For i = 0 To UserList.Count - 1
|
||||
If i > UserList.Count - 1 Then Exit For
|
||||
Dim User = UserList.Values(i)
|
||||
SendDisconnectRequest(User)
|
||||
Next
|
||||
End If
|
||||
Catch ex As Exception
|
||||
Log(ex, "结束 IOI 进程时发送 Disconnect 信息失败")
|
||||
End Try
|
||||
'关闭所有 Ioi 进程
|
||||
For Each ProcessObject In Process.GetProcesses
|
||||
If ProcessObject.ProcessName <> "IOI 联机模块" Then Continue For
|
||||
IoiStop = True
|
||||
Try
|
||||
ProcessObject.Kill()
|
||||
Log("[IOI] 已关闭联机模块:" & ProcessObject.Id)
|
||||
If SleepWhenKilled Then Thread.Sleep(3000) '等待 3 秒确认进程已退出
|
||||
Catch ex As Exception
|
||||
Log(ex, "关闭联机模块失败(" & ProcessObject.Id & ")")
|
||||
End Try
|
||||
Next
|
||||
'初始化
|
||||
IoiProcess = Nothing
|
||||
IoiId = Nothing
|
||||
IoiPassword = Nothing
|
||||
IoiState = LoadState.Waiting
|
||||
UserList = New Dictionary(Of String, LinkUserIoi)
|
||||
RoomListForMe = New List(Of RoomEntry)
|
||||
Return False
|
||||
End Function
|
||||
''' <summary>
|
||||
''' 启动 Ioi,并等待初始化完成后退出运行,同时更新 IoiId 与 IoiPassword。
|
||||
@@ -248,130 +23,11 @@ StartDownload:
|
||||
''' 若 Ioi 正在运行,则会先停止其运行。
|
||||
''' </summary>
|
||||
Public Shared Function IoiStart() As Boolean
|
||||
IoiStop(True)
|
||||
Log("[IOI] 启动联机模块进程")
|
||||
Dim Info = New ProcessStartInfo With {
|
||||
.FileName = PathIoi,
|
||||
.UseShellExecute = False,
|
||||
.CreateNoWindow = True,
|
||||
.RedirectStandardError = True,
|
||||
.RedirectStandardOutput = True,
|
||||
.WorkingDirectory = PathTemp
|
||||
}
|
||||
IoiProcess = New Process() With {.StartInfo = Info}
|
||||
Using outputWaitHandle As New AutoResetEvent(False)
|
||||
Using errorWaitHandle As New AutoResetEvent(False)
|
||||
AddHandler IoiProcess.OutputDataReceived, Function(sender, e)
|
||||
Try
|
||||
If e.Data Is Nothing Then
|
||||
outputWaitHandle.[Set]()
|
||||
Else
|
||||
IoiLogLine(e.Data)
|
||||
End If
|
||||
Catch ex As ObjectDisposedException
|
||||
Catch ex As Exception
|
||||
Log(ex, "读取联机模块信息失败")
|
||||
IoiState = LoadState.Failed
|
||||
End Try
|
||||
Return Nothing
|
||||
End Function
|
||||
AddHandler IoiProcess.ErrorDataReceived, Function(sender, e)
|
||||
Try
|
||||
If e.Data Is Nothing Then
|
||||
errorWaitHandle.[Set]()
|
||||
Else
|
||||
IoiLogLine(e.Data)
|
||||
End If
|
||||
Catch ex As ObjectDisposedException
|
||||
Catch ex As Exception
|
||||
Log(ex, "读取联机模块错误信息失败")
|
||||
IoiState = LoadState.Failed
|
||||
End Try
|
||||
Return Nothing
|
||||
End Function
|
||||
IoiProcess.Start()
|
||||
IoiState = LoadState.Loading
|
||||
IoiProcess.BeginOutputReadLine()
|
||||
IoiProcess.BeginErrorReadLine()
|
||||
'等待
|
||||
Do Until IoiProcess.HasExited OrElse IoiState <> LoadState.Loading
|
||||
Thread.Sleep(10)
|
||||
Loop
|
||||
'输出
|
||||
If IoiState = LoadState.Finished Then
|
||||
Log("[IOI] 联机模块启动成功")
|
||||
Return True
|
||||
Else
|
||||
Throw New Exception("联机模块启动失败")
|
||||
End If
|
||||
'Select Case IoiState
|
||||
' Case LoadState.Finished
|
||||
' Log("[IOI] 联机模块启动成功")
|
||||
' Return True
|
||||
' Case LoadState.Aborted
|
||||
' Log("[IOI] 联机模块要求更新")
|
||||
' Return False
|
||||
' Case LoadState.Failed
|
||||
' Log("[IOI] 联机模块启动出现异常")
|
||||
' Return False
|
||||
' Case Else 'LoadState.Loading
|
||||
' Throw New Exception("联机模块启动失败,请检查你的网络连接")
|
||||
'End Select
|
||||
End Using
|
||||
End Using
|
||||
Return False
|
||||
End Function
|
||||
|
||||
'Ioi 日志
|
||||
Private Shared Sub IoiLogLine(Content As String)
|
||||
|
||||
'初始化
|
||||
If Content.Contains(" > http://127.0.0.1:55555/") Then Exit Sub
|
||||
If Content.Contains("All done") Then
|
||||
If IoiId IsNot Nothing AndAlso IoiPassword IsNot Nothing Then
|
||||
IoiState = LoadState.Finished
|
||||
Else
|
||||
Log("[IOI] 联机模块汇报初始化完成,但未提供账户信息")
|
||||
IoiState = LoadState.Failed
|
||||
End If
|
||||
Exit Sub
|
||||
End If
|
||||
If Content.Contains("Password :: ") Then
|
||||
IoiPassword = Content.Split({"Password :: "}, StringSplitOptions.None)(1)
|
||||
Exit Sub '为保证安全不记录密码到 Log
|
||||
End If
|
||||
|
||||
'初始化
|
||||
If Content.Contains("ID :: ") Then IoiId = Content.Split({"ID :: "}, StringSplitOptions.None)(1)
|
||||
If Content.Contains("Initialization failed") OrElse Content.Contains("The version is ") Then IoiState = LoadState.Aborted
|
||||
|
||||
'系统回应
|
||||
If Content.Contains("'portssub' from ") Then LastPortsId = Content.Split(" ").Last
|
||||
If Content.Contains("Listening tcp ") Then
|
||||
If UserList.ContainsKey(LastPortsId) Then
|
||||
UserList(LastPortsId).Ports(Content.Split(" ").Last) = RegexSeek(Content, "(?<=Listening tcp )[^:]+")
|
||||
Else
|
||||
Log("[IOI] 未在列表中的用户出现意料外的连接信息")
|
||||
NetRequestOnce("http://127.0.0.1:55555/api/link?id=" & LastPortsId & "&password=" & IoiPassword, "DELETE", "", "", 500)
|
||||
End If
|
||||
End If
|
||||
|
||||
'断开连接
|
||||
If Content.Contains("Closed tcp connection from ") AndAlso Content.Contains(":55557") Then
|
||||
For i = 0 To UserList.Count - 1
|
||||
Dim User = UserList.Values(i)
|
||||
If Not Content.Contains(User.Ports(55557)) OrElse User.IsDisposed Then Continue For
|
||||
Log("[IOI] 检测到 55557 端口断开(" & User.DisplayName & ")")
|
||||
UserRemove(User, True)
|
||||
Exit For
|
||||
Next
|
||||
End If
|
||||
|
||||
'写入日志
|
||||
If Not Content.Contains("read /dev/stdin: The handle is invalid.") AndAlso LogLinesCount < If(ModeDebug, 10000, 1000) Then
|
||||
LogLinesCount += 1
|
||||
Log("[IOI] " & Content)
|
||||
End If
|
||||
|
||||
End Sub
|
||||
Private Shared LogLinesCount As Integer = 0
|
||||
Private Shared LastPortsId As String = "" '上一个收到 portssub 的 ID,用于记录端口
|
||||
@@ -384,94 +40,10 @@ StartDownload:
|
||||
Private Shared UserListIdentifyCache As String = ""
|
||||
Private Shared RoomListIdentifyCache As String = ""
|
||||
Public Sub RefreshUi()
|
||||
Try
|
||||
'确认用户列表缓存
|
||||
Dim UserListIdentify As String = Join(UserList, vbCrLf)
|
||||
If UserListIdentify <> UserListIdentifyCache Then
|
||||
UserListIdentifyCache = UserListIdentify
|
||||
'刷新列表项
|
||||
PanUserList.Children.Clear()
|
||||
For i = 0 To UserList.Count - 1
|
||||
If i > UserList.Count - 1 Then Exit For
|
||||
PanUserList.Children.Add(UserList.Values(i).ToListItem)
|
||||
Next
|
||||
'刷新列表标题
|
||||
CardUser.Title = "已连接的玩家 (" & PanUserList.Children.Count & ")"
|
||||
End If
|
||||
'刷新用户列表项
|
||||
For Each UserItem As MyListItem In PanUserList.Children
|
||||
CType(UserItem.Tag, LinkUserIoi).RefreshUi(UserItem)
|
||||
Next
|
||||
'确认房间列表缓存
|
||||
Dim RoomListIdentify As String = Join(GetRoomList(), vbCrLf)
|
||||
If RoomListIdentify <> RoomListIdentifyCache Then
|
||||
RoomListIdentifyCache = RoomListIdentify
|
||||
'刷新列表项
|
||||
PanRoom.Children.Clear()
|
||||
For Each Room In GetRoomList()
|
||||
PanRoom.Children.Add(Room.ToListItem)
|
||||
Next
|
||||
End If
|
||||
'刷新房间列表项
|
||||
For Each RoomItem As MyListItem In PanRoom.Children
|
||||
CType(RoomItem.Tag, RoomEntry).RefreshUi(RoomItem)
|
||||
Next
|
||||
'刷新操作提示
|
||||
If UserList.Count = 0 Then
|
||||
If RoomListForMe.Count = 0 Then
|
||||
LabHint.Text = "若想创建房间,请点击创建房间按钮,并按说明进行操作。" & vbCrLf & "若想加入他人的房间,请点击建立连接,然后输入对方的联机码。"
|
||||
Else
|
||||
LabHint.Text = "若想让其他人加入你的房间,请点击复制联机码,然后让你的朋友输入你的联机码以建立连接。"
|
||||
End If
|
||||
Else
|
||||
If GetRoomList.Count = 0 Then
|
||||
LabHint.Text = "若想创建房间,请点击创建房间按钮,然后输入对局域网开放后 MC 显示的端口号,或本地服务端的端口号。"
|
||||
ElseIf RoomListForMe.Count = 0 Then
|
||||
'已有连接,本人没有房间,对方有房间
|
||||
LabHint.Text = "若想加入某个房间,直接点击该房间即可获取说明。"
|
||||
Else
|
||||
'已有连接,且本人有房间
|
||||
LabHint.Text = "指向你所创建的房间,能在右侧找到修改房间名称、关闭房间等选项。" &
|
||||
If(RoomListForMe.Count <> GetRoomList.Count, vbCrLf & "若想加入其他人的房间,直接点击该房间即可获取说明。", "")
|
||||
End If
|
||||
End If
|
||||
Catch ex As Exception
|
||||
Log(ex, "联机模块 UI 时钟运行失败", LogLevel.Feedback)
|
||||
End Try
|
||||
End Sub
|
||||
|
||||
'工作线程刷新
|
||||
Public Sub RefreshWorker()
|
||||
Try
|
||||
'检测退出
|
||||
If InitLoader.State = LoadState.Finished AndAlso IoiProcess.HasExited Then
|
||||
Log("[IOI] 联机模块出现异常!", LogLevel.Hint)
|
||||
ModuleStopManually()
|
||||
End If
|
||||
'检测用户
|
||||
For i = 0 To UserList.Values.Count - 1
|
||||
If i > UserList.Values.Count - 1 Then Exit For
|
||||
Dim User = UserList.Values(i)
|
||||
If User.Progress < 1 Then Continue For '跳过连接中的用户
|
||||
'发送心跳包
|
||||
If Date.Now - User.LastSend > New TimeSpan(0, 0, RandomInteger(50, 30)) Then
|
||||
RunInNewThread(Sub()
|
||||
Try
|
||||
SendUpdateRequest(User, 1)
|
||||
Catch ex As Exception
|
||||
Log(ex, "心跳包发送失败(" & User.DisplayName & ")", LogLevel.Normal)
|
||||
End Try
|
||||
End Sub, "Link Heartbeat " & User.Id)
|
||||
End If
|
||||
'检测被动离线
|
||||
If Date.Now - User.LastReceive > New TimeSpan(0, 2, 0) Then
|
||||
SendDisconnectRequest(User)
|
||||
Hint("与 " & User.DisplayName & " 的连接已中断!", HintType.Critical)
|
||||
End If
|
||||
Next
|
||||
Catch ex As Exception
|
||||
Log(ex, "联机模块工作时钟运行失败", LogLevel.Feedback)
|
||||
End Try
|
||||
End Sub
|
||||
|
||||
#End Region
|
||||
@@ -482,65 +54,6 @@ StartDownload:
|
||||
''' 发送 Portsub 请求并等待获取控制台端口。进度将从 0 变化至 80%。
|
||||
''' </summary>
|
||||
Private Shared Sub SendPortsubRequest(User As LinkUserIoi)
|
||||
Log("[IOI] 尝试建立连接:" & User.Id)
|
||||
'向对方发送 portsub 请求
|
||||
Dim Retry As Integer = 0
|
||||
RetryLink:
|
||||
Dim Result As JObject = GetJson(NetRequestOnce("http://127.0.0.1:55555/api/link?id=" & User.Id & "&password=" & IoiPassword, "PUT", "", "", 100000))
|
||||
'失败与重试
|
||||
If Result("msg") IsNot Nothing Then
|
||||
Dim ErrorMessage As String = Result("msg").ToString
|
||||
Select Case ErrorMessage
|
||||
Case "failed to find any peer in table"
|
||||
Retry += 1
|
||||
ErrorMessage = "我方网络环境不佳,连接失败。" '初始化对等机列表超时
|
||||
Log("[IOI] 尝试建立连接结果:未找到对等机,第 " & Retry & " 级重试")
|
||||
Case "routing: not found"
|
||||
Retry += 4
|
||||
ErrorMessage = "我方或对方网络环境不佳,或对方已关闭联机模块,未找到路由。" '未知情况
|
||||
Log("[IOI] 尝试建立连接结果:无法连接到路由,第 " & Retry & " 级重试")
|
||||
Case "you are already connected to specified host"
|
||||
If User.IsDisposed Then Throw New ThreadInterruptedException("用户对象已被释放")
|
||||
Log("[IOI] 尝试建立连接结果:已与对方连接")
|
||||
GoTo Done
|
||||
'Retry += 1
|
||||
'NetRequestOnce("http://127.0.0.1:55555/api/link?id=" & User.Id & "&password=" & IoiPassword, "DELETE", "", "", 100000)
|
||||
'ErrorMessage = "已与对方连接。" '双向连接偶尔导致
|
||||
'Log("[IOI] 已与对方连接,尝试中断现有连接,第 " & Retry & " 级重试")
|
||||
Case "dial backoff"
|
||||
Retry += 20
|
||||
ErrorMessage = "对方网络环境不佳,或对方已关闭联机模块。请尝试让对方主动连接你,而不是你去连接对方。" 'NAT2 连 NAT4 导致
|
||||
Log("[IOI] 尝试建立连接结果:NAT 异常,第 " & Retry & " 级重试")
|
||||
Case Else
|
||||
If ErrorMessage.Contains("all dials failed") Then
|
||||
Retry += 8
|
||||
ErrorMessage = "我方或对方网络环境不佳,或对方已关闭联机模块,连接失败。" '网络不佳,或对方已关闭模块
|
||||
Log("[IOI] 尝试建立连接结果:连接失败,第 " & Retry & " 级重试")
|
||||
Else
|
||||
Retry += 8
|
||||
Log("[IOI] 尝试建立连接结果:未知错误(" & ErrorMessage & "),第 " & Retry & " 级重试")
|
||||
End If
|
||||
End Select
|
||||
If User.IsDisposed Then Throw New ThreadInterruptedException("用户对象已被释放")
|
||||
If Retry <= 64 Then
|
||||
User.Progress = Retry * 0.01 + 0.05
|
||||
Thread.Sleep(3000)
|
||||
GoTo RetryLink
|
||||
Else
|
||||
Throw New InvalidOperationException(ErrorMessage)
|
||||
End If
|
||||
End If
|
||||
Log("[IOI] 尝试建立连接结果:成功")
|
||||
'等待获取对方端口
|
||||
Done:
|
||||
Dim WaitCount As Integer = 0
|
||||
Do Until User.Ports.ContainsKey(55555) AndAlso User.Ports.ContainsKey(55557)
|
||||
WaitCount += 1
|
||||
User.Progress = 0.7 + WaitCount / 200 * 0.1 '70% ~ 80%
|
||||
If WaitCount = 100 Then Throw New Exception("连接超时,请尝试重新连接(未收到端口回报)!")
|
||||
Thread.Sleep(150)
|
||||
Loop
|
||||
User.Progress = 0.8
|
||||
End Sub
|
||||
|
||||
''' <summary>
|
||||
@@ -584,20 +97,6 @@ Done:
|
||||
''' 尝试发送断开请求,并将其从用户列表中移除。
|
||||
''' </summary>
|
||||
Private Shared Sub SendDisconnectRequest(User As LinkUserIoi, Optional Message As String = Nothing, Optional IsError As Boolean = False)
|
||||
Dim RawJson As New JObject()
|
||||
RawJson("id") = IoiId
|
||||
RawJson("type") = "disconnect"
|
||||
If Message IsNot Nothing Then
|
||||
RawJson("message") = Message
|
||||
RawJson("isError") = IsError
|
||||
End If
|
||||
Try
|
||||
User.Send(RawJson)
|
||||
Thread.Sleep(50)
|
||||
Catch
|
||||
End Try
|
||||
NetRequestOnce("http://127.0.0.1:55555/api/link?id=" & User.Id & "&password=" & IoiPassword, "DELETE", "", "", 500)
|
||||
User.Dispose()
|
||||
End Sub
|
||||
|
||||
#End Region
|
||||
@@ -606,29 +105,9 @@ Done:
|
||||
|
||||
'刷新连接
|
||||
Private Shared Sub BtnListRefresh_Click(sender As MyIconButton, e As EventArgs)
|
||||
Dim User As LinkUserIoi = sender.Tag
|
||||
User.PingRecord.Clear()
|
||||
FrmLinkIoi.RefreshUi()
|
||||
RunInThread(Sub()
|
||||
Try
|
||||
SendUpdateRequest(User, 1)
|
||||
Catch ex As Exception
|
||||
If InitLoader.State = LoadState.Finished Then Log(ex, "刷新与 " & User.DisplayName & " 的连接失败", LogLevel.Hint)
|
||||
End Try
|
||||
End Sub)
|
||||
End Sub
|
||||
'断开连接
|
||||
Private Shared Sub BtnListDisconnect_Click(sender As MyIconButton, e As EventArgs)
|
||||
Dim User As LinkUserIoi = sender.Tag
|
||||
sender.IsEnabled = False
|
||||
RunInThread(Sub()
|
||||
If User.Progress < 1 AndAlso User.RelativeThread IsNot Nothing AndAlso User.RelativeThread.IsAlive Then
|
||||
NetRequestOnce("http://127.0.0.1:55555/api/link?id=" & User.Id & "&password=" & IoiPassword, "DELETE", "", "", 500)
|
||||
User.Dispose()
|
||||
Else
|
||||
SendDisconnectRequest(User, GetPlayerName() & " 主动断开了连接!")
|
||||
End If
|
||||
End Sub)
|
||||
End Sub
|
||||
'复制联机码
|
||||
Public Shared Sub BtnLeftCopy_Click() Handles BtnLeftCopy.Click
|
||||
@@ -680,46 +159,10 @@ Done:
|
||||
|
||||
#Region "请求核心"
|
||||
|
||||
Private Shared Listener As Socket = Nothing
|
||||
''' <summary>
|
||||
''' 启动 Socket 监听核心。
|
||||
''' </summary>
|
||||
Public Shared Sub StartSocketListener()
|
||||
If Listener IsNot Nothing Then Exit Sub '已经启动过了
|
||||
Listener = New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp) With {.ReceiveTimeout = 1000000000, .SendTimeout = 1000000000}
|
||||
Listener.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, True)
|
||||
Try
|
||||
Listener.Bind(New IPEndPoint(IPAddress.Any, 55557))
|
||||
Catch ex As Exception
|
||||
Log(ex, "初次启动 Socket 监听核心失败,开始重试")
|
||||
Thread.Sleep(1000)
|
||||
Listener.Bind(New IPEndPoint(IPAddress.Any, 55557))
|
||||
End Try
|
||||
Listener.Listen(100)
|
||||
Log("[IOI] 已启动 Socket 监听核心")
|
||||
RunInNewThread(Sub()
|
||||
While True
|
||||
Try
|
||||
'获取新的 Socket
|
||||
Dim bytes(1024) As Byte
|
||||
Dim ClientSocket As Socket = Listener.Accept()
|
||||
'获取初始输入信息
|
||||
Dim RequestInput As String = Encoding.UTF8.GetString(bytes, 0, ClientSocket.Receive(bytes))
|
||||
If Not RequestInput.StartsWith("PCL - ") Then Exit Sub
|
||||
Dim RawData As String
|
||||
Try
|
||||
RawData = SecretDecrypt(WebUtility.UrlDecode(RequestInput.Substring(6)))
|
||||
Log("[IOI] 接收到新的 Socket:" & RawData)
|
||||
PageLinkIoi.ReceiveJson(GetJson(RawData), ClientSocket)
|
||||
Catch ex As Exception
|
||||
Log(ex, "新的 Socket 处理出错(内容:" & RequestInput & ")")
|
||||
End Try
|
||||
Catch ex As Exception
|
||||
Log(ex, "Socket 监听出错")
|
||||
Thread.Sleep(3000) '防止死循环出错
|
||||
End Try
|
||||
End While
|
||||
End Sub, "Socket Listener")
|
||||
End Sub
|
||||
|
||||
#End Region
|
||||
@@ -738,40 +181,9 @@ Done:
|
||||
'请求管理
|
||||
Public Socket As Socket = Nothing
|
||||
Public Sub Send(Request As JObject)
|
||||
If Socket Is Nothing Then Throw New Exception("该用户尚未绑定 Socket")
|
||||
Dim Data As String = Request.ToString(Newtonsoft.Json.Formatting.None)
|
||||
If ModeDebug Then Log("[IOI] 发送联机数据包(" & DisplayName & "):" & Data)
|
||||
Data = "PCL - " & WebUtility.UrlEncode(SecretEncrypt(Data))
|
||||
Me.LastSend = Date.Now
|
||||
Socket.Send(Encoding.UTF8.GetBytes(Data))
|
||||
End Sub
|
||||
Public ListenerThread As Thread = Nothing
|
||||
Public Sub StartListener()
|
||||
If ListenerThread IsNot Nothing Then Exit Sub
|
||||
'启动监听
|
||||
ListenerThread = RunInNewThread(Sub()
|
||||
Try
|
||||
Dim bytes(1024) As Byte
|
||||
While PageLinkIoi.UserList.ContainsValue(Me)
|
||||
Dim RequestInput As String = Encoding.UTF8.GetString(bytes, 0, Socket.Receive(bytes))
|
||||
If Not RequestInput.StartsWith("PCL - ") Then Exit Sub
|
||||
Dim RawData As String = SecretDecrypt(WebUtility.UrlDecode(RequestInput.Substring(6)))
|
||||
If ModeDebug Then Log("[IOI] 接收联机数据包(" & DisplayName & "):" & RawData)
|
||||
PageLinkIoi.ReceiveJson(GetJson(RawData)) '调用去实际的联机模块
|
||||
End While
|
||||
Catch ex As ThreadInterruptedException
|
||||
Log("[IOI] 用户监听已中断(" & DisplayName & ")")
|
||||
Catch ex As Exception
|
||||
If IsDisposed Then Exit Sub
|
||||
If ex.GetType.Equals(GetType(SocketException)) AndAlso CType(ex, SocketException).SocketErrorCode = 10053 Then
|
||||
Log("[IOI] 客户端已关闭(" & DisplayName & ")")
|
||||
PageLinkIoi.UserRemove(CType(Me, PageLinkIoi.LinkUserIoi), True)
|
||||
Exit Sub
|
||||
End If
|
||||
Log(ex, "用户监听出错(" & DisplayName & ")")
|
||||
PageLinkIoi.UserRemove(CType(Me, PageLinkIoi.LinkUserIoi), True)
|
||||
End Try
|
||||
End Sub, "Link Listener " & DisplayName)
|
||||
End Sub
|
||||
Public Sub BindSocket(Socket As Socket)
|
||||
If Me.Socket IsNot Nothing Then Throw New Exception("该用户已经绑定了 Socket")
|
||||
@@ -975,135 +387,12 @@ Done:
|
||||
|
||||
'正向与反向连接
|
||||
Public Shared Sub BtnLeftCreate_Click() Handles BtnLeftCreate.Click
|
||||
''获取信息
|
||||
'Dim Code As String = MyMsgBoxInput("", New ObjectModel.Collection(Of Validate) From {New ValidateLength(9, 99999)}, "", "输入对方的联机码", "确定", "取消")
|
||||
'If Code Is Nothing Then Exit Sub
|
||||
''检查
|
||||
'If Code.StartsWith("P") AndAlso Code.Length < 48 Then
|
||||
' Hint("你输入的可能是 HiPer 的联机码,请在左侧的联机方式中选择 HiPer!", HintType.Critical) : Exit Sub
|
||||
'End If
|
||||
'Dim Id As String, DisplayName As String
|
||||
'Try '解密失败检查
|
||||
' Id = "12D3" & Code.Substring(0, 48)
|
||||
' DisplayName = SecretDecrypt(Code.Substring(48))
|
||||
'Catch
|
||||
' Hint("你输入的联机码有误!", HintType.Critical)
|
||||
' Exit Sub
|
||||
'End Try
|
||||
'If Id = IoiId Then '自我连接检查
|
||||
' Hint("我连我自己?搁这卡 Bug 呢?", HintType.Critical)
|
||||
' Exit Sub
|
||||
'End If
|
||||
''开始
|
||||
'Dim User As New LinkUserIoi(Id, DisplayName)
|
||||
'User.RelativeThread = RunInNewThread(Sub()
|
||||
' Dim WaitCount As Integer = 0
|
||||
' Try
|
||||
' '加入列表
|
||||
' If UserList.ContainsKey(Id) Then
|
||||
' Hint(UserList(Id).DisplayName & " 已在列表中,无需再次连接!")
|
||||
' Exit Sub
|
||||
' Else
|
||||
' UserList.Add(Id, User)
|
||||
' End If
|
||||
' '发送 portsub 请求(0% -> 80%)
|
||||
' SendPortsubRequest(User)
|
||||
' '构建 Socket(81% -> 82%)
|
||||
' Dim ClientSocket As New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp) With {.ReceiveTimeout = 1000000000, .SendTimeout = 1000000000}
|
||||
' ClientSocket.Connect(New IPEndPoint(IPAddress.Parse(User.Ports(55557)), 55557))
|
||||
' User.BindSocket(ClientSocket)
|
||||
' User.Progress = 0.82
|
||||
' '发送 connect 请求(83% -> 85%)
|
||||
' SendConnectRequest(User)
|
||||
' User.Progress = 0.85
|
||||
' '等待对方向自己请求
|
||||
' Log("[IOI] 加入成功,等待反向请求")
|
||||
' Do While User.Progress < 0.9999
|
||||
' User.Progress += 0.0002
|
||||
' If User.Progress > 0.98 AndAlso User.Progress < 0.9999 Then Throw New Exception("对方未回应连接请求!")
|
||||
' Thread.Sleep(100)
|
||||
' Loop
|
||||
' Hint("已连接到 " & User.DisplayName & "!", HintType.Finish)
|
||||
' Catch ex As ThreadInterruptedException
|
||||
' Log("[IOI] 已中断主动发起的连接(" & User.DisplayName & ")")
|
||||
' Catch ex As InvalidOperationException
|
||||
' 'API 返回的错误
|
||||
' NetRequestOnce("http://127.0.0.1:55555/api/link?id=" & Id & "&password=" & IoiPassword, "DELETE", "", "", 500)
|
||||
' User.Dispose()
|
||||
' If InitLoader.State = LoadState.Finished Then Log("与 " & DisplayName & " 建立连接失败:" & ex.Message, LogLevel.Msgbox)
|
||||
' Catch ex As Exception
|
||||
' '常规错误
|
||||
' NetRequestOnce("http://127.0.0.1:55555/api/link?id=" & Id & "&password=" & IoiPassword, "DELETE", "", "", 500)
|
||||
' User.Dispose()
|
||||
' If ex.InnerException IsNot Nothing AndAlso TypeOf ex.InnerException Is ThreadInterruptedException Then Exit Sub
|
||||
' If InitLoader.State = LoadState.Finished Then Log(ex, "与 " & DisplayName & " 建立连接失败", LogLevel.Msgbox)
|
||||
' End Try
|
||||
' End Sub, "Link Create " & DisplayName)
|
||||
End Sub
|
||||
Private Shared Sub SendPortsubBack(User As LinkUserIoi, TargetVersion As Integer)
|
||||
Try
|
||||
SendPortsubRequest(User)
|
||||
User.Progress = 0.9
|
||||
If TargetVersion > RequestVersion Then
|
||||
SendDisconnectRequest(User, "无法连接到 " & GetPlayerName() & ":对方的 PCL 版本过低!", True)
|
||||
Throw New InvalidOperationException("你的 PCL 版本过低!")
|
||||
ElseIf TargetVersion < RequestVersion Then
|
||||
SendDisconnectRequest(User, "无法连接到 " & GetPlayerName() & ":你的 PCL 版本过低!", True)
|
||||
Throw New InvalidOperationException("对方的 PCL 版本过低!")
|
||||
Else
|
||||
SendUpdateRequest(User, 1)
|
||||
User.Progress = 1
|
||||
Hint(User.DisplayName & " 已与你建立连接!")
|
||||
End If
|
||||
Catch ex As ThreadInterruptedException
|
||||
Log("[IOI] 已中断被动建立的连接(" & User.DisplayName & ")")
|
||||
Catch ex As InvalidOperationException
|
||||
'API 返回的错误
|
||||
NetRequestOnce("http://127.0.0.1:55555/api/link?id=" & User.Id & "&password=" & IoiPassword, "DELETE", "", "", 500)
|
||||
User.Dispose()
|
||||
If InitLoader.State = LoadState.Finished Then Log("与 " & User.DisplayName & " 建立连接失败:" & ex.Message, LogLevel.Hint)
|
||||
Catch ex As Exception
|
||||
'常规错误
|
||||
NetRequestOnce("http://127.0.0.1:55555/api/link?id=" & User.Id & "&password=" & IoiPassword, "DELETE", "", "", 500)
|
||||
User.Dispose()
|
||||
If InitLoader.State = LoadState.Finished Then Log(ex, "与 " & User.DisplayName & " 建立连接失败", LogLevel.Hint)
|
||||
End Try
|
||||
End Sub
|
||||
|
||||
'创建房间
|
||||
Private Sub LinkCreate() Handles BtnCreate.Click
|
||||
'If MyMsgBox("请先进入 MC 并暂停游戏,在暂停页面选择对局域网开放,然后在下一个窗口输入 MC 显示的端口号。" & vbCrLf & "若使用服务端开服,则直接在下一个窗口输入服务器配置中的端口号即可。", "提示", "继续", "取消") = 2 Then Exit Sub
|
||||
''获取端口号
|
||||
'Dim Port As String = MyMsgBoxInput("", New ObjectModel.Collection(Of Validate) From {
|
||||
' New ValidateInteger(0, 65535),
|
||||
' New ValidateExceptSame({"55555", "55557"}, "端口不能为 %!"),
|
||||
' New ValidateExceptSame(RoomListForMe.Select(AddressOf RoomEntry.SelectPort), "端口 % 已创建过房间,请在删除该房间后继续!")
|
||||
' }, "", "输入端口号", "确定", "取消")
|
||||
'If Port Is Nothing Then Exit Sub
|
||||
''获取显示名称
|
||||
'Dim DisplayName As String = MyMsgBoxInput(GetPlayerName() & " 的房间 - " & Port, New ObjectModel.Collection(Of Validate) From {
|
||||
' New ValidateNullOrWhiteSpace(), New ValidateLength(1, 40), New ValidateFilter()
|
||||
' }, "", "输入房间名(建议包含游戏版本等信息)", "确定", "取消")
|
||||
'If DisplayName Is Nothing Then Exit Sub
|
||||
'DisplayName = DisplayName.Trim
|
||||
''开始
|
||||
'RunInThread(Sub()
|
||||
' Try
|
||||
' '请求
|
||||
' Dim Result As JObject = GetJson(NetRequestOnce("http://127.0.0.1:55555/api/port?proto=tcp&port=" & Port & "&password=" & IoiPassword, "PUT", "", "", 100000))
|
||||
' If Result("msg") IsNot Nothing Then Throw New InvalidOperationException(Result("msg").ToString)
|
||||
' '成功
|
||||
' RoomListForMe.Add(New RoomEntry(Port, DisplayName))
|
||||
' Hint("房间 " & DisplayName & " 已创建!", HintType.Finish)
|
||||
' SendUpdateRequestToAllUsers()
|
||||
' Catch ex As InvalidOperationException
|
||||
' 'API 返回的错误
|
||||
' Log("创建房间失败:" & ex.Message, LogLevel.Msgbox)
|
||||
' Catch ex As Exception
|
||||
' '常规错误
|
||||
' Log(ex, "创建房间失败", LogLevel.Msgbox)
|
||||
' End Try
|
||||
' End Sub)
|
||||
End Sub
|
||||
Private Shared Sub SendUpdateRequestToAllUsers()
|
||||
For i = 0 To UserList.Count - 1
|
||||
@@ -1119,18 +408,6 @@ Done:
|
||||
End Sub
|
||||
'修改房间名称
|
||||
Private Shared Sub BtnRoomEdit_Click(sender As MyIconButton, e As EventArgs)
|
||||
'Dim Room As RoomEntry = sender.Tag
|
||||
''获取房间名
|
||||
'Dim DisplayName As String = MyMsgBoxInput(Room.DisplayName, New ObjectModel.Collection(Of Validate) From {
|
||||
' New ValidateNullOrWhiteSpace(),
|
||||
' New ValidateLength(1, 40)
|
||||
' }, "", "输入房间名(建议包含游戏版本等信息)", "确定", "取消")
|
||||
'If DisplayName Is Nothing Then Exit Sub
|
||||
'DisplayName = DisplayName.Trim
|
||||
''修改
|
||||
'Room.DisplayName = DisplayName
|
||||
'FrmLinkIoi.RefreshUi()
|
||||
'SendUpdateRequestToAllUsers()
|
||||
End Sub
|
||||
'加入房间
|
||||
Private Shared Sub BtnRoom_Click(sender As MyListItem, e As EventArgs)
|
||||
@@ -1141,25 +418,6 @@ Done:
|
||||
End Sub
|
||||
'关闭房间
|
||||
Private Shared Sub BtnRoomClose_Click(sender As MyIconButton, e As EventArgs)
|
||||
Dim Room As RoomEntry = sender.Tag
|
||||
RunInThread(Sub()
|
||||
Try
|
||||
'远程移除
|
||||
Dim Result As JObject = GetJson(NetRequestOnce("http://127.0.0.1:55555/api/port?proto=tcp&port=" & Room.Port & "&password=" & IoiPassword, "DELETE", "", "", 100000))
|
||||
If Result("msg") IsNot Nothing Then Throw New InvalidOperationException(Result("msg").ToString)
|
||||
'本地移除
|
||||
RoomListForMe.Remove(Room)
|
||||
'成功
|
||||
RunInUi(Sub() FrmLinkIoi.RefreshUi())
|
||||
SendUpdateRequestToAllUsers()
|
||||
Catch ex As InvalidOperationException
|
||||
'API 返回的错误
|
||||
If InitLoader.State = LoadState.Finished Then Log("移除房间失败:" & ex.Message, LogLevel.Msgbox)
|
||||
Catch ex As Exception
|
||||
'常规错误
|
||||
If InitLoader.State = LoadState.Finished Then Log(ex, "移除房间失败", LogLevel.Msgbox)
|
||||
End Try
|
||||
End Sub)
|
||||
End Sub
|
||||
|
||||
'获取数据包
|
||||
@@ -1238,21 +496,9 @@ Done:
|
||||
''' 从用户列表中移除一位用户。提示信息视作该用户主动离开。
|
||||
''' </summary>
|
||||
Public Shared Sub UserRemove(User As LinkUserIoi, ShowLeaveMessage As Boolean)
|
||||
If Not UserList.ContainsKey(User.Id) Then Exit Sub
|
||||
If ShowLeaveMessage Then Hint(User.DisplayName & " 已离开!")
|
||||
NetRequestOnce("http://127.0.0.1:55555/api/link?id=" & User.Id & "&password=" & IoiPassword, "DELETE", "", "", 500)
|
||||
User.Dispose()
|
||||
End Sub
|
||||
|
||||
'关闭联机模块按钮
|
||||
Private Shared Sub ModuleStateChanged(Loader As LoaderBase, NewState As LoadState, OldState As LoadState) Handles InitLoader.OnStateChangedUi
|
||||
If FrmLinkLeft IsNot Nothing Then CType(FrmLinkLeft.ItemIoi.Buttons(0), MyIconButton).Visibility = If(NewState = LoadState.Finished, Visibility.Visible, Visibility.Collapsed)
|
||||
End Sub
|
||||
Public Shared Sub ModuleStopManually()
|
||||
IoiStop(False)
|
||||
InitLoader.Error = New Exception("联机模块已关闭,点击以重新启动")
|
||||
InitLoader.State = LoadState.Failed
|
||||
IoiState = LoadState.Failed
|
||||
End Sub
|
||||
|
||||
End Class
|
||||
|
||||
Reference in New Issue
Block a user