| | |
| | | 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> |
| | | { |
| | | // NetUpdateBehaviour m_NetUpdateBehaviour; |
| | | //限制客户端的下一个包是登录包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; |
| | |
| | | } |
| | | } |
| | | |
| | | private ClientSocket mainSocket; |
| | | public bool mainSocketConnected { get { return mainSocket == null ? false : mainSocket.connected; } } |
| | | private ClientSocket mainSocket; // 保留兼容,但不再直接使用 |
| | | |
| | | public bool mainSocketConnected |
| | | { |
| | | get { return networkService?.IsConnected ?? false; } |
| | | } |
| | | |
| | | public float timeSinceMainSocketLastProtocol |
| | | { |
| | | get { return mainSocket == null ? Time.time : (float)(DateTime.Now - mainSocket.lastPackageTime).TotalSeconds; } |
| | | get |
| | | { |
| | | if (networkService == null) |
| | | return Time.time; |
| | | |
| | | var lastTime = networkService.LastPackageTime; |
| | | if (lastTime == DateTime.MinValue) |
| | | return Time.time; // 从未收包 |
| | | |
| | | return (float)(DateTime.Now - lastTime).TotalSeconds; |
| | | } |
| | | } |
| | | |
| | | public bool crossServerConnected_Loigc { get; set; } |
| | | private ClientSocket crossServerSocket; |
| | | public bool crossServerSocketConnected { get { return crossServerConnected_Loigc && (crossServerSocket == null ? false : crossServerSocket.connected); } } |
| | | |
| | | public float timeSinceCrossServerSocketLastProtocol |
| | | { |
| | | get { return crossServerSocket == null ? Time.time : (float)(DateTime.Now - crossServerSocket.lastPackageTime).TotalSeconds; } |
| | | } |
| | | |
| | | Queue<GameNetPackBasic> mainProtocolQueue = new Queue<GameNetPackBasic>(); |
| | | Queue<GameNetPackBasic> crossSeverProtocolQueue = new Queue<GameNetPackBasic>(); |
| | | |
| | | public CrossServerData crossServerData { get; private set; } |
| | | |
| | | public GameNetSystem() |
| | | { |
| | | var gameObject = new GameObject("NetUpdateBehaviour"); |
| | | GameObject.DontDestroyOnLoad(gameObject); |
| | | // m_NetUpdateBehaviour = gameObject.AddComponent<NetUpdateBehaviour>(); |
| | | // m_NetUpdateBehaviour.RegisterUpdateCallBack(OnUpdate); |
| | | m_NetUpdateBehaviour = gameObject.AddComponent<NetUpdateBehaviour>(); |
| | | m_NetUpdateBehaviour.RegisterUpdateCallBack(OnUpdate); |
| | | |
| | | neverConnectState = gameObject.AddComponent<NeverConnectState>(); |
| | | accountLoginState = gameObject.AddComponent<AccountLoginState>(); |
| | |
| | | { |
| | | try |
| | | { |
| | | if (mainSocketConnected) |
| | | if (networkService != null && networkService.IsConnected) |
| | | { |
| | | mainSocket.CloseConnect(); |
| | | networkService.Disconnect(); |
| | | } |
| | | } |
| | | catch (System.Exception ex) |
| | |
| | | Debug.Log(ex); |
| | | } |
| | | |
| | | mainSocket = new ClientSocket(ServerType.Main); |
| | | mainProtocolQueue.Clear(); |
| | | |
| | | mainSocket.Connect(ip, port, (bool ok) => |
| | | // 根据 Main.CurrentNetworkType 选择网络类型 |
| | | Debug.Log($"[GameNetSystem] 连接服务器 {ip}:{port},使用{(Main.CurrentNetworkType == NetworkType.WebSocket ? "WebSocket" : "TCP")}"); |
| | | |
| | | if (Main.CurrentNetworkType == NetworkType.WebSocket) |
| | | { |
| | | if (onConnected != null) |
| | | { |
| | | onConnected(ok); |
| | | } |
| | | }); |
| | | // 使用 WebSocket |
| | | ConnectWithWebSocket(ip, port, onConnected); |
| | | } |
| | | else |
| | | { |
| | | // 使用 TCP Socket(通过适配器) |
| | | ConnectWithTCP(ip, port, onConnected); |
| | | } |
| | | } |
| | | |
| | | public void BeginConnectCrossServer(string ip, int port, Action<bool> onConnected) |
| | | private async void ConnectWithTCP(string ip, int port, Action<bool> onConnected) |
| | | { |
| | | try |
| | | { |
| | | crossServerConnected_Loigc = false; |
| | | if (crossServerSocketConnected) |
| | | // 创建 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) |
| | | { |
| | | crossServerSocket.CloseConnect(); |
| | | onConnected(success); |
| | | } |
| | | } |
| | | catch (System.Exception ex) |
| | | { |
| | | Debug.Log(ex); |
| | | } |
| | | |
| | | crossServerSocket = new ClientSocket(ServerType.CrossSever); |
| | | crossSeverProtocolQueue.Clear(); |
| | | this.crossServerSocket.Connect(ip, port, (bool ok) => |
| | | { |
| | | Debug.LogError($"[GameNetSystem] TCP 连接异常: {ex.Message}"); |
| | | if (onConnected != null) |
| | | { |
| | | onConnected(ok); |
| | | onConnected(false); |
| | | } |
| | | }); |
| | | } |
| | | } |
| | | |
| | | public void UpdateCrossServerData(string ip, int port, byte state) |
| | | private async void ConnectWithWebSocket(string ip, int port, Action<bool> onConnected) |
| | | { |
| | | this.crossServerData = new CrossServerData(ip, port, state); |
| | | if (this.crossServerData.crossState == 0) |
| | | try |
| | | { |
| | | crossServerConnected_Loigc = false; |
| | | // 创建 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) |
| | | { |
| | | if (mainSocket != null) |
| | | Debug.LogError("protocol to send: " + protocol.ToString()); |
| | | |
| | | if (waitLogin) |
| | | { |
| | | mainSocket.SendInfo(protocol); |
| | | 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 (mainSocket != null) |
| | | if (networkService != null) |
| | | { |
| | | mainSocket.SendInfo(vBytes); |
| | | networkService.SendInfo(vBytes); |
| | | } |
| | | } |
| | | |
| | | public void SendToCrossServer(GameNetPackBasic protocol) |
| | | { |
| | | if (crossServerSocket != null) |
| | | { |
| | | protocol.socketType = ServerType.CrossSever; |
| | | crossServerSocket.SendInfo(protocol); |
| | | DebugPkgCache.Push(protocol); |
| | | } |
| | | } |
| | | |
| | | public void PushPackage(GameNetPackBasic protocol, ServerType type) |
| | | { |
| | |
| | | |
| | | if (PackageRegedit.Contain(protocol.cmd)) |
| | | { |
| | | switch (type) |
| | | { |
| | | case ServerType.Main: |
| | | mainProtocolQueue.Enqueue(protocol); |
| | | break; |
| | | case ServerType.CrossSever: |
| | | crossSeverProtocolQueue.Enqueue(protocol); |
| | | break; |
| | | default: |
| | | break; |
| | | } |
| | | mainProtocolQueue.Enqueue(protocol); |
| | | |
| | | DebugPkgCache.Push(protocol); |
| | | } |
| | |
| | | { |
| | | try |
| | | { |
| | | if (mainSocket != null) |
| | | if (networkService != null) |
| | | { |
| | | mainSocket.CloseConnect(); |
| | | } |
| | | |
| | | if (crossServerSocket != null) |
| | | { |
| | | crossServerSocket.CloseConnect(); |
| | | networkService.Disconnect(); |
| | | } |
| | | |
| | | mainProtocolQueue.Clear(); |
| | | crossSeverProtocolQueue.Clear(); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | |
| | | finally |
| | | { |
| | | netState = NetState.DisConnected; |
| | | // var loginModel = ModelCenter.Instance.GetModel<LoginModel>(); |
| | | // loginModel.busy = false; |
| | | // CrossServerLogin.Instance.busy = false; |
| | | LoginManager.Instance.busy = false; |
| | | } |
| | | } |
| | | |
| | | public void DisconnectCrossServer() |
| | | { |
| | | try |
| | | { |
| | | if (crossServerSocket != null) |
| | | { |
| | | crossServerSocket.CloseConnect(); |
| | | } |
| | | |
| | | crossSeverProtocolQueue.Clear(); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | Debug.Log(ex); |
| | | } |
| | | finally |
| | | { |
| | | // CrossServerLogin.Instance.busy = false; |
| | | } |
| | | } |
| | | |
| | | public void Reconnect() |
| | | { |
| | | try |
| | | { |
| | | if (mainSocket != null) |
| | | if (networkService != null) |
| | | { |
| | | mainSocket.CloseConnect(); |
| | | } |
| | | |
| | | if (crossServerSocket != null) |
| | | { |
| | | crossServerSocket.CloseConnect(); |
| | | networkService.Disconnect(); |
| | | } |
| | | |
| | | mainProtocolQueue.Clear(); |
| | | crossSeverProtocolQueue.Clear(); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | |
| | | finally |
| | | { |
| | | netState = NetState.AccountLogin; |
| | | // CrossServerLogin.Instance.busy = false; |
| | | // var loginModel = ModelCenter.Instance.GetModel<LoginModel>(); |
| | | // loginModel.busy = false; |
| | | // loginModel.ReAccountLogin(); |
| | | LoginManager.Instance.busy = false; |
| | | LoginManager.Instance.ReAccountLogin(); |
| | | } |
| | | } |
| | | |
| | | public void LoginOut() |
| | | { |
| | | // if (CameraController.Instance != null) |
| | | // CameraController.Instance.SetInGame(false); |
| | | // DTC0102_tagCDBPlayer.isAfterPlayerDataInitialize = false; |
| | | |
| | | try |
| | | { |
| | | // ynmbxxjUtil.Instance.RoleLoginOut(); |
| | | crossServerConnected_Loigc = false; |
| | | SDKUtils.Instance.RoleLoginOut(); |
| | | |
| | | if (mainSocket != null) |
| | | if (networkService != null) |
| | | { |
| | | mainSocket.CloseConnect(); |
| | | } |
| | | |
| | | if (crossServerSocket != null) |
| | | { |
| | | crossServerSocket.CloseConnect(); |
| | | networkService.Disconnect(); |
| | | } |
| | | |
| | | mainProtocolQueue.Clear(); |
| | | crossSeverProtocolQueue.Clear(); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | |
| | | finally |
| | | { |
| | | netState = NetState.NerverConnect; |
| | | // TODO YYL |
| | | |
| | | // CrossServerLogin.Instance.busy = false; |
| | | // //ArenaManager.isArenaClient = false; |
| | | // var loginModel = ModelCenter.Instance.GetModel<LoginModel>(); |
| | | // loginModel.busy = false; |
| | | // WindowJumpMgr.Instance.ClearJumpData(); |
| | | LoginManager.Instance.busy = false; |
| | | |
| | | // StageLoad.Instance.PushSceneLoadCommand(new StageLoad.StageLoadCommand() |
| | | // { |
| | | // toMapId = 1, |
| | | // toLineId = 0, |
| | | // needEmpty = false, |
| | | // needLoadResource = true, |
| | | // serverType = ServerType.Main, |
| | | // isClientLoadMap = true |
| | | // }); |
| | | // //CameraManager.uiCamera.clearFlags = CameraClearFlags.SolidColor; |
| | | // //GameObject obj = GameObject.Find("NormalCanvas"); |
| | | // //int count = obj.transform.childCount; |
| | | // //for (int i = count - 1; i >= 0; --i) |
| | | // //{ |
| | | // // //Debug.LogError(obj.transform.GetChild(i).name); |
| | | // // GameObject.Destroy(obj.transform.GetChild(i).gameObject); |
| | | // //} |
| | | // //SceneManager.LoadScene("Empty"); |
| | | StageManager.Instance.ReturnToLoginScene(); |
| | | NetLinkWin.Hide(); |
| | | // DTC0403_tagPlayerLoginLoadOK.neverLoginOk = true; |
| | | } |
| | | } |
| | | |
| | |
| | | |
| | | 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); |
| | | } |
| | | } |
| | | while (crossSeverProtocolQueue.Count > 0) |
| | | { |
| | | var package = crossSeverProtocolQueue.Dequeue(); |
| | | if (package != null) |
| | | { |
| | | PackageRegedit.Distribute(package); |
| | |
| | | DisConnected = 6, |
| | | } |
| | | |
| | | public struct CrossServerData |
| | | { |
| | | public string ip; |
| | | public int port; |
| | | public CrossServerState crossState; |
| | | |
| | | public CrossServerData(string ip, int port, byte state) |
| | | { |
| | | this.ip = ip; |
| | | this.port = port; |
| | | this.crossState = (CrossServerState)state; |
| | | } |
| | | } |
| | | |
| | | public enum CrossServerState |
| | | { |
| | | No = 0, |
| | | Yes = 1, |
| | | Error = 2, |
| | | } |
| | | |
| | | } |
| | | |
| | | public enum ServerType |
| | | { |
| | | Main = 1, |
| | | CrossSever = 2, |
| | | B430 = 2, |
| | | MainFight = 3, |
| | | } |