using System; using System.Collections.Generic; using System.Linq; using System.Reflection; namespace ETModel { public enum DLLType { Model, Hotfix, Editor, } public sealed class EventSystem { private readonly Dictionary allComponents = new Dictionary(); private readonly Dictionary assemblies = new Dictionary(); private readonly Dictionary> allEvents = new Dictionary>(); private readonly UnOrderMultiMap awakeSystems = new UnOrderMultiMap(); private readonly UnOrderMultiMap startSystems = new UnOrderMultiMap(); private readonly UnOrderMultiMap destroySystems = new UnOrderMultiMap(); private readonly UnOrderMultiMap loadSystems = new UnOrderMultiMap(); private readonly UnOrderMultiMap updateSystems = new UnOrderMultiMap(); private readonly UnOrderMultiMap lateUpdateSystems = new UnOrderMultiMap(); private readonly UnOrderMultiMap changeSystems = new UnOrderMultiMap(); private Queue updates = new Queue(); private Queue updates2 = new Queue(); private readonly Queue starts = new Queue(); private Queue loaders = new Queue(); private Queue loaders2 = new Queue(); private Queue lateUpdates = new Queue(); private Queue lateUpdates2 = new Queue(); public void Add(DLLType dllType, Assembly assembly) { this.assemblies[dllType] = assembly; this.awakeSystems.Clear(); this.lateUpdateSystems.Clear(); this.updateSystems.Clear(); this.startSystems.Clear(); this.loadSystems.Clear(); this.changeSystems.Clear(); Type[] types = DllHelper.GetMonoTypes(); foreach (Type type in types) { object[] attrs = type.GetCustomAttributes(typeof(ObjectSystemAttribute), false); if (attrs.Length == 0) { continue; } object obj = Activator.CreateInstance(type); IAwakeSystem objectSystem = obj as IAwakeSystem; if (objectSystem != null) { this.awakeSystems.Add(objectSystem.Type(), objectSystem); } IUpdateSystem updateSystem = obj as IUpdateSystem; if (updateSystem != null) { this.updateSystems.Add(updateSystem.Type(), updateSystem); } ILateUpdateSystem lateUpdateSystem = obj as ILateUpdateSystem; if (lateUpdateSystem != null) { this.lateUpdateSystems.Add(lateUpdateSystem.Type(), lateUpdateSystem); } IStartSystem startSystem = obj as IStartSystem; if (startSystem != null) { this.startSystems.Add(startSystem.Type(), startSystem); } IDestroySystem destroySystem = obj as IDestroySystem; if (destroySystem != null) { this.destroySystems.Add(destroySystem.Type(), destroySystem); } ILoadSystem loadSystem = obj as ILoadSystem; if (loadSystem != null) { this.loadSystems.Add(loadSystem.Type(), loadSystem); } IChangeSystem changeSystem = obj as IChangeSystem; if (changeSystem != null) { this.changeSystems.Add(changeSystem.Type(), changeSystem); } } this.allEvents.Clear(); foreach (Type type in types) { object[] attrs = type.GetCustomAttributes(typeof(EventAttribute), false); foreach (object attr in attrs) { EventAttribute aEventAttribute = (EventAttribute)attr; object obj = Activator.CreateInstance(type); IEvent iEvent = obj as IEvent; if (iEvent == null) { Log.Error($"{obj.GetType().Name} 没有继承IEvent"); } this.RegisterEvent(aEventAttribute.Type, iEvent); } } this.Load(); } public void RegisterEvent(string eventId, IEvent e) { if (!this.allEvents.ContainsKey(eventId)) { this.allEvents.Add(eventId, new List()); } this.allEvents[eventId].Add(e); } public Assembly Get(DLLType dllType) { return this.assemblies[dllType]; } public Assembly[] GetAll() { return this.assemblies.Values.ToArray(); } public void Add(Component component) { this.allComponents.Add(component.InstanceId, component); Type type = component.GetType(); if (this.loadSystems.ContainsKey(type)) { this.loaders.Enqueue(component.InstanceId); } if (this.updateSystems.ContainsKey(type)) { this.updates.Enqueue(component.InstanceId); } if (this.startSystems.ContainsKey(type)) { this.starts.Enqueue(component.InstanceId); } if (this.lateUpdateSystems.ContainsKey(type)) { this.lateUpdates.Enqueue(component.InstanceId); } } public void Remove(long id) { this.allComponents.Remove(id); } public Component Get(long id) { Component component = null; this.allComponents.TryGetValue(id, out component); return component; } public void Awake(Component component) { List iAwakeSystems = this.awakeSystems[component.GetType()]; if (iAwakeSystems == null) { return; } foreach (IAwakeSystem aAwakeSystem in iAwakeSystems) { if (aAwakeSystem == null) { continue; } IAwake iAwake = aAwakeSystem as IAwake; if (iAwake == null) { continue; } try { iAwake.Run(component); } catch (Exception e) { Log.Error(e); } } } public void Awake(Component component, P1 p1) { List iAwakeSystems = this.awakeSystems[component.GetType()]; if (iAwakeSystems == null) { return; } foreach (IAwakeSystem aAwakeSystem in iAwakeSystems) { if (aAwakeSystem == null) { continue; } IAwake iAwake = aAwakeSystem as IAwake; if (iAwake == null) { continue; } try { iAwake.Run(component, p1); } catch (Exception e) { Log.Error(e); } } } public void Awake(Component component, P1 p1, P2 p2) { List iAwakeSystems = this.awakeSystems[component.GetType()]; if (iAwakeSystems == null) { return; } foreach (IAwakeSystem aAwakeSystem in iAwakeSystems) { if (aAwakeSystem == null) { continue; } IAwake iAwake = aAwakeSystem as IAwake; if (iAwake == null) { continue; } try { iAwake.Run(component, p1, p2); } catch (Exception e) { Log.Error(e); } } } public void Awake(Component component, P1 p1, P2 p2, P3 p3) { List iAwakeSystems = this.awakeSystems[component.GetType()]; if (iAwakeSystems == null) { return; } foreach (IAwakeSystem aAwakeSystem in iAwakeSystems) { if (aAwakeSystem == null) { continue; } IAwake iAwake = aAwakeSystem as IAwake; if (iAwake == null) { continue; } try { iAwake.Run(component, p1, p2, p3); } catch (Exception e) { Log.Error(e); } } } public void Change(Component component) { List iChangeSystems = this.changeSystems[component.GetType()]; if (iChangeSystems == null) { return; } foreach (IChangeSystem iChangeSystem in iChangeSystems) { if (iChangeSystem == null) { continue; } try { iChangeSystem.Run(component); } catch (Exception e) { Log.Error(e); } } } public void Load() { while (this.loaders.Count > 0) { long instanceId = this.loaders.Dequeue(); Component component; if (!this.allComponents.TryGetValue(instanceId, out component)) { continue; } if (component.IsDisposed) { continue; } List iLoadSystems = this.loadSystems[component.GetType()]; if (iLoadSystems == null) { continue; } this.loaders2.Enqueue(instanceId); foreach (ILoadSystem iLoadSystem in iLoadSystems) { try { iLoadSystem.Run(component); } catch (Exception e) { Log.Error(e); } } } ObjectHelper.Swap(ref this.loaders, ref this.loaders2); } private void Start() { while (this.starts.Count > 0) { long instanceId = this.starts.Dequeue(); Component component; if (!this.allComponents.TryGetValue(instanceId, out component)) { continue; } List iStartSystems = this.startSystems[component.GetType()]; if (iStartSystems == null) { continue; } foreach (IStartSystem iStartSystem in iStartSystems) { try { iStartSystem.Run(component); } catch (Exception e) { Log.Error(e); } } } } public void Destroy(Component component) { List iDestroySystems = this.destroySystems[component.GetType()]; if (iDestroySystems == null) { return; } foreach (IDestroySystem iDestroySystem in iDestroySystems) { if (iDestroySystem == null) { continue; } try { iDestroySystem.Run(component); } catch (Exception e) { Log.Error(e); } } } public void Update() { this.Start(); while (this.updates.Count > 0) { long instanceId = this.updates.Dequeue(); Component component; if (!this.allComponents.TryGetValue(instanceId, out component)) { continue; } if (component.IsDisposed) { continue; } List iUpdateSystems = this.updateSystems[component.GetType()]; if (iUpdateSystems == null) { continue; } this.updates2.Enqueue(instanceId); foreach (IUpdateSystem iUpdateSystem in iUpdateSystems) { try { iUpdateSystem.Run(component); } catch (Exception e) { Log.Error(e); } } } ObjectHelper.Swap(ref this.updates, ref this.updates2); } public void LateUpdate() { while (this.lateUpdates.Count > 0) { long instanceId = this.lateUpdates.Dequeue(); Component component; if (!this.allComponents.TryGetValue(instanceId, out component)) { continue; } if (component.IsDisposed) { continue; } List iLateUpdateSystems = this.lateUpdateSystems[component.GetType()]; if (iLateUpdateSystems == null) { continue; } this.lateUpdates2.Enqueue(instanceId); foreach (ILateUpdateSystem iLateUpdateSystem in iLateUpdateSystems) { try { iLateUpdateSystem.Run(component); } catch (Exception e) { Log.Error(e); } } } ObjectHelper.Swap(ref this.lateUpdates, ref this.lateUpdates2); } public void Run(string type) { List iEvents; if (!this.allEvents.TryGetValue(type, out iEvents)) { return; } foreach (IEvent iEvent in iEvents) { try { iEvent?.Handle(); } catch (Exception e) { Log.Error(e); } } } public void Run(string type, A a) { List iEvents; if (!this.allEvents.TryGetValue(type, out iEvents)) { return; } foreach (IEvent iEvent in iEvents) { try { iEvent?.Handle(a); } catch (Exception e) { Log.Error(e); } } } public void Run(string type, A a, B b) { List iEvents; if (!this.allEvents.TryGetValue(type, out iEvents)) { return; } foreach (IEvent iEvent in iEvents) { try { iEvent?.Handle(a, b); } catch (Exception e) { Log.Error(e); } } } public void Run(string type, A a, B b, C c) { List iEvents; if (!this.allEvents.TryGetValue(type, out iEvents)) { return; } foreach (IEvent iEvent in iEvents) { try { iEvent?.Handle(a, b, c); } catch (Exception e) { Log.Error(e); } } } } }