From 7485411ab2a2570f70cf37135647c22ad557c5d3 Mon Sep 17 00:00:00 2001
From: beck-thompson <107373427+beck-thompson@users.noreply.github.com>
Date: Fri, 27 Sep 2024 21:40:24 -0700
Subject: [PATCH] Predict appraisal tool verb! (#32496)
* First commit
* Network :(
---
.../Cargo/Systems/ClientPriceGunSystem.cs | 21 +++++++
.../Cargo/Components/PriceGunComponent.cs | 10 ---
.../Cargo/Systems/PriceGunSystem.cs | 61 ++++---------------
.../Cargo/Components/PriceGunComponent.cs | 11 ++++
Content.Shared/Cargo/SharedPriceGunSystem.cs | 55 +++++++++++++++++
5 files changed, 98 insertions(+), 60 deletions(-)
create mode 100644 Content.Client/Cargo/Systems/ClientPriceGunSystem.cs
delete mode 100644 Content.Server/Cargo/Components/PriceGunComponent.cs
create mode 100644 Content.Shared/Cargo/Components/PriceGunComponent.cs
create mode 100644 Content.Shared/Cargo/SharedPriceGunSystem.cs
diff --git a/Content.Client/Cargo/Systems/ClientPriceGunSystem.cs b/Content.Client/Cargo/Systems/ClientPriceGunSystem.cs
new file mode 100644
index 0000000000..f173932478
--- /dev/null
+++ b/Content.Client/Cargo/Systems/ClientPriceGunSystem.cs
@@ -0,0 +1,21 @@
+using Content.Shared.Timing;
+using Content.Shared.Cargo.Systems;
+
+namespace Content.Client.Cargo.Systems;
+
+///
+/// This handles...
+///
+public sealed class ClientPriceGunSystem : SharedPriceGunSystem
+{
+ [Dependency] private readonly UseDelaySystem _useDelay = default!;
+
+ protected override bool GetPriceOrBounty(EntityUid priceGunUid, EntityUid target, EntityUid user)
+ {
+ if (!TryComp(priceGunUid, out UseDelayComponent? useDelay) || _useDelay.IsDelayed((priceGunUid, useDelay)))
+ return false;
+
+ // It feels worse if the cooldown is predicted but the popup isn't! So only do the cooldown reset on the server.
+ return true;
+ }
+}
diff --git a/Content.Server/Cargo/Components/PriceGunComponent.cs b/Content.Server/Cargo/Components/PriceGunComponent.cs
deleted file mode 100644
index 7207beae99..0000000000
--- a/Content.Server/Cargo/Components/PriceGunComponent.cs
+++ /dev/null
@@ -1,10 +0,0 @@
-namespace Content.Server.Cargo.Components;
-
-///
-/// This is used for the price gun, which calculates the price of any object it appraises.
-///
-[RegisterComponent]
-public sealed partial class PriceGunComponent : Component
-{
-
-}
diff --git a/Content.Server/Cargo/Systems/PriceGunSystem.cs b/Content.Server/Cargo/Systems/PriceGunSystem.cs
index 19fe07bd25..94f9f9cba9 100644
--- a/Content.Server/Cargo/Systems/PriceGunSystem.cs
+++ b/Content.Server/Cargo/Systems/PriceGunSystem.cs
@@ -1,73 +1,34 @@
-using Content.Server.Cargo.Components;
using Content.Server.Popups;
using Content.Shared.IdentityManagement;
-using Content.Shared.Interaction;
using Content.Shared.Timing;
-using Content.Shared.Verbs;
+using Content.Shared.Cargo.Systems;
namespace Content.Server.Cargo.Systems;
-///
-/// This handles...
-///
-public sealed class PriceGunSystem : EntitySystem
+public sealed class PriceGunSystem : SharedPriceGunSystem
{
[Dependency] private readonly UseDelaySystem _useDelay = default!;
[Dependency] private readonly PricingSystem _pricingSystem = default!;
[Dependency] private readonly PopupSystem _popupSystem = default!;
[Dependency] private readonly CargoSystem _bountySystem = default!;
- ///
- public override void Initialize()
+ protected override bool GetPriceOrBounty(EntityUid priceGunUid, EntityUid target, EntityUid user)
{
- SubscribeLocalEvent(OnAfterInteract);
- SubscribeLocalEvent>(OnUtilityVerb);
- }
-
- private void OnUtilityVerb(EntityUid uid, PriceGunComponent component, GetVerbsEvent args)
- {
- if (!args.CanAccess || !args.CanInteract || args.Using == null)
- return;
-
- if (!TryComp(uid, out UseDelayComponent? useDelay) || _useDelay.IsDelayed((uid, useDelay)))
- return;
-
- var price = _pricingSystem.GetPrice(args.Target);
-
- var verb = new UtilityVerb()
- {
- Act = () =>
- {
- _popupSystem.PopupEntity(Loc.GetString("price-gun-pricing-result", ("object", Identity.Entity(args.Target, EntityManager)), ("price", $"{price:F2}")), args.User, args.User);
- _useDelay.TryResetDelay((uid, useDelay));
- },
- Text = Loc.GetString("price-gun-verb-text"),
- Message = Loc.GetString("price-gun-verb-message", ("object", Identity.Entity(args.Target, EntityManager)))
- };
-
- args.Verbs.Add(verb);
- }
-
- private void OnAfterInteract(EntityUid uid, PriceGunComponent component, AfterInteractEvent args)
- {
- if (!args.CanReach || args.Target == null || args.Handled)
- return;
-
- if (!TryComp(uid, out UseDelayComponent? useDelay) || _useDelay.IsDelayed((uid, useDelay)))
- return;
+ if (!TryComp(priceGunUid, out UseDelayComponent? useDelay) || _useDelay.IsDelayed((priceGunUid, useDelay)))
+ return false;
// Check if we're scanning a bounty crate
- if (_bountySystem.IsBountyComplete(args.Target.Value, out _))
+ if (_bountySystem.IsBountyComplete(target, out _))
{
- _popupSystem.PopupEntity(Loc.GetString("price-gun-bounty-complete"), args.User, args.User);
+ _popupSystem.PopupEntity(Loc.GetString("price-gun-bounty-complete"), user, user);
}
else // Otherwise appraise the price
{
- double price = _pricingSystem.GetPrice(args.Target.Value);
- _popupSystem.PopupEntity(Loc.GetString("price-gun-pricing-result", ("object", Identity.Entity(args.Target.Value, EntityManager)), ("price", $"{price:F2}")), args.User, args.User);
+ var price = _pricingSystem.GetPrice(target);
+ _popupSystem.PopupEntity(Loc.GetString("price-gun-pricing-result", ("object", Identity.Entity(target, EntityManager)), ("price", $"{price:F2}")), user, user);
}
- _useDelay.TryResetDelay((uid, useDelay));
- args.Handled = true;
+ _useDelay.TryResetDelay((priceGunUid, useDelay));
+ return true;
}
}
diff --git a/Content.Shared/Cargo/Components/PriceGunComponent.cs b/Content.Shared/Cargo/Components/PriceGunComponent.cs
new file mode 100644
index 0000000000..7024f1195a
--- /dev/null
+++ b/Content.Shared/Cargo/Components/PriceGunComponent.cs
@@ -0,0 +1,11 @@
+using Robust.Shared.GameStates;
+
+namespace Content.Shared.Cargo.Components;
+
+///
+/// This is used for the price gun, which calculates the price of any object it appraises.
+///
+[RegisterComponent, NetworkedComponent]
+public sealed partial class PriceGunComponent : Component
+{
+}
diff --git a/Content.Shared/Cargo/SharedPriceGunSystem.cs b/Content.Shared/Cargo/SharedPriceGunSystem.cs
new file mode 100644
index 0000000000..779d55055a
--- /dev/null
+++ b/Content.Shared/Cargo/SharedPriceGunSystem.cs
@@ -0,0 +1,55 @@
+using Content.Shared.Cargo.Components;
+using Content.Shared.IdentityManagement;
+using Content.Shared.Interaction;
+using Content.Shared.Verbs;
+
+namespace Content.Shared.Cargo.Systems;
+
+///
+/// The price gun system! If this component is on an entity, you can scan objects (Click or use verb) to see their price.
+///
+public abstract class SharedPriceGunSystem : EntitySystem
+{
+ public override void Initialize()
+ {
+ base.Initialize();
+ SubscribeLocalEvent>(OnUtilityVerb);
+ SubscribeLocalEvent(OnAfterInteract);
+ }
+
+ private void OnUtilityVerb(EntityUid uid, PriceGunComponent component, GetVerbsEvent args)
+ {
+ if (!args.CanAccess || !args.CanInteract || args.Using == null)
+ return;
+
+ var verb = new UtilityVerb()
+ {
+ Act = () =>
+ {
+ GetPriceOrBounty(uid, args.Target, args.User);
+ },
+ Text = Loc.GetString("price-gun-verb-text"),
+ Message = Loc.GetString("price-gun-verb-message", ("object", Identity.Entity(args.Target, EntityManager)))
+ };
+
+ args.Verbs.Add(verb);
+ }
+
+ private void OnAfterInteract(Entity entity, ref AfterInteractEvent args)
+ {
+ if (!args.CanReach || args.Target == null || args.Handled)
+ return;
+
+ args.Handled |= GetPriceOrBounty(entity, args.Target.Value, args.User);
+ }
+
+ ///
+ /// Find the price or confirm if the item is a bounty. Will give a popup of the result to the passed user.
+ ///
+ ///
+ ///
+ /// This is abstract for prediction. When the bounty system / cargo systems that are necessary are moved to shared,
+ /// combine all the server, client, and shared stuff into one non abstract file.
+ ///
+ protected abstract bool GetPriceOrBounty(EntityUid priceGunUid, EntityUid target, EntityUid user);
+}
--
2.51.2