mirror of
https://github.com/Alex-Rachel/TEngine.git
synced 2025-08-14 16:51:28 +00:00
Compare commits
61 Commits
demo
...
TEngine3.0
Author | SHA1 | Date | |
---|---|---|---|
![]() |
abd152b072 | ||
![]() |
470e62d9c4 | ||
![]() |
481b5911ab | ||
![]() |
05d3aff05e | ||
![]() |
86bb6353dc | ||
![]() |
334698b6e6 | ||
![]() |
2684bd29f5 | ||
![]() |
c568c62404 | ||
![]() |
699ccb3b09 | ||
![]() |
f92bf5c602 | ||
![]() |
cd87c71281 | ||
![]() |
94c137b3c6 | ||
![]() |
120a86b396 | ||
![]() |
383dc50fe3 | ||
![]() |
2369e8723c | ||
![]() |
344f3293ad | ||
![]() |
5d361dd188 | ||
![]() |
a2f7fe907a | ||
![]() |
5b3f64689f | ||
![]() |
2258c13892 | ||
![]() |
a70d2e7d17 | ||
![]() |
b15f51631a | ||
![]() |
da12bd7cab | ||
![]() |
98bcaef6b7 | ||
![]() |
71d1286144 | ||
![]() |
9359a81a96 | ||
![]() |
a9542646c1 | ||
![]() |
0890ca9bdb | ||
![]() |
ec409c7e15 | ||
![]() |
4bc63fafc8 | ||
![]() |
fe0f9afd6d | ||
![]() |
4632a0c099 | ||
![]() |
60e57bb80b | ||
![]() |
b7c79d0438 | ||
![]() |
62b7c9e4d6 | ||
![]() |
75a6977afb | ||
![]() |
659da836ac | ||
![]() |
07c459051f | ||
![]() |
4253a81e78 | ||
![]() |
e498abacd1 | ||
![]() |
f16759483f | ||
![]() |
899472a5db | ||
![]() |
e65245371a | ||
![]() |
b04fff4ec9 | ||
![]() |
d8f8fd01d9 | ||
![]() |
9b1c5e6f0a | ||
![]() |
b2b5c9274c | ||
![]() |
b814d689d8 | ||
![]() |
ca6de42d67 | ||
![]() |
c3e9b76fd6 | ||
![]() |
dca7b71457 | ||
![]() |
7106454dfb | ||
![]() |
b97e24aa6d | ||
![]() |
bec4cba501 | ||
![]() |
0568d5f8b2 | ||
![]() |
49db48e7fc | ||
![]() |
92fc5e0bcd | ||
![]() |
11391e597e | ||
![]() |
6b64f3b261 | ||
![]() |
dff6ba4e6d | ||
![]() |
036c89a6d1 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -116,3 +116,4 @@ UserSettings/Layouts/default-2021.dwlt
|
||||
Assets/UnityOnlineServiceData.meta
|
||||
Assets/UnityOnlineServiceData
|
||||
|
||||
.DS_Store
|
||||
|
8
Assets/GameScripts/Editor/Inspector.meta
Normal file
8
Assets/GameScripts/Editor/Inspector.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 22d1bcdd317c6f64daeb9bf9742495f2
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
8
Assets/GameScripts/Editor/Postprocessor.meta
Normal file
8
Assets/GameScripts/Editor/Postprocessor.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4944189ec9c939b45a65d93c704a22ec
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
33
Assets/GameScripts/HotFix/GameBase/Attribute.cs
Normal file
33
Assets/GameScripts/HotFix/GameBase/Attribute.cs
Normal file
@@ -0,0 +1,33 @@
|
||||
using System;
|
||||
|
||||
namespace TEngine
|
||||
{
|
||||
#region Attribute
|
||||
|
||||
[AttributeUsage(AttributeTargets.Class)]
|
||||
public class UpdateAttribute : Attribute
|
||||
{
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.Class)]
|
||||
public class FixedUpdateAttribute : Attribute
|
||||
{
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.Class)]
|
||||
public class LateUpdateAttribute : Attribute
|
||||
{
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.Class)]
|
||||
public class RoleLoginAttribute : Attribute
|
||||
{
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.Class)]
|
||||
public class RoleLogoutAttribute : Attribute
|
||||
{
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
3
Assets/GameScripts/HotFix/GameBase/Attribute.cs.meta
Normal file
3
Assets/GameScripts/HotFix/GameBase/Attribute.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 80791cccf63d44faa348884ea0c506a2
|
||||
timeCreated: 1684553027
|
@@ -51,6 +51,10 @@
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void OnRoleLogin()
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void OnRoleLogout()
|
||||
{
|
||||
}
|
||||
|
@@ -1,9 +1,10 @@
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace TEngine
|
||||
{
|
||||
/// <summary>
|
||||
/// 通过LogicSys来驱动且具备Unity完整生命周期的单例(不继承MonoBehaviour)
|
||||
/// 通过LogicSys来驱动且具备Unity完整生命周期的单例(不继承MonoBehaviour)。
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
public abstract class BehaviourSingleton<T> : BaseBehaviourSingleton where T : BaseBehaviourSingleton, new()
|
||||
@@ -53,13 +54,29 @@ namespace TEngine
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 帧更新。
|
||||
/// <remarks>需要UpdateAttribute。</remarks>
|
||||
/// </summary>
|
||||
public virtual void Update()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 后帧更新。
|
||||
/// <remarks>需要LateUpdateAttribute。</remarks>
|
||||
/// </summary>
|
||||
public virtual void LateUpdate()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 物理帧更新。
|
||||
/// <remarks>需要FixedUpdateAttribute。</remarks>
|
||||
/// </summary>
|
||||
public virtual void FixedUpdate()
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void Destroy()
|
||||
{
|
||||
@@ -84,12 +101,25 @@ namespace TEngine
|
||||
private readonly List<BaseBehaviourSingleton> _listStart = new List<BaseBehaviourSingleton>();
|
||||
private readonly List<BaseBehaviourSingleton> _listUpdate = new List<BaseBehaviourSingleton>();
|
||||
private readonly List<BaseBehaviourSingleton> _listLateUpdate = new List<BaseBehaviourSingleton>();
|
||||
private readonly List<BaseBehaviourSingleton> _listFixedUpdate = new List<BaseBehaviourSingleton>();
|
||||
|
||||
public void RegSingleton(BaseBehaviourSingleton inst)
|
||||
{
|
||||
Log.Assert(!_listInst.Contains(inst));
|
||||
_listInst.Add(inst);
|
||||
_listStart.Add(inst);
|
||||
if (HadAttribute<UpdateAttribute>(inst.GetType()))
|
||||
{
|
||||
_listUpdate.Add(inst);
|
||||
}
|
||||
if (HadAttribute<LateUpdateAttribute>(inst.GetType()))
|
||||
{
|
||||
_listLateUpdate.Add(inst);
|
||||
}
|
||||
if (HadAttribute<FixedUpdateAttribute>(inst.GetType()))
|
||||
{
|
||||
_listFixedUpdate.Add(inst);
|
||||
}
|
||||
}
|
||||
|
||||
public void UnRegSingleton(BaseBehaviourSingleton inst)
|
||||
@@ -174,6 +204,20 @@ namespace TEngine
|
||||
TProfiler.EndFirstSample();
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnFixedUpdate()
|
||||
{
|
||||
var listFixedUpdate = _listFixedUpdate;
|
||||
var listFixedUpdateCnt = listFixedUpdate.Count;
|
||||
for (int i = 0; i < listFixedUpdateCnt; i++)
|
||||
{
|
||||
var inst = listFixedUpdate[i];
|
||||
|
||||
TProfiler.BeginFirstSample(inst.GetType().FullName);
|
||||
inst.FixedUpdate();
|
||||
TProfiler.EndFirstSample();
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnDestroy()
|
||||
{
|
||||
@@ -208,5 +252,12 @@ namespace TEngine
|
||||
inst.OnDrawGizmos();
|
||||
}
|
||||
}
|
||||
|
||||
private bool HadAttribute<T>(Type type) where T:Attribute
|
||||
{
|
||||
T attribute = Attribute.GetCustomAttribute(type, typeof(T)) as T;
|
||||
|
||||
return attribute != null;
|
||||
}
|
||||
}
|
||||
}
|
@@ -35,15 +35,21 @@ public interface ILogicSys
|
||||
/// </summary>
|
||||
void OnFixedUpdate();
|
||||
|
||||
/// <summary>
|
||||
/// 登录账号/角色时调用
|
||||
/// </summary>
|
||||
void OnRoleLogin();
|
||||
|
||||
/// <summary>
|
||||
/// 清理数据接口,切换账号/角色时调用
|
||||
/// </summary>
|
||||
void OnRoleLogout();
|
||||
|
||||
/// <summary>
|
||||
/// OnDrawGizmos
|
||||
/// 绘制调试接口
|
||||
/// </summary>
|
||||
void OnDrawGizmos();
|
||||
|
||||
/// <summary>
|
||||
/// 暂停游戏
|
||||
/// </summary>
|
||||
|
1118
Assets/GameScripts/HotFix/GameBase/Redux.cs
Normal file
1118
Assets/GameScripts/HotFix/GameBase/Redux.cs
Normal file
File diff suppressed because it is too large
Load Diff
3
Assets/GameScripts/HotFix/GameBase/Redux.cs.meta
Normal file
3
Assets/GameScripts/HotFix/GameBase/Redux.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 464445719fff48a78021df4a4a6b05a5
|
||||
timeCreated: 1684552621
|
@@ -30,11 +30,11 @@ namespace GameBase
|
||||
{
|
||||
if (_root == null)
|
||||
{
|
||||
_root = GameObject.Find("[SingletonMgr]");
|
||||
_root = GameObject.Find("[GameModule]");
|
||||
|
||||
if (_root == null)
|
||||
{
|
||||
_root = new GameObject("[SingletonMgr]")
|
||||
_root = new GameObject("[GameModule]")
|
||||
{
|
||||
transform =
|
||||
{
|
||||
@@ -42,7 +42,7 @@ namespace GameBase
|
||||
}
|
||||
};
|
||||
}
|
||||
UnityEngine.Object.DontDestroyOnLoad(_root);
|
||||
Object.DontDestroyOnLoad(_root);
|
||||
}
|
||||
return _root;
|
||||
}
|
||||
@@ -70,7 +70,7 @@ namespace GameBase
|
||||
_gameObjects.Add(go.name, go);
|
||||
if (Application.isPlaying)
|
||||
{
|
||||
UnityEngine.Object.DontDestroyOnLoad(go);
|
||||
Object.DontDestroyOnLoad(go);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -80,7 +80,7 @@ namespace GameBase
|
||||
if (_gameObjects != null && _gameObjects.ContainsKey(go.name))
|
||||
{
|
||||
_gameObjects.Remove(go.name);
|
||||
UnityEngine.Object.Destroy(go);
|
||||
Object.Destroy(go);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -17,7 +17,7 @@ namespace GameBase
|
||||
{
|
||||
if (_instance == null)
|
||||
{
|
||||
var ins = UnityEngine.Object.FindObjectOfType<T>();
|
||||
var ins = FindObjectOfType<T>();
|
||||
if (ins != null)
|
||||
{
|
||||
var obj = ins.gameObject;
|
||||
@@ -32,11 +32,16 @@ namespace GameBase
|
||||
GameObject go = SingletonMgr.GetGameObject(instName);
|
||||
if (go == null)
|
||||
{
|
||||
go = GameObject.Find($"{instName}");
|
||||
go = GameObject.Find($"[{instName}]");
|
||||
if (go == null)
|
||||
{
|
||||
go = new GameObject(instName);
|
||||
go.transform.position = Vector3.zero;
|
||||
go = new GameObject($"[{instName}]")
|
||||
{
|
||||
transform =
|
||||
{
|
||||
position = Vector3.zero
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,11 +106,9 @@ namespace GameBase
|
||||
|
||||
public static void Release()
|
||||
{
|
||||
if (_instance != null)
|
||||
{
|
||||
SingletonMgr.Release(_instance.gameObject);
|
||||
_instance = null;
|
||||
}
|
||||
if (_instance == null) return;
|
||||
SingletonMgr.Release(_instance.gameObject);
|
||||
_instance = null;
|
||||
}
|
||||
}
|
||||
}
|
@@ -25,7 +25,8 @@ public partial class GameApp
|
||||
/// </summary>
|
||||
private void RegisterAllSystem()
|
||||
{
|
||||
|
||||
//带生命周期的单例系统。
|
||||
AddLogicSys(BehaviourSingleSystem.Instance);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@@ -11,7 +11,7 @@
|
||||
],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"allowUnsafeCode": true,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
|
@@ -0,0 +1,166 @@
|
||||
using TEngine;
|
||||
|
||||
namespace GameLogic
|
||||
{
|
||||
public enum ClientConnectWatcherStatus
|
||||
{
|
||||
StatusInit,
|
||||
StatusReconnectAuto,
|
||||
StatusReconnectConfirm,
|
||||
StatusWaitExit
|
||||
}
|
||||
|
||||
public class ClientConnectWatcher
|
||||
{
|
||||
private readonly GameClient _client;
|
||||
private ClientConnectWatcherStatus _status;
|
||||
private float _statusTime;
|
||||
private int _reconnectCnt = 0;
|
||||
private int _disconnectReason = 0;
|
||||
|
||||
private bool _enable = false;
|
||||
|
||||
public bool Enable
|
||||
{
|
||||
get => _enable;
|
||||
set
|
||||
{
|
||||
if (_enable != value)
|
||||
{
|
||||
_enable = value;
|
||||
if (_enable)
|
||||
{
|
||||
OnEnable();
|
||||
}
|
||||
else
|
||||
{
|
||||
OnDisable();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private ClientConnectWatcherStatus Status
|
||||
{
|
||||
get => _status;
|
||||
set
|
||||
{
|
||||
if (_status == value) return;
|
||||
_status = value;
|
||||
_statusTime = NowTime;
|
||||
}
|
||||
}
|
||||
|
||||
private float NowTime => GameTime.unscaledTime;
|
||||
|
||||
public ClientConnectWatcher(GameClient client)
|
||||
{
|
||||
_client = client;
|
||||
_statusTime = NowTime;
|
||||
_status = ClientConnectWatcherStatus.StatusInit;
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
if (!_enable)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (_client.IsEntered)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
switch (_status)
|
||||
{
|
||||
case ClientConnectWatcherStatus.StatusInit:
|
||||
UpdateOnInitStatus();
|
||||
break;
|
||||
case ClientConnectWatcherStatus.StatusReconnectAuto:
|
||||
UpdateOnReconnectAuto();
|
||||
break;
|
||||
case ClientConnectWatcherStatus.StatusReconnectConfirm:
|
||||
UpdateOnReconnectConfirm();
|
||||
break;
|
||||
case ClientConnectWatcherStatus.StatusWaitExit:
|
||||
UpdateOnWaitExit();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void OnReConnect()
|
||||
{
|
||||
if (_status == ClientConnectWatcherStatus.StatusReconnectConfirm)
|
||||
{
|
||||
Status = ClientConnectWatcherStatus.StatusReconnectAuto;
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateOnInitStatus()
|
||||
{
|
||||
int autoReconnectMaxCount = 4;
|
||||
if (_reconnectCnt <= autoReconnectMaxCount)
|
||||
{
|
||||
if (_reconnectCnt == 0)
|
||||
{
|
||||
_disconnectReason = _client.LastNetErrCode;
|
||||
}
|
||||
|
||||
Status = ClientConnectWatcherStatus.StatusReconnectAuto;
|
||||
_reconnectCnt++;
|
||||
|
||||
//重连
|
||||
_client.Reconnect();
|
||||
}
|
||||
else
|
||||
{
|
||||
Status = ClientConnectWatcherStatus.StatusReconnectConfirm;
|
||||
_reconnectCnt++;
|
||||
// UISys.Mgr.ShowUI(GAME_UI_TYPE.Tip_NetDisconn, UISys.Mgr.GetUIWindowParam().SetParam("errCode", m_disconnectReason));
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateOnReconnectAuto()
|
||||
{
|
||||
if (_client.IsEntered)
|
||||
{
|
||||
Status = ClientConnectWatcherStatus.StatusInit;
|
||||
_reconnectCnt = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
float nowTime = NowTime;
|
||||
var timeoutTime = 10f;
|
||||
|
||||
if (_statusTime + timeoutTime < nowTime)
|
||||
{
|
||||
Log.Error("UpdateOnReconnectAuto timeout: {0}", timeoutTime);
|
||||
|
||||
//切换到默认的,下一帧继续判断是否需要自动还是手动
|
||||
Status = ClientConnectWatcherStatus.StatusInit;
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateOnReconnectConfirm()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void UpdateOnWaitExit()
|
||||
{
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
Status = ClientConnectWatcherStatus.StatusInit;
|
||||
_reconnectCnt = 0;
|
||||
}
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
Status = ClientConnectWatcherStatus.StatusInit;
|
||||
_reconnectCnt = 0;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3e4e637f3da340dd9512150c3e2ff087
|
||||
timeCreated: 1684334948
|
428
Assets/GameScripts/HotFix/GameLogic/Network/GameClient.cs
Normal file
428
Assets/GameScripts/HotFix/GameLogic/Network/GameClient.cs
Normal file
@@ -0,0 +1,428 @@
|
||||
using System.Net.Sockets;
|
||||
using GameBase;
|
||||
using GameProto;
|
||||
using TEngine;
|
||||
using CSPkg = GameProto.CSPkg;
|
||||
|
||||
namespace GameLogic
|
||||
{
|
||||
public enum GameClientStatus
|
||||
{
|
||||
StatusInit, //初始化
|
||||
StatusReconnect, //重新连接
|
||||
StatusClose, //断开连接
|
||||
StatusLogin, //登录中
|
||||
StatusEnter, //AccountLogin成功,进入服务器了
|
||||
}
|
||||
|
||||
public enum CsMsgResult
|
||||
{
|
||||
NoError = 0,
|
||||
NetworkError = 1,
|
||||
InternalError = 2,
|
||||
MsgTimeOut = 3,
|
||||
PingTimeOut = 4,
|
||||
}
|
||||
|
||||
//定义消息回报的回调接口
|
||||
public delegate void CsMsgDelegate(CsMsgResult result, CSPkg msg);
|
||||
|
||||
/// <summary>
|
||||
/// 统计网络协议的接口
|
||||
/// </summary>
|
||||
public delegate void CsMsgStatDelegate(int cmdID, int pkgSize);
|
||||
|
||||
public class GameClient : Singleton<GameClient>
|
||||
{
|
||||
private readonly INetworkChannel _channel;
|
||||
|
||||
private GameClientStatus _status = GameClientStatus.StatusInit;
|
||||
|
||||
private readonly MsgDispatcher _dispatcher;
|
||||
|
||||
private readonly ClientConnectWatcher _connectWatcher;
|
||||
|
||||
private float _lastLogDisconnectErrTime = 0f;
|
||||
|
||||
private int _lastNetErrCode = 0;
|
||||
|
||||
public int LastNetErrCode => _lastNetErrCode;
|
||||
|
||||
public GameClientStatus Status
|
||||
{
|
||||
get => _status;
|
||||
set => _status = value;
|
||||
}
|
||||
|
||||
public bool IsEntered => _status == GameClientStatus.StatusEnter;
|
||||
|
||||
/// <summary>
|
||||
/// 连续心跳超时
|
||||
/// </summary>
|
||||
private int _heatBeatTimeoutNum = 0;
|
||||
|
||||
private int _ping = -1;
|
||||
|
||||
private float NowTime => GameTime.unscaledTime;
|
||||
|
||||
private string _lastHost = null;
|
||||
private int _lastPort = 0;
|
||||
|
||||
public GameClient()
|
||||
{
|
||||
_connectWatcher = new ClientConnectWatcher(this);
|
||||
_dispatcher = new MsgDispatcher();
|
||||
_dispatcher.SetTimeout(5f);
|
||||
GameEvent.AddEventListener<INetworkChannel,object>(NetworkEvent.NetworkConnectedEvent,OnNetworkConnected);
|
||||
GameEvent.AddEventListener<INetworkChannel>(NetworkEvent.NetworkClosedEvent,OnNetworkClosed);
|
||||
GameEvent.AddEventListener<INetworkChannel,NetworkErrorCode,SocketError,string>(NetworkEvent.NetworkErrorEvent,OnNetworkError);
|
||||
GameEvent.AddEventListener<INetworkChannel,object>(NetworkEvent.NetworkCustomErrorEvent,OnNetworkCustomError);
|
||||
_channel = Network.Instance.CreateNetworkChannel("GameClient", ServiceType.Tcp, new NetworkChannelHelper());
|
||||
}
|
||||
|
||||
private void OnNetworkConnected(INetworkChannel channel, object userdata)
|
||||
{
|
||||
bool isReconnect = (_status == GameClientStatus.StatusReconnect);
|
||||
//准备登录
|
||||
Status = GameClientStatus.StatusLogin;
|
||||
|
||||
OnServerConnected(isReconnect);
|
||||
}
|
||||
|
||||
private void OnNetworkClosed(INetworkChannel channel)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private void OnNetworkError(INetworkChannel channel, NetworkErrorCode networkErrorCode, SocketError socketError, string errorMessage)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private void OnNetworkCustomError(INetworkChannel channel, object userData)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void Connect(string host, int port, bool reconnect = false)
|
||||
{
|
||||
ResetParam();
|
||||
if (!reconnect)
|
||||
{
|
||||
SetWatchReconnect(false);
|
||||
}
|
||||
|
||||
if (reconnect)
|
||||
{
|
||||
// GameEvent.Get<ICommUI>().ShowWaitUITip(WaitUISeq.LOGINWORLD_SEQID, G.R(TextDefine.ID_TIPS_RECONNECTING));
|
||||
}
|
||||
else
|
||||
{
|
||||
// GameEvent.Get<ICommUI>().ShowWaitUI(WaitUISeq.LOGINWORLD_SEQID);
|
||||
}
|
||||
|
||||
_lastHost = host;
|
||||
_lastPort = port;
|
||||
|
||||
Status = reconnect ? GameClientStatus.StatusReconnect : GameClientStatus.StatusInit;
|
||||
|
||||
_channel.Connect(host, port);
|
||||
}
|
||||
|
||||
public void Reconnect()
|
||||
{
|
||||
if (string.IsNullOrEmpty(_lastHost) || _lastPort <= 0)
|
||||
{
|
||||
// GameModule.UI.ShowTipMsg("Invalid reconnect param");
|
||||
return;
|
||||
}
|
||||
|
||||
_connectWatcher.OnReConnect();
|
||||
Connect(_lastHost, _lastPort, true);
|
||||
}
|
||||
|
||||
|
||||
public void Shutdown()
|
||||
{
|
||||
_channel.Close();
|
||||
_status = GameClientStatus.StatusInit;
|
||||
}
|
||||
|
||||
public void OnServerConnected(bool isReconnect)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public bool SendCsMsg(CSPkg reqPkg)
|
||||
{
|
||||
if (!IsStatusCanSendMsg(reqPkg.Head.MsgId))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return DoSendData(reqPkg);
|
||||
}
|
||||
|
||||
public bool IsStatusCanSendMsg(uint msgId)
|
||||
{
|
||||
bool canSend = false;
|
||||
if (_status == GameClientStatus.StatusLogin)
|
||||
{
|
||||
canSend = (msgId == (uint)CSMsgID.CsCmdActLoginReq);
|
||||
}
|
||||
|
||||
if (_status == GameClientStatus.StatusEnter)
|
||||
{
|
||||
canSend = true;
|
||||
}
|
||||
|
||||
if (!canSend)
|
||||
{
|
||||
float nowTime = NowTime;
|
||||
if (_lastLogDisconnectErrTime + 5 < nowTime)
|
||||
{
|
||||
Log.Error("GameClient not connected, send msg failed, msgId[{0}]", msgId);
|
||||
_lastLogDisconnectErrTime = nowTime;
|
||||
}
|
||||
|
||||
//UISys.Mgr.ShowTipMsg(TextDefine.ID_ERR_NETWORKD_DISCONNECT);
|
||||
}
|
||||
|
||||
return canSend;
|
||||
}
|
||||
|
||||
public bool SendCsMsg(CSPkg reqPkg, uint resCmd, CsMsgDelegate resHandler = null, bool needShowWaitUI = true)
|
||||
{
|
||||
if (!IsStatusCanSendMsg(reqPkg.Head.MsgId))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var ret = DoSendData(reqPkg);
|
||||
if (!ret)
|
||||
{
|
||||
if (resHandler != null)
|
||||
{
|
||||
resHandler(CsMsgResult.InternalError, null);
|
||||
}
|
||||
|
||||
_dispatcher.NotifyCmdError(resCmd, CsMsgResult.InternalError);
|
||||
}
|
||||
else
|
||||
{
|
||||
//注册消息
|
||||
if (resHandler != null)
|
||||
{
|
||||
_dispatcher.RegSeqHandle(reqPkg.Head.Echo, resCmd, resHandler);
|
||||
if (reqPkg.Head.Echo > 0 && IsWaitingCmd(resCmd) && needShowWaitUI)
|
||||
{
|
||||
// TODO
|
||||
// GameEvent.Get<ICommUI>().ShowWaitUI(reqPkg.Head.Echo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
private bool DoSendData(CSPkg reqPkg)
|
||||
{
|
||||
if (!IsIgnoreLog(reqPkg.Head.MsgId))
|
||||
{
|
||||
Log.Debug("[c-s] CmdId[{0}]\n{1}", reqPkg.Head.MsgId, reqPkg.Body.ToString());
|
||||
}
|
||||
var sendRet = _channel.Send(reqPkg);
|
||||
return sendRet;
|
||||
}
|
||||
|
||||
private bool IsIgnoreLog(uint msgId)
|
||||
{
|
||||
bool ignoreLog = false;
|
||||
switch (msgId)
|
||||
{
|
||||
case (uint)CSMsgID.CsCmdHeatbeatReq:
|
||||
case (uint)CSMsgID.CsCmdHeatbeatRes:
|
||||
ignoreLog = true;
|
||||
break;
|
||||
}
|
||||
return ignoreLog;
|
||||
}
|
||||
|
||||
public static bool IsWaitingCmd(uint msgId)
|
||||
{
|
||||
//心跳包不需要读条等待
|
||||
if (msgId == (uint)CSMsgID.CsCmdHeatbeatRes)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void ResetParam()
|
||||
{
|
||||
_lastLogDisconnectErrTime = 0f;
|
||||
_heatBeatTimeoutNum = 0;
|
||||
_lastHbTime = 0f;
|
||||
_ping = -1;
|
||||
_lastNetErrCode = 0;
|
||||
}
|
||||
|
||||
public void OnUpdate()
|
||||
{
|
||||
_dispatcher.Update();
|
||||
TickHeartBeat();
|
||||
CheckHeatBeatTimeout();
|
||||
_connectWatcher.Update();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 注册静态消息
|
||||
/// </summary>
|
||||
/// <param name="iCmdID"></param>
|
||||
/// <param name="msgDelegate"></param>
|
||||
public void RegCmdHandle(int iCmdID, CsMsgDelegate msgDelegate)
|
||||
{
|
||||
_dispatcher.RegCmdHandle((uint)iCmdID, msgDelegate);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 移除消息处理函数
|
||||
/// </summary>
|
||||
/// <param name="cmdId"></param>
|
||||
/// <param name="msgDelegate"></param>
|
||||
public void RmvCmdHandle(int cmdId, CsMsgDelegate msgDelegate)
|
||||
{
|
||||
_dispatcher.RmvCmdHandle((uint)cmdId, msgDelegate);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置加密密钥
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
public void SetEncryptKey(string key)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置是否需要监控网络重连。
|
||||
/// 登录成功后,开启监控,可以自动重连或者提示玩家重连。
|
||||
/// </summary>
|
||||
/// <param name="needWatch"></param>
|
||||
public void SetWatchReconnect(bool needWatch)
|
||||
{
|
||||
_connectWatcher.Enable = needWatch;
|
||||
}
|
||||
|
||||
public bool IsNetworkOkAndLogin()
|
||||
{
|
||||
return _status == GameClientStatus.StatusEnter;
|
||||
}
|
||||
|
||||
#region 心跳处理
|
||||
|
||||
/// <summary>
|
||||
/// 最近一次心跳的时间
|
||||
/// </summary>
|
||||
private float _lastHbTime = 0f;
|
||||
|
||||
/// <summary>
|
||||
/// 心跳间隔
|
||||
/// </summary>
|
||||
private readonly float _heartBeatDurTime = 5;
|
||||
|
||||
/// <summary>
|
||||
/// 心跳超时的最大次数
|
||||
/// </summary>
|
||||
private const int HeatBeatTimeoutMaxCount = 2;
|
||||
|
||||
private bool CheckHeatBeatTimeout()
|
||||
{
|
||||
if (_heatBeatTimeoutNum >= HeatBeatTimeoutMaxCount)
|
||||
{
|
||||
//断开连接
|
||||
Shutdown();
|
||||
|
||||
//准备重连
|
||||
_heatBeatTimeoutNum = 0;
|
||||
Status = GameClientStatus.StatusClose;
|
||||
Log.Error("heat beat detect timeout");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void TickHeartBeat()
|
||||
{
|
||||
if (Status != GameClientStatus.StatusEnter)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var nowTime = NowTime;
|
||||
if (_lastHbTime + _heartBeatDurTime < nowTime)
|
||||
{
|
||||
_lastHbTime = nowTime;
|
||||
|
||||
CSPkg heatPkg = ProtobufUtility.BuildCsMsg((int)CSMsgID.CsCmdHeatbeatReq);
|
||||
heatPkg.Body.HeatBeatReq = new CSHeatBeatReq { HeatEchoTime = _lastHbTime };
|
||||
SendCsMsg(heatPkg, (int)CSMsgID.CsCmdHeatbeatRes, HandleHeatBeatRes);
|
||||
}
|
||||
}
|
||||
|
||||
void HandleHeatBeatRes(CsMsgResult result, CSPkg msg)
|
||||
{
|
||||
if (result != CsMsgResult.NoError)
|
||||
{
|
||||
//如果是超时了,则标记最近收到包的次数
|
||||
if (result == CsMsgResult.MsgTimeOut)
|
||||
{
|
||||
_heatBeatTimeoutNum++;
|
||||
Log.Warning("heat beat timeout: {0}", _heatBeatTimeoutNum);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var resBody = msg.Body.HeatBeatRes;
|
||||
float diffTime = NowTime - resBody.HeatEchoTime;
|
||||
_ping = (int)(diffTime * 1000);
|
||||
_heatBeatTimeoutNum = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Ping值
|
||||
|
||||
/// <summary>
|
||||
/// ping值
|
||||
/// </summary>
|
||||
public int Ping
|
||||
{
|
||||
get
|
||||
{
|
||||
if (IsPingValid())
|
||||
{
|
||||
return _ping / 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsPingValid()
|
||||
{
|
||||
if (IsNetworkOkAndLogin())
|
||||
{
|
||||
return _ping >= 0;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8c5441725c9f4d98a7790dc76a6a0c48
|
||||
timeCreated: 1684331687
|
@@ -1,19 +0,0 @@
|
||||
using System;
|
||||
using ProtoBuf;
|
||||
|
||||
namespace GameLogic
|
||||
{
|
||||
[Serializable, ProtoContract(Name = @"HeartBeat")]
|
||||
public class HeartBeat : PacketBase
|
||||
{
|
||||
public HeartBeat()
|
||||
{
|
||||
}
|
||||
|
||||
public override int Id => 1;
|
||||
|
||||
public override void Clear()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d8b9b60d2abf409ca9dd2ce00506ac79
|
||||
timeCreated: 1682046644
|
265
Assets/GameScripts/HotFix/GameLogic/Network/MsgDispatcher.cs
Normal file
265
Assets/GameScripts/HotFix/GameLogic/Network/MsgDispatcher.cs
Normal file
@@ -0,0 +1,265 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using GameProto;
|
||||
using TEngine;
|
||||
using CSPkg = GameProto.CSPkg;
|
||||
|
||||
namespace GameLogic
|
||||
{
|
||||
internal class MsgHandleDataToRmv
|
||||
{
|
||||
public uint MsgId;
|
||||
public CsMsgDelegate Handle;
|
||||
};
|
||||
|
||||
class MsgDispatcher
|
||||
{
|
||||
const int CheckTimeoutPerframe = 10;
|
||||
const int MaxMsgHandle = 256;
|
||||
|
||||
private readonly CsMsgDelegate[] _aMsgHandles = new CsMsgDelegate[MaxMsgHandle];
|
||||
private readonly float[] _fMsgRegTime = new float[MaxMsgHandle];
|
||||
private readonly UInt32[] _adwMsgRegSeq = new UInt32[MaxMsgHandle]; //因为_aiMsgRegResCmdID存储的是hash,不能保证一定seqid一样,所以这儿存储下,用来校验
|
||||
private readonly uint[] _aiMsgRegResCmdID = new uint[MaxMsgHandle];
|
||||
|
||||
UInt32 _dwLastCheckIndex = 0;
|
||||
|
||||
private readonly Dictionary<uint, List<CsMsgDelegate>> _mapCmdHandle = new Dictionary<uint, List<CsMsgDelegate>>();
|
||||
private readonly List<CsMsgStatDelegate> _listStatHandle = new List<CsMsgStatDelegate>();
|
||||
|
||||
//防止在处理消息的时候又删除了消息映射,所以这儿加了个队列来做个保护
|
||||
private readonly List<MsgHandleDataToRmv> _rmvList = new List<MsgHandleDataToRmv>();
|
||||
private bool _isInHandleLoop = false;
|
||||
private float _timeout = 5;
|
||||
|
||||
// 清理所有的网络消息
|
||||
public void CleanAllNetMsg()
|
||||
{
|
||||
_mapCmdHandle.Clear();
|
||||
}
|
||||
|
||||
public void SetTimeout(float timeout)
|
||||
{
|
||||
_timeout = timeout;
|
||||
}
|
||||
|
||||
public void RegSeqHandle(UInt32 dwMsgSeqID, uint iResCmdID, CsMsgDelegate msgDelegate)
|
||||
{
|
||||
UInt32 hashIndex = dwMsgSeqID % MaxMsgHandle;
|
||||
if (_aMsgHandles[hashIndex] != null)
|
||||
{
|
||||
OnCallSeqHandle(_adwMsgRegSeq[hashIndex], _aiMsgRegResCmdID[hashIndex]);
|
||||
NotifyTimeout(_aMsgHandles[hashIndex]);
|
||||
RmvReg((int)hashIndex);
|
||||
}
|
||||
|
||||
_aMsgHandles[hashIndex] = msgDelegate;
|
||||
_fMsgRegTime[hashIndex] = NowTime;
|
||||
_adwMsgRegSeq[hashIndex] = dwMsgSeqID;
|
||||
_aiMsgRegResCmdID[hashIndex] = iResCmdID;
|
||||
}
|
||||
|
||||
public void RegCmdHandle(uint iCmdID, CsMsgDelegate msgDelegate)
|
||||
{
|
||||
if (!_mapCmdHandle.TryGetValue(iCmdID, out var listHandle))
|
||||
{
|
||||
listHandle = new List<CsMsgDelegate>();
|
||||
_mapCmdHandle[iCmdID] = listHandle;
|
||||
}
|
||||
|
||||
if (listHandle != null)
|
||||
{
|
||||
if (listHandle.Contains(msgDelegate))
|
||||
{
|
||||
Log.Error("-------------repeat RegCmdHandle:{0}-----------", iCmdID);
|
||||
}
|
||||
|
||||
listHandle.Add(msgDelegate);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 注册统计处理接口
|
||||
/// </summary>
|
||||
/// <param name="handler"></param>
|
||||
public void RegCmdStatHandle(CsMsgStatDelegate handler)
|
||||
{
|
||||
_listStatHandle.Add(handler);
|
||||
}
|
||||
|
||||
public void DispatchCmdStat(int cmdID, int pkgSize)
|
||||
{
|
||||
foreach (CsMsgStatDelegate handle in _listStatHandle)
|
||||
{
|
||||
handle(cmdID, pkgSize);
|
||||
}
|
||||
}
|
||||
|
||||
public void RmvCmdHandle(uint iCmdID, CsMsgDelegate msgDelegate)
|
||||
{
|
||||
if (_isInHandleLoop)
|
||||
{
|
||||
MsgHandleDataToRmv toRmvData = new MsgHandleDataToRmv();
|
||||
toRmvData.MsgId = iCmdID;
|
||||
toRmvData.Handle = msgDelegate;
|
||||
|
||||
_rmvList.Add(toRmvData);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_mapCmdHandle.TryGetValue(iCmdID, out var listHandle))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (listHandle != null)
|
||||
{
|
||||
listHandle.Remove(msgDelegate);
|
||||
}
|
||||
}
|
||||
|
||||
public void NotifyCmdError(uint iCmdID, CsMsgResult result)
|
||||
{
|
||||
NotifyCmdHandle(iCmdID, result, default(CSPkg));
|
||||
}
|
||||
|
||||
protected bool NotifyCmdHandle(uint cmdID, CsMsgResult result, CSPkg pkg)
|
||||
{
|
||||
bool ret = false;
|
||||
if (_mapCmdHandle.TryGetValue(cmdID, out var listHandle))
|
||||
{
|
||||
_isInHandleLoop = true;
|
||||
|
||||
var rmvList = _rmvList;
|
||||
rmvList.Clear();
|
||||
foreach (CsMsgDelegate handle in listHandle)
|
||||
{
|
||||
ret = true;
|
||||
|
||||
TProfiler.BeginSample("handle");
|
||||
handle(result, pkg);
|
||||
TProfiler.EndSample();
|
||||
}
|
||||
|
||||
_isInHandleLoop = false;
|
||||
|
||||
//再统一删除掉
|
||||
int rmvCnt = rmvList.Count;
|
||||
for (int i = 0; i < rmvCnt; i++)
|
||||
{
|
||||
var rmvItem = rmvList[i];
|
||||
Log.Error("-------------remove cmd handle on loop:{0}-----------", rmvItem.MsgId);
|
||||
RmvCmdHandle(rmvItem.MsgId, rmvItem.Handle);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
protected void OnCallSeqHandle(UInt32 echoSeq, uint resCmdID)
|
||||
{
|
||||
if (echoSeq > 0)
|
||||
{
|
||||
// TODO
|
||||
// GameEvent.Get<ICommUI>().FinWaitUI(echoSeq);
|
||||
}
|
||||
}
|
||||
|
||||
protected void NotifyTimeout(CsMsgDelegate msgHandler)
|
||||
{
|
||||
msgHandler(CsMsgResult.MsgTimeOut, default(CSPkg));
|
||||
}
|
||||
|
||||
public void NotifySeqError(UInt32 dwSeqID, CsMsgResult result)
|
||||
{
|
||||
UInt32 hashIndex = dwSeqID % MaxMsgHandle;
|
||||
|
||||
//先判断是否有注册的指定消息
|
||||
if (_aMsgHandles[hashIndex] != null &&
|
||||
_adwMsgRegSeq[hashIndex] == dwSeqID)
|
||||
{
|
||||
OnCallSeqHandle(dwSeqID, _aiMsgRegResCmdID[hashIndex]);
|
||||
_aMsgHandles[hashIndex](result, null);
|
||||
|
||||
RmvReg((int)hashIndex);
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsCmdFilterNoLog(int cmdID)
|
||||
{
|
||||
switch (cmdID)
|
||||
{
|
||||
case (int)CSMsgID.CsCmdHeatbeatRes:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void NotifyMsg(CSPkg msg)
|
||||
{
|
||||
UInt32 dwSeq = msg.Head.Echo;
|
||||
UInt32 hashIndex = dwSeq % MaxMsgHandle;
|
||||
//判断是否有固定的消息处理流程
|
||||
bool bHaveHandle = NotifyCmdHandle(msg.Head.MsgId, CsMsgResult.NoError, msg);
|
||||
|
||||
//再判断是否有注册的指定消息
|
||||
if (_aMsgHandles[hashIndex] != null &&
|
||||
_adwMsgRegSeq[hashIndex] == dwSeq &&
|
||||
_aiMsgRegResCmdID[hashIndex] == (int)msg.Head.MsgId)
|
||||
{
|
||||
OnCallSeqHandle(_adwMsgRegSeq[hashIndex], _aiMsgRegResCmdID[hashIndex]);
|
||||
_aMsgHandles[hashIndex](CsMsgResult.NoError, msg);
|
||||
RmvReg((int)hashIndex);
|
||||
bHaveHandle = true;
|
||||
}
|
||||
|
||||
if (!bHaveHandle)
|
||||
{
|
||||
Log.Debug("there is no handle for Msg[{0}]", msg.Head.MsgId);
|
||||
}
|
||||
}
|
||||
|
||||
private float NowTime => GameTime.unscaledTime;
|
||||
|
||||
public void Update()
|
||||
{
|
||||
CheckTimeOut();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 定时检查是否请求超时。
|
||||
/// </summary>
|
||||
private void CheckTimeOut()
|
||||
{
|
||||
float timeout = _timeout;
|
||||
float nowTime = NowTime;
|
||||
for (int i = 0; i < CheckTimeoutPerframe; i++)
|
||||
{
|
||||
_dwLastCheckIndex = (_dwLastCheckIndex + 1) % MaxMsgHandle;
|
||||
if (_aMsgHandles[_dwLastCheckIndex] != null)
|
||||
{
|
||||
if (_fMsgRegTime[_dwLastCheckIndex] + timeout < nowTime)
|
||||
{
|
||||
Log.Error("msg timeout, resCmdID[{0}], reqSeq[{1}]", _aiMsgRegResCmdID[_dwLastCheckIndex],
|
||||
_adwMsgRegSeq[_dwLastCheckIndex]);
|
||||
|
||||
OnCallSeqHandle(_adwMsgRegSeq[_dwLastCheckIndex], _aiMsgRegResCmdID[_dwLastCheckIndex]);
|
||||
NotifyTimeout(_aMsgHandles[_dwLastCheckIndex]);
|
||||
|
||||
RmvReg((int)_dwLastCheckIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void RmvReg(int index)
|
||||
{
|
||||
_aMsgHandles[index] = null;
|
||||
_adwMsgRegSeq[index] = 0;
|
||||
_aiMsgRegResCmdID[index] = 0;
|
||||
_fMsgRegTime[index] = 0;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7d667fb84fed4c5f93a06c464585512f
|
||||
timeCreated: 1684333223
|
@@ -1,10 +1,10 @@
|
||||
using ProtoBuf;
|
||||
using ProtoBuf.Meta;
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Sockets;
|
||||
using System.Reflection;
|
||||
using GameProto;
|
||||
using Google.Protobuf;
|
||||
using TEngine;
|
||||
|
||||
namespace GameLogic
|
||||
@@ -29,31 +29,6 @@ namespace GameLogic
|
||||
{
|
||||
_networkChannel = networkChannel;
|
||||
|
||||
// 反射注册包和包处理函数。
|
||||
Type packetBaseType = typeof(ProtoPacket);
|
||||
Assembly assembly = Assembly.GetExecutingAssembly();
|
||||
Type[] types = assembly.GetTypes();
|
||||
for (int i = 0; i < types.Length; i++)
|
||||
{
|
||||
if (!types[i].IsClass || types[i].IsAbstract)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (types[i].BaseType == packetBaseType)
|
||||
{
|
||||
PacketBase packetBase = (PacketBase)Activator.CreateInstance(types[i]);
|
||||
Type packetType = GetServerToClientPacketType(packetBase.Id);
|
||||
if (packetType != null)
|
||||
{
|
||||
Log.Warning("Already exist packet type '{0}', check '{1}' or '{2}'?.", packetBase.Id.ToString(), packetType.Name, packetBase.GetType().Name);
|
||||
continue;
|
||||
}
|
||||
|
||||
_serverToClientPacketTypes.Add(packetBase.Id, types[i]);
|
||||
}
|
||||
}
|
||||
|
||||
GameEvent.AddEventListener<INetworkChannel, object>(NetworkEvent.NetworkConnectedEvent, OnNetworkConnected);
|
||||
GameEvent.AddEventListener<INetworkChannel>(NetworkEvent.NetworkClosedEvent, OnNetworkClosed);
|
||||
GameEvent.AddEventListener<INetworkChannel, int>(NetworkEvent.NetworkMissHeartBeatEvent, OnNetworkMissHeartBeat);
|
||||
@@ -84,13 +59,16 @@ namespace GameLogic
|
||||
_networkChannel.Socket.SendBufferSize = 1024 * 64;
|
||||
}
|
||||
|
||||
public CSPkg HeartBeatPack = new CSPkg { Head = new CSPkgHead(), Body = new CSPkgBody() };
|
||||
|
||||
/// <summary>
|
||||
/// 发送心跳消息包。
|
||||
/// </summary>
|
||||
/// <returns>是否发送心跳消息包成功。</returns>
|
||||
public bool SendHeartBeat()
|
||||
{
|
||||
_networkChannel.Send(MemoryPool.Acquire<HeartBeat>());
|
||||
HeartBeatPack.Head.MsgId = (uint)CSMsgID.CsCmdHeatbeatReq;
|
||||
_networkChannel.Send(HeartBeatPack);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -101,10 +79,9 @@ namespace GameLogic
|
||||
/// <param name="packet">要序列化的消息包。</param>
|
||||
/// <param name="destination">要序列化的目标流。</param>
|
||||
/// <returns>是否序列化成功。</returns>
|
||||
public bool Serialize<T>(T packet, Stream destination) where T : Packet
|
||||
public bool Serialize(CSPkg packet, Stream destination)
|
||||
{
|
||||
PacketBase packetImpl = packet as PacketBase;
|
||||
if (packetImpl == null)
|
||||
if (packet == null)
|
||||
{
|
||||
Log.Warning("Packet is invalid.");
|
||||
return false;
|
||||
@@ -112,14 +89,7 @@ namespace GameLogic
|
||||
|
||||
_cachedStream.SetLength(_cachedStream.Capacity); // 此行防止 Array.Copy 的数据无法写入
|
||||
_cachedStream.Position = 0L;
|
||||
|
||||
PacketHeader packetHeader = MemoryPool.Acquire<PacketHeader>();
|
||||
Serializer.Serialize(_cachedStream, packetHeader);
|
||||
MemoryPool.Release(packetHeader);
|
||||
|
||||
Serializer.SerializeWithLengthPrefix(_cachedStream, packet, PrefixStyle.Fixed32);
|
||||
MemoryPool.Release((IMemory)packet);
|
||||
|
||||
global::ProtobufUtility.ToStreamWithHead(packet,_cachedStream);
|
||||
_cachedStream.WriteTo(destination);
|
||||
return true;
|
||||
}
|
||||
@@ -134,7 +104,9 @@ namespace GameLogic
|
||||
{
|
||||
// 注意:此函数并不在主线程调用!
|
||||
customErrorData = null;
|
||||
return (IPacketHeader)RuntimeTypeModel.Default.Deserialize(source, MemoryPool.Acquire<PacketHeader>(), typeof(PacketHeader));
|
||||
PacketHeader packetHeader = MemoryPool.Acquire<PacketHeader>();
|
||||
packetHeader.PacketLength = ((MemoryStream)source).GetBuffer()[0];
|
||||
return packetHeader;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -144,7 +116,7 @@ namespace GameLogic
|
||||
/// <param name="source">要反序列化的来源流。</param>
|
||||
/// <param name="customErrorData">用户自定义错误数据。</param>
|
||||
/// <returns>反序列化后的消息包。</returns>
|
||||
public Packet DeserializePacket(IPacketHeader packetHeader, Stream source, out object customErrorData)
|
||||
public CSPkg DeserializePacket(IPacketHeader packetHeader, Stream source, out object customErrorData)
|
||||
{
|
||||
// 注意:此函数并不在主线程调用!
|
||||
customErrorData = null;
|
||||
@@ -156,17 +128,17 @@ namespace GameLogic
|
||||
return null;
|
||||
}
|
||||
|
||||
Packet packet = null;
|
||||
CSPkg csPkg = null;
|
||||
if (scPacketHeader.IsValid)
|
||||
{
|
||||
Type packetType = GetServerToClientPacketType(scPacketHeader.Id);
|
||||
if (packetType != null)
|
||||
try
|
||||
{
|
||||
packet = (Packet)RuntimeTypeModel.Default.DeserializeWithLengthPrefix(source, MemoryPool.Acquire(packetType), packetType, PrefixStyle.Fixed32, 0);
|
||||
csPkg = global::ProtobufUtility.Deserialize(((MemoryStream)source).GetBuffer(),0,scPacketHeader.PacketLength);
|
||||
Log.Debug("[s-c] CmdId[{0}]\n{1}", csPkg.Head.MsgId, csPkg.ToString());
|
||||
}
|
||||
else
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Warning("Can not deserialize packet for packet id '{0}'.", scPacketHeader.Id.ToString());
|
||||
Log.Warning(e);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -175,7 +147,7 @@ namespace GameLogic
|
||||
}
|
||||
|
||||
MemoryPool.Release(scPacketHeader);
|
||||
return packet;
|
||||
return csPkg;
|
||||
}
|
||||
|
||||
private Type GetServerToClientPacketType(int id)
|
||||
|
@@ -1,6 +1,8 @@
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using GameProto;
|
||||
using Google.Protobuf;
|
||||
|
||||
namespace TEngine
|
||||
{
|
||||
@@ -163,7 +165,7 @@ namespace TEngine
|
||||
/// <typeparam name="T">消息包类型。</typeparam>
|
||||
/// <param name="packet">要发送的消息包。</param>
|
||||
/// <returns>消息包是否发送成功。</returns>
|
||||
bool Send<T>(T packet) where T : Packet;
|
||||
bool Send(CSPkg packet);
|
||||
|
||||
/// <summary>
|
||||
/// 向远程主机发送消息包并注册消息回调。
|
||||
@@ -173,6 +175,6 @@ namespace TEngine
|
||||
/// <param name="resHandler">要注册的回调。</param>
|
||||
/// <param name="needShowWaitUI">是否需要等待UI。</param>
|
||||
/// <returns>消息包是否发送成功。</returns>
|
||||
bool Send<T>(T packet, CsMsgDelegate resHandler, bool needShowWaitUI = false) where T : Packet;
|
||||
bool Send(CSPkg packet, CsMsgDelegate resHandler, bool needShowWaitUI = false);
|
||||
}
|
||||
}
|
@@ -1,4 +1,5 @@
|
||||
using System.IO;
|
||||
using GameProto;
|
||||
|
||||
namespace TEngine
|
||||
{
|
||||
@@ -44,7 +45,7 @@ namespace TEngine
|
||||
/// <param name="packet">要序列化的消息包。</param>
|
||||
/// <param name="destination">要序列化的目标流。</param>
|
||||
/// <returns>是否序列化成功。</returns>
|
||||
bool Serialize<T>(T packet, Stream destination) where T : Packet;
|
||||
bool Serialize(CSPkg packet, Stream destination);
|
||||
|
||||
/// <summary>
|
||||
/// 反序列化消息包头。
|
||||
@@ -61,6 +62,6 @@ namespace TEngine
|
||||
/// <param name="source">要反序列化的来源流。</param>
|
||||
/// <param name="customErrorData">用户自定义错误数据。</param>
|
||||
/// <returns>反序列化后的消息包。</returns>
|
||||
Packet DeserializePacket(IPacketHeader packetHeader, Stream source, out object customErrorData);
|
||||
CSPkg DeserializePacket(IPacketHeader packetHeader, Stream source, out object customErrorData);
|
||||
}
|
||||
}
|
@@ -1,5 +1,6 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Net.Sockets;
|
||||
using GameBase;
|
||||
using UnityEngine;
|
||||
|
||||
namespace TEngine
|
||||
@@ -8,9 +9,9 @@ namespace TEngine
|
||||
/// 网络组件。
|
||||
/// </summary>
|
||||
[DisallowMultipleComponent]
|
||||
public sealed class Network : GameFrameworkModuleBase
|
||||
public sealed class Network : UnitySingleton<Network>
|
||||
{
|
||||
private static INetworkManager m_NetworkManager = null;
|
||||
private NetworkManager m_NetworkManager = null;
|
||||
|
||||
/// <summary>
|
||||
/// 获取网络频道数量。
|
||||
@@ -20,11 +21,12 @@ namespace TEngine
|
||||
/// <summary>
|
||||
/// 游戏框架组件初始化。
|
||||
/// </summary>
|
||||
protected override void Awake()
|
||||
public override void Awake()
|
||||
{
|
||||
base.Awake();
|
||||
|
||||
m_NetworkManager = GameFrameworkEntry.GetModule<INetworkManager>();
|
||||
// m_NetworkManager = GameFrameworkEntry.GetModule<INetworkManager>();
|
||||
m_NetworkManager = new NetworkManager();
|
||||
if (m_NetworkManager == null)
|
||||
{
|
||||
Log.Fatal("Network manager is invalid.");
|
||||
@@ -38,12 +40,17 @@ namespace TEngine
|
||||
m_NetworkManager.NetworkCustomError += OnNetworkCustomError;
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
m_NetworkManager.Update(GameTime.deltaTime, GameTime.unscaledDeltaTime);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查是否存在网络频道。
|
||||
/// </summary>
|
||||
/// <param name="name">网络频道名称。</param>
|
||||
/// <returns>是否存在网络频道。</returns>
|
||||
public static bool HasNetworkChannel(string name)
|
||||
public bool HasNetworkChannel(string name)
|
||||
{
|
||||
return m_NetworkManager.HasNetworkChannel(name);
|
||||
}
|
||||
@@ -53,7 +60,7 @@ namespace TEngine
|
||||
/// </summary>
|
||||
/// <param name="name">网络频道名称。</param>
|
||||
/// <returns>要获取的网络频道。</returns>
|
||||
public static INetworkChannel GetNetworkChannel(string name)
|
||||
public INetworkChannel GetNetworkChannel(string name)
|
||||
{
|
||||
return m_NetworkManager.GetNetworkChannel(name);
|
||||
}
|
||||
@@ -62,11 +69,11 @@ namespace TEngine
|
||||
/// 获取所有网络频道。
|
||||
/// </summary>
|
||||
/// <returns>所有网络频道。</returns>
|
||||
public static INetworkChannel[] StaticGetAllNetworkChannels()
|
||||
public INetworkChannel[] StaticGetAllNetworkChannels()
|
||||
{
|
||||
return m_NetworkManager.GetAllNetworkChannels();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 获取所有网络频道。
|
||||
/// </summary>
|
||||
@@ -80,7 +87,7 @@ namespace TEngine
|
||||
/// 获取所有网络频道。
|
||||
/// </summary>
|
||||
/// <param name="results">所有网络频道。</param>
|
||||
public static void GetAllNetworkChannels(List<INetworkChannel> results)
|
||||
public void GetAllNetworkChannels(List<INetworkChannel> results)
|
||||
{
|
||||
m_NetworkManager.GetAllNetworkChannels(results);
|
||||
}
|
||||
@@ -92,7 +99,8 @@ namespace TEngine
|
||||
/// <param name="serviceType">网络服务类型。</param>
|
||||
/// <param name="networkChannelHelper">网络频道辅助器。</param>
|
||||
/// <returns>要创建的网络频道。</returns>
|
||||
public static INetworkChannel CreateNetworkChannel(string name, ServiceType serviceType, INetworkChannelHelper networkChannelHelper)
|
||||
public INetworkChannel CreateNetworkChannel(string name, ServiceType serviceType,
|
||||
INetworkChannelHelper networkChannelHelper)
|
||||
{
|
||||
return m_NetworkManager.CreateNetworkChannel(name, serviceType, networkChannelHelper);
|
||||
}
|
||||
@@ -102,7 +110,7 @@ namespace TEngine
|
||||
/// </summary>
|
||||
/// <param name="channelName">网络频道名称。</param>
|
||||
/// <returns>是否销毁网络频道成功。</returns>
|
||||
public static bool DestroyNetworkChannel(string channelName)
|
||||
public bool DestroyNetworkChannel(string channelName)
|
||||
{
|
||||
return m_NetworkManager.DestroyNetworkChannel(channelName);
|
||||
}
|
||||
@@ -122,7 +130,8 @@ namespace TEngine
|
||||
GameEvent.Send(NetworkEvent.NetworkMissHeartBeatEvent, channel, missCount);
|
||||
}
|
||||
|
||||
private void OnNetworkError(INetworkChannel channel, NetworkErrorCode networkErrorCode, SocketError socketError, string errorMessage)
|
||||
private void OnNetworkError(INetworkChannel channel, NetworkErrorCode networkErrorCode, SocketError socketError,
|
||||
string errorMessage)
|
||||
{
|
||||
GameEvent.Send(NetworkEvent.NetworkErrorEvent, channel, networkErrorCode, socketError, errorMessage);
|
||||
}
|
@@ -2,6 +2,8 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using GameProto;
|
||||
using Google.Protobuf;
|
||||
|
||||
namespace TEngine
|
||||
{
|
||||
@@ -15,7 +17,7 @@ namespace TEngine
|
||||
private const float DefaultHeartBeatInterval = 30f;
|
||||
|
||||
private readonly string _name;
|
||||
protected readonly Queue<Packet> SendPacketPool;
|
||||
protected readonly Queue<CSPkg> SendPacketPool;
|
||||
protected readonly INetworkChannelHelper NetworkChannelHelper;
|
||||
protected AddressFamily MAddressFamily;
|
||||
protected bool MResetHeartBeatElapseSecondsWhenReceivePacket;
|
||||
@@ -48,7 +50,7 @@ namespace TEngine
|
||||
/// <summary>
|
||||
/// 消息包缓存堆栈。
|
||||
/// </summary>
|
||||
private readonly Queue<Packet> _packsQueue = new Queue<Packet>();
|
||||
private readonly Queue<CSPkg> _packsQueue = new Queue<CSPkg>();
|
||||
|
||||
/// <summary>
|
||||
/// 初始化网络频道基类的新实例。
|
||||
@@ -58,7 +60,7 @@ namespace TEngine
|
||||
public NetworkChannelBase(string name, INetworkChannelHelper networkChannelHelper)
|
||||
{
|
||||
_name = name ?? string.Empty;
|
||||
SendPacketPool = new Queue<Packet>();
|
||||
SendPacketPool = new Queue<CSPkg>();
|
||||
NetworkChannelHelper = networkChannelHelper;
|
||||
MAddressFamily = AddressFamily.Unknown;
|
||||
MResetHeartBeatElapseSecondsWhenReceivePacket = false;
|
||||
@@ -411,9 +413,8 @@ namespace TEngine
|
||||
/// <summary>
|
||||
/// 向远程主机发送消息包。
|
||||
/// </summary>
|
||||
/// <typeparam name="T">消息包类型。</typeparam>
|
||||
/// <param name="packet">要发送的消息包。</param>
|
||||
public bool Send<T>(T packet) where T : Packet
|
||||
public bool Send(CSPkg packet)
|
||||
{
|
||||
if (MSocket == null)
|
||||
{
|
||||
@@ -461,14 +462,13 @@ namespace TEngine
|
||||
/// <summary>
|
||||
/// 向远程主机发送消息包并注册消息回调。
|
||||
/// </summary>
|
||||
/// <typeparam name="T">消息包类型。</typeparam>
|
||||
/// <param name="packet">要发送的消息包。</param>
|
||||
/// <param name="resHandler">要注册的回调。</param>
|
||||
/// <param name="needShowWaitUI">是否需要等待UI。</param>
|
||||
/// <returns>消息包是否发送成功。</returns>
|
||||
public bool Send<T>(T packet, CsMsgDelegate resHandler, bool needShowWaitUI = false) where T : Packet
|
||||
public bool Send(CSPkg packet, CsMsgDelegate resHandler, bool needShowWaitUI = false)
|
||||
{
|
||||
RegisterMsgHandler(packet.Id,resHandler,false);
|
||||
RegisterMsgHandler((int)packet.Head.MsgId,resHandler,false);
|
||||
return Send(packet);
|
||||
}
|
||||
|
||||
@@ -511,16 +511,16 @@ namespace TEngine
|
||||
|
||||
while (SendPacketPool.Count > 0)
|
||||
{
|
||||
Packet packet = null;
|
||||
CSPkg csPkg = null;
|
||||
lock (SendPacketPool)
|
||||
{
|
||||
packet = SendPacketPool.Dequeue();
|
||||
csPkg = SendPacketPool.Dequeue();
|
||||
}
|
||||
|
||||
bool serializeResult = false;
|
||||
try
|
||||
{
|
||||
serializeResult = NetworkChannelHelper.Serialize(packet, MSendState.Stream);
|
||||
serializeResult = NetworkChannelHelper.Serialize(csPkg, MSendState.Stream);
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
@@ -614,22 +614,22 @@ namespace TEngine
|
||||
|
||||
try
|
||||
{
|
||||
Packet packet = NetworkChannelHelper.DeserializePacket(MReceiveState.PacketHeader, MReceiveState.Stream, out var customErrorData);
|
||||
CSPkg csPkg = NetworkChannelHelper.DeserializePacket(MReceiveState.PacketHeader, MReceiveState.Stream, out var customErrorData);
|
||||
|
||||
if (customErrorData != null && NetworkChannelCustomError != null)
|
||||
{
|
||||
NetworkChannelCustomError(this, customErrorData);
|
||||
}
|
||||
|
||||
if (packet != null)
|
||||
if (csPkg != null)
|
||||
{
|
||||
lock (_cacheHandlerQueue)
|
||||
{
|
||||
if (_msgHandlerMap.TryGetValue((int)packet.Id, out var listHandle))
|
||||
if (_msgHandlerMap.TryGetValue((int)csPkg.Head.MsgId, out var listHandle))
|
||||
{
|
||||
_cacheHandlerQueue.Enqueue(listHandle);
|
||||
|
||||
_packsQueue.Enqueue(packet);
|
||||
_packsQueue.Enqueue(csPkg);
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,21 +1,23 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net.Sockets;
|
||||
using GameBase;
|
||||
using GameProto;
|
||||
|
||||
namespace TEngine
|
||||
{
|
||||
/// <summary>
|
||||
/// 网络消息委托。
|
||||
/// </summary>
|
||||
public delegate void CsMsgDelegate(Packet packet);
|
||||
|
||||
public delegate void CsMsgDelegate(CSPkg csPkg);
|
||||
|
||||
/// <summary>
|
||||
/// 网络管理器。
|
||||
/// </summary>
|
||||
internal sealed partial class NetworkManager : GameFrameworkModule, INetworkManager
|
||||
internal sealed partial class NetworkManager : Singleton<NetworkManager>, INetworkManager
|
||||
{
|
||||
private readonly Dictionary<string, NetworkChannelBase> _networkChannels;
|
||||
|
||||
|
||||
private Action<INetworkChannel, object> _networkConnectedEventHandler;
|
||||
private Action<INetworkChannel> _networkClosedEventHandler;
|
||||
private Action<INetworkChannel, int> _networkMissHeartBeatEventHandler;
|
||||
@@ -90,7 +92,7 @@ namespace TEngine
|
||||
/// </summary>
|
||||
/// <param name="elapseSeconds">逻辑流逝时间,以秒为单位。</param>
|
||||
/// <param name="realElapseSeconds">真实流逝时间,以秒为单位。</param>
|
||||
internal override void Update(float elapseSeconds, float realElapseSeconds)
|
||||
public void Update(float elapseSeconds, float realElapseSeconds)
|
||||
{
|
||||
foreach (KeyValuePair<string, NetworkChannelBase> networkChannel in _networkChannels)
|
||||
{
|
||||
@@ -101,7 +103,7 @@ namespace TEngine
|
||||
/// <summary>
|
||||
/// 关闭并清理网络管理器。
|
||||
/// </summary>
|
||||
internal override void Shutdown()
|
||||
public void Shutdown()
|
||||
{
|
||||
foreach (KeyValuePair<string, NetworkChannelBase> networkChannel in _networkChannels)
|
||||
{
|
||||
@@ -183,7 +185,8 @@ namespace TEngine
|
||||
/// <param name="serviceType">网络服务类型。</param>
|
||||
/// <param name="networkChannelHelper">网络频道辅助器。</param>
|
||||
/// <returns>要创建的网络频道。</returns>
|
||||
public INetworkChannel CreateNetworkChannel(string name, ServiceType serviceType, INetworkChannelHelper networkChannelHelper)
|
||||
public INetworkChannel CreateNetworkChannel(string name, ServiceType serviceType,
|
||||
INetworkChannelHelper networkChannelHelper)
|
||||
{
|
||||
if (networkChannelHelper == null)
|
||||
{
|
||||
@@ -197,7 +200,8 @@ namespace TEngine
|
||||
|
||||
if (HasNetworkChannel(name))
|
||||
{
|
||||
throw new GameFrameworkException(Utility.Text.Format("Already exist network channel '{0}'.", name ?? string.Empty));
|
||||
throw new GameFrameworkException(Utility.Text.Format("Already exist network channel '{0}'.",
|
||||
name ?? string.Empty));
|
||||
}
|
||||
|
||||
NetworkChannelBase networkChannel = null;
|
||||
@@ -210,17 +214,18 @@ namespace TEngine
|
||||
case ServiceType.TcpWithSyncReceive:
|
||||
networkChannel = new TcpWithSyncReceiveNetworkChannel(name, networkChannelHelper);
|
||||
break;
|
||||
|
||||
|
||||
case ServiceType.Udp:
|
||||
networkChannel = new UdpNetworkChannel(name, networkChannelHelper);
|
||||
break;
|
||||
|
||||
|
||||
case ServiceType.Kcp:
|
||||
networkChannel = new KcpNetworkChannel(name, networkChannelHelper);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new GameFrameworkException(Utility.Text.Format("Not supported service type '{0}'.", serviceType));
|
||||
throw new GameFrameworkException(Utility.Text.Format("Not supported service type '{0}'.",
|
||||
serviceType));
|
||||
}
|
||||
|
||||
networkChannel.NetworkChannelConnected += OnNetworkChannelConnected;
|
||||
@@ -249,6 +254,7 @@ namespace TEngine
|
||||
networkChannel.Shutdown();
|
||||
return name != null && _networkChannels.Remove(name);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -285,7 +291,8 @@ namespace TEngine
|
||||
}
|
||||
}
|
||||
|
||||
private void OnNetworkChannelError(NetworkChannelBase networkChannel, NetworkErrorCode errorCode, SocketError socketErrorCode, string errorMessage)
|
||||
private void OnNetworkChannelError(NetworkChannelBase networkChannel, NetworkErrorCode errorCode,
|
||||
SocketError socketErrorCode, string errorMessage)
|
||||
{
|
||||
if (_networkErrorEventHandler != null)
|
||||
{
|
||||
@@ -307,4 +314,4 @@ namespace TEngine
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,24 +0,0 @@
|
||||
using TEngine;
|
||||
|
||||
namespace GameLogic
|
||||
{
|
||||
/// <summary>
|
||||
/// 网络消息包基类。
|
||||
/// </summary>
|
||||
public abstract class PacketBase : Packet
|
||||
{
|
||||
/// <summary>
|
||||
/// 网络消息包Id。
|
||||
/// </summary>
|
||||
public int ProtoId;
|
||||
|
||||
/// <summary>
|
||||
/// 网络消息包包体。
|
||||
/// </summary>
|
||||
public byte[] ProtoBody;
|
||||
|
||||
public void Close()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: acea4283f57644b6b4452354d23f2803
|
||||
timeCreated: 1682045887
|
@@ -1,15 +0,0 @@
|
||||
namespace GameLogic
|
||||
{
|
||||
/// <summary>
|
||||
/// 网络消息包。
|
||||
/// </summary>
|
||||
public partial class ProtoPacket : PacketBase
|
||||
{
|
||||
public override int Id => 1;
|
||||
|
||||
public override void Clear()
|
||||
{
|
||||
Close();
|
||||
}
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user