- 修复第一次连接时ClientID为0导致匹配失败的问题 - 在GameClientMatchmaker中添加ClientID检测和自动重连逻辑 - 当检测到ClientID为0时,等待0.5秒后自动断开并重新连接 - 优化MatchmakingPanel显示逻辑,根据ClientID状态显示正确的连接状态
310 lines
9.5 KiB
C#
310 lines
9.5 KiB
C#
using System.Collections;
|
||
using System.Collections.Generic;
|
||
using UnityEngine;
|
||
using Unity.Netcode;
|
||
using UnityEngine.Events;
|
||
using TcgEngine.UI;
|
||
|
||
namespace TcgEngine.Client
|
||
{
|
||
/// <summary>
|
||
/// 匹配器的主客户端脚本
|
||
/// 将向服务器发送请求并在匹配成功或失败时接收响应
|
||
/// </summary>
|
||
|
||
public class GameClientMatchmaker : MonoBehaviour
|
||
{
|
||
public UnityAction<MatchmakingResult> onMatchmaking;
|
||
public UnityAction<MatchmakingList> onMatchmakingList;
|
||
public UnityAction<MatchList> onMatchList;
|
||
|
||
private bool matchmaking = false;
|
||
private float timer = 0f;
|
||
private float match_timer = 0f;
|
||
private string matchmaking_group;
|
||
private int matchmaking_players;
|
||
private UnityAction<bool> connect_callback;
|
||
|
||
private float clientid_check_timer = 0f;
|
||
private bool reconnecting = false;
|
||
|
||
private static GameClientMatchmaker _instance;
|
||
|
||
void Awake()
|
||
{
|
||
_instance = this;
|
||
}
|
||
|
||
private void Start()
|
||
{
|
||
TcgNetwork.Get().onConnect += OnConnect;
|
||
TcgNetwork.Get().onDisconnect += OnDisconnect;
|
||
Messaging.ListenMsg("matchmaking", ReceiveMatchmaking);
|
||
Messaging.ListenMsg("matchmaking_list", ReceiveMatchmakingList);
|
||
Messaging.ListenMsg("match_list", ReceiveMatchList);
|
||
}
|
||
|
||
private void OnDestroy()
|
||
{
|
||
Disconnect(); //Disconnect when switching scene
|
||
|
||
if (TcgNetwork.Get() != null)
|
||
{
|
||
TcgNetwork.Get().onConnect -= OnConnect;
|
||
TcgNetwork.Get().onDisconnect -= OnDisconnect;
|
||
Messaging.UnListenMsg("matchmaking");
|
||
Messaging.UnListenMsg("matchmaking_list");
|
||
Messaging.UnListenMsg("match_list");
|
||
}
|
||
}
|
||
|
||
void Update()
|
||
{
|
||
if (matchmaking)
|
||
{
|
||
timer += Time.deltaTime;
|
||
match_timer += Time.deltaTime;
|
||
|
||
ulong client_id = TcgNetwork.Get().ClientID;
|
||
|
||
//检测ClientID为0的情况(连接未完全建立)
|
||
if (IsConnected() && client_id == 0 && !reconnecting)
|
||
{
|
||
clientid_check_timer += Time.deltaTime;
|
||
|
||
//如果超过3秒ClientID仍为0,断开并重连
|
||
if (clientid_check_timer > 0.5f)
|
||
{
|
||
Debug.Log("ClientID is 0 after 3 seconds, reconnecting...");
|
||
reconnecting = true;
|
||
|
||
//保存匹配信息
|
||
string saved_group = matchmaking_group;
|
||
int saved_players = matchmaking_players;
|
||
|
||
//断开连接
|
||
Disconnect();
|
||
|
||
//延迟后重新开始匹配
|
||
StartCoroutine(ReconnectAfterDelay(saved_group, saved_players));
|
||
|
||
clientid_check_timer = 0f;
|
||
}
|
||
}
|
||
else if (IsConnected() && client_id != 0)
|
||
{
|
||
//ClientID正常,重置计时器
|
||
clientid_check_timer = 0f;
|
||
reconnecting = false;
|
||
}
|
||
|
||
//Send periodic request
|
||
if (IsConnected() && client_id != 0 && timer > 2f)
|
||
{
|
||
timer = 0f;
|
||
SendMatchRequest(true, matchmaking_group, matchmaking_players);
|
||
}
|
||
|
||
//Disconnected, stop
|
||
if (!IsConnected() && !IsConnecting() && timer > 5f)
|
||
{
|
||
StopMatchmaking();
|
||
}
|
||
}
|
||
}
|
||
|
||
private IEnumerator ReconnectAfterDelay(string group, int players)
|
||
{
|
||
yield return new WaitForSeconds(0.5f);
|
||
|
||
Debug.Log($"Reconnecting with group: {group}, players: {players}");
|
||
StartMatchmaking(group, players);
|
||
reconnecting = false;
|
||
}
|
||
|
||
public void StartMatchmaking(string group, int nb_players)
|
||
{
|
||
if (matchmaking)
|
||
StopMatchmaking();
|
||
|
||
Debug.Log("Start Matchmaking!");
|
||
matchmaking_group = group;
|
||
matchmaking_players = nb_players;
|
||
matchmaking = true;
|
||
match_timer = 0f;
|
||
timer = 0f;
|
||
|
||
Connect(NetworkData.Get().url, NetworkData.Get().port, (bool success) =>
|
||
{
|
||
if (success)
|
||
{
|
||
SendMatchRequest(false, group, nb_players);
|
||
}
|
||
else
|
||
{
|
||
StopMatchmaking();
|
||
}
|
||
});
|
||
}
|
||
|
||
public void StopMatchmaking()
|
||
{
|
||
if (matchmaking)
|
||
{
|
||
Debug.Log("Stop Matchmaking!");
|
||
onMatchmaking?.Invoke(null);
|
||
matchmaking_group = "";
|
||
matchmaking_players = 0;
|
||
matchmaking = false;
|
||
}
|
||
}
|
||
|
||
public void RefreshMatchmakingList()
|
||
{
|
||
Connect(NetworkData.Get().url, NetworkData.Get().port, (bool success) =>
|
||
{
|
||
if (success)
|
||
SendMatchmakingListRequest();
|
||
});
|
||
}
|
||
|
||
public void RefreshMatchList(string username)
|
||
{
|
||
Connect(NetworkData.Get().url, NetworkData.Get().port, (bool success) =>
|
||
{
|
||
if (success)
|
||
SendMatchListRequest(username);
|
||
});
|
||
}
|
||
|
||
public void Connect(string url, ushort port, UnityAction<bool> callback = null)
|
||
{
|
||
//Must be logged in to API to connect
|
||
if (!Authenticator.Get().IsSignedIn())
|
||
{
|
||
callback?.Invoke(false);
|
||
return;
|
||
}
|
||
|
||
//Check if already connected
|
||
if (IsConnected() || IsConnecting())
|
||
{
|
||
callback?.Invoke(IsConnected());
|
||
return;
|
||
}
|
||
|
||
connect_callback = callback;
|
||
TcgNetwork.Get().StartClient(url, port);
|
||
}
|
||
|
||
public void Disconnect()
|
||
{
|
||
TcgNetwork.Get()?.Disconnect();
|
||
}
|
||
|
||
private void OnConnect()
|
||
{
|
||
Debug.Log("Connected to server!");
|
||
connect_callback?.Invoke(true);
|
||
connect_callback = null;
|
||
}
|
||
|
||
private void OnDisconnect()
|
||
{
|
||
StopMatchmaking(); //Stop if currently running
|
||
connect_callback?.Invoke(false);
|
||
connect_callback = null;
|
||
matchmaking = false;
|
||
}
|
||
|
||
private void SendMatchRequest(bool refresh, string group, int nb_players)
|
||
{
|
||
MsgMatchmaking msg_match = new MsgMatchmaking();
|
||
UserData udata = Authenticator.Get().GetUserData();
|
||
msg_match.user_id = Authenticator.Get().GetUserId();
|
||
msg_match.username = Authenticator.Get().GetUsername();
|
||
msg_match.group = group;
|
||
msg_match.players = nb_players;
|
||
msg_match.elo = udata.elo;
|
||
msg_match.time = match_timer;
|
||
msg_match.refresh = refresh;
|
||
Messaging.SendObject("matchmaking", ServerID, msg_match, NetworkDelivery.Reliable);
|
||
}
|
||
|
||
private void SendMatchmakingListRequest()
|
||
{
|
||
MsgMatchmakingList msg_match = new MsgMatchmakingList();
|
||
msg_match.username = ""; //Return all users
|
||
Messaging.SendObject("matchmaking_list", ServerID, msg_match, NetworkDelivery.Reliable);
|
||
}
|
||
|
||
private void SendMatchListRequest(string username)
|
||
{
|
||
MsgMatchmakingList msg_match = new MsgMatchmakingList();
|
||
msg_match.username = username;
|
||
Messaging.SendObject("match_list", ServerID, msg_match, NetworkDelivery.Reliable);
|
||
}
|
||
|
||
private void ReceiveMatchmaking(ulong client_id, FastBufferReader reader)
|
||
{
|
||
reader.ReadNetworkSerializable(out MatchmakingResult msg);
|
||
|
||
if (IsConnected() && matchmaking && matchmaking_group == msg.group)
|
||
{
|
||
matchmaking = !msg.success; //Stop matchmaking if success
|
||
onMatchmaking?.Invoke(msg);
|
||
}
|
||
}
|
||
|
||
private void ReceiveMatchmakingList(ulong client_id, FastBufferReader reader)
|
||
{
|
||
reader.ReadNetworkSerializable(out MatchmakingList list);
|
||
onMatchmakingList?.Invoke(list);
|
||
}
|
||
|
||
private void ReceiveMatchList(ulong client_id, FastBufferReader reader)
|
||
{
|
||
reader.ReadNetworkSerializable(out MatchList list);
|
||
onMatchList?.Invoke(list);
|
||
}
|
||
|
||
public bool IsMatchmaking()
|
||
{
|
||
return matchmaking;
|
||
}
|
||
|
||
public string GetGroup()
|
||
{
|
||
return matchmaking_group;
|
||
}
|
||
|
||
public int GetNbPlayers()
|
||
{
|
||
return matchmaking_players;
|
||
}
|
||
|
||
public float GetTimer()
|
||
{
|
||
return match_timer;
|
||
}
|
||
|
||
public bool IsConnected()
|
||
{
|
||
return TcgNetwork.Get().IsConnected();
|
||
}
|
||
|
||
public bool IsConnecting()
|
||
{
|
||
return TcgNetwork.Get().IsConnecting();
|
||
}
|
||
|
||
public ulong ServerID { get { return TcgNetwork.Get().ServerID; } }
|
||
public NetworkMessaging Messaging { get { return TcgNetwork.Get().Messaging; } }
|
||
|
||
public static GameClientMatchmaker Get()
|
||
{
|
||
return _instance;
|
||
}
|
||
}
|
||
|
||
} |