Browse Source

调整服务器hotfix,model工程share引用方式,避免客户端修改导致服务器报错

johnclot69 1 year ago
parent
commit
7cc93bcd9d
47 changed files with 1716 additions and 14 deletions
  1. 0 7
      DotNet/Hotfix/DotNet.Hotfix.csproj
  2. 20 0
      DotNet/Hotfix/Share/ConstValue.cs
  3. 17 0
      DotNet/Hotfix/Share/EntryEvent1_InitShare.cs
  4. 97 0
      DotNet/Hotfix/Share/Module/AI/AIComponentSystem.cs
  5. 54 0
      DotNet/Hotfix/Share/Module/AI/AIDispatcherComponentSystem.cs
  6. 113 0
      DotNet/Hotfix/Share/Module/Console/ConsoleComponentSystem.cs
  7. 34 0
      DotNet/Hotfix/Share/Module/Console/ReloadConfigConsoleHandler.cs
  8. 22 0
      DotNet/Hotfix/Share/Module/Console/ReloadDllConsoleHandler.cs
  9. 116 0
      DotNet/Hotfix/Share/Module/Message/MessageDispatcherComponentSystem.cs
  10. 58 0
      DotNet/Hotfix/Share/Module/Message/NetThreadComponentSystem.cs
  11. 38 0
      DotNet/Hotfix/Share/Module/Message/SessionAcceptTimeoutComponentSystem.cs
  12. 40 0
      DotNet/Hotfix/Share/Module/Scene/ClientSceneManagerComponentSystem.cs
  13. 12 0
      DotNet/Hotfix/Share/Module/Scene/CurrentScenesComponentSystem.cs
  14. 35 0
      DotNet/Hotfix/Share/Module/Scene/ServerSceneManagerComponentSystem.cs
  15. 0 0
      DotNet/Hotfix/Share/Plugins/Example/HotfixShare.cs
  16. 0 7
      DotNet/Model/DotNet.Model.csproj
  17. 43 0
      DotNet/Model/Share/Entry.cs
  18. 57 0
      DotNet/Model/Share/EventType.cs
  19. 18 0
      DotNet/Model/Share/Module/AI/AAIHandler.cs
  20. 15 0
      DotNet/Model/Share/Module/AI/AIComponent.cs
  21. 35 0
      DotNet/Model/Share/Module/AI/AIConfig.cs
  22. 13 0
      DotNet/Model/Share/Module/AI/AIDispatcherComponent.cs
  23. 15 0
      DotNet/Model/Share/Module/Actor/IActorMessage.cs
  24. 16 0
      DotNet/Model/Share/Module/ActorLocation/ActorResponse.cs
  25. 14 0
      DotNet/Model/Share/Module/ActorLocation/IActorLocationMessage.cs
  26. 23 0
      DotNet/Model/Share/Module/Console/ConsoleComponent.cs
  27. 12 0
      DotNet/Model/Share/Module/Console/ConsoleHandlerAttribute.cs
  28. 7 0
      DotNet/Model/Share/Module/Console/IConsoleHandler.cs
  29. 26 0
      DotNet/Model/Share/Module/Console/ModeContex.cs
  30. 37 0
      DotNet/Model/Share/Module/Message/AMHandler.cs
  31. 62 0
      DotNet/Model/Share/Module/Message/ErrorCode.cs
  32. 12 0
      DotNet/Model/Share/Module/Message/IMHandler.cs
  33. 36 0
      DotNet/Model/Share/Module/Message/IMessage.cs
  34. 31 0
      DotNet/Model/Share/Module/Message/MessageDispatcherComponent.cs
  35. 12 0
      DotNet/Model/Share/Module/Message/MessageHandlerAttribute.cs
  36. 14 0
      DotNet/Model/Share/Module/Message/NetThreadComponent.cs
  37. 59 0
      DotNet/Model/Share/Module/Message/OpcodeHelper.cs
  38. 96 0
      DotNet/Model/Share/Module/Message/OpcodeTypeComponent.cs
  39. 14 0
      DotNet/Model/Share/Module/Message/ResponseTypeAttribute.cs
  40. 170 0
      DotNet/Model/Share/Module/Message/Session.cs
  41. 9 0
      DotNet/Model/Share/Module/Message/SessionAcceptTimeoutComponent.cs
  42. 168 0
      DotNet/Model/Share/Module/ObjectWait/ObjectWait.cs
  43. 9 0
      DotNet/Model/Share/Module/Scene/ClientSceneManagerComponent.cs
  44. 9 0
      DotNet/Model/Share/Module/Scene/CurrentScenesComponent.cs
  45. 9 0
      DotNet/Model/Share/Module/Scene/ServerSceneManagerComponent.cs
  46. 1 0
      DotNet/Model/Share/Plugins/Example/ModelShare.cs
  47. 18 0
      DotNet/Model/Share/TimerInvokeType.cs

+ 0 - 7
DotNet/Hotfix/DotNet.Hotfix.csproj

@@ -21,13 +21,6 @@
         <Optimize>false</Optimize>
         <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
     </PropertyGroup>
-    <ItemGroup>
-
-        <Compile Include="..\..\Unity\Assets\Scripts\Codes\Hotfix\Share\**\*.cs">
-            <Link>Share\%(RecursiveDir)%(FileName)%(Extension)</Link> 
-        </Compile>
-        
-    </ItemGroup>
     <ItemGroup>
         <ProjectReference Include="..\..\Share\Analyzer\Share.Analyzer.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
         <ProjectReference Include="..\App\DotNet.App.csproj" />

+ 20 - 0
DotNet/Hotfix/Share/ConstValue.cs

@@ -0,0 +1,20 @@
+namespace ET
+{
+    /// <summary>
+    /// 静态常量
+    /// </summary>
+    public static class ConstValue
+    {
+        // 本地测试
+        // public const string RouterHttpHost = "127.0.0.1";
+        // 阿里云测试
+        public const string RouterHttpHost = "47.98.144.16";
+        
+        public const int RouterHttpPort = 30300;
+        
+        //session过期时间(毫秒),设置小于等于0时,session永不过期
+        public const int SessionTimeoutTime = 5 * 1000;
+
+        public const int fightTimeRefreshTime = 1 * 1000;
+    }
+}

+ 17 - 0
DotNet/Hotfix/Share/EntryEvent1_InitShare.cs

@@ -0,0 +1,17 @@
+namespace ET
+{
+    [Event(SceneType.Process)]
+    public class EntryEvent1_InitShare: AEvent<EventType.EntryEvent1>
+    {
+        protected override async ETTask Run(Scene scene, EventType.EntryEvent1 args)
+        {
+            Root.Instance.Scene.AddComponent<NetThreadComponent>();
+            Root.Instance.Scene.AddComponent<OpcodeTypeComponent>();
+            Root.Instance.Scene.AddComponent<MessageDispatcherComponent>();
+            Root.Instance.Scene.AddComponent<AIDispatcherComponent>();
+            Root.Instance.Scene.AddComponent<ClientSceneManagerComponent>();
+
+            await ETTask.CompletedTask;
+        }
+    }
+}

+ 97 - 0
DotNet/Hotfix/Share/Module/AI/AIComponentSystem.cs

@@ -0,0 +1,97 @@
+using System;
+
+namespace ET
+{
+    [FriendOf(typeof(AIComponent))]
+    [FriendOf(typeof(AIDispatcherComponent))]
+    public static class AIComponentSystem
+    {
+        [Invoke(TimerInvokeType.AITimer)]
+        public class AITimer: ATimer<AIComponent>
+        {
+            protected override void Run(AIComponent self)
+            {
+                try
+                {
+                    self.Check();
+                }
+                catch (Exception e)
+                {
+                    Log.Error($"move timer error: {self.Id}\n{e}");
+                }
+            }
+        }
+    
+        [ObjectSystem]
+        public class AIComponentAwakeSystem: AwakeSystem<AIComponent, int>
+        {
+            protected override void Awake(AIComponent self, int aiConfigId)
+            {
+                self.AIConfigId = aiConfigId;
+                self.Timer = TimerComponent.Instance.NewRepeatedTimer(1000, TimerInvokeType.AITimer, self);
+            }
+        }
+
+        [ObjectSystem]
+        public class AIComponentDestroySystem: DestroySystem<AIComponent>
+        {
+            protected override void Destroy(AIComponent self)
+            {
+                TimerComponent.Instance?.Remove(ref self.Timer);
+                self.CancellationToken?.Cancel();
+                self.CancellationToken = null;
+                self.Current = 0;
+            }
+        }
+        
+        public static void Check(this AIComponent self)
+        {
+            if (self.Parent == null)
+            {
+                TimerComponent.Instance.Remove(ref self.Timer);
+                return;
+            }
+
+            var oneAI = AIConfigCategory.Instance.AIConfigs[self.AIConfigId];
+
+            foreach (AIConfig aiConfig in oneAI.Values)
+            {
+
+                AIDispatcherComponent.Instance.AIHandlers.TryGetValue(aiConfig.Name, out AAIHandler aaiHandler);
+
+                if (aaiHandler == null)
+                {
+                    Log.Error($"not found aihandler: {aiConfig.Name}");
+                    continue;
+                }
+
+                int ret = aaiHandler.Check(self, aiConfig);
+                if (ret != 0)
+                {
+                    continue;
+                }
+
+                if (self.Current == aiConfig.Id)
+                {
+                    break;
+                }
+
+                self.Cancel(); // 取消之前的行为
+                ETCancellationToken cancellationToken = new ETCancellationToken();
+                self.CancellationToken = cancellationToken;
+                self.Current = aiConfig.Id;
+
+                aaiHandler.Execute(self, aiConfig, cancellationToken).Coroutine();
+                return;
+            }
+            
+        }
+
+        private static void Cancel(this AIComponent self)
+        {
+            self.CancellationToken?.Cancel();
+            self.Current = 0;
+            self.CancellationToken = null;
+        }
+    }
+} 

+ 54 - 0
DotNet/Hotfix/Share/Module/AI/AIDispatcherComponentSystem.cs

@@ -0,0 +1,54 @@
+using System;
+
+namespace ET
+{
+    [FriendOf(typeof(AIDispatcherComponent))]
+    public static class AIDispatcherComponentSystem
+    {
+        [ObjectSystem]
+        public class AIDispatcherComponentAwakeSystem: AwakeSystem<AIDispatcherComponent>
+        {
+            protected override void Awake(AIDispatcherComponent self)
+            {
+                AIDispatcherComponent.Instance = self;
+                self.Load();
+            }
+        }
+
+        [ObjectSystem]
+        public class AIDispatcherComponentLoadSystem: LoadSystem<AIDispatcherComponent>
+        {
+            protected override void Load(AIDispatcherComponent self)
+            {
+                self.Load();
+            }
+        }
+
+        [ObjectSystem]
+        public class AIDispatcherComponentDestroySystem: DestroySystem<AIDispatcherComponent>
+        {
+            protected override void Destroy(AIDispatcherComponent self)
+            {
+                self.AIHandlers.Clear();
+                AIDispatcherComponent.Instance = null;
+            }
+        }
+        
+        private static void Load(this AIDispatcherComponent self)
+        {
+            self.AIHandlers.Clear();
+            
+            var types = EventSystem.Instance.GetTypes(typeof (AIHandlerAttribute));
+            foreach (Type type in types)
+            {
+                AAIHandler aaiHandler = Activator.CreateInstance(type) as AAIHandler;
+                if (aaiHandler == null)
+                {
+                    Log.Error($"robot ai is not AAIHandler: {type.Name}");
+                    continue;
+                }
+                self.AIHandlers.Add(type.Name, aaiHandler);
+            }
+        }
+    }
+}

+ 113 - 0
DotNet/Hotfix/Share/Module/Console/ConsoleComponentSystem.cs

@@ -0,0 +1,113 @@
+using System;
+using System.Collections.Generic;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace ET
+{
+    [FriendOf(typeof(ConsoleComponent))]
+    [FriendOf(typeof(ModeContex))]
+    public static class ConsoleComponentSystem
+    {
+        [ObjectSystem]
+        public class ConsoleComponentAwakeSystem: AwakeSystem<ConsoleComponent>
+        {
+            protected override void Awake(ConsoleComponent self)
+            {
+                self.Load();
+            
+                self.Start().Coroutine();
+            }
+        }
+
+        [ObjectSystem]
+        public class ConsoleComponentLoadSystem: LoadSystem<ConsoleComponent>
+        {
+            protected override void Load(ConsoleComponent self)
+            {
+                self.Load();
+            }
+        }
+        
+        public static void Load(this ConsoleComponent self)
+        {
+            self.Handlers.Clear();
+
+            HashSet<Type> types = EventSystem.Instance.GetTypes(typeof (ConsoleHandlerAttribute));
+
+            foreach (Type type in types)
+            {
+                object[] attrs = type.GetCustomAttributes(typeof(ConsoleHandlerAttribute), false);
+                if (attrs.Length == 0)
+                {
+                    continue;
+                }
+
+                ConsoleHandlerAttribute consoleHandlerAttribute = (ConsoleHandlerAttribute)attrs[0];
+
+                object obj = Activator.CreateInstance(type);
+
+                IConsoleHandler iConsoleHandler = obj as IConsoleHandler;
+                if (iConsoleHandler == null)
+                {
+                    throw new Exception($"ConsoleHandler handler not inherit IConsoleHandler class: {obj.GetType().FullName}");
+                }
+                self.Handlers.Add(consoleHandlerAttribute.Mode, iConsoleHandler);
+            }
+        }
+        
+        public static async ETTask Start(this ConsoleComponent self)
+        {
+            self.CancellationTokenSource = new CancellationTokenSource();
+
+            while (true)
+            {
+                try
+                {
+                    ModeContex modeContex = self.GetComponent<ModeContex>();
+                    string line = await Task.Factory.StartNew(() =>
+                    {
+                        Console.Write($"{modeContex?.Mode ?? ""}> ");
+                        return Console.In.ReadLine();
+                    }, self.CancellationTokenSource.Token);
+                    
+                    line = line.Trim();
+
+                    switch (line)
+                    {
+                        case "":
+                            break;
+                        case "exit":
+                            self.RemoveComponent<ModeContex>();
+                            break;
+                        default:
+                        {
+                            string[] lines = line.Split(" ");
+                            string mode = modeContex == null? lines[0] : modeContex.Mode;
+
+                            if (!self.Handlers.TryGetValue(mode, out IConsoleHandler iConsoleHandler))
+                            {
+                                Log.Console($"not found command: {line}");
+                                break;
+                            }
+
+                            if (modeContex == null)
+                            {
+                                modeContex = self.AddComponent<ModeContex>();
+                                modeContex.Mode = mode;
+                            }
+                            await iConsoleHandler.Run(modeContex, line);
+                            break;
+                        }
+                    }
+
+
+                }
+                catch (Exception e)
+                {
+                    Log.Console(e.ToString());
+                }
+            }
+        }
+    }
+}

+ 34 - 0
DotNet/Hotfix/Share/Module/Console/ReloadConfigConsoleHandler.cs

@@ -0,0 +1,34 @@
+using System;
+
+namespace ET
+{
+    [ConsoleHandler(ConsoleMode.ReloadConfig)]
+    public class ReloadConfigConsoleHandler: IConsoleHandler
+    {
+        public async ETTask Run(ModeContex contex, string content)
+        {
+            switch (content)
+            {
+                case ConsoleMode.ReloadConfig:
+                    contex.Parent.RemoveComponent<ModeContex>();
+                    Log.Console("C must have config name, like: C UnitConfig");
+                    break;
+                default:
+                    string[] ss = content.Split(" ");
+                    string configName = ss[1];
+                    string category = $"{configName}Category";
+                    Type type = EventSystem.Instance.GetType($"ET.{category}");
+                    if (type == null)
+                    {
+                        Log.Console($"reload config but not find {category}");
+                        return;
+                    }
+                    ConfigComponent.Instance.LoadOneConfig(type);
+                    Log.Console($"reload config {configName} finish!");
+                    break;
+            }
+            
+            await ETTask.CompletedTask;
+        }
+    }
+}

+ 22 - 0
DotNet/Hotfix/Share/Module/Console/ReloadDllConsoleHandler.cs

@@ -0,0 +1,22 @@
+namespace ET
+{
+    [ConsoleHandler(ConsoleMode.ReloadDll)]
+    public class ReloadDllConsoleHandler: IConsoleHandler
+    {
+        public async ETTask Run(ModeContex contex, string content)
+        {
+            switch (content)
+            {
+                case ConsoleMode.ReloadDll:
+                    contex.Parent.RemoveComponent<ModeContex>();
+                    
+                    CodeLoader.Instance.LoadHotfix();
+                    
+                    EventSystem.Instance.Load();
+                    break;
+            }
+            
+            await ETTask.CompletedTask;
+        }
+    }
+}

+ 116 - 0
DotNet/Hotfix/Share/Module/Message/MessageDispatcherComponentSystem.cs

@@ -0,0 +1,116 @@
+using System;
+using System.Collections.Generic;
+
+namespace ET
+{
+    /// <summary>
+    /// 消息分发组件
+    /// </summary>
+    [FriendOf(typeof(MessageDispatcherComponent))]
+    public static class MessageDispatcherComponentHelper
+    {
+        [ObjectSystem]
+        public class MessageDispatcherComponentAwakeSystem: AwakeSystem<MessageDispatcherComponent>
+        {
+            protected override void Awake(MessageDispatcherComponent self)
+            {
+                MessageDispatcherComponent.Instance = self;
+                self.Load();
+            }
+        }
+
+        [ObjectSystem]
+        public class MessageDispatcherComponentLoadSystem: LoadSystem<MessageDispatcherComponent>
+        {
+            protected override void Load(MessageDispatcherComponent self)
+            {
+                self.Load();
+            }
+        }
+
+        [ObjectSystem]
+        public class MessageDispatcherComponentDestroySystem: DestroySystem<MessageDispatcherComponent>
+        {
+            protected override void Destroy(MessageDispatcherComponent self)
+            {
+                MessageDispatcherComponent.Instance = null;
+                self.Handlers.Clear();
+            }
+        }
+
+        private static void Load(this MessageDispatcherComponent self)
+        {
+            self.Handlers.Clear();
+
+            HashSet<Type> types = EventSystem.Instance.GetTypes(typeof (MessageHandlerAttribute));
+
+            foreach (Type type in types)
+            {
+                IMHandler iMHandler = Activator.CreateInstance(type) as IMHandler;
+                if (iMHandler == null)
+                {
+                    Log.Error($"message handle {type.Name} 需要继承 IMHandler");
+                    continue;
+                }
+
+                object[] attrs = type.GetCustomAttributes(typeof(MessageHandlerAttribute), false);
+                
+                foreach (object attr in attrs)
+                {
+                    MessageHandlerAttribute messageHandlerAttribute = attr as MessageHandlerAttribute;
+                    
+                    Type messageType = iMHandler.GetMessageType();
+                    
+                    ushort opcode = NetServices.Instance.GetOpcode(messageType);
+                    if (opcode == 0)
+                    {
+                        Log.Error($"消息opcode为0: {messageType.Name}");
+                        continue;
+                    }
+
+                    MessageDispatcherInfo messageDispatcherInfo = new (messageHandlerAttribute.SceneType, iMHandler);
+                    self.RegisterHandler(opcode, messageDispatcherInfo);
+                }
+            }
+        }
+
+        private static void RegisterHandler(this MessageDispatcherComponent self, ushort opcode, MessageDispatcherInfo handler)
+        {
+            if (!self.Handlers.ContainsKey(opcode))
+            {
+                self.Handlers.Add(opcode, new List<MessageDispatcherInfo>());
+            }
+
+            self.Handlers[opcode].Add(handler);
+        }
+
+        public static void Handle(this MessageDispatcherComponent self, Session session, object message)
+        {
+            List<MessageDispatcherInfo> actions;
+            ushort opcode = NetServices.Instance.GetOpcode(message.GetType());
+            if (!self.Handlers.TryGetValue(opcode, out actions))
+            {
+                Log.Error($"消息没有处理: {opcode} {message}");
+                return;
+            }
+
+            SceneType sceneType = session.DomainScene().SceneType;
+            foreach (MessageDispatcherInfo ev in actions)
+            {
+                if (ev.SceneType != sceneType)
+                {
+                    continue;
+                }
+                
+                try
+                {
+                    ev.IMHandler.Handle(session, message);
+                }
+                catch (Exception e)
+                {
+                    Log.Error(e);
+                }
+            }
+        }
+    }
+}

+ 58 - 0
DotNet/Hotfix/Share/Module/Message/NetThreadComponentSystem.cs

@@ -0,0 +1,58 @@
+using System;
+using System.Threading;
+
+namespace ET
+{
+    [FriendOf(typeof(NetThreadComponent))]
+    public static class NetThreadComponentSystem
+    {
+        [ObjectSystem]
+        public class AwakeSystem: AwakeSystem<NetThreadComponent>
+        {
+            protected override void Awake(NetThreadComponent self)
+            {
+                NetThreadComponent.Instance = self;
+
+                // 网络线程
+                self.thread = new Thread(self.NetThreadUpdate);
+                self.thread.Start();
+            }
+        }
+        
+        [ObjectSystem]
+        public class LateUpdateSystem: LateUpdateSystem<NetThreadComponent>
+        {
+            protected override void LateUpdate(NetThreadComponent self)
+            {
+                self.MainThreadUpdate();
+            }
+        }
+        
+        [ObjectSystem]
+        public class DestroySystem: DestroySystem<NetThreadComponent>
+        {
+            protected override void Destroy(NetThreadComponent self)
+            {
+                NetThreadComponent.Instance = null;
+                self.isStop = true;
+                self.thread.Join(1000);
+            }
+        }
+
+        // 主线程Update
+        private static void MainThreadUpdate(this NetThreadComponent self)
+        {
+            NetServices.Instance.UpdateInMainThread();
+        }
+
+        // 网络线程Update
+        private static void NetThreadUpdate(this NetThreadComponent self)
+        {
+            while (!self.isStop)
+            {
+                NetServices.Instance.UpdateInNetThread();
+                Thread.Sleep(1);
+            }
+        }
+    }
+}

+ 38 - 0
DotNet/Hotfix/Share/Module/Message/SessionAcceptTimeoutComponentSystem.cs

@@ -0,0 +1,38 @@
+using System;
+
+namespace ET
+{
+    [Invoke(TimerInvokeType.SessionAcceptTimeout)]
+    public class SessionAcceptTimeout: ATimer<SessionAcceptTimeoutComponent>
+    {
+        protected override void Run(SessionAcceptTimeoutComponent self)
+        {
+            try
+            {
+                self.Parent.Dispose();
+            }
+            catch (Exception e)
+            {
+                Log.Error($"move timer error: {self.Id}\n{e}");
+            }
+        }
+    }
+    
+    [ObjectSystem]
+    public class SessionAcceptTimeoutComponentAwakeSystem: AwakeSystem<SessionAcceptTimeoutComponent>
+    {
+        protected override void Awake(SessionAcceptTimeoutComponent self)
+        {
+            self.Timer = TimerComponent.Instance.NewOnceTimer(TimeHelper.ServerNow() + 5000, TimerInvokeType.SessionAcceptTimeout, self);
+        }
+    }
+
+    [ObjectSystem]
+    public class SessionAcceptTimeoutComponentDestroySystem: DestroySystem<SessionAcceptTimeoutComponent>
+    {
+        protected override void Destroy(SessionAcceptTimeoutComponent self)
+        {
+            TimerComponent.Instance.Remove(ref self.Timer);
+        }
+    }
+}

+ 40 - 0
DotNet/Hotfix/Share/Module/Scene/ClientSceneManagerComponentSystem.cs

@@ -0,0 +1,40 @@
+namespace ET
+{
+    [FriendOf(typeof(ClientSceneManagerComponent))]
+    public static class ClientSceneManagerComponentSystem
+    {
+        [ObjectSystem]
+        public class ClientSceneManagerComponentAwakeSystem: AwakeSystem<ClientSceneManagerComponent>
+        {
+            protected override void Awake(ClientSceneManagerComponent self)
+            {
+                ClientSceneManagerComponent.Instance = self;
+            }
+        }
+
+        [ObjectSystem]
+        public class ClientSceneManagerComponentDestroySystem: DestroySystem<ClientSceneManagerComponent>
+        {
+            protected override void Destroy(ClientSceneManagerComponent self)
+            {
+                ClientSceneManagerComponent.Instance = null;
+            }
+        }
+        
+        public static Scene ClientScene(this Entity entity)
+        {
+            return ClientSceneManagerComponent.Instance.Get(entity.DomainZone());
+        }
+        
+        public static Scene Get(this ClientSceneManagerComponent self, int id)
+        {
+            Scene scene = self.GetChild<Scene>(id);
+            return scene;
+        }
+        
+        public static void Remove(this ClientSceneManagerComponent self, int id)
+        {
+            self.RemoveChild(id);
+        }
+    }
+}

+ 12 - 0
DotNet/Hotfix/Share/Module/Scene/CurrentScenesComponentSystem.cs

@@ -0,0 +1,12 @@
+using System;
+
+namespace ET
+{
+    public static class CurrentScenesComponentSystem
+    {
+        public static Scene CurrentScene(this Scene clientScene)
+        {
+            return clientScene.GetComponent<CurrentScenesComponent>()?.Scene;
+        }
+    }
+}

+ 35 - 0
DotNet/Hotfix/Share/Module/Scene/ServerSceneManagerComponentSystem.cs

@@ -0,0 +1,35 @@
+namespace ET
+{
+    [FriendOf(typeof(ServerSceneManagerComponent))]
+    public static class ServerSceneManagerComponentSystem
+    {
+        [ObjectSystem]
+        public class ServerSceneManagerComponentAwakeSystem: AwakeSystem<ServerSceneManagerComponent>
+        {
+            protected override void Awake(ServerSceneManagerComponent self)
+            {
+                ServerSceneManagerComponent.Instance = self;
+            }
+        }
+
+        [ObjectSystem]
+        public class ServerSceneManagerComponentDestroySystem: DestroySystem<ServerSceneManagerComponent>
+        {
+            protected override void Destroy(ServerSceneManagerComponent self)
+            {
+                ServerSceneManagerComponent.Instance = null;
+            }
+        }
+        
+        public static Scene Get(this ServerSceneManagerComponent self, int id)
+        {
+            Scene scene = self.GetChild<Scene>(id);
+            return scene;
+        }
+        
+        public static void Remove(this ServerSceneManagerComponent self, int id)
+        {
+            self.RemoveChild(id);
+        }
+    }
+}

+ 0 - 0
DotNet/Hotfix/Share/Plugins/Example/HotfixShare.cs


+ 0 - 7
DotNet/Model/DotNet.Model.csproj

@@ -23,13 +23,6 @@
         <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
         <Optimize>true</Optimize>
     </PropertyGroup>
-    <ItemGroup>
-
-        <Compile Include="..\..\Unity\Assets\Scripts\Codes\Model\Share\**\*.cs">
-            <Link>Share\%(RecursiveDir)%(FileName)%(Extension)</Link>
-        </Compile>
-        
-    </ItemGroup> 
     <ItemGroup> 
         <ProjectReference Include="..\..\Share\Analyzer\Share.Analyzer.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
         <ProjectReference Include="..\Core\DotNet.Core.csproj" />

+ 43 - 0
DotNet/Model/Share/Entry.cs

@@ -0,0 +1,43 @@
+namespace ET
+{
+    namespace EventType
+    {
+        public struct EntryLoadCfg { }
+
+        public struct EntryEvent1 { }   
+        
+        public struct EntryEvent2 { } 
+        
+        public struct EntryEvent3 { } 
+    }
+    
+    public static class Entry
+    {
+        public static void Init()
+        {
+            
+        }
+        
+        public static void Start()
+        {
+            StartAsync().Coroutine();
+        }
+        
+        private static async ETTask StartAsync()
+        {
+            Log.Debug("Entry start");
+            WinPeriod.Init();
+            
+            MongoHelper.Init();
+            ProtobufHelper.Init();
+            
+            Game.AddSingleton<NetServices>();
+            Game.AddSingleton<Root>();
+            await EventSystem.Instance.PublishAsync(Root.Instance.Scene, new EventType.EntryLoadCfg());
+
+            await EventSystem.Instance.PublishAsync(Root.Instance.Scene, new EventType.EntryEvent1());
+            await EventSystem.Instance.PublishAsync(Root.Instance.Scene, new EventType.EntryEvent2());
+            await EventSystem.Instance.PublishAsync(Root.Instance.Scene, new EventType.EntryEvent3());
+        }
+    }
+}

+ 57 - 0
DotNet/Model/Share/EventType.cs

@@ -0,0 +1,57 @@
+namespace ET
+{
+    namespace EventType
+    {
+        public struct SceneChangeStart
+        {
+        }
+        
+        public struct SceneChangeFinish
+        {
+        }
+        
+        public struct AfterCreateClientScene
+        {
+        }
+        
+        public struct AfterCreateCurrentScene
+        {
+        }
+
+        public struct AppStartInitFinish
+        {
+        }
+
+        public struct LoginFinish
+        {
+        }
+
+        public struct MainFnish
+        {
+        }
+
+        public struct StartFightRoomFnish
+        {
+        }
+
+        public struct EnterMapFinish
+        {
+        }
+
+        public struct AfterUnitCreate
+        {
+        }
+
+        public struct JoinRoomPush
+        {
+        }
+
+        public struct KickPush
+        {
+        }
+
+        public struct ReadyPush
+        {
+        }
+    }
+}

+ 18 - 0
DotNet/Model/Share/Module/AI/AAIHandler.cs

@@ -0,0 +1,18 @@
+using System;
+
+namespace ET
+{
+    public class AIHandlerAttribute: BaseAttribute
+    {
+    }
+    
+    [AIHandler]
+    public abstract class AAIHandler
+    {
+        // 检查是否满足条件
+        public abstract int Check(AIComponent aiComponent, AIConfig aiConfig);
+
+        // 协程编写必须可以取消
+        public abstract ETTask Execute(AIComponent aiComponent, AIConfig aiConfig, ETCancellationToken cancellationToken);
+    }
+}

+ 15 - 0
DotNet/Model/Share/Module/AI/AIComponent.cs

@@ -0,0 +1,15 @@
+namespace ET
+{
+    // 客户端挂在ClientScene上,服务端挂在Unit上
+    [ComponentOf(typeof(Scene))]
+    public class AIComponent: Entity, IAwake<int>, IDestroy
+    {
+        public int AIConfigId;
+        
+        public ETCancellationToken CancellationToken;
+
+        public long Timer;
+
+        public int Current;
+    }
+}

+ 35 - 0
DotNet/Model/Share/Module/AI/AIConfig.cs

@@ -0,0 +1,35 @@
+using System.Collections.Generic;
+using System.ComponentModel;
+using MongoDB.Bson;
+using MongoDB.Bson.Serialization.Attributes;
+using ProtoBuf;
+
+namespace ET
+{
+	public partial class AIConfigCategory
+	{
+		[ProtoIgnore]
+		[BsonIgnore]
+		public Dictionary<int, SortedDictionary<int, AIConfig>> AIConfigs = new Dictionary<int, SortedDictionary<int, AIConfig>>();
+
+		public SortedDictionary<int, AIConfig> GetAI(int aiConfigId)
+		{
+			return this.AIConfigs[aiConfigId];
+		}
+
+		public override void AfterEndInit()
+		{
+			foreach (var kv in this.GetAll())
+			{
+				SortedDictionary<int, AIConfig> aiNodeConfig;
+				if (!this.AIConfigs.TryGetValue(kv.Value.AIConfigId, out aiNodeConfig))
+				{
+					aiNodeConfig = new SortedDictionary<int, AIConfig>();
+					this.AIConfigs.Add(kv.Value.AIConfigId, aiNodeConfig);
+				}
+				
+				aiNodeConfig.Add(kv.Key, kv.Value);
+			}
+		}
+	}
+}

+ 13 - 0
DotNet/Model/Share/Module/AI/AIDispatcherComponent.cs

@@ -0,0 +1,13 @@
+using System.Collections.Generic;
+
+namespace ET
+{
+    [ComponentOf(typeof(Scene))]
+    public class AIDispatcherComponent: Entity, IAwake, IDestroy, ILoad
+    {
+        [StaticField]
+        public static AIDispatcherComponent Instance;
+        
+        public Dictionary<string, AAIHandler> AIHandlers = new Dictionary<string, AAIHandler>();
+    }
+}

+ 15 - 0
DotNet/Model/Share/Module/Actor/IActorMessage.cs

@@ -0,0 +1,15 @@
+namespace ET
+{
+    // 不需要返回消息
+    public interface IActorMessage: IMessage
+    {
+    }
+
+    public interface IActorRequest: IRequest
+    {
+    }
+
+    public interface IActorResponse: IResponse
+    {
+    }
+}

+ 16 - 0
DotNet/Model/Share/Module/ActorLocation/ActorResponse.cs

@@ -0,0 +1,16 @@
+using ProtoBuf;
+
+namespace ET
+{
+    [Message(ushort.MaxValue)]
+    [ProtoContract]
+    public partial class ActorResponse: ProtoObject, IActorResponse
+    {
+        [ProtoMember(1)]
+        public int RpcId { get; set; }
+        [ProtoMember(2)]
+        public int Error { get; set; }
+        [ProtoMember(3)]
+        public string Message { get; set; }
+    }
+}

+ 14 - 0
DotNet/Model/Share/Module/ActorLocation/IActorLocationMessage.cs

@@ -0,0 +1,14 @@
+namespace ET
+{
+    public interface IActorLocationMessage: IActorRequest
+    {
+    }
+
+    public interface IActorLocationRequest: IActorRequest
+    {
+    }
+
+    public interface IActorLocationResponse: IActorResponse
+    {
+    }
+}

+ 23 - 0
DotNet/Model/Share/Module/Console/ConsoleComponent.cs

@@ -0,0 +1,23 @@
+using System.Collections.Generic;
+using System.Threading;
+
+namespace ET
+{
+    public static class ConsoleMode
+    {
+        public const string ReloadDll = "R";
+        public const string ReloadConfig = "C";
+        public const string ShowMemory = "M";
+        public const string Repl = "Repl";
+        public const string Debugger = "Debugger";
+        public const string CreateRobot = "CreateRobot";
+        public const string Robot = "Robot";
+    }
+
+    [ComponentOf(typeof(Scene))]
+    public class ConsoleComponent: Entity, IAwake, ILoad
+    {
+        public CancellationTokenSource CancellationTokenSource;
+        public Dictionary<string, IConsoleHandler> Handlers = new Dictionary<string, IConsoleHandler>();
+    }
+}

+ 12 - 0
DotNet/Model/Share/Module/Console/ConsoleHandlerAttribute.cs

@@ -0,0 +1,12 @@
+namespace ET
+{
+    public class ConsoleHandlerAttribute: BaseAttribute
+    {
+        public string Mode { get; }
+
+        public ConsoleHandlerAttribute(string mode)
+        {
+            this.Mode = mode;
+        }
+    }
+}

+ 7 - 0
DotNet/Model/Share/Module/Console/IConsoleHandler.cs

@@ -0,0 +1,7 @@
+namespace ET
+{
+    public interface IConsoleHandler
+    {
+        ETTask Run(ModeContex contex, string content);
+    }
+}

+ 26 - 0
DotNet/Model/Share/Module/Console/ModeContex.cs

@@ -0,0 +1,26 @@
+namespace ET
+{
+    [ObjectSystem]
+    public class ModeContexAwakeSystem: AwakeSystem<ModeContex>
+    {
+        protected override void Awake(ModeContex self)
+        {
+            self.Mode = "";
+        }
+    }
+
+    [ObjectSystem]
+    public class ModeContexDestroySystem: DestroySystem<ModeContex>
+    {
+        protected override void Destroy(ModeContex self)
+        {
+            self.Mode = "";
+        }
+    }
+
+    [ComponentOf(typeof(ConsoleComponent))]
+    public class ModeContex: Entity, IAwake, IDestroy
+    {
+        public string Mode = "";
+    }
+}

+ 37 - 0
DotNet/Model/Share/Module/Message/AMHandler.cs

@@ -0,0 +1,37 @@
+using System;
+
+namespace ET
+{
+    public abstract class AMHandler<Message>: IMHandler where Message : class
+    {
+        protected abstract ETTask Run(Session session, Message message);
+
+        public void Handle(Session session, object msg)
+        {
+            Message message = msg as Message;
+            if (message == null)
+            {
+                Log.Error($"消息类型转换错误: {msg.GetType().Name} to {typeof (Message).Name}");
+                return;
+            }
+
+            if (session.IsDisposed)
+            {
+                Log.Error($"session disconnect {msg}");
+                return;
+            }
+
+            this.Run(session, message).Coroutine();
+        }
+
+        public Type GetMessageType()
+        {
+            return typeof (Message);
+        }
+
+        public Type GetResponseType()
+        {
+            return null;
+        }
+    }
+}

+ 62 - 0
DotNet/Model/Share/Module/Message/ErrorCode.cs

@@ -0,0 +1,62 @@
+namespace ET
+{
+    /// <summary>
+    /// 1-11004 是SocketError请看SocketError定义
+    ///-----------------------------------
+    /// 100000-109999是Core层的错误
+    /// 110000以下的错误请看ErrorCore.cs
+    /// 这里配置逻辑层的错误码
+    /// 110000 - 200000是抛异常的错误
+    ///  200001以上不抛异常
+    /// </summary>
+    public static partial class ErrorCode
+    {
+        public const int ERR_Success = 0;
+
+        /** 系统错误 **/
+        public const int ERR_SystemError = 200002;
+        /** 操作错误 **/
+        public const int ERR_OperationError = 200003;
+        /** 参数错误 **/
+        public const int ERR_ParameterError = 200004;
+        /** 登陆错误 **/
+        public const int ERR_LoginError = 200005;
+        /** 重复请求 **/
+        public const int ERR_RequestRepeatedly = 200006;
+        /** 请输入用户名和密码 **/
+        public const int ERR_UserNameOrPasswordIsNull = 200007;
+        /** 用户名或密码格式错误 **/
+        public const int ERR_UserNameOrPasswordFormatError = 200008;
+        /** 用户名或密码错误 **/
+        public const int ERR_UserNameOrPasswordError = 200009;
+        /** 已被永久封禁 **/
+        public const int ERR_UserPermanentBan = 200010;
+        /** 已被限时封禁 **/
+        public const int ERR_UserBanTime = 200011;
+        /** 请输入角色名 **/
+        public const int ERR_PlayerNameIsNull = 200012;
+        /** 该职业有误 **/
+        public const int ERR_ProNotProper = 200013;
+        /** 该性别有误 **/
+        public const int ERR_SexNotProper = 200014;
+        /** 创角失败 **/
+        public const int ERR_CreatePlayerError = 200015;
+        /** 该角色已经绑定 **/
+        public const int ERR_PlayerIdIsBind = 200016;
+        /** 选角出错 **/
+        public const int ERR_BindPlayerError = 200017;
+        /** 操作过快,请稍后重试 **/
+        public const int ERR_OperationToFast = 200018;
+        /** 场景不存在 **/
+        public const int ERR_EnterMapError = 200019;
+        /** 配置错误 **/
+        public const int ERR_ConfigError = 200020;
+        /** 账号已在其他地方登录 **/
+        public const int ERR_AccountAlreadyLoggedInElsewhere = 200021;
+        /** 角色已在其他地方登录 **/
+        public const int ERR_PlayerAlreadyLoggedInElsewhere = 200022;
+        /** 创建单位玩家有误 **/
+        public const int ERR_CreateUnitPlayerError = 200023;
+
+    }
+}

+ 12 - 0
DotNet/Model/Share/Module/Message/IMHandler.cs

@@ -0,0 +1,12 @@
+using System;
+
+namespace ET
+{
+    public interface IMHandler
+    {
+        void Handle(Session session, object message);
+        Type GetMessageType();
+
+        Type GetResponseType();
+    }
+}

+ 36 - 0
DotNet/Model/Share/Module/Message/IMessage.cs

@@ -0,0 +1,36 @@
+namespace ET
+{
+    public interface IMessage
+    {
+    }
+
+    public interface IRequest: IMessage
+    {
+        int RpcId
+        {
+            get;
+            set;
+        }
+    }
+
+    public interface IResponse: IMessage
+    {
+        int Error
+        {
+            get;
+            set;
+        }
+
+        string Message
+        {
+            get;
+            set;
+        }
+
+        int RpcId
+        {
+            get;
+            set;
+        }
+    }
+}

+ 31 - 0
DotNet/Model/Share/Module/Message/MessageDispatcherComponent.cs

@@ -0,0 +1,31 @@
+using System.Collections.Generic;
+
+namespace ET
+{
+    public class MessageDispatcherInfo
+    {
+        public SceneType SceneType { get; }
+        public IMHandler IMHandler { get; }
+
+        public MessageDispatcherInfo(SceneType sceneType, IMHandler imHandler)
+        {
+            this.SceneType = sceneType;
+            this.IMHandler = imHandler;
+        }
+    }
+    
+    /// <summary>
+    /// 消息分发组件
+    /// </summary>
+    [ComponentOf(typeof(Scene))]
+    public class MessageDispatcherComponent: Entity, IAwake, IDestroy, ILoad
+    {
+        public static MessageDispatcherComponent Instance
+        {
+            get;
+            set;
+        }
+
+        public readonly Dictionary<ushort, List<MessageDispatcherInfo>> Handlers = new();
+    }
+}

+ 12 - 0
DotNet/Model/Share/Module/Message/MessageHandlerAttribute.cs

@@ -0,0 +1,12 @@
+namespace ET
+{
+    public class MessageHandlerAttribute: BaseAttribute
+    {
+        public SceneType SceneType { get; }
+
+        public MessageHandlerAttribute(SceneType sceneType)
+        {
+            this.SceneType = sceneType;
+        }
+    }
+}

+ 14 - 0
DotNet/Model/Share/Module/Message/NetThreadComponent.cs

@@ -0,0 +1,14 @@
+using System.Threading;
+
+namespace ET
+{
+    [ComponentOf(typeof(Scene))]
+    public class NetThreadComponent: Entity, IAwake, ILateUpdate, IDestroy
+    {
+        [StaticField]
+        public static NetThreadComponent Instance;
+        
+        public Thread thread;
+        public bool isStop;
+    }
+}

+ 59 - 0
DotNet/Model/Share/Module/Message/OpcodeHelper.cs

@@ -0,0 +1,59 @@
+using System.Collections.Generic;
+
+namespace ET
+{
+    public static class OpcodeHelper
+    {
+        [StaticField]
+        private static readonly HashSet<ushort> ignoreDebugLogMessageSet = new HashSet<ushort>
+        {
+            OuterMessage.C2G_Ping,
+            OuterMessage.G2C_Ping,
+            OuterMessage.C2G_Benchmark,
+            OuterMessage.G2C_Benchmark,
+            ushort.MaxValue, // ActorResponse
+        };
+
+        private static bool IsNeedLogMessage(ushort opcode)
+        {
+            if (ignoreDebugLogMessageSet.Contains(opcode))
+            {
+                return false;
+            }
+
+            return true;
+        }
+
+        public static bool IsOuterMessage(ushort opcode)
+        {
+            return opcode < OpcodeRangeDefine.OuterMaxOpcode;
+        }
+
+        public static bool IsInnerMessage(ushort opcode)
+        {
+            return opcode >= OpcodeRangeDefine.InnerMinOpcode;
+        }
+
+        public static void LogMsg(int zone, object message)
+        {
+            ushort opcode = NetServices.Instance.GetOpcode(message.GetType());
+            if (!IsNeedLogMessage(opcode))
+            {
+                return;
+            }
+            
+            Logger.Instance.Debug("zone: {0} {1}", zone, message);
+        }
+        
+        public static void LogMsg(long actorId, object message)
+        {
+            ushort opcode = NetServices.Instance.GetOpcode(message.GetType());
+            if (!IsNeedLogMessage(opcode))
+            {
+                return;
+            }
+            
+            Logger.Instance.Debug("actorId: {0} {1}", actorId, message);
+        }
+    }
+}

+ 96 - 0
DotNet/Model/Share/Module/Message/OpcodeTypeComponent.cs

@@ -0,0 +1,96 @@
+using System;
+using System.Collections.Generic;
+
+namespace ET
+{
+    [FriendOf(typeof(OpcodeTypeComponent))]
+    public static class OpcodeTypeComponentSystem
+    {
+        [ObjectSystem]
+        public class OpcodeTypeComponentAwakeSystem: AwakeSystem<OpcodeTypeComponent>
+        {
+            protected override void Awake(OpcodeTypeComponent self)
+            {
+                OpcodeTypeComponent.Instance = self;
+                
+                self.requestResponse.Clear();
+
+                HashSet<Type> types = EventSystem.Instance.GetTypes(typeof (MessageAttribute));
+                foreach (Type type in types)
+                {
+                    object[] att = type.GetCustomAttributes(typeof (MessageAttribute), false);
+                    if (att.Length == 0)
+                    {
+                        continue;
+                    }
+
+                    MessageAttribute messageAttribute = att[0] as MessageAttribute;
+                    if (messageAttribute == null)
+                    {
+                        continue;
+                    }
+                    ushort opcode = messageAttribute.Opcode;
+
+                    if (OpcodeHelper.IsOuterMessage(opcode) && typeof (IActorMessage).IsAssignableFrom(type))
+                    {
+                        self.outrActorMessage.Add(opcode);
+                    }
+                
+                    // 检查request response
+                    if (typeof (IRequest).IsAssignableFrom(type))
+                    {
+                        if (typeof (IActorLocationMessage).IsAssignableFrom(type))
+                        {
+                            self.requestResponse.Add(type, typeof(ActorResponse));
+                            continue;
+                        }
+                    
+                        var attrs = type.GetCustomAttributes(typeof (ResponseTypeAttribute), false);
+                        if (attrs.Length == 0)
+                        {
+                            Log.Error($"not found responseType: {type}");
+                            continue;
+                        }
+
+                        ResponseTypeAttribute responseTypeAttribute = attrs[0] as ResponseTypeAttribute;
+                        self.requestResponse.Add(type, EventSystem.Instance.GetType($"ET.{responseTypeAttribute.Type}"));
+                    }
+                }
+            }
+        }
+
+        [ObjectSystem]
+        public class OpcodeTypeComponentDestroySystem: DestroySystem<OpcodeTypeComponent>
+        {
+            protected override void Destroy(OpcodeTypeComponent self)
+            {
+                OpcodeTypeComponent.Instance = null;
+            }
+        }
+
+        public static bool IsOutrActorMessage(this OpcodeTypeComponent self, ushort opcode)
+        {
+            return self.outrActorMessage.Contains(opcode);
+        }
+
+        public static Type GetResponseType(this OpcodeTypeComponent self, Type request)
+        {
+            if (!self.requestResponse.TryGetValue(request, out Type response))
+            {
+                throw new Exception($"not found response type, request type: {request.GetType().Name}");
+            }
+            return response;
+        }
+    }
+
+    [ComponentOf(typeof(Scene))]
+    public class OpcodeTypeComponent: Entity, IAwake, IDestroy
+    {
+        [StaticField]
+        public static OpcodeTypeComponent Instance;
+        
+        public HashSet<ushort> outrActorMessage = new HashSet<ushort>();
+        
+        public readonly Dictionary<Type, Type> requestResponse = new Dictionary<Type, Type>();
+    }
+}

+ 14 - 0
DotNet/Model/Share/Module/Message/ResponseTypeAttribute.cs

@@ -0,0 +1,14 @@
+using System;
+
+namespace ET
+{
+    public class ResponseTypeAttribute: BaseAttribute
+    {
+        public string Type { get; }
+
+        public ResponseTypeAttribute(string type)
+        {
+            this.Type = type;
+        }
+    }
+}

+ 170 - 0
DotNet/Model/Share/Module/Message/Session.cs

@@ -0,0 +1,170 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Net;
+
+namespace ET
+{
+    public readonly struct RpcInfo
+    {
+        public readonly IRequest Request;
+        public readonly ETTask<IResponse> Tcs;
+
+        public RpcInfo(IRequest request)
+        {
+            this.Request = request;
+            this.Tcs = ETTask<IResponse>.Create(true);
+        }
+    }
+    
+    [FriendOf(typeof(Session))]
+    public static class SessionSystem
+    {
+        [ObjectSystem]
+        public class SessionAwakeSystem: AwakeSystem<Session, int>
+        {
+            protected override void Awake(Session self, int serviceId)
+            {
+                self.ServiceId = serviceId;
+                long timeNow = TimeHelper.ClientNow();
+                self.LastRecvTime = timeNow;
+                self.LastSendTime = timeNow;
+
+                self.requestCallbacks.Clear();
+            
+                Log.Info($"session create: zone: {self.DomainZone()} id: {self.Id} {timeNow} ");
+            }
+        }
+        
+        [ObjectSystem]
+        public class SessionDestroySystem: DestroySystem<Session>
+        {
+            protected override void Destroy(Session self)
+            {
+                NetServices.Instance.RemoveChannel(self.ServiceId, self.Id, self.Error);
+            
+                foreach (RpcInfo responseCallback in self.requestCallbacks.Values.ToArray())
+                {
+                    responseCallback.Tcs.SetException(new RpcException(self.Error, $"session dispose: {self.Id} {self.RemoteAddress}"));
+                }
+
+                Log.Info($"session dispose: {self.RemoteAddress} id: {self.Id} ErrorCode: {self.Error}, please see ErrorCode.cs! {TimeHelper.ClientNow()}");
+            
+                self.requestCallbacks.Clear();
+            }
+        }
+        
+        public static void OnResponse(this Session self, IResponse response)
+        {
+            if (!self.requestCallbacks.TryGetValue(response.RpcId, out var action))
+            {
+                return;
+            }
+
+            self.requestCallbacks.Remove(response.RpcId);
+            if (ErrorCore.IsRpcNeedThrowException(response.Error))
+            {
+                action.Tcs.SetException(new Exception($"Rpc error, request: {action.Request} response: {response}"));
+                return;
+            }
+            action.Tcs.SetResult(response);
+        }
+        
+        public static async ETTask<IResponse> Call(this Session self, IRequest request, ETCancellationToken cancellationToken)
+        {
+            int rpcId = ++Session.RpcId;
+            RpcInfo rpcInfo = new RpcInfo(request);
+            self.requestCallbacks[rpcId] = rpcInfo;
+            request.RpcId = rpcId;
+
+            self.Send(request);
+            
+            void CancelAction()
+            {
+                if (!self.requestCallbacks.TryGetValue(rpcId, out RpcInfo action))
+                {
+                    return;
+                }
+
+                self.requestCallbacks.Remove(rpcId);
+                Type responseType = OpcodeTypeComponent.Instance.GetResponseType(action.Request.GetType());
+                IResponse response = (IResponse) Activator.CreateInstance(responseType);
+                response.Error = ErrorCore.ERR_Cancel;
+                action.Tcs.SetResult(response);
+            }
+
+            IResponse ret;
+            try
+            {
+                cancellationToken?.Add(CancelAction);
+                ret = await rpcInfo.Tcs;
+            }
+            finally
+            {
+                cancellationToken?.Remove(CancelAction);
+            }
+            return ret;
+        }
+
+        public static async ETTask<IResponse> Call(this Session self, IRequest request)
+        {
+            int rpcId = ++Session.RpcId;
+            RpcInfo rpcInfo = new RpcInfo(request);
+            self.requestCallbacks[rpcId] = rpcInfo;
+            request.RpcId = rpcId;
+            self.Send(request);
+            return await rpcInfo.Tcs;
+        }
+
+        public static void Send(this Session self, IMessage message)
+        {
+            self.Send(0, message);
+        }
+        
+        public static void Send(this Session self, long actorId, IMessage message)
+        {
+            self.LastSendTime = TimeHelper.ClientNow();
+            OpcodeHelper.LogMsg(self.DomainZone(), message);
+            NetServices.Instance.SendMessage(self.ServiceId, self.Id, actorId, message);
+        }
+    }
+
+    [ChildOf]
+    public sealed class Session: Entity, IAwake<int>, IDestroy
+    {
+        public int ServiceId { get; set; }
+        
+        public static int RpcId
+        {
+            get;
+            set;
+        }
+
+        public readonly Dictionary<int, RpcInfo> requestCallbacks = new Dictionary<int, RpcInfo>();
+        
+        public long LastRecvTime
+        {
+            get;
+            set;
+        }
+
+        public long LastSendTime
+        {
+            get;
+            set;
+        }
+
+        public int Error
+        {
+            get;
+            set;
+        }
+
+        public IPEndPoint RemoteAddress
+        {
+            get;
+            set;
+        }
+    }
+}

+ 9 - 0
DotNet/Model/Share/Module/Message/SessionAcceptTimeoutComponent.cs

@@ -0,0 +1,9 @@
+namespace ET
+{
+    // 刚accept的session只持续5秒,必须通过验证,否则断开
+    [ComponentOf(typeof(Session))]
+    public class SessionAcceptTimeoutComponent: Entity, IAwake, IDestroy
+    {
+        public long Timer;
+    }
+}

+ 168 - 0
DotNet/Model/Share/Module/ObjectWait/ObjectWait.cs

@@ -0,0 +1,168 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace ET
+{
+    public static class WaitTypeError
+    {
+        public const int Success = 0;
+        public const int Destroy = 1;
+        public const int Cancel = 2;
+        public const int Timeout = 3;
+    }
+    
+    public interface IWaitType
+    {
+        int Error
+        {
+            get;
+            set;
+        }
+    }
+
+    [FriendOf(typeof(ObjectWait))]
+    public static class ObjectWaitSystem
+    {
+        [ObjectSystem]
+        public class ObjectWaitAwakeSystem: AwakeSystem<ObjectWait>
+        {
+            protected override void Awake(ObjectWait self)
+            {
+                self.tcss.Clear();
+            }
+        }
+
+        [ObjectSystem]
+        public class ObjectWaitDestroySystem: DestroySystem<ObjectWait>
+        {
+            protected override void Destroy(ObjectWait self)
+            {
+                foreach (object v in self.tcss.Values.ToArray())
+                {
+                    ((IDestroyRun) v).SetResult();
+                }
+            }
+        }
+
+        private interface IDestroyRun
+        {
+            void SetResult();
+        }
+
+        private class ResultCallback<K>: IDestroyRun where K : struct, IWaitType
+        {
+            private ETTask<K> tcs;
+
+            public ResultCallback()
+            {
+                this.tcs = ETTask<K>.Create(true);
+            }
+
+            public bool IsDisposed
+            {
+                get
+                {
+                    return this.tcs == null;
+                }
+            }
+
+            public ETTask<K> Task => this.tcs;
+
+            public void SetResult(K k)
+            {
+                var t = tcs;
+                this.tcs = null;
+                t.SetResult(k);
+            }
+
+            public void SetResult()
+            {
+                var t = tcs;
+                this.tcs = null;
+                t.SetResult(new K() { Error = WaitTypeError.Destroy });
+            }
+        }
+        
+        public static async ETTask<T> Wait<T>(this ObjectWait self, ETCancellationToken cancellationToken = null) where T : struct, IWaitType
+        {
+            ResultCallback<T> tcs = new ResultCallback<T>();
+            Type type = typeof (T);
+            self.tcss.Add(type, tcs);
+
+            void CancelAction()
+            {
+                self.Notify(new T() { Error = WaitTypeError.Cancel });
+            }
+
+            T ret;
+            try
+            {
+                cancellationToken?.Add(CancelAction);
+                ret = await tcs.Task;
+            }
+            finally
+            {
+                cancellationToken?.Remove(CancelAction);    
+            }
+            return ret;
+        }
+
+        public static async ETTask<T> Wait<T>(this ObjectWait self, int timeout, ETCancellationToken cancellationToken = null) where T : struct, IWaitType
+        {
+            ResultCallback<T> tcs = new ResultCallback<T>();
+            async ETTask WaitTimeout()
+            {
+                await TimerComponent.Instance.WaitAsync(timeout, cancellationToken);
+                if (cancellationToken.IsCancel())
+                {
+                    return;
+                }
+                if (tcs.IsDisposed)
+                {
+                    return;
+                }
+                self.Notify(new T() { Error = WaitTypeError.Timeout });
+            }
+            
+            WaitTimeout().Coroutine();
+            
+            self.tcss.Add(typeof (T), tcs);
+            
+            void CancelAction()
+            {
+                self.Notify(new T() { Error = WaitTypeError.Cancel });
+            }
+            
+            T ret;
+            try
+            {
+                cancellationToken?.Add(CancelAction);
+                ret = await tcs.Task;
+            }
+            finally
+            {
+                cancellationToken?.Remove(CancelAction);    
+            }
+            return ret;
+        }
+
+        public static void Notify<T>(this ObjectWait self, T obj) where T : struct, IWaitType
+        {
+            Type type = typeof (T);
+            if (!self.tcss.TryGetValue(type, out object tcs))
+            {
+                return;
+            }
+
+            self.tcss.Remove(type);
+            ((ResultCallback<T>) tcs).SetResult(obj);
+        }
+    }
+
+    [ComponentOf]
+    public class ObjectWait: Entity, IAwake, IDestroy
+    {
+        public Dictionary<Type, object> tcss = new Dictionary<Type, object>();
+    }
+}

+ 9 - 0
DotNet/Model/Share/Module/Scene/ClientSceneManagerComponent.cs

@@ -0,0 +1,9 @@
+namespace ET
+{
+    [ComponentOf(typeof(Scene))]
+    public class ClientSceneManagerComponent: Entity, IAwake, IDestroy
+    {
+        [StaticField]
+        public static ClientSceneManagerComponent Instance;
+    }
+}

+ 9 - 0
DotNet/Model/Share/Module/Scene/CurrentScenesComponent.cs

@@ -0,0 +1,9 @@
+namespace ET
+{
+    // 可以用来管理多个客户端场景,比如大世界会加载多块场景
+    [ComponentOf(typeof(Scene))]
+    public class CurrentScenesComponent: Entity, IAwake
+    {
+        public Scene Scene { get; set; }
+    }
+}

+ 9 - 0
DotNet/Model/Share/Module/Scene/ServerSceneManagerComponent.cs

@@ -0,0 +1,9 @@
+namespace ET
+{
+    [ComponentOf(typeof(Scene))]
+    public class ServerSceneManagerComponent: Entity, IAwake, IDestroy
+    {
+        [StaticField]
+        public static ServerSceneManagerComponent Instance;
+    }
+}

+ 1 - 0
DotNet/Model/Share/Plugins/Example/ModelShare.cs

@@ -0,0 +1 @@
+

+ 18 - 0
DotNet/Model/Share/TimerInvokeType.cs

@@ -0,0 +1,18 @@
+namespace ET
+{
+    [UniqueId(100, 10000)]
+    public static class TimerInvokeType
+    {
+        // 框架层100-200,逻辑层的timer type从200起
+        public const int WaitTimer = 100;
+        public const int SessionIdleChecker = 101;
+        public const int ActorLocationSenderChecker = 102;
+        public const int ActorMessageSenderChecker = 103;
+        
+        // 框架层100-200,逻辑层的timer type 200-300
+        public const int MoveTimer = 201;
+        public const int AITimer = 202;
+        public const int SessionAcceptTimeout = 203;
+        public const int fightTimeShow = 204;
+    }
+}