Files
tbd-station-14/Content.Shared/Inventory/RelaySubscriptionHelpers.cs
Pieter-Jan Briers 843d79be5f Fire extinguishers can now extinguish items, including when held/worn (#36267)
* Fire extinguishers now put out candles

This did not actually require any changes to flammable or extinguishers directly, the only necessary changes were to make the collision actually work.

Vapor entities (also used for fire extinguishers) now have a collision layer, so they can hit items.

Added a new FlammableSetCollisionWake component to actually enable collision on candles while they are lit, because otherwise CollisionWake on entities gets in the way too.

* Extinguishing items is now relayed to held/worn items

This means held candles get extinguished too.

Involved moving the core logic of ExtinguishReaction into an event so that it can be relayed via the existing hand/inventory relay logic.

* Add helper functions for subscribing to relayed events.

Use these in FlammableSystem

* Make extinguishers work on cigarettes too

A bunch of renaming to make the rest of my code work with SmokableComponent

---------

Co-authored-by: metalgearsloth <comedian_vs_clown@hotmail.com>
2025-04-14 19:00:47 +10:00

124 lines
5.1 KiB
C#

using Content.Shared.Hands;
namespace Content.Shared.Inventory;
/// <summary>
/// Helper functions for subscribing to component events that are also relayed via hands/inventory.
/// </summary>
public static class RelaySubscriptionHelpers
{
/// <summary>
/// Subscribe to an event, along with different relayed event wrappers, in one call.
/// </summary>
/// <param name="subs">Subscriptions for the entity system we're subscribing on.</param>
/// <param name="handler">The event handler to be called for the event.</param>
/// <param name="baseEvent">Whether to subscribe the base event type.</param>
/// <param name="inventory">Whether to subscribe for <see cref="T:Content.Shared.Inventory.InventoryRelayedEvent`1"/>.</param>
/// <param name="held">Whether to subscribe for <see cref="T:Content.Shared.Hands.HeldRelayedEvent`1"/>.</param>
/// <seealso cref="M:Robust.Shared.GameObjects.EntitySystem.SubscribeLocalEvent``2(Robust.Shared.GameObjects.EntityEventRefHandler{``0,``1},System.Type[],System.Type[])"/>
public static void SubscribeWithRelay<TComp, TEvent>(
this EntitySystem.Subscriptions subs,
EntityEventRefHandler<TComp, TEvent> handler,
bool baseEvent = true,
bool inventory = true,
bool held = true)
where TEvent : notnull
where TComp : IComponent
{
if (baseEvent)
subs.SubscribeLocalEvent(handler);
if (inventory)
{
subs.SubscribeLocalEvent((Entity<TComp> ent, ref InventoryRelayedEvent<TEvent> ev) =>
{
handler(ent, ref ev.Args);
});
}
if (held)
{
subs.SubscribeLocalEvent((Entity<TComp> ent, ref HeldRelayedEvent<TEvent> ev) =>
{
handler(ent, ref ev.Args);
});
}
}
/// <summary>
/// Subscribe to an event, along with different relayed event wrappers, in one call.
/// </summary>
/// <param name="subs">Subscriptions for the entity system we're subscribing on.</param>
/// <param name="handler">The event handler to be called for the event.</param>
/// <param name="baseEvent">Whether to subscribe the base event type.</param>
/// <param name="inventory">Whether to subscribe for <see cref="T:Content.Shared.Inventory.InventoryRelayedEvent`1"/>.</param>
/// <param name="held">Whether to subscribe for <see cref="T:Content.Shared.Hands.HeldRelayedEvent`1"/>.</param>
/// <seealso cref="M:Robust.Shared.GameObjects.EntitySystem.SubscribeLocalEvent``2(Robust.Shared.GameObjects.ComponentEventHandler{``0,``1},System.Type[],System.Type[])"/>
public static void SubscribeWithRelay<TComp, TEvent>(
this EntitySystem.Subscriptions subs,
ComponentEventHandler<TComp, TEvent> handler,
bool baseEvent = true,
bool inventory = true,
bool held = true)
where TEvent : notnull
where TComp : IComponent
{
if (baseEvent)
subs.SubscribeLocalEvent(handler);
if (inventory)
{
subs.SubscribeLocalEvent((EntityUid uid, TComp component, InventoryRelayedEvent<TEvent> args) =>
{
handler(uid, component, args.Args);
});
}
if (held)
{
subs.SubscribeLocalEvent((EntityUid uid, TComp component, HeldRelayedEvent<TEvent> args) =>
{
handler(uid, component, args.Args);
});
}
}
/// <summary>
/// Subscribe to an event, along with different relayed event wrappers, in one call.
/// </summary>
/// <param name="subs">Subscriptions for the entity system we're subscribing on.</param>
/// <param name="handler">The event handler to be called for the event.</param>
/// <param name="baseEvent">Whether to subscribe the base event type.</param>
/// <param name="inventory">Whether to subscribe for <see cref="T:Content.Shared.Inventory.InventoryRelayedEvent`1"/>.</param>
/// <param name="held">Whether to subscribe for <see cref="T:Content.Shared.Hands.HeldRelayedEvent`1"/>.</param>
/// <seealso cref="M:Robust.Shared.GameObjects.EntitySystem.SubscribeLocalEvent``2(Robust.Shared.GameObjects.ComponentEventRefHandler{``0,``1},System.Type[],System.Type[])"/>
public static void SubscribeWithRelay<TComp, TEvent>(
this EntitySystem.Subscriptions subs,
ComponentEventRefHandler<TComp, TEvent> handler,
bool baseEvent = true,
bool inventory = true,
bool held = true)
where TEvent : notnull
where TComp : IComponent
{
if (baseEvent)
subs.SubscribeLocalEvent(handler);
if (inventory)
{
subs.SubscribeLocalEvent((EntityUid uid, TComp component, ref InventoryRelayedEvent<TEvent> args) =>
{
handler(uid, component, ref args.Args);
});
}
if (held)
{
subs.SubscribeLocalEvent((EntityUid uid, TComp component, ref HeldRelayedEvent<TEvent> args) =>
{
handler(uid, component, ref args.Args);
});
}
}
}