[+] 接入ET8服务端

[+] 接入ET8服务端
This commit is contained in:
ALEXTANG
2023-07-13 12:23:48 +08:00
parent e0be062006
commit 336d4b2eb9
1316 changed files with 130657 additions and 626 deletions

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: d2c1d7db177785844a4b941708d953b9
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

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

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: de532cb8e5e687a4bb61aa666459d086
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View 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();
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 4d77ea7dfe040894aa330386e3b7bb8f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

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

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 4293e004a928ffb43bf52f374808d139
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 2e5141370ec84e1282c5d0a38f2ef25b
timeCreated: 1688537612

View File

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

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a11bff036359a2143aca1de23150ce40
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: c38213e2fca6b8b489ffb3fee170c51f
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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);
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 25a13c7e1f3127848a33352576e747c9
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 0e5f376ea66398e4f8d5fc5d700b4373
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 46ac4bf2b7bf6ea468ccbfbf09367733
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

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

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: eb3ae6bd37192c648b88723824beaaa7
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 9517a733443387b49a227cfb10aa82d6
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

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

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 9fbd99f39ddd82042af56cdbf9ce8dc3
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 0d507c6bfa0e3424380311d17689451c
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

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

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d7e7628945100a44193d11f6c86856fb
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5ba66d6939e13bc47b59fe326cac0526
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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());
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: eff9697e3de79f54dbfd7996f55c6f47
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: b99fb42c78388f147beaf9a963a80458
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

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

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 69fc464a314f79d46922ca7c44dad617
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

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

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0b8fc07def7b312469c243c3ccad1b39
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

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

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 6c4d413c1206d8844b7f6ccc95dd2ce6
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

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

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f76a73cf5e806e9499c3eb92aeeb46d2
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 90e53c0be7b8aab4c827ed76d193ca42
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: b9016545e3eb60946afce20928d2d34b
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

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

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 0f70391ff9eb499db68bae992a9c85b6
timeCreated: 1688540041

View File

@@ -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);
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: f3ac2d21dada4f2b8b51b26e0efe891e
timeCreated: 1688540239

View File

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

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: dee733932d1381941bc0496fc337341a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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());
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5d8c6e9a02dc4ab41ad32d56d9594354
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

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

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 02d16f101211408496a7e86b273ed882
timeCreated: 1688536630

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 657f5f7736369e24786203c1c377ec14
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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}");
}
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: df3747692b8ee23439aa241d5dcfabdc
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 0dd08876e79fc2e4e92db27f7a59b403
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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}");
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 4c6ca4a5394922f488127ebb53362456
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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]));
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 567a551c7abf2fd4c9b592af991b609e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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);
}
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 55f4125eddb1aa543bfdce8f42b4d5f9
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

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

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c76c4f4f2b0cbc5458c3a39c18717d31
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: