diff --git a/Content.Client/Access/AccessOverlay.cs b/Content.Client/Access/AccessOverlay.cs index 1ba2dc613f..2be3d07e90 100644 --- a/Content.Client/Access/AccessOverlay.cs +++ b/Content.Client/Access/AccessOverlay.cs @@ -11,14 +11,16 @@ public sealed class AccessOverlay : Overlay { private readonly IEntityManager _entityManager; private readonly EntityLookupSystem _lookup; + private readonly SharedTransformSystem _xform; private readonly Font _font; public override OverlaySpace Space => OverlaySpace.ScreenSpace; - public AccessOverlay(IEntityManager entManager, IResourceCache cache, EntityLookupSystem lookup) + public AccessOverlay(IEntityManager entManager, IResourceCache cache, EntityLookupSystem lookup, SharedTransformSystem xform) { _entityManager = entManager; _lookup = lookup; + _xform = xform; _font = cache.GetFont("/Fonts/NotoSans/NotoSans-Regular.ttf", 12); } @@ -71,7 +73,7 @@ public sealed class AccessOverlay : Overlay textStr = ""; } - var screenPos = args.ViewportControl.WorldToScreen(xform.WorldPosition); + var screenPos = args.ViewportControl.WorldToScreen(_xform.GetWorldPosition(xform)); args.ScreenHandle.DrawString(_font, screenPos, textStr, Color.Gold); } diff --git a/Content.Client/Access/AccessSystem.cs b/Content.Client/Access/AccessSystem.cs index a5680ab937..a510d6cae7 100644 --- a/Content.Client/Access/AccessSystem.cs +++ b/Content.Client/Access/AccessSystem.cs @@ -2,4 +2,6 @@ using Content.Shared.Access.Systems; namespace Content.Client.Access; -public sealed class AccessSystem : SharedAccessSystem {} +public sealed class AccessSystem : SharedAccessSystem +{ +} diff --git a/Content.Client/Access/Commands/ShowAccessReadersCommand.cs b/Content.Client/Access/Commands/ShowAccessReadersCommand.cs index fa26df1944..7c804dd969 100644 --- a/Content.Client/Access/Commands/ShowAccessReadersCommand.cs +++ b/Content.Client/Access/Commands/ShowAccessReadersCommand.cs @@ -13,7 +13,8 @@ public sealed class ShowAccessReadersCommand : IConsoleCommand { var collection = IoCManager.Instance; - if (collection == null) return; + if (collection == null) + return; var overlay = collection.Resolve(); @@ -25,9 +26,10 @@ public sealed class ShowAccessReadersCommand : IConsoleCommand var entManager = collection.Resolve(); var cache = collection.Resolve(); - var system = entManager.EntitySysManager.GetEntitySystem(); + var lookup = entManager.System(); + var xform = entManager.System(); - overlay.AddOverlay(new AccessOverlay(entManager, cache, system)); + overlay.AddOverlay(new AccessOverlay(entManager, cache, lookup, xform)); shell.WriteLine($"Set access reader debug overlay to true"); } } diff --git a/Content.Client/Access/UI/AgentIDCardBoundUserInterface.cs b/Content.Client/Access/UI/AgentIDCardBoundUserInterface.cs index a7c499c12e..6eae796856 100644 --- a/Content.Client/Access/UI/AgentIDCardBoundUserInterface.cs +++ b/Content.Client/Access/UI/AgentIDCardBoundUserInterface.cs @@ -56,9 +56,10 @@ namespace Content.Client.Access.UI protected override void Dispose(bool disposing) { base.Dispose(disposing); - if (!disposing) return; + if (!disposing) + return; + _window?.Dispose(); } } - } diff --git a/Content.Client/Access/UI/IdCardConsoleBoundUserInterface.cs b/Content.Client/Access/UI/IdCardConsoleBoundUserInterface.cs index f1350a21b4..292759dc87 100644 --- a/Content.Client/Access/UI/IdCardConsoleBoundUserInterface.cs +++ b/Content.Client/Access/UI/IdCardConsoleBoundUserInterface.cs @@ -51,7 +51,9 @@ namespace Content.Client.Access.UI protected override void Dispose(bool disposing) { base.Dispose(disposing); - if (!disposing) return; + if (!disposing) + return; + _window?.Dispose(); } diff --git a/Content.Client/Access/UI/IdCardConsoleWindow.xaml.cs b/Content.Client/Access/UI/IdCardConsoleWindow.xaml.cs index ffd949a643..f8450fe578 100644 --- a/Content.Client/Access/UI/IdCardConsoleWindow.xaml.cs +++ b/Content.Client/Access/UI/IdCardConsoleWindow.xaml.cs @@ -15,6 +15,8 @@ namespace Content.Client.Access.UI public sealed partial class IdCardConsoleWindow : DefaultWindow { [Dependency] private readonly IPrototypeManager _prototypeManager = default!; + [Dependency] private readonly ILogManager _logManager = default!; + private readonly ISawmill _logMill = default!; private readonly IdCardConsoleBoundUserInterface _owner; @@ -30,6 +32,7 @@ namespace Content.Client.Access.UI { RobustXamlLoader.Load(this); IoCManager.InjectDependencies(this); + _logMill = _logManager.GetSawmill(SharedIdCardConsoleSystem.Sawmill); _owner = owner; @@ -67,7 +70,7 @@ namespace Content.Client.Access.UI { if (!prototypeManager.TryIndex(access, out var accessLevel)) { - Logger.ErrorS(SharedIdCardConsoleSystem.Sawmill, $"Unable to find accesslevel for {access}"); + _logMill.Error($"Unable to find accesslevel for {access}"); continue; } diff --git a/Content.IntegrationTests/Tests/Access/AccessReaderTest.cs b/Content.IntegrationTests/Tests/Access/AccessReaderTest.cs index b5074008a6..4ca960c7dd 100644 --- a/Content.IntegrationTests/Tests/Access/AccessReaderTest.cs +++ b/Content.IntegrationTests/Tests/Access/AccessReaderTest.cs @@ -1,7 +1,11 @@ using System.Collections.Generic; +using System.Linq; +using Content.Shared.Access; using Content.Shared.Access.Components; using Content.Shared.Access.Systems; using Robust.Shared.GameObjects; +using Robust.Shared.Prototypes; +using Serilog; namespace Content.IntegrationTests.Tests.Access { @@ -9,6 +13,35 @@ namespace Content.IntegrationTests.Tests.Access [TestOf(typeof(AccessReaderComponent))] public sealed class AccessReaderTest { + [Test] + public async Task TestProtoTags() + { + await using var pair = await PoolManager.GetServerClient(new PoolSettings() { NoClient = true }); + var server = pair.Pair.Server; + + var protoManager = server.ResolveDependency(); + var accessName = server.ResolveDependency().GetComponentName(typeof(AccessReaderComponent)); + + await server.WaitAssertion(() => + { + foreach (var ent in protoManager.EnumeratePrototypes()) + { + if (!ent.Components.TryGetComponent(accessName, out var access)) + continue; + + var reader = (AccessReaderComponent) access; + var allTags = reader.AccessLists.SelectMany(c => c).Union(reader.DenyTags); + + foreach (var level in allTags) + { + Assert.That(protoManager.HasIndex(level), $"Invalid access level: {level} found on {ent}"); + } + } + }); + + await pair.CleanReturnAsync(); + } + [Test] public async Task TestTags() { diff --git a/Content.Server/Access/Components/AgentIDCardComponent.cs b/Content.Server/Access/Components/AgentIDCardComponent.cs index 00fbbf4c5c..cc267034b8 100644 --- a/Content.Server/Access/Components/AgentIDCardComponent.cs +++ b/Content.Server/Access/Components/AgentIDCardComponent.cs @@ -2,5 +2,6 @@ namespace Content.Server.Access.Components { [RegisterComponent] public sealed class AgentIDCardComponent : Component - {} + { + } } diff --git a/Content.Server/Access/Systems/AccessSystem.cs b/Content.Server/Access/Systems/AccessSystem.cs index 8a6ad24411..f185d0ff98 100644 --- a/Content.Server/Access/Systems/AccessSystem.cs +++ b/Content.Server/Access/Systems/AccessSystem.cs @@ -4,5 +4,4 @@ namespace Content.Server.Access.Systems; public sealed class AccessSystem : SharedAccessSystem { - } diff --git a/Content.Server/Access/Systems/IdCardSystem.cs b/Content.Server/Access/Systems/IdCardSystem.cs index 279268c0b6..4fcc2ada53 100644 --- a/Content.Server/Access/Systems/IdCardSystem.cs +++ b/Content.Server/Access/Systems/IdCardSystem.cs @@ -18,6 +18,7 @@ namespace Content.Server.Access.Systems [Dependency] private readonly IRobustRandom _random = default!; [Dependency] private readonly IPrototypeManager _prototypeManager = default!; [Dependency] private readonly IAdminLogManager _adminLogger = default!; + [Dependency] private readonly MetaDataSystem _metaSystem = default!; public override void Initialize() { @@ -112,7 +113,7 @@ namespace Content.Server.Access.Systems if (player != null) { _adminLogger.Add(LogType.Identity, LogImpact.Low, - $"{ToPrettyString(player.Value):player} has changed the job title of {ToPrettyString(id.Owner):entity} to {jobTitle} "); + $"{ToPrettyString(player.Value):player} has changed the job title of {ToPrettyString(uid):entity} to {jobTitle} "); } return true; } @@ -149,7 +150,7 @@ namespace Content.Server.Access.Systems if (player != null) { _adminLogger.Add(LogType.Identity, LogImpact.Low, - $"{ToPrettyString(player.Value):player} has changed the name of {ToPrettyString(id.Owner):entity} to {fullName} "); + $"{ToPrettyString(player.Value):player} has changed the name of {ToPrettyString(uid):entity} to {fullName} "); } return true; } @@ -174,7 +175,7 @@ namespace Content.Server.Access.Systems : Loc.GetString("access-id-card-component-owner-full-name-job-title-text", ("fullName", id.FullName), ("jobSuffix", jobSuffix)); - EntityManager.GetComponent(id.Owner).EntityName = val; + _metaSystem.SetEntityName(uid, val); } } } diff --git a/Content.Server/Access/Systems/IdExaminableSystem.cs b/Content.Server/Access/Systems/IdExaminableSystem.cs index c849cd5aeb..4dd0857c67 100644 --- a/Content.Server/Access/Systems/IdExaminableSystem.cs +++ b/Content.Server/Access/Systems/IdExaminableSystem.cs @@ -21,9 +21,8 @@ public sealed class IdExaminableSystem : EntitySystem private void OnGetExamineVerbs(EntityUid uid, IdExaminableComponent component, GetVerbsEvent args) { - var detailsRange = _examineSystem.IsInDetailsRange(args.User, uid); - var info = GetInfo(component.Owner) ?? Loc.GetString("id-examinable-component-verb-no-id"); + var info = GetInfo(uid) ?? Loc.GetString("id-examinable-component-verb-no-id"); var verb = new ExamineVerb() { @@ -36,7 +35,7 @@ public sealed class IdExaminableSystem : EntitySystem Category = VerbCategory.Examine, Disabled = !detailsRange, Message = Loc.GetString("id-examinable-component-verb-disabled"), - Icon = new SpriteSpecifier.Texture(new ("/Textures/Interface/character.svg.192dpi.png")) + Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/character.svg.192dpi.png")) }; args.Verbs.Add(verb); @@ -47,12 +46,13 @@ public sealed class IdExaminableSystem : EntitySystem if (_inventorySystem.TryGetSlotEntity(uid, "id", out var idUid)) { // PDA - if (EntityManager.TryGetComponent(idUid, out PdaComponent? pda) && pda.ContainedId is not null) + if (EntityManager.TryGetComponent(idUid, out PdaComponent? pda) && + TryComp(pda.ContainedId, out var id)) { - return GetNameAndJob(pda.ContainedId); + return GetNameAndJob(id); } // ID Card - if (EntityManager.TryGetComponent(idUid, out IdCardComponent? id)) + if (EntityManager.TryGetComponent(idUid, out id)) { return GetNameAndJob(id); } diff --git a/Content.Server/Access/Systems/PresetIdCardSystem.cs b/Content.Server/Access/Systems/PresetIdCardSystem.cs index 086c1143dd..3192e45d65 100644 --- a/Content.Server/Access/Systems/PresetIdCardSystem.cs +++ b/Content.Server/Access/Systems/PresetIdCardSystem.cs @@ -26,15 +26,16 @@ namespace Content.Server.Access.Systems { // Go over all ID cards and make sure they're correctly configured for extended access. - foreach (var card in EntityQuery()) + var query = EntityQueryEnumerator(); + while (query.MoveNext(out var uid, out var card)) { - var station = _stationSystem.GetOwningStation(card.Owner); + var station = _stationSystem.GetOwningStation(uid); // If we're not on an extended access station, the ID is already configured correctly from MapInit. if (station == null || !Comp(station.Value).ExtendedAccess) return; - SetupIdAccess(card.Owner, card, true); + SetupIdAccess(uid, card, true); } } @@ -45,7 +46,7 @@ namespace Content.Server.Access.Systems // or may not yet know whether it is on extended access (players not spawned yet). // PlayerJobsAssigned makes sure extended access is configured correctly in that case. - var station = _stationSystem.GetOwningStation(id.Owner); + var station = _stationSystem.GetOwningStation(uid); var extended = false; if (station != null) extended = Comp(station.Value).ExtendedAccess; diff --git a/Content.Server/Administration/Commands/SetOutfitCommand.cs b/Content.Server/Administration/Commands/SetOutfitCommand.cs index a9f1f6a8e4..6fbc282bb9 100644 --- a/Content.Server/Administration/Commands/SetOutfitCommand.cs +++ b/Content.Server/Administration/Commands/SetOutfitCommand.cs @@ -2,6 +2,7 @@ using Content.Server.Administration.UI; using Content.Server.EUI; using Content.Server.Hands.Systems; using Content.Server.Preferences.Managers; +using Content.Shared.Access.Components; using Content.Shared.Administration; using Content.Shared.Hands.Components; using Content.Shared.Inventory; @@ -16,7 +17,7 @@ using Robust.Shared.Prototypes; namespace Content.Server.Administration.Commands { [AdminCommand(AdminFlags.Admin)] - sealed class SetOutfitCommand : IConsoleCommand + public sealed class SetOutfitCommand : IConsoleCommand { [Dependency] private readonly IEntityManager _entities = default!; [Dependency] private readonly IPrototypeManager _prototypes = default!; @@ -25,7 +26,7 @@ namespace Content.Server.Administration.Commands public string Description => Loc.GetString("set-outfit-command-description", ("requiredComponent", nameof(InventoryComponent))); - public string Help => Loc.GetString("set-outfit-command-help-text", ("command",Command)); + public string Help => Loc.GetString("set-outfit-command-help-text", ("command", Command)); public void Execute(IConsoleShell shell, string argStr, string[] args) { @@ -51,7 +52,7 @@ namespace Content.Server.Administration.Commands if (!_entities.HasComponent(target)) { - shell.WriteLine(Loc.GetString("shell-target-entity-does-not-have-message",("missing", "inventory"))); + shell.WriteLine(Loc.GetString("shell-target-entity-does-not-have-message", ("missing", "inventory"))); return; } @@ -106,9 +107,9 @@ namespace Content.Server.Administration.Commands var equipmentEntity = entityManager.SpawnEntity(gearStr, entityManager.GetComponent(target).Coordinates); if (slot.Name == "id" && entityManager.TryGetComponent(equipmentEntity, out var pdaComponent) && - pdaComponent.ContainedId != null) + entityManager.TryGetComponent(pdaComponent.ContainedId, out var id)) { - pdaComponent.ContainedId.FullName = entityManager.GetComponent(target).EntityName; + id.FullName = entityManager.GetComponent(target).EntityName; } invSystem.TryEquip(target, equipmentEntity, slot.Name, silent: true, force: true, inventory: inventoryComponent); diff --git a/Content.Server/Administration/Systems/AdminVerbSystem.Tools.cs b/Content.Server/Administration/Systems/AdminVerbSystem.Tools.cs index ced46189b6..7ce0112226 100644 --- a/Content.Server/Administration/Systems/AdminVerbSystem.Tools.cs +++ b/Content.Server/Administration/Systems/AdminVerbSystem.Tools.cs @@ -10,6 +10,7 @@ using Content.Server.Damage.Components; using Content.Server.Doors.Systems; using Content.Server.Hands.Systems; using Content.Server.Power.Components; +using Content.Server.Power.EntitySystems; using Content.Server.Stack; using Content.Server.Station.Components; using Content.Server.Station.Systems; @@ -49,6 +50,9 @@ public sealed partial class AdminVerbSystem [Dependency] private readonly AdminTestArenaSystem _adminTestArenaSystem = default!; [Dependency] private readonly StationJobsSystem _stationJobsSystem = default!; [Dependency] private readonly JointSystem _jointSystem = default!; + [Dependency] private readonly BatterySystem _batterySystem = default!; + [Dependency] private readonly SharedTransformSystem _xformSystem = default!; + [Dependency] private readonly MetaDataSystem _metaSystem = default!; private void AddTricksVerbs(GetVerbsEvent args) { @@ -80,7 +84,6 @@ public sealed partial class AdminVerbSystem ? "admin-trick-unbolt-description" : "admin-trick-bolt-description"), Priority = (int) (bolts.BoltsDown ? TricksVerbPriorities.Unbolt : TricksVerbPriorities.Bolt), - }; args.Verbs.Add(bolt); } @@ -91,7 +94,7 @@ public sealed partial class AdminVerbSystem { Text = airlock.EmergencyAccess ? "Emergency Access Off" : "Emergency Access On", Category = VerbCategory.Tricks, - Icon = new SpriteSpecifier.Texture(new ("/Textures/Interface/AdminActions/emergency_access.png")), + Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/AdminActions/emergency_access.png")), Act = () => { _airlockSystem.ToggleEmergencyAccess(args.Target, airlock); @@ -100,9 +103,7 @@ public sealed partial class AdminVerbSystem Message = Loc.GetString(airlock.EmergencyAccess ? "admin-trick-emergency-access-off-description" : "admin-trick-emergency-access-on-description"), - Priority = (int) (airlock.EmergencyAccess - ? TricksVerbPriorities.EmergencyAccessOff - : TricksVerbPriorities.EmergencyAccessOn), + Priority = (int) (airlock.EmergencyAccess ? TricksVerbPriorities.EmergencyAccessOff : TricksVerbPriorities.EmergencyAccessOn), }; args.Verbs.Add(emergencyAccess); } @@ -113,7 +114,7 @@ public sealed partial class AdminVerbSystem { Text = "Rejuvenate", Category = VerbCategory.Tricks, - Icon = new SpriteSpecifier.Texture(new ("/Textures/Interface/AdminActions/rejuvenate.png")), + Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/AdminActions/rejuvenate.png")), Act = () => { RejuvenateCommand.PerformRejuvenate(args.Target); @@ -131,7 +132,7 @@ public sealed partial class AdminVerbSystem { Text = "Make Indestructible", Category = VerbCategory.Tricks, - Icon = new SpriteSpecifier.Texture(new ("/Textures/Interface/VerbIcons/plus.svg.192dpi.png")), + Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/VerbIcons/plus.svg.192dpi.png")), Act = () => { _godmodeSystem.EnableGodmode(args.Target); @@ -148,7 +149,7 @@ public sealed partial class AdminVerbSystem { Text = "Make Vulnerable", Category = VerbCategory.Tricks, - Icon = new SpriteSpecifier.Texture(new ("/Textures/Interface/VerbIcons/plus.svg.192dpi.png")), + Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/VerbIcons/plus.svg.192dpi.png")), Act = () => { _godmodeSystem.DisableGodmode(args.Target); @@ -166,11 +167,11 @@ public sealed partial class AdminVerbSystem { Text = "Refill Battery", Category = VerbCategory.Tricks, - Icon = new SpriteSpecifier.Texture(new ("/Textures/Interface/AdminActions/fill_battery.png")), + Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/AdminActions/fill_battery.png")), Act = () => { - battery.CurrentCharge = battery.MaxCharge; - Dirty(battery); + _batterySystem.SetCharge(args.Target, battery.MaxCharge, battery); + Dirty(args.Target, battery); }, Impact = LogImpact.Medium, Message = Loc.GetString("admin-trick-refill-battery-description"), @@ -182,11 +183,11 @@ public sealed partial class AdminVerbSystem { Text = "Drain Battery", Category = VerbCategory.Tricks, - Icon = new SpriteSpecifier.Texture(new ("/Textures/Interface/AdminActions/drain_battery.png")), + Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/AdminActions/drain_battery.png")), Act = () => { - battery.CurrentCharge = 0; - Dirty(battery); + _batterySystem.SetCharge(args.Target, 0, battery); + Dirty(args.Target, battery); }, Impact = LogImpact.Medium, Message = Loc.GetString("admin-trick-drain-battery-description"), @@ -198,7 +199,7 @@ public sealed partial class AdminVerbSystem { Text = "Infinite Battery", Category = VerbCategory.Tricks, - Icon = new SpriteSpecifier.Texture(new ("/Textures/Interface/AdminActions/infinite_battery.png")), + Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/AdminActions/infinite_battery.png")), Act = () => { var recharger = EnsureComp(args.Target); @@ -218,7 +219,7 @@ public sealed partial class AdminVerbSystem { Text = "Block Unanchoring", Category = VerbCategory.Tricks, - Icon = new SpriteSpecifier.Texture(new ("/Textures/Interface/VerbIcons/anchor.svg.192dpi.png")), + Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/VerbIcons/anchor.svg.192dpi.png")), Act = () => { RemComp(args.Target, anchor); @@ -236,7 +237,7 @@ public sealed partial class AdminVerbSystem { Text = "Refill Internals Oxygen", Category = VerbCategory.Tricks, - Icon = new SpriteSpecifier.Rsi(new ("/Textures/Objects/Tanks/oxygen.rsi"), "icon"), + Icon = new SpriteSpecifier.Rsi(new("/Textures/Objects/Tanks/oxygen.rsi"), "icon"), Act = () => { RefillGasTank(args.Target, Gas.Oxygen, tank); @@ -251,7 +252,7 @@ public sealed partial class AdminVerbSystem { Text = "Refill Internals Nitrogen", Category = VerbCategory.Tricks, - Icon = new SpriteSpecifier.Rsi(new ("/Textures/Objects/Tanks/red.rsi"), "icon"), + Icon = new SpriteSpecifier.Rsi(new("/Textures/Objects/Tanks/red.rsi"), "icon"), Act = () => { RefillGasTank(args.Target, Gas.Nitrogen, tank); @@ -266,7 +267,7 @@ public sealed partial class AdminVerbSystem { Text = "Refill Internals Plasma", Category = VerbCategory.Tricks, - Icon = new SpriteSpecifier.Rsi(new ("/Textures/Objects/Tanks/plasma.rsi"), "icon"), + Icon = new SpriteSpecifier.Rsi(new("/Textures/Objects/Tanks/plasma.rsi"), "icon"), Act = () => { RefillGasTank(args.Target, Gas.Plasma, tank); @@ -284,7 +285,7 @@ public sealed partial class AdminVerbSystem { Text = "Refill Internals Oxygen", Category = VerbCategory.Tricks, - Icon = new SpriteSpecifier.Rsi(new ("/Textures/Objects/Tanks/oxygen.rsi"), "icon"), + Icon = new SpriteSpecifier.Rsi(new("/Textures/Objects/Tanks/oxygen.rsi"), "icon"), Act = () => { foreach (var slot in _inventorySystem.GetSlots(args.Target)) @@ -316,7 +317,7 @@ public sealed partial class AdminVerbSystem { Text = "Refill Internals Nitrogen", Category = VerbCategory.Tricks, - Icon = new SpriteSpecifier.Rsi(new ("/Textures/Objects/Tanks/red.rsi"), "icon"), + Icon = new SpriteSpecifier.Rsi(new("/Textures/Objects/Tanks/red.rsi"), "icon"), Act = () => { foreach (var slot in _inventorySystem.GetSlots(args.Target)) @@ -348,7 +349,7 @@ public sealed partial class AdminVerbSystem { Text = "Refill Internals Plasma", Category = VerbCategory.Tricks, - Icon = new SpriteSpecifier.Rsi(new ("/Textures/Objects/Tanks/plasma.rsi"), "icon"), + Icon = new SpriteSpecifier.Rsi(new("/Textures/Objects/Tanks/plasma.rsi"), "icon"), Act = () => { foreach (var slot in _inventorySystem.GetSlots(args.Target)) @@ -381,12 +382,12 @@ public sealed partial class AdminVerbSystem { Text = "Send to test arena", Category = VerbCategory.Tricks, - Icon = new SpriteSpecifier.Texture(new ("/Textures/Interface/VerbIcons/eject.svg.192dpi.png")), + Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/VerbIcons/eject.svg.192dpi.png")), Act = () => { var (mapUid, gridUid) = _adminTestArenaSystem.AssertArenaLoaded(player); - Transform(args.Target).Coordinates = new EntityCoordinates(gridUid ?? mapUid, Vector2.One); + _xformSystem.SetCoordinates(args.Target, new EntityCoordinates(gridUid ?? mapUid, Vector2.One)); }, Impact = LogImpact.Medium, Message = Loc.GetString("admin-trick-send-to-test-arena-description"), @@ -402,7 +403,7 @@ public sealed partial class AdminVerbSystem { Text = "Grant All Access", Category = VerbCategory.Tricks, - Icon = new SpriteSpecifier.Rsi(new ("/Textures/Objects/Misc/id_cards.rsi"), "centcom"), + Icon = new SpriteSpecifier.Rsi(new("/Textures/Objects/Misc/id_cards.rsi"), "centcom"), Act = () => { GiveAllAccess(activeId.Value); @@ -417,7 +418,7 @@ public sealed partial class AdminVerbSystem { Text = "Revoke All Access", Category = VerbCategory.Tricks, - Icon = new SpriteSpecifier.Rsi(new ("/Textures/Objects/Misc/id_cards.rsi"), "default"), + Icon = new SpriteSpecifier.Rsi(new("/Textures/Objects/Misc/id_cards.rsi"), "default"), Act = () => { RevokeAllAccess(activeId.Value); @@ -435,7 +436,7 @@ public sealed partial class AdminVerbSystem { Text = "Grant All Access", Category = VerbCategory.Tricks, - Icon = new SpriteSpecifier.Rsi(new ("/Textures/Objects/Misc/id_cards.rsi"), "centcom"), + Icon = new SpriteSpecifier.Rsi(new("/Textures/Objects/Misc/id_cards.rsi"), "centcom"), Act = () => { GiveAllAccess(args.Target); @@ -450,7 +451,7 @@ public sealed partial class AdminVerbSystem { Text = "Revoke All Access", Category = VerbCategory.Tricks, - Icon = new SpriteSpecifier.Rsi(new ("/Textures/Objects/Misc/id_cards.rsi"), "default"), + Icon = new SpriteSpecifier.Rsi(new("/Textures/Objects/Misc/id_cards.rsi"), "default"), Act = () => { RevokeAllAccess(args.Target); @@ -469,7 +470,7 @@ public sealed partial class AdminVerbSystem { Text = "Adjust Stack", Category = VerbCategory.Tricks, - Icon = new SpriteSpecifier.Texture(new ("/Textures/Interface/AdminActions/adjust-stack.png")), + Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/AdminActions/adjust-stack.png")), Act = () => { // Unbounded intentionally. @@ -488,7 +489,7 @@ public sealed partial class AdminVerbSystem { Text = "Fill Stack", Category = VerbCategory.Tricks, - Icon = new SpriteSpecifier.Texture(new ("/Textures/Interface/AdminActions/fill-stack.png")), + Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/AdminActions/fill-stack.png")), Act = () => { _stackSystem.SetCount(args.Target, _stackSystem.GetMaxCount(stack), stack); @@ -504,12 +505,12 @@ public sealed partial class AdminVerbSystem { Text = "Rename", Category = VerbCategory.Tricks, - Icon = new SpriteSpecifier.Texture(new ("/Textures/Interface/AdminActions/rename.png")), + Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/AdminActions/rename.png")), Act = () => { _quickDialog.OpenDialog(player, "Rename", "Name", (string newName) => { - MetaData(args.Target).EntityName = newName; + _metaSystem.SetEntityName(args.Target, newName); }); }, Impact = LogImpact.Medium, @@ -522,12 +523,12 @@ public sealed partial class AdminVerbSystem { Text = "Redescribe", Category = VerbCategory.Tricks, - Icon = new SpriteSpecifier.Texture(new ("/Textures/Interface/AdminActions/redescribe.png")), + Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/AdminActions/redescribe.png")), Act = () => { _quickDialog.OpenDialog(player, "Redescribe", "Description", (LongString newDescription) => { - MetaData(args.Target).EntityDescription = newDescription.String; + _metaSystem.SetEntityDescription(args.Target, newDescription.String); }); }, Impact = LogImpact.Medium, @@ -540,15 +541,15 @@ public sealed partial class AdminVerbSystem { Text = "Redescribe", Category = VerbCategory.Tricks, - Icon = new SpriteSpecifier.Texture(new ("/Textures/Interface/AdminActions/rename_and_redescribe.png")), + Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/AdminActions/rename_and_redescribe.png")), Act = () => { _quickDialog.OpenDialog(player, "Rename & Redescribe", "Name", "Description", (string newName, LongString newDescription) => { var meta = MetaData(args.Target); - meta.EntityName = newName; - meta.EntityDescription = newDescription.String; + _metaSystem.SetEntityName(args.Target, newName, meta); + _metaSystem.SetEntityDescription(args.Target, newDescription.String, meta); }); }, Impact = LogImpact.Medium, @@ -565,7 +566,7 @@ public sealed partial class AdminVerbSystem { Text = "Bar job slots", Category = VerbCategory.Tricks, - Icon = new SpriteSpecifier.Texture(new ("/Textures/Interface/AdminActions/bar_jobslots.png")), + Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/AdminActions/bar_jobslots.png")), Act = () => { foreach (var (job, _) in _stationJobsSystem.GetJobs(args.Target)) @@ -584,7 +585,7 @@ public sealed partial class AdminVerbSystem { Text = "Locate Cargo Shuttle", Category = VerbCategory.Tricks, - Icon = new SpriteSpecifier.Rsi(new ("/Textures/Clothing/Head/Soft/cargosoft.rsi"), "icon"), + Icon = new SpriteSpecifier.Rsi(new("/Textures/Clothing/Head/Soft/cargosoft.rsi"), "icon"), Act = () => { var shuttle = Comp(args.Target).Shuttle; @@ -592,7 +593,7 @@ public sealed partial class AdminVerbSystem if (shuttle is null) return; - Transform(args.User).Coordinates = new EntityCoordinates(shuttle.Value, Vector2.Zero); + _xformSystem.SetCoordinates(args.User, new EntityCoordinates(shuttle.Value, Vector2.Zero)); }, Impact = LogImpact.Low, Message = Loc.GetString("admin-trick-locate-cargo-shuttle-description"), @@ -607,7 +608,7 @@ public sealed partial class AdminVerbSystem { Text = "Refill Battery", Category = VerbCategory.Tricks, - Icon = new SpriteSpecifier.Texture(new ("/Textures/Interface/AdminActions/fill_battery.png")), + Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/AdminActions/fill_battery.png")), Act = () => { foreach (var ent in childEnum) @@ -615,8 +616,8 @@ public sealed partial class AdminVerbSystem if (!HasComp(ent)) continue; var battery = EnsureComp(ent); - battery.CurrentCharge = battery.MaxCharge; - Dirty(battery); + _batterySystem.SetCharge(ent, battery.MaxCharge, battery); + Dirty(ent, battery); } }, Impact = LogImpact.Extreme, @@ -629,7 +630,7 @@ public sealed partial class AdminVerbSystem { Text = "Drain Battery", Category = VerbCategory.Tricks, - Icon = new SpriteSpecifier.Texture(new ("/Textures/Interface/AdminActions/drain_battery.png")), + Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/AdminActions/drain_battery.png")), Act = () => { foreach (var ent in childEnum) @@ -637,8 +638,8 @@ public sealed partial class AdminVerbSystem if (!HasComp(ent)) continue; var battery = EnsureComp(ent); - battery.CurrentCharge = 0; - Dirty(battery); + _batterySystem.SetCharge(ent, 0, battery); + Dirty(ent, battery); } }, Impact = LogImpact.Extreme, @@ -651,7 +652,7 @@ public sealed partial class AdminVerbSystem { Text = "Infinite Battery", Category = VerbCategory.Tricks, - Icon = new SpriteSpecifier.Texture(new ("/Textures/Interface/AdminActions/infinite_battery.png")), + Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/AdminActions/infinite_battery.png")), Act = () => { // this kills the sloth @@ -680,7 +681,7 @@ public sealed partial class AdminVerbSystem { Text = "Halt Movement", Category = VerbCategory.Tricks, - Icon = new SpriteSpecifier.Texture(new ("/Textures/Interface/AdminActions/halt.png")), + Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/AdminActions/halt.png")), Act = () => { _physics.SetLinearVelocity(args.Target, Vector2.Zero, body: physics); @@ -703,7 +704,7 @@ public sealed partial class AdminVerbSystem { Text = "Unpause Map", Category = VerbCategory.Tricks, - Icon = new SpriteSpecifier.Texture(new ("/Textures/Interface/AdminActions/play.png")), + Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/AdminActions/play.png")), Act = () => { _mapManager.SetMapPaused(map.MapId, false); @@ -720,7 +721,7 @@ public sealed partial class AdminVerbSystem { Text = "Pause Map", Category = VerbCategory.Tricks, - Icon = new SpriteSpecifier.Texture(new ("/Textures/Interface/AdminActions/pause.png")), + Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/AdminActions/pause.png")), Act = () => { _mapManager.SetMapPaused(map.MapId, true); @@ -740,10 +741,10 @@ public sealed partial class AdminVerbSystem { Text = "Snap Joints", Category = VerbCategory.Tricks, - Icon = new SpriteSpecifier.Texture(new ("/Textures/Interface/AdminActions/snap_joints.png")), + Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/AdminActions/snap_joints.png")), Act = () => { - _jointSystem.ClearJoints(joints); + _jointSystem.ClearJoints(args.Target, joints); }, Impact = LogImpact.Medium, Message = Loc.GetString("admin-trick-snap-joints-description"), @@ -758,7 +759,7 @@ public sealed partial class AdminVerbSystem { Text = "Make Minigun", Category = VerbCategory.Tricks, - Icon = new SpriteSpecifier.Rsi(new ("/Textures/Objects/Weapons/Guns/HMGs/minigun.rsi"), "icon"), + Icon = new SpriteSpecifier.Rsi(new("/Textures/Objects/Weapons/Guns/HMGs/minigun.rsi"), "icon"), Act = () => { gun.FireRate = 15; @@ -776,7 +777,7 @@ public sealed partial class AdminVerbSystem { Text = "Set Bullet Amount", Category = VerbCategory.Tricks, - Icon = new SpriteSpecifier.Rsi(new ("/Textures/Objects/Fun/caps.rsi"), "mag-6"), + Icon = new SpriteSpecifier.Rsi(new("/Textures/Objects/Fun/caps.rsi"), "mag-6"), Act = () => { _quickDialog.OpenDialog(player, "Set Bullet Amount", $"Amount (max {ballisticAmmo.Capacity}):", (int amount) => @@ -858,12 +859,10 @@ public sealed partial class AdminVerbSystem { return slotEntity.Value; } - else if (TryComp(slotEntity, out var pda)) + else if (TryComp(slotEntity, out var pda) + && HasComp(pda.ContainedId)) { - if (pda.ContainedId != null) - { - return pda.ContainedId.Owner; - } + return pda.ContainedId; } } else if (TryComp(target, out var hands)) @@ -891,40 +890,40 @@ public sealed partial class AdminVerbSystem private void RevokeAllAccess(EntityUid entity) { - _accessSystem.TrySetTags(entity, new string[]{}); + _accessSystem.TrySetTags(entity, Array.Empty()); } public enum TricksVerbPriorities { Bolt = 0, - Unbolt = 0, - EmergencyAccessOn = -1, // These are separate intentionally for `invokeverb` shenanigans. - EmergencyAccessOff = -1, - MakeIndestructible = -2, - MakeVulnerable = -2, - BlockUnanchoring = -3, - RefillBattery = -4, - DrainBattery = -5, - RefillOxygen = -6, - RefillNitrogen = -7, - RefillPlasma = -8, - SendToTestArena = -9, - GrantAllAccess = -10, - RevokeAllAccess = -11, - Rejuvenate = -12, - AdjustStack = -13, - FillStack = -14, - Rename = -15, - Redescribe = -16, - RenameAndRedescribe = -17, - BarJobSlots = -18, - LocateCargoShuttle = -19, - InfiniteBattery = -20, - HaltMovement = -21, - Unpause = -22, - Pause = -23, - SnapJoints = -24, - MakeMinigun = -25, - SetBulletAmount = -26, + Unbolt = -1, + EmergencyAccessOn = -2, + EmergencyAccessOff = -3, + MakeIndestructible = -4, + MakeVulnerable = -5, + BlockUnanchoring = -6, + RefillBattery = -7, + DrainBattery = -8, + RefillOxygen = -9, + RefillNitrogen = -10, + RefillPlasma = -11, + SendToTestArena = -12, + GrantAllAccess = -13, + RevokeAllAccess = -14, + Rejuvenate = -15, + AdjustStack = -16, + FillStack = -17, + Rename = -18, + Redescribe = -19, + RenameAndRedescribe = -20, + BarJobSlots = -21, + LocateCargoShuttle = -22, + InfiniteBattery = -23, + HaltMovement = -24, + Unpause = -25, + Pause = -26, + SnapJoints = -27, + MakeMinigun = -28, + SetBulletAmount = -29, } } diff --git a/Content.Server/PDA/PdaSystem.cs b/Content.Server/PDA/PdaSystem.cs index 1fbdb5b0ff..31df32f7ad 100644 --- a/Content.Server/PDA/PdaSystem.cs +++ b/Content.Server/PDA/PdaSystem.cs @@ -9,6 +9,7 @@ using Content.Server.PDA.Ringer; using Content.Server.Station.Systems; using Content.Server.Store.Components; using Content.Server.Store.Systems; +using Content.Shared.Access.Components; using Content.Shared.PDA; using Robust.Server.GameObjects; using Robust.Server.Player; @@ -117,14 +118,15 @@ namespace Content.Server.PDA // TODO: Update the level and name of the station with each call to UpdatePdaUi is only needed for latejoin players. // TODO: If someone can implement changing the level and name of the station when changing the PDA grid, this can be removed. + var id = CompOrNull(pda.ContainedId); var state = new PdaUpdateState( pda.FlashlightOn, pda.PenSlot.HasItem, new PdaIdInfoText { ActualOwnerName = pda.OwnerName, - IdOwner = pda.ContainedId?.FullName, - JobTitle = pda.ContainedId?.JobTitle, + IdOwner = id?.FullName, + JobTitle = id?.JobTitle, StationAlertLevel = pda.StationAlertLevel, StationAlertColor = pda.StationAlertColor }, diff --git a/Content.Server/Sandbox/SandboxSystem.cs b/Content.Server/Sandbox/SandboxSystem.cs index dc96eb9d43..ec9b1a0c3c 100644 --- a/Content.Server/Sandbox/SandboxSystem.cs +++ b/Content.Server/Sandbox/SandboxSystem.cs @@ -93,7 +93,7 @@ namespace Content.Server.Sandbox if (e.NewStatus != SessionStatus.Connected || e.OldStatus != SessionStatus.Connecting) return; - RaiseNetworkEvent(new MsgSandboxStatus {SandboxAllowed = IsSandboxEnabled}, e.Session.ConnectedClient); + RaiseNetworkEvent(new MsgSandboxStatus { SandboxAllowed = IsSandboxEnabled }, e.Session.ConnectedClient); } private void SandboxRespawnReceived(MsgSandboxRespawn message, EntitySessionEventArgs args) @@ -113,7 +113,7 @@ namespace Content.Server.Sandbox return; var player = _playerManager.GetSessionByChannel(args.SenderSession.ConnectedClient); - if (player.AttachedEntity is not {} attached) + if (player.AttachedEntity is not { } attached) { return; } @@ -130,17 +130,17 @@ namespace Content.Server.Sandbox } else if (TryComp(slotEntity, out var pda)) { - if (pda.ContainedId == null) + if (pda.ContainedId is null) { var newID = CreateFreshId(); - if (TryComp(pda.Owner, out var itemSlots)) + if (TryComp(slotEntity, out var itemSlots)) { _slots.TryInsert(slotEntity.Value, pda.IdSlot, newID, null); } } else { - UpgradeId(pda.ContainedId.Owner); + UpgradeId(pda.ContainedId!.Value); } } } @@ -189,7 +189,7 @@ namespace Content.Server.Sandbox private void UpdateSandboxStatusForAll() { - RaiseNetworkEvent(new MsgSandboxStatus {SandboxAllowed = IsSandboxEnabled}); + RaiseNetworkEvent(new MsgSandboxStatus { SandboxAllowed = IsSandboxEnabled }); } } } diff --git a/Content.Server/Station/Systems/StationSpawningSystem.cs b/Content.Server/Station/Systems/StationSpawningSystem.cs index 583a325fd7..02cdcc7e95 100644 --- a/Content.Server/Station/Systems/StationSpawningSystem.cs +++ b/Content.Server/Station/Systems/StationSpawningSystem.cs @@ -7,6 +7,7 @@ using Content.Server.Mind.Commands; using Content.Server.PDA; using Content.Server.Roles; using Content.Server.Station.Components; +using Content.Shared.Access.Components; using Content.Shared.Access.Systems; using Content.Shared.CCVar; using Content.Shared.Hands.Components; @@ -44,6 +45,7 @@ public sealed class StationSpawningSystem : EntitySystem [Dependency] private readonly PdaSystem _pdaSystem = default!; [Dependency] private readonly SharedAccessSystem _accessSystem = default!; [Dependency] private readonly IdentitySystem _identity = default!; + [Dependency] private readonly MetaDataSystem _metaSystem = default!; private bool _randomizeCharacters; @@ -73,7 +75,7 @@ public sealed class StationSpawningSystem : EntitySystem var ev = new PlayerSpawningEvent(job, profile, station); RaiseLocalEvent(ev); - DebugTools.Assert(ev.SpawnResult is {Valid: true} or null); + DebugTools.Assert(ev.SpawnResult is { Valid: true } or null); return ev.SpawnResult; } @@ -146,7 +148,7 @@ public sealed class StationSpawningSystem : EntitySystem if (profile != null) { _humanoidSystem.LoadProfile(entity.Value, profile); - MetaData(entity.Value).EntityName = profile.Name; + _metaSystem.SetEntityName(entity.Value, profile.Name); if (profile.FlavorText != "" && _configurationManager.GetCVar(CCVars.FlavorText)) { AddComp(entity.Value).Content = profile.FlavorText; @@ -158,7 +160,7 @@ public sealed class StationSpawningSystem : EntitySystem return entity.Value; } - private void DoJobSpecials(Job? job, EntityUid entity) + private static void DoJobSpecials(Job? job, EntityUid entity) { foreach (var jobSpecial in job?.Prototype.Special ?? Array.Empty()) { @@ -211,11 +213,10 @@ public sealed class StationSpawningSystem : EntitySystem if (!_inventorySystem.TryGetSlotEntity(entity, "id", out var idUid)) return; - if (!EntityManager.TryGetComponent(idUid, out PdaComponent? pdaComponent) || pdaComponent.ContainedId == null) + if (!EntityManager.TryGetComponent(idUid, out PdaComponent? pdaComponent) || !TryComp(pdaComponent.ContainedId, out var card)) return; - var card = pdaComponent.ContainedId; - var cardId = card.Owner; + var cardId = pdaComponent.ContainedId.Value; _cardSystem.TryChangeFullName(cardId, characterName, card); _cardSystem.TryChangeJobTitle(cardId, jobPrototype.LocalizedName, card); diff --git a/Content.Server/StationRecords/Systems/StationRecordsSystem.cs b/Content.Server/StationRecords/Systems/StationRecordsSystem.cs index 973ff67f3c..f98bc67c33 100644 --- a/Content.Server/StationRecords/Systems/StationRecordsSystem.cs +++ b/Content.Server/StationRecords/Systems/StationRecordsSystem.cs @@ -59,7 +59,7 @@ public sealed class StationRecordsSystem : EntitySystem string? jobId, StationRecordsComponent? records = null) { if (!Resolve(station, ref records) - || String.IsNullOrEmpty(jobId) + || string.IsNullOrEmpty(jobId) || !_prototypeManager.HasIndex(jobId)) { return; @@ -204,7 +204,7 @@ public sealed class StationRecordsSystem : EntitySystem { if (!Resolve(station, ref records)) { - return new (StationRecordKey, T)[]{}; + return Array.Empty<(StationRecordKey, T)>(); } return records.Records.GetRecordsOfType(); diff --git a/Content.Server/Verbs/Commands/InvokeVerbCommand.cs b/Content.Server/Verbs/Commands/InvokeVerbCommand.cs index 543e907a7e..af2131fb55 100644 --- a/Content.Server/Verbs/Commands/InvokeVerbCommand.cs +++ b/Content.Server/Verbs/Commands/InvokeVerbCommand.cs @@ -22,7 +22,7 @@ namespace Content.Server.Verbs.Commands } var entityManager = IoCManager.Resolve(); - var verbSystem = EntitySystem.Get(); + var verbSystem = entityManager.System(); // get the 'player' entity (defaulting to command user, otherwise uses a uid) EntityUid? playerEntity = null; diff --git a/Content.Shared/Access/AccessGroupPrototype.cs b/Content.Shared/Access/AccessGroupPrototype.cs index e3a8ddec07..67da25c29e 100644 --- a/Content.Shared/Access/AccessGroupPrototype.cs +++ b/Content.Shared/Access/AccessGroupPrototype.cs @@ -14,6 +14,6 @@ public sealed class AccessGroupPrototype : IPrototype [IdDataField] public string ID { get; } = default!; - [DataField("tags", required: true, customTypeSerializer:typeof(PrototypeIdHashSetSerializer))] + [DataField("tags", required: true, customTypeSerializer: typeof(PrototypeIdHashSetSerializer))] public HashSet Tags = default!; } diff --git a/Content.Shared/Access/Components/AccessReaderComponent.cs b/Content.Shared/Access/Components/AccessReaderComponent.cs index 53e59ec94b..94aec90355 100644 --- a/Content.Shared/Access/Components/AccessReaderComponent.cs +++ b/Content.Shared/Access/Components/AccessReaderComponent.cs @@ -1,4 +1,3 @@ -using Content.Shared.Access.Systems; using Content.Shared.StationRecords; using Robust.Shared.GameStates; using Robust.Shared.Serialization; @@ -59,4 +58,3 @@ public sealed class AccessReaderComponentState : ComponentState AccessKeys = accessKeys; } } - diff --git a/Content.Shared/Access/Components/IdCardComponent.cs b/Content.Shared/Access/Components/IdCardComponent.cs index 39cfb8972a..578d614f12 100644 --- a/Content.Shared/Access/Components/IdCardComponent.cs +++ b/Content.Shared/Access/Components/IdCardComponent.cs @@ -1,7 +1,6 @@ using Content.Shared.Access.Systems; using Content.Shared.PDA; using Robust.Shared.GameStates; -using Robust.Shared.Serialization; namespace Content.Shared.Access.Components { @@ -17,8 +16,7 @@ namespace Content.Shared.Access.Components [DataField("jobTitle")] [AutoNetworkedField] - [Access(typeof(SharedIdCardSystem), typeof(SharedPdaSystem), typeof(SharedAgentIdCardSystem), - Other = AccessPermissions.ReadWrite)] + [Access(typeof(SharedIdCardSystem), typeof(SharedPdaSystem), typeof(SharedAgentIdCardSystem), Other = AccessPermissions.ReadWrite)] public string? JobTitle; } } diff --git a/Content.Shared/Access/SharedAgentIDCardSystem.cs b/Content.Shared/Access/SharedAgentIDCardSystem.cs index c3e75e4436..2105f39011 100644 --- a/Content.Shared/Access/SharedAgentIDCardSystem.cs +++ b/Content.Shared/Access/SharedAgentIDCardSystem.cs @@ -48,6 +48,7 @@ namespace Content.Shared.Access.Systems public sealed class AgentIDCardJobChangedMessage : BoundUserInterfaceMessage { public string Job { get; } + public AgentIDCardJobChangedMessage(string job) { Job = job; diff --git a/Content.Shared/Access/Systems/AccessReaderSystem.cs b/Content.Shared/Access/Systems/AccessReaderSystem.cs index 7c848c1aa7..01eb4eb7e6 100644 --- a/Content.Shared/Access/Systems/AccessReaderSystem.cs +++ b/Content.Shared/Access/Systems/AccessReaderSystem.cs @@ -11,286 +11,272 @@ using Content.Shared.Hands.EntitySystems; using Content.Shared.StationRecords; using Robust.Shared.GameStates; -namespace Content.Shared.Access.Systems +namespace Content.Shared.Access.Systems; + +public sealed class AccessReaderSystem : EntitySystem { - public sealed class AccessReaderSystem : EntitySystem + [Dependency] private readonly InventorySystem _inventorySystem = default!; + [Dependency] private readonly SharedHandsSystem _handsSystem = default!; + + public override void Initialize() { - [Dependency] private readonly IPrototypeManager _prototypeManager = default!; - [Dependency] private readonly InventorySystem _inventorySystem = default!; - [Dependency] private readonly SharedHandsSystem _handsSystem = default!; + base.Initialize(); - public override void Initialize() + SubscribeLocalEvent(OnEmagged); + SubscribeLocalEvent(OnLinkAttempt); + + SubscribeLocalEvent(OnGetState); + SubscribeLocalEvent(OnHandleState); + } + + private void OnGetState(EntityUid uid, AccessReaderComponent component, ref ComponentGetState args) + { + args.State = new AccessReaderComponentState(component.Enabled, component.DenyTags, component.AccessLists, + component.AccessKeys); + } + + private void OnHandleState(EntityUid uid, AccessReaderComponent component, ref ComponentHandleState args) + { + if (args.Current is not AccessReaderComponentState state) + return; + component.Enabled = state.Enabled; + component.AccessKeys = new (state.AccessKeys); + component.AccessLists = new (state.AccessLists); + component.DenyTags = new (state.DenyTags); + } + + private void OnLinkAttempt(EntityUid uid, AccessReaderComponent component, LinkAttemptEvent args) + { + if (args.User == null) // AutoLink (and presumably future external linkers) have no user. + return; + if (!HasComp(uid) && !IsAllowed(args.User.Value, component)) + args.Cancel(); + } + + private void OnEmagged(EntityUid uid, AccessReaderComponent reader, ref GotEmaggedEvent args) + { + args.Handled = true; + reader.Enabled = false; + Dirty(reader); + } + + /// + /// Searches the source for access tags + /// then compares it with the targets readers access list to see if it is allowed. + /// + /// The entity that wants access. + /// The entity to search for an access reader + /// Optional reader from the target entity + public bool IsAllowed(EntityUid source, EntityUid target, AccessReaderComponent? reader = null) + { + if (!Resolve(target, ref reader, false)) + return true; + return IsAllowed(source, reader); + } + + /// + /// Searches the given entity for access tags + /// then compares it with the readers access list to see if it is allowed. + /// + /// The entity that wants access. + /// A reader from a different entity + public bool IsAllowed(EntityUid entity, AccessReaderComponent reader) + { + var allEnts = FindPotentialAccessItems(entity); + + // Access reader is totally disabled, so access is always allowed. + if (!reader.Enabled) + return true; + + if (AreAccessTagsAllowed(FindAccessTags(entity, allEnts), reader)) + return true; + + if (AreStationRecordKeysAllowed(FindStationRecordKeys(entity, allEnts), reader)) + return true; + + return false; + } + + /// + /// Compares the given tags with the readers access list to see if it is allowed. + /// + /// A list of access tags + /// An access reader to check against + public bool AreAccessTagsAllowed(ICollection accessTags, AccessReaderComponent reader) + { + if (reader.DenyTags.Overlaps(accessTags)) { - base.Initialize(); - SubscribeLocalEvent(OnInit); - SubscribeLocalEvent(OnEmagged); - SubscribeLocalEvent(OnLinkAttempt); - - SubscribeLocalEvent(OnGetState); - SubscribeLocalEvent(OnHandleState); - } - - private void OnGetState(EntityUid uid, AccessReaderComponent component, ref ComponentGetState args) - { - args.State = new AccessReaderComponentState(component.Enabled, component.DenyTags, component.AccessLists, - component.AccessKeys); - } - - private void OnHandleState(EntityUid uid, AccessReaderComponent component, ref ComponentHandleState args) - { - if (args.Current is not AccessReaderComponentState state) - return; - component.Enabled = state.Enabled; - component.AccessKeys = new (state.AccessKeys); - component.AccessLists = new (state.AccessLists); - component.DenyTags = new (state.DenyTags); - } - - private void OnLinkAttempt(EntityUid uid, AccessReaderComponent component, LinkAttemptEvent args) - { - if (args.User == null) // AutoLink (and presumably future external linkers) have no user. - return; - if (!HasComp(uid) && !IsAllowed(args.User.Value, component)) - args.Cancel(); - } - - private void OnInit(EntityUid uid, AccessReaderComponent reader, ComponentInit args) - { - var allTags = reader.AccessLists.SelectMany(c => c).Union(reader.DenyTags); - foreach (var level in allTags) - { - if (!_prototypeManager.HasIndex(level)) - { - Logger.ErrorS("access", $"Invalid access level: {level}"); - } - } - } - - private void OnEmagged(EntityUid uid, AccessReaderComponent reader, ref GotEmaggedEvent args) - { - args.Handled = true; - reader.Enabled = false; - Dirty(reader); - } - - /// - /// Searches the source for access tags - /// then compares it with the targets readers access list to see if it is allowed. - /// - /// The entity that wants access. - /// The entity to search for an access reader - /// Optional reader from the target entity - public bool IsAllowed(EntityUid source, EntityUid target, AccessReaderComponent? reader = null) - { - if (!Resolve(target, ref reader, false)) - return true; - return IsAllowed(source, reader); - } - - /// - /// Searches the given entity for access tags - /// then compares it with the readers access list to see if it is allowed. - /// - /// The entity that wants access. - /// A reader from a different entity - public bool IsAllowed(EntityUid entity, AccessReaderComponent reader) - { - var allEnts = FindPotentialAccessItems(entity); - - // Access reader is totally disabled, so access is always allowed. - if (!reader.Enabled) - return true; - - if (AreAccessTagsAllowed(FindAccessTags(entity, allEnts), reader)) - return true; - - if (AreStationRecordKeysAllowed(FindStationRecordKeys(entity, allEnts), reader)) - return true; + // Sec owned by cargo. + // Note that in resolving the issue with only one specific item "counting" for access, this became a bit more strict. + // As having an ID card in any slot that "counts" with a denied access group will cause denial of access. + // DenyTags doesn't seem to be used right now anyway, though, so it'll be dependent on whoever uses it to figure out if this matters. return false; } - /// - /// Compares the given tags with the readers access list to see if it is allowed. - /// - /// A list of access tags - /// An access reader to check against - public bool AreAccessTagsAllowed(ICollection accessTags, AccessReaderComponent reader) + return reader.AccessLists.Count == 0 || reader.AccessLists.Any(a => a.IsSubsetOf(accessTags)); + } + + /// + /// Compares the given stationrecordkeys with the accessreader to see if it is allowed. + /// + public bool AreStationRecordKeysAllowed(ICollection keys, AccessReaderComponent reader) + { + return keys.Any() && reader.AccessKeys.Any(keys.Contains); + } + + /// + /// Finds all the items that could potentially give access to a given entity + /// + public HashSet FindPotentialAccessItems(EntityUid uid) + { + FindAccessItemsInventory(uid, out var items); + + var ev = new GetAdditionalAccessEvent { - if (reader.DenyTags.Overlaps(accessTags)) - { - // Sec owned by cargo. + Entities = items + }; + RaiseLocalEvent(uid, ref ev); + items.Add(uid); + return items; + } - // Note that in resolving the issue with only one specific item "counting" for access, this became a bit more strict. - // As having an ID card in any slot that "counts" with a denied access group will cause denial of access. - // DenyTags doesn't seem to be used right now anyway, though, so it'll be dependent on whoever uses it to figure out if this matters. - return false; - } + /// + /// Finds the access tags on the given entity + /// + /// The entity that is being searched. + /// All of the items to search for access. If none are passed in, will be used. + public ICollection FindAccessTags(EntityUid uid, HashSet? items = null) + { + HashSet? tags = null; + var owned = false; - return reader.AccessLists.Count == 0 || reader.AccessLists.Any(a => a.IsSubsetOf(accessTags)); + items ??= FindPotentialAccessItems(uid); + + foreach (var ent in items) + { + FindAccessTagsItem(ent, ref tags, ref owned); } - /// - /// Compares the given stationrecordkeys with the accessreader to see if it is allowed. - /// - public bool AreStationRecordKeysAllowed(ICollection keys, AccessReaderComponent reader) + return (ICollection?) tags ?? Array.Empty(); + } + + /// + /// Finds the access tags on the given entity + /// + /// The entity that is being searched. + /// All of the items to search for access. If none are passed in, will be used. + public ICollection FindStationRecordKeys(EntityUid uid, HashSet? items = null) + { + HashSet keys = new(); + + items ??= FindPotentialAccessItems(uid); + + foreach (var ent in items) { - return keys.Any() && reader.AccessKeys.Any(keys.Contains); + if (FindStationRecordKeyItem(ent, out var key)) + keys.Add(key.Value); } - /// - /// Finds all the items that could potentially give access to a given entity - /// - public HashSet FindPotentialAccessItems(EntityUid uid) - { - FindAccessItemsInventory(uid, out var items); + return keys; + } - var ev = new GetAdditionalAccessEvent - { - Entities = items - }; - RaiseLocalEvent(uid, ref ev); - items.Add(uid); - return items; + /// + /// Try to find on this item + /// or inside this item (if it's pda) + /// This version merges into a set or replaces the set. + /// If owned is false, the existing tag-set "isn't ours" and can't be merged with (is read-only). + /// + private void FindAccessTagsItem(EntityUid uid, ref HashSet? tags, ref bool owned) + { + if (!FindAccessTagsItem(uid, out var targetTags)) + { + // no tags, no problem + return; } - - /// - /// Finds the access tags on the given entity - /// - /// The entity that is being searched. - /// All of the items to search for access. If none are passed in, will be used. - public ICollection FindAccessTags(EntityUid uid, HashSet? items = null) + if (tags != null) { - HashSet? tags = null; - var owned = false; - - items ??= FindPotentialAccessItems(uid); - - foreach (var ent in items) + // existing tags, so copy to make sure we own them + if (!owned) { - FindAccessTagsItem(ent, ref tags, ref owned); + tags = new(tags); + owned = true; } - - return (ICollection?) tags ?? Array.Empty(); + // then merge + tags.UnionWith(targetTags); } - - /// - /// Finds the access tags on the given entity - /// - /// The entity that is being searched. - /// All of the items to search for access. If none are passed in, will be used. - public ICollection FindStationRecordKeys(EntityUid uid, HashSet? items = null) + else { - HashSet keys = new(); - - items ??= FindPotentialAccessItems(uid); - - foreach (var ent in items) - { - if (FindStationRecordKeyItem(ent, out var key)) - keys.Add(key.Value); - } - - return keys; - } - - /// - /// Try to find on this item - /// or inside this item (if it's pda) - /// This version merges into a set or replaces the set. - /// If owned is false, the existing tag-set "isn't ours" and can't be merged with (is read-only). - /// - private void FindAccessTagsItem(EntityUid uid, ref HashSet? tags, ref bool owned) - { - if (!FindAccessTagsItem(uid, out var targetTags)) - { - // no tags, no problem - return; - } - if (tags != null) - { - // existing tags, so copy to make sure we own them - if (!owned) - { - tags = new(tags); - owned = true; - } - // then merge - tags.UnionWith(targetTags); - } - else - { - // no existing tags, so now they're ours - tags = targetTags; - owned = false; - } - } - - public bool FindAccessItemsInventory(EntityUid uid, out HashSet items) - { - items = new(); - - foreach (var item in _handsSystem.EnumerateHeld(uid)) - { - items.Add(item); - } - - // maybe its inside an inventory slot? - if (_inventorySystem.TryGetSlotEntity(uid, "id", out var idUid)) - { - items.Add(idUid.Value); - } - - return items.Any(); - } - - /// - /// Try to find on this item - /// or inside this item (if it's pda) - /// - private bool FindAccessTagsItem(EntityUid uid, [NotNullWhen(true)] out HashSet? tags) - { - if (TryComp(uid, out AccessComponent? access)) - { - tags = access.Tags; - return true; - } - - if (TryComp(uid, out PdaComponent? pda) && - pda.ContainedId?.Owner is {Valid: true} id) - { - tags = EntityManager.GetComponent(id).Tags; - return true; - } - - tags = null; - return false; - } - - /// - /// Try to find on this item - /// or inside this item (if it's pda) - /// - private bool FindStationRecordKeyItem(EntityUid uid, [NotNullWhen(true)] out StationRecordKey? key) - { - if (TryComp(uid, out StationRecordKeyStorageComponent? storage) && storage.Key != null) - { - key = storage.Key; - return true; - } - - if (TryComp(uid, out var pda) && - pda.ContainedId?.Owner is {Valid: true} id) - { - if (TryComp(id, out var pdastorage) && pdastorage.Key != null) - { - key = pdastorage.Key; - return true; - } - } - - key = null; - return false; + // no existing tags, so now they're ours + tags = targetTags; + owned = false; } } + + public bool FindAccessItemsInventory(EntityUid uid, out HashSet items) + { + items = new(); + + foreach (var item in _handsSystem.EnumerateHeld(uid)) + { + items.Add(item); + } + + // maybe its inside an inventory slot? + if (_inventorySystem.TryGetSlotEntity(uid, "id", out var idUid)) + { + items.Add(idUid.Value); + } + + return items.Any(); + } + + /// + /// Try to find on this item + /// or inside this item (if it's pda) + /// + private bool FindAccessTagsItem(EntityUid uid, [NotNullWhen(true)] out HashSet? tags) + { + if (TryComp(uid, out AccessComponent? access)) + { + tags = access.Tags; + return true; + } + + if (TryComp(uid, out PdaComponent? pda) && + pda.ContainedId is { Valid: true } id) + { + tags = EntityManager.GetComponent(id).Tags; + return true; + } + + tags = null; + return false; + } + + /// + /// Try to find on this item + /// or inside this item (if it's pda) + /// + private bool FindStationRecordKeyItem(EntityUid uid, [NotNullWhen(true)] out StationRecordKey? key) + { + if (TryComp(uid, out StationRecordKeyStorageComponent? storage) && storage.Key != null) + { + key = storage.Key; + return true; + } + + if (TryComp(uid, out var pda) && + pda.ContainedId is { Valid: true } id) + { + if (TryComp(id, out var pdastorage) && pdastorage.Key != null) + { + key = pdastorage.Key; + return true; + } + } + + key = null; + return false; + } } diff --git a/Content.Shared/Access/Systems/SharedIdCardSystem.cs b/Content.Shared/Access/Systems/SharedIdCardSystem.cs index 02cfd016ec..3ef57827e5 100644 --- a/Content.Shared/Access/Systems/SharedIdCardSystem.cs +++ b/Content.Shared/Access/Systems/SharedIdCardSystem.cs @@ -17,7 +17,7 @@ public abstract class SharedIdCardSystem : EntitySystem public bool TryFindIdCard(EntityUid uid, [NotNullWhen(true)] out IdCardComponent? idCard) { // check held item? - if (EntityManager.TryGetComponent(uid, out HandsComponent? hands) && + if (TryComp(uid, out HandsComponent? hands) && hands.ActiveHandEntity is EntityUid heldItem && TryGetIdCard(heldItem, out idCard)) { @@ -30,9 +30,7 @@ public abstract class SharedIdCardSystem : EntitySystem // check inventory slot? if (_inventorySystem.TryGetSlotEntity(uid, "id", out var idUid) && TryGetIdCard(idUid.Value, out idCard)) - { return true; - } return false; } @@ -43,12 +41,12 @@ public abstract class SharedIdCardSystem : EntitySystem /// public bool TryGetIdCard(EntityUid uid, [NotNullWhen(true)] out IdCardComponent? idCard) { - if (EntityManager.TryGetComponent(uid, out idCard)) + if (TryComp(uid, out idCard)) return true; - if (EntityManager.TryGetComponent(uid, out PdaComponent? pda) && pda.ContainedId != null) + if (TryComp(uid, out PdaComponent? pda) + && TryComp(pda.ContainedId, out idCard)) { - idCard = pda.ContainedId; return true; } diff --git a/Content.Shared/PDA/PdaComponent.cs b/Content.Shared/PDA/PdaComponent.cs index 1cd81c0fcf..dbaf614eb5 100644 --- a/Content.Shared/PDA/PdaComponent.cs +++ b/Content.Shared/PDA/PdaComponent.cs @@ -30,7 +30,7 @@ namespace Content.Shared.PDA [DataField("id", customTypeSerializer: typeof(PrototypeIdSerializer))] public string? IdCard; - [ViewVariables] public IdCardComponent? ContainedId; + [ViewVariables] public EntityUid? ContainedId; [ViewVariables] public bool FlashlightOn; [ViewVariables] public string? OwnerName; diff --git a/Content.Shared/PDA/SharedPdaSystem.cs b/Content.Shared/PDA/SharedPdaSystem.cs index 7f7ab5c877..96cf8c981b 100644 --- a/Content.Shared/PDA/SharedPdaSystem.cs +++ b/Content.Shared/PDA/SharedPdaSystem.cs @@ -40,7 +40,7 @@ namespace Content.Shared.PDA protected virtual void OnItemInserted(EntityUid uid, PdaComponent pda, EntInsertedIntoContainerMessage args) { if (args.Container.ID == PdaComponent.PdaIdSlotId) - pda.ContainedId = CompOrNull(args.Entity); + pda.ContainedId = args.Entity; UpdatePdaAppearance(uid, pda); }