ActorComponent.cs 2.5 KB
Newer Older
1
using System;
2 3
using System.Collections.Generic;
using System.Threading.Tasks;
4 5 6

namespace Model
{
7 8 9
	public struct ActorMessageInfo
	{
		public Session Session;
10
		public ActorRequest Message;
11 12
	}

13
	[ObjectEvent]
14
	public class ActorComponentEvent : ObjectEvent<ActorComponent>, IAwake, IAwake<IEntityActorHandler>, IStart
15
	{
16 17 18 19 20
		public void Awake()
		{
			this.Get().Awake();
		}

21
		public void Awake(IEntityActorHandler iEntityActorHandler)
22
		{
23
			this.Get().Awake(iEntityActorHandler);
24
		}
25 26 27 28 29

		public void Start()
		{
			this.Get().Start();
		}
30 31 32
	}

	/// <summary>
33
	/// 挂上这个组件表示该Entity是一个Actor, 它会将Entity位置注册到Location Server, 接收的消息将会队列处理
34 35 36
	/// </summary>
	public class ActorComponent: Component
	{
37 38
		private IEntityActorHandler entityActorHandler;

39 40
		private long actorId;

41
		// 队列处理消息
42
		private readonly EQueue<ActorMessageInfo> queue = new EQueue<ActorMessageInfo>();
43 44 45

		private TaskCompletionSource<ActorMessageInfo> tcs;

46
		public void Awake()
47
		{
48 49
			this.entityActorHandler = new CommonEntityActorHandler();
		}
50

51 52 53 54 55 56 57
		public void Awake(IEntityActorHandler iEntityActorHandler)
		{
			this.entityActorHandler = iEntityActorHandler;
		}
		
		public async void Start()
		{
58 59
			this.actorId = this.Entity.Id;
			Game.Scene.GetComponent<ActorManagerComponent>().Add(this.Entity);
60
			await Game.Scene.GetComponent<LocationProxyComponent>().Add(this.actorId);
61 62 63 64 65 66
			this.HandleAsync();
		}

		public void Add(ActorMessageInfo info)
		{
			this.queue.Enqueue(info);
67
			
68 69 70 71
			if (this.tcs == null)
			{
				return;
			}
72 73

			var t = this.tcs;
74
			this.tcs = null;
75
			t.SetResult(this.queue.Dequeue());
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
		}

		private Task<ActorMessageInfo> GetAsync()
		{
			if (this.queue.Count > 0)
			{
				return Task.FromResult(this.queue.Dequeue());
			}

			this.tcs = new TaskCompletionSource<ActorMessageInfo>();
			return this.tcs.Task;
		}

		private async void HandleAsync()
		{
			while (true)
92
			{
93 94 95
				try
				{
					ActorMessageInfo info = await this.GetAsync();
96
					await this.entityActorHandler.Handle(info.Session, this.Entity, info.Message);
97 98 99 100 101
				}
				catch (Exception e)
				{
					Log.Error(e.ToString());
				}
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
			}
		}

		public override async void Dispose()
		{
			try
			{
				if (this.Id == 0)
				{
					return;
				}

				base.Dispose();

				Game.Scene.GetComponent<ActorManagerComponent>().Remove(actorId);

				await Game.Scene.GetComponent<LocationProxyComponent>().Remove(this.actorId);
			}
120
			catch (Exception)
121
			{
122
				Log.Error($"unregister actor fail: {this.actorId}");
123 124 125 126
			}
		}
	}
}