using System; namespace ET.Client { [Invoke(TimerInvokeType.SessionIdleChecker)] public class SessionIdleChecker: ATimer { protected override void Run(SessionIdleCheckerComponent self) { try { self.Check(); } catch (Exception e) { Log.Error($"idle check error: {self.Id}\n{e}"); } } } [ObjectSystem] public class SessionIdleCheckerComponentAwakeSystem: AwakeSystem { protected override void Awake(SessionIdleCheckerComponent self) { self.RepeatedTimer = TimerComponent.Instance.NewRepeatedTimer(ConstValue.SessionTimeoutTime / 2 +100, TimerInvokeType.SessionIdleChecker, self); } } [ObjectSystem] public class SessionIdleCheckerComponentDestroySystem: DestroySystem { protected override void Destroy(SessionIdleCheckerComponent self) { TimerComponent.Instance?.Remove(ref self.RepeatedTimer); } } public static class SessionIdleCheckerComponentSystem { public static void Check(this SessionIdleCheckerComponent self) { Session session = self.GetParent(); long timeNow = TimeHelper.ClientNow(); if (timeNow - session.LastRecvTime < ConstValue.SessionTimeoutTime/2 && timeNow - session.LastSendTime < ConstValue.SessionTimeoutTime/2) { return; } session.Call(new C2G_Ping()).Coroutine(); if(timeNow - session.LastRecvTime > ConstValue.SessionTimeoutTime) { session.Dispose(); EventSystem.Instance.Publish(); } } } }