提交 8ab531a1 编写于 作者: T tanghai

修改事件接口,不再使用Env传事件参数

上级 bbe269f6
......@@ -39,6 +39,7 @@
</ItemGroup>
<ItemGroup>
<Compile Include="AddressHelper.cs" />
<Compile Include="Event\SleepTimeoutEvent.cs" />
<Compile Include="Event\BuffTimeoutEvent.cs" />
<Compile Include="BehaviorTreeNode\Not.cs" />
<Compile Include="BehaviorTreeNode\Selector.cs" />
......
......@@ -4,9 +4,9 @@ using MongoDB.Bson;
namespace Controller
{
[Event(EventType.BuffTimeout, ServerType.City)]
public class BuffTimeoutEvent: IEvent
public class BuffTimeoutEvent: AEvent<Env>
{
public void Run(Env env)
public override void Run(Env env)
{
Unit owner = World.Instance.GetComponent<UnitComponent>().Get(env.Get<ObjectId>(EnvKey.OwnerId));
if (owner == null)
......
using System.Threading.Tasks;
using Model;
namespace Controller
{
[Event(EventType.SleepTimeout, ServerType.City)]
public class SleepTimeoutEvent_RunTcs : AEvent<Env>
{
public override void Run(Env env)
{
TaskCompletionSource<bool> tcs =
env.Get<TaskCompletionSource<bool>>(EnvKey.SleepTimeout_TaskCompletionSource);
tcs.SetResult(true);
}
}
}
\ No newline at end of file
......@@ -62,13 +62,13 @@ namespace Model
env[EnvKey.Owner] = this.Owner;
env[EnvKey.Buff] = buff;
World.Instance.GetComponent<EventComponent<EventAttribute>>().Run(EventType.BeforeAddBuff, env);
World.Instance.GetComponent<EventComponent<EventAttribute>>().RunAsync(EventType.BeforeAddBuff, env);
this.buffs.Add(buff);
this.idBuff.Add(buff.Id, buff);
this.typeBuff.Add(buff.Config.Type, buff);
World.Instance.GetComponent<EventComponent<EventAttribute>>().Run(EventType.AfterAddBuff, env);
World.Instance.GetComponent<EventComponent<EventAttribute>>().RunAsync(EventType.AfterAddBuff, env);
}
public Buff GetById(ObjectId id)
......@@ -103,13 +103,13 @@ namespace Model
env[EnvKey.Buff] = buff;
World.Instance.GetComponent<EventComponent<EventAttribute>>()
.Run(EventType.BeforeRemoveBuff, env);
.RunAsync(EventType.BeforeRemoveBuff, env);
this.buffs.Remove(buff);
this.idBuff.Remove(buff.Id);
this.typeBuff.Remove(buff.Config.Type, buff);
World.Instance.GetComponent<EventComponent<EventAttribute>>().Run(EventType.AfterRemoveBuff, env);
World.Instance.GetComponent<EventComponent<EventAttribute>>().RunAsync(EventType.AfterRemoveBuff, env);
buff.Dispose();
}
......
......@@ -3,19 +3,18 @@ using System.Collections.Generic;
using System.Reflection;
using System.Threading.Tasks;
using Common.Base;
using Common.Logger;
namespace Model
{
public class EventComponent<AttributeType>: Component<World>, IAssemblyLoader
where AttributeType : AEventAttribute
{
private Dictionary<EventType, List<IEvent>> eventSyncs;
private Dictionary<EventType, List<IEventAsync>> eventAsyncs;
private Dictionary<EventType, List<object>> allEvents;
public void Load(Assembly assembly)
{
this.eventSyncs = new Dictionary<EventType, List<IEvent>>();
this.eventAsyncs = new Dictionary<EventType, List<IEventAsync>>();
this.allEvents = new Dictionary<EventType, List<object>>();
ServerType serverType = World.Instance.Options.ServerType;
......@@ -35,76 +34,180 @@ namespace Model
}
object obj = Activator.CreateInstance(t);
IEvent iEvent = obj as IEvent;
if (iEvent != null)
if (obj == null)
{
if (!this.eventSyncs.ContainsKey(aEventAttribute.Type))
throw new Exception(string.Format("event not inherit IEvent or IEventAsync interface: {0}",
obj.GetType().FullName));
}
if (!this.allEvents.ContainsKey(aEventAttribute.Type))
{
this.allEvents.Add(aEventAttribute.Type, new List<object>());
}
this.allEvents[aEventAttribute.Type].Add(obj);
}
}
public async Task RunAsync(EventType type)
{
List<object> iEvents = null;
if (!this.allEvents.TryGetValue(type, out iEvents))
{
return;
}
foreach (object obj in iEvents)
{
try
{
AEvent iEvent = obj as AEvent;
if (iEvent == null)
{
this.eventSyncs.Add(aEventAttribute.Type, new List<IEvent>());
throw new GameException(string.Format("event type: {0} is not IEvent", type));
}
this.eventSyncs[aEventAttribute.Type].Add(iEvent);
continue;
iEvent.Run();
await iEvent.RunAsync();
}
catch (Exception err)
{
Log.Debug(err.ToString());
}
}
}
IEventAsync iEventAsync = obj as IEventAsync;
// ReSharper disable once InvertIf
if (iEventAsync != null)
public async Task RunAsync<A>(EventType type, A a)
{
List<object> iEvents = null;
if (!this.allEvents.TryGetValue(type, out iEvents))
{
return;
}
foreach (object obj in iEvents)
{
try
{
if (!this.eventAsyncs.ContainsKey(aEventAttribute.Type))
AEvent<A> iEvent = obj as AEvent<A>;
if (iEvent == null)
{
this.eventAsyncs.Add(aEventAttribute.Type, new List<IEventAsync>());
throw new GameException(string.Format("event type: {0} is not IEvent<{1}>", type, typeof(A).Name));
}
this.eventAsyncs[aEventAttribute.Type].Add(iEventAsync);
continue;
iEvent.Run(a);
await iEvent.RunAsync(a);
}
catch (Exception err)
{
Log.Debug(err.ToString());
}
throw new Exception(string.Format("event not inherit IEvent or IEventAsync interface: {0}",
obj.GetType().FullName));
}
}
public void Run(EventType type, Env env)
public async Task RunAsync<A, B>(EventType type, A a, B b)
{
List<IEvent> iEventSyncs = null;
if (!this.eventSyncs.TryGetValue(type, out iEventSyncs))
List<object> iEvents = null;
if (!this.allEvents.TryGetValue(type, out iEvents))
{
throw new Exception(string.Format("no event handler, AttributeType: {0} type: {1}",
typeof (AttributeType).Name, type));
return;
}
foreach (IEvent iEventSync in iEventSyncs)
foreach (object obj in iEvents)
{
iEventSync.Run(env);
try
{
AEvent<A, B> iEvent = obj as AEvent<A, B>;
if (iEvent == null)
{
throw new GameException(string.Format("event type: {0} is not IEvent<{1}, {2}>", type, typeof(A).Name, typeof(B).Name));
}
iEvent.Run(a, b);
await iEvent.RunAsync(a, b);
}
catch (Exception err)
{
Log.Debug(err.ToString());
}
}
}
public async Task RunAsync(EventType type, Env env)
public async Task RunAsync<A, B, C>(EventType type, A a, B b, C c)
{
List<IEvent> iEventSyncs = null;
this.eventSyncs.TryGetValue(type, out iEventSyncs);
List<object> iEvents = null;
if (!this.allEvents.TryGetValue(type, out iEvents))
{
return;
}
List<IEventAsync> iEventAsyncs = null;
this.eventAsyncs.TryGetValue(type, out iEventAsyncs);
foreach (object obj in iEvents)
{
try
{
AEvent<A, B, C> iEvent = obj as AEvent<A, B, C>;
if (iEvent == null)
{
throw new GameException(string.Format("event type: {0} is not IEvent<{1}, {2}, {3}>", type,
typeof(A).Name, typeof(B).Name, typeof(C).Name));
}
iEvent.Run(a, b, c);
await iEvent.RunAsync(a, b, c);
}
catch (Exception err)
{
Log.Debug(err.ToString());
}
}
}
if (iEventSyncs == null && iEventAsyncs == null)
public async Task RunAsync<A, B, C, D>(EventType type, A a, B b, C c, D d)
{
List<object> iEvents = null;
if (!this.allEvents.TryGetValue(type, out iEvents))
{
throw new Exception(string.Format("no event handler, AttributeType: {0} type: {1}",
typeof (AttributeType).Name, type));
return;
}
if (iEventSyncs != null)
foreach (object obj in iEvents)
{
foreach (IEvent iEventSync in iEventSyncs)
try
{
iEventSync.Run(env);
AEvent<A, B, C, D> iEvent = obj as AEvent<A, B, C, D>;
if (iEvent == null)
{
throw new GameException(string.Format("event type: {0} is not IEvent<{1}, {2}, {3}, {4}>", type,
typeof(A).Name, typeof(B).Name, typeof(C).Name, typeof(D).Name));
}
iEvent.Run(a, b, c, d);
await iEvent.RunAsync(a, b, c, d);
}
catch (Exception err)
{
Log.Debug(err.ToString());
}
}
}
public async Task RunAsync<A, B, C, D, E>(EventType type, A a, B b, C c, D d, E e)
{
List<object> iEvents = null;
if (!this.allEvents.TryGetValue(type, out iEvents))
{
return;
}
if (iEventAsyncs != null)
foreach (object obj in iEvents)
{
foreach (IEventAsync iEventAsync in iEventAsyncs)
try
{
AEvent<A, B, C, D, E> iEvent = obj as AEvent<A, B, C, D, E>;
if (iEvent == null)
{
throw new GameException(string.Format("event type: {0} is not IEvent<{1}, {2}, {3}, {4}, {5}>", type,
typeof(A).Name, typeof(B).Name, typeof(C).Name, typeof(D).Name, typeof(E).Name));
}
iEvent.Run(a, b, c, d, e);
await iEvent.RunAsync(a, b, c, d, e);
}
catch (Exception err)
{
await iEventAsync.RunAsync(env);
Log.Debug(err.ToString());
}
}
}
......
......@@ -68,20 +68,15 @@ namespace Model
while (true)
{
byte[] messageBytes = await channel.RecvAsync();
Env env = new Env();
env[EnvKey.Channel] = channel;
env[EnvKey.MessageBytes] = messageBytes;
Opcode opcode = (Opcode)BitConverter.ToUInt16(messageBytes, 0);
env[EnvKey.Opcode] = opcode;
if (!MessageTypeHelper.IsClientMessage(opcode))
if (!OpcodeHelper.IsClientMessage(opcode))
{
continue;
}
#pragma warning disable 4014
World.Instance.GetComponent<EventComponent<EventAttribute>>()
.RunAsync(EventType.GateRecvClientMessage, env);
#pragma warning restore 4014
ObjectId unitId = channel.GetComponent<ChannelUnitInfoComponent>().UnitId;
Actor actor = World.Instance.GetComponent<ActorComponent>().Get(unitId);
actor.Add(messageBytes);
}
}
......
......@@ -109,7 +109,7 @@ namespace Model
}
// 如果是server message(发给client的消息),说明这是gate server,需要根据unitid查到channel,进行发送
if (MessageTypeHelper.IsServerMessage(opcode))
if (OpcodeHelper.IsServerMessage(opcode))
{
byte[] idBuffer = new byte[12];
Array.Copy(messageBytes, 2, idBuffer, 0, 12);
......@@ -176,23 +176,21 @@ namespace Model
var tcs = new TaskCompletionSource<T>();
this.requestCallback[this.requestId] = (messageBytes, status) =>
{
if (status == RpcResponseStatus.Timeout)
switch (status)
{
tcs.SetException(new Exception(
string.Format("rpc timeout {0} {1}", opcode, MongoHelper.ToJson(request))));
return;
}
if (status == RpcResponseStatus.Exception)
{
BinaryFormatter formatter = new BinaryFormatter(null, new StreamingContext(StreamingContextStates.All));
Exception exception;
using (MemoryStream stream = new MemoryStream(messageBytes))
{
stream.Seek(6, SeekOrigin.Begin);
exception = (Exception)formatter.Deserialize(stream);
}
tcs.SetException(exception);
return;
case RpcResponseStatus.Timeout:
tcs.SetException(new Exception(
string.Format("rpc timeout {0} {1}", opcode, MongoHelper.ToJson(request))));
return;
case RpcResponseStatus.Exception:
BinaryFormatter formatter = new BinaryFormatter(null, new StreamingContext(StreamingContextStates.All));
Exception exception;
using (MemoryStream stream = new MemoryStream(messageBytes, 6, messageBytes.Length - 6))
{
exception = (Exception)formatter.Deserialize(stream);
}
tcs.SetException(exception);
return;
}
// RpcResponseStatus.Succee
......
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Common.Base;
using Common.Helper;
using MongoDB.Bson;
......@@ -21,9 +23,7 @@ namespace Model
/// key: time, value: timer id
/// </summary>
private readonly MultiMap<long, ObjectId> timeId = new MultiMap<long, ObjectId>();
private readonly Queue<long> timeoutTimer = new Queue<long>();
public ObjectId Add(long time, EventType callbackEvent, Env env)
{
Timer timer = new Timer
......@@ -48,31 +48,38 @@ namespace Model
this.timeId.Remove(timer.Time, timer.Id);
}
public Task<bool> Sleep(int time)
{
TaskCompletionSource<bool> tcs = new TaskCompletionSource<bool>();
Env env = new Env();
env[EnvKey.SleepTimeout_TaskCompletionSource] = tcs;
this.Add(TimeHelper.Now() + time, EventType.SleepTimeout, env);
return tcs.Task;
}
public void Update()
{
long timeNow = TimeHelper.Now();
foreach (long time in this.timeId.Keys)
while (true)
{
if (time > timeNow)
KeyValuePair<long, List<ObjectId>> first = this.timeId.First;
if (first.Key > timeNow)
{
break;
return;
}
this.timeoutTimer.Enqueue(time);
}
while (this.timeoutTimer.Count > 0)
{
long key = this.timeoutTimer.Dequeue();
List<ObjectId> timeOutId = this.timeId[key];
foreach (ObjectId id in timeOutId)
List<ObjectId> timeoutId = first.Value;
this.timeId.Remove(first.Key);
foreach (ObjectId id in timeoutId)
{
Timer timer;
if (!this.timers.TryGetValue(id, out timer))
{
continue;
}
this.Remove(id);
World.Instance.GetComponent<EventComponent<EventAttribute>>().Run(timer.CallbackEvent, timer.Env);
this.timers.Remove(id);
World.Instance.GetComponent<EventComponent<EventAttribute>>().RunAsync(timer.CallbackEvent, timer.Env);
}
}
}
......
......@@ -12,5 +12,7 @@
public const string Opcode = "Opcode";
public const string MessageUnitId = "MessageUnitId";
public const string RpcRequestId = "RpcRequestId";
public const string SleepTimeout_TaskCompletionSource = "SleepTimeout_TaskCompletionSource";
}
}
\ No newline at end of file
......@@ -7,9 +7,6 @@
BeforeRemoveBuff = 2,
AfterRemoveBuff = 3,
BuffTimeout = 4,
LogicRecvClientMessage = 5,
LogicRecvRequestMessage = 6,
GateRecvClientMessage = 7,
GateRecvServerMessage = 8,
SleepTimeout = 9,
}
}
\ No newline at end of file
namespace Model
using System.Threading.Tasks;
namespace Model
{
public interface IEvent
public abstract class AEvent
{
void Run(Env env);
public virtual void Run()
{
}
public async virtual Task RunAsync()
{
}
}
public abstract class AEvent<A>
{
public virtual void Run(A a)
{
}
public async virtual Task RunAsync(A a)
{
}
}
public abstract class AEvent<A, B>
{
public virtual void Run(A a, B b)
{
}
public async virtual Task RunAsync(A a, B b)
{
}
}
public abstract class AEvent<A, B, C>
{
public virtual void Run(A a, B b, C c)
{
}
public async virtual Task RunAsync(A a, B b, C c)
{
}
}
public abstract class AEvent<A, B, C, D>
{
public virtual void Run(A a, B b, C c, D d)
{
}
public async virtual Task RunAsync(A a, B b, C c, D d)
{
}
}
public abstract class AEvent<A, B, C, D, E>
{
public virtual void Run(A a, B b, C c, D d, E e)
{
}
public async virtual Task RunAsync(A a, B b, C c, D d, E e)
{
}
}
}
\ No newline at end of file
using System.Threading.Tasks;
namespace Model
{
public interface IEventAsync
{
Task RunAsync(Env env);
}
}
\ No newline at end of file
......@@ -84,7 +84,6 @@
<Compile Include="ICategory.cs" />
<Compile Include="IConfigLoader.cs" />
<Compile Include="IRegister.cs" />
<Compile Include="IEventAsync.cs" />
<Compile Include="IEvent.cs" />
<Compile Include="IFactory.cs" />
<Compile Include="IStart.cs" />
......@@ -93,6 +92,7 @@
<Compile Include="NodeType.cs" />
<Compile Include="Opcode.cs" />
<Compile Include="NumDefine.cs" />
<Compile Include="OpcodeHelper.cs" />
<Compile Include="Options.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="ServerType.cs" />
......
......@@ -6,43 +6,4 @@
RpcResponse = 30000,
RpcException = 30001,
}
public static class MessageTypeHelper
{
public static bool IsClientMessage(Opcode opcode)
{
if ((ushort)opcode > 0 && (ushort)opcode < 10000)
{
return true;
}
return false;
}
public static bool IsServerMessage(Opcode opcode)
{
if ((ushort)opcode > 10000 && (ushort)opcode < 20000)
{
return true;
}
return false;
}
public static bool IsRpcRequestMessage(Opcode opcode)
{
if ((ushort)opcode > 20000 && (ushort)opcode < 30000)
{
return true;
}
return false;
}
public static bool IsRpcResponseMessage(Opcode opcode)
{
if ((ushort)opcode > 30000 && (ushort)opcode < 40000)
{
return true;
}
return false;
}
}
}
\ No newline at end of file
namespace Model
{
public static class OpcodeHelper
{
public static bool IsClientMessage(Opcode opcode)
{
if ((ushort)opcode > 0 && (ushort)opcode < 10000)
{
return true;
}
return false;
}
public static bool IsServerMessage(Opcode opcode)
{
if ((ushort)opcode > 10000 && (ushort)opcode < 20000)
{
return true;
}
return false;
}
public static bool IsRpcRequestMessage(Opcode opcode)
{
if ((ushort)opcode > 20000 && (ushort)opcode < 30000)
{
return true;
}
return false;
}
public static bool IsRpcResponseMessage(Opcode opcode)
{
if ((ushort)opcode > 30000 && (ushort)opcode < 40000)
{
return true;
}
return false;
}
}
}
using System.Collections.Generic;
using System.Linq;
namespace Common.Base
{
......@@ -26,6 +27,14 @@ namespace Common.Base
this.dictionary[t] = list;
}
public KeyValuePair<T, List<K>> First
{
get
{
return dictionary.First();
}
}
public bool Remove(T t, K k)
{
List<K> list;
......
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Common.Helper;
using MongoDB.Bson;
......@@ -20,7 +21,7 @@ namespace Common.Base
/// <summary>
/// key: time, value: timer id
/// </summary>
private readonly MultiMap<long, ObjectId> timeGuid = new MultiMap<long, ObjectId>();
private readonly MultiMap<long, ObjectId> timeId = new MultiMap<long, ObjectId>();
private readonly Queue<long> timeoutTimer = new Queue<long>();
......@@ -28,7 +29,7 @@ namespace Common.Base
{
Timer timer = new Timer { Id = ObjectId.GenerateNewId(), Time = time, Action = action };
this.timers[timer.Id] = timer;
this.timeGuid.Add(timer.Time, timer.Id);
this.timeId.Add(timer.Time, timer.Id);
return timer.Id;
}
......@@ -40,7 +41,7 @@ namespace Common.Base
return;
}
this.timers.Remove(timer.Id);
this.timeGuid.Remove(timer.Time, timer.Id);
this.timeId.Remove(timer.Time, timer.Id);
}
public Task<bool> Sleep(int time)
......@@ -50,30 +51,36 @@ namespace Common.Base
return tcs.Task;
}
public Task<bool> Sleep(int time, CancellationToken token)
{
TaskCompletionSource<bool> tcs = new TaskCompletionSource<bool>();
ObjectId id = this.Add(TimeHelper.Now() + time, () => { tcs.SetResult(true); });
token.Register(() => { this.Remove(id); });
return tcs.Task;
}
public void Refresh()
{
long timeNow = TimeHelper.Now();
foreach (long time in this.timeGuid.Keys)
while (true)
{
if (time > timeNow)
KeyValuePair<long, List<ObjectId>> first = this.timeId.First;
if (first.Key > timeNow)
{
break;
return;
}
this.timeoutTimer.Enqueue(time);
}
while (this.timeoutTimer.Count > 0)
{
long key = this.timeoutTimer.Dequeue();
ObjectId[] timeoutIds = this.timeGuid.GetAll(key);
foreach (ObjectId id in timeoutIds)
List<ObjectId> timeoutId = first.Value;
this.timeId.Remove(first.Key);
foreach (ObjectId id in timeoutId)
{
Timer timer;
if (!this.timers.TryGetValue(id, out timer))
{
continue;
}
this.Remove(id);
this.timers.Remove(id);
timer.Action();
}
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册