using UnityEngine;
|
using System;
|
using System.Collections;
|
using System.Collections.Generic;
|
using Cysharp.Threading.Tasks;
|
|
public enum NetworkType
|
{
|
TCP, // 使用原有的 TCP Socket
|
WebSocket // 使用 WebSocket(小游戏平台)
|
}
|
|
public class GameNetSystem : Singleton<GameNetSystem>
|
{
|
//限制客户端的下一个包是登录包C0101_tagCPlayerLogin,如果不是登录包不允许发送
|
bool waitLogin = false; //等待发送登录包,如果有其他包直接屏蔽,避免断线重连的情况发了攻击包之类的
|
//等待服务端0403的包后才能发其他的功能包,只有C0123_tagCClientPackVersion 和 C0101_tagCPlayerLogin 可以发送
|
bool waitLoginMap = false;
|
|
// 网络服务接口(统一支持 TCP 和 WebSocket)
|
private INetworkService networkService;
|
|
NetUpdateBehaviour m_NetUpdateBehaviour;
|
NeverConnectState neverConnectState;
|
AccountLoginState accountLoginState;
|
// CreateOrSelectRoleState createOrSelectRoleState;
|
RoleLoginState roleLoginState;
|
ConnectedState connectedState;
|
DisconnectState disconnectState;
|
|
NetState m_NetState;
|
public NetState netState
|
{
|
get { return this.m_NetState; }
|
set
|
{
|
if (this.m_NetState != value)
|
{
|
switch (m_NetState)
|
{
|
case NetState.NerverConnect:
|
neverConnectState.OnExit();
|
break;
|
case NetState.AccountLogin:
|
accountLoginState.OnExit();
|
break;
|
// case NetState.CreateOrSelectRole:
|
// // createOrSelectRoleState.OnExit();
|
// break;
|
case NetState.RoleLogin:
|
roleLoginState.OnExit();
|
break;
|
case NetState.Connected:
|
connectedState.OnExit();
|
break;
|
case NetState.DisConnected:
|
disconnectState.OnExit();
|
break;
|
}
|
|
this.m_NetState = value;
|
switch (m_NetState)
|
{
|
case NetState.NerverConnect:
|
neverConnectState.OnEnter();
|
break;
|
case NetState.AccountLogin:
|
accountLoginState.OnEnter();
|
break;
|
// case NetState.CreateOrSelectRole:
|
// // createOrSelectRoleState.OnEnter();
|
// break;
|
case NetState.RoleLogin:
|
roleLoginState.OnEnter();
|
break;
|
case NetState.Connected:
|
connectedState.OnEnter();
|
break;
|
case NetState.DisConnected:
|
disconnectState.OnEnter();
|
break;
|
}
|
}
|
}
|
}
|
|
private ClientSocket mainSocket; // 保留兼容,但不再直接使用
|
|
public bool mainSocketConnected
|
{
|
get { return networkService?.IsConnected ?? false; }
|
}
|
|
public float timeSinceMainSocketLastProtocol
|
{
|
get
|
{
|
if (networkService == null)
|
return Time.time;
|
|
var lastTime = networkService.LastPackageTime;
|
if (lastTime == DateTime.MinValue)
|
return Time.time; // 从未收包
|
|
return (float)(DateTime.Now - lastTime).TotalSeconds;
|
}
|
}
|
|
|
Queue<GameNetPackBasic> mainProtocolQueue = new Queue<GameNetPackBasic>();
|
|
|
public GameNetSystem()
|
{
|
var gameObject = new GameObject("NetUpdateBehaviour");
|
GameObject.DontDestroyOnLoad(gameObject);
|
m_NetUpdateBehaviour = gameObject.AddComponent<NetUpdateBehaviour>();
|
m_NetUpdateBehaviour.RegisterUpdateCallBack(OnUpdate);
|
|
neverConnectState = gameObject.AddComponent<NeverConnectState>();
|
accountLoginState = gameObject.AddComponent<AccountLoginState>();
|
// createOrSelectRoleState = gameObject.AddComponent<CreateOrSelectRoleState>();
|
roleLoginState = gameObject.AddComponent<RoleLoginState>();
|
connectedState = gameObject.AddComponent<ConnectedState>();
|
disconnectState = gameObject.AddComponent<DisconnectState>();
|
|
netState = NetState.NerverConnect;
|
}
|
|
public void BeginConnectGameServer(string ip, int port, Action<bool> onConnected)
|
{
|
try
|
{
|
if (networkService != null && networkService.IsConnected)
|
{
|
networkService.Disconnect();
|
}
|
}
|
catch (System.Exception ex)
|
{
|
Debug.Log(ex);
|
}
|
|
mainProtocolQueue.Clear();
|
|
// 根据 Main.CurrentNetworkType 选择网络类型
|
Debug.Log($"[GameNetSystem] 连接服务器 {ip}:{port},使用{(Main.CurrentNetworkType == NetworkType.WebSocket ? "WebSocket" : "TCP")}");
|
|
if (Main.CurrentNetworkType == NetworkType.WebSocket)
|
{
|
// 使用 WebSocket
|
ConnectWithWebSocket(ip, port, onConnected);
|
}
|
else
|
{
|
// 使用 TCP Socket(通过适配器)
|
ConnectWithTCP(ip, port, onConnected);
|
}
|
}
|
|
private async void ConnectWithTCP(string ip, int port, Action<bool> onConnected)
|
{
|
try
|
{
|
// 创建 TCP Socket 适配器(不修改 ClientSocket)
|
networkService = new ClientSocketAdapter(ServerType.Main);
|
|
// 订阅状态事件
|
networkService.OnStateChanged += OnNetworkStateChanged;
|
|
// 连接
|
string url = $"{ip}:{port}";
|
Debug.Log($"[GameNetSystem] TCP 开始连接: {url}");
|
bool success = await networkService.ConnectAsync(url);
|
|
Debug.Log($"[GameNetSystem] TCP 连接{(success ? "成功" : "失败")}: {url}");
|
|
// 兼容:保留 mainSocket 引用(但通过 networkService 访问)
|
mainSocket = (networkService as ClientSocketAdapter)?.GetClientSocket();
|
|
if (onConnected != null)
|
{
|
onConnected(success);
|
}
|
}
|
catch (System.Exception ex)
|
{
|
Debug.LogError($"[GameNetSystem] TCP 连接异常: {ex.Message}");
|
if (onConnected != null)
|
{
|
onConnected(false);
|
}
|
}
|
}
|
|
private async void ConnectWithWebSocket(string ip, int port, Action<bool> onConnected)
|
{
|
try
|
{
|
// 创建 WebSocket 服务(传入 ServerType,与 ClientSocket 一致)
|
networkService = new WebSocketNetworkService(ServerType.Main);
|
|
// 订阅状态事件
|
networkService.OnStateChanged += OnNetworkStateChanged;
|
|
string url = $"ws://{ip}:{port}";
|
Debug.Log($"[GameNetSystem] WebSocket 开始连接: {url}");
|
bool success = await networkService.ConnectAsync(url);
|
|
Debug.Log($"[GameNetSystem] WebSocket 连接{(success ? "成功" : "失败")}: {url}");
|
|
if (onConnected != null)
|
{
|
onConnected(success);
|
}
|
}
|
catch (System.Exception ex)
|
{
|
Debug.LogError($"[GameNetSystem] WebSocket 连接异常: {ex.Message}");
|
if (onConnected != null)
|
{
|
onConnected(false);
|
}
|
}
|
}
|
|
private void OnNetworkStateChanged(NetworkState state)
|
{
|
Debug.Log($"[GameNetSystem] 网络状态变化: {state}");
|
|
// 断开连接时触发断线处理
|
if (state == NetworkState.Disconnected || state == NetworkState.Closed)
|
{
|
netState = NetState.DisConnected;
|
}
|
}
|
|
//限制客户端的下一个包是登录包C0101_tagCPlayerLogin,如果不是登录包不允许发送
|
public void SetIsWaitLogin(bool _wait)
|
{
|
waitLogin = _wait;
|
}
|
|
//等待服务端0403的包后才能发其他的功能包,只有C0123_tagCClientPackVersion 和 C0101_tagCPlayerLogin 可以发送
|
public void SetIsWaitLoginMap(bool _wait)
|
{
|
waitLoginMap = _wait;
|
}
|
|
public bool GetIsWaitLoginMap()
|
{
|
return waitLoginMap;
|
}
|
|
//0403登录之前的包缓存
|
Queue<GameNetPackBasic> sendQueue = new Queue<GameNetPackBasic>();
|
|
public void SendCachePackage()
|
{
|
int cnt = sendQueue.Count;
|
while (sendQueue.Count > 0)
|
{
|
SendInfo(sendQueue.Dequeue());
|
}
|
Debug.Log($"重点提醒:0403登录后 发送缓存包数量 {cnt} 个");
|
}
|
|
public void SendInfo(GameNetPackBasic protocol)
|
{
|
Debug.LogError("protocol to send: " + protocol.ToString());
|
|
if (waitLogin)
|
{
|
if (protocol is not C0101_tagCPlayerLogin)
|
{
|
Debug.LogWarning("等待执行登录,不允许发送其他包 " + protocol.ToString());
|
return;
|
}
|
}
|
|
// 0102是从地图发送的 说明已登录,但可能卡顿导致通知route状态慢于客户端,依然需要防范
|
if (waitLoginMap)
|
{
|
if (protocol is not C0123_tagCClientPackVersion && protocol is not C0101_tagCPlayerLogin)
|
{
|
Debug.LogError("重点提醒:登录完成前的封包先加入队列 等0403回包后再一起发送服务端 " + protocol.ToString());
|
sendQueue.Enqueue(protocol);
|
return;
|
}
|
}
|
|
if (networkService != null)
|
{
|
networkService.SendInfo(protocol);
|
DebugPkgCache.Push(protocol);
|
}
|
}
|
|
public void SendInfo(byte[] vBytes)
|
{
|
if (networkService != null)
|
{
|
networkService.SendInfo(vBytes);
|
}
|
}
|
|
|
public void PushPackage(GameNetPackBasic protocol, ServerType type)
|
{
|
lock (this)
|
{
|
if (protocol == null)
|
{
|
return;
|
}
|
|
if (PackageRegedit.Contain(protocol.cmd))
|
{
|
mainProtocolQueue.Enqueue(protocol);
|
|
DebugPkgCache.Push(protocol);
|
}
|
else
|
{
|
Debug.LogErrorFormat("数据包(cmd:{0})未登记!", protocol.cmd);
|
}
|
}
|
}
|
|
public void Disconnect()
|
{
|
try
|
{
|
if (networkService != null)
|
{
|
networkService.Disconnect();
|
}
|
|
mainProtocolQueue.Clear();
|
}
|
catch (Exception ex)
|
{
|
Debug.Log(ex);
|
}
|
finally
|
{
|
netState = NetState.DisConnected;
|
LoginManager.Instance.busy = false;
|
}
|
}
|
|
|
|
public void Reconnect()
|
{
|
try
|
{
|
if (networkService != null)
|
{
|
networkService.Disconnect();
|
}
|
|
mainProtocolQueue.Clear();
|
}
|
catch (Exception ex)
|
{
|
Debug.Log(ex);
|
}
|
finally
|
{
|
netState = NetState.AccountLogin;
|
LoginManager.Instance.busy = false;
|
LoginManager.Instance.ReAccountLogin();
|
}
|
}
|
|
public void LoginOut()
|
{
|
try
|
{
|
SDKUtils.Instance.RoleLoginOut();
|
|
if (networkService != null)
|
{
|
networkService.Disconnect();
|
}
|
|
mainProtocolQueue.Clear();
|
}
|
catch (Exception ex)
|
{
|
Debug.Log(ex);
|
}
|
finally
|
{
|
netState = NetState.NerverConnect;
|
|
LoginManager.Instance.busy = false;
|
|
StageManager.Instance.ReturnToLoginScene();
|
NetLinkWin.Hide();
|
}
|
}
|
|
public void OnAccountLogin()
|
{
|
netState = NetState.AccountLogin;
|
}
|
|
public void OnEnterWorld()
|
{
|
netState = NetState.RoleLogin;
|
}
|
|
void OnUpdate()
|
{
|
if (networkService != null)
|
{
|
if (networkService is WebSocketNetworkService wsService) { wsService.Update(); }
|
}
|
|
lock (this)
|
{
|
while (mainProtocolQueue.Count > 0)
|
{
|
var package = mainProtocolQueue.Dequeue();
|
if (package != null)
|
{
|
PackageRegedit.Distribute(package);
|
}
|
}
|
}
|
|
}
|
|
public enum NetState
|
{
|
NerverConnect = 1,
|
AccountLogin = 2,
|
// CreateOrSelectRole = 3,
|
RoleLogin = 4,
|
Connected = 5,
|
DisConnected = 6,
|
}
|
|
|
}
|
|
public enum ServerType
|
{
|
Main = 1,
|
B430 = 2,
|
MainFight = 3,
|
}
|