mirror of
https://github.com/space-wizards/RobustToolbox.git
synced 2026-09-01 17:47:24 +02:00
* Implement the singleton methods. * Fix API + Tests. * Move remark. * Typo fix + Proxies. * Pause remarks. * No, really, we don't obey paused! * Release notes. * testdocs. * Poke * The API design axe. * Update Robust.Shared.IntegrationTests/GameObjects/EntityManagerSingletonTests.cs Co-authored-by: pathetic meowmeow <uhhadd@gmail.com> * Remove unused doc comment blerb --------- Co-authored-by: pathetic meowmeow <uhhadd@gmail.com> Co-authored-by: PJB3005 <pieterjan.briers+git@gmail.com>
240 lines
7.6 KiB
C#
240 lines
7.6 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics.CodeAnalysis;
|
|
using System.Linq;
|
|
using Robust.Shared.Map;
|
|
using Robust.Shared.Prototypes;
|
|
using Robust.Shared.Utility;
|
|
|
|
namespace Robust.Shared.GameObjects;
|
|
|
|
public abstract partial class EntityManager
|
|
{
|
|
public Entity<TComp1> Single<TComp1>()
|
|
where TComp1: IComponent
|
|
{
|
|
var index = _entTraitArray[CompIdx.ArrayIndex<TComp1>()];
|
|
|
|
if (index.Keys.FirstOrNull() is { } ent && index.Count == 1)
|
|
{
|
|
return new Entity<TComp1>(ent, (TComp1)index[ent]);
|
|
}
|
|
|
|
if (index.Count > 1)
|
|
{
|
|
throw new NonUniqueSingletonException(index.Keys.ToArray(), typeof(TComp1));
|
|
}
|
|
else
|
|
{
|
|
// 0.
|
|
throw new MatchNotFoundException(typeof(TComp1));
|
|
}
|
|
}
|
|
|
|
public Entity<TComp1, TComp2> Single<TComp1, TComp2>()
|
|
where TComp1: IComponent
|
|
where TComp2: IComponent
|
|
{
|
|
var query = AllEntityQueryEnumerator<TComp1, TComp2>();
|
|
|
|
if (!query.MoveNext(out var ent, out var comp1, out var comp2))
|
|
throw new MatchNotFoundException(typeof(TComp1), typeof(TComp2));
|
|
|
|
if (query.MoveNext(out var ent2, out _, out _))
|
|
{
|
|
var list = new List<EntityUid> { ent, ent2 };
|
|
|
|
while (query.MoveNext(out var ent3, out _, out _))
|
|
{
|
|
list.Add(ent3);
|
|
}
|
|
|
|
throw new NonUniqueSingletonException(list.ToArray(), typeof(TComp1), typeof(TComp2));
|
|
}
|
|
|
|
return new(ent, comp1, comp2);
|
|
}
|
|
|
|
public Entity<TComp1, TComp2, TComp3> Single<TComp1, TComp2, TComp3>()
|
|
where TComp1: IComponent
|
|
where TComp2: IComponent
|
|
where TComp3: IComponent
|
|
{
|
|
var query = AllEntityQueryEnumerator<TComp1, TComp2, TComp3>();
|
|
|
|
if (!query.MoveNext(out var ent, out var comp1, out var comp2, out var comp3))
|
|
throw new MatchNotFoundException(typeof(TComp1), typeof(TComp2), typeof(TComp3));
|
|
|
|
if (query.MoveNext(out var ent2, out _, out _, out _))
|
|
{
|
|
var list = new List<EntityUid> { ent, ent2 };
|
|
|
|
while (query.MoveNext(out var ent3, out _, out _, out _))
|
|
{
|
|
list.Add(ent3);
|
|
}
|
|
|
|
throw new NonUniqueSingletonException(list.ToArray(), typeof(TComp1), typeof(TComp2), typeof(TComp3));
|
|
}
|
|
|
|
return new(ent, comp1, comp2, comp3);
|
|
}
|
|
|
|
public Entity<TComp1, TComp2, TComp3, TComp4> Single<TComp1, TComp2, TComp3, TComp4>()
|
|
where TComp1: IComponent
|
|
where TComp2: IComponent
|
|
where TComp3: IComponent
|
|
where TComp4: IComponent
|
|
{
|
|
var query = AllEntityQueryEnumerator<TComp1, TComp2, TComp3, TComp4>();
|
|
|
|
if (!query.MoveNext(out var ent, out var comp1, out var comp2, out var comp3, out var comp4))
|
|
throw new MatchNotFoundException(typeof(TComp1), typeof(TComp2), typeof(TComp3), typeof(TComp4));
|
|
|
|
if (query.MoveNext(out var ent2, out _, out _, out _, out _))
|
|
{
|
|
var list = new List<EntityUid> { ent, ent2 };
|
|
|
|
while (query.MoveNext(out var ent3, out _, out _, out _, out _))
|
|
{
|
|
list.Add(ent3);
|
|
}
|
|
|
|
throw new NonUniqueSingletonException(list.ToArray(), typeof(TComp1), typeof(TComp2), typeof(TComp3), typeof(TComp4));
|
|
}
|
|
|
|
return new(ent, comp1, comp2, comp3, comp4);
|
|
}
|
|
|
|
public bool TrySingle<TComp1>([NotNullWhen(true)] out Entity<TComp1>? entity)
|
|
where TComp1: IComponent
|
|
{
|
|
var index = _entTraitArray[CompIdx.ArrayIndex<TComp1>()];
|
|
|
|
if (index.Keys.FirstOrNull() is { } ent && index.Count == 1)
|
|
{
|
|
entity = new Entity<TComp1>(ent, (TComp1)index[ent]);
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
entity = null;
|
|
}
|
|
|
|
if (index.Count > 1)
|
|
{
|
|
throw new NonUniqueSingletonException(index.Keys.ToArray(), typeof(TComp1));
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
public bool TrySingle<TComp1, TComp2>([NotNullWhen(true)] out Entity<TComp1, TComp2>? entity)
|
|
where TComp1: IComponent
|
|
where TComp2: IComponent
|
|
{
|
|
var query = AllEntityQueryEnumerator<TComp1, TComp2>();
|
|
|
|
if (!query.MoveNext(out var ent, out var comp1, out var comp2))
|
|
{
|
|
entity = null;
|
|
return false;
|
|
}
|
|
|
|
if (query.MoveNext(out var ent2, out _, out _))
|
|
{
|
|
var list = new List<EntityUid> { ent, ent2 };
|
|
|
|
while (query.MoveNext(out var ent3, out _, out _))
|
|
{
|
|
list.Add(ent3);
|
|
}
|
|
|
|
throw new NonUniqueSingletonException(list.ToArray(), typeof(TComp1), typeof(TComp2));
|
|
}
|
|
|
|
entity = new(ent, comp1, comp2);
|
|
return true;
|
|
}
|
|
|
|
public bool TrySingle<TComp1, TComp2, TComp3>([NotNullWhen(true)] out Entity<TComp1, TComp2, TComp3>? entity)
|
|
where TComp1: IComponent
|
|
where TComp2: IComponent
|
|
where TComp3: IComponent
|
|
{
|
|
var query = AllEntityQueryEnumerator<TComp1, TComp2, TComp3>();
|
|
|
|
if (!query.MoveNext(out var ent, out var comp1, out var comp2, out var comp3))
|
|
{
|
|
entity = null;
|
|
return false;
|
|
}
|
|
|
|
if (query.MoveNext(out var ent2, out _, out _, out _))
|
|
{
|
|
var list = new List<EntityUid> { ent, ent2 };
|
|
|
|
while (query.MoveNext(out var ent3, out _, out _, out _))
|
|
{
|
|
list.Add(ent3);
|
|
}
|
|
|
|
throw new NonUniqueSingletonException(list.ToArray(), typeof(TComp1), typeof(TComp2), typeof(TComp3));
|
|
}
|
|
|
|
entity = new(ent, comp1, comp2, comp3);
|
|
return true;
|
|
}
|
|
|
|
public bool TrySingle<TComp1, TComp2, TComp3, TComp4>([NotNullWhen(true)] out Entity<TComp1, TComp2, TComp3, TComp4>? entity)
|
|
where TComp1: IComponent
|
|
where TComp2: IComponent
|
|
where TComp3: IComponent
|
|
where TComp4: IComponent
|
|
{
|
|
var query = AllEntityQueryEnumerator<TComp1, TComp2, TComp3, TComp4>();
|
|
|
|
if (!query.MoveNext(out var ent, out var comp1, out var comp2, out var comp3, out var comp4))
|
|
{
|
|
entity = null;
|
|
return false;
|
|
}
|
|
|
|
if (query.MoveNext(out var ent2, out _, out _, out _, out _))
|
|
{
|
|
var list = new List<EntityUid> { ent, ent2 };
|
|
|
|
while (query.MoveNext(out var ent3, out _, out _, out _, out _))
|
|
{
|
|
list.Add(ent3);
|
|
}
|
|
|
|
throw new NonUniqueSingletonException(list.ToArray(), typeof(TComp1), typeof(TComp2), typeof(TComp3), typeof(TComp4));
|
|
}
|
|
|
|
entity = new(ent, comp1, comp2, comp3, comp4);
|
|
return true;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Exception for when <see cref="float"/> and co cannot find a unique match.
|
|
/// </summary>
|
|
/// <param name="matches">The set of matching entities.</param>
|
|
/// <param name="components">The set of components you tried to match over.</param>
|
|
public sealed class NonUniqueSingletonException(EntityUid[] matches, params Type[] components) : Exception
|
|
{
|
|
public override string Message =>
|
|
$"Expected precisely one entity to match the component set {string.Join(", ", components)}, but found {matches.Length}: {string.Join(", ", matches)}";
|
|
}
|
|
|
|
/// <summary>
|
|
/// Exception for when <see cref="float"/> and co cannot find any match.
|
|
/// </summary>
|
|
/// <param name="components">The set of components you tried to match over.</param>
|
|
public sealed class MatchNotFoundException(params Type[] components) : Exception
|
|
{
|
|
public override string Message =>
|
|
$"Expected precisely one entity to match the component set {string.Join(", ", components)}, but found none.";
|
|
}
|