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:
@@ -0,0 +1,310 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using MongoDB.Bson;
|
||||
|
||||
namespace ET.Server
|
||||
{
|
||||
[EntitySystemOf(typeof(ActorLocationSenderOneType))]
|
||||
[FriendOf(typeof(ActorLocationSenderOneType))]
|
||||
[FriendOf(typeof(ActorLocationSender))]
|
||||
public static partial class ActorLocationSenderComponentSystem
|
||||
{
|
||||
[Invoke(TimerInvokeType.ActorLocationSenderChecker)]
|
||||
public class ActorLocationSenderChecker: ATimer<ActorLocationSenderOneType>
|
||||
{
|
||||
protected override void Run(ActorLocationSenderOneType self)
|
||||
{
|
||||
try
|
||||
{
|
||||
self.Check();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Error($"move timer error: {self.Id}\n{e}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[EntitySystem]
|
||||
private static void Awake(this ActorLocationSenderOneType self, int locationType)
|
||||
{
|
||||
self.LocationType = locationType;
|
||||
// 每10s扫描一次过期的actorproxy进行回收,过期时间是2分钟
|
||||
// 可能由于bug或者进程挂掉,导致ActorLocationSender发送的消息没有确认,结果无法自动删除,每一分钟清理一次这种ActorLocationSender
|
||||
self.CheckTimer = self.Fiber().TimerComponent.NewRepeatedTimer(10 * 1000, TimerInvokeType.ActorLocationSenderChecker, self);
|
||||
}
|
||||
|
||||
[EntitySystem]
|
||||
private static void Destroy(this ActorLocationSenderOneType self)
|
||||
{
|
||||
self.Fiber().TimerComponent?.Remove(ref self.CheckTimer);
|
||||
}
|
||||
|
||||
private static void Check(this ActorLocationSenderOneType self)
|
||||
{
|
||||
using (ListComponent<long> list = ListComponent<long>.Create())
|
||||
{
|
||||
long timeNow = self.Fiber().TimeInfo.ServerNow();
|
||||
foreach ((long key, Entity value) in self.Children)
|
||||
{
|
||||
ActorLocationSender actorLocationMessageSender = (ActorLocationSender) value;
|
||||
|
||||
if (timeNow > actorLocationMessageSender.LastSendOrRecvTime + ActorLocationSenderOneType.TIMEOUT_TIME)
|
||||
{
|
||||
list.Add(key);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (long id in list)
|
||||
{
|
||||
self.Remove(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static ActorLocationSender GetOrCreate(this ActorLocationSenderOneType self, long id)
|
||||
{
|
||||
if (id == 0)
|
||||
{
|
||||
throw new Exception($"actor id is 0");
|
||||
}
|
||||
|
||||
if (self.Children.TryGetValue(id, out Entity actorLocationSender))
|
||||
{
|
||||
return (ActorLocationSender) actorLocationSender;
|
||||
}
|
||||
|
||||
actorLocationSender = self.AddChildWithId<ActorLocationSender>(id);
|
||||
return (ActorLocationSender) actorLocationSender;
|
||||
}
|
||||
|
||||
// 有需要主动删除actorMessageSender的需求,比如断线重连,玩家登录了不同的Gate,这时候需要通知map删掉之前的actorMessageSender
|
||||
// 然后重新创建新的,重新请求新的ActorId
|
||||
public static void Remove(this ActorLocationSenderOneType self, long id)
|
||||
{
|
||||
if (!self.Children.TryGetValue(id, out Entity actorMessageSender))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
actorMessageSender.Dispose();
|
||||
}
|
||||
|
||||
// 发给不会改变位置的actorlocation用这个,这种actor消息不会阻塞发送队列,性能更高
|
||||
// 发送过去找不到actor不会重试,用此方法,你得保证actor提前注册好了location
|
||||
public static void Send(this ActorLocationSenderOneType self, long entityId, IActorMessage message)
|
||||
{
|
||||
self.SendInner(entityId, message).Coroutine();
|
||||
}
|
||||
|
||||
private static async ETTask SendInner(this ActorLocationSenderOneType self, long entityId, IActorMessage message)
|
||||
{
|
||||
ActorLocationSender actorLocationSender = self.GetOrCreate(entityId);
|
||||
|
||||
Scene root = self.Root();
|
||||
|
||||
if (actorLocationSender.ActorId != default)
|
||||
{
|
||||
actorLocationSender.LastSendOrRecvTime = self.Fiber().TimeInfo.ServerNow();
|
||||
root.GetComponent<ActorSenderComponent>().Send(actorLocationSender.ActorId, message);
|
||||
return;
|
||||
}
|
||||
|
||||
long instanceId = actorLocationSender.InstanceId;
|
||||
|
||||
int coroutineLockType = (self.LocationType << 16) | CoroutineLockType.ActorLocationSender;
|
||||
using (await root.Fiber.CoroutineLockComponent.Wait(coroutineLockType, entityId))
|
||||
{
|
||||
if (actorLocationSender.InstanceId != instanceId)
|
||||
{
|
||||
throw new RpcException(ErrorCore.ERR_ActorTimeout, $"{message}");
|
||||
}
|
||||
|
||||
if (actorLocationSender.ActorId == default)
|
||||
{
|
||||
actorLocationSender.ActorId = await root.GetComponent<LocationProxyComponent>().Get(self.LocationType, actorLocationSender.Id);
|
||||
if (actorLocationSender.InstanceId != instanceId)
|
||||
{
|
||||
throw new RpcException(ErrorCore.ERR_ActorLocationSenderTimeout2, $"{message}");
|
||||
}
|
||||
}
|
||||
|
||||
actorLocationSender.LastSendOrRecvTime = self.Fiber().TimeInfo.ServerNow();
|
||||
root.GetComponent<ActorSenderComponent>().Send(actorLocationSender.ActorId, message);
|
||||
}
|
||||
}
|
||||
|
||||
// 发给不会改变位置的actorlocation用这个,这种actor消息不会阻塞发送队列,性能更高,发送过去找不到actor不会重试
|
||||
// 发送过去找不到actor不会重试,用此方法,你得保证actor提前注册好了location
|
||||
public static async ETTask<IActorResponse> Call(this ActorLocationSenderOneType self, long entityId, IActorRequest request)
|
||||
{
|
||||
ActorLocationSender actorLocationSender = self.GetOrCreate(entityId);
|
||||
|
||||
Scene root = self.Root();
|
||||
|
||||
if (actorLocationSender.ActorId != default)
|
||||
{
|
||||
actorLocationSender.LastSendOrRecvTime = self.Fiber().TimeInfo.ServerNow();
|
||||
return await root.GetComponent<ActorSenderComponent>().Call(actorLocationSender.ActorId, request);
|
||||
}
|
||||
|
||||
long instanceId = actorLocationSender.InstanceId;
|
||||
|
||||
int coroutineLockType = (self.LocationType << 16) | CoroutineLockType.ActorLocationSender;
|
||||
using (await root.Fiber.CoroutineLockComponent.Wait(coroutineLockType, entityId))
|
||||
{
|
||||
if (actorLocationSender.InstanceId != instanceId)
|
||||
{
|
||||
throw new RpcException(ErrorCore.ERR_ActorTimeout, $"{request}");
|
||||
}
|
||||
|
||||
if (actorLocationSender.ActorId == default)
|
||||
{
|
||||
actorLocationSender.ActorId = await root.GetComponent<LocationProxyComponent>().Get(self.LocationType, actorLocationSender.Id);
|
||||
if (actorLocationSender.InstanceId != instanceId)
|
||||
{
|
||||
throw new RpcException(ErrorCore.ERR_ActorLocationSenderTimeout2, $"{request}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
actorLocationSender.LastSendOrRecvTime = self.Fiber().TimeInfo.ServerNow();
|
||||
return await root.GetComponent<ActorSenderComponent>().Call(actorLocationSender.ActorId, request);
|
||||
}
|
||||
|
||||
public static void Send(this ActorLocationSenderOneType self, long entityId, IActorLocationMessage message)
|
||||
{
|
||||
self.Call(entityId, message).Coroutine();
|
||||
}
|
||||
|
||||
public static async ETTask<IActorResponse> Call(this ActorLocationSenderOneType self, long entityId, IActorLocationRequest iActorRequest)
|
||||
{
|
||||
ActorLocationSender actorLocationSender = self.GetOrCreate(entityId);
|
||||
|
||||
Scene root = self.Root();
|
||||
|
||||
int rpcId = root.GetComponent<ActorSenderComponent>().GetRpcId();
|
||||
iActorRequest.RpcId = rpcId;
|
||||
|
||||
long actorLocationSenderInstanceId = actorLocationSender.InstanceId;
|
||||
int coroutineLockType = (self.LocationType << 16) | CoroutineLockType.ActorLocationSender;
|
||||
using (await root.Fiber.CoroutineLockComponent.Wait(coroutineLockType, entityId))
|
||||
{
|
||||
if (actorLocationSender.InstanceId != actorLocationSenderInstanceId)
|
||||
{
|
||||
throw new RpcException(ErrorCore.ERR_ActorTimeout, $"{iActorRequest}");
|
||||
}
|
||||
|
||||
// 队列中没处理的消息返回跟上个消息一样的报错
|
||||
if (actorLocationSender.Error == ErrorCore.ERR_NotFoundActor)
|
||||
{
|
||||
return ActorHelper.CreateResponse(iActorRequest, actorLocationSender.Error);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
return await self.CallInner(actorLocationSender, rpcId, iActorRequest);
|
||||
}
|
||||
catch (RpcException)
|
||||
{
|
||||
self.Remove(actorLocationSender.Id);
|
||||
throw;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
self.Remove(actorLocationSender.Id);
|
||||
throw new Exception($"{iActorRequest}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static async ETTask<IActorResponse> CallInner(this ActorLocationSenderOneType self, ActorLocationSender actorLocationSender, int rpcId, IActorRequest iActorRequest)
|
||||
{
|
||||
int failTimes = 0;
|
||||
long instanceId = actorLocationSender.InstanceId;
|
||||
actorLocationSender.LastSendOrRecvTime = self.Fiber().TimeInfo.ServerNow();
|
||||
|
||||
Scene root = self.Root();
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (actorLocationSender.ActorId == default)
|
||||
{
|
||||
actorLocationSender.ActorId = await root.GetComponent<LocationProxyComponent>().Get(self.LocationType, actorLocationSender.Id);
|
||||
if (actorLocationSender.InstanceId != instanceId)
|
||||
{
|
||||
throw new RpcException(ErrorCore.ERR_ActorLocationSenderTimeout2, $"{iActorRequest}");
|
||||
}
|
||||
}
|
||||
|
||||
if (actorLocationSender.ActorId == default)
|
||||
{
|
||||
actorLocationSender.Error = ErrorCore.ERR_NotFoundActor;
|
||||
return ActorHelper.CreateResponse(iActorRequest, ErrorCore.ERR_NotFoundActor);
|
||||
}
|
||||
IActorResponse response = await root.GetComponent<ActorSenderComponent>().Call(actorLocationSender.ActorId, rpcId, iActorRequest, needException: false);
|
||||
|
||||
if (actorLocationSender.InstanceId != instanceId)
|
||||
{
|
||||
throw new RpcException(ErrorCore.ERR_ActorLocationSenderTimeout3, $"{iActorRequest}");
|
||||
}
|
||||
|
||||
switch (response.Error)
|
||||
{
|
||||
case ErrorCore.ERR_NotFoundActor:
|
||||
{
|
||||
// 如果没找到Actor,重试
|
||||
++failTimes;
|
||||
if (failTimes > 20)
|
||||
{
|
||||
Log.Debug($"actor send message fail, actorid: {actorLocationSender.Id} {iActorRequest}");
|
||||
actorLocationSender.Error = ErrorCore.ERR_NotFoundActor;
|
||||
// 这里不能删除actor,要让后面等待发送的消息也返回ERR_NotFoundActor,直到超时删除
|
||||
return response;
|
||||
}
|
||||
|
||||
// 等待0.5s再发送
|
||||
await root.Fiber.TimerComponent.WaitAsync(500);
|
||||
if (actorLocationSender.InstanceId != instanceId)
|
||||
{
|
||||
throw new RpcException(ErrorCore.ERR_ActorLocationSenderTimeout4, $"{iActorRequest}");
|
||||
}
|
||||
|
||||
actorLocationSender.ActorId = default;
|
||||
continue;
|
||||
}
|
||||
case ErrorCore.ERR_ActorTimeout:
|
||||
{
|
||||
throw new RpcException(response.Error, $"{iActorRequest}");
|
||||
}
|
||||
}
|
||||
|
||||
if (ErrorCore.IsRpcNeedThrowException(response.Error))
|
||||
{
|
||||
throw new RpcException(response.Error, $"Message: {response.Message} Request: {iActorRequest}");
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[EntitySystemOf(typeof(ActorLocationSenderComponent))]
|
||||
[FriendOf(typeof (ActorLocationSenderComponent))]
|
||||
public static partial class ActorLocationSenderManagerComponentSystem
|
||||
{
|
||||
[EntitySystem]
|
||||
private static void Awake(this ActorLocationSenderComponent self)
|
||||
{
|
||||
for (int i = 0; i < self.ActorLocationSenderComponents.Length; ++i)
|
||||
{
|
||||
self.ActorLocationSenderComponents[i] = self.AddChild<ActorLocationSenderOneType, int>(i);
|
||||
}
|
||||
}
|
||||
|
||||
public static ActorLocationSenderOneType Get(this ActorLocationSenderComponent self, int locationType)
|
||||
{
|
||||
return self.ActorLocationSenderComponents[locationType];
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d9c5b5f290f9eb049a98efe57de93c0e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,26 @@
|
||||
using System;
|
||||
|
||||
namespace ET.Server
|
||||
{
|
||||
[EntitySystemOf(typeof(ActorLocationSender))]
|
||||
[FriendOf(typeof(ActorLocationSender))]
|
||||
public static partial class ActorLocationSenderSystem
|
||||
{
|
||||
[EntitySystem]
|
||||
private static void Awake(this ActorLocationSender self)
|
||||
{
|
||||
self.LastSendOrRecvTime = self.Fiber().TimeInfo.ServerNow();
|
||||
self.ActorId = default;
|
||||
self.Error = 0;
|
||||
}
|
||||
|
||||
[EntitySystem]
|
||||
private static void Destroy(this ActorLocationSender self)
|
||||
{
|
||||
Log.Debug($"actor location remove: {self.Id}");
|
||||
self.LastSendOrRecvTime = 0;
|
||||
self.ActorId = default;
|
||||
self.Error = 0;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c78fb4596a5212845bde1ec4757efa39
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,96 @@
|
||||
using System;
|
||||
|
||||
namespace ET.Server
|
||||
{
|
||||
[EnableClass]
|
||||
public abstract class ActorMessageLocationHandler<E, Message>: IMActorHandler where E : Entity where Message : class, IActorLocationMessage
|
||||
{
|
||||
protected abstract ETTask Run(E entity, Message message);
|
||||
|
||||
public async ETTask Handle(Entity entity, Address fromAddress, MessageObject actorMessage)
|
||||
{
|
||||
if (actorMessage is not Message message)
|
||||
{
|
||||
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).FullName} --{typeof (Message).FullName}");
|
||||
return;
|
||||
}
|
||||
|
||||
ActorResponse response = new() {RpcId = message.RpcId};
|
||||
entity.Root().GetComponent<ActorInnerComponent>().Reply(fromAddress, response);
|
||||
|
||||
await this.Run(e, message);
|
||||
}
|
||||
|
||||
public Type GetRequestType()
|
||||
{
|
||||
return typeof (Message);
|
||||
}
|
||||
|
||||
public Type GetResponseType()
|
||||
{
|
||||
return typeof (ActorResponse);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
[EnableClass]
|
||||
public abstract class ActorMessageLocationHandler<E, Request, Response>: IMActorHandler where E : Entity where Request : MessageObject, IActorLocationRequest where Response : MessageObject, IActorLocationResponse
|
||||
{
|
||||
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()
|
||||
{
|
||||
return typeof (Request);
|
||||
}
|
||||
|
||||
public Type GetResponseType()
|
||||
{
|
||||
return typeof (Response);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1366e4041bf79d1468b108c582082181
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,21 @@
|
||||
using System.Net;
|
||||
|
||||
namespace ET.Server
|
||||
{
|
||||
[Invoke((long)SceneType.Location)]
|
||||
public class FiberInit_Location: 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>();
|
||||
root.AddComponent<ActorSenderComponent>();
|
||||
root.AddComponent<LocationManagerComoponent>();
|
||||
|
||||
await ETTask.CompletedTask;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: dfa61d7b9671c944c8edbcfffc94b189
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,137 @@
|
||||
using System;
|
||||
|
||||
namespace ET.Server
|
||||
{
|
||||
[EntitySystemOf(typeof(LockInfo))]
|
||||
[FriendOf(typeof(LockInfo))]
|
||||
public static partial class LockInfoSystem
|
||||
{
|
||||
[EntitySystem]
|
||||
private static void Awake(this LockInfo self, ActorId lockActorId, CoroutineLock coroutineLock)
|
||||
{
|
||||
self.CoroutineLock = coroutineLock;
|
||||
self.LockActorId = lockActorId;
|
||||
}
|
||||
|
||||
[EntitySystem]
|
||||
private static void Destroy(this LockInfo self)
|
||||
{
|
||||
self.CoroutineLock.Dispose();
|
||||
self.LockActorId = default;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[EntitySystemOf(typeof(LocationOneType))]
|
||||
[FriendOf(typeof(LocationOneType))]
|
||||
[FriendOf(typeof(LockInfo))]
|
||||
public static partial class LocationOneTypeSystem
|
||||
{
|
||||
[EntitySystem]
|
||||
private static void Awake(this LocationOneType self, int locationType)
|
||||
{
|
||||
self.LocationType = locationType;
|
||||
}
|
||||
|
||||
public static async ETTask Add(this LocationOneType self, long key, ActorId instanceId)
|
||||
{
|
||||
int coroutineLockType = (self.LocationType << 16) | CoroutineLockType.Location;
|
||||
using (await self.Fiber().CoroutineLockComponent.Wait(coroutineLockType, key))
|
||||
{
|
||||
self.locations[key] = instanceId;
|
||||
Log.Info($"location add key: {key} instanceId: {instanceId}");
|
||||
}
|
||||
}
|
||||
|
||||
public static async ETTask Remove(this LocationOneType self, long key)
|
||||
{
|
||||
int coroutineLockType = (self.LocationType << 16) | CoroutineLockType.Location;
|
||||
using (await self.Fiber().CoroutineLockComponent.Wait(coroutineLockType, key))
|
||||
{
|
||||
self.locations.Remove(key);
|
||||
Log.Info($"location remove key: {key}");
|
||||
}
|
||||
}
|
||||
|
||||
public static async ETTask Lock(this LocationOneType self, long key, ActorId actorId, int time = 0)
|
||||
{
|
||||
int coroutineLockType = (self.LocationType << 16) | CoroutineLockType.Location;
|
||||
CoroutineLock coroutineLock = await self.Fiber().CoroutineLockComponent.Wait(coroutineLockType, key);
|
||||
|
||||
LockInfo lockInfo = self.AddChild<LockInfo, ActorId, CoroutineLock>(actorId, coroutineLock);
|
||||
self.lockInfos.Add(key, lockInfo);
|
||||
|
||||
Log.Info($"location lock key: {key} instanceId: {actorId}");
|
||||
|
||||
if (time > 0)
|
||||
{
|
||||
async ETTask TimeWaitAsync()
|
||||
{
|
||||
long lockInfoInstanceId = lockInfo.InstanceId;
|
||||
await self.Fiber().TimerComponent.WaitAsync(time);
|
||||
if (lockInfo.InstanceId != lockInfoInstanceId)
|
||||
{
|
||||
return;
|
||||
}
|
||||
Log.Info($"location timeout unlock key: {key} instanceId: {actorId} newInstanceId: {actorId}");
|
||||
self.UnLock(key, actorId, actorId);
|
||||
}
|
||||
TimeWaitAsync().Coroutine();
|
||||
}
|
||||
}
|
||||
|
||||
public static void UnLock(this LocationOneType self, long key, ActorId oldActorId, ActorId newInstanceId)
|
||||
{
|
||||
if (!self.lockInfos.TryGetValue(key, out LockInfo lockInfo))
|
||||
{
|
||||
Log.Error($"location unlock not found key: {key} {oldActorId}");
|
||||
return;
|
||||
}
|
||||
|
||||
if (oldActorId != lockInfo.LockActorId)
|
||||
{
|
||||
Log.Error($"location unlock oldInstanceId is different: {key} {oldActorId}");
|
||||
return;
|
||||
}
|
||||
|
||||
Log.Info($"location unlock key: {key} instanceId: {oldActorId} newInstanceId: {newInstanceId}");
|
||||
|
||||
self.locations[key] = newInstanceId;
|
||||
|
||||
self.lockInfos.Remove(key);
|
||||
|
||||
// 解锁
|
||||
lockInfo.Dispose();
|
||||
}
|
||||
|
||||
public static async ETTask<ActorId> Get(this LocationOneType self, long key)
|
||||
{
|
||||
int coroutineLockType = (self.LocationType << 16) | CoroutineLockType.Location;
|
||||
using (await self.Fiber().CoroutineLockComponent.Wait(coroutineLockType, key))
|
||||
{
|
||||
self.locations.TryGetValue(key, out ActorId actorId);
|
||||
Log.Info($"location get key: {key} actorId: {actorId}");
|
||||
return actorId;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[EntitySystemOf(typeof(LocationManagerComoponent))]
|
||||
[FriendOf(typeof (LocationManagerComoponent))]
|
||||
public static partial class LocationComoponentSystem
|
||||
{
|
||||
[EntitySystem]
|
||||
private static void Awake(this LocationManagerComoponent self)
|
||||
{
|
||||
for (int i = 0; i < self.LocationOneTypes.Length; ++i)
|
||||
{
|
||||
self.LocationOneTypes[i] = self.AddChild<LocationOneType, int>(i);
|
||||
}
|
||||
}
|
||||
|
||||
public static LocationOneType Get(this LocationManagerComoponent self, int locationType)
|
||||
{
|
||||
return self.LocationOneTypes[locationType];
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c4a35bb25143640b1a80652d551b4ce9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,64 @@
|
||||
using System;
|
||||
|
||||
namespace ET.Server
|
||||
{
|
||||
public static partial class LocationProxyComponentSystem
|
||||
{
|
||||
private static ActorId GetLocationSceneId(long key)
|
||||
{
|
||||
return StartSceneConfigCategory.Instance.LocationConfig.ActorId;
|
||||
}
|
||||
|
||||
public static async ETTask Add(this LocationProxyComponent self, int type, long key, ActorId actorId)
|
||||
{
|
||||
Log.Info($"location proxy add {key}, {actorId} {self.Fiber().TimeInfo.ServerNow()}");
|
||||
await self.Root().GetComponent<ActorSenderComponent>().Call(GetLocationSceneId(key),
|
||||
new ObjectAddRequest() { Type = type, Key = key, ActorId = actorId });
|
||||
}
|
||||
|
||||
public static async ETTask Lock(this LocationProxyComponent self, int type, long key, ActorId actorId, int time = 60000)
|
||||
{
|
||||
Log.Info($"location proxy lock {key}, {actorId} {self.Fiber().TimeInfo.ServerNow()}");
|
||||
await self.Root().GetComponent<ActorSenderComponent>().Call(GetLocationSceneId(key),
|
||||
new ObjectLockRequest() { Type = type, Key = key, ActorId = actorId, Time = time });
|
||||
}
|
||||
|
||||
public static async ETTask UnLock(this LocationProxyComponent self, int type, long key, ActorId oldActorId, ActorId newActorId)
|
||||
{
|
||||
Log.Info($"location proxy unlock {key}, {newActorId} {self.Fiber().TimeInfo.ServerNow()}");
|
||||
await self.Root().GetComponent<ActorSenderComponent>().Call(GetLocationSceneId(key),
|
||||
new ObjectUnLockRequest() { Type = type, Key = key, OldActorId = oldActorId, NewActorId = newActorId });
|
||||
}
|
||||
|
||||
public static async ETTask Remove(this LocationProxyComponent self, int type, long key)
|
||||
{
|
||||
Log.Info($"location proxy add {key}, {self.Fiber().TimeInfo.ServerNow()}");
|
||||
await self.Root().GetComponent<ActorSenderComponent>().Call(GetLocationSceneId(key),
|
||||
new ObjectRemoveRequest() { Type = type, Key = key });
|
||||
}
|
||||
|
||||
public static async ETTask<ActorId> Get(this LocationProxyComponent self, int type, long key)
|
||||
{
|
||||
if (key == 0)
|
||||
{
|
||||
throw new Exception($"get location key 0");
|
||||
}
|
||||
|
||||
// location server配置到共享区,一个大战区可以配置N多个location server,这里暂时为1
|
||||
ObjectGetResponse response =
|
||||
(ObjectGetResponse) await self.Root().GetComponent<ActorSenderComponent>().Call(GetLocationSceneId(key),
|
||||
new ObjectGetRequest() { Type = type, Key = key });
|
||||
return response.ActorId;
|
||||
}
|
||||
|
||||
public static async ETTask AddLocation(this Entity self, int type)
|
||||
{
|
||||
await self.Root().GetComponent<LocationProxyComponent>().Add(type, self.Id, self.GetActorId());
|
||||
}
|
||||
|
||||
public static async ETTask RemoveLocation(this Entity self, int type)
|
||||
{
|
||||
await self.Root().GetComponent<LocationProxyComponent>().Remove(type, self.Id);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 898ea95a00c4c6442bd0bd8322094277
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,13 @@
|
||||
using System;
|
||||
|
||||
namespace ET.Server
|
||||
{
|
||||
[ActorMessageHandler(SceneType.Location)]
|
||||
public class ObjectAddRequestHandler: ActorMessageHandler<Scene, ObjectAddRequest, ObjectAddResponse>
|
||||
{
|
||||
protected override async ETTask Run(Scene scene, ObjectAddRequest request, ObjectAddResponse response)
|
||||
{
|
||||
await scene.GetComponent<LocationManagerComoponent>().Get(request.Type).Add(request.Key, request.ActorId);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0f6c2757c99f36b459abe314a571260c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,13 @@
|
||||
using System;
|
||||
|
||||
namespace ET.Server
|
||||
{
|
||||
[ActorMessageHandler(SceneType.Location)]
|
||||
public class ObjectGetRequestHandler: ActorMessageHandler<Scene, ObjectGetRequest, ObjectGetResponse>
|
||||
{
|
||||
protected override async ETTask Run(Scene scene, ObjectGetRequest request, ObjectGetResponse response)
|
||||
{
|
||||
response.ActorId = await scene.GetComponent<LocationManagerComoponent>().Get(request.Type).Get(request.Key);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7c7646f47e2c7394ba566e5fda9cd3dc
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,13 @@
|
||||
using System;
|
||||
|
||||
namespace ET.Server
|
||||
{
|
||||
[ActorMessageHandler(SceneType.Location)]
|
||||
public class ObjectLockRequestHandler: ActorMessageHandler<Scene, ObjectLockRequest, ObjectLockResponse>
|
||||
{
|
||||
protected override async ETTask Run(Scene scene, ObjectLockRequest request, ObjectLockResponse response)
|
||||
{
|
||||
await scene.GetComponent<LocationManagerComoponent>().Get(request.Type).Lock(request.Key, request.ActorId, request.Time);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4be989f429e198044aec36d3fbfef1f7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,13 @@
|
||||
using System;
|
||||
|
||||
namespace ET.Server
|
||||
{
|
||||
[ActorMessageHandler(SceneType.Location)]
|
||||
public class ObjectRemoveRequestHandler: ActorMessageHandler<Scene, ObjectRemoveRequest, ObjectRemoveResponse>
|
||||
{
|
||||
protected override async ETTask Run(Scene scene, ObjectRemoveRequest request, ObjectRemoveResponse response)
|
||||
{
|
||||
await scene.GetComponent<LocationManagerComoponent>().Get(request.Type).Remove(request.Key);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9d16c6c9a7661cc4389e5b14d72ff25d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,15 @@
|
||||
using System;
|
||||
|
||||
namespace ET.Server
|
||||
{
|
||||
[ActorMessageHandler(SceneType.Location)]
|
||||
public class ObjectUnLockRequestHandler: ActorMessageHandler<Scene, ObjectUnLockRequest, ObjectUnLockResponse>
|
||||
{
|
||||
protected override async ETTask Run(Scene scene, ObjectUnLockRequest request, ObjectUnLockResponse response)
|
||||
{
|
||||
scene.GetComponent<LocationManagerComoponent>().Get(request.Type).UnLock(request.Key, request.OldActorId, request.NewActorId);
|
||||
|
||||
await ETTask.CompletedTask;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 77b92c4f020a77b4b98b215b660cfe3b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Reference in New Issue
Block a user