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.Client/Administration/UI/Notes/AdminNotesLinePopup.xaml.cs b/Content.Client/Administration/UI/Notes/AdminNotesLinePopup.xaml.cs index d78f2aac49..4dd4427487 100644 --- a/Content.Client/Administration/UI/Notes/AdminNotesLinePopup.xaml.cs +++ b/Content.Client/Administration/UI/Notes/AdminNotesLinePopup.xaml.cs @@ -1,4 +1,4 @@ -using Content.Shared.Administration.Notes; +using Content.Shared.Administration.Notes; using Content.Shared.Database; using Robust.Client.AutoGenerated; using Robust.Client.UserInterface.Controls; @@ -18,6 +18,7 @@ public sealed partial class AdminNotesLinePopup : Popup public AdminNotesLinePopup(SharedAdminNote note, string playerName, bool showDelete, bool showEdit) { + IoCManager.InjectDependencies(this); RobustXamlLoader.Load(this); NoteId = note.Id; diff --git a/Content.Client/Administration/UI/Notes/NoteEdit.xaml.cs b/Content.Client/Administration/UI/Notes/NoteEdit.xaml.cs index 23dd1b83ec..5cd3da438e 100644 --- a/Content.Client/Administration/UI/Notes/NoteEdit.xaml.cs +++ b/Content.Client/Administration/UI/Notes/NoteEdit.xaml.cs @@ -163,7 +163,7 @@ public sealed partial class NoteEdit : FancyWindow return; if (DeleteResetOn is null) { - DeleteResetOn = _gameTiming.CurTime.Add(TimeSpan.FromSeconds(3)); + DeleteResetOn = _gameTiming.RealTime + TimeSpan.FromSeconds(3); SubmitButton.Text = Loc.GetString("admin-note-editor-submit-confirm"); SubmitButton.ModulateSelfOverride = Color.Red; // Task.Delay(3000).ContinueWith(_ => ResetSubmitButton()); // TODO: fix @@ -185,7 +185,7 @@ public sealed partial class NoteEdit : FancyWindow { base.FrameUpdate(args); // This checks for null for free, do not invert it as null always produces a false value - if (DeleteResetOn > _gameTiming.CurTime) + if (DeleteResetOn < _gameTiming.RealTime) { ResetSubmitButton(); DeleteResetOn = null; diff --git a/Content.Client/Administration/UI/Tabs/AdminbusTab/LoadBlueprintsWindow.xaml.cs b/Content.Client/Administration/UI/Tabs/AdminbusTab/LoadBlueprintsWindow.xaml.cs index 374093c576..0cc3294df1 100644 --- a/Content.Client/Administration/UI/Tabs/AdminbusTab/LoadBlueprintsWindow.xaml.cs +++ b/Content.Client/Administration/UI/Tabs/AdminbusTab/LoadBlueprintsWindow.xaml.cs @@ -40,6 +40,7 @@ namespace Content.Client.Administration.UI.Tabs.AdminbusTab private void Reset() { var entManager = IoCManager.Resolve(); + var xformSystem = entManager.System(); var playerManager = IoCManager.Resolve(); var player = playerManager.LocalPlayer?.ControlledEntity; @@ -50,16 +51,16 @@ namespace Content.Client.Administration.UI.Tabs.AdminbusTab if (entManager.TryGetComponent(player, out var xform)) { currentMap = xform.MapID; - position = xform.WorldPosition; + position = xformSystem.GetWorldPosition(xform); if (entManager.TryGetComponent(xform.GridUid, out var gridXform)) { - rotation = gridXform.WorldRotation; + rotation = xformSystem.GetWorldRotation(gridXform); } else { // MapId moment - rotation = xform.WorldRotation - xform.LocalRotation; + rotation = xformSystem.GetWorldRotation(xform) - xform.LocalRotation; } } diff --git a/Content.Client/Administration/UI/Tabs/AtmosTab/AddGasWindow.xaml.cs b/Content.Client/Administration/UI/Tabs/AtmosTab/AddGasWindow.xaml.cs index 55db123ea6..87db34fbec 100644 --- a/Content.Client/Administration/UI/Tabs/AtmosTab/AddGasWindow.xaml.cs +++ b/Content.Client/Administration/UI/Tabs/AtmosTab/AddGasWindow.xaml.cs @@ -1,4 +1,3 @@ -using System.Collections.Generic; using System.Linq; using Content.Client.Atmos.EntitySystems; using Content.Shared.Atmos.Prototypes; @@ -8,9 +7,6 @@ using Robust.Client.Console; using Robust.Client.Player; using Robust.Client.UserInterface.Controls; using Robust.Client.UserInterface.CustomControls; -using Robust.Shared.GameObjects; -using Robust.Shared.IoC; -using Robust.Shared.Map; using Robust.Shared.Map.Components; namespace Content.Client.Administration.UI.Tabs.AtmosTab @@ -19,24 +15,31 @@ namespace Content.Client.Administration.UI.Tabs.AtmosTab [UsedImplicitly] public sealed partial class AddGasWindow : DefaultWindow { - private IEnumerable? _gridData; + private List? _gridData; private IEnumerable? _gasData; protected override void EnteredTree() { // Fill out grids - _gridData = IoCManager.Resolve().GetAllGrids().Where(g => (int) g.Owner != 0); - foreach (var grid in _gridData) + var entManager = IoCManager.Resolve(); + var playerManager = IoCManager.Resolve(); + + var gridQuery = entManager.AllEntityQueryEnumerator(); + _gridData ??= new List(); + _gridData.Clear(); + + while (gridQuery.MoveNext(out var uid, out _)) { - var player = IoCManager.Resolve().LocalPlayer?.ControlledEntity; - var playerGrid = IoCManager.Resolve().GetComponentOrNull(player)?.GridUid; - GridOptions.AddItem($"{grid.Owner} {(playerGrid == grid.Owner ? " (Current)" : "")}"); + var player = playerManager.LocalPlayer?.ControlledEntity; + var playerGrid = entManager.GetComponentOrNull(player)?.GridUid; + GridOptions.AddItem($"{uid} {(playerGrid == uid ? " (Current)" : "")}"); } GridOptions.OnItemSelected += eventArgs => GridOptions.SelectId(eventArgs.Id); // Fill out gases - _gasData = EntitySystem.Get().Gases; + _gasData = entManager.System().Gases; + foreach (var gas in _gasData) { var gasName = Loc.GetString(gas.Name); @@ -53,8 +56,7 @@ namespace Content.Client.Administration.UI.Tabs.AtmosTab if (_gridData == null || _gasData == null) return; - var gridList = _gridData.ToList(); - var gridIndex = gridList[GridOptions.SelectedId].Owner; + var gridIndex = _gridData[GridOptions.SelectedId]; var gasList = _gasData.ToList(); var gasId = gasList[GasOptions.SelectedId].ID; diff --git a/Content.Client/Administration/UI/Tabs/AtmosTab/FillGasWindow.xaml.cs b/Content.Client/Administration/UI/Tabs/AtmosTab/FillGasWindow.xaml.cs index 34212ac6d3..5e17d3d031 100644 --- a/Content.Client/Administration/UI/Tabs/AtmosTab/FillGasWindow.xaml.cs +++ b/Content.Client/Administration/UI/Tabs/AtmosTab/FillGasWindow.xaml.cs @@ -19,24 +19,32 @@ namespace Content.Client.Administration.UI.Tabs.AtmosTab [UsedImplicitly] public sealed partial class FillGasWindow : DefaultWindow { - private IEnumerable? _gridData; + private List? _gridData; private IEnumerable? _gasData; protected override void EnteredTree() { // Fill out grids - _gridData = IoCManager.Resolve().GetAllGrids().Where(g => (int) g.Owner != 0); - foreach (var grid in _gridData) + var entManager = IoCManager.Resolve(); + var playerManager = IoCManager.Resolve(); + + var gridQuery = entManager.AllEntityQueryEnumerator(); + _gridData ??= new List(); + _gridData.Clear(); + + while (gridQuery.MoveNext(out var uid, out _)) { - var player = IoCManager.Resolve().LocalPlayer?.ControlledEntity; - var playerGrid = IoCManager.Resolve().GetComponentOrNull(player)?.GridUid; - GridOptions.AddItem($"{grid.Owner} {(playerGrid == grid.Owner ? " (Current)" : "")}"); + var player = playerManager.LocalPlayer?.ControlledEntity; + var playerGrid = entManager.GetComponentOrNull(player)?.GridUid; + GridOptions.AddItem($"{uid} {(playerGrid == uid ? " (Current)" : "")}"); + _gridData.Add(uid); } GridOptions.OnItemSelected += eventArgs => GridOptions.SelectId(eventArgs.Id); // Fill out gases - _gasData = EntitySystem.Get().Gases; + _gasData = entManager.System().Gases; + foreach (var gas in _gasData) { var gasName = Loc.GetString(gas.Name); @@ -53,8 +61,7 @@ namespace Content.Client.Administration.UI.Tabs.AtmosTab if (_gridData == null || _gasData == null) return; - var gridList = _gridData.ToList(); - var gridIndex = gridList[GridOptions.SelectedId].Owner; + var gridIndex = _gridData[GridOptions.SelectedId]; var gasList = _gasData.ToList(); var gasId = gasList[GasOptions.SelectedId].ID; diff --git a/Content.Client/Administration/UI/Tabs/AtmosTab/SetTemperatureWindow.xaml.cs b/Content.Client/Administration/UI/Tabs/AtmosTab/SetTemperatureWindow.xaml.cs index 028dccd014..c49cb02511 100644 --- a/Content.Client/Administration/UI/Tabs/AtmosTab/SetTemperatureWindow.xaml.cs +++ b/Content.Client/Administration/UI/Tabs/AtmosTab/SetTemperatureWindow.xaml.cs @@ -17,16 +17,23 @@ namespace Content.Client.Administration.UI.Tabs.AtmosTab [UsedImplicitly] public sealed partial class SetTemperatureWindow : DefaultWindow { - private IEnumerable? _data; + private List? _data; protected override void EnteredTree() { - _data = IoCManager.Resolve().GetAllGrids().Where(g => (int) g.Owner != 0); - foreach (var grid in _data) + var entManager = IoCManager.Resolve(); + var playerManager = IoCManager.Resolve(); + + var gridQuery = entManager.AllEntityQueryEnumerator(); + _data ??= new List(); + _data.Clear(); + + while (gridQuery.MoveNext(out var uid, out _)) { - var player = IoCManager.Resolve().LocalPlayer?.ControlledEntity; - var playerGrid = IoCManager.Resolve().GetComponentOrNull(player)?.GridUid; - GridOptions.AddItem($"{grid.Owner} {(playerGrid == grid.Owner ? " (Current)" : "")}"); + var player = playerManager.LocalPlayer?.ControlledEntity; + var playerGrid = entManager.GetComponentOrNull(player)?.GridUid; + GridOptions.AddItem($"{uid} {(playerGrid == uid ? " (Current)" : "")}"); + _data.Add(uid); } GridOptions.OnItemSelected += eventArgs => GridOptions.SelectId(eventArgs.Id); @@ -37,8 +44,8 @@ namespace Content.Client.Administration.UI.Tabs.AtmosTab { if (_data == null) return; - var dataList = _data.ToList(); - var selectedGrid = dataList[GridOptions.SelectedId].Owner; + + var selectedGrid = _data[GridOptions.SelectedId]; IoCManager.Resolve() .ExecuteCommand($"settemp {TileXSpin.Value} {TileYSpin.Value} {selectedGrid} {TemperatureSpin.Value}"); } diff --git a/Content.Client/Audio/AmbientSoundOverlay.cs b/Content.Client/Audio/AmbientSoundOverlay.cs index 9e43bfa793..3110d81384 100644 --- a/Content.Client/Audio/AmbientSoundOverlay.cs +++ b/Content.Client/Audio/AmbientSoundOverlay.cs @@ -9,9 +9,9 @@ namespace Content.Client.Audio; /// public sealed class AmbientSoundOverlay : Overlay { - private IEntityManager _entManager; - private AmbientSoundSystem _ambient; - private EntityLookupSystem _lookup; + private readonly IEntityManager _entManager; + private readonly AmbientSoundSystem _ambient; + private readonly EntityLookupSystem _lookup; public override OverlaySpace Space => OverlaySpace.WorldSpace; @@ -27,6 +27,7 @@ public sealed class AmbientSoundOverlay : Overlay var worldHandle = args.WorldHandle; var ambientQuery = _entManager.GetEntityQuery(); var xformQuery = _entManager.GetEntityQuery(); + var xformSystem = _entManager.System(); const float Size = 0.25f; const float Alpha = 0.25f; @@ -40,16 +41,16 @@ public sealed class AmbientSoundOverlay : Overlay { if (_ambient.IsActive(ambientSound)) { - worldHandle.DrawCircle(xform.WorldPosition, Size, Color.LightGreen.WithAlpha(Alpha * 2f)); + worldHandle.DrawCircle(xformSystem.GetWorldPosition(xform), Size, Color.LightGreen.WithAlpha(Alpha * 2f)); } else { - worldHandle.DrawCircle(xform.WorldPosition, Size, Color.Orange.WithAlpha(Alpha)); + worldHandle.DrawCircle(xformSystem.GetWorldPosition(xform), Size, Color.Orange.WithAlpha(Alpha)); } } else { - worldHandle.DrawCircle(xform.WorldPosition, Size, Color.Red.WithAlpha(Alpha)); + worldHandle.DrawCircle(xformSystem.GetWorldPosition(xform), Size, Color.Red.WithAlpha(Alpha)); } } } diff --git a/Content.Client/Inventory/ClientInventorySystem.cs b/Content.Client/Inventory/ClientInventorySystem.cs index afd15a272d..b454ad27a3 100644 --- a/Content.Client/Inventory/ClientInventorySystem.cs +++ b/Content.Client/Inventory/ClientInventorySystem.cs @@ -32,7 +32,7 @@ namespace Content.Client.Inventory public Action? EntitySlotUpdate = null; public Action? OnSlotAdded = null; public Action? OnSlotRemoved = null; - public Action? OnLinkInventorySlots = null; + public Action? OnLinkInventorySlots = null; public Action? OnUnlinkInventory = null; public Action? OnSpriteUpdate = null; @@ -138,7 +138,7 @@ namespace Content.Client.Inventory } } - OnLinkInventorySlots?.Invoke(component); + OnLinkInventorySlots?.Invoke(uid, component); } public override void Shutdown() @@ -173,7 +173,7 @@ namespace Content.Client.Inventory } OnUnlinkInventory?.Invoke(); - OnLinkInventorySlots?.Invoke(component); + OnLinkInventorySlots?.Invoke(player.Value, component); } public void SetSlotHighlight(EntityUid owner, InventorySlotsComponent component, string slotName, bool state) diff --git a/Content.Client/Light/Components/LightBehaviourComponent.cs b/Content.Client/Light/Components/LightBehaviourComponent.cs index 5f574cdd5b..6e4c26df53 100644 --- a/Content.Client/Light/Components/LightBehaviourComponent.cs +++ b/Content.Client/Light/Components/LightBehaviourComponent.cs @@ -384,7 +384,7 @@ namespace Content.Client.Light.Components public readonly List Behaviours = new(); [ViewVariables(VVAccess.ReadOnly)] - private readonly List _animations = new(); + public readonly List Animations = new(); [ViewVariables(VVAccess.ReadOnly)] private Dictionary _originalPropertyValues = new(); @@ -400,60 +400,11 @@ namespace Content.Client.Light.Components AnimationTracks = {behaviour} }; - _animations.Add(new AnimationContainer(key, animation, behaviour)); + Animations.Add(new AnimationContainer(key, animation, behaviour)); key++; } } - protected override void Startup() - { - base.Startup(); - - // TODO: Do NOT ensure component here. And use eventbus events instead... - Owner.EnsureComponent(); - - if (_entMan.TryGetComponent(Owner, out AnimationPlayerComponent? animation)) - { -#pragma warning disable 618 - animation.AnimationCompleted += OnAnimationCompleted; -#pragma warning restore 618 - } - - foreach (var container in _animations) - { - container.LightBehaviour.Initialize(Owner, _random, _entMan); - } - - // we need to initialize all behaviours before starting any - foreach (var container in _animations) - { - if (container.LightBehaviour.Enabled) - { - StartLightBehaviour(container.LightBehaviour.ID); - } - } - } - - private void OnAnimationCompleted(string key) - { - var container = _animations.FirstOrDefault(x => x.FullKey == key); - - if (container == null) - { - return; - } - - if (container.LightBehaviour.IsLooped) - { - container.LightBehaviour.UpdatePlaybackValues(container.Animation); - - if (_entMan.TryGetComponent(Owner, out AnimationPlayerComponent? animation)) - { - animation.Play(container.Animation, container.FullKey); - } - } - } - /// /// If we disable all the light behaviours we want to be able to revert the light to its original state. /// @@ -485,7 +436,7 @@ namespace Content.Client.Light.Components return; } - foreach (var container in _animations) + foreach (var container in Animations) { if (container.LightBehaviour.ID == id || id == string.Empty) { @@ -516,7 +467,7 @@ namespace Content.Client.Light.Components var toRemove = new List(); - foreach (var container in _animations) + foreach (var container in Animations) { if (container.LightBehaviour.ID == id || id == string.Empty) { @@ -534,7 +485,7 @@ namespace Content.Client.Light.Components foreach (var container in toRemove) { - _animations.Remove(container); + Animations.Remove(container); } if (resetToOriginalSettings && _entMan.TryGetComponent(Owner, out PointLightComponent? light)) @@ -559,7 +510,7 @@ namespace Content.Client.Light.Components return false; } - return _animations.Any(container => animation.HasRunningAnimation(KeyPrefix + container.Key)); + return Animations.Any(container => animation.HasRunningAnimation(KeyPrefix + container.Key)); } /// @@ -569,7 +520,7 @@ namespace Content.Client.Light.Components { var key = 0; - while (_animations.Any(x => x.Key == key)) + while (Animations.Any(x => x.Key == key)) { key++; } @@ -582,7 +533,7 @@ namespace Content.Client.Light.Components behaviour.Initialize(Owner, _random, _entMan); var container = new AnimationContainer(key, animation, behaviour); - _animations.Add(container); + Animations.Add(container); if (playImmediately) { diff --git a/Content.Client/Light/EntitySystems/LightBehaviorSystem.cs b/Content.Client/Light/EntitySystems/LightBehaviorSystem.cs new file mode 100644 index 0000000000..11f69165cf --- /dev/null +++ b/Content.Client/Light/EntitySystems/LightBehaviorSystem.cs @@ -0,0 +1,55 @@ +using System.Linq; +using Content.Client.Light.Components; +using Robust.Client.GameObjects; +using Robust.Shared.Random; + +namespace Content.Client.Light.EntitySystems; + +public sealed class LightBehaviorSystem : EntitySystem +{ + [Dependency] private readonly IRobustRandom _random = default!; + [Dependency] private readonly AnimationPlayerSystem _player = default!; + + public override void Initialize() + { + base.Initialize(); + SubscribeLocalEvent(OnLightStartup); + SubscribeLocalEvent(OnBehaviorAnimationCompleted); + } + + private void OnBehaviorAnimationCompleted(EntityUid uid, LightBehaviourComponent component, AnimationCompletedEvent args) + { + var container = component.Animations.FirstOrDefault(x => x.FullKey == args.Key); + + if (container == null) + { + return; + } + + if (container.LightBehaviour.IsLooped) + { + container.LightBehaviour.UpdatePlaybackValues(container.Animation); + _player.Play(uid, container.Animation, container.FullKey); + } + } + + private void OnLightStartup(EntityUid uid, LightBehaviourComponent component, ComponentStartup args) + { + // TODO: Do NOT ensure component here. And use eventbus events instead... + EnsureComp(uid); + + foreach (var container in component.Animations) + { + container.LightBehaviour.Initialize(uid, _random, EntityManager); + } + + // we need to initialize all behaviours before starting any + foreach (var container in component.Animations) + { + if (container.LightBehaviour.Enabled) + { + component.StartLightBehaviour(container.LightBehaviour.ID); + } + } + } +} diff --git a/Content.Client/Movement/Systems/JetpackSystem.cs b/Content.Client/Movement/Systems/JetpackSystem.cs index 1c8e859e34..f0836ee9b6 100644 --- a/Content.Client/Movement/Systems/JetpackSystem.cs +++ b/Content.Client/Movement/Systems/JetpackSystem.cs @@ -14,7 +14,7 @@ public sealed class JetpackSystem : SharedJetpackSystem [Dependency] private readonly IGameTiming _timing = default!; [Dependency] private readonly IMapManager _mapManager = default!; [Dependency] private readonly ClothingSystem _clothing = default!; - [Dependency] private readonly SharedAppearanceSystem _appearance = default!; + [Dependency] private readonly SharedTransformSystem _transform = default!; public override void Initialize() { @@ -22,7 +22,7 @@ public sealed class JetpackSystem : SharedJetpackSystem SubscribeLocalEvent(OnJetpackAppearance); } - protected override bool CanEnable(JetpackComponent component) + protected override bool CanEnable(EntityUid uid, JetpackComponent component) { // No predicted atmos so you'd have to do a lot of funny to get this working. return false; @@ -30,7 +30,7 @@ public sealed class JetpackSystem : SharedJetpackSystem private void OnJetpackAppearance(EntityUid uid, JetpackComponent component, ref AppearanceChangeEvent args) { - _appearance.TryGetData(uid, JetpackVisuals.Enabled, out var enabled, args.Component); + Appearance.TryGetData(uid, JetpackVisuals.Enabled, out var enabled, args.Component); var state = "icon" + (enabled ? "-on" : ""); args.Sprite?.LayerSetState(0, state); @@ -43,16 +43,21 @@ public sealed class JetpackSystem : SharedJetpackSystem { base.Update(frameTime); - if (!_timing.IsFirstTimePredicted) return; + if (!_timing.IsFirstTimePredicted) + return; - foreach (var comp in EntityQuery()) + // TODO: Please don't copy-paste this I beg + // make a generic particle emitter system / actual particles instead. + var query = EntityQueryEnumerator(); + + while (query.MoveNext(out var uid, out var comp)) { if (_timing.CurTime < comp.TargetTime) continue; comp.TargetTime = _timing.CurTime + TimeSpan.FromSeconds(comp.EffectCooldown); - CreateParticles(comp.Owner); + CreateParticles(uid); } } @@ -62,7 +67,9 @@ public sealed class JetpackSystem : SharedJetpackSystem if (Container.TryGetContainingContainer(uid, out var container) && TryComp(container.Owner, out var body) && body.LinearVelocity.LengthSquared() < 1f) + { return; + } var uidXform = Transform(uid); var coordinates = uidXform.Coordinates; @@ -70,19 +77,17 @@ public sealed class JetpackSystem : SharedJetpackSystem if (_mapManager.TryGetGrid(gridUid, out var grid)) { - coordinates = new EntityCoordinates(grid.Owner, grid.WorldToLocal(coordinates.ToMapPos(EntityManager))); + coordinates = new EntityCoordinates(gridUid.Value, grid.WorldToLocal(coordinates.ToMapPos(EntityManager, _transform))); } else if (uidXform.MapUid != null) { - coordinates = new EntityCoordinates(uidXform.MapUid.Value, uidXform.WorldPosition); + coordinates = new EntityCoordinates(uidXform.MapUid.Value, _transform.GetWorldPosition(uidXform)); } else { return; } - var ent = Spawn("JetpackEffect", coordinates); - var xform = Transform(ent); - xform.Coordinates = coordinates; + Spawn("JetpackEffect", coordinates); } } diff --git a/Content.Client/UserInterface/Systems/Inventory/InventoryUIController.cs b/Content.Client/UserInterface/Systems/Inventory/InventoryUIController.cs index e7ad70b058..cd0236519f 100644 --- a/Content.Client/UserInterface/Systems/Inventory/InventoryUIController.cs +++ b/Content.Client/UserInterface/Systems/Inventory/InventoryUIController.cs @@ -28,6 +28,7 @@ public sealed class InventoryUIController : UIController, IOnStateEntered _slotGroups = new(); @@ -222,26 +223,26 @@ public sealed class InventoryUIController : UIController, IOnStateEntered(); + 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.Database/Migrations/Postgres/20230503001749_AdminNotesImprovement.cs b/Content.Server.Database/Migrations/Postgres/20230503001749_AdminNotesImprovement.cs index bfcaaabbd5..4047915b2c 100644 --- a/Content.Server.Database/Migrations/Postgres/20230503001749_AdminNotesImprovement.cs +++ b/Content.Server.Database/Migrations/Postgres/20230503001749_AdminNotesImprovement.cs @@ -28,10 +28,6 @@ namespace Content.Server.Database.Migrations.Postgres name: "FK_admin_notes_player_player_user_id", table: "admin_notes"); - migrationBuilder.DropCheckConstraint( - name: "HaveEitherAddressOrUserIdOrHWId", - table: "server_role_ban"); - migrationBuilder.DropCheckConstraint( name: "HaveEitherAddressOrUserIdOrHWId", table: "server_ban"); 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/BanList/BanListEui.cs b/Content.Server/Administration/BanList/BanListEui.cs index a3edd4ec48..8da2acf829 100644 --- a/Content.Server/Administration/BanList/BanListEui.cs +++ b/Content.Server/Administration/BanList/BanListEui.cs @@ -31,6 +31,13 @@ public sealed class BanListEui : BaseEui _admins.OnPermsChanged += OnPermsChanged; } + public override void Closed() + { + base.Closed(); + + _admins.OnPermsChanged -= OnPermsChanged; + } + public override EuiStateBase GetNewState() { return new BanListEuiState(BanListPlayerName, Bans); @@ -42,10 +49,6 @@ public sealed class BanListEui : BaseEui { Close(); } - else - { - StateDirty(); - } } private async Task LoadFromDb() diff --git a/Content.Server/Administration/Commands/DepartmentBanCommand.cs b/Content.Server/Administration/Commands/DepartmentBanCommand.cs index 2dbd2f940f..a2e527b22a 100644 --- a/Content.Server/Administration/Commands/DepartmentBanCommand.cs +++ b/Content.Server/Administration/Commands/DepartmentBanCommand.cs @@ -99,8 +99,6 @@ public sealed class DepartmentBanCommand : IConsoleCommand { _banManager.CreateRoleBan(targetUid, located.Username, shell.Player?.UserId, null, targetHWid, job, minutes, severity, reason, now); } - - _banManager.SendRoleBans(located.UserId); } public CompletionResult GetCompletion(IConsoleShell shell, string[] args) diff --git a/Content.Server/Administration/Commands/RoleBanCommand.cs b/Content.Server/Administration/Commands/RoleBanCommand.cs index 23762755ed..8b535977ee 100644 --- a/Content.Server/Administration/Commands/RoleBanCommand.cs +++ b/Content.Server/Administration/Commands/RoleBanCommand.cs @@ -1,4 +1,4 @@ -using System.Linq; +using System.Linq; using System.Text; using Content.Server.Administration.Managers; using Content.Shared.Administration; @@ -87,7 +87,6 @@ public sealed class RoleBanCommand : IConsoleCommand var targetHWid = located.LastHWId; _bans.CreateRoleBan(targetUid, located.Username, shell.Player?.UserId, null, targetHWid, job, minutes, severity, reason, DateTimeOffset.UtcNow); - _bans.SendRoleBans(located.UserId); } public CompletionResult GetCompletion(IConsoleShell shell, string[] args) 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/Managers/BanManager.cs b/Content.Server/Administration/Managers/BanManager.cs index 197daa1d46..cc76438e28 100644 --- a/Content.Server/Administration/Managers/BanManager.cs +++ b/Content.Server/Administration/Managers/BanManager.cs @@ -40,6 +40,8 @@ public sealed class BanManager : IBanManager, IPostInjectInit public void Initialize() { _playerManager.PlayerStatusChanged += OnPlayerStatusChanged; + + _netManager.RegisterNetMessage(); } private async void OnPlayerStatusChanged(object? sender, SessionStatusEventArgs e) @@ -212,6 +214,11 @@ public sealed class BanManager : IBanManager, IPostInjectInit var length = expires == null ? Loc.GetString("cmd-roleban-inf") : Loc.GetString("cmd-roleban-until", ("expires", expires)); _chat.SendAdminAlert(Loc.GetString("cmd-roleban-success", ("target", targetUsername ?? "null"), ("role", role), ("reason", reason), ("length", length))); + + if (target != null) + { + SendRoleBans(target.Value); + } } public HashSet? GetJobBans(NetUserId playerUserId) 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/Content.Server.csproj b/Content.Server/Content.Server.csproj index 33d3871372..fa3ee60eb9 100644 --- a/Content.Server/Content.Server.csproj +++ b/Content.Server/Content.Server.csproj @@ -15,7 +15,6 @@ - diff --git a/Content.Server/Database/ServerDbBase.cs b/Content.Server/Database/ServerDbBase.cs index 1a192ceaf1..3f0186c5c1 100644 --- a/Content.Server/Database/ServerDbBase.cs +++ b/Content.Server/Database/ServerDbBase.cs @@ -1312,70 +1312,67 @@ INSERT INTO player_round (players_id, rounds_id) VALUES ({players[player]}, {id} // You can't group queries, as player will not always exist. When it doesn't, the // whole query returns nothing var player = await db.DbContext.Player.SingleOrDefaultAsync(p => p.UserId == user); - return await (from ban in db.DbContext.Ban - where ban.PlayerUserId == user && - !ban.Hidden - select ban) + var bans = await db.DbContext.Ban + .Where(ban => ban.PlayerUserId == user && !ban.Hidden) .Include(ban => ban.Unban) .Include(ban => ban.Round) .ThenInclude(r => r!.Server) .Include(ban => ban.CreatedBy) .Include(ban => ban.LastEditedBy) .Include(ban => ban.Unban) - .ToAsyncEnumerable() - .SelectAwait(async ban => - new ServerBanNote(ban.Id, ban.RoundId, ban.Round, ban.PlayerUserId, player, - ban.PlaytimeAtNote, ban.Reason, ban.Severity, ban.CreatedBy, ban.BanTime, - ban.LastEditedBy, ban.LastEditedAt, ban.ExpirationTime, ban.Hidden, - ban.Unban?.UnbanningAdmin == null - ? null - : await db.DbContext.Player.SingleOrDefaultAsync(p => p.UserId == ban.Unban.UnbanningAdmin.Value), - ban.Unban?.UnbanTime) - ).ToListAsync(); + .ToArrayAsync(); + + var banNotes = new List(); + foreach (var ban in bans) + { + var banNote = new ServerBanNote(ban.Id, ban.RoundId, ban.Round, ban.PlayerUserId, player, + ban.PlaytimeAtNote, ban.Reason, ban.Severity, ban.CreatedBy, ban.BanTime, + ban.LastEditedBy, ban.LastEditedAt, ban.ExpirationTime, ban.Hidden, + ban.Unban?.UnbanningAdmin == null + ? null + : await db.DbContext.Player.SingleOrDefaultAsync( + p => p.UserId == ban.Unban.UnbanningAdmin.Value), + ban.Unban?.UnbanTime); + + banNotes.Add(banNote); + } + + return banNotes; } protected async Task> GetGroupedServerRoleBansAsNotesForUser(DbGuard db, Guid user) { // Server side query - var bansQuery = - (from ban in db.DbContext.RoleBan - where ban.PlayerUserId == user && - !ban.Hidden - select ban) + var bansQuery = await db.DbContext.RoleBan + .Where(ban => ban.PlayerUserId == user && !ban.Hidden) .Include(ban => ban.Unban) .Include(ban => ban.Round) .ThenInclude(r => r!.Server) .Include(ban => ban.CreatedBy) .Include(ban => ban.LastEditedBy) .Include(ban => ban.Unban) - .ToAsyncEnumerable(); + .ToArrayAsync(); // Client side query, as EF can't do groups yet - var bansEnumerable = - (from ban in bansQuery - group ban by new - { - ban.BanTime, - ban.CreatedBy, - ban.Reason, - Unbanned = ban.Unban == null - } - into banGroup - select banGroup) - .AsAsyncEnumerable(); + var bansEnumerable = bansQuery + .GroupBy(ban => new { ban.BanTime, CreatedBy = (Player?)ban.CreatedBy, ban.Reason, Unbanned = ban.Unban == null }) + .Select(banGroup => banGroup) + .ToArray(); List bans = new(); var player = await db.DbContext.Player.SingleOrDefaultAsync(p => p.UserId == user); - await foreach (var banGroup in bansEnumerable) + foreach (var banGroup in bansEnumerable) { - var firstBan = await banGroup.FirstAsync(); + var firstBan = banGroup.First(); Player? unbanningAdmin = null; + if (firstBan.Unban?.UnbanningAdmin is not null) unbanningAdmin = await db.DbContext.Player.SingleOrDefaultAsync(p => p.UserId == firstBan.Unban.UnbanningAdmin.Value); + bans.Add(new ServerRoleBanNote(firstBan.Id, firstBan.RoundId, firstBan.Round, firstBan.PlayerUserId, player, firstBan.PlaytimeAtNote, firstBan.Reason, firstBan.Severity, firstBan.CreatedBy, firstBan.BanTime, firstBan.LastEditedBy, firstBan.LastEditedAt, firstBan.ExpirationTime, - firstBan.Hidden, await banGroup.Select(ban => ban.RoleId.Replace(BanManager.JobPrefix, null)).ToArrayAsync(), + firstBan.Hidden, banGroup.Select(ban => ban.RoleId.Replace(BanManager.JobPrefix, null)).ToArray(), unbanningAdmin, firstBan.Unban?.UnbanTime)); } diff --git a/Content.Server/Movement/Components/StressTestMovementComponent.cs b/Content.Server/Movement/Components/StressTestMovementComponent.cs index 10b8fbc674..d897b5fae2 100644 --- a/Content.Server/Movement/Components/StressTestMovementComponent.cs +++ b/Content.Server/Movement/Components/StressTestMovementComponent.cs @@ -1,18 +1,10 @@ using System.Numerics; -namespace Content.Server.Movement.Components +namespace Content.Server.Movement.Components; + +[RegisterComponent] +public sealed class StressTestMovementComponent : Component { - [RegisterComponent] - public sealed class StressTestMovementComponent : Component - { - public float Progress { get; set; } - public Vector2 Origin { get; set; } - - protected override void Startup() - { - base.Startup(); - - Origin = IoCManager.Resolve().GetComponent(Owner).WorldPosition; - } - } + public float Progress { get; set; } + public Vector2 Origin { get; set; } } diff --git a/Content.Server/Movement/StressTestMovementSystem.cs b/Content.Server/Movement/StressTestMovementSystem.cs index 5483b89b48..632af9cecf 100644 --- a/Content.Server/Movement/StressTestMovementSystem.cs +++ b/Content.Server/Movement/StressTestMovementSystem.cs @@ -1,32 +1,42 @@ using System.Numerics; using Content.Server.Movement.Components; -using JetBrains.Annotations; -namespace Content.Server.Movement +namespace Content.Server.Movement; + +public sealed class StressTestMovementSystem : EntitySystem { - [UsedImplicitly] - internal sealed class StressTestMovementSystem : EntitySystem + [Dependency] private readonly SharedTransformSystem _transform = default!; + + public override void Initialize() { - public override void Update(float frameTime) + base.Initialize(); + SubscribeLocalEvent(OnStressStartup); + } + + private void OnStressStartup(EntityUid uid, StressTestMovementComponent component, ComponentStartup args) + { + component.Origin = _transform.GetWorldPosition(uid); + } + + public override void Update(float frameTime) + { + base.Update(frameTime); + + var query = EntityQueryEnumerator(); + + while (query.MoveNext(out var uid, out var stressTest, out var transform)) { - base.Update(frameTime); + stressTest.Progress += frameTime; - foreach (var stressTest in EntityManager.EntityQuery(true)) + if (stressTest.Progress > 1) { - var transform = EntityManager.GetComponent(stressTest.Owner); - - stressTest.Progress += frameTime; - - if (stressTest.Progress > 1) - { - stressTest.Progress -= 1; - } - - var x = MathF.Sin(stressTest.Progress * MathHelper.TwoPi); - var y = MathF.Cos(stressTest.Progress * MathHelper.TwoPi); - - transform.WorldPosition = stressTest.Origin + (new Vector2(x, y) * 5); + stressTest.Progress -= 1; } + + var x = MathF.Sin(stressTest.Progress * MathHelper.TwoPi); + var y = MathF.Cos(stressTest.Progress * MathHelper.TwoPi); + + _transform.SetWorldPosition(transform, stressTest.Origin + new Vector2(x, y) * 5); } } } diff --git a/Content.Server/Movement/Systems/JetpackSystem.cs b/Content.Server/Movement/Systems/JetpackSystem.cs index 5b8ecd29f8..4de854f38f 100644 --- a/Content.Server/Movement/Systems/JetpackSystem.cs +++ b/Content.Server/Movement/Systems/JetpackSystem.cs @@ -12,38 +12,40 @@ public sealed class JetpackSystem : SharedJetpackSystem [Dependency] private readonly GasTankSystem _gasTank = default!; [Dependency] private readonly IGameTiming _timing = default!; - private const float UpdateCooldown = 0.5f; - - protected override bool CanEnable(JetpackComponent component) + protected override bool CanEnable(EntityUid uid, JetpackComponent component) { - return base.CanEnable(component) && TryComp(component.Owner, out var gasTank) && !(gasTank.Air.TotalMoles < component.MoleUsage); + return base.CanEnable(uid, component) && + TryComp(uid, out var gasTank) && + !(gasTank.Air.TotalMoles < component.MoleUsage); } public override void Update(float frameTime) { base.Update(frameTime); - var toDisable = new ValueList(); + var toDisable = new ValueList<(EntityUid Uid, JetpackComponent Component)>(); + var query = EntityQueryEnumerator(); - foreach (var (active, comp, gasTank) in EntityQuery()) + while (query.MoveNext(out var uid, out var active, out var comp, out var gasTank)) { - if (_timing.CurTime < active.TargetTime) continue; + if (_timing.CurTime < active.TargetTime) + continue; active.TargetTime = _timing.CurTime + TimeSpan.FromSeconds(active.EffectCooldown); var air = _gasTank.RemoveAir(gasTank, comp.MoleUsage); if (air == null || !MathHelper.CloseTo(air.TotalMoles, comp.MoleUsage, 0.001f)) { - toDisable.Add(comp); + toDisable.Add((uid, comp)); continue; } _gasTank.UpdateUserInterface(gasTank); } - foreach (var comp in toDisable) + foreach (var (uid, comp) in toDisable) { - SetEnabled(comp, false); + SetEnabled(uid, comp, false); } } } 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 c6a81a3f8a..63e45f9843 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/StationEvents/Events/AnomalySpawnRule.cs b/Content.Server/StationEvents/Events/AnomalySpawnRule.cs index 6ed2c0eb45..a59af52f6d 100644 --- a/Content.Server/StationEvents/Events/AnomalySpawnRule.cs +++ b/Content.Server/StationEvents/Events/AnomalySpawnRule.cs @@ -1,9 +1,7 @@ -using System.Linq; -using Content.Server.Anomaly; +using Content.Server.Anomaly; using Content.Server.GameTicking.Rules.Components; using Content.Server.Station.Components; using Content.Server.StationEvents.Components; -using Robust.Shared.Random; namespace Content.Server.StationEvents.Events; @@ -30,13 +28,9 @@ public sealed class AnomalySpawnRule : StationEventSystem(chosenStation, out var stationData)) return; - EntityUid? grid = null; - foreach (var g in stationData.Grids.Where(HasComp)) - { - grid = g; - } + var grid = StationSystem.GetLargestGrid(stationData); - if (grid is not { }) + if (grid is null) return; var amountToSpawn = Math.Max(1, (int) MathF.Round(GetSeverityModifier() / 2)); 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/Tabletop/TabletopSystem.Map.cs b/Content.Server/Tabletop/TabletopSystem.Map.cs index 4048962591..362fbc5550 100644 --- a/Content.Server/Tabletop/TabletopSystem.Map.cs +++ b/Content.Server/Tabletop/TabletopSystem.Map.cs @@ -50,12 +50,13 @@ namespace Content.Server.Tabletop TabletopMap = _mapManager.CreateMap(); _tabletops = 0; + var mapUid = _mapManager.GetMapEntityId(TabletopMap); - var mapComp = EntityManager.GetComponent(_mapManager.GetMapEntityId(TabletopMap)); + var mapComp = EntityManager.GetComponent(mapUid); // Lighting is always disabled in tabletop world. mapComp.LightingEnabled = false; - mapComp.Dirty(); + Dirty(mapUid, mapComp); } /// 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/Containers/ItemSlot/ItemSlotsComponent.cs b/Content.Shared/Containers/ItemSlot/ItemSlotsComponent.cs index dafb33fce1..319bf5cd53 100644 --- a/Content.Shared/Containers/ItemSlot/ItemSlotsComponent.cs +++ b/Content.Shared/Containers/ItemSlot/ItemSlotsComponent.cs @@ -77,13 +77,6 @@ namespace Content.Shared.Containers.ItemSlots [DataField("ejectSound")] public SoundSpecifier EjectSound = new SoundPathSpecifier("/Audio/Weapons/Guns/MagOut/revolver_magout.ogg"); - /// - /// Options used for playing the insert/eject sounds. - /// - [DataField("soundOptions")] - [Obsolete("Use the sound specifer parameters instead")] - public AudioParams SoundOptions = AudioParams.Default; - /// /// The name of this item slot. This will be shown to the user in the verb menu. /// @@ -228,7 +221,6 @@ namespace Content.Shared.Containers.ItemSlots InsertSound = other.InsertSound; EjectSound = other.EjectSound; - SoundOptions = other.SoundOptions; Name = other.Name; Locked = other.Locked; InsertOnInteract = other.InsertOnInteract; diff --git a/Content.Shared/Containers/ItemSlot/ItemSlotsSystem.cs b/Content.Shared/Containers/ItemSlot/ItemSlotsSystem.cs index 48c5e9c331..42df026159 100644 --- a/Content.Shared/Containers/ItemSlot/ItemSlotsSystem.cs +++ b/Content.Shared/Containers/ItemSlot/ItemSlotsSystem.cs @@ -65,7 +65,7 @@ namespace Content.Shared.Containers.ItemSlots if (slot.HasItem || string.IsNullOrEmpty(slot.StartingItem)) continue; - var item = EntityManager.SpawnEntity(slot.StartingItem, EntityManager.GetComponent(itemSlots.Owner).Coordinates); + var item = EntityManager.SpawnEntity(slot.StartingItem, EntityManager.GetComponent(uid).Coordinates); slot.ContainerSlot?.Insert(item); } } @@ -77,7 +77,7 @@ namespace Content.Shared.Containers.ItemSlots { foreach (var (id, slot) in itemSlots.Slots) { - slot.ContainerSlot = _containers.EnsureContainer(itemSlots.Owner, id); + slot.ContainerSlot = _containers.EnsureContainer(uid, id); } } @@ -93,13 +93,13 @@ namespace Content.Shared.Containers.ItemSlots if (itemSlots.Slots.TryGetValue(id, out var existing)) { if (existing.Local) - Logger.Error($"Duplicate item slot key. Entity: {EntityManager.GetComponent(itemSlots.Owner).EntityName} ({uid}), key: {id}"); + Log.Error($"Duplicate item slot key. Entity: {EntityManager.GetComponent(uid).EntityName} ({uid}), key: {id}"); else // server state takes priority slot.CopyFrom(existing); } - slot.ContainerSlot = _containers.EnsureContainer(itemSlots.Owner, id); + slot.ContainerSlot = _containers.EnsureContainer(uid, id); itemSlots.Slots[id] = slot; Dirty(itemSlots); } @@ -340,7 +340,7 @@ namespace Content.Shared.Containers.ItemSlots if (ejected != null && ejected.Value && user != null) _adminLogger.Add(LogType.Action, LogImpact.Low, $"{ToPrettyString(user.Value)} ejected {ToPrettyString(item)} from {slot.ContainerSlot?.ID + " slot of "}{ToPrettyString(uid)}"); - _audioSystem.PlayPredicted(slot.EjectSound, uid, excludeUserAudio ? user : null, slot.SoundOptions); + _audioSystem.PlayPredicted(slot.EjectSound, uid, excludeUserAudio ? user : null); } /// @@ -477,9 +477,11 @@ namespace Content.Shared.Containers.ItemSlots ? Loc.GetString(slot.Name) : EntityManager.GetComponent(slot.Item.Value).EntityName ?? string.Empty; - AlternativeVerb verb = new(); - verb.IconEntity = slot.Item; - verb.Act = () => TryEjectToHands(uid, slot, args.User, excludeUserAudio: true); + AlternativeVerb verb = new() + { + IconEntity = slot.Item, + Act = () => TryEjectToHands(uid, slot, args.User, excludeUserAudio: true) + }; if (slot.EjectVerbText == null) { @@ -538,18 +540,20 @@ namespace Content.Shared.Containers.ItemSlots var verbSubject = slot.Name != string.Empty ? Loc.GetString(slot.Name) - : Name(args.Using.Value) ?? string.Empty; + : Name(args.Using.Value); - InteractionVerb insertVerb = new(); - insertVerb.IconEntity = args.Using; - insertVerb.Act = () => Insert(uid, slot, args.Using.Value, args.User, excludeUserAudio: true); + InteractionVerb insertVerb = new() + { + IconEntity = args.Using, + Act = () => Insert(uid, slot, args.Using.Value, args.User, excludeUserAudio: true) + }; if (slot.InsertVerbText != null) { insertVerb.Text = Loc.GetString(slot.InsertVerbText); insertVerb.Icon = new SpriteSpecifier.Texture( - new("/Textures/Interface/VerbIcons/insert.svg.192dpi.png")); + new ResPath("/Textures/Interface/VerbIcons/insert.svg.192dpi.png")); } else if(slot.EjectOnInteract) { @@ -558,7 +562,7 @@ namespace Content.Shared.Containers.ItemSlots insertVerb.Text = Loc.GetString("place-item-verb-text", ("subject", verbSubject)); insertVerb.Icon = new SpriteSpecifier.Texture( - new("/Textures/Interface/VerbIcons/drop.svg.192dpi.png")); + new ResPath("/Textures/Interface/VerbIcons/drop.svg.192dpi.png")); } else { @@ -635,7 +639,7 @@ namespace Content.Shared.Containers.ItemSlots return; slot.Locked = locked; - itemSlots.Dirty(); + Dirty(uid, itemSlots); } /// diff --git a/Content.Shared/Cuffs/Components/CuffableComponent.cs b/Content.Shared/Cuffs/Components/CuffableComponent.cs index 7c431ff9a3..4cfeec5636 100644 --- a/Content.Shared/Cuffs/Components/CuffableComponent.cs +++ b/Content.Shared/Cuffs/Components/CuffableComponent.cs @@ -39,18 +39,6 @@ public sealed class CuffableComponent : Component /// [DataField("canStillInteract"), ViewVariables(VVAccess.ReadWrite)] public bool CanStillInteract = true; - - /// - /// Damage is applied to someone when they try to uncuff themselves. - /// - [DataField("damageOnResist"), ViewVariables(VVAccess.ReadWrite)] - public DamageSpecifier DamageOnResist = new() - { - DamageDict = new() - { - { "Blunt", 3.0 }, - } - }; } [Serializable, NetSerializable] diff --git a/Content.Shared/Cuffs/Components/HandcuffComponent.cs b/Content.Shared/Cuffs/Components/HandcuffComponent.cs index 27f8a0a112..398fce4fc7 100644 --- a/Content.Shared/Cuffs/Components/HandcuffComponent.cs +++ b/Content.Shared/Cuffs/Components/HandcuffComponent.cs @@ -1,3 +1,4 @@ +using Content.Shared.Damage; using Robust.Shared.Audio; using Robust.Shared.GameStates; using Robust.Shared.Prototypes; @@ -47,6 +48,15 @@ public sealed class HandcuffComponent : Component [DataField("brokenPrototype", customTypeSerializer: typeof(PrototypeIdSerializer)), ViewVariables(VVAccess.ReadWrite)] public string? BrokenPrototype; + [DataField("damageOnResist"), ViewVariables(VVAccess.ReadWrite)] + public DamageSpecifier DamageOnResist = new() + { + DamageDict = new() + { + { "Blunt", 3.0 }, + } + }; + /// /// The path of the RSI file used for the player cuffed overlay. /// diff --git a/Content.Shared/Cuffs/SharedCuffableSystem.cs b/Content.Shared/Cuffs/SharedCuffableSystem.cs index 39385bf795..470256c9a6 100644 --- a/Content.Shared/Cuffs/SharedCuffableSystem.cs +++ b/Content.Shared/Cuffs/SharedCuffableSystem.cs @@ -266,7 +266,7 @@ namespace Content.Shared.Cuffs private void OnCuffAfterInteract(EntityUid uid, HandcuffComponent component, AfterInteractEvent args) { - if (args.Target is not {Valid: true} target) + if (args.Target is not { Valid: true } target) return; if (!args.CanReach) @@ -580,7 +580,7 @@ namespace Content.Shared.Cuffs if (isOwner) { - _damageSystem.TryChangeDamage(target, cuffable.DamageOnResist, true, false); + _damageSystem.TryChangeDamage(target, cuff.DamageOnResist, true, false); } if (_net.IsServer) diff --git a/Content.Shared/Doors/Systems/SharedDoorSystem.cs b/Content.Shared/Doors/Systems/SharedDoorSystem.cs index 0b4bd21f4a..64e6d7a8cd 100644 --- a/Content.Shared/Doors/Systems/SharedDoorSystem.cs +++ b/Content.Shared/Doors/Systems/SharedDoorSystem.cs @@ -23,14 +23,14 @@ public abstract class SharedDoorSystem : EntitySystem { [Dependency] protected readonly IGameTiming GameTiming = default!; [Dependency] protected readonly SharedPhysicsSystem PhysicsSystem = default!; - [Dependency] private readonly DamageableSystem _damageableSystem = default!; - [Dependency] private readonly SharedStunSystem _stunSystem = default!; + [Dependency] private readonly DamageableSystem _damageableSystem = default!; + [Dependency] private readonly SharedStunSystem _stunSystem = default!; [Dependency] protected readonly TagSystem Tags = default!; [Dependency] protected readonly SharedAudioSystem Audio = default!; - [Dependency] private readonly EntityLookupSystem _entityLookup = default!; + [Dependency] private readonly EntityLookupSystem _entityLookup = default!; [Dependency] protected readonly SharedAppearanceSystem AppearanceSystem = default!; - [Dependency] private readonly OccluderSystem _occluder = default!; - [Dependency] private readonly AccessReaderSystem _accessReaderSystem = default!; + [Dependency] private readonly OccluderSystem _occluder = default!; + [Dependency] private readonly AccessReaderSystem _accessReaderSystem = default!; /// /// A body must have an intersection percentage larger than this in order to be considered as colliding with a diff --git a/Content.Shared/Implants/Components/ImplanterComponent.cs b/Content.Shared/Implants/Components/ImplanterComponent.cs index 0bdae1979d..8cb7ae9091 100644 --- a/Content.Shared/Implants/Components/ImplanterComponent.cs +++ b/Content.Shared/Implants/Components/ImplanterComponent.cs @@ -8,7 +8,7 @@ using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototy namespace Content.Shared.Implants.Components; /// -/// Implanters are used to implant or extract implants from an entity +/// Implanters are used to implant or extract implants from an entity. /// Some can be single use (implant only) or some can draw out an implant /// //TODO: Rework drawing to work with implant cases when surgery is in diff --git a/Content.Shared/Implants/SharedImplanterSystem.cs b/Content.Shared/Implants/SharedImplanterSystem.cs index b95fd4e642..3cbf511eaf 100644 --- a/Content.Shared/Implants/SharedImplanterSystem.cs +++ b/Content.Shared/Implants/SharedImplanterSystem.cs @@ -59,9 +59,9 @@ public abstract class SharedImplanterSystem : EntitySystem implantContainer.Insert(implant.Value); if (component.CurrentMode == ImplanterToggleMode.Inject && !component.ImplantOnly) - DrawMode(component); + DrawMode(implanter, component); else - ImplantMode(component); + ImplantMode(implanter, component); Dirty(component); } @@ -74,8 +74,8 @@ public abstract class SharedImplanterSystem : EntitySystem [NotNullWhen(true)] out EntityUid? implant, [NotNullWhen(true)] out SubdermalImplantComponent? implantComp) { - implant = component.ImplanterSlot.ContainerSlot?.ContainedEntities?.FirstOrDefault(); - if (!TryComp(implant, out implantComp)) + implant = component.ImplanterSlot.ContainerSlot?.ContainedEntities.FirstOrDefault(); + if (!TryComp(implant, out implantComp)) return false; var ev = new AddImplantAttemptEvent(user, target, implant.Value, implanter); @@ -101,7 +101,7 @@ public abstract class SharedImplanterSystem : EntitySystem foreach (var implant in implantContainer.ContainedEntities) { if (!implantCompQuery.TryGetComponent(implant, out var implantComp)) - return; + continue; //Don't remove a permanent implant and look for the next that can be drawn if (!implantContainer.CanRemove(implant)) @@ -124,27 +124,27 @@ public abstract class SharedImplanterSystem : EntitySystem } if (component.CurrentMode == ImplanterToggleMode.Draw && !component.ImplantOnly && !permanentFound) - ImplantMode(component); + ImplantMode(implanter, component); Dirty(component); } } - private void ImplantMode(ImplanterComponent component) + private void ImplantMode(EntityUid uid, ImplanterComponent component) { component.CurrentMode = ImplanterToggleMode.Inject; - ChangeOnImplantVisualizer(component); + ChangeOnImplantVisualizer(uid, component); } - private void DrawMode(ImplanterComponent component) + private void DrawMode(EntityUid uid, ImplanterComponent component) { component.CurrentMode = ImplanterToggleMode.Draw; - ChangeOnImplantVisualizer(component); + ChangeOnImplantVisualizer(uid, component); } - private void ChangeOnImplantVisualizer(ImplanterComponent component) + private void ChangeOnImplantVisualizer(EntityUid uid, ImplanterComponent component) { - if (!TryComp(component.Owner, out var appearance)) + if (!TryComp(uid, out var appearance)) return; bool implantFound; @@ -156,17 +156,17 @@ public abstract class SharedImplanterSystem : EntitySystem implantFound = false; if (component.CurrentMode == ImplanterToggleMode.Inject && !component.ImplantOnly) - _appearance.SetData(component.Owner, ImplanterVisuals.Full, implantFound, appearance); + _appearance.SetData(uid, ImplanterVisuals.Full, implantFound, appearance); else if (component.CurrentMode == ImplanterToggleMode.Inject && component.ImplantOnly) { - _appearance.SetData(component.Owner, ImplanterVisuals.Full, implantFound, appearance); - _appearance.SetData(component.Owner, ImplanterImplantOnlyVisuals.ImplantOnly, component.ImplantOnly, + _appearance.SetData(uid, ImplanterVisuals.Full, implantFound, appearance); + _appearance.SetData(uid, ImplanterImplantOnlyVisuals.ImplantOnly, component.ImplantOnly, appearance); } else - _appearance.SetData(component.Owner, ImplanterVisuals.Full, implantFound, appearance); + _appearance.SetData(uid, ImplanterVisuals.Full, implantFound, appearance); } } diff --git a/Content.Shared/Movement/Systems/SharedJetpackSystem.cs b/Content.Shared/Movement/Systems/SharedJetpackSystem.cs index 9fdac9ff55..77bf97b25a 100644 --- a/Content.Shared/Movement/Systems/SharedJetpackSystem.cs +++ b/Content.Shared/Movement/Systems/SharedJetpackSystem.cs @@ -6,20 +6,17 @@ using Content.Shared.Movement.Events; using Content.Shared.Popups; using Robust.Shared.Containers; using Robust.Shared.GameStates; -using Robust.Shared.Network; -using Robust.Shared.Player; using Robust.Shared.Serialization; -using Robust.Shared.Timing; namespace Content.Shared.Movement.Systems; public abstract class SharedJetpackSystem : EntitySystem { - [Dependency] protected readonly MovementSpeedModifierSystem MovementSpeedModifier = default!; - [Dependency] protected readonly SharedAppearanceSystem Appearance = default!; + [Dependency] private readonly MovementSpeedModifierSystem _movementSpeedModifier = default!; + [Dependency] protected readonly SharedAppearanceSystem Appearance = default!; [Dependency] protected readonly SharedContainerSystem Container = default!; - [Dependency] private readonly SharedPopupSystem _popup = default!; - [Dependency] private readonly SharedMoverController _mover = default!; + [Dependency] private readonly SharedMoverController _mover = default!; + [Dependency] private readonly SharedPopupSystem _popup = default!; public override void Initialize() { @@ -55,14 +52,16 @@ public abstract class SharedJetpackSystem : EntitySystem { _popup.PopupClient(Loc.GetString("jetpack-to-grid"), uid, uid); - SetEnabled(jetpack, false, uid); + SetEnabled(user.Jetpack, jetpack, false, uid); } } } private void OnJetpackUserHandleState(EntityUid uid, JetpackUserComponent component, ref ComponentHandleState args) { - if (args.Current is not JetpackUserComponentState state) return; + if (args.Current is not JetpackUserComponentState state) + return; + component.Jetpack = state.Jetpack; } @@ -76,7 +75,7 @@ public abstract class SharedJetpackSystem : EntitySystem private void OnJetpackDropped(EntityUid uid, JetpackComponent component, DroppedEvent args) { - SetEnabled(component, false, args.User); + SetEnabled(uid, component, false, args.User); } private void OnJetpackUserCanWeightless(EntityUid uid, JetpackUserComponent component, ref CanWeightlessMoveEvent args) @@ -89,22 +88,24 @@ public abstract class SharedJetpackSystem : EntitySystem if (TryComp(component.Jetpack, out var jetpack) && !CanEnableOnGrid(args.Transform.GridUid)) { - SetEnabled(jetpack, false, uid); + SetEnabled(component.Jetpack, jetpack, false, uid); _popup.PopupClient(Loc.GetString("jetpack-to-grid"), uid, uid); } } - private void SetupUser(EntityUid uid, JetpackComponent component) + private void SetupUser(EntityUid user, EntityUid jetpackUid) { - var user = EnsureComp(uid); - _mover.SetRelay(uid, component.Owner); - user.Jetpack = component.Owner; + var userComp = EnsureComp(user); + _mover.SetRelay(user, jetpackUid); + userComp.Jetpack = jetpackUid; } private void RemoveUser(EntityUid uid) { - if (!RemComp(uid)) return; + if (!RemComp(uid)) + return; + RemComp(uid); } @@ -120,7 +121,7 @@ public abstract class SharedJetpackSystem : EntitySystem return; } - SetEnabled(component, !IsEnabled(uid)); + SetEnabled(uid, component, !IsEnabled(uid)); } private bool CanEnableOnGrid(EntityUid? gridUid) @@ -139,44 +140,48 @@ public abstract class SharedJetpackSystem : EntitySystem return HasComp(uid); } - public void SetEnabled(JetpackComponent component, bool enabled, EntityUid? user = null) + public void SetEnabled(EntityUid uid, JetpackComponent component, bool enabled, EntityUid? user = null) { - if (IsEnabled(component.Owner) == enabled || - enabled && !CanEnable(component)) return; + if (IsEnabled(uid) == enabled || + enabled && !CanEnable(uid, component)) + { + return; + } if (enabled) { - EnsureComp(component.Owner); + EnsureComp(uid); } else { - RemComp(component.Owner); + RemComp(uid); } if (user == null) { - Container.TryGetContainingContainer(component.Owner, out var container); + Container.TryGetContainingContainer(uid, out var container); user = container?.Owner; } // Can't activate if no one's using. - if (user == null && enabled) return; + if (user == null && enabled) + return; if (user != null) { if (enabled) { - SetupUser(user.Value, component); + SetupUser(user.Value, uid); } else { RemoveUser(user.Value); } - MovementSpeedModifier.RefreshMovementSpeedModifiers(user.Value); + _movementSpeedModifier.RefreshMovementSpeedModifiers(user.Value); } - Appearance.SetData(component.Owner, JetpackVisuals.Enabled, enabled); + Appearance.SetData(uid, JetpackVisuals.Enabled, enabled); Dirty(component); } @@ -185,7 +190,7 @@ public abstract class SharedJetpackSystem : EntitySystem return HasComp(uid); } - protected virtual bool CanEnable(JetpackComponent component) + protected virtual bool CanEnable(EntityUid uid, JetpackComponent component) { 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); } diff --git a/Content.Shared/StepTrigger/Systems/StepTriggerSystem.cs b/Content.Shared/StepTrigger/Systems/StepTriggerSystem.cs index 1591ce623a..0fb87ff375 100644 --- a/Content.Shared/StepTrigger/Systems/StepTriggerSystem.cs +++ b/Content.Shared/StepTrigger/Systems/StepTriggerSystem.cs @@ -1,6 +1,4 @@ using Content.Shared.StepTrigger.Components; -using Content.Shared.Tag; -using Robust.Shared.Collections; using Robust.Shared.GameStates; using Robust.Shared.Map.Components; using Robust.Shared.Physics; @@ -74,26 +72,26 @@ public sealed class StepTriggerSystem : EntitySystem foreach (var otherUid in component.Colliding) { - UpdateColliding(component, transform, otherUid, query); + UpdateColliding(uid, component, transform, otherUid, query); } return false; } - private void UpdateColliding(StepTriggerComponent component, TransformComponent ownerTransform, EntityUid otherUid, EntityQuery query) + private void UpdateColliding(EntityUid uid, StepTriggerComponent component, TransformComponent ownerTransform, EntityUid otherUid, EntityQuery query) { if (!query.TryGetComponent(otherUid, out var otherPhysics)) return; // TODO: This shouldn't be calculating based on world AABBs. - var ourAabb = _entityLookup.GetWorldAABB(component.Owner, ownerTransform); + var ourAabb = _entityLookup.GetWorldAABB(uid, ownerTransform); var otherAabb = _entityLookup.GetWorldAABB(otherUid); if (!ourAabb.Intersects(otherAabb)) { if (component.CurrentlySteppedOn.Remove(otherUid)) { - Dirty(component); + Dirty(uid, component); } return; } @@ -101,17 +99,16 @@ public sealed class StepTriggerSystem : EntitySystem if (otherPhysics.LinearVelocity.Length() < component.RequiredTriggerSpeed || component.CurrentlySteppedOn.Contains(otherUid) || otherAabb.IntersectPercentage(ourAabb) < component.IntersectRatio - || !CanTrigger(component.Owner, otherUid, component)) + || !CanTrigger(uid, otherUid, component)) { return; } - var ev = new StepTriggeredEvent { Source = component.Owner, Tripper = otherUid }; - RaiseLocalEvent(component.Owner, ref ev, true); + var ev = new StepTriggeredEvent { Source = uid, Tripper = otherUid }; + RaiseLocalEvent(uid, ref ev, true); component.CurrentlySteppedOn.Add(otherUid); - Dirty(component); - return; + Dirty(uid, component); } private bool CanTrigger(EntityUid uid, EntityUid otherUid, StepTriggerComponent component) @@ -140,7 +137,7 @@ public sealed class StepTriggerSystem : EntitySystem if (component.Colliding.Add(otherUid)) { - Dirty(component); + Dirty(uid, component); } } @@ -152,7 +149,7 @@ public sealed class StepTriggerSystem : EntitySystem return; component.CurrentlySteppedOn.Remove(otherUid); - Dirty(component); + Dirty(uid, component); if (component.Colliding.Count == 0) { @@ -211,7 +208,7 @@ public sealed class StepTriggerSystem : EntitySystem return; component.IntersectRatio = ratio; - Dirty(component); + Dirty(uid, component); } public void SetRequiredTriggerSpeed(EntityUid uid, float speed, StepTriggerComponent? component = null) @@ -223,7 +220,7 @@ public sealed class StepTriggerSystem : EntitySystem return; component.RequiredTriggerSpeed = speed; - Dirty(component); + Dirty(uid, component); } public void SetActive(EntityUid uid, bool active, StepTriggerComponent? component = null) @@ -235,7 +232,7 @@ public sealed class StepTriggerSystem : EntitySystem return; component.Active = active; - Dirty(component); + Dirty(uid, component); } } diff --git a/Content.Shared/Storage/EntitySystems/SharedItemCounterSystem.cs b/Content.Shared/Storage/EntitySystems/SharedItemCounterSystem.cs index b2912db2a5..8ef62c45c4 100644 --- a/Content.Shared/Storage/EntitySystems/SharedItemCounterSystem.cs +++ b/Content.Shared/Storage/EntitySystems/SharedItemCounterSystem.cs @@ -21,32 +21,32 @@ namespace Content.Shared.Storage.EntitySystems private void CounterEntityInserted(EntityUid uid, ItemCounterComponent itemCounter, EntInsertedIntoContainerMessage args) { - if (!EntityManager.TryGetComponent(itemCounter.Owner, out AppearanceComponent? appearanceComponent)) + if (!EntityManager.TryGetComponent(uid, out AppearanceComponent? appearanceComponent)) return; var count = GetCount(args, itemCounter); if (count == null) return; - _appearance.SetData(itemCounter.Owner, StackVisuals.Actual, count, appearanceComponent); + _appearance.SetData(uid, StackVisuals.Actual, count, appearanceComponent); if (itemCounter.MaxAmount != null) - _appearance.SetData(itemCounter.Owner, StackVisuals.MaxCount, itemCounter.MaxAmount, appearanceComponent); + _appearance.SetData(uid, StackVisuals.MaxCount, itemCounter.MaxAmount, appearanceComponent); } private void CounterEntityRemoved(EntityUid uid, ItemCounterComponent itemCounter, EntRemovedFromContainerMessage args) { - if (!EntityManager.TryGetComponent(itemCounter.Owner, out AppearanceComponent? appearanceComponent)) + if (!EntityManager.TryGetComponent(uid, out AppearanceComponent? appearanceComponent)) return; var count = GetCount(args, itemCounter); if (count == null) return; - _appearance.SetData(itemCounter.Owner, StackVisuals.Actual, count, appearanceComponent); + _appearance.SetData(uid, StackVisuals.Actual, count, appearanceComponent); if (itemCounter.MaxAmount != null) - _appearance.SetData(itemCounter.Owner, StackVisuals.MaxCount, itemCounter.MaxAmount, appearanceComponent); + _appearance.SetData(uid, StackVisuals.MaxCount, itemCounter.MaxAmount, appearanceComponent); } protected abstract int? GetCount(ContainerModifiedMessage msg, ItemCounterComponent itemCounter); diff --git a/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.Interactions.cs b/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.Interactions.cs index 4ffbe8fc63..53dc9dfced 100644 --- a/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.Interactions.cs +++ b/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.Interactions.cs @@ -78,7 +78,7 @@ public abstract partial class SharedGunSystem Audio.PlayPredicted(component.SoundModeToggle, uid, user); Popup(Loc.GetString("gun-selected-mode", ("mode", GetLocSelector(fire))), uid, user); - Dirty(component); + Dirty(uid, component); } /// diff --git a/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.Revolver.cs b/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.Revolver.cs index 040d3f5713..50a89cb93e 100644 --- a/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.Revolver.cs +++ b/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.Revolver.cs @@ -8,6 +8,7 @@ using Robust.Shared.Serialization; using Robust.Shared.Utility; using System; using System.Linq; +using JetBrains.Annotations; namespace Content.Shared.Weapons.Ranged.Systems; @@ -164,7 +165,7 @@ public partial class SharedGunSystem Popup(Loc.GetString("gun-revolver-insert"), revolverUid, user); UpdateRevolverAppearance(revolverUid, component); UpdateAmmoCount(uid); - Dirty(component); + Dirty(uid, component); return true; } @@ -223,6 +224,7 @@ public partial class SharedGunSystem return count; } + [PublicAPI] private int GetRevolverUnspentCount(RevolverAmmoProviderComponent component) { var count = 0; @@ -261,7 +263,8 @@ public partial class SharedGunSystem if (slot == null) { - if (chamber == null) continue; + if (chamber == null) + continue; // Too lazy to make a new method don't sue me. if (!_netManager.IsClient) @@ -294,7 +297,7 @@ public partial class SharedGunSystem Audio.PlayPredicted(component.SoundEject, revolverUid, user); UpdateAmmoCount(revolverUid); UpdateRevolverAppearance(revolverUid, component); - Dirty(component); + Dirty(revolverUid, component); } } @@ -366,12 +369,12 @@ public partial class SharedGunSystem component.AmmoContainer.Remove(ent.Value); component.AmmoSlots[index] = null; args.Ammo.Add((ent.Value, EnsureComp(ent.Value))); - Transform(ent.Value).Coordinates = args.Coordinates; + TransformSystem.SetCoordinates(ent.Value, args.Coordinates); } } UpdateRevolverAppearance(uid, component); - Dirty(component); + Dirty(uid, component); } private void Cycle(RevolverAmmoProviderComponent component, int count = 1) diff --git a/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.cs b/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.cs index 3d0530e3aa..f0500d1fbd 100644 --- a/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.cs +++ b/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.cs @@ -329,7 +329,7 @@ public abstract partial class SharedGunSystem : EntitySystem CauseImpulse(fromCoordinates, toCoordinates.Value, user, userPhysics); } - Dirty(gun); + Dirty(gunUid, gun); } public void Shoot( @@ -366,7 +366,7 @@ public abstract partial class SharedGunSystem : EntitySystem protected void SetCartridgeSpent(EntityUid uid, CartridgeAmmoComponent cartridge, bool spent) { if (cartridge.Spent != spent) - Dirty(cartridge); + Dirty(uid, cartridge); cartridge.Spent = spent; Appearance.SetData(uid, AmmoVisuals.Spent, spent); @@ -380,14 +380,14 @@ public abstract partial class SharedGunSystem : EntitySystem bool playSound = true) { // TODO: Sound limit version. - var offsetPos = (Random.NextVector2(EjectOffset)); + var offsetPos = Random.NextVector2(EjectOffset); var xform = Transform(entity); var coordinates = xform.Coordinates; coordinates = coordinates.Offset(offsetPos); - xform.LocalRotation = Random.NextAngle(); - xform.Coordinates = coordinates; + TransformSystem.SetLocalRotation(xform, Random.NextAngle()); + TransformSystem.SetCoordinates(entity, xform, coordinates); if (playSound && TryComp(entity, out var cartridge)) { diff --git a/Resources/Audio/Ambience/Antag/attributions.yml b/Resources/Audio/Ambience/Antag/attributions.yml index 6f76d64d85..3d7d5c737c 100644 --- a/Resources/Audio/Ambience/Antag/attributions.yml +++ b/Resources/Audio/Ambience/Antag/attributions.yml @@ -1,4 +1,4 @@ -- files: ["nukeops_start.ogg"] +- files: ["nukeops_start.ogg, traitor_start.ogg"] license: "CC-BY-SA-3.0" copyright: "Taken from TG station" source: "https://github.com/tgstation/tgstation/commit/827967c9650c23af64280ad1491405fed8f644c5#diff-6cc910b7cad9ac4333c8d0885fc844746066120b465d8d4ba8f7019169316574" diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index 0daa7842c2..2ea1a04b09 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,41 +1,4 @@ Entries: -- author: VigersRay - changes: - - {message: 'Added alert level, instruction and shift duration in PDA!', type: Add} - - {message: Fix uknown station name in PDA for latejoin!, type: Fix} - id: 3801 - time: '2023-05-17T20:35:41.0000000+00:00' -- author: metalgearsloth - changes: - - {message: Add lathe recipe for tethergun., type: Add} - id: 3802 - time: '2023-05-18T02:07:11.0000000+00:00' -- author: DrSmugleaf - changes: - - {message: Fixed Next on the admin logs UI resending the same logs., type: Fix} - id: 3803 - time: '2023-05-18T05:51:17.0000000+00:00' -- author: FluffiestFloof - changes: - - {message: Updated the Suit Storage look., type: Tweak} - id: 3804 - time: '2023-05-18T17:52:05.0000000+00:00' -- author: EmoGarbage404 - changes: - - {message: Vending machines can now be completely destroyed., type: Fix} - id: 3805 - time: '2023-05-18T23:48:14.0000000+00:00' -- author: themias - changes: - - {message: Mobs that are in critical condition no longer appear as dead on the - crew monitor, type: Fix} - id: 3806 - time: '2023-05-18T23:49:55.0000000+00:00' -- author: OctoRocket - changes: - - {message: 'Antifreeze tastes warm now, because it is antifreeze.', type: Tweak} - id: 3807 - time: '2023-05-19T02:21:57.0000000+00:00' - author: metalgearsloth changes: - {message: Disabled zombies preset temporarily until they have more work done., @@ -2983,3 +2946,40 @@ Entries: - {message: new and improved ban panel, type: Add} id: 4300 time: '2023-07-21T11:38:53.0000000+00:00' +- author: Errant + changes: + - {message: Nitrogen tank settings have been adjusted to avoid gas wastage, type: Tweak} + id: 4301 + time: '2023-07-21T19:02:39.0000000+00:00' +- author: JimGamemaster + changes: + - {message: Space Creatures can now float in space, type: Tweak} + id: 4302 + time: '2023-07-21T20:10:21.0000000+00:00' +- author: brainfood1183 + changes: + - {message: Strait Jackets can now be used to restrain individuals., type: Add} + id: 4303 + time: '2023-07-22T22:14:25.0000000+00:00' +- author: Emisse + changes: + - {message: Beds and medical beds now heal blunt and cold specifically instead of + brute and burn groups., type: Tweak} + id: 4304 + time: '2023-07-23T03:18:06.0000000+00:00' +- author: EmoGarbage404 + changes: + - {message: Midround anomaly spawns no longer have a high chance of spawning in + escape pods., type: Fix} + id: 4305 + time: '2023-07-23T03:57:13.0000000+00:00' +- author: FillerVK + changes: + - {message: Departure Terminal update., type: Tweak} + id: 4306 + time: '2023-07-23T05:32:04.0000000+00:00' +- author: Flareguy + changes: + - {message: Changed the roundstart traitor sound effect back to the old one., type: Tweak} + id: 4307 + time: '2023-07-23T05:53:01.0000000+00:00' diff --git a/Resources/Locale/en-US/cuffs/components/cuffable-component.ftl b/Resources/Locale/en-US/cuffs/components/cuffable-component.ftl index 52c416ce9d..d84ed3f781 100644 --- a/Resources/Locale/en-US/cuffs/components/cuffable-component.ftl +++ b/Resources/Locale/en-US/cuffs/components/cuffable-component.ftl @@ -1,17 +1,17 @@ cuffable-component-cannot-interact-message = You can't do that! -cuffable-component-cannot-remove-cuffs-too-far-message = You are too far away to remove the cuffs. +cuffable-component-cannot-remove-cuffs-too-far-message = You are too far away to remove the restraints. -cuffable-component-start-uncuffing-self = You start to painfully wriggle out of your cuffs. -cuffable-component-start-uncuffing-observer = {$user} starts uncuffing {$target}! -cuffable-component-start-uncuffing-target-message = You start uncuffing {$targetName}. -cuffable-component-start-uncuffing-by-other-message = {$otherName} starts uncuffing you! +cuffable-component-start-uncuffing-self = You start to painfully wriggle out of your restraints. +cuffable-component-start-uncuffing-observer = {$user} starts unrestraining {$target}! +cuffable-component-start-uncuffing-target-message = You start unrestraining {$targetName}. +cuffable-component-start-uncuffing-by-other-message = {$otherName} starts unrestraining you! -cuffable-component-remove-cuffs-success-message = You successfully remove the cuffs. -cuffable-component-remove-cuffs-by-other-success-message = {$otherName} uncuffs your hands. -cuffable-component-remove-cuffs-to-other-partial-success-message = You successfully remove the cuffs. {$cuffedHandCount} of {$otherName}'s hands remain cuffed. -cuffable-component-remove-cuffs-by-other-partial-success-message = {$otherName} removes your cuffs. {$cuffedHandCount} of your hands remain cuffed. -cuffable-component-remove-cuffs-partial-success-message = You successfully remove the cuffs. {$cuffedHandCount} of your hands remain cuffed. -cuffable-component-remove-cuffs-fail-message = You fail to remove the cuffs. +cuffable-component-remove-cuffs-success-message = You successfully remove the restraints. +cuffable-component-remove-cuffs-by-other-success-message = {$otherName} unrestrains your hands. +cuffable-component-remove-cuffs-to-other-partial-success-message = You successfully remove the restraints. {$cuffedHandCount} of {$otherName}'s hands remain restrained. +cuffable-component-remove-cuffs-by-other-partial-success-message = {$otherName} removes your restraints. {$cuffedHandCount} of your hands remain restrained. +cuffable-component-remove-cuffs-partial-success-message = You successfully remove the restraints. {$cuffedHandCount} of your hands remain restrained. +cuffable-component-remove-cuffs-fail-message = You fail to remove the restraints. -# UncuffVerb -uncuff-verb-get-data-text = Uncuff \ No newline at end of file +# UnrestrainVerb +uncuff-verb-get-data-text = Unrestrain diff --git a/Resources/Locale/en-US/cuffs/components/handcuff-component.ftl b/Resources/Locale/en-US/cuffs/components/handcuff-component.ftl index 4d74143d50..2d295b5d1b 100644 --- a/Resources/Locale/en-US/cuffs/components/handcuff-component.ftl +++ b/Resources/Locale/en-US/cuffs/components/handcuff-component.ftl @@ -1,17 +1,17 @@ -handcuff-component-target-self = You start cuffing yourself. -handcuff-component-cuffs-broken-error = The cuffs are broken! +handcuff-component-target-self = You start restraining yourself. +handcuff-component-cuffs-broken-error = The restraints are broken! handcuff-component-target-has-no-hands-error = {$targetName} has no hands! handcuff-component-target-has-no-free-hands-error = {$targetName} has no free hands! -handcuff-component-too-far-away-error = You are too far away to use the cuffs! -handcuff-component-start-cuffing-observer = {$user} starts cuffing {$target}! -handcuff-component-start-cuffing-target-message = You start cuffing {$targetName}. -handcuff-component-start-cuffing-by-other-message = {$otherName} starts cuffing you! -handcuff-component-cuff-observer-success-message = {$user} cuffs {$target}. -handcuff-component-cuff-other-success-message = You successfully cuff {$otherName}. -handcuff-component-cuff-by-other-success-message = You have been cuffed by {$otherName}! -handcuff-component-cuff-self-success-message = You cuff yourself. -handcuff-component-cuff-interrupt-message = You were interrupted while cuffing {$targetName}! -handcuff-component-cuff-interrupt-other-message = You interrupt {$otherName} while they are cuffing you! -handcuff-component-cuff-interrupt-self-message = You were interrupted while cuffing yourself. -handcuff-component-cuff-interrupt-buckled-message = You can't buckle while cuffed! -handcuff-component-cuff-interrupt-unbuckled-message = You can't unbuckle while cuffed! +handcuff-component-too-far-away-error = You are too far away to use the restraints! +handcuff-component-start-cuffing-observer = {$user} starts restraining {$target}! +handcuff-component-start-cuffing-target-message = You start restraining {$targetName}. +handcuff-component-start-cuffing-by-other-message = {$otherName} starts restraining you! +handcuff-component-cuff-observer-success-message = {$user} restrains {$target}. +handcuff-component-cuff-other-success-message = You successfully restrain {$otherName}. +handcuff-component-cuff-by-other-success-message = You have been restrained by {$otherName}! +handcuff-component-cuff-self-success-message = You restrain yourself. +handcuff-component-cuff-interrupt-message = You were interrupted while unrestraining {$targetName}! +handcuff-component-cuff-interrupt-other-message = You interrupt {$otherName} while they are restraining you! +handcuff-component-cuff-interrupt-self-message = You were interrupted while unrestraining yourself. +handcuff-component-cuff-interrupt-buckled-message = You can't buckle while restrained! +handcuff-component-cuff-interrupt-unbuckled-message = You can't unbuckle while restrained! diff --git a/Resources/Maps/Misc/terminal.yml b/Resources/Maps/Misc/terminal.yml index 262dbf5951..08be47e4bb 100644 --- a/Resources/Maps/Misc/terminal.yml +++ b/Resources/Maps/Misc/terminal.yml @@ -5,8 +5,8 @@ tilemap: 0: Space 10: FloorAsteroidSand 23: FloorDark + 32: FloorDarkPlastic 39: FloorGlass - 50: FloorLino 69: FloorSteel 79: FloorTechMaint 94: Lattice @@ -43,7 +43,7 @@ entities: tiles: AAAAAAAAAAAAAAAAAAAAAAAAAABfAAAAFwAAA0UAAAEXAAAACgAAABcAAAFFAAACFwAAA18AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAXwAAABcAAAJFAAACFwAAAAoAAAAXAAACRQAAAxcAAANfAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF8AAAAXAAAARQAAARcAAAMKAAAAFwAAAUUAAAAXAAAAXwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABfAAAAFwAAA0UAAAMXAAACCgAAABcAAANFAAACFwAAAV8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABfAAAAXwAAAF8AAABFAAAARQAAA0UAAAFFAAADRQAAAV8AAABfAAAAXwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAXwAAAF8AAABfAAAARQAAAUUAAAInAAAARQAAAkUAAAJfAAAAXwAAAF8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF8AAABfAAAAXwAAAEUAAABFAAAAJwAAAEUAAANFAAABXwAAAF8AAABfAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF8AAABFAAABRQAAACcAAABFAAABRQAAAV8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABfAAAARQAAAkUAAAAnAAAARQAAAkUAAABfAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAXwAAAEUAAAJFAAAAJwAAAEUAAANFAAADXwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF8AAABFAAABRQAAAkUAAABFAAAARQAAAl8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF8AAABfAAAAXwAAAEUAAAFFAAADRQAAA18AAABfAAAAXwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABfAAAARQAAAUUAAAJFAAACRQAAAUUAAABFAAADRQAAAl8AAAAAAAAAAAAAAF8AAABfAAAAXwAAAF8AAABfAAAAXwAAAEUAAAJFAAABRQAAAycAAABFAAADRQAAAEUAAAJfAAAAAAAAAAAAAABFAAABRQAAA0UAAANFAAAARQAAAEUAAABFAAADRQAAAEUAAAInAAAARQAAA0UAAAJFAAADXwAAAAAAAAAAAAAARQAAA0UAAANFAAABRQAAAEUAAABFAAADRQAAA0UAAABFAAABJwAAAEUAAABFAAAARQAAAl8AAAAAAAAAAAAAAA== -1,0: ind: -1,0 - tiles: AAAAAF8AAAAXAAACRQAAAUUAAAFFAAADRQAAAEUAAABFAAACRQAAAEUAAABFAAABRQAAAEUAAAJFAAACRQAAAwAAAABfAAAAFwAAAxcAAAMXAAACFwAAAxcAAAIXAAABFwAAAl8AAABFAAADRQAAAEUAAABFAAADRQAAA0UAAAAAAAAAXwAAAF8AAAAyAAAAMgAAADIAAAAyAAAAMgAAAF8AAABfAAAAXwAAAF8AAABfAAAAXwAAAF8AAABfAAAAAAAAAAAAAABfAAAAMgAAADIAAAAyAAAAMgAAADIAAABfAAAAXgAAAF8AAABfAAAAXwAAAF8AAABfAAAAXwAAAAAAAAAAAAAAXwAAAF8AAAAyAAAAMgAAADIAAABfAAAAXwAAAF4AAABfAAAAXwAAAF8AAABfAAAAXwAAAF8AAAAAAAAAAAAAAAAAAABfAAAAXwAAAF8AAABfAAAAXwAAAAAAAABeAAAAXwAAAF8AAABfAAAAXwAAAF8AAABfAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAXgAAAF8AAABfAAAAXwAAAF8AAABfAAAAXwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA== + tiles: AAAAAF8AAAAXAAACRQAAAUUAAAFFAAADRQAAAEUAAABFAAACRQAAAEUAAABFAAABRQAAAEUAAAJFAAACRQAAAwAAAABfAAAAFwAAAxcAAAMXAAACFwAAAxcAAAIXAAABFwAAAl8AAABFAAADRQAAAEUAAABFAAADRQAAA0UAAAAAAAAAXwAAAF8AAAAgAAAAIAAAACAAAAAgAAAAIAAAAF8AAABfAAAAXwAAAF8AAABfAAAAXwAAAF8AAABfAAAAAAAAAAAAAAAgAAAAIAAAACAAAAAgAAAAIAAAACAAAAAgAAAAXgAAAF8AAABfAAAAXwAAAF8AAABfAAAAXwAAAAAAAAAAAAAAIAAAACAAAAAgAAAAIAAAACAAAAAgAAAAIAAAAF4AAABfAAAAXwAAAF8AAABfAAAAXwAAAF8AAAAAAAAAAAAAAAAAAAAgAAAAIAAAACAAAAAgAAAAIAAAAAAAAABeAAAAXwAAAF8AAABfAAAAXwAAAF8AAABfAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAXgAAAF8AAABfAAAAXwAAAF8AAABfAAAAXwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA== 0,-2: ind: 0,-2 tiles: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABfAAAAXwAAAF8AAABfAAAAXwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABfAAAAXwAAAEUAAAJFAAADRQAAAV8AAABfAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAXwAAAEUAAANFAAAAJwAAAEUAAANFAAAAXwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABfAAAAXwAAAF8AAABFAAACRQAAAScAAABFAAADRQAAA18AAABfAAAAXwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAXwAAAF8AAABfAAAARQAAA0UAAAMnAAAARQAAA0UAAAFfAAAAXwAAAF8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF8AAABfAAAAXwAAAEUAAAFFAAABRQAAA0UAAAFFAAACXwAAAF8AAABfAAAAAAAAAA== @@ -127,22 +127,22 @@ entities: color: '#FFFFFFFF' id: BrickTileSteelEndN decals: - 300: -11,-1 - 311: -11,-7 - 314: -11,-18 - 315: 9,2 - 316: 9,-7 - 317: 9,-18 + 279: -11,-1 + 290: -11,-7 + 293: -11,-18 + 294: 9,2 + 295: 9,-7 + 296: 9,-18 - node: color: '#FFFFFFFF' id: BrickTileSteelEndS decals: - 299: -11,-3 - 312: -11,-11 - 313: -11,-20 - 318: 9,-20 - 319: 9,-11 - 320: 9,-3 + 278: -11,-3 + 291: -11,-11 + 292: -11,-20 + 297: 9,-20 + 298: 9,-11 + 299: 9,-3 - node: color: '#FFFFFFFF' id: BrickTileSteelLineE @@ -163,19 +163,19 @@ entities: 163: 10,-15 164: 10,-14 165: 10,-13 - 301: -11,-2 - 307: -11,-19 - 308: -11,-10 - 309: -11,-9 - 310: -11,-8 - 321: 9,-2 - 322: 9,-1 - 323: 9,0 - 324: 9,1 - 325: 9,-10 - 326: 9,-9 - 327: 9,-8 - 328: 9,-19 + 280: -11,-2 + 286: -11,-19 + 287: -11,-10 + 288: -11,-9 + 289: -11,-8 + 300: 9,-2 + 301: 9,-1 + 302: 9,0 + 303: 9,1 + 304: 9,-10 + 305: 9,-9 + 306: 9,-8 + 307: 9,-19 - node: color: '#FFFFFFFF' id: BrickTileSteelLineN @@ -212,19 +212,19 @@ entities: 171: 8,-15 172: 8,-14 173: 8,-13 - 302: -11,-2 - 303: -11,-10 - 304: -11,-9 - 305: -11,-8 - 306: -11,-19 - 329: 9,-19 - 330: 9,-10 - 331: 9,-9 - 332: 9,-8 - 333: 9,-2 - 334: 9,-1 - 335: 9,0 - 336: 9,1 + 281: -11,-2 + 282: -11,-10 + 283: -11,-9 + 284: -11,-8 + 285: -11,-19 + 308: 9,-19 + 309: 9,-10 + 310: 9,-9 + 311: 9,-8 + 312: 9,-2 + 313: 9,-1 + 314: 9,0 + 315: 9,1 - node: color: '#FFFFFFFF' id: BushATwo @@ -323,27 +323,6 @@ entities: id: Grassb5 decals: 2: 8.998546,-14.854745 - - node: - color: '#9FED5850' - id: HalfTileOverlayGreyscale - decals: - 242: 12,-2 - 243: 11,-2 - 244: 12,1 - 245: 11,1 - 246: 7,1 - 247: 6,1 - 256: 9,4 - - node: - color: '#9FED5850' - id: HalfTileOverlayGreyscale180 - decals: - 238: 12,-4 - 239: 11,-4 - 240: 7,-4 - 241: 6,-4 - 248: 12,-1 - 249: 11,-1 - node: color: '#D4D4D496' id: HalfTileOverlayGreyscale180 @@ -354,26 +333,26 @@ entities: color: '#334E6DC8' id: HalfTileOverlayGreyscale270 decals: - 263: -2,-2 - 264: -2,-1 - 265: -2,0 - 266: -2,1 - 267: 1,-2 - 268: 1,-1 - 269: 1,0 - 270: 1,1 + 242: -2,-2 + 243: -2,-1 + 244: -2,0 + 245: -2,1 + 246: 1,-2 + 247: 1,-1 + 248: 1,0 + 249: 1,1 - node: color: '#334E6DC8' id: HalfTileOverlayGreyscale90 decals: - 259: 0,-2 - 260: 0,-1 - 261: 0,0 - 262: 0,1 - 271: -3,-2 - 272: -3,-1 - 273: -3,0 - 274: -3,1 + 238: 0,-2 + 239: 0,-1 + 240: 0,0 + 241: 0,1 + 250: -3,-2 + 251: -3,-1 + 252: -3,0 + 253: -3,1 - node: color: '#334E6DC8' id: QuarterTileOverlayGreyscale @@ -388,12 +367,12 @@ entities: 191: -13,-2 192: -13,-3 193: -13,-4 - 283: -1,0 - 284: 0,-1 - 285: -1,-1 - 286: 0,-2 - 292: 2,-2 - 298: -4,1 + 262: -1,0 + 263: 0,-1 + 264: -1,-1 + 265: 0,-2 + 271: 2,-2 + 277: -4,1 - node: color: '#52B4E950' id: QuarterTileOverlayGreyscale @@ -408,11 +387,6 @@ entities: 102: -13,-19 103: -13,-18 104: -13,-17 - - node: - color: '#9FED5850' - id: QuarterTileOverlayGreyscale - decals: - 257: 8,3 - node: color: '#D4D4D496' id: QuarterTileOverlayGreyscale @@ -435,12 +409,12 @@ entities: color: '#334E6DC8' id: QuarterTileOverlayGreyscale180 decals: - 279: -1,-1 - 280: -2,0 - 281: -1,0 - 282: -2,1 - 290: 2,-2 - 296: -4,1 + 258: -1,-1 + 259: -2,0 + 260: -1,0 + 261: -2,1 + 269: 2,-2 + 275: -4,1 - node: color: '#52B4E950' id: QuarterTileOverlayGreyscale180 @@ -483,12 +457,12 @@ entities: color: '#334E6DC8' id: QuarterTileOverlayGreyscale270 decals: - 277: -1,0 - 278: 0,-1 - 287: 2,-2 - 288: 2,-1 - 289: 3,-2 - 297: -4,1 + 256: -1,0 + 257: 0,-1 + 266: 2,-2 + 267: 2,-1 + 268: 3,-2 + 276: -4,1 - node: color: '#52B4E950' id: QuarterTileOverlayGreyscale270 @@ -531,12 +505,12 @@ entities: color: '#334E6DC8' id: QuarterTileOverlayGreyscale90 decals: - 275: -2,0 - 276: -1,-1 - 291: 2,-2 - 293: -4,1 - 294: -4,0 - 295: -5,1 + 254: -2,0 + 255: -1,-1 + 270: 2,-2 + 272: -4,1 + 273: -4,0 + 274: -5,1 - node: color: '#52B4E950' id: QuarterTileOverlayGreyscale90 @@ -551,11 +525,6 @@ entities: 111: -9,-19 112: -9,-18 113: -9,-17 - - node: - color: '#9FED5850' - id: QuarterTileOverlayGreyscale90 - decals: - 258: 10,3 - node: color: '#D4D4D496' id: QuarterTileOverlayGreyscale90 @@ -579,28 +548,6 @@ entities: id: StandClear decals: 237: 3,4 - - node: - color: '#9FED5850' - id: ThreeQuarterTileOverlayGreyscale - decals: - 253: 7,3 - 254: 8,4 - - node: - color: '#9FED5850' - id: ThreeQuarterTileOverlayGreyscale180 - decals: - 252: 11,2 - - node: - color: '#9FED5850' - id: ThreeQuarterTileOverlayGreyscale270 - decals: - 250: 7,2 - - node: - color: '#9FED5850' - id: ThreeQuarterTileOverlayGreyscale90 - decals: - 251: 11,3 - 255: 10,4 - node: color: '#FFFFFFFF' id: WarnBox @@ -766,6 +713,13 @@ entities: - type: RadiationGridResistance - type: SpreaderGrid - type: GridPathfinding +- proto: AirlockEngineeringLocked + entities: + - uid: 726 + components: + - pos: 2.5,2.5 + parent: 818 + type: Transform - proto: AirlockExternalEngineeringLocked entities: - uid: 408 @@ -1061,6 +1015,38 @@ entities: pos: 4.5,4.5 parent: 818 type: Transform +- proto: BannerEngineering + entities: + - uid: 716 + components: + - pos: -4.5,3.5 + parent: 818 + type: Transform + - uid: 725 + components: + - pos: 3.5,3.5 + parent: 818 + type: Transform +- proto: BannerNanotrasen + entities: + - uid: 803 + components: + - pos: -5.5,1.5 + parent: 818 + type: Transform + - uid: 804 + components: + - pos: 4.5,1.5 + parent: 818 + type: Transform +- proto: BarSign + entities: + - uid: 762 + components: + - rot: 3.141592653589793 rad + pos: -10.5,5.5 + parent: 818 + type: Transform - proto: BlockGameArcade entities: - uid: 727 @@ -1075,11 +1061,31 @@ entities: pos: -13.5,0.5 parent: 818 type: Transform -- proto: BoxFolderYellow +- proto: BookBartendersManual entities: - - uid: 761 + - uid: 190 components: - - pos: 12.452511,-2.444745 + - rot: 3.141592653589793 rad + pos: -12.7162,2.6149585 + parent: 818 + type: Transform +- proto: BookshelfFilled + entities: + - uid: 442 + components: + - pos: 7.5,3.5 + parent: 818 + type: Transform + - uid: 752 + components: + - pos: 11.5,3.5 + parent: 818 + type: Transform +- proto: BoozeDispenser + entities: + - uid: 710 + components: + - pos: -11.5,4.5 parent: 818 type: Transform - proto: CableApcExtension @@ -2307,38 +2313,6 @@ entities: pos: -3.5,4.5 parent: 818 type: Transform -- proto: CarpetGreen - entities: - - uid: 707 - components: - - pos: -11.5,2.5 - parent: 818 - type: Transform - - uid: 708 - components: - - pos: -11.5,3.5 - parent: 818 - type: Transform - - uid: 714 - components: - - pos: -10.5,2.5 - parent: 818 - type: Transform - - uid: 715 - components: - - pos: -10.5,3.5 - parent: 818 - type: Transform - - uid: 716 - components: - - pos: -9.5,2.5 - parent: 818 - type: Transform - - uid: 717 - components: - - pos: -9.5,3.5 - parent: 818 - type: Transform - proto: Catwalk entities: - uid: 563 @@ -2620,89 +2594,47 @@ entities: pos: 12.5,-12.5 parent: 818 type: Transform - - uid: 735 +- proto: ChairOfficeDark + entities: + - uid: 591 components: - - rot: -1.5707963267948966 rad - pos: 10.5,4.5 + - rot: 3.141592653589793 rad + pos: 9.5,3.5 parent: 818 type: Transform - - uid: 736 +- proto: ChairWood + entities: + - uid: 177 + components: + - rot: 3.141592653589793 rad + pos: 9.5,-1.5 + parent: 818 + type: Transform + - uid: 704 + components: + - pos: 10.5,1.5 + parent: 818 + type: Transform + - uid: 735 components: - rot: 1.5707963267948966 rad - pos: 8.5,4.5 + pos: 7.5,0.5 parent: 818 type: Transform - uid: 745 components: - - pos: 12.5,1.5 + - pos: 8.5,1.5 parent: 818 type: Transform - uid: 746 components: - - pos: 11.5,1.5 + - pos: 9.5,1.5 parent: 818 type: Transform - uid: 747 components: - - rot: 3.141592653589793 rad - pos: 12.5,-0.5 - parent: 818 - type: Transform - - uid: 748 - components: - - rot: 3.141592653589793 rad - pos: 11.5,-0.5 - parent: 818 - type: Transform - - uid: 749 - components: - - pos: 12.5,-1.5 - parent: 818 - type: Transform - - uid: 750 - components: - - pos: 11.5,-1.5 - parent: 818 - type: Transform - - uid: 751 - components: - - rot: 3.141592653589793 rad - pos: 12.5,-3.5 - parent: 818 - type: Transform - - uid: 752 - components: - - rot: 3.141592653589793 rad - pos: 11.5,-3.5 - parent: 818 - type: Transform - - uid: 753 - components: - - pos: 6.5,1.5 - parent: 818 - type: Transform - - uid: 754 - components: - - pos: 7.5,1.5 - parent: 818 - type: Transform - - uid: 755 - components: - - rot: 3.141592653589793 rad - pos: 6.5,-3.5 - parent: 818 - type: Transform - - uid: 756 - components: - - rot: 3.141592653589793 rad - pos: 7.5,-3.5 - parent: 818 - type: Transform -- proto: ChessBoard - entities: - - uid: 737 - components: - - pos: 9.521464,4.5636826 + - rot: -1.5707963267948966 rad + pos: 11.5,0.5 parent: 818 type: Transform - proto: ClosetWallEmergencyFilledRandom @@ -2721,27 +2653,32 @@ entities: type: Transform - proto: ComfyChair entities: - - uid: 711 + - uid: 595 components: - - rot: -1.5707963267948966 rad - pos: -8.5,3.5 + - rot: 3.141592653589793 rad + pos: 6.5,-3.5 parent: 818 type: Transform - - uid: 712 + - uid: 718 components: - - rot: 1.5707963267948966 rad - pos: -12.5,2.5 + - pos: 12.5,-1.5 parent: 818 type: Transform - - uid: 713 + - uid: 749 components: - - rot: 1.5707963267948966 rad - pos: -12.5,3.5 + - pos: 12.5,1.5 parent: 818 type: Transform - - uid: 722 + - uid: 759 components: - - pos: -10.5,4.5 + - rot: 3.141592653589793 rad + pos: 12.5,-0.5 + parent: 818 + type: Transform + - uid: 760 + components: + - rot: 3.141592653589793 rad + pos: 12.5,-3.5 parent: 818 type: Transform - proto: FirelockEdge @@ -3115,11 +3052,6 @@ entities: - pos: 3.5,-2.5 parent: 818 type: Transform - - uid: 181 - components: - - pos: -0.5,-2.5 - parent: 818 - type: Transform - uid: 183 components: - pos: -3.5,-2.5 @@ -3130,11 +3062,6 @@ entities: - pos: 4.5,-2.5 parent: 818 type: Transform - - uid: 188 - components: - - pos: 0.5,-2.5 - parent: 818 - type: Transform - uid: 191 components: - pos: -5.5,-2.5 @@ -3150,11 +3077,6 @@ entities: - pos: 2.5,-2.5 parent: 818 type: Transform - - uid: 230 - components: - - pos: -1.5,-2.5 - parent: 818 - type: Transform - uid: 233 components: - pos: -8.5,-4.5 @@ -3345,43 +3267,17 @@ entities: - pos: -3.5,2.5 parent: 818 type: Transform - - uid: 587 - components: - - pos: -4.5,2.5 - parent: 818 - type: Transform - - uid: 591 - components: - - pos: 3.5,2.5 - parent: 818 - type: Transform - uid: 594 components: - pos: 0.5,2.5 parent: 818 type: Transform - - uid: 725 - components: - - pos: 2.5,2.5 - parent: 818 - type: Transform - - uid: 726 - components: - - pos: 1.5,2.5 - parent: 818 - type: Transform -- proto: LampGold +- proto: PaperBin10 entities: - - uid: 719 + - uid: 737 components: - - pos: -9.496585,4.914251 - parent: 818 - type: Transform -- proto: Pen - entities: - - uid: 762 - components: - - pos: 11.5468645,0.58650494 + - rot: 3.141592653589793 rad + pos: 8.5,4.5 parent: 818 type: Transform - proto: PosterLegitNanotrasenLogo @@ -3448,6 +3344,18 @@ entities: - pos: -7.5,-3.5 parent: 818 type: Transform +- proto: PottedPlantRandomPlastic + entities: + - uid: 708 + components: + - pos: -13.5,1.5 + parent: 818 + type: Transform + - uid: 755 + components: + - pos: -13.5,-3.5 + parent: 818 + type: Transform - proto: Poweredlight entities: - uid: 195 @@ -3466,6 +3374,20 @@ entities: type: Transform - enabled: False type: AmbientSound +- proto: RandomDrinkBottle + entities: + - uid: 709 + components: + - pos: -10.5,2.5 + parent: 818 + type: Transform +- proto: RandomDrinkGlass + entities: + - uid: 754 + components: + - pos: -11.5,2.5 + parent: 818 + type: Transform - proto: ReinforcedWindow entities: - uid: 19 @@ -3740,11 +3662,6 @@ entities: - pos: 13.5,-14.5 parent: 818 type: Transform - - uid: 177 - components: - - pos: 0.5,-2.5 - parent: 818 - type: Transform - uid: 185 components: - pos: -5.5,-2.5 @@ -3755,11 +3672,6 @@ entities: - pos: 2.5,-2.5 parent: 818 type: Transform - - uid: 190 - components: - - pos: -1.5,-2.5 - parent: 818 - type: Transform - uid: 192 components: - pos: 4.5,-2.5 @@ -3950,16 +3862,6 @@ entities: - pos: 12.5,3.5 parent: 818 type: Transform - - uid: 342 - components: - - pos: -0.5,-2.5 - parent: 818 - type: Transform - - uid: 575 - components: - - pos: -4.5,2.5 - parent: 818 - type: Transform - uid: 576 components: - pos: -3.5,2.5 @@ -3985,19 +3887,39 @@ entities: - pos: 0.5,2.5 parent: 818 type: Transform - - uid: 595 +- proto: SignNanotrasen1 + entities: + - uid: 721 components: - - pos: 1.5,2.5 + - pos: -2.5,-2.5 parent: 818 type: Transform - - uid: 596 +- proto: SignNanotrasen2 + entities: + - uid: 722 components: - - pos: 3.5,2.5 + - pos: -1.5,-2.5 parent: 818 type: Transform - - uid: 734 +- proto: SignNanotrasen3 + entities: + - uid: 719 components: - - pos: 2.5,2.5 + - pos: -0.5,-2.5 + parent: 818 + type: Transform +- proto: SignNanotrasen4 + entities: + - uid: 801 + components: + - pos: 0.5,-2.5 + parent: 818 + type: Transform +- proto: SignNanotrasen5 + entities: + - uid: 802 + components: + - pos: 1.5,-2.5 parent: 818 type: Transform - proto: SignNosmoking @@ -4089,6 +4011,13 @@ entities: - pos: -2.5,4.5 parent: 818 type: Transform +- proto: soda_dispenser + entities: + - uid: 795 + components: + - pos: -10.5,4.5 + parent: 818 + type: Transform - proto: SpaceVillainArcadeFilled entities: - uid: 731 @@ -4265,96 +4194,6 @@ entities: - pos: 12.5,-12.5 parent: 818 type: Transform - - uid: 795 - components: - - pos: 12.5,-1.5 - parent: 818 - type: Transform - - uid: 796 - components: - - pos: 11.5,-1.5 - parent: 818 - type: Transform - - uid: 797 - components: - - pos: 11.5,-0.5 - parent: 818 - type: Transform - - uid: 798 - components: - - pos: 12.5,-0.5 - parent: 818 - type: Transform - - uid: 799 - components: - - pos: 12.5,-3.5 - parent: 818 - type: Transform - - uid: 800 - components: - - pos: 11.5,-3.5 - parent: 818 - type: Transform - - uid: 801 - components: - - pos: 7.5,-3.5 - parent: 818 - type: Transform - - uid: 802 - components: - - pos: 6.5,-3.5 - parent: 818 - type: Transform - - uid: 803 - components: - - pos: 6.5,1.5 - parent: 818 - type: Transform - - uid: 804 - components: - - pos: 7.5,1.5 - parent: 818 - type: Transform - - uid: 805 - components: - - pos: 11.5,1.5 - parent: 818 - type: Transform - - uid: 806 - components: - - pos: 12.5,1.5 - parent: 818 - type: Transform - - uid: 807 - components: - - pos: 10.5,4.5 - parent: 818 - type: Transform - - uid: 808 - components: - - pos: -8.5,3.5 - parent: 818 - type: Transform - - uid: 809 - components: - - pos: 8.5,4.5 - parent: 818 - type: Transform - - uid: 810 - components: - - pos: -10.5,4.5 - parent: 818 - type: Transform - - uid: 811 - components: - - pos: -12.5,3.5 - parent: 818 - type: Transform - - uid: 812 - components: - - pos: -12.5,2.5 - parent: 818 - type: Transform - uid: 813 components: - pos: -12.5,-2.5 @@ -4425,6 +4264,32 @@ entities: pos: -12.5,0.5 parent: 818 type: Transform +- proto: StoolBar + entities: + - uid: 230 + components: + - rot: 3.141592653589793 rad + pos: -9.5,1.5 + parent: 818 + type: Transform + - uid: 342 + components: + - rot: 3.141592653589793 rad + pos: -11.5,1.5 + parent: 818 + type: Transform + - uid: 433 + components: + - rot: 3.141592653589793 rad + pos: -10.5,1.5 + parent: 818 + type: Transform + - uid: 717 + components: + - rot: 3.141592653589793 rad + pos: -12.5,1.5 + parent: 818 + type: Transform - proto: SubstationBasic entities: - uid: 215 @@ -4432,53 +4297,127 @@ entities: - pos: -0.5,4.5 parent: 818 type: Transform -- proto: Table +- proto: TableCarpet entities: - - uid: 739 + - uid: 596 components: - - pos: 9.5,4.5 + - rot: 3.141592653589793 rad + pos: 10.5,0.5 + parent: 818 + type: Transform + - uid: 640 + components: + - rot: 3.141592653589793 rad + pos: 10.5,-0.5 + parent: 818 + type: Transform + - uid: 703 + components: + - rot: 3.141592653589793 rad + pos: 9.5,-0.5 + parent: 818 + type: Transform + - uid: 736 + components: + - rot: 3.141592653589793 rad + pos: 8.5,-0.5 parent: 818 type: Transform - uid: 757 components: - - pos: 11.5,-2.5 + - rot: 3.141592653589793 rad + pos: 9.5,0.5 parent: 818 type: Transform - uid: 758 components: - - pos: 12.5,-2.5 + - rot: 3.141592653589793 rad + pos: 8.5,0.5 parent: 818 type: Transform - - uid: 759 +- proto: TableReinforced + entities: + - uid: 707 + components: + - rot: -1.5707963267948966 rad + pos: -10.5,4.5 + parent: 818 + type: Transform + - uid: 751 + components: + - rot: -1.5707963267948966 rad + pos: -11.5,4.5 + parent: 818 + type: Transform + - uid: 761 + components: + - rot: -1.5707963267948966 rad + pos: -9.5,4.5 + parent: 818 + type: Transform + - uid: 796 + components: + - rot: -1.5707963267948966 rad + pos: -10.5,2.5 + parent: 818 + type: Transform + - uid: 797 + components: + - rot: -1.5707963267948966 rad + pos: -12.5,2.5 + parent: 818 + type: Transform + - uid: 798 + components: + - rot: -1.5707963267948966 rad + pos: -11.5,2.5 + parent: 818 + type: Transform + - uid: 799 + components: + - rot: -1.5707963267948966 rad + pos: -9.5,2.5 + parent: 818 + type: Transform +- proto: TableWood + entities: + - uid: 441 components: - pos: 12.5,0.5 parent: 818 type: Transform - - uid: 760 + - uid: 575 components: - - pos: 11.5,0.5 + - pos: 6.5,-2.5 parent: 818 type: Transform -- proto: TableCarpet + - uid: 587 + components: + - pos: 12.5,-2.5 + parent: 818 + type: Transform + - uid: 706 + components: + - pos: 9.5,4.5 + parent: 818 + type: Transform + - uid: 750 + components: + - pos: 10.5,4.5 + parent: 818 + type: Transform + - uid: 756 + components: + - pos: 8.5,4.5 + parent: 818 + type: Transform +- proto: VendingMachineBooze entities: - - uid: 710 - components: - - rot: -1.5707963267948966 rad - pos: -8.5,2.5 - parent: 818 - type: Transform - - uid: 718 - components: - - pos: -9.5,4.5 - parent: 818 - type: Transform -- proto: VendingMachineCigs - entities: - - uid: 709 + - uid: 753 components: - flags: SessionSpecific type: MetaData - - pos: -11.5,4.5 + - pos: -9.5,4.5 parent: 818 type: Transform - proto: VendingMachineCola @@ -4490,6 +4429,15 @@ entities: - pos: -12.5,-5.5 parent: 818 type: Transform +- proto: VendingMachineGames + entities: + - uid: 748 + components: + - flags: SessionSpecific + type: MetaData + - pos: 6.5,1.5 + parent: 818 + type: Transform - proto: VendingMachineSnack entities: - uid: 637 @@ -4499,6 +4447,15 @@ entities: - pos: -12.5,-6.5 parent: 818 type: Transform +- proto: VendingMachineSnackGreen + entities: + - uid: 800 + components: + - flags: SessionSpecific + type: MetaData + - pos: -7.5,1.5 + parent: 818 + type: Transform - proto: WallRiveted entities: - uid: 10 @@ -5059,6 +5016,36 @@ entities: - pos: 1.5,6.5 parent: 818 type: Transform + - uid: 711 + components: + - pos: -1.5,-2.5 + parent: 818 + type: Transform + - uid: 712 + components: + - pos: -0.5,-2.5 + parent: 818 + type: Transform + - uid: 713 + components: + - pos: 0.5,-2.5 + parent: 818 + type: Transform + - uid: 714 + components: + - pos: 3.5,2.5 + parent: 818 + type: Transform + - uid: 715 + components: + - pos: -4.5,2.5 + parent: 818 + type: Transform + - uid: 734 + components: + - pos: 1.5,2.5 + parent: 818 + type: Transform - proto: WarpPoint entities: - uid: 638 @@ -5068,16 +5055,22 @@ entities: type: Transform - location: Terminal type: WarpPoint -- proto: Windoor +- proto: WindoorSecure entities: - - uid: 721 + - uid: 188 components: - rot: 3.141592653589793 rad - pos: -10.5,1.5 + pos: -8.5,2.5 parent: 818 type: Transform - proto: WindowReinforcedDirectional entities: + - uid: 181 + components: + - rot: 1.5707963267948966 rad + pos: -9.5,2.5 + parent: 818 + type: Transform - uid: 659 components: - pos: 9.5,-15.5 @@ -5240,28 +5233,4 @@ entities: pos: 10.5,-16.5 parent: 818 type: Transform - - uid: 703 - components: - - rot: 3.141592653589793 rad - pos: -8.5,1.5 - parent: 818 - type: Transform - - uid: 704 - components: - - rot: 3.141592653589793 rad - pos: -9.5,1.5 - parent: 818 - type: Transform - - uid: 705 - components: - - rot: 3.141592653589793 rad - pos: -11.5,1.5 - parent: 818 - type: Transform - - uid: 706 - components: - - rot: 3.141592653589793 rad - pos: -12.5,1.5 - parent: 818 - type: Transform ... diff --git a/Resources/Prototypes/Catalog/Fills/Items/gas_tanks.yml b/Resources/Prototypes/Catalog/Fills/Items/gas_tanks.yml index fe2d1911c1..3be38d7074 100644 --- a/Resources/Prototypes/Catalog/Fills/Items/gas_tanks.yml +++ b/Resources/Prototypes/Catalog/Fills/Items/gas_tanks.yml @@ -87,7 +87,7 @@ name: nitrogen tank components: - type: GasTank - outputPressure: 101.325 + outputPressure: 21.27825 air: volume: 15 moles: diff --git a/Resources/Prototypes/Catalog/Fills/Lockers/security.yml b/Resources/Prototypes/Catalog/Fills/Lockers/security.yml index 1d60469fae..42d74c089f 100644 --- a/Resources/Prototypes/Catalog/Fills/Lockers/security.yml +++ b/Resources/Prototypes/Catalog/Fills/Lockers/security.yml @@ -128,7 +128,7 @@ - id: WeaponRevolverInspector - id: DrinkDetFlask - id: SpeedLoaderMagnum - - id: ForensicGloves + - id: ClothingHandsGlovesForensic - type: entity id: ClosetBombFilled diff --git a/Resources/Prototypes/Entities/Clothing/Hands/gloves.yml b/Resources/Prototypes/Entities/Clothing/Hands/gloves.yml index 66b857fc5b..6601fb9bed 100644 --- a/Resources/Prototypes/Entities/Clothing/Hands/gloves.yml +++ b/Resources/Prototypes/Entities/Clothing/Hands/gloves.yml @@ -343,7 +343,7 @@ - type: entity parent: ClothingHandsBase - id: ForensicGloves + id: ClothingHandsGlovesForensic name: forensic gloves description: Do not leave fibers or fingerprints. If you work without them, you're A TERRIBLE DETECTIVE. components: @@ -352,4 +352,3 @@ - type: Clothing sprite: Clothing/Hands/Gloves/forensic.rsi - type: FingerprintMask - diff --git a/Resources/Prototypes/Entities/Clothing/OuterClothing/misc.yml b/Resources/Prototypes/Entities/Clothing/OuterClothing/misc.yml index ab0020b1aa..3f45bd4e8e 100644 --- a/Resources/Prototypes/Entities/Clothing/OuterClothing/misc.yml +++ b/Resources/Prototypes/Entities/Clothing/OuterClothing/misc.yml @@ -145,17 +145,6 @@ - type: Clothing sprite: Clothing/OuterClothing/Misc/santa.rsi -- type: entity - parent: ClothingOuterBase - id: ClothingOuterStraightjacket - name: straight jacket - description: A straight jacket. - components: - - type: Sprite - sprite: Clothing/OuterClothing/Misc/straight_jacket.rsi - - type: Clothing - sprite: Clothing/OuterClothing/Misc/straight_jacket.rsi - # Is this wizard wearing a fanny pack??? - type: entity parent: ClothingOuterBase diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/space.yml b/Resources/Prototypes/Entities/Mobs/NPCs/space.yml index 7d86433123..c53770f583 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/space.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/space.yml @@ -36,6 +36,7 @@ 150: Dead - type: Stamina excess: 150 + - type: MovementAlwaysTouching - type: Bloodstream bloodMaxVolume: 300 bloodReagent: Cryoxadone diff --git a/Resources/Prototypes/Entities/Mobs/Species/base.yml b/Resources/Prototypes/Entities/Mobs/Species/base.yml index 63db855e88..b35f2d7968 100644 --- a/Resources/Prototypes/Entities/Mobs/Species/base.yml +++ b/Resources/Prototypes/Entities/Mobs/Species/base.yml @@ -120,11 +120,6 @@ - map: ["enum.HumanoidVisualLayers.RFoot"] - map: ["enum.HumanoidVisualLayers.LHand"] - map: ["enum.HumanoidVisualLayers.RHand"] - - map: ["enum.HumanoidVisualLayers.Handcuffs"] - color: "#ffffff" - sprite: Objects/Misc/handcuffs.rsi - state: body-overlay-2 - visible: false - map: [ "id" ] - map: [ "gloves" ] - map: [ "shoes" ] @@ -143,6 +138,11 @@ - map: [ "head" ] - map: [ "pocket1" ] - map: [ "pocket2" ] + - map: ["enum.HumanoidVisualLayers.Handcuffs"] + color: "#ffffff" + sprite: Objects/Misc/handcuffs.rsi + state: body-overlay-2 + visible: false - map: [ "clownedon" ] # Dynamically generated sprite: "Effects/creampie.rsi" state: "creampie_human" diff --git a/Resources/Prototypes/Entities/Objects/Misc/handcuffs.yml b/Resources/Prototypes/Entities/Objects/Misc/handcuffs.yml index b21f47cb60..4d0aeba0d5 100644 --- a/Resources/Prototypes/Entities/Objects/Misc/handcuffs.yml +++ b/Resources/Prototypes/Entities/Objects/Misc/handcuffs.yml @@ -117,3 +117,24 @@ sprite: Objects/Misc/cablecuffs.rsi state: cuff-broken color: forestgreen + +- type: entity + parent: Handcuffs + id: ClothingOuterStraightjacket + name: straitjacket + description: Used to restrain those who may cause harm to themselves or others. + components: + - type: Item + size: 20 + - type: Handcuff + cuffedRSI: Clothing/OuterClothing/Misc/straight_jacket.rsi + breakoutTime: 100 + damageOnResist: + types: + Blunt: 0 + cuffTime: 10 + uncuffTime: 10 + stunBonus: 4 + - type: Sprite + sprite: Clothing/OuterClothing/Misc/straight_jacket.rsi + state: icon diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Launchers/launchers.yml b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Launchers/launchers.yml index ea102509fe..4be8f44de1 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Launchers/launchers.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Launchers/launchers.yml @@ -33,6 +33,7 @@ map: ["enum.GunVisualLayers.Base"] - type: Clothing sprite: Objects/Weapons/Guns/Launchers/china_lake.rsi + - type: AmmoCounter - type: Gun fireRate: 1 selectedMode: SemiAuto diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Shotguns/shotguns.yml b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Shotguns/shotguns.yml index 3dd896f99b..36a058ef86 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Shotguns/shotguns.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Shotguns/shotguns.yml @@ -66,6 +66,7 @@ slots: - Back - suitStorage + - type: AmmoCounter - type: Gun fireRate: 2 selectedMode: FullAuto diff --git a/Resources/Prototypes/Entities/Structures/Furniture/beds.yml b/Resources/Prototypes/Entities/Structures/Furniture/beds.yml index 3382a2e0ab..1d37ada25e 100644 --- a/Resources/Prototypes/Entities/Structures/Furniture/beds.yml +++ b/Resources/Prototypes/Entities/Structures/Furniture/beds.yml @@ -6,11 +6,9 @@ components: - type: HealOnBuckle damage: - groups: - Brute: -0.2 ## 0.1 per - Burn: -0.2 types: Poison: -0.1 + Blunt: -0.1 - type: Physics bodyType: Static - type: Fixtures @@ -70,11 +68,10 @@ state: bed-MED - type: HealOnBuckle damage: - groups: - Brute: -0.4 ## 0.2 per - Burn: -0.4 types: Poison: -0.2 + Cold: -0.4 + Blunt: -0.2 - type: Construction graph: bed node: medicalbed diff --git a/Resources/Textures/Clothing/OuterClothing/Misc/straight_jacket.rsi/equipped-OUTERCLOTHING.png b/Resources/Textures/Clothing/OuterClothing/Misc/straight_jacket.rsi/body-overlay-2.png similarity index 100% rename from Resources/Textures/Clothing/OuterClothing/Misc/straight_jacket.rsi/equipped-OUTERCLOTHING.png rename to Resources/Textures/Clothing/OuterClothing/Misc/straight_jacket.rsi/body-overlay-2.png diff --git a/Resources/Textures/Clothing/OuterClothing/Misc/straight_jacket.rsi/meta.json b/Resources/Textures/Clothing/OuterClothing/Misc/straight_jacket.rsi/meta.json index e482264df5..b41f0209d7 100644 --- a/Resources/Textures/Clothing/OuterClothing/Misc/straight_jacket.rsi/meta.json +++ b/Resources/Textures/Clothing/OuterClothing/Misc/straight_jacket.rsi/meta.json @@ -11,7 +11,7 @@ "name": "icon" }, { - "name": "equipped-OUTERCLOTHING", + "name": "body-overlay-2", "directions": 4 }, { diff --git a/Resources/migration.yml b/Resources/migration.yml index fd372c7998..b6b2bbaf3f 100644 --- a/Resources/migration.yml +++ b/Resources/migration.yml @@ -108,3 +108,6 @@ Intercom: IntercomCommon # 2023-07-12 ToyAssistant: ToyFigurinePassenger + +# 2023-07-20 +ForensicGloves: ClothingHandsGlovesForensic diff --git a/RobustToolbox b/RobustToolbox index bbc4668f9c..c52db4d3f2 160000 --- a/RobustToolbox +++ b/RobustToolbox @@ -1 +1 @@ -Subproject commit bbc4668f9c0a62c292c11cdd5054876043c35ade +Subproject commit c52db4d3f2f2de83be85c782eeff2e8cbf8bd38e diff --git a/Tools/package_server_build.py b/Tools/package_server_build.py index 73b8f9d731..8824fbff9b 100755 --- a/Tools/package_server_build.py +++ b/Tools/package_server_build.py @@ -72,7 +72,6 @@ SERVER_CONTENT_ASSEMBLIES = [ SERVER_EXTRA_ASSEMBLIES = [ "Npgsql.", "Microsoft", - "System.Linq.Async", ] SERVER_NOT_EXTRA_ASSEMBLIES = [