diff --git a/AwperativeKernel.sln.DotSettings.user b/AwperativeKernel.sln.DotSettings.user index de6613a..0c40b79 100644 --- a/AwperativeKernel.sln.DotSettings.user +++ b/AwperativeKernel.sln.DotSettings.user @@ -1,6 +1,7 @@  ForceIncluded ForceIncluded + ForceIncluded <AssemblyExplorer> <Assembly Path="/Users/averynorris/Programming/Test/Awperative/Awperative/bin/Debug/net8.0/Awperative.dll" /> </AssemblyExplorer> \ No newline at end of file diff --git a/AwperativeKernel/Kernel/Component/Component.cs b/AwperativeKernel/Kernel/Component/Component.cs index 79fe4ad..b15fb69 100644 --- a/AwperativeKernel/Kernel/Component/Component.cs +++ b/AwperativeKernel/Kernel/Component/Component.cs @@ -18,38 +18,42 @@ public abstract partial class Component : ComponentDocker, IDisposable - /// - /// Current parent of the Component. Can be either Scene or another Component. - /// + /// Current parent of the Component. Can be either Scene or another Component. public ComponentDocker ComponentDocker { get; internal set; } = null; - - /// - /// If the component receives time events or not. - /// - public bool Enabled = true; - - - /// /// Component name /// - public string Name; - - + [NotNull] + public string Name { + get => _name; + set { if (!NotNull.VerifyOrThrow(value)) return; _name = value; } + } private string _name; + /// Represents the state of this Component, The largest bit represents if the Component is enabled or not, while the + /// next 7 represent its priority + [UnsafeInternal] + private byte OrderProfile; + + /// If the component receives time events or not. + [CalculatedProperty] [CalculatedPropertyExpense("Very Low")] + public bool Enabled { + get => (OrderProfile & 128) > 0; + set => OrderProfile = (byte)((OrderProfile & 127) | (value ? 128 : 0)); + } - - - - /// - /// Order for when Components are called on. Only applies between Components on the same Docker. - /// + /// Represents the Component's Update priority, can be set to any value ranging from -64 to 63; otherwise an error will throw! + [CalculatedProperty] [CalculatedPropertyExpense("Very Low")] public int Priority { - get => _priority; set => ComponentDocker.UpdatePriority(this, value); - } internal int _priority; + get => (sbyte)(OrderProfile << 1) >> 1; + set { + if(!ValueFitsRange.VerifyOrThrow(value, -64, 63)) return; + OrderProfile = (byte)((OrderProfile & 0x80) | (value & 0x7F)); + ComponentDocker.UpdatePriority(this, value); + } + } @@ -204,12 +208,16 @@ public abstract partial class Component : ComponentDocker, IDisposable public ImmutableArray GetAllChildren() { - List targets = [.._Components]; - for (int i = 0; i < targets.Count; i++) targets.InsertRange(i + 1, targets[i]._Components); + List targets = [.._components]; + for (int i = 0; i < targets.Count; i++) targets.InsertRange(i + 1, targets[i]._components); return [..targets]; } public virtual void Dispose() { GC.SuppressFinalize(this); } + + public override string ToString() { + return this.Name; + } } \ No newline at end of file diff --git a/AwperativeKernel/Kernel/ComponentDocker/Attributes/DockerOwns.cs b/AwperativeKernel/Kernel/ComponentDocker/Attributes/DockerOwns.cs index 61e39cf..b0049a1 100644 --- a/AwperativeKernel/Kernel/ComponentDocker/Attributes/DockerOwns.cs +++ b/AwperativeKernel/Kernel/ComponentDocker/Attributes/DockerOwns.cs @@ -1,4 +1,6 @@ using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; namespace AwperativeKernel; @@ -7,7 +9,7 @@ namespace AwperativeKernel; /// /// Requires that the Docker owns the parameter /// -[AttributeUsage(AttributeTargets.Parameter)] +[AttributeUsage(AttributeTargets.All)] public class DockerOwns : Attribute { @@ -38,7 +40,7 @@ public class DockerOwns : Attribute /// /// Requires that the Docker does not own the parameter /// -[AttributeUsage(AttributeTargets.Parameter)] +[AttributeUsage(AttributeTargets.All)] public class DockerDoesntOwn : Attribute { @@ -69,7 +71,7 @@ public class DockerDoesntOwn : Attribute /// /// Requires that the component is not attached to any Docker /// -[AttributeUsage(AttributeTargets.Parameter)] +[AttributeUsage(AttributeTargets.All)] public class OrphanComponent : Attribute { @@ -101,7 +103,7 @@ public class OrphanComponent : Attribute /// /// Requires that the Component is not null /// -[AttributeUsage(AttributeTargets.Parameter)] +[AttributeUsage(AttributeTargets.All)] public class ComponentNotNull : Attribute { @@ -125,7 +127,7 @@ public class ComponentNotNull : Attribute /// /// Requires that the Docker is not null /// -[AttributeUsage(AttributeTargets.Parameter)] +[AttributeUsage(AttributeTargets.All)] public class DockerNotNull : Attribute { @@ -149,7 +151,7 @@ public class DockerNotNull : Attribute /// /// Requires that the Scene is not null /// -[AttributeUsage(AttributeTargets.Parameter)] +[AttributeUsage(AttributeTargets.All)] public class SceneNotNull : Attribute { @@ -157,7 +159,6 @@ public class SceneNotNull : Attribute /// /// Verifies if the Scene is not null! Throws an error otherwise. /// - /// /// public static bool VerifyOrThrow(Scene __scene) { if (__scene != null) return true; @@ -170,10 +171,56 @@ public class SceneNotNull : Attribute +/// +/// Requires that everything in the collection is not null +/// +[AttributeUsage(AttributeTargets.All)] +public class CollectionNotNull : Attribute +{ + + + /// + /// Verifies if the Scene is not null! Throws an error otherwise. + /// + /// + public static bool VerifyOrThrow(Collection __collection) { + for (var i = 0; i < __collection.Count; i++) + if (__collection[i] == null) + Debug.LogError("A Given Collection has null members!", ["Type"], [__collection.GetType().Name]); + + return Awperative.IgnoreErrors; + } +} + + + +/// +/// Requires that everything in the collection is not null +/// +[AttributeUsage(AttributeTargets.All)] +public class EnumeratorNotNull : Attribute +{ + + + /// + /// Verifies if the Scene is not null! Throws an error otherwise. + /// + /// + public static bool VerifyOrThrow(IEnumerable __enumerator) { + foreach (object obj in __enumerator) + if (obj == null) + Debug.LogError("A Given Enumerator has null members!", ["Type"], [__enumerator.GetType().Name]); + + return Awperative.IgnoreErrors; + } +} + + + /// /// Requires that the object is not null /// -[AttributeUsage(AttributeTargets.Parameter)] +[AttributeUsage(AttributeTargets.All)] public class NotNull : Attribute { @@ -181,7 +228,6 @@ public class NotNull : Attribute /// /// Verifies if the Scene is not null! Throws an error otherwise. /// - /// /// public static bool VerifyOrThrow(Object __object) { if (__object != null) return true; @@ -199,7 +245,7 @@ public class NotNull : Attribute /// /// Requires that the Docker is a different docker than the one given /// -[AttributeUsage(AttributeTargets.Parameter)] +[AttributeUsage(AttributeTargets.All)] public class DifferentDocker : Attribute { @@ -207,7 +253,6 @@ public class DifferentDocker : Attribute /// /// Verifies if the Dockers are different! /// - /// /// public static bool VerifyOrThrow(ComponentDocker __docker, ComponentDocker __other) { if (__docker != __other) return true; @@ -220,4 +265,54 @@ public class DifferentDocker : Attribute return Awperative.IgnoreErrors; } -} \ No newline at end of file +} + + + +/// +/// Requires that the index fits a given collection +/// +[AttributeUsage(AttributeTargets.All)] +public class ValueFitsRange : Attribute +{ + + + /// + /// Verifies if the value fits a range + /// + /// + /// + public static bool VerifyOrThrow(int __index, int __min, int __max) { + if (__index >= __min && __index <= __max) return true; + + Debug.LogError("Value does not fit range!", ["Index"], [__index.ToString("N0")]); + + return Awperative.IgnoreErrors; + } +} + + + +/// +/// Shows that the given object is unsafe (ex. it doesn't check for null values and such, or it doesn't have guardrails based on cases). +/// This is just for internal/private methods to remind myself how to call it :) The reasoning is case by case, but most of the time, +/// it is because all of the exposing public methods already check, and double checks would only slow me down +/// +[AttributeUsage(AttributeTargets.All)] +public class UnsafeInternal : Attribute { } + + + +/// +/// Shows that the given object (meant for external use) is calculated every time it is called! Good to know for performance heavy systems. +/// +[AttributeUsage(AttributeTargets.All)] +public class CalculatedProperty() : Attribute { } + + + +/// +/// Just a way to write how expensive a calculated property can be. +/// +[AttributeUsage(AttributeTargets.All)] +public class CalculatedPropertyExpense(string Expense) : Attribute { } \ No newline at end of file diff --git a/AwperativeKernel/Kernel/ComponentDocker/Core/ComponentDocker.cs b/AwperativeKernel/Kernel/ComponentDocker/Core/ComponentDocker.cs index 688b341..343a24f 100644 --- a/AwperativeKernel/Kernel/ComponentDocker/Core/ComponentDocker.cs +++ b/AwperativeKernel/Kernel/ComponentDocker/Core/ComponentDocker.cs @@ -5,8 +5,6 @@ using System.Collections.Immutable; using System.Diagnostics; using System.Linq; using System.Reflection; -using AwperativeKernel.Attributes; - namespace AwperativeKernel; @@ -16,66 +14,68 @@ namespace AwperativeKernel; /// /// Please don't inherit this. I don't know why you would /// Avery Norris -public abstract partial class ComponentDocker : IEnumerable, IEnumerable, IEquatable, IEquatable +public abstract partial class ComponentDocker : IEnumerable, IEnumerable, IEquatable, IEquatable, IEquatable { - public bool Equals(Component __other) { - if (this is Component component) { - return component == __other; - } else return false; - } - - public bool Equals(ComponentDocker __other) { - return this == __other; - } - - - //blocks external inheritance + //Blocks external inheritance internal ComponentDocker() {} - - IEnumerator IEnumerable.GetEnumerator() { - return GetEnumerator(); - } - - public IEnumerator GetEnumerator() { - Console.WriteLine("enumerator called" + _Components.Count); - return new ComponentDockEnum([.._Components]); - } - - - - /// - /// List of all Components belonging to the Docker, Please Use Add, Get, Move and Destroy to modify it. - /// - public ImmutableArray Components => [.._Components]; - - - - /// - /// Amount of all Components in the Docker - /// - public int Count => _Components.Count; - - - /// /// Core of Docker, contains all of our precious Components. Sorts them by their priorities with highest going first. /// If they are equal it defaults to hash codes to ensure consistent Behavior /// - internal List _Components = new(); - internal Dictionary> _ComponentDictionary = new(); - internal Dictionary> _taggedComponents = new(); + + /// Core of the Docker, holds all of the Components, sorted by update priority. + [UnsafeInternal] internal List _components = new(); + /// Holds a list of Components at each of their types. This optimizes Get<Type> to O(1) + [UnsafeInternal] internal Dictionary> _componentTypeDictionary = new(); + /// Stores a Component in a list at each of their tags. This optimizes Get(string tag) to O(1) + [UnsafeInternal] internal Dictionary> _componentTagDictionary = new(); - /// - /// How Priority is sorted. - /// - private readonly static Comparer _componentSorter = Comparer.Create((a, b) => { - int result = b.Priority.CompareTo(a.Priority); - return (result != 0) ? result : a.GetHashCode().CompareTo(b.GetHashCode()); - }); + //Indexers to allow juicy speedy: for loops + public Component this[[ValueFitsRange] int __index] { + get => !ValueFitsRange.VerifyOrThrow(__index, 0, _components.Count) ? null : _components[__index]; + set { if (!ValueFitsRange.VerifyOrThrow(__index, 0, _components.Count)) return; _components[__index] = value; } + } + + //Allows uint indexing, which makes me mad because nobody ever does those. To convert it over we just mask the largest bit, and cast to integer. That way + //no sign flipping buisness happens. + public Component this[uint __index] => this[(int) (__index & 0x7FFFFFFF)]; + + + //Enumerators for convenient foreach loops + IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } + public IEnumerator GetEnumerator() { return new ComponentDockEnum([.._components]); } + + + /// List of all Components belonging to the Docker, Please Use Add, Get, Move and Destroy to modify it + public IReadOnlyList Components => _components; + + /// Amount of Components attached to the Docker + public int Count => _components.Count; + + + + /// Compares the Docker to another Scene. + public bool Equals(Scene __other) { + if (this is Scene scene) + return scene == __other; + return false; + } + + /// Compares the Docker to another Component. + public bool Equals(Component __other) { + if (this is Component component) + return component == __other; + return false; + } + + /// Compares the Docker to another Docker. + public bool Equals(ComponentDocker __other) { + return this == __other; + } @@ -86,305 +86,69 @@ public abstract partial class ComponentDocker : IEnumerable, IEnumerable /// Component to modify /// New priority for Component + [UnsafeInternal] internal void UpdatePriority(Component __component, int __priority) { - //add ownership enforcement/method - _Components.Sort(_componentSorter); - __component._priority = __priority; + _components.Sort(Awperative._prioritySorter); } - - //internal void TryEvent(Component __component, Awperative.TimeEvent __timeEvent) => __component.TryEvent(__timeEvent); - - + /// + /// Sends an event to all Children and tells them to continue it. + /// + /// Type of event to send + [UnsafeInternal] internal void ChainEvent(int __timeEvent) { - for (int i = 0; i < _Components.Count; i++) { - _Components[i].TryEvent(__timeEvent); - _Components[i].ChainEvent(__timeEvent); + for (int i = 0; i < _components.Count; i++) { + _components[i].TryEvent(__timeEvent); + _components[i].ChainEvent(__timeEvent); } } - - - - - - - - - - - - - - - - - - - - - - - - - - - - /// - /// Add component to its proper place in the dictionary and resort values to match priorities. - /// - /// Component to hash - /// Value to try and hash - internal void HashTaggedComponent(Component __component, string __tag) { - - - if (!__component._tags.Add(__tag)) { - Debug.LogError("Component already has tag!", ["Component", "Type", "Tag", "Docker"], - [__component.GetHashCode().ToString(), __component.GetType().ToString(), __tag, GetHashCode().ToString()]); return; - } - - if (_taggedComponents.TryGetValue(__tag, out SortedSet components)) { - components.Add(__component); - - } else { _taggedComponents.Add(__tag, new SortedSet(_componentSorter)); _taggedComponents[__tag].Add(__component); } - } - - - - /// - /// + /// Add a Component into the lists and dictionaries. /// /// - /// - internal void UnhashTaggedComponent(Component __component, string __tag) { - - if (!__component._tags.Remove(__tag)) { - Debug.LogError("Component already doesn't have that tag!", ["Component", "Type", "Tag", "Docker"], - [__component.GetHashCode().ToString(), __component.GetType().ToString(), __tag, GetHashCode().ToString()]); return; - } - - - if (_taggedComponents.TryGetValue(__tag, out SortedSet components)) { - components.Remove(__component); - - if(components.Count == 0) - _taggedComponents.Remove(__tag); - } - } - - - - - - /// - /// Finds the first instance of a component with a given tag - /// - /// Tag to search for - /// - internal Component Get(string __tag) { - if (_taggedComponents.TryGetValue(__tag, out SortedSet components)) - return ((Component[])[..components])[0]; - - return null; - } - - - - /// - /// Finds the first instance of a component with a given tag - /// - /// Tag to search for - /// Component that has been found - /// - internal bool TryGet(string __tag, out Component __component) { __component = Get(__tag); return __component != null; } - - - - /// - /// Finds all Components with a given tag - /// - /// - /// - internal ImmutableArray GetAll(string __tag) { - if (_taggedComponents.TryGetValue(__tag, out SortedSet components)) - return [..components]; - - return []; - } - - - - /// - /// Searches for all Components with a given tag - /// - /// - /// - /// - internal bool TryGetAll(string __tag, out ImmutableArray __components) { __components = GetAll(__tag); return __components.Length > 0; } - - - - /// - /// Finds the first Component that has all the given tags - /// - /// - /// - internal Component Get(List __tags) { ImmutableArray returnValue = GetAll(__tags); return returnValue.Length > 0 ? returnValue[0] : null; } - - - - /// - /// Finds the first Component that has all the given tags - /// - /// - /// - internal bool TryGet(List __tags, out Component __component) { __component = Get(__tags); return __component != null; } - - - - /// - /// Finds all Components that have all the given tags - /// - /// - /// - internal ImmutableArray GetAll(List __tags) { - - if (__tags.Count == 0) - return []; - - SortedSet foundComponents = _taggedComponents[__tags[0]]; - - for (int i = 1; i < __tags.Count; i++) { - foreach (Component component in (Component[])[..foundComponents]) { - if (!_taggedComponents[__tags[i]].Contains(component)) foundComponents.Remove(component); - } - } - - return [..foundComponents]; - } - - - - /// - /// Tries to get all components with the given tags - /// - /// - /// - /// - internal bool TryGetAll(List __tags, out ImmutableArray __components) { __components = GetAll(__tags); return __components.Length > 0; } - - - - - - /// - /// Searches and returns the first Component of a type found on the Docker. - /// - /// The Type of Component to search for - /// - public __Type Get<__Type>() where __Type : Component { - - - - //Iterates through the loop and returns if a match is found - foreach (Component component in (Component[])[.._Components]) - if (component is __Type foundComponent) return foundComponent; - - - - //Throws error if there is no Component found - Debug.LogError("Docker does not have target Component", ["Type", "Docker"], - [typeof(__Type).ToString(), GetHashCode().ToString()]); return null; - } - - - - /// - /// - /// - /// - /// - /// - public bool TryGet<__Type>(out __Type __component) where __Type : Component { __component = Get<__Type>(); return __component != null; } - - - - - - /// - /// Searches and returns all Components of a type found on the Docker. - /// - /// The Type of Components to search for - /// - public ImmutableArray<__Type> GetAll<__Type>() where __Type : Component { - - - - List<__Type> foundComponents = []; - - - //Iterates through the loop and returns if a match is found - foreach (Component component in (Component[])[.._Components]) { - if (component is __Type foundComponent) { - foundComponents.Add(foundComponent); - } - } - - - //Throws error if there is no Component found - if (foundComponents.Count == 0) { - Debug.LogError("Docker does not have target Component", ["Type", "Docker"], - [typeof(__Type).ToString(), GetHashCode().ToString()]); - return []; - } - - - - return [..foundComponents]; - } - - - - /// - /// - /// - /// - /// - /// - public bool TryGetAll<__Type>(out ImmutableArray<__Type> __components) where __Type : Component { __components = GetAll<__Type>(); return __components.Length > 0; } - - - - - - - - + [UnsafeInternal] private void AddComponentToLists(Component __component) { var Type = __component.GetType(); - _Components.Add(__component); - if (!_ComponentDictionary.TryAdd(Type, [__component])) _ComponentDictionary[Type].Add(__component); + _components.Add(__component); + if (!_componentTypeDictionary.TryAdd(Type, [__component])) _componentTypeDictionary[Type].Add(__component); - for(var i = 0; i < __component.Tags.Length; i++) { HashTaggedComponent(__component.Tags[i], __component); } + for(var i = 0; i < __component.Tags.Length; i++) { AddTagToComponent(__component.Tags[i], __component); } } + /// + /// Removes a Component from the lists and dictionaries. + /// + /// + [UnsafeInternal] private void RemoveComponentFromLists(Component __component) { var Type = __component.GetType(); - _Components.Remove(__component); + _components.Remove(__component); - if(!_ComponentDictionary.ContainsKey(Type)) _ComponentDictionary[Type].Remove(__component); + if(!_componentTypeDictionary.ContainsKey(Type)) _componentTypeDictionary[Type].Remove(__component); - for(var i = 0; i < __component.Tags.Length; i++) { UnhashTaggedComponent(__component.Tags[i], __component); } + for(var i = 0; i < __component.Tags.Length; i++) { RemoveTagFromComponent(__component.Tags[i], __component); } } - private void HashTaggedComponent(string __tag, Component __component) { - if (!_taggedComponents.TryAdd(__component.Tags[i], [__component])) - _taggedComponents[__component.Tags[i]].Add(__component); + /// + /// Hashes a Component in the tag dictionary + /// + /// Tag to add + /// Component to add it to + [UnsafeInternal] + private void AddTagToComponent(string __tag, Component __component) { + if (!_componentTagDictionary.TryAdd(__tag, [__component])) + _componentTagDictionary[__tag].Add(__component); } - private void UnhashTaggedComponent(string __tag, Component __component) { - if(!_taggedComponents.ContainsKey(__tag)) _taggedComponents[__tag].Remove(__component); + /// + /// Unhashes a Component from the tag dictionary + /// + /// Tag to remove + /// Component to remove it from + [UnsafeInternal] + private void RemoveTagFromComponent(string __tag, Component __component) { + if(!_componentTagDictionary.ContainsKey(__tag)) _componentTagDictionary[__tag].Remove(__component); } } \ No newline at end of file diff --git a/AwperativeKernel/Kernel/ComponentDocker/Core/ComponentDockerExposure.cs b/AwperativeKernel/Kernel/ComponentDocker/Core/ComponentDockerExposure.cs index e396e20..45673e2 100644 --- a/AwperativeKernel/Kernel/ComponentDocker/Core/ComponentDockerExposure.cs +++ b/AwperativeKernel/Kernel/ComponentDocker/Core/ComponentDockerExposure.cs @@ -1,5 +1,12 @@ +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Collections.ObjectModel; +using System.Linq; +using System.Runtime.CompilerServices; + + namespace AwperativeKernel; @@ -12,14 +19,16 @@ public abstract partial class ComponentDocker /// /// /// - public bool Contains([NotNull] string __tag) => NotNull.VerifyOrThrow(__tag) && _taggedComponents.ContainsKey(__tag); + public bool Contains([NotNull] string __tag) + => NotNull.VerifyOrThrow(__tag) && _componentTagDictionary.ContainsKey(__tag); /// /// Returns a bool for if the Docker contains a Component of that type or not /// /// Type of the Component - public bool Contains<__Type>() where __Type : Component => _ComponentDictionary.ContainsKey(typeof(__Type)); + public bool Contains<__Type>() where __Type : Component + => _componentTypeDictionary.ContainsKey(typeof(__Type)); @@ -28,5 +37,330 @@ public abstract partial class ComponentDocker /// /// /// - public bool Contains([ComponentNotNull,DockerOwns] Component __component) => NotNull.VerifyOrThrow(__component) && DockerOwns.VerifyOrThrow(this, __component) && _Components.Contains(__component); + public bool Contains([ComponentNotNull,DockerOwns] Component __component) + => NotNull.VerifyOrThrow(__component) && DockerOwns.VerifyOrThrow(this, __component) && _components.Contains(__component); + + /// + /// Finds all Components that have all the given tags + /// + /// + /// + public bool Contains<__Type>(string __tag) { + return GetAll<__Type>(__tag).Any(); + } + + /// + /// Finds all Components that have all the given tags + /// + /// + /// + public bool Contains(IList __tags) { + return GetAll(__tags).Any(); + } + + /// + /// Finds all Components that have all the given tags + /// + /// + /// + public bool Contains(IEnumerable __tags) { + return GetAll(__tags).Any(); + } + + /// + /// Finds all Components that have all the given tags + /// + /// + /// + public bool Contains<__Type>(IList __tags) { + return GetAll<__Type>(__tags).Any(); + } + + /// + /// Finds all Components that have all the given tags + /// + /// + /// + public bool Contains<__Type>(IEnumerable __tags) { + return GetAll<__Type>(__tags).Any(); + } + + + + + + /// + /// Searches and returns the first Component of a type found on the Docker. + /// + /// The Type of Component to search for + /// + public __Type Get<__Type>() where __Type : Component { + return _componentTypeDictionary.TryGetValue(typeof(__Type), out var Components) ? (__Type)Components.FirstOrDefault() : null; + } + + /// + /// + /// + /// + /// + /// + public bool TryGet<__Type>(out __Type __component) where __Type : Component { + __component = Get<__Type>(); return __component != null; + } + + + + /// + /// Searches and returns all Components of a type found on the Docker. + /// + /// The Type of Components to search for + /// + public IReadOnlyList<__Type> GetAll<__Type>() where __Type : Component { + return (IReadOnlyList<__Type>)_componentTypeDictionary.GetValueOrDefault(typeof(__Type)).ToList(); + } + + /// + /// + /// + /// + /// + /// + public bool TryGetAll<__Type>(out IReadOnlyList<__Type> __components) where __Type : Component { + __components = GetAll<__Type>(); return __components.Any(); + } + + + + + + /// + /// Finds all Components that have all the given tags + /// + /// + /// + public IReadOnlyList GetAll(IList __tags) { + + if (__tags.Count == 0) + return []; + + HashSet components; + + if (_componentTagDictionary.TryGetValue(__tags[0], out var firstComponents)) components = firstComponents; else return []; + + for (var i = 1; i < __tags.Count; i++) + if (_componentTagDictionary.TryGetValue(__tags[i], out var taggedComponents)) + foreach (var component in components) if (!taggedComponents.Contains(component)) components.Remove(component);else return []; + + return components.ToList(); + } + + /// + /// Finds all Components that have all the given tags + /// + /// + /// + public bool TryGetAll(IList __tags, out IReadOnlyList __components) { + __components = GetAll(__tags); return __components.Any(); + } + + + + /// + /// Finds all Components that have all the given tags, slower than GetAll() using IList. If you are being high performance, use that. + /// + /// + /// + public IReadOnlyList GetAll(IEnumerable __tags) { + + if (!__tags.Any()) + return []; + + HashSet components; + + if (_componentTagDictionary.TryGetValue(__tags.First(), out var firstComponents)) components = firstComponents; else return []; + + foreach(var tag in __tags) + if (_componentTagDictionary.TryGetValue(tag, out var taggedComponents)) + foreach (var component in components) if (!taggedComponents.Contains(component)) components.Remove(component);else return []; + + return components.ToList(); + } + + /// + /// Finds all Components that have all the given tags + /// + /// + /// + public bool TryGetAll(IEnumerable __tags, out IReadOnlyList __components) { + __components = GetAll(__tags); return __components.Any(); + } + + + + + + /// + /// Finds all Components that have all the given tags + /// + /// + /// + public IReadOnlyList<__Type> GetAll<__Type>(IList __tags) { + + if (!__tags.Any()) + return []; + + HashSet<__Type> components = []; + + if (_componentTagDictionary.TryGetValue(__tags[0], out var firstComponents)) + foreach (var component in firstComponents) if (component is __Type typedComponent) components.Add(typedComponent); + + for (var i = 1; i < __tags.Count; i++) + if (_componentTagDictionary.TryGetValue(__tags[i], out var taggedComponents)) + foreach (var component in components) if (!taggedComponents.Contains(component as Component)) components.Remove(component);else return []; + + return components.ToList(); + } + + /// + /// Finds all Components that have all the given tags + /// + /// + /// + public bool TryGetAll<__Type>(IList __tags, out IReadOnlyList<__Type> __components) { + __components = GetAll<__Type>(__tags); return __components.Any(); + } + + + + + + /// + /// Finds all Components that have all the given tags + /// + /// + /// + public IReadOnlyList<__Type> GetAll<__Type>(IEnumerable __tags) { + + if (!__tags.Any()) + return []; + + HashSet<__Type> components = []; + + if (_componentTagDictionary.TryGetValue(__tags.First(), out var firstComponents)) + foreach (var component in firstComponents) if (component is __Type typedComponent) components.Add(typedComponent); + + foreach(string tag in __tags) + if (_componentTagDictionary.TryGetValue(tag, out var taggedComponents)) + foreach (var component in components) if (!taggedComponents.Contains(component as Component)) components.Remove(component);else return []; + + return components.ToList(); + } + + /// + /// Finds all Components that have all the given tags + /// + /// + /// + public bool TryGetAll<__Type>(IEnumerable __tags, out IReadOnlyList<__Type> __components) { + __components = GetAll<__Type>(__tags); return __components.Any(); + } + + + + /// + /// Finds all Components that have all the given tags + /// + /// + /// + public IReadOnlyList GetAll(string __tag) { + return GetAll([__tag]); + } + + /// + /// Finds all Components that have all the given tags + /// + /// + /// + public bool TryGetAll(string __tag, out IReadOnlyList __components) { + __components = GetAll(__tag); return __components.Any(); + } + + + + /// + /// Finds all Components that have all the given tags + /// + /// + /// + public IReadOnlyList<__Type> GetAll<__Type>(string __tag) { + return GetAll<__Type>([__tag]); + } + + /// + /// Finds all Components that have all the given tags + /// + /// + /// + public bool TryGetAll<__Type>(string __tag, out IReadOnlyList<__Type> __components) { + __components = GetAll<__Type>(__tag); return __components.Any(); + } + + + + public Component Get(IList __tags) { + return GetAll(__tags).FirstOrDefault(); + } + + public bool TryGet(IList __tags, out Component __component) { + __component = Get(__tags); return __component != null; + } + + + + public Component Get(IEnumerable __tags) { + return GetAll(__tags).FirstOrDefault(); + } + + public bool TryGet(IEnumerable __tags, out Component __component) { + __component = Get(__tags); return __component != null; + } + + + + public __Type Get<__Type>(IList __tags) { + return GetAll<__Type>(__tags).FirstOrDefault(); + } + + public bool TryGet<__Type>(IList __tags, out __Type __component) { + __component = Get<__Type>(__tags); return __component != null; + } + + + + public Component Get(string __tag) { + return GetAll([__tag]).FirstOrDefault(); + } + + public bool TryGet(string __tag, out Component __component) { + __component = Get(__tag); return __component != null; + } + + + + public __Type Get<__Type>(string __tag) { + return Get<__Type>([__tag]); + } + + public bool TryGet<__Type>(string __tag, out __Type __component) { + __component = Get<__Type>([__tag]); return __component != null; + } + + + + + + + + + } \ No newline at end of file diff --git a/AwperativeKernel/Kernel/ComponentDocker/Core/ComponentDockerManagement.cs b/AwperativeKernel/Kernel/ComponentDocker/Core/ComponentDockerManagement.cs index 292fdde..3ad9a5c 100644 --- a/AwperativeKernel/Kernel/ComponentDocker/Core/ComponentDockerManagement.cs +++ b/AwperativeKernel/Kernel/ComponentDocker/Core/ComponentDockerManagement.cs @@ -185,5 +185,5 @@ public abstract partial class ComponentDocker /// /// Destroys all Components attached to Docker /// - public void DestroyAll() { for(var i = 0; i < _Components.Count; i++) Destroy(_Components[i]); } + public void DestroyAll() { for(var i = 0; i < _components.Count; i++) Destroy(_components[i]); } } \ No newline at end of file diff --git a/AwperativeKernel/Kernel/Overhead/Awperative/Awperative.cs b/AwperativeKernel/Kernel/Overhead/Awperative/Awperative.cs index 33fcbb9..afd337d 100644 --- a/AwperativeKernel/Kernel/Overhead/Awperative/Awperative.cs +++ b/AwperativeKernel/Kernel/Overhead/Awperative/Awperative.cs @@ -144,8 +144,12 @@ public static class Awperative } - } + + internal static Comparer _prioritySorter = Comparer.Create((a, b) => { + int result = b.Priority.CompareTo(a.Priority); + return (result != 0) ? result : a.GetHashCode().CompareTo(b.GetHashCode()); + }); diff --git a/AwperativeKernel/obj/Debug/net8.0/AwperativeKernel.AssemblyInfo.cs b/AwperativeKernel/obj/Debug/net8.0/AwperativeKernel.AssemblyInfo.cs index f3ac88e..7d064cd 100644 --- a/AwperativeKernel/obj/Debug/net8.0/AwperativeKernel.AssemblyInfo.cs +++ b/AwperativeKernel/obj/Debug/net8.0/AwperativeKernel.AssemblyInfo.cs @@ -13,7 +13,7 @@ using System.Reflection; [assembly: System.Reflection.AssemblyCompanyAttribute("AwperativeKernel")] [assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] -[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+abd47153ad47e5c2d5300dcab27ac4628f468ab1")] +[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+89daba3278f3425069ad72c1e889e2d5c12ffebb")] [assembly: System.Reflection.AssemblyProductAttribute("AwperativeKernel")] [assembly: System.Reflection.AssemblyTitleAttribute("AwperativeKernel")] [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] diff --git a/AwperativeKernel/obj/Debug/net8.0/AwperativeKernel.AssemblyInfoInputs.cache b/AwperativeKernel/obj/Debug/net8.0/AwperativeKernel.AssemblyInfoInputs.cache index 5663421..409b4e2 100644 --- a/AwperativeKernel/obj/Debug/net8.0/AwperativeKernel.AssemblyInfoInputs.cache +++ b/AwperativeKernel/obj/Debug/net8.0/AwperativeKernel.AssemblyInfoInputs.cache @@ -1 +1 @@ -8e04a8f03c26d3cf7cdf50da4979193904b566d6f40392f132e749a5bd9092b9 +fd20f709f0c09dd5820bb098e786f44ec3ff4e66593743fc97dd004440680728 diff --git a/AwperativeKernel/obj/Debug/net8.0/AwperativeKernel.csproj.CoreCompileInputs.cache b/AwperativeKernel/obj/Debug/net8.0/AwperativeKernel.csproj.CoreCompileInputs.cache index 29e9348..8423b84 100644 --- a/AwperativeKernel/obj/Debug/net8.0/AwperativeKernel.csproj.CoreCompileInputs.cache +++ b/AwperativeKernel/obj/Debug/net8.0/AwperativeKernel.csproj.CoreCompileInputs.cache @@ -1 +1 @@ -e4b135c3045a438e4953bde74a036a568da5652715efda203daab787973e7f7e +fb1e5e1f7af8237ad8bd2d22975bb0a75e1f0b64faaaa35af565406d250bd296