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
|
|||
|
}
|
|||
|
}
|