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