447 lines
16 KiB
C#
447 lines
16 KiB
C#
//**********************************************//
|
||
//作者:#AUTHOR#
|
||
//日期:#DATE#
|
||
//简述:#DESCRIPTION#
|
||
//*********************************************//
|
||
using Thousandto.Code.Center;
|
||
using Thousandto.Core.Base;
|
||
using Thousandto.Plugins.Common;
|
||
using UnityEngine;
|
||
|
||
namespace Thousandto.Code.Logic
|
||
{
|
||
/// <summary>
|
||
/// 断线重连
|
||
/// </summary>
|
||
public class ReconnectSystem : BaseSystem
|
||
{
|
||
#region//常量定义
|
||
|
||
//重连尝试次数
|
||
private const int CN_RECONNECT_TRY_COUNT = 5;
|
||
|
||
//Socket连接的等待时间
|
||
private const float CN_SOCKET_CONNECT_WAIT_TIME = 3;
|
||
|
||
//等待网络消息的时间
|
||
private const float CN_NET_MESSAGE_WAIT_TIME = 3;
|
||
|
||
#endregion
|
||
|
||
#region //成员变量
|
||
private string _sign;
|
||
//是否允许断线重连
|
||
private bool _enable = false;
|
||
//当前状态
|
||
private ReconnectStateCode _state = ReconnectStateCode.Idle;
|
||
|
||
//尝试次数
|
||
private int _remainCount = 5;
|
||
|
||
//等待时间 秒
|
||
private float _waitTime = 3;
|
||
#endregion
|
||
|
||
#region //属性
|
||
|
||
//断线前的地图id
|
||
public int LastMapId { get; set; }
|
||
//正常切换场景记录切换前的坐标、分线等等,以防万一真的重连,这里能取数据
|
||
public Vector3 LastPlayerPos { get; set; }
|
||
//正在重连的次数
|
||
public int TryCount
|
||
{
|
||
get
|
||
{
|
||
return CN_RECONNECT_TRY_COUNT - _remainCount;
|
||
}
|
||
}
|
||
|
||
//剩余次数
|
||
public int RemainCount
|
||
{
|
||
get
|
||
{
|
||
return _remainCount;
|
||
}
|
||
}
|
||
#endregion
|
||
|
||
#region//公共接口处理
|
||
|
||
#region //初始化
|
||
public void Initialize()
|
||
{
|
||
GameCenter.Networker.OnSocketDisconnect = OnMonitorSocketState;
|
||
}
|
||
#endregion
|
||
|
||
#region //公有函数
|
||
public void Reconnect()
|
||
{
|
||
//开始重连的
|
||
LastMapId = -1;
|
||
LastPlayerPos = Vector3.zero;
|
||
_state = ReconnectStateCode.StartReconnect;
|
||
}
|
||
|
||
|
||
//在重连中返回到登陆
|
||
public void ReturnToLogin()
|
||
{
|
||
//当前状态为空闲
|
||
_state = ReconnectStateCode.Idle;
|
||
//现在不是重连状态
|
||
GameGlobalData.IsReconnecting = false;
|
||
//不能重连
|
||
_enable = false;
|
||
//返回到登陆
|
||
GameCenter.GameSceneSystem.ReturnToLogin();
|
||
}
|
||
|
||
//设置是否激活
|
||
public void SetEnable(bool value)
|
||
{
|
||
//当前状态为空闲
|
||
_state = ReconnectStateCode.Idle;
|
||
//不能重连
|
||
_enable = value;
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region//处理网络消息
|
||
|
||
//public bool TestRightSign = true;
|
||
//3.发送请求重连的消息
|
||
public void SendReqReconnect()
|
||
{
|
||
Debug.LogError("SendReqReconnect=" + _sign);
|
||
MSG_heart.ReqReconnect req = new MSG_heart.ReqReconnect();
|
||
req.playerId = GameCenter.GameSceneSystem.GetLocalPlayerID();
|
||
//req.sign = TestRightSign ? _sign : "00";
|
||
req.sign = _sign;
|
||
req.Send();
|
||
}
|
||
|
||
//发送已经设置了sign成功的消息
|
||
public void SendReqSetReconnectSignSuccess()
|
||
{
|
||
//收到sign就要告诉服务器
|
||
MSG_heart.ReqSetReconnectSignSuccess req = new MSG_heart.ReqSetReconnectSignSuccess();
|
||
req.Send();
|
||
}
|
||
|
||
//断线重连需要用到的sign值,每10分钟刷新这个值,随后重连用这个值
|
||
public void GS2U_ResReconnectSign(MSG_heart.ResReconnectSign result)
|
||
{
|
||
//Debug.LogError("接收到:sign=" + result.sign);
|
||
_sign = result.sign;
|
||
SendReqSetReconnectSignSuccess();
|
||
}
|
||
|
||
//断线重连失败
|
||
public void GS2U_ResHeartFailed(MSG_heart.ResHeartFailed result)
|
||
{
|
||
//设置全局标志当前不在重连了
|
||
GameGlobalData.IsReconnecting = false;
|
||
//重连成功
|
||
if (result.reason == 0)
|
||
{
|
||
Debug.LogError("3.1 接受到服务器的断线重连成功");
|
||
_state = ReconnectStateCode.ReconnectSuccess;
|
||
//可以心跳
|
||
GameCenter.HeartSystem.EnabelHeartMsg(true);
|
||
//关闭重连界面
|
||
GameCenter.EventManager.PushFixEvent((int)UIEventDefine.UI_RECONNECTFORM_CLOSE);
|
||
|
||
if (result.mapModelId == GameCenter.ReconnectSystem.LastMapId ||
|
||
result.mapModelId == -1)
|
||
{
|
||
Debug.Log("3.1.1 断线重连成功,最后的地图与重连返回的服务器地图相同,当前地图ID: " + result.mapModelId);
|
||
//断线重连,如果没有切换地图,需要向服务器发送loadFinish消息
|
||
NetHandler.SendMessage_ReqLoadFinish();
|
||
}
|
||
else
|
||
{
|
||
Debug.Log(string.Format("3.1.2 断线重连成功, 最后的地图与重连返回的服务器地图不同, mapModleId={0} my saved mapId={1}", result.mapModelId, GameCenter.ReconnectSystem.LastMapId));
|
||
//GameCenter.GameSceneSystem.StartChangeToMap(result.mapModelId, result.lineId, new Vector2(LastPlayerPos.x, LastPlayerPos.z));
|
||
}
|
||
|
||
GameCenter.PushFixEvent(Global.LogicEventDefine.EID_EVENT_RECONNECT_SUCCESS);
|
||
}
|
||
else
|
||
{
|
||
_state = ReconnectStateCode.ReconnectFail;
|
||
Debug.LogError("3.2 接受到服务器的断线重连失败! reason:" + result.reason.ToString());
|
||
}
|
||
}
|
||
|
||
#endregion
|
||
|
||
#endregion
|
||
|
||
#region//保护类型的方法
|
||
//心跳处理
|
||
protected override bool OnUpdate(float deltaTime)
|
||
{
|
||
if (!_enable) return true;
|
||
switch (_state)
|
||
{
|
||
case ReconnectStateCode.StartReconnect:
|
||
{
|
||
//等待判断是否可以进行重连
|
||
_state = ReconnectStateCode.WaitCheckReconnect;
|
||
StartupReconnect();
|
||
}
|
||
break;
|
||
case ReconnectStateCode.ReconnectSocketCD:
|
||
{
|
||
_waitTime -= deltaTime;
|
||
if (_waitTime <= 0)
|
||
{
|
||
_state = ReconnectStateCode.StartConnectSocket;
|
||
}
|
||
}
|
||
break;
|
||
case ReconnectStateCode.StartConnectSocket:
|
||
{
|
||
StartConnectSocket();
|
||
}
|
||
break;
|
||
case ReconnectStateCode.SocketConnectSuccess:
|
||
{
|
||
//等待网络消息,或者直接退出到登陆
|
||
_state = ReconnectStateCode.WaitNetMessage;
|
||
ReconnectSocketSuccess();
|
||
_waitTime = CN_NET_MESSAGE_WAIT_TIME;
|
||
}
|
||
break;
|
||
case ReconnectStateCode.WaitNetMessage:
|
||
{//等待网络消息,如果超时,表示连接失败
|
||
_waitTime -= deltaTime;
|
||
if (_waitTime <= 0)
|
||
{
|
||
_state = ReconnectStateCode.WaitNetMessageFail;
|
||
}
|
||
}
|
||
break;
|
||
case ReconnectStateCode.WaitNetMessageFail:
|
||
case ReconnectStateCode.SocketConnectFail:
|
||
case ReconnectStateCode.ReconnectFail:
|
||
{
|
||
ProcessFail(_state);
|
||
GameCenter.PushFixEvent(UIEventDefine.UI_RECONNECTFORM_OPEN);
|
||
|
||
}
|
||
break;
|
||
}
|
||
return true;
|
||
}
|
||
|
||
#endregion
|
||
|
||
|
||
#region //私有函数
|
||
|
||
//0.监控网络状态
|
||
private void OnMonitorSocketState(int code)
|
||
{
|
||
//Socket断开,只有在空闲的情况下,才会去重新开始连,其他情况表示正在进行重连操作.所以不做开始处理重连处理.
|
||
if (_enable && (_state == ReconnectStateCode.Idle || _state == ReconnectStateCode.ReconnectSuccess))
|
||
{
|
||
LastMapId = -1;
|
||
LastPlayerPos = Vector3.zero;
|
||
_state = ReconnectStateCode.StartReconnect;
|
||
GameGlobalData.IsReconnecting = true;
|
||
}
|
||
else if (_state == ReconnectStateCode.WaitNetMessage)
|
||
{
|
||
//如果当前是等待网络消息,那么直接重连失败.
|
||
_state = ReconnectStateCode.ReconnectFail;
|
||
}
|
||
else
|
||
{
|
||
Debug.LogError("0.0.不能进行重连,因为当前重连状态:" + _state.ToString()+";;;enable:"+ _enable);
|
||
//如果是创建角色界面,直接打开退出界面
|
||
if (GameCenter.FormStateSystem.FormIsOpenByEventID((int)UIEventDefine.UICREATEPLAYERFORM_OPEN))
|
||
{
|
||
_state = ReconnectStateCode.WaitExitReconnect;
|
||
_remainCount = 0;
|
||
GameCenter.EventManager.PushFixEvent((int)UIEventDefine.UI_RECONNECTFORM_OPEN, null, null, null, false, 0);
|
||
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
//1开启断线重连
|
||
private void StartupReconnect()
|
||
{
|
||
//1.1.判断是否开启重连
|
||
if (CheckReconnectCondition())
|
||
{//打开重连界面
|
||
//初始化尝试次数
|
||
_remainCount = CN_RECONNECT_TRY_COUNT;
|
||
//1.1.1 记录当前场景ID
|
||
if (GameCenter.GameSceneSystem.ActivedScene != null)
|
||
LastMapId = GameCenter.GameSceneSystem.ActivedScene.MapId;
|
||
|
||
//1.1.2 记录角色的位置
|
||
if (GameCenter.GameSceneSystem.GetLocalPlayer() != null)
|
||
LastPlayerPos = GameCenter.GameSceneSystem.GetLocalPlayer().Position;
|
||
|
||
Debug.Log("1.1 启动断线重连");
|
||
_state = ReconnectStateCode.ReconnectSocketCD;
|
||
_waitTime = CN_SOCKET_CONNECT_WAIT_TIME;
|
||
_remainCount = CN_RECONNECT_TRY_COUNT;
|
||
//GameCenter.EventManager.PushFixEvent((int)UIEventDefine.UI_RECONNECTFORM_OPEN);
|
||
}
|
||
else
|
||
{//重连条件不足,弹出返回登陆的对话框
|
||
|
||
Debug.Log("1.2 断线重连启动失败,打开返回登陆对话框!");
|
||
_remainCount = 0;
|
||
_state = ReconnectStateCode.WaitExitReconnect;
|
||
GameCenter.PushFixEvent(UIEventDefine.UI_RECONNECTFORM_OPEN);
|
||
|
||
}
|
||
}
|
||
|
||
//1.1判断重连条件
|
||
private bool CheckReconnectCondition()
|
||
{
|
||
if (string.IsNullOrEmpty(_sign))
|
||
{
|
||
Debug.LogError("1.0.当前Sign值为空,不能进行重连");
|
||
return false;
|
||
}
|
||
|
||
if (GameCenter.GameStateSystem == null || GameCenter.GameStateSystem.GetCurState() == null)
|
||
{
|
||
Debug.LogError("1.0.游戏状态还没有开启,不能进行重连");
|
||
return false;
|
||
}
|
||
|
||
if (GameCenter.GameStateSystem.GetCurState().GetStateId() != (int)GameStateId.World)
|
||
{
|
||
Debug.LogError("1.0.游戏状态还没有在World中,不能进行重连.");
|
||
return false;
|
||
}
|
||
|
||
if (GameCenter.GameSceneSystem.GetLocalPlayer() == null)
|
||
{
|
||
Debug.LogError("1.0.主角信息没有加载,不能进行重连.");
|
||
return false;
|
||
}
|
||
return true;
|
||
}
|
||
|
||
//2.0 进行Socket重连
|
||
private void StartConnectSocket()
|
||
{
|
||
|
||
//socket连接成功的状态,直接跳过
|
||
if (GameCenter.Networker.IsConnected)
|
||
{
|
||
//如果当前网络是连接状态,那么就直接发送重连消息
|
||
Debug.Log("2.1.2 当前网络状态是连接状态,直接判断连接socket成功!");
|
||
_state = ReconnectStateCode.SocketConnectSuccess;
|
||
return;
|
||
}
|
||
else
|
||
{
|
||
Debug.Log("2.0 重连Socket");
|
||
_state = ReconnectStateCode.WaitSocketConnecting;
|
||
//断线重连第一步,把Socket先连上,后面才能发送消息
|
||
GameCenter.Networker.Connect(
|
||
_result =>
|
||
{
|
||
|
||
if (_result)
|
||
{
|
||
UnityEngine.Debug.Log("2.1 重新连接Socket成功!");
|
||
_state = ReconnectStateCode.SocketConnectSuccess;
|
||
}
|
||
else
|
||
{
|
||
UnityEngine.Debug.Log("2.2.重新连接Socket失败!");
|
||
_state = ReconnectStateCode.SocketConnectFail;
|
||
}
|
||
});
|
||
}
|
||
|
||
}
|
||
|
||
//3. 重连Socket尝试完成,发送断线消息
|
||
private void ReconnectSocketSuccess()
|
||
{
|
||
GameCenter.GameSceneSystem.ActivedScene.Entities.RemoveAllRemoteObjects();
|
||
GameCenter.GameSceneSystem.GetLocalPlayer().ClearStrikeBackCharacter();
|
||
Debug.LogError("3.0 往服务器发送断线重连请求.");
|
||
GameCenter.Networker.StartThread();
|
||
//发送断线重连消息
|
||
SendReqReconnect();
|
||
}
|
||
|
||
//4.socket连接失败或者
|
||
private void ProcessFail(ReconnectStateCode failCode)
|
||
{
|
||
Debug.LogErrorFormat("4.0上次重连失败,失败原因:{0},重连剩余次数:{1}", failCode.ToString(), _remainCount);
|
||
if (_remainCount > 0)
|
||
{
|
||
//如果失败,就继续进行连接
|
||
_state = ReconnectStateCode.ReconnectSocketCD;
|
||
_waitTime = CN_SOCKET_CONNECT_WAIT_TIME;
|
||
_remainCount--;
|
||
GameCenter.PushFixEvent(UIEventDefine.UI_RECONNECTFORM_OPEN);
|
||
}
|
||
else
|
||
{
|
||
|
||
Debug.LogError("4.0重连次数使用完毕,返回登陆");
|
||
_state = ReconnectStateCode.WaitExitReconnect;
|
||
Networker.Instance.Disconnect(false);
|
||
GameCenter.PushFixEvent(UIEventDefine.UI_RECONNECTFORM_OPEN);
|
||
}
|
||
}
|
||
|
||
#endregion
|
||
|
||
|
||
#region//私有枚举
|
||
//重连状态
|
||
private enum ReconnectStateCode
|
||
{
|
||
|
||
//空闲,没有进行重连过
|
||
Idle,
|
||
//开始重连
|
||
StartReconnect,
|
||
//等待判断是否可以重连
|
||
WaitCheckReconnect,
|
||
//等待Socket的连接的CD
|
||
ReconnectSocketCD,
|
||
//开始Socket的连接
|
||
StartConnectSocket,
|
||
//等待Socket正在连接
|
||
WaitSocketConnecting,
|
||
//Socket连接成功
|
||
SocketConnectSuccess,
|
||
//连接失败
|
||
SocketConnectFail,
|
||
//等待网络消息
|
||
WaitNetMessage,
|
||
//等待网络消息失败
|
||
WaitNetMessageFail,
|
||
//重连成功
|
||
ReconnectSuccess,
|
||
//重连失败
|
||
ReconnectFail,
|
||
//等待退出连接
|
||
WaitExitReconnect,
|
||
}
|
||
#endregion
|
||
}
|
||
}
|