Browse Source

1.增加TimerComponent,用于buff过期回调
2.回调不能使用delegate,delegate会导致无法reload.使用事件分发同的回调事件,比如BuffTimeout了会分发到BuffTimeoutCallback类中进行回调处理

tanghai 11 năm trước cách đây
mục cha
commit
854d191195

+ 20 - 0
CSharp/Game/Controller/Callback/BuffTimeoutCallback.cs

@@ -0,0 +1,20 @@
+using Common.Event;
+using Model;
+using MongoDB.Bson;
+
+namespace Controller
+{
+    [Callback(CallbackType.BuffTimeoutCallback)]
+    public class BuffTimeoutCallback: IEvent
+    {
+        public void Run(Env env)
+        {
+            Unit owner = World.Instance.GetComponent<UnitComponent>().Get(env.Get<ObjectId>(EnvKey.OwnerId));
+            if (owner == null)
+            {
+                return;
+            }
+            owner.GetComponent<BuffComponent>().RemoveById(env.Get<ObjectId>(EnvKey.BuffId));
+        }
+    }
+}

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

@@ -52,6 +52,8 @@
     <Compile Include="ConfigCategory\GlobalCategory.cs" />
     <Compile Include="ConfigCategory\NodeCategory.cs" />
     <Compile Include="ConfigCategory\UnitCategory.cs" />
+    <Compile Include="Callback\BuffTimeoutCallback.cs" />
+    <Compile Include="Event\AfterAddBuff.cs" />
     <Compile Include="NodeType.cs" />
     <Compile Include="Factory\UnitFactory.cs" />
     <Compile Include="UnitType.cs" />

+ 14 - 0
CSharp/Game/Controller/Event/AfterAddBuff.cs

@@ -0,0 +1,14 @@
+using Common.Event;
+using Model;
+
+namespace Controller
+{
+    [Event(EventType.AfterAddBuff)]
+    public class AddBuffToTimer: IEvent
+    {
+        public void Run(Env env)
+        {
+
+        }
+    }
+}

+ 38 - 0
CSharp/Game/Model/Buff.cs

@@ -1,4 +1,6 @@
 using Common.Base;
+using Common.Helper;
+using MongoDB.Bson;
 using MongoDB.Bson.Serialization.Attributes;
 
 namespace Model
@@ -8,9 +10,45 @@ namespace Model
         [BsonElement]
         private int configId { get; set; }
 
+        [BsonElement]
+        private long expiration;
+
+        [BsonIgnore]
+        private ObjectId timerId;
+
+        [BsonIgnore]
+        public long Expiration 
+        {
+            get
+            {
+                return this.expiration;
+            }
+            set
+            {
+                this.expiration = value;
+            }
+        }
+
+        [BsonIgnore]
+        public ObjectId TimerId 
+        {
+            get
+            {
+                return this.timerId;
+            }
+            set
+            {
+                this.timerId = value;
+            }
+        }
+
         public Buff(int configId)
         {
             this.configId = configId;
+            if (this.Config.Duration != 0)
+            {
+                this.Expiration = TimeHelper.Now() + this.Config.Duration;
+            }
         }
 
         [BsonIgnore]

+ 36 - 11
CSharp/Game/Model/Component/BuffComponent.cs

@@ -12,8 +12,10 @@ namespace Model
         [BsonElement]
         private HashSet<Buff> buffs;
 
+        [BsonIgnore]
         private Dictionary<ObjectId, Buff> idBuff;
 
+        [BsonIgnore]
         private MultiMap<BuffType, Buff> typeBuff;
 
         public BuffComponent()
@@ -40,9 +42,32 @@ namespace Model
             {
                 this.idBuff.Add(buff.Id, buff);
                 this.typeBuff.Add(buff.Config.Type, buff);
+                AddToTimer(this.Owner, buff);
             }
         }
 
+        private static void AddToTimer(Unit owner, Buff buff)
+        {
+            if (buff.Expiration == 0)
+            {
+                return;
+            }
+            Env env = new Env();
+            env[EnvKey.OwnerId] = owner.Id;
+            env[EnvKey.BuffId] = buff.Id;
+            buff.TimerId = World.Instance.GetComponent<TimerComponent>()
+                    .Add(buff.Expiration, CallbackType.BuffTimeoutCallback, env);
+        }
+
+        private static void RemoveFromTimer(Buff buff)
+        {
+            if (buff.Expiration == 0)
+            {
+                return;
+            }
+            World.Instance.GetComponent<TimerComponent>().Remove(buff.TimerId);
+        }
+
         public void Add(Buff buff)
         {
             if (this.buffs.Contains(buff))
@@ -59,13 +84,14 @@ namespace Model
             env[EnvKey.Owner] = this.Owner;
             env[EnvKey.Buff] = buff;
 
-            World.Instance.GetComponent<EventComponent<EventAttribute>>().Trigger(EventType.BeforeAddBuff, env);
+            World.Instance.GetComponent<EventComponent<EventAttribute>>().Run(EventType.BeforeAddBuff, env);
 
             this.buffs.Add(buff);
             this.idBuff.Add(buff.Id, buff);
             this.typeBuff.Add(buff.Config.Type, buff);
+            AddToTimer(this.Owner, buff);
 
-            World.Instance.GetComponent<EventComponent<EventAttribute>>().Trigger(EventType.AfterAddBuff, env);
+            World.Instance.GetComponent<EventComponent<EventAttribute>>().Run(EventType.AfterAddBuff, env);
         }
 
         public Buff GetById(ObjectId id)
@@ -85,35 +111,34 @@ namespace Model
 
         public Buff[] GetByType(BuffType type)
         {
-            return this.typeBuff.GetByKey(type);
+            return this.typeBuff.GetAll(type);
         }
 
-        private bool Remove(Buff buff)
+        private void Remove(Buff buff)
         {
             if (buff == null)
             {
-                return false;
+                return;
             }
 
             Env env = new Env();
             env[EnvKey.Owner] = this.Owner;
             env[EnvKey.Buff] = buff;
 
-            World.Instance.GetComponent<EventComponent<EventAttribute>>().Trigger(EventType.BeforeRemoveBuff, env);
+            World.Instance.GetComponent<EventComponent<EventAttribute>>().Run(EventType.BeforeRemoveBuff, env);
 
             this.buffs.Remove(buff);
             this.idBuff.Remove(buff.Id);
             this.typeBuff.Remove(buff.Config.Type, buff);
+            RemoveFromTimer(buff);
 
-            World.Instance.GetComponent<EventComponent<EventAttribute>>().Trigger(EventType.AfterRemoveBuff, env);
-
-            return true;
+            World.Instance.GetComponent<EventComponent<EventAttribute>>().Run(EventType.AfterRemoveBuff, env);
         }
 
-        public bool RemoveById(ObjectId id)
+        public void RemoveById(ObjectId id)
         {
             Buff buff = this.GetById(id);
-            return this.Remove(buff);
+            this.Remove(buff);
         }
 
         public void RemoveByType(BuffType type)

+ 2 - 2
CSharp/Game/Model/Component/EventComponent.cs

@@ -41,7 +41,7 @@ namespace Model
             }
         }
 
-        public void Trigger(int type, Env env)
+        public void Run(int type, Env env)
         {
             List<IEvent> iEventDict = null;
             if (!this.events.TryGetValue(type, out iEventDict))
@@ -51,7 +51,7 @@ namespace Model
 
             foreach (var iEvent in iEventDict)
             {
-                iEvent.Trigger(env);
+                iEvent.Run(env);
             }
         }
     }

+ 79 - 0
CSharp/Game/Model/Component/TimerComponent.cs

@@ -0,0 +1,79 @@
+using System.Collections.Generic;
+using Common.Base;
+using Common.Event;
+using Common.Helper;
+using MongoDB.Bson;
+
+namespace Model
+{
+    public class TimerComponent: Component<World>
+    {
+        private class Timer
+        {
+            public ObjectId Id { get; set; }
+            public long Time { get; set; }
+            public int CallbackId { get; set; }
+            public Env Env { get; set; }
+        }
+
+        private readonly Dictionary<ObjectId, Timer> timers = new Dictionary<ObjectId, Timer>();
+
+        /// <summary>
+        /// key: time, value: timer id
+        /// </summary>
+        private readonly MultiMap<long, ObjectId> timeId = new MultiMap<long, ObjectId>();
+
+        public ObjectId Add(long time, int callbackId, Env env)
+        {
+            Timer timer = new Timer
+            {
+                Id = ObjectId.GenerateNewId(), 
+                Time = time, 
+                CallbackId = callbackId,
+                Env = env
+            };
+            this.timers[timer.Id] = timer;
+            this.timeId.Add(timer.Time, timer.Id);
+            return timer.Id;
+        }
+
+        public void Remove(ObjectId id)
+        {
+            Timer timer;
+            if (!this.timers.TryGetValue(id, out timer))
+            {
+                return;
+            }
+            this.timeId.Remove(timer.Time, timer.Id);
+        }
+
+        public void Update()
+        {
+            long timeNow = TimeHelper.Now();
+            List<long> timeoutTimer = new List<long>();
+            foreach (long time in this.timeId.Keys)
+            {
+                if (time > timeNow)
+                {
+                    break;
+                }
+                timeoutTimer.Add(time);
+            }
+
+            foreach (long key in timeoutTimer)
+            {
+                List<ObjectId> timeOutId = this.timeId[key];
+                foreach (ObjectId id in timeOutId)
+                {
+                    Timer timer;
+                    if (!this.timers.TryGetValue(id, out timer))
+                    {
+                        continue;
+                    }
+                    this.Remove(id);
+                    World.Instance.GetComponent<EventComponent<CallbackAttribute>>().Run(timer.CallbackId, timer.Env);
+                }
+            }
+        }
+    }
+}

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

@@ -3,6 +3,8 @@
     public static class EnvKey
     {
         public const string Owner = "Owner";
+        public const string OwnerId = "OwnerId";
         public const string Buff = "Buff";
+        public const string BuffId = "BuffId";
     }
 }

+ 7 - 0
CSharp/Game/Model/EventAttribute.cs

@@ -8,4 +8,11 @@ namespace Model
         {
         }
     }
+
+    public class CallbackAttribute : AEventAttribute
+    {
+        public CallbackAttribute(int type): base(type)
+        {
+        }
+    }
 }

+ 5 - 0
CSharp/Game/Model/EventType.cs

@@ -7,4 +7,9 @@
         public const int BeforeRemoveBuff = 2;
         public const int AfterRemoveBuff = 3;
     }
+
+    public static class CallbackType
+    {
+        public const int BuffTimeoutCallback = 0;
+    }
 }

+ 1 - 0
CSharp/Game/Model/Model.csproj

@@ -56,6 +56,7 @@
     <Compile Include="Component\BuffComponent.cs" />
     <Compile Include="Component\ConfigComponent.cs" />
     <Compile Include="Component\EventComponent.cs" />
+    <Compile Include="Component\TimerComponent.cs" />
     <Compile Include="Config\UnitConfig.cs" />
     <Compile Include="Config\BuffConfig.cs" />
     <Compile Include="EnvKey.cs" />

+ 9 - 4
CSharp/Game/MongoDBTest/MongoDBTest.cs

@@ -1,5 +1,4 @@
 using System;
-using System.Threading;
 using Common.Helper;
 using Microsoft.VisualStudio.TestTools.UnitTesting;
 using Model;
@@ -25,7 +24,9 @@ namespace MongoDBTest
 
             // 加载配置
             world.AddComponent<ConfigComponent>();
+            world.AddComponent<EventComponent<CallbackAttribute>>();
             world.AddComponent<EventComponent<EventAttribute>>();
+            world.AddComponent<TimerComponent>();
             world.AddComponent<UnitComponent>();
             world.AddComponent<FactoryComponent<Unit>>();
             world.AddComponent<BehaviorTreeComponent>();
@@ -43,10 +44,14 @@ namespace MongoDBTest
             Console.WriteLine(MongoHelper.ToJson(player2));
             Assert.AreEqual(MongoHelper.ToJson(player1), MongoHelper.ToJson(player2));
 
-            Thread.Sleep(20 * 1000);
-            world.Load();
+            Unit player3 = player1.Clone();
 
-            Assert.AreEqual(MongoHelper.ToJson(player1), MongoHelper.ToJson(player2));
+            Assert.AreEqual(MongoHelper.ToJson(player1), MongoHelper.ToJson(player3));
+
+            //Thread.Sleep(20 * 1000);
+            //world.Load();
+            //
+            //Assert.AreEqual(MongoHelper.ToJson(player1), MongoHelper.ToJson(player2));
         }
     }
 }

+ 1 - 1
CSharp/Platform/Common/Base/Component.cs

@@ -13,7 +13,7 @@ namespace Common.Base
         [BsonIgnore]
         public T Owner
         {
-            protected get
+            get
             {
                 return owner;
             }

+ 34 - 28
CSharp/Platform/Common/Base/Entity.cs

@@ -1,40 +1,46 @@
 using System;
 using System.Collections.Generic;
 using System.Linq;
+using Common.Helper;
 using MongoDB.Bson.Serialization.Attributes;
 
 namespace Common.Base
 {
-    public abstract class Entity<K> : Object where K : Entity<K>
+    public abstract class Entity<T> : Object where T : Entity<T>
     {
         [BsonElement] 
         [BsonIgnoreIfNull]
-        private HashSet<Component<K>> components;
+        private HashSet<Component<T>> components;
 
-        private Dictionary<Type, Component<K>> componentDict = new Dictionary<Type, Component<K>>();
+        private Dictionary<Type, Component<T>> componentDict = new Dictionary<Type, Component<T>>();
 
-        public T AddComponent<T>() where T : Component<K>, new()
+        public T Clone()
         {
-            T t = new T { Owner = (K) this };
+            return MongoHelper.FromBson<T>(MongoHelper.ToBson(this));
+        }
+
+        public K AddComponent<K>() where K : Component<T>, new()
+        {
+            K component = new K { Owner = (T) this };
 
-            if (this.componentDict.ContainsKey(t.GetComponentType()))
+            if (this.componentDict.ContainsKey(component.GetComponentType()))
             {
                 throw new Exception(
                     string.Format("AddComponent, component already exist, id: {0}, component: {1}",
-                    this.Id, typeof(T).Name));
+                    this.Id, typeof(K).Name));
             }
 
             if (this.components == null)
             {
-                this.components = new HashSet<Component<K>>();
+                this.components = new HashSet<Component<T>>();
             }
 
-            this.components.Add(t);
-            this.componentDict.Add(t.GetComponentType(), t);
-            return t;
+            this.components.Add(component);
+            this.componentDict.Add(component.GetComponentType(), component);
+            return component;
         }
 
-        public void AddComponent(Component<K> component)
+        public void AddComponent(Component<T> component)
         {
             if (this.componentDict.ContainsKey(component.GetComponentType()))
             {
@@ -45,24 +51,24 @@ namespace Common.Base
 
             if (this.components == null)
             {
-                this.components = new HashSet<Component<K>>();
+                this.components = new HashSet<Component<T>>();
             }
             this.components.Add(component);
             this.componentDict.Add(component.GetComponentType(), component);
         }
 
-        public void RemoveComponent<T>() where T : Component<K>
+        public void RemoveComponent<K>() where K : Component<T>
         {
-            Component<K> t;
-            if (!this.componentDict.TryGetValue(typeof (T), out t))
+            Component<T> component;
+            if (!this.componentDict.TryGetValue(typeof (K), out component))
             {
                 throw new Exception(
                     string.Format("RemoveComponent, component not exist, id: {0}, component: {1}",
-                    this.Id, typeof(T).Name));
+                    this.Id, typeof(K).Name));
             }
             
-            this.components.Remove(t);
-            this.componentDict.Remove(typeof(T));
+            this.components.Remove(component);
+            this.componentDict.Remove(typeof(K));
 
             if (this.components.Count == 0)
             {
@@ -70,17 +76,17 @@ namespace Common.Base
             }
         }
 
-        public T GetComponent<T>() where T : Component<K>
+        public K GetComponent<K>() where K : Component<T>
         {
-            Component<K> t;
-            if (!this.componentDict.TryGetValue(typeof (T), out t))
+            Component<T> component;
+            if (!this.componentDict.TryGetValue(typeof (K), out component))
             {
-                return default (T);
+                return default (K);
             }
-            return (T) t;
+            return (K) component;
         }
 
-        public Component<K>[] GetComponents()
+        public Component<T>[] GetComponents()
         {
             return this.components.ToArray();
         }
@@ -88,8 +94,8 @@ namespace Common.Base
         public override void BeginInit()
         {
             base.BeginInit();
-            this.components = new HashSet<Component<K>>();
-            this.componentDict = new Dictionary<Type, Component<K>>();
+            this.components = new HashSet<Component<T>>();
+            this.componentDict = new Dictionary<Type, Component<T>>();
         }
 
         public override void EndInit()
@@ -102,7 +108,7 @@ namespace Common.Base
             }
             foreach (var component in this.components)
             {
-                component.Owner = (K)this;
+                component.Owner = (T) this;
                 this.componentDict.Add(component.GetComponentType(), component);
             }
         }

+ 1 - 1
CSharp/Platform/Common/Base/MultiMap.cs

@@ -56,7 +56,7 @@ namespace Common.Base
         /// </summary>
         /// <param name="t"></param>
         /// <returns></returns>
-        public K[] GetByKey(T t)
+        public K[] GetAll(T t)
         {
             List<K> list;
             this.dictionary.TryGetValue(t, out list);

+ 16 - 16
CSharp/Platform/Common/Base/Object.cs

@@ -25,6 +25,22 @@ namespace Common.Base
             this.Id = id;
         }
 
+        public virtual void BeginInit()
+        {
+            if (this.values == null)
+            {
+                this.values = new Dictionary<string, object>();
+            }
+        }
+
+        public virtual void EndInit()
+        {
+            if (this.values.Count == 0)
+            {
+                this.values = null;
+            }
+        }
+
         public object this[string key]
         {
             get
@@ -101,21 +117,5 @@ namespace Common.Base
         {
             return this.values.GetEnumerator();
         }
-
-        public virtual void BeginInit()
-        {
-            if (this.values == null)
-            {
-                this.values = new Dictionary<string, object>();
-            }
-        }
-
-        public virtual void EndInit()
-        {
-            if (this.values.Count == 0)
-            {
-                this.values = null;
-            }
-        }
     }
 }

+ 1 - 1
CSharp/Platform/Common/Event/IEvent.cs

@@ -2,6 +2,6 @@
 {
     public interface IEvent
     {
-        void Trigger(Env env);
+        void Run(Env env);
     }
 }

+ 2 - 2
CSharp/Platform/Common/Helper/TimeHelper.cs

@@ -4,10 +4,10 @@ namespace Common.Helper
 {
     public static class TimeHelper
     {
-        public static long EpochTimeSecond()
+        public static long Now()
         {
             var epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
-            return Convert.ToInt64((DateTime.UtcNow - epoch).TotalSeconds);
+            return Convert.ToInt64((DateTime.UtcNow - epoch).TotalMilliseconds);
         }
     }
 }