using Content.Shared.Tag; using Robust.Shared.Serialization; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List; 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 /// [DataDefinition] [Serializable, NetSerializable] public sealed class EntityWhitelist { /// /// Component names that are allowed in the whitelist. /// [DataField("components")] public string[]? Components = null; [NonSerialized] private List? _registrations = null; /// /// Tags that are allowed in the whitelist. /// [DataField("tags", customTypeSerializer:typeof(PrototypeIdListSerializer))] public List? Tags = null; /// /// 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; 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) { _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(); entityManager ??= IoCManager.Resolve(); if (_registrations != null) { foreach (var reg in _registrations) { if (entityManager.HasComponent(uid, reg.Type)) { if (!RequireAll) return true; } else if (RequireAll) return false; } } if (Tags != null && entityManager.TryGetComponent(uid, out TagComponent? tags)) { var tagSystem = EntitySystem.Get(); return RequireAll ? tagSystem.HasAllTags(tags, Tags) : tagSystem.HasAnyTag(tags, Tags); } return false; } } }