Prechádzať zdrojové kódy

1.服务端消息大部分可以热更,把能热更的消息移动到hotfix层,需要保存状态的消息例如FrameMessage需要手写放到ETModel层
2.一部分服务端逻辑移动到hotfix层

tanghai 7 rokov pred
rodič
commit
2b191c8b82
32 zmenil súbory, kde vykonal 589 pridanie a 596 odobranie
  1. 0 12
      Proto/OuterMessage.proto
  2. 0 2
      Server/Hotfix/Module/Actor/ActorMessageDispatherComponentSystem.cs
  3. 194 0
      Server/Hotfix/Module/Actor/ActorProxySystem.cs
  4. 13 26
      Server/Hotfix/Module/Benchmark/BenchmarkComponentSystem.cs
  5. 30 41
      Server/Hotfix/Module/BigWorld/LockComponentSystem.cs
  6. 51 0
      Server/Hotfix/Module/BigWorld/MasterComponentSystem.cs
  7. 83 0
      Server/Hotfix/Module/DB/DBProxyComponentSystem.cs
  8. 57 0
      Server/Hotfix/Module/Location/LocationProxyComponentSystem.cs
  9. 1 1
      Server/Hotfix/Module/Message/HotfixMessage.cs
  10. 0 0
      Server/Hotfix/Module/Message/HotfixOpcode.cs
  11. 1 1
      Server/Hotfix/Module/Message/InnerMessage.cs
  12. 0 0
      Server/Hotfix/Module/Message/InnerOpcode.cs
  13. 1 37
      Server/Hotfix/Module/Message/OuterMessage.cs
  14. 5 7
      Server/Hotfix/Module/Message/OuterOpcode.cs
  15. 2 10
      Server/Hotfix/Server.Hotfix.csproj
  16. 0 71
      Server/Model/Component/Unit/MasterComponent.cs
  17. 3 188
      Server/Model/Module/Actor/ActorProxy.cs
  18. 13 0
      Server/Model/Module/Benchmark/BenchmarkComponent.cs
  19. 25 0
      Server/Model/Module/BigWorld/LockComponent.cs
  20. 30 0
      Server/Model/Module/BigWorld/MasterComponent.cs
  21. 2 75
      Server/Model/Module/DB/DBProxyComponent.cs
  22. 0 58
      Server/Model/Module/Location/LocationProxyComponent.cs
  23. 4 10
      Server/Model/Server.Model.csproj
  24. 4 4
      Unity/Assets/Editor/Proto2CsEditor/Proto2CSEditor.cs
  25. 42 0
      Unity/Assets/Scripts/Module/FrameSync/FrameMessage.cs
  26. 12 0
      Unity/Assets/Scripts/Module/FrameSync/FrameMessage.cs.meta
  27. 2 0
      Unity/Assets/Scripts/Module/Message/Opcode.cs
  28. 0 36
      Unity/Assets/Scripts/Module/Message/OuterMessage.cs
  29. 5 7
      Unity/Assets/Scripts/Module/Message/OuterOpcode.cs
  30. 1 1
      Unity/Hotfix/UI/UILobby/Component/UILobbyComponent.cs
  31. 8 4
      Unity/Unity.csproj
  32. 0 5
      Unity/Unity.sln

+ 0 - 12
Proto/OuterMessage.proto

@@ -44,18 +44,6 @@ message Actor_CreateUnits // IActorMessage
     repeated UnitInfo Units = 1;
 }
 
-message OneFrameMessage // IActorMessage
-{
-	required uint16 Op = 1;
-	required bytes AMessage = 2;
-}
-
-message FrameMessage // IActorMessage
-{
-	required int32 Frame = 1;
-	repeated OneFrameMessage Messages = 2;
-}
-
 message Frame_ClickMap // IFrameMessage
 {
 	required int32 X = 1;

+ 0 - 2
Server/Hotfix/Module/Actor/ActorMessageDispatherComponentSystem.cs

@@ -36,8 +36,6 @@ namespace ETHotfix
 		{
 			AppType appType = self.Entity.GetComponent<StartConfigComponent>().StartConfig.AppType;
 
-			Log.Info("apptype: " + appType);
-
 			self.ActorMessageHandlers.Clear();
 			self.ActorTypeHandlers.Clear();
 

+ 194 - 0
Server/Hotfix/Module/Actor/ActorProxySystem.cs

@@ -0,0 +1,194 @@
+using System;
+using System.Collections.Generic;
+using System.Threading;
+using System.Threading.Tasks;
+using ETModel;
+
+namespace ETHotfix
+{
+	[ObjectSystem]
+	public class ActorProxyAwakeSystem : AwakeSystem<ActorProxy>
+	{
+		public override void Awake(ActorProxy self)
+		{
+			self.Awake();
+		}
+	}
+
+	[ObjectSystem]
+	public class ActorProxyStartSystem : StartSystem<ActorProxy>
+	{
+		public override async void Start(ActorProxy self)
+		{
+			int appId = await Game.Scene.GetComponent<LocationProxyComponent>().Get(self.Id);
+			self.Address = Game.Scene.GetComponent<StartConfigComponent>().Get(appId).GetComponent<InnerConfig>().IPEndPoint;
+
+			self.UpdateAsync();
+		}
+	}
+	
+	[ObjectSystem]
+	public class ActorProxyDestroySystem : DestroySystem<ActorProxy>
+	{
+		public override void Destroy(ActorProxy self)
+		{
+			if (self.IsDisposed)
+			{
+				return;
+			}
+
+			self.LastSendTime = 0;
+			self.Address = null;
+
+			while (self.WaitingTasks.Count > 0)
+			{
+				ActorTask actorTask = self.WaitingTasks.Dequeue();
+				actorTask.RunFail(ErrorCode.ERR_NotFoundActor);
+			}
+
+			self.failTimes = 0;
+			var t = self.tcs;
+			self.tcs = null;
+			t?.SetResult(new ActorTask());
+		}
+	}
+
+	public static class ActorProxyEx
+	{
+		public static void Awake(this ActorProxy self)
+		{
+			self.LastSendTime = TimeHelper.Now();
+			self.tcs = null;
+			self.CancellationTokenSource = new CancellationTokenSource();
+		}
+
+		private static void Add(this ActorProxy self, ActorTask task)
+		{
+			if (self.IsDisposed)
+			{
+				throw new Exception("ActorProxy Disposed! dont hold actorproxy");
+			}
+
+			self.WaitingTasks.Enqueue(task);
+			// failtimes > 0表示正在重试,这时候不能加到正在发送队列
+			if (self.failTimes == 0)
+			{
+				self.AllowGet();
+			}
+		}
+
+		private static void AllowGet(this ActorProxy self)
+		{
+			if (self.tcs == null || self.WaitingTasks.Count <= 0)
+			{
+				return;
+			}
+
+			ActorTask task = self.WaitingTasks.Peek();
+
+			var t = self.tcs;
+			self.tcs = null;
+			t.SetResult(task);
+		}
+
+		private static Task<ActorTask> GetAsync(this ActorProxy self)
+		{
+			if (self.WaitingTasks.Count > 0)
+			{
+				ActorTask task = self.WaitingTasks.Peek();
+				return Task.FromResult(task);
+			}
+
+			self.tcs = new TaskCompletionSource<ActorTask>();
+			return self.tcs.Task;
+		}
+
+		public static async void UpdateAsync(this ActorProxy self)
+		{
+			while (true)
+			{
+				ActorTask actorTask = await self.GetAsync();
+				if (self.IsDisposed)
+				{
+					return;
+				}
+
+				try
+				{
+					await self.RunTask(actorTask);
+				}
+				catch (Exception e)
+				{
+					Log.Error(e);
+					return;
+				}
+			}
+		}
+
+		private static async Task RunTask(this ActorProxy self, ActorTask task)
+		{
+			try
+			{
+				IResponse response = await task.Run();
+
+				// 如果没找到Actor,重试
+				if (response.Error == ErrorCode.ERR_NotFoundActor)
+				{
+					self.CancellationTokenSource.Cancel();
+					++self.failTimes;
+
+					// 失败10次则清空actor发送队列,返回失败
+					if (self.failTimes > 10)
+					{
+						// 失败直接删除actorproxy
+						Log.Info($"actor send message fail, actorid: {self.Id}");
+						Game.Scene.GetComponent<ActorProxyComponent>().Remove(self.Id);
+						return;
+					}
+
+					// 等待1s再发送
+					await Game.Scene.GetComponent<TimerComponent>().WaitAsync(1000);
+					int appId = await Game.Scene.GetComponent<LocationProxyComponent>().Get(self.Id);
+					self.Address = Game.Scene.GetComponent<StartConfigComponent>().Get(appId).GetComponent<InnerConfig>().IPEndPoint;
+					self.CancellationTokenSource = new CancellationTokenSource();
+					self.AllowGet();
+					return;
+				}
+
+				// 发送成功
+				self.LastSendTime = TimeHelper.Now();
+				self.failTimes = 0;
+
+				self.WaitingTasks.Dequeue();
+			}
+			catch (Exception e)
+			{
+				Log.Error(e);
+			}
+		}
+
+		public static void Send(this ActorProxy self, IActorMessage message)
+		{
+			ActorTask task = new ActorTask { message = message, proxy = self };
+			self.Add(task);
+		}
+
+		public static Task<IResponse> Call(this ActorProxy self, IActorRequest request)
+		{
+			ActorTask task = new ActorTask { message = request, proxy = self, Tcs = new TaskCompletionSource<IResponse>() };
+			self.Add(task);
+			return task.Tcs.Task;
+		}
+
+		public static string DebugQueue(this ActorProxy self, Queue<ActorTask> tasks)
+		{
+			string s = "";
+			foreach (ActorTask task in tasks)
+			{
+				s += $" {task.message.GetType().Name}";
+			}
+
+			return s;
+		}
+	}
+}

+ 13 - 26
Server/Model/Component/BenchmarkComponent.cs → Server/Hotfix/Module/Benchmark/BenchmarkComponentSystem.cs

@@ -1,8 +1,9 @@
 using System;
 using System.Net;
 using System.Threading.Tasks;
+using ETModel;
 
-namespace ETModel
+namespace ETHotfix
 {
 	[ObjectSystem]
 	public class BenchmarkComponentSystem : AwakeSystem<BenchmarkComponent, IPEndPoint>
@@ -13,20 +14,16 @@ namespace ETModel
 		}
 	}
 
-	public class BenchmarkComponent: Component
+	public static class BenchmarkComponentEx
 	{
-		private int k;
-
-		private long time1 = TimeHelper.ClientNow();
-
-		public void Awake(IPEndPoint ipEndPoint)
+		public static void Awake(this BenchmarkComponent self, IPEndPoint ipEndPoint)
 		{
 			try
 			{
 				NetOuterComponent networkComponent = Game.Scene.GetComponent<NetOuterComponent>();
 				for (int i = 0; i < 1000; i++)
 				{
-					this.TestAsync(networkComponent, ipEndPoint, i);
+					self.TestAsync(networkComponent, ipEndPoint, i);
 				}
 			}
 			catch (Exception e)
@@ -35,7 +32,7 @@ namespace ETModel
 			}
 		}
 
-		public async void TestAsync(NetOuterComponent networkComponent, IPEndPoint ipEndPoint, int j)
+		public static async void TestAsync(this BenchmarkComponent self, NetOuterComponent networkComponent, IPEndPoint ipEndPoint, int j)
 		{
 			try
 			{
@@ -45,7 +42,7 @@ namespace ETModel
 					while (i < 100000000)
 					{
 						++i;
-						await this.Send(session, j);
+						await self.Send(session, j);
 					}
 				}
 			}
@@ -59,37 +56,27 @@ namespace ETModel
 			}
 		}
 
-		public async Task Send(Session session, int j)
+		public static async Task Send(this BenchmarkComponent self, Session session, int j)
 		{
 			try
 			{
 				await session.Call(new C2R_Ping());
-				++this.k;
+				++self.k;
 
-				if (this.k % 100000 != 0)
+				if (self.k % 100000 != 0)
 				{
 					return;
 				}
 
 				long time2 = TimeHelper.ClientNow();
-				long time = time2 - this.time1;
-				this.time1 = time2;
-				Log.Info($"Benchmark k: {this.k} 每10W次耗时: {time} ms");
+				long time = time2 - self.time1;
+				self.time1 = time2;
+				Log.Info($"Benchmark k: {self.k} 每10W次耗时: {time} ms");
 			}
 			catch (Exception e)
 			{
 				Log.Error(e);
 			}
 		}
-
-		public override void Dispose()
-		{
-			if (this.IsDisposed)
-			{
-				return;
-			}
-
-			base.Dispose();
-		}
 	}
 }

+ 30 - 41
Server/Model/Component/Unit/LockComponent.cs → Server/Hotfix/Module/BigWorld/LockComponentSystem.cs

@@ -2,16 +2,10 @@
 using System.Collections.Generic;
 using System.Net;
 using System.Threading.Tasks;
+using ETModel;
 
-namespace ETModel
+namespace ETHotfix
 {
-	public enum LockStatus
-	{
-		LockedNot,
-		LockRequesting,
-		Locked,
-	}
-
 	[ObjectSystem]
 	public class LockComponentAwakeSystem : AwakeSystem<LockComponent, IPEndPoint>
 	{
@@ -24,92 +18,87 @@ namespace ETModel
 	/// <summary>
 	/// 分布式锁组件,Unit对象可能在不同进程上有镜像,访问该对象的时候需要对他加锁
 	/// </summary>
-	public class LockComponent: Component
+	public static class LockComponentEx
 	{
-		private LockStatus status = LockStatus.LockedNot;
-		private IPEndPoint address;
-		private int lockCount;
-		private readonly Queue<TaskCompletionSource<bool>> queue = new Queue<TaskCompletionSource<bool>>();
-
-		public void Awake(IPEndPoint addr)	
+		public static void Awake(this LockComponent self, IPEndPoint addr)	
 		{
-			this.address = addr;
+			self.address = addr;
 		}
 		
-		public async Task Lock()
+		public static async Task Lock(this LockComponent self)
 		{
-			++this.lockCount;
+			++self.lockCount;
 
-			if (this.status == LockStatus.Locked)
+			if (self.status == LockStatus.Locked)
 			{
 				return;
 			}
-			if (this.status == LockStatus.LockRequesting)
+			if (self.status == LockStatus.LockRequesting)
 			{
-				await WaitLock();
+				await self.WaitLock();
 				return;
 			}
 			
-			this.status = LockStatus.LockRequesting;
+			self.status = LockStatus.LockRequesting;
 
 			// 真身直接本地请求锁,镜像需要调用Rpc获取锁
-			MasterComponent masterComponent = this.Entity.GetComponent<MasterComponent>();
+			MasterComponent masterComponent = self.Entity.GetComponent<MasterComponent>();
 			if (masterComponent != null)
 			{
-				await masterComponent.Lock(this.address);
+				await masterComponent.Lock(self.address);
 			}
 			else
 			{
-				RequestLock();
-				await WaitLock();
+				self.RequestLock();
+				await self.WaitLock();
 			}
 		}
 
-		private Task<bool> WaitLock()
+		private static Task<bool> WaitLock(this LockComponent self)
 		{
-			if (this.status == LockStatus.Locked)
+			if (self.status == LockStatus.Locked)
 			{
 				return Task.FromResult(true);
 			}
 
 			TaskCompletionSource<bool> tcs = new TaskCompletionSource<bool>();
-			this.queue.Enqueue(tcs);
+			self.queue.Enqueue(tcs);
 			return tcs.Task;
 		}
 
-		private async void RequestLock()
+		private static async void RequestLock(this LockComponent self)
 		{
 			try
 			{
-				Session session = Game.Scene.GetComponent<NetInnerComponent>().Get(this.address);
+				Session session = Game.Scene.GetComponent<NetInnerComponent>().Get(self.address);
 				string serverAddress = Game.Scene.GetComponent<StartConfigComponent>().StartConfig.ServerIP;
-				G2G_LockRequest request = new G2G_LockRequest { Id = this.Entity.Id, Address = serverAddress };
+				G2G_LockRequest request = new G2G_LockRequest { Id = self.Entity.Id, Address = serverAddress };
 				await session.Call(request);
 
-				this.status = LockStatus.Locked;
+				self.status = LockStatus.Locked;
 
-				foreach (TaskCompletionSource<bool> taskCompletionSource in this.queue)
+				foreach (TaskCompletionSource<bool> taskCompletionSource in self.queue)
 				{
 					taskCompletionSource.SetResult(true);
 				}
-				this.queue.Clear();
+				self.queue.Clear();
 			}
 			catch (Exception e)
 			{
-				Log.Error($"获取锁失败: {this.address} {this.Entity.Id} {e}");
+				Log.Error($"获取锁失败: {self.address} {self.Entity.Id} {e}");
 			}
 		}
 
-		public async Task Release()
+		public static async Task Release(this LockComponent self)
 		{
-			--this.lockCount;
-			if (this.lockCount != 0)
+			--self.lockCount;
+			if (self.lockCount != 0)
 			{
 				return;
 			}
 
-			this.status = LockStatus.LockedNot;
-			Session session = Game.Scene.GetComponent<NetInnerComponent>().Get(this.address);
+			self.status = LockStatus.LockedNot;
+			Session session = Game.Scene.GetComponent<NetInnerComponent>().Get(self.address);
 			G2G_LockReleaseRequest request = new G2G_LockReleaseRequest();
 			await session.Call(request);
 		}

+ 51 - 0
Server/Hotfix/Module/BigWorld/MasterComponentSystem.cs

@@ -0,0 +1,51 @@
+using System.Collections.Generic;
+using System.Net;
+using System.Threading.Tasks;
+using ETModel;
+
+namespace ETHotfix
+{
+	public static class MasterComponentEx
+	{
+		public static void AddGhost(this MasterComponent self, IPEndPoint address)
+		{
+			self.ghostsAddress.Add(address);
+		}
+
+		public static void RemoveGhost(this MasterComponent self, IPEndPoint address)
+		{
+			self.ghostsAddress.Remove(address);
+		}
+
+		public static Task<bool> Lock(this MasterComponent self, IPEndPoint address)
+		{
+			if (self.lockedAddress == null)
+			{
+				self.lockedAddress = address;
+				return Task.FromResult(true);
+			}
+
+			TaskCompletionSource<bool> tcs = new TaskCompletionSource<bool>();
+			LockInfo lockInfo = new LockInfo(address, tcs);
+			self.queue.Enqueue(lockInfo);
+			return tcs.Task;
+		}
+
+		public static void Release(this MasterComponent self, IPEndPoint address)
+		{
+			if (!self.lockedAddress.Equals(address))
+			{
+				Log.Error($"解锁地址与锁地址不匹配! {self.lockedAddress} {address}");
+				return;
+			}
+			if (self.queue.Count == 0)
+			{
+				self.lockedAddress = null;
+				return;
+			}
+			LockInfo lockInfo = self.queue.Dequeue();
+			self.lockedAddress = lockInfo.Address;
+			lockInfo.Tcs.SetResult(true);
+		}
+	}
+}

+ 83 - 0
Server/Hotfix/Module/DB/DBProxyComponentSystem.cs

@@ -0,0 +1,83 @@
+using System.Collections.Generic;
+using System.Threading;
+using System.Threading.Tasks;
+using ETModel;
+
+namespace ETHotfix
+{
+	[ObjectSystem]
+	public class DbProxyComponentSystem : AwakeSystem<DBProxyComponent>
+	{
+		public override void Awake(DBProxyComponent self)
+		{
+			self.Awake();
+		}
+	}
+	
+	/// <summary>
+	/// 用来与数据库操作代理
+	/// </summary>
+	public static class DBProxyComponentEx
+	{
+		public static void Awake(this DBProxyComponent self)
+		{
+			StartConfig dbStartConfig = Game.Scene.GetComponent<StartConfigComponent>().DBConfig;
+			self.dbAddress = dbStartConfig.GetComponent<InnerConfig>().IPEndPoint;
+		}
+
+		public static async Task Save(this DBProxyComponent self, ComponentWithId component, bool needCache = true)
+		{
+			Session session = Game.Scene.GetComponent<NetInnerComponent>().Get(self.dbAddress);
+			await session.Call(new DBSaveRequest { Component = component, NeedCache = needCache});
+		}
+
+		public static async Task SaveBatch(this DBProxyComponent self, List<ComponentWithId> components, bool needCache = true)
+		{
+			Session session = Game.Scene.GetComponent<NetInnerComponent>().Get(self.dbAddress);
+			await session.Call(new DBSaveBatchRequest { Components = components, NeedCache = needCache});
+		}
+
+		public static async Task Save(this DBProxyComponent self, ComponentWithId component, bool needCache, CancellationToken cancellationToken)
+		{
+			Session session = Game.Scene.GetComponent<NetInnerComponent>().Get(self.dbAddress);
+			await session.Call(new DBSaveRequest { Component = component, NeedCache = needCache}, cancellationToken);
+		}
+
+		public static async void SaveLog(this DBProxyComponent self, ComponentWithId component)
+		{
+			Session session = Game.Scene.GetComponent<NetInnerComponent>().Get(self.dbAddress);
+			await session.Call(new DBSaveRequest { Component = component,  NeedCache = false, CollectionName = "Log" });
+		}
+
+		public static async Task<T> Query<T>(this DBProxyComponent self, long id, bool needCache = true) where T: ComponentWithId
+		{
+			Session session = Game.Scene.GetComponent<NetInnerComponent>().Get(self.dbAddress);
+			DBQueryResponse dbQueryResponse = (DBQueryResponse)await session.Call(new DBQueryRequest { CollectionName = typeof(T).Name, Id = id, NeedCache = needCache });
+			return (T)dbQueryResponse.Component;
+		}
+
+		public static async Task<List<T>> QueryBatch<T>(this DBProxyComponent self, List<long> ids, bool needCache = true) where T : ComponentWithId
+		{
+			List<T> list = new List<T>();
+			Session session = Game.Scene.GetComponent<NetInnerComponent>().Get(self.dbAddress);
+			DBQueryBatchResponse dbQueryBatchResponse = (DBQueryBatchResponse)await session.Call(new DBQueryBatchRequest { CollectionName = typeof(T).Name, IdList = ids, NeedCache = needCache});
+			foreach (ComponentWithId component in dbQueryBatchResponse.Components)
+			{
+				list.Add((T)component);
+			}
+			return list;
+		}
+
+		public static async Task<List<T>> QueryJson<T>(this DBProxyComponent self, string json) where T : ComponentWithId
+		{
+			List<T> list = new List<T>();
+			Session session = Game.Scene.GetComponent<NetInnerComponent>().Get(self.dbAddress);
+			DBQueryJsonResponse dbQueryJsonResponse = (DBQueryJsonResponse)await session.Call(new DBQueryJsonRequest { CollectionName = typeof(T).Name, Json = json });
+			foreach (ComponentWithId component in dbQueryJsonResponse.Components)
+			{
+				list.Add((T)component);
+			}
+			return list;
+		}
+	}
+}

+ 57 - 0
Server/Hotfix/Module/Location/LocationProxyComponentSystem.cs

@@ -0,0 +1,57 @@
+using System.Threading.Tasks;
+using ETModel;
+
+namespace ETHotfix
+{
+	[ObjectSystem]
+	public class LocationProxyComponentSystem : AwakeSystem<LocationProxyComponent>
+	{
+		public override void Awake(LocationProxyComponent self)
+		{
+			self.Awake();
+		}
+	}
+
+	public static class LocationProxyComponentEx
+	{
+		public static void Awake(this LocationProxyComponent self)
+		{
+			StartConfigComponent startConfigComponent = Game.Scene.GetComponent<StartConfigComponent>();
+			self.AppId = startConfigComponent.StartConfig.AppId;
+
+			StartConfig startConfig = startConfigComponent.LocationConfig;
+			self.LocationAddress = startConfig.GetComponent<InnerConfig>().IPEndPoint;
+		}
+
+		public static async Task Add(this LocationProxyComponent self, long key)
+		{
+			Session session = Game.Scene.GetComponent<NetInnerComponent>().Get(self.LocationAddress);
+			await session.Call(new ObjectAddRequest() { Key = key, AppId = self.AppId });
+		}
+
+		public static async Task Lock(this LocationProxyComponent self, long key, int time = 1000)
+		{
+			Session session = Game.Scene.GetComponent<NetInnerComponent>().Get(self.LocationAddress);
+			await session.Call(new ObjectLockRequest() { Key = key, LockAppId = self.AppId, Time = time });
+		}
+
+		public static async Task UnLock(this LocationProxyComponent self, long key, int value)
+		{
+			Session session = Game.Scene.GetComponent<NetInnerComponent>().Get(self.LocationAddress);
+			await session.Call(new ObjectUnLockRequest() { Key = key, UnLockAppId = self.AppId, AppId = value});
+		}
+
+		public static async Task Remove(this LocationProxyComponent self, long key)
+		{
+			Session session = Game.Scene.GetComponent<NetInnerComponent>().Get(self.LocationAddress);
+			await session.Call(new ObjectRemoveRequest() { Key = key });
+		}
+
+		public static async Task<int> Get(this LocationProxyComponent self, long key)
+		{
+			Session session = Game.Scene.GetComponent<NetInnerComponent>().Get(self.LocationAddress);
+			ObjectGetResponse response = (ObjectGetResponse)await session.Call(new ObjectGetRequest() { Key = key });
+			return response.AppId;
+		}
+	}
+}

+ 1 - 1
Server/Model/Module/Message/HotfixMessage.cs → Server/Hotfix/Module/Message/HotfixMessage.cs

@@ -2,7 +2,7 @@ using ProtoBuf;
 using ETModel;
 using System.Collections.Generic;
 using MongoDB.Bson.Serialization.Attributes;
-namespace ETModel
+namespace ETHotfix
 {
 	[Message(HotfixOpcode.C2R_Login)]
 	[ProtoContract]

+ 0 - 0
Server/Model/Module/Message/HotfixOpcode.cs → Server/Hotfix/Module/Message/HotfixOpcode.cs


+ 1 - 1
Server/Model/Module/Message/InnerMessage.cs → Server/Hotfix/Module/Message/InnerMessage.cs

@@ -2,7 +2,7 @@ using ProtoBuf;
 using ETModel;
 using System.Collections.Generic;
 using MongoDB.Bson.Serialization.Attributes;
-namespace ETModel
+namespace ETHotfix
 {
 /// <summary>
 /// 传送unit

+ 0 - 0
Server/Model/Module/Message/InnerOpcode.cs → Server/Hotfix/Module/Message/InnerOpcode.cs


+ 1 - 37
Server/Model/Module/Message/OuterMessage.cs → Server/Hotfix/Module/Message/OuterMessage.cs

@@ -2,7 +2,7 @@ using ProtoBuf;
 using ETModel;
 using System.Collections.Generic;
 using MongoDB.Bson.Serialization.Attributes;
-namespace ETModel
+namespace ETHotfix
 {
 	[Message(OuterOpcode.Actor_Test)]
 	[ProtoContract]
@@ -142,42 +142,6 @@ namespace ETModel
 
 	}
 
-	[Message(OuterOpcode.OneFrameMessage)]
-	[ProtoContract]
-	public partial class OneFrameMessage: IActorMessage
-	{
-		[ProtoMember(90, IsRequired = true)]
-		public int RpcId { get; set; }
-
-		[ProtoMember(93, IsRequired = true)]
-		public long ActorId { get; set; }
-
-		[ProtoMember(1, IsRequired = true)]
-		public ushort Op;
-
-		[ProtoMember(2, IsRequired = true)]
-		public byte[] AMessage;
-
-	}
-
-	[Message(OuterOpcode.FrameMessage)]
-	[ProtoContract]
-	public partial class FrameMessage: IActorMessage
-	{
-		[ProtoMember(90, IsRequired = true)]
-		public int RpcId { get; set; }
-
-		[ProtoMember(93, IsRequired = true)]
-		public long ActorId { get; set; }
-
-		[ProtoMember(1, IsRequired = true)]
-		public int Frame;
-
-		[ProtoMember(2)]
-		public List<OneFrameMessage> Messages = new List<OneFrameMessage>();
-
-	}
-
 	[Message(OuterOpcode.Frame_ClickMap)]
 	[ProtoContract]
 	public partial class Frame_ClickMap: IFrameMessage

+ 5 - 7
Server/Model/Module/Message/OuterOpcode.cs → Server/Hotfix/Module/Message/OuterOpcode.cs

@@ -11,12 +11,10 @@ namespace ETModel
 		 public const ushort G2C_EnterMap = 107;
 		 public const ushort UnitInfo = 108;
 		 public const ushort Actor_CreateUnits = 109;
-		 public const ushort OneFrameMessage = 110;
-		 public const ushort FrameMessage = 111;
-		 public const ushort Frame_ClickMap = 112;
-		 public const ushort C2M_Reload = 113;
-		 public const ushort M2C_Reload = 114;
-		 public const ushort C2R_Ping = 115;
-		 public const ushort R2C_Ping = 116;
+		 public const ushort Frame_ClickMap = 110;
+		 public const ushort C2M_Reload = 111;
+		 public const ushort M2C_Reload = 112;
+		 public const ushort C2R_Ping = 113;
+		 public const ushort R2C_Ping = 114;
 	}
 }

+ 2 - 10
Server/Hotfix/Server.Hotfix.csproj

@@ -1,37 +1,29 @@
-<Project Sdk="Microsoft.NET.Sdk">
-
+<Project Sdk="Microsoft.NET.Sdk">
   <PropertyGroup>
     <TargetFramework>netcoreapp2.0</TargetFramework>
     <AssemblyName>Hotfix</AssemblyName>
     <RootNamespace>ETHotfix</RootNamespace>
   </PropertyGroup>
-	
   <PropertyGroup>
     <AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
   </PropertyGroup>
-
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
     <DefineConstants>TRACE;DEBUG;NETCOREAPP2_0;SERVER</DefineConstants>
     <OutputPath>..\..\Bin\</OutputPath>
   </PropertyGroup>
-
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
     <DefineConstants>TRACE;RELEASE;NETCOREAPP2_0;SERVER</DefineConstants>
     <OutputPath>..\..\Bin\</OutputPath>
   </PropertyGroup>
-
   <ItemGroup>
     <Compile Remove="Other\**" />
     <EmbeddedResource Remove="Other\**" />
     <None Remove="Other\**" />
   </ItemGroup>
-
   <ItemGroup>
     <ProjectReference Include="..\Model\Server.Model.csproj" />
   </ItemGroup>
-
   <ItemGroup>
     <Folder Include="Module\Http\" />
   </ItemGroup>
-
-</Project>
+</Project>

+ 0 - 71
Server/Model/Component/Unit/MasterComponent.cs

@@ -1,71 +0,0 @@
-using System.Collections.Generic;
-using System.Net;
-using System.Threading.Tasks;
-
-namespace ETModel
-{
-	public class LockInfo
-	{
-		public IPEndPoint Address;
-		public TaskCompletionSource<bool> Tcs;
-
-		public LockInfo(IPEndPoint address, TaskCompletionSource<bool> tcs)
-		{
-			this.Address = address;
-			this.Tcs = tcs;
-		}
-	}
-	
-	public class MasterComponent : Component
-	{
-		/// 镜像的地址
-		private readonly List<IPEndPoint> ghostsAddress = new List<IPEndPoint>();
-
-		/// 当前获取锁的进程地址
-		private IPEndPoint lockedAddress;
-
-		/// 请求锁的队列
-		private readonly Queue<LockInfo> queue = new Queue<LockInfo>();
-
-		public void AddGhost(IPEndPoint address)
-		{
-			this.ghostsAddress.Add(address);
-		}
-
-		public void RemoveGhost(IPEndPoint address)
-		{
-			this.ghostsAddress.Remove(address);
-		}
-
-		public Task<bool> Lock(IPEndPoint address)
-		{
-			if (this.lockedAddress == null)
-			{
-				this.lockedAddress = address;
-				return Task.FromResult(true);
-			}
-
-			TaskCompletionSource<bool> tcs = new TaskCompletionSource<bool>();
-			LockInfo lockInfo = new LockInfo(address, tcs);
-			this.queue.Enqueue(lockInfo);
-			return tcs.Task;
-		}
-
-		public void Release(IPEndPoint address)
-		{
-			if (!this.lockedAddress.Equals(address))
-			{
-				Log.Error($"解锁地址与锁地址不匹配! {this.lockedAddress} {address}");
-				return;
-			}
-			if (this.queue.Count == 0)
-			{
-				this.lockedAddress = null;
-				return;
-			}
-			LockInfo lockInfo = this.queue.Dequeue();
-			this.lockedAddress = lockInfo.Address;
-			lockInfo.Tcs.SetResult(true);
-		}
-	}
-}

+ 3 - 188
Server/Model/Module/Actor/ActorProxy.cs

@@ -1,32 +1,10 @@
-using System;
-using System.Collections.Generic;
+using System.Collections.Generic;
 using System.Net;
 using System.Threading;
 using System.Threading.Tasks;
 
 namespace ETModel
 {
-	[ObjectSystem]
-	public class ActorProxyAwakeSystem : AwakeSystem<ActorProxy>
-	{
-		public override void Awake(ActorProxy self)
-		{
-			self.Awake();
-		}
-	}
-
-	[ObjectSystem]
-	public class ActorProxyStartSystem : StartSystem<ActorProxy>
-	{
-		public override async void Start(ActorProxy self)
-		{
-			int appId = await Game.Scene.GetComponent<LocationProxyComponent>().Get(self.Id);
-			self.Address = Game.Scene.GetComponent<StartConfigComponent>().Get(appId).GetComponent<InnerConfig>().IPEndPoint;
-
-			self.UpdateAsync();
-		}
-	}
-
 	public sealed class ActorProxy : ComponentWithId
 	{
 		// actor的地址
@@ -38,173 +16,10 @@ namespace ETModel
 		// 最近发送消息的时间
 		public long LastSendTime;
 
-		private TaskCompletionSource<ActorTask> tcs;
+		public TaskCompletionSource<ActorTask> tcs;
 
 		public CancellationTokenSource CancellationTokenSource;
 
-		private int failTimes;
-		
-		public void Awake()
-		{
-			this.LastSendTime = TimeHelper.Now();
-			this.tcs = null;
-			this.CancellationTokenSource = new CancellationTokenSource();
-		}
-
-		public override void Dispose()
-		{
-			if (this.IsDisposed)
-			{
-				return;
-			}
-
-			base.Dispose();
-			this.LastSendTime = 0;
-			this.Address = null;
-
-			while (this.WaitingTasks.Count > 0)
-			{
-				ActorTask actorTask = this.WaitingTasks.Dequeue();
-				actorTask.RunFail(ErrorCode.ERR_NotFoundActor);
-			}
-
-			this.failTimes = 0;
-			var t = this.tcs;
-			this.tcs = null;
-			t?.SetResult(new ActorTask());
-		}
-		
-		private void Add(ActorTask task)
-		{
-			if (this.IsDisposed)
-			{
-				throw new Exception("ActorProxy Disposed! dont hold actorproxy");
-			}
-			this.WaitingTasks.Enqueue(task);
-			// failtimes > 0表示正在重试,这时候不能加到正在发送队列
-			if (this.failTimes == 0)
-			{
-				this.AllowGet();
-			}
-		}
-		
-		private void AllowGet()
-		{
-			if (this.tcs == null || this.WaitingTasks.Count <= 0)
-			{
-				return;
-			}
-			ActorTask task = this.WaitingTasks.Peek();
-
-			var t = this.tcs;
-			this.tcs = null;
-			t.SetResult(task);
-		}
-
-		private Task<ActorTask> GetAsync()
-		{
-			if (this.WaitingTasks.Count > 0)
-			{
-				ActorTask task = this.WaitingTasks.Peek();
-				return Task.FromResult(task);
-			}
-			
-			this.tcs = new TaskCompletionSource<ActorTask>();
-			return this.tcs.Task;
-		}
-
-		public async void UpdateAsync()
-		{
-			while (true)
-			{
-				ActorTask actorTask = await this.GetAsync();
-				if (this.IsDisposed)
-				{
-					return;
-				}
-				try
-				{
-					await this.RunTask(actorTask);
-				}
-				catch (Exception e)
-				{
-					Log.Error(e);
-					return;
-				}
-			}
-		}
-
-		private async Task RunTask(ActorTask task)
-		{
-			try
-			{
-				IResponse response = await task.Run();
-
-				// 如果没找到Actor,重试
-				if (response.Error == ErrorCode.ERR_NotFoundActor)
-				{
-					this.CancellationTokenSource.Cancel();
-					++this.failTimes;
-					
-					// 失败10次则清空actor发送队列,返回失败
-					if (this.failTimes > 10)
-					{
-						// 失败直接删除actorproxy
-						Log.Info($"actor send message fail, actorid: {this.Id}");
-						Game.Scene.GetComponent<ActorProxyComponent>().Remove(this.Id);
-						return;
-					}
-					// 等待1s再发送
-					await Game.Scene.GetComponent<TimerComponent>().WaitAsync(1000);
-					int appId = await Game.Scene.GetComponent<LocationProxyComponent>().Get(this.Id);
-					this.Address = Game.Scene.GetComponent<StartConfigComponent>().Get(appId).GetComponent<InnerConfig>().IPEndPoint;
-					this.CancellationTokenSource = new CancellationTokenSource();
-					this.AllowGet();
-					return;
-				}
-
-				// 发送成功
-				this.LastSendTime = TimeHelper.Now();
-				this.failTimes = 0;
-
-				this.WaitingTasks.Dequeue();
-			}
-			catch (Exception e)
-			{
-				Log.Error(e);
-			}
-		}
-
-		public void Send(IActorMessage message)
-		{
-			ActorTask task = new ActorTask
-			{
-				message = message,
-				proxy = this
-			};
-			this.Add(task);
-		}
-
-		public Task<IResponse> Call(IActorRequest request)
-		{
-			ActorTask task = new ActorTask
-			{
-				message = request,
-				proxy = this,
-				Tcs = new TaskCompletionSource<IResponse>()
-			};
-			this.Add(task);
-			return task.Tcs.Task;
-		}
-
-		public string DebugQueue(Queue<ActorTask> tasks)
-		{
-			string s = "";
-			foreach (ActorTask task in tasks)
-			{
-				s += $" {task.message.GetType().Name}";
-			}
-			return s;
-		}
+		public int failTimes;
 	}
 }

+ 13 - 0
Server/Model/Module/Benchmark/BenchmarkComponent.cs

@@ -0,0 +1,13 @@
+using System;
+using System.Net;
+using System.Threading.Tasks;
+
+namespace ETModel
+{
+	public class BenchmarkComponent: Component
+	{
+		public int k;
+
+		public long time1 = TimeHelper.ClientNow();
+	}
+}

+ 25 - 0
Server/Model/Module/BigWorld/LockComponent.cs

@@ -0,0 +1,25 @@
+using System;
+using System.Collections.Generic;
+using System.Net;
+using System.Threading.Tasks;
+
+namespace ETModel
+{
+	public enum LockStatus
+	{
+		LockedNot,
+		LockRequesting,
+		Locked,
+	}
+
+	/// <summary>
+	/// 分布式锁组件,Unit对象可能在不同进程上有镜像,访问该对象的时候需要对他加锁
+	/// </summary>
+	public class LockComponent: Component
+	{
+		public LockStatus status = LockStatus.LockedNot;
+		public IPEndPoint address;
+		public int lockCount;
+		public readonly Queue<TaskCompletionSource<bool>> queue = new Queue<TaskCompletionSource<bool>>();
+	}
+}

+ 30 - 0
Server/Model/Module/BigWorld/MasterComponent.cs

@@ -0,0 +1,30 @@
+using System.Collections.Generic;
+using System.Net;
+using System.Threading.Tasks;
+
+namespace ETModel
+{
+	public class LockInfo
+	{
+		public IPEndPoint Address;
+		public TaskCompletionSource<bool> Tcs;
+
+		public LockInfo(IPEndPoint address, TaskCompletionSource<bool> tcs)
+		{
+			this.Address = address;
+			this.Tcs = tcs;
+		}
+	}
+	
+	public class MasterComponent : Component
+	{
+		/// 镜像的地址
+		public readonly List<IPEndPoint> ghostsAddress = new List<IPEndPoint>();
+
+		/// 当前获取锁的进程地址
+		public IPEndPoint lockedAddress;
+
+		/// 请求锁的队列
+		public readonly Queue<LockInfo> queue = new Queue<LockInfo>();
+	}
+}

+ 2 - 75
Server/Model/Module/DB/DBProxyComponent.cs

@@ -1,85 +1,12 @@
-using System.Collections.Generic;
-using System.Net;
-using System.Threading;
-using System.Threading.Tasks;
+using System.Net;
 
 namespace ETModel
 {
-	[ObjectSystem]
-	public class DbProxyComponentSystem : AwakeSystem<DBProxyComponent>
-	{
-		public override void Awake(DBProxyComponent self)
-		{
-			self.Awake();
-		}
-	}
-	
 	/// <summary>
 	/// 用来与数据库操作代理
 	/// </summary>
-	public class DBProxyComponent : Component
+	public class DBProxyComponent: Component
 	{
 		public IPEndPoint dbAddress;
-
-		public void Awake()
-		{
-			StartConfig dbStartConfig = Game.Scene.GetComponent<StartConfigComponent>().DBConfig;
-			dbAddress = dbStartConfig.GetComponent<InnerConfig>().IPEndPoint;
-		}
-
-		public async Task Save(ComponentWithId component, bool needCache = true)
-		{
-			Session session = Game.Scene.GetComponent<NetInnerComponent>().Get(dbAddress);
-			await session.Call(new DBSaveRequest { Component = component, NeedCache = needCache});
-		}
-
-		public async Task SaveBatch(List<ComponentWithId> components, bool needCache = true)
-		{
-			Session session = Game.Scene.GetComponent<NetInnerComponent>().Get(dbAddress);
-			await session.Call(new DBSaveBatchRequest { Components = components, NeedCache = needCache});
-		}
-
-		public async Task Save(ComponentWithId component, bool needCache, CancellationToken cancellationToken)
-		{
-			Session session = Game.Scene.GetComponent<NetInnerComponent>().Get(dbAddress);
-			await session.Call(new DBSaveRequest { Component = component, NeedCache = needCache}, cancellationToken);
-		}
-
-		public async void SaveLog(ComponentWithId component)
-		{
-			Session session = Game.Scene.GetComponent<NetInnerComponent>().Get(dbAddress);
-			await session.Call(new DBSaveRequest { Component = component,  NeedCache = false, CollectionName = "Log" });
-		}
-
-		public async Task<T> Query<T>(long id, bool needCache = true) where T: ComponentWithId
-		{
-			Session session = Game.Scene.GetComponent<NetInnerComponent>().Get(dbAddress);
-			DBQueryResponse dbQueryResponse = (DBQueryResponse)await session.Call(new DBQueryRequest { CollectionName = typeof(T).Name, Id = id, NeedCache = needCache });
-			return (T)dbQueryResponse.Component;
-		}
-
-		public async Task<List<T>> QueryBatch<T>(List<long> ids, bool needCache = true) where T : ComponentWithId
-		{
-			List<T> list = new List<T>();
-			Session session = Game.Scene.GetComponent<NetInnerComponent>().Get(dbAddress);
-			DBQueryBatchResponse dbQueryBatchResponse = (DBQueryBatchResponse)await session.Call(new DBQueryBatchRequest { CollectionName = typeof(T).Name, IdList = ids, NeedCache = needCache});
-			foreach (ComponentWithId component in dbQueryBatchResponse.Components)
-			{
-				list.Add((T)component);
-			}
-			return list;
-		}
-
-		public async Task<List<T>> QueryJson<T>(string json) where T : ComponentWithId
-		{
-			List<T> list = new List<T>();
-			Session session = Game.Scene.GetComponent<NetInnerComponent>().Get(dbAddress);
-			DBQueryJsonResponse dbQueryJsonResponse = (DBQueryJsonResponse)await session.Call(new DBQueryJsonRequest { CollectionName = typeof(T).Name, Json = json });
-			foreach (ComponentWithId component in dbQueryJsonResponse.Components)
-			{
-				list.Add((T)component);
-			}
-			return list;
-		}
 	}
 }

+ 0 - 58
Server/Model/Module/Location/LocationProxyComponent.cs

@@ -3,68 +3,10 @@ using System.Threading.Tasks;
 
 namespace ETModel
 {
-	[ObjectSystem]
-	public class LocationProxyComponentSystem : AwakeSystem<LocationProxyComponent>
-	{
-		public override void Awake(LocationProxyComponent self)
-		{
-			self.Awake();
-		}
-	}
-
 	public class LocationProxyComponent : Component
 	{
 		public IPEndPoint LocationAddress;
 
 		public int AppId;
-
-		public void Awake()
-		{
-			StartConfigComponent startConfigComponent = Game.Scene.GetComponent<StartConfigComponent>();
-			this.AppId = startConfigComponent.StartConfig.AppId;
-
-			StartConfig startConfig = startConfigComponent.LocationConfig;
-			this.LocationAddress = startConfig.GetComponent<InnerConfig>().IPEndPoint;
-		}
-
-		public async Task Add(long key)
-		{
-			Session session = Game.Scene.GetComponent<NetInnerComponent>().Get(this.LocationAddress);
-			await session.Call(new ObjectAddRequest() { Key = key, AppId = this.AppId });
-		}
-
-		public async Task Lock(long key, int time = 1000)
-		{
-			Session session = Game.Scene.GetComponent<NetInnerComponent>().Get(this.LocationAddress);
-			await session.Call(new ObjectLockRequest() { Key = key, LockAppId = this.AppId, Time = time });
-		}
-
-		public async Task UnLock(long key, int value)
-		{
-			Session session = Game.Scene.GetComponent<NetInnerComponent>().Get(this.LocationAddress);
-			await session.Call(new ObjectUnLockRequest() { Key = key, UnLockAppId = this.AppId, AppId = value});
-		}
-
-		public async Task Remove(long key)
-		{
-			Session session = Game.Scene.GetComponent<NetInnerComponent>().Get(this.LocationAddress);
-			await session.Call(new ObjectRemoveRequest() { Key = key });
-		}
-
-		public async Task<int> Get(long key)
-		{
-			Session session = Game.Scene.GetComponent<NetInnerComponent>().Get(this.LocationAddress);
-			ObjectGetResponse response = (ObjectGetResponse)await session.Call(new ObjectGetRequest() { Key = key });
-			return response.AppId;
-		}
-
-		public override void Dispose()
-		{
-			if (this.IsDisposed)
-			{
-				return;
-			}
-			base.Dispose();
-		}
 	}
 }

+ 4 - 10
Server/Model/Server.Model.csproj

@@ -1,25 +1,20 @@
-<Project Sdk="Microsoft.NET.Sdk">
-
+<Project Sdk="Microsoft.NET.Sdk">
   <PropertyGroup>
     <TargetFramework>netcoreapp2.0</TargetFramework>
     <AssemblyName>Model</AssemblyName>
     <RootNamespace>Model</RootNamespace>
   </PropertyGroup>
-
   <PropertyGroup>
     <AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
   </PropertyGroup>
-
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
     <DefineConstants>TRACE;DEBUG;NETCOREAPP2_0;SERVER</DefineConstants>
     <OutputPath>..\..\Bin\</OutputPath>
   </PropertyGroup>
-
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
     <DefineConstants>TRACE;RELEASE;NETCOREAPP2_0;SERVER</DefineConstants>
     <OutputPath>..\..\Bin\</OutputPath>
   </PropertyGroup>
-
   <ItemGroup>
     <Compile Include="..\..\Unity\Assets\Scripts\Base\DoubleMap.cs" Link="Base\DoubleMap.cs" />
     <Compile Include="..\..\Unity\Assets\Scripts\Base\Event\Env.cs" Link="Base\Event\Env.cs" />
@@ -69,6 +64,7 @@
     <Compile Include="..\..\Unity\Assets\Scripts\Module\Config\ConfigAttribute.cs" Link="Module\Config\ConfigAttribute.cs" />
     <Compile Include="..\..\Unity\Assets\Scripts\Module\Config\ConfigComponent.cs" Link="Module\Config\ConfigComponent.cs" />
     <Compile Include="..\..\Unity\Assets\Scripts\Module\Config\IConfig.cs" Link="Module\Config\IConfig.cs" />
+    <Compile Include="..\..\Unity\Assets\Scripts\Module\FrameSync\FrameMessage.cs" Link="Module\FrameSync\FrameMessage.cs" />
     <Compile Include="..\..\Unity\Assets\Scripts\Module\Message\AMHandler.cs" Link="Module\Message\AMHandler.cs" />
     <Compile Include="..\..\Unity\Assets\Scripts\Module\Message\ErrorCode.cs" Link="Module\Message\ErrorCode.cs" />
     <Compile Include="..\..\Unity\Assets\Scripts\Module\Message\IActorMessage.cs" Link="Module\Message\IActorMessage.cs" />
@@ -104,24 +100,22 @@
     <Compile Include="..\..\Unity\Assets\Scripts\Module\Numeric\NumericWatcherComponent.cs" Link="Module\Numeric\NumericWatcherComponent.cs" />
     <Compile Include="..\..\Unity\Assets\Scripts\Other\AppType.cs" Link="Other\AppType.cs" />
   </ItemGroup>
-
   <ItemGroup>
     <PackageReference Include="CommandLineParser" Version="2.2.1" />
     <PackageReference Include="NLog" Version="4.5.0-rc04" />
     <PackageReference Include="protobuf-net" Version="2.3.4" />
     <PackageReference Include="SharpZipLib" Version="1.0.0-alpha2" />
   </ItemGroup>
-
   <ItemGroup>
     <ProjectReference Include="..\ThirdParty\MongodbDriver\DotNetCoreDriver\MongoDB.Bson\MongoDB.Bson.csproj" />
     <ProjectReference Include="..\ThirdParty\MongodbDriver\DotNetCoreDriver\MongoDB.Driver.Core\MongoDB.Driver.Core.csproj" />
     <ProjectReference Include="..\ThirdParty\MongodbDriver\DotNetCoreDriver\MongoDB.Driver\MongoDB.Driver.csproj" />
   </ItemGroup>
-
   <ItemGroup>
     <Folder Include="Component\Config\" />
+    <Folder Include="Component\Unit" />
     <Folder Include="Module\Message\Network\KCP\" />
     <Folder Include="Module\Message\Network\TCP\" />
     <Folder Include="Module\Numeric\" />
   </ItemGroup>
-</Project>
+</Project>

+ 4 - 4
Unity/Assets/Editor/Proto2CsEditor/Proto2CSEditor.cs

@@ -24,7 +24,7 @@ namespace ETEditor
 	public class Proto2CSEditor : EditorWindow
 	{
 		private const string protoPath = "../Proto/";
-		private const string serverMessagePath = "../Server/Model/Module/Message/";
+		private const string serverMessagePath = "../Server/Hotfix/Module/Message/";
 		private const string clientMessagePath = "Assets/Scripts/Module/Message/";
 		private const string hotfixMessagePath = "Hotfix/Module/Message/";
 		private static readonly char[] splitChars = { ' ', '\t' };
@@ -38,7 +38,7 @@ namespace ETEditor
 			Proto2CS("ETModel", "OuterMessage.proto", clientMessagePath, "OuterOpcode", 100, HeadFlag.Proto);
 			GenerateOpcode("OuterOpcode", clientMessagePath);
 
-			Proto2CS("ETModel", "OuterMessage.proto", serverMessagePath, "OuterOpcode", 100, HeadFlag.Proto | HeadFlag.Bson, false);
+			Proto2CS("ETHotfix", "OuterMessage.proto", serverMessagePath, "OuterOpcode", 100, HeadFlag.Proto | HeadFlag.Bson, false);
 			GenerateOpcode("OuterOpcode", serverMessagePath);
 
 			msgOpcode.Clear();
@@ -46,11 +46,11 @@ namespace ETEditor
 			GenerateOpcode("HotfixOpcode", hotfixMessagePath);
 
 			msgOpcode.Clear();
-			Proto2CS("ETModel", "HotfixMessage.proto", serverMessagePath, "HotfixOpcode", 10000, HeadFlag.Bson, false);
+			Proto2CS("ETHotfix", "HotfixMessage.proto", serverMessagePath, "HotfixOpcode", 10000, HeadFlag.Bson, false);
 			GenerateOpcode("HotfixOpcode", serverMessagePath);
 
 			msgOpcode.Clear();
-			Proto2CS("ETModel", "InnerMessage.proto", serverMessagePath, "InnerOpcode", 1000, HeadFlag.Bson, false);
+			Proto2CS("ETHotfix", "InnerMessage.proto", serverMessagePath, "InnerOpcode", 1000, HeadFlag.Bson, false);
 			GenerateOpcode("InnerOpcode", serverMessagePath);
 
 			AssetDatabase.Refresh();

+ 42 - 0
Unity/Assets/Scripts/Module/FrameSync/FrameMessage.cs

@@ -0,0 +1,42 @@
+using System.Collections.Generic;
+using ProtoBuf;
+
+namespace ETModel
+{
+
+    [Message(Opcode.OneFrameMessage)]
+    [ProtoContract]
+    public partial class OneFrameMessage: IActorMessage
+    {
+        [ProtoMember(90, IsRequired = true)]
+        public int RpcId { get; set; }
+
+        [ProtoMember(93, IsRequired = true)]
+        public long ActorId { get; set; }
+
+        [ProtoMember(1, IsRequired = true)]
+        public ushort Op;
+
+        [ProtoMember(2, IsRequired = true)]
+        public byte[] AMessage;
+
+    }
+
+    [Message(Opcode.FrameMessage)]
+    [ProtoContract]
+    public partial class FrameMessage: IActorMessage
+    {
+        [ProtoMember(90, IsRequired = true)]
+        public int RpcId { get; set; }
+
+        [ProtoMember(93, IsRequired = true)]
+        public long ActorId { get; set; }
+
+        [ProtoMember(1, IsRequired = true)]
+        public int Frame;
+
+        [ProtoMember(2)]
+        public List<OneFrameMessage> Messages = new List<OneFrameMessage>();
+
+    }
+}

+ 12 - 0
Unity/Assets/Scripts/Module/FrameSync/FrameMessage.cs.meta

@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 6a109203eeeb90d46ab73f54fd2a82a5
+timeCreated: 1524623132
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 2 - 0
Unity/Assets/Scripts/Module/Message/Opcode.cs

@@ -3,5 +3,7 @@ namespace ETModel
 	public static partial class Opcode
 	{
 		public const ushort ActorResponse = 1;
+		public const ushort FrameMessage = 2;
+		public const ushort OneFrameMessage = 3;
 	}
 }

+ 0 - 36
Unity/Assets/Scripts/Module/Message/OuterMessage.cs

@@ -142,42 +142,6 @@ namespace ETModel
 
 	}
 
-	[Message(OuterOpcode.OneFrameMessage)]
-	[ProtoContract]
-	public partial class OneFrameMessage: IActorMessage
-	{
-		[ProtoMember(90, IsRequired = true)]
-		public int RpcId { get; set; }
-
-		[ProtoMember(93, IsRequired = true)]
-		public long ActorId { get; set; }
-
-		[ProtoMember(1, IsRequired = true)]
-		public ushort Op;
-
-		[ProtoMember(2, IsRequired = true)]
-		public byte[] AMessage;
-
-	}
-
-	[Message(OuterOpcode.FrameMessage)]
-	[ProtoContract]
-	public partial class FrameMessage: IActorMessage
-	{
-		[ProtoMember(90, IsRequired = true)]
-		public int RpcId { get; set; }
-
-		[ProtoMember(93, IsRequired = true)]
-		public long ActorId { get; set; }
-
-		[ProtoMember(1, IsRequired = true)]
-		public int Frame;
-
-		[ProtoMember(2, TypeName = "ETModel.OneFrameMessage")]
-		public List<OneFrameMessage> Messages = new List<OneFrameMessage>();
-
-	}
-
 	[Message(OuterOpcode.Frame_ClickMap)]
 	[ProtoContract]
 	public partial class Frame_ClickMap: IFrameMessage

+ 5 - 7
Unity/Assets/Scripts/Module/Message/OuterOpcode.cs

@@ -11,12 +11,10 @@ namespace ETModel
 		 public const ushort G2C_EnterMap = 107;
 		 public const ushort UnitInfo = 108;
 		 public const ushort Actor_CreateUnits = 109;
-		 public const ushort OneFrameMessage = 110;
-		 public const ushort FrameMessage = 111;
-		 public const ushort Frame_ClickMap = 112;
-		 public const ushort C2M_Reload = 113;
-		 public const ushort M2C_Reload = 114;
-		 public const ushort C2R_Ping = 115;
-		 public const ushort R2C_Ping = 116;
+		 public const ushort Frame_ClickMap = 110;
+		 public const ushort C2M_Reload = 111;
+		 public const ushort M2C_Reload = 112;
+		 public const ushort C2R_Ping = 113;
+		 public const ushort R2C_Ping = 114;
 	}
 }

+ 1 - 1
Unity/Hotfix/UI/UILobby/Component/UILobbyComponent.cs

@@ -23,7 +23,7 @@ namespace ETHotfix
 		{
 			ReferenceCollector rc = this.GetParent<UI>().GameObject.GetComponent<ReferenceCollector>();
 			GameObject sendBtn = rc.Get<GameObject>("Send");
-			GameObject sendRpcBtn = rc.Get<GameObject>("SendRpc");
+			GameObject sendRpcBtn = rc.Get<GameObject>("" + "SendRpc");
 			sendBtn.GetComponent<Button>().onClick.Add(this.OnSend);
 			sendRpcBtn.GetComponent<Button>().onClick.Add(this.OnSendRpc);
 

+ 8 - 4
Unity/Unity.csproj

@@ -12,13 +12,16 @@
     <ProjectTypeGuids>{E097FAD1-6243-4DAD-9C02-E9B9EFC3FFC1};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
     <TargetFrameworkIdentifier>.NETFramework</TargetFrameworkIdentifier>
     <TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
-    <TargetFrameworkProfile></TargetFrameworkProfile>
-    <CompilerResponseFile></CompilerResponseFile>
+    <TargetFrameworkProfile>
+    </TargetFrameworkProfile>
+    <CompilerResponseFile>
+    </CompilerResponseFile>
     <UnityProjectGenerator>VSTU</UnityProjectGenerator>
     <UnityProjectType>Game:1</UnityProjectType>
     <UnityBuildTarget>StandaloneWindows:5</UnityBuildTarget>
     <UnityVersion>2017.1.3p2</UnityVersion>
-    <RootNamespace></RootNamespace>
+    <RootNamespace>
+    </RootNamespace>
     <LangVersion>6</LangVersion>
   </PropertyGroup>
   <PropertyGroup>
@@ -266,6 +269,7 @@
     <Compile Include="Assets\Scripts\Module\FrameSync\AnimatorComponent.cs" />
     <Compile Include="Assets\Scripts\Module\FrameSync\CameraComponent.cs" />
     <Compile Include="Assets\Scripts\Module\FrameSync\ClientFrameComponent.cs" />
+    <Compile Include="Assets\Scripts\Module\FrameSync\FrameMessage.cs" />
     <Compile Include="Assets\Scripts\Module\FrameSync\MoveComponent.cs" />
     <Compile Include="Assets\Scripts\Module\FrameSync\Player.cs" />
     <Compile Include="Assets\Scripts\Module\FrameSync\PlayerComponent.cs" />
@@ -774,4 +778,4 @@
   </ItemGroup>
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
   <Target Name="GenerateTargetFrameworkMonikerAttribute" />
-</Project>
+</Project>

+ 0 - 5
Unity/Unity.sln

@@ -1,8 +1,6 @@
 
 Microsoft Visual Studio Solution File, Format Version 12.00
 # Visual Studio 15
-VisualStudioVersion = 15.0.27428.2015
-MinimumVisualStudioVersion = 10.0.40219.1
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Unity.Plugins", "Unity.Plugins.csproj", "{D1FDB199-0FB7-099D-3771-C6A942E4E326}"
 EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Unity", "Unity.csproj", "{CF118143-7E37-744F-BE45-3F55345FEC40}"
@@ -43,7 +41,4 @@ Global
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE
 	EndGlobalSection
-	GlobalSection(ExtensibilityGlobals) = postSolution
-		SolutionGuid = {300FBDB7-5336-420B-B6BE-7E5F863E4F8B}
-	EndGlobalSection
 EndGlobal