using System; using System.Collections; using System.Collections.Generic; using BestHTTP.SocketIO; using Cute; using UnityEngine; using Wizard; public class Gungnir : IDisposable { private enum ConnectingStatus { ONLINE, WAITING, OFFLINE, TIMEOUT } public enum DisconnectStatus { NOT, SELF_DISCONNECT, OPPONENT_DISCONNECT } public const string URI = "Gungnir"; public const string EMIT_ALIVE = "alive"; private const string CURRENT_SEQUENCE = "currentSeq"; public const string ACTION_SEQ = "actionSeq"; private const string OCS_KEY = "ocs"; private const string SCS_KEY = "scs"; private const string CLIENT_PUB_SEQ_KEY = "clientPubSeq"; private const string CLIENT_REQ_RESEND_KEY = "reqResend"; private const float REPORT_INTERVAL = 5f; private RealTimeNetworkAgent _agent; private ConnectionReporter _connectionReporter; public Action OnAlive; public Action OnOpponentAlive; public Action OnOpponentDisconnect; public Action OnOpponentOffLine; public Action OnOpponentTimeOut; public Action OnResendEmitData; public bool _isNotEmit; private int _receiveReSendZeroNum; public List _actionSeqPubSeqList = new List(); public int _actionSequenceNum; private float _gungnirLogWaitTimer; private Coroutine _gungnirAckCheckCoroutine; public const float SUCCESS_GUNGNIR_RECEIVE_LOG_TIME = 5f; public DisconnectStatus _DisconnectStatus { get; private set; } public long LastSuccessTime { get; private set; } public bool IsSendActionSequenceNum { get; private set; } public bool IsEnableTimeoutCallBack { get; set; } = true; public long GungnirReceiveCheckTime { get; private set; } public Gungnir(RealTimeNetworkAgent agent) { _agent = agent; _connectionReporter = new ConnectionReporter(agent, EmitGungnir, 5f); Tick(); _DisconnectStatus = DisconnectStatus.NOT; } private IEnumerator GungnirLogAckCheck() { while (true) { _gungnirLogWaitTimer += Time.deltaTime; if (_gungnirLogWaitTimer >= 2f) { break; } yield return null; } if (!LocalLog._isSendGungnirLog) { _agent.NetworkLogger.LogInfo("OnGungnirLog"); } LocalLog._isSendGungnirLog = true; } public void Start() { _agent.NetworkLogger.LogInfo("Gungnir: Start"); _connectionReporter.StartReporter(); LocalLog.InitGungnirLog(); LocalLog.InitDisconnectLog(); } public void Stop() { _connectionReporter.StopReporter(); _agent.NetworkLogger.LogInfo("Gungnir: Stop"); LocalLog.AddGungnirLog("GungnirStopReporter "); } public void SetSendActionSequenceNumFlag(bool isActive) { if (!isActive && IsSendActionSequenceNum) { _agent.NetworkLogger.LogInfo("GungnirSendActionSeq:OFF"); } if (isActive && !IsSendActionSequenceNum) { _agent.NetworkLogger.LogInfo("GungnirSendActionSeq:ON"); } IsSendActionSequenceNum = isActive; } public void EmitGungnir() { if (GameMgr.GetIns().IsWatchBattle || _isNotEmit) { return; } if (_agent.IsOpen()) { _agent.SocketManager.Socket.Emit("alive", OnAckPacket, CreateEmitData()); if (IsRecordGungnirLog()) { _gungnirAckCheckCoroutine = _agent.StartCoroutine(GungnirLogAckCheck()); } LocalLog.AddGungnirLog("EmitGungnir"); return; } LocalLog.AddGungnirLog("NotOpenEmitGungnir"); if (!LocalLog._isSendGungnirLog) { _agent.NetworkLogger.LogInfo("OnGungnirLog"); } if (IsRecordGungnirLog()) { LocalLog._isSendGungnirLog = true; } } private bool IsRecordGungnirLog() { if (_agent == null || _agent.CurrentMatchingStatus != RealTimeNetworkAgent.MatchingStatus.Prepared || GameMgr.GetIns() == null || GameMgr.GetIns().IsWatchBattle) { return false; } return true; } private byte[] CreateEmitData() { Dictionary dictionary = _agent.CreateEmitData("Gungnir", null, isTrySend: false); dictionary.Add("currentSeq", _agent.MaxMessageSequenceNumber); if (IsSendActionSequenceNum) { dictionary.Add("actionSeq", _actionSequenceNum); } return _agent.CreatePackEmitData(dictionary); } private void OnAckPacket(Socket socket, Packet originalPacket, params object[] args) { Tick(); OnAlive.Call(); LocalLog.AddGungnirLog("GungnirOnAck"); if (_gungnirAckCheckCoroutine != null) { _agent.StopCoroutine(_gungnirAckCheckCoroutine); } _gungnirLogWaitTimer = 0f; } public void ReceiveGungnir(Packet originalPacket, params object[] args) { Dictionary dictionary = _agent.DeserializeEncryptedPacket(originalPacket); if (dictionary.Count == 0) { LocalLog.AddGungnirLog("ReceiveGungnirDataZero"); return; } string text = dictionary["uri"].ToString(); if (text != NetworkBattleDefine.NetworkURINames[NetworkBattleDefine.NetworkBattleURI.Gungnir]) { LocalLog.AddGungnirLog("ReceiveGungnirNoUri[" + text + "]"); } else { if (_agent.HandleingNodeResultCodeIfNeeded(dictionary)) { return; } if (_agent.IsExistTitleReturnError) { LocalLog.AddGungnirLog("ReceiveGungnirIsExistTitleReturnError"); return; } GungnirReceiveCheckTime = TimeUtil.GetAbsoluteTime().Ticks; Tick(); OnAlive.Call(); if (dictionary.ContainsKey(NetworkBattleDefine.NetworkParameter.resultCode.ToString()) && int.Parse(dictionary[NetworkBattleDefine.NetworkParameter.resultCode.ToString()].ToString()) == 30002) { return; } if (dictionary.ContainsKey("reqResend")) { int num = int.Parse(dictionary["reqResend"].ToString()); if (num == 0) { _receiveReSendZeroNum++; } if (num == 1 || _receiveReSendZeroNum >= 2) { _receiveReSendZeroNum = 0; if (dictionary.ContainsKey("clientPubSeq")) { int arg = int.Parse(dictionary["clientPubSeq"].ToString()); OnResendEmitData.Call(arg); } } } if ((ConnectingStatus)Enum.Parse(typeof(ConnectingStatus), dictionary["scs"].ToString()) == ConnectingStatus.OFFLINE) { _agent.NetworkLogger.LogInfo("Gungnir: Self Offline"); if (_agent.IsBattleStart) { _DisconnectStatus = DisconnectStatus.SELF_DISCONNECT; } return; } switch ((ConnectingStatus)Enum.Parse(typeof(ConnectingStatus), dictionary["ocs"].ToString())) { case ConnectingStatus.ONLINE: OnOpponentAlive.Call(); break; case ConnectingStatus.WAITING: _agent.NetworkLogger.LogInfo("Gungnir: Opponent Disconnect"); OnOpponentDisconnect.Call(); break; case ConnectingStatus.OFFLINE: OpponentOffLine(); _agent.NetworkLogger.LogInfo("Gungnir: Opponent Offline"); OnOpponentOffLine.Call(); break; case ConnectingStatus.TIMEOUT: OpponentOffLine(); _agent.NetworkLogger.LogInfo("Gungnir: Opponent TimeOut"); if (IsEnableTimeoutCallBack) { OnOpponentTimeOut.Call(); } break; } } } private void OpponentOffLine() { if (_agent.IsBattleStart) { _DisconnectStatus = DisconnectStatus.OPPONENT_DISCONNECT; } } public void Tick() { LastSuccessTime = TimeUtil.GetAbsoluteTime().Ticks; } public void Dispose() { if (_gungnirAckCheckCoroutine != null) { _agent.StopCoroutine(_gungnirAckCheckCoroutine); } _connectionReporter.StopReporter(); _connectionReporter = null; _agent = null; } }