Skip to content

Component Expressions Neofox: magnify

Neofox: thumbsup Meta-Level Component References

Component Expressions let you refer to components in a strongly typed way at a meta-level – perfect for building queries, filtering, and runtime inspection!

What are Component Expressions?

Component Expressions (Comp<C>) are a way to reference components by their type and optional relation target. They're used primarily for:

  • Building Queries dynamically
  • Filtering Streams
  • Runtime inspection and serialization

Strongly Typed Expressions

Comp<C>.Plain

Creates an expression for a "plain" component – one with no relation target.

cs
// Reference a plain Position component
var posExpr = Comp<Position>.Plain;

// Use in stream filters
stream.Subset = [Comp<Position>.Plain];

Comp<R>.Matching(Entity relation)

Creates an expression for a relation component pointing to a specific entity.

cs
var parent = world.Spawn();

// Reference the ChildOf relation to 'parent'
var childOfParent = Comp<ChildOf>.Matching(parent);

Creates an expression for an object link to a specific object.

cs
var gameObject = new GameObject("Player");

// Reference the link to this specific object
var linkExpr = Comp<GameObject>.Matching(gameObject);

Comp<T>.Matching(Match match)

Creates an expression with wildcard matching.

cs
// Match any component of type Health (plain or relation)
var anyHealth = Comp<Health>.Matching(Match.Any);

// Match only entity relations of type Owes
var owesRelation = Comp<Owes>.Matching(Match.Entity);

// Match only object links of type Texture
var textureLinks = Comp<Texture>.Matching(Match.Object);

Match Wildcards

MatchDescription
Match.AnyAny target (includes plain)
Match.PlainNo target (plain components only)
Match.EntityEntity-to-entity relations
Match.ObjectObject links
Match.TargetAny relation (Entity or Object, not Plain)

Boxed Components Neofox: box

For runtime inspection and serialization, fennecs provides boxed component access through Entity.Components.

Entity.Components

Returns all components on an entity as IReadOnlyList<Component>:

cs
using var world = new World();
var entity = world.Spawn();
entity.Add(123);
entity.Add(69.420);
entity.Add(new Position { X = 10, Y = 20 });
entity.Add(Link.With("hello world"));

var components = entity.Components;
Console.WriteLine($"Entity has {components.Count} components");

foreach (var component in components)
{
    Console.WriteLine($"  {component.Type.Name}: {component.Box.Value}");
}

The Component Struct

Component is a managed struct containing metadata about a component:

PropertyTypeDescription
TypeSystem.TypeThe backing type of the component
BoxIStrongBoxThe boxed value
isRelationboolIs this a relation to another Entity?
isLinkboolIs this an Object Link?
targetEntityEntityThe relation target (if isRelation)

Usage Example

cs
foreach (var component in entity.Components)
{
    if (component.isRelation)
    {
        Console.WriteLine($"Relation to {component.targetEntity}");
    }
    else if (component.isLink)
    {
        Console.WriteLine($"Link to {component.Box.Value}");
    }
    else
    {
        Console.WriteLine($"Plain: {component.Type.Name} = {component.Box.Value}");
    }
}

Neofox: owo Boxed Components are Copies

The Component.Box.Value is a copy for value type components, but the same reference for shareables and object links.

Don't modify boxed components – use the Entity CRUD API (Add, Remove, Ref) instead.

Quick Reference

ExpressionCreates Reference To
Comp<C>.PlainPlain component (no target)
Comp<C>.Matching(entity)Relation to entity
Comp<C>.Matching(obj)Object link
Comp<C>.Matching(Match.Any)Any matching component
PropertyPurpose
Entity.ComponentsAll components (boxed)
Component.TypeBacking type
Component.BoxBoxed value
Component.isRelationIs entity relation?
Component.isLinkIs object link?

fennecs is released under the MIT License. Neofox is released under the CC BY-NC-SA 4.0 License.