From f3b460c8b48f38da28f183676d49858b62b6a340 Mon Sep 17 00:00:00 2001 From: DamianX Date: Sun, 1 Sep 2019 22:57:22 +0200 Subject: [PATCH] IDs and access (#319) * something about access * Fixed deny animation --- Content.Client/EntryPoint.cs | 3 + .../Components/Doors/AirlockVisualizer2D.cs | 21 +++++ .../Components/Access/AccessComponent.cs | 22 +++++ .../Access/AccessReaderComponent.cs | 86 ++++++++++++++++++ .../Components/Access/IdCardComponent.cs | 25 +++++ .../Components/Doors/ServerDoorComponent.cs | 28 +++++- .../Components/Doors/SharedDoorComponent.cs | 1 + Resources/Audio/machines/airlock_deny.ogg | Bin 0 -> 8481 bytes .../Entities/buildings/airlock_base.yml | 1 + .../Entities/buildings/airlock_types.yml | 10 ++ .../Entities/items/clothing/IDs.yml | 11 ++- .../Clothing/id_cards.rsi/assistant.png | Bin 0 -> 389 bytes .../Textures/Clothing/id_cards.rsi/meta.json | 1 + 13 files changed, 205 insertions(+), 4 deletions(-) create mode 100644 Content.Server/GameObjects/Components/Access/AccessComponent.cs create mode 100644 Content.Server/GameObjects/Components/Access/AccessReaderComponent.cs create mode 100644 Content.Server/GameObjects/Components/Access/IdCardComponent.cs create mode 100644 Resources/Audio/machines/airlock_deny.ogg create mode 100644 Resources/Textures/Clothing/id_cards.rsi/assistant.png create mode 100644 Resources/Textures/Clothing/id_cards.rsi/meta.json diff --git a/Content.Client/EntryPoint.cs b/Content.Client/EntryPoint.cs index d3032c8720..2c7040f6f2 100644 --- a/Content.Client/EntryPoint.cs +++ b/Content.Client/EntryPoint.cs @@ -99,6 +99,9 @@ namespace Content.Client "PlayerInputMover", "Computer", "AsteroidRock", + "IdCard", + "Access", + "AccessReader", }; foreach (var ignoreName in registerIgnore) diff --git a/Content.Client/GameObjects/Components/Doors/AirlockVisualizer2D.cs b/Content.Client/GameObjects/Components/Doors/AirlockVisualizer2D.cs index 85c348e003..a565f07207 100644 --- a/Content.Client/GameObjects/Components/Doors/AirlockVisualizer2D.cs +++ b/Content.Client/GameObjects/Components/Doors/AirlockVisualizer2D.cs @@ -16,6 +16,7 @@ namespace Content.Client.GameObjects.Components.Doors private Animation CloseAnimation; private Animation OpenAnimation; + private Animation DenyAnimation; public override void LoadData(YamlMappingNode node) { @@ -23,6 +24,7 @@ namespace Content.Client.GameObjects.Components.Doors var openSound = node.GetNode("open_sound").AsString(); var closeSound = node.GetNode("close_sound").AsString(); + var denySound = node.GetNode("deny_sound").AsString(); CloseAnimation = new Animation {Length = TimeSpan.FromSeconds(1.2f)}; { @@ -57,6 +59,18 @@ namespace Content.Client.GameObjects.Components.Doors OpenAnimation.AnimationTracks.Add(sound); sound.KeyFrames.Add(new AnimationTrackPlaySound.KeyFrame(openSound, 0)); } + + DenyAnimation = new Animation {Length = TimeSpan.FromSeconds(0.45f)}; + { + var flick = new AnimationTrackSpriteFlick(); + DenyAnimation.AnimationTracks.Add(flick); + flick.LayerKey = DoorVisualLayers.Base; + flick.KeyFrames.Add(new AnimationTrackSpriteFlick.KeyFrame("deny", 0f)); + + var sound = new AnimationTrackPlaySound(); + DenyAnimation.AnimationTracks.Add(sound); + sound.KeyFrames.Add(new AnimationTrackPlaySound.KeyFrame(denySound, 0)); + } } public override void InitializeEntity(IEntity entity) @@ -102,6 +116,13 @@ namespace Content.Client.GameObjects.Components.Doors sprite.LayerSetState(DoorVisualLayers.Base, "open"); sprite.LayerSetVisible(DoorVisualLayers.BaseUnlit, false); break; + case DoorVisualState.Deny: + sprite.LayerSetVisible(DoorVisualLayers.BaseUnlit, false); + if (!animPlayer.HasRunningAnimation(AnimationKey)) + { + animPlayer.Play(DenyAnimation, AnimationKey); + } + break; default: throw new ArgumentOutOfRangeException(); } diff --git a/Content.Server/GameObjects/Components/Access/AccessComponent.cs b/Content.Server/GameObjects/Components/Access/AccessComponent.cs new file mode 100644 index 0000000000..4de9021f28 --- /dev/null +++ b/Content.Server/GameObjects/Components/Access/AccessComponent.cs @@ -0,0 +1,22 @@ +using System.Collections.Generic; +using Robust.Shared.GameObjects; +using Robust.Shared.Serialization; +using Robust.Shared.ViewVariables; + +namespace Content.Server.GameObjects.Components.Access +{ + [RegisterComponent] + public class AccessComponent : Component + { + public override string Name => "Access"; + private List _tags; + [ViewVariables] + public List Tags => _tags; + public override void ExposeData(ObjectSerializer serializer) + { + base.ExposeData(serializer); + + serializer.DataField(ref _tags, "tags", new List()); + } + } +} diff --git a/Content.Server/GameObjects/Components/Access/AccessReaderComponent.cs b/Content.Server/GameObjects/Components/Access/AccessReaderComponent.cs new file mode 100644 index 0000000000..ffa555006e --- /dev/null +++ b/Content.Server/GameObjects/Components/Access/AccessReaderComponent.cs @@ -0,0 +1,86 @@ +using System.Collections.Generic; +using Content.Server.Interfaces.GameObjects; +using Content.Shared.GameObjects.Components.Inventory; +using JetBrains.Annotations; +using Robust.Shared.GameObjects; +using Robust.Shared.Interfaces.GameObjects; +using Robust.Shared.Serialization; +using Robust.Shared.ViewVariables; + +namespace Content.Server.GameObjects.Components.Access +{ + [RegisterComponent] + public class AccessReader : Component + { + public override string Name => "AccessReader"; + private List _necessaryTags; + private List _sufficientTags; + + public bool IsAllowed(IEntity entity) + { + var accessProvider = FindAccessProvider(entity); + return accessProvider != null && IsAllowed(accessProvider); + } + + private bool IsAllowed(AccessComponent accessProvider) + { + foreach (var sufficient in _sufficientTags) + { + if (accessProvider.Tags.Contains(sufficient)) + { + return true; + } + } + foreach (var necessary in _necessaryTags) + { + if (!accessProvider.Tags.Contains(necessary)) + { + return false; + } + } + return true; + } + + [CanBeNull] + private static AccessComponent FindAccessProvider(IEntity entity) + { + if (entity.TryGetComponent(out AccessComponent accessComponent)) + { + return accessComponent; + } + + if (entity.TryGetComponent(out IHandsComponent handsComponent)) + { + var activeHandEntity = handsComponent.GetActiveHand?.Owner; + if (activeHandEntity != null && + activeHandEntity.TryGetComponent(out AccessComponent handAccessComponent)) + { + return handAccessComponent; + } + } + else + { + return null; + } + if (entity.TryGetComponent(out InventoryComponent inventoryComponent)) + { + if (inventoryComponent.HasSlot(EquipmentSlotDefines.Slots.IDCARD) && + inventoryComponent.TryGetSlotItem(EquipmentSlotDefines.Slots.IDCARD, out ItemComponent item) && + item.Owner.TryGetComponent(out AccessComponent idAccessComponent) + ) + { + return idAccessComponent; + } + } + return null; + } + + public override void ExposeData(ObjectSerializer serializer) + { + base.ExposeData(serializer); + + serializer.DataField(ref _necessaryTags, "necessary" ,new List()); + serializer.DataField(ref _sufficientTags, "sufficient", new List()); + } + } +} diff --git a/Content.Server/GameObjects/Components/Access/IdCardComponent.cs b/Content.Server/GameObjects/Components/Access/IdCardComponent.cs new file mode 100644 index 0000000000..0449164baf --- /dev/null +++ b/Content.Server/GameObjects/Components/Access/IdCardComponent.cs @@ -0,0 +1,25 @@ +using System.Security.Cryptography; +using Robust.Shared.GameObjects; +using Robust.Shared.Serialization; +using Robust.Shared.ViewVariables; + +namespace Content.Server.GameObjects.Components.Access +{ + [RegisterComponent] + public class IdCardComponent : Component + { + public override string Name => "IdCard"; + [ViewVariables(VVAccess.ReadWrite)] + private string _fullName; + [ViewVariables(VVAccess.ReadWrite)] + private string _jobTitle; + + public override void ExposeData(ObjectSerializer serializer) + { + base.ExposeData(serializer); + + serializer.DataField(ref _fullName, "fullName", string.Empty); + serializer.DataField(ref _jobTitle, "jobTitle", string.Empty); + } + } +} diff --git a/Content.Server/GameObjects/Components/Doors/ServerDoorComponent.cs b/Content.Server/GameObjects/Components/Doors/ServerDoorComponent.cs index 3ddee7f3bf..60d9bf7197 100644 --- a/Content.Server/GameObjects/Components/Doors/ServerDoorComponent.cs +++ b/Content.Server/GameObjects/Components/Doors/ServerDoorComponent.cs @@ -1,4 +1,5 @@ using System; +using Content.Server.GameObjects.Components.Access; using Content.Server.GameObjects.EntitySystems; using Content.Shared.GameObjects.Components.Doors; using Robust.Server.GameObjects; @@ -26,6 +27,7 @@ namespace Content.Server.GameObjects private static readonly TimeSpan CloseTime = TimeSpan.FromSeconds(1.2f); private static readonly TimeSpan OpenTimeOne = TimeSpan.FromSeconds(0.3f); private static readonly TimeSpan OpenTimeTwo = TimeSpan.FromSeconds(0.9f); + private static readonly TimeSpan DenyTime = TimeSpan.FromSeconds(0.45f); public override void Initialize() { @@ -51,7 +53,7 @@ namespace Content.Server.GameObjects } else if (_state == DoorState.Closed) { - Open(); + TryOpen(eventArgs.User); } } @@ -73,11 +75,24 @@ namespace Content.Server.GameObjects return; } - Open(); + TryOpen(msg.Entity); break; } } + public void TryOpen(IEntity user) + { + if (Owner.TryGetComponent(out AccessReader accessReader)) + { + if (!accessReader.IsAllowed(user)) + { + Deny(); + return; + } + } + Open(); + } + public void Open() { if (_state != DoorState.Closed) @@ -120,6 +135,15 @@ namespace Content.Server.GameObjects return true; } + public void Deny() + { + _appearance.SetData(DoorVisuals.VisualState, DoorVisualState.Deny); + Timer.Spawn(DenyTime, () => + { + _appearance.SetData(DoorVisuals.VisualState, DoorVisualState.Closed); + }); + } + private const float AUTO_CLOSE_DELAY = 5; public void OnUpdate(float frameTime) { diff --git a/Content.Shared/GameObjects/Components/Doors/SharedDoorComponent.cs b/Content.Shared/GameObjects/Components/Doors/SharedDoorComponent.cs index 2a1a57ed3a..0a50523380 100644 --- a/Content.Shared/GameObjects/Components/Doors/SharedDoorComponent.cs +++ b/Content.Shared/GameObjects/Components/Doors/SharedDoorComponent.cs @@ -18,5 +18,6 @@ namespace Content.Shared.GameObjects.Components.Doors Opening, Open, Closing, + Deny, } } diff --git a/Resources/Audio/machines/airlock_deny.ogg b/Resources/Audio/machines/airlock_deny.ogg new file mode 100644 index 0000000000000000000000000000000000000000..1bd0a190cb38ff974a8f62091a39cd5b2badd7ce GIT binary patch literal 8481 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 literal 0 HcmV?d00001 diff --git a/Resources/Prototypes/Entities/buildings/airlock_base.yml b/Resources/Prototypes/Entities/buildings/airlock_base.yml index d0c5a3aafb..0412bcd78e 100644 --- a/Resources/Prototypes/Entities/buildings/airlock_base.yml +++ b/Resources/Prototypes/Entities/buildings/airlock_base.yml @@ -34,6 +34,7 @@ - type: AirlockVisualizer2D open_sound: /Audio/machines/airlock_open.ogg close_sound: /Audio/machines/airlock_close.ogg + deny_sound: /Audio/machines/airlock_deny.ogg placement: mode: SnapgridCenter diff --git a/Resources/Prototypes/Entities/buildings/airlock_types.yml b/Resources/Prototypes/Entities/buildings/airlock_types.yml index c2e7548bfa..9c033d391c 100644 --- a/Resources/Prototypes/Entities/buildings/airlock_types.yml +++ b/Resources/Prototypes/Entities/buildings/airlock_types.yml @@ -14,6 +14,7 @@ - type: AirlockVisualizer2D open_sound: /Audio/machines/airlock_ext_open.ogg close_sound: /Audio/machines/airlock_ext_close.ogg + deny_sound: /Audio/machines/airlock_deny.ogg - type: entity parent: airlock @@ -25,3 +26,12 @@ - type: Icon sprite: Buildings/airlock_engineering.rsi + +- type: entity + parent: airlock_engineering + id: airlock_engineering_locked + name: Locked Engineering Airlock + components: + - type: AccessReader + required: ["engineering"] + diff --git a/Resources/Prototypes/Entities/items/clothing/IDs.yml b/Resources/Prototypes/Entities/items/clothing/IDs.yml index 137e135216..85b2ba7dea 100644 --- a/Resources/Prototypes/Entities/items/clothing/IDs.yml +++ b/Resources/Prototypes/Entities/items/clothing/IDs.yml @@ -5,9 +5,16 @@ description: A card necessary to access various areas aboard the station components: - type: Sprite - texture: Clothing/idcard_standard.png + sprite: Clothing/id_cards.rsi + state: assistant - type: Icon - texture: Clothing/idcard_standard.png + sprite: Clothing/id_cards.rsi + state: assistant - type: Clothing Slots: - idcard + - type: IdCard + fullName: John Doe + jobTitle: Assistant + - type: Access + tags: ["civilian", "maintenance", "engineering"] diff --git a/Resources/Textures/Clothing/id_cards.rsi/assistant.png b/Resources/Textures/Clothing/id_cards.rsi/assistant.png new file mode 100644 index 0000000000000000000000000000000000000000..e3ebb17277776328eecdf4522197aededb64f9c7 GIT binary patch literal 389 zcmV;00eb$4P)C#yQ zhYk)7anKwI+Bs|8Xd*}QcC9YIdL50x-L-^A%q~Bg+#Lu zK#%#_aU1~NK6ZI(H`#x$#dIvIk(W$OYzhHO{qvu-=x4+IpI9Vb<5CnSLUDu`4=>X6dS9O`SJRjo6 z0RUb%U+A`bT-@~mP)gOxGZYO#p=i)*Eg2xsVzHoAwbGK52Kc@((&^xx-t`&N0UQU9 jzY>{lLW{*>`Ex!2wSkEyx!Mw<00000NkvXXu0mjfaCEF` literal 0 HcmV?d00001 diff --git a/Resources/Textures/Clothing/id_cards.rsi/meta.json b/Resources/Textures/Clothing/id_cards.rsi/meta.json new file mode 100644 index 0000000000..3480e885c2 --- /dev/null +++ b/Resources/Textures/Clothing/id_cards.rsi/meta.json @@ -0,0 +1 @@ +{"version": 1, "size": {"x": 32, "y": 32}, "states": [{"name": "assistant", "directions": 1, "delays": [[1.0]]}]} \ No newline at end of file