-
Notifications
You must be signed in to change notification settings - Fork 3.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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>
- Loading branch information
1 parent
046d062
commit c3a0ba9
Showing
2 changed files
with
167 additions
and
80 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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; | ||
|
||
/// <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; | ||
} | ||
} |