]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
Replace BlockSolutionAccessComponent with an attempt event (#26988)
authorTayrtahn <tayrtahn@gmail.com>
Fri, 21 Jun 2024 03:04:02 +0000 (23:04 -0400)
committerGitHub <noreply@github.com>
Fri, 21 Jun 2024 03:04:02 +0000 (13:04 +1000)
* BlockSolutionAccessComponent now only blocks one specified solution.

* Significant overhaul
Separated spilling when worn functionality into its own component/system.
Removed BlockSolutionAccessComponent.
Added an event for solution access.

Content.Server/Fluids/EntitySystems/PuddleSystem.Spillable.cs
Content.Shared/Chemistry/Components/BlockSolutionAccessComponent.cs [deleted file]
Content.Shared/Chemistry/EntitySystems/SharedSolutionContainerSystem.cs
Content.Shared/Fluids/Components/SpillWhenWornComponent.cs [new file with mode: 0644]
Content.Shared/Fluids/Components/SpillableComponent.cs
Content.Shared/Fluids/EntitySystems/SpillWhenWornSystem.cs [new file with mode: 0644]
Resources/Prototypes/Entities/Objects/Tools/bucket.yml

index d02dd44e81fa283add120efa4bc8a9be5de55623..2eaf19170b761302f4163f63d7ab9155ce2bc6c3 100644 (file)
@@ -27,8 +27,6 @@ public sealed partial class PuddleSystem
         SubscribeLocalEvent<SpillableComponent, LandEvent>(SpillOnLand);
         // Openable handles the event if it's closed
         SubscribeLocalEvent<SpillableComponent, MeleeHitEvent>(SplashOnMeleeHit, after: [typeof(OpenableSystem)]);
-        SubscribeLocalEvent<SpillableComponent, ClothingGotEquippedEvent>(OnGotEquipped);
-        SubscribeLocalEvent<SpillableComponent, ClothingGotUnequippedEvent>(OnGotUnequipped);
         SubscribeLocalEvent<SpillableComponent, SolutionContainerOverflowEvent>(OnOverflow);
         SubscribeLocalEvent<SpillableComponent, SpillDoAfterEvent>(OnDoAfter);
         SubscribeLocalEvent<SpillableComponent, AttemptPacifiedThrowEvent>(OnAttemptPacifiedThrow);
@@ -97,33 +95,6 @@ public sealed partial class PuddleSystem
         }
     }
 
-    private void OnGotEquipped(Entity<SpillableComponent> entity, ref ClothingGotEquippedEvent args)
-    {
-        if (!entity.Comp.SpillWorn)
-            return;
-
-        if (!_solutionContainerSystem.TryGetSolution(entity.Owner, entity.Comp.SolutionName, out var soln, out var solution))
-            return;
-
-        // block access to the solution while worn
-        AddComp<BlockSolutionAccessComponent>(entity);
-
-        if (solution.Volume == 0)
-            return;
-
-        // spill all solution on the player
-        var drainedSolution = _solutionContainerSystem.Drain(entity.Owner, soln.Value, solution.Volume);
-        TrySplashSpillAt(entity.Owner, Transform(args.Wearer).Coordinates, drainedSolution, out _);
-    }
-
-    private void OnGotUnequipped(Entity<SpillableComponent> entity, ref ClothingGotUnequippedEvent args)
-    {
-        if (!entity.Comp.SpillWorn)
-            return;
-
-        RemCompDeferred<BlockSolutionAccessComponent>(entity);
-    }
-
     private void SpillOnLand(Entity<SpillableComponent> entity, ref LandEvent args)
     {
         if (!_solutionContainerSystem.TryGetSolution(entity.Owner, entity.Comp.SolutionName, out var soln, out var solution))
diff --git a/Content.Shared/Chemistry/Components/BlockSolutionAccessComponent.cs b/Content.Shared/Chemistry/Components/BlockSolutionAccessComponent.cs
deleted file mode 100644 (file)
index 182f92d..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-using Robust.Shared.GameStates;
-
-namespace Content.Shared.Chemistry.Components;
-
-/// <summary>
-/// Blocks all attempts to access solutions contained by this entity.
-/// </summary>
-[RegisterComponent, NetworkedComponent]
-public sealed partial class BlockSolutionAccessComponent : Component
-{
-}
index 5e58a0944a496e1cbf00961768deaf0231f76541..7e00157b6ee3b9d63d6d87025c971971e0cfc436 100644 (file)
@@ -48,6 +48,12 @@ public partial record struct SolutionOverflowEvent(Entity<SolutionComponent> Sol
     public bool Handled = false;
 }
 
+[ByRefEvent]
+public partial record struct SolutionAccessAttemptEvent(string SolutionName)
+{
+    public bool Cancelled;
+}
+
 /// <summary>
 /// Part of Chemistry system deal with SolutionContainers
 /// </summary>
@@ -156,12 +162,6 @@ public abstract partial class SharedSolutionContainerSystem : EntitySystem
         [NotNullWhen(true)] out Entity<SolutionComponent>? entity,
         bool errorOnMissing = false)
     {
-        if (TryComp(container, out BlockSolutionAccessComponent? blocker))
-        {
-            entity = null;
-            return false;
-        }
-
         EntityUid uid;
         if (name is null)
             uid = container;
@@ -170,7 +170,18 @@ public abstract partial class SharedSolutionContainerSystem : EntitySystem
             solutionContainer is ContainerSlot solutionSlot &&
             solutionSlot.ContainedEntity is { } containedSolution
         )
+        {
+            var attemptEv = new SolutionAccessAttemptEvent(name);
+            RaiseLocalEvent(container, ref attemptEv);
+
+            if (attemptEv.Cancelled)
+            {
+                entity = null;
+                return false;
+            }
+
             uid = containedSolution;
+        }
         else
         {
             entity = null;
@@ -218,11 +229,14 @@ public abstract partial class SharedSolutionContainerSystem : EntitySystem
         if (!Resolve(container, ref container.Comp, logMissing: false))
             yield break;
 
-        if (HasComp<BlockSolutionAccessComponent>(container))
-            yield break;
-
         foreach (var name in container.Comp.Containers)
         {
+            var attemptEv = new SolutionAccessAttemptEvent(name);
+            RaiseLocalEvent(container, ref attemptEv);
+
+            if (attemptEv.Cancelled)
+                continue;
+
             if (ContainerSystem.GetContainer(container, $"solution@{name}") is ContainerSlot slot && slot.ContainedEntity is { } solutionId)
                 yield return (name, (solutionId, Comp<SolutionComponent>(solutionId)));
         }
diff --git a/Content.Shared/Fluids/Components/SpillWhenWornComponent.cs b/Content.Shared/Fluids/Components/SpillWhenWornComponent.cs
new file mode 100644 (file)
index 0000000..d456d18
--- /dev/null
@@ -0,0 +1,24 @@
+using Robust.Shared.GameStates;
+
+namespace Content.Shared.Fluids.Components;
+
+/// <summary>
+/// This entity will spill its contained solution onto the wearer when worn, and its
+/// (empty) contents will be inaccessible while still worn.
+/// </summary>
+[RegisterComponent]
+[NetworkedComponent, AutoGenerateComponentState]
+public sealed partial class SpillWhenWornComponent : Component
+{
+    /// <summary>
+    /// Name of the solution to spill.
+    /// </summary>
+    [DataField]
+    public string Solution = "default";
+
+    /// <summary>
+    /// Tracks if this item is currently being worn.
+    /// </summary>
+    [DataField, AutoNetworkedField]
+    public bool IsWorn;
+}
index 51bb73a11fe4eb0b9aa96d2d959fb151a37e2bc9..cc57dbf2b60bb598cfc475890033b8d326607e74 100644 (file)
@@ -14,13 +14,6 @@ public sealed partial class SpillableComponent : Component
     [DataField("solution")]
     public string SolutionName = "puddle";
 
-    /// <summary>
-    ///     Should this item be spilled when worn as clothing?
-    ///     Doesn't count for pockets or hands.
-    /// </summary>
-    [DataField]
-    public bool SpillWorn = true;
-
     [DataField]
     public float? SpillDelay;
 
diff --git a/Content.Shared/Fluids/EntitySystems/SpillWhenWornSystem.cs b/Content.Shared/Fluids/EntitySystems/SpillWhenWornSystem.cs
new file mode 100644 (file)
index 0000000..210dbfd
--- /dev/null
@@ -0,0 +1,55 @@
+using Content.Shared.Chemistry.EntitySystems;
+using Content.Shared.Clothing;
+using Content.Shared.Fluids.Components;
+
+namespace Content.Shared.Fluids.EntitySystems;
+
+/// <inheritdoc cref="SpillWhenWornComponent"/>
+public sealed class SpillWhenWornSystem : EntitySystem
+{
+    [Dependency] private readonly SharedSolutionContainerSystem _solutionContainer = default!;
+    [Dependency] private readonly SharedPuddleSystem _puddle = default!;
+
+    public override void Initialize()
+    {
+        base.Initialize();
+
+        SubscribeLocalEvent<SpillWhenWornComponent, ClothingGotEquippedEvent>(OnGotEquipped);
+        SubscribeLocalEvent<SpillWhenWornComponent, ClothingGotUnequippedEvent>(OnGotUnequipped);
+        SubscribeLocalEvent<SpillWhenWornComponent, SolutionAccessAttemptEvent>(OnSolutionAccessAttempt);
+    }
+
+    private void OnGotEquipped(Entity<SpillWhenWornComponent> ent, ref ClothingGotEquippedEvent args)
+    {
+        if (_solutionContainer.TryGetSolution(ent.Owner, ent.Comp.Solution, out var soln, out var solution)
+            && solution.Volume > 0)
+        {
+            // Spill all solution on the player
+            var drainedSolution = _solutionContainer.Drain(ent.Owner, soln.Value, solution.Volume);
+            _puddle.TrySplashSpillAt(ent.Owner, Transform(args.Wearer).Coordinates, drainedSolution, out _);
+        }
+
+        // Flag as worn after draining, otherwise we'll block ourself from accessing!
+        ent.Comp.IsWorn = true;
+        Dirty(ent);
+    }
+
+    private void OnGotUnequipped(Entity<SpillWhenWornComponent> ent, ref ClothingGotUnequippedEvent args)
+    {
+        ent.Comp.IsWorn = false;
+        Dirty(ent);
+    }
+
+    private void OnSolutionAccessAttempt(Entity<SpillWhenWornComponent> ent, ref SolutionAccessAttemptEvent args)
+    {
+        // If we're not being worn right now, we don't care
+        if (!ent.Comp.IsWorn)
+            return;
+
+        // Make sure it's the right solution
+        if (ent.Comp.Solution != args.SolutionName)
+            return;
+
+        args.Cancelled = true;
+    }
+}
index 77c5e548978afcc1b5d75b237c6c6091b795e773..58c8dae2b05aa942e45cb20df53dda3d9c5d9eb3 100644 (file)
@@ -45,6 +45,8 @@
         Blunt: 0
   - type: Spillable
     solution: bucket
+  - type: SpillWhenWorn
+    solution: bucket
   - type: DrawableSolution
     solution: bucket
   - type: RefillableSolution