This commit is contained in:
2026-02-27 19:50:38 -05:00
parent abd47153ad
commit 89daba3278
16 changed files with 648 additions and 282 deletions

View File

@@ -1,4 +1,6 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation"> <wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ABuffer_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2025_002E2_003Fresharper_002Dhost_003FSourcesCache_003F3dda17b8c491847aa4bd7c56dd3774cd376d43c76c182d041c160bbf4b812b0_003FBuffer_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AObject_002ECoreCLR_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2025_002E2_003Fresharper_002Dhost_003FSourcesCache_003F41f5f1afc2e9972034b9b24da6b9c16efd59be6d5ae907d0ea203e7865bed2_003FObject_002ECoreCLR_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/Environment/AssemblyExplorer/XmlDocument/@EntryValue">&lt;AssemblyExplorer&gt; <s:String x:Key="/Default/Environment/AssemblyExplorer/XmlDocument/@EntryValue">&lt;AssemblyExplorer&gt;
&lt;Assembly Path="/Users/averynorris/Programming/Test/Awperative/Awperative/bin/Debug/net8.0/Awperative.dll" /&gt; &lt;Assembly Path="/Users/averynorris/Programming/Test/Awperative/Awperative/bin/Debug/net8.0/Awperative.dll" /&gt;
&lt;/AssemblyExplorer&gt;</s:String></wpf:ResourceDictionary> &lt;/AssemblyExplorer&gt;</s:String></wpf:ResourceDictionary>

View File

@@ -2,6 +2,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Immutable; using System.Collections.Immutable;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using Microsoft.VisualBasic; using Microsoft.VisualBasic;
@@ -12,15 +13,15 @@ namespace AwperativeKernel;
public abstract partial class Component : ComponentDocker public abstract partial class Component : ComponentDocker, IDisposable
{ {
/// <summary> /// <summary>
/// Current parent of the Component. Can be either Scene or another Component. /// Current parent of the Component. Can be either Scene or another Component.
/// </summary> /// </summary>
public ComponentDocker ComponentDocker { get; internal set; } public ComponentDocker ComponentDocker { get; internal set; } = null;
@@ -38,12 +39,8 @@ public abstract partial class Component : ComponentDocker
///
internal Collection<Action> EventDelegates = [];
@@ -58,30 +55,6 @@ public abstract partial class Component : ComponentDocker
/// <summary>
/// To be called when the Component is created.
/// </summary>
/// <param name="__parent"> Docker that this spawned in this Component</param>
/// <param name="__name"> Name of the component</param>
internal void Initiate(ComponentDocker __parent, string __name, ICollection<string> __tags, Type __type) {
ComponentDocker = __parent;
Name = __name;
_tags = [..__tags];
if (Awperative._TypeAssociatedTimeEvents.TryGetValue(__type, out byte eventProfile)) {
for (int i = 0; i < Awperative.ComponentEvents.Count; i++) {
if ((eventProfile & (1 << i)) > 0)
EventDelegates.Add((Action)Delegate.CreateDelegate(typeof(Action), this, __type.GetMethod(Awperative.ComponentEvents[i])!));
else EventDelegates.Add(null);
}
} else {
Debug.LogError("Awperative does not recognize the given type! Perhaps it was created after Start() was called?", ["Type"], [__type.Name]);
}
}
/// <summary> /// <summary>
@@ -98,7 +71,8 @@ public abstract partial class Component : ComponentDocker
public void TryEvent(int __timeEvent) { public void TryEvent(int __timeEvent) {
EventDelegates[__timeEvent]?.Invoke(); Action<Component> eventDelegates = Awperative._TypeAssociatedTimeEvents[GetType()][__timeEvent];
eventDelegates?.Invoke(this);
} }
@@ -234,4 +208,8 @@ public abstract partial class Component : ComponentDocker
for (int i = 0; i < targets.Count; i++) targets.InsertRange(i + 1, targets[i]._Components); for (int i = 0; i < targets.Count; i++) targets.InsertRange(i + 1, targets[i]._Components);
return [..targets]; return [..targets];
} }
public virtual void Dispose() {
GC.SuppressFinalize(this);
}
} }

View File

@@ -0,0 +1,223 @@
using System;
namespace AwperativeKernel;
/// <summary>
/// Requires that the Docker owns the parameter
/// </summary>
[AttributeUsage(AttributeTargets.Parameter)]
public class DockerOwns : Attribute
{
/// <summary>
/// Verifies if the Component is actually owned by Docker. Throws an error if not.
/// </summary>
/// <param name="__docker">Docker we are checking ownership for</param>
/// <param name="__component">Component to check for</param>
public static bool VerifyOrThrow(ComponentDocker __docker, Component __component) {
if (__docker.Contains(__component)) return true;
Debug.LogError("Docker does not own the Component!", ["ComponentType", "ComponentName", "ComponentHash", "DockerType", "DockerName", "DockerHash"], [
__component.GetType().Name,
__component.Name,
__component.GetHashCode().ToString("N0"),
__docker.GetType().Name,
__docker switch { Scene scene => scene.Name, Component component => component.Name, _ => "unknown" },
__docker.GetHashCode().ToString("N0")
]);
return Awperative.IgnoreErrors;
}
}
/// <summary>
/// Requires that the Docker does not own the parameter
/// </summary>
[AttributeUsage(AttributeTargets.Parameter)]
public class DockerDoesntOwn : Attribute
{
/// <summary>
/// Verifies if the Component is actually not owned by Docker. Throws an error if not.
/// </summary>
/// <param name="__docker">Docker we are checking ownership for</param>
/// <param name="__component">Component to check for</param>
public static bool VerifyOrThrow(ComponentDocker __docker, Component __component) {
if (!__docker.Contains(__component)) return true;
Debug.LogError("Docker owns the Component!", ["ComponentType", "ComponentName", "ComponentHash", "DockerType", "DockerName", "DockerHash"], [
__component.GetType().Name,
__component.Name,
__component.GetHashCode().ToString("N0"),
__docker.GetType().Name,
__docker switch { Scene scene => scene.Name, Component component => component.Name, _ => "unknown" },
__docker.GetHashCode().ToString("N0")
]);
return Awperative.IgnoreErrors;
}
}
/// <summary>
/// Requires that the component is not attached to any Docker
/// </summary>
[AttributeUsage(AttributeTargets.Parameter)]
public class OrphanComponent : Attribute
{
/// <summary>
/// Verifies if the Component is an orphan, not fully accurate, because it only checks if the docker is null, this means it is technically possible
/// to have a component already attached to a docker, and still verify it as false if Docker is null, but this should be impossible in practice.
/// </summary>
/// <param name="__component"></param>
/// <returns></returns>
public static bool VerifyOrThrow(Component __component) {
if (__component.ComponentDocker == null) return true;
Debug.LogError("Component is already owned!", ["ComponentType", "ComponentName", "ComponentHash", "DockerType", "DockerName", "DockerHash"], [
__component.GetType().Name,
__component.Name,
__component.GetHashCode().ToString("N0"),
__component.ComponentDocker.GetType().Name,
__component.ComponentDocker switch { Scene scene => scene.Name, Component component => component.Name, _ => "unknown" },
__component.ComponentDocker.GetHashCode().ToString("N0")
]);
return Awperative.IgnoreErrors;
}
}
/// <summary>
/// Requires that the Component is not null
/// </summary>
[AttributeUsage(AttributeTargets.Parameter)]
public class ComponentNotNull : Attribute
{
/// <summary>
/// Verifies if the Component is not null! Throws an error otherwise.
/// </summary>
/// <param name="__component"></param>
/// <returns></returns>
public static bool VerifyOrThrow(Component __component) {
if (__component != null) return true;
Debug.LogError("Component is null!");
return Awperative.IgnoreErrors;
}
}
/// <summary>
/// Requires that the Docker is not null
/// </summary>
[AttributeUsage(AttributeTargets.Parameter)]
public class DockerNotNull : Attribute
{
/// <summary>
/// Verifies if the Docker is not null! Throws an error otherwise.
/// </summary>
/// <param name="__componentDocker"></param>
/// <returns></returns>
public static bool VerifyOrThrow(ComponentDocker __componentDocker) {
if (__componentDocker != null) return true;
Debug.LogError("Docker is null!");
return Awperative.IgnoreErrors;
}
}
/// <summary>
/// Requires that the Scene is not null
/// </summary>
[AttributeUsage(AttributeTargets.Parameter)]
public class SceneNotNull : Attribute
{
/// <summary>
/// Verifies if the Scene is not null! Throws an error otherwise.
/// </summary>
/// <param name="__componentDocker"></param>
/// <returns></returns>
public static bool VerifyOrThrow(Scene __scene) {
if (__scene != null) return true;
Debug.LogError("Scene is null!");
return Awperative.IgnoreErrors;
}
}
/// <summary>
/// Requires that the object is not null
/// </summary>
[AttributeUsage(AttributeTargets.Parameter)]
public class NotNull : Attribute
{
/// <summary>
/// Verifies if the Scene is not null! Throws an error otherwise.
/// </summary>
/// <param name="__componentDocker"></param>
/// <returns></returns>
public static bool VerifyOrThrow(Object __object) {
if (__object != null) return true;
Debug.LogError("A Given parameter is null!", ["Type"],
[__object.GetType().Name
]);
return Awperative.IgnoreErrors;
}
}
/// <summary>
/// Requires that the Docker is a different docker than the one given
/// </summary>
[AttributeUsage(AttributeTargets.Parameter)]
public class DifferentDocker : Attribute
{
/// <summary>
/// Verifies if the Dockers are different!
/// </summary>
/// <param name="__componentDocker"></param>
/// <returns></returns>
public static bool VerifyOrThrow(ComponentDocker __docker, ComponentDocker __other) {
if (__docker != __other) return true;
Debug.LogError("The Dockers are the same!", ["DockerType, DockerName, DockerHash"], [
__docker.GetType().Name,
__docker switch { Scene scene => scene.Name, Component component => component.Name, _ => "unknown" },
__docker.GetHashCode().ToString("N0")
]);
return Awperative.IgnoreErrors;
}
}

View File

@@ -0,0 +1,62 @@
using System;
using System.Collections;
using System.Collections.Generic;
namespace AwperativeKernel;
/// <summary>
/// Provides an Enumerator for the Component Docker, Loops through all Components in the Docker all for your convenience :)
/// </summary>
/// <param name="__components">Reference to the Component Docker's components, (List to Enumerate through)</param>
/// <remarks> Enumerates on a snapshot of the list. This allows you to modify the ComponentDocker's collection during the loop. </remarks>
/// <author> Avery Norris </author>
public class ComponentDockEnum(Component[] __components) : IEnumerator, IEnumerator<Component>, IDisposable
{
//Current index of the loop
private int index = -1;
/// <summary>
/// Gets the current Component;
/// </summary>
public Component Current => __components[index];
/// <summary>
/// Get the current Component as a generic object
/// </summary>
object IEnumerator.Current => Current;
/// <summary>
/// Proceeds to the next index of the loop
/// </summary>
/// <returns> Returns true or false, depending on whether the Enumeration should continue</returns>
bool IEnumerator.MoveNext() { ++index; return index < __components.Length; }
/// <summary>
/// Resets the loop back to the very start
/// </summary>
public void Reset() => index = -1;
/// <summary>
/// Destroys the enumerator
/// </summary>
public void Dispose() => GC.SuppressFinalize(this);
}

View File

@@ -1,9 +1,11 @@
using System; using System;
using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Immutable; using System.Collections.Immutable;
using System.Collections.ObjectModel; using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using AwperativeKernel.Attributes;
namespace AwperativeKernel; namespace AwperativeKernel;
@@ -14,9 +16,33 @@ namespace AwperativeKernel;
/// </summary> /// </summary>
/// <remarks> Please don't inherit this. I don't know why you would</remarks> /// <remarks> Please don't inherit this. I don't know why you would</remarks>
/// <author> Avery Norris </author> /// <author> Avery Norris </author>
public abstract class ComponentDocker public abstract partial class ComponentDocker : IEnumerable, IEnumerable<Component>, IEquatable<Component>, IEquatable<ComponentDocker>
{ {
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
internal ComponentDocker() {}
IEnumerator IEnumerable.GetEnumerator() {
return GetEnumerator();
}
public IEnumerator<Component> GetEnumerator() {
Console.WriteLine("enumerator called" + _Components.Count);
return new ComponentDockEnum([.._Components]);
}
/// <summary> /// <summary>
@@ -37,7 +63,9 @@ public abstract class ComponentDocker
/// Core of Docker, contains all of our precious Components. Sorts them by their priorities with highest going first. /// 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 /// If they are equal it defaults to hash codes to ensure consistent Behavior
/// </summary> /// </summary>
internal SortedSet<Component> _Components = new(_componentSorter); internal List<Component> _Components = new();
internal Dictionary<Type, HashSet<Component>> _ComponentDictionary = new();
internal Dictionary<string, HashSet<Component>> _taggedComponents = new();
@@ -60,163 +88,34 @@ public abstract class ComponentDocker
/// <param name="__priority"> New priority for Component</param> /// <param name="__priority"> New priority for Component</param>
internal void UpdatePriority(Component __component, int __priority) { internal void UpdatePriority(Component __component, int __priority) {
//add ownership enforcement/method //add ownership enforcement/method
_Components.Sort(_componentSorter);
foreach (String tag in __component._tags) _taggedComponents[tag].Remove(__component); _Components.Remove(__component);
__component._priority = __priority; __component._priority = __priority;
foreach (String tag in __component._tags) _taggedComponents[tag].Add(__component); _Components.Add(__component);
} }
//internal void TryEvent(Component __component, Awperative.TimeEvent __timeEvent) => __component.TryEvent(__timeEvent); //internal void TryEvent(Component __component, Awperative.TimeEvent __timeEvent) => __component.TryEvent(__timeEvent);
internal void ChainEvent(int __timeEvent) { foreach (Component component in _Components) { component.TryEvent(__timeEvent); component.ChainEvent(__timeEvent); }}
/// <summary>
/// Add a new Component to the Docker; This is the only way they should be created.
/// </summary>
/// <param name="__args"> Arguments to construct the Component with</param>
/// <typeparam name="__Type"> Type of Component to instantiate</typeparam>
/// <returns></returns>s
public __Type Add<__Type>(object[] __args, string name = "", ICollection<string> tags = null) where __Type : Component {
Type newComponentType = typeof(__Type);
if(name == "") { name = newComponentType.Name; }
if (tags == null) tags = [];
//Component does not have a constructor that matches the given args
if (newComponentType.GetConstructor(__args.Select(x => x.GetType()).ToArray()) == null) {
Debug.LogError("Component cannot be constructed with the given arguments",
["Type", "Args"],
[newComponentType.ToString(), "[" + string.Join(", ", __args.Select(x => x.ToString())) + "]"]); return null;
};
Component newComponent; internal void ChainEvent(int __timeEvent) {
for (int i = 0; i < _Components.Count; i++) {
_Components[i].TryEvent(__timeEvent);
_Components[i].ChainEvent(__timeEvent);
//Tries to instantiate Component, and sends a fail call if an issue occurs.
try { newComponent = (__Type)Activator.CreateInstance(newComponentType, __args); }
catch {
Debug.LogError("Component creation failed!", ["Type", "Args", "Docker"],
[newComponentType.ToString(), "[" + string.Join(", ", __args.Select(x => x.ToString())) + "]", GetHashCode().ToString()]); return null;
} }
//If Component is null do not add
if(newComponent == null) {
Debug.LogError("Activator created Null Component", ["Type", "Args", "Docker"],
[newComponentType.ToString(), "[" + string.Join(", ", __args.Select(x => x.ToString())) + "]", GetHashCode().ToString()]); return null;
}
//Add to docker and initialize the new Component
_Components.Add(newComponent);
newComponent.Initiate(this, name, tags, newComponentType);
newComponent.TryEvent(4);
newComponent.ChainEvent(4);
return (__Type) newComponent;
} }
/// <summary>
/// Adds a new Component to the Docker; This is the only way they should be created.
/// </summary>
/// <typeparam name="__Type"></typeparam>
/// <returns></returns>
public __Type Add<__Type>(string name = "", string[] tags = null) where __Type : Component => Add<__Type>([], name: name, tags: tags);
/// <summary>
/// Transfers a child Component to another Docker
/// </summary>
/// <param name="__component"> Component to move</param>
/// <param name="__componentDocker"> Docker to move component to</param>
/// <remarks> Components cannot transfer themselves with this Method!</remarks>
public void Move(Component __component, ComponentDocker __componentDocker) {
//This allows self transfer behavior while preserving Docker's actual job, Before all other statements to prevent Double-Debugging.
if (__component == this) { __component.ComponentDocker.Move(__component, __componentDocker); return; }
if (__component == null) {
Debug.LogError("Component is null!", ["CurrentDocker", "NewDocker"],
[GetHashCode().ToString(), __componentDocker.GetHashCode().ToString()]); return; }
if (!_Components.Contains(__component)) {
Debug.LogError("Docker does not have ownership of Component", ["Component", "Type", "CurrentDocker", "NewDocker"],
[__component.GetHashCode().ToString(), __component.GetType().ToString(), GetHashCode().ToString(), __componentDocker.GetHashCode().ToString()]); return; }
//Update docker lists
__componentDocker._Components.Add(__component);
_Components.Remove(__component);
//Update components parent
__component.ComponentDocker = __componentDocker;
}
/// <summary>
/// Transfers the first found Component of a specific type to another Docker
/// </summary>
/// <param name="__componentDocker"> Docker to move component to</param>
/// <typeparam name="__Type"> Type of component</typeparam>
public void Move<__Type>(ComponentDocker __componentDocker) where __Type : Component => Move(Get<__Type>(), __componentDocker);
/// <summary>
/// Transfers all Components in a list to another Docker.
/// </summary>
/// <param name="__Components"> List of Components to transfer</param>
/// <param name="__componentDocker"> Docker to move Component to</param>
public void MoveAll(IEnumerable<Component> __Components, ComponentDocker __componentDocker) { foreach (Component Component in (Component[])[..__Components]) Move(Component, __componentDocker); }
/// <summary>
/// Transfers all Components of a type to another Docker.
/// </summary>
/// <param name="__componentDocker"> Target Docker</param>
/// <typeparam name="__Type"> Type of Components to transfer</typeparam>
public void MoveAll<__Type>(ComponentDocker __componentDocker) where __Type : Component => MoveAll(GetAll<__Type>(), __componentDocker);
@@ -224,13 +123,9 @@ public abstract class ComponentDocker
/// /// <summary>
/// Holds Components at Keys of their tags.
/// </summary>
internal Dictionary<string, SortedSet<Component>> _taggedComponents = [];
@@ -463,97 +358,33 @@ public abstract class ComponentDocker
/// <summary>
/// Returns a bool based on if the Docker contains a Component with the given tag or not
/// </summary>
/// <param name="__tag"></param>
/// <returns></returns>
public bool Contains(string __tag) => _taggedComponents.ContainsKey(__tag);
/// <summary>
/// Returns a bool based on if the Docker contains a Component of that type or not
/// </summary>
/// <typeparam name="__Type">Type of the Component</typeparam>
/// <returns></returns>
public bool Contains<__Type>() where __Type : Component => _Components.Any(x => x is __Type);
/// <summary>
/// Returns a bool based on if the current __Component is owned by this Docker
/// </summary>
/// <param name="__component"></param>
/// <returns></returns>
public bool Contains(Component __component) => _Components.Contains(__component);
/// <summary>
/// Destroys a Component attached to docker
/// </summary>
/// <param name="__component"></param>
public void Remove(Component __component) {
//Component is null
if (__component == null) {
Debug.LogError("Component is null", ["CurrentDocker"],
[GetHashCode().ToString()]); return;
}
private void AddComponentToLists(Component __component) {
var Type = __component.GetType();
_Components.Add(__component);
if (!_ComponentDictionary.TryAdd(Type, [__component])) _ComponentDictionary[Type].Add(__component);
for(var i = 0; i < __component.Tags.Length; i++) { HashTaggedComponent(__component.Tags[i], __component); }
//Docker doesn't have Component
if (!_Components.Contains(__component)) {
Debug.LogError("Docker does not have ownership of Component", ["Component", "Type", "CurrentDocker"],
[__component.GetHashCode().ToString(), __component.GetType().ToString(), GetHashCode().ToString()]); return;
}
__component.TryEvent(5);
__component.ChainEvent(5);
foreach (string tag in __component._tags) UnhashTaggedComponent(__component, tag);
__component.ComponentDocker = null;
_Components.Remove(__component);
} }
/// <summary>
/// Destroys the first found Component of a given type
/// </summary>
/// <typeparam name="__Type"> Type of Component to destroy</typeparam>
public void Remove<__Type>() where __Type : Component => Remove(Get<__Type>());
private void RemoveComponentFromLists(Component __component) {
var Type = __component.GetType();
_Components.Remove(__component);
if(!_ComponentDictionary.ContainsKey(Type)) _ComponentDictionary[Type].Remove(__component);
for(var i = 0; i < __component.Tags.Length; i++) { UnhashTaggedComponent(__component.Tags[i], __component); }
}
private void HashTaggedComponent(string __tag, Component __component) {
if (!_taggedComponents.TryAdd(__component.Tags[i], [__component]))
_taggedComponents[__component.Tags[i]].Add(__component);
}
/// <summary> private void UnhashTaggedComponent(string __tag, Component __component) {
/// Destroys all Components from a given collection. if(!_taggedComponents.ContainsKey(__tag)) _taggedComponents[__tag].Remove(__component);
/// </summary> }
/// <param name="__Components"></param>
public void RemoveAll(IEnumerable<Component> __Components) { foreach (Component component in (Component[])[..__Components]) { Remove(component); } }
/// <summary>
/// Destroys all Components of a given type
/// </summary>
/// <typeparam name="__Type"></typeparam>
public void RemoveAll<__Type>() where __Type : Component => RemoveAll(GetAll<__Type>());
/// <summary>
/// Destroys all Components attached to Docker
/// </summary>
public void RemoveAll() { foreach (Component component in (Component[])[.._Components]) { Remove(component); } }
} }

View File

@@ -0,0 +1,32 @@
namespace AwperativeKernel;
public abstract partial class ComponentDocker
{
/// <summary>
/// Returns a bool based on if the Docker contains a Component with the given tag or not
/// </summary>
/// <param name="__tag"></param>
/// <returns></returns>
public bool Contains([NotNull] string __tag) => NotNull.VerifyOrThrow(__tag) && _taggedComponents.ContainsKey(__tag);
/// <summary>
/// Returns a bool for if the Docker contains a Component of that type or not
/// </summary>
/// <typeparam name="__Type">Type of the Component</typeparam>
public bool Contains<__Type>() where __Type : Component => _ComponentDictionary.ContainsKey(typeof(__Type));
/// <summary>
/// Returns a bool based on if the current __Component is owned by this Docker
/// </summary>
/// <param name="__component"></param>
/// <returns></returns>
public bool Contains([ComponentNotNull,DockerOwns] Component __component) => NotNull.VerifyOrThrow(__component) && DockerOwns.VerifyOrThrow(this, __component) && _Components.Contains(__component);
}

View File

@@ -0,0 +1,189 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics.CodeAnalysis;
namespace AwperativeKernel;
public abstract partial class ComponentDocker
{
/// <summary>
/// Adds a previously instantiated Component to the Docker
/// </summary>
/// <param name="__component">The Component to add</param>
/// <remarks> This is NOT meant to transfer a Component from one docker to another (Please use Move() for that).
/// And If you are just instantiating an Empty Component, also consider instead using Add&lt;Type&gt;();</remarks>
/// <author> Avery Norris</author>
#nullable enable
public void Add([ComponentNotNull,OrphanComponent] Component __component) {
if(!ComponentNotNull.VerifyOrThrow(__component)) return;
if(!OrphanComponent.VerifyOrThrow(__component)) return;
//Component has already been added to another docker
if (__component.ComponentDocker != null) { Debug.LogError("You cannot use add if the Component already belongs to a Docker, use Component.Transfer();"); return; }
InitiateComponent(__component);
}
/// <summary>
/// Add a new Component to the Docker; and returns a reference to it!
/// </summary>
/// <typeparam name="__Type"> Type of Component to instantiate</typeparam>
/// <remarks>Component cannot have a Constructor</remarks>
/// <author> Avery Norris</author>
public __Type Add<__Type>() where __Type : Component, new() { Component newComponent = new __Type(); InitiateComponent(newComponent); return (__Type)newComponent; }
/// <summary>
/// Add a new Component to the Docker; and returns a reference to it!
/// </summary>
/// <typeparam name="__Type"> Type of Component to instantiate</typeparam>
/// <remarks>Component cannot have a Constructor</remarks>
/// <author> Avery Norris</author>
public __Type Add<__Type>(string name = null, int priority = 0, Collection<string> tags = null) where __Type : Component, new() {
Component newComponent = new __Type();
newComponent.Name = name ??= typeof(__Type).Name;
newComponent._tags = [..tags ??= []];
newComponent._priority = priority;
InitiateComponent(newComponent); return (__Type)newComponent;
}
/// <summary>
/// Sets important Component variables; and tries to send the Create() event.
/// </summary>
/// <param name="__component"></param>
/// <typeparam name="__Type"></typeparam>
private void InitiateComponent(Component __component) {
//add to Component Docker's lists
AddComponentToLists(__component);
__component.ComponentDocker = this;
//create event
__component.TryEvent(4); __component.ChainEvent(4);
}
/// <summary>
/// Transfers a Component to another Docker
/// </summary>
/// <param name="__component"> Component to move</param>
/// <param name="__componentDocker"> Docker to move component to</param>
/// <remarks> Components cannot transfer themselves with this Method!</remarks>
public void Move([ComponentNotNull,DockerOwns] Component __component, [DockerNotNull,DifferentDocker] ComponentDocker __componentDocker) {
if(!ComponentNotNull.VerifyOrThrow(__component)) return;
if(!DockerOwns.VerifyOrThrow(this, __component)) return;
if(!DockerNotNull.VerifyOrThrow(__componentDocker)) return;
if(!DifferentDocker.VerifyOrThrow(this, __componentDocker)) return;
if (!Contains(__component)) {
Debug.LogError("Docker does not have ownership over Component!", ["ComponentType"], [__component.GetType().Name]); return;
}
if (__componentDocker == this) {
Debug.LogError("Docker already has Component!", ["ComponentType"], [__component.GetType().Name]); return;
}
var type = __component.GetType();
//Modify collections on both Dockers
RemoveComponentFromLists(__component);
__componentDocker.AddComponentToLists(__component);
__component.ComponentDocker = __componentDocker;
}
/// <summary>
/// Transfers the first found Component of a specific type to another Docker
/// </summary>
/// <param name="__componentDocker"> Docker to move the Component to</param>
/// <typeparam name="__Type"> Type of component</typeparam>
public void Move<__Type>([DockerNotNull,DifferentDocker] ComponentDocker __componentDocker) where __Type : Component => Move(Get<__Type>(), __componentDocker);
/// <summary>
/// Transfers all Components in a collection to another Docker.
/// </summary>
/// <param name="__Components"> The Components that need to be transferred</param>
/// <param name="__componentDocker"> Docker to move Component to</param>
public void MoveAll([ComponentNotNull,DockerOwns] IEnumerable<Component> __Components, [DockerNotNull,DifferentDocker] ComponentDocker __componentDocker) { foreach (Component Component in (Component[])[..__Components]) Move(Component, __componentDocker); }
/// <summary>
/// Transfers all Components of a type to another Docker.
/// </summary>
/// <param name="__componentDocker"> Target Docker</param>
/// <typeparam name="__Type"> Type of Components to transfer</typeparam>
public void MoveAll<__Type>([DockerNotNull, DifferentDocker] ComponentDocker __componentDocker) where __Type : Component => MoveAll(GetAll<__Type>(), __componentDocker);
/// <summary>
/// Destroys a Component attached to the Docker
/// </summary>
/// <param name="__component"></param>
public void Destroy([ComponentNotNull,DockerOwns] Component __component) {
if(!ComponentNotNull.VerifyOrThrow(__component)) return;
if(!DockerOwns.VerifyOrThrow(this, __component)) return;
__component.TryEvent(5);
__component.ChainEvent(5);
RemoveComponentFromLists(__component);
__component.ComponentDocker = null;
__component.Dispose();
}
/// <summary>
/// Destroys the first found Component of a given type
/// </summary>
/// <typeparam name="__Type"> Type of Component to destroy</typeparam>
public void Destroy<__Type>() where __Type : Component => Destroy(Get<__Type>());
/// <summary>
/// Destroys all Components from a given collection.
/// </summary>
/// <param name="__Components"></param>
public void DestroyAll([ComponentNotNull, DockerOwns] Collection<Component> __Components) { for (var i = 0; i < __Components.Count; i++) Destroy(__Components[i]); }
/// <summary>
/// Destroys all Components of a given type
/// </summary>
/// <typeparam name="__Type"></typeparam>
public void DestroyAll<__Type>() where __Type : Component => DestroyAll(GetAll<__Type>());
/// <summary>
/// Destroys all Components attached to Docker
/// </summary>
public void DestroyAll() { for(var i = 0; i < _Components.Count; i++) Destroy(_Components[i]); }
}

View File

@@ -146,15 +146,17 @@ public static class Debug
/// </summary> /// </summary>
/// <param name="__message"> Message to debug</param> /// <param name="__message"> Message to debug</param>
public static void LogError(string __message) => LogGeneric(__message, "ERR", [], []); public static void LogError(string __message) => LogGeneric(__message, "ERR", [], []);
/// <summary> /// <summary>
/// Writes the current message to the log file. With any given call sign. /// Writes the current message to the log file. With any given call sign.
/// </summary> /// </summary>
/// <param name="__message"> Message to debug</param> /// <param name="__message"> Message to debug</param>
/// <param name="__parameters"> Names of values to debug</param> /// <param name="__parameters"> Names of values to debug</param>
/// <param name="__values"> Values to debug</param> /// <param name="__values"> Values to debug</param>
public static void LogError(string __message, string[] __parameters, string[] __values) => LogGeneric(__message, "ERR", __parameters, __values); public static void LogError(string __message, string[] __parameters, string[] __values) {
if(Awperative.DebugErrors) LogGeneric(__message, "ERR", __parameters, __values, Awperative.ThrowExceptions);
}
/// <summary> /// <summary>
/// Writes the current message to the log file if the condition is true. /// Writes the current message to the log file if the condition is true.
/// </summary> /// </summary>
@@ -173,11 +175,14 @@ public static class Debug
/// <param name="__callSign"> Message identifier</param> /// <param name="__callSign"> Message identifier</param>
/// <param name="__parameters"> Names of values to debug</param> /// <param name="__parameters"> Names of values to debug</param>
/// <param name="__values"> Values to debug</param> /// <param name="__values"> Values to debug</param>
public static void LogGeneric(string __message, string __callSign, string[] __parameters, string[] __values) { /// <param name="__exception"> Should this throw an exception instead</param>
public static void LogGeneric(string __message, string __callSign, string[] __parameters, string[] __values, bool __exception = false) {
string output = "\n\n" + __callSign + "- \"" + __message + "\"\n STK-" + new StackTrace(); string output = "\n\n" + __callSign + "- \"" + __message + "\"\n STK-" + new StackTrace();
for (int i = 0; i < __parameters.Length || i < __values.Length; i++) for (int i = 0; i < __parameters.Length || i < __values.Length; i++)
output += "\n " + __parameters[i] + "- " + __values[i]; output += "\n " + __parameters[i] + "- " + __values[i];
if (__exception) throw new Exception(output);
File.AppendAllText(LogFilePath, output); File.AppendAllText(LogFilePath, output);
} }

View File

@@ -2,7 +2,9 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Immutable; using System.Collections.Immutable;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Diagnostics.CodeAnalysis;
using System.Linq; using System.Linq;
using System.Linq.Expressions;
using System.Reflection; using System.Reflection;
@@ -44,6 +46,7 @@ public static class Awperative
public static bool DebugMode = false; public static bool DebugMode = false;
@@ -111,22 +114,37 @@ public static class Awperative
foreach (Type type in Assembly.GetCallingAssembly().GetTypes()) { foreach (Type type in Assembly.GetCallingAssembly().GetTypes()) {
if (type.IsSubclassOf(typeof(Component))) { if (type.IsSubclassOf(typeof(Component))) {
Action<Component>[] timeEvents = new Action<Component>[ComponentEvents.Count];
byte eventProfile = 0; byte eventProfile = 0;
List<string> debugProfile = []; List<string> debugProfile = [];
for(int i = 0; i < ComponentEvents.Count; i++) { for(int i = 0; i < ComponentEvents.Count; i++) {
if (type.GetMethod(ComponentEvents[i]) != null) { MethodInfo eventMethod = type.GetMethod(ComponentEvents[i]);
eventProfile |= (byte)(1 << i);
if (eventMethod != null) {
debugProfile.Add(ComponentEvents[i]); debugProfile.Add(ComponentEvents[i]);
}
var ComponentInstanceParameter = Expression.Parameter(typeof(Component), "__component");
var Casting = Expression.Convert(ComponentInstanceParameter, type);
var Call = Expression.Call(Casting, eventMethod);
var Lambda = Expression.Lambda<Action<Component>>(Call, ComponentInstanceParameter);
timeEvents[i] = Lambda.Compile();
} else timeEvents[i] = null;
} }
Debug.LogAction("Evaluated Component! ", ["Type", "Time Events", "Profile"], [type.Name, "[" + string.Join(", ", debugProfile.Select(x => x.ToString())) + "]", eventProfile.ToString()]); Debug.LogAction("Evaluated Component! ", ["Type", "Time Events", "Profile"], [type.Name, "[" + string.Join(", ", debugProfile.Select(x => x.ToString())) + "]", eventProfile.ToString()]);
_TypeAssociatedTimeEvents.Add(type, eventProfile); _TypeAssociatedTimeEvents.Add(type, timeEvents);
} }
} }
} }
@@ -134,6 +152,7 @@ public static class Awperative
/// <summary> /// <summary>
/// Starts Awperative up! This method runs forever. /// Starts Awperative up! This method runs forever.
/// </summary> /// </summary>
[DoesNotReturn]
public static void Run() { public static void Run() {
Base = new Base(); Base = new Base();
Base.Run(); Base.Run();
@@ -158,5 +177,30 @@ public static class Awperative
/// List of all type of components and the associated time events /// List of all type of components and the associated time events
/// Each event is a 0 or 1 based on true or false, stored at their index in the byte /// Each event is a 0 or 1 based on true or false, stored at their index in the byte
/// </summary> /// </summary>
internal static Dictionary<Type, byte> _TypeAssociatedTimeEvents = []; internal static Dictionary<Type, Action<Component>[]> _TypeAssociatedTimeEvents = [];
public static SafetyLevel safetyLevel {
get => _safetyLevel;
set {
ThrowExceptions = value is SafetyLevel.Extreme;
IgnoreErrors = value is SafetyLevel.Low or SafetyLevel.None;
DebugErrors = value is not SafetyLevel.None;
_safetyLevel = value;
}
} private static SafetyLevel _safetyLevel;
public static bool ThrowExceptions { get; private set; } = false;
public static bool IgnoreErrors { get; private set; } = false;
public static bool DebugErrors { get; private set; } = true;
//What to do if there is an error, keep in mind low and none still can have errors, because you are turning off validation checking
public enum SafetyLevel {
Extreme, //Throw exceptions and stop the whole program
Normal, //Just debug it to the console, and halt current process
Low, //Push through tasks but debug error
None, //Ignore most/all errors and do not debug it,
}
} }

View File

@@ -13,7 +13,7 @@ using System.Reflection;
[assembly: System.Reflection.AssemblyCompanyAttribute("AwperativeKernel")] [assembly: System.Reflection.AssemblyCompanyAttribute("AwperativeKernel")]
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] [assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+32fdae32482131f6e177956aee0f9ddcdf9877cf")] [assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+abd47153ad47e5c2d5300dcab27ac4628f468ab1")]
[assembly: System.Reflection.AssemblyProductAttribute("AwperativeKernel")] [assembly: System.Reflection.AssemblyProductAttribute("AwperativeKernel")]
[assembly: System.Reflection.AssemblyTitleAttribute("AwperativeKernel")] [assembly: System.Reflection.AssemblyTitleAttribute("AwperativeKernel")]
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]

View File

@@ -1 +1 @@
22a4163440a667e1fc9f683e846ca5e0db424c2a4e8629dde601d67fa1038af8 8e04a8f03c26d3cf7cdf50da4979193904b566d6f40392f132e749a5bd9092b9

View File

@@ -1 +1 @@
1492481e4eae3b80db2d149ab088600d21214f29161b6bc87c6dbab466600b9b e4b135c3045a438e4953bde74a036a568da5652715efda203daab787973e7f7e