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