From 52ef8f9b7035e840d98efddc94bc6e8f9488dbd7 Mon Sep 17 00:00:00 2001 From: TNE <38938720+JustTNE@users.noreply.github.com> Date: Mon, 4 Sep 2023 14:53:13 +0200 Subject: [PATCH] Allow drag-and-drop insertion of reagents into the ChemMaster (#19796) * Add DumpableSolutionComponent Separates out the component from "DrainComponent" that allows one to drag a bucket/any reagent container onto a drain/sink/toilet to empty it and allows other reagent containers to reuse the code effortlessly. * Give the ChemMaster 4000 the DumpableSolution Component Allows drag and dropping solutions into the ChemMaster much like you used to be able to do exclusively with drains. This also allows dumping jugs into them. --- .../SolutionContainerSystem.Capabilities.cs | 15 ++++++++++ .../EntitySystems/PuddleSystem.Transfers.cs | 30 ++++++++++++------- .../Interaction/InteractionSystem.cs | 1 + .../Components/DumpableSolutionComponent.cs | 25 ++++++++++++++++ Content.Shared/Fluids/SharedPuddleSystem.cs | 14 +++++++-- .../Objects/Specific/Janitorial/janitor.yml | 2 ++ .../Entities/Structures/Furniture/sink.yml | 2 ++ .../Entities/Structures/Furniture/toilet.yml | 2 ++ .../Structures/Machines/chem_master.yml | 3 ++ 9 files changed, 82 insertions(+), 12 deletions(-) create mode 100644 Content.Shared/Chemistry/Components/DumpableSolutionComponent.cs diff --git a/Content.Server/Chemistry/EntitySystems/SolutionContainerSystem.Capabilities.cs b/Content.Server/Chemistry/EntitySystems/SolutionContainerSystem.Capabilities.cs index 0e47881c84..3b8505efd4 100644 --- a/Content.Server/Chemistry/EntitySystems/SolutionContainerSystem.Capabilities.cs +++ b/Content.Server/Chemistry/EntitySystems/SolutionContainerSystem.Capabilities.cs @@ -91,6 +91,21 @@ public sealed partial class SolutionContainerSystem return true; } + public bool TryGetDumpableSolution(EntityUid uid, + [NotNullWhen(true)] out Solution? solution, + DumpableSolutionComponent? dumpable = null, + SolutionContainerManagerComponent? manager = null) + { + if (!Resolve(uid, ref dumpable, ref manager, false) + || !manager.Solutions.TryGetValue(dumpable.Solution, out solution)) + { + solution = null; + return false; + } + + return true; + } + public bool TryGetDrawableSolution(EntityUid uid, [NotNullWhen(true)] out Solution? solution, DrawableSolutionComponent? drawable = null, diff --git a/Content.Server/Fluids/EntitySystems/PuddleSystem.Transfers.cs b/Content.Server/Fluids/EntitySystems/PuddleSystem.Transfers.cs index c73685c288..ba73adf389 100644 --- a/Content.Server/Fluids/EntitySystems/PuddleSystem.Transfers.cs +++ b/Content.Server/Fluids/EntitySystems/PuddleSystem.Transfers.cs @@ -24,20 +24,26 @@ public sealed partial class PuddleSystem return; } - TryComp(args.Target, out var drainable); - - _solutionContainerSystem.TryGetDrainableSolution(args.Target, out var drainableSolution, drainable); - - // Dump reagents into drain - if (TryComp(args.Target, out var drain) && drainable != null) + // Dump reagents into DumpableSolution + if (TryComp(args.Target, out var dump)) { - if (drainableSolution == null || solution == null) + _solutionContainerSystem.TryGetDumpableSolution(args.Target, out var dumpableSolution, dump); + if (dumpableSolution == null || solution == null) return; - var split = _solutionContainerSystem.SplitSolution(uid, solution, drainableSolution.AvailableVolume); + bool success = true; + if (dump.Unlimited) + { + var split = _solutionContainerSystem.SplitSolution(uid, solution, solution.Volume); + dumpableSolution.AddSolution(split, _prototypeManager); + } + else + { + var split = _solutionContainerSystem.SplitSolution(uid, solution, dumpableSolution.AvailableVolume); + success = _solutionContainerSystem.TryAddSolution(args.Target, dumpableSolution, split); + } - // TODO: Drane refactor - if (_solutionContainerSystem.TryAddSolution(args.Target, drainableSolution, split)) + if (success) { _audio.PlayPvs(AbsorbentComponent.DefaultTransferSound, args.Target); } @@ -49,6 +55,10 @@ public sealed partial class PuddleSystem return; } + TryComp(args.Target, out var drainable); + + _solutionContainerSystem.TryGetDrainableSolution(args.Target, out var drainableSolution, drainable); + // Take reagents from target if (drainable != null) { diff --git a/Content.Server/Interaction/InteractionSystem.cs b/Content.Server/Interaction/InteractionSystem.cs index 3b03d56ee7..f887e565a9 100644 --- a/Content.Server/Interaction/InteractionSystem.cs +++ b/Content.Server/Interaction/InteractionSystem.cs @@ -89,6 +89,7 @@ namespace Content.Server.Interaction var dropArgs = new DragDropTargetEvent(user.Value, msg.Dragged); + // trigger dragdrops on the target entity (what you are dropping onto) RaiseLocalEvent(msg.Target, ref dropArgs); } diff --git a/Content.Shared/Chemistry/Components/DumpableSolutionComponent.cs b/Content.Shared/Chemistry/Components/DumpableSolutionComponent.cs new file mode 100644 index 0000000000..ad9e1f19a6 --- /dev/null +++ b/Content.Shared/Chemistry/Components/DumpableSolutionComponent.cs @@ -0,0 +1,25 @@ +using Robust.Shared.GameStates; + +namespace Content.Shared.Chemistry.Components; + +/// +/// Denotes the solution that can be easily dumped into (completely removed from the dumping container into this one) +/// Think pouring a container fully into this. +/// +[RegisterComponent, NetworkedComponent] +public sealed partial class DumpableSolutionComponent : Component +{ + /// + /// Solution name that can be dumped into. + /// + [ViewVariables(VVAccess.ReadWrite)] + [DataField("solution")] + public string Solution { get; set; } = "default"; + + /// + /// Whether the solution can be dumped into infinitely. + /// + [ViewVariables(VVAccess.ReadWrite)] + [DataField("unlimited")] + public bool Unlimited { get; set; } = false; +} diff --git a/Content.Shared/Fluids/SharedPuddleSystem.cs b/Content.Shared/Fluids/SharedPuddleSystem.cs index 161ea1469d..056c3ba919 100644 --- a/Content.Shared/Fluids/SharedPuddleSystem.cs +++ b/Content.Shared/Fluids/SharedPuddleSystem.cs @@ -17,8 +17,9 @@ public abstract class SharedPuddleSystem : EntitySystem { base.Initialize(); SubscribeLocalEvent(OnRefillableCanDrag); - SubscribeLocalEvent(OnRefillableCanDropDragged); + SubscribeLocalEvent(OnDumpCanDropTarget); SubscribeLocalEvent(OnDrainCanDropTarget); + SubscribeLocalEvent(OnRefillableCanDropDragged); } private void OnRefillableCanDrag(EntityUid uid, RefillableSolutionComponent component, ref CanDragEvent args) @@ -26,6 +27,15 @@ public abstract class SharedPuddleSystem : EntitySystem args.Handled = true; } + private void OnDumpCanDropTarget(EntityUid uid, DumpableSolutionComponent component, ref CanDropTargetEvent args) + { + if (HasComp(args.Dragged)) + { + args.CanDrop = true; + args.Handled = true; + } + } + private void OnDrainCanDropTarget(EntityUid uid, DrainableSolutionComponent component, ref CanDropTargetEvent args) { if (HasComp(args.Dragged)) @@ -37,7 +47,7 @@ public abstract class SharedPuddleSystem : EntitySystem private void OnRefillableCanDropDragged(EntityUid uid, RefillableSolutionComponent component, ref CanDropDraggedEvent args) { - if (!HasComp(args.Target) && !HasComp(args.Target)) + if (!HasComp(args.Target) && !HasComp(args.Target)) return; args.CanDrop = true; diff --git a/Resources/Prototypes/Entities/Objects/Specific/Janitorial/janitor.yml b/Resources/Prototypes/Entities/Objects/Specific/Janitorial/janitor.yml index 011db23bc8..e1755c9756 100644 --- a/Resources/Prototypes/Entities/Objects/Specific/Janitorial/janitor.yml +++ b/Resources/Prototypes/Entities/Objects/Specific/Janitorial/janitor.yml @@ -417,6 +417,8 @@ sound: path: /Audio/Ambience/Objects/drain.ogg - type: Drain + - type: DumpableSolution + solution: drainBuffer - type: Appearance - type: SolutionContainerVisuals maxFillLevels: 1 diff --git a/Resources/Prototypes/Entities/Structures/Furniture/sink.yml b/Resources/Prototypes/Entities/Structures/Furniture/sink.yml index 10f43a2050..9ae1a2bb3d 100644 --- a/Resources/Prototypes/Entities/Structures/Furniture/sink.yml +++ b/Resources/Prototypes/Entities/Structures/Furniture/sink.yml @@ -37,6 +37,8 @@ - type: ReagentTank - type: Drain autoDrain: false + - type: DumpableSolution + solution: drainBuffer - type: Damageable damageContainer: Inorganic damageModifierSet: Metallic diff --git a/Resources/Prototypes/Entities/Structures/Furniture/toilet.yml b/Resources/Prototypes/Entities/Structures/Furniture/toilet.yml index af0d2f1794..353129c5a4 100644 --- a/Resources/Prototypes/Entities/Structures/Furniture/toilet.yml +++ b/Resources/Prototypes/Entities/Structures/Furniture/toilet.yml @@ -36,6 +36,8 @@ - type: Appearance - type: Drain autoDrain: false + - type: DumpableSolution + solution: drainBuffer - type: SolutionContainerVisuals maxFillLevels: 1 fillBaseName: fill- diff --git a/Resources/Prototypes/Entities/Structures/Machines/chem_master.yml b/Resources/Prototypes/Entities/Structures/Machines/chem_master.yml index 1a012c5a6a..8c006572ed 100644 --- a/Resources/Prototypes/Entities/Structures/Machines/chem_master.yml +++ b/Resources/Prototypes/Entities/Structures/Machines/chem_master.yml @@ -86,6 +86,9 @@ - type: SolutionContainerManager solutions: buffer: {} + - type: DumpableSolution + solution: buffer + unlimited: true - type: GuideHelp guides: - Chemicals