]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
Changeling cleanup and bugfix (#39843)
authorslarticodefast <161409025+slarticodefast@users.noreply.github.com>
Sun, 24 Aug 2025 13:50:19 +0000 (15:50 +0200)
committerGitHub <noreply@github.com>
Sun, 24 Aug 2025 13:50:19 +0000 (15:50 +0200)
* fixes and cleanup

* key

Content.Client/Changeling/Systems/ChangelingIdentitySystem.cs [new file with mode: 0644]
Content.Client/Changeling/UI/ChangelingTransformBoundUserInterface.cs [moved from Content.Client/Changeling/Transform/ChangelingTransformBoundUserInterface.cs with 72% similarity]
Content.Client/Changeling/UI/ChangelingTransformMenu.xaml [moved from Content.Client/Changeling/Transform/ChangelingTransformMenu.xaml with 100% similarity]
Content.Client/Changeling/UI/ChangelingTransformMenu.xaml.cs [moved from Content.Client/Changeling/Transform/ChangelingTransformMenu.xaml.cs with 80% similarity]
Content.Server/Changeling/Systems/ChangelingIdentitySystem.cs [new file with mode: 0644]
Content.Shared/Changeling/Components/ChangelingIdentityComponent.cs
Content.Shared/Changeling/Systems/ChangelingDevourSystem.cs
Content.Shared/Changeling/Systems/ChangelingTransformSystem.UI.cs
Content.Shared/Changeling/Systems/ChangelingTransformSystem.cs
Content.Shared/Changeling/Systems/SharedChangelingIdentitySystem.cs [moved from Content.Shared/Changeling/Systems/ChangelingIdentitySystem.cs with 68% similarity]

diff --git a/Content.Client/Changeling/Systems/ChangelingIdentitySystem.cs b/Content.Client/Changeling/Systems/ChangelingIdentitySystem.cs
new file mode 100644 (file)
index 0000000..348cfee
--- /dev/null
@@ -0,0 +1,30 @@
+using Content.Shared.Changeling.Components;
+using Content.Shared.Changeling.Systems;
+using Robust.Client.GameObjects;
+
+namespace Content.Client.Changeling.Systems;
+
+public sealed class ChangelingIdentitySystem : SharedChangelingIdentitySystem
+{
+    [Dependency] private readonly UserInterfaceSystem _ui = default!;
+
+    public override void Initialize()
+    {
+        base.Initialize();
+
+        SubscribeLocalEvent<ChangelingIdentityComponent, AfterAutoHandleStateEvent>(OnAfterAutoHandleState);
+    }
+
+    private void OnAfterAutoHandleState(Entity<ChangelingIdentityComponent> ent, ref AfterAutoHandleStateEvent args)
+    {
+        UpdateUi(ent);
+    }
+
+    public void UpdateUi(EntityUid uid)
+    {
+        if (_ui.TryGetOpenUi(uid, ChangelingTransformUiKey.Key, out var bui))
+        {
+            bui.Update();
+        }
+    }
+}
similarity index 72%
rename from Content.Client/Changeling/Transform/ChangelingTransformBoundUserInterface.cs
rename to Content.Client/Changeling/UI/ChangelingTransformBoundUserInterface.cs
index 94012313035b58058f9503e945d010a0c97815c9..8220e1870891631a59e0c863f0c0936e6477cfc4 100644 (file)
@@ -2,7 +2,7 @@
 using JetBrains.Annotations;
 using Robust.Client.UserInterface;
 
-namespace Content.Client.Changeling.Transform;
+namespace Content.Client.Changeling.UI;
 
 [UsedImplicitly]
 public sealed partial class ChangelingTransformBoundUserInterface(EntityUid owner, Enum uiKey) : BoundUserInterface(owner, uiKey)
@@ -16,16 +16,16 @@ public sealed partial class ChangelingTransformBoundUserInterface(EntityUid owne
         _window = this.CreateWindow<ChangelingTransformMenu>();
 
         _window.OnIdentitySelect += SendIdentitySelect;
+
+        _window.Update(Owner);
     }
 
-    protected override void UpdateState(BoundUserInterfaceState state)
+    public override void Update()
     {
-        base.UpdateState(state);
-
-        if (state is not ChangelingTransformBoundUserInterfaceState current)
+        if (_window == null)
             return;
 
-        _window?.UpdateState(current);
+        _window.Update(Owner);
     }
 
     public void SendIdentitySelect(NetEntity identityId)
similarity index 80%
rename from Content.Client/Changeling/Transform/ChangelingTransformMenu.xaml.cs
rename to Content.Client/Changeling/UI/ChangelingTransformMenu.xaml.cs
index fa2deaf4313cdf08206d0a4d63f8a4b761d91f19..ebd4e90440088e0e33de723a47a21e1bdca10e7a 100644 (file)
@@ -1,11 +1,11 @@
 using System.Numerics;
 using Content.Client.UserInterface.Controls;
-using Content.Shared.Changeling.Systems;
+using Content.Shared.Changeling.Components;
 using Robust.Client.AutoGenerated;
 using Robust.Client.UserInterface.Controls;
 using Robust.Client.UserInterface.XAML;
 
-namespace Content.Client.Changeling.Transform;
+namespace Content.Client.Changeling.UI;
 
 [GenerateTypedNameReferences]
 public sealed partial class ChangelingTransformMenu : RadialMenu
@@ -19,13 +19,15 @@ public sealed partial class ChangelingTransformMenu : RadialMenu
         IoCManager.InjectDependencies(this);
     }
 
-    public void UpdateState(ChangelingTransformBoundUserInterfaceState state)
+    public void Update(EntityUid uid)
     {
         Main.DisposeAllChildren();
-        foreach (var identity in state.Identites)
-        {
-            var identityUid = _entity.GetEntity(identity);
 
+        if (!_entity.TryGetComponent<ChangelingIdentityComponent>(uid, out var identityComp))
+            return;
+
+        foreach (var identityUid in identityComp.ConsumedIdentities)
+        {
             if (!_entity.TryGetComponent<MetaDataComponent>(identityUid, out var metadata))
                 continue;
 
@@ -48,7 +50,7 @@ public sealed partial class ChangelingTransformMenu : RadialMenu
             entView.SetEntity(identityUid);
             button.OnButtonUp += _ =>
             {
-                OnIdentitySelect?.Invoke(identity);
+                OnIdentitySelect?.Invoke(_entity.GetNetEntity(identityUid));
                 Close();
             };
             button.AddChild(entView);
diff --git a/Content.Server/Changeling/Systems/ChangelingIdentitySystem.cs b/Content.Server/Changeling/Systems/ChangelingIdentitySystem.cs
new file mode 100644 (file)
index 0000000..8cb3dec
--- /dev/null
@@ -0,0 +1,5 @@
+using Content.Shared.Changeling.Systems;
+
+namespace Content.Server.Changeling.Systems;
+
+public sealed class ChangelingIdentitySystem : SharedChangelingIdentitySystem;
index 2779164e4e099c4a1eb5fbc1267aebc2474671a5..8e74f83537355597d9635cd0fb6cf255b9e36b39 100644 (file)
@@ -8,7 +8,7 @@ namespace Content.Shared.Changeling.Components;
 /// The storage component for Changelings, it handles the link between a changeling and its consumed identities
 /// that exist on a paused map.
 /// </summary>
-[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
+[RegisterComponent, NetworkedComponent, AutoGenerateComponentState(raiseAfterAutoHandleState: true)]
 public sealed partial class ChangelingIdentityComponent : Component
 {
     /// <summary>
index a064858d43f77dbdcbfcbe94e0b692d80ac53fad..500ee06b22d1d04d1be28a4cf5296a5d367211b6 100644 (file)
@@ -32,7 +32,7 @@ public sealed class ChangelingDevourSystem : EntitySystem
     [Dependency] private readonly EntityWhitelistSystem _whitelistSystem = default!;
     [Dependency] private readonly DamageableSystem _damageable = default!;
     [Dependency] private readonly MobStateSystem _mobState = default!;
-    [Dependency] private readonly ChangelingIdentitySystem _changelingIdentitySystem = default!;
+    [Dependency] private readonly SharedChangelingIdentitySystem _changelingIdentitySystem = default!;
     [Dependency] private readonly InventorySystem _inventorySystem = default!;
     [Dependency] private readonly SharedAudioSystem _audio = default!;
     [Dependency] private readonly ISharedAdminLogManager _adminLogger = default!;
index 98926631dc95b1ca09fb26864af1e63e7e4b97ea..e55514735281bfb5edcdd53c671d09222068a022 100644 (file)
@@ -14,20 +14,8 @@ public sealed class ChangelingTransformIdentitySelectMessage(NetEntity targetIde
     public readonly NetEntity TargetIdentity = targetIdentity;
 }
 
-// TODO: Replace with component states.
-// We are already networking the ChangelingIdentityComponent, which contains all this information,
-// so we can just read it from them from the component and update the UI in an AfterAuotHandleState subscription.
 [Serializable, NetSerializable]
-public sealed class ChangelingTransformBoundUserInterfaceState(List<NetEntity> identities) : BoundUserInterfaceState
-{
-    /// <summary>
-    /// The uids of the cloned identities.
-    /// </summary>
-    public readonly List<NetEntity> Identites = identities;
-}
-
-[Serializable, NetSerializable]
-public enum TransformUI : byte
+public enum ChangelingTransformUiKey : byte
 {
     Key,
 }
index 31f22b9294dc6eb7ae5aa869d203bc930b7b92ee..cf8d9d7cb6ee247a278eceb2b273ca435dd3d8a7 100644 (file)
@@ -44,7 +44,7 @@ public sealed partial class ChangelingTransformSystem : EntitySystem
         _actionsSystem.AddAction(ent, ref ent.Comp.ChangelingTransformActionEntity, ent.Comp.ChangelingTransformAction);
 
         var userInterfaceComp = EnsureComp<UserInterfaceComponent>(ent);
-        _uiSystem.SetUi((ent, userInterfaceComp), TransformUI.Key, new InterfaceData(ChangelingBuiXmlGeneratedName));
+        _uiSystem.SetUi((ent, userInterfaceComp), ChangelingTransformUiKey.Key, new InterfaceData(ChangelingBuiXmlGeneratedName));
     }
 
     private void OnShutdown(Entity<ChangelingTransformComponent> ent, ref ComponentShutdown args)
@@ -64,18 +64,9 @@ public sealed partial class ChangelingTransformSystem : EntitySystem
         if (!TryComp<ChangelingIdentityComponent>(ent, out var userIdentity))
             return;
 
-        if (!_uiSystem.IsUiOpen((ent, userInterfaceComp), TransformUI.Key, args.Performer))
+        if (!_uiSystem.IsUiOpen((ent, userInterfaceComp), ChangelingTransformUiKey.Key, args.Performer))
         {
-            _uiSystem.OpenUi((ent, userInterfaceComp), TransformUI.Key, args.Performer);
-
-            var identityData = new List<NetEntity>();
-
-            foreach (var consumedIdentity in userIdentity.ConsumedIdentities)
-            {
-                identityData.Add(GetNetEntity(consumedIdentity));
-            }
-
-            _uiSystem.SetUiState((ent, userInterfaceComp), TransformUI.Key, new ChangelingTransformBoundUserInterfaceState(identityData));
+            _uiSystem.OpenUi((ent, userInterfaceComp), ChangelingTransformUiKey.Key, args.Performer);
         } //TODO: Can add a Else here with TransformInto and CloseUI to make a quick switch,
           // issue right now is that Radials cover the Action buttons so clicking the action closes the UI (due to clicking off a radial causing it to close, even with UI)
           // but pressing the number does.
@@ -108,7 +99,7 @@ public sealed partial class ChangelingTransformSystem : EntitySystem
         else
             _adminLogger.Add(LogType.Action, LogImpact.Medium, $"{ToPrettyString(ent.Owner):player} begun an attempt to transform into \"{Name(targetIdentity)}\"");
 
-        var result = _doAfterSystem.TryStartDoAfter(new DoAfterArgs(
+        _doAfterSystem.TryStartDoAfter(new DoAfterArgs(
             EntityManager,
             ent,
             ent.Comp.TransformWindup,
@@ -127,7 +118,7 @@ public sealed partial class ChangelingTransformSystem : EntitySystem
     private void OnTransformSelected(Entity<ChangelingTransformComponent> ent,
         ref ChangelingTransformIdentitySelectMessage args)
     {
-        _uiSystem.CloseUi(ent.Owner, TransformUI.Key, ent);
+        _uiSystem.CloseUi(ent.Owner, ChangelingTransformUiKey.Key, ent);
 
         if (!TryGetEntity(args.TargetIdentity, out var targetIdentity))
             return;
similarity index 68%
rename from Content.Shared/Changeling/Systems/ChangelingIdentitySystem.cs
rename to Content.Shared/Changeling/Systems/SharedChangelingIdentitySystem.cs
index 8467cc570211247fbf00cb1b4f7c4237c91c9c8a..e7e46d79a1f16a8ecfaf00a478d4b6fed2a20a89 100644 (file)
@@ -2,7 +2,6 @@
 using Content.Shared.Changeling.Components;
 using Content.Shared.Cloning;
 using Content.Shared.Humanoid;
-using Content.Shared.Mind.Components;
 using Content.Shared.NameModifier.EntitySystems;
 using Robust.Shared.GameStates;
 using Robust.Shared.Map;
@@ -12,7 +11,7 @@ using Robust.Shared.Prototypes;
 
 namespace Content.Shared.Changeling.Systems;
 
-public sealed class ChangelingIdentitySystem : EntitySystem
+public abstract class SharedChangelingIdentitySystem : EntitySystem
 {
     [Dependency] private readonly INetManager _net = default!;
     [Dependency] private readonly IPrototypeManager _prototype = default!;
@@ -32,22 +31,19 @@ public sealed class ChangelingIdentitySystem : EntitySystem
 
         SubscribeLocalEvent<ChangelingIdentityComponent, MapInitEvent>(OnMapInit);
         SubscribeLocalEvent<ChangelingIdentityComponent, ComponentShutdown>(OnShutdown);
-        SubscribeLocalEvent<ChangelingIdentityComponent, MindAddedMessage>(OnMindAdded);
-        SubscribeLocalEvent<ChangelingIdentityComponent, MindRemovedMessage>(OnMindRemoved);
+        SubscribeLocalEvent<ChangelingIdentityComponent, PlayerAttachedEvent>(OnPlayerAttached);
+        SubscribeLocalEvent<ChangelingIdentityComponent, PlayerDetachedEvent>(OnPlayerDetached);
         SubscribeLocalEvent<ChangelingStoredIdentityComponent, ComponentRemove>(OnStoredRemove);
     }
 
-    private void OnMindAdded(Entity<ChangelingIdentityComponent> ent, ref MindAddedMessage args)
+    private void OnPlayerAttached(Entity<ChangelingIdentityComponent> ent, ref PlayerAttachedEvent args)
     {
-        if (!TryComp<ActorComponent>(args.Container.Owner, out var actor))
-            return;
-
-        HandOverPvsOverride(actor.PlayerSession, ent.Comp);
+        HandOverPvsOverride(ent, args.Player);
     }
 
-    private void OnMindRemoved(Entity<ChangelingIdentityComponent> ent, ref MindRemovedMessage args)
+    private void OnPlayerDetached(Entity<ChangelingIdentityComponent> ent, ref PlayerDetachedEvent args)
     {
-        CleanupPvsOverride(ent, args.Container.Owner);
+        CleanupPvsOverride(ent, args.Player);
     }
 
     private void OnMapInit(Entity<ChangelingIdentityComponent> ent, ref MapInitEvent args)
@@ -59,7 +55,8 @@ public sealed class ChangelingIdentitySystem : EntitySystem
 
     private void OnShutdown(Entity<ChangelingIdentityComponent> ent, ref ComponentShutdown args)
     {
-        CleanupPvsOverride(ent, ent.Owner);
+        if (TryComp<ActorComponent>(ent, out var actor))
+            CleanupPvsOverride(ent, actor.PlayerSession);
         CleanupChangelingNullspaceIdentities(ent);
     }
 
@@ -107,66 +104,63 @@ public sealed class ChangelingIdentitySystem : EntitySystem
         // Movercontrollers and mob collisions are currently being calculated even for paused entities.
         // Spawning all of them in the same spot causes severe performance problems.
         // Cryopods and Polymorph have the same problem.
-        var mob = Spawn(speciesPrototype.Prototype, new MapCoordinates(new Vector2(2 * _numberOfStoredIdentities++, 0), PausedMapId!.Value));
+        var clone = Spawn(speciesPrototype.Prototype, new MapCoordinates(new Vector2(2 * _numberOfStoredIdentities++, 0), PausedMapId!.Value));
 
-        var storedIdentity = EnsureComp<ChangelingStoredIdentityComponent>(mob);
+        var storedIdentity = EnsureComp<ChangelingStoredIdentityComponent>(clone);
         storedIdentity.OriginalEntity = target; // TODO: network this once we have WeakEntityReference or the autonetworking source gen is fixed
 
         if (TryComp<ActorComponent>(target, out var actor))
             storedIdentity.OriginalSession = actor.PlayerSession;
 
-        _humanoidSystem.CloneAppearance(target, mob);
-        _cloningSystem.CloneComponents(target, mob, settings);
+        _humanoidSystem.CloneAppearance(target, clone);
+        _cloningSystem.CloneComponents(target, clone, settings);
 
         var targetName = _nameMod.GetBaseName(target);
-        _metaSystem.SetEntityName(mob, targetName);
-        ent.Comp.ConsumedIdentities.Add(mob);
+        _metaSystem.SetEntityName(clone, targetName);
+        ent.Comp.ConsumedIdentities.Add(clone);
 
         Dirty(ent);
-        HandlePvsOverride(ent, mob);
+        HandlePvsOverride(ent, clone);
 
-        return mob;
+        return clone;
     }
 
     /// <summary>
-    /// Simple helper to add a PVS override to a Nullspace Identity
+    /// Simple helper to add a PVS override to a nullspace identity.
     /// </summary>
-    /// <param name="uid"></param>
-    /// <param name="target"></param>
-    private void HandlePvsOverride(EntityUid uid, EntityUid target)
+    /// <param name="uid">The actor that should get the override.</param>
+    /// <param name="identity">The identity stored in nullspace.</param>
+    private void HandlePvsOverride(EntityUid uid, EntityUid identity)
     {
         if (!TryComp<ActorComponent>(uid, out var actor))
             return;
 
-        _pvsOverrideSystem.AddSessionOverride(target, actor.PlayerSession);
+        _pvsOverrideSystem.AddSessionOverride(identity, actor.PlayerSession);
     }
 
     /// <summary>
-    /// Cleanup all Pvs Overrides for the owner of the ChangelingIdentity
+    /// Cleanup all PVS overrides for the owner of the ChangelingIdentity
     /// </summary>
-    /// <param name="ent">the Changeling itself</param>
-    /// <param name="entityUid">Who specifically to cleanup from, usually just the same owner, but in the case of a mindswap we want to clean up the victim</param>
-    private void CleanupPvsOverride(Entity<ChangelingIdentityComponent> ent, EntityUid entityUid)
+    /// <param name="ent">The changeling storing the identities.</param>
+    /// <param name="entityUid"The session you wish to remove the overrides from.</param>
+    private void CleanupPvsOverride(Entity<ChangelingIdentityComponent> ent, ICommonSession session)
     {
-        if (!TryComp<ActorComponent>(entityUid, out var actor))
-            return;
-
         foreach (var identity in ent.Comp.ConsumedIdentities)
         {
-            _pvsOverrideSystem.RemoveSessionOverride(identity, actor.PlayerSession);
+            _pvsOverrideSystem.RemoveSessionOverride(identity, session);
         }
     }
 
     /// <summary>
-    /// Inform another Session of the entities stored for Transformation
+    /// Inform another session of the entities stored for transformation.
     /// </summary>
-    /// <param name="session">The Session you wish to inform</param>
-    /// <param name="comp">The Target storage of identities</param>
-    public void HandOverPvsOverride(ICommonSession session, ChangelingIdentityComponent comp)
+    /// <param name="ent">The changeling storing the identities.</param>
+    /// <param name="session">The session you wish to inform.</param>
+    public void HandOverPvsOverride(Entity<ChangelingIdentityComponent> ent, ICommonSession session)
     {
-        foreach (var entity in comp.ConsumedIdentities)
+        foreach (var identity in ent.Comp.ConsumedIdentities)
         {
-            _pvsOverrideSystem.AddSessionOverride(entity, session);
+            _pvsOverrideSystem.AddSessionOverride(identity, session);
         }
     }