]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
feat: properly perform predicted porta pottys (fix toilet prediction) (#39394)
authorPerry Fraser <perryprog@users.noreply.github.com>
Wed, 6 Aug 2025 01:34:41 +0000 (21:34 -0400)
committerGitHub <noreply@github.com>
Wed, 6 Aug 2025 01:34:41 +0000 (18:34 -0700)
Content.Server/Toilet/ToiletSystem.cs [deleted file]
Content.Shared/Toilet/Components/ToiletComponent.cs
Content.Shared/Toilet/Systems/SharedToiletSystem.cs [deleted file]
Content.Shared/Toilet/Systems/ToiletSystem.cs [new file with mode: 0644]
Resources/Prototypes/Entities/Structures/Furniture/toilet.yml

diff --git a/Content.Server/Toilet/ToiletSystem.cs b/Content.Server/Toilet/ToiletSystem.cs
deleted file mode 100644 (file)
index e184ddf..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-using Content.Shared.Toilet.Systems;
-
-namespace Content.Server.Toilet;
-
-public sealed class ToiletSystem : SharedToiletSystem
-{
-
-}
index 5de74e08f6ea62ca1ee8526843169649e58d0dab..ab1d3909808a02428f9680689d117711442efd9a 100644 (file)
@@ -2,39 +2,36 @@ using Robust.Shared.Audio;
 using Robust.Shared.GameStates;
 using Robust.Shared.Serialization;
 
-namespace Content.Shared.Toilet.Components
+namespace Content.Shared.Toilet.Components;
+
+/// <summary>
+/// Seats that can toggled up and down with visuals to match.
+/// </summary>
+[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
+public sealed partial class ToiletComponent : Component
 {
     /// <summary>
-    /// Toilets that can be flushed, seats toggled up and down, items hidden in cistern.
+    /// Toggles seat state.
     /// </summary>
-    [RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
-    public sealed partial class ToiletComponent : Component
-    {
-        /// <summary>
-        /// Toggles seat state.
-        /// </summary>
-        [DataField, AutoNetworkedField]
-        public bool ToggleSeat;
-
-
-        /// <summary>
-        /// Sound to play when toggling toilet seat.
-        /// </summary>
-        [DataField]
-        public SoundSpecifier SeatSound = new SoundPathSpecifier("/Audio/Effects/toilet_seat_down.ogg");
-    }
+    [DataField, AutoNetworkedField]
+    public bool ToggleSeat;
 
-    [Serializable, NetSerializable]
-    public enum ToiletVisuals : byte
-    {
-        SeatVisualState,
-    }
+    /// <summary>
+    /// Sound to play when toggling toilet seat.
+    /// </summary>
+    [DataField]
+    public SoundSpecifier SeatSound = new SoundPathSpecifier("/Audio/Effects/toilet_seat_down.ogg");
+}
 
-    [Serializable, NetSerializable]
-    public enum SeatVisualState : byte
-    {
-        SeatUp,
-        SeatDown
-    }
+[Serializable, NetSerializable]
+public enum ToiletVisuals : byte
+{
+    SeatVisualState,
 }
 
+[Serializable, NetSerializable]
+public enum SeatVisualState : byte
+{
+    SeatUp,
+    SeatDown,
+}
diff --git a/Content.Shared/Toilet/Systems/SharedToiletSystem.cs b/Content.Shared/Toilet/Systems/SharedToiletSystem.cs
deleted file mode 100644 (file)
index f11af33..0000000
+++ /dev/null
@@ -1,109 +0,0 @@
-using Content.Shared.Buckle.Components;
-using Content.Shared.Interaction;
-using Content.Shared.Verbs;
-using Content.Shared.Plunger.Components;
-using Robust.Shared.Audio.Systems;
-using Robust.Shared.Random;
-using Robust.Shared.Utility;
-using Content.Shared.Toilet.Components;
-
-namespace Content.Shared.Toilet.Systems
-{
-    /// <summary>
-    /// Handles sprite changes for both toilet seat up and down as well as for lid open and closed. Handles interactions with hidden stash
-    /// </summary>
-
-    public abstract class SharedToiletSystem : EntitySystem
-    {
-        [Dependency] private readonly IRobustRandom _random = default!;
-        [Dependency] private readonly SharedAudioSystem _audio = default!;
-        [Dependency] private readonly SharedAppearanceSystem _appearance = default!;
-
-        public override void Initialize()
-        {
-            base.Initialize();
-
-            SubscribeLocalEvent<ToiletComponent, MapInitEvent>(OnMapInit);
-            SubscribeLocalEvent<ToiletComponent, GetVerbsEvent<AlternativeVerb>>(OnToggleSeatVerb);
-            SubscribeLocalEvent<ToiletComponent, ActivateInWorldEvent>(OnActivateInWorld);
-        }
-
-        private void OnMapInit(EntityUid uid, ToiletComponent component, MapInitEvent args)
-        {
-            if (_random.Prob(0.5f))
-                component.ToggleSeat = true;
-
-            if (_random.Prob(0.3f))
-            {
-                TryComp<PlungerUseComponent>(uid, out var plunger);
-
-                if (plunger == null)
-                    return;
-
-                plunger.NeedsPlunger = true;
-            }
-
-            UpdateAppearance(uid);
-            Dirty(uid, component);
-        }
-
-        public bool CanToggle(EntityUid uid)
-        {
-            return TryComp<StrapComponent>(uid, out var strap) && strap.BuckledEntities.Count == 0;
-        }
-
-        private void OnToggleSeatVerb(EntityUid uid, ToiletComponent component, GetVerbsEvent<AlternativeVerb> args)
-        {
-            if (!args.CanInteract || !args.CanAccess || !CanToggle(uid) || args.Hands == null)
-                return;
-
-            AlternativeVerb toggleVerb = new()
-            {
-                Act = () => ToggleToiletSeat(uid, args.User, component)
-            };
-
-            if (component.ToggleSeat)
-            {
-                toggleVerb.Text = Loc.GetString("toilet-seat-close");
-                toggleVerb.Icon =
-                    new SpriteSpecifier.Texture(new ResPath("/Textures/Interface/VerbIcons/close.svg.192dpi.png"));
-            }
-            else
-            {
-                toggleVerb.Text = Loc.GetString("toilet-seat-open");
-                toggleVerb.Icon =
-                    new SpriteSpecifier.Texture(new ResPath("/Textures/Interface/VerbIcons/open.svg.192dpi.png"));
-            }
-            args.Verbs.Add(toggleVerb);
-        }
-
-        private void OnActivateInWorld(EntityUid uid, ToiletComponent comp, ActivateInWorldEvent args)
-        {
-            if (args.Handled || !args.Complex)
-                return;
-
-            args.Handled = true;
-            ToggleToiletSeat(uid, args.User, comp);
-        }
-
-        public void ToggleToiletSeat(EntityUid uid, EntityUid? user = null, ToiletComponent? component = null, MetaDataComponent? meta = null)
-        {
-            if (!Resolve(uid, ref component))
-                return;
-
-            component.ToggleSeat = !component.ToggleSeat;
-
-            _audio.PlayPredicted(component.SeatSound, uid, uid);
-            UpdateAppearance(uid, component);
-            Dirty(uid, component, meta);
-        }
-
-        private void UpdateAppearance(EntityUid uid, ToiletComponent? component = null)
-        {
-            if (!Resolve(uid, ref component))
-                return;
-
-            _appearance.SetData(uid, ToiletVisuals.SeatVisualState, component.ToggleSeat ? SeatVisualState.SeatUp : SeatVisualState.SeatDown);
-        }
-    }
-}
diff --git a/Content.Shared/Toilet/Systems/ToiletSystem.cs b/Content.Shared/Toilet/Systems/ToiletSystem.cs
new file mode 100644 (file)
index 0000000..ad08012
--- /dev/null
@@ -0,0 +1,116 @@
+using Content.Shared.Buckle.Components;
+using Content.Shared.Interaction;
+using Content.Shared.Verbs;
+using Content.Shared.Plunger.Components;
+using Robust.Shared.Audio.Systems;
+using Robust.Shared.Random;
+using Robust.Shared.Utility;
+using Content.Shared.Toilet.Components;
+
+namespace Content.Shared.Toilet.Systems;
+
+/// <summary>
+/// Handles sprite changes for both toilet seat up and down as well as for lid
+/// open and closed.
+/// </summary>
+public sealed class ToiletSystem : EntitySystem
+{
+    [Dependency] private readonly IRobustRandom _random = default!;
+    [Dependency] private readonly SharedAudioSystem _audio = default!;
+    [Dependency] private readonly SharedAppearanceSystem _appearance = default!;
+
+    public override void Initialize()
+    {
+        base.Initialize();
+
+        SubscribeLocalEvent<ToiletComponent, MapInitEvent>(OnMapInit);
+        SubscribeLocalEvent<ToiletComponent, GetVerbsEvent<AlternativeVerb>>(OnToggleSeatVerb);
+        SubscribeLocalEvent<ToiletComponent, ActivateInWorldEvent>(OnActivateInWorld);
+    }
+
+    private void OnMapInit(Entity<ToiletComponent> ent, ref MapInitEvent args)
+    {
+        if (_random.Prob(0.5f))
+        {
+            ent.Comp.ToggleSeat = true;
+            Dirty(ent);
+        }
+
+        if (_random.Prob(0.3f)
+            && TryComp<PlungerUseComponent>(ent, out var plunger))
+        {
+            plunger.NeedsPlunger = true;
+            Dirty(ent, plunger);
+        }
+
+        UpdateAppearance(ent);
+    }
+
+    private void OnToggleSeatVerb(Entity<ToiletComponent> ent, ref GetVerbsEvent<AlternativeVerb> args)
+    {
+        if (!args.CanInteract || !args.CanAccess || args.Hands == null || !CanToggle(ent))
+            return;
+
+        var user = args.User;
+        AlternativeVerb toggleVerb = new() { Act = () => ToggleToiletSeat(ent.AsNullable(), user) };
+
+        if (ent.Comp.ToggleSeat)
+        {
+            toggleVerb.Text = Loc.GetString("toilet-seat-close");
+            toggleVerb.Icon =
+                new SpriteSpecifier.Texture(new ResPath("/Textures/Interface/VerbIcons/close.svg.192dpi.png"));
+        }
+        else
+        {
+            toggleVerb.Text = Loc.GetString("toilet-seat-open");
+            toggleVerb.Icon =
+                new SpriteSpecifier.Texture(new ResPath("/Textures/Interface/VerbIcons/open.svg.192dpi.png"));
+        }
+        args.Verbs.Add(toggleVerb);
+    }
+
+    private void OnActivateInWorld(Entity<ToiletComponent> ent, ref ActivateInWorldEvent args)
+    {
+        if (args.Handled || !args.Complex)
+            return;
+
+        args.Handled = true;
+        ToggleToiletSeat(ent.AsNullable(), args.User);
+    }
+
+    private void UpdateAppearance(Entity<ToiletComponent> ent)
+    {
+        _appearance.SetData(ent,
+            ToiletVisuals.SeatVisualState,
+            ent.Comp.ToggleSeat ? SeatVisualState.SeatUp : SeatVisualState.SeatDown);
+    }
+
+
+    /// <summary>
+    /// Toggles a toilet's seat. Yup. Doesn't check if anyone is on the seat.
+    /// </summary>
+    /// <param name="ent">The toilet being seat-toggled.</param>
+    /// <param name="user">The user doing the toggling; used for predicted audio.</param>
+    /// <seealso cref="CanToggle" />
+    public void ToggleToiletSeat(Entity<ToiletComponent?> ent, EntityUid? user = null)
+    {
+        if (!Resolve(ent, ref ent.Comp))
+            return;
+
+        ent.Comp.ToggleSeat = !ent.Comp.ToggleSeat;
+
+        _audio.PlayPredicted(ent.Comp.SeatSound, ent, user);
+        UpdateAppearance((ent, ent.Comp));
+        Dirty(ent);
+    }
+
+    /// <summary>
+    /// Whether or not a toilet seat can be toggled without phasing through
+    /// someone's back. (That is, no one is seated on it.)
+    /// </summary>
+    /// <seealso cref="ToggleToiletSeat" />
+    public bool CanToggle(EntityUid uid)
+    {
+        return TryComp<StrapComponent>(uid, out var strap) && strap.BuckledEntities.Count == 0;
+    }
+}
index 1b5ac30a9c4afebfde3e7d5d39d7eba4c5605710..a6753766d532aaa1b775c7af96160fb86a20383e 100644 (file)
@@ -75,6 +75,9 @@
     autoDrain: false
   - type: StaticPrice
     price: 100
+  - type: ActivatableUI
+    key: enum.DisposalUnitUiKey.Key
+    verbOnly: true # Not strictly needed, but we want E to toggle lid
   - type: UserInterface
     interfaces:
       enum.DisposalUnitUiKey.Key: