Skip to content

Commit

Permalink
Body code cleanup (#24946)
Browse files Browse the repository at this point in the history
* Fix test

* Kill float accumulators

* Use entity proxy methods

* DataField auto name generation where possible

* Kill comp properties

* Clean up server comps

* Make events record structs

* Clean up shared body code

* Clean up server body code

* Rename organ events to be same names as in med refactor
  • Loading branch information
0x6273 authored Mar 28, 2024
1 parent 527c2c4 commit 37b8d78
Show file tree
Hide file tree
Showing 32 changed files with 914 additions and 818 deletions.
39 changes: 18 additions & 21 deletions Content.IntegrationTests/Tests/Body/LungTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
using Robust.Shared.GameObjects;
using Robust.Shared.Map;
using Robust.Shared.Map.Components;
using Robust.Shared.Maths;
using System.Linq;
using System.Numerics;

Expand Down Expand Up @@ -61,12 +60,11 @@ public async Task AirConsistencyTest()
var mapManager = server.ResolveDependency<IMapManager>();
var entityManager = server.ResolveDependency<IEntityManager>();
var mapLoader = entityManager.System<MapLoaderSystem>();
RespiratorSystem respSys = default;
MetabolizerSystem metaSys = default;

MapId mapId;
EntityUid? grid = null;
BodyComponent body = default;
RespiratorComponent resp = default;
EntityUid human = default;
GridAtmosphereComponent relevantAtmos = default;
var startingMoles = 0.0f;
Expand Down Expand Up @@ -99,17 +97,15 @@ float GetMapMoles()

await server.WaitAssertion(() =>
{
var coords = new Vector2(0.5f, -1f);
var coordinates = new EntityCoordinates(grid.Value, coords);
var center = new Vector2(0.5f, 0.5f);
var coordinates = new EntityCoordinates(grid.Value, center);
human = entityManager.SpawnEntity("HumanLungDummy", coordinates);
respSys = entityManager.System<RespiratorSystem>();
metaSys = entityManager.System<MetabolizerSystem>();
relevantAtmos = entityManager.GetComponent<GridAtmosphereComponent>(grid.Value);
startingMoles = GetMapMoles();
startingMoles = 100f; // Hardcoded because GetMapMoles returns 900 here for some reason.
#pragma warning disable NUnit2045
Assert.That(entityManager.TryGetComponent(human, out body), Is.True);
Assert.That(entityManager.HasComponent<RespiratorComponent>(human), Is.True);
Assert.That(entityManager.TryGetComponent(human, out resp), Is.True);
#pragma warning restore NUnit2045
});

Expand All @@ -118,18 +114,19 @@ await server.WaitAssertion(() =>
var inhaleCycles = 100;
for (var i = 0; i < inhaleCycles; i++)
{
await server.WaitAssertion(() =>
{
// inhale
respSys.Update(2.0f);
Assert.That(GetMapMoles(), Is.LessThan(startingMoles));
// metabolize + exhale
metaSys.Update(1.0f);
metaSys.Update(1.0f);
respSys.Update(2.0f);
Assert.That(GetMapMoles(), Is.EqualTo(startingMoles).Within(0.0002));
});
// Breathe in
await PoolManager.WaitUntil(server, () => resp.Status == RespiratorStatus.Exhaling);
Assert.That(
GetMapMoles(), Is.LessThan(startingMoles),
"Did not inhale in any gas"
);

// Breathe out
await PoolManager.WaitUntil(server, () => resp.Status == RespiratorStatus.Inhaling);
Assert.That(
GetMapMoles(), Is.EqualTo(startingMoles).Within(0.0002),
"Did not exhale as much gas as was inhaled"
);
}

await pair.CleanReturnAsync();
Expand Down
10 changes: 4 additions & 6 deletions Content.Server/Bed/BedSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -93,9 +93,8 @@ private void OnBuckleChange(EntityUid uid, StasisBedComponent component, ref Buc
if (!this.IsPowered(uid, EntityManager))
return;

var metabolicEvent = new ApplyMetabolicMultiplierEvent
{Uid = args.BuckledEntity, Multiplier = component.Multiplier, Apply = args.Buckling};
RaiseLocalEvent(args.BuckledEntity, metabolicEvent);
var metabolicEvent = new ApplyMetabolicMultiplierEvent(args.BuckledEntity, component.Multiplier, args.Buckling);
RaiseLocalEvent(args.BuckledEntity, ref metabolicEvent);
}

private void OnPowerChanged(EntityUid uid, StasisBedComponent component, ref PowerChangedEvent args)
Expand All @@ -121,9 +120,8 @@ private void UpdateMetabolisms(EntityUid uid, StasisBedComponent component, bool

foreach (var buckledEntity in strap.BuckledEntities)
{
var metabolicEvent = new ApplyMetabolicMultiplierEvent
{Uid = buckledEntity, Multiplier = component.Multiplier, Apply = shouldApply};
RaiseLocalEvent(buckledEntity, metabolicEvent);
var metabolicEvent = new ApplyMetabolicMultiplierEvent(buckledEntity, component.Multiplier, shouldApply);
RaiseLocalEvent(buckledEntity, ref metabolicEvent);
}
}
}
Expand Down
86 changes: 41 additions & 45 deletions Content.Server/Body/Commands/AddHandCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ public void Execute(IConsoleShell shell, string argStr, string[] args)
switch (args.Length)
{
case 0:
{
if (player == null)
{
shell.WriteLine("Only a player can run this command without arguments.");
Expand All @@ -50,71 +49,68 @@ public void Execute(IConsoleShell shell, string argStr, string[] args)
entity = player.AttachedEntity.Value;
hand = _entManager.SpawnEntity(DefaultHandPrototype, _entManager.GetComponent<TransformComponent>(entity).Coordinates);
break;
}
case 1:
{
if (NetEntity.TryParse(args[0], out var uidNet) && _entManager.TryGetEntity(uidNet, out var uid))
{
if (!_entManager.EntityExists(uid))
if (NetEntity.TryParse(args[0], out var uidNet) && _entManager.TryGetEntity(uidNet, out var uid))
{
shell.WriteLine($"No entity found with uid {uid}");
return;
if (!_entManager.EntityExists(uid))
{
shell.WriteLine($"No entity found with uid {uid}");
return;
}

entity = uid.Value;
hand = _entManager.SpawnEntity(DefaultHandPrototype, _entManager.GetComponent<TransformComponent>(entity).Coordinates);
}
else
{
if (player == null)
{
shell.WriteLine("You must specify an entity to add a hand to when using this command from the server terminal.");
return;
}

if (player.AttachedEntity == null)
{
shell.WriteLine("You don't have an entity to add a hand to.");
return;
}

entity = player.AttachedEntity.Value;
hand = _entManager.SpawnEntity(args[0], _entManager.GetComponent<TransformComponent>(entity).Coordinates);
}

entity = uid.Value;
hand = _entManager.SpawnEntity(DefaultHandPrototype, _entManager.GetComponent<TransformComponent>(entity).Coordinates);
break;
}
else
case 2:
{
if (player == null)
if (!NetEntity.TryParse(args[0], out var netEnt) || !_entManager.TryGetEntity(netEnt, out var uid))
{
shell.WriteLine("You must specify an entity to add a hand to when using this command from the server terminal.");
shell.WriteLine($"{args[0]} is not a valid entity uid.");
return;
}

if (player.AttachedEntity == null)
if (!_entManager.EntityExists(uid))
{
shell.WriteLine("You don't have an entity to add a hand to.");
shell.WriteLine($"No entity exists with uid {uid}.");
return;
}

entity = player.AttachedEntity.Value;
hand = _entManager.SpawnEntity(args[0], _entManager.GetComponent<TransformComponent>(entity).Coordinates);
}

break;
}
case 2:
{
if (!NetEntity.TryParse(args[0], out var netEnt) || !_entManager.TryGetEntity(netEnt, out var uid))
{
shell.WriteLine($"{args[0]} is not a valid entity uid.");
return;
}
entity = uid.Value;

if (!_entManager.EntityExists(uid))
{
shell.WriteLine($"No entity exists with uid {uid}.");
return;
}
if (!_protoManager.HasIndex<EntityPrototype>(args[1]))
{
shell.WriteLine($"No hand entity exists with id {args[1]}.");
return;
}

entity = uid.Value;
hand = _entManager.SpawnEntity(args[1], _entManager.GetComponent<TransformComponent>(entity).Coordinates);

if (!_protoManager.HasIndex<EntityPrototype>(args[1]))
{
shell.WriteLine($"No hand entity exists with id {args[1]}.");
return;
break;
}

hand = _entManager.SpawnEntity(args[1], _entManager.GetComponent<TransformComponent>(entity).Coordinates);

break;
}
default:
{
shell.WriteLine(Help);
return;
}
}

if (!_entManager.TryGetComponent(entity, out BodyComponent? body) || body.RootContainer.ContainedEntity == null)
Expand All @@ -139,7 +135,7 @@ public void Execute(IConsoleShell shell, string argStr, string[] args)

var slotId = part.GetHashCode().ToString();

if (!bodySystem.TryCreatePartSlotAndAttach(attachAt.Id, slotId, hand, BodyPartType.Hand,attachAt.Component, part))
if (!bodySystem.TryCreatePartSlotAndAttach(attachAt.Id, slotId, hand, BodyPartType.Hand, attachAt.Component, part))
{
shell.WriteError($"Couldn't create a slot with id {slotId} on entity {_entManager.ToPrettyString(entity)}");
return;
Expand Down
4 changes: 2 additions & 2 deletions Content.Server/Body/Commands/AttachBodyPartCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -103,11 +103,11 @@ public void Execute(IConsoleShell shell, string argStr, string[] args)
// ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract
if (body.RootContainer.ContainedEntity != null)
{
bodySystem.AttachPartToRoot(bodyId,partUid.Value, body ,part);
bodySystem.AttachPartToRoot(bodyId, partUid.Value, body, part);
}
else
{
var (rootPartId,rootPart) = bodySystem.GetRootPartOrNull(bodyId, body)!.Value;
var (rootPartId, rootPart) = bodySystem.GetRootPartOrNull(bodyId, body)!.Value;
if (!bodySystem.TryCreatePartSlotAndAttach(rootPartId, slotId, partUid.Value, part.PartType, rootPart, part))
{
shell.WriteError($"Could not create slot {slotId} on entity {_entManager.ToPrettyString(bodyId)}");
Expand Down
14 changes: 5 additions & 9 deletions Content.Server/Body/Components/BeingGibbedEvent.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
namespace Content.Server.Body.Components;

public sealed class BeingGibbedEvent : EntityEventArgs
{
public readonly HashSet<EntityUid> GibbedParts;

public BeingGibbedEvent(HashSet<EntityUid> gibbedParts)
{
GibbedParts = gibbedParts;
}
}
/// <summary>
/// Raised when a body gets gibbed, before it is deleted.
/// </summary>
[ByRefEvent]
public readonly record struct BeingGibbedEvent(HashSet<EntityUid> GibbedParts);
34 changes: 20 additions & 14 deletions Content.Server/Body/Components/BloodstreamComponent.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
using Content.Server.Body.Systems;
using Content.Server.Chemistry.EntitySystems;
using Content.Shared.Chemistry.Components;
using Content.Shared.Chemistry.Reagent;
using Content.Shared.Damage;
using Content.Shared.Damage.Prototypes;
using Content.Shared.FixedPoint;
using Robust.Shared.Audio;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;

namespace Content.Server.Body.Components
{
Expand All @@ -16,7 +18,17 @@ public sealed partial class BloodstreamComponent : Component
public static string DefaultBloodSolutionName = "bloodstream";
public static string DefaultBloodTemporarySolutionName = "bloodstreamTemporary";

public float AccumulatedFrametime = 0.0f;
/// <summary>
/// The next time that blood level will be updated and bloodloss damage dealt.
/// </summary>
[DataField(customTypeSerializer: typeof(TimeOffsetSerializer))]
public TimeSpan NextUpdate;

/// <summary>
/// The interval at which this component updates.
/// </summary>
[DataField]
public TimeSpan UpdateInterval = TimeSpan.FromSeconds(3);

/// <summary>
/// How much is this entity currently bleeding?
Expand All @@ -32,7 +44,7 @@ public sealed partial class BloodstreamComponent : Component
public float BleedAmount;

/// <summary>
/// How much should bleeding should be reduced every update interval?
/// How much should bleeding be reduced every update interval?
/// </summary>
[DataField]
public float BleedReductionAmount = 0.33f;
Expand Down Expand Up @@ -63,18 +75,12 @@ public sealed partial class BloodstreamComponent : Component
[DataField(required: true)]
public DamageSpecifier BloodlossHealDamage = new();

/// <summary>
/// How frequently should this bloodstream update, in seconds?
/// </summary>
[DataField]
public float UpdateInterval = 3.0f;

// TODO shouldn't be hardcoded, should just use some organ simulation like bone marrow or smth.
/// <summary>
/// How much reagent of blood should be restored each update interval?
/// </summary>
[DataField]
public float BloodRefreshAmount = 1.0f;
public FixedPoint2 BloodRefreshAmount = 1.0f;

/// <summary>
/// How much blood needs to be in the temporary solution in order to create a puddle?
Expand All @@ -89,8 +95,8 @@ public sealed partial class BloodstreamComponent : Component
/// <remarks>
/// For example, piercing damage is increased while poison damage is nullified entirely.
/// </remarks>
[DataField(customTypeSerializer:typeof(PrototypeIdSerializer<DamageModifierSetPrototype>))]
public string DamageBleedModifiers = "BloodlossHuman";
[DataField]
public ProtoId<DamageModifierSetPrototype> DamageBleedModifiers = "BloodlossHuman";

/// <summary>
/// The sound to be played when a weapon instantly deals blood loss damage.
Expand Down Expand Up @@ -126,7 +132,7 @@ public sealed partial class BloodstreamComponent : Component
/// Slime-people might use slime as their blood or something like that.
/// </remarks>
[DataField]
public string BloodReagent = "Blood";
public ProtoId<ReagentPrototype> BloodReagent = "Blood";

/// <summary>Name/Key that <see cref="BloodSolution"/> is indexed by.</summary>
[DataField]
Expand Down Expand Up @@ -164,6 +170,6 @@ public sealed partial class BloodstreamComponent : Component
/// Variable that stores the amount of status time added by having a low blood level.
/// </summary>
[ViewVariables(VVAccess.ReadWrite)]
public float StatusTime;
public TimeSpan StatusTime;
}
}
14 changes: 8 additions & 6 deletions Content.Server/Body/Components/InternalsComponent.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
using System.Threading;
namespace Content.Server.Body.Components
{
/// <summary>
Expand All @@ -7,14 +6,17 @@ namespace Content.Server.Body.Components
[RegisterComponent]
public sealed partial class InternalsComponent : Component
{
[ViewVariables] public EntityUid? GasTankEntity { get; set; }
[ViewVariables] public EntityUid? BreathToolEntity { get; set; }
[ViewVariables]
public EntityUid? GasTankEntity;

[ViewVariables]
public EntityUid? BreathToolEntity;

/// <summary>
/// Toggle Internals delay (seconds) when the target is not you.
/// Toggle Internals delay when the target is not you.
/// </summary>
[ViewVariables(VVAccess.ReadWrite)]
[DataField("delay")]
public float Delay = 3;
[DataField]
public TimeSpan Delay = TimeSpan.FromSeconds(3);
}
}
4 changes: 2 additions & 2 deletions Content.Server/Body/Components/LungComponent.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using Content.Server.Atmos;
using Content.Server.Atmos;
using Content.Server.Body.Systems;
using Content.Shared.Alert;
using Content.Shared.Atmos;
Expand All @@ -11,7 +11,7 @@ public sealed partial class LungComponent : Component
{
[DataField]
[Access(typeof(LungSystem), Other = AccessPermissions.ReadExecute)] // FIXME Friends
public GasMixture Air { get; set; } = new()
public GasMixture Air = new()
{
Volume = 6,
Temperature = Atmospherics.NormalBodyTemperature
Expand Down
Loading

0 comments on commit 37b8d78

Please sign in to comment.