From 662d2ee964e934138ab945bde64fc390454e7db2 Mon Sep 17 00:00:00 2001
From: ScarKy0 <106310278+ScarKy0@users.noreply.github.com>
Date: Sat, 27 Dec 2025 18:09:33 +0100
Subject: [PATCH] ReagentGrinder Comp and API to shared (#41956)
* init
* API
* review
* return
* review
* I tend to be stupid
---
.../EntitySystems/ReagentGrinderSystem.cs | 8 +++
.../Components/ReagentGrinderComponent.cs | 52 --------------
.../EntitySystems/ReagentGrinderSystem.cs | 47 +++----------
.../Components/ReagentGrinderComponent.cs | 54 +++++++++++++++
.../SharedReagentGrinderSystem.cs | 68 +++++++++++++++++++
.../Kitchen/SharedReagentGrinder.cs | 1 +
6 files changed, 140 insertions(+), 90 deletions(-)
create mode 100644 Content.Client/Kitchen/EntitySystems/ReagentGrinderSystem.cs
delete mode 100644 Content.Server/Kitchen/Components/ReagentGrinderComponent.cs
create mode 100644 Content.Shared/Kitchen/Components/ReagentGrinderComponent.cs
create mode 100644 Content.Shared/Kitchen/EntitySystems/SharedReagentGrinderSystem.cs
diff --git a/Content.Client/Kitchen/EntitySystems/ReagentGrinderSystem.cs b/Content.Client/Kitchen/EntitySystems/ReagentGrinderSystem.cs
new file mode 100644
index 0000000000..5eebd4a0fb
--- /dev/null
+++ b/Content.Client/Kitchen/EntitySystems/ReagentGrinderSystem.cs
@@ -0,0 +1,8 @@
+using Content.Shared.Kitchen.EntitySystems;
+using JetBrains.Annotations;
+
+namespace Content.Client.Kitchen.EntitySystems;
+
+[UsedImplicitly]
+public sealed class ReagentGrinderSystem : SharedReagentGrinderSystem;
+
diff --git a/Content.Server/Kitchen/Components/ReagentGrinderComponent.cs b/Content.Server/Kitchen/Components/ReagentGrinderComponent.cs
deleted file mode 100644
index 5bbbe2dc8d..0000000000
--- a/Content.Server/Kitchen/Components/ReagentGrinderComponent.cs
+++ /dev/null
@@ -1,52 +0,0 @@
-using Content.Shared.Kitchen;
-using Content.Server.Kitchen.EntitySystems;
-using Robust.Shared.Audio;
-
-namespace Content.Server.Kitchen.Components
-{
- ///
- /// The combo reagent grinder/juicer. The reason why grinding and juicing are seperate is simple,
- /// think of grinding as a utility to break an object down into its reagents. Think of juicing as
- /// converting something into its single juice form. E.g, grind an apple and get the nutriment and sugar
- /// it contained, juice an apple and get "apple juice".
- ///
- [Access(typeof(ReagentGrinderSystem)), RegisterComponent]
- public sealed partial class ReagentGrinderComponent : Component
- {
- [DataField]
- public int StorageMaxEntities = 6;
-
- [DataField]
- public TimeSpan WorkTime = TimeSpan.FromSeconds(3.5); // Roughly matches the grind/juice sounds.
-
- [DataField]
- public float WorkTimeMultiplier = 1;
-
- [DataField]
- public SoundSpecifier ClickSound { get; set; } = new SoundPathSpecifier("/Audio/Machines/machine_switch.ogg");
-
- [DataField]
- public SoundSpecifier GrindSound { get; set; } = new SoundPathSpecifier("/Audio/Machines/blender.ogg");
-
- [DataField]
- public SoundSpecifier JuiceSound { get; set; } = new SoundPathSpecifier("/Audio/Machines/juicer.ogg");
-
- [DataField]
- public GrinderAutoMode AutoMode = GrinderAutoMode.Off;
-
- public EntityUid? AudioStream;
- }
-
- [Access(typeof(ReagentGrinderSystem)), RegisterComponent]
- public sealed partial class ActiveReagentGrinderComponent : Component
- {
- ///
- /// Remaining time until the grinder finishes grinding/juicing.
- ///
- [ViewVariables]
- public TimeSpan EndTime;
-
- [ViewVariables]
- public GrinderProgram Program;
- }
-}
diff --git a/Content.Server/Kitchen/EntitySystems/ReagentGrinderSystem.cs b/Content.Server/Kitchen/EntitySystems/ReagentGrinderSystem.cs
index b850bc87fa..a709f4b8d9 100644
--- a/Content.Server/Kitchen/EntitySystems/ReagentGrinderSystem.cs
+++ b/Content.Server/Kitchen/EntitySystems/ReagentGrinderSystem.cs
@@ -1,5 +1,3 @@
-using Content.Server.Kitchen.Components;
-using Content.Server.Power.Components;
using Content.Server.Power.EntitySystems;
using Content.Server.Stack;
using Content.Shared.Chemistry.EntitySystems;
@@ -20,15 +18,15 @@ using Robust.Shared.Audio.Systems;
using Robust.Shared.Containers;
using Robust.Shared.Timing;
using System.Linq;
-using Content.Server.Construction.Completions;
using Content.Server.Jittering;
using Content.Shared.Jittering;
+using Content.Shared.Kitchen.EntitySystems;
using Content.Shared.Power;
namespace Content.Server.Kitchen.EntitySystems
{
[UsedImplicitly]
- internal sealed class ReagentGrinderSystem : EntitySystem
+ internal sealed class ReagentGrinderSystem : SharedReagentGrinderSystem
{
[Dependency] private readonly IGameTiming _timing = default!;
[Dependency] private readonly SharedSolutionContainerSystem _solutionContainersSystem = default!;
@@ -67,6 +65,8 @@ namespace Content.Server.Kitchen.EntitySystems
{
entity.Comp.AutoMode = (GrinderAutoMode) (((byte) entity.Comp.AutoMode + 1) % Enum.GetValues(typeof(GrinderAutoMode)).Length);
+ Dirty(entity);
+
UpdateUiState(entity);
}
@@ -90,12 +90,7 @@ namespace Content.Server.Kitchen.EntitySystems
foreach (var item in inputContainer.ContainedEntities.ToList())
{
- var solution = active.Program switch
- {
- GrinderProgram.Grind => GetGrindSolution(item),
- GrinderProgram.Juice => CompOrNull(item)?.JuiceSolution,
- _ => null,
- };
+ var solution = GetGrinderSolution(item, active.Program);
if (solution is null)
continue;
@@ -218,8 +213,8 @@ namespace Content.Server.Kitchen.EntitySystems
&& _solutionContainersSystem.TryGetFitsInDispenser(outputContainer.Value, out _, out containerSolution)
&& inputContainer.ContainedEntities.Count > 0)
{
- canGrind = inputContainer.ContainedEntities.All(CanGrind);
- canJuice = inputContainer.ContainedEntities.All(CanJuice);
+ canGrind = inputContainer.ContainedEntities.All(x => CanGrind(x));
+ canJuice = inputContainer.ContainedEntities.All(x => CanJuice(x));
}
var state = new ReagentGrinderInterfaceState(
@@ -293,10 +288,10 @@ namespace Content.Server.Kitchen.EntitySystems
SoundSpecifier? sound;
switch (program)
{
- case GrinderProgram.Grind when inputContainer.ContainedEntities.All(CanGrind):
+ case GrinderProgram.Grind when inputContainer.ContainedEntities.All(x => CanGrind(x)):
sound = reagentGrinder.GrindSound;
break;
- case GrinderProgram.Juice when inputContainer.ContainedEntities.All(CanJuice):
+ case GrinderProgram.Juice when inputContainer.ContainedEntities.All(x => CanJuice(x)):
sound = reagentGrinder.JuiceSound;
break;
default:
@@ -317,29 +312,5 @@ namespace Content.Server.Kitchen.EntitySystems
{
_audioSystem.PlayPvs(reagentGrinder.Comp.ClickSound, reagentGrinder.Owner, AudioParams.Default.WithVolume(-2f));
}
-
- private Solution? GetGrindSolution(EntityUid uid)
- {
- if (TryComp(uid, out var extractable)
- && extractable.GrindableSolution is not null
- && _solutionContainersSystem.TryGetSolution(uid, extractable.GrindableSolution, out _, out var solution))
- {
- return solution;
- }
- else
- return null;
- }
-
- private bool CanGrind(EntityUid uid)
- {
- var solutionName = CompOrNull(uid)?.GrindableSolution;
-
- return solutionName is not null && _solutionContainersSystem.TryGetSolution(uid, solutionName, out _, out _);
- }
-
- private bool CanJuice(EntityUid uid)
- {
- return CompOrNull(uid)?.JuiceSolution is not null;
- }
}
}
diff --git a/Content.Shared/Kitchen/Components/ReagentGrinderComponent.cs b/Content.Shared/Kitchen/Components/ReagentGrinderComponent.cs
new file mode 100644
index 0000000000..6b8eb6f4ac
--- /dev/null
+++ b/Content.Shared/Kitchen/Components/ReagentGrinderComponent.cs
@@ -0,0 +1,54 @@
+using Content.Shared.Kitchen.EntitySystems;
+using Robust.Shared.Audio;
+using Robust.Shared.GameStates;
+
+namespace Content.Shared.Kitchen.Components;
+
+///
+/// The combo reagent grinder/juicer. The reason why grinding and juicing are seperate is simple,
+/// think of grinding as a utility to break an object down into its reagents. Think of juicing as
+/// converting something into its single juice form. E.g, grind an apple and get the nutriment and sugar
+/// it contained, juice an apple and get "apple juice".
+///
+[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
+[Access(typeof(SharedReagentGrinderSystem))]
+public sealed partial class ReagentGrinderComponent : Component
+{
+ [DataField, AutoNetworkedField]
+ public int StorageMaxEntities = 6;
+
+ [DataField, AutoNetworkedField]
+ public TimeSpan WorkTime = TimeSpan.FromSeconds(3.5); // Roughly matches the grind/juice sounds.
+
+ [DataField, AutoNetworkedField]
+ public float WorkTimeMultiplier = 1;
+
+ [DataField]
+ public SoundSpecifier ClickSound { get; set; } = new SoundPathSpecifier("/Audio/Machines/machine_switch.ogg");
+
+ [DataField]
+ public SoundSpecifier GrindSound { get; set; } = new SoundPathSpecifier("/Audio/Machines/blender.ogg");
+
+ [DataField]
+ public SoundSpecifier JuiceSound { get; set; } = new SoundPathSpecifier("/Audio/Machines/juicer.ogg");
+
+ [DataField, AutoNetworkedField]
+ public GrinderAutoMode AutoMode = GrinderAutoMode.Off;
+
+ public EntityUid? AudioStream;
+}
+
+[RegisterComponent, NetworkedComponent]
+[Access(typeof(SharedReagentGrinderSystem))]
+public sealed partial class ActiveReagentGrinderComponent : Component
+{
+ ///
+ /// Remaining time until the grinder finishes grinding/juicing.
+ ///
+ [ViewVariables]
+ public TimeSpan EndTime;
+
+ [ViewVariables]
+ public GrinderProgram Program;
+}
+
diff --git a/Content.Shared/Kitchen/EntitySystems/SharedReagentGrinderSystem.cs b/Content.Shared/Kitchen/EntitySystems/SharedReagentGrinderSystem.cs
new file mode 100644
index 0000000000..b54fd1d49e
--- /dev/null
+++ b/Content.Shared/Kitchen/EntitySystems/SharedReagentGrinderSystem.cs
@@ -0,0 +1,68 @@
+using Content.Shared.Chemistry.EntitySystems;
+using Content.Shared.Chemistry.Components;
+using Content.Shared.Kitchen.Components;
+using JetBrains.Annotations;
+
+namespace Content.Shared.Kitchen.EntitySystems;
+
+[UsedImplicitly]
+public abstract class SharedReagentGrinderSystem : EntitySystem
+{
+ [Dependency] private readonly SharedSolutionContainerSystem _solutionContainersSystem = default!;
+
+ ///
+ /// Gets the solutions from an entity using the specified Grinder program.
+ ///
+ /// The entity which we check for solutions.
+ /// The grinder program.
+ /// The solution received, or null if none.
+ public Solution? GetGrinderSolution(Entity ent, GrinderProgram program)
+ {
+ if (!Resolve(ent, ref ent.Comp, false))
+ return null;
+
+ switch (program)
+ {
+ case GrinderProgram.Grind:
+ if (_solutionContainersSystem.TryGetSolution(ent.Owner, ent.Comp.GrindableSolution, out _, out var solution))
+ {
+ return solution;
+ }
+ break;
+ case GrinderProgram.Juice:
+ return ent.Comp.JuiceSolution;
+ }
+
+ return null;
+ }
+
+ ///
+ /// Checks whether the entity can be ground using a ReagentGrinder.
+ ///
+ /// The entity to check.
+ /// True if it can be ground, otherwise false.
+ public bool CanGrind(Entity ent)
+ {
+ if (!Resolve(ent, ref ent.Comp, false))
+ return false;
+
+ if (ent.Comp.GrindableSolution == null)
+ return false;
+
+ return _solutionContainersSystem.TryGetSolution(ent.Owner, ent.Comp.GrindableSolution, out _, out _);
+ }
+
+ ///
+ /// Checks whether the entity can be juiced using a ReagentGrinder.
+ ///
+ /// The entity to check.
+ /// True if it can be juiced, otherwise false.
+ public bool CanJuice(Entity ent)
+ {
+ if (!Resolve(ent, ref ent.Comp, false))
+ return false;
+
+ return ent.Comp.JuiceSolution is not null;
+ }
+}
+
diff --git a/Content.Shared/Kitchen/SharedReagentGrinder.cs b/Content.Shared/Kitchen/SharedReagentGrinder.cs
index 579db239c8..83088555da 100644
--- a/Content.Shared/Kitchen/SharedReagentGrinder.cs
+++ b/Content.Shared/Kitchen/SharedReagentGrinder.cs
@@ -81,6 +81,7 @@ namespace Content.Shared.Kitchen
Key
}
+ [Serializable, NetSerializable]
public enum GrinderAutoMode : byte
{
Off,
--
2.52.0