HandsSystem Refactor (#38438)

* checkpoint

* pt 2

* pt... i forgot

* pt 4

* patch

* More test fixes

* optimization!!!

* the REAL hand system

* fix RetractableItemActionSystem.cs oversight

* the review

* test

* remove test usage of body prototype

* Update Content.IntegrationTests/Tests/Interaction/InteractionTest.cs

Co-authored-by: Tayrtahn <tayrtahn@gmail.com>

* hellcode

* hellcode 2

* Minor cleanup

* test

* Chasing the last of the bugs

* changes

---------

Co-authored-by: Tayrtahn <tayrtahn@gmail.com>
This commit is contained in:
Nemanja
2025-06-25 09:13:03 -04:00
committed by GitHub
parent 6cffa8aabe
commit 524725d378
79 changed files with 849 additions and 897 deletions

View File

@@ -1,5 +1,4 @@
using System.Numerics;
using Content.Server.Inventory;
using Content.Server.Stack;
using Content.Server.Stunnable;
using Content.Shared.ActionBlocker;
@@ -10,9 +9,7 @@ using Content.Shared.Explosion;
using Content.Shared.Hands.Components;
using Content.Shared.Hands.EntitySystems;
using Content.Shared.Input;
using Content.Shared.Inventory.VirtualItem;
using Content.Shared.Movement.Pulling.Components;
using Content.Shared.Movement.Pulling.Events;
using Content.Shared.Movement.Pulling.Systems;
using Content.Shared.Stacks;
using Content.Shared.Standing;
@@ -24,7 +21,6 @@ using Robust.Shared.Physics.Components;
using Robust.Shared.Player;
using Robust.Shared.Random;
using Robust.Shared.Timing;
using Robust.Shared.Utility;
namespace Content.Server.Hands.Systems
{
@@ -87,10 +83,9 @@ namespace Content.Server.Hands.Systems
if (ent.Comp.DisableExplosionRecursion)
return;
foreach (var hand in ent.Comp.Hands.Values)
foreach (var held in EnumerateHeld(ent.AsNullable()))
{
if (hand.HeldEntity is { } uid)
args.Contents.Add(uid);
args.Contents.Add(held);
}
}
@@ -112,7 +107,7 @@ namespace Content.Server.Hands.Systems
args.Handled = true; // no shove/stun.
}
private void HandleBodyPartAdded(EntityUid uid, HandsComponent component, ref BodyPartAddedEvent args)
private void HandleBodyPartAdded(Entity<HandsComponent> ent, ref BodyPartAddedEvent args)
{
if (args.Part.Comp.PartType != BodyPartType.Hand)
return;
@@ -127,7 +122,7 @@ namespace Content.Server.Hands.Systems
_ => throw new ArgumentOutOfRangeException(nameof(args.Part.Comp.Symmetry))
};
AddHand(uid, args.Slot, location);
AddHand(ent.AsNullable(), args.Slot, location);
}
private void HandleBodyPartRemoved(EntityUid uid, HandsComponent component, ref BodyPartRemovedEvent args)
@@ -155,8 +150,8 @@ namespace Content.Server.Hands.Systems
{
if (ContainerSystem.IsEntityInContainer(player) ||
!TryComp(player, out HandsComponent? hands) ||
hands.ActiveHandEntity is not { } throwEnt ||
!_actionBlockerSystem.CanThrow(player, throwEnt))
!TryGetActiveItem((player, hands), out var throwEnt) ||
!_actionBlockerSystem.CanThrow(player, throwEnt.Value))
return false;
if (_timing.CurTime < hands.NextThrowTime)
@@ -165,7 +160,7 @@ namespace Content.Server.Hands.Systems
if (EntityManager.TryGetComponent(throwEnt, out StackComponent? stack) && stack.Count > 1 && stack.ThrowIndividually)
{
var splitStack = _stackSystem.Split(throwEnt, 1, EntityManager.GetComponent<TransformComponent>(player).Coordinates, stack);
var splitStack = _stackSystem.Split(throwEnt.Value, 1, EntityManager.GetComponent<TransformComponent>(player).Coordinates, stack);
if (splitStack is not {Valid: true})
return false;
@@ -185,14 +180,14 @@ namespace Content.Server.Hands.Systems
// Let other systems change the thrown entity (useful for virtual items)
// or the throw strength.
var ev = new BeforeThrowEvent(throwEnt, direction, throwSpeed, player);
var ev = new BeforeThrowEvent(throwEnt.Value, direction, throwSpeed, player);
RaiseLocalEvent(player, ref ev);
if (ev.Cancelled)
return true;
// This can grief the above event so we raise it afterwards
if (IsHolding(player, throwEnt, out _, hands) && !TryDrop(player, throwEnt, handsComp: hands))
if (IsHolding((player, hands), throwEnt, out _) && !TryDrop(player, throwEnt.Value))
return false;
_throwingSystem.TryThrow(ev.ItemUid, ev.Direction, ev.ThrowSpeed, ev.PlayerUid, compensateFriction: !HasComp<LandAtCursorComponent>(ev.ItemUid));
@@ -207,20 +202,20 @@ namespace Content.Server.Hands.Systems
var spreadMaxAngle = Angle.FromDegrees(DropHeldItemsSpread);
var fellEvent = new FellDownEvent(entity);
RaiseLocalEvent(entity, fellEvent, false);
RaiseLocalEvent(entity, fellEvent);
foreach (var hand in entity.Comp.Hands.Values)
foreach (var hand in entity.Comp.Hands.Keys)
{
if (hand.HeldEntity is not EntityUid held)
if (!TryGetHeldItem(entity.AsNullable(), hand, out var heldEntity))
continue;
var throwAttempt = new FellDownThrowAttemptEvent(entity);
RaiseLocalEvent(hand.HeldEntity.Value, ref throwAttempt);
RaiseLocalEvent(heldEntity.Value, ref throwAttempt);
if (throwAttempt.Cancelled)
continue;
if (!TryDrop(entity, hand, null, checkActionBlocker: false, handsComp: entity.Comp))
if (!TryDrop(entity.AsNullable(), hand, checkActionBlocker: false))
continue;
// Rotate the item's throw vector a bit for each item
@@ -231,12 +226,12 @@ namespace Content.Server.Hands.Systems
itemVelocity *= _random.NextFloat(1f);
// Heavier objects don't get thrown as far
// If the item doesn't have a physics component, it isn't going to get thrown anyway, but we'll assume infinite mass
itemVelocity *= _physicsQuery.TryComp(held, out var heldPhysics) ? heldPhysics.InvMass : 0;
itemVelocity *= _physicsQuery.TryComp(heldEntity, out var heldPhysics) ? heldPhysics.InvMass : 0;
// Throw at half the holder's intentional throw speed and
// vary the speed a little to make it look more interesting
var throwSpeed = entity.Comp.BaseThrowspeed * _random.NextFloat(0.45f, 0.55f);
_throwingSystem.TryThrow(held,
_throwingSystem.TryThrow(heldEntity.Value,
itemVelocity,
throwSpeed,
entity,