Files
test/Assets/PerfectWorld/Scripts/Common/EC_PendingAction.cs

321 lines
9.2 KiB
C#

// 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())
{
// 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<CECPendingAction> m_actions = new List<CECPendingAction>();
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;
}