NEARLY THERE

This commit is contained in:
2026-03-01 19:28:14 -05:00
parent 41dbab5ce3
commit daff25af55
24 changed files with 688 additions and 857 deletions

View File

@@ -1,6 +1,5 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel;
namespace AwperativeKernel; namespace AwperativeKernel;
@@ -30,6 +29,7 @@ public static class DebugAttributes
/// <summary> Returns true or false based on the given condition from the attribute, unless Debug.IgnoreErrors is true, in which it will always return true, but still try to throw errors. </summary> /// <summary> Returns true or false based on the given condition from the attribute, unless Debug.IgnoreErrors is true, in which it will always return true, but still try to throw errors. </summary>
/// <usage> It is required to use VerifyOrThrow() to validate important conditions for methods within the kernel. You may also feel free to use this outside in any modules or games. /// <usage> It is required to use VerifyOrThrow() to validate important conditions for methods within the kernel. You may also feel free to use this outside in any modules or games.
/// It is easiest to use VerifyOrThrow like : (In your method) if(!Attribute.VerifyOrThrow()) return; That way the attribute can exit the code if the condition is false.</usage> /// It is easiest to use VerifyOrThrow like : (In your method) if(!Attribute.VerifyOrThrow()) return; That way the attribute can exit the code if the condition is false.</usage>
[MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.Medium), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.ON)]
public static bool VerifyOrThrow(ComponentDocker __docker, Component __component) { public static bool VerifyOrThrow(ComponentDocker __docker, Component __component) {
if (__docker.Contains(__component)) return true; if (__docker.Contains(__component)) return true;
@@ -56,6 +56,7 @@ public static class DebugAttributes
/// <inheritdoc cref="DockerOwns.VerifyOrThrow"/> /// <inheritdoc cref="DockerOwns.VerifyOrThrow"/>
[MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.Medium), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.ON)]
public static bool VerifyOrThrow(ComponentDocker __docker, Component __component) { public static bool VerifyOrThrow(ComponentDocker __docker, Component __component) {
if (!__docker.Contains(__component)) return true; if (!__docker.Contains(__component)) return true;
@@ -82,6 +83,7 @@ public static class DebugAttributes
/// <inheritdoc cref="DockerOwns.VerifyOrThrow"/> /// <inheritdoc cref="DockerOwns.VerifyOrThrow"/>
[MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.O1)]
public static bool VerifyOrThrow(Component __component) { public static bool VerifyOrThrow(Component __component) {
if (__component.ComponentDocker == null) return true; if (__component.ComponentDocker == null) return true;
@@ -108,6 +110,7 @@ public static class DebugAttributes
/// <inheritdoc cref="DockerOwns.VerifyOrThrow"/> /// <inheritdoc cref="DockerOwns.VerifyOrThrow"/>
[MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.O1)]
public static bool VerifyOrThrow(ComponentDocker __docker, ComponentDocker __other) { public static bool VerifyOrThrow(ComponentDocker __docker, ComponentDocker __other) {
if (!__docker.Equals(__other)) return true; if (!__docker.Equals(__other)) return true;
@@ -130,6 +133,7 @@ public static class DebugAttributes
/// <inheritdoc cref="DockerOwns.VerifyOrThrow"/> /// <inheritdoc cref="DockerOwns.VerifyOrThrow"/>
[MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.O1)]
public static bool VerifyOrThrow(Component __component) { public static bool VerifyOrThrow(Component __component) {
if (__component != null) return true; if (__component != null) return true;
@@ -148,6 +152,7 @@ public static class DebugAttributes
/// <inheritdoc cref="DockerOwns.VerifyOrThrow"/> /// <inheritdoc cref="DockerOwns.VerifyOrThrow"/>
[MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.O1)]
public static bool VerifyOrThrow(ComponentDocker __componentDocker) { public static bool VerifyOrThrow(ComponentDocker __componentDocker) {
if (__componentDocker != null) return true; if (__componentDocker != null) return true;
@@ -166,6 +171,7 @@ public static class DebugAttributes
/// <inheritdoc cref="DockerOwns.VerifyOrThrow"/> /// <inheritdoc cref="DockerOwns.VerifyOrThrow"/>
[MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.O1)]
public static bool VerifyOrThrow(Scene __scene) { public static bool VerifyOrThrow(Scene __scene) {
if (__scene != null) return true; if (__scene != null) return true;

View File

@@ -4,30 +4,66 @@ using System;
namespace AwperativeKernel; namespace AwperativeKernel;
/// <summary>
/// Provides many handy cosmetic attributes for methods to specify use cases or provide information.
/// </summary>
/// <author> Avery Norris </author>
public static class MarkerAttributes public static class MarkerAttributes
{ {
/// <summary> /// <summary> 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).
/// 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, /// 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 /// it is because all the exposing public methods already check, and double checks would only slow me down </summary>
/// </summary>
[AttributeUsage(AttributeTargets.All)] [AttributeUsage(AttributeTargets.All)]
public class UnsafeInternal : Attribute { } public class UnsafeInternal : Attribute { }
/// <summary> /// <summary> Shows that the given object is calculated every time it is called! Good to know for performance heavy systems. </summary>
/// Shows that the given object (meant for external use) is calculated every time it is called! Good to know for performance heavy systems.
/// </summary>
[AttributeUsage(AttributeTargets.All)] [AttributeUsage(AttributeTargets.All)]
public class CalculatedProperty() : Attribute { } public class CalculatedProperty : Attribute { }
/// <summary> /// <summary> Just a way to write how expensive a calculated property or method can be. </summary>
/// Just a way to write how expensive a calculated property can be.
/// </summary>
[AttributeUsage(AttributeTargets.All)] [AttributeUsage(AttributeTargets.All)]
public class CalculatedPropertyExpense(string Expense) : Attribute { } public class Expense(Expense.ExpenseLevel __expense) : Attribute
{
public enum ExpenseLevel {
None,
VeryLow,
Low,
Medium,
High,
VeryHigh,
}
public ExpenseLevel expense = __expense;
}
/// <summary> Just a way to write the time complexity of a calculated property or method. </summary>
[AttributeUsage(AttributeTargets.All)]
public class Complexity(Complexity.TimeComplexity __complexity) : Attribute
{
public enum TimeComplexity
{
O1,
OLogN,
ON,
ONLogN,
ON2,
ON3
}
public TimeComplexity complexity = __complexity;
}
/// <summary> Shows that the given method does not actually belong to the object, but instead just calls a lambda to another method. </summary>
[AttributeUsage(AttributeTargets.All)]
public class MethodPointer : Attribute { }
} }

View File

@@ -1,32 +1,26 @@
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Immutable;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using Microsoft.VisualBasic;
namespace AwperativeKernel; namespace AwperativeKernel;
/// <summary>
/// The backing class for components in Awperative; provides access to a few important methods, and inheriting this is required to receive time based events.
/// When Start() is called, Awperative reflectively analyzes all classes that inherits component, and checks for given events. See the wiki for more information!
/// </summary>
/// <author> Avery Norris </author>
public abstract partial class Component : ComponentDocker public abstract partial class Component : ComponentDocker
{ {
/// <summary> Current parent of the Component. Can be either Scene or another Component.</summary> /// <summary> Current parent of the Component. Can be either a Scene or another Component.</summary>
[MarkerAttributes.UnsafeInternal] [MarkerAttributes.UnsafeInternal]
public ComponentDocker ComponentDocker { get; set; } = null; public ComponentDocker ComponentDocker { get; internal set; } = null;
/// <summary> /// <summary> Component's name </summary>
/// Component name [DebugAttributes.NotNull]
/// </summary>
[NotNull]
public string Name { public string Name {
get => _name; get => _name;
set { if (!DebugAttributes.NotNull.VerifyOrThrow(value)) return; _name = value; } set { if (!DebugAttributes.NotNull.VerifyOrThrow(value)) return; _name = value; }
@@ -34,19 +28,19 @@ public abstract partial class Component : ComponentDocker
/// <summary> Represents the state of this Component, The largest bit represents if the Component is enabled or not, while the /// <summary> Represents the state of this Component, The largest bit represents if the Component is enabled or not, while the
/// next 7 represent its priority </summary> /// next 7 represent its priority like so : (Enabled -> 0 | Priority -> 0000000) </summary>
[MarkerAttributes.UnsafeInternal] [MarkerAttributes.UnsafeInternal]
private byte OrderProfile; private byte OrderProfile;
/// <summary> If the component receives time events or not. </summary> /// <summary> If the component receives time events or not. </summary>
[MarkerAttributes.CalculatedProperty, MarkerAttributes.CalculatedPropertyExpense("Very Low")] [MarkerAttributes.CalculatedProperty, MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.O1)]
public bool Enabled { public bool Enabled {
get => (OrderProfile & 128) > 0; get => (OrderProfile & 128) > 0;
set => OrderProfile = (byte)((OrderProfile & 127) | (value ? 128 : 0)); set => OrderProfile = (byte)((OrderProfile & 127) | (value ? 128 : 0));
} }
/// <summary> Represents the Component's Update priority, can be set to any value ranging from -64 to 63; otherwise an error will throw! </summary> /// <summary> Represents the Component's Update priority; higher priorities get updated first. Can be any integer in the range -64 -> 63. </summary>
[MarkerAttributes.CalculatedProperty, MarkerAttributes.CalculatedPropertyExpense("Very Low")] [MarkerAttributes.CalculatedProperty, MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.O1)]
public int Priority { public int Priority {
get => (sbyte)(OrderProfile << 1) >> 1; get => (sbyte)(OrderProfile << 1) >> 1;
set { set {
@@ -55,62 +49,46 @@ public abstract partial class Component : ComponentDocker
ComponentDocker.UpdatePriority(this, value); ComponentDocker.UpdatePriority(this, value);
} }
} }
/// <summary>
/// Attempts to send an Event to the Component, terminates if the Component does not have the given Event /// <summary> A list of all tags belonging to the component. Use AddTag() to modify it.</summary>
/// </summary> public IReadOnlySet<string> Tags => _tags;
/// <param name="__timeEvent">Type of Event</param> [MarkerAttributes.UnsafeInternal] internal HashSet<string> _tags = [];
/// <summary> Attempts to send an event to the component, and quietly exits if not.</summary>
[MarkerAttributes.UnsafeInternal] [MarkerAttributes.UnsafeInternal]
internal void TryEvent(int __timeEvent) { internal void TryEvent(int __timeEvent) {
Awperative._TypeAssociatedTimeEvents[GetType()][__timeEvent]?.Invoke(this); Awperative._TypeAssociatedTimeEvents[GetType()][__timeEvent]?.Invoke(this);
} }
/// <summary>
/// Identifiers for Components.
/// </summary>
public IReadOnlyList<string> Tags => [.._tags];
[MarkerAttributes.UnsafeInternal] internal HashSet<string> _tags = [];
/// <summary> Adds a new tag to the component</summary>
[MarkerAttributes.CalculatedProperty, MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.Low), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.ON)]
public void AddTag([DebugAttributes.NotNull, DebugAttributes.CollectionDoesntContain] string __tag) {
/// <summary>
/// Adds a new tag to the Component
/// </summary>
/// <param name="__tag"> The tag to add</param>
public void AddTag([DebugAttributes.NotNull, DebugAttributes.CollectionDoesntContain] string __tag)
{
if(!DebugAttributes.NotNull.VerifyOrThrow(__tag)) return; if(!DebugAttributes.NotNull.VerifyOrThrow(__tag)) return;
if(!DebugAttributes.CollectionDoesntContain.VerifyOrThrow(__tag, _tags)) return; if(!DebugAttributes.CollectionDoesntContain.VerifyOrThrow(__tag, _tags)) return;
_tags.Add(__tag); _tags.Add(__tag);
ComponentDocker.AddTagToComponent(__tag, this); ComponentDocker.HashTaggedComponent(__tag, this);
} }
/// <summary> /// <summary> Removes a tag from the component.</summary>
/// Adds a new tag to the Component [MarkerAttributes.CalculatedProperty, MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.Low), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.ON)]
/// </summary> public void RemoveTag([DebugAttributes.NotNull,DebugAttributes.CollectionContains] string __tag) {
/// <param name="__tag"> The tag to add</param>
public void RemoveTag([DebugAttributes.NotNull,DebugAttributes.CollectionContains] string __tag)
{
if (!DebugAttributes.NotNull.VerifyOrThrow(__tag)) return; if (!DebugAttributes.NotNull.VerifyOrThrow(__tag)) return;
if(!DebugAttributes.CollectionContains.VerifyOrThrow(__tag, _tags)) return; if(!DebugAttributes.CollectionContains.VerifyOrThrow(__tag, _tags)) return;
_tags.Remove(__tag); _tags.Remove(__tag);
ComponentDocker.RemoveTagFromComponent(__tag, this); ComponentDocker.UnhashTaggedComponent(__tag, this);
} }
/// <summary> Just gives the Component's name. But makes debugging a little easier :).</summary>
public override string ToString() { public override string ToString() {
return this.Name; return this.Name;
} }

View File

@@ -0,0 +1,50 @@
using System.Collections.Generic;
namespace AwperativeKernel;
public abstract partial class Component
{
/// <summary> Scene the Component resides in. To save ram it's not stored but calculated on the fly. </summary>
[MarkerAttributes.CalculatedProperty, MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.Medium), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.ON)]
public Scene Scene => __QueryScene();
private Scene __QueryScene() {
if (ComponentDocker is Scene scene) return scene;
if (ComponentDocker is Component Component) return Component.__QueryScene();
return null;
}
/// <summary> Returns the Parent Component. Will be null if the Component's parent is a Scene. </summary>
[MarkerAttributes.CalculatedProperty, MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.O1)]
public Component Parent => __QueryParent();
private Component __QueryParent() {
if (ComponentDocker is Component Component)
return Component;
return null;
}
/// <summary> All parent Components and the parents of the parents up until the Scene. Will only list parents of parents, not uncle Components. And will not list the Scene </summary>
[MarkerAttributes.CalculatedProperty, MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.Medium), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.ON)]
public IEnumerable<Component> AllParents => __QueryComponents();
private IEnumerable<Component> __QueryComponents() {
List<Component> returnValue = [];
ComponentDocker currentComponentDocker = ComponentDocker;
while (currentComponentDocker is not AwperativeKernel.Scene) {
if (currentComponentDocker is Component Component) {
returnValue.Add(Component);
currentComponentDocker = Component.ComponentDocker;
}
}
return returnValue;
}
}

View File

@@ -1,52 +0,0 @@
using System.Collections.Generic;
namespace AwperativeKernel;
public abstract partial class Component
{
/// <summary>
/// Scene the Component resides in.
/// </summary>
[CalculatedProperty, CalculatedPropertyExpense("Medium: O(Parents)")]
public Scene Scene => __QueryScene();
private Scene __QueryScene() {
if (ComponentDocker is Scene scene) return scene;
if (ComponentDocker is Component Component) return Component.__QueryScene();
return null;
}
/// <summary>
/// Returns the Parent Component. Will be null if the Component is at the base of a scene.
/// </summary>
[CalculatedProperty, CalculatedPropertyExpense("Very Low O(1)")]
public Component Parent => __QueryParent();
private Component __QueryParent() {
if (ComponentDocker is Component Component)
return Component;
return null;
}
/// <summary>
/// All parent Components and the parents of the parents up until the Scene. Will only list parents of parents, not uncle Components.
/// </summary>
[CalculatedProperty, CalculatedPropertyExpense("Medium O(Parents)")]
public IReadOnlyList<Component> AllParents => __QueryComponents();
private IReadOnlyList<Component> __QueryComponents() {
List<Component> returnValue = [];
ComponentDocker currentComponentDocker = ComponentDocker;
while (!(currentComponentDocker is Scene))
if (currentComponentDocker is Component Component) {
returnValue.Add(Component);
currentComponentDocker = Component.ComponentDocker;
}
return [..returnValue];
}
}

View File

@@ -1,33 +1,40 @@
namespace AwperativeKernel; namespace AwperativeKernel;
public abstract partial class Component public abstract partial class Component
{ {
/// <inheritdoc cref="Awperative.CreateScene"/> /// <inheritdoc cref="Awperative.CreateScene"/>
[MarkerAttributes.MethodPointer]
public static Scene CreateScene(string __name) => Awperative.CreateScene(__name); public static Scene CreateScene(string __name) => Awperative.CreateScene(__name);
/// <inheritdoc cref="Awperative.GetScene"/> /// <inheritdoc cref="Awperative.GetScene"/>
[MarkerAttributes.MethodPointer]
public static Scene GetScene(string __name) => Awperative.GetScene(__name); public static Scene GetScene(string __name) => Awperative.GetScene(__name);
/// <inheritdoc cref="Awperative.CloseScene(AwperativeKernel.Scene)"/> /// <inheritdoc cref="Awperative.CloseScene(AwperativeKernel.Scene)"/>
[MarkerAttributes.MethodPointer]
public void RemoveScene(Scene __scene) => Awperative.CloseScene(__scene); public void RemoveScene(Scene __scene) => Awperative.CloseScene(__scene);
/// <inheritdock cref="Awperative.CloseScene(string)" /> /// <inheritdock cref="Awperative.CloseScene(string)" />
[MarkerAttributes.MethodPointer]
public void RemoveScene(string __name) => Awperative.CloseScene(__name); public void RemoveScene(string __name) => Awperative.CloseScene(__name);
/// <inheritdoc cref="ComponentDocker.Move"/> /// <inheritdoc cref="ComponentDocker.Move"/>
[MarkerAttributes.MethodPointer]
public void Move(ComponentDocker __newDocker) => ComponentDocker.Move(this, __newDocker); public void Move(ComponentDocker __newDocker) => ComponentDocker.Move(this, __newDocker);
/// <summary> Makes the Component destroy itself </summary> /// <summary> Makes the Component destroy itself </summary>
[MarkerAttributes.MethodPointer]
public void Destroy() => ComponentDocker.Destroy(this); public void Destroy() => ComponentDocker.Destroy(this);
} }

View File

@@ -0,0 +1,143 @@
using System;
using System.Collections;
using System.Collections.Generic;
namespace AwperativeKernel;
/// <summary>
/// Base class for all Awperative objects. Responsible for Managing hierarchy between Components and Scenes, has Extensive Component Manipulation Available.
/// Also transfers Time and Carries most of the responsibilities akin to the Component. NOT FOR INHERITING, please use docker by inheriting component.
/// </summary>
/// <author> Avery Norris </author>
public abstract partial class ComponentDocker : IEnumerable<Component>, IEquatable<Component>, IEquatable<ComponentDocker>, IEquatable<Scene>
{
//Blocks external inheritance
internal ComponentDocker() {}
/// <summary> Core of the Docker, holds all of the Components, sorted by update priority.</summary>
[MarkerAttributes.UnsafeInternal] internal readonly List<Component> _components = [];
/// <summary> Holds a list of Components at each of their types. This optimizes Get&lt;Type&gt; to O(1) </summary>
[MarkerAttributes.UnsafeInternal] internal readonly Dictionary<Type, HashSet<Component>> _componentTypeDictionary = new();
/// <summary> Stores a Component in a list at each of their tags. This optimizes Get(string tag) to O(1)</summary>
[MarkerAttributes.UnsafeInternal] internal readonly Dictionary<string, HashSet<Component>> _componentTagDictionary = new();
/// <summary> All children belonging to the Component. </summary>
public IEnumerable<Component> Children => _components;
/// <summary> All children and children of children until the bottom of the scene. Uses Breadth First Search. </summary>
[MarkerAttributes.CalculatedProperty, MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.High), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.ON)]
public IEnumerable<Component> AllChildren => GetAllChildren();
public IEnumerable<Component> GetAllChildren() {
List<Component> returnValue = [];
Queue<Component> queue = new(_components);
while (queue.Count > 0) {
Component current = queue.Dequeue();
returnValue.Add(current);
for (int i = 0; i < current.Count; i++) queue.Enqueue(current[i]);
}
return returnValue;
}
/// <summary>Amount of Components attached to the Docker</summary>
public int Count => _components.Count;
//Indexers to make for loops easier.
public Component this[[DebugAttributes.ValueFitsRange] int __index] {
get => !DebugAttributes.ValueFitsRange.VerifyOrThrow(__index, 0, _components.Count) ? null : _components[__index];
set { if (!DebugAttributes.ValueFitsRange.VerifyOrThrow(__index, 0, _components.Count)) return; _components[__index] = value; }
}
//Enumerators that allow convenient foreach loops.
IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); }
public IEnumerator<Component> GetEnumerator() { return new ComponentDockEnum([.._components]); }
/// <summary>Compares the Docker to another Scene.</summary>
public bool Equals(Scene __other) {
if (this is Scene scene)
return scene == __other;
return false;
}
/// <summary>Compares the Docker to another Component.</summary>
public bool Equals(Component __other) {
if (this is Component component)
return component == __other;
return false;
}
/// <summary>Compares the Docker to another Docker.</summary>
public bool Equals(ComponentDocker __other) {
return this == __other;
}
/// <summary> Resorts the component list to order of priority </summary>
[MarkerAttributes.UnsafeInternal]
internal void UpdatePriority(Component __component, int __priority) {
_components.Sort(Awperative._prioritySorter);
}
/// <summary> Sends an event to all Children and tells them to continue it. </summary>
/// <param name="__timeEvent"> Integer ID of the event to send. </param>
[MarkerAttributes.UnsafeInternal]
internal void ChainEvent(int __timeEvent) {
for (int i = 0; i < _components.Count; i++) {
_components[i].TryEvent(__timeEvent);
_components[i].ChainEvent(__timeEvent);
}
}
/// <summary> Add a Component to the Docker. </summary>
[MarkerAttributes.UnsafeInternal]
private void AddComponentToLists(Component __component) {
Type Type = __component.GetType();
_components.Add(__component);
if (!_componentTypeDictionary.TryAdd(Type, [__component])) _componentTypeDictionary[Type].Add(__component);
foreach (string tag in __component._tags) HashTaggedComponent(tag, __component);
}
/// <summary> Removes a Component from the Docker. </summary>
[MarkerAttributes.UnsafeInternal]
private void RemoveComponentFromLists(Component __component) {
Type Type = __component.GetType();
_components.Remove(__component);
if(_componentTypeDictionary.TryGetValue(Type, out HashSet<Component> value)) value.Remove(__component);
foreach (string tag in __component._tags) UnhashTaggedComponent(tag, __component);
}
/// <summary> Hashes a component in the tag dictionary </summary>
[MarkerAttributes.UnsafeInternal]
internal void HashTaggedComponent(string __tag, Component __component) {
if (!_componentTagDictionary.TryAdd(__tag, [__component]))
_componentTagDictionary[__tag].Add(__component);
}
/// <summary> Removes a component's hash from the tag dictionary </summary>
[MarkerAttributes.UnsafeInternal]
internal void UnhashTaggedComponent(string __tag, Component __component) {
if(!_componentTagDictionary.ContainsKey(__tag)) _componentTagDictionary[__tag].Remove(__component);
}
}

View File

@@ -0,0 +1,164 @@
using System.Collections.Generic;
using System.Linq;
namespace AwperativeKernel;
public abstract partial class ComponentDocker
{
/// <summary> Tells you whether the docker contains a component with the given tag </summary>
[MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.O1)]
public bool Contains([DebugAttributes.NotNull] string __tag) => DebugAttributes.NotNull.VerifyOrThrow(__tag) && _componentTagDictionary.ContainsKey(__tag);
/// <summary> Tells you whether the docker contains a component with the given type</summary>
[MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.O1)]
public bool Contains<__Type>() where __Type : Component => _componentTypeDictionary.ContainsKey(typeof(__Type));
/// <summary> Tells you whether the docker contains a component with a given type and tag</summary>
[MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.O1)]
public bool Contains<__Type>([DebugAttributes.NotNull] string __tag) where __Type : Component => DebugAttributes.NotNull.VerifyOrThrow(__tag) && GetAll<__Type>(__tag).Any();
/// <summary> Tells you whether the docker contains a component with all the given tags </summary>
[MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.O1)]
public bool Contains(IEnumerable<string> __tags) => GetAll(__tags).Any();
/// <summary> Tells you whether the docker contains a component with all the given tags and the type</summary>
[MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.O1)]
public bool Contains<__Type>(IEnumerable<string> __tags) where __Type : Component => GetAll<__Type>(__tags).Any();
/// <summary> Tells you whether the docker contains the given component.</summary>
[MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.O1)]
public bool Contains([DebugAttributes.ComponentNotNull] Component __component) => DebugAttributes.NotNull.VerifyOrThrow(__component) && _componentTypeDictionary.TryGetValue(__component.GetType(), out var components) && components.Contains(__component);
/// <summary> Finds the first component with a given Type</summary>
[MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.O1)]
public __Type Get<__Type>() where __Type : Component => _componentTypeDictionary.TryGetValue(typeof(__Type), out HashSet<Component> Components) ? (__Type)Components.FirstOrDefault() : null;
/// <summary> Tries to find the first component with a given tag, and returns false if there is none</summary>
[MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.O1)]
public bool TryGet<__Type>(out __Type __component) where __Type : Component { __component = Get<__Type>(); return __component != null; }
/// <summary> Gets all components of a given type</summary>
[MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.O1)]
public IEnumerable<__Type> GetAll<__Type>() where __Type : Component => _componentTypeDictionary.TryGetValue(typeof(__Type), out var components) ? components.OfType<__Type>().ToList() : [];
/// <summary> Tries to get all components of a given type and returns false if there are none</summary>
[MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.O1)]
public bool TryGetAll<__Type>(out IEnumerable<__Type> __components) where __Type : Component { __components = GetAll<__Type>(); return __components.Any(); }
/// <summary> Finds all components that have all the given tags</summary>
[MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.ON)]
public IEnumerable<Component> GetAll(IEnumerable<string> __tags) {
HashSet<Component> 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))
components.RemoveWhere(x => !taggedComponents.Contains(x));
return components;
}
/// <summary> Tries to find all components that have all the given tags, returns false if there are none</summary>
[MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.ON)]
public bool TryGetAll(IEnumerable<string> __tags, out IEnumerable<Component> __components)
{ __components = GetAll(__tags); return __components.Any(); }
/// <summary> Finds all Components that have the given type, and all the given tags</summary>
[MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.ON)]
public IEnumerable<__Type> GetAll<__Type>(IEnumerable<string> __tags) where __Type : Component {
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))
components.RemoveWhere(x => !taggedComponents.Contains(x as Component));
return components.ToList();
}
/// <summary> Tries to find all the components that have the given tags and type, returns false if there are none</summary>
[MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.ON)]
public bool TryGetAll<__Type>(IEnumerable<string> __tags, out IEnumerable<__Type> __components) where __Type : Component {
__components = GetAll<__Type>(__tags); return __components.Any();
}
/// <summary> Gets all the components with the given tag</summary>
[MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.O1)]
public IEnumerable<Component> GetAll(string __tag) => GetAll([__tag]);
/// <summary> Tries to get all the components with the given tag, returns false if there are none</summary>
[MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.O1)]
public bool TryGetAll(string __tag, out IEnumerable<Component> __components) { __components = GetAll(__tag); return __components.Any(); }
/// <summary> Gets all the components that have a certain type, and a certain tag</summary>
[MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.ON)]
public IEnumerable<__Type> GetAll<__Type>(string __tag) where __Type : Component => GetAll<__Type>([__tag]);
/// <summary> Tries to get all the components with a certain tag, and a type. Returns false if there are none</summary>
[MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.ON)]
public bool TryGetAll<__Type>(string __tag, out IEnumerable<__Type> __components) where __Type : Component { __components = GetAll<__Type>(__tag); return __components.Any(); }
/// <summary> Gets the first component with all the given tags</summary>
[MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.ON)]
public Component Get(IEnumerable<string> __tags) => GetAll(__tags).FirstOrDefault();
/// <summary> Tries to get the first component with all the given tags. Returns false if there are none</summary>
[MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.ON)]
public bool TryGet(IEnumerable<string> __tags, out Component __component) { __component = Get(__tags); return __component != null; }
/// <summary> Finds the first component with the given tag</summary>
[MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.O1)]
public Component Get(string __tag) => GetAll([__tag]).FirstOrDefault();
/// <summary> Tries to find the first component with the given tag, returns false if there is none</summary>
[MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.O1)]
public bool TryGet(string __tag, out Component __component) { __component = Get(__tag); return __component != null; }
/// <summary> Gets the first component with the given type and tag</summary>
[MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.ON)]
public __Type Get<__Type>(string __tag) where __Type : Component => GetAll<__Type>(__tag).FirstOrDefault();
/// <summary> Tries to get the first component with the given type and tag, returns false if there is none.</summary>
[MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.ON)]
public bool TryGet<__Type>(string __tag, out __Type __component) where __Type : Component { __component = Get<__Type>(__tag); return __component != null; }
}

View File

@@ -0,0 +1,96 @@
using System.Collections.Generic;
using System.Linq;
namespace AwperativeKernel;
public abstract partial class ComponentDocker
{
/// <summary> Moves a component belonging to the docker to another docker</summary>
public void Move([DebugAttributes.ComponentNotNull,DebugAttributes.DockerOwns] Component __component, [DebugAttributes.DockerNotNull,DebugAttributes.DifferentDocker] ComponentDocker __componentDocker) {
if(!DebugAttributes.ComponentNotNull.VerifyOrThrow(__component)) return;
if(!DebugAttributes.DockerOwns.VerifyOrThrow(this, __component)) return;
if(!DebugAttributes.DockerNotNull.VerifyOrThrow(__componentDocker)) return;
if(!DebugAttributes.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;
}
RemoveComponentFromLists(__component);
__componentDocker.AddComponentToLists(__component);
__component.ComponentDocker = __componentDocker;
}
/// <summary> Moves all components in a list to another docker</summary>
public void MoveAll([DebugAttributes.EnumeratorNotNull, DebugAttributes.DockerOwns] IEnumerable<Component> __Components, [DebugAttributes.DockerNotNull, DebugAttributes.DifferentDocker] ComponentDocker __componentDocker) {
if(!DebugAttributes.EnumeratorNotNull.VerifyOrThrow(__Components)) return;
if(!DebugAttributes.DockerNotNull.VerifyOrThrow(__componentDocker)) return;
if(!DebugAttributes.DifferentDocker.VerifyOrThrow(this, __componentDocker)) return;
foreach (Component Component in __Components) {
if(!DebugAttributes.DockerOwns.VerifyOrThrow(__componentDocker, Component)) return;
Move(Component, __componentDocker);
}
}
/// <summary> Moves the first component with a given Type</summary>
[MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.O1)]
public void Move<__Type>(ComponentDocker __componentDocker) where __Type : Component => Move(Get<__Type>(), __componentDocker);
/// <summary> Moves all components of a given type</summary>
[MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.Low), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.ON)]
public void MoveAll<__Type>(ComponentDocker __componentDocker) where __Type : Component => MoveAll(GetAll<__Type>(), __componentDocker);
/// <summary> Moves all components that have all the given tags</summary>
[MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.ON)]
public void MoveAll(IEnumerable<string> __tags, ComponentDocker __componentDocker) => MoveAll(GetAll(__tags), __componentDocker);
/// <summary> Moves all Components that have the given type, and all the given tags</summary>
[MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.ON)]
public void MoveAll<__Type>(IEnumerable<string> __tags, ComponentDocker __componentDocker) where __Type : Component => MoveAll(GetAll<__Type>(__tags), __componentDocker);
/// <summary> Moves all the components with the given tag</summary>
[MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.O1)]
public void MoveAll(string __tag, ComponentDocker __componentDocker) => MoveAll(GetAll([__tag]), __componentDocker);
/// <summary> Moves all the components that have a certain type, and a certain tag</summary>
[MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.ON)]
public void MoveAll<__Type>(string __tag, ComponentDocker __componentDocker) where __Type : Component => MoveAll(GetAll<__Type>([__tag]), __componentDocker);
/// <summary> Moves the first component with the given tag</summary>
[MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.O1)]
public void Move(string __tag, ComponentDocker __componentDocker) => Move(GetAll([__tag]).FirstOrDefault(), __componentDocker);
/// <summary> Moves the moves component with the given type and tag</summary>
[MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.ON)]
public void Move<__Type>(string __tag, ComponentDocker __componentDocker) where __Type : Component => Move(GetAll<__Type>(__tag).FirstOrDefault(), __componentDocker);
}

View File

@@ -0,0 +1,128 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
namespace AwperativeKernel;
public abstract partial class ComponentDocker
{
/// <summary> Attaches a preexisting component to the docker, this is not transferring the component, the method will throw an error if the component is already attached to a docker</summary>
[MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.Medium), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.O1)]
public void Add([DebugAttributes.ComponentNotNull,DebugAttributes.OrphanComponent] Component __component) {
if(!DebugAttributes.ComponentNotNull.VerifyOrThrow(__component)) return;
if(!DebugAttributes.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> Creates a new instance of that type of component and attaches it to the docker, and returns a reference to it.</summary>
public __Type Add<__Type>() where __Type : Component, new() { Component newComponent = new __Type(); InitiateComponent(newComponent); return (__Type)newComponent; }
/// <summary> Creates a new instance of that type of component and attaches it to the docker, and returns a reference to it.</summary>
public __Type Add<__Type>(string name = null, [DebugAttributes.ValueFitsRange] 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> Initiates a component into the docker. </summary>
[MarkerAttributes.UnsafeInternal]
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> Destroys a component attached to the Docker </summary>
/// <param name="__component"></param>
public void Destroy([DebugAttributes.ComponentNotNull,DebugAttributes.DockerOwns] Component __component) {
Stopwatch timer = Stopwatch.StartNew();
if(!DebugAttributes.ComponentNotNull.VerifyOrThrow(__component)) return;
if(!DebugAttributes.DockerOwns.VerifyOrThrow(this, __component)) return;
__component.TryEvent(5);
__component.ChainEvent(5);
RemoveComponentFromLists(__component);
__component.ComponentDocker = null;
}
/// <summary> Destroys all the components in a given list </summary>
public void DestroyAll([DebugAttributes.ComponentNotNull, DebugAttributes.DockerOwns] IEnumerable<Component> __Components) { foreach(Component component in __Components) Destroy(component); }
/// <summary> Destroys the first component with a given Type</summary>
[MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.O1)]
public void Destroy<__Type>() where __Type : Component => Destroy(Get<__Type>());
/// <summary> Destroys all components of a given type</summary>
[MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.Low), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.ON)]
public void DestroyAll<__Type>() where __Type : Component => DestroyAll(GetAll<__Type>());
/// <summary> Destroys all components that have all the given tags</summary>
[MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.ON)]
public void DestroyAll(IEnumerable<string> __tags) => DestroyAll(GetAll(__tags));
/// <summary> Destroys all Components that have the given type, and all the given tags</summary>
[MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.ON)]
public void DestroyAll<__Type>(IEnumerable<string> __tags) where __Type : Component => DestroyAll(GetAll<__Type>(__tags));
/// <summary> Destroys all the components with the given tag</summary>
[MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.O1)]
public void DestroyAll(string __tag) => DestroyAll(GetAll([__tag]));
/// <summary> Destroys all the components that have a certain type, and a certain tag</summary>
[MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.ON)]
public void DestroyAll<__Type>(string __tag) where __Type : Component => DestroyAll(GetAll<__Type>([__tag]));
/// <summary> Destroys the first component with the given tag</summary>
[MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.O1)]
public void Destroy(string __tag) => Destroy(GetAll([__tag]).FirstOrDefault());
/// <summary> Destroys the Destroys component with the given type and tag</summary>
[MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.ON)]
public void Destroy<__Type>(string __tag) where __Type : Component => Destroy(GetAll<__Type>(__tag).FirstOrDefault());
}

View File

@@ -1,168 +0,0 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
namespace AwperativeKernel;
/// <summary>
/// Base class for all Awperative objects. Responsible for Managing hierarchy between Components and Scenes, has Extensive Component Manipulation Available.
/// Also transfers Time and Carries most of the responsibilities akin to the Component.
/// </summary>
/// <remarks> Please don't inherit this. I don't know why you would</remarks>
/// <author> Avery Norris </author>
public abstract partial class ComponentDocker : IEnumerable, IEnumerable<Component>, IEquatable<Component>, IEquatable<ComponentDocker>, IEquatable<Scene>
{
//Blocks external inheritance
internal ComponentDocker() {}
/// <summary> Core of the Docker, holds all of the Components, sorted by update priority.</summary>
[UnsafeInternal] internal readonly List<Component> _components = [];
/// <summary> Holds a list of Components at each of their types. This optimizes Get&lt;Type&gt; to O(1) </summary>
[UnsafeInternal] internal readonly Dictionary<Type, HashSet<Component>> _componentTypeDictionary = new();
/// <summary> Stores a Component in a list at each of their tags. This optimizes Get(string tag) to O(1)</summary>
[UnsafeInternal] internal readonly Dictionary<string, HashSet<Component>> _componentTagDictionary = new();
//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<Component> GetEnumerator() { return new ComponentDockEnum([.._components]); }
/// <summary>Amount of Components attached to the Docker</summary>
public int Count => _components.Count;
/// <summary>Compares the Docker to another Scene.</summary>
public bool Equals(Scene __other) {
if (this is Scene scene)
return scene == __other;
return false;
}
/// <summary>Compares the Docker to another Component.</summary>
public bool Equals(Component __other) {
if (this is Component component)
return component == __other;
return false;
}
/// <summary>Compares the Docker to another Docker.</summary>
public bool Equals(ComponentDocker __other) {
return this == __other;
}
/// <summary>
/// Resorts member of Component list to match the Priority.
/// </summary>
/// <param name="__component"> Component to modify</param>
/// <param name="__priority"> New priority for Component</param>
[UnsafeInternal]
internal void UpdatePriority(Component __component, int __priority) {
_components.Sort(Awperative._prioritySorter);
}
/// <summary>
/// Sends an event to all Children and tells them to continue it.
/// </summary>
/// <param name="__timeEvent"> Type of event to send</param>
[UnsafeInternal]
internal void ChainEvent(int __timeEvent) {
for (int i = 0; i < _components.Count; i++) {
_components[i].TryEvent(__timeEvent);
_components[i].ChainEvent(__timeEvent);
}
}
/// <summary>
/// Add a Component into the lists and dictionaries.
/// </summary>
/// <param name="__component"></param>
[UnsafeInternal]
private void AddComponentToLists(Component __component) {
var Type = __component.GetType();
_components.Add(__component);
if (!_componentTypeDictionary.TryAdd(Type, [__component])) _componentTypeDictionary[Type].Add(__component);
foreach (var tag in __component._tags) AddTagToComponent(tag, __component);
}
/// <summary>
/// Removes a Component from the lists and dictionaries.
/// </summary>
/// <param name="__component"></param>
[UnsafeInternal]
private void RemoveComponentFromLists(Component __component) {
var Type = __component.GetType();
_components.Remove(__component);
if(_componentTypeDictionary.TryGetValue(Type, out var value)) value.Remove(__component);
foreach (var tag in __component._tags) RemoveTagFromComponent(tag, __component);
}
/// <summary>
/// Hashes a Component in the tag dictionary
/// </summary>
/// <param name="__tag">Tag to add</param>
/// <param name="__component">Component to add it to</param>
[UnsafeInternal]
internal void AddTagToComponent(string __tag, Component __component) {
if (!_componentTagDictionary.TryAdd(__tag, [__component]))
_componentTagDictionary[__tag].Add(__component);
}
/// <summary>
/// Unhashes a Component from the tag dictionary
/// </summary>
/// <param name="__tag">Tag to remove</param>
/// <param name="__component">Component to remove it from</param>
[UnsafeInternal]
internal void RemoveTagFromComponent(string __tag, Component __component) {
if(!_componentTagDictionary.ContainsKey(__tag)) _componentTagDictionary[__tag].Remove(__component);
}
/// <summary>
/// All children belonging to the Component.
/// </summary>
[CalculatedProperty, CalculatedPropertyExpense("Very Low")]
public IReadOnlyList<Component> Children => _components;
/// <summary>
/// All children and their children until the bottom of the scene. Uses Breadth First Search.
/// </summary>
[CalculatedProperty, CalculatedPropertyExpense("Medium O(Children)")]
public IReadOnlyList<Component> AllChildren => GetAllChildren();
public IReadOnlyList<Component> GetAllChildren() {
List<Component> targets = [.._components];
for (int i = 0; i < targets.Count; i++) targets.InsertRange(i + 1, targets[i]._components);
return [..targets];
}
}

View File

@@ -1,366 +0,0 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Collections.ObjectModel;
using System.Linq;
using System.Runtime.CompilerServices;
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) && _componentTagDictionary.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
=> _componentTypeDictionary.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] Component __component)
=> NotNull.VerifyOrThrow(__component) && _componentTypeDictionary.TryGetValue(__component.GetType(), out var components) && components.Contains(__component);
/// <summary>
/// Finds all Components that have all the given tags
/// </summary>
/// <param name="__tags"></param>
/// <returns></returns>
public bool Contains<__Type>([NotNull] string __tag)
=> NotNull.VerifyOrThrow(__tag) && GetAll<__Type>(__tag).Any();
/// <summary>
/// Finds all Components that have all the given tags
/// </summary>
/// <param name="__tags"></param>
/// <returns></returns>
public bool Contains(IList<string> __tags) {
return GetAll(__tags).Any();
}
/// <summary>
/// Finds all Components that have all the given tags
/// </summary>
/// <param name="__tags"></param>
/// <returns></returns>
public bool Contains(IEnumerable<string> __tags) {
return GetAll(__tags).Any();
}
/// <summary>
/// Finds all Components that have all the given tags
/// </summary>
/// <param name="__tags"></param>
/// <returns></returns>
public bool Contains<__Type>(IList<string> __tags) {
return GetAll<__Type>(__tags).Any();
}
/// <summary>
/// Finds all Components that have all the given tags
/// </summary>
/// <param name="__tags"></param>
/// <returns></returns>
public bool Contains<__Type>(IEnumerable<string> __tags) {
return GetAll<__Type>(__tags).Any();
}
/// <summary>
/// Searches and returns the first Component of a type found on the Docker.
/// </summary>
/// <typeparam name="__Type"> The Type of Component to search for</typeparam>
/// <returns></returns>
public __Type Get<__Type>() where __Type : Component {
return _componentTypeDictionary.TryGetValue(typeof(__Type), out var Components) ? (__Type)Components.FirstOrDefault() : null;
}
/// <summary>
///
/// </summary>
/// <param name="__component"></param>
/// <typeparam name="__Type"></typeparam>
/// <returns></returns>
public bool TryGet<__Type>(out __Type __component) where __Type : Component {
__component = Get<__Type>(); return __component != null;
}
/// <summary>
/// Searches and returns all Components of a type found on the Docker.
/// </summary>
/// <typeparam name="__Type"> The Type of Components to search for</typeparam>
/// <returns></returns>
public IReadOnlyList<__Type> GetAll<__Type>() where __Type : Component {
return _componentTypeDictionary.TryGetValue(typeof(__Type), out var components) ? components.OfType<__Type>().ToList() : [];
}
/// <summary>
///
/// </summary>
/// <param name="__components"></param>
/// <typeparam name="__Type"></typeparam>
/// <returns></returns>
public bool TryGetAll<__Type>(out IReadOnlyList<__Type> __components) where __Type : Component {
__components = GetAll<__Type>(); return __components.Any();
}
/// <summary>
/// Finds all Components that have all the given tags
/// </summary>
/// <param name="__tags"></param>
/// <returns></returns>
public IReadOnlyList<Component> GetAll(IList<string> __tags) {
if (__tags.Count == 0)
return [];
HashSet<Component> 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();
}
/// <summary>
/// Finds all Components that have all the given tags
/// </summary>
/// <param name="__tags"></param>
/// <returns></returns>
public bool TryGetAll(IList<string> __tags, out IReadOnlyList<Component> __components) {
__components = GetAll(__tags); return __components.Any();
}
/// <summary>
/// Finds all Components that have all the given tags, slower than GetAll() using IList. If you are being high performance, use that.
/// </summary>
/// <param name="__tags"></param>
/// <returns></returns>
public IReadOnlyList<Component> GetAll(IEnumerable<string> __tags) {
if (!__tags.Any())
return [];
HashSet<Component> 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();
}
/// <summary>
/// Finds all Components that have all the given tags
/// </summary>
/// <param name="__tags"></param>
/// <returns></returns>
public bool TryGetAll(IEnumerable<string> __tags, out IReadOnlyList<Component> __components) {
__components = GetAll(__tags); return __components.Any();
}
/// <summary>
/// Finds all Components that have all the given tags
/// </summary>
/// <param name="__tags"></param>
/// <returns></returns>
public IReadOnlyList<__Type> GetAll<__Type>(IList<string> __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();
}
/// <summary>
/// Finds all Components that have all the given tags
/// </summary>
/// <param name="__tags"></param>
/// <returns></returns>
public bool TryGetAll<__Type>(IList<string> __tags, out IReadOnlyList<__Type> __components) {
__components = GetAll<__Type>(__tags); return __components.Any();
}
/// <summary>
/// Finds all Components that have all the given tags
/// </summary>
/// <param name="__tags"></param>
/// <returns></returns>
public IReadOnlyList<__Type> GetAll<__Type>(IEnumerable<string> __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();
}
/// <summary>
/// Finds all Components that have all the given tags
/// </summary>
/// <param name="__tags"></param>
/// <returns></returns>
public bool TryGetAll<__Type>(IEnumerable<string> __tags, out IReadOnlyList<__Type> __components) {
__components = GetAll<__Type>(__tags); return __components.Any();
}
/// <summary>
/// Finds all Components that have all the given tags
/// </summary>
/// <param name="__tags"></param>
/// <returns></returns>
public IReadOnlyList<Component> GetAll(string __tag) {
return GetAll([__tag]);
}
/// <summary>
/// Finds all Components that have all the given tags
/// </summary>
/// <param name="__tags"></param>
/// <returns></returns>
public bool TryGetAll(string __tag, out IReadOnlyList<Component> __components) {
__components = GetAll(__tag); return __components.Any();
}
/// <summary>
/// Finds all Components that have all the given tags
/// </summary>
/// <param name="__tags"></param>
/// <returns></returns>
public IReadOnlyList<__Type> GetAll<__Type>(string __tag) {
return GetAll<__Type>([__tag]);
}
/// <summary>
/// Finds all Components that have all the given tags
/// </summary>
/// <param name="__tags"></param>
/// <returns></returns>
public bool TryGetAll<__Type>(string __tag, out IReadOnlyList<__Type> __components) {
__components = GetAll<__Type>(__tag); return __components.Any();
}
public Component Get(IList<string> __tags) {
return GetAll(__tags).FirstOrDefault();
}
public bool TryGet(IList<string> __tags, out Component __component) {
__component = Get(__tags); return __component != null;
}
public Component Get(IEnumerable<string> __tags) {
return GetAll(__tags).FirstOrDefault();
}
public bool TryGet(IEnumerable<string> __tags, out Component __component) {
__component = Get(__tags); return __component != null;
}
public __Type Get<__Type>(IList<string> __tags) {
return GetAll<__Type>(__tags).FirstOrDefault();
}
public bool TryGet<__Type>(IList<string> __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;
}
}

View File

@@ -1,191 +0,0 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
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, [ValueFitsRange] 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);
public TimeSpan total;
/// <summary>
/// Destroys a Component attached to the Docker
/// </summary>
/// <param name="__component"></param>
public void Destroy([ComponentNotNull,DockerOwns] Component __component) {
Stopwatch timer = Stopwatch.StartNew();
if(!ComponentNotNull.VerifyOrThrow(__component)) return;
if(!DockerOwns.VerifyOrThrow(this, __component)) return;
__component.TryEvent(5);
__component.ChainEvent(5);
RemoveComponentFromLists(__component);
__component.ComponentDocker = null;
timer.Stop();
total += timer.Elapsed;
}
/// <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 => DestroyAll(GetAll<__Type>());
/// <summary>
/// Destroys all Components from a given collection.
/// </summary>
/// <param name="__Components"></param>
public void DestroyAll([ComponentNotNull, DockerOwns] IReadOnlyList<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

@@ -27,16 +27,16 @@ public static partial class Awperative
/// <summary> /// <summary>
/// Bottom class of Awperative. Contains the OpenTK Instance. /// Bottom class of Awperative. Contains the OpenTK Instance.
/// </summary> /// </summary>
[NotNull, UnsafeInternal] private static Base Base; [DebugAttributes.NotNull, MarkerAttributes.UnsafeInternal] private static Base Base;
/// <summary> /// <summary>
/// List of all scenes currently loaded in the kernel. /// List of all scenes currently loaded in the kernel.
/// </summary> /// </summary>
[CalculatedProperty, CalculatedPropertyExpense("Very Low")] [MarkerAttributes.CalculatedProperty]
public static IReadOnlyList<Scene> Scenes => [.._scenes]; public static IEnumerable<Scene> Scenes => [.._scenes];
[UnsafeInternal] internal static HashSet<Scene> _scenes { get; private set; } = []; [MarkerAttributes.UnsafeInternal] internal static HashSet<Scene> _scenes { get; private set; } = [];
@@ -68,7 +68,7 @@ public static partial class Awperative
public static void AddScene(Scene __scene) { public static void AddScene(Scene __scene) {
if (!ContainsScene(__scene.Name)) { if (!ContainsScene(__scene.Name)) {
_scenes.Add(__scene); _scenes.Add(__scene);
} else Debug.LogError("Awperative already has a Scene with that name!", ["Scene", "Name"], [GetScene(__scene.Name).GetHashCode().ToString(), __scene.Name]); return null; } else Debug.LogError("Awperative already has a Scene with that name!", ["Scene", "Name"], [GetScene(__scene.Name).GetHashCode().ToString(), __scene.Name]); return;
} }

View File

@@ -17,13 +17,13 @@ public interface IDebugger
public void Stop(); public void Stop();
public void LogAction(string __message); public void LogAction(string __message);
public void LogAction(string __message, IReadOnlyList<string> __values, IReadOnlyList<string> __args); public void LogAction(string __message, IEnumerable<string> __values, IEnumerable<string> __args);
public void LogWarning(string __message); public void LogWarning(string __message);
public void LogWarning(string __message, IReadOnlyList<string> __values, IReadOnlyList<string> __args); public void LogWarning(string __message, IEnumerable<string> __values, IEnumerable<string> __args);
public void LogError(string __message); public void LogError(string __message);
public void LogError(string __message, IReadOnlyList<string> __values, IReadOnlyList<string> __args); public void LogError(string __message, IEnumerable<string> __values, IEnumerable<string> __args);

View File

@@ -7,5 +7,5 @@ namespace AwperativeKernel;
public interface IModuleManager public interface IModuleManager
{ {
public IReadOnlyList<Assembly> GetDependencies(); public IEnumerable<Assembly> GetDependencies();
} }

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+8c3803fcdf9411da13e462596847a88f1080bb39")] [assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+41dbab5ce36d1e19917d80ba23482cbbd5b04533")]
[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 @@
1401ec548e06fa205cbd38d50de2d7971689c7694c0af3dc509c2945921d606a b1a9e115a38433219f1f2e46313d2b5f0dd905c9ce83715b972f620249d7097d

View File

@@ -1 +1 @@
22dd22d60e6c8fbd5110065c2450e37bceb89fe776160bf2e51e6a6a8825b2b1 5635b864dfc1ecaa0f2c52b65d178dd300857fd622e8afa48acfcadbd77f72d1

View File

@@ -1 +1 @@
17722975223225869 17722975227348769