Commit c7d0c79b authored by hex's avatar hex

refactor(mycard): harden request flow and connection resilience

parent d6536a39
using UnityEngine;
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Threading;
public class MyCard : WindowServantSP
{
public bool isMatching = false;
public bool isRequesting = false;
//const string mycardTiramisuAddress = "tiramisu.mycard.moe";
//const string mycardTiramisuAthleticPort = "8911";
//const string mycardTiramisuEntertainPort = "7911";
private Coroutine requestCoroutine = null;
private Coroutine requestCoroutine = null;
private Thread joinThread = null;
MyCardHelper mycardHelper;
UIInput inputUsername;
UIInput inputPsw;
......@@ -48,10 +43,19 @@ public class MyCard : WindowServantSP
public void TerminateRequest()
{
if (mycardHelper != null)
{
mycardHelper.CancelCurrentRequest();
}
if (requestCoroutine != null)
{
Program.I().StopCoroutine(requestCoroutine);
requestCoroutine = null;
}
if (isRequesting)
{
isRequesting = false;
Program.PrintToChat(InterString.Get("匹配已中断。"));
}
......@@ -80,56 +84,102 @@ public class MyCard : WindowServantSP
Application.OpenURL("https://ygobbs.com/");
}
IEnumerator MatchCoroutine(string username, string password, string matchType) {
isRequesting = true;
Program.PrintToChat(InterString.Get("正在登录至 MyCard。"));
bool loginSuccess = false;
string failReason = "";
// 启动并等待登录协程完成
yield return Program.I().StartCoroutine(mycardHelper.Login(username, password, (success, reason) => {
loginSuccess = success;
failReason = reason;
}));
if (!loginSuccess) {
Program.PrintToChat(InterString.Get("MyCard 登录失败。原因: ") + failReason);
isRequesting = false;
yield break; // 结束协程
bool TryStartJoinThread(MatchResultObject matchResultObject)
{
if (matchResultObject == null)
{
return false;
}
Program.PrintToChat(InterString.Get("MyCard 登录成功,用户名: ") + mycardHelper.username);
// Program.PrintToChat(InterString.Get("正在获取匹配秘钥。"));
yield return Program.I().StartCoroutine(mycardHelper.GetUserU16Secret((success, reason) =>
if (joinThread != null && joinThread.IsAlive)
{
loginSuccess = success;
failReason = reason;
}));
if (!loginSuccess)
return false;
}
string address = matchResultObject.address;
string userName = mycardHelper.username;
string port = matchResultObject.port.ToString();
string roomPassword = matchResultObject.password;
string version = "0x" + string.Format("{0:X}", Config.ClientVersion);
joinThread = new Thread(() =>
{
Program.PrintToChat(InterString.Get("获取用户密钥失败。请重新登录。原因: ") + failReason);
isRequesting = false;
yield break; // 结束协程
TcpHelper.join(address, userName, port, roomPassword, version);
});
joinThread.Name = "MyCardJoinThread";
joinThread.IsBackground = true;
joinThread.Start();
return true;
}
IEnumerator MatchCoroutine(string username, string password, string matchType)
{
isRequesting = true;
try
{
Program.PrintToChat(InterString.Get("正在登录至 MyCard。"));
bool loginSuccess = false;
string failReason = "";
yield return Program.I().StartCoroutine(mycardHelper.Login(username, password, (success, reason) =>
{
loginSuccess = success;
failReason = reason;
}));
if (!loginSuccess)
{
Program.PrintToChat(InterString.Get("MyCard 登录失败。原因: ") + failReason);
yield break;
}
Program.PrintToChat(InterString.Get("MyCard 登录成功,用户名: ") + mycardHelper.username);
yield return Program.I().StartCoroutine(mycardHelper.GetUserU16Secret((success, reason) =>
{
loginSuccess = success;
failReason = reason;
}));
if (!loginSuccess)
{
Program.PrintToChat(InterString.Get("获取用户密钥失败。请重新登录。原因: ") + failReason);
yield break;
}
Program.PrintToChat(InterString.Get("正在请求匹配。匹配类型: ") + matchType);
MatchResultObject matchResultObject = null;
yield return Program.I().StartCoroutine(mycardHelper.RequestMatch(matchType, (result, reason) =>
{
matchResultObject = result;
failReason = reason;
}));
if (matchResultObject == null)
{
Program.PrintToChat(InterString.Get("匹配请求失败。原因: ") + failReason);
yield break;
}
if (!TryStartJoinThread(matchResultObject))
{
Program.PrintToChat(InterString.Get("连接任务已存在,请稍后再试。"));
yield break;
}
Program.PrintToChat(InterString.Get("匹配成功。正在进入房间。"));
isMatching = true;
}
// Program.PrintToChat(InterString.Get("获取匹配秘钥成功。"));
Program.PrintToChat(InterString.Get("正在请求匹配。匹配类型: ") + matchType);
MatchResultObject matchResultObject = null;
// 启动并等待匹配协程完成
yield return Program.I().StartCoroutine(mycardHelper.RequestMatch(matchType, (result, reason) => {
matchResultObject = result;
failReason = reason;
}));
if (matchResultObject == null) {
Program.PrintToChat(InterString.Get("匹配请求失败。原因: ") + failReason);
finally
{
isRequesting = false;
yield break;
requestCoroutine = null;
}
Program.PrintToChat(InterString.Get("匹配成功。正在进入房间。"));
this.isMatching = true;
// TcpHelper.join 内部自己创建并管理线程,这里直接调用是安全的
// 只要 TcpHelper.join 本身及其后续操作不调用 Unity API
(new Thread(() => { TcpHelper.join(matchResultObject.address, mycardHelper.username, matchResultObject.port.ToString(), matchResultObject.password, "0x" + String.Format("{0:X}", Config.ClientVersion)); })).Start();
isRequesting = false;
requestCoroutine = null;
}
void StartMatch(string matchType)
{
string username = inputUsername.value;
......@@ -143,16 +193,20 @@ public class MyCard : WindowServantSP
{
TerminateRequest();
}
SaveUser();
Program.PrintToChat(InterString.Get("已开始匹配。"));
// 启动协程,而不是线程
mycardHelper.ResetCancellation();
requestCoroutine = Program.I().StartCoroutine(MatchCoroutine(username, password, matchType));
}
void onClickJoinAthletic() {
void onClickJoinAthletic()
{
StartMatch("athletic");
}
void onClickJoinEntertain() {
void onClickJoinEntertain()
{
StartMatch("entertain");
}
}
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment