diff --git a/Content.Server/Administration/Commands/ControlMob.cs b/Content.Server/Administration/Commands/ControlMob.cs index eeebabc970..b0797215e2 100644 --- a/Content.Server/Administration/Commands/ControlMob.cs +++ b/Content.Server/Administration/Commands/ControlMob.cs @@ -61,15 +61,8 @@ namespace Content.Server.Administration.Commands DebugTools.AssertNotNull(mind); - var oldEntity = mind!.CurrentEntity; - mindComponent.Mind?.TransferTo(null); - mind.TransferTo(target); - - DebugTools.AssertNotNull(oldEntity); - - if (oldEntity!.HasComponent()) - oldEntity.Delete(); + mind!.TransferTo(target); } } } diff --git a/Content.Server/GameObjects/Components/Medical/CloningPodComponent.cs b/Content.Server/GameObjects/Components/Medical/CloningPodComponent.cs index d9c34ed756..fdf247a077 100644 --- a/Content.Server/GameObjects/Components/Medical/CloningPodComponent.cs +++ b/Content.Server/GameObjects/Components/Medical/CloningPodComponent.cs @@ -1,4 +1,4 @@ -#nullable enable +#nullable enable using System; using Content.Server.Eui; using Content.Server.GameObjects.Components.Mobs; @@ -203,9 +203,6 @@ namespace Content.Server.GameObjects.Components.Medical { if (message.Sender == _capturedMind) { - //If the captured mind is in a ghost, we want to get rid of it. - _capturedMind.VisitingEntity?.Delete(); - //Transfer the mind to the new mob _capturedMind.TransferTo(_bodyContainer.ContainedEntity); diff --git a/Content.Server/GameObjects/Components/Mobs/MindComponent.cs b/Content.Server/GameObjects/Components/Mobs/MindComponent.cs index 16024481b6..ec1d2d43d8 100644 --- a/Content.Server/GameObjects/Components/Mobs/MindComponent.cs +++ b/Content.Server/GameObjects/Components/Mobs/MindComponent.cs @@ -1,4 +1,4 @@ -#nullable enable +#nullable enable using Content.Server.GameObjects.Components.Observer; using Content.Server.GameTicking; using Content.Server.Interfaces.GameTicking; @@ -22,9 +22,6 @@ namespace Content.Server.GameObjects.Components.Mobs [RegisterComponent] public class MindComponent : Component, IExamine { - [DataField("show_examine_info")] - private bool _showExamineInfo; - /// public override string Name => "Mind"; @@ -61,6 +58,8 @@ namespace Content.Server.GameObjects.Components.Mobs /// public void InternalEjectMind() { + if (!Deleted) + Owner.EntityManager.EventBus.RaiseLocalEvent(Owner.Uid, new MindRemovedMessage()); Mind = null; } @@ -94,7 +93,7 @@ namespace Content.Server.GameObjects.Components.Mobs Mind!.TransferTo(visiting); } - else if(GhostOnShutdown) + else if (GhostOnShutdown) { var spawnPosition = Owner.Transform.Coordinates; // Use a regular timer here because the entity has probably been deleted. @@ -153,4 +152,8 @@ namespace Content.Server.GameObjects.Components.Mobs } } } + + public class MindRemovedMessage : EntityEventArgs + { + } } diff --git a/Content.Server/GameObjects/Components/Mobs/VisitingMindComponent.cs b/Content.Server/GameObjects/Components/Mobs/VisitingMindComponent.cs index f5177b6467..5f3b8db61f 100644 --- a/Content.Server/GameObjects/Components/Mobs/VisitingMindComponent.cs +++ b/Content.Server/GameObjects/Components/Mobs/VisitingMindComponent.cs @@ -1,4 +1,5 @@ -using Content.Server.Mobs; +#nullable enable +using Content.Server.Mobs; using Robust.Shared.GameObjects; using Robust.Shared.ViewVariables; @@ -18,4 +19,8 @@ namespace Content.Server.GameObjects.Components.Mobs Mind?.UnVisit(); } } + + public class MindUnvisitedMessage : EntityEventArgs + { + } } diff --git a/Content.Server/GameObjects/Components/Observer/AcceptCloningEui.cs b/Content.Server/GameObjects/Components/Observer/AcceptCloningEui.cs index 0a8c8d17aa..ab80384316 100644 --- a/Content.Server/GameObjects/Components/Observer/AcceptCloningEui.cs +++ b/Content.Server/GameObjects/Components/Observer/AcceptCloningEui.cs @@ -28,7 +28,9 @@ namespace Content.Server.GameObjects.Components.Observer return; } - Player.ContentData()?.Mind?.TransferTo(_newMob); + var mind = Player.ContentData()?.Mind; + mind?.TransferTo(_newMob); + mind?.UnVisit(); Close(); } } diff --git a/Content.Server/GameObjects/Components/Observer/GhostComponent.cs b/Content.Server/GameObjects/Components/Observer/GhostComponent.cs index b68b0f3a21..bf1e95f91a 100644 --- a/Content.Server/GameObjects/Components/Observer/GhostComponent.cs +++ b/Content.Server/GameObjects/Components/Observer/GhostComponent.cs @@ -72,6 +72,26 @@ namespace Content.Server.GameObjects.Components.Observer base.Shutdown(); } + public override void OnAdd() + { + base.OnAdd(); + + if (Owner.TryGetComponent(out var mind)) + { + mind.GhostOnShutdown = false; + } + } + + public override void OnRemove() + { + base.OnRemove(); + + if (Owner.TryGetComponent(out var mind)) + { + mind.GhostOnShutdown = true; + } + } + public override ComponentState GetComponentState(ICommonSession player) => new GhostComponentState(CanReturnToBody); public override void HandleNetworkMessage(ComponentMessage message, INetChannel netChannel, ICommonSession? session = null!) @@ -92,13 +112,12 @@ namespace Content.Server.GameObjects.Components.Observer { var o = actor.playerSession.ContentData()!.Mind; o?.UnVisit(); - Owner.Delete(); } break; } case ReturnToCloneComponentMessage _: - if (Owner.TryGetComponent(out VisitingMindComponent? mind)) + if (Owner.TryGetComponent(out VisitingMindComponent? mind) && mind.Mind != null) { Owner.EntityManager.EventBus.RaiseEvent(EventSource.Local, new GhostReturnMessage(mind.Mind)); } diff --git a/Content.Server/GameObjects/EntitySystems/GhostSystem.cs b/Content.Server/GameObjects/EntitySystems/GhostSystem.cs new file mode 100644 index 0000000000..df704048ab --- /dev/null +++ b/Content.Server/GameObjects/EntitySystems/GhostSystem.cs @@ -0,0 +1,44 @@ +#nullable enable +using Content.Server.GameObjects.Components.Mobs; +using Content.Server.GameObjects.Components.Observer; +using JetBrains.Annotations; +using Robust.Server.GameObjects; +using Robust.Shared.GameObjects; +using System; + +namespace Content.Server.GameObjects.EntitySystems +{ + [UsedImplicitly] + public class GhostSystem : EntitySystem + { + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnMindRemovedMessage); + SubscribeLocalEvent(OnMindUnvisitedMessage); + } + + private void OnMindRemovedMessage(EntityUid uid, GhostComponent component, MindRemovedMessage args) + { + if (!EntityManager.TryGetEntity(uid, out var entity)) + return; + DeleteEntity(entity); + } + + private void OnMindUnvisitedMessage(EntityUid uid, GhostComponent component, MindUnvisitedMessage args) + { + if (!EntityManager.TryGetEntity(uid, out var entity)) + return; + DeleteEntity(entity); + } + + private void DeleteEntity(IEntity? entity) + { + if (entity?.Deleted == true) + return; + + entity?.Delete(); + } + } +} diff --git a/Content.Server/GameTicking/GamePreset.cs b/Content.Server/GameTicking/GamePreset.cs index 7a3ca2287a..ed61a016c7 100644 --- a/Content.Server/GameTicking/GamePreset.cs +++ b/Content.Server/GameTicking/GamePreset.cs @@ -45,7 +45,6 @@ namespace Content.Server.GameTicking if (mind.VisitingEntity != null) { mind.UnVisit(); - mind.VisitingEntity.Delete(); } var position = playerEntity?.Transform.Coordinates ?? IoCManager.Resolve().GetObserverSpawnPoint(); diff --git a/Content.Server/GameTicking/GameTicker.cs b/Content.Server/GameTicking/GameTicker.cs index f305495498..f44761d123 100644 --- a/Content.Server/GameTicking/GameTicker.cs +++ b/Content.Server/GameTicking/GameTicker.cs @@ -416,13 +416,8 @@ namespace Content.Server.GameTicking public void Respawn(IPlayerSession targetPlayer) { - var ghost = targetPlayer.AttachedEntity?.GetComponentOrNull(); - targetPlayer.ContentData()?.WipeMind(); - if (ghost?.Deleted == false) - ghost.Owner.Delete(); - if (LobbyEnabled) _playerJoinLobby(targetPlayer); else diff --git a/Content.Server/GlobalVerbs/ControlMobVerb.cs b/Content.Server/GlobalVerbs/ControlMobVerb.cs index c28dd69c4a..e051ec19fc 100644 --- a/Content.Server/GlobalVerbs/ControlMobVerb.cs +++ b/Content.Server/GlobalVerbs/ControlMobVerb.cs @@ -55,13 +55,9 @@ namespace Content.Server.GlobalVerbs var userMind = player.ContentData()?.Mind; var targetMind = target.GetComponent(); - var oldEntity = userMind?.CurrentEntity; targetMind.Mind?.TransferTo(null); userMind?.TransferTo(target); - - if (oldEntity != null && oldEntity.HasComponent()) - oldEntity.Delete(); } } } diff --git a/Content.Server/Mobs/Mind.cs b/Content.Server/Mobs/Mind.cs index 17db9bf2ce..29885ee342 100644 --- a/Content.Server/Mobs/Mind.cs +++ b/Content.Server/Mobs/Mind.cs @@ -313,6 +313,8 @@ namespace Content.Server.Mobs { oldVisitingEnt.RemoveComponent(); } + + oldVisitingEnt.EntityManager.EventBus.RaiseLocalEvent(oldVisitingEnt.Uid, new MindUnvisitedMessage()); } public bool TryGetSession([NotNullWhen(true)] out IPlayerSession? session)