using System; using System.Collections; using System.Collections.Generic; using System.Reflection; using Fort23.UTool; using UnityEngine.Profiling; using Utility; namespace Fort23.Core { using OneTypeSystems = UnOrderMultiMap; public sealed class EventSystem : IDisposable { private static EventSystem instance; public static EventSystem Instance { get { if (instance == null) { instance = new EventSystem(); } return instance; } } // private readonly Dictionary _allEntities = new Dictionary(); private readonly Dictionary _assemblies = new Dictionary(); private readonly UnOrderMultiMapSet _mapSet = new UnOrderMultiMapSet(); private Queue _updates = new Queue(); private Queue _updates2 = new Queue(); private Queue _lateUpdates = new Queue(); private Queue _lateUpdates2 = new Queue(); private readonly Map>> currEntity = new Map>>(); private readonly Map>> allEntityMethodName = new Map>>(); private EventSystem() { // TODO 手动添加所包含的程序集 string[] assemblyNames = { "Fort23.Core.dll","Fort23.Mono.dll", "Fort23.GameData.dll" }; foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies()) { string assemblyName = $"{assembly.GetName().Name}.dll"; if (!((IList)assemblyNames).Contains(assemblyName)) { continue; } Add(assembly); } } public Assembly GetAssembly(string key) { if (_assemblies.ContainsKey(key)) { return _assemblies[key]; } return null; } public void Add(Assembly assembly) { this._assemblies[$"{assembly.GetName().Name}.dll"] = assembly; } public HashSet GetTypes(Type systemAttributeType) { if (!this._mapSet.ContainsKey(systemAttributeType)) { return new HashSet(); } return this._mapSet[systemAttributeType]; } public List GetTypes() { List allTypes = new List(); foreach (Assembly assembly in this._assemblies.Values) { allTypes.AddRange(assembly.GetTypes()); } return allTypes; } public Map> GetCustomMethod(Entity component) { Type type = component.GetType(); Map> methodName = null; if (allEntityMethodName.TryGetValue(type, out methodName)) { return methodName; } methodName = new Map>(); var methodInfos = type.GetMethods(); for (int i = 0; i < methodInfos.Length; i++) { CustomMethod customMethod = methodInfos[i].GetCustomAttribute(); if (customMethod != null) { if (!methodName.TryGetValue(customMethod.CustomMethodType, out List allEntityMethodName)) { allEntityMethodName = new List(); methodName.Add(customMethod.CustomMethodType, allEntityMethodName); } allEntityMethodName.Add(methodInfos[i]); } } allEntityMethodName.Add(type, methodName); return methodName; } public void RegisterSystem(Entity component, bool isRegister = true) { if (!isRegister) { this.Remove(component); return; } if (currEntity.ContainsKey(component)) { return; // LogTool.Error("纯在相同的key" + component.InstanceID + "____" + component.GetType()); } Map> allName = GetCustomMethod(component); currEntity.Add(component, allName); for (allName.Begin(); allName.Next();) { if (allName.Key == CustomMethodType.Update) { _updates.Enqueue(component); } if (allName.Key == CustomMethodType.LateUpdate) { _lateUpdates.Enqueue(component); } } } public void Remove(Entity instanceId) { this.currEntity.Remove(instanceId); } public Map> Get(Entity instanceId) { Map> component = null; this.currEntity.TryGetValue(instanceId, out component); return component; } public bool IsRegister(Entity instanceId) { return this.currEntity.ContainsKey(instanceId); } public void Awake(Entity component, object[] data) { try { Dispatch(component, CustomMethodType.Awake, data); } catch (Exception e) { LogTool.Exception(e); } } public void Dispatch(Entity component, CustomMethodType customMethodType, object[] data) { Map> typeData = Get(component); if (typeData == null) { return; } if (typeData.TryGetValue(customMethodType, out List w)) { for (int i = 0; i < w.Count; i++) { w[i].Invoke(component, data); } } } public void Destroy(Entity component) { try { Dispatch(component, CustomMethodType.Destroy, null); } catch (Exception e) { LogTool.Exception(e); } } public void Update() { while (this._updates.Count > 0) { Entity instanceId = this._updates.Dequeue(); if (instanceId.IsDisposed) { continue; } this._updates2.Enqueue(instanceId); try { if (instanceId.IsUpdate()) { Dispatch(instanceId, CustomMethodType.Update, null); } } catch (Exception e) { LogTool.Error(e); // throw new Exception(e.Message); } } ObjectHelper.Swap(ref this._updates, ref this._updates2); } public void LateUpdate() { while (this._lateUpdates.Count > 0) { Entity instanceId = this._lateUpdates.Dequeue(); if (instanceId.IsDisposed) { continue; } this._lateUpdates2.Enqueue(instanceId); try { if (instanceId.IsUpdate()) { Dispatch(instanceId, CustomMethodType.LateUpdate, null); } } catch (Exception e) { LogTool.Exception(e); } } ObjectHelper.Swap(ref this._lateUpdates, ref this._lateUpdates2); } public void Dispose() { instance = null; } } }