--- /dev/null
+using Content.Shared.Kitchen.EntitySystems;
+using JetBrains.Annotations;
+
+namespace Content.Client.Kitchen.EntitySystems;
+
+[UsedImplicitly]
+public sealed class ReagentGrinderSystem : SharedReagentGrinderSystem;
+
+++ /dev/null
-using Content.Shared.Kitchen;
-using Content.Server.Kitchen.EntitySystems;
-using Robust.Shared.Audio;
-
-namespace Content.Server.Kitchen.Components
-{
- /// <summary>
- /// 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".
- /// </summary>
- [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
- {
- /// <summary>
- /// Remaining time until the grinder finishes grinding/juicing.
- /// </summary>
- [ViewVariables]
- public TimeSpan EndTime;
-
- [ViewVariables]
- public GrinderProgram Program;
- }
-}
-using Content.Server.Kitchen.Components;
-using Content.Server.Power.Components;
using Content.Server.Power.EntitySystems;
using Content.Server.Stack;
using Content.Shared.Chemistry.EntitySystems;
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!;
{
entity.Comp.AutoMode = (GrinderAutoMode) (((byte) entity.Comp.AutoMode + 1) % Enum.GetValues(typeof(GrinderAutoMode)).Length);
+ Dirty(entity);
+
UpdateUiState(entity);
}
foreach (var item in inputContainer.ContainedEntities.ToList())
{
- var solution = active.Program switch
- {
- GrinderProgram.Grind => GetGrindSolution(item),
- GrinderProgram.Juice => CompOrNull<ExtractableComponent>(item)?.JuiceSolution,
- _ => null,
- };
+ var solution = GetGrinderSolution(item, active.Program);
if (solution is null)
continue;
&& _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(
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:
{
_audioSystem.PlayPvs(reagentGrinder.Comp.ClickSound, reagentGrinder.Owner, AudioParams.Default.WithVolume(-2f));
}
-
- private Solution? GetGrindSolution(EntityUid uid)
- {
- if (TryComp<ExtractableComponent>(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<ExtractableComponent>(uid)?.GrindableSolution;
-
- return solutionName is not null && _solutionContainersSystem.TryGetSolution(uid, solutionName, out _, out _);
- }
-
- private bool CanJuice(EntityUid uid)
- {
- return CompOrNull<ExtractableComponent>(uid)?.JuiceSolution is not null;
- }
}
}
--- /dev/null
+using Content.Shared.Kitchen.EntitySystems;
+using Robust.Shared.Audio;
+using Robust.Shared.GameStates;
+
+namespace Content.Shared.Kitchen.Components;
+
+/// <summary>
+/// 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".
+/// </summary>
+[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
+{
+ /// <summary>
+ /// Remaining time until the grinder finishes grinding/juicing.
+ /// </summary>
+ [ViewVariables]
+ public TimeSpan EndTime;
+
+ [ViewVariables]
+ public GrinderProgram Program;
+}
+
--- /dev/null
+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!;
+
+ /// <summary>
+ /// Gets the solutions from an entity using the specified Grinder program.
+ /// </summary>
+ /// <param name="ent">The entity which we check for solutions.</param>
+ /// <param name="program">The grinder program.</param>
+ /// <returns>The solution received, or null if none.</returns>
+ public Solution? GetGrinderSolution(Entity<ExtractableComponent?> 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;
+ }
+
+ /// <summary>
+ /// Checks whether the entity can be ground using a ReagentGrinder.
+ /// </summary>
+ /// <param name="ent">The entity to check.</param>
+ /// <returns>True if it can be ground, otherwise false.</returns>
+ public bool CanGrind(Entity<ExtractableComponent?> 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 _);
+ }
+
+ /// <summary>
+ /// Checks whether the entity can be juiced using a ReagentGrinder.
+ /// </summary>
+ /// <param name="ent">The entity to check.</param>
+ /// <returns>True if it can be juiced, otherwise false.</returns>
+ public bool CanJuice(Entity<ExtractableComponent?> ent)
+ {
+ if (!Resolve(ent, ref ent.Comp, false))
+ return false;
+
+ return ent.Comp.JuiceSolution is not null;
+ }
+}
+
Key
}
+ [Serializable, NetSerializable]
public enum GrinderAutoMode : byte
{
Off,