diff --git a/Content.Client/Fluids/MoppingSystem.cs b/Content.Client/Fluids/MoppingSystem.cs new file mode 100644 index 0000000000..90f8ba4e8b --- /dev/null +++ b/Content.Client/Fluids/MoppingSystem.cs @@ -0,0 +1,20 @@ +using Content.Client.Fluids.UI; +using Content.Client.Items; +using Content.Shared.Fluids; +using Robust.Client.UserInterface; + +namespace Content.Client.Fluids; + +public sealed class MoppingSystem : SharedMoppingSystem +{ + public override void Initialize() + { + base.Initialize(); + Subs.ItemStatus(GetAbsorbent); + } + + private Control GetAbsorbent(EntityUid arg) + { + return new AbsorbentItemStatus(arg, EntityManager); + } +} diff --git a/Content.Client/Fluids/UI/AbsorbentItemStatus.xaml b/Content.Client/Fluids/UI/AbsorbentItemStatus.xaml new file mode 100644 index 0000000000..d8cb4fc89b --- /dev/null +++ b/Content.Client/Fluids/UI/AbsorbentItemStatus.xaml @@ -0,0 +1,13 @@ + + + + + + diff --git a/Content.Client/Fluids/UI/AbsorbentItemStatus.xaml.cs b/Content.Client/Fluids/UI/AbsorbentItemStatus.xaml.cs new file mode 100644 index 0000000000..772be44efd --- /dev/null +++ b/Content.Client/Fluids/UI/AbsorbentItemStatus.xaml.cs @@ -0,0 +1,31 @@ +using Content.Shared.Fluids; +using Robust.Client.AutoGenerated; +using Robust.Client.UserInterface; +using Robust.Client.UserInterface.XAML; +using Robust.Shared.Timing; + +namespace Content.Client.Fluids.UI +{ + [GenerateTypedNameReferences] + public sealed partial class AbsorbentItemStatus : Control + { + private readonly IEntityManager _entManager; + private readonly EntityUid _uid; + + public AbsorbentItemStatus(EntityUid uid, IEntityManager entManager) + { + RobustXamlLoader.Load(this); + _uid = uid; + _entManager = entManager; + } + + protected override void FrameUpdate(FrameEventArgs args) + { + base.FrameUpdate(args); + if (!_entManager.TryGetComponent(_uid, out var absorbent)) + return; + + PercentBar.Value = absorbent.Progress; + } + } +} diff --git a/Content.Server/Fluids/EntitySystems/MoppingSystem.cs b/Content.Server/Fluids/EntitySystems/MoppingSystem.cs index b21315aab0..44939ad969 100644 --- a/Content.Server/Fluids/EntitySystems/MoppingSystem.cs +++ b/Content.Server/Fluids/EntitySystems/MoppingSystem.cs @@ -1,3 +1,4 @@ +using System.Linq; using Content.Server.Chemistry.Components.SolutionManager; using Content.Server.Chemistry.EntitySystems; using Content.Server.DoAfter; @@ -5,6 +6,7 @@ using Content.Server.Fluids.Components; using Content.Server.Popups; using Content.Shared.Chemistry.Components; using Content.Shared.FixedPoint; +using Content.Shared.Fluids; using Content.Shared.Interaction; using Content.Shared.Tag; using JetBrains.Annotations; @@ -15,7 +17,7 @@ using Robust.Shared.Map; namespace Content.Server.Fluids.EntitySystems; [UsedImplicitly] -public sealed class MoppingSystem : EntitySystem +public sealed class MoppingSystem : SharedMoppingSystem { [Dependency] private readonly DoAfterSystem _doAfterSystem = default!; [Dependency] private readonly SpillableSystem _spillableSystem = default!; @@ -30,11 +32,37 @@ public sealed class MoppingSystem : EntitySystem public override void Initialize() { base.Initialize(); + SubscribeLocalEvent(OnAbsorbentInit); SubscribeLocalEvent(OnAfterInteract); + SubscribeLocalEvent(OnAbsorbentSolutionChange); SubscribeLocalEvent(OnTransferCancelled); SubscribeLocalEvent(OnTransferComplete); } + private void OnAbsorbentInit(EntityUid uid, AbsorbentComponent component, ComponentInit args) + { + // TODO: I know dirty on init but no prediction moment. + UpdateAbsorbent(uid, component); + } + + private void OnAbsorbentSolutionChange(EntityUid uid, AbsorbentComponent component, SolutionChangedEvent args) + { + UpdateAbsorbent(uid, component); + } + + private void UpdateAbsorbent(EntityUid uid, AbsorbentComponent component) + { + if (!_solutionSystem.TryGetSolution(uid, AbsorbentComponent.SolutionName, out var solution)) + return; + + var oldProgress = component.Progress; + + component.Progress = (float) (solution.Volume / solution.MaxVolume); + if (component.Progress.Equals(oldProgress)) + return; + Dirty(component); + } + private void OnAfterInteract(EntityUid uid, AbsorbentComponent component, AfterInteractEvent args) { if (!args.CanReach || args.Handled) diff --git a/Content.Server/Fluids/Components/AbsorbentComponent.cs b/Content.Shared/Fluids/AbsorbentComponent.cs similarity index 90% rename from Content.Server/Fluids/Components/AbsorbentComponent.cs rename to Content.Shared/Fluids/AbsorbentComponent.cs index 5e02d518e7..011e123e90 100644 --- a/Content.Server/Fluids/Components/AbsorbentComponent.cs +++ b/Content.Shared/Fluids/AbsorbentComponent.cs @@ -1,15 +1,18 @@ -using Content.Server.Fluids.EntitySystems; using Content.Shared.FixedPoint; using Robust.Shared.Audio; +using Robust.Shared.GameStates; -namespace Content.Server.Fluids.Components; +namespace Content.Shared.Fluids; /// /// For entities that can clean up puddles /// -[RegisterComponent, Access(typeof(MoppingSystem))] +[RegisterComponent, NetworkedComponent] public sealed class AbsorbentComponent : Component { + // TODO: Predicted solutions my beloved. + public float Progress; + public const string SolutionName = "absorbed"; [DataField("pickupAmount")] diff --git a/Content.Shared/Fluids/SharedMoppingSystem.cs b/Content.Shared/Fluids/SharedMoppingSystem.cs new file mode 100644 index 0000000000..8e6dcc829a --- /dev/null +++ b/Content.Shared/Fluids/SharedMoppingSystem.cs @@ -0,0 +1,39 @@ +using Robust.Shared.GameStates; +using Robust.Shared.Serialization; + +namespace Content.Shared.Fluids; + +public abstract class SharedMoppingSystem : EntitySystem +{ + public override void Initialize() + { + base.Initialize(); + SubscribeLocalEvent(OnAbsorbentGetState); + SubscribeLocalEvent(OnAbsorbentHandleState); + } + + private void OnAbsorbentHandleState(EntityUid uid, AbsorbentComponent component, ref ComponentHandleState args) + { + if (args.Current is not AbsorbentComponentState state) + return; + + if (component.Progress.Equals(state.Progress)) + return; + + component.Progress = state.Progress; + } + + private void OnAbsorbentGetState(EntityUid uid, AbsorbentComponent component, ref ComponentGetState args) + { + args.State = new AbsorbentComponentState() + { + Progress = component.Progress, + }; + } + + [Serializable, NetSerializable] + protected sealed class AbsorbentComponentState : ComponentState + { + public float Progress; + } +}