mirror of
https://github.com/Alex-Rachel/TEngine.git
synced 2025-08-14 16:51:28 +00:00
[+] 接入ET8服务端
[+] 接入ET8服务端
This commit is contained in:
8
Assets/GameScripts/DotNet/Hotfix/Client/Demo/AI.meta
Normal file
8
Assets/GameScripts/DotNet/Hotfix/Client/Demo/AI.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d2c1d7db177785844a4b941708d953b9
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
43
Assets/GameScripts/DotNet/Hotfix/Client/Demo/AI/AI_Attack.cs
Normal file
43
Assets/GameScripts/DotNet/Hotfix/Client/Demo/AI/AI_Attack.cs
Normal file
@@ -0,0 +1,43 @@
|
||||
namespace ET.Client
|
||||
{
|
||||
public class AI_Attack: AAIHandler
|
||||
{
|
||||
public override int Check(AIComponent aiComponent, AIConfig aiConfig)
|
||||
{
|
||||
long sec = aiComponent.Fiber().TimeInfo.ClientNow() / 1000 % 15;
|
||||
if (sec >= 10)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
public override async ETTask Execute(AIComponent aiComponent, AIConfig aiConfig, ETCancellationToken cancellationToken)
|
||||
{
|
||||
Fiber fiber = aiComponent.Fiber();
|
||||
|
||||
Unit myUnit = UnitHelper.GetMyUnitFromClientScene(fiber.Root);
|
||||
if (myUnit == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// 停在当前位置
|
||||
fiber.Root.GetComponent<ClientSenderCompnent>().Send(new C2M_Stop());
|
||||
|
||||
Log.Debug("开始攻击");
|
||||
|
||||
for (int i = 0; i < 100000; ++i)
|
||||
{
|
||||
Log.Debug($"攻击: {i}次");
|
||||
|
||||
// 因为协程可能被中断,任何协程都要传入cancellationToken,判断如果是中断则要返回
|
||||
await fiber.TimerComponent.WaitAsync(1000, cancellationToken);
|
||||
if (cancellationToken.IsCancel())
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: de532cb8e5e687a4bb61aa666459d086
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
42
Assets/GameScripts/DotNet/Hotfix/Client/Demo/AI/AI_XunLuo.cs
Normal file
42
Assets/GameScripts/DotNet/Hotfix/Client/Demo/AI/AI_XunLuo.cs
Normal file
@@ -0,0 +1,42 @@
|
||||
using Unity.Mathematics;
|
||||
|
||||
namespace ET.Client
|
||||
{
|
||||
public class AI_XunLuo: AAIHandler
|
||||
{
|
||||
public override int Check(AIComponent aiComponent, AIConfig aiConfig)
|
||||
{
|
||||
long sec = aiComponent.Fiber().TimeInfo.ClientNow() / 1000 % 15;
|
||||
if (sec < 10)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
public override async ETTask Execute(AIComponent aiComponent, AIConfig aiConfig, ETCancellationToken cancellationToken)
|
||||
{
|
||||
Scene root = aiComponent.Root();
|
||||
|
||||
Unit myUnit = UnitHelper.GetMyUnitFromClientScene(root);
|
||||
if (myUnit == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Log.Debug("开始巡逻");
|
||||
|
||||
while (true)
|
||||
{
|
||||
XunLuoPathComponent xunLuoPathComponent = myUnit.GetComponent<XunLuoPathComponent>();
|
||||
float3 nextTarget = xunLuoPathComponent.GetCurrent();
|
||||
await myUnit.MoveToAsync(nextTarget, cancellationToken);
|
||||
if (cancellationToken.IsCancel())
|
||||
{
|
||||
return;
|
||||
}
|
||||
xunLuoPathComponent.MoveNext();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4d77ea7dfe040894aa330386e3b7bb8f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,18 @@
|
||||
using Unity.Mathematics;
|
||||
|
||||
namespace ET.Client
|
||||
{
|
||||
[FriendOf(typeof(XunLuoPathComponent))]
|
||||
public static partial class XunLuoPathComponentSystem
|
||||
{
|
||||
public static float3 GetCurrent(this XunLuoPathComponent self)
|
||||
{
|
||||
return self.path[self.Index];
|
||||
}
|
||||
|
||||
public static void MoveNext(this XunLuoPathComponent self)
|
||||
{
|
||||
self.Index = ++self.Index % self.path.Length;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4293e004a928ffb43bf52f374808d139
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
3
Assets/GameScripts/DotNet/Hotfix/Client/Demo/Main.meta
Normal file
3
Assets/GameScripts/DotNet/Hotfix/Client/Demo/Main.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2e5141370ec84e1282c5d0a38f2ef25b
|
||||
timeCreated: 1688537612
|
@@ -0,0 +1,47 @@
|
||||
namespace ET.Client
|
||||
{
|
||||
[EntitySystemOf(typeof(ClientSenderCompnent))]
|
||||
[FriendOf(typeof(ClientSenderCompnent))]
|
||||
public static partial class ClientSenderCompnentSystem
|
||||
{
|
||||
[EntitySystem]
|
||||
private static void Awake(this ClientSenderCompnent self)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
[EntitySystem]
|
||||
private static void Destroy(this ClientSenderCompnent self)
|
||||
{
|
||||
if (self.fiberId != 0)
|
||||
{
|
||||
FiberManager.Instance.Remove(self.fiberId);
|
||||
}
|
||||
}
|
||||
|
||||
public static async ETTask<long> LoginAsync(this ClientSenderCompnent self, string account, string password)
|
||||
{
|
||||
self.fiberId = await FiberManager.Instance.Create(SchedulerType.ThreadPool, 0, SceneType.NetClient, "");
|
||||
self.netClientActorId = new ActorId(self.Fiber().Process, self.fiberId);
|
||||
|
||||
NetClient2Main_Login response = await self.Fiber().ActorInnerComponent.Call(self.netClientActorId, new Main2NetClient_Login() { Account = account, Password = password }) as NetClient2Main_Login;
|
||||
return response.PlayerId;
|
||||
}
|
||||
|
||||
public static void Send(this ClientSenderCompnent self, IMessage message)
|
||||
{
|
||||
A2NetClient_Message a2NetClientMessage = A2NetClient_Message.Create();
|
||||
a2NetClientMessage.MessageObject = message;
|
||||
self.Fiber().ActorInnerComponent.Send(self.netClientActorId, a2NetClientMessage);
|
||||
}
|
||||
|
||||
public static async ETTask<IResponse> Call(this ClientSenderCompnent self, IRequest request, bool needException = true)
|
||||
{
|
||||
A2NetClient_Request a2NetClientRequest = A2NetClient_Request.Create();
|
||||
a2NetClientRequest.MessageObject = request;
|
||||
A2NetClient_Response response = await self.Fiber().ActorInnerComponent.Call(self.netClientActorId, a2NetClientRequest, needException: needException) as A2NetClient_Response;
|
||||
return response.MessageObject;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a11bff036359a2143aca1de23150ce40
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c38213e2fca6b8b489ffb3fee170c51f
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,37 @@
|
||||
using System;
|
||||
|
||||
|
||||
namespace ET.Client
|
||||
{
|
||||
public static partial class EnterMapHelper
|
||||
{
|
||||
public static async ETTask EnterMapAsync(Scene root)
|
||||
{
|
||||
try
|
||||
{
|
||||
G2C_EnterMap g2CEnterMap = await root.GetComponent<ClientSenderCompnent>().Call(new C2G_EnterMap()) as G2C_EnterMap;
|
||||
|
||||
// 等待场景切换完成
|
||||
await root.GetComponent<ObjectWait>().Wait<Wait_SceneChangeFinish>();
|
||||
|
||||
EventSystem.Instance.Publish(root, new EventType.EnterMapFinish());
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Error(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static async ETTask Match(Fiber fiber)
|
||||
{
|
||||
try
|
||||
{
|
||||
G2C_Match g2CEnterMap = await fiber.Root.GetComponent<ClientSenderCompnent>().Call(new C2G_Match()) as G2C_Match;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 25a13c7e1f3127848a33352576e747c9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0e5f376ea66398e4f8d5fc5d700b4373
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,15 @@
|
||||
namespace ET.Client
|
||||
{
|
||||
[ActorMessageHandler(SceneType.Demo)]
|
||||
public class M2C_PathfindingResultHandler : ActorMessageHandler<Scene, M2C_PathfindingResult>
|
||||
{
|
||||
protected override async ETTask Run(Scene root, M2C_PathfindingResult message)
|
||||
{
|
||||
Unit unit = root.CurrentScene().GetComponent<UnitComponent>().Get(message.Id);
|
||||
|
||||
float speed = unit.GetComponent<NumericComponent>().GetAsFloat(NumericType.Speed);
|
||||
|
||||
await unit.GetComponent<MoveComponent>().MoveToAsync(message.Points, speed);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 46ac4bf2b7bf6ea468ccbfbf09367733
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,24 @@
|
||||
using Unity.Mathematics;
|
||||
|
||||
namespace ET.Client
|
||||
{
|
||||
[ActorMessageHandler(SceneType.Demo)]
|
||||
public class M2C_StopHandler : ActorMessageHandler<Scene, M2C_Stop>
|
||||
{
|
||||
protected override async ETTask Run(Scene root, M2C_Stop message)
|
||||
{
|
||||
Unit unit = root.CurrentScene().GetComponent<UnitComponent>().Get(message.Id);
|
||||
if (unit == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
MoveComponent moveComponent = unit.GetComponent<MoveComponent>();
|
||||
moveComponent.Stop(message.Error == 0);
|
||||
unit.Position = message.Position;
|
||||
unit.Rotation = message.Rotation;
|
||||
unit.GetComponent<ObjectWait>()?.Notify(new Wait_UnitStop() {Error = message.Error});
|
||||
await ETTask.CompletedTask;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: eb3ae6bd37192c648b88723824beaaa7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,36 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Numerics;
|
||||
using Unity.Mathematics;
|
||||
|
||||
namespace ET.Client
|
||||
{
|
||||
public static partial class MoveHelper
|
||||
{
|
||||
// 可以多次调用,多次调用的话会取消上一次的协程
|
||||
public static async ETTask<int> MoveToAsync(this Unit unit, float3 targetPos, ETCancellationToken cancellationToken = null)
|
||||
{
|
||||
C2M_PathfindingResult msg = new C2M_PathfindingResult() { Position = targetPos };
|
||||
unit.Root().GetComponent<ClientSenderCompnent>().Send(msg);
|
||||
|
||||
ObjectWait objectWait = unit.GetComponent<ObjectWait>();
|
||||
|
||||
// 要取消上一次的移动协程
|
||||
objectWait.Notify(new Wait_UnitStop() { Error = WaitTypeError.Cancel });
|
||||
|
||||
// 一直等到unit发送stop
|
||||
Wait_UnitStop waitUnitStop = await objectWait.Wait<Wait_UnitStop>(cancellationToken);
|
||||
if (cancellationToken.IsCancel())
|
||||
{
|
||||
return WaitTypeError.Cancel;
|
||||
}
|
||||
return waitUnitStop.Error;
|
||||
}
|
||||
|
||||
public static async ETTask MoveToAsync(this Unit unit, List<float3> path)
|
||||
{
|
||||
float speed = unit.GetComponent<NumericComponent>().GetAsFloat(NumericType.Speed);
|
||||
MoveComponent moveComponent = unit.GetComponent<MoveComponent>();
|
||||
await moveComponent.MoveToAsync(path, speed);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9517a733443387b49a227cfb10aa82d6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,12 @@
|
||||
namespace ET.Client
|
||||
{
|
||||
[ActorMessageHandler(SceneType.All)]
|
||||
public class NetClient2Main_SessionDisposeHandler: ActorMessageHandler<Scene, NetClient2Main_SessionDispose>
|
||||
{
|
||||
protected override async ETTask Run(Scene entity, NetClient2Main_SessionDispose message)
|
||||
{
|
||||
Log.Error($"session dispose, error: {message.Error}");
|
||||
await ETTask.CompletedTask;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9fbd99f39ddd82042af56cdbf9ce8dc3
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0d507c6bfa0e3424380311d17689451c
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,14 @@
|
||||
namespace ET.Client
|
||||
{
|
||||
public static class CurrentSceneFactory
|
||||
{
|
||||
public static Scene Create(long id, string name, CurrentScenesComponent currentScenesComponent)
|
||||
{
|
||||
Scene currentScene = EntitySceneFactory.CreateScene(currentScenesComponent, id, currentScenesComponent.Fiber().IdGenerater.GenerateInstanceId(), SceneType.Current, name);
|
||||
currentScenesComponent.Scene = currentScene;
|
||||
|
||||
EventSystem.Instance.Publish(currentScene, new EventType.AfterCreateCurrentScene());
|
||||
return currentScene;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d7e7628945100a44193d11f6c86856fb
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,11 @@
|
||||
namespace ET.Client
|
||||
{
|
||||
[ActorMessageHandler(SceneType.Demo)]
|
||||
public class M2C_StartSceneChangeHandler : ActorMessageHandler<Scene, M2C_StartSceneChange>
|
||||
{
|
||||
protected override async ETTask Run(Scene root, M2C_StartSceneChange message)
|
||||
{
|
||||
await SceneChangeHelper.SceneChangeTo(root, message.SceneName, message.SceneInstanceId);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5ba66d6939e13bc47b59fe326cac0526
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,29 @@
|
||||
namespace ET.Client
|
||||
{
|
||||
public static partial class SceneChangeHelper
|
||||
{
|
||||
// 场景切换协程
|
||||
public static async ETTask SceneChangeTo(Scene root, string sceneName, long sceneInstanceId)
|
||||
{
|
||||
root.RemoveComponent<AIComponent>();
|
||||
|
||||
CurrentScenesComponent currentScenesComponent = root.GetComponent<CurrentScenesComponent>();
|
||||
currentScenesComponent.Scene?.Dispose(); // 删除之前的CurrentScene,创建新的
|
||||
Scene currentScene = CurrentSceneFactory.Create(sceneInstanceId, sceneName, currentScenesComponent);
|
||||
UnitComponent unitComponent = currentScene.AddComponent<UnitComponent>();
|
||||
|
||||
// 可以订阅这个事件中创建Loading界面
|
||||
EventSystem.Instance.Publish(root, new EventType.SceneChangeStart());
|
||||
// 等待CreateMyUnit的消息
|
||||
Wait_CreateMyUnit waitCreateMyUnit = await root.GetComponent<ObjectWait>().Wait<Wait_CreateMyUnit>();
|
||||
M2C_CreateMyUnit m2CCreateMyUnit = waitCreateMyUnit.Message;
|
||||
Unit unit = UnitFactory.Create(currentScene, m2CCreateMyUnit.Unit);
|
||||
unitComponent.Add(unit);
|
||||
root.RemoveComponent<AIComponent>();
|
||||
|
||||
EventSystem.Instance.Publish(currentScene, new EventType.SceneChangeFinish());
|
||||
// 通知等待场景切换的协程
|
||||
root.GetComponent<ObjectWait>().Notify(new Wait_SceneChangeFinish());
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: eff9697e3de79f54dbfd7996f55c6f47
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b99fb42c78388f147beaf9a963a80458
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,13 @@
|
||||
namespace ET.Client
|
||||
{
|
||||
[ActorMessageHandler(SceneType.Demo)]
|
||||
public class M2C_CreateMyUnitHandler: ActorMessageHandler<Scene, M2C_CreateMyUnit>
|
||||
{
|
||||
protected override async ETTask Run(Scene root, M2C_CreateMyUnit message)
|
||||
{
|
||||
// 通知场景切换协程继续往下走
|
||||
root.GetComponent<ObjectWait>().Notify(new Wait_CreateMyUnit() {Message = message});
|
||||
await ETTask.CompletedTask;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 69fc464a314f79d46922ca7c44dad617
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,22 @@
|
||||
namespace ET.Client
|
||||
{
|
||||
[ActorMessageHandler(SceneType.Demo)]
|
||||
public class M2C_CreateUnitsHandler: ActorMessageHandler<Scene, M2C_CreateUnits>
|
||||
{
|
||||
protected override async ETTask Run(Scene root, M2C_CreateUnits message)
|
||||
{
|
||||
Scene currentScene = root.CurrentScene();
|
||||
UnitComponent unitComponent = currentScene.GetComponent<UnitComponent>();
|
||||
|
||||
foreach (UnitInfo unitInfo in message.Units)
|
||||
{
|
||||
if (unitComponent.Get(unitInfo.UnitId) != null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
Unit unit = UnitFactory.Create(currentScene, unitInfo);
|
||||
}
|
||||
await ETTask.CompletedTask;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0b8fc07def7b312469c243c3ccad1b39
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,21 @@
|
||||
namespace ET.Client
|
||||
{
|
||||
[ActorMessageHandler(SceneType.Demo)]
|
||||
public class M2C_RemoveUnitsHandler: ActorMessageHandler<Scene, M2C_RemoveUnits>
|
||||
{
|
||||
protected override async ETTask Run(Scene root, M2C_RemoveUnits message)
|
||||
{
|
||||
UnitComponent unitComponent = root.CurrentScene()?.GetComponent<UnitComponent>();
|
||||
if (unitComponent == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
foreach (long unitId in message.Units)
|
||||
{
|
||||
unitComponent.Remove(unitId);
|
||||
}
|
||||
|
||||
await ETTask.CompletedTask;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6c4d413c1206d8844b7f6ccc95dd2ce6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,41 @@
|
||||
using Unity.Mathematics;
|
||||
|
||||
namespace ET.Client
|
||||
{
|
||||
public static partial class UnitFactory
|
||||
{
|
||||
public static Unit Create(Scene currentScene, UnitInfo unitInfo)
|
||||
{
|
||||
UnitComponent unitComponent = currentScene.GetComponent<UnitComponent>();
|
||||
Unit unit = unitComponent.AddChildWithId<Unit, int>(unitInfo.UnitId, unitInfo.ConfigId);
|
||||
unitComponent.Add(unit);
|
||||
|
||||
unit.Position = unitInfo.Position;
|
||||
unit.Forward = unitInfo.Forward;
|
||||
|
||||
NumericComponent numericComponent = unit.AddComponent<NumericComponent>();
|
||||
|
||||
foreach (var kv in unitInfo.KV)
|
||||
{
|
||||
numericComponent.Set(kv.Key, kv.Value);
|
||||
}
|
||||
|
||||
unit.AddComponent<MoveComponent>();
|
||||
if (unitInfo.MoveInfo != null)
|
||||
{
|
||||
if (unitInfo.MoveInfo.Points.Count > 0)
|
||||
{
|
||||
unitInfo.MoveInfo.Points[0] = unit.Position;
|
||||
unit.MoveToAsync(unitInfo.MoveInfo.Points).Coroutine();
|
||||
}
|
||||
}
|
||||
|
||||
unit.AddComponent<ObjectWait>();
|
||||
|
||||
unit.AddComponent<XunLuoPathComponent>();
|
||||
|
||||
EventSystem.Instance.Publish(unit.Scene(), new EventType.AfterUnitCreate() {Unit = unit});
|
||||
return unit;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f76a73cf5e806e9499c3eb92aeeb46d2
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,18 @@
|
||||
namespace ET.Client
|
||||
{
|
||||
public static partial class UnitHelper
|
||||
{
|
||||
public static Unit GetMyUnitFromClientScene(Scene root)
|
||||
{
|
||||
PlayerComponent playerComponent = root.GetComponent<PlayerComponent>();
|
||||
Scene currentScene = root.GetComponent<CurrentScenesComponent>().Scene;
|
||||
return currentScene.GetComponent<UnitComponent>().Get(playerComponent.MyId);
|
||||
}
|
||||
|
||||
public static Unit GetMyUnitFromCurrentScene(Scene currentScene)
|
||||
{
|
||||
PlayerComponent playerComponent = currentScene.Root().GetComponent<PlayerComponent>();
|
||||
return currentScene.GetComponent<UnitComponent>().Get(playerComponent.MyId);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 90e53c0be7b8aab4c827ed76d193ca42
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b9016545e3eb60946afce20928d2d34b
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,12 @@
|
||||
namespace ET.Client
|
||||
{
|
||||
[ActorMessageHandler(SceneType.NetClient)]
|
||||
public class A2NetClient_MessageHandler: ActorMessageHandler<Scene, A2NetClient_Message>
|
||||
{
|
||||
protected override async ETTask Run(Scene root, A2NetClient_Message message)
|
||||
{
|
||||
root.GetComponent<SessionComponent>().Session.Send(message.MessageObject);
|
||||
await ETTask.CompletedTask;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0f70391ff9eb499db68bae992a9c85b6
|
||||
timeCreated: 1688540041
|
@@ -0,0 +1,11 @@
|
||||
namespace ET.Client
|
||||
{
|
||||
[ActorMessageHandler(SceneType.NetClient)]
|
||||
public class A2NetClient_RequestHandler: ActorMessageHandler<Scene, A2NetClient_Request, A2NetClient_Response>
|
||||
{
|
||||
protected override async ETTask Run(Scene root, A2NetClient_Request request, A2NetClient_Response response)
|
||||
{
|
||||
response.MessageObject = await root.GetComponent<SessionComponent>().Session.Call(request.MessageObject);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f3ac2d21dada4f2b8b51b26e0efe891e
|
||||
timeCreated: 1688540239
|
@@ -0,0 +1,16 @@
|
||||
namespace ET.Client
|
||||
{
|
||||
[Invoke((long)SceneType.NetClient)]
|
||||
public class FiberInit_NetClient: AInvokeHandler<FiberInit, ETTask>
|
||||
{
|
||||
public override async ETTask Handle(FiberInit fiberInit)
|
||||
{
|
||||
Scene root = fiberInit.Fiber.Root;
|
||||
root.AddComponent<MailBoxComponent, MailBoxType>(MailBoxType.UnOrderedMessage);
|
||||
root.AddComponent<TimerComponent>();
|
||||
root.AddComponent<CoroutineLockComponent>();
|
||||
root.AddComponent<ActorInnerComponent>();
|
||||
await ETTask.CompletedTask;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: dee733932d1381941bc0496fc337341a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,17 @@
|
||||
namespace ET.Client
|
||||
{
|
||||
public static class LoginHelper
|
||||
{
|
||||
public static async ETTask Login(Scene root, string account, string password)
|
||||
{
|
||||
root.RemoveComponent<ClientSenderCompnent>();
|
||||
ClientSenderCompnent clientSenderCompnent = root.AddComponent<ClientSenderCompnent>();
|
||||
|
||||
long playerId = await clientSenderCompnent.LoginAsync(account, password);
|
||||
|
||||
root.GetComponent<PlayerComponent>().MyId = playerId;
|
||||
|
||||
await EventSystem.Instance.PublishAsync(root, new EventType.LoginFinish());
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5d8c6e9a02dc4ab41ad32d56d9594354
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,43 @@
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
|
||||
namespace ET.Client
|
||||
{
|
||||
[ActorMessageHandler(SceneType.NetClient)]
|
||||
public class Main2NetClient_LoginHandler: ActorMessageHandler<Scene, Main2NetClient_Login, NetClient2Main_Login>
|
||||
{
|
||||
protected override async ETTask Run(Scene root, Main2NetClient_Login request, NetClient2Main_Login response)
|
||||
{
|
||||
string account = request.Account;
|
||||
string password = request.Password;
|
||||
// 创建一个ETModel层的Session
|
||||
root.RemoveComponent<RouterAddressComponent>();
|
||||
// 获取路由跟realmDispatcher地址
|
||||
RouterAddressComponent routerAddressComponent = root.GetComponent<RouterAddressComponent>();
|
||||
if (routerAddressComponent == null)
|
||||
{
|
||||
routerAddressComponent =
|
||||
root.AddComponent<RouterAddressComponent, string, int>(ConstValue.RouterHttpHost, ConstValue.RouterHttpPort);
|
||||
await routerAddressComponent.Init();
|
||||
root.AddComponent<NetClientComponent, AddressFamily>(routerAddressComponent.RouterManagerIPAddress.AddressFamily);
|
||||
}
|
||||
IPEndPoint realmAddress = routerAddressComponent.GetRealmAddress(account);
|
||||
|
||||
R2C_Login r2CLogin;
|
||||
using (Session session = await RouterHelper.CreateRouterSession(root, realmAddress))
|
||||
{
|
||||
r2CLogin = (R2C_Login)await session.Call(new C2R_Login() { Account = account, Password = password });
|
||||
}
|
||||
|
||||
// 创建一个gate Session,并且保存到SessionComponent中
|
||||
Session gateSession = await RouterHelper.CreateRouterSession(root, NetworkHelper.ToIPEndPoint(r2CLogin.Address));
|
||||
gateSession.AddComponent<ClientSessionErrorComponent>();
|
||||
root.AddComponent<SessionComponent>().Session = gateSession;
|
||||
G2C_LoginGate g2CLoginGate = (G2C_LoginGate)await gateSession.Call(new C2G_LoginGate() { Key = r2CLogin.Key, GateId = r2CLogin.GateId });
|
||||
|
||||
Log.Debug("登陆gate成功!");
|
||||
|
||||
response.PlayerId = g2CLoginGate.PlayerId;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 02d16f101211408496a7e86b273ed882
|
||||
timeCreated: 1688536630
|
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 657f5f7736369e24786203c1c377ec14
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,64 @@
|
||||
using System;
|
||||
|
||||
namespace ET.Client
|
||||
{
|
||||
[EntitySystemOf(typeof(PingComponent))]
|
||||
public static partial class PingComponentSystem
|
||||
{
|
||||
[EntitySystem]
|
||||
private static void Awake(this PingComponent self)
|
||||
{
|
||||
self.PingAsync().Coroutine();
|
||||
}
|
||||
|
||||
[EntitySystem]
|
||||
private static void Destroy(this PingComponent self)
|
||||
{
|
||||
self.Ping = default;
|
||||
}
|
||||
|
||||
private static async ETTask PingAsync(this PingComponent self)
|
||||
{
|
||||
Session session = self.GetParent<Session>();
|
||||
long instanceId = self.InstanceId;
|
||||
Fiber fiber = self.Fiber();
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (self.InstanceId != instanceId)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
long time1 = self.Fiber().TimeInfo.ClientNow();
|
||||
try
|
||||
{
|
||||
C2G_Ping c2GPing = C2G_Ping.Create(true);
|
||||
using G2C_Ping response = await session.Call(c2GPing) as G2C_Ping;
|
||||
|
||||
if (self.InstanceId != instanceId)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
long time2 = self.Fiber().TimeInfo.ClientNow();
|
||||
self.Ping = time2 - time1;
|
||||
|
||||
fiber.TimeInfo.ServerMinusClientTime = response.Time + (time2 - time1) / 2 - time2;
|
||||
|
||||
await fiber.TimerComponent.WaitAsync(2000);
|
||||
}
|
||||
catch (RpcException e)
|
||||
{
|
||||
// session断开导致ping rpc报错,记录一下即可,不需要打成error
|
||||
Log.Info($"ping error: {self.Id} {e.Error}");
|
||||
return;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Error($"ping error: \n{e}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: df3747692b8ee23439aa241d5dcfabdc
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0dd08876e79fc2e4e92db27f7a59b403
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,25 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
|
||||
namespace ET.Client
|
||||
{
|
||||
public static partial class HttpClientHelper
|
||||
{
|
||||
public static async ETTask<string> Get(string link)
|
||||
{
|
||||
try
|
||||
{
|
||||
using HttpClient httpClient = new();
|
||||
HttpResponseMessage response = await httpClient.GetAsync(link);
|
||||
string result = await response.Content.ReadAsStringAsync();
|
||||
return result;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new Exception($"http request fail: {link.Substring(0,link.IndexOf('?'))}\n{e}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4c6ca4a5394922f488127ebb53362456
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,82 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
|
||||
namespace ET.Client
|
||||
{
|
||||
[EntitySystemOf(typeof(RouterAddressComponent))]
|
||||
[FriendOf(typeof(RouterAddressComponent))]
|
||||
public static partial class RouterAddressComponentSystem
|
||||
{
|
||||
[EntitySystem]
|
||||
private static void Awake(this RouterAddressComponent self, string address, int port)
|
||||
{
|
||||
self.RouterManagerHost = address;
|
||||
self.RouterManagerPort = port;
|
||||
}
|
||||
|
||||
public static async ETTask Init(this RouterAddressComponent self)
|
||||
{
|
||||
self.RouterManagerIPAddress = NetworkHelper.GetHostAddress(self.RouterManagerHost);
|
||||
await self.GetAllRouter();
|
||||
}
|
||||
|
||||
private static async ETTask GetAllRouter(this RouterAddressComponent self)
|
||||
{
|
||||
string url = $"http://{self.RouterManagerHost}:{self.RouterManagerPort}/get_router?v={RandomGenerator.RandUInt32()}";
|
||||
Log.Debug($"start get router info: {url}");
|
||||
string routerInfo = await HttpClientHelper.Get(url);
|
||||
Log.Debug($"recv router info: {routerInfo}");
|
||||
HttpGetRouterResponse httpGetRouterResponse = MongoHelper.FromJson<HttpGetRouterResponse>(routerInfo);
|
||||
self.Info = httpGetRouterResponse;
|
||||
Log.Debug($"start get router info finish: {MongoHelper.ToJson(httpGetRouterResponse)}");
|
||||
|
||||
// 打乱顺序
|
||||
RandomGenerator.BreakRank(self.Info.Routers);
|
||||
|
||||
self.WaitTenMinGetAllRouter().Coroutine();
|
||||
}
|
||||
|
||||
// 等10分钟再获取一次
|
||||
public static async ETTask WaitTenMinGetAllRouter(this RouterAddressComponent self)
|
||||
{
|
||||
await self.Fiber().TimerComponent.WaitAsync(5 * 60 * 1000);
|
||||
if (self.IsDisposed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
await self.GetAllRouter();
|
||||
}
|
||||
|
||||
public static IPEndPoint GetAddress(this RouterAddressComponent self)
|
||||
{
|
||||
if (self.Info.Routers.Count == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
string address = self.Info.Routers[self.RouterIndex++ % self.Info.Routers.Count];
|
||||
string[] ss = address.Split(':');
|
||||
IPAddress ipAddress = IPAddress.Parse(ss[0]);
|
||||
if (self.RouterManagerIPAddress.AddressFamily == AddressFamily.InterNetworkV6)
|
||||
{
|
||||
ipAddress = ipAddress.MapToIPv6();
|
||||
}
|
||||
return new IPEndPoint(ipAddress, int.Parse(ss[1]));
|
||||
}
|
||||
|
||||
public static IPEndPoint GetRealmAddress(this RouterAddressComponent self, string account)
|
||||
{
|
||||
int v = account.Mode(self.Info.Realms.Count);
|
||||
string address = self.Info.Realms[v];
|
||||
string[] ss = address.Split(':');
|
||||
IPAddress ipAddress = IPAddress.Parse(ss[0]);
|
||||
//if (self.IPAddress.AddressFamily == AddressFamily.InterNetworkV6)
|
||||
//{
|
||||
// ipAddress = ipAddress.MapToIPv6();
|
||||
//}
|
||||
return new IPEndPoint(ipAddress, int.Parse(ss[1]));
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 567a551c7abf2fd4c9b592af991b609e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,71 @@
|
||||
using System;
|
||||
using System.Net;
|
||||
|
||||
namespace ET.Client
|
||||
{
|
||||
[EntitySystemOf(typeof(RouterCheckComponent))]
|
||||
public static partial class RouterCheckComponentSystem
|
||||
{
|
||||
[EntitySystem]
|
||||
private static void Awake(this RouterCheckComponent self)
|
||||
{
|
||||
self.CheckAsync().Coroutine();
|
||||
}
|
||||
|
||||
private static async ETTask CheckAsync(this RouterCheckComponent self)
|
||||
{
|
||||
Session session = self.GetParent<Session>();
|
||||
long instanceId = self.InstanceId;
|
||||
Fiber fiber = self.Fiber();
|
||||
Scene root = fiber.Root;
|
||||
while (true)
|
||||
{
|
||||
if (self.InstanceId != instanceId)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
await fiber.TimerComponent.WaitAsync(1000);
|
||||
|
||||
if (self.InstanceId != instanceId)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
long time = self.Fiber().TimeInfo.ClientFrameTime();
|
||||
|
||||
if (time - session.LastRecvTime < 7 * 1000)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
long sessionId = session.Id;
|
||||
|
||||
(uint localConn, uint remoteConn) = session.AService.GetChannelConn(sessionId);
|
||||
|
||||
IPEndPoint realAddress = self.GetParent<Session>().RemoteAddress;
|
||||
Log.Info($"get recvLocalConn start: {root.Id} {realAddress} {localConn} {remoteConn}");
|
||||
|
||||
(uint recvLocalConn, IPEndPoint routerAddress) = await RouterHelper.GetRouterAddress(root, realAddress, localConn, remoteConn);
|
||||
if (recvLocalConn == 0)
|
||||
{
|
||||
Log.Error($"get recvLocalConn fail: {root.Id} {routerAddress} {realAddress} {localConn} {remoteConn}");
|
||||
continue;
|
||||
}
|
||||
|
||||
Log.Info($"get recvLocalConn ok: {root.Id} {routerAddress} {realAddress} {recvLocalConn} {localConn} {remoteConn}");
|
||||
|
||||
session.LastRecvTime = self.Fiber().TimeInfo.ClientNow();
|
||||
|
||||
session.AService.ChangeAddress(sessionId, routerAddress);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 55f4125eddb1aa543bfdce8f42b4d5f9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,109 @@
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
|
||||
namespace ET.Client
|
||||
{
|
||||
public static partial class RouterHelper
|
||||
{
|
||||
// 注册router
|
||||
public static async ETTask<Session> CreateRouterSession(Scene root, IPEndPoint address)
|
||||
{
|
||||
(uint recvLocalConn, IPEndPoint routerAddress) = await GetRouterAddress(root, address, 0, 0);
|
||||
|
||||
if (recvLocalConn == 0)
|
||||
{
|
||||
throw new Exception($"get router fail: {root.Id} {address}");
|
||||
}
|
||||
|
||||
Log.Info($"get router: {recvLocalConn} {routerAddress}");
|
||||
|
||||
Session routerSession = root.GetComponent<NetClientComponent>().Create(routerAddress, address, recvLocalConn);
|
||||
routerSession.AddComponent<PingComponent>();
|
||||
routerSession.AddComponent<RouterCheckComponent>();
|
||||
|
||||
return routerSession;
|
||||
}
|
||||
|
||||
public static async ETTask<(uint, IPEndPoint)> GetRouterAddress(Scene root, IPEndPoint address, uint localConn, uint remoteConn)
|
||||
{
|
||||
Log.Info($"start get router address: {root.Id} {address} {localConn} {remoteConn}");
|
||||
//return (RandomHelper.RandUInt32(), address);
|
||||
RouterAddressComponent routerAddressComponent = root.GetComponent<RouterAddressComponent>();
|
||||
IPEndPoint routerInfo = routerAddressComponent.GetAddress();
|
||||
|
||||
uint recvLocalConn = await Connect(root, routerInfo, address, localConn, remoteConn);
|
||||
|
||||
Log.Info($"finish get router address: {root.Id} {address} {localConn} {remoteConn} {recvLocalConn} {routerInfo}");
|
||||
return (recvLocalConn, routerInfo);
|
||||
}
|
||||
|
||||
// 向router申请
|
||||
private static async ETTask<uint> Connect(Scene root, IPEndPoint routerAddress, IPEndPoint realAddress, uint localConn, uint remoteConn)
|
||||
{
|
||||
uint connectId = RandomGenerator.RandUInt32();
|
||||
|
||||
using Socket socket = new Socket(routerAddress.AddressFamily, SocketType.Dgram, ProtocolType.Udp);
|
||||
|
||||
int count = 20;
|
||||
byte[] sendCache = new byte[512];
|
||||
byte[] recvCache = new byte[512];
|
||||
|
||||
uint synFlag = localConn == 0? KcpProtocalType.RouterSYN : KcpProtocalType.RouterReconnectSYN;
|
||||
sendCache.WriteTo(0, synFlag);
|
||||
sendCache.WriteTo(1, localConn);
|
||||
sendCache.WriteTo(5, remoteConn);
|
||||
sendCache.WriteTo(9, connectId);
|
||||
byte[] addressBytes = realAddress.ToString().ToByteArray();
|
||||
Array.Copy(addressBytes, 0, sendCache, 13, addressBytes.Length);
|
||||
|
||||
Log.Info($"router connect: {connectId} {localConn} {remoteConn} {routerAddress} {realAddress}");
|
||||
|
||||
EndPoint recvIPEndPoint = new IPEndPoint(IPAddress.Any, 0);
|
||||
|
||||
long lastSendTimer = 0;
|
||||
|
||||
Fiber fiber = root.Fiber;
|
||||
while (true)
|
||||
{
|
||||
long timeNow = fiber.TimeInfo.ClientFrameTime();
|
||||
if (timeNow - lastSendTimer > 300)
|
||||
{
|
||||
if (--count < 0)
|
||||
{
|
||||
Log.Error($"router connect timeout fail! {localConn} {remoteConn} {routerAddress} {realAddress}");
|
||||
return 0;
|
||||
}
|
||||
lastSendTimer = timeNow;
|
||||
// 发送
|
||||
socket.SendTo(sendCache, 0, addressBytes.Length + 13, SocketFlags.None, routerAddress);
|
||||
}
|
||||
|
||||
await fiber.TimerComponent.WaitFrameAsync();
|
||||
|
||||
// 接收
|
||||
if (socket.Available > 0)
|
||||
{
|
||||
int messageLength = socket.ReceiveFrom(recvCache, ref recvIPEndPoint);
|
||||
if (messageLength != 9)
|
||||
{
|
||||
Log.Error($"router connect error1: {connectId} {messageLength} {localConn} {remoteConn} {routerAddress} {realAddress}");
|
||||
continue;
|
||||
}
|
||||
|
||||
byte flag = recvCache[0];
|
||||
if (flag != KcpProtocalType.RouterReconnectACK && flag != KcpProtocalType.RouterACK)
|
||||
{
|
||||
Log.Error($"router connect error2: {connectId} {synFlag} {flag} {localConn} {remoteConn} {routerAddress} {realAddress}");
|
||||
continue;
|
||||
}
|
||||
|
||||
uint recvRemoteConn = BitConverter.ToUInt32(recvCache, 1);
|
||||
uint recvLocalConn = BitConverter.ToUInt32(recvCache, 5);
|
||||
Log.Info($"router connect finish: {connectId} {recvRemoteConn} {recvLocalConn} {localConn} {remoteConn} {routerAddress} {realAddress}");
|
||||
return recvLocalConn;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c76c4f4f2b0cbc5458c3a39c18717d31
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Reference in New Issue
Block a user