]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
Size-based entity whitelist (#26798)
authorErrant <35878406+Errant-4@users.noreply.github.com>
Tue, 30 Apr 2024 15:06:56 +0000 (17:06 +0200)
committerGitHub <noreply@github.com>
Tue, 30 Apr 2024 15:06:56 +0000 (11:06 -0400)
* 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>
Content.Shared/Tag/TagSystem.cs
Content.Shared/Whitelist/EntityWhitelist.cs

index 62197dc319ace6abe64fa5868aca7dca099fa91d..c2ea28d4c3cbc3d7434a8e04ec53cac01822df0c 100644 (file)
@@ -234,6 +234,21 @@ public sealed class TagSystem : EntitySystem
     /// </summary>
     /// <param name="entity">The entity to check.</param>
     /// <param name="ids">The tags to check for.</param>
+    /// <returns>true if they all exist, false otherwise.</returns>
+    /// <exception cref="UnknownPrototypeException">
+    ///     Thrown if one of the ids represents an unregistered <see cref="TagPrototype"/>.
+    /// </exception>
+    public bool HasAllTags(EntityUid entity, List<ProtoId<TagPrototype>> ids)
+    {
+        return TryComp<TagComponent>(entity, out var component) &&
+               HasAllTags(component, ids);
+    }
+
+    /// <summary>
+    ///     Checks if any of the given tags have been added to an entity.
+    /// </summary>
+    /// <param name="entity">The entity to check.</param>
+    /// <param name="ids">The tags to check for.</param>
     /// <returns>true if any of them exist, false otherwise.</returns>
     /// <exception cref="UnknownPrototypeException">
     ///     Thrown if one of the ids represents an unregistered <see cref="TagPrototype"/>.
@@ -245,7 +260,7 @@ public sealed class TagSystem : EntitySystem
     }
 
     /// <summary>
-    ///     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.
     /// </summary>
     /// <param name="entity">The entity to check.</param>
     /// <param name="id">The tag to check for.</param>
@@ -256,7 +271,7 @@ public sealed class TagSystem : EntitySystem
     public bool HasAnyTag(EntityUid entity, string id) => HasTag(entity, id);
 
     /// <summary>
-    ///     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.
     /// </summary>
     /// <param name="entity">The entity to check.</param>
     /// <param name="ids">The tags to check for.</param>
@@ -271,7 +286,22 @@ public sealed class TagSystem : EntitySystem
     }
 
     /// <summary>
-    ///     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.
+    /// </summary>
+    /// <param name="entity">The entity to check.</param>
+    /// <param name="ids">The tags to check for.</param>
+    /// <returns>true if any of them exist, false otherwise.</returns>
+    /// <exception cref="UnknownPrototypeException">
+    ///     Thrown if one of the ids represents an unregistered <see cref="TagPrototype"/>.
+    /// </exception>
+    public bool HasAnyTag(EntityUid entity, List<ProtoId<TagPrototype>> ids)
+    {
+        return TryComp<TagComponent>(entity, out var component) &&
+               HasAnyTag(component, ids);
+    }
+
+    /// <summary>
+    ///     Checks if any of the given tags have been added to an entity.
     /// </summary>
     /// <param name="entity">The entity to check.</param>
     /// <param name="ids">The tags to check for.</param>
@@ -478,6 +508,26 @@ public sealed class TagSystem : EntitySystem
         return true;
     }
 
+    /// <summary>
+    ///     Checks if all of the given tags have been added.
+    /// </summary>
+    /// <param name="ids">The tags to check for.</param>
+    /// <returns>true if they all exist, false otherwise.</returns>
+    /// <exception cref="UnknownPrototypeException">
+    ///     Thrown if one of the ids represents an unregistered <see cref="TagPrototype"/>.
+    /// </exception>
+    public bool HasAllTags(TagComponent component, List<ProtoId<TagPrototype>> ids)
+    {
+        var stringIds = new List<string>();
+        foreach (var tag in ids)
+        {
+            stringIds.Add(tag.Id);
+        }
+
+        return HasAllTags(component, stringIds);
+    }
+
+
     /// <summary>
     ///     Checks if any of the given tags have been added.
     /// </summary>
@@ -548,6 +598,25 @@ public sealed class TagSystem : EntitySystem
         return false;
     }
 
+    /// <summary>
+    ///     Checks if any of the given tags have been added.
+    /// </summary>
+    /// <param name="ids">The tags to check for.</param>
+    /// <returns>true if any of them exist, false otherwise.</returns>
+    /// <exception cref="UnknownPrototypeException">
+    ///     Thrown if one of the ids represents an unregistered <see cref="TagPrototype"/>.
+    /// </exception>
+    public bool HasAnyTag(TagComponent comp, List<ProtoId<TagPrototype>> ids)
+    {
+        var stringIds = new List<string>();
+        foreach (var tag in ids)
+        {
+            stringIds.Add(tag.Id);
+        }
+
+        return HasAnyTag(comp, stringIds);
+    }
+
     /// <summary>
     ///     Tries to remove a tag if it exists.
     /// </summary>
index b412a09b989acc2532464c7d0a3341f92b813017..7fa6ce7f824f88ccd55f872baa5a6b3366d5561b 100644 (file)
+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;
+
+/// <summary>
+///     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.
+/// </summary>
+/// <code>
+/// whitelist:
+///   tags:
+///   - Cigarette
+///   - FirelockElectronics
+///   components:
+///   - Buckle
+///   - AsteroidRock
+///   sizes:
+///   - Tiny
+///   - Large
+/// </code>
+[DataDefinition]
+[Serializable, NetSerializable]
+public sealed partial class EntityWhitelist
 {
     /// <summary>
-    ///     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.
     /// </summary>
-    /// <code>
-    /// whitelist:
-    ///   tags:
-    ///     - Cigarette
-    ///     - FirelockElectronics
-    ///   components:
-    ///     - Buckle
-    ///     - AsteroidRock
-    /// </code>
-    [DataDefinition]
-    [Serializable, NetSerializable]
-    public sealed partial class EntityWhitelist
-    {
-        /// <summary>
-        ///     Component names that are allowed in the whitelist.
-        /// </summary>
-        [DataField("components")] public string[]? Components = null;
-        // TODO yaml validation
+    [DataField] public string[]? Components;
+    // TODO yaml validation
 
-        [NonSerialized]
-        private List<ComponentRegistration>? _registrations = null;
+    /// <summary>
+    ///     Item sizes that are allowed in the whitelist.
+    /// </summary>
+    [DataField]
+    public List<ProtoId<ItemSizePrototype>>? Sizes;
 
-        /// <summary>
-        ///     Tags that are allowed in the whitelist.
-        /// </summary>
-        [DataField("tags", customTypeSerializer:typeof(PrototypeIdListSerializer<TagPrototype>))]
-        public List<string>? Tags = null;
+    [NonSerialized]
+    private List<ComponentRegistration>? _registrations;
 
-        /// <summary>
-        ///     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.
-        /// </summary>
-        [DataField("requireAll")]
-        public bool RequireAll = false;
+    /// <summary>
+    ///     Tags that are allowed in the whitelist.
+    /// </summary>
+    [DataField]
+    public List<ProtoId<TagPrototype>>? Tags;
 
-        public void UpdateRegistrations()
-        {
-            if (Components == null) return;
+    /// <summary>
+    ///     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.
+    /// </summary>
+    [DataField]
+    public bool RequireAll;
 
-            var compfact = IoCManager.Resolve<IComponentFactory>();
-            _registrations = new List<ComponentRegistration>();
-            foreach (var name in Components)
+    public void UpdateRegistrations()
+    {
+
+        if (Components == null)
+            return;
+
+        var compFact = IoCManager.Resolve<IComponentFactory>();
+        _registrations = new List<ComponentRegistration>();
+        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!");
             }
         }
+    }
 
-        /// <summary>
-        ///     Returns whether a given entity fits the whitelist.
-        /// </summary>
-        public bool IsValid(EntityUid uid, IEntityManager? entityManager = null)
-        {
-            if (Components != null && _registrations == null)
-                UpdateRegistrations();
+    /// <summary>
+    ///     Returns whether a given entity fits the whitelist.
+    /// </summary>
+    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<TagSystem>();
-                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<TagSystem>();
+            return RequireAll ? tagSystem.HasAllTags(tags, Tags) : tagSystem.HasAnyTag(tags, Tags);
         }
+
+        if (RequireAll)
+            return true;
+
+        return false;
     }
 }