Files
Main/Assets/Code/Logic/_Required/Reconnect/ReconnectSystem_New.cs

447 lines
16 KiB
C#
Raw Permalink Normal View History

2025-01-25 04:38:09 +08:00
//**********************************************//
//作者:#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
}
}