Access refactor
Access is now done through a list of access lists, instead of the necessary/sufficient system that was extremely confusing. Added a "deny" list so you can screw over sec. Cleaned the API up so it all uses sets and such. PDA now relays access read-only to fix edge cases.
This commit is contained in:
@@ -4,29 +4,42 @@ using Robust.Shared.GameObjects;
|
|||||||
using Robust.Shared.Serialization;
|
using Robust.Shared.Serialization;
|
||||||
using Robust.Shared.ViewVariables;
|
using Robust.Shared.ViewVariables;
|
||||||
|
|
||||||
|
#nullable enable
|
||||||
|
|
||||||
namespace Content.Server.GameObjects.Components.Access
|
namespace Content.Server.GameObjects.Components.Access
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Simple mutable access provider found on ID cards and such.
|
||||||
|
/// </summary>
|
||||||
[RegisterComponent]
|
[RegisterComponent]
|
||||||
[ComponentReference(typeof(IAccess))]
|
[ComponentReference(typeof(IAccess))]
|
||||||
public class AccessComponent : Component, IAccess
|
public class AccessComponent : Component, IAccess
|
||||||
{
|
{
|
||||||
public override string Name => "Access";
|
public override string Name => "Access";
|
||||||
|
|
||||||
[ViewVariables]
|
[ViewVariables]
|
||||||
private List<string> _tags;
|
private readonly HashSet<string> _tags = new HashSet<string>();
|
||||||
|
|
||||||
|
public ISet<string> Tags => _tags;
|
||||||
|
public bool IsReadOnly => false;
|
||||||
|
|
||||||
public override void ExposeData(ObjectSerializer serializer)
|
public override void ExposeData(ObjectSerializer serializer)
|
||||||
{
|
{
|
||||||
base.ExposeData(serializer);
|
base.ExposeData(serializer);
|
||||||
serializer.DataField(ref _tags, "tags", new List<string>());
|
|
||||||
|
serializer.DataReadWriteFunction("tags", new List<string>(),
|
||||||
|
value =>
|
||||||
|
{
|
||||||
|
_tags.Clear();
|
||||||
|
_tags.UnionWith(value);
|
||||||
|
},
|
||||||
|
() => new List<string>(_tags));
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<string> GetTags()
|
public void SetTags(IEnumerable<string> newTags)
|
||||||
{
|
{
|
||||||
return _tags;
|
_tags.Clear();
|
||||||
}
|
_tags.UnionWith(newTags);
|
||||||
|
|
||||||
public void SetTags(List<string> newTags)
|
|
||||||
{
|
|
||||||
_tags = newTags;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using Content.Server.Interfaces;
|
using Content.Server.Interfaces;
|
||||||
using Content.Server.Interfaces.GameObjects;
|
using Content.Server.Interfaces.GameObjects;
|
||||||
using Content.Shared.GameObjects.Components.Inventory;
|
using Content.Shared.GameObjects.Components.Inventory;
|
||||||
@@ -9,54 +10,70 @@ using Robust.Shared.Interfaces.GameObjects;
|
|||||||
using Robust.Shared.Serialization;
|
using Robust.Shared.Serialization;
|
||||||
using Robust.Shared.ViewVariables;
|
using Robust.Shared.ViewVariables;
|
||||||
|
|
||||||
|
#nullable enable
|
||||||
|
|
||||||
namespace Content.Server.GameObjects.Components.Access
|
namespace Content.Server.GameObjects.Components.Access
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Stores access levels necessary to "use" an entity
|
||||||
|
/// and allows checking if something or somebody is authorized with these access levels.
|
||||||
|
/// </summary>
|
||||||
|
[PublicAPI]
|
||||||
[RegisterComponent]
|
[RegisterComponent]
|
||||||
public class AccessReader : Component
|
public class AccessReader : Component
|
||||||
{
|
{
|
||||||
public override string Name => "AccessReader";
|
public override string Name => "AccessReader";
|
||||||
[ViewVariables]
|
|
||||||
private List<string> _necessaryTags;
|
private readonly List<ISet<string>> _accessLists = new List<ISet<string>>();
|
||||||
[ViewVariables]
|
private readonly HashSet<string> _denyTags = new HashSet<string>();
|
||||||
private List<string> _sufficientTags;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Searches an <see cref="AccessComponent"/> in the entity itself, in its active hand or in its ID slot.
|
/// List of access lists to check allowed against. For an access check to pass
|
||||||
/// Returns true if an <see cref="AccessComponent"/> is found and its tags list contains
|
/// there has to be an access list that is a subset of the access in the checking list.
|
||||||
/// at least one of <see cref="_sufficientTags"/> or all of <see cref="_necessaryTags"/>.
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[ViewVariables] public IList<ISet<string>> AccessLists => _accessLists;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The set of tags that will automatically deny an allowed check, if any of them are present.
|
||||||
|
/// </summary>
|
||||||
|
[ViewVariables] public ISet<string> DenyTags => _denyTags;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Searches an <see cref="IAccess"/> in the entity itself, in its active hand or in its ID slot.
|
||||||
|
/// Then compares the found access with the configured access lists to see if it is allowed.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// If no access is found, an empty set is used instead.
|
||||||
|
/// </remarks>
|
||||||
/// <param name="entity">The entity to be searched for access.</param>
|
/// <param name="entity">The entity to be searched for access.</param>
|
||||||
public bool IsAllowed(IEntity entity)
|
public bool IsAllowed(IEntity entity)
|
||||||
{
|
{
|
||||||
var tags = FindAccessTags(entity);
|
var tags = FindAccessTags(entity);
|
||||||
return tags != null && IsAllowed(tags);
|
return IsAllowed(tags);
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool IsAllowed(List<string> accessTags)
|
public bool IsAllowed(IAccess access)
|
||||||
{
|
{
|
||||||
foreach (var sufficient in _sufficientTags)
|
return IsAllowed(access.Tags);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsAllowed(ICollection<string> accessTags)
|
||||||
|
{
|
||||||
|
if (_denyTags.Overlaps(accessTags))
|
||||||
{
|
{
|
||||||
if (accessTags.Contains(sufficient))
|
// Sec owned by cargo.
|
||||||
{
|
return false;
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
foreach (var necessary in _necessaryTags)
|
|
||||||
{
|
return _accessLists.Count == 0 || _accessLists.Any(a => a.IsSubsetOf(accessTags));
|
||||||
if (!accessTags.Contains(necessary))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[CanBeNull]
|
[CanBeNull]
|
||||||
private static List<string> FindAccessTags(IEntity entity)
|
private static ICollection<string> FindAccessTags(IEntity entity)
|
||||||
{
|
{
|
||||||
if (entity.TryGetComponent(out IAccess accessComponent))
|
if (entity.TryGetComponent(out IAccess accessComponent))
|
||||||
{
|
{
|
||||||
return accessComponent.GetTags();
|
return accessComponent.Tags;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (entity.TryGetComponent(out IHandsComponent handsComponent))
|
if (entity.TryGetComponent(out IHandsComponent handsComponent))
|
||||||
@@ -65,32 +82,42 @@ namespace Content.Server.GameObjects.Components.Access
|
|||||||
if (activeHandEntity != null &&
|
if (activeHandEntity != null &&
|
||||||
activeHandEntity.TryGetComponent(out IAccess handAccessComponent))
|
activeHandEntity.TryGetComponent(out IAccess handAccessComponent))
|
||||||
{
|
{
|
||||||
return handAccessComponent.GetTags();
|
return handAccessComponent.Tags;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return null;
|
return Array.Empty<string>();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (entity.TryGetComponent(out InventoryComponent inventoryComponent))
|
if (entity.TryGetComponent(out InventoryComponent inventoryComponent))
|
||||||
{
|
{
|
||||||
if (inventoryComponent.HasSlot(EquipmentSlotDefines.Slots.IDCARD) &&
|
if (inventoryComponent.HasSlot(EquipmentSlotDefines.Slots.IDCARD) &&
|
||||||
inventoryComponent.TryGetSlotItem(EquipmentSlotDefines.Slots.IDCARD, out ItemComponent item) &&
|
inventoryComponent.TryGetSlotItem(EquipmentSlotDefines.Slots.IDCARD, out ItemComponent item) &&
|
||||||
item.Owner.TryGetComponent(out IAccess idAccessComponent)
|
item.Owner.TryGetComponent(out IAccess idAccessComponent)
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
return idAccessComponent.GetTags();
|
return idAccessComponent.Tags;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
|
||||||
|
return Array.Empty<string>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void ExposeData(ObjectSerializer serializer)
|
public override void ExposeData(ObjectSerializer serializer)
|
||||||
{
|
{
|
||||||
base.ExposeData(serializer);
|
base.ExposeData(serializer);
|
||||||
|
|
||||||
serializer.DataField(ref _necessaryTags, "necessary" ,new List<string>());
|
serializer.DataReadWriteFunction("access", new List<List<string>>(),
|
||||||
serializer.DataField(ref _sufficientTags, "sufficient", new List<string>());
|
v =>
|
||||||
|
{
|
||||||
|
if (v.Count != 0)
|
||||||
|
{
|
||||||
|
_accessLists.Clear();
|
||||||
|
_accessLists.AddRange(v.Select(a => new HashSet<string>(a)));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
() => _accessLists.Select(p => new List<string>(p)).ToList());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using Content.Server.GameObjects.EntitySystems;
|
using Content.Server.GameObjects.EntitySystems;
|
||||||
using Content.Server.Interfaces;
|
using Content.Server.Interfaces;
|
||||||
using Content.Server.Interfaces.GameObjects;
|
using Content.Server.Interfaces.GameObjects;
|
||||||
@@ -180,7 +181,7 @@ namespace Content.Server.GameObjects.Components.Access
|
|||||||
true,
|
true,
|
||||||
targetIdComponent.FullName,
|
targetIdComponent.FullName,
|
||||||
targetIdComponent.JobTitle,
|
targetIdComponent.JobTitle,
|
||||||
targetAccessComponent.GetTags(),
|
targetAccessComponent.Tags.ToArray(),
|
||||||
_privilegedIdContainer.ContainedEntity?.Name ?? "",
|
_privilegedIdContainer.ContainedEntity?.Name ?? "",
|
||||||
_targetIdContainer.ContainedEntity?.Name ?? "");
|
_targetIdContainer.ContainedEntity?.Name ?? "");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Content.Server.GameObjects.Components.Access;
|
using Content.Server.GameObjects.Components.Access;
|
||||||
@@ -6,18 +8,18 @@ using Content.Server.Interfaces;
|
|||||||
using Content.Server.Interfaces.PDA;
|
using Content.Server.Interfaces.PDA;
|
||||||
using Content.Shared.GameObjects;
|
using Content.Shared.GameObjects;
|
||||||
using Content.Shared.GameObjects.Components.PDA;
|
using Content.Shared.GameObjects.Components.PDA;
|
||||||
using JetBrains.Annotations;
|
|
||||||
using Robust.Server.GameObjects;
|
using Robust.Server.GameObjects;
|
||||||
using Robust.Server.GameObjects.Components.Container;
|
using Robust.Server.GameObjects.Components.Container;
|
||||||
using Robust.Server.GameObjects.Components.UserInterface;
|
using Robust.Server.GameObjects.Components.UserInterface;
|
||||||
using Robust.Server.Interfaces.GameObjects;
|
using Robust.Server.Interfaces.GameObjects;
|
||||||
using Robust.Shared.GameObjects;
|
using Robust.Shared.GameObjects;
|
||||||
using Robust.Shared.Interfaces.GameObjects;
|
using Robust.Shared.Interfaces.GameObjects;
|
||||||
using Robust.Shared.Interfaces.Network;
|
|
||||||
using Robust.Shared.IoC;
|
using Robust.Shared.IoC;
|
||||||
using Robust.Shared.Localization;
|
using Robust.Shared.Localization;
|
||||||
using Robust.Shared.Players;
|
|
||||||
using Robust.Shared.Serialization;
|
using Robust.Shared.Serialization;
|
||||||
|
using Robust.Shared.ViewVariables;
|
||||||
|
|
||||||
|
#nullable enable
|
||||||
|
|
||||||
namespace Content.Server.GameObjects.Components.PDA
|
namespace Content.Server.GameObjects.Components.PDA
|
||||||
{
|
{
|
||||||
@@ -26,24 +28,29 @@ namespace Content.Server.GameObjects.Components.PDA
|
|||||||
[ComponentReference(typeof(IAccess))]
|
[ComponentReference(typeof(IAccess))]
|
||||||
public class PDAComponent : SharedPDAComponent, IInteractUsing, IActivate, IUse, IAccess
|
public class PDAComponent : SharedPDAComponent, IInteractUsing, IActivate, IUse, IAccess
|
||||||
{
|
{
|
||||||
#pragma warning disable 649
|
[Dependency] private readonly IPDAUplinkManager _uplinkManager = default!;
|
||||||
[Dependency] protected readonly IPDAUplinkManager _uplinkManager;
|
[Dependency] private readonly IEntityManager _entityManager = default!;
|
||||||
[Dependency] protected readonly IEntityManager _entityManager;
|
|
||||||
#pragma warning restore 649
|
|
||||||
|
|
||||||
private Container _idSlot;
|
[ViewVariables] private Container _idSlot = default!;
|
||||||
private PointLightComponent _pdaLight;
|
[ViewVariables] private PointLightComponent _pdaLight = default!;
|
||||||
private bool _lightOn = false;
|
[ViewVariables] private bool _lightOn;
|
||||||
private BoundUserInterface _interface;
|
[ViewVariables] private BoundUserInterface _interface = default!;
|
||||||
private string _startingIdCard;
|
[ViewVariables] private string _startingIdCard = default!;
|
||||||
public bool IdSlotEmpty => _idSlot.ContainedEntities.Count < 1;
|
[ViewVariables] public bool IdSlotEmpty => _idSlot.ContainedEntities.Count < 1;
|
||||||
public IEntity OwnerMob { get; private set; }
|
[ViewVariables] public IEntity? OwnerMob { get; private set; }
|
||||||
|
|
||||||
public IdCardComponent ContainedID { get; private set; }
|
[ViewVariables] public IdCardComponent? ContainedID { get; private set; }
|
||||||
|
|
||||||
private AppearanceComponent _appearance;
|
[ViewVariables] private AppearanceComponent _appearance = default!;
|
||||||
|
|
||||||
private UplinkAccount _syndicateUplinkAccount;
|
[ViewVariables] private UplinkAccount? _syndicateUplinkAccount;
|
||||||
|
|
||||||
|
[ViewVariables] private readonly PdaAccessSet _accessSet;
|
||||||
|
|
||||||
|
public PDAComponent()
|
||||||
|
{
|
||||||
|
_accessSet = new PdaAccessSet(this);
|
||||||
|
}
|
||||||
|
|
||||||
public override void ExposeData(ObjectSerializer serializer)
|
public override void ExposeData(ObjectSerializer serializer)
|
||||||
{
|
{
|
||||||
@@ -89,7 +96,6 @@ namespace Content.Server.GameObjects.Components.PDA
|
|||||||
|
|
||||||
case PDAUplinkBuyListingMessage buyMsg:
|
case PDAUplinkBuyListingMessage buyMsg:
|
||||||
{
|
{
|
||||||
|
|
||||||
if (!_uplinkManager.TryPurchaseItem(_syndicateUplinkAccount, buyMsg.ListingToBuy))
|
if (!_uplinkManager.TryPurchaseItem(_syndicateUplinkAccount, buyMsg.ListingToBuy))
|
||||||
{
|
{
|
||||||
//TODO: Send a message that tells the buyer they are too poor or something.
|
//TODO: Send a message that tells the buyer they are too poor or something.
|
||||||
@@ -112,13 +118,14 @@ namespace Content.Server.GameObjects.Components.PDA
|
|||||||
//Do we have an account? If so provide the info.
|
//Do we have an account? If so provide the info.
|
||||||
if (_syndicateUplinkAccount != null)
|
if (_syndicateUplinkAccount != null)
|
||||||
{
|
{
|
||||||
var accData = new UplinkAccountData(_syndicateUplinkAccount.AccountHolder, _syndicateUplinkAccount.Balance);
|
var accData = new UplinkAccountData(_syndicateUplinkAccount.AccountHolder,
|
||||||
|
_syndicateUplinkAccount.Balance);
|
||||||
var listings = _uplinkManager.FetchListings.ToArray();
|
var listings = _uplinkManager.FetchListings.ToArray();
|
||||||
_interface.SetState(new PDAUpdateState(_lightOn,ownerInfo,accData,listings));
|
_interface.SetState(new PDAUpdateState(_lightOn, ownerInfo, accData, listings));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_interface.SetState(new PDAUpdateState(_lightOn,ownerInfo));
|
_interface.SetState(new PDAUpdateState(_lightOn, ownerInfo));
|
||||||
}
|
}
|
||||||
|
|
||||||
UpdatePDAAppearance();
|
UpdatePDAAppearance();
|
||||||
@@ -141,10 +148,10 @@ namespace Content.Server.GameObjects.Components.PDA
|
|||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
InsertIdCard(idCardComponent);
|
InsertIdCard(idCardComponent);
|
||||||
UpdatePDAUserInterface();
|
UpdatePDAUserInterface();
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void IActivate.Activate(ActivateEventArgs eventArgs)
|
void IActivate.Activate(ActivateEventArgs eventArgs)
|
||||||
@@ -153,6 +160,7 @@ namespace Content.Server.GameObjects.Components.PDA
|
|||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_interface.Open(actor.playerSession);
|
_interface.Open(actor.playerSession);
|
||||||
UpdatePDAAppearance();
|
UpdatePDAAppearance();
|
||||||
}
|
}
|
||||||
@@ -163,6 +171,7 @@ namespace Content.Server.GameObjects.Components.PDA
|
|||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
_interface.Open(actor.playerSession);
|
_interface.Open(actor.playerSession);
|
||||||
UpdatePDAAppearance();
|
UpdatePDAAppearance();
|
||||||
return true;
|
return true;
|
||||||
@@ -211,7 +220,7 @@ namespace Content.Server.GameObjects.Components.PDA
|
|||||||
|
|
||||||
private void HandleIDEjection(IEntity pdaUser)
|
private void HandleIDEjection(IEntity pdaUser)
|
||||||
{
|
{
|
||||||
if (IdSlotEmpty)
|
if (ContainedID == null)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -241,14 +250,129 @@ namespace Content.Server.GameObjects.Components.PDA
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
List<string> IAccess.GetTags()
|
private ISet<string>? GetContainedAccess()
|
||||||
{
|
{
|
||||||
return ContainedID?.Owner.GetComponent<AccessComponent>()?.GetTags();
|
return ContainedID?.Owner?.GetComponent<AccessComponent>()?.Tags;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IAccess.SetTags(List<string> newTags)
|
ISet<string> IAccess.Tags => _accessSet;
|
||||||
|
bool IAccess.IsReadOnly => true;
|
||||||
|
|
||||||
|
void IAccess.SetTags(IEnumerable<string> newTags)
|
||||||
{
|
{
|
||||||
ContainedID?.Owner.GetComponent<AccessComponent>().SetTags(newTags);
|
throw new NotSupportedException("PDA access list is read-only.");
|
||||||
|
}
|
||||||
|
|
||||||
|
private sealed class PdaAccessSet : ISet<string>
|
||||||
|
{
|
||||||
|
private readonly PDAComponent _pdaComponent;
|
||||||
|
private static readonly HashSet<string> EmptySet = new HashSet<string>();
|
||||||
|
|
||||||
|
public PdaAccessSet(PDAComponent pdaComponent)
|
||||||
|
{
|
||||||
|
_pdaComponent = pdaComponent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerator<string> GetEnumerator()
|
||||||
|
{
|
||||||
|
var contained = _pdaComponent.GetContainedAccess() ?? EmptySet;
|
||||||
|
return contained.GetEnumerator();
|
||||||
|
}
|
||||||
|
|
||||||
|
IEnumerator IEnumerable.GetEnumerator()
|
||||||
|
{
|
||||||
|
return GetEnumerator();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ICollection<string>.Add(string item)
|
||||||
|
{
|
||||||
|
throw new NotSupportedException("PDA access list is read-only.");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ExceptWith(IEnumerable<string> other)
|
||||||
|
{
|
||||||
|
throw new NotSupportedException("PDA access list is read-only.");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void IntersectWith(IEnumerable<string> other)
|
||||||
|
{
|
||||||
|
throw new NotSupportedException("PDA access list is read-only.");
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsProperSubsetOf(IEnumerable<string> other)
|
||||||
|
{
|
||||||
|
var set = _pdaComponent.GetContainedAccess() ?? EmptySet;
|
||||||
|
return set.IsProperSubsetOf(other);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsProperSupersetOf(IEnumerable<string> other)
|
||||||
|
{
|
||||||
|
var set = _pdaComponent.GetContainedAccess() ?? EmptySet;
|
||||||
|
return set.IsProperSupersetOf(other);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsSubsetOf(IEnumerable<string> other)
|
||||||
|
{
|
||||||
|
var set = _pdaComponent.GetContainedAccess() ?? EmptySet;
|
||||||
|
return set.IsSubsetOf(other);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsSupersetOf(IEnumerable<string> other)
|
||||||
|
{
|
||||||
|
var set = _pdaComponent.GetContainedAccess() ?? EmptySet;
|
||||||
|
return set.IsSupersetOf(other);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Overlaps(IEnumerable<string> other)
|
||||||
|
{
|
||||||
|
var set = _pdaComponent.GetContainedAccess() ?? EmptySet;
|
||||||
|
return set.Overlaps(other);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool SetEquals(IEnumerable<string> other)
|
||||||
|
{
|
||||||
|
var set = _pdaComponent.GetContainedAccess() ?? EmptySet;
|
||||||
|
return set.SetEquals(other);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SymmetricExceptWith(IEnumerable<string> other)
|
||||||
|
{
|
||||||
|
throw new NotSupportedException("PDA access list is read-only.");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UnionWith(IEnumerable<string> other)
|
||||||
|
{
|
||||||
|
throw new NotSupportedException("PDA access list is read-only.");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ISet<string>.Add(string item)
|
||||||
|
{
|
||||||
|
throw new NotSupportedException("PDA access list is read-only.");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Clear()
|
||||||
|
{
|
||||||
|
throw new NotSupportedException("PDA access list is read-only.");
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Contains(string item)
|
||||||
|
{
|
||||||
|
return _pdaComponent.GetContainedAccess()?.Contains(item) ?? false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CopyTo(string[] array, int arrayIndex)
|
||||||
|
{
|
||||||
|
var set = _pdaComponent.GetContainedAccess() ?? EmptySet;
|
||||||
|
set.CopyTo(array, arrayIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Remove(string item)
|
||||||
|
{
|
||||||
|
throw new NotSupportedException("PDA access list is read-only.");
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Count => _pdaComponent.GetContainedAccess()?.Count ?? 0;
|
||||||
|
public bool IsReadOnly => true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -647,8 +647,8 @@ namespace Content.Server.GameTicking
|
|||||||
card.JobTitle = jobPrototype.Name;
|
card.JobTitle = jobPrototype.Name;
|
||||||
|
|
||||||
var access = card.Owner.GetComponent<AccessComponent>();
|
var access = card.Owner.GetComponent<AccessComponent>();
|
||||||
var accessTags = access.GetTags();
|
var accessTags = access.Tags;
|
||||||
accessTags.AddRange(jobPrototype.Access);
|
accessTags.UnionWith(jobPrototype.Access);
|
||||||
access.SetTags(accessTags);
|
access.SetTags(accessTags);
|
||||||
pdaComponent.SetPDAOwner(mob);
|
pdaComponent.SetPDAOwner(mob);
|
||||||
var mindComponent = mob.GetComponent<MindComponent>();
|
var mindComponent = mob.GetComponent<MindComponent>();
|
||||||
|
|||||||
@@ -1,11 +1,34 @@
|
|||||||
|
using System;
|
||||||
|
using Content.Server.GameObjects.Components.Access;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
#nullable enable
|
||||||
|
|
||||||
namespace Content.Server.Interfaces
|
namespace Content.Server.Interfaces
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Contains access levels that can be checked to see if somebody has access with an <see cref="AccessReader"/>.
|
||||||
|
/// </summary>
|
||||||
public interface IAccess
|
public interface IAccess
|
||||||
{
|
{
|
||||||
public List<string> GetTags();
|
/// <summary>
|
||||||
|
/// The set of access tags this thing has.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// This set may be read-only. Check <see cref="IsReadOnly"/> if you want to mutate it.
|
||||||
|
/// </remarks>
|
||||||
|
ISet<string> Tags { get; }
|
||||||
|
|
||||||
public void SetTags(List<string> newTags);
|
/// <summary>
|
||||||
|
/// Whether the <see cref="Tags"/> list is read-only.
|
||||||
|
/// </summary>
|
||||||
|
bool IsReadOnly { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Replaces the set of access tags we have with the provided set.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="newTags">The new access tags</param>
|
||||||
|
/// <exception cref="NotSupportedException">If this access tag list is read-only.</exception>
|
||||||
|
void SetTags(IEnumerable<string> newTags);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,14 +52,14 @@ namespace Content.Shared.GameObjects.Components.Access
|
|||||||
public readonly string TargetIdName;
|
public readonly string TargetIdName;
|
||||||
public readonly string TargetIdFullName;
|
public readonly string TargetIdFullName;
|
||||||
public readonly string TargetIdJobTitle;
|
public readonly string TargetIdJobTitle;
|
||||||
public readonly List<string> TargetIdAccessList;
|
public readonly string[] TargetIdAccessList;
|
||||||
|
|
||||||
public IdCardConsoleBoundUserInterfaceState(bool isPrivilegedIdPresent,
|
public IdCardConsoleBoundUserInterfaceState(bool isPrivilegedIdPresent,
|
||||||
bool isPrivilegedIdAuthorized,
|
bool isPrivilegedIdAuthorized,
|
||||||
bool isTargetIdPresent,
|
bool isTargetIdPresent,
|
||||||
string targetIdFullName,
|
string targetIdFullName,
|
||||||
string targetIdJobTitle,
|
string targetIdJobTitle,
|
||||||
List<string> targetIdAccessList, string privilegedIdName, string targetIdName)
|
string[] targetIdAccessList, string privilegedIdName, string targetIdName)
|
||||||
{
|
{
|
||||||
IsPrivilegedIdPresent = isPrivilegedIdPresent;
|
IsPrivilegedIdPresent = isPrivilegedIdPresent;
|
||||||
IsPrivilegedIdAuthorized = isPrivilegedIdAuthorized;
|
IsPrivilegedIdAuthorized = isPrivilegedIdAuthorized;
|
||||||
|
|||||||
@@ -0,0 +1,85 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using Content.Server.GameObjects.Components.Access;
|
||||||
|
using NUnit.Framework;
|
||||||
|
|
||||||
|
namespace Content.Tests.Server.GameObjects.Components.Access
|
||||||
|
{
|
||||||
|
[TestFixture]
|
||||||
|
[TestOf(typeof(AccessReader))]
|
||||||
|
public class AccessReaderTest : ContentUnitTest
|
||||||
|
{
|
||||||
|
[Test]
|
||||||
|
public void TestEmpty()
|
||||||
|
{
|
||||||
|
var reader = new AccessReader();
|
||||||
|
|
||||||
|
Assert.That(reader.IsAllowed(new[] {"Foo"}), Is.True);
|
||||||
|
Assert.That(reader.IsAllowed(new[] {"Bar"}), Is.True);
|
||||||
|
Assert.That(reader.IsAllowed(new string[] {}), Is.True);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestDeny()
|
||||||
|
{
|
||||||
|
var reader = new AccessReader();
|
||||||
|
reader.DenyTags.Add("A");
|
||||||
|
|
||||||
|
Assert.That(reader.IsAllowed(new[] {"Foo"}), Is.True);
|
||||||
|
Assert.That(reader.IsAllowed(new[] {"A"}), Is.False);
|
||||||
|
Assert.That(reader.IsAllowed(new[] {"A", "Foo"}), Is.False);
|
||||||
|
Assert.That(reader.IsAllowed(new string[] {}), Is.True);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestOneList()
|
||||||
|
{
|
||||||
|
var reader = new AccessReader();
|
||||||
|
reader.AccessLists.Add(new HashSet<string> {"A"});
|
||||||
|
|
||||||
|
Assert.That(reader.IsAllowed(new[] {"A"}), Is.True);
|
||||||
|
Assert.That(reader.IsAllowed(new[] {"B"}), Is.False);
|
||||||
|
Assert.That(reader.IsAllowed(new[] {"A", "B"}), Is.True);
|
||||||
|
Assert.That(reader.IsAllowed(new string[] {}), Is.False);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestOneListTwoItems()
|
||||||
|
{
|
||||||
|
var reader = new AccessReader();
|
||||||
|
reader.AccessLists.Add(new HashSet<string> {"A", "B"});
|
||||||
|
|
||||||
|
Assert.That(reader.IsAllowed(new[] {"A"}), Is.False);
|
||||||
|
Assert.That(reader.IsAllowed(new[] {"B"}), Is.False);
|
||||||
|
Assert.That(reader.IsAllowed(new[] {"A", "B"}), Is.True);
|
||||||
|
Assert.That(reader.IsAllowed(new string[] {}), Is.False);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestTwoList()
|
||||||
|
{
|
||||||
|
var reader = new AccessReader();
|
||||||
|
reader.AccessLists.Add(new HashSet<string> {"A"});
|
||||||
|
reader.AccessLists.Add(new HashSet<string> {"B", "C"});
|
||||||
|
|
||||||
|
Assert.That(reader.IsAllowed(new[] {"A"}), Is.True);
|
||||||
|
Assert.That(reader.IsAllowed(new[] {"B"}), Is.False);
|
||||||
|
Assert.That(reader.IsAllowed(new[] {"A", "B"}), Is.True);
|
||||||
|
Assert.That(reader.IsAllowed(new[] {"C", "B"}), Is.True);
|
||||||
|
Assert.That(reader.IsAllowed(new[] {"C", "B", "A"}), Is.True);
|
||||||
|
Assert.That(reader.IsAllowed(new string[] {}), Is.False);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestDenyList()
|
||||||
|
{
|
||||||
|
var reader = new AccessReader();
|
||||||
|
reader.AccessLists.Add(new HashSet<string> {"A"});
|
||||||
|
reader.DenyTags.Add("B");
|
||||||
|
|
||||||
|
Assert.That(reader.IsAllowed(new[] {"A"}), Is.True);
|
||||||
|
Assert.That(reader.IsAllowed(new[] {"B"}), Is.False);
|
||||||
|
Assert.That(reader.IsAllowed(new[] {"A", "B"}), Is.False);
|
||||||
|
Assert.That(reader.IsAllowed(new string[] {}), Is.False);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7484,8 +7484,8 @@ entities:
|
|||||||
pos: 6.5,17.5
|
pos: 6.5,17.5
|
||||||
rot: -1.5707963267948966 rad
|
rot: -1.5707963267948966 rad
|
||||||
type: Transform
|
type: Transform
|
||||||
- necessary:
|
- access:
|
||||||
- HeadOfPersonnel
|
- - HeadOfPersonnel
|
||||||
type: AccessReader
|
type: AccessReader
|
||||||
- uid: 1042
|
- uid: 1042
|
||||||
type: reinforced_wall
|
type: reinforced_wall
|
||||||
@@ -22369,8 +22369,8 @@ entities:
|
|||||||
pos: 5.5,25.5
|
pos: 5.5,25.5
|
||||||
rot: -1.5707963267948966 rad
|
rot: -1.5707963267948966 rad
|
||||||
type: Transform
|
type: Transform
|
||||||
- necessary:
|
- access:
|
||||||
- Captain
|
- - Captain
|
||||||
type: AccessReader
|
type: AccessReader
|
||||||
- uid: 2893
|
- uid: 2893
|
||||||
type: AirlockMaintCommonLocked
|
type: AirlockMaintCommonLocked
|
||||||
@@ -22527,9 +22527,9 @@ entities:
|
|||||||
pos: 38.5,1.5
|
pos: 38.5,1.5
|
||||||
rot: -1.5707963267948966 rad
|
rot: -1.5707963267948966 rad
|
||||||
type: Transform
|
type: Transform
|
||||||
- necessary:
|
- access:
|
||||||
- Engineering
|
- - Engineering
|
||||||
- Command
|
- Command
|
||||||
type: AccessReader
|
type: AccessReader
|
||||||
- uid: 2912
|
- uid: 2912
|
||||||
type: Catwalk
|
type: Catwalk
|
||||||
@@ -22545,8 +22545,8 @@ entities:
|
|||||||
pos: 11.5,20.5
|
pos: 11.5,20.5
|
||||||
rot: -1.5707963267948966 rad
|
rot: -1.5707963267948966 rad
|
||||||
type: Transform
|
type: Transform
|
||||||
- necessary:
|
- access:
|
||||||
- HeadOfPersonnel
|
- - HeadOfPersonnel
|
||||||
type: AccessReader
|
type: AccessReader
|
||||||
- uid: 2914
|
- uid: 2914
|
||||||
type: AirlockExternalLocked
|
type: AirlockExternalLocked
|
||||||
@@ -22601,8 +22601,8 @@ entities:
|
|||||||
pos: -8.5,-7.5
|
pos: -8.5,-7.5
|
||||||
rot: -1.5707963267948966 rad
|
rot: -1.5707963267948966 rad
|
||||||
type: Transform
|
type: Transform
|
||||||
- necessary:
|
- access:
|
||||||
- Service
|
- - Service
|
||||||
type: AccessReader
|
type: AccessReader
|
||||||
- uid: 2921
|
- uid: 2921
|
||||||
type: AirlockServiceGlassLocked
|
type: AirlockServiceGlassLocked
|
||||||
@@ -22687,8 +22687,8 @@ entities:
|
|||||||
pos: -20.5,11.5
|
pos: -20.5,11.5
|
||||||
rot: -1.5707963267948966 rad
|
rot: -1.5707963267948966 rad
|
||||||
type: Transform
|
type: Transform
|
||||||
- necessary:
|
- access:
|
||||||
- Janitor
|
- - Janitor
|
||||||
type: AccessReader
|
type: AccessReader
|
||||||
- uid: 2932
|
- uid: 2932
|
||||||
type: AirlockEngineeringGlassLocked
|
type: AirlockEngineeringGlassLocked
|
||||||
@@ -22735,9 +22735,9 @@ entities:
|
|||||||
pos: 20.5,-13.5
|
pos: 20.5,-13.5
|
||||||
rot: -1.5707963267948966 rad
|
rot: -1.5707963267948966 rad
|
||||||
type: Transform
|
type: Transform
|
||||||
- necessary:
|
- access:
|
||||||
- Medical
|
- - Medical
|
||||||
- Command
|
- Command
|
||||||
type: AccessReader
|
type: AccessReader
|
||||||
- uid: 2937
|
- uid: 2937
|
||||||
type: AirlockCommandGlassLocked
|
type: AirlockCommandGlassLocked
|
||||||
@@ -22748,9 +22748,9 @@ entities:
|
|||||||
pos: -8.5,-21.5
|
pos: -8.5,-21.5
|
||||||
rot: -1.5707963267948966 rad
|
rot: -1.5707963267948966 rad
|
||||||
type: Transform
|
type: Transform
|
||||||
- necessary:
|
- access:
|
||||||
- Research
|
- - Research
|
||||||
- Command
|
- Command
|
||||||
type: AccessReader
|
type: AccessReader
|
||||||
- uid: 2938
|
- uid: 2938
|
||||||
type: AirlockCommandGlassLocked
|
type: AirlockCommandGlassLocked
|
||||||
@@ -22761,9 +22761,9 @@ entities:
|
|||||||
pos: -3.5,-21.5
|
pos: -3.5,-21.5
|
||||||
rot: -1.5707963267948966 rad
|
rot: -1.5707963267948966 rad
|
||||||
type: Transform
|
type: Transform
|
||||||
- necessary:
|
- access:
|
||||||
- Research
|
- - Research
|
||||||
- Command
|
- Command
|
||||||
type: AccessReader
|
type: AccessReader
|
||||||
- uid: 2939
|
- uid: 2939
|
||||||
type: AirlockScienceLocked
|
type: AirlockScienceLocked
|
||||||
@@ -22801,8 +22801,8 @@ entities:
|
|||||||
pos: -25.5,10.5
|
pos: -25.5,10.5
|
||||||
rot: -1.5707963267948966 rad
|
rot: -1.5707963267948966 rad
|
||||||
type: Transform
|
type: Transform
|
||||||
- necessary:
|
- access:
|
||||||
- Maintenance
|
- - Maintenance
|
||||||
type: AccessReader
|
type: AccessReader
|
||||||
- uid: 2943
|
- uid: 2943
|
||||||
type: AirlockServiceGlassLocked
|
type: AirlockServiceGlassLocked
|
||||||
@@ -22813,8 +22813,8 @@ entities:
|
|||||||
pos: -25.5,8.5
|
pos: -25.5,8.5
|
||||||
rot: -1.5707963267948966 rad
|
rot: -1.5707963267948966 rad
|
||||||
type: Transform
|
type: Transform
|
||||||
- necessary:
|
- access:
|
||||||
- Maintenance
|
- - Maintenance
|
||||||
type: AccessReader
|
type: AccessReader
|
||||||
- uid: 2944
|
- uid: 2944
|
||||||
type: AirlockGlass
|
type: AirlockGlass
|
||||||
@@ -22834,8 +22834,8 @@ entities:
|
|||||||
pos: -20.5,-7.5
|
pos: -20.5,-7.5
|
||||||
rot: -1.5707963267948966 rad
|
rot: -1.5707963267948966 rad
|
||||||
type: Transform
|
type: Transform
|
||||||
- necessary:
|
- access:
|
||||||
- Theatre
|
- - Theatre
|
||||||
type: AccessReader
|
type: AccessReader
|
||||||
- uid: 2946
|
- uid: 2946
|
||||||
type: Airlock
|
type: Airlock
|
||||||
@@ -22889,8 +22889,8 @@ entities:
|
|||||||
pos: -14.5,-4.5
|
pos: -14.5,-4.5
|
||||||
rot: -1.5707963267948966 rad
|
rot: -1.5707963267948966 rad
|
||||||
type: Transform
|
type: Transform
|
||||||
- necessary:
|
- access:
|
||||||
- Service
|
- - Service
|
||||||
type: AccessReader
|
type: AccessReader
|
||||||
- uid: 2952
|
- uid: 2952
|
||||||
type: AirlockMaintCommonLocked
|
type: AirlockMaintCommonLocked
|
||||||
@@ -22899,8 +22899,8 @@ entities:
|
|||||||
pos: -16.5,-7.5
|
pos: -16.5,-7.5
|
||||||
rot: -1.5707963267948966 rad
|
rot: -1.5707963267948966 rad
|
||||||
type: Transform
|
type: Transform
|
||||||
- necessary:
|
- access:
|
||||||
- Service
|
- - Service
|
||||||
type: AccessReader
|
type: AccessReader
|
||||||
- uid: 2953
|
- uid: 2953
|
||||||
type: AirlockMaintCommonLocked
|
type: AirlockMaintCommonLocked
|
||||||
@@ -23002,8 +23002,8 @@ entities:
|
|||||||
pos: 7.5,6.5
|
pos: 7.5,6.5
|
||||||
rot: -1.5707963267948966 rad
|
rot: -1.5707963267948966 rad
|
||||||
type: Transform
|
type: Transform
|
||||||
- necessary:
|
- access:
|
||||||
- External
|
- - External
|
||||||
type: AccessReader
|
type: AccessReader
|
||||||
- uid: 2966
|
- uid: 2966
|
||||||
type: AirlockCommandGlassLocked
|
type: AirlockCommandGlassLocked
|
||||||
@@ -23014,8 +23014,8 @@ entities:
|
|||||||
pos: 9.5,6.5
|
pos: 9.5,6.5
|
||||||
rot: -1.5707963267948966 rad
|
rot: -1.5707963267948966 rad
|
||||||
type: Transform
|
type: Transform
|
||||||
- necessary:
|
- access:
|
||||||
- External
|
- - External
|
||||||
type: AccessReader
|
type: AccessReader
|
||||||
- uid: 2967
|
- uid: 2967
|
||||||
type: AirlockMaintCommandLocked
|
type: AirlockMaintCommandLocked
|
||||||
@@ -23024,8 +23024,8 @@ entities:
|
|||||||
pos: 8.5,12.5
|
pos: 8.5,12.5
|
||||||
rot: -1.5707963267948966 rad
|
rot: -1.5707963267948966 rad
|
||||||
type: Transform
|
type: Transform
|
||||||
- necessary:
|
- access:
|
||||||
- External
|
- - External
|
||||||
type: AccessReader
|
type: AccessReader
|
||||||
- uid: 2968
|
- uid: 2968
|
||||||
type: AirlockCargoGlassLocked
|
type: AirlockCargoGlassLocked
|
||||||
@@ -23063,8 +23063,8 @@ entities:
|
|||||||
pos: 20.5,14.5
|
pos: 20.5,14.5
|
||||||
rot: -1.5707963267948966 rad
|
rot: -1.5707963267948966 rad
|
||||||
type: Transform
|
type: Transform
|
||||||
- necessary:
|
- access:
|
||||||
- Cargo
|
- - Cargo
|
||||||
type: AccessReader
|
type: AccessReader
|
||||||
- uid: 2972
|
- uid: 2972
|
||||||
type: AirlockExternalLocked
|
type: AirlockExternalLocked
|
||||||
@@ -23075,8 +23075,8 @@ entities:
|
|||||||
pos: 20.5,16.5
|
pos: 20.5,16.5
|
||||||
rot: -1.5707963267948966 rad
|
rot: -1.5707963267948966 rad
|
||||||
type: Transform
|
type: Transform
|
||||||
- necessary:
|
- access:
|
||||||
- Cargo
|
- - Cargo
|
||||||
type: AccessReader
|
type: AccessReader
|
||||||
- uid: 2973
|
- uid: 2973
|
||||||
type: AirlockExternalLocked
|
type: AirlockExternalLocked
|
||||||
@@ -23087,8 +23087,8 @@ entities:
|
|||||||
pos: 22.5,16.5
|
pos: 22.5,16.5
|
||||||
rot: -1.5707963267948966 rad
|
rot: -1.5707963267948966 rad
|
||||||
type: Transform
|
type: Transform
|
||||||
- necessary:
|
- access:
|
||||||
- Cargo
|
- - Cargo
|
||||||
type: AccessReader
|
type: AccessReader
|
||||||
- uid: 2974
|
- uid: 2974
|
||||||
type: AirlockExternalLocked
|
type: AirlockExternalLocked
|
||||||
@@ -23099,8 +23099,8 @@ entities:
|
|||||||
pos: 22.5,14.5
|
pos: 22.5,14.5
|
||||||
rot: -1.5707963267948966 rad
|
rot: -1.5707963267948966 rad
|
||||||
type: Transform
|
type: Transform
|
||||||
- necessary:
|
- access:
|
||||||
- Cargo
|
- - Cargo
|
||||||
type: AccessReader
|
type: AccessReader
|
||||||
- uid: 2975
|
- uid: 2975
|
||||||
type: AirlockExternalLocked
|
type: AirlockExternalLocked
|
||||||
@@ -23118,9 +23118,9 @@ entities:
|
|||||||
pos: -8.5,18.5
|
pos: -8.5,18.5
|
||||||
rot: -1.5707963267948966 rad
|
rot: -1.5707963267948966 rad
|
||||||
type: Transform
|
type: Transform
|
||||||
- necessary:
|
- access:
|
||||||
- Security
|
- - Security
|
||||||
- Command
|
- Command
|
||||||
type: AccessReader
|
type: AccessReader
|
||||||
- uid: 2977
|
- uid: 2977
|
||||||
type: Poweredlight
|
type: Poweredlight
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
suffix: Service, Locked
|
suffix: Service, Locked
|
||||||
components:
|
components:
|
||||||
- type: AccessReader
|
- type: AccessReader
|
||||||
necessary: ["Service"]
|
access: [["Service"]]
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: AirlockExternal
|
parent: AirlockExternal
|
||||||
@@ -13,7 +13,7 @@
|
|||||||
suffix: External, Locked
|
suffix: External, Locked
|
||||||
components:
|
components:
|
||||||
- type: AccessReader
|
- type: AccessReader
|
||||||
necessary: ["External"]
|
access: [["External"]]
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: AirlockEngineering
|
parent: AirlockEngineering
|
||||||
@@ -21,7 +21,7 @@
|
|||||||
suffix: Engineering, Locked
|
suffix: Engineering, Locked
|
||||||
components:
|
components:
|
||||||
- type: AccessReader
|
- type: AccessReader
|
||||||
necessary: ["Engineering"]
|
access: [["Engineering"]]
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: AirlockCargo
|
parent: AirlockCargo
|
||||||
@@ -29,7 +29,7 @@
|
|||||||
suffix: Cargo, Locked
|
suffix: Cargo, Locked
|
||||||
components:
|
components:
|
||||||
- type: AccessReader
|
- type: AccessReader
|
||||||
necessary: ["Cargo"]
|
access: [["Cargo"]]
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: AirlockMedical
|
parent: AirlockMedical
|
||||||
@@ -37,7 +37,7 @@
|
|||||||
suffix: Medical, Locked
|
suffix: Medical, Locked
|
||||||
components:
|
components:
|
||||||
- type: AccessReader
|
- type: AccessReader
|
||||||
necessary: ["Medical"]
|
access: [["Medical"]]
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: AirlockScience
|
parent: AirlockScience
|
||||||
@@ -45,7 +45,7 @@
|
|||||||
suffix: Science, Locked
|
suffix: Science, Locked
|
||||||
components:
|
components:
|
||||||
- type: AccessReader
|
- type: AccessReader
|
||||||
necessary: ["Research"]
|
access: [["Research"]]
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: AirlockCommand
|
parent: AirlockCommand
|
||||||
@@ -53,7 +53,7 @@
|
|||||||
suffix: Command, Locked
|
suffix: Command, Locked
|
||||||
components:
|
components:
|
||||||
- type: AccessReader
|
- type: AccessReader
|
||||||
necessary: ["Command"]
|
access: [["Command"]]
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: AirlockSecurity
|
parent: AirlockSecurity
|
||||||
@@ -61,7 +61,7 @@
|
|||||||
suffix: Security, Locked
|
suffix: Security, Locked
|
||||||
components:
|
components:
|
||||||
- type: AccessReader
|
- type: AccessReader
|
||||||
necessary: ["Security"]
|
access: [["Security"]]
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: AirlockSecurity
|
parent: AirlockSecurity
|
||||||
@@ -69,7 +69,7 @@
|
|||||||
suffix: Vault, Locked
|
suffix: Vault, Locked
|
||||||
components:
|
components:
|
||||||
- type: AccessReader
|
- type: AccessReader
|
||||||
necessary: ["Security", "Command"]
|
access: [["Security", "Command"]]
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: AirlockCommand
|
parent: AirlockCommand
|
||||||
@@ -77,7 +77,7 @@
|
|||||||
suffix: EVA, Locked
|
suffix: EVA, Locked
|
||||||
components:
|
components:
|
||||||
- type: AccessReader
|
- type: AccessReader
|
||||||
necessary: ["External"]
|
access: [["External"]]
|
||||||
|
|
||||||
# Glass Airlocks
|
# Glass Airlocks
|
||||||
- type: entity
|
- type: entity
|
||||||
@@ -86,7 +86,7 @@
|
|||||||
suffix: Service, Locked
|
suffix: Service, Locked
|
||||||
components:
|
components:
|
||||||
- type: AccessReader
|
- type: AccessReader
|
||||||
necessary: ["Service"]
|
access: [["Service"]]
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: AirlockEngineeringGlass
|
parent: AirlockEngineeringGlass
|
||||||
@@ -94,7 +94,7 @@
|
|||||||
suffix: Glass, Locked
|
suffix: Glass, Locked
|
||||||
components:
|
components:
|
||||||
- type: AccessReader
|
- type: AccessReader
|
||||||
necessary: ["Engineering"]
|
access: [["Engineering"]]
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: AirlockCargoGlass
|
parent: AirlockCargoGlass
|
||||||
@@ -102,7 +102,7 @@
|
|||||||
suffix: Cargo, Locked
|
suffix: Cargo, Locked
|
||||||
components:
|
components:
|
||||||
- type: AccessReader
|
- type: AccessReader
|
||||||
necessary: ["Cargo"]
|
access: [["Cargo"]]
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: AirlockMedicalGlass
|
parent: AirlockMedicalGlass
|
||||||
@@ -110,7 +110,7 @@
|
|||||||
suffix: Medical, Locked
|
suffix: Medical, Locked
|
||||||
components:
|
components:
|
||||||
- type: AccessReader
|
- type: AccessReader
|
||||||
necessary: ["Medical"]
|
access: [["Medical"]]
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: AirlockScienceGlass
|
parent: AirlockScienceGlass
|
||||||
@@ -118,7 +118,7 @@
|
|||||||
suffix: Science, Locked
|
suffix: Science, Locked
|
||||||
components:
|
components:
|
||||||
- type: AccessReader
|
- type: AccessReader
|
||||||
necessary: ["Research"]
|
access: [["Research"]]
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: AirlockCommandGlass
|
parent: AirlockCommandGlass
|
||||||
@@ -126,7 +126,7 @@
|
|||||||
suffix: Command, Locked
|
suffix: Command, Locked
|
||||||
components:
|
components:
|
||||||
- type: AccessReader
|
- type: AccessReader
|
||||||
necessary: ["Command"]
|
access: [["Command"]]
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: AirlockSecurityGlass
|
parent: AirlockSecurityGlass
|
||||||
@@ -134,7 +134,7 @@
|
|||||||
suffix: Security, Locked
|
suffix: Security, Locked
|
||||||
components:
|
components:
|
||||||
- type: AccessReader
|
- type: AccessReader
|
||||||
necessary: ["Security"]
|
access: [["Security"]]
|
||||||
|
|
||||||
# Maintenance Hatchs
|
# Maintenance Hatchs
|
||||||
- type: entity
|
- type: entity
|
||||||
@@ -143,7 +143,7 @@
|
|||||||
suffix: Locked
|
suffix: Locked
|
||||||
components:
|
components:
|
||||||
- type: AccessReader
|
- type: AccessReader
|
||||||
necessary: ["Maintenance"]
|
access: [["Maintenance"]]
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: AirlockMaintCargo
|
parent: AirlockMaintCargo
|
||||||
@@ -151,7 +151,7 @@
|
|||||||
suffix: Cargo, Locked
|
suffix: Cargo, Locked
|
||||||
components:
|
components:
|
||||||
- type: AccessReader
|
- type: AccessReader
|
||||||
necessary: ["Cargo", "Maintenance"]
|
access: [["Cargo"]]
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: AirlockMaintCommand
|
parent: AirlockMaintCommand
|
||||||
@@ -159,7 +159,7 @@
|
|||||||
suffix: Command, Locked
|
suffix: Command, Locked
|
||||||
components:
|
components:
|
||||||
- type: AccessReader
|
- type: AccessReader
|
||||||
necessary: ["Command", "Maintenance"]
|
access: [["Command"]]
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: AirlockMaintCommon
|
parent: AirlockMaintCommon
|
||||||
@@ -167,7 +167,7 @@
|
|||||||
suffix: Common, Locked
|
suffix: Common, Locked
|
||||||
components:
|
components:
|
||||||
- type: AccessReader
|
- type: AccessReader
|
||||||
necessary: ["Maintenance"]
|
access: [["Maintenance"]]
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: AirlockMaintEngi
|
parent: AirlockMaintEngi
|
||||||
@@ -175,15 +175,15 @@
|
|||||||
suffix: Engineering, Locked
|
suffix: Engineering, Locked
|
||||||
components:
|
components:
|
||||||
- type: AccessReader
|
- type: AccessReader
|
||||||
necessary: ["Engineering", "Maintenance"]
|
access: [["Engineering"]]
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: AirlockMaintInt
|
parent: AirlockMaintInt
|
||||||
id: AirlockMaintIntLocked
|
id: AirlockMaintIntLocked
|
||||||
suffix: Interior, Locked
|
suffix: Interior, Locked
|
||||||
components:
|
components:
|
||||||
- type: AccessReader
|
- type: AccessReader
|
||||||
necessary: ["Maintenance"]
|
access: [["Maintenance"]]
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: AirlockMaintMed
|
parent: AirlockMaintMed
|
||||||
@@ -191,7 +191,7 @@
|
|||||||
suffix: Medical, Locked
|
suffix: Medical, Locked
|
||||||
components:
|
components:
|
||||||
- type: AccessReader
|
- type: AccessReader
|
||||||
necessary: ["Medical", "Maintenance"]
|
access: [["Medical"]]
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: AirlockMaintRnD
|
parent: AirlockMaintRnD
|
||||||
@@ -199,7 +199,7 @@
|
|||||||
suffix: RnD, Locked
|
suffix: RnD, Locked
|
||||||
components:
|
components:
|
||||||
- type: AccessReader
|
- type: AccessReader
|
||||||
necessary: ["Research", "Maintenance"]
|
access: [["Research"]]
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: AirlockMaintSec
|
parent: AirlockMaintSec
|
||||||
@@ -207,4 +207,4 @@
|
|||||||
suffix: Security, Locked
|
suffix: Security, Locked
|
||||||
components:
|
components:
|
||||||
- type: AccessReader
|
- type: AccessReader
|
||||||
necessary: ["Security", "Maintenance"]
|
access: [["Security"]]
|
||||||
|
|||||||
@@ -158,7 +158,7 @@
|
|||||||
name: ID Card Computer
|
name: ID Card Computer
|
||||||
components:
|
components:
|
||||||
- type: AccessReader
|
- type: AccessReader
|
||||||
necessary: ["HeadOfPersonnel"]
|
access: [["HeadOfPersonnel"]]
|
||||||
- type: IdCardConsole
|
- type: IdCardConsole
|
||||||
- type: UserInterface
|
- type: UserInterface
|
||||||
interfaces:
|
interfaces:
|
||||||
|
|||||||
Reference in New Issue
Block a user