diff --git a/Content.Client/Animals/Systems/ParrotMemorySystem.cs b/Content.Client/Animals/Systems/ParrotMemorySystem.cs new file mode 100644 index 0000000000..cdf62a4eae --- /dev/null +++ b/Content.Client/Animals/Systems/ParrotMemorySystem.cs @@ -0,0 +1,5 @@ +using Content.Shared.Animals.Systems; + +namespace Content.Client.Animals.Systems; + +public sealed class ParrotMemorySystem : SharedParrotMemorySystem; diff --git a/Content.Server/Animals/Systems/ParrotMemorySystem.cs b/Content.Server/Animals/Systems/ParrotMemorySystem.cs index eb3429821c..56843094a1 100644 --- a/Content.Server/Animals/Systems/ParrotMemorySystem.cs +++ b/Content.Server/Animals/Systems/ParrotMemorySystem.cs @@ -8,10 +8,10 @@ using Content.Server.Radio; using Content.Server.Speech; using Content.Server.Speech.Components; using Content.Server.Vocalization.Systems; +using Content.Shared.Animals.Components; +using Content.Shared.Animals.Systems; using Content.Shared.Database; using Content.Shared.Mobs.Systems; -using Content.Shared.Popups; -using Content.Shared.Verbs; using Content.Shared.Whitelist; using Robust.Shared.Network; using Robust.Shared.Random; @@ -25,7 +25,7 @@ namespace Content.Server.Animals.Systems; /// (radiovocalizer) and stores them in a list. When an entity with a VocalizerComponent attempts to vocalize, this will /// try to set the message from memory. /// -public sealed partial class ParrotMemorySystem : EntitySystem +public sealed partial class ParrotMemorySystem : SharedParrotMemorySystem { [Dependency] private readonly EntityWhitelistSystem _whitelist = default!; [Dependency] private readonly IAdminLogManager _adminLogger = default!; @@ -42,8 +42,6 @@ public sealed partial class ParrotMemorySystem : EntitySystem SubscribeLocalEvent(OnErase); - SubscribeLocalEvent>(OnGetVerbs); - SubscribeLocalEvent(ListenerOnMapInit); SubscribeLocalEvent(OnListen); @@ -57,30 +55,6 @@ public sealed partial class ParrotMemorySystem : EntitySystem DeletePlayerMessages(args.PlayerNetUserId); } - private void OnGetVerbs(Entity entity, ref GetVerbsEvent args) - { - var user = args.User; - - // limit this to admins - if (!_admin.IsAdmin(user)) - return; - - // simple verb that just clears the memory list - var clearMemoryVerb = new Verb() - { - Text = Loc.GetString("parrot-verb-clear-memory"), - Category = VerbCategory.Admin, - Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/AdminActions/clear-parrot.png")), - Act = () => - { - entity.Comp.SpeechMemories.Clear(); - _popup.PopupEntity(Loc.GetString("parrot-popup-memory-cleared"), entity, user, PopupType.Medium); - }, - }; - - args.Verbs.Add(clearMemoryVerb); - } - private void ListenerOnMapInit(Entity entity, ref MapInitEvent args) { // If an entity has a ParrotListenerComponent it really ought to have an ActiveListenerComponent diff --git a/Content.Server/Animals/Components/ParrotMemoryComponent.cs b/Content.Shared/Animals/Components/ParrotMemoryComponent.cs similarity index 67% rename from Content.Server/Animals/Components/ParrotMemoryComponent.cs rename to Content.Shared/Animals/Components/ParrotMemoryComponent.cs index 69908a0a9e..e1c5ba8ed9 100644 --- a/Content.Server/Animals/Components/ParrotMemoryComponent.cs +++ b/Content.Shared/Animals/Components/ParrotMemoryComponent.cs @@ -1,57 +1,61 @@ +using Content.Shared.Animals.Systems; +using Robust.Shared.GameStates; using Robust.Shared.Network; +using Robust.Shared.Serialization; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom; -namespace Content.Server.Animals.Components; +namespace Content.Shared.Animals.Components; /// -/// Makes an entity able to memorize chat/radio messages +/// Makes an entity able to memorize chat/radio messages. /// -[RegisterComponent] +[RegisterComponent, NetworkedComponent] [AutoGenerateComponentPause] public sealed partial class ParrotMemoryComponent : Component { /// - /// List of SpeechMemory records this entity has learned + /// List of SpeechMemory records this entity has learned. /// [DataField] - public List SpeechMemories = []; + public List SpeechMemories = new(); /// - /// The % chance an entity with this component learns a phrase when learning is off cooldown + /// The % chance an entity with this component learns a phrase when learning is off cooldown. /// [DataField] public float LearnChance = 0.6f; /// - /// Time after which another attempt can be made at learning a phrase + /// Time after which another attempt can be made at learning a phrase. /// [DataField] public TimeSpan LearnCooldown = TimeSpan.FromMinutes(1); /// - /// Next time at which the parrot can attempt to learn something + /// Next time at which the parrot can attempt to learn something. /// [DataField(customTypeSerializer: typeof(TimeOffsetSerializer))] [AutoPausedField] public TimeSpan NextLearnInterval = TimeSpan.Zero; /// - /// The number of speech entries that are remembered + /// The number of speech entries that are remembered. /// [DataField] public int MaxSpeechMemory = 50; /// - /// Minimum length of a speech entry + /// Minimum length of a speech entry. /// [DataField] public int MinEntryLength = 4; /// - /// Maximum length of a speech entry + /// Maximum length of a speech entry. /// [DataField] public int MaxEntryLength = 50; } +[Serializable, NetSerializable] public record struct SpeechMemory(NetUserId? NetUserId, string Message); diff --git a/Content.Shared/Animals/Systems/SharedParrotMemorySystem.cs b/Content.Shared/Animals/Systems/SharedParrotMemorySystem.cs new file mode 100644 index 0000000000..fb8e3309ea --- /dev/null +++ b/Content.Shared/Animals/Systems/SharedParrotMemorySystem.cs @@ -0,0 +1,48 @@ +using Content.Shared.Administration.Managers; +using Content.Shared.Animals.Components; +using Content.Shared.Popups; +using Content.Shared.Verbs; +using Robust.Shared.Network; +using Robust.Shared.Utility; + +namespace Content.Shared.Animals.Systems; + +public abstract class SharedParrotMemorySystem : EntitySystem +{ + [Dependency] private readonly SharedPopupSystem _popup = default!; + [Dependency] private readonly ISharedAdminManager _admin = default!; + [Dependency] private readonly INetManager _net = default!; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent>(OnGetVerbs); + } + + private void OnGetVerbs(Entity entity, ref GetVerbsEvent args) + { + var user = args.User; + + // limit this to admins + if (!_admin.IsAdmin(user)) + return; + + // simple verb that just clears the memory list + var clearMemoryVerb = new Verb() + { + Text = Loc.GetString("parrot-verb-clear-memory"), + Category = VerbCategory.Admin, + Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/AdminActions/clear-parrot.png")), + Act = () => + { + _popup.PopupClient(Loc.GetString("parrot-popup-memory-cleared"), entity.Owner, user); + + if (_net.IsServer) + entity.Comp.SpeechMemories.Clear(); + }, + }; + + args.Verbs.Add(clearMemoryVerb); + } +}