]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
Add prediction to Openable (#25477)
authorTayrtahn <tayrtahn@gmail.com>
Fri, 23 Feb 2024 01:09:43 +0000 (20:09 -0500)
committerGitHub <noreply@github.com>
Fri, 23 Feb 2024 01:09:43 +0000 (12:09 +1100)
* Fix formatting problem with FullOpened

* Moved to Shared and networked

* Revert "Fix formatting problem with FullOpened"

This reverts commit f8353403da830a4402bdd457bcf24a2432a5f566.

Content.Client/Nutrition/EntitySystems/OpenableSystem.cs [new file with mode: 0644]
Content.Server/Nutrition/EntitySystems/OpenableSystem.cs
Content.Shared/Nutrition/Components/OpenableComponent.cs [moved from Content.Server/Nutrition/Components/OpenableComponent.cs with 86% similarity]
Content.Shared/Nutrition/EntitySystems/SharedOpenableSystem.cs

diff --git a/Content.Client/Nutrition/EntitySystems/OpenableSystem.cs b/Content.Client/Nutrition/EntitySystems/OpenableSystem.cs
new file mode 100644 (file)
index 0000000..f8c3f7c
--- /dev/null
@@ -0,0 +1,7 @@
+using Content.Shared.Nutrition.EntitySystems;
+
+namespace Content.Client.Nutrition.EntitySystems;
+
+public sealed class OpenableSystem : SharedOpenableSystem
+{
+}
index 373b97700f40937a8640553a0f0189edc613fdff..8037b61572af4f3bdeb3ff371072a6f366d16cbf 100644 (file)
@@ -1,16 +1,6 @@
 using Content.Server.Chemistry.EntitySystems;
-using Content.Server.Fluids.EntitySystems;
 using Content.Shared.Nutrition.EntitySystems;
-using Content.Server.Nutrition.Components;
-using Content.Shared.Examine;
-using Content.Shared.Interaction;
-using Content.Shared.Interaction.Events;
 using Content.Shared.Nutrition.Components;
-using Content.Shared.Popups;
-using Content.Shared.Verbs;
-using Content.Shared.Weapons.Melee.Events;
-using Robust.Shared.Audio.Systems;
-using Robust.Shared.Utility;
 
 namespace Content.Server.Nutrition.EntitySystems;
 
@@ -19,43 +9,11 @@ namespace Content.Server.Nutrition.EntitySystems;
 /// </summary>
 public sealed class OpenableSystem : SharedOpenableSystem
 {
-    [Dependency] private readonly SharedAppearanceSystem _appearance = default!;
-    [Dependency] private readonly SharedAudioSystem _audio = default!;
-    [Dependency] private readonly SharedPopupSystem _popup = default!;
-
     public override void Initialize()
     {
         base.Initialize();
 
-        SubscribeLocalEvent<OpenableComponent, ComponentInit>(OnInit);
-        SubscribeLocalEvent<OpenableComponent, UseInHandEvent>(OnUse);
-        SubscribeLocalEvent<OpenableComponent, ExaminedEvent>(OnExamined, after: new[] { typeof(PuddleSystem) });
         SubscribeLocalEvent<OpenableComponent, SolutionTransferAttemptEvent>(OnTransferAttempt);
-        SubscribeLocalEvent<OpenableComponent, MeleeHitEvent>(HandleIfClosed);
-        SubscribeLocalEvent<OpenableComponent, AfterInteractEvent>(HandleIfClosed);
-        SubscribeLocalEvent<OpenableComponent, GetVerbsEvent<Verb>>(AddOpenCloseVerbs);
-    }
-
-    private void OnInit(EntityUid uid, OpenableComponent comp, ComponentInit args)
-    {
-        UpdateAppearance(uid, comp);
-    }
-
-    private void OnUse(EntityUid uid, OpenableComponent comp, UseInHandEvent args)
-    {
-        if (args.Handled || !comp.OpenableByHand)
-            return;
-
-        args.Handled = TryOpen(uid, comp);
-    }
-
-    private void OnExamined(EntityUid uid, OpenableComponent comp, ExaminedEvent args)
-    {
-        if (!comp.Opened || !args.IsInDetailsRange)
-            return;
-
-        var text = Loc.GetString(comp.ExamineText);
-        args.PushMarkup(text);
     }
 
     private void OnTransferAttempt(EntityUid uid, OpenableComponent comp, SolutionTransferAttemptEvent args)
@@ -66,135 +24,4 @@ public sealed class OpenableSystem : SharedOpenableSystem
             args.Cancel(Loc.GetString("drink-component-try-use-drink-not-open", ("owner", uid)));
         }
     }
-
-    private void HandleIfClosed(EntityUid uid, OpenableComponent comp, HandledEntityEventArgs args)
-    {
-        // prevent spilling/pouring/whatever drinks when closed
-        args.Handled = !comp.Opened;
-    }
-
-    private void AddOpenCloseVerbs(EntityUid uid, OpenableComponent comp, GetVerbsEvent<Verb> args)
-    {
-        if (args.Hands == null || !args.CanAccess || !args.CanInteract)
-            return;
-
-        Verb verb;
-        if (comp.Opened)
-        {
-            if (!comp.Closeable)
-                return;
-
-            verb = new()
-            {
-                Text = Loc.GetString(comp.CloseVerbText),
-                Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/VerbIcons/close.svg.192dpi.png")),
-                Act = () => TryClose(args.Target, comp)
-            };
-        }
-        else
-        {
-            verb = new()
-            {
-                Text = Loc.GetString(comp.OpenVerbText),
-                Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/VerbIcons/open.svg.192dpi.png")),
-                Act = () => TryOpen(args.Target, comp)
-            };
-        }
-        args.Verbs.Add(verb);
-    }
-
-    /// <summary>
-    /// Returns true if the entity either does not have OpenableComponent or it is opened.
-    /// Drinks that don't have OpenableComponent are automatically open, so it returns true.
-    /// </summary>
-    public bool IsOpen(EntityUid uid, OpenableComponent? comp = null)
-    {
-        if (!Resolve(uid, ref comp, false))
-            return true;
-
-        return comp.Opened;
-    }
-
-    /// <summary>
-    /// Returns true if the entity both has OpenableComponent and is not opened.
-    /// Drinks that don't have OpenableComponent are automatically open, so it returns false.
-    /// If user is not null a popup will be shown to them.
-    /// </summary>
-    public bool IsClosed(EntityUid uid, EntityUid? user = null, OpenableComponent? comp = null)
-    {
-        if (!Resolve(uid, ref comp, false))
-            return false;
-
-        if (comp.Opened)
-            return false;
-
-        if (user != null)
-            _popup.PopupEntity(Loc.GetString(comp.ClosedPopup, ("owner", uid)), user.Value, user.Value);
-
-        return true;
-    }
-
-    /// <summary>
-    /// Update open visuals to the current value.
-    /// </summary>
-    public void UpdateAppearance(EntityUid uid, OpenableComponent? comp = null, AppearanceComponent? appearance = null)
-    {
-        if (!Resolve(uid, ref comp))
-            return;
-
-        _appearance.SetData(uid, OpenableVisuals.Opened, comp.Opened, appearance);
-    }
-
-    /// <summary>
-    /// Sets the opened field and updates open visuals.
-    /// </summary>
-    public void SetOpen(EntityUid uid, bool opened = true, OpenableComponent? comp = null)
-    {
-        if (!Resolve(uid, ref comp, false) || opened == comp.Opened)
-            return;
-
-        comp.Opened = opened;
-
-        if (opened)
-        {
-            var ev = new OpenableOpenedEvent();
-            RaiseLocalEvent(uid, ref ev);
-        }
-        else
-        {
-            var ev = new OpenableClosedEvent();
-            RaiseLocalEvent(uid, ref ev);
-        }
-
-        UpdateAppearance(uid, comp);
-    }
-
-    /// <summary>
-    /// If closed, opens it and plays the sound.
-    /// </summary>
-    /// <returns>Whether it got opened</returns>
-    public bool TryOpen(EntityUid uid, OpenableComponent? comp = null)
-    {
-        if (!Resolve(uid, ref comp, false) || comp.Opened)
-            return false;
-
-        SetOpen(uid, true, comp);
-        _audio.PlayPvs(comp.Sound, uid);
-        return true;
-    }
-
-    /// <summary>
-    /// If opened, closes it and plays the close sound, if one is defined.
-    /// </summary>
-    /// <returns>Whether it got closed</returns>
-    public bool TryClose(EntityUid uid, OpenableComponent? comp = null)
-    {
-        if (!Resolve(uid, ref comp, false) || !comp.Opened || !comp.Closeable)
-            return false;
-
-        SetOpen(uid, false, comp);
-        if (comp.CloseSound != null)
-            _audio.PlayPvs(comp.CloseSound, uid);
-        return true;
-    }
 }
similarity index 86%
rename from Content.Server/Nutrition/Components/OpenableComponent.cs
rename to Content.Shared/Nutrition/Components/OpenableComponent.cs
index cc24bf44dca46705497bd8272e105564797a7b39..3a230fc765dd5d3a9f0c99c503ab7dd26e2b42f2 100644 (file)
@@ -1,27 +1,29 @@
-using Content.Server.Nutrition.EntitySystems;
+using Content.Shared.Nutrition.EntitySystems;
 using Robust.Shared.Audio;
+using Robust.Shared.GameStates;
 
-namespace Content.Server.Nutrition.Components;
+namespace Content.Shared.Nutrition.Components;
 
 /// <summary>
 /// A drink or food that can be opened.
 /// Starts closed, open it with Z or E.
 /// </summary>
-[RegisterComponent, Access(typeof(OpenableSystem))]
+[NetworkedComponent, AutoGenerateComponentState]
+[RegisterComponent, Access(typeof(SharedOpenableSystem))]
 public sealed partial class OpenableComponent : Component
 {
     /// <summary>
     /// Whether this drink or food is opened or not.
     /// Drinks can only be drunk or poured from/into when open, and food can only be eaten when open.
     /// </summary>
-    [DataField]
+    [DataField, AutoNetworkedField]
     public bool Opened;
 
     /// <summary>
     /// If this is false you cant press Z to open it.
     /// Requires an OpenBehavior damage threshold or other logic to open.
     /// </summary>
-    [DataField]
+    [DataField, AutoNetworkedField]
     public bool OpenableByHand = true;
 
     /// <summary>
@@ -61,7 +63,7 @@ public sealed partial class OpenableComponent : Component
     /// <summary>
     /// Can this item be closed again after opening?
     /// </summary>
-    [DataField]
+    [DataField, AutoNetworkedField]
     public bool Closeable;
 
     /// <summary>
index 274de89003a18e5cdb24cf7d51a42539b4553c58..f3b1127578d93969579d98cf823a0bf25b66e6e8 100644 (file)
@@ -1,7 +1,189 @@
+using Content.Shared.Examine;
+using Content.Shared.Interaction;
+using Content.Shared.Interaction.Events;
+using Content.Shared.Nutrition.Components;
+using Content.Shared.Popups;
+using Content.Shared.Verbs;
+using Content.Shared.Weapons.Melee.Events;
+using Robust.Shared.Audio.Systems;
+using Robust.Shared.Utility;
+
 namespace Content.Shared.Nutrition.EntitySystems;
 
+/// <summary>
+/// Provides API for openable food and drinks, handles opening on use and preventing transfer when closed.
+/// </summary>
 public abstract partial class SharedOpenableSystem : EntitySystem
 {
+    [Dependency] protected readonly SharedAppearanceSystem Appearance = default!;
+    [Dependency] protected readonly SharedAudioSystem Audio = default!;
+    [Dependency] protected readonly SharedPopupSystem Popup = default!;
+
+    public override void Initialize()
+    {
+        base.Initialize();
+
+        SubscribeLocalEvent<OpenableComponent, ComponentInit>(OnInit);
+        SubscribeLocalEvent<OpenableComponent, UseInHandEvent>(OnUse);
+        SubscribeLocalEvent<OpenableComponent, ExaminedEvent>(OnExamined);
+        SubscribeLocalEvent<OpenableComponent, MeleeHitEvent>(HandleIfClosed);
+        SubscribeLocalEvent<OpenableComponent, AfterInteractEvent>(HandleIfClosed);
+        SubscribeLocalEvent<OpenableComponent, GetVerbsEvent<Verb>>(AddOpenCloseVerbs);
+    }
+
+    private void OnInit(EntityUid uid, OpenableComponent comp, ComponentInit args)
+    {
+        UpdateAppearance(uid, comp);
+    }
+
+    private void OnUse(EntityUid uid, OpenableComponent comp, UseInHandEvent args)
+    {
+        if (args.Handled || !comp.OpenableByHand)
+            return;
+
+        args.Handled = TryOpen(uid, comp, args.User);
+    }
+
+    private void OnExamined(EntityUid uid, OpenableComponent comp, ExaminedEvent args)
+    {
+        if (!comp.Opened || !args.IsInDetailsRange)
+            return;
+
+        var text = Loc.GetString(comp.ExamineText);
+        args.PushMarkup(text);
+    }
+
+    private void HandleIfClosed(EntityUid uid, OpenableComponent comp, HandledEntityEventArgs args)
+    {
+        // prevent spilling/pouring/whatever drinks when closed
+        args.Handled = !comp.Opened;
+    }
+
+    private void AddOpenCloseVerbs(EntityUid uid, OpenableComponent comp, GetVerbsEvent<Verb> args)
+    {
+        if (args.Hands == null || !args.CanAccess || !args.CanInteract)
+            return;
+
+        Verb verb;
+        if (comp.Opened)
+        {
+            if (!comp.Closeable)
+                return;
+
+            verb = new()
+            {
+                Text = Loc.GetString(comp.CloseVerbText),
+                Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/VerbIcons/close.svg.192dpi.png")),
+                Act = () => TryClose(args.Target, comp, args.User)
+            };
+        }
+        else
+        {
+            verb = new()
+            {
+                Text = Loc.GetString(comp.OpenVerbText),
+                Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/VerbIcons/open.svg.192dpi.png")),
+                Act = () => TryOpen(args.Target, comp, args.User)
+            };
+        }
+        args.Verbs.Add(verb);
+    }
+
+    /// <summary>
+    /// Returns true if the entity either does not have OpenableComponent or it is opened.
+    /// Drinks that don't have OpenableComponent are automatically open, so it returns true.
+    /// </summary>
+    public bool IsOpen(EntityUid uid, OpenableComponent? comp = null)
+    {
+        if (!Resolve(uid, ref comp, false))
+            return true;
+
+        return comp.Opened;
+    }
+
+    /// <summary>
+    /// Returns true if the entity both has OpenableComponent and is not opened.
+    /// Drinks that don't have OpenableComponent are automatically open, so it returns false.
+    /// If user is not null a popup will be shown to them.
+    /// </summary>
+    public bool IsClosed(EntityUid uid, EntityUid? user = null, OpenableComponent? comp = null)
+    {
+        if (!Resolve(uid, ref comp, false))
+            return false;
+
+        if (comp.Opened)
+            return false;
+
+        if (user != null)
+            Popup.PopupEntity(Loc.GetString(comp.ClosedPopup, ("owner", uid)), user.Value, user.Value);
+
+        return true;
+    }
+
+    /// <summary>
+    /// Update open visuals to the current value.
+    /// </summary>
+    public void UpdateAppearance(EntityUid uid, OpenableComponent? comp = null, AppearanceComponent? appearance = null)
+    {
+        if (!Resolve(uid, ref comp))
+            return;
+
+        Appearance.SetData(uid, OpenableVisuals.Opened, comp.Opened, appearance);
+    }
+
+    /// <summary>
+    /// Sets the opened field and updates open visuals.
+    /// </summary>
+    public void SetOpen(EntityUid uid, bool opened = true, OpenableComponent? comp = null)
+    {
+        if (!Resolve(uid, ref comp, false) || opened == comp.Opened)
+            return;
+
+        comp.Opened = opened;
+        Dirty(uid, comp);
+
+        if (opened)
+        {
+            var ev = new OpenableOpenedEvent();
+            RaiseLocalEvent(uid, ref ev);
+        }
+        else
+        {
+            var ev = new OpenableClosedEvent();
+            RaiseLocalEvent(uid, ref ev);
+        }
+
+        UpdateAppearance(uid, comp);
+    }
+
+    /// <summary>
+    /// If closed, opens it and plays the sound.
+    /// </summary>
+    /// <returns>Whether it got opened</returns>
+    public bool TryOpen(EntityUid uid, OpenableComponent? comp = null, EntityUid? user = null)
+    {
+        if (!Resolve(uid, ref comp, false) || comp.Opened)
+            return false;
+
+        SetOpen(uid, true, comp);
+        Audio.PlayPredicted(comp.Sound, uid, user);
+        return true;
+    }
+
+    /// <summary>
+    /// If opened, closes it and plays the close sound, if one is defined.
+    /// </summary>
+    /// <returns>Whether it got closed</returns>
+    public bool TryClose(EntityUid uid, OpenableComponent? comp = null, EntityUid? user = null)
+    {
+        if (!Resolve(uid, ref comp, false) || !comp.Opened || !comp.Closeable)
+            return false;
+
+        SetOpen(uid, false, comp);
+        if (comp.CloseSound != null)
+            Audio.PlayPredicted(comp.CloseSound, uid, user);
+        return true;
+    }
 }
 
 /// <summary>