Skip to content

Commit

Permalink
Documents the Entity-Component framework
Browse files Browse the repository at this point in the history
  • Loading branch information
shnakamura committed Sep 20, 2024
1 parent d0297b7 commit 34d64c7
Show file tree
Hide file tree
Showing 11 changed files with 115 additions and 58 deletions.
18 changes: 18 additions & 0 deletions src/Aurora/Aurora.csproj.DotSettings
Original file line number Diff line number Diff line change
Expand Up @@ -42,17 +42,35 @@
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=common_005C_005Ffootsteps/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=content_005Citems_005Cweapons_005Cranged_005C_005Ftomahawks/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=content_005Cprojectiles_005Cranged_005C_005Ftomahawks/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=core_005Cconfiguration/@EntryIndexedValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=core_005Cec_005C_005Fcomponents/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=core_005Cec_005C_005Fentities/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=core_005Cec/@EntryIndexedValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=core_005Cgraphics_005C_005Frenderers/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=core_005Cio_005C_005Fgenerators/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=core_005Cio_005C_005Fprefabs/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=core_005Cio_005C_005Freaders/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=core_005Cio_005C_005Fsources/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=core_005Citems_005C_005Fcomponents/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=core_005Cnpcs/@EntryIndexedValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=core_005Cnpcs_005C_005Fcomponents/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=core_005Cphysics_005C_005Fcomponents/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=core_005Cphysics/@EntryIndexedValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=core_005Cphysics_005C_005Fkinematics/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=core_005Cprojectiles/@EntryIndexedValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=core_005Cprojectiles_005C_005Fcomponents/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=core_005Ctitles/@EntryIndexedValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=core_005Cwindow_005Ctitles/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=core_005Cwindow_005C_005Ftitles/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=core_005C_005Fconfiguration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=core_005C_005Fec/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=core_005C_005Fec_005C_005Fcomponents/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=core_005C_005Fec_005C_005Fentities/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=core_005C_005Fnpcs/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=core_005C_005Fnpcs_005C_005Fcomponents/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=core_005C_005Fphysics/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=core_005C_005Fphysics_005C_005Fcomponents/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=core_005C_005Fprojectiles/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=core_005C_005Fprojectiles_005C_005Fcomponents/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=utilities_005Cextensions/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=utilities_005C_005Fextensions/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
10 changes: 0 additions & 10 deletions src/Aurora/Core/EC/Component.cs

This file was deleted.

16 changes: 0 additions & 16 deletions src/Aurora/Core/EC/IEntity.cs

This file was deleted.

19 changes: 19 additions & 0 deletions src/Aurora/Core/EC/_Components/Component.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
namespace Aurora.Core.EC;

public abstract class Component : IComponent
{
/// <summary>
/// The entity this component is attached to.
/// </summary>
public Entity Entity { get; }

/// <summary>
/// Called every update cycle for this component's logic.
/// </summary>
public virtual void Update() { }

/// <summary>
/// Called every update cycle for this component's rendering logic.
/// </summary>
public virtual void Render() { }
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
using Aurora.Utilities;

namespace Aurora.Core.EC;

public sealed class ComponentSystem : ModSystem
Expand All @@ -22,7 +20,7 @@ private static void OnUpdateEvent() {
for (var i = 0; i < Components.Length; i++) {
var component = Components[i];

if (!component.Parent.Active) {
if (!component.Entity.Active) {
continue;
}

Expand All @@ -34,7 +32,7 @@ private static void OnRenderEvent() {
for (var i = 0; i < Components.Length; i++) {
var component = Components[i];

if (!component.Parent.Active) {
if (!component.Entity.Active) {
continue;
}

Expand All @@ -60,23 +58,28 @@ public override void PostUpdateWorld() {
OnUpdate?.Invoke();
}

public static bool Has<T>(int id) where T : IComponent {
if (id < 0 || id >= ComponentData<T>.Components.Length) {
return false;
}

return (ComponentData<T>.Flags[id] & ComponentData<T>.Mask) != 0;
}

public static T Get<T>(int id) where T : IComponent {
/// <summary>
/// Retrieves a component of the specified type from an entity.
/// </summary>
/// <param name="id">The identify of the entity to retrieve the component from.</param>
/// <typeparam name="T">The type of the component to retrieve.</typeparam>
/// <returns>The instance of the component if found; otherwise, <c>null</c>.</returns>
public static T Get<T>(int id) where T : class, IComponent {
if (id < 0 || id >= ComponentData<T>.Components.Length) {
return default;
return null;
}

return ComponentData<T>.Components[id];
}

public static T Set<T>(int id, T? value) where T : IComponent {
/// <summary>
/// Sets the value of a component of the specified type to an entity.
/// </summary>
/// <param name="id">The identity of the entity to set the component to.</param>
/// <param name="value">The value of the component.</param>
/// <typeparam name="T">The type of the component to set.</typeparam>
/// <returns>The assigned component instance.</returns>
public static T Set<T>(int id, T? value) where T : class, IComponent {
if (id >= ComponentData<T>.Components.Length) {
var newSize = Math.Max(1, ComponentData<T>.Components.Length);

Expand All @@ -103,7 +106,27 @@ public static T Set<T>(int id, T? value) where T : IComponent {
return ComponentData<T>.Components[id];
}

public static bool Remove<T>(int id) where T : IComponent {
/// <summary>
/// Checks whether an entity has a component of the specified type or not.
/// </summary>
/// <param name="id">The identity of the entity to check.</param>
/// <typeparam name="T">The type of the component to check.</typeparam>
/// <returns><c>true</c> if the component was found; otherwise, <c>false</c>.</returns>
public static bool Has<T>(int id) where T : class, IComponent {
if (id < 0 || id >= ComponentData<T>.Components.Length) {
return false;
}

return (ComponentData<T>.Flags[id] & ComponentData<T>.Mask) != 0;
}

/// <summary>
/// Attempts to remove a component of the specified type from an entity.
/// </summary>
/// <param name="id">The identity of the entity to remove the component from.</param>
/// <typeparam name="T">The type of the component to remove.</typeparam>
/// <returns><c>true</c> if the component was successfully removed; otherwise, <c>false</c>.</returns>
public static bool Remove<T>(int id) where T : class, IComponent {
if (id < 0 || id >= ComponentData<T>.Components.Length) {
return false;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ namespace Aurora.Core.EC;

public interface IComponent
{
Entity Parent { get; }
Entity Entity { get; }

void Update();

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
using System.Collections.Generic;

namespace Aurora.Core.EC;

public struct Entity : IEntity
Expand All @@ -25,18 +23,18 @@ internal Entity(int id) {
/// Retrieves a component of the specified type from this entity.
/// </summary>
/// <typeparam name="T">The type of the component to retrieve.</typeparam>
/// <returns>The instance of the component if found; otherwise, <c>default</c>.</returns>
public T Get<T>() where T : IComponent {
/// <returns>The instance of the component if found; otherwise, <c>null</c>.</returns>
public T Get<T>() where T : class, IComponent {
return ComponentSystem.Get<T>(Id);
}

/// <summary>
/// Sets the value of a component of the specified type to this entity.
/// </summary>
/// <param name="value">The value of the component.</param>
/// <param name="value">The value of the component to set.</param>
/// <typeparam name="T">The type of the component to set.</typeparam>
/// <returns>The assigned component instance.</returns>
public T Set<T>(T? value) where T : IComponent {
public T Set<T>(T? value) where T : class, IComponent {
return ComponentSystem.Set(Id, value);
}

Expand All @@ -45,7 +43,7 @@ public T Set<T>(T? value) where T : IComponent {
/// </summary>
/// <typeparam name="T">The type of component to check.</typeparam>
/// <returns><c>true</c> if the component was found; otherwise, <c>false</c>.</returns>
public bool Has<T>() where T : IComponent {
public bool Has<T>() where T : class, IComponent {
return ComponentSystem.Has<T>(Id);
}

Expand All @@ -54,7 +52,7 @@ public bool Has<T>() where T : IComponent {
/// </summary>
/// <typeparam name="T">The type of the component to remove.</typeparam>
/// <returns><c>true</c> if the component was successfully removed; otherwise, <c>false</c>.</returns>
public bool Remove<T>() where T : IComponent {
public bool Remove<T>() where T : class, IComponent {
return ComponentSystem.Remove<T>(Id);
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework.Input;

namespace Aurora.Core.EC;

Expand Down Expand Up @@ -34,7 +32,7 @@ public static Entity Create(bool activate) {
}

/// <summary>
/// Removes an instance of an entity from its identity.
/// Removes an instance of an entity.
/// </summary>
/// <param name="entityId">The identity of the entity to remove.</param>
/// <returns><c>true</c> if the entity was successfully removed; otherwise, <c>false</c>.</returns>
Expand All @@ -52,7 +50,7 @@ public static bool Remove(int id) {
}

/// <summary>
/// Checks whether an entity is active or not from its identity.
/// Checks whether an entity is active or not.
/// </summary>
/// <param name="id">The identity of the entity to check.</param>
/// <returns><c>true</c> if the entity is active; otherwise, <c>false</c>.</returns>
Expand All @@ -65,7 +63,7 @@ internal static bool GetActive(int id) {
}

/// <summary>
/// Sets the active status of an entity from its identity.
/// Sets the active status of an entity.
/// </summary>
/// <param name="id">The identity of the entity to set.</param>
/// <param name="value">The value of the status to set.</param>
Expand Down
16 changes: 16 additions & 0 deletions src/Aurora/Core/EC/_Entities/IEntity.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
namespace Aurora.Core.EC;

public interface IEntity
{
int Id { get; }

bool Active { get; set; }

T Get<T>() where T : class, IComponent;

T Set<T>(T? value) where T : class, IComponent;

bool Has<T>() where T : class, IComponent;

bool Remove<T>() where T : class, IComponent;
}
3 changes: 1 addition & 2 deletions src/Aurora/Core/Graphics/_Renderers/PlayerOutlineRenderer.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
using System.Collections.Generic;
using Aurora.Core.Graphics;
using Aurora.Utilities;
using ReLogic.Content;

namespace Aurora.Content.Items.Miscellaneous;
namespace Aurora.Core.Graphics;

/// <summary>
/// Handles the registration and rendering of player outlines.
Expand Down
12 changes: 12 additions & 0 deletions src/Aurora/Core/Physics/_Components/Transform.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using Aurora.Core.EC;

namespace Aurora.Core.Physics;

public sealed class Transform(Vector2 position, Vector2? scale = null, float rotation = 0f) : Component
{
public Vector2 Position = position;

public Vector2 Scale = scale ?? Vector2.One;

public float Rotation = rotation;
}

0 comments on commit 34d64c7

Please sign in to comment.