Просмотр исходного кода

1.Actor不挂在Unit身上,World上挂一个ActorComponet管理所有的Actor
2.opcode改成ushort类型

tanghai 11 лет назад
Родитель
Сommit
1bddbd0f93

+ 4 - 2
CSharp/Game/Controller/Controller.csproj

@@ -49,9 +49,11 @@
     <Compile Include="ConfigCategory\ServerInfoCategory.cs" />
     <Compile Include="ConfigCategory\UnitCategory.cs" />
     <Compile Include="Event\GateRecvServerMessageEvent.cs" />
-    <Compile Include="Event\LogicRecvMessageEvent.cs" />
+    <Compile Include="Event\LogicRecvRpcMessageEvent.cs" />
+    <Compile Include="Event\LogicRecvClientMessageEvent.cs" />
     <Compile Include="Event\GateRecvClientMessageEvent.cs" />
-    <Compile Include="Factory\UnitFactory.cs" />
+    <Compile Include="Factory\UnitPlayerFactory.cs" />
+    <Compile Include="MessageParseHelper.cs" />
     <Compile Include="Message\CMsgLoginEvent.cs" />
     <Compile Include="NodeType.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />

+ 5 - 9
CSharp/Game/Controller/Event/GateRecvClientMessageEvent.cs

@@ -1,5 +1,4 @@
-using System;
-using Common.Network;
+using Common.Network;
 using Model;
 
 namespace Controller
@@ -9,19 +8,16 @@ namespace Controller
 	{
 		public void Run(Env env)
 		{
-			byte[] message = env.Get<byte[]>(EnvKey.Message);
+			byte[] messageBytes = env.Get<byte[]>(EnvKey.MessageBytes);
 			AChannel channel = env.Get<AChannel>(EnvKey.Channel);
 
 			// 进行消息分发
 			ChannelUnitInfoComponent channelUnitInfoComponent =
 					channel.GetComponent<ChannelUnitInfoComponent>();
-			byte[] idBuffer = channelUnitInfoComponent.UnitId.ToByteArray();
-			byte[] buffer = new byte[message.Length + 12];
-			Array.Copy(message, 0, buffer, 0, 4);
-			Array.Copy(idBuffer, 0, buffer, 4, idBuffer.Length);
-			Array.Copy(message, 4, buffer, 4 + 12, message.Length - 4);
+			byte[] bytes = MessageParseHelper.ClientToGateMessageChangeToLogicMessage(messageBytes,
+					channelUnitInfoComponent.UnitId);
 			string address = AddressHelper.GetAddressByServerName(channelUnitInfoComponent.ServerName);
-			World.Instance.GetComponent<NetworkComponent>().SendAsync(address, buffer);
+			World.Instance.GetComponent<NetworkComponent>().SendAsync(address, bytes);
 		}
 	}
 }

+ 3 - 5
CSharp/Game/Controller/Event/GateRecvServerMessageEvent.cs

@@ -9,14 +9,12 @@ namespace Controller
 	{
 		public void Run(Env env)
 		{
-			byte[] message = env.Get<byte[]>(EnvKey.Message);
+			byte[] messageBytes = env.Get<byte[]>(EnvKey.MessageBytes);
 			byte[] idBuffer = new byte[12];
-			Array.Copy(message, 2, idBuffer, 0, 12);
+			Array.Copy(messageBytes, 2, idBuffer, 0, 12);
 			ObjectId unitId = new ObjectId(idBuffer);
 
-			byte[] buffer = new byte[message.Length - 12];
-			Array.Copy(message, 0, buffer, 0, 2);
-			Array.Copy(message, 14, buffer, 2, message.Length - 14);
+			byte[] buffer = MessageParseHelper.LogicToGateMessageChangeToClientMessage(messageBytes);
 			World.Instance.GetComponent<GateNetworkComponent>().SendAsync(unitId, buffer);
 		}
 	}

+ 22 - 0
CSharp/Game/Controller/Event/LogicRecvClientMessageEvent.cs

@@ -0,0 +1,22 @@
+using Model;
+using MongoDB.Bson;
+
+namespace Controller
+{
+	[Event(EventType.LogicRecvClientMessage, ServerType.All)]
+	public class LogicRecvClientMessageEvent: IEventSync
+	{
+		public void Run(Env env)
+		{
+			byte[] messageBytes = env.Get<byte[]>(EnvKey.MessageBytes);
+			// 如果是客户端消息,转交给unit actor处理
+			MessageParseHelper.LogicParseClientToGateToLogicMessage(messageBytes, env);
+			ObjectId unitId = env.Get<ObjectId>(EnvKey.MessageUnitId);
+			Actor actor = World.Instance.GetComponent<ActorComponent>().Get(unitId);
+			if (actor != null)
+			{
+				actor.Add(env);
+			}
+		}
+	}
+}

+ 0 - 48
CSharp/Game/Controller/Event/LogicRecvMessageEvent.cs

@@ -1,48 +0,0 @@
-using System;
-using System.Threading.Tasks;
-using Common.Network;
-using Model;
-using MongoDB.Bson;
-
-namespace Controller
-{
-	[Event(EventType.LogicRecvMessage, ServerType.All)]
-	public class LogicRecvMessageEvent: IEventAsync
-	{
-		public async Task RunAsync(Env env)
-		{
-			byte[] message = env.Get<byte[]>(EnvKey.Message);
-			AChannel channel = env.Get<AChannel>(EnvKey.Channel);
-			int opcode = BitConverter.ToUInt16(message, 0);
-			// 如果是客户端消息,转交给unit actor处理
-			// 逻辑服收到客户端消息opcode(2) + id(12) + content
-			if (MessageTypeHelper.IsClientMessage(opcode))
-			{
-				byte[] idBuffer = new byte[12];
-				Array.Copy(message, 2, idBuffer, 0, 12);
-				ObjectId unitId = new ObjectId(idBuffer);
-				Unit unit = World.Instance.GetComponent<UnitComponent>().Get(unitId);
-				if (unit != null)
-				{
-					unit.GetComponent<ActorComponent>().Add(env);
-				}
-				return;
-			}
-			
-			try
-			{
-				await World.Instance.GetComponent<EventComponent<MessageAttribute>>().RunAsync(opcode, env);
-			}
-			catch (Exception e)
-			{
-				// 如果是rpc请求,统一处理一下异常
-				if (MessageTypeHelper.IsRpcRequestMessage(opcode))
-				{
-					int id = BitConverter.ToInt32(message, 4);
-					World.Instance.GetComponent<NetworkComponent>().ResponseException(channel, id, 0, e.Message);
-				}
-				throw;
-			}
-		}
-	}
-}

+ 31 - 0
CSharp/Game/Controller/Event/LogicRecvRpcMessageEvent.cs

@@ -0,0 +1,31 @@
+using System;
+using System.Threading.Tasks;
+using Common.Network;
+using Model;
+
+namespace Controller
+{
+	[Event(EventType.LogicRecvRpcMessage, ServerType.All)]
+	public class LogicRecvRpcMessageEventEvent : IEventAsync
+	{
+		public async Task RunAsync(Env env)
+		{
+			byte[] messageBytes = env.Get<byte[]>(EnvKey.MessageBytes);
+			AChannel channel = env.Get<AChannel>(EnvKey.Channel);
+			ushort opcode = env.Get<ushort>(EnvKey.Opcode);
+
+			MessageParseHelper.LogicParseRpcRequestMessage(messageBytes, env);
+			
+			try
+			{
+				await World.Instance.GetComponent<MessageComponent>().RunAsync(opcode, env);
+			}
+			catch (Exception e)
+			{
+				int requestId = env.Get<int>(EnvKey.RpcRequestId);
+				World.Instance.GetComponent<NetworkComponent>().RpcException(channel, requestId, 0, e.Message);
+				throw;
+			}
+		}
+	}
+}

+ 0 - 17
CSharp/Game/Controller/Factory/UnitFactory.cs

@@ -1,17 +0,0 @@
-using Model;
-
-namespace Controller
-{
-	[Factory(typeof (Unit), UnitType.GatePlayer)]
-	public class UnitGatePlayerFactory: IFactory<Unit>
-	{
-		public Unit Create(int configId)
-		{
-			Unit player = new Unit(configId);
-			player.AddComponent<BuffComponent>();
-			player.AddComponent<ActorComponent>();
-			World.Instance.GetComponent<UnitComponent>().Add(player);
-			return player;
-		}
-	}
-}

+ 15 - 0
CSharp/Game/Controller/Factory/UnitPlayerFactory.cs

@@ -0,0 +1,15 @@
+using Model;
+
+namespace Controller
+{
+	[Factory(typeof (Unit), UnitType.GatePlayer)]
+	public class UnitGatePlayerFactory: IFactory<Unit>
+	{
+		public Unit Create(int configId)
+		{
+			Unit gatePlayer = new Unit(configId);
+			World.Instance.GetComponent<UnitComponent>().Add(gatePlayer);
+			return gatePlayer;
+		}
+	}
+}

+ 4 - 6
CSharp/Game/Controller/Message/CMsgLoginEvent.cs

@@ -1,8 +1,7 @@
-using Common.Helper;
-using Common.Network;
+using Common.Network;
 using Model;
 
-namespace Controller.Message
+namespace Controller
 {
 	public class CMsgLogin
 	{
@@ -10,13 +9,12 @@ namespace Controller.Message
 		public byte[] PassMd5 { get; set; }
 	}
 
-	[Message(MessageType.CMsgLogin, ServerType.Realm)]
+	[Message(Opcode.CMsgLogin, typeof(CMsgLogin), ServerType.Gate)]
 	internal class CMsgLoginEvent: IEventSync
 	{
 		public void Run(Env env)
 		{
-			var messageBytes = env.Get<byte[]>(EnvKey.Message);
-			CMsgLogin cmsg = MongoHelper.FromBson<CMsgLogin>(messageBytes, 2);
+			CMsgLogin cmsg = env.Get<CMsgLogin>(EnvKey.Message);
 			Unit unit = World.Instance.GetComponent<FactoryComponent<Unit>>().Create(UnitType.GatePlayer, 1);
 
 			AChannel channel = env.Get<AChannel>(EnvKey.Channel);

+ 67 - 0
CSharp/Game/Controller/MessageParseHelper.cs

@@ -0,0 +1,67 @@
+using System;
+using System.Collections.Generic;
+using System.Reflection.Emit;
+using Common.Helper;
+using Model;
+using MongoDB.Bson;
+
+namespace Controller
+{
+	public static class MessageParseHelper
+	{
+		public static void LogicParseClientToGateToLogicMessage(byte[] message, Env env)
+		{
+			ushort opcode = BitConverter.ToUInt16(message, 0);
+			env[EnvKey.Opcode] = opcode;
+			byte[] bytes = new byte[12];
+			Array.Copy(message, 2, bytes, 0, 12);
+			env[EnvKey.MessageUnitId] = new ObjectId(bytes);
+			Type messageType =
+					World.Instance.GetComponent<MessageComponent>().GetClassType(opcode);
+			env[EnvKey.Message] = MongoHelper.FromBson(messageType, message, 14, message.Length - 14);
+		}
+
+		public static void GateParseClientToGateMessage(byte[] message, Env env)
+		{
+			ushort opcode = BitConverter.ToUInt16(message, 0);
+			env[EnvKey.Opcode] = opcode;
+			Type messageType =
+					World.Instance.GetComponent<MessageComponent>().GetClassType(opcode);
+			env[EnvKey.Message] = MongoHelper.FromBson(messageType, message, 2, message.Length - 2);
+		}
+
+		public static void LogicParseRpcRequestMessage(byte[] message, Env env)
+		{
+			ushort opcode = BitConverter.ToUInt16(message, 0);
+			int requestId = BitConverter.ToInt32(message, 2);
+			env[EnvKey.Opcode] = opcode;
+			env[EnvKey.RpcRequestId] = requestId;
+			Type messageType = World.Instance.GetComponent<MessageComponent>().GetClassType(opcode);
+			env[EnvKey.Message] = MongoHelper.FromBson(messageType, message, 2, message.Length - 2);
+		}
+
+		/// <summary>
+		/// 客户端的消息经gate转发给logic server需要在协议中插入unitid
+		/// </summary>
+		public static byte[] ClientToGateMessageChangeToLogicMessage(byte[] messageBytes, ObjectId id)
+		{
+			byte[] idBuffer = id.ToByteArray();
+			byte[] buffer = new byte[messageBytes.Length + 12];
+			Array.Copy(messageBytes, 0, buffer, 0, 2);
+			Array.Copy(idBuffer, 0, buffer, 2, idBuffer.Length);
+			Array.Copy(messageBytes, 2, buffer, 14, messageBytes.Length - 2);
+			return buffer;
+		}
+
+		/// <summary>
+		/// Logic的消息经gate转发给client,需要在协议中删除unitid
+		/// </summary>
+		public static byte[] LogicToGateMessageChangeToClientMessage(byte[] messageBytes)
+		{
+			byte[] buffer = new byte[messageBytes.Length - 12];
+			Array.Copy(messageBytes, 0, buffer, 0, 2);
+			Array.Copy(messageBytes, 14, buffer, 2, messageBytes.Length - 14);
+			return buffer;
+		}
+	}
+}

+ 74 - 0
CSharp/Game/Model/Actor.cs

@@ -0,0 +1,74 @@
+using System;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using Common.Base;
+using Common.Logger;
+using MongoDB.Bson;
+
+namespace Model
+{
+	public class Actor : Entity<Unit>, IDisposable
+	{
+		private readonly Queue<Env> msgEnvQueue = new Queue<Env>();
+
+		private Action msgAction = () => { };
+
+		private Env Env { get; set; }
+
+		private bool isStop;
+
+		public Actor(ObjectId id): base(id)
+		{
+			this.Start();
+		}
+
+		private async void Start()
+		{
+			while (!this.isStop)
+			{
+				try
+				{
+					Env env = await this.Get();
+					this.Env = env;
+					ushort opcode = env.Get<ushort>(EnvKey.Opcode);
+					await World.Instance.GetComponent<MessageComponent>().RunAsync(opcode, env);
+				}
+				catch (Exception e)
+				{
+					Log.Trace(string.Format(e.ToString()));
+				}
+			}
+		}
+
+		public void Add(Env msgEnv)
+		{
+			this.msgEnvQueue.Enqueue(msgEnv);
+			this.msgAction();
+		}
+
+		private Task<Env> Get()
+		{
+			var tcs = new TaskCompletionSource<Env>();
+			if (this.msgEnvQueue.Count > 0)
+			{
+				Env env = this.msgEnvQueue.Dequeue();
+				tcs.SetResult(env);
+			}
+			else
+			{
+				this.msgAction = () =>
+				{
+					this.msgAction = () => { };
+					Env msg = this.msgEnvQueue.Dequeue();
+					tcs.SetResult(msg);
+				};
+			}
+			return tcs.Task;
+		}
+
+		public void Dispose()
+		{
+			this.isStop = true;
+		}
+	}
+}

+ 12 - 51
CSharp/Game/Model/Component/ActorComponent.cs

@@ -1,67 +1,28 @@
-using System;
-using System.Collections.Generic;
-using System.Threading.Tasks;
+using System.Collections.Generic;
 using Common.Base;
-using Common.Logger;
+using MongoDB.Bson;
 
 namespace Model
 {
-	public class ActorComponent: Component<Unit>
+	public class ActorComponent : Component<World>
 	{
-		private readonly Queue<Env> msgEnvQueue = new Queue<Env>();
+		private readonly Dictionary<ObjectId, Actor> actors = new Dictionary<ObjectId, Actor>();
 
-		private Action msgAction = () => { };
-
-		private Env Env { get; set; }
-
-		public ActorComponent()
-		{
-			this.Start();
-		}
-
-		private async void Start()
+		public Actor Get(ObjectId id)
 		{
-			while (true)
-			{
-				try
-				{
-					Env env = await this.Get();
-					this.Env = env;
-					var message = env.Get<byte[]>(EnvKey.Message);
-					int opcode = BitConverter.ToUInt16(message, 0);
-					await World.Instance.GetComponent<EventComponent<MessageAttribute>>().RunAsync(opcode, env);
-				}
-				catch (Exception e)
-				{
-					Log.Trace(string.Format(e.ToString()));
-				}
-			}
+			return this.actors[id];
 		}
 
-		public void Add(Env msgEnv)
+		public void Add(Actor actor)
 		{
-			this.msgEnvQueue.Enqueue(msgEnv);
-			this.msgAction();
+			this.actors[actor.Id] = actor;
 		}
 
-		private Task<Env> Get()
+		public void Remove(ObjectId id)
 		{
-			var tcs = new TaskCompletionSource<Env>();
-			if (this.msgEnvQueue.Count > 0)
-			{
-				Env env = this.msgEnvQueue.Dequeue();
-				tcs.SetResult(env);
-			}
-			else
-			{
-				this.msgAction = () =>
-				{
-					this.msgAction = () => { };
-					Env msg = this.msgEnvQueue.Dequeue();
-					tcs.SetResult(msg);
-				};
-			}
-			return tcs.Task;
+			Actor actor = this.Get(id);
+			this.actors.Remove(id);
+			actor.Dispose();
 		}
 	}
 }

+ 5 - 5
CSharp/Game/Model/Component/GateNetworkComponent.cs

@@ -67,19 +67,19 @@ namespace Model
 		{
 			while (true)
 			{
-				byte[] message = await channel.RecvAsync();
+				byte[] messageBytes = await channel.RecvAsync();
 				Env env = new Env();
 				env[EnvKey.Channel] = channel;
-				env[EnvKey.Message] = message;
-				int opcode = BitConverter.ToUInt16(message, 0);
-
+				env[EnvKey.MessageBytes] = messageBytes;
+				ushort opcode = BitConverter.ToUInt16(messageBytes, 0);
+				env[EnvKey.Opcode] = opcode;
 				if (!MessageTypeHelper.IsClientMessage(opcode))
 				{
 					continue;
 				}
 
 				World.Instance.GetComponent<EventComponent<EventAttribute>>()
-						.Run(EventType.GateRecvClientMessage, env);
+						.RunAsync(EventType.GateRecvClientMessage, env);
 			}
 		}
 

+ 120 - 0
CSharp/Game/Model/Component/MessageComponent.cs

@@ -0,0 +1,120 @@
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+using System.Threading.Tasks;
+using Common.Base;
+
+namespace Model
+{
+	public class MessageComponent: Component<World>, IAssemblyLoader
+	{
+		private Dictionary<ushort, List<IEventSync>> eventSyncs;
+		private Dictionary<ushort, List<IEventAsync>> eventAsyncs;
+		private Dictionary<ushort, Type> typeClassType;
+
+		public void Load(Assembly assembly)
+		{
+			this.eventSyncs = new Dictionary<ushort, List<IEventSync>>();
+			this.eventAsyncs = new Dictionary<ushort, List<IEventAsync>>();
+			this.typeClassType = new Dictionary<ushort, Type>();
+
+			ServerType serverType = World.Instance.Options.ServerType;
+
+			Type[] types = assembly.GetTypes();
+			foreach (Type t in types)
+			{
+				object[] attrs = t.GetCustomAttributes(typeof (MessageAttribute), false);
+				if (attrs.Length == 0)
+				{
+					continue;
+				}
+
+				MessageAttribute messageAttribute = (MessageAttribute)attrs[0];
+				if (!messageAttribute.Contains(serverType))
+				{
+					continue;
+				}
+
+				this.typeClassType[messageAttribute.Opcode] = messageAttribute.ClassType;
+
+				object obj = Activator.CreateInstance(t);
+
+				IEventSync iEventSync = obj as IEventSync;
+				if (iEventSync != null)
+				{
+					if (!this.eventSyncs.ContainsKey(messageAttribute.Opcode))
+					{
+						this.eventSyncs.Add(messageAttribute.Opcode, new List<IEventSync>());
+					}
+					this.eventSyncs[messageAttribute.Opcode].Add(iEventSync);
+					continue;
+				}
+
+				IEventAsync iEventAsync = obj as IEventAsync;
+				if (iEventAsync != null)
+				{
+					if (!this.eventAsyncs.ContainsKey(messageAttribute.Opcode))
+					{
+						this.eventAsyncs.Add(messageAttribute.Opcode, new List<IEventAsync>());
+					}
+					this.eventAsyncs[messageAttribute.Opcode].Add(iEventAsync);
+					continue;
+				}
+
+				throw new Exception(string.Format("message handler not inherit IEventSync or IEventAsync interface: {0}",
+						obj.GetType().FullName));
+			}
+		}
+
+		public Type GetClassType(ushort opcode)
+		{
+			return this.typeClassType[opcode];
+		}
+
+		public void Run(ushort opcode, Env env)
+		{
+			List<IEventSync> iEventSyncs = null;
+			if (!this.eventSyncs.TryGetValue(opcode, out iEventSyncs))
+			{
+				throw new Exception(string.Format("no message handler, MessageAttribute: {0} opcode: {1}",
+						typeof(MessageAttribute).Name, opcode));
+			}
+
+			foreach (IEventSync iEventSync in iEventSyncs)
+			{
+				iEventSync.Run(env);
+			}
+		}
+
+		public async Task RunAsync(ushort opcode, Env env)
+		{
+			List<IEventSync> iEventSyncs = null;
+			this.eventSyncs.TryGetValue(opcode, out iEventSyncs);
+
+			List<IEventAsync> iEventAsyncs = null;
+			this.eventAsyncs.TryGetValue(opcode, out iEventAsyncs);
+
+			if (iEventSyncs == null && iEventAsyncs == null)
+			{
+				throw new Exception(string.Format("no message handler, MessageAttribute: {0} opcode: {1}",
+						typeof(MessageAttribute).Name, opcode));
+			}
+
+			if (iEventSyncs != null)
+			{
+				foreach (IEventSync iEventSync in iEventSyncs)
+				{
+					iEventSync.Run(env);
+				}
+			}
+
+			if (iEventAsyncs != null)
+			{
+				foreach (IEventAsync iEventAsync in iEventAsyncs)
+				{
+					await iEventAsync.RunAsync(env);
+				}
+			}
+		}
+	}
+}

+ 59 - 26
CSharp/Game/Model/Component/NetworkComponent.cs

@@ -9,17 +9,23 @@ using UNet;
 
 namespace Model
 {
-	public enum RpcStatus
+	public enum RpcResponseStatus
 	{
-		OK,
+		Succee,
 		Timeout,
 		Exception,
 	}
 
 	public class RpcExcetionInfo
 	{
-		public int ErrorCode { get; set; }
-		public string ErrorInfo { get; set; }
+		public int ErrorCode { get; private set; }
+		public string ErrorInfo { get; private set; }
+
+		public RpcExcetionInfo(int errorCode, string errorInfo)
+		{
+			this.ErrorCode = errorCode;
+			this.ErrorInfo = errorInfo;
+		}
 	}
 
 	public class NetworkComponent: Component<World>, IUpdate, IStart
@@ -28,8 +34,8 @@ namespace Model
 
 		private int requestId;
 
-		private readonly Dictionary<int, Action<byte[], RpcStatus>> requestCallback =
-				new Dictionary<int, Action<byte[], RpcStatus>>();
+		private readonly Dictionary<int, Action<byte[], RpcResponseStatus>> requestCallback =
+				new Dictionary<int, Action<byte[], RpcResponseStatus>>();
 
 		private void Accept(string host, int port, NetworkProtocol protocol = NetworkProtocol.TCP)
 		{
@@ -83,27 +89,46 @@ namespace Model
 				Env env = new Env();
 				env[EnvKey.Channel] = channel;
 				env[EnvKey.Message] = message;
-				int opcode = BitConverter.ToUInt16(message, 0);
+				ushort opcode = BitConverter.ToUInt16(message, 0);
+				env[EnvKey.Opcode] = opcode;
 
 				// 表示消息是rpc响应消息
-				if (opcode == 0)
+				if (opcode == Opcode.RpcResponse)
 				{
 					int id = BitConverter.ToInt32(message, 2);
-					this.RequestCallback(channel, id, message, RpcStatus.OK);
+					this.RequestCallback(channel, id, message, RpcResponseStatus.Succee);
 					continue;
 				}
 
-				// 如果是发给client的消息,说明这是gate server,需要根据unitid查到channel,进行发送
+				// rpc异常
+				if (opcode == Opcode.RpcException)
+				{
+					int id = BitConverter.ToInt32(message, 2);
+					this.RequestCallback(channel, id, message, RpcResponseStatus.Exception);
+					continue;
+				}
+
+				// 如果是server message(发给client的消息),说明这是gate server,需要根据unitid查到channel,进行发送
 				if (MessageTypeHelper.IsServerMessage(opcode))
 				{
 					World.Instance.GetComponent<EventComponent<EventAttribute>>()
-							.Run(EventType.GateRecvServerMessage, env);
+							.RunAsync(EventType.GateRecvServerMessage, env);
 					continue;
 				}
 
 				// 进行消息分发
-				World.Instance.GetComponent<EventComponent<EventAttribute>>()
-						.Run(EventType.LogicRecvMessage, env);
+				if (MessageTypeHelper.IsClientMessage(opcode))
+				{
+					World.Instance.GetComponent<EventComponent<EventAttribute>>()
+							.RunAsync(EventType.LogicRecvClientMessage, env);
+					continue;
+				}
+
+				if (MessageTypeHelper.IsRpcRequestMessage(opcode))
+				{
+					World.Instance.GetComponent<EventComponent<EventAttribute>>()
+							.RunAsync(EventType.LogicRecvRpcMessage, env);
+				}
 			}
 		}
 
@@ -113,23 +138,31 @@ namespace Model
 			channel.SendAsync(buffer);
 		}
 
+		public void SendAsync(string address, List<byte[]> buffers)
+		{
+			AChannel channel = this.service.GetChannel(address);
+			channel.SendAsync(buffers);
+		}
+
 		// 消息回调或者超时回调
-		public void RequestCallback(AChannel channel, int id, byte[] buffer, RpcStatus status)
+		public void RequestCallback(AChannel channel, int id, byte[] buffer, RpcResponseStatus responseStatus)
 		{
-			Action<byte[], RpcStatus> action;
+			Action<byte[], RpcResponseStatus> action;
 			if (!this.requestCallback.TryGetValue(id, out action))
 			{
 				return;
 			}
-			action(buffer, status);
 			this.requestCallback.Remove(id);
+			action(buffer, responseStatus);
 		}
 
 		/// <summary>
 		/// Rpc请求
 		/// </summary>
-		public Task<T> Request<T, K>(AChannel channel, short type, K request, int waitTime = 0)
+		public Task<T> RpcRequest<T, K>(string address, short type, K request, int waitTime = 0)
 		{
+			AChannel channel = this.service.GetChannel(address);
+
 			++this.requestId;
 			byte[] requestBuffer = MongoHelper.ToBson(request);
 			byte[] typeBuffer = BitConverter.GetBytes(type);
@@ -138,13 +171,13 @@ namespace Model
 			var tcs = new TaskCompletionSource<T>();
 			this.requestCallback[this.requestId] = (e, b) =>
 			{
-				if (b == RpcStatus.Timeout)
+				if (b == RpcResponseStatus.Timeout)
 				{
 					tcs.SetException(new Exception(
 						string.Format("rpc timeout {0} {1}", type, MongoHelper.ToJson(request))));
 					return;
 				}
-				if (b == RpcStatus.Exception)
+				if (b == RpcResponseStatus.Exception)
 				{
 					RpcExcetionInfo errorInfo = MongoHelper.FromBson<RpcExcetionInfo>(e, 8);
 					tcs.SetException(new Exception(
@@ -152,7 +185,7 @@ namespace Model
 					return;
 				}
 
-				// RpcStatus.OK
+				// RpcResponseStatus.Succee
 				T response = MongoHelper.FromBson<T>(e, 6);
 				tcs.SetResult(response);
 			};
@@ -160,7 +193,7 @@ namespace Model
 			if (waitTime > 0)
 			{
 				this.service.Timer.Add(TimeHelper.Now() + waitTime,
-						() => { this.RequestCallback(channel, this.requestId, null, RpcStatus.Timeout); });
+						() => { this.RequestCallback(channel, this.requestId, null, RpcResponseStatus.Timeout); });
 			}
 			return tcs.Task;
 		}
@@ -168,10 +201,10 @@ namespace Model
 		/// <summary>
 		/// Rpc响应
 		/// </summary>
-		public void Response<T>(AChannel channel, int id, T response)
+		public void RpcResponse<T>(AChannel channel, int id, T response)
 		{
 			byte[] responseBuffer = MongoHelper.ToBson(response);
-			byte[] typeBuffer = BitConverter.GetBytes(0);
+			byte[] typeBuffer = BitConverter.GetBytes(Opcode.RpcResponse);
 			byte[] idBuffer = BitConverter.GetBytes(id);
 			channel.SendAsync(new List<byte[]> { typeBuffer, idBuffer, responseBuffer });
 		}
@@ -179,11 +212,11 @@ namespace Model
 		/// <summary>
 		/// Rpc响应
 		/// </summary>
-		public void ResponseException(AChannel channel, int id, int errorCode, string errorInfo)
+		public void RpcException(AChannel channel, int id, int errorCode, string errorInfo)
 		{
-			byte[] typeBuffer = BitConverter.GetBytes(0);
+			byte[] typeBuffer = BitConverter.GetBytes(Opcode.RpcException);
 			byte[] idBuffer = BitConverter.GetBytes(id);
-			RpcExcetionInfo info = new RpcExcetionInfo { ErrorCode = errorCode, ErrorInfo = errorInfo };
+			RpcExcetionInfo info = new RpcExcetionInfo(errorCode, errorInfo);
 			byte[] responseBuffer = MongoHelper.ToBson(info);
 			channel.SendAsync(new List<byte[]> { typeBuffer, idBuffer, responseBuffer });
 		}

+ 4 - 0
CSharp/Game/Model/EnvKey.cs

@@ -6,7 +6,11 @@
 		public const string OwnerId = "OwnerId";
 		public const string Buff = "Buff";
 		public const string BuffId = "BuffId";
+		public const string MessageBytes = "MessageBytes";
 		public const string Message = "Message";
 		public const string Channel = "Channel";
+		public const string Opcode = "Opcode";
+		public const string MessageUnitId = "MessageUnitId";
+		public const string RpcRequestId = "RpcRequestId";
 	}
 }

+ 3 - 2
CSharp/Game/Model/EventType.cs

@@ -7,8 +7,9 @@
 		public const int BeforeRemoveBuff = 2;
 		public const int AfterRemoveBuff = 3;
 		public const int BuffTimeout = 4;
-		public const int LogicRecvMessage = 5;
-		public const int GateRecvClientMessage = 6;
+		public const int LogicRecvClientMessage = 5;
+		public const int LogicRecvRpcMessage = 6;
+		public const int GateRecvClientMessage = 7;
 		public const int GateRecvServerMessage = 8;
 	}
 }

+ 16 - 0
CSharp/Game/Model/GameException.cs

@@ -0,0 +1,16 @@
+using System;
+
+namespace Model
+{
+	public class GameException: Exception
+	{
+		public int ErrorCode { get; private set; }
+
+		public string ErrorInfo { get; private set; }
+
+		public GameException(int errorCode, string errorInfo): base(errorInfo)
+		{
+			this.ErrorCode = errorCode;
+		}
+	}
+}

+ 24 - 4
CSharp/Game/Model/MessageAttribute.cs

@@ -1,12 +1,32 @@
-namespace Model
+using System;
+
+namespace Model
 {
 	/// <summary>
-	/// 搭配EventComponent用来分发消息
+	/// 搭配MessageComponent用来分发消息
 	/// </summary>
-	public class MessageAttribute: AEventAttribute
+	public class MessageAttribute: Attribute
 	{
-		public MessageAttribute(int type, ServerType serverType): base(type, serverType)
+		public ushort Opcode { get; private set; }
+
+		public Type ClassType { get; private set; }
+
+		private ServerType ServerType { get; set; }
+
+		public MessageAttribute(ushort opcode, Type classType, ServerType serverType)
 		{
+			this.Opcode = opcode;
+			this.ClassType = classType;
+			this.ServerType = serverType;
+		}
+
+		public bool Contains(ServerType serverType)
+		{
+			if ((this.ServerType & serverType) == 0)
+			{
+				return false;
+			}
+			return true;
 		}
 	}
 }

+ 5 - 2
CSharp/Game/Model/Model.csproj

@@ -53,16 +53,18 @@
     <Compile Include="BehaviorTree\NodeAttribute.cs" />
     <Compile Include="Buff.cs" />
     <Compile Include="BuffType.cs" />
-    <Compile Include="Component\ActorComponent.cs" />
+    <Compile Include="Actor.cs" />
     <Compile Include="Component\BehaviorTreeComponent.cs" />
     <Compile Include="Component\BuffComponent.cs" />
     <Compile Include="Component\ChannelUnitInfoComponent.cs" />
     <Compile Include="Component\ConfigComponent.cs" />
+    <Compile Include="Component\MessageComponent.cs" />
     <Compile Include="Component\EventComponent.cs" />
     <Compile Include="Component\FactoryComponent.cs" />
     <Compile Include="Component\GateNetworkComponent.cs" />
     <Compile Include="Component\NetworkComponent.cs" />
     <Compile Include="Component\TimerComponent.cs" />
+    <Compile Include="Component\ActorComponent.cs" />
     <Compile Include="Component\UnitComponent.cs" />
     <Compile Include="ConfigAttribute.cs" />
     <Compile Include="Config\BuffConfig.cs" />
@@ -75,6 +77,7 @@
     <Compile Include="EventAttribute.cs" />
     <Compile Include="EventType.cs" />
     <Compile Include="FactoryAttribute.cs" />
+    <Compile Include="GameException.cs" />
     <Compile Include="IAssemblyLoader.cs" />
     <Compile Include="ICategory.cs" />
     <Compile Include="IConfigLoader.cs" />
@@ -84,7 +87,7 @@
     <Compile Include="IStart.cs" />
     <Compile Include="IUpdate.cs" />
     <Compile Include="MessageAttribute.cs" />
-    <Compile Include="MessageType.cs" />
+    <Compile Include="Opcode.cs" />
     <Compile Include="NumDefine.cs" />
     <Compile Include="Options.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />

+ 8 - 9
CSharp/Game/Model/MessageType.cs → CSharp/Game/Model/Opcode.cs

@@ -1,10 +1,10 @@
 namespace Model
 {
-	public static class MessageType
+	public static class Opcode
 	{
 		#region client message 0
 
-		public const int CMsgLogin = 1;
+		public const ushort CMsgLogin = 1;
 
 		#endregion client message 10000
 
@@ -16,14 +16,13 @@
 
 		#endregion rpc request message 30000
 
-		#region rpc request message 30000
-
-		#endregion rpc request message 40000
+		public const ushort RpcResponse = 30000;
+		public const ushort RpcException = 30001;
 	}
 
 	public static class MessageTypeHelper
 	{
-		public static bool IsClientMessage(int opcode)
+		public static bool IsClientMessage(ushort opcode)
 		{
 			if (opcode > 0 && opcode < 10000)
 			{
@@ -32,7 +31,7 @@
 			return false;
 		}
 
-		public static bool IsServerMessage(int opcode)
+		public static bool IsServerMessage(ushort opcode)
 		{
 			if (opcode > 10000 && opcode < 20000)
 			{
@@ -41,7 +40,7 @@
 			return false;
 		}
 
-		public static bool IsRpcRequestMessage(int opcode)
+		public static bool IsRpcRequestMessage(ushort opcode)
 		{
 			if (opcode > 20000 && opcode < 30000)
 			{
@@ -50,7 +49,7 @@
 			return false;
 		}
 
-		public static bool IsRpcResponseMessage(int opcode)
+		public static bool IsRpcResponseMessage(ushort opcode)
 		{
 			if (opcode > 30000 && opcode < 40000)
 			{

+ 3 - 2
CSharp/Game/Model/UnitType.cs

@@ -3,7 +3,8 @@
 	public static class UnitType
 	{
 		public const int GatePlayer = 1;
-		public const int Npc = 2;
-		public const int Dog = 3;
+		public const int Player = 2;
+		public const int Npc = 3;
+		public const int Dog = 4;
 	}
 }

+ 9 - 0
CSharp/Platform/Common/Base/Entity.cs

@@ -2,6 +2,7 @@
 using System.Collections.Generic;
 using System.Linq;
 using Common.Helper;
+using MongoDB.Bson;
 using MongoDB.Bson.Serialization.Attributes;
 
 namespace Common.Base
@@ -13,6 +14,14 @@ namespace Common.Base
 
 		private Dictionary<Type, Component<T>> componentDict = new Dictionary<Type, Component<T>>();
 
+		protected Entity()
+		{
+		}
+
+		protected Entity(ObjectId id): base(id)
+		{
+		}
+
 		public T Clone()
 		{
 			return MongoHelper.FromBson<T>(MongoHelper.ToBson(this));

+ 11 - 1
CSharp/Platform/Common/Helper/MongoHelper.cs

@@ -28,11 +28,21 @@ namespace Common.Helper
 			return obj.ToBson();
 		}
 
-		public static object FromBson(byte[] bytes, Type type)
+		public static object FromBson(Type type, byte[] bytes)
 		{
 			return BsonSerializer.Deserialize(bytes, type);
 		}
 
+		public static object FromBson(Type type, byte[] bytes, int index, int count)
+		{
+			using (MemoryStream memoryStream = new MemoryStream(bytes))
+			{
+				memoryStream.Seek(index, SeekOrigin.Begin);
+				memoryStream.Seek(index + count, SeekOrigin.End);
+				return BsonSerializer.Deserialize(memoryStream, type);
+			}
+		}
+
 		public static T FromBson<T>(byte[] bytes, int index = 0)
 		{
 			using (MemoryStream memoryStream = new MemoryStream(bytes))