[+] 接入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,11 @@
namespace ET
{
public static partial class ConstValue
{
public const string RouterHttpHost = "127.0.0.1";
public const int RouterHttpPort = 30300;
public const int SessionTimeoutTime = 30 * 1000;
}
}

View File

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

View File

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

View File

@@ -0,0 +1,17 @@
namespace ET
{
[Event(SceneType.Main)]
public class EntryEvent1_InitShare: AEvent<Scene, EventType.EntryEvent1>
{
protected override async ETTask Run(Scene root, EventType.EntryEvent1 args)
{
await World.Instance.AddSingleton<ConfigComponent>().LoadAsync();
root.AddComponent<ObjectWait>();
root.AddComponent<MailBoxComponent, MailBoxType>(MailBoxType.UnOrderedMessage);
root.AddComponent<ActorInnerComponent>();
await ETTask.CompletedTask;
}
}
}

View File

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

View File

@@ -0,0 +1,14 @@
namespace ET
{
[Invoke((long)SceneType.Main)]
public class FiberInit_Main: AInvokeHandler<FiberInit, ETTask>
{
public override async ETTask Handle(FiberInit fiberInit)
{
Scene root = fiberInit.Fiber.Root;
await EventSystem.Instance.PublishAsync(root, new EventType.EntryEvent1());
await EventSystem.Instance.PublishAsync(root, new EventType.EntryEvent2());
await EventSystem.Instance.PublishAsync(root, new EventType.EntryEvent3());
}
}
}

View File

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

View File

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

View File

@@ -0,0 +1,32 @@
using System;
using ET.Client;
using TrueSync;
namespace ET
{
[EntitySystemOf(typeof(LSInputComponent))]
[LSEntitySystemOf(typeof(LSInputComponent))]
public static partial class LSInputComponentSystem
{
[EntitySystem]
private static void Awake(this LSInputComponent self)
{
}
[LSEntitySystem]
private static void LSUpdate(this LSInputComponent self)
{
LSUnit unit = self.GetParent<LSUnit>();
TSVector2 v2 = self.LSInput.V * 6 * 50 / 1000;
if (v2.LengthSquared() < 0.0001f)
{
return;
}
TSVector oldPos = unit.Position;
unit.Position += new TSVector(v2.x, 0, v2.y);
unit.Forward = unit.Position - oldPos;
}
}
}

View File

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

View File

@@ -0,0 +1,17 @@
namespace ET
{
public static partial class LSUnitFactory
{
public static LSUnit Init(LSWorld lsWorld, LockStepUnitInfo unitInfo)
{
LSUnitComponent lsUnitComponent = lsWorld.GetComponent<LSUnitComponent>();
LSUnit lsUnit = lsUnitComponent.AddChildWithId<LSUnit>(unitInfo.PlayerId);
lsUnit.Position = unitInfo.Position;
lsUnit.Rotation = unitInfo.Rotation;
lsUnit.AddComponent<LSInputComponent>();
return lsUnit;
}
}
}

View File

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

View File

@@ -0,0 +1,100 @@
using System;
using System.Collections.Generic;
using System.IO;
namespace ET
{
[FriendOf(typeof(Room))]
public static partial class RoomSystem
{
public static Room Room(this Entity entity)
{
return entity.IScene as Room;
}
public static void Init(this Room self, List<LockStepUnitInfo> unitInfos, long startTime, int frame = -1)
{
self.StartTime = startTime;
self.AuthorityFrame = frame;
self.PredictionFrame = frame;
self.Replay.UnitInfos = unitInfos;
self.FrameBuffer = new FrameBuffer(frame);
self.FixedTimeCounter = new FixedTimeCounter(self.StartTime, 0, LSConstValue.UpdateInterval);
LSWorld lsWorld = self.LSWorld;
lsWorld.Frame = frame + 1;
lsWorld.AddComponent<LSUnitComponent>();
for (int i = 0; i < unitInfos.Count; ++i)
{
LockStepUnitInfo unitInfo = unitInfos[i];
LSUnitFactory.Init(lsWorld, unitInfo);
self.PlayerIds.Add(unitInfo.PlayerId);
}
}
public static void Update(this Room self, OneFrameInputs oneFrameInputs)
{
LSWorld lsWorld = self.LSWorld;
// 设置输入到每个LSUnit身上
LSUnitComponent unitComponent = lsWorld.GetComponent<LSUnitComponent>();
foreach (var kv in oneFrameInputs.Inputs)
{
LSUnit lsUnit = unitComponent.GetChild<LSUnit>(kv.Key);
LSInputComponent lsInputComponent = lsUnit.GetComponent<LSInputComponent>();
lsInputComponent.LSInput = kv.Value;
}
if (!self.IsReplay)
{
// 保存当前帧场景数据
self.SaveLSWorld();
self.Record(self.LSWorld.Frame);
}
lsWorld.Update();
}
public static LSWorld GetLSWorld(this Room self, SceneType sceneType, int frame)
{
MemoryBuffer memoryBuffer = self.FrameBuffer.Snapshot(frame);
memoryBuffer.Seek(0, SeekOrigin.Begin);
LSWorld lsWorld = MongoHelper.Deserialize(typeof (LSWorld), memoryBuffer) as LSWorld;
lsWorld.SceneType = sceneType;
memoryBuffer.Seek(0, SeekOrigin.Begin);
return lsWorld;
}
private static void SaveLSWorld(this Room self)
{
int frame = self.LSWorld.Frame;
MemoryBuffer memoryBuffer = self.FrameBuffer.Snapshot(frame);
memoryBuffer.Seek(0, SeekOrigin.Begin);
memoryBuffer.SetLength(0);
MongoHelper.Serialize(self.LSWorld, memoryBuffer);
memoryBuffer.Seek(0, SeekOrigin.Begin);
long hash = memoryBuffer.GetBuffer().Hash(0, (int) memoryBuffer.Length);
self.FrameBuffer.SetHash(frame, hash);
}
// 记录需要存档的数据
public static void Record(this Room self, int frame)
{
if (frame > self.AuthorityFrame)
{
return;
}
OneFrameInputs oneFrameInputs = self.FrameBuffer.FrameInputs(frame);
OneFrameInputs saveInput = new();
oneFrameInputs.CopyTo(saveInput);
self.Replay.FrameInputs.Add(saveInput);
if (frame % LSConstValue.SaveLSWorldFrameCount == 0)
{
MemoryBuffer memoryBuffer = self.FrameBuffer.Snapshot(frame);
byte[] bytes = memoryBuffer.ToArray();
self.Replay.Snapshots.Add(bytes);
}
}
}
}

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,92 @@
using System;
namespace ET
{
[EntitySystemOf(typeof(AIComponent))]
[FriendOf(typeof(AIComponent))]
[FriendOf(typeof(AIDispatcherComponent))]
public static partial class AIComponentSystem
{
[Invoke(TimerInvokeType.AITimer)]
public class AITimer: ATimer<AIComponent>
{
protected override void Run(AIComponent self)
{
try
{
self.Check();
}
catch (Exception e)
{
Log.Error($"move timer error: {self.Id}\n{e}");
}
}
}
[EntitySystem]
private static void Awake(this AIComponent self, int aiConfigId)
{
self.AIConfigId = aiConfigId;
self.Timer = self.Fiber().TimerComponent.NewRepeatedTimer(1000, TimerInvokeType.AITimer, self);
}
[EntitySystem]
private static void Destroy(this AIComponent self)
{
self.Fiber().TimerComponent?.Remove(ref self.Timer);
self.CancellationToken?.Cancel();
self.CancellationToken = null;
self.Current = 0;
}
private static void Check(this AIComponent self)
{
if (self.Parent == null)
{
self.Fiber().TimerComponent.Remove(ref self.Timer);
return;
}
var oneAI = AIConfigCategory.Instance.AIConfigs[self.AIConfigId];
foreach (AIConfig aiConfig in oneAI.Values)
{
AAIHandler aaiHandler = AIDispatcherComponent.Instance.Get(aiConfig.Name);
if (aaiHandler == null)
{
Log.Error($"not found aihandler: {aiConfig.Name}");
continue;
}
int ret = aaiHandler.Check(self, aiConfig);
if (ret != 0)
{
continue;
}
if (self.Current == aiConfig.Id)
{
break;
}
self.Cancel(); // 取消之前的行为
ETCancellationToken cancellationToken = new ETCancellationToken();
self.CancellationToken = cancellationToken;
self.Current = aiConfig.Id;
aaiHandler.Execute(self, aiConfig, cancellationToken).Coroutine();
return;
}
}
private static void Cancel(this AIComponent self)
{
self.CancellationToken?.Cancel();
self.Current = 0;
self.CancellationToken = null;
}
}
}

View File

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

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: ee3a9e6a195849ee8792a8793fb0bdd6
timeCreated: 1687789835

View File

@@ -0,0 +1,99 @@
using System;
namespace ET
{
public static partial class ActorHandleHelper
{
[EnableAccessEntiyChild]
public static async ETTask HandleMessage(Fiber fiber, ActorId actorId, MessageObject message)
{
await ETTask.CompletedTask;
/*
// 收到actor消息,放入actor队列
switch (message)
{
case IActorRequest iActorRequest:
{
switch (mailBoxComponent.MailboxType)
{
case MailboxType.OrderedMessage:
{
using (await CoroutineLockComponent.Instance.Wait(CoroutineLockType.Mailbox, actorId.InstanceId))
{
if (entity.InstanceId != actorId.InstanceId)
{
IActorResponse response = ActorHelper.CreateResponse(iActorRequest, ErrorCore.ERR_NotFoundActor);
ActorMessageSenderComponent.Instance.Reply(actorId, response);
break;
}
await ActorMessageDispatcherComponent.Instance.Handle(entity, actorId, iActorRequest);
}
break;
}
case MailboxType.UnOrderMessageDispatcher:
{
await ActorMessageDispatcherComponent.Instance.Handle(entity, actorId, iActorRequest);
break;
}
default:
throw new Exception($"no mailboxtype: {mailBoxComponent.MailboxType} {iActorRequest}");
}
break;
}
case IActorMessage iActorMessage:
{
mailBoxComponent = Fiber.Instance.Mailboxes.Get(actorId.InstanceId);
if (mailBoxComponent == null)
{
Log.Error($"actor not found mailbox: {actorId} {iActorMessage}");
return;
}
mailBoxComponent.Add(iActorMessage as MessageObject);
switch (mailBoxComponent.MailboxType)
{
case MailboxType.OrderedMessage:
{
using (await CoroutineLockComponent.Instance.Wait(CoroutineLockType.Mailbox, actorId.InstanceId))
{
if (entity.InstanceId != actorId.InstanceId)
{
break;
}
await ActorMessageDispatcherComponent.Instance.Handle(entity, actorId, iActorMessage);
}
break;
}
case MailboxType.UnOrderMessageDispatcher:
{
await ActorMessageDispatcherComponent.Instance.Handle(entity, actorId, iActorMessage);
break;
}
case MailboxType.GateSession:
{
if (entity is PlayerSessionComponent playerSessionComponent)
{
playerSessionComponent.Session?.Send(iActorMessage);
}
break;
}
default:
throw new Exception($"no mailboxtype: {mailBoxComponent.MailboxType} {iActorMessage}");
}
break;
}
}
*/
}
}
}

View File

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

View File

@@ -0,0 +1,104 @@
using System;
namespace ET
{
[EnableClass]
public abstract class ActorMessageHandler<E, Message>: IMActorHandler where E : Entity where Message : class, IActorMessage
{
protected abstract ETTask Run(E entity, Message message);
public async ETTask Handle(Entity entity, Address fromAddress, MessageObject actorMessage)
{
if (actorMessage is not Message msg)
{
Log.Error($"消息类型转换错误: {actorMessage.GetType().FullName} to {typeof (Message).Name}");
return;
}
if (entity is not E e)
{
Log.Error($"Actor类型转换错误: {entity.GetType().FullName} to {typeof (E).Name} --{typeof (Message).FullName}");
return;
}
await this.Run(e, msg);
}
public Type GetRequestType()
{
if (typeof (IActorLocationMessage).IsAssignableFrom(typeof (Message)))
{
Log.Error($"message is IActorLocationMessage but handler is AMActorHandler: {typeof (Message)}");
}
return typeof (Message);
}
public Type GetResponseType()
{
return null;
}
}
[EnableClass]
public abstract class ActorMessageHandler<E, Request, Response>: IMActorHandler where E : Entity where Request : MessageObject, IActorRequest where Response : MessageObject, IActorResponse
{
protected abstract ETTask Run(E unit, Request request, Response response);
public async ETTask Handle(Entity entity, Address fromAddress, MessageObject actorMessage)
{
try
{
if (actorMessage is not Request request)
{
Log.Error($"消息类型转换错误: {actorMessage.GetType().FullName} to {typeof (Request).Name}");
return;
}
if (entity is not E ee)
{
Log.Error($"Actor类型转换错误: {entity.GetType().FullName} to {typeof (E).FullName} --{typeof (Request).FullName}");
return;
}
int rpcId = request.RpcId;
Response response = ObjectPool.Instance.Fetch<Response>();
try
{
await this.Run(ee, request, response);
}
catch (Exception exception)
{
Log.Error(exception);
response.Error = ErrorCore.ERR_RpcFail;
response.Message = exception.ToString();
}
response.RpcId = rpcId;
entity.Root().GetComponent<ActorInnerComponent>().Reply(fromAddress, response);
}
catch (Exception e)
{
throw new Exception($"解释消息失败: {actorMessage.GetType().FullName}", e);
}
}
public Type GetRequestType()
{
if (typeof (IActorLocationRequest).IsAssignableFrom(typeof (Request)))
{
Log.Error($"message is IActorLocationMessage but handler is AMActorRpcHandler: {typeof (Request)}");
}
return typeof (Request);
}
public Type GetResponseType()
{
return typeof (Response);
}
}
}

View File

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

View File

@@ -0,0 +1,40 @@
namespace ET
{
[Invoke((long)MailBoxType.OrderedMessage)]
public class MailBoxType_OrderedMessageHandler: AInvokeHandler<MailBoxInvoker>
{
public override void Handle(MailBoxInvoker args)
{
HandleInner(args).Coroutine();
}
private static async ETTask HandleInner(MailBoxInvoker args)
{
MailBoxComponent mailBoxComponent = args.MailBoxComponent;
// 对象池回收
using MessageObject messageObject = args.MessageObject;
CoroutineLockComponent coroutineLockComponent = mailBoxComponent.CoroutineLockComponent;
if (coroutineLockComponent == null)
{
return;
}
long instanceId = mailBoxComponent.InstanceId;
using (await coroutineLockComponent.Wait(CoroutineLockType.Mailbox, mailBoxComponent.ParentInstanceId))
{
if (mailBoxComponent.InstanceId != instanceId)
{
if (messageObject is IActorRequest request)
{
IActorResponse resp = ActorHelper.CreateResponse(request, ErrorCore.ERR_NotFoundActor);
mailBoxComponent.Root().GetComponent<ActorInnerComponent>().Reply(args.FromAddress, resp);
}
return;
}
await ActorMessageDispatcherComponent.Instance.Handle(mailBoxComponent.Parent, args.FromAddress, messageObject);
}
}
}
}

View File

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

View File

@@ -0,0 +1,20 @@
namespace ET
{
[Invoke((long)MailBoxType.UnOrderedMessage)]
public class MailBoxType_UnOrderedMessageHandler: AInvokeHandler<MailBoxInvoker>
{
public override void Handle(MailBoxInvoker args)
{
HandleAsync(args).Coroutine();
}
private static async ETTask HandleAsync(MailBoxInvoker args)
{
MailBoxComponent mailBoxComponent = args.MailBoxComponent;
using MessageObject messageObject = args.MessageObject;
await ActorMessageDispatcherComponent.Instance.Handle(mailBoxComponent.Parent, args.FromAddress, messageObject);
}
}
}

View File

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

View File

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

View File

@@ -0,0 +1,69 @@
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
namespace ET
{
[EntitySystemOf(typeof(ConsoleComponent))]
[FriendOf(typeof(ConsoleComponent))]
[FriendOf(typeof(ModeContex))]
public static partial class ConsoleComponentSystem
{
[EntitySystem]
private static void Awake(this ConsoleComponent self)
{
self.Start().Coroutine();
}
private static async ETTask Start(this ConsoleComponent self)
{
self.CancellationTokenSource = new CancellationTokenSource();
while (true)
{
try
{
ModeContex modeContex = self.GetComponent<ModeContex>();
string line = await Task.Factory.StartNew(() =>
{
Console.Write($"{modeContex?.Mode ?? ""}> ");
return Console.In.ReadLine();
}, self.CancellationTokenSource.Token);
line = line.Trim();
switch (line)
{
case "":
break;
case "exit":
self.RemoveComponent<ModeContex>();
break;
default:
{
string[] lines = line.Split(" ");
string mode = modeContex == null? lines[0] : modeContex.Mode;
IConsoleHandler iConsoleHandler = ConsoleDispatcher.Instance.Get(mode);
if (modeContex == null)
{
modeContex = self.AddComponent<ModeContex>();
modeContex.Mode = mode;
}
await iConsoleHandler.Run(self.Fiber(), modeContex, line);
break;
}
}
}
catch (Exception e)
{
Log.Console(e.ToString());
}
}
}
}
}

View File

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

View File

@@ -0,0 +1,34 @@
using System;
namespace ET
{
[ConsoleHandler(ConsoleMode.ReloadConfig)]
public class ReloadConfigConsoleHandler: IConsoleHandler
{
public async ETTask Run(Fiber fiber, ModeContex contex, string content)
{
switch (content)
{
case ConsoleMode.ReloadConfig:
contex.Parent.RemoveComponent<ModeContex>();
Log.Console("C must have config name, like: C UnitConfig");
break;
default:
string[] ss = content.Split(" ");
string configName = ss[1];
string category = $"{configName}Category";
Type type = EventSystem.Instance.GetType($"ET.{category}");
if (type == null)
{
Log.Console($"reload config but not find {category}");
return;
}
ConfigComponent.Instance.Reload(type);
Log.Console($"reload config {configName} finish!");
break;
}
await ETTask.CompletedTask;
}
}
}

View File

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

View File

@@ -0,0 +1,12 @@
namespace ET
{
[ConsoleHandler(ConsoleMode.ReloadDll)]
public class ReloadDllConsoleHandler: IConsoleHandler
{
public async ETTask Run(Fiber fiber, ModeContex contex, string content)
{
await ETTask.CompletedTask;
CodeLoader.Instance.LoadHotfix();
}
}
}

View File

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

View File

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

View File

@@ -0,0 +1,40 @@
using System;
namespace ET
{
[EntitySystemOf(typeof(SessionAcceptTimeoutComponent))]
[FriendOf(typeof(SessionAcceptTimeoutComponent))]
public static partial class SessionAcceptTimeoutComponentHelper
{
[Invoke(TimerInvokeType.SessionAcceptTimeout)]
public class SessionAcceptTimeout: ATimer<SessionAcceptTimeoutComponent>
{
protected override void Run(SessionAcceptTimeoutComponent self)
{
try
{
self.Parent.Dispose();
}
catch (Exception e)
{
Log.Error($"move timer error: {self.Id}\n{e}");
}
}
}
[EntitySystem]
private static void Awake(this SessionAcceptTimeoutComponent self)
{
self.Timer = self.Fiber().TimerComponent.NewOnceTimer(self.Fiber().TimeInfo.ServerNow() + 5000, TimerInvokeType.SessionAcceptTimeout, self);
}
[EntitySystem]
private static void Destroy(this SessionAcceptTimeoutComponent self)
{
self.Fiber().TimerComponent?.Remove(ref self.Timer);
}
}
}

View File

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

View File

@@ -0,0 +1,55 @@
using System;
namespace ET
{
[EntitySystemOf(typeof(SessionIdleCheckerComponent))]
[FriendOf(typeof(SessionIdleCheckerComponent))]
public static partial class SessionIdleCheckerComponentSystem
{
[Invoke(TimerInvokeType.SessionIdleChecker)]
public class SessionIdleChecker: ATimer<SessionIdleCheckerComponent>
{
protected override void Run(SessionIdleCheckerComponent self)
{
try
{
self.Check();
}
catch (Exception e)
{
Log.Error($"session idle checker timer error: {self.Id}\n{e}");
}
}
}
[EntitySystem]
private static void Awake(this SessionIdleCheckerComponent self)
{
self.RepeatedTimer = self.Fiber().TimerComponent.NewRepeatedTimer(CheckInteral, TimerInvokeType.SessionIdleChecker, self);
}
[EntitySystem]
private static void Destroy(this SessionIdleCheckerComponent self)
{
self.Fiber().TimerComponent?.Remove(ref self.RepeatedTimer);
}
public const int CheckInteral = 2000;
private static void Check(this SessionIdleCheckerComponent self)
{
Session session = self.GetParent<Session>();
long timeNow = self.Fiber().TimeInfo.ClientNow();
if (timeNow - session.LastRecvTime < ConstValue.SessionTimeoutTime && timeNow - session.LastSendTime < ConstValue.SessionTimeoutTime)
{
return;
}
Log.Info($"session timeout: {session.Id} {timeNow} {session.LastRecvTime} {session.LastSendTime} {timeNow - session.LastRecvTime} {timeNow - session.LastSendTime}");
session.Error = ErrorCore.ERR_SessionSendOrRecvTimeout;
session.Dispose();
}
}
}

View File

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

View File

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

View File

@@ -0,0 +1,294 @@
using System;
using System.Collections.Generic;
using Unity.Mathematics;
namespace ET
{
[EntitySystemOf(typeof(MoveComponent))]
[FriendOf(typeof(MoveComponent))]
public static partial class MoveComponentSystem
{
[Invoke(TimerInvokeType.MoveTimer)]
public class MoveTimer: ATimer<MoveComponent>
{
protected override void Run(MoveComponent self)
{
try
{
self.MoveForward(true);
}
catch (Exception e)
{
Log.Error($"move timer error: {self.Id}\n{e}");
}
}
}
[EntitySystem]
private static void Destroy(this MoveComponent self)
{
self.MoveFinish(false);
}
[EntitySystem]
private static void Awake(this MoveComponent self)
{
self.StartTime = 0;
self.StartPos = float3.zero;
self.NeedTime = 0;
self.MoveTimer = 0;
self.tcs = null;
self.Targets.Clear();
self.Speed = 0;
self.N = 0;
self.TurnTime = 0;
}
public static bool IsArrived(this MoveComponent self)
{
return self.Targets.Count == 0;
}
public static bool ChangeSpeed(this MoveComponent self, float speed)
{
if (self.IsArrived())
{
return false;
}
if (speed < 0.0001)
{
return false;
}
Unit unit = self.GetParent<Unit>();
using ListComponent<float3> path = ListComponent<float3>.Create();
self.MoveForward(false);
path.Add(unit.Position); // 第一个是Unit的pos
for (int i = self.N; i < self.Targets.Count; ++i)
{
path.Add(self.Targets[i]);
}
self.MoveToAsync(path, speed).Coroutine();
return true;
}
// 该方法不需要用cancelToken的方式取消因为即使不传入cancelToken多次调用该方法也要取消之前的移动协程,上层可以stop取消
public static async ETTask<bool> MoveToAsync(this MoveComponent self, List<float3> target, float speed, int turnTime = 100)
{
self.Stop(false);
foreach (float3 v in target)
{
self.Targets.Add(v);
}
self.IsTurnHorizontal = true;
self.TurnTime = turnTime;
self.Speed = speed;
self.tcs = ETTask<bool>.Create(true);
EventSystem.Instance.Publish(self.Scene(), new EventType.MoveStart() {Unit = self.GetParent<Unit>()});
self.StartMove();
bool moveRet = await self.tcs;
if (moveRet)
{
EventSystem.Instance.Publish(self.Scene(), new EventType.MoveStop() {Unit = self.GetParent<Unit>()});
}
return moveRet;
}
// ret: 停止的时候,移动协程的返回值
private static void MoveForward(this MoveComponent self, bool ret)
{
Unit unit = self.GetParent<Unit>();
long timeNow = self.Fiber().TimeInfo.ClientNow();
long moveTime = timeNow - self.StartTime;
while (true)
{
if (moveTime <= 0)
{
return;
}
// 计算位置插值
if (moveTime >= self.NeedTime)
{
unit.Position = self.NextTarget;
if (self.TurnTime > 0)
{
unit.Rotation = self.To;
}
}
else
{
// 计算位置插值
float amount = moveTime * 1f / self.NeedTime;
if (amount > 0)
{
float3 newPos = math.lerp(self.StartPos, self.NextTarget, amount);
unit.Position = newPos;
}
// 计算方向插值
if (self.TurnTime > 0)
{
amount = moveTime * 1f / self.TurnTime;
if (amount > 1)
{
amount = 1f;
}
quaternion q = math.slerp(self.From, self.To, amount);
unit.Rotation = q;
}
}
moveTime -= self.NeedTime;
// 表示这个点还没走完,等下一帧再来
if (moveTime < 0)
{
return;
}
// 到这里说明这个点已经走完
// 如果是最后一个点
if (self.N >= self.Targets.Count - 1)
{
unit.Position = self.NextTarget;
unit.Rotation = self.To;
self.MoveFinish(ret);
return;
}
self.SetNextTarget();
}
}
private static void StartMove(this MoveComponent self)
{
self.BeginTime = self.Fiber().TimeInfo.ClientNow();
self.StartTime = self.BeginTime;
self.SetNextTarget();
self.MoveTimer = self.Fiber().TimerComponent.NewFrameTimer(TimerInvokeType.MoveTimer, self);
}
private static void SetNextTarget(this MoveComponent self)
{
Unit unit = self.GetParent<Unit>();
++self.N;
// 时间计算用服务端的位置, 但是移动要用客户端的位置来插值
float3 v = self.GetFaceV();
float distance = math.length(v);
// 插值的起始点要以unit的真实位置来算
self.StartPos = unit.Position;
self.StartTime += self.NeedTime;
self.NeedTime = (long) (distance / self.Speed * 1000);
if (self.TurnTime > 0)
{
// 要用unit的位置
float3 faceV = self.GetFaceV();
if (math.lengthsq(faceV) < 0.0001f)
{
return;
}
self.From = unit.Rotation;
if (self.IsTurnHorizontal)
{
faceV.y = 0;
}
if (Math.Abs(faceV.x) > 0.01 || Math.Abs(faceV.z) > 0.01)
{
self.To = quaternion.LookRotation(faceV, math.up());
}
return;
}
if (self.TurnTime == 0) // turn time == 0 立即转向
{
float3 faceV = self.GetFaceV();
if (self.IsTurnHorizontal)
{
faceV.y = 0;
}
if (Math.Abs(faceV.x) > 0.01 || Math.Abs(faceV.z) > 0.01)
{
self.To = quaternion.LookRotation(faceV, math.up());
unit.Rotation = self.To;
}
}
}
private static float3 GetFaceV(this MoveComponent self)
{
return self.NextTarget - self.PreTarget;
}
public static bool FlashTo(this MoveComponent self, float3 target)
{
Unit unit = self.GetParent<Unit>();
unit.Position = target;
return true;
}
// ret: 停止的时候,移动协程的返回值
public static void Stop(this MoveComponent self, bool ret)
{
if (self.Targets.Count > 0)
{
self.MoveForward(ret);
}
self.MoveFinish(ret);
}
private static void MoveFinish(this MoveComponent self, bool ret)
{
if (self.StartTime == 0)
{
return;
}
self.StartTime = 0;
self.StartPos = float3.zero;
self.BeginTime = 0;
self.NeedTime = 0;
self.Targets.Clear();
self.Speed = 0;
self.N = 0;
self.TurnTime = 0;
self.IsTurnHorizontal = false;
self.Fiber().TimerComponent?.Remove(ref self.MoveTimer);
if (self.tcs != null)
{
var tcs = self.tcs;
self.tcs = null;
tcs.SetResult(ret);
}
}
}
}

View File

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

View File

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

View File

@@ -0,0 +1,13 @@
namespace ET
{
// 分发数值监听
[Event(SceneType.All)] // 服务端Map需要分发, 客户端CurrentScene也要分发
public class NumericChangeEvent_NotifyWatcher: AEvent<Scene, EventType.NumbericChange>
{
protected override async ETTask Run(Scene scene, EventType.NumbericChange args)
{
NumericWatcherComponent.Instance.Run(args.Unit, args);
await ETTask.CompletedTask;
}
}
}

View File

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

View File

@@ -0,0 +1,13 @@
namespace ET
{
/// <summary>
/// 客户端监视hp数值变化改变血条值
/// </summary>
[NumericWatcher(SceneType.Current, NumericType.Hp)]
public class NumericWatcher_Hp_ShowUI : INumericWatcher
{
public void Run(Unit unit, EventType.NumbericChange args)
{
}
}
}

View File

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

View File

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

View File

@@ -0,0 +1,168 @@
using System;
using System.Collections.Generic;
using Unity.Mathematics;
namespace ET
{
[EntitySystemOf(typeof(PathfindingComponent))]
[FriendOf(typeof(PathfindingComponent))]
public static partial class PathfindingComponentSystem
{
[EntitySystem]
private static void Awake(this PathfindingComponent self, string name)
{
self.Name = name;
byte[] buffer = NavmeshComponent.Instance.Get(name);
self.navMesh = Recast.RecastLoad(buffer, buffer.Length);
if (self.navMesh == IntPtr.Zero)
{
throw new Exception($"nav load fail: {name}");
}
}
[EntitySystem]
private static void Destroy(this PathfindingComponent self)
{
self.Name = string.Empty;
Recast.RecastClear(self.navMesh);
self.navMesh = IntPtr.Zero;
}
public static void Find(this PathfindingComponent self, float3 start, float3 target, List<float3> result)
{
if (self.navMesh == IntPtr.Zero)
{
Log.Debug("寻路| Find 失败 pathfinding ptr is zero");
throw new Exception($"pathfinding ptr is zero: {self.Scene().Name}");
}
self.StartPos[0] = -start.x;
self.StartPos[1] = start.y;
self.StartPos[2] = start.z;
self.EndPos[0] = -target.x;
self.EndPos[1] = target.y;
self.EndPos[2] = target.z;
//Log.Debug($"start find path: {self.GetParent<Unit>().Id}");
int n = Recast.RecastFind(self.navMesh, self.extents, self.StartPos, self.EndPos, self.Result);
if (n < 0)
{
throw new Exception($"find path error: {n}");
}
for (int i = 0; i < n; ++i)
{
int index = i * 3;
result.Add(new float3(-self.Result[index], self.Result[index + 1], self.Result[index + 2]));
}
//Log.Debug($"finish find path: {self.GetParent<Unit>().Id} {result.ListToString()}");
}
public static void FindWithAdjust(this PathfindingComponent self, float3 start, float3 target, List<float3> result,float adjustRaduis)
{
self.Find(start, target, result);
for (int i = 0; i < result.Count; i++)
{
float3 adjust = self.FindRandomPointWithRaduis(result[i], adjustRaduis);
result[i] = adjust;
}
}
public static float3 FindRandomPointWithRaduis(this PathfindingComponent self, float3 pos, float raduis)
{
if (self.navMesh == IntPtr.Zero)
{
throw new Exception($"pathfinding ptr is zero: {self.Scene().Name}");
}
if (raduis > PathfindingComponent.FindRandomNavPosMaxRadius * 0.001f)
{
throw new Exception($"pathfinding raduis is too largecur: {raduis}, max: {PathfindingComponent.FindRandomNavPosMaxRadius}");
}
int degrees = RandomGenerator.RandomNumber(0, 360);
float r = RandomGenerator.RandomNumber(0, (int) (raduis * 1000)) / 1000f;
float x = r * math.cos(math.radians(degrees));
float z = r * math.sin(math.radians(degrees));
float3 findpos = new float3(pos.x + x, pos.y, pos.z + z);
return self.RecastFindNearestPoint(findpos);
}
/// <summary>
/// 以pos为中心各自在宽和高的左右 前后两个方向延伸
/// </summary>
/// <param name="self"></param>
/// <param name="pos"></param>
/// <param name="width"></param>
/// <param name="height"></param>
/// <returns></returns>
/// <exception cref="Exception"></exception>
public static float3 FindRandomPointWithRectangle(this PathfindingComponent self, float3 pos, int width, int height)
{
if (self.navMesh == IntPtr.Zero)
{
throw new Exception($"pathfinding ptr is zero: {self.Scene().Name}");
}
if (width > PathfindingComponent.FindRandomNavPosMaxRadius * 0.001f || height > PathfindingComponent.FindRandomNavPosMaxRadius * 0.001f)
{
throw new Exception($"pathfinding rectangle is too largewidth: {width} height: {height}, max: {PathfindingComponent.FindRandomNavPosMaxRadius}");
}
float x = RandomGenerator.RandomNumber(-width, width);
float z = RandomGenerator.RandomNumber(-height, height);
float3 findpos = new float3(pos.x + x, pos.y, pos.z + z);
return self.RecastFindNearestPoint(findpos);
}
public static float3 FindRandomPointWithRaduis(this PathfindingComponent self, float3 pos, float minRadius, float maxRadius)
{
if (self.navMesh == IntPtr.Zero)
{
throw new Exception($"pathfinding ptr is zero: {self.Scene().Name}");
}
if (maxRadius > PathfindingComponent.FindRandomNavPosMaxRadius * 0.001f)
{
throw new Exception($"pathfinding raduis is too largecur: {maxRadius}, max: {PathfindingComponent.FindRandomNavPosMaxRadius}");
}
int degrees = RandomGenerator.RandomNumber(0, 360);
float r = RandomGenerator.RandomNumber((int) (minRadius * 1000), (int) (maxRadius * 1000)) / 1000f;
float x = r * math.cos(math.radians(degrees));
float z = r * math.sin(math.radians(degrees));
float3 findpos = new float3(pos.x + x, pos.y, pos.z + z);
return self.RecastFindNearestPoint(findpos);
}
public static float3 RecastFindNearestPoint(this PathfindingComponent self, float3 pos)
{
if (self.navMesh == IntPtr.Zero)
{
throw new Exception($"pathfinding ptr is zero: {self.Scene().Name}");
}
self.StartPos[0] = -pos.x;
self.StartPos[1] = pos.y;
self.StartPos[2] = pos.z;
int ret = Recast.RecastFindNearestPoint(self.navMesh, self.extents, self.StartPos, self.EndPos);
if (ret == 0)
{
throw new Exception($"RecastFindNearestPoint fail, 可能是位置配置有问题: sceneName:{self.Scene().Name} {pos} {self.Name} {self.GetParent<Unit>().Id} {self.GetParent<Unit>().Config.Id} {self.EndPos.ArrayToString()}");
}
return new float3(-self.EndPos[0], self.EndPos[1], self.EndPos[2]);
}
}
}

View File

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

View File

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

View File

@@ -0,0 +1,12 @@
using System;
namespace ET
{
public static partial class CurrentScenesComponentSystem
{
public static Scene CurrentScene(this Scene root)
{
return root.GetComponent<CurrentScenesComponent>()?.Scene;
}
}
}

View File

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

View File

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

View File

@@ -0,0 +1,21 @@
namespace ET
{
public static partial class UnitComponentSystem
{
public static void Add(this UnitComponent self, Unit unit)
{
}
public static Unit Get(this UnitComponent self, long id)
{
Unit unit = self.GetChild<Unit>(id);
return unit;
}
public static void Remove(this UnitComponent self, long id)
{
Unit unit = self.GetChild<Unit>(id);
unit?.Dispose();
}
}
}

View File

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

View File

@@ -0,0 +1,12 @@
namespace ET
{
[EntitySystemOf(typeof(Unit))]
public static partial class UnitSystem
{
[EntitySystem]
private static void Awake(this Unit self, int configId)
{
self.ConfigId = configId;
}
}
}

View File

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

View File

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

View File

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

View File

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