From 91740ef5be670e5f2d7f44fdf16d442cbc4579e5 Mon Sep 17 00:00:00 2001 From: beck-thompson <107373427+beck-thompson@users.noreply.github.com> Date: Tue, 9 Jul 2024 22:51:47 -0700 Subject: [PATCH] Fix typing indicators! (#29492) * First commit * Removed pause stuff * Make the event better * Forgot to add the comment * Proto id stuff * cool comments * serializer * Added the time stuff --- .../TypingIndicatorVisualizerSystem.cs | 19 +++++- .../SharedTypingIndicatorSystem.cs | 21 ++++--- .../TypingIndicator/TypingChangedEvent.cs | 18 ------ .../TypingIndicatorClothingComponent.cs | 23 +++++-- .../TypingIndicatorComponent.cs | 7 +-- .../TypingIndicator/TypingIndicatorEvents.cs | 60 +++++++++++++++++++ 6 files changed, 111 insertions(+), 37 deletions(-) delete mode 100644 Content.Shared/Chat/TypingIndicator/TypingChangedEvent.cs create mode 100644 Content.Shared/Chat/TypingIndicator/TypingIndicatorEvents.cs diff --git a/Content.Client/Chat/TypingIndicator/TypingIndicatorVisualizerSystem.cs b/Content.Client/Chat/TypingIndicator/TypingIndicatorVisualizerSystem.cs index d04c9d661d..e89f7ab500 100644 --- a/Content.Client/Chat/TypingIndicator/TypingIndicatorVisualizerSystem.cs +++ b/Content.Client/Chat/TypingIndicator/TypingIndicatorVisualizerSystem.cs @@ -2,21 +2,36 @@ using Robust.Client.GameObjects; using Robust.Client.Graphics; using Robust.Shared.Prototypes; +using Content.Shared.Inventory; namespace Content.Client.Chat.TypingIndicator; public sealed class TypingIndicatorVisualizerSystem : VisualizerSystem { [Dependency] private readonly IPrototypeManager _prototypeManager = default!; + [Dependency] private readonly InventorySystem _inventory = default!; + protected override void OnAppearanceChange(EntityUid uid, TypingIndicatorComponent component, ref AppearanceChangeEvent args) { if (args.Sprite == null) return; - if (!_prototypeManager.TryIndex(component.Prototype, out var proto)) + var currentTypingIndicator = component.TypingIndicatorPrototype; + + var evt = new BeforeShowTypingIndicatorEvent(); + + if (TryComp(uid, out var inventoryComp)) + _inventory.RelayEvent((uid, inventoryComp), ref evt); + + var overrideIndicator = evt.GetMostRecentIndicator(); + + if (overrideIndicator != null) + currentTypingIndicator = overrideIndicator.Value; + + if (!_prototypeManager.TryIndex(currentTypingIndicator, out var proto)) { - Log.Error($"Unknown typing indicator id: {component.Prototype}"); + Log.Error($"Unknown typing indicator id: {component.TypingIndicatorPrototype}"); return; } diff --git a/Content.Shared/Chat/TypingIndicator/SharedTypingIndicatorSystem.cs b/Content.Shared/Chat/TypingIndicator/SharedTypingIndicatorSystem.cs index dffe3cc185..9d60d334db 100644 --- a/Content.Shared/Chat/TypingIndicator/SharedTypingIndicatorSystem.cs +++ b/Content.Shared/Chat/TypingIndicator/SharedTypingIndicatorSystem.cs @@ -1,6 +1,8 @@ using Content.Shared.ActionBlocker; using Content.Shared.Clothing; +using Content.Shared.Inventory; using Robust.Shared.Player; +using Robust.Shared.Timing; namespace Content.Shared.Chat.TypingIndicator; @@ -11,6 +13,7 @@ public abstract class SharedTypingIndicatorSystem : EntitySystem { [Dependency] private readonly ActionBlockerSystem _actionBlocker = default!; [Dependency] private readonly SharedAppearanceSystem _appearance = default!; + [Dependency] private readonly IGameTiming _timing = default!; /// /// Default ID of @@ -26,6 +29,7 @@ public abstract class SharedTypingIndicatorSystem : EntitySystem SubscribeLocalEvent(OnGotEquipped); SubscribeLocalEvent(OnGotUnequipped); + SubscribeLocalEvent>(BeforeShow); SubscribeAllEvent(OnTypingChanged); } @@ -44,20 +48,19 @@ public abstract class SharedTypingIndicatorSystem : EntitySystem SetTypingIndicatorEnabled(uid, false); } - private void OnGotEquipped(EntityUid uid, TypingIndicatorClothingComponent component, ClothingGotEquippedEvent args) + private void OnGotEquipped(Entity entity, ref ClothingGotEquippedEvent args) { - if (!TryComp(args.Wearer, out var indicator)) - return; - - indicator.Prototype = component.Prototype; + entity.Comp.GotEquippedTime = _timing.CurTime; } - private void OnGotUnequipped(EntityUid uid, TypingIndicatorClothingComponent component, ClothingGotUnequippedEvent args) + private void OnGotUnequipped(Entity entity, ref ClothingGotUnequippedEvent args) { - if (!TryComp(args.Wearer, out var indicator)) - return; + entity.Comp.GotEquippedTime = null; + } - indicator.Prototype = InitialIndicatorId; + private void BeforeShow(Entity entity, ref InventoryRelayedEvent args) + { + args.Args.TryUpdateTimeAndIndicator(entity.Comp.TypingIndicatorPrototype, entity.Comp.GotEquippedTime); } private void OnTypingChanged(TypingChangedEvent ev, EntitySessionEventArgs args) diff --git a/Content.Shared/Chat/TypingIndicator/TypingChangedEvent.cs b/Content.Shared/Chat/TypingIndicator/TypingChangedEvent.cs deleted file mode 100644 index 6245f19b5d..0000000000 --- a/Content.Shared/Chat/TypingIndicator/TypingChangedEvent.cs +++ /dev/null @@ -1,18 +0,0 @@ -using Robust.Shared.Serialization; - -namespace Content.Shared.Chat.TypingIndicator; - -/// -/// Networked event from client. -/// Send to server when client started/stopped typing in chat input field. -/// -[Serializable, NetSerializable] -public sealed class TypingChangedEvent : EntityEventArgs -{ - public readonly bool IsTyping; - - public TypingChangedEvent(bool isTyping) - { - IsTyping = isTyping; - } -} diff --git a/Content.Shared/Chat/TypingIndicator/TypingIndicatorClothingComponent.cs b/Content.Shared/Chat/TypingIndicator/TypingIndicatorClothingComponent.cs index 5ec8185587..4993e912e9 100644 --- a/Content.Shared/Chat/TypingIndicator/TypingIndicatorClothingComponent.cs +++ b/Content.Shared/Chat/TypingIndicator/TypingIndicatorClothingComponent.cs @@ -1,13 +1,28 @@ using Robust.Shared.GameStates; -using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; +using Robust.Shared.Prototypes; +using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom; namespace Content.Shared.Chat.TypingIndicator; -[RegisterComponent, NetworkedComponent] +/// +/// If an item is equipped to someones inventory (Anything but the pockets), and has this component +/// the users typing indicator will be replaced by the prototype given in TypingIndicatorPrototype. +/// +[RegisterComponent, NetworkedComponent, AutoGenerateComponentPause] [Access(typeof(SharedTypingIndicatorSystem))] public sealed partial class TypingIndicatorClothingComponent : Component { + /// + /// The typing indicator that will override the default typing indicator when the item is equipped to a users + /// inventory. + /// [ViewVariables(VVAccess.ReadWrite)] - [DataField("proto", required: true, customTypeSerializer: typeof(PrototypeIdSerializer))] - public string Prototype = default!; + [DataField("proto", required: true)] + public ProtoId TypingIndicatorPrototype = default!; + + /// + /// This stores the time the item was equipped in someones inventory. If null, item is currently not equipped. + /// + [DataField, AutoPausedField] + public TimeSpan? GotEquippedTime = null; } diff --git a/Content.Shared/Chat/TypingIndicator/TypingIndicatorComponent.cs b/Content.Shared/Chat/TypingIndicator/TypingIndicatorComponent.cs index a4507b06b8..f263de4913 100644 --- a/Content.Shared/Chat/TypingIndicator/TypingIndicatorComponent.cs +++ b/Content.Shared/Chat/TypingIndicator/TypingIndicatorComponent.cs @@ -1,5 +1,5 @@ using Robust.Shared.GameStates; -using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; +using Robust.Shared.Prototypes; namespace Content.Shared.Chat.TypingIndicator; @@ -14,7 +14,6 @@ public sealed partial class TypingIndicatorComponent : Component /// /// Prototype id that store all visual info about typing indicator. /// - [ViewVariables(VVAccess.ReadWrite)] - [DataField("proto", customTypeSerializer: typeof(PrototypeIdSerializer))] - public string Prototype = SharedTypingIndicatorSystem.InitialIndicatorId; + [DataField("proto")] + public ProtoId TypingIndicatorPrototype = "default"; } diff --git a/Content.Shared/Chat/TypingIndicator/TypingIndicatorEvents.cs b/Content.Shared/Chat/TypingIndicator/TypingIndicatorEvents.cs new file mode 100644 index 0000000000..600f86c0d2 --- /dev/null +++ b/Content.Shared/Chat/TypingIndicator/TypingIndicatorEvents.cs @@ -0,0 +1,60 @@ +using Robust.Shared.Serialization; +using Content.Shared.Inventory; +using Robust.Shared.Prototypes; +using Robust.Shared.Serialization.Manager.Exceptions; + +namespace Content.Shared.Chat.TypingIndicator; + +/// +/// Networked event from client. +/// Send to server when client started/stopped typing in chat input field. +/// +[Serializable, NetSerializable] +public sealed class TypingChangedEvent : EntityEventArgs +{ + public readonly bool IsTyping; + + public TypingChangedEvent(bool isTyping) + { + IsTyping = isTyping; + } +} + +/// +/// This event will be broadcast right before displaying an entities typing indicator. +/// If _overrideIndicator is not null after the event is finished it will be used. +/// +[Serializable, NetSerializable] +public sealed class BeforeShowTypingIndicatorEvent : IInventoryRelayEvent +{ + public SlotFlags TargetSlots { get; } = SlotFlags.WITHOUT_POCKET; + + private ProtoId? _overrideIndicator = null; + private TimeSpan? _latestEquipTime = null; + public BeforeShowTypingIndicatorEvent() + { + _overrideIndicator = null; + _latestEquipTime = null; + } + /// + /// Will only update the time and indicator if the given time is more recent than + /// the stored time or if the stored time is null. + /// + /// + /// True if the given time is more recent than the stored time, and false otherwise. + /// + public bool TryUpdateTimeAndIndicator(ProtoId? indicator, TimeSpan? equipTime) + { + if (equipTime != null && (_latestEquipTime == null || _latestEquipTime < equipTime)) + { + _latestEquipTime = equipTime; + _overrideIndicator = indicator; + return true; + } + return false; + } + public ProtoId? GetMostRecentIndicator() + { + return _overrideIndicator; + } +} -- 2.51.2