Skip to content

Commit

Permalink
cherry pick "fix solution contents duplication on spill behavior" (#3…
Browse files Browse the repository at this point in the history
…3231) (#2157)

I’M SCREAMING INTO THE VOID AND IT’S NOT LISTENING
  • Loading branch information
MilonPL authored Nov 9, 2024
1 parent 72355a4 commit 96fc62c
Showing 1 changed file with 49 additions and 31 deletions.
80 changes: 49 additions & 31 deletions Content.Server/Destructible/Thresholds/Behaviors/SpillBehavior.cs
Original file line number Diff line number Diff line change
@@ -1,42 +1,60 @@
using Content.Shared.Chemistry.EntitySystems;
using Content.Server.Fluids.EntitySystems;
using Content.Shared.Chemistry.Components;
using Content.Shared.Chemistry.EntitySystems;
using Content.Shared.Fluids.Components;
using JetBrains.Annotations;

namespace Content.Server.Destructible.Thresholds.Behaviors
namespace Content.Server.Destructible.Thresholds.Behaviors;

[UsedImplicitly]
[DataDefinition]
public sealed partial class SpillBehavior : IThresholdBehavior
{
[UsedImplicitly]
[DataDefinition]
public sealed partial class SpillBehavior : IThresholdBehavior
{
[DataField]
public string? Solution;
/// <summary>
/// Optional fallback solution name if SpillableComponent is not present.
/// </summary>
[DataField]
public string? Solution;

/// <summary>
/// If there is a SpillableComponent on EntityUidowner use it to create a puddle/smear.
/// Or whatever solution is specified in the behavior itself.
/// If none are available do nothing.
/// </summary>
/// <param name="owner">Entity on which behavior is executed</param>
/// <param name="system">system calling the behavior</param>
/// <param name="cause"></param>
public void Execute(EntityUid owner, DestructibleSystem system, EntityUid? cause = null)
{
var solutionContainerSystem = system.EntityManager.System<SharedSolutionContainerSystem>();
var spillableSystem = system.EntityManager.System<PuddleSystem>();
/// <summary>
/// When triggered, spills the entity's solution onto the ground.
/// Will first try to use the solution from a SpillableComponent if present,
/// otherwise falls back to the solution specified in the behavior's data fields.
/// The solution is properly drained/split before spilling to prevent double-spilling with other behaviors.
/// </summary>
/// <param name="owner">Entity whose solution will be spilled</param>
/// <param name="system">System calling this behavior</param>
/// <param name="cause">Optional entity that caused this behavior to trigger</param>
public void Execute(EntityUid owner, DestructibleSystem system, EntityUid? cause = null)
{
var solutionContainerSystem = system.EntityManager.System<SharedSolutionContainerSystem>();
var spillableSystem = system.EntityManager.System<PuddleSystem>();
var coordinates = system.EntityManager.GetComponent<TransformComponent>(owner).Coordinates;

var coordinates = system.EntityManager.GetComponent<TransformComponent>(owner).Coordinates;
Solution targetSolution;

if (system.EntityManager.TryGetComponent(owner, out SpillableComponent? spillableComponent) &&
solutionContainerSystem.TryGetSolution(owner, spillableComponent.SolutionName, out _, out var compSolution))
{
spillableSystem.TrySplashSpillAt(owner, coordinates, compSolution, out _, false, user: cause);
}
else if (Solution != null &&
solutionContainerSystem.TryGetSolution(owner, Solution, out _, out var behaviorSolution))
{
spillableSystem.TrySplashSpillAt(owner, coordinates, behaviorSolution, out _, user: cause);
}
// First try to get solution from SpillableComponent
if (system.EntityManager.TryGetComponent(owner, out SpillableComponent? spillableComponent) &&
solutionContainerSystem.TryGetSolution(owner, spillableComponent.SolutionName, out var solution, out var compSolution))
{
// If entity is drainable, drain the solution. Otherwise just split it.
// Both methods ensure the solution is properly removed.
targetSolution = system.EntityManager.HasComponent<DrainableSolutionComponent>(owner)
? solutionContainerSystem.Drain((owner, system.EntityManager.GetComponent<DrainableSolutionComponent>(owner)), solution.Value, compSolution.Volume)
: compSolution.SplitSolution(compSolution.Volume);
}
// Fallback to solution specified in behavior data
else if (Solution != null &&
solutionContainerSystem.TryGetSolution(owner, Solution, out var solutionEnt, out var behaviorSolution))
{
targetSolution = system.EntityManager.HasComponent<DrainableSolutionComponent>(owner)
? solutionContainerSystem.Drain((owner, system.EntityManager.GetComponent<DrainableSolutionComponent>(owner)), solutionEnt.Value, behaviorSolution.Volume)
: behaviorSolution.SplitSolution(behaviorSolution.Volume);
}
else
return;

// Spill the solution that was drained/split
spillableSystem.TrySplashSpillAt(owner, coordinates, targetSolution, out _, false, cause);
}
}

0 comments on commit 96fc62c

Please sign in to comment.