CatStation/Content.Shared/Whitelist/EntityWhitelistSystem.cs
Centronias 8ad82dc665
Refactor hunger and thirst systems (#34166)
* ready

* oop forgot the HUD stuff

* woooo examinable generalized tooooo

* oop I forgot to rename the files

* bungled the merge, I guess

* this is called hubris

* Verin's comments

* PR comments

how did I use `ProtoId<> Hunger` in more than a few spots but then just say "thirst can stay a literal :^)"?

also changed a few spots to my beloved
```
functionInvocation(
  one
  param
  per
  line
)
```
```

* Satiation effect condition now with ADDED FUNCTIONALITY?? :o

* tfw you trust the markov chain recommendation because long generic type names are tough q-q

* TFW YOU TRUST THE MARKOV CHAIN BUT IT DOESN'T UNDERSTAND THE DIFFERING SEMANTICS OF MAX AND MIN AHHHHH

* tfw you think to yourself "i need to fix the effects", but then forget to and the code doesn't even compile.

* centralize satiation constants

* other small comments

* The enum is dead.
But at what cost?

* oop

* like 12 more ooperses

* green checks are mine by right; I have performed the rites; I have done my part; you will not deny me this succor

* oops I changed the semantics from `<=` to just `<` and didn't update the tests :)

* serialization has bested me :agony:

also PR comments

* never trust the auto merge :agony:

* literally just this

* force engine back to master because idk why it's different

* fix randomness and update master

* submodule fuckery

* fall before my might

* okay I ran the linter, ARE YOU HAPPY??

* cursed ovis, trouble me no more

* protoman stuff

* inb4 linter bonks me

* break non-critical stuff from the main satiation proto

* ![live crundle reaction](https://preview.redd.it/xh68xqcz518g1.png?width=677&format=png&auto=webp&s=79ba10fe49ec3f8306217732321a7c5429bdfb14)

inb4 this breaks something somewhere lmao

* my two greatest PRs COLLIDE

I wonder why robust says it's changed :hmmclueless

* sanity is at an all-time low

* serialization, I guess

* I don't believe you

* field deltas on class \w*satiation\w*components

* PR comments

* 我做泥團子 😔

* doc + kill one property that's trivially accessible after the threshold caching changes

* fixes

---------

Co-authored-by: Princess Cheeseballs <66055347+Pronana@users.noreply.github.com>
Co-authored-by: AJCM-git <ajcm_mail@disroot.org>
2026-08-08 22:44:24 +00:00

153 lines
4.9 KiB
C#

using System.Diagnostics.CodeAnalysis;
using Content.Shared.Item;
using Content.Shared.Tag;
namespace Content.Shared.Whitelist;
public sealed partial class EntityWhitelistSystem : EntitySystem
{
[Dependency] private TagSystem _tag = default!;
[Dependency] private EntityQuery<ItemComponent> _itemQuery = default!;
private CompName _itemComponentName = default;
private CompName _tagComponentName = default;
public override void Initialize()
{
base.Initialize();
// caching for minor performance improvement
_itemComponentName = CompName.Get<ItemComponent>(Factory);
_tagComponentName = CompName.Get<TagComponent>(Factory);
}
/// <summary>
/// Checks whether a given entity satisfies a whitelist.
/// Returns false if the entity is null.
/// </summary>
public bool IsValid(EntityWhitelist list, [NotNullWhen(true)] EntityUid? uid)
{
return uid != null && IsValid(list, uid.Value);
}
/// <summary>
/// Checks whether a given entity satisfies a whitelist.
/// </summary>
public bool IsValid(EntityWhitelist list, EntityUid uid)
{
list.Registrations ??= StringsToRegs(list.Components);
if (list.Registrations != null)
{
foreach (var reg in list.Registrations)
{
if (EntityManager.HasComponent(uid, reg))
{
if (!list.RequireAll)
return true;
}
else if (list.RequireAll)
return false;
}
}
if (list.Sizes != null && _itemQuery.TryComp(uid, out var itemComp))
{
if (list.Sizes.Contains(itemComp.Size))
return true;
}
if (list.Tags != null)
{
return list.RequireAll
? _tag.HasAllTags(uid, list.Tags)
: _tag.HasAnyTag(uid, list.Tags);
}
return list.RequireAll;
}
/// The following are a list of "helper functions" that are basically the same as each other
/// to help make code that uses EntityWhitelist a bit more readable because at the moment
/// it is quite clunky having to write out component.Whitelist == null ? true : _whitelist.IsValid(component.Whitelist, uid)
/// several times in a row and makes comparisons easier to read
/// <summary>
/// Checks whether a given entity is allowed by a whitelist and not blocked by a blacklist.
/// If a blacklist is provided and it matches then this returns false.
/// If a whitelist is provided and it does not match then this returns false.
/// If either list is null it does not get checked.
/// </summary>
public bool CheckBoth([NotNullWhen(true)] EntityUid? uid, EntityWhitelist? blacklist = null, EntityWhitelist? whitelist = null)
{
if (uid == null)
return false;
if (blacklist != null && IsValid(blacklist, uid))
return false;
return whitelist == null || IsValid(whitelist, uid);
}
/// <summary>
/// Helper function to determine if a whitelist is not null and the entity is on list.
/// </summary>
public bool IsWhitelistPass(EntityWhitelist? whitelist, EntityUid uid)
{
if (whitelist == null)
return false;
return IsValid(whitelist, uid);
}
/// <summary>
/// Helper function to determine if a whitelist is not null and the entity is not on the list.
/// </summary>
public bool IsWhitelistFail(EntityWhitelist? whitelist, EntityUid uid)
{
if (whitelist == null)
return false;
return !IsValid(whitelist, uid);
}
/// <summary>
/// Helper function to determine if a whitelist is either null or the entity is on the list.
/// </summary>
public bool IsWhitelistPassOrNull(EntityWhitelist? whitelist, EntityUid uid)
{
if (whitelist == null)
return true;
return IsValid(whitelist, uid);
}
/// <summary>
/// Helper function to determine if a whitelist is either null or the entity is not on the list.
/// </summary>
public bool IsWhitelistFailOrNull(EntityWhitelist? whitelist, EntityUid uid)
{
if (whitelist == null)
return true;
return !IsValid(whitelist, uid);
}
private List<ComponentRegistration>? StringsToRegs(string[]? input)
{
if (input == null || input.Length == 0)
return null;
var list = new List<ComponentRegistration>(input.Length);
foreach (var name in input)
{
if (Factory.TryGetRegistration(name, out var registration))
list.Add(registration);
else if (Factory.GetComponentAvailability(name) != ComponentAvailability.Ignore)
Log.Error($"{nameof(StringsToRegs)} failed: Unknown component name {name} passed to EntityWhitelist!");
}
return list;
}
}