Compare commits

...

2 commits

Author SHA1 Message Date
D. Moonfire fb0a03e963 feat(entity): added SetAll() which takes a params list
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
ci/woodpecker/manual/woodpecker Pipeline was successful
- added unit test to verify
- minor code clean up to get the tests running

closes #1
2023-01-14 17:13:01 -06:00
D. Moonfire e4c9e82b99 refactor: cleaning up code to newer C# standards 2023-01-14 16:51:06 -06:00
18 changed files with 1259 additions and 1161 deletions

View file

@ -3,471 +3,506 @@ using System.Collections.Generic;
using System.Collections.Immutable; using System.Collections.Immutable;
using System.Threading; using System.Threading;
namespace MfGames.Gallium namespace MfGames.Gallium;
/// <summary>
/// A low-overhead entity with identification.
/// </summary>
public record Entity
{ {
/// <summary> public Entity()
/// A low-overhead entity with identification. : this(Interlocked.Increment(ref nextId))
/// </summary>
public record Entity
{ {
/// <inheritdoc /> }
public virtual bool Equals(Entity? other)
private Entity(int id)
{
this.Id = id;
this.Components = ImmutableDictionary.Create<Type, object>();
}
/// <inheritdoc />
public virtual bool Equals(Entity? other)
{
if (ReferenceEquals(null, other))
{ {
if (ReferenceEquals(null, other))
{
return false;
}
if (ReferenceEquals(this, other))
{
return true;
}
return this.Id == other.Id;
}
/// <inheritdoc />
public override int GetHashCode()
{
return this.Id;
}
private ImmutableDictionary<Type, object> Components { get; set; }
/// <summary>
/// The internal ID to ensure the entities are unique. Since we are not
/// worried about serialization or using the identifiers from one call
/// to another, we can use a simple interlocked identifier instead of
/// a factory or provider method.
/// </summary>
private static int nextId;
public Entity()
: this(Interlocked.Increment(ref nextId))
{
}
private Entity(int id)
{
this.Id = id;
this.Components = ImmutableDictionary.Create<Type, object>();
}
/// <summary>
/// Gets a value indicating whether the entity has a specific type of
/// component registered.
/// </summary>
/// <typeparam name="T1">The component type.</typeparam>
/// <returns>True if the type exists, otherwise false.</returns>
public bool Has<T1>()
{
return this.Has(typeof(T1));
}
/// <summary>
/// Gets a value indicating whether the entity has components of the given types
/// registered.
/// </summary>
/// <typeparam name="T1">The first component type.</typeparam>
/// <typeparam name="T2">The second component type.</typeparam>
/// <returns>
/// True if there are components of the given type exists, otherwise
/// false.
/// </returns>
public bool HasAll<T1, T2>()
{
return this.HasAll(typeof(T1), typeof(T2));
}
/// <summary>
/// Gets a value indicating whether the entity has components of the given types
/// registered.
/// </summary>
/// <typeparam name="T1">The first component type.</typeparam>
/// <typeparam name="T2">The second component type.</typeparam>
/// <typeparam name="T3">The third component type.</typeparam>
/// <returns>
/// True if there are components of the given type exists, otherwise
/// false.
/// </returns>
public bool HasAll<T1, T2, T3>()
{
return this.HasAll(typeof(T1), typeof(T2), typeof(T3));
}
/// <summary>
/// Gets a value indicating whether the entity has components of the given types
/// registered.
/// </summary>
/// <typeparam name="T1">The first component type.</typeparam>
/// <typeparam name="T2">The second component type.</typeparam>
/// <typeparam name="T3">The third component type.</typeparam>
/// <typeparam name="T4">The third component type.</typeparam>
/// <returns>
/// True if there are components of the given type exists, otherwise
/// false.
/// </returns>
public bool HasAll<T1, T2, T3, T4>()
{
return this.HasAll(typeof(T1), typeof(T2), typeof(T3), typeof(T4));
}
/// <summary>
/// Gets a value indicating whether the entity has a specific type of
/// component registered.
/// </summary>
/// <param name="type">The component type.</param>
/// <returns>True if the type exists, otherwise false.</returns>
public bool Has(Type type)
{
return this.Components.ContainsKey(type);
}
/// <summary>
/// Gets a value indicating whether the entity has components for all the given
/// types.
/// </summary>
/// <param name="t1">The component type.</param>
/// <param name="t2">The component type.</param>
/// <returns>True if the type exists, otherwise false.</returns>
public bool HasAll(
Type t1,
Type t2)
{
return this.Has(t1) && this.Components.ContainsKey(t2);
}
/// <summary>
/// Gets a value indicating whether the entity has components for all the given
/// types.
/// </summary>
/// <param name="t1">The component type.</param>
/// <param name="t2">The component type.</param>
/// <param name="t3">The component type.</param>
/// <returns>True if the type exists, otherwise false.</returns>
public bool HasAll(
Type t1,
Type t2,
Type t3)
{
return this.HasAll(t1, t2) && this.Components.ContainsKey(t3);
}
/// <summary>
/// Gets a value indicating whether the entity has components for all the given
/// types.
/// </summary>
/// <param name="t1">The component type.</param>
/// <param name="t2">The component type.</param>
/// <param name="t3">The component type.</param>
/// <param name="t4">The component type.</param>
/// <returns>True if the type exists, otherwise false.</returns>
public bool HasAll(
Type t1,
Type t2,
Type t3,
Type t4)
{
return this.HasAll(t1, t2, t3) && this.Components.ContainsKey(t4);
}
/// <summary>
/// Retrieves a registered component of the given type.
/// </summary>
/// <typeparam name="TType">The component type.</typeparam>
/// <returns>The registered object.</returns>
public TType Get<TType>()
{
return (TType)this.Components[typeof(TType)];
}
/// <summary>
/// Retrieves a registered component of the given type and casts it to
/// TType.
/// </summary>
/// <param name="type">The component key.</param>
/// <typeparam name="TType">The component type.</typeparam>
/// <returns>The registered object.</returns>
public TType Get<TType>(Type type)
{
return (TType)this.Components[type];
}
/// <summary>
/// Gets the number of components registered in the entity.
/// </summary>
public int Count => this.Components.Count;
/// <summary>
/// Gets the given component type if inside the entity, otherwise the
/// default value.
/// </summary>
/// <typeparam name="TType">The component type.</typeparam>
/// <returns>The found component or default (typically null).</returns>
public TType? GetOptional<TType>()
{
return this.Has<TType>() ? this.Get<TType>() : default;
}
/// <summary>
/// Attempts to get the value, if present. If not, this returns false
/// and the value is undefined. Otherwise, this method returns true
/// and the actual value inside that variable.
/// </summary>
/// <param name="value">The value if contained in the entity.</param>
/// <typeparam name="T1">The component type.</typeparam>
/// <returns>True if found, otherwise false.</returns>
public bool TryGet<T1>(out T1 value)
{
if (this.Has<T1>())
{
value = this.Get<T1>();
return true;
}
value = default!;
return false; return false;
} }
/// <summary> if (ReferenceEquals(this, other))
/// Attempts to get the values, if present. If not, this returns false
/// and the value is undefined. Otherwise, this method returns true
/// and the actual value inside that variable.
/// </summary>
/// <param name="value1">The value if contained in the entity.</param>
/// <param name="value2">The value if contained in the entity.</param>
/// <typeparam name="T1">The first component type.</typeparam>
/// <typeparam name="T2">The second component type.</typeparam>
/// <returns>True if found, otherwise false.</returns>
public bool TryGet<T1, T2>(
out T1 value1,
out T2 value2)
{ {
if (this.HasAll<T1, T2>()) return true;
{ }
value1 = this.Get<T1>();
value2 = this.Get<T2>();
return true; return this.Id == other.Id;
}
/// <inheritdoc />
public override int GetHashCode()
{
return this.Id.GetHashCode();
}
private ImmutableDictionary<Type, object> Components { get; init; }
/// <summary>
/// The internal ID to ensure the entities are unique. Since we are not
/// worried about serialization or using the identifiers from one call
/// to another, we can use a simple interlocked identifier instead of
/// a factory or provider method.
/// </summary>
private static int nextId;
/// <summary>
/// Gets a value indicating whether the entity has a specific type of
/// component registered.
/// </summary>
/// <typeparam name="T1">The component type.</typeparam>
/// <returns>True if the type exists, otherwise false.</returns>
public bool Has<T1>()
{
return this.Has(typeof(T1));
}
/// <summary>
/// Gets a value indicating whether the entity has components of the given types
/// registered.
/// </summary>
/// <typeparam name="T1">The first component type.</typeparam>
/// <typeparam name="T2">The second component type.</typeparam>
/// <returns>
/// True if there are components of the given type exists, otherwise
/// false.
/// </returns>
public bool HasAll<T1, T2>()
{
return this.HasAll(typeof(T1), typeof(T2));
}
/// <summary>
/// Gets a value indicating whether the entity has components of the given types
/// registered.
/// </summary>
/// <typeparam name="T1">The first component type.</typeparam>
/// <typeparam name="T2">The second component type.</typeparam>
/// <typeparam name="T3">The third component type.</typeparam>
/// <returns>
/// True if there are components of the given type exists, otherwise
/// false.
/// </returns>
public bool HasAll<T1, T2, T3>()
{
return this.HasAll(typeof(T1), typeof(T2), typeof(T3));
}
/// <summary>
/// Gets a value indicating whether the entity has components of the given types
/// registered.
/// </summary>
/// <typeparam name="T1">The first component type.</typeparam>
/// <typeparam name="T2">The second component type.</typeparam>
/// <typeparam name="T3">The third component type.</typeparam>
/// <typeparam name="T4">The third component type.</typeparam>
/// <returns>
/// True if there are components of the given type exists, otherwise
/// false.
/// </returns>
public bool HasAll<T1, T2, T3, T4>()
{
return this.HasAll(typeof(T1), typeof(T2), typeof(T3), typeof(T4));
}
/// <summary>
/// Gets a value indicating whether the entity has a specific type of
/// component registered.
/// </summary>
/// <param name="type">The component type.</param>
/// <returns>True if the type exists, otherwise false.</returns>
public bool Has(Type type)
{
return this.Components.ContainsKey(type);
}
/// <summary>
/// Gets a value indicating whether the entity has components for all the given
/// types.
/// </summary>
/// <param name="t1">The component type.</param>
/// <param name="t2">The component type.</param>
/// <returns>True if the type exists, otherwise false.</returns>
public bool HasAll(
Type t1,
Type t2)
{
return this.Has(t1) && this.Components.ContainsKey(t2);
}
/// <summary>
/// Gets a value indicating whether the entity has components for all the given
/// types.
/// </summary>
/// <param name="t1">The component type.</param>
/// <param name="t2">The component type.</param>
/// <param name="t3">The component type.</param>
/// <returns>True if the type exists, otherwise false.</returns>
public bool HasAll(
Type t1,
Type t2,
Type t3)
{
return this.HasAll(t1, t2) && this.Components.ContainsKey(t3);
}
/// <summary>
/// Gets a value indicating whether the entity has components for all the given
/// types.
/// </summary>
/// <param name="t1">The component type.</param>
/// <param name="t2">The component type.</param>
/// <param name="t3">The component type.</param>
/// <param name="t4">The component type.</param>
/// <returns>True if the type exists, otherwise false.</returns>
public bool HasAll(
Type t1,
Type t2,
Type t3,
Type t4)
{
return this.HasAll(t1, t2, t3) && this.Components.ContainsKey(t4);
}
/// <summary>
/// Retrieves a registered component of the given type.
/// </summary>
/// <typeparam name="TType">The component type.</typeparam>
/// <returns>The registered object.</returns>
public TType Get<TType>()
{
return (TType)this.Components[typeof(TType)];
}
/// <summary>
/// Retrieves a registered component of the given type and casts it to
/// TType.
/// </summary>
/// <param name="type">The component key.</param>
/// <typeparam name="TType">The component type.</typeparam>
/// <returns>The registered object.</returns>
public TType Get<TType>(Type type)
{
return (TType)this.Components[type];
}
/// <summary>
/// Gets the number of components registered in the entity.
/// </summary>
public int Count => this.Components.Count;
/// <summary>
/// Gets the given component type if inside the entity, otherwise the
/// default value.
/// </summary>
/// <typeparam name="TType">The component type.</typeparam>
/// <returns>The found component or default (typically null).</returns>
public TType? GetOptional<TType>()
{
return this.Has<TType>() ? this.Get<TType>() : default;
}
/// <summary>
/// Attempts to get the value, if present. If not, this returns false
/// and the value is undefined. Otherwise, this method returns true
/// and the actual value inside that variable.
/// </summary>
/// <param name="value">The value if contained in the entity.</param>
/// <typeparam name="T1">The component type.</typeparam>
/// <returns>True if found, otherwise false.</returns>
public bool TryGet<T1>(out T1 value)
{
if (this.Has<T1>())
{
value = this.Get<T1>();
return true;
}
value = default!;
return false;
}
/// <summary>
/// Attempts to get the values, if present. If not, this returns false
/// and the value is undefined. Otherwise, this method returns true
/// and the actual value inside that variable.
/// </summary>
/// <param name="value1">The value if contained in the entity.</param>
/// <param name="value2">The value if contained in the entity.</param>
/// <typeparam name="T1">The first component type.</typeparam>
/// <typeparam name="T2">The second component type.</typeparam>
/// <returns>True if found, otherwise false.</returns>
public bool TryGet<T1, T2>(
out T1 value1,
out T2 value2)
{
if (this.HasAll<T1, T2>())
{
value1 = this.Get<T1>();
value2 = this.Get<T2>();
return true;
}
value1 = default!;
value2 = default!;
return false;
}
/// <summary>
/// Attempts to get the values, if present. If not, this returns false
/// and the value is undefined. Otherwise, this method returns true
/// and the actual value inside that variable.
/// </summary>
/// <param name="value1">The value if contained in the entity.</param>
/// <param name="value2">The value if contained in the entity.</param>
/// <param name="value3">The value if contained in the entity.</param>
/// <typeparam name="T1">The first component type.</typeparam>
/// <typeparam name="T2">The second component type.</typeparam>
/// <typeparam name="T3">The third component type.</typeparam>
/// <returns>True if found, otherwise false.</returns>
public bool TryGet<T1, T2, T3>(
out T1 value1,
out T2 value2,
out T3 value3)
{
if (this.HasAll<T1, T2, T3>())
{
value1 = this.Get<T1>();
value2 = this.Get<T2>();
value3 = this.Get<T3>();
return true;
}
value1 = default!;
value2 = default!;
value3 = default!;
return false;
}
/// <summary>
/// Attempts to get the values, if present. If not, this returns false
/// and the value is undefined. Otherwise, this method returns true
/// and the actual value inside that variable.
/// </summary>
/// <param name="value1">The value if contained in the entity.</param>
/// <param name="value2">The value if contained in the entity.</param>
/// <param name="value3">The value if contained in the entity.</param>
/// <param name="value4">The value if contained in the entity.</param>
/// <typeparam name="T1">The first component type.</typeparam>
/// <typeparam name="T2">The second component type.</typeparam>
/// <typeparam name="T3">The third component type.</typeparam>
/// <typeparam name="T4">The fourth component type.</typeparam>
/// <returns>True if found, otherwise false.</returns>
public bool TryGet<T1, T2, T3, T4>(
out T1 value1,
out T2 value2,
out T3 value3,
out T4 value4)
{
if (this.HasAll<T1, T2, T3, T4>())
{
value1 = this.Get<T1>();
value2 = this.Get<T2>();
value3 = this.Get<T3>();
value4 = this.Get<T4>();
return true;
}
value1 = default!;
value2 = default!;
value3 = default!;
value4 = default!;
return false;
}
/// <summary>
/// Sets the component in the entity, regardless if there was a
/// component already registered.
/// </summary>
/// <param name="component">The component to register.</param>
/// <typeparam name="T1">The component type.</typeparam>
/// <returns>The entity for chaining.</returns>
/// <exception cref="ArgumentNullException"></exception>
public Entity Set<T1>(T1 component)
{
if (component == null)
{
throw new ArgumentNullException(nameof(component));
}
if (this.Components.TryGetValue(typeof(T1), out object? value)
&& value is T1
&& value.Equals(component))
{
return this;
}
return this with
{
Components = this.Components.SetItem(typeof(T1), component),
};
}
/// <summary>
/// Sets zero or more components into an entity in a single call. This does
/// not allow for specifying the data type; each item will be added with
/// the result of `component.GetType()`.
/// </summary>
/// <param name="components">
/// The components to add to the entity. Any null objects
/// will be ignored.
/// </param>
/// <returns>
/// A new Entity with the modified component collection if there is at
/// least one component to set, otherwise the same entity.
/// </returns>
public Entity SetAll(params object?[] components)
{
if (components.Length == 0)
{
return this;
}
ImmutableDictionary<Type, object> collection = this.Components;
foreach (object? component in components)
{
if (component != null)
{
collection = collection.SetItem(component.GetType(), component);
} }
value1 = default!;
value2 = default!;
return false;
} }
/// <summary> return this with
/// Attempts to get the values, if present. If not, this returns false
/// and the value is undefined. Otherwise, this method returns true
/// and the actual value inside that variable.
/// </summary>
/// <param name="value1">The value if contained in the entity.</param>
/// <param name="value2">The value if contained in the entity.</param>
/// <param name="value3">The value if contained in the entity.</param>
/// <typeparam name="T1">The first component type.</typeparam>
/// <typeparam name="T2">The second component type.</typeparam>
/// <typeparam name="T3">The third component type.</typeparam>
/// <returns>True if found, otherwise false.</returns>
public bool TryGet<T1, T2, T3>(
out T1 value1,
out T2 value2,
out T3 value3)
{ {
if (this.HasAll<T1, T2, T3>()) Components = collection,
{ };
value1 = this.Get<T1>(); }
value2 = this.Get<T2>();
value3 = this.Get<T3>();
return true; /// <summary>
} /// Adds a component to the entity.
/// </summary>
value1 = default!; /// <param name="component">The component to register.</param>
value2 = default!; /// <typeparam name="T1">The component type.</typeparam>
value3 = default!; /// <returns>
/// The same entity if the component is already registered, otherwise a
return false; /// cloned entity with the new component.
} /// </returns>
/// <exception cref="ArgumentNullException"></exception>
/// <summary> public Entity Add<T1>(T1 component)
/// Attempts to get the values, if present. If not, this returns false {
/// and the value is undefined. Otherwise, this method returns true if (component == null)
/// and the actual value inside that variable.
/// </summary>
/// <param name="value1">The value if contained in the entity.</param>
/// <param name="value2">The value if contained in the entity.</param>
/// <param name="value3">The value if contained in the entity.</param>
/// <param name="value4">The value if contained in the entity.</param>
/// <typeparam name="T1">The first component type.</typeparam>
/// <typeparam name="T2">The second component type.</typeparam>
/// <typeparam name="T3">The third component type.</typeparam>
/// <typeparam name="T4">The fourth component type.</typeparam>
/// <returns>True if found, otherwise false.</returns>
public bool TryGet<T1, T2, T3, T4>(
out T1 value1,
out T2 value2,
out T3 value3,
out T4 value4)
{ {
if (this.HasAll<T1, T2, T3, T4>()) throw new ArgumentNullException(nameof(component));
{
value1 = this.Get<T1>();
value2 = this.Get<T2>();
value3 = this.Get<T3>();
value4 = this.Get<T4>();
return true;
}
value1 = default!;
value2 = default!;
value3 = default!;
value4 = default!;
return false;
} }
/// <summary> if (this.Has<T1>())
/// Sets the component in the entity, regardless if there was a
/// component already registered.
/// </summary>
/// <param name="component">The component to register.</param>
/// <typeparam name="T1">The component type.</typeparam>
/// <returns>The entity for chaining.</returns>
/// <exception cref="ArgumentNullException"></exception>
public Entity Set<T1>(T1 component)
{ {
if (component == null) throw new ArgumentException(
{ "An element with the same type ("
throw new ArgumentNullException(nameof(component)); + typeof(T1).FullName
} + ") already exists.",
nameof(component));
if (this.Components.TryGetValue(typeof(T1), out object? value)
&& value is T1
&& value.Equals(component))
{
return this;
}
return this with
{
Components = this.Components.SetItem(typeof(T1), component),
};
} }
/// <summary> if (this.Components.TryGetValue(typeof(T1), out object? value)
/// Adds a component to the entity. && value is T1
/// </summary> && value.Equals(component))
/// <param name="component">The component to register.</param>
/// <typeparam name="T1">The component type.</typeparam>
/// <returns>
/// The same entity if the component is already registered, otherwise a
/// cloned entity with the new component.
/// </returns>
/// <exception cref="ArgumentNullException"></exception>
public Entity Add<T1>(T1 component)
{ {
if (component == null) return this;
{
throw new ArgumentNullException(nameof(component));
}
if (this.Has<T1>())
{
throw new ArgumentException(
"An element with the same type ("
+ typeof(T1).FullName
+ ") already exists.",
nameof(component));
}
if (this.Components.TryGetValue(typeof(T1), out object? value)
&& value is T1
&& value.Equals(component))
{
return this;
}
return this with
{
Components = this.Components.Add(typeof(T1), component),
};
} }
/// <summary> return this with
/// Removes a component to the entity.
/// </summary>
/// <typeparam name="TType">The component type.</typeparam>
/// <returns>
/// The same entity if the component is already removed, otherwise a
/// cloned entity without the new component.
/// </returns>
/// <exception cref="ArgumentNullException"></exception>
public Entity Remove<TType>()
{ {
return this.Remove(typeof(TType)); Components = this.Components.Add(typeof(T1), component)
} };
}
/// <summary> /// <summary>
/// Removes a component to the entity. /// Removes a component to the entity.
/// </summary> /// </summary>
/// <returns> /// <typeparam name="TType">The component type.</typeparam>
/// The same entity if the component is already removed, otherwise a /// <returns>
/// cloned entity without the new component. /// The same entity if the component is already removed, otherwise a
/// </returns> /// cloned entity without the new component.
/// <param name="type">The component type to remove.</param> /// </returns>
public Entity Remove(Type type) /// <exception cref="ArgumentNullException"></exception>
public Entity Remove<TType>()
{
return this.Remove(typeof(TType));
}
/// <summary>
/// Removes a component to the entity.
/// </summary>
/// <returns>
/// The same entity if the component is already removed, otherwise a
/// cloned entity without the new component.
/// </returns>
/// <param name="type">The component type to remove.</param>
public Entity Remove(Type type)
{
if (!this.Has(type))
{ {
if (!this.Has(type)) return this;
{
return this;
}
return this with
{
Components = this.Components.Remove(type),
};
} }
/// <summary> return this with
/// Gets the identifier of the entity. This should be treated as an
/// opaque field.
/// </summary>
public int Id { get; private init; }
/// <summary>
/// Creates a copy of the entity, including copying the identifier.
/// </summary>
/// <returns></returns>
public Entity ExactCopy()
{ {
return this with { }; Components = this.Components.Remove(type)
} };
}
/// <summary> /// <summary>
/// Creates a copy of the entity, including components, but with a new /// Gets the identifier of the entity. This should be treated as an
/// identifier. /// opaque field.
/// </summary> /// </summary>
/// <returns></returns> public int Id { get; private init; }
public Entity Copy()
{
return this with
{
Id = Interlocked.Increment(ref nextId),
};
}
/// <summary> /// <summary>
/// Retrieves a list of the component types currently registered in the /// Creates a copy of the entity, including copying the identifier.
/// Entity. /// </summary>
/// </summary> /// <returns></returns>
/// <returns>An enumerable of the various component keys.</returns> public Entity ExactCopy()
public IEnumerable<Type> GetComponentTypes() {
return this with { };
}
/// <summary>
/// Creates a copy of the entity, including components, but with a new
/// identifier.
/// </summary>
/// <returns></returns>
public Entity Copy()
{
return this with
{ {
return this.Components.Keys; Id = Interlocked.Increment(ref nextId)
} };
}
/// <summary>
/// Retrieves a list of the component types currently registered in the
/// Entity.
/// </summary>
/// <returns>An enumerable of the various component keys.</returns>
public IEnumerable<Type> GetComponentTypes()
{
return this.Components.Keys;
} }
} }

View file

@ -2,28 +2,27 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
namespace MfGames.Gallium namespace MfGames.Gallium;
public static class JoinEntityExtensions
{ {
public static class JoinEntityExtensions /// <summary>
/// Merges two sets of entities using the identifier to determine which
/// entities are the same. The `merge` function takes both of the
/// entities with the Entity from the `input` first and the one from
/// `other` second. The returning entity is put into the collection. If
/// an entity from the input is not found in other, then it is just
/// passed on.
/// </summary>
/// <param name="input">The enumerable of entities to merge to.</param>
/// <param name="other">The collection of entities to merge from.</param>
/// <param name="merge">The callback to merge the two.</param>
/// <returns>An sequence of entities, merged and unmerged.</returns>
public static IEnumerable<Entity> JoinEntity(
this IEnumerable<Entity> input,
ICollection<Entity> other,
Func<Entity, Entity, Entity> merge)
{ {
/// <summary> return input.Join(other, a => a.Id, a => a.Id, merge);
/// Merges two sets of entities using the identifier to determine which
/// entities are the same. The `merge` function takes both of the
/// entities with the Entity from the `input` first and the one from
/// `other` second. The returning entity is put into the collection. If
/// an entity from the input is not found in other, then it is just
/// passed on.
/// </summary>
/// <param name="input">The enumerable of entities to merge to.</param>
/// <param name="other">The collection of entities to merge from.</param>
/// <param name="merge">The callback to merge the two.</param>
/// <returns>An sequence of entities, merged and unmerged.</returns>
public static IEnumerable<Entity> JoinEntity(
this IEnumerable<Entity> input,
ICollection<Entity> other,
Func<Entity, Entity, Entity> merge)
{
return input.Join(other, a => a.Id, a => a.Id, merge);
}
} }
} }

View file

@ -16,7 +16,8 @@ public static class SelectComponentExtensions
/// <param name="entities">The entities to process.</param> /// <param name="entities">The entities to process.</param>
/// <typeparam name="T1">The component type being searched.</typeparam> /// <typeparam name="T1">The component type being searched.</typeparam>
/// <returns>A sequence of T1.</returns> /// <returns>A sequence of T1.</returns>
public static IEnumerable<T1> SelectComponent<T1>(this IEnumerable<Entity> entities) public static IEnumerable<T1> SelectComponent<T1>(
this IEnumerable<Entity> entities)
{ {
foreach (Entity entity in entities) foreach (Entity entity in entities)
{ {

View file

@ -37,7 +37,8 @@ public static class SelectComponentOrDefaultExtensions
/// <param name="entities">The entities to process.</param> /// <param name="entities">The entities to process.</param>
/// <typeparam name="T1">The component type being searched.</typeparam> /// <typeparam name="T1">The component type being searched.</typeparam>
/// <returns>A sequence of T1.</returns> /// <returns>A sequence of T1.</returns>
public static IEnumerable<T1?> SelectComponentOrDefault<T1>(this IEnumerable<Entity> entities) public static IEnumerable<T1?> SelectComponentOrDefault<T1>(
this IEnumerable<Entity> entities)
{ {
foreach (Entity entity in entities) foreach (Entity entity in entities)
{ {

View file

@ -1,260 +1,279 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
namespace MfGames.Gallium namespace MfGames.Gallium;
public static class SelectEntityExtensions
{ {
public static class SelectEntityExtensions /// <summary>
/// Selects an entity from the given list, filtering on entities with
/// the given components.
/// </summary>
/// <param name="entities">The entities to parse.</param>
/// <param name="selectWithComponents">
/// The transformation function for the entity and selected components. If this
/// returns null, then the entity
/// will be filtered out.
/// </param>
/// <param name="includeEntitiesWithoutComponents">
/// If true, then entities without all the components are included. Otherwise, they
/// are excluded.
/// </param>
/// <typeparam name="T1">The type of the first component.</typeparam>
/// <returns>An enumeration of transformed entities.</returns>
public static IEnumerable<Entity> SelectEntity<T1>(
this IEnumerable<Entity> entities,
Func<Entity, T1, Entity?> selectWithComponents,
bool includeEntitiesWithoutComponents = true)
{ {
/// <summary> return entities.SelectEntity(
/// Selects an entity from the given list, filtering on entities with selectWithComponents,
/// the given components. includeEntitiesWithoutComponents ? a => a : a => null);
/// </summary> }
/// <param name="entities">The entities to parse.</param>
/// <param name="selectWithComponents">
/// The transformation function for the entity and selected components. If this
/// returns null, then the entity
/// will be filtered out.
/// </param>
/// <param name="includeEntitiesWithoutComponents">
/// If true, then entities without all the components are included. Otherwise, they
/// are excluded.
/// </param>
/// <typeparam name="T1">The type of the first component.</typeparam>
/// <returns>An enumeration of transformed entities.</returns>
public static IEnumerable<Entity> SelectEntity<T1>(
this IEnumerable<Entity> entities,
Func<Entity, T1, Entity?> selectWithComponents,
bool includeEntitiesWithoutComponents = true)
{
return entities.SelectEntity(selectWithComponents, includeEntitiesWithoutComponents ? a => a : a => null);
}
/// <summary> /// <summary>
/// Selects an entity from the given list, filtering on entities with /// Selects an entity from the given list, filtering on entities with
/// the given components. /// the given components.
/// </summary> /// </summary>
/// <param name="entities">The entities to parse.</param> /// <param name="entities">The entities to parse.</param>
/// <param name="selectWithComponents"> /// <param name="selectWithComponents">
/// The transformation function for the entity and selected components. If this /// The transformation function for the entity and selected components. If this
/// returns null, then the entity /// returns null, then the entity
/// will be filtered out. /// will be filtered out.
/// </param> /// </param>
/// <param name="includeEntitiesWithoutComponents"> /// <param name="includeEntitiesWithoutComponents">
/// If true, then entities without all the components are included. Otherwise, they /// If true, then entities without all the components are included. Otherwise, they
/// are excluded. /// are excluded.
/// </param> /// </param>
/// <typeparam name="T1">The type of the first component.</typeparam> /// <typeparam name="T1">The type of the first component.</typeparam>
/// <typeparam name="T2">The type of the second component.</typeparam> /// <typeparam name="T2">The type of the second component.</typeparam>
/// <returns>An enumeration of transformed entities.</returns> /// <returns>An enumeration of transformed entities.</returns>
public static IEnumerable<Entity> SelectEntity<T1, T2>( public static IEnumerable<Entity> SelectEntity<T1, T2>(
this IEnumerable<Entity> entities, this IEnumerable<Entity> entities,
Func<Entity, T1, T2, Entity?> selectWithComponents, Func<Entity, T1, T2, Entity?> selectWithComponents,
bool includeEntitiesWithoutComponents = true) bool includeEntitiesWithoutComponents = true)
{ {
return entities.SelectEntity(selectWithComponents, includeEntitiesWithoutComponents ? a => a : a => null); return entities.SelectEntity(
} selectWithComponents,
includeEntitiesWithoutComponents ? a => a : a => null);
}
/// <summary> /// <summary>
/// Selects an entity from the given list, filtering on entities with /// Selects an entity from the given list, filtering on entities with
/// the given components. /// the given components.
/// </summary> /// </summary>
/// <param name="entities">The entities to parse.</param> /// <param name="entities">The entities to parse.</param>
/// <param name="selectWithComponents"> /// <param name="selectWithComponents">
/// The transformation function for the entity and selected components. If this /// The transformation function for the entity and selected components. If this
/// returns null, then the entity /// returns null, then the entity
/// will be filtered out. /// will be filtered out.
/// </param> /// </param>
/// <param name="includeEntitiesWithoutComponents"> /// <param name="includeEntitiesWithoutComponents">
/// If true, then entities without all the components are included. Otherwise, they /// If true, then entities without all the components are included. Otherwise, they
/// are excluded. /// are excluded.
/// </param> /// </param>
/// <typeparam name="T1">The type of the first component.</typeparam> /// <typeparam name="T1">The type of the first component.</typeparam>
/// <typeparam name="T2">The type of the second component.</typeparam> /// <typeparam name="T2">The type of the second component.</typeparam>
/// <typeparam name="T3">The type of the third component.</typeparam> /// <typeparam name="T3">The type of the third component.</typeparam>
/// <returns>An enumeration of transformed entities.</returns> /// <returns>An enumeration of transformed entities.</returns>
public static IEnumerable<Entity> SelectEntity<T1, T2, T3>( public static IEnumerable<Entity> SelectEntity<T1, T2, T3>(
this IEnumerable<Entity> entities, this IEnumerable<Entity> entities,
Func<Entity, T1, T2, T3, Entity?> selectWithComponents, Func<Entity, T1, T2, T3, Entity?> selectWithComponents,
bool includeEntitiesWithoutComponents = true) bool includeEntitiesWithoutComponents = true)
{ {
return entities.SelectEntity(selectWithComponents, includeEntitiesWithoutComponents ? a => a : a => null); return entities.SelectEntity(
} selectWithComponents,
includeEntitiesWithoutComponents ? a => a : a => null);
}
/// <summary> /// <summary>
/// Selects an entity from the given list, filtering on entities with /// Selects an entity from the given list, filtering on entities with
/// the given components. /// the given components.
/// </summary> /// </summary>
/// <param name="entities">The entities to parse.</param> /// <param name="entities">The entities to parse.</param>
/// <param name="selectWithComponents"> /// <param name="selectWithComponents">
/// The transformation function for the entity and selected components. If this /// The transformation function for the entity and selected components. If this
/// returns null, then the entity /// returns null, then the entity
/// will be filtered out. /// will be filtered out.
/// </param> /// </param>
/// <param name="includeEntitiesWithoutComponents"> /// <param name="includeEntitiesWithoutComponents">
/// If true, then entities without all the components are included. Otherwise, they /// If true, then entities without all the components are included. Otherwise, they
/// are excluded. /// are excluded.
/// </param> /// </param>
/// <typeparam name="T1">The type of the first component.</typeparam> /// <typeparam name="T1">The type of the first component.</typeparam>
/// <typeparam name="T2">The type of the second component.</typeparam> /// <typeparam name="T2">The type of the second component.</typeparam>
/// <typeparam name="T3">The type of the third component.</typeparam> /// <typeparam name="T3">The type of the third component.</typeparam>
/// <typeparam name="T4">The type of the fourth component.</typeparam> /// <typeparam name="T4">The type of the fourth component.</typeparam>
/// <returns>An enumeration of transformed entities.</returns> /// <returns>An enumeration of transformed entities.</returns>
public static IEnumerable<Entity> SelectEntity<T1, T2, T3, T4>( public static IEnumerable<Entity> SelectEntity<T1, T2, T3, T4>(
this IEnumerable<Entity> entities, this IEnumerable<Entity> entities,
Func<Entity, T1, T2, T3, T4, Entity?> selectWithComponents, Func<Entity, T1, T2, T3, T4, Entity?> selectWithComponents,
bool includeEntitiesWithoutComponents = true) bool includeEntitiesWithoutComponents = true)
{ {
return entities.SelectEntity(selectWithComponents, includeEntitiesWithoutComponents ? a => a : a => null); return entities.SelectEntity(
} selectWithComponents,
includeEntitiesWithoutComponents ? a => a : a => null);
}
/// <summary> /// <summary>
/// Selects an entity from the given list, filtering on entities with /// Selects an entity from the given list, filtering on entities with
/// the given components. /// the given components.
/// </summary> /// </summary>
/// <param name="entities">The entities to parse.</param> /// <param name="entities">The entities to parse.</param>
/// <param name="selectWithComponents"> /// <param name="selectWithComponents">
/// The transformation function for the entity and selected components. If this /// The transformation function for the entity and selected components. If this
/// returns null, then the entity /// returns null, then the entity
/// will be filtered out. /// will be filtered out.
/// </param> /// </param>
/// <param name="selectWithoutComponents"> /// <param name="selectWithoutComponents">
/// The optional transformation function for entities that do not have all the /// The optional transformation function for entities that do not have all the
/// components. If returns null, /// components. If returns null,
/// then the entity will not be included. /// then the entity will not be included.
/// </param> /// </param>
/// <typeparam name="T1">The type of the first component.</typeparam> /// <typeparam name="T1">The type of the first component.</typeparam>
/// <returns>An enumeration of transformed entities.</returns> /// <returns>An enumeration of transformed entities.</returns>
public static IEnumerable<Entity> SelectEntity<T1>( public static IEnumerable<Entity> SelectEntity<T1>(
this IEnumerable<Entity> entities, this IEnumerable<Entity> entities,
Func<Entity, T1, Entity?> selectWithComponents, Func<Entity, T1, Entity?> selectWithComponents,
Func<Entity, Entity?> selectWithoutComponents) Func<Entity, Entity?> selectWithoutComponents)
{
foreach (Entity entity in entities)
{ {
foreach (Entity entity in entities) Entity? result = entity.TryGet(out T1 value1)
? selectWithComponents?.Invoke(entity, value1)
: selectWithoutComponents?.Invoke(entity);
if (result != null)
{ {
Entity? result = entity.TryGet(out T1 value1) yield return result;
? selectWithComponents?.Invoke(entity, value1)
: selectWithoutComponents?.Invoke(entity);
if (result != null)
{
yield return result;
}
} }
} }
}
/// <summary> /// <summary>
/// Selects an entity from the given list, filtering on entities with /// Selects an entity from the given list, filtering on entities with
/// the given components. /// the given components.
/// </summary> /// </summary>
/// <param name="entities">The entities to parse.</param> /// <param name="entities">The entities to parse.</param>
/// <param name="selectWithComponents"> /// <param name="selectWithComponents">
/// The transformation function for the entity and selected components. If this /// The transformation function for the entity and selected components. If this
/// returns null, then the entity /// returns null, then the entity
/// will be filtered out. /// will be filtered out.
/// </param> /// </param>
/// <param name="selectWithoutComponents"> /// <param name="selectWithoutComponents">
/// The optional transformation function for entities that do not have all the /// The optional transformation function for entities that do not have all the
/// components. If returns null, /// components. If returns null,
/// then the entity will not be included. /// then the entity will not be included.
/// </param> /// </param>
/// <typeparam name="T1">The type of the first component.</typeparam> /// <typeparam name="T1">The type of the first component.</typeparam>
/// <typeparam name="T2">The type of the second component.</typeparam> /// <typeparam name="T2">The type of the second component.</typeparam>
/// <returns>An enumeration of transformed entities.</returns> /// <returns>An enumeration of transformed entities.</returns>
public static IEnumerable<Entity> SelectEntity<T1, T2>( public static IEnumerable<Entity> SelectEntity<T1, T2>(
this IEnumerable<Entity> entities, this IEnumerable<Entity> entities,
Func<Entity, T1, T2, Entity?> selectWithComponents, Func<Entity, T1, T2, Entity?> selectWithComponents,
Func<Entity, Entity?> selectWithoutComponents) Func<Entity, Entity?> selectWithoutComponents)
{
foreach (Entity entity in entities)
{ {
foreach (Entity entity in entities) Entity? result = entity.TryGet(out T1 value1)
{ && entity.TryGet(out T2 value2)
Entity? result = entity.TryGet(out T1 value1) && entity.TryGet(out T2 value2)
? selectWithComponents?.Invoke(entity, value1, value2) ? selectWithComponents?.Invoke(entity, value1, value2)
: selectWithoutComponents?.Invoke(entity); : selectWithoutComponents?.Invoke(entity);
if (result != null) if (result != null)
{ {
yield return result; yield return result;
}
} }
} }
}
/// <summary> /// <summary>
/// Selects an entity from the given list, filtering on entities with /// Selects an entity from the given list, filtering on entities with
/// the given components. /// the given components.
/// </summary> /// </summary>
/// <param name="entities">The entities to parse.</param> /// <param name="entities">The entities to parse.</param>
/// <param name="selectWithComponents"> /// <param name="selectWithComponents">
/// The transformation function for the entity and selected components. If this /// The transformation function for the entity and selected components. If this
/// returns null, then the entity /// returns null, then the entity
/// will be filtered out. /// will be filtered out.
/// </param> /// </param>
/// <param name="selectWithoutComponents"> /// <param name="selectWithoutComponents">
/// The optional transformation function for entities that do not have all the /// The optional transformation function for entities that do not have all the
/// components. If returns null, /// components. If returns null,
/// then the entity will not be included. /// then the entity will not be included.
/// </param> /// </param>
/// <typeparam name="T1">The type of the first component.</typeparam> /// <typeparam name="T1">The type of the first component.</typeparam>
/// <typeparam name="T2">The type of the second component.</typeparam> /// <typeparam name="T2">The type of the second component.</typeparam>
/// <typeparam name="T3">The type of the third component.</typeparam> /// <typeparam name="T3">The type of the third component.</typeparam>
/// <returns>An enumeration of transformed entities.</returns> /// <returns>An enumeration of transformed entities.</returns>
public static IEnumerable<Entity> SelectEntity<T1, T2, T3>( public static IEnumerable<Entity> SelectEntity<T1, T2, T3>(
this IEnumerable<Entity> entities, this IEnumerable<Entity> entities,
Func<Entity, T1, T2, T3, Entity?> selectWithComponents, Func<Entity, T1, T2, T3, Entity?> selectWithComponents,
Func<Entity, Entity?> selectWithoutComponents) Func<Entity, Entity?> selectWithoutComponents)
{
foreach (Entity entity in entities)
{ {
foreach (Entity entity in entities) Entity? result =
{ entity.TryGet(out T1 value1)
Entity? result = && entity.TryGet(out T2 value2)
entity.TryGet(out T1 value1) && entity.TryGet(out T2 value2) && entity.TryGet(out T3 value3) && entity.TryGet(out T3 value3)
? selectWithComponents?.Invoke(entity, value1, value2, value3) ? selectWithComponents?.Invoke(
: selectWithoutComponents?.Invoke(entity); entity,
value1,
value2,
value3)
: selectWithoutComponents?.Invoke(entity);
if (result != null) if (result != null)
{ {
yield return result; yield return result;
}
} }
} }
}
/// <summary> /// <summary>
/// Selects an entity from the given list, filtering on entities with /// Selects an entity from the given list, filtering on entities with
/// the given components. /// the given components.
/// </summary> /// </summary>
/// <param name="entities">The entities to parse.</param> /// <param name="entities">The entities to parse.</param>
/// <param name="selectWithComponents"> /// <param name="selectWithComponents">
/// The transformation function for the entity and selected components. If this /// The transformation function for the entity and selected components. If this
/// returns null, then the entity /// returns null, then the entity
/// will be filtered out. /// will be filtered out.
/// </param> /// </param>
/// <param name="selectWithoutComponents"> /// <param name="selectWithoutComponents">
/// The optional transformation function for entities that do not have all the /// The optional transformation function for entities that do not have all the
/// components. If returns null, /// components. If returns null,
/// then the entity will not be included. /// then the entity will not be included.
/// </param> /// </param>
/// <typeparam name="T1">The type of the first component.</typeparam> /// <typeparam name="T1">The type of the first component.</typeparam>
/// <typeparam name="T2">The type of the second component.</typeparam> /// <typeparam name="T2">The type of the second component.</typeparam>
/// <typeparam name="T3">The type of the third component.</typeparam> /// <typeparam name="T3">The type of the third component.</typeparam>
/// <typeparam name="T4">The type of the third component.</typeparam> /// <typeparam name="T4">The type of the third component.</typeparam>
/// <returns>An enumeration of transformed entities.</returns> /// <returns>An enumeration of transformed entities.</returns>
public static IEnumerable<Entity> SelectEntity<T1, T2, T3, T4>( public static IEnumerable<Entity> SelectEntity<T1, T2, T3, T4>(
this IEnumerable<Entity> entities, this IEnumerable<Entity> entities,
Func<Entity, T1, T2, T3, T4, Entity?> selectWithComponents, Func<Entity, T1, T2, T3, T4, Entity?> selectWithComponents,
Func<Entity, Entity?> selectWithoutComponents) Func<Entity, Entity?> selectWithoutComponents)
{
foreach (Entity entity in entities)
{ {
foreach (Entity entity in entities) Entity? result =
{ entity.TryGet(out T1 value1)
Entity? result = && entity.TryGet(out T2 value2)
entity.TryGet(out T1 value1) && entity.TryGet(out T3 value3)
&& entity.TryGet(out T2 value2) && entity.TryGet(out T4 value4)
&& entity.TryGet(out T3 value3) ? selectWithComponents?.Invoke(
&& entity.TryGet(out T4 value4) entity,
? selectWithComponents?.Invoke(entity, value1, value2, value3, value4) value1,
: selectWithoutComponents?.Invoke(entity); value2,
value3,
value4)
: selectWithoutComponents?.Invoke(entity);
if (result != null) if (result != null)
{ {
yield return result; yield return result;
}
} }
} }
} }

View file

@ -189,7 +189,9 @@ public static class SplitEntityExtensions
Type t1, Type t1,
Func<Entity, object, bool> test) Func<Entity, object, bool> test)
{ {
return SplitEntity(entities, a => a.Has(t1) && test(a, a.Get<object>(t1))); return SplitEntity(
entities,
a => a.Has(t1) && test(a, a.Get<object>(t1)));
} }
/// <summary> /// <summary>

View file

@ -2,47 +2,46 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
namespace MfGames.Gallium namespace MfGames.Gallium;
public static class WhereEntityExtensions
{ {
public static class WhereEntityExtensions public static IEnumerable<Entity> WhereEntity<T1>(
this IEnumerable<Entity> entities,
Func<Entity, T1, bool> include)
{ {
public static IEnumerable<Entity> WhereEntity<T1>( return entities.Where(x => x.Has<T1>() && include(x, x.Get<T1>()));
this IEnumerable<Entity> entities, }
Func<Entity, T1, bool> include)
{
return entities.Where(x => x.Has<T1>() && include(x, x.Get<T1>()));
}
public static IEnumerable<Entity> WhereEntity<T1, T2>( public static IEnumerable<Entity> WhereEntity<T1, T2>(
this IEnumerable<Entity> entities, this IEnumerable<Entity> entities,
Func<Entity, T1, T2, bool> include) Func<Entity, T1, T2, bool> include)
{ {
return entities.Where( return entities.Where(
x => x.HasAll<T1, T2>() x => x.HasAll<T1, T2>()
&& include(x, x.Get<T1>(), x.Get<T2>())); && include(x, x.Get<T1>(), x.Get<T2>()));
} }
public static IEnumerable<Entity> WhereEntity<T1, T2, T3>( public static IEnumerable<Entity> WhereEntity<T1, T2, T3>(
this IEnumerable<Entity> entities, this IEnumerable<Entity> entities,
Func<Entity, T1, T2, T3, bool> include) Func<Entity, T1, T2, T3, bool> include)
{ {
return entities.Where( return entities.Where(
x => x.HasAll<T1, T2, T3>() x => x.HasAll<T1, T2, T3>()
&& include(x, x.Get<T1>(), x.Get<T2>(), x.Get<T3>())); && include(x, x.Get<T1>(), x.Get<T2>(), x.Get<T3>()));
} }
public static IEnumerable<Entity> WhereEntity<T1, T2, T3, T4>( public static IEnumerable<Entity> WhereEntity<T1, T2, T3, T4>(
this IEnumerable<Entity> entities, this IEnumerable<Entity> entities,
Func<Entity, T1, T2, T3, T4, bool> include) Func<Entity, T1, T2, T3, T4, bool> include)
{ {
return entities.Where( return entities.Where(
x => x.HasAll<T1, T2, T3, T4>() x => x.HasAll<T1, T2, T3, T4>()
&& include( && include(
x, x,
x.Get<T1>(), x.Get<T1>(),
x.Get<T2>(), x.Get<T2>(),
x.Get<T3>(), x.Get<T3>(),
x.Get<T4>())); x.Get<T4>()));
}
} }
} }

View file

@ -1,28 +1,31 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
namespace MfGames.Gallium namespace MfGames.Gallium;
public static class WhereEntityHasExtensions
{ {
public static class WhereEntityHasExtensions public static IEnumerable<Entity> WhereEntityHas<T1>(
this IEnumerable<Entity> entities)
{ {
public static IEnumerable<Entity> WhereEntityHas<T1>(this IEnumerable<Entity> entities) return entities.Where(x => x.Has<T1>());
{ }
return entities.Where(x => x.Has<T1>());
}
public static IEnumerable<Entity> WhereEntityHasAll<T1, T2>(this IEnumerable<Entity> entities) public static IEnumerable<Entity> WhereEntityHasAll
{ <T1, T2>(this IEnumerable<Entity> entities)
return entities.Where(x => x.HasAll<T1, T2>()); {
} return entities.Where(x => x.HasAll<T1, T2>());
}
public static IEnumerable<Entity> WhereEntityHasAll<T1, T2, T3>(this IEnumerable<Entity> entities) public static IEnumerable<Entity> WhereEntityHasAll
{ <T1, T2, T3>(this IEnumerable<Entity> entities)
return entities.Where(x => x.HasAll<T1, T2, T3>()); {
} return entities.Where(x => x.HasAll<T1, T2, T3>());
}
public static IEnumerable<Entity> WhereEntityHasAll<T1, T2, T3, T4>(this IEnumerable<Entity> entities) public static IEnumerable<Entity> WhereEntityHasAll
{ <T1, T2, T3, T4>(this IEnumerable<Entity> entities)
return entities.Where(x => x.HasAll<T1, T2, T3, T4>()); {
} return entities.Where(x => x.HasAll<T1, T2, T3, T4>());
} }
} }

View file

@ -1,28 +1,31 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
namespace MfGames.Gallium namespace MfGames.Gallium;
public static class WhereEntityNotHasExtensions
{ {
public static class WhereEntityNotHasExtensions public static IEnumerable<Entity> WhereEntityNotHas<T1>(
this IEnumerable<Entity> entities)
{ {
public static IEnumerable<Entity> WhereEntityNotHas<T1>(this IEnumerable<Entity> entities) return entities.Where(x => !x.Has<T1>());
{ }
return entities.Where(x => !x.Has<T1>());
}
public static IEnumerable<Entity> WhereEntityNotHasAll<T1, T2>(this IEnumerable<Entity> entities) public static IEnumerable<Entity> WhereEntityNotHasAll
{ <T1, T2>(this IEnumerable<Entity> entities)
return entities.Where(x => !x.HasAll<T1, T2>()); {
} return entities.Where(x => !x.HasAll<T1, T2>());
}
public static IEnumerable<Entity> WhereEntityNotHasAll<T1, T2, T3>(this IEnumerable<Entity> entities) public static IEnumerable<Entity> WhereEntityNotHasAll
{ <T1, T2, T3>(this IEnumerable<Entity> entities)
return entities.Where(x => !x.HasAll<T1, T2, T3>()); {
} return entities.Where(x => !x.HasAll<T1, T2, T3>());
}
public static IEnumerable<Entity> WhereEntityNotHasAll<T1, T2, T3, T4>(this IEnumerable<Entity> entities) public static IEnumerable<Entity> WhereEntityNotHasAll
{ <T1, T2, T3, T4>(this IEnumerable<Entity> entities)
return entities.Where(x => !x.HasAll<T1, T2, T3, T4>()); {
} return entities.Where(x => !x.HasAll<T1, T2, T3, T4>());
} }
} }

View file

@ -1,216 +1,252 @@
using System; using System;
using MfGames.Gallium;
using Xunit; using Xunit;
using Xunit.Abstractions; using Xunit.Abstractions;
namespace MfGames.Gallium.Tests namespace MfGames.Gallium.Tests;
public class EntityTests : GalliumTestsBase
{ {
public class EntityTests : GalliumTestsBase public EntityTests(ITestOutputHelper output)
: base(output)
{ {
public EntityTests(ITestOutputHelper output) }
: base(output)
{
}
[Fact] [Fact]
public void AddingComponentOnceWorks() public void AddingComponentOnceWorks()
{ {
var component1 = new TestComponent1(); var component1 = new TestComponent1();
Entity entity1 = new Entity().Add(component1); Entity entity1 = new Entity().Add(component1);
Assert.Equal(1, entity1.Count); Assert.Equal(1, entity1.Count);
Assert.True(entity1.Has<TestComponent1>()); Assert.True(entity1.Has<TestComponent1>());
Assert.Equal(component1, entity1.Get<TestComponent1>()); Assert.Equal(component1, entity1.Get<TestComponent1>());
} }
[Fact] [Fact]
public void AddingComponentViaInterfaceWork() public void AddingComponentViaInterfaceWork()
{ {
var component1 = new TestComponent3a(); var component1 = new TestComponent3a();
Entity entity1 = new Entity().Add<ITestComponent3>(component1); Entity entity1 = new Entity().Add<ITestComponent3>(component1);
Assert.Equal(1, entity1.Count); Assert.Equal(1, entity1.Count);
Assert.False(entity1.Has<TestComponent3a>()); Assert.False(entity1.Has<TestComponent3a>());
Assert.True(entity1.Has<ITestComponent3>()); Assert.True(entity1.Has<ITestComponent3>());
Assert.Equal(component1, entity1.Get<ITestComponent3>()); Assert.Equal(component1, entity1.Get<ITestComponent3>());
} }
[Fact] [Fact]
public void AddingTwiceThrowsException() public void AddingTwiceThrowsException()
{ {
var component1 = new TestComponent1(); var component1 = new TestComponent1();
Exception exception = Assert.Throws<ArgumentException>( Exception exception = Assert.Throws<ArgumentException>(
() => new Entity() () => new Entity()
.Add(component1) .Add(component1)
.Add(component1)); .Add(component1));
Assert.Equal( Assert.Equal(
"An element with the same type " "An element with the same type "
+ "(MfGames.Gallium.Tests.TestComponent1)" + "(MfGames.Gallium.Tests.TestComponent1)"
+ " already exists. (Parameter 'component')", + " already exists. (Parameter 'component')",
exception.Message); exception.Message);
} }
[Fact] [Fact]
public void CopyEntityAlsoCopiesComponents() public void CopyEntityAlsoCopiesComponents()
{ {
var component1 = new TestComponent1(); var component1 = new TestComponent1();
Entity entity1 = new Entity().Add(component1); Entity entity1 = new Entity().Add(component1);
Entity entity2 = entity1.Copy(); Entity entity2 = entity1.Copy();
Assert.Equal(1, entity2.Count); Assert.Equal(1, entity2.Count);
Assert.True(entity2.Has<TestComponent1>()); Assert.True(entity2.Has<TestComponent1>());
Assert.Equal(component1, entity2.Get<TestComponent1>()); Assert.Equal(component1, entity2.Get<TestComponent1>());
} }
[Fact] [Fact]
public void ExactCopyEntityAlsoCopiesComponents() public void ExactCopyEntityAlsoCopiesComponents()
{ {
var component1 = new TestComponent1(); var component1 = new TestComponent1();
Entity entity1 = new Entity().Add(component1); Entity entity1 = new Entity().Add(component1);
Entity entity2 = entity1.ExactCopy(); Entity entity2 = entity1.ExactCopy();
Assert.Equal(1, entity2.Count); Assert.Equal(1, entity2.Count);
Assert.True(entity2.Has<TestComponent1>()); Assert.True(entity2.Has<TestComponent1>());
Assert.Equal(component1, entity2.Get<TestComponent1>()); Assert.Equal(component1, entity2.Get<TestComponent1>());
} }
[Fact] [Fact]
public void GetOptionalWorks() public void GetOptionalWorks()
{ {
var component1 = new TestComponent1(); var component1 = new TestComponent1();
Entity entity1 = new Entity().Add(component1); Entity entity1 = new Entity().Add(component1);
Assert.Equal(component1, entity1.GetOptional<TestComponent1>()); Assert.Equal(component1, entity1.GetOptional<TestComponent1>());
Assert.Null(entity1.GetOptional<TestComponent2>()); Assert.Null(entity1.GetOptional<TestComponent2>());
} }
[Fact] [Fact]
public void HasReturnsFalseIfNotRegistered() public void HasReturnsFalseIfNotRegistered()
{ {
var entity1 = new Entity(); var entity1 = new Entity();
Assert.False(entity1.Has<TestComponent1>()); Assert.False(entity1.Has<TestComponent1>());
} }
[Fact] [Fact]
public void NewEntityHasNoComponents() public void NewEntityHasNoComponents()
{ {
var entity1 = new Entity(); var entity1 = new Entity();
Assert.Equal(0, entity1.Count); Assert.Equal(0, entity1.Count);
} }
[Fact] [Fact]
public void RemoveAlreadyMissingComponentWorks() public void RemoveAlreadyMissingComponentWorks()
{ {
var entity1 = new Entity(); var entity1 = new Entity();
Assert.Equal(0, entity1.Count); Assert.Equal(0, entity1.Count);
Entity entity2 = entity1.Remove<TestComponent1>(); Entity entity2 = entity1.Remove<TestComponent1>();
Assert.Equal(0, entity1.Count); Assert.Equal(0, entity1.Count);
Assert.Equal(0, entity2.Count); Assert.Equal(0, entity2.Count);
} }
[Fact] [Fact]
public void RemoveComponentDoesNotRemoveFromCopies() public void RemoveComponentDoesNotRemoveFromCopies()
{ {
var component1 = new TestComponent1(); var component1 = new TestComponent1();
Entity entity1 = new Entity().Add(component1); Entity entity1 = new Entity().Add(component1);
Entity entity2 = entity1.ExactCopy(); Entity entity2 = entity1.ExactCopy();
Entity entity3 = entity1.Copy(); Entity entity3 = entity1.Copy();
Assert.Equal(1, entity1.Count); Assert.Equal(1, entity1.Count);
Assert.Equal(1, entity2.Count); Assert.Equal(1, entity2.Count);
Assert.Equal(1, entity3.Count); Assert.Equal(1, entity3.Count);
Entity entity1A = entity1.Remove<TestComponent1>(); Entity entity1A = entity1.Remove<TestComponent1>();
Assert.Equal(1, entity1.Count); Assert.Equal(1, entity1.Count);
Assert.Equal(0, entity1A.Count); Assert.Equal(0, entity1A.Count);
Assert.Equal(1, entity2.Count); Assert.Equal(1, entity2.Count);
Assert.Equal(1, entity3.Count); Assert.Equal(1, entity3.Count);
} }
[Fact] [Fact]
public void RemoveComponentWorks() public void RemoveComponentWorks()
{ {
var component1 = new TestComponent1(); var component1 = new TestComponent1();
Entity entity1 = new Entity().Add(component1); Entity entity1 = new Entity().Add(component1);
Assert.Equal(1, entity1.Count); Assert.Equal(1, entity1.Count);
Entity entity2 = entity1.Remove<TestComponent1>(); Entity entity2 = entity1.Remove<TestComponent1>();
Assert.Equal(1, entity1.Count); Assert.Equal(1, entity1.Count);
Assert.Equal(0, entity2.Count); Assert.Equal(0, entity2.Count);
} }
[Fact] [Fact]
public void SettingComponentsWorks() public void SetAllSkipsNull()
{ {
var component1 = new TestComponent3a(); var component1 = new TestComponent1();
var component2 = new TestComponent3b(); var component2 = new TestComponent2();
Entity entity1 = new Entity().SetAll(component1, null);
Entity entity1 = new Entity() Assert.Equal(1, entity1.Count);
.Set<ITestComponent3>(component1) Assert.True(entity1.Has<TestComponent1>());
.Set<ITestComponent3>(component1) Assert.False(entity1.Has<TestComponent2>());
.Set<ITestComponent3>(component2); }
Assert.Equal(1, entity1.Count); [Fact]
Assert.Equal(component2, entity1.Get<ITestComponent3>()); public void SetAllWithNothingWorks()
} {
Entity entity1 = new Entity().SetAll();
[Fact] Assert.Equal(0, entity1.Count);
public void TryGetWorks() Assert.False(entity1.Has<TestComponent1>());
{ Assert.False(entity1.Has<TestComponent2>());
var component1 = new TestComponent1(); }
Entity entity1 = new Entity().Add(component1);
bool result1 = entity1.TryGet(out TestComponent1 value1); [Fact]
public void SetAllWorks()
{
var component1 = new TestComponent1();
var component2 = new TestComponent2();
Entity entity1 = new Entity().SetAll(component1, component2);
Assert.True(result1); Assert.Equal(2, entity1.Count);
Assert.Equal(component1, value1); Assert.True(entity1.Has<TestComponent1>());
Assert.True(entity1.Has<TestComponent2>());
Assert.False(entity1.Has<TestComponent3a>());
}
bool result2 = entity1.TryGet(out TestComponent2 _); [Fact]
public void SettingComponentsWorks()
{
var component1 = new TestComponent3a();
var component2 = new TestComponent3b();
Assert.False(result2); Entity entity1 = new Entity()
} .Set<ITestComponent3>(component1)
.Set<ITestComponent3>(component1)
.Set<ITestComponent3>(component2);
[Fact] Assert.Equal(1, entity1.Count);
public void TwoCopiesHaveDifferentIds() Assert.Equal(component2, entity1.Get<ITestComponent3>());
{ }
var entity1 = new Entity();
Entity entity2 = entity1.Copy();
Assert.NotEqual(entity1.Id, entity2.Id); [Fact]
Assert.NotEqual(entity1, entity2); public void TryGetWorks()
Assert.False(entity1 == entity2); {
} var component1 = new TestComponent1();
Entity entity1 = new Entity().Add(component1);
[Fact] bool result1 = entity1.TryGet(out TestComponent1 value1);
public void TwoEntitiesHaveDifferentIds()
{
var entity1 = new Entity();
var entity2 = new Entity();
Assert.NotEqual(entity1.Id, entity2.Id); Assert.True(result1);
Assert.NotEqual(entity1, entity2); Assert.Equal(component1, value1);
Assert.False(entity1 == entity2);
}
[Fact] bool result2 = entity1.TryGet(out TestComponent2 _);
public void TwoExactCopiesHaveDifferentIds()
{
var entity1 = new Entity();
Entity entity2 = entity1.ExactCopy();
Assert.Equal(entity1.Id, entity2.Id); Assert.False(result2);
Assert.Equal(entity1, entity2); }
Assert.True(entity1 == entity2);
} [Fact]
public void TwoCopiesHaveDifferentIds()
{
var entity1 = new Entity();
Entity entity2 = entity1.Copy();
Assert.NotEqual(entity1.Id, entity2.Id);
Assert.NotEqual(entity1, entity2);
Assert.False(entity1 == entity2);
}
[Fact]
public void TwoEntitiesHaveDifferentIds()
{
var entity1 = new Entity();
var entity2 = new Entity();
Assert.NotEqual(entity1.Id, entity2.Id);
Assert.NotEqual(entity1, entity2);
Assert.False(entity1 == entity2);
}
[Fact]
public void TwoExactCopiesHaveDifferentIds()
{
var entity1 = new Entity();
Entity entity2 = entity1.ExactCopy();
Assert.Equal(entity1.Id, entity2.Id);
Assert.Equal(entity1, entity2);
Assert.True(entity1 == entity2);
} }
} }

View file

@ -1,215 +1,221 @@
using System.Linq; using System.Linq;
using MfGames.Gallium;
using Xunit; using Xunit;
namespace MfGames.Gallium.Tests namespace MfGames.Gallium.Tests;
public class EnumerableEntityTests
{ {
public class EnumerableEntityTests [Fact]
public void ForComponentsC1()
{ {
[Fact] Entity[] entities =
public void ForComponentsC1()
{ {
Entity[] entities = new Entity().Add("1")
{ .Add(new TestComponent1()),
new Entity().Add("1") new Entity().Add("2")
.Add(new TestComponent1()), .Add(new TestComponent2()),
new Entity().Add("2") new Entity().Add("3")
.Add(new TestComponent2()), .Add(new TestComponent1())
new Entity().Add("3") };
.Add(new TestComponent1()),
};
Assert.Equal( Assert.Equal(
new[] { "1!", "2", "3!" }, new[] { "1!", "2", "3!" },
entities.SelectEntity<TestComponent1>( entities.SelectEntity<TestComponent1>(
( (
e, e,
_) => e.Set(e.Get<string>() + "!")) _) => e.Set(e.Get<string>() + "!"))
.Select(x => x.Get<string>()) .Select(x => x.Get<string>())
.ToArray()); .ToArray());
} }
[Fact] [Fact]
public void ForComponentsC2() public void ForComponentsC2()
{
Entity[] entities =
{ {
Entity[] entities = new Entity().Add("1")
{ .Add(new TestComponent1()),
new Entity().Add("1") new Entity().Add("2")
.Add(new TestComponent1()), .Add(new TestComponent2()),
new Entity().Add("2") new Entity().Add("3")
.Add(new TestComponent2()), .Add(new TestComponent1())
new Entity().Add("3") .Add(new TestComponent2())
.Add(new TestComponent1()) };
.Add(new TestComponent2()),
};
Assert.Equal( Assert.Equal(
new[] { "1", "2", "3!" }, new[] { "1", "2", "3!" },
entities.SelectEntity<TestComponent1, TestComponent2>( entities.SelectEntity<TestComponent1, TestComponent2>(
( (
e, e,
_, _,
_) => e.Set(e.Get<string>() + "!")) _) => e.Set(e.Get<string>() + "!"))
.Select(x => x.Get<string>()) .Select(x => x.Get<string>())
.ToArray()); .ToArray());
} }
[Fact] [Fact]
public void ForComponentsC3() public void ForComponentsC3()
{
Entity[] entities =
{ {
Entity[] entities = new Entity().Add("1")
{ .Add(new TestComponent1()),
new Entity().Add("1") new Entity().Add("2")
.Add(new TestComponent1()), .Add(new TestComponent2())
new Entity().Add("2") .Add<ITestComponent3>(new TestComponent3b()),
.Add(new TestComponent2()) new Entity().Add("3")
.Add<ITestComponent3>(new TestComponent3b()), .Add<ITestComponent3>(new TestComponent3a())
new Entity().Add("3") .Add(new TestComponent1())
.Add<ITestComponent3>(new TestComponent3a()) .Add(new TestComponent2())
.Add(new TestComponent1()) };
.Add(new TestComponent2()),
};
Assert.Equal( Assert.Equal(
new[] { "1", "2", "3-TestComponent3a" }, new[] { "1", "2", "3-TestComponent3a" },
entities.SelectEntity<TestComponent1, TestComponent2, ITestComponent3>( entities
( .SelectEntity<TestComponent1, TestComponent2, ITestComponent3>(
e, (
_, e,
_, _,
t) => e.Set( _,
e.Get<string>() t) => e.Set(
+ "-" e.Get<string>()
+ t.GetType() + "-"
.Name)) + t.GetType()
.Select(x => x.Get<string>()) .Name))
.ToArray()); .Select(x => x.Get<string>())
} .ToArray());
}
[Fact] [Fact]
public void HasComponentsC1() public void HasComponentsC1()
{
Entity[] entities =
{ {
Entity[] entities = new Entity().Add("1")
{ .Add(new TestComponent1()),
new Entity().Add("1") new Entity().Add("2")
.Add(new TestComponent1()), .Add(new TestComponent2()),
new Entity().Add("2") new Entity().Add("3")
.Add(new TestComponent2()), .Add(new TestComponent1())
new Entity().Add("3") };
.Add(new TestComponent1()),
};
Assert.Equal( Assert.Equal(
new[] { "1", "3" }, new[] { "1", "3" },
entities.WhereEntityHas<TestComponent1>() entities.WhereEntityHas<TestComponent1>()
.Select(x => x.Get<string>()) .Select(x => x.Get<string>())
.ToArray()); .ToArray());
} }
[Fact] [Fact]
public void HasComponentsC2() public void HasComponentsC2()
{
Entity[] entities =
{ {
Entity[] entities = new Entity().Add("1")
{ .Add(new TestComponent1()),
new Entity().Add("1") new Entity().Add("2")
.Add(new TestComponent1()), .Add(new TestComponent2())
new Entity().Add("2") .Add(new TestComponent1()),
.Add(new TestComponent2()) new Entity().Add("3")
.Add(new TestComponent1()), .Add(new TestComponent1())
new Entity().Add("3") };
.Add(new TestComponent1()),
};
Assert.Equal( Assert.Equal(
new[] { "2" }, new[] { "2" },
entities.WhereEntityHasAll<TestComponent1, TestComponent2>() entities.WhereEntityHasAll<TestComponent1, TestComponent2>()
.Select(x => x.Get<string>()) .Select(x => x.Get<string>())
.ToArray()); .ToArray());
} }
[Fact] [Fact]
public void HasComponentsC3() public void HasComponentsC3()
{
Entity[] entities =
{ {
Entity[] entities = new Entity().Add("1")
{ .Add(new TestComponent1())
new Entity().Add("1") .Add<ITestComponent3>(new TestComponent3b())
.Add(new TestComponent1()) .Add(new TestComponent2()),
.Add<ITestComponent3>(new TestComponent3b()) new Entity().Add("2")
.Add(new TestComponent2()), .Add(new TestComponent2())
new Entity().Add("2") .Add(new TestComponent1()),
.Add(new TestComponent2()) new Entity().Add("3")
.Add(new TestComponent1()), .Add<ITestComponent3>(new TestComponent3a())
new Entity().Add("3") };
.Add<ITestComponent3>(new TestComponent3a()),
};
Assert.Equal( Assert.Equal(
new[] { "1" }, new[] { "1" },
entities.WhereEntityHasAll<TestComponent1, TestComponent2, ITestComponent3>() entities
.Select(x => x.Get<string>()) .WhereEntityHasAll<TestComponent1, TestComponent2,
.ToArray()); ITestComponent3>()
} .Select(x => x.Get<string>())
.ToArray());
}
[Fact] [Fact]
public void NotComponentsC1() public void NotComponentsC1()
{
Entity[] entities =
{ {
Entity[] entities = new Entity().Add("1")
{ .Add(new TestComponent1()),
new Entity().Add("1") new Entity().Add("2")
.Add(new TestComponent1()), .Add(new TestComponent2()),
new Entity().Add("2") new Entity().Add("3")
.Add(new TestComponent2()), .Add(new TestComponent1())
new Entity().Add("3") };
.Add(new TestComponent1()),
};
Assert.Equal( Assert.Equal(
new[] { "2" }, new[] { "2" },
entities.WhereEntityNotHas<TestComponent1>() entities.WhereEntityNotHas<TestComponent1>()
.Select(x => x.Get<string>()) .Select(x => x.Get<string>())
.ToArray()); .ToArray());
} }
[Fact] [Fact]
public void NotComponentsC2() public void NotComponentsC2()
{
Entity[] entities =
{ {
Entity[] entities = new Entity().Add("1")
{ .Add(new TestComponent1()),
new Entity().Add("1") new Entity().Add("2")
.Add(new TestComponent1()), .Add(new TestComponent2())
new Entity().Add("2") .Add(new TestComponent1()),
.Add(new TestComponent2()) new Entity().Add("3")
.Add(new TestComponent1()), };
new Entity().Add("3"),
};
Assert.Equal( Assert.Equal(
new[] { "1", "3" }, new[] { "1", "3" },
entities.WhereEntityNotHasAll<TestComponent1, TestComponent2>() entities.WhereEntityNotHasAll<TestComponent1, TestComponent2>()
.Select(x => x.Get<string>()) .Select(x => x.Get<string>())
.ToArray()); .ToArray());
} }
[Fact] [Fact]
public void NotComponentsC3() public void NotComponentsC3()
{
Entity[] entities =
{ {
Entity[] entities = new Entity().Add("1")
{ .Add(new TestComponent1()),
new Entity().Add("1") new Entity().Add("2")
.Add(new TestComponent1()), .Add(new TestComponent1())
new Entity().Add("2") .Add(new TestComponent2())
.Add(new TestComponent1()) .Add<ITestComponent3>(new TestComponent3b()),
.Add(new TestComponent2()) new Entity().Add("3")
.Add<ITestComponent3>(new TestComponent3b()), .Add<ITestComponent3>(new TestComponent3a())
new Entity().Add("3") };
.Add<ITestComponent3>(new TestComponent3a()),
};
Assert.Equal( Assert.Equal(
new string[] { "1", "3" }, new[] { "1", "3" },
entities.WhereEntityNotHasAll<TestComponent1, TestComponent2, ITestComponent3>() entities
.Select(x => x.Get<string>()) .WhereEntityNotHasAll<TestComponent1, TestComponent2,
.ToArray()); ITestComponent3>()
} .Select(x => x.Get<string>())
.ToArray());
} }
} }

View file

@ -3,39 +3,38 @@ using Serilog.Core;
using Xunit.Abstractions; using Xunit.Abstractions;
namespace MfGames.Gallium.Tests namespace MfGames.Gallium.Tests;
/// <summary>
/// Common initialization logic for Gallium-based tests including setting
/// up containers, logging, and Serilog.
/// </summary>
public abstract class GalliumTestsBase
{ {
/// <summary> protected GalliumTestsBase(ITestOutputHelper output)
/// Common initialization logic for Gallium-based tests including setting
/// up containers, logging, and Serilog.
/// </summary>
public abstract class GalliumTestsBase
{ {
protected GalliumTestsBase(ITestOutputHelper output) this.Output = output;
{
this.Output = output;
// Set up logging. // Set up logging.
const string Template = const string Template =
"[{Level:u3}] " "[{Level:u3}] "
+ "({SourceContext}) {Message}" + "({SourceContext}) {Message}"
+ "{NewLine}{Exception}"; + "{NewLine}{Exception}";
this.Logger = new LoggerConfiguration() this.Logger = new LoggerConfiguration()
.WriteTo.TestOutput( .WriteTo.TestOutput(
output, output,
outputTemplate: Template) outputTemplate: Template)
.CreateLogger(); .CreateLogger();
}
/// <summary>
/// Gets the output for the tests.
/// </summary>
public ITestOutputHelper Output { get; }
/// <summary>
/// Gets the logger used to report messages about the test.
/// </summary>
protected Logger Logger { get; }
} }
/// <summary>
/// Gets the output for the tests.
/// </summary>
public ITestOutputHelper Output { get; }
/// <summary>
/// Gets the logger used to report messages about the test.
/// </summary>
protected Logger Logger { get; }
} }

View file

@ -1,6 +1,5 @@
namespace MfGames.Gallium.Tests namespace MfGames.Gallium.Tests;
public interface ITestComponent3
{ {
public interface ITestComponent3
{
}
} }

View file

@ -10,10 +10,10 @@
<Version>1.4.0</Version> <Version>1.4.0</Version>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.1" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.1"/>
<PackageReference Include="Serilog.Sinks.XUnit" Version="3.0.3" /> <PackageReference Include="Serilog.Sinks.XUnit" Version="3.0.3"/>
<PackageReference Include="JunitXml.TestLogger" Version="3.0.114" /> <PackageReference Include="JunitXml.TestLogger" Version="3.0.114"/>
<PackageReference Include="xunit" Version="2.4.2" /> <PackageReference Include="xunit" Version="2.4.2"/>
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5"> <PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
@ -24,6 +24,6 @@
</PackageReference> </PackageReference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\..\src\MfGames.Gallium\MfGames.Gallium.csproj" /> <ProjectReference Include="..\..\src\MfGames.Gallium\MfGames.Gallium.csproj"/>
</ItemGroup> </ItemGroup>
</Project> </Project>

View file

@ -1,6 +1,5 @@
namespace MfGames.Gallium.Tests namespace MfGames.Gallium.Tests;
public class TestComponent1
{ {
public class TestComponent1
{
}
} }

View file

@ -1,6 +1,5 @@
namespace MfGames.Gallium.Tests namespace MfGames.Gallium.Tests;
public class TestComponent2
{ {
public class TestComponent2
{
}
} }

View file

@ -1,6 +1,5 @@
namespace MfGames.Gallium.Tests namespace MfGames.Gallium.Tests;
public class TestComponent3a : ITestComponent3
{ {
public class TestComponent3a : ITestComponent3
{
}
} }

View file

@ -1,6 +1,5 @@
namespace MfGames.Gallium.Tests namespace MfGames.Gallium.Tests;
public class TestComponent3b : ITestComponent3
{ {
public class TestComponent3b : ITestComponent3
{
}
} }