using Content.Shared.Chemistry.Components; using Content.Shared.Chemistry.Components.SolutionManager; using Content.Shared.Chemistry.Reaction; using Content.Shared.FixedPoint; namespace Content.Shared.Chemistry.EntitySystems; #region Events /// /// An event raised when more reagents are added to a (managed) solution than it can hold. /// [ByRefEvent] public record struct SolutionContainerOverflowEvent(EntityUid SolutionEnt, Solution SolutionHolder, Solution Overflow) { /// The entity which contains the solution that has overflowed. public readonly EntityUid SolutionEnt = SolutionEnt; /// The solution that has overflowed. public readonly Solution SolutionHolder = SolutionHolder; /// The reagents that have overflowed the solution. public readonly Solution Overflow = Overflow; /// The volume by which the solution has overflowed. public readonly FixedPoint2 OverflowVol = Overflow.Volume; /// Whether some subscriber has taken care of the effects of the overflow. public bool Handled = false; } /// /// Ref event used to relay events raised on solution entities to their containers. /// /// /// The event that is being relayed. /// The container entity that the event is being relayed to. [ByRefEvent] public record struct SolutionRelayEvent(TEvent Event, Entity Solution) { public readonly Entity Solution = Solution; public TEvent Event = Event; } /// /// Ref event used to relay events raised on solution containers to their contained solutions. /// /// /// The event that is being relayed. /// The solution entity that the event is being relayed to. /// The name of the solution entity that the event is being relayed to. [ByRefEvent] public record struct SolutionContainerRelayEvent(TEvent Event, Entity SolutionEnt, string Name) { public readonly Entity SolutionEnt = SolutionEnt; public readonly string Name = Name; public TEvent Event = Event; } #endregion Events public abstract partial class SharedSolutionContainerSystem { protected void InitializeRelays() { SubscribeLocalEvent(OnSolutionOverflow); SubscribeLocalEvent(RelaySolutionRefEvent); } #region Event Handlers protected virtual void OnSolutionOverflow(Entity entity, ref SolutionOverflowEvent args) { var solution = args.Solution.Comp.Solution; var overflow = solution.SplitSolution(args.Overflow); var relayEv = new SolutionContainerOverflowEvent(entity.Owner, solution, overflow) { Handled = args.Handled, }; RaiseLocalEvent(entity.Comp.Container, ref relayEv); args.Handled = relayEv.Handled; } #region Relay Event Handlers private void RelaySolutionValEvent(EntityUid uid, ContainedSolutionComponent comp, TEvent @event) { var solution = Comp(uid); var relayEvent = new SolutionRelayEvent(@event, (uid, solution)); RaiseLocalEvent(comp.Container, ref relayEvent); } private void RelaySolutionRefEvent(Entity entity, ref TEvent @event) { var solution = Comp(entity); var relayEvent = new SolutionRelayEvent(@event, (entity, solution)); RaiseLocalEvent(entity.Comp.Container, ref relayEvent); @event = relayEvent.Event; } private void RelaySolutionContainerEvent(EntityUid uid, SolutionManagerComponent comp, TEvent @event) { foreach (var (name, soln) in EnumerateSolutions((uid, comp))) { var relayEvent = new SolutionContainerRelayEvent(@event, soln, name!); RaiseLocalEvent(soln, ref relayEvent); } } private void RelaySolutionContainerEvent(Entity entity, ref TEvent @event) { foreach (var (name, soln) in EnumerateSolutions((entity.Owner, entity.Comp))) { var relayEvent = new SolutionContainerRelayEvent(@event, soln, name!); RaiseLocalEvent(soln, ref relayEvent); @event = relayEvent.Event; } } #endregion Relay Event Handlers #endregion Event Handlers }