Add EntManager + ProtoManager helpers for random picks (#4869)

* Add EntManager + ProtoManager helpers for random picks

Lets us cleanup content a bit from these being re-implemented.

* weh
This commit is contained in:
metalgearsloth
2024-04-14 14:55:55 +10:00
committed by GitHub
parent cd24fd46b6
commit fd60dc2887
4 changed files with 113 additions and 3 deletions

View File

@@ -39,8 +39,7 @@ END TEMPLATE-->
### New features
* You can now specify CVar overrides via environment variable with the `ROBUST_CVAR_*` prefix. For example `ROBUST_CVAR_game__hostname=foobar` would set the appropriate CVar. Double underscores in the environment variable name are replaced with ".".
* Added non-generic variant of `GetCVar` to `IConfigurationManager`.
* Add TryGetRandom to EntityManager to get a random entity with the specified component and TryGetRandom to IPrototypeManager to return a random prototype of the specified type.
### Bugfixes

View File

@@ -1,4 +1,7 @@
namespace Robust.Shared.GameObjects
using Robust.Shared.Collections;
using Robust.Shared.Random;
namespace Robust.Shared.GameObjects
{
public static class EntityManagerExt
{
@@ -19,5 +22,79 @@
return default;
}
/// <summary>
/// Picks an entity at random with the supplied component.
/// </summary>
public static bool TryGetRandom<TComp1>(this IEntityManager entManager, IRobustRandom random, out EntityUid entity, bool includePaused = false) where TComp1 : IComponent
{
var entities = new ValueList<EntityUid>();
if (includePaused)
{
var query = entManager.AllEntityQueryEnumerator<TComp1>();
while (query.MoveNext(out var uid, out _))
{
entities.Add(uid);
}
}
else
{
var query = entManager.EntityQueryEnumerator<TComp1>();
while (query.MoveNext(out var uid, out _))
{
entities.Add(uid);
}
}
if (entities.Count == 0)
{
entity = EntityUid.Invalid;
return false;
}
entity = random.Pick(entities);
return true;
}
/// <summary>
/// Picks an entity at random with the supplied components.
/// </summary>
public static bool TryGetRandom<TComp1, TComp2>(this IEntityManager entManager, IRobustRandom random, out EntityUid entity, bool includePaused = false)
where TComp1 : IComponent
where TComp2 : IComponent
{
var entities = new ValueList<EntityUid>();
if (includePaused)
{
var query = entManager.AllEntityQueryEnumerator<TComp1, TComp2>();
while (query.MoveNext(out var uid, out _, out _))
{
entities.Add(uid);
}
}
else
{
var query = entManager.EntityQueryEnumerator<TComp1, TComp2>();
while (query.MoveNext(out var uid, out _, out _))
{
entities.Add(uid);
}
}
if (entities.Count == 0)
{
entity = EntityUid.Invalid;
return false;
}
entity = random.Pick(entities);
return true;
}
}
}

View File

@@ -3,6 +3,7 @@ using System.Collections.Frozen;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using Robust.Shared.Random;
using Robust.Shared.Serialization.Manager;
using Robust.Shared.Serialization.Manager.Attributes;
using Robust.Shared.Serialization.Markdown;
@@ -386,6 +387,11 @@ public interface IPrototypeManager
/// For example: /Prototypes/Guidebook
/// </param>
void AbstractDirectory(ResPath path);
/// <summary>
/// Tries to get a random prototype.
/// </summary>
bool TryGetRandom<T>(IRobustRandom random, [NotNullWhen(true)] out IPrototype? prototype) where T : class, IPrototype;
}
internal interface IPrototypeManagerInternal : IPrototypeManager

View File

@@ -1082,6 +1082,34 @@ namespace Robust.Shared.Prototypes
_prototypeDataCache[prototype.ID] = data;
return data;
}
public bool TryGetRandom<T>(IRobustRandom random, [NotNullWhen(true)] out IPrototype? prototype) where T : class, IPrototype
{
var count = Count<T>();
if (count == 0)
{
prototype = null;
return false;
}
var index = 0;
var picked = random.Next(count);
foreach (var proto in EnumeratePrototypes<T>())
{
if (index == picked)
{
prototype = proto;
return true;
}
index++;
}
throw new ArgumentOutOfRangeException($"Unable to pick valid prototype for {typeof(T)}?");
}
}
public sealed class InvalidPrototypeNameException : Exception