From 3e599e230674684b62f2ee4e5afe95ed6d85c96f Mon Sep 17 00:00:00 2001 From: Leon Friedrich <60421075+ElectroJr@users.noreply.github.com> Date: Mon, 31 Jul 2023 15:57:52 +1200 Subject: [PATCH] Add missing CleanReturnAsync() to some tests. (#18471) --- .../Tests/Body/SaveLoadReparentTest.cs | 4 ++ .../Tests/LogErrorTest.cs | 2 + .../Tests/Networking/ConnectTest.cs | 2 + Content.Server/Body/Systems/BodySystem.cs | 65 ++++++++++++++++++- Content.Shared/Body/Organ/OrganComponent.cs | 3 +- Content.Shared/Body/Part/BodyPartComponent.cs | 7 +- .../Body/Systems/SharedBodySystem.Body.cs | 2 +- .../Body/Systems/SharedBodySystem.Parts.cs | 6 +- 8 files changed, 84 insertions(+), 7 deletions(-) diff --git a/Content.IntegrationTests/Tests/Body/SaveLoadReparentTest.cs b/Content.IntegrationTests/Tests/Body/SaveLoadReparentTest.cs index d89048ce53..c6a13a5861 100644 --- a/Content.IntegrationTests/Tests/Body/SaveLoadReparentTest.cs +++ b/Content.IntegrationTests/Tests/Body/SaveLoadReparentTest.cs @@ -157,7 +157,11 @@ public sealed class SaveLoadReparentTest Assert.That(component.ParentSlot.Child, Is.EqualTo(id)); }); } + + maps.DeleteMap(mapId); } }); + + await pairTracker.CleanReturnAsync(); } } diff --git a/Content.IntegrationTests/Tests/LogErrorTest.cs b/Content.IntegrationTests/Tests/LogErrorTest.cs index 733d6d3b82..a8ebb6d7b0 100644 --- a/Content.IntegrationTests/Tests/LogErrorTest.cs +++ b/Content.IntegrationTests/Tests/LogErrorTest.cs @@ -28,5 +28,7 @@ public sealed class LogErrorTest // But errors do await server.WaitPost(() => Assert.Throws(() => logmill.Error("test"))); await client.WaitPost(() => Assert.Throws(() => logmill.Error("test"))); + + await pairTracker.CleanReturnAsync(); } } diff --git a/Content.IntegrationTests/Tests/Networking/ConnectTest.cs b/Content.IntegrationTests/Tests/Networking/ConnectTest.cs index 23f995a9b4..8433c84ee4 100644 --- a/Content.IntegrationTests/Tests/Networking/ConnectTest.cs +++ b/Content.IntegrationTests/Tests/Networking/ConnectTest.cs @@ -30,6 +30,8 @@ namespace Content.IntegrationTests.Tests.Networking Assert.That(clEntityManager.GetComponent(lastSvEntity).Coordinates, Is.EqualTo(svEntityManager.GetComponent(lastSvEntity).Coordinates)); + + await pairTracker.CleanReturnAsync(); } } } diff --git a/Content.Server/Body/Systems/BodySystem.cs b/Content.Server/Body/Systems/BodySystem.cs index 57603c35dc..43294976fe 100644 --- a/Content.Server/Body/Systems/BodySystem.cs +++ b/Content.Server/Body/Systems/BodySystem.cs @@ -5,8 +5,8 @@ using Content.Server.GameTicking; using Content.Server.Humanoid; using Content.Server.Kitchen.Components; using Content.Server.Mind; -using Content.Server.Mind.Components; using Content.Shared.Body.Components; +using Content.Shared.Body.Organ; using Content.Shared.Body.Part; using Content.Shared.Body.Prototypes; using Content.Shared.Body.Systems; @@ -36,11 +36,74 @@ public sealed class BodySystem : SharedBodySystem { base.Initialize(); + SubscribeLocalEvent(OnPartStartup); + SubscribeLocalEvent(OnBodyStartup); SubscribeLocalEvent(OnRelayMoveInput); SubscribeLocalEvent(OnApplyMetabolicMultiplier); SubscribeLocalEvent(OnBeingMicrowaved); } + private void OnPartStartup(EntityUid uid, BodyPartComponent component, ComponentStartup args) + { + // This inter-entity relationship makes be deeply uncomfortable because its probably going to re-encounter + // all of the networking & startup ordering issues that containers and joints have. + // TODO just use containers. Please. + + foreach (var slot in component.Children.Values) + { + DebugTools.Assert(slot.Parent == uid); + if (slot.Child == null) + continue; + + if (TryComp(slot.Child, out BodyPartComponent? child)) + { + child.ParentSlot = slot; + Dirty(slot.Child.Value); + continue; + } + + Log.Error($"Body part encountered missing limbs: {ToPrettyString(uid)}. Slot: {slot.Id}"); + slot.Child = null; + } + + foreach (var slot in component.Organs.Values) + { + DebugTools.Assert(slot.Parent == uid); + if (slot.Child == null) + continue; + + if (TryComp(slot.Child, out OrganComponent? child)) + { + child.ParentSlot = slot; + Dirty(slot.Child.Value); + continue; + } + + Log.Error($"Body part encountered missing organ: {ToPrettyString(uid)}. Slot: {slot.Id}"); + slot.Child = null; + } + } + + private void OnBodyStartup(EntityUid uid, BodyComponent component, ComponentStartup args) + { + if (component.Root is not { } slot) + return; + + DebugTools.Assert(slot.Parent == uid); + if (slot.Child == null) + return; + + if (!TryComp(slot.Child, out BodyPartComponent? child)) + { + Log.Error($"Body part encountered missing limbs: {ToPrettyString(uid)}. Slot: {slot.Id}"); + slot.Child = null; + return; + } + + child.ParentSlot = slot; + Dirty(slot.Child.Value); + } + private void OnRelayMoveInput(EntityUid uid, BodyComponent component, ref MoveInputEvent args) { if (_mobState.IsDead(uid) && _mindSystem.TryGetMind(uid, out var mind)) diff --git a/Content.Shared/Body/Organ/OrganComponent.cs b/Content.Shared/Body/Organ/OrganComponent.cs index bd0465ff36..ac676e9980 100644 --- a/Content.Shared/Body/Organ/OrganComponent.cs +++ b/Content.Shared/Body/Organ/OrganComponent.cs @@ -10,6 +10,7 @@ public sealed class OrganComponent : Component [DataField("body")] public EntityUid? Body; - [DataField("parent")] + // TODO use containers. See comments in BodyPartComponent. + // Do not rely on this in client-side code. public OrganSlot? ParentSlot; } diff --git a/Content.Shared/Body/Part/BodyPartComponent.cs b/Content.Shared/Body/Part/BodyPartComponent.cs index 1cc333b9bb..6e06b1dc0d 100644 --- a/Content.Shared/Body/Part/BodyPartComponent.cs +++ b/Content.Shared/Body/Part/BodyPartComponent.cs @@ -12,12 +12,17 @@ public sealed class BodyPartComponent : Component [DataField("body")] public EntityUid? Body; - [DataField("parent")] + // This inter-entity relationship makes be deeply uncomfortable because its probably going to re-encounter all of the + // networking issues that containers and joints have. + // TODO just use containers. Please. + // Do not use set or get data from this in client-side code. public BodyPartSlot? ParentSlot; + // Do not use set or get data from this in client-side code. [DataField("children")] public Dictionary Children = new(); + // See all the above ccomments. [DataField("organs")] public Dictionary Organs = new(); diff --git a/Content.Shared/Body/Systems/SharedBodySystem.Body.cs b/Content.Shared/Body/Systems/SharedBodySystem.Body.cs index 3b464ca115..45cb9bfa6d 100644 --- a/Content.Shared/Body/Systems/SharedBodySystem.Body.cs +++ b/Content.Shared/Body/Systems/SharedBodySystem.Body.cs @@ -48,7 +48,7 @@ public partial class SharedBodySystem if (args.Current is not BodyComponentState state) return; - body.Root = state.Root; + body.Root = state.Root; // TODO use containers. This is broken and does not work. body.GibSound = state.GibSound; } diff --git a/Content.Shared/Body/Systems/SharedBodySystem.Parts.cs b/Content.Shared/Body/Systems/SharedBodySystem.Parts.cs index eab2dae602..c0c1c963b4 100644 --- a/Content.Shared/Body/Systems/SharedBodySystem.Parts.cs +++ b/Content.Shared/Body/Systems/SharedBodySystem.Parts.cs @@ -42,9 +42,9 @@ public partial class SharedBodySystem return; part.Body = state.Body; - part.ParentSlot = state.ParentSlot; - part.Children = state.Children; - part.Organs = state.Organs; + part.ParentSlot = state.ParentSlot; // TODO use containers. This is broken and does not work. + part.Children = state.Children; // TODO use containers. This is broken and does not work. + part.Organs = state.Organs; // TODO end my suffering. part.PartType = state.PartType; part.IsVital = state.IsVital; part.Symmetry = state.Symmetry;