合理化Address协议逻辑

合理化Address协议逻辑
This commit is contained in:
ALEXTANG
2023-07-21 17:50:47 +08:00
parent 144ba9f222
commit e5456da482
14 changed files with 78 additions and 69 deletions

View File

@@ -35,8 +35,8 @@ namespace TEngine.DataStructure
if (layer <= rLevel) if (layer <= rLevel)
{ {
var currentRight = cur.Right; var currentRight = cur.Right;
cur.Right = new SkipTableNode<TValue>(sortKey, viceKey, key, value,
layer == 1 ? cur.Index + 1 : 0, cur, cur.Right, null); cur.Right = new SkipTableNode<TValue>(sortKey, viceKey, key, value, layer == 1 ? cur.Index + 1 : 0, cur, cur.Right, null);
if (currentRight != null) if (currentRight != null)
{ {

View File

@@ -528,6 +528,7 @@ namespace TEngine
try try
{ {
Scene = scene;
#if TENGINE_NET #if TENGINE_NET
RuntimeId = IdFactory.NextEntityId(scene.RouteId); RuntimeId = IdFactory.NextEntityId(scene.RouteId);
#else #else
@@ -546,7 +547,6 @@ namespace TEngine
foreach (var entity in _treeDb) foreach (var entity in _treeDb)
{ {
entity.Parent = this; entity.Parent = this;
entity.Scene = scene;
entity.Deserialize(scene, resetId); entity.Deserialize(scene, resetId);
_tree.Add(entity.GetType(), entity); _tree.Add(entity.GetType(), entity);
} }
@@ -558,7 +558,6 @@ namespace TEngine
foreach (var entity in _multiDb) foreach (var entity in _multiDb)
{ {
entity.Parent = this; entity.Parent = this;
entity.Scene = scene;
entity.Deserialize(scene, resetId); entity.Deserialize(scene, resetId);
_multi.Add(entity.Id, (ISupportedMultiEntity)entity); _multi.Add(entity.Id, (ISupportedMultiEntity)entity);
} }

View File

@@ -217,7 +217,7 @@ namespace TEngine
StringBuilder infoBuilder = GetFormatString(type, logString); StringBuilder infoBuilder = GetFormatString(type, logString);
if (type == LogLevel.ERROR || type == LogLevel.WARNING || type == LogLevel.EXCEPTION) if (type == LogLevel.ERROR || type == LogLevel.EXCEPTION)
{ {
StackFrame[] sf = new StackTrace().GetFrames(); StackFrame[] sf = new StackTrace().GetFrames();
for (int i = 0; i < sf.Length; i++) for (int i = 0; i < sf.Length; i++)

View File

@@ -26,6 +26,7 @@ namespace TEngine.Logic
{ {
_session = (Session)Parent; _session = (Session)Parent;
_selfRunTimeId = RuntimeId; _selfRunTimeId = RuntimeId;
RepeatedSend().Coroutine();
_timerId = TimerScheduler.Instance.Unity.RepeatedTimer(interval, () => RepeatedSend().Coroutine()); _timerId = TimerScheduler.Instance.Unity.RepeatedTimer(interval, () => RepeatedSend().Coroutine());
} }
@@ -57,6 +58,7 @@ namespace TEngine.Logic
var responseTime = TimeHelper.Now; var responseTime = TimeHelper.Now;
Ping = (int)(responseTime - requestTime) / 2; Ping = (int)(responseTime - requestTime) / 2;
TimeHelper.TimeDiff = pingResponse.Now + Ping - responseTime; TimeHelper.TimeDiff = pingResponse.Now + Ping - responseTime;
Log.Info("----------- HeartBeat -----------");
} }
} }
} }

View File

@@ -1,50 +1,26 @@
#pragma warning disable CS8603
#pragma warning disable CS8600
#if TENGINE_NET #if TENGINE_NET
namespace TEngine.Core.Network; namespace TEngine.Core.Network;
public sealed class AddressableRouteComponentAwakeSystem : AwakeSystem<AddressableRouteComponent>
{
protected override void Awake(AddressableRouteComponent self)
{
self.Awake();
}
}
/// <summary> /// <summary>
/// 可寻址消息组件、挂载了这个组件可以接收和发送Addressable消息 /// 可寻址消息组件、挂载了这个组件可以接收和发送Addressable消息
/// </summary> /// </summary>
public sealed class AddressableRouteComponent : Entity public sealed class AddressableRouteComponent : Entity
{ {
private long _parentId; private long _routeId;
private long _addressableRouteId; private long _addressableId;
public static readonly CoroutineLockQueueType AddressableRouteMessageLock = new CoroutineLockQueueType("AddressableRouteMessageLock"); public static readonly CoroutineLockQueueType AddressableRouteMessageLock = new CoroutineLockQueueType("AddressableRouteMessageLock");
public override void Dispose() public override void Dispose()
{ {
_parentId = 0; _routeId = 0;
_addressableRouteId = 0; _addressableId = 0;
base.Dispose(); base.Dispose();
} }
public void Awake() public void SetAddressableId(long addressableId)
{ {
if (Parent == null) _addressableId = addressableId;
{
throw new Exception("AddressableRouteComponent must be mounted under a component");
}
if (Parent.RuntimeId == 0)
{
throw new Exception("AddressableRouteComponent.Parent.RuntimeId is null");
}
_parentId = Parent.Id;
}
public void SetAddressableRouteId(long addressableRouteId)
{
_addressableRouteId = addressableRouteId;
} }
public void Send(IAddressableRouteMessage message) public void Send(IAddressableRouteMessage message)
@@ -68,21 +44,21 @@ public sealed class AddressableRouteComponent : Entity
var runtimeId = RuntimeId; var runtimeId = RuntimeId;
IResponse iRouteResponse = null; IResponse iRouteResponse = null;
using (await AddressableRouteMessageLock.Lock(_parentId, "AddressableRouteComponent Call MemoryStream")) using (await AddressableRouteMessageLock.Lock(_addressableId, "AddressableRouteComponent Call MemoryStream"))
{ {
while (!IsDisposed) while (!IsDisposed)
{ {
if (_addressableRouteId == 0) if (_routeId == 0)
{ {
_addressableRouteId = await AddressableHelper.GetAddressableRouteId(Scene, _parentId); _routeId = await AddressableHelper.GetAddressableRouteId(Scene, _addressableId);
} }
if (_addressableRouteId == 0) if (_routeId == 0)
{ {
return MessageDispatcherSystem.Instance.CreateResponse(requestType, CoreErrorCode.ErrNotFoundRoute); return MessageDispatcherSystem.Instance.CreateResponse(requestType, CoreErrorCode.ErrNotFoundRoute);
} }
iRouteResponse = await MessageHelper.CallInnerRoute(Scene, _addressableRouteId, routeTypeOpCode, requestType, request); iRouteResponse = await MessageHelper.CallInnerRoute(Scene, _routeId, routeTypeOpCode, requestType, request);
if (runtimeId != RuntimeId) if (runtimeId != RuntimeId)
{ {
@@ -99,7 +75,7 @@ public sealed class AddressableRouteComponent : Entity
{ {
if (++failCount > 20) if (++failCount > 20)
{ {
Log.Error($"AddressableComponent.Call failCount > 20 route send message fail, routeId: {_addressableRouteId} AddressableRouteComponent:{Id}"); Log.Error($"AddressableComponent.Call failCount > 20 route send message fail, routeId: {_routeId} AddressableRouteComponent:{Id}");
return iRouteResponse; return iRouteResponse;
} }
@@ -110,7 +86,7 @@ public sealed class AddressableRouteComponent : Entity
iRouteResponse.ErrorCode = CoreErrorCode.ErrRouteTimeout; iRouteResponse.ErrorCode = CoreErrorCode.ErrRouteTimeout;
} }
_addressableRouteId = 0; _routeId = 0;
continue; continue;
} }
default: default:
@@ -134,21 +110,21 @@ public sealed class AddressableRouteComponent : Entity
var failCount = 0; var failCount = 0;
var runtimeId = RuntimeId; var runtimeId = RuntimeId;
using (await AddressableRouteMessageLock.Lock(_parentId,"AddressableRouteComponent Call")) using (await AddressableRouteMessageLock.Lock(_addressableId,"AddressableRouteComponent Call"))
{ {
while (true) while (true)
{ {
if (_addressableRouteId == 0) if (_routeId == 0)
{ {
_addressableRouteId = await AddressableHelper.GetAddressableRouteId(Scene, _parentId); _routeId = await AddressableHelper.GetAddressableRouteId(Scene, _addressableId);
} }
if (_addressableRouteId == 0) if (_routeId == 0)
{ {
return MessageDispatcherSystem.Instance.CreateResponse(request, CoreErrorCode.ErrNotFoundRoute); return MessageDispatcherSystem.Instance.CreateResponse(request, CoreErrorCode.ErrNotFoundRoute);
} }
var iRouteResponse = await MessageHelper.CallInnerRoute(Scene, _addressableRouteId, request); var iRouteResponse = await MessageHelper.CallInnerRoute(Scene, _routeId, request);
if (runtimeId != RuntimeId) if (runtimeId != RuntimeId)
{ {
@@ -161,7 +137,7 @@ public sealed class AddressableRouteComponent : Entity
{ {
if (++failCount > 20) if (++failCount > 20)
{ {
Log.Error($"AddressableRouteComponent.Call failCount > 20 route send message fail, routeId: {_addressableRouteId} AddressableRouteComponent:{Id}"); Log.Error($"AddressableRouteComponent.Call failCount > 20 route send message fail, routeId: {_routeId} AddressableRouteComponent:{Id}");
return iRouteResponse; return iRouteResponse;
} }
@@ -172,7 +148,7 @@ public sealed class AddressableRouteComponent : Entity
iRouteResponse.ErrorCode = CoreErrorCode.ErrRouteTimeout; iRouteResponse.ErrorCode = CoreErrorCode.ErrRouteTimeout;
} }
_addressableRouteId = 0; _routeId = 0;
continue; continue;
} }
case CoreErrorCode.ErrRouteTimeout: case CoreErrorCode.ErrRouteTimeout:

View File

@@ -144,7 +144,7 @@ namespace TEngine.Core.Network
scene = entity.Scene; scene = entity.Scene;
} }
Log.Error($"SceneWorld:{session.Scene.World.Id} SceneRouteId:{scene.RouteId} SceneType:{scene.SceneInfo.SceneType} EntityId {tEntity.Id} : Error {e}"); Log.Error($"SceneWorld:{session.Scene.World?.Id} SceneRouteId:{scene.RouteId} SceneType:{scene.SceneInfo.SceneType} EntityId {tEntity.Id} : Error {e}");
} }
finally finally
{ {

View File

@@ -75,7 +75,7 @@ namespace TEngine.Demo
private void OnConnectComplete() private void OnConnectComplete()
{ {
IsConnect = true; IsConnect = true;
Scene.Session.AddComponent<SessionHeartbeatComponent>().Start(15); Scene.Session.AddComponent<SessionHeartbeatComponent>().Start(15000);
LogDebug("已连接到服务器"); LogDebug("已连接到服务器");
} }

View File

@@ -25,8 +25,3 @@ catch (Exception e)
{ {
Log.Error(e); Log.Error(e);
} }

View File

@@ -3,10 +3,10 @@ package Sining.Message;
/// Gate跟Map服务器进行通讯、注册Address协议 /// Gate跟Map服务器进行通讯、注册Address协议
message I_G2M_LoginAddressRequest // IRouteRequest,I_M2G_LoginAddressResponse message I_G2M_LoginAddressRequest // IRouteRequest,I_M2G_LoginAddressResponse
{ {
long AddressId = 1; // 用来关联Address的Id,一般是账号Id或UnitId这些不会变动的 long AddressableId = 1; // 用来关联Address的Id,一般是账号Id或UnitId这些不会变动的
long GateRouteId = 2; // Gate的RouteIdId用于Map发送给客户端时需要 long GateRouteId = 2; // Gate的RouteIdId用于Map发送给客户端时需要
} }
message I_M2G_LoginAddressResponse // IRouteResponse message I_M2G_LoginAddressResponse // IRouteResponse
{ {
long AddressableId = 1;
} }

View File

@@ -17,7 +17,7 @@ namespace TEngine
public uint OpCode() { return InnerOpcode.I_G2M_LoginAddressRequest; } public uint OpCode() { return InnerOpcode.I_G2M_LoginAddressRequest; }
public long RouteTypeOpCode() { return CoreRouteType.Route; } public long RouteTypeOpCode() { return CoreRouteType.Route; }
[ProtoMember(1)] [ProtoMember(1)]
public long AddressId { get; set; } public long AddressableId { get; set; }
[ProtoMember(2)] [ProtoMember(2)]
public long GateRouteId { get; set; } public long GateRouteId { get; set; }
} }
@@ -27,5 +27,7 @@ namespace TEngine
public uint OpCode() { return InnerOpcode.I_M2G_LoginAddressResponse; } public uint OpCode() { return InnerOpcode.I_M2G_LoginAddressResponse; }
[ProtoMember(91, IsRequired = true)] [ProtoMember(91, IsRequired = true)]
public uint ErrorCode { get; set; } public uint ErrorCode { get; set; }
[ProtoMember(1)]
public long AddressableId { get; set; }
} }
} }

View File

@@ -24,14 +24,14 @@ public class H_C2G_LoginAddressRequestHandler : MessageRPC<H_C2G_LoginAddressReq
// 1、首选分配一个可用、负载比较低的服务器给这个Unit、我这里就在ServerConfig.xsl表里拿一个MAP了、但实际开发过程可能比这个要复杂 // 1、首选分配一个可用、负载比较低的服务器给这个Unit、我这里就在ServerConfig.xsl表里拿一个MAP了、但实际开发过程可能比这个要复杂
// 我这里就简单些一个做为演示、其实这些逻辑开发者完全可以自己封装一个接口来做。 // 我这里就简单些一个做为演示、其实这些逻辑开发者完全可以自己封装一个接口来做。
// 在ServerConfig.xsl里找到MAP的进程、看到ID是3072通过这个Id在SceneConfig.xsl里找到对应的Scene的EntityId // 在ServerConfig.xsl里找到MAP的进程、看到ID是3072通过这个Id在SceneConfig.xsl里找到对应的Scene的EntityId
var sceneEntityId = Helper.AddressableSceneHelper.GetSceneEntityIdByRouteId(3072); var sceneEntityId = Helper.AddressableSceneHelper.GetSceneEntityId();
// 2、在InnerMessage里定义一个协议、用于Gate跟Map通讯的协议I_G2M_LoginAddress // 2、在InnerMessage里定义一个协议、用于Gate跟Map通讯的协议I_G2M_LoginAddress
var loginAddressResponse = (I_M2G_LoginAddressResponse)await MessageHelper.CallInnerRoute(session.Scene, var loginAddressResponse = (I_M2G_LoginAddressResponse)await MessageHelper.CallInnerRoute(session.Scene,
sceneEntityId, sceneEntityId,
new I_G2M_LoginAddressRequest() new I_G2M_LoginAddressRequest()
{ {
AddressId = session.Id, AddressableId = session.Id,
GateRouteId = session.RuntimeId, GateRouteId = session.RuntimeId,
}); });
if (loginAddressResponse.ErrorCode != 0) if (loginAddressResponse.ErrorCode != 0)
@@ -40,7 +40,7 @@ public class H_C2G_LoginAddressRequestHandler : MessageRPC<H_C2G_LoginAddressReq
return; return;
} }
// 3、可寻址消息组件、挂载了这个组件可以接收和发送Addressable消息 // 3、可寻址消息组件、挂载了这个组件可以接收和发送Addressable消息
session.AddComponent<AddressableRouteComponent>(); session.AddComponent<AddressableRouteComponent>().SetAddressableId(loginAddressResponse.AddressableId);
} }
} }
#endif #endif

View File

@@ -36,10 +36,10 @@ namespace TEngine.Logic
// 一般这个信息是数据库里拿到或者其他服务器给传递过来了、这里主要演示怎么注册Address、所以这些步骤这里就不做了 // 一般这个信息是数据库里拿到或者其他服务器给传递过来了、这里主要演示怎么注册Address、所以这些步骤这里就不做了
// 这里我就模拟一个假的Unit数据使用 // 这里我就模拟一个假的Unit数据使用
// 1、首先创建一个Unit // 1、首先创建一个Unit
var unit = AddressManage.Add(scene, request.AddressId, request.GateRouteId); var unit = AddressManage.Add(scene, request.AddressableId, request.GateRouteId);
// 2、挂在AddressableMessageComponent组件、让这个Unit支持Address、并且会自动注册到网格中 // 2、挂在AddressableMessageComponent组件、让这个Unit支持Address、并且会自动注册到网格中
await unit.AddComponent<AddressableMessageComponent>().Register(); await unit.AddComponent<AddressableMessageComponent>().Register();
await FTask.CompletedTask; response.AddressableId = unit.Id;
} }
} }
} }

View File

@@ -33,10 +33,10 @@ public static class AddressableSceneHelper
return sceneEntityId; return sceneEntityId;
} }
public static long GetSceneEntityIdByRouteId(uint routeId) public static long GetSceneEntityIdBySceneId(uint sceneId)
{ {
var sceneEntityId = 0L; var sceneEntityId = 0L;
var sceneConfig = SceneConfigData.Instance.Get(routeId); var sceneConfig = SceneConfigData.Instance.Get(sceneId);
sceneEntityId = sceneConfig.EntityId; sceneEntityId = sceneConfig.EntityId;
return sceneEntityId; return sceneEntityId;
} }

View File

@@ -0,0 +1,35 @@
namespace TEngine.Helper;
public class GameTickWatcher
{
private long m_startTick = 0;
public GameTickWatcher()
{
Refresh();
}
public void Refresh()
{
m_startTick = DateTime.Now.Ticks;
}
/// <summary>
/// 计算用时。
/// </summary>
/// <returns></returns>
public float ElapseTime()
{
long endTick = DateTime.Now.Ticks;
return (endTick - m_startTick) / 10000f / 1000.0f;
}
/// <summary>
/// 计算用时。
/// </summary>
/// <returns></returns>
public void LogElapseTime(string tag)
{
Console.WriteLine($"计算用时:{tag} 耗时 {this.ElapseTime()}");
}
}