// Filename : EC_PendingAction.cs // Creator : Xu Wenbin // Date : 2011/11/09 // Converted from C++: EC_PendingAction.cpp / EC_PendingAction.h using System.Collections.Generic; using BrewMonster; using BrewMonster.Network; using BrewMonster.UI; using CSNetwork; using UnityEngine; // Logout type constants (C++: gnetdef.h) // _PLAYER_LOGOUT_FULL 0, _PLAYER_LOGOUT_HALF 1 public static class PendingActionConstants { public const int _PLAYER_LOGOUT_FULL = 0; public const int _PLAYER_LOGOUT_HALF = 1; } // CECPendingAction — base class for delayed/pending actions public abstract class CECPendingAction { // 执行的时限 / Execution time limit private readonly CECCounter m_Counter; // 是否还需要执行 / Whether still needs to execute private bool m_bNeedExecute; // 是否收到外界执行指示 / Whether received external execute trigger private bool m_bTriggered; // 执行结果:是否成功执行 / Execute result: whether executed successfully private bool m_bExecuteResult; public CECPendingAction(uint dwTimerPeriod) { m_Counter = new CECCounter(); m_Counter.SetPeriod((float)dwTimerPeriod); m_bNeedExecute = true; m_bTriggered = false; m_bExecuteResult = false; } public void Update(uint dwElapsedTime) { if (GetNeedExecute()) { // 每次都尝试执行 / Try execute every time if (m_Counter.IncCounter((float)dwElapsedTime)) { // 计时器到 / Timer reached // 强制执行 / Force execute m_bExecuteResult = Execute(); // 不需要再进行尝试 / No need to try again m_bNeedExecute = false; } // else 计时中 / else counting } } public void Trigger() { if (!GetNeedExecute()) { // 计时器已经强制执行,不需要再触发执行 / Timer already forced execute, no need to trigger again return; } if (GetTriggered()) { // 不允许多次触发 / Multiple trigger not allowed return; } m_bTriggered = true; m_bExecuteResult = Execute(); m_bNeedExecute = false; } public bool GetNeedExecute() => m_bNeedExecute; public bool GetTriggered() => m_bTriggered; public abstract string GetName(); protected abstract bool Execute(); // Whether currently in game (session connected, game state in-game, host ready) protected bool IsInGame() { var pSession = GetGameSession(); var pGameRun = GetGameRun(); var pHost = pGameRun?.GetHostPlayer(); return pSession != null && pSession.IsConnected && pGameRun != null && pGameRun.GetGameState() == (int)GameState.GS_GAME && pHost != null && pHost.HostIsReady(); } protected static CECGameRun GetGameRun() => EC_Game.GetGameRun(); protected static GameSession GetGameSession() => UnityGameSession.Instance?.GameSession; protected static CECHostPlayer GetHostPlayer() => GetGameRun()?.GetHostPlayer(); } // 游戏小退 / Game logout (half — back to select role) public class CECPendingLogoutHalf : CECPendingAction { public CECPendingLogoutHalf(uint dwTimerPeriod = 5000) : base(dwTimerPeriod) { } protected override bool Execute() { bool bSuccess = false; if (IsInGame()) { #region agent log #if UNITY_EDITOR || DEVELOPMENT_BUILD DebugSessionLog.Write("CECPendingLogoutHalf.Execute", "logout_half_execute", "E", new DebugSessionPayload { frame = Time.frameCount }); #endif #endregion // TODO: currently, we logout logic != C++, need to implement properly GetGameSession().c2s_SendCmdLogout(PendingActionConstants._PLAYER_LOGOUT_HALF); // UnityGameSession.ReturnToSelectRole(); bSuccess = true; } return bSuccess; } public override string GetName() => "CECPendingLogoutHalf"; } // 游戏大退 / Game logout (full — account logout) public class CECPendingLogoutFull : CECPendingAction { public CECPendingLogoutFull(uint dwTimerPeriod = 5000) : base(dwTimerPeriod) { } protected override bool Execute() { bool bSuccess = false; if (IsInGame()) { // TODO: currently, we logout logic != C++, need to implement properly // C++ code: GetGameSession()->SendPlayerLogout(PendingActionConstants::_PLAYER_LOGOUT_FULL); GetGameSession().c2s_SendCmdLogout(PendingActionConstants._PLAYER_LOGOUT_FULL); // UnityGameSession.LogoutAccount(); bSuccess = true; } return bSuccess; } public override string GetName() => "CECPendingLogoutFull"; } // 寄售角色 / Selling role public class CECPendingSellingRole : CECPendingAction { public CECPendingSellingRole(uint dwTimerPeriod = 5000) : base(dwTimerPeriod) { } protected override bool Execute() { bool bSuccess = false; if (IsInGame()) { // GetGameSession().SendPlayerLogout(PendingActionConstants._PLAYER_LOGOUT_HALF); // GetGameRun().SetSellingRoleID(GetHostPlayer().GetCharacterID()); UnityGameSession.ReturnToSelectRole(); bSuccess = true; } return bSuccess; } public override string GetName() => "CECPendingSellingRole"; } // 跨服小退 / Cross-server logout (half) public class CECPendingLogoutCrossServer : CECPendingAction { public CECPendingLogoutCrossServer(uint dwTimerPeriod = 5000) : base(dwTimerPeriod) { } protected override bool Execute() { GetGameRun().SetLogoutFlag(2); return true; } public override string GetName() => "CECPendingLogoutCrossServer"; } // 进出跨服 / Cross-server get in or out // m_bGetIn: 进入跨服时为 true;否则为 false / true when entering cross-server; otherwise false public class CECPendingCrossServerGetInOut : CECPendingAction { private readonly bool m_bGetIn; public CECPendingCrossServerGetInOut(bool bGetIn, uint dwTimerPeriod = 5000) : base(dwTimerPeriod) { m_bGetIn = bGetIn; } protected override bool Execute() { bool bSuccess = false; if (IsInGame()) { var session = GetGameSession(); if (session != null) { if (m_bGetIn) session.c2s_CmdNPCSevCrossServerGetIn(); else session.c2s_CmdNPCSevCrossServerGetOut(); } } var pGameUIMan = GetGameRun()?.GetUIManager()?.GetInGameUIMan(); if (pGameUIMan is CECGameUIMan inGameUIMan) inGameUIMan.EndNPCService(); return bSuccess; } public override string GetName() => "CECPendingCrossServerGetInOut"; } // CECPendingActionArray — container for multiple pending actions public class CECPendingActionArray { private readonly List m_actions = new List(); private bool m_bAllowMultiActions; public CECPendingActionArray(bool bAllowMultiActions) { m_bAllowMultiActions = bAllowMultiActions; } ~CECPendingActionArray() { Clear(); } public void Append(CECPendingAction pAction) { // 添加新事件 / Add new event if (pAction == null) { Debug.Assert(false); return; } if (!pAction.GetNeedExecute()) { Debug.Assert(false); return; } if (!GetAllowMultiAction()) Clear(); m_actions.Add(pAction); } public void AppendForSaveConfig(CECPendingAction pAction) { if (pAction == null) { Debug.Assert(false); return; } if (!pAction.GetNeedExecute()) { Debug.Assert(false); return; } uint saveResult = EC_Game.GetGameRun().SaveConfigsToServer(); if (saveResult != 2) { pAction.Trigger(); return; } Append(pAction); } public void Update(uint dwElapsedTime) { if (m_actions.Count == 0) return; for (int i = m_actions.Count - 1; i >= 0; i--) { CECPendingAction pAction = m_actions[i]; pAction.Update(dwElapsedTime); if (!pAction.GetNeedExecute()) { m_actions.RemoveAt(i); } } } public void TriggerAll() { if (m_actions.Count == 0) return; foreach (var pAction in m_actions) { if (pAction.GetNeedExecute()) pAction.Trigger(); } } public void Clear() { // 清除当前所有事件 / Clear all current events if (m_actions.Count == 0) return; m_actions.Clear(); } public void SetAllowMultiAction(bool bAllow) { if (GetAllowMultiAction() == bAllow) return; m_bAllowMultiActions = bAllow; // 按时间先后顺序,只保留队列最后一个 / By time order, keep only the last one in queue if (!bAllow && m_actions.Count > 1) { var last = m_actions[m_actions.Count - 1]; m_actions.Clear(); m_actions.Add(last); } } public bool GetAllowMultiAction() => m_bAllowMultiActions; }