327 lines
9.4 KiB
C#
327 lines
9.4 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())
|
|
{
|
|
#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<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;
|
|
}
|