From: Errant <35878406+Errant-4@users.noreply.github.com> Date: Tue, 30 Apr 2024 15:06:56 +0000 (+0200) Subject: Size-based entity whitelist (#26798) X-Git-Url: https://git.smokeofanarchy.ru/gitweb.cgi?a=commitdiff_plain;h=c3a0ba9dd890a617236082674730cb12669a688b;p=space-station-14.git Size-based entity whitelist (#26798) * Size based whitelisting * namespace and misc refactor * modern datafields, what will they think of next Co-authored-by: Nemanja <98561806+EmoGarbage404@users.noreply.github.com> * the future is now Co-authored-by: Nemanja <98561806+EmoGarbage404@users.noreply.github.com> * Update TagSystem to work with ProtoId lists * I guess someone might run into these too, one day * copypaste moment * update to sawmill * Okay, but what if it just worked --------- Co-authored-by: Nemanja <98561806+EmoGarbage404@users.noreply.github.com> --- diff --git a/Content.Shared/Tag/TagSystem.cs b/Content.Shared/Tag/TagSystem.cs index 62197dc319..c2ea28d4c3 100644 --- a/Content.Shared/Tag/TagSystem.cs +++ b/Content.Shared/Tag/TagSystem.cs @@ -234,6 +234,21 @@ public sealed class TagSystem : EntitySystem /// /// The entity to check. /// The tags to check for. + /// true if they all exist, false otherwise. + /// + /// Thrown if one of the ids represents an unregistered . + /// + public bool HasAllTags(EntityUid entity, List> ids) + { + return TryComp(entity, out var component) && + HasAllTags(component, ids); + } + + /// + /// Checks if any of the given tags have been added to an entity. + /// + /// The entity to check. + /// The tags to check for. /// true if any of them exist, false otherwise. /// /// Thrown if one of the ids represents an unregistered . @@ -245,7 +260,7 @@ public sealed class TagSystem : EntitySystem } /// - /// Checks if all of the given tags have been added to an entity. + /// Checks if any of the given tags have been added to an entity. /// /// The entity to check. /// The tag to check for. @@ -256,7 +271,7 @@ public sealed class TagSystem : EntitySystem public bool HasAnyTag(EntityUid entity, string id) => HasTag(entity, id); /// - /// Checks if all of the given tags have been added to an entity. + /// Checks if any of the given tags have been added to an entity. /// /// The entity to check. /// The tags to check for. @@ -271,7 +286,22 @@ public sealed class TagSystem : EntitySystem } /// - /// Checks if all of the given tags have been added to an entity. + /// Checks if any of the given tags have been added to an entity. + /// + /// The entity to check. + /// The tags to check for. + /// true if any of them exist, false otherwise. + /// + /// Thrown if one of the ids represents an unregistered . + /// + public bool HasAnyTag(EntityUid entity, List> ids) + { + return TryComp(entity, out var component) && + HasAnyTag(component, ids); + } + + /// + /// Checks if any of the given tags have been added to an entity. /// /// The entity to check. /// The tags to check for. @@ -478,6 +508,26 @@ public sealed class TagSystem : EntitySystem return true; } + /// + /// Checks if all of the given tags have been added. + /// + /// The tags to check for. + /// true if they all exist, false otherwise. + /// + /// Thrown if one of the ids represents an unregistered . + /// + public bool HasAllTags(TagComponent component, List> ids) + { + var stringIds = new List(); + foreach (var tag in ids) + { + stringIds.Add(tag.Id); + } + + return HasAllTags(component, stringIds); + } + + /// /// Checks if any of the given tags have been added. /// @@ -548,6 +598,25 @@ public sealed class TagSystem : EntitySystem return false; } + /// + /// Checks if any of the given tags have been added. + /// + /// The tags to check for. + /// true if any of them exist, false otherwise. + /// + /// Thrown if one of the ids represents an unregistered . + /// + public bool HasAnyTag(TagComponent comp, List> ids) + { + var stringIds = new List(); + foreach (var tag in ids) + { + stringIds.Add(tag.Id); + } + + return HasAnyTag(comp, stringIds); + } + /// /// Tries to remove a tag if it exists. /// diff --git a/Content.Shared/Whitelist/EntityWhitelist.cs b/Content.Shared/Whitelist/EntityWhitelist.cs index b412a09b98..7fa6ce7f82 100644 --- a/Content.Shared/Whitelist/EntityWhitelist.cs +++ b/Content.Shared/Whitelist/EntityWhitelist.cs @@ -1,103 +1,121 @@ +using Content.Shared.Item; using Content.Shared.Tag; +using Robust.Shared.Prototypes; using Robust.Shared.Serialization; -using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List; -namespace Content.Shared.Whitelist +namespace Content.Shared.Whitelist; + +/// +/// Used to determine whether an entity fits a certain whitelist. +/// Does not whitelist by prototypes, since that is undesirable; you're better off just adding a tag to all +/// entity prototypes that need to be whitelisted, and checking for that. +/// +/// +/// whitelist: +/// tags: +/// - Cigarette +/// - FirelockElectronics +/// components: +/// - Buckle +/// - AsteroidRock +/// sizes: +/// - Tiny +/// - Large +/// +[DataDefinition] +[Serializable, NetSerializable] +public sealed partial class EntityWhitelist { /// - /// Used to determine whether an entity fits a certain whitelist. - /// Does not whitelist by prototypes, since that is undesirable; you're better off just adding a tag to all - /// entity prototypes that need to be whitelisted, and checking for that. + /// Component names that are allowed in the whitelist. /// - /// - /// whitelist: - /// tags: - /// - Cigarette - /// - FirelockElectronics - /// components: - /// - Buckle - /// - AsteroidRock - /// - [DataDefinition] - [Serializable, NetSerializable] - public sealed partial class EntityWhitelist - { - /// - /// Component names that are allowed in the whitelist. - /// - [DataField("components")] public string[]? Components = null; - // TODO yaml validation + [DataField] public string[]? Components; + // TODO yaml validation - [NonSerialized] - private List? _registrations = null; + /// + /// Item sizes that are allowed in the whitelist. + /// + [DataField] + public List>? Sizes; - /// - /// Tags that are allowed in the whitelist. - /// - [DataField("tags", customTypeSerializer:typeof(PrototypeIdListSerializer))] - public List? Tags = null; + [NonSerialized] + private List? _registrations; - /// - /// If false, an entity only requires one of these components or tags to pass the whitelist. If true, an - /// entity requires to have ALL of these components and tags to pass. - /// - [DataField("requireAll")] - public bool RequireAll = false; + /// + /// Tags that are allowed in the whitelist. + /// + [DataField] + public List>? Tags; - public void UpdateRegistrations() - { - if (Components == null) return; + /// + /// If false, an entity only requires one of these components or tags to pass the whitelist. If true, an + /// entity requires to have ALL of these components and tags to pass. + /// The "Sizes" criteria will ignores this, since an item can only have one size. + /// + [DataField] + public bool RequireAll; - var compfact = IoCManager.Resolve(); - _registrations = new List(); - foreach (var name in Components) + public void UpdateRegistrations() + { + + if (Components == null) + return; + + var compFact = IoCManager.Resolve(); + _registrations = new List(); + foreach (var name in Components) + { + var availability = compFact.GetComponentAvailability(name); + if (compFact.TryGetRegistration(name, out var registration) + && availability == ComponentAvailability.Available) { - var availability = compfact.GetComponentAvailability(name); - if (compfact.TryGetRegistration(name, out var registration) - && availability == ComponentAvailability.Available) - { - _registrations.Add(registration); - } - else if (availability == ComponentAvailability.Unknown) - { - Logger.Warning($"Unknown component name {name} passed to EntityWhitelist!"); - } + _registrations.Add(registration); + } + else if (availability == ComponentAvailability.Unknown) + { + Logger.Warning($"Unknown component name {name} passed to EntityWhitelist!"); } } + } - /// - /// Returns whether a given entity fits the whitelist. - /// - public bool IsValid(EntityUid uid, IEntityManager? entityManager = null) - { - if (Components != null && _registrations == null) - UpdateRegistrations(); + /// + /// Returns whether a given entity fits the whitelist. + /// + public bool IsValid(EntityUid uid, IEntityManager? entityManager = null) + { + if (Components != null && _registrations == null) + UpdateRegistrations(); - IoCManager.Resolve(ref entityManager); - if (_registrations != null) + IoCManager.Resolve(ref entityManager); + if (_registrations != null) + { + foreach (var reg in _registrations) { - foreach (var reg in _registrations) + if (entityManager.HasComponent(uid, reg.Type)) { - if (entityManager.HasComponent(uid, reg.Type)) - { - if (!RequireAll) - return true; - } - else if (RequireAll) - return false; + if (!RequireAll) + return true; } + else if (RequireAll) + return false; } + } - if (Tags != null && entityManager.TryGetComponent(uid, out TagComponent? tags)) - { - var tagSystem = entityManager.System(); - return RequireAll ? tagSystem.HasAllTags(tags, Tags) : tagSystem.HasAnyTag(tags, Tags); - } - - if (RequireAll) + if (Sizes != null && entityManager.TryGetComponent(uid, out ItemComponent? itemComp)) + { + if (Sizes.Contains(itemComp.Size)) return true; + } - return false; + if (Tags != null && entityManager.TryGetComponent(uid, out TagComponent? tags)) + { + var tagSystem = entityManager.System(); + return RequireAll ? tagSystem.HasAllTags(tags, Tags) : tagSystem.HasAnyTag(tags, Tags); } + + if (RequireAll) + return true; + + return false; } }