diff --git a/Content.Client/CosmaticDrift/CryoSleep/AcceptCryoWindow.cs b/Content.Client/CosmaticDrift/CryoSleep/AcceptCryoWindow.cs deleted file mode 100644 index 03c774ff7e..0000000000 --- a/Content.Client/CosmaticDrift/CryoSleep/AcceptCryoWindow.cs +++ /dev/null @@ -1,39 +0,0 @@ -using Robust.Client.UserInterface; -using Robust.Client.UserInterface.Controls; -using Robust.Client.UserInterface.CustomControls; -using static Robust.Client.UserInterface.Controls.BoxContainer; - -namespace Content.Client.CryoSleep; -public sealed class AcceptCryoWindow : DefaultWindow -{ - public readonly Button DenyButton; - public readonly Button AcceptButton; - public readonly BoxContainer ButtonBox; - public readonly BoxContainer InnerBox; - - public AcceptCryoWindow() - { - Title = Loc.GetString("accept-cryo-window-title"); - - AcceptButton = new Button() { Text = Loc.GetString("accept-cryo-window-accept-button") }; - DenyButton = new Button() { Text = Loc.GetString("accept-cryo-window-deny-button") }; - - // This one holds the buttons - ButtonBox = new BoxContainer() - { - Orientation = LayoutOrientation.Horizontal, - Align = AlignMode.Center, - Children = { AcceptButton, (new Control() { MinSize = new Vector2i(20, 0) }), DenyButton } - }; - - // This one holds the button container - InnerBox = new BoxContainer() - { - Orientation = LayoutOrientation.Vertical, - Children = { (new Label() { Text = Loc.GetString("accept-cryo-window-prompt-text-part") }), ButtonBox } - }; - - // Put it all together - Contents.AddChild(new BoxContainer { Orientation = LayoutOrientation.Vertical, Children = { InnerBox } }); - } -} diff --git a/Content.Client/CosmaticDrift/CryoSleep/CryoSleepEui.cs b/Content.Client/CosmaticDrift/CryoSleep/CryoSleepEui.cs deleted file mode 100644 index c1da1ea805..0000000000 --- a/Content.Client/CosmaticDrift/CryoSleep/CryoSleepEui.cs +++ /dev/null @@ -1,39 +0,0 @@ -using Content.Client.Eui; -using Content.Shared.CryoSleep; -using Robust.Client.Graphics; - -namespace Content.Client.CryoSleep; - -public sealed class CryoSleepEui : BaseEui -{ - private readonly AcceptCryoWindow _window; - - public CryoSleepEui() - { - _window = new AcceptCryoWindow(); - - _window.DenyButton.OnPressed += _ => - { - SendMessage(new AcceptCryoChoiceMessage(AcceptCryoUiButton.Deny)); - _window.Close(); - }; - - _window.AcceptButton.OnPressed += _ => - { - SendMessage(new AcceptCryoChoiceMessage(AcceptCryoUiButton.Accept)); - _window.Close(); - }; - } - - public override void Opened() - { - IoCManager.Resolve().RequestWindowAttention(); - _window.OpenCentered(); - } - - public override void Closed() - { - _window.Close(); - } - -} diff --git a/Content.Server/Bed/Cryostorage/CryostorageSystem.cs b/Content.Server/Bed/Cryostorage/CryostorageSystem.cs index 11184bee0a..7940308306 100644 --- a/Content.Server/Bed/Cryostorage/CryostorageSystem.cs +++ b/Content.Server/Bed/Cryostorage/CryostorageSystem.cs @@ -1,23 +1,17 @@ -using System.Linq; using Content.Server.Chat.Managers; using Content.Server.GameTicking; -using Content.Server.Hands.Systems; -using Content.Server.Inventory; -using Content.Server.Popups; using Content.Server.Station.Components; using Content.Server.Station.Systems; -using Content.Shared.UserInterface; -using Content.Shared.Access.Systems; using Content.Shared.Bed.Cryostorage; using Content.Shared.Chat; using Content.Shared.Climbing.Systems; using Content.Shared.Database; -using Content.Shared.Hands.Components; using Content.Shared.Mind.Components; -using Robust.Server.Audio; using Robust.Server.Containers; using Robust.Server.GameObjects; using Robust.Server.Player; +using Robust.Shared.Audio; +using Robust.Shared.Audio.Systems; using Robust.Shared.Containers; using Robust.Shared.Enums; using Robust.Shared.Network; @@ -30,27 +24,20 @@ public sealed class CryostorageSystem : SharedCryostorageSystem { [Dependency] private readonly IChatManager _chatManager = default!; [Dependency] private readonly IPlayerManager _playerManager = default!; - [Dependency] private readonly AudioSystem _audio = default!; - [Dependency] private readonly AccessReaderSystem _accessReader = default!; + [Dependency] private readonly SharedAudioSystem _audio = default!; [Dependency] private readonly ClimbSystem _climb = default!; [Dependency] private readonly ContainerSystem _container = default!; [Dependency] private readonly GameTicker _gameTicker = default!; - [Dependency] private readonly HandsSystem _hands = default!; - [Dependency] private readonly ServerInventorySystem _inventory = default!; - [Dependency] private readonly PopupSystem _popup = default!; [Dependency] private readonly StationSystem _station = default!; [Dependency] private readonly StationJobsSystem _stationJobs = default!; [Dependency] private readonly TransformSystem _transform = default!; - [Dependency] private readonly UserInterfaceSystem _ui = default!; + [Dependency] private readonly LostAndFoundSystem _lostAndFound = default!; /// public override void Initialize() { base.Initialize(); - SubscribeLocalEvent(OnBeforeUIOpened); - SubscribeLocalEvent(OnRemoveItemBuiMessage); - SubscribeLocalEvent(OnPlayerSpawned); SubscribeLocalEvent(OnMindRemoved); @@ -64,61 +51,6 @@ public override void Shutdown() _playerManager.PlayerStatusChanged -= PlayerStatusChanged; } - private void OnBeforeUIOpened(Entity ent, ref BeforeActivatableUIOpenEvent args) - { - UpdateCryostorageUIState(ent); - } - - private void OnRemoveItemBuiMessage(Entity ent, ref CryostorageRemoveItemBuiMessage args) - { - var (_, comp) = ent; - if (args.Session.AttachedEntity is not { } attachedEntity) - return; - - var cryoContained = GetEntity(args.StoredEntity); - - if (!comp.StoredPlayers.Contains(cryoContained) || !IsInPausedMap(cryoContained)) - return; - - if (!HasComp(attachedEntity)) - return; - - if (!_accessReader.IsAllowed(attachedEntity, ent)) - { - _popup.PopupEntity(Loc.GetString("cryostorage-popup-access-denied"), attachedEntity, attachedEntity); - return; - } - - EntityUid? entity = null; - if (args.Type == CryostorageRemoveItemBuiMessage.RemovalType.Hand) - { - if (_hands.TryGetHand(cryoContained, args.Key, out var hand)) - entity = hand.HeldEntity; - } - else - { - if (_inventory.TryGetSlotContainer(cryoContained, args.Key, out var slot, out _)) - entity = slot.ContainedEntity; - } - - if (entity == null) - return; - - AdminLog.Add(LogType.Action, LogImpact.High, - $"{ToPrettyString(attachedEntity):player} removed item {ToPrettyString(entity)} from cryostorage-contained player " + - $"{ToPrettyString(cryoContained):player}, stored in cryostorage {ToPrettyString(ent)}"); - _container.TryRemoveFromContainer(entity.Value); - _transform.SetCoordinates(entity.Value, Transform(attachedEntity).Coordinates); - _hands.PickupOrDrop(attachedEntity, entity.Value); - UpdateCryostorageUIState(ent); - } - - private void UpdateCryostorageUIState(Entity ent) - { - var state = new CryostorageBuiState(GetAllContainedData(ent).ToList()); - _ui.TrySetUiState(ent, CryostorageUIKey.Key, state); - } - private void OnPlayerSpawned(Entity ent, ref PlayerSpawnCompleteEvent args) { // if you spawned into cryostorage, we're not gonna round-remove you. @@ -186,7 +118,8 @@ public void HandleEnterCryostorage(Entity ent, Ne } } - _audio.PlayPvs(cryostorageComponent.RemoveSound, ent); + // play the cryostasis sound effect; need to use coordinates since the body gets deleted + _audio.PlayPvs("/Audio/SimpleStation14/Effects/cryostasis.ogg", Transform(ent).Coordinates, AudioParams.Default.WithVolume(6f)); EnsurePausedMap(); if (PausedMap == null) @@ -204,9 +137,19 @@ public void HandleEnterCryostorage(Entity ent, Ne } comp.AllowReEnteringBody = false; _transform.SetParent(ent, PausedMap.Value); - cryostorageComponent.StoredPlayers.Add(ent); - Dirty(ent, comp); - UpdateCryostorageUIState((cryostorageEnt.Value, cryostorageComponent)); + + // try to get the lost and found and add the player to it + var query = EntityQueryEnumerator(); + query.MoveNext(out var storage, out var lostAndFoundComponent); + + if (TryComp(storage, out var lostAndFoundComp)) + { + lostAndFoundComp.StoredPlayers.Add(ent); + Dirty(ent, comp); + _lostAndFound.UpdateCryostorageUIState((storage, lostAndFoundComp)); + + } + AdminLog.Add(LogType.Action, LogImpact.High, $"{ToPrettyString(ent):player} was entered into cryostorage inside of {ToPrettyString(cryostorageEnt.Value)}"); } @@ -235,9 +178,18 @@ private void HandleCryostorageReconnection(Entity } comp.GracePeriodEndTime = null; - cryostorageComponent.StoredPlayers.Remove(uid); + + // try to get the lost and found and remove the player from it + var query = EntityQueryEnumerator(); + query.MoveNext(out var storage, out var lostAndFoundComponent); + + if (TryComp(storage, out var lostAndFoundComp)) + { + lostAndFoundComp.StoredPlayers.Remove(uid); + _lostAndFound.UpdateCryostorageUIState((storage, lostAndFoundComp)); + } + AdminLog.Add(LogType.Action, LogImpact.High, $"{ToPrettyString(entity):player} re-entered the game from cryostorage {ToPrettyString(cryostorage)}"); - UpdateCryostorageUIState((cryostorage, cryostorageComponent)); } protected override void OnInsertedContainer(Entity ent, ref EntInsertedIntoContainerMessage args) @@ -257,36 +209,6 @@ protected override void OnInsertedContainer(Entity ent, re _chatManager.ChatMessageToOne(ChatChannel.Server, msg, msg, uid, false, actor.PlayerSession.Channel); } - private IEnumerable GetAllContainedData(Entity ent) - { - foreach (var contained in ent.Comp.StoredPlayers) - { - yield return GetContainedData(contained); - } - } - - private CryostorageContainedPlayerData GetContainedData(EntityUid uid) - { - var data = new CryostorageContainedPlayerData(); - data.PlayerName = Name(uid); - data.PlayerEnt = GetNetEntity(uid); - - var enumerator = _inventory.GetSlotEnumerator(uid); - while (enumerator.NextItem(out var item, out var slotDef)) - { - data.ItemSlots.Add(slotDef.Name, Name(item)); - } - - foreach (var hand in _hands.EnumerateHands(uid)) - { - if (hand.HeldEntity == null) - continue; - - data.HeldItems.Add(hand.Name, Name(hand.HeldEntity.Value)); - } - - return data; - } public override void Update(float frameTime) { diff --git a/Content.Server/Bed/Cryostorage/LostAndFoundSystem.cs b/Content.Server/Bed/Cryostorage/LostAndFoundSystem.cs new file mode 100644 index 0000000000..0fd33f793e --- /dev/null +++ b/Content.Server/Bed/Cryostorage/LostAndFoundSystem.cs @@ -0,0 +1,124 @@ +using System.Linq; +using Content.Server.Hands.Systems; +using Content.Server.Inventory; +using Content.Server.Popups; +using Content.Shared.Access.Systems; +using Content.Shared.UserInterface; +using Content.Shared.Bed.Cryostorage; +using Content.Shared.Database; +using Content.Shared.Hands.Components; +using Robust.Server.Containers; +using Robust.Server.GameObjects; + +namespace Content.Server.Bed.Cryostorage; + +/// +public sealed class LostAndFoundSystem : SharedLostAndFoundSystem +{ + [Dependency] private readonly ServerInventorySystem _inventory = default!; + [Dependency] private readonly UserInterfaceSystem _ui = default!; + [Dependency] private readonly HandsSystem _hands = default!; + [Dependency] private readonly AccessReaderSystem _accessReader = default!; + [Dependency] private readonly PopupSystem _popup = default!; + [Dependency] private readonly ContainerSystem _container = default!; + [Dependency] private readonly TransformSystem _transform = default!; + + /// + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnBeforeUIOpened); + SubscribeLocalEvent(OnRemoveItemBuiMessage); + } + + private void OnBeforeUIOpened(Entity ent, ref BeforeActivatableUIOpenEvent args) + { + UpdateCryostorageUIState(ent); + } + + private void OnRemoveItemBuiMessage(Entity ent, ref CryostorageRemoveItemBuiMessage args) + { + Log.Debug("on remove item bui message"); + + var (_, comp) = ent; + if (args.Session.AttachedEntity is not { } attachedEntity) + return; + + var cryoContained = GetEntity(args.StoredEntity); + + if (!comp.StoredPlayers.Contains(cryoContained) || !IsInPausedMap(cryoContained)) + return; + + if (!HasComp(attachedEntity)) + return; + + if (!_accessReader.IsAllowed(attachedEntity, ent)) + { + _popup.PopupEntity(Loc.GetString("cryostorage-popup-access-denied"), attachedEntity, attachedEntity); + return; + } + + EntityUid? entity = null; + if (args.Type == CryostorageRemoveItemBuiMessage.RemovalType.Hand) + { + if (_hands.TryGetHand(cryoContained, args.Key, out var hand)) + entity = hand.HeldEntity; + } + else + { + if (_inventory.TryGetSlotContainer(cryoContained, args.Key, out var slot, out _)) + entity = slot.ContainedEntity; + } + + if (entity == null) + return; + + AdminLog.Add(LogType.Action, LogImpact.High, + $"{ToPrettyString(attachedEntity):player} removed item {ToPrettyString(entity)} from cryostorage-contained player " + + $"{ToPrettyString(cryoContained):player}, stored in cryostorage {ToPrettyString(ent)}"); + _container.TryRemoveFromContainer(entity.Value); + _transform.SetCoordinates(entity.Value, Transform(attachedEntity).Coordinates); + _hands.PickupOrDrop(attachedEntity, entity.Value); + UpdateCryostorageUIState(ent); + } + + + public void UpdateCryostorageUIState(Entity ent) + { + var state = new CryostorageBuiState(GetAllContainedData(ent).ToList()); + _ui.TrySetUiState(ent, CryostorageUIKey.Key, state); + } + + private IEnumerable GetAllContainedData(Entity ent) + { + foreach (var contained in ent.Comp.StoredPlayers) + { + yield return GetContainedData(contained); + } + } + + private CryostorageContainedPlayerData GetContainedData(EntityUid uid) + { + var data = new CryostorageContainedPlayerData(); + data.PlayerName = Name(uid); + data.PlayerEnt = GetNetEntity(uid); + + var enumerator = _inventory.GetSlotEnumerator(uid); + while (enumerator.NextItem(out var item, out var slotDef)) + { + data.ItemSlots.Add(slotDef.Name, Name(item)); + } + + foreach (var hand in _hands.EnumerateHands(uid)) + { + if (hand.HeldEntity == null) + continue; + + data.HeldItems.Add(hand.Name, Name(hand.HeldEntity.Value)); + } + + return data; + } + +} diff --git a/Content.Server/CosmaticDrift/CryoSleep/CryoSleepComponent.cs b/Content.Server/CosmaticDrift/CryoSleep/CryoSleepComponent.cs deleted file mode 100644 index a3f6e9652d..0000000000 --- a/Content.Server/CosmaticDrift/CryoSleep/CryoSleepComponent.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System.Numerics; -using Robust.Shared.Audio; -using Robust.Shared.Containers; - -namespace Content.Server.CryoSleep; -[RegisterComponent] -public sealed partial class CryoSleepComponent : Component -{ - public ContainerSlot BodyContainer = default!; - - /// - /// Whether or not spawns are routed through the cryopod. - /// - [DataField("doSpawns"), ViewVariables(VVAccess.ReadWrite)] - public bool DoSpawns = false; - - /// - /// The sound that is played when a player spawns in the pod. - /// - [DataField("arrivalSound")] - public SoundSpecifier ArrivalSound = new SoundPathSpecifier("/Audio/Effects/teleport_arrival.ogg"); - - /// - /// How long the entity initially is asleep for upon joining. - /// - [DataField("initialSleepDurationRange")] - public Vector2 InitialSleepDurationRange = new (5, 10); - - public CryoSleepEui eui = default!; -} diff --git a/Content.Server/CosmaticDrift/CryoSleep/CryoSleepEui.cs b/Content.Server/CosmaticDrift/CryoSleep/CryoSleepEui.cs deleted file mode 100644 index a13dd3819e..0000000000 --- a/Content.Server/CosmaticDrift/CryoSleep/CryoSleepEui.cs +++ /dev/null @@ -1,36 +0,0 @@ -using Content.Server.EUI; -using Content.Shared.CryoSleep; -using Content.Shared.Eui; - -namespace Content.Server.CryoSleep; - -public sealed class CryoSleepEui : BaseEui -{ - private readonly CryoSleepSystem _cryoSystem; - private readonly EntityUid _mind; - - public CryoSleepEui(EntityUid mind, CryoSleepSystem cryoSys) - { - _mind = mind; - _cryoSystem = cryoSys; - } - - public override void HandleMessage(EuiMessageBase msg) - { - base.HandleMessage(msg); - - if (msg is not AcceptCryoChoiceMessage choice || - choice.Button == AcceptCryoUiButton.Deny) - { - Close(); - return; - } - - if (_mind is { Valid: true } body) - { - _cryoSystem.CryoStoreBody(body); - } - - Close(); - } -} diff --git a/Content.Server/CosmaticDrift/CryoSleep/CryoSleepSystem.cs b/Content.Server/CosmaticDrift/CryoSleep/CryoSleepSystem.cs deleted file mode 100644 index 82a3ebf13e..0000000000 --- a/Content.Server/CosmaticDrift/CryoSleep/CryoSleepSystem.cs +++ /dev/null @@ -1,274 +0,0 @@ -using Content.Server.Chat.Systems; -using Content.Server.CosmaticDrift.Storage.Components; -using Content.Server.EUI; -using Content.Server.Forensics; -using Content.Server.GameTicking; -using Content.Server.Mind; -using Content.Server.Station.Systems; -using Content.Server.StationRecords.Systems; -using Content.Server.Storage.Components; -using Content.Server.Storage.EntitySystems; -using Content.Server.Warps; -using Content.Shared.ActionBlocker; -using Content.Shared.Climbing.Systems; -using Content.Shared.Destructible; -using Content.Shared.DragDrop; -using Content.Shared.Inventory; -using Content.Shared.Mind; -using Content.Shared.Mobs.Components; -using Content.Shared.PDA; -using Content.Shared.Roles.Jobs; -using Content.Shared.StationRecords; -using Content.Shared.Verbs; -using Robust.Server.Containers; -using Robust.Shared.Audio; -using Robust.Shared.Audio.Systems; -using Robust.Shared.Containers; -using Robust.Shared.Enums; - -namespace Content.Server.CryoSleep; - -public sealed class CryoSleepSystem : EntitySystem -{ - [Dependency] private readonly EuiManager _euiManager = null!; - [Dependency] private readonly ActionBlockerSystem _actionBlocker = default!; - [Dependency] private readonly ClimbSystem _climb = default!; - [Dependency] private readonly StationJobsSystem _stationJobsSystem = default!; - [Dependency] private readonly SharedJobSystem _sharedJobSystem = default!; - [Dependency] private readonly StationSystem _stationSystem = default!; - [Dependency] private readonly MindSystem _mindSystem = default!; - [Dependency] private readonly ContainerSystem _container = default!; - [Dependency] private readonly GameTicker _gameTicker = default!; - [Dependency] private readonly InventorySystem _inventory = default!; - [Dependency] private readonly StationRecordsSystem _stationRecords = default!; - [Dependency] private readonly ChatSystem _chatSystem = default!; - [Dependency] private readonly EntityStorageSystem _entityStorage = default!; - [Dependency] private readonly SharedAudioSystem _audioSystem = default!; - - - public override void Initialize() - { - base.Initialize(); - - SubscribeLocalEvent(ComponentInit); - - SubscribeLocalEvent>(AddAlternativeVerbs); - SubscribeLocalEvent((e, c, _) => EjectBody(e, c)); - SubscribeLocalEvent(OnDragDrop); - } - - private void ComponentInit(EntityUid uid, CryoSleepComponent component, ComponentInit args) - { - component.BodyContainer = _container.EnsureContainer(uid, "body_container"); - } - - - private bool InsertBody(EntityUid uid, EntityUid? toInsert, CryoSleepComponent component) - { - if (toInsert == null || IsOccupied(component)) - return false; - - if (!HasComp(toInsert.Value)) - return false; - - var inserted = component.BodyContainer.Insert(toInsert.Value, EntityManager); - - return inserted; - } - - public bool RespawnUser(EntityUid? toInsert, CryoSleepComponent component, bool force) - { - // Play the cryosleep pod opening sound effect. - _audioSystem.PlayPvs("/Audio/SimpleStation14/Effects/cryosleep_open.ogg", component.Owner, AudioParams.Default.WithVolume(6f)); - - if (toInsert == null) - return false; - - if (IsOccupied(component) && !force) - return false; - - if (_mindSystem.TryGetMind(toInsert.Value, out var mind, out var mindComp)) - { - var session = mindComp.Session; - if (session != null && session.Status == SessionStatus.Disconnected) - { - InsertBody(toInsert.Value, component.Owner, component); - return true; - } - } - - var success = component.BodyContainer.Insert(toInsert.Value, EntityManager); - - if (success && mindComp?.Session != null) - { - component.eui = new CryoSleepEui(mind, this); - _euiManager.OpenEui(component.eui, mindComp.Session); - } - - return success; - } - - public void CryoStoreBody(EntityUid mindId) - { - if (!_sharedJobSystem.MindTryGetJob(mindId, out _, out var prototype)) - return; - - if (!TryComp(mindId, out var mind)) - return; - - var body = mind.CurrentEntity; - var job = prototype; - - var name = mind.CharacterName; - - if (body == null) - return; - - // Play the cryostasis sound effect. Need to use coordinates since the body gets deleted. - _audioSystem.PlayPvs("/Audio/SimpleStation14/Effects/cryostasis.ogg", Transform(body.Value).Coordinates, AudioParams.Default.WithVolume(6f)); - - // Remove the record. Hopefully. - foreach (var item in _inventory.GetHandOrInventoryEntities(body.Value)) - { - if (TryComp(item, out PdaComponent? pda) && TryComp(pda.ContainedId, out StationRecordKeyStorageComponent? keyStorage) && keyStorage.Key is { } key && _stationRecords.TryGetRecord(key.OriginStation, key, out GeneralStationRecord? record)) - { - if (TryComp(body, out DnaComponent? dna) && - dna.DNA != record.DNA) - { - continue; - } - - if (TryComp(body, out FingerprintComponent? fingerPrint) && - fingerPrint.Fingerprint != record.Fingerprint) - { - continue; - } - - _stationRecords.RemoveRecord(key.OriginStation, key); - Del(item); - } - } - - // Move their items - MoveItems(body.Value); - - _gameTicker.OnGhostAttempt(mindId, false, true, mind: mind); - EntityManager.DeleteEntity(body); - - // This is awful, it feels awful, and I hate it. Warp points are really the only thing I can confirm exists on every station, though CC might cause issues so ideally I'd use one with a var set - var query = EntityQueryEnumerator(); - query.MoveNext(out var warpPoint, out var comp); - - // sets job slot - var xform = Transform(warpPoint); - - if (!xform.GridUid.HasValue) - return; - - var station = _stationSystem.GetOwningStation(xform.GridUid.Value); - if (!station.HasValue) - return; - - if (job == null) - return; - - _stationJobsSystem.TryGetJobSlot(station.Value, job, out var amount); - if (!amount.HasValue) - return; - - _stationJobsSystem.TrySetJobSlot(station.Value, job, (int) amount.Value + 1, true); - - _chatSystem.DispatchStationAnnouncement(station.Value, Loc.GetString("cryo-leave-announcement", ("character", name!), ("job", job.LocalizedName)), "Cryo Pod", false); - } - - private bool EjectBody(EntityUid pod, CryoSleepComponent component) - { - if (!IsOccupied(component)) - return false; - - var toEject = component.BodyContainer.ContainedEntity; - if (toEject == null) - return false; - - component.BodyContainer.Remove(toEject.Value); - _climb.ForciblySetClimbing(toEject.Value, pod); - - _euiManager.CloseEui(component.eui); - - return true; - } - - private bool IsOccupied(CryoSleepComponent component) - { - return component.BodyContainer.ContainedEntity != null; - } - - private void AddAlternativeVerbs(EntityUid uid, CryoSleepComponent component, GetVerbsEvent args) - { - if (!args.CanAccess || !args.CanInteract) - return; - - // Insert self verb - if (!IsOccupied(component) && - _actionBlocker.CanMove(args.User)) - { - AlternativeVerb verb = new() - { - Act = () => RespawnUser(args.User, component, false), - Category = VerbCategory.Insert, - Text = Loc.GetString("medical-scanner-verb-enter") - }; - args.Verbs.Add(verb); - } - - // Eject somebody verb - if (IsOccupied(component)) - { - AlternativeVerb verb = new() - { - Act = () => EjectBody(component.Owner, component), - Category = VerbCategory.Eject, - Text = Loc.GetString("medical-scanner-verb-noun-occupant") - }; - args.Verbs.Add(verb); - } - } - - private void OnDragDrop(EntityUid uid, CryoSleepComponent component, ref DragDropTargetEvent args) - { - if (args.Handled || args.User != args.Dragged) - return; - - RespawnUser(args.User, component, false); - } - - private void MoveItems(EntityUid uid) - { - //// Make sure the entity being cryo'd has an inventory - //if (!HasComp(uid)) - // return; - - // Get the locker - var query = EntityQueryEnumerator(); - query.MoveNext(out var locker, out var lostAndFoundComponent); - - //// Make sure the locker exists and has storage - //if (!locker.Valid || !TryComp(uid, out var lockerStorageComp)) - // return; - TryComp(uid, out var lockerStorageComp); - - var coordinates = Transform(locker).Coordinates; - - // Go through their inventory and put everything in al ocker - foreach (var item in _inventory.GetHandOrInventoryEntities(uid)) - { - if (!item.IsValid() || !TryComp(item, out var comp)) - continue; - - var proto = comp.EntityPrototype; - var ent = EntityManager.SpawnEntity(proto!.ID, coordinates); - - _entityStorage.Insert(ent, locker, lockerStorageComp); - } - } -} diff --git a/Content.Server/CosmaticDrift/Storage/Components/LostAndFoundComponent.cs b/Content.Server/CosmaticDrift/Storage/Components/LostAndFoundComponent.cs deleted file mode 100644 index b059619cf4..0000000000 --- a/Content.Server/CosmaticDrift/Storage/Components/LostAndFoundComponent.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Content.Server.CosmaticDrift.Storage.Components; - -[RegisterComponent] -public sealed partial class LostAndFoundComponent : Component -{ - -} diff --git a/Content.Shared/Bed/Cryostorage/CryostorageComponent.cs b/Content.Shared/Bed/Cryostorage/CryostorageComponent.cs index 48f451d6bb..ca1838a00d 100644 --- a/Content.Shared/Bed/Cryostorage/CryostorageComponent.cs +++ b/Content.Shared/Bed/Cryostorage/CryostorageComponent.cs @@ -29,13 +29,6 @@ public sealed partial class CryostorageComponent : Component [AutoNetworkedField] public TimeSpan GracePeriod = TimeSpan.FromMinutes(5f); - /// - /// A list of players who have actively entered cryostorage. - /// - [DataField] - [AutoNetworkedField] - public List StoredPlayers = new(); - /// /// Sound that is played when a player is removed by a cryostorage. /// @@ -48,67 +41,3 @@ public enum CryostorageVisuals : byte { Full } - -[Serializable, NetSerializable] -public record struct CryostorageContainedPlayerData() -{ - /// - /// The player's IC name - /// - public string PlayerName = string.Empty; - - /// - /// The player's entity - /// - public NetEntity PlayerEnt = NetEntity.Invalid; - - /// - /// A dictionary relating a slot definition name to the name of the item inside of it. - /// - public Dictionary ItemSlots = new(); - - /// - /// A dictionary relating a hand ID to the hand name and the name of the item being held. - /// - public Dictionary HeldItems = new(); -} - -[Serializable, NetSerializable] -public sealed class CryostorageBuiState : BoundUserInterfaceState -{ - public List PlayerData; - - public CryostorageBuiState(List playerData) - { - PlayerData = playerData; - } -} - -[Serializable, NetSerializable] -public sealed class CryostorageRemoveItemBuiMessage : BoundUserInterfaceMessage -{ - public NetEntity StoredEntity; - - public string Key; - - public RemovalType Type; - - public enum RemovalType : byte - { - Hand, - Inventory - } - - public CryostorageRemoveItemBuiMessage(NetEntity storedEntity, string key, RemovalType type) - { - StoredEntity = storedEntity; - Key = key; - Type = type; - } -} - -[Serializable, NetSerializable] -public enum CryostorageUIKey : byte -{ - Key -} diff --git a/Content.Shared/Bed/Cryostorage/LostAndFoundComponent.cs b/Content.Shared/Bed/Cryostorage/LostAndFoundComponent.cs new file mode 100644 index 0000000000..637fe88642 --- /dev/null +++ b/Content.Shared/Bed/Cryostorage/LostAndFoundComponent.cs @@ -0,0 +1,85 @@ +using Robust.Shared.GameStates; +using Robust.Shared.Serialization; + +namespace Content.Shared.Bed.Cryostorage; + +/// +/// This is used for a container which holds the items lost +/// when a player enters cryostorage. +/// +[RegisterComponent, NetworkedComponent] +[AutoGenerateComponentState] +public sealed partial class LostAndFoundComponent : Component +{ + /// + /// A list of players who have actively entered cryostorage. + /// + [DataField] + [AutoNetworkedField] + public List StoredPlayers = new(); + +} + +[Serializable, NetSerializable] +public record struct CryostorageContainedPlayerData() +{ + /// + /// The player's IC name + /// + public string PlayerName = string.Empty; + + /// + /// The player's entity + /// + public NetEntity PlayerEnt = NetEntity.Invalid; + + /// + /// A dictionary relating a slot definition name to the name of the item inside of it. + /// + public Dictionary ItemSlots = new(); + + /// + /// A dictionary relating a hand ID to the hand name and the name of the item being held. + /// + public Dictionary HeldItems = new(); +} + +[Serializable, NetSerializable] +public sealed class CryostorageBuiState : BoundUserInterfaceState +{ + public List PlayerData; + + public CryostorageBuiState(List playerData) + { + PlayerData = playerData; + } +} + +[Serializable, NetSerializable] +public sealed class CryostorageRemoveItemBuiMessage : BoundUserInterfaceMessage +{ + public NetEntity StoredEntity; + + public string Key; + + public RemovalType Type; + + public enum RemovalType : byte + { + Hand, + Inventory + } + + public CryostorageRemoveItemBuiMessage(NetEntity storedEntity, string key, RemovalType type) + { + StoredEntity = storedEntity; + Key = key; + Type = type; + } +} + +[Serializable, NetSerializable] +public enum CryostorageUIKey : byte +{ + Key +} diff --git a/Content.Shared/Bed/Cryostorage/SharedCryostorageSystem.cs b/Content.Shared/Bed/Cryostorage/SharedCryostorageSystem.cs index 14a76ee45c..718a981398 100644 --- a/Content.Shared/Bed/Cryostorage/SharedCryostorageSystem.cs +++ b/Content.Shared/Bed/Cryostorage/SharedCryostorageSystem.cs @@ -4,6 +4,8 @@ using Content.Shared.GameTicking; using Content.Shared.Mind; using Content.Shared.Mind.Components; +using Robust.Shared.Audio; +using Robust.Shared.Audio.Systems; using Robust.Shared.Configuration; using Robust.Shared.Containers; using Robust.Shared.Map; @@ -22,6 +24,7 @@ public abstract class SharedCryostorageSystem : EntitySystem [Dependency] private readonly IMapManager _mapManager = default!; [Dependency] private readonly SharedAppearanceSystem _appearance = default!; [Dependency] protected readonly SharedMindSystem Mind = default!; + [Dependency] private readonly SharedAudioSystem _audio = default!; protected EntityUid? PausedMap { get; private set; } @@ -33,7 +36,6 @@ public override void Initialize() SubscribeLocalEvent(OnInsertedContainer); SubscribeLocalEvent(OnRemovedContainer); SubscribeLocalEvent(OnInsertAttempt); - SubscribeLocalEvent(OnShutdownContainer); SubscribeLocalEvent(OnCanDropTarget); SubscribeLocalEvent(OnRemovedContained); @@ -72,6 +74,12 @@ protected virtual void OnInsertedContainer(Entity ent, ref containedComp.GracePeriodEndTime = Timing.CurTime + delay; containedComp.Cryostorage = ent; Dirty(args.Entity, containedComp); + + // play sound, checking for client-side prediction to avoid double audio + if (!Timing.InPrediction) + return; + + _audio.PlayPvs("/Audio/SimpleStation14/Effects/cryosleep_open.ogg", ent, AudioParams.Default.WithVolume(6f)); } private void OnRemovedContainer(Entity ent, ref EntRemovedFromContainerMessage args) @@ -102,22 +110,6 @@ private void OnInsertAttempt(Entity ent, ref ContainerIsIn } } - private void OnShutdownContainer(Entity ent, ref ComponentShutdown args) - { - var comp = ent.Comp; - foreach (var stored in comp.StoredPlayers) - { - if (TryComp(stored, out var containedComponent)) - { - containedComponent.Cryostorage = null; - Dirty(stored, containedComponent); - } - } - - comp.StoredPlayers.Clear(); - Dirty(ent, comp); - } - private void OnCanDropTarget(Entity ent, ref CanDropTargetEvent args) { if (args.Dragged == args.User) @@ -148,7 +140,11 @@ private void OnShutdownContained(Entity ent, ref { var comp = ent.Comp; - CompOrNull(comp.Cryostorage)?.StoredPlayers.Remove(ent); + // try to get the lost and found and remove the player from it + var query = EntityQueryEnumerator(); + query.MoveNext(out var storage, out var lostAndFoundComponent); + CompOrNull(storage)?.StoredPlayers.Remove(ent); + ent.Comp.Cryostorage = null; Dirty(ent, comp); } diff --git a/Content.Shared/Bed/Cryostorage/SharedLostAndFoundSystem.cs b/Content.Shared/Bed/Cryostorage/SharedLostAndFoundSystem.cs new file mode 100644 index 0000000000..215b9ee5da --- /dev/null +++ b/Content.Shared/Bed/Cryostorage/SharedLostAndFoundSystem.cs @@ -0,0 +1,43 @@ +using Content.Shared.Administration.Logs; + +namespace Content.Shared.Bed.Cryostorage; + +/// +/// This handles +/// +public abstract class SharedLostAndFoundSystem : EntitySystem +{ + [Dependency] protected readonly ISharedAdminLogManager AdminLog = default!; + + protected EntityUid? PausedMap { get; private set; } + + /// + public override void Initialize() + { + SubscribeLocalEvent(OnShutdownContainer); + } + + private void OnShutdownContainer(Entity ent, ref ComponentShutdown args) + { + var comp = ent.Comp; + foreach (var stored in comp.StoredPlayers) + { + if (TryComp(stored, out var containedComponent)) + { + containedComponent.Cryostorage = null; + Dirty(stored, containedComponent); + } + } + + comp.StoredPlayers.Clear(); + Dirty(ent, comp); + } + + public bool IsInPausedMap(Entity entity) + { + var (_, comp) = entity; + comp ??= Transform(entity); + + return comp.MapUid != null && comp.MapUid == PausedMap; + } +} diff --git a/Content.Shared/CosmaticDrift/CryoSleep/AcceptCryoSleepEuiMessage.cs b/Content.Shared/CosmaticDrift/CryoSleep/AcceptCryoSleepEuiMessage.cs deleted file mode 100644 index 9cff25f811..0000000000 --- a/Content.Shared/CosmaticDrift/CryoSleep/AcceptCryoSleepEuiMessage.cs +++ /dev/null @@ -1,22 +0,0 @@ -using Content.Shared.Eui; -using Robust.Shared.Serialization; - -namespace Content.Shared.CryoSleep; - -[Serializable, NetSerializable] -public enum AcceptCryoUiButton -{ - Deny, - Accept, -} - -[Serializable, NetSerializable] -public sealed class AcceptCryoChoiceMessage : EuiMessageBase -{ - public readonly AcceptCryoUiButton Button; - - public AcceptCryoChoiceMessage(AcceptCryoUiButton button) - { - Button = button; - } -} diff --git a/Resources/Locale/en-US/cosmaticdrift/cryosleep/cryosleep-component.ftl b/Resources/Locale/en-US/cosmaticdrift/cryosleep/cryosleep-component.ftl deleted file mode 100644 index c44f60a8fd..0000000000 --- a/Resources/Locale/en-US/cosmaticdrift/cryosleep/cryosleep-component.ftl +++ /dev/null @@ -1,7 +0,0 @@ -## UI -accept-cryo-window-accept-button = Accept -accept-cryo-window-deny-button = Cancel -accept-cryo-window-prompt-text-part = Enter cryosleep and end your shift as this character? -accept-cryo-window-title = Cryostasis Sleep Chamber - -cryo-leave-announcement = {$character} ({$job}) has gone into cryosleep. diff --git a/Resources/Prototypes/CosmaticDrift/Entities/Structures/Machines/cryo_sleep_pod.yml b/Resources/Prototypes/CosmaticDrift/Entities/Structures/Machines/cryo_sleep_pod.yml deleted file mode 100644 index 856e4c47c0..0000000000 --- a/Resources/Prototypes/CosmaticDrift/Entities/Structures/Machines/cryo_sleep_pod.yml +++ /dev/null @@ -1,30 +0,0 @@ -- type: entity - id: MachineCryoSleepPod - parent: BaseMachine - name: cryosleep chamber - description: Perfect for having a 10,000 year nap. - components: - - type: Sprite - sprite: CosmaticDrift/Structures/cryosleep_pod.rsi - drawdepth: Mobs - layers: - - state: sleeper_1 - - type: InteractionOutline - - type: Anchorable - - type: Physics - bodyType: Static - - type: MaterialStorage - - type: Appearance - - type: CryoSleep - - type: Climbable - - type: Transform - noRot: false - - type: ContainerContainer - containers: - body_container: - !type:ContainerSlot - - type: Destructible - thresholds: - - trigger: - !type:DamageTrigger - damage: 0 diff --git a/Resources/Prototypes/CosmaticDrift/Entities/Structures/Storage/lockers.yml b/Resources/Prototypes/CosmaticDrift/Entities/Structures/Storage/lockers.yml deleted file mode 100644 index 5080194ab9..0000000000 --- a/Resources/Prototypes/CosmaticDrift/Entities/Structures/Storage/lockers.yml +++ /dev/null @@ -1,15 +0,0 @@ -- type: entity - parent: LockerBaseSecure - id: LockerLostAndFound - name: lost and found locker - components: - - type: LostAndFound - - type: EntityStorage - capacity: 999 # Supposed to fit a lot. - - type: Appearance - - type: EntityStorageVisuals - stateBaseClosed: lost_and_found - stateDoorOpen: lost_and_found_open - stateDoorClosed: lost_and_found_door - - type: AccessReader - access: [["HeadOfPersonnel"]] diff --git a/Resources/Prototypes/Entities/Structures/Storage/lost_and_found.yml b/Resources/Prototypes/Entities/Structures/Storage/lost_and_found.yml new file mode 100644 index 0000000000..98279309d9 --- /dev/null +++ b/Resources/Prototypes/Entities/Structures/Storage/lost_and_found.yml @@ -0,0 +1,34 @@ +- type: entity + parent: BaseMachinePowered + id: LostAndFound + name: lost and found storage unit + description: A storage unit containing belongings of individuals in cryostorage. + components: + - type: Sprite + noRot: true + sprite: Structures/Storage/lost_and_found.rsi + layers: + - state: icon + map: ["base"] + - type: UserInterface + interfaces: + - key: enum.CryostorageUIKey.Key + type: CryostorageBoundUserInterface + - type: ActivatableUI + key: enum.CryostorageUIKey.Key + - type: AccessReader + breakOnEmag: false + access: [["HeadOfPersonnel"]] + - type: InteractionOutline + - type: LostAndFound + - type: ApcPowerReceiver + - type: Physics + bodyType: Static + - type: PointLight + color: "#35A3E6" + radius: 1.1 + energy: 1.5 + castShadows: false + - type: ContainerContainer + containers: + storage: !type:ContainerSlot diff --git a/Resources/Prototypes/Entities/Structures/cryopod.yml b/Resources/Prototypes/Entities/Structures/cryopod.yml index 9063e8b138..d0628a3ac4 100644 --- a/Resources/Prototypes/Entities/Structures/cryopod.yml +++ b/Resources/Prototypes/Entities/Structures/cryopod.yml @@ -10,12 +10,6 @@ layers: - state: sleeper_0 map: ["base"] - - type: UserInterface - interfaces: - - key: enum.CryostorageUIKey.Key - type: CryostorageBoundUserInterface - - type: ActivatableUI - key: enum.CryostorageUIKey.Key - type: AccessReader breakOnEmag: false access: [["Cryogenics"]] diff --git a/Resources/Textures/CosmaticDrift/Structures/Storage/lost_and_found.rsi/lost_and_found.png b/Resources/Textures/CosmaticDrift/Structures/Storage/lost_and_found.rsi/lost_and_found.png deleted file mode 100644 index 2991a3ced1..0000000000 Binary files a/Resources/Textures/CosmaticDrift/Structures/Storage/lost_and_found.rsi/lost_and_found.png and /dev/null differ diff --git a/Resources/Textures/CosmaticDrift/Structures/Storage/lost_and_found.rsi/lost_and_found_door.png b/Resources/Textures/CosmaticDrift/Structures/Storage/lost_and_found.rsi/lost_and_found_door.png deleted file mode 100644 index ed87665239..0000000000 Binary files a/Resources/Textures/CosmaticDrift/Structures/Storage/lost_and_found.rsi/lost_and_found_door.png and /dev/null differ diff --git a/Resources/Textures/CosmaticDrift/Structures/Storage/lost_and_found.rsi/lost_and_found_open.png b/Resources/Textures/CosmaticDrift/Structures/Storage/lost_and_found.rsi/lost_and_found_open.png deleted file mode 100644 index 22443c0d2f..0000000000 Binary files a/Resources/Textures/CosmaticDrift/Structures/Storage/lost_and_found.rsi/lost_and_found_open.png and /dev/null differ diff --git a/Resources/Textures/CosmaticDrift/Structures/Storage/lost_and_found.rsi/meta.json b/Resources/Textures/CosmaticDrift/Structures/Storage/lost_and_found.rsi/meta.json deleted file mode 100644 index a51eae3eed..0000000000 --- a/Resources/Textures/CosmaticDrift/Structures/Storage/lost_and_found.rsi/meta.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "version": 1, - "size": { - "x": 32, - "y": 32 - }, - "copyright": "Lost and found resprited by PursuitInAshes", - "license": "CC-BY-SA-3.0", - "states": [ - { - "name": "lost_and_found" - }, - { - "name": "lost_and_found_door" - }, - { - "name": "lost_and_found_open" - } - ] -} diff --git a/Resources/Textures/CosmaticDrift/Structures/cryosleep_pod.rsi/meta.json b/Resources/Textures/CosmaticDrift/Structures/cryosleep_pod.rsi/meta.json deleted file mode 100644 index 2e0c397392..0000000000 --- a/Resources/Textures/CosmaticDrift/Structures/cryosleep_pod.rsi/meta.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "version": 1, - "license": "CC-BY-SA-3.0", - "copyright": "Taken from vg at commit https://github.com/vgstation-coders/vgstation13/commit/a16e41020a93479e9a7e2af343b1b74f7f2a61bd", - "size": { - "x": 32, - "y": 32 - }, - "states": [ - { - "name": "sleeper_0", - "directions": 4 - }, - { - "name": "sleeper_1", - "directions": 4, - "delays": [ - [ 0.2, 0.2, 0.2, 0.2 ], - [ 0.2, 0.2, 0.2, 0.2 ], - [ 0.2, 0.2, 0.2, 0.2 ], - [ 0.2, 0.2, 0.2, 0.2 ] - ] - } - ] -} diff --git a/Resources/Textures/CosmaticDrift/Structures/cryosleep_pod.rsi/sleeper_0.png b/Resources/Textures/CosmaticDrift/Structures/cryosleep_pod.rsi/sleeper_0.png deleted file mode 100644 index 7f67b0decf..0000000000 Binary files a/Resources/Textures/CosmaticDrift/Structures/cryosleep_pod.rsi/sleeper_0.png and /dev/null differ diff --git a/Resources/Textures/CosmaticDrift/Structures/cryosleep_pod.rsi/sleeper_1.png b/Resources/Textures/CosmaticDrift/Structures/cryosleep_pod.rsi/sleeper_1.png deleted file mode 100644 index 2061c3ad43..0000000000 Binary files a/Resources/Textures/CosmaticDrift/Structures/cryosleep_pod.rsi/sleeper_1.png and /dev/null differ diff --git a/Resources/Textures/Structures/Storage/closet.rsi/lost_and_found.png b/Resources/Textures/Structures/Storage/closet.rsi/lost_and_found.png deleted file mode 100644 index 2991a3ced1..0000000000 Binary files a/Resources/Textures/Structures/Storage/closet.rsi/lost_and_found.png and /dev/null differ diff --git a/Resources/Textures/Structures/Storage/closet.rsi/lost_and_found_door.png b/Resources/Textures/Structures/Storage/closet.rsi/lost_and_found_door.png deleted file mode 100644 index ed87665239..0000000000 Binary files a/Resources/Textures/Structures/Storage/closet.rsi/lost_and_found_door.png and /dev/null differ diff --git a/Resources/Textures/Structures/Storage/closet.rsi/lost_and_found_open.png b/Resources/Textures/Structures/Storage/closet.rsi/lost_and_found_open.png deleted file mode 100644 index 22443c0d2f..0000000000 Binary files a/Resources/Textures/Structures/Storage/closet.rsi/lost_and_found_open.png and /dev/null differ diff --git a/Resources/Textures/Structures/Storage/closet.rsi/meta.json b/Resources/Textures/Structures/Storage/closet.rsi/meta.json index e96928554a..98bbe8085a 100644 --- a/Resources/Textures/Structures/Storage/closet.rsi/meta.json +++ b/Resources/Textures/Structures/Storage/closet.rsi/meta.json @@ -4,7 +4,7 @@ "x": 32, "y": 32 }, - "copyright": "Taken from tgstation, brigmedic locker is a resprited CMO locker by PuroSlavKing (Github), lost and found resprited by PursuitInAshes", + "copyright": "Taken from tgstation, brigmedic locker is a resprited CMO locker by PuroSlavKing (Github)", "license": "CC-BY-SA-3.0", "states": [ { @@ -362,15 +362,6 @@ { "name": "locked" }, - { - "name": "lost_and_found" - }, - { - "name": "lost_and_found_door" - }, - { - "name": "lost_and_found_open" - }, { "name": "med" }, diff --git a/Resources/Textures/Structures/Storage/lost_and_found.rsi/icon.png b/Resources/Textures/Structures/Storage/lost_and_found.rsi/icon.png new file mode 100644 index 0000000000..819bd7f7cc Binary files /dev/null and b/Resources/Textures/Structures/Storage/lost_and_found.rsi/icon.png differ diff --git a/Resources/Textures/Structures/Storage/lost_and_found.rsi/meta.json b/Resources/Textures/Structures/Storage/lost_and_found.rsi/meta.json new file mode 100644 index 0000000000..f3f536e805 --- /dev/null +++ b/Resources/Textures/Structures/Storage/lost_and_found.rsi/meta.json @@ -0,0 +1,14 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Created by Discord user Finket, based on a sprite by Discord user Hyenh#6078", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "icon" + } + ] +}