Bugfix: Better lifecycle handling for DisposalHolderComponent and BeingDisposedComponent (#45140)

* DisposalHolder lifecycle calls

* shorter, no goober comment

* scammed by tests

* scammed, yet again, by tests
This commit is contained in:
Whatstone 2026-08-04 16:30:50 -04:00 • committed by GitHub
parent 3046ce6728
commit 7ef5e506a0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -19,41 +19,41 @@ namespace Content.Shared.Disposal.Holder;
/// </summary>
public abstract partial class SharedDisposalHolderSystem : EntitySystem
{
[Dependency] private INetManager _net = default!;
[Dependency] private DamageableSystem _damageable = default!;
[Dependency] private DisposalTubeSystem _disposalTube = default!;
[Dependency] private SharedAudioSystem _audio = default!;
[Dependency] private SharedContainerSystem _container = default!;
[Dependency] private SharedEyeSystem _eye = default!;
[Dependency] private SharedPhysicsSystem _physics = default!;
[Dependency] private SharedTransformSystem _xform = default!;
[Dependency] private INetManager _net = default!;
[Dependency] private SharedEyeSystem _eye = default!;
private EntityQuery<TransformComponent> _xformQuery;
[Dependency] private EntityQuery<TransformComponent> _xformQuery;
/// <summary>
/// Allowed characters for tagging disposed entities.
/// </summary>
public static readonly Regex TagRegex = new("^[a-zA-Z0-9, ]*$", RegexOptions.Compiled);
public override void Initialize()
{
base.Initialize();
_xformQuery = GetEntityQuery<TransformComponent>();
SubscribeLocalEvent<DisposalHolderComponent, ComponentStartup>(OnComponentStartup);
SubscribeLocalEvent<DisposalHolderComponent, BeforeExplodeEvent>(OnExploded);
SubscribeLocalEvent<ActorComponent, DisposalSystemTransitionEvent>(OnActorTransition);
SubscribeLocalEvent<BeingDisposedComponent, GetVisMaskEvent>(OnGetVisibility);
}
[SubscribeLocalEvent]
private void OnComponentStartup(Entity<DisposalHolderComponent> ent, ref ComponentStartup args)
{
// Ensure the holder will have its container
ent.Comp.Container = _container.EnsureContainer<Container>(ent, nameof(DisposalHolderComponent));
}
[SubscribeLocalEvent]
private void OnComponentRemove(Entity<DisposalHolderComponent> ent, ref ComponentRemove args)
{
if (ent.Comp.Container is not { } container)
return;
// Inform the contained entities that they aren't in disposals anymore.
foreach (var contained in container.ContainedEntities)
DetachEntity(contained);
}
[SubscribeLocalEvent]
private void OnExploded(Entity<DisposalHolderComponent> ent, ref BeforeExplodeEvent args)
{
if (ent.Comp.Container == null)
@ -62,12 +62,14 @@ public abstract partial class SharedDisposalHolderSystem : EntitySystem
args.Contents.AddRange(ent.Comp.Container.ContainedEntities);
}
[SubscribeLocalEvent]
private void OnActorTransition(Entity<ActorComponent> ent, ref DisposalSystemTransitionEvent args)
{
// Refreshes visibility mask of a player, leading to OnGetVisibility being called
_eye.RefreshVisibilityMask(ent.Owner);
}
[SubscribeLocalEvent]
private void OnGetVisibility(Entity<BeingDisposedComponent> entity, ref GetVisMaskEvent ev)
{
// Prevents mispredictions by allowing players in the disposal system
@ -76,6 +78,13 @@ public abstract partial class SharedDisposalHolderSystem : EntitySystem
ev.VisibilityMask |= (int)VisibilityFlags.Subfloor;
}
[SubscribeLocalEvent]
private void OnDisposedRemovedFromContainer(Entity<BeingDisposedComponent> ent, ref EntGotRemovedFromContainerMessage args)
{
if (args.Container.Owner == ent.Comp.Holder)
DetachEntity(ent);
}
/// <summary>
/// Ejects all entities inside a disposal holder from the disposals system.
/// </summary>