diff --git a/Content.Server/Administration/Systems/AdminSystem.cs b/Content.Server/Administration/Systems/AdminSystem.cs index 99551c714c..ce18a1e4f7 100644 --- a/Content.Server/Administration/Systems/AdminSystem.cs +++ b/Content.Server/Administration/Systems/AdminSystem.cs @@ -98,6 +98,7 @@ public sealed class AdminSystem : EntitySystem SubscribeLocalEvent(OnRoleEvent); SubscribeLocalEvent(OnRoleEvent); SubscribeLocalEvent(OnRoundRestartCleanup); + SubscribeLocalEvent(OnPlayerRenamed); } private void OnRoundRestartCleanup(RoundRestartCleanupEvent ev) @@ -124,6 +125,11 @@ public sealed class AdminSystem : EntitySystem } } + private void OnPlayerRenamed(Entity ent, ref EntityRenamedEvent args) + { + UpdatePlayerList(ent.Comp.PlayerSession); + } + public void UpdatePlayerList(ICommonSession player) { _playerList[player.UserId] = GetPlayerInfo(player.Data, player); diff --git a/Content.Server/IdentityManagement/IdentitySystem.cs b/Content.Server/IdentityManagement/IdentitySystem.cs index 4766b89172..e110a42483 100644 --- a/Content.Server/IdentityManagement/IdentitySystem.cs +++ b/Content.Server/IdentityManagement/IdentitySystem.cs @@ -39,6 +39,7 @@ public sealed class IdentitySystem : SharedIdentitySystem SubscribeLocalEvent((uid, _, _) => QueueIdentityUpdate(uid)); SubscribeLocalEvent((uid, _, _) => QueueIdentityUpdate(uid)); SubscribeLocalEvent((uid, _, _) => QueueIdentityUpdate(uid)); + SubscribeLocalEvent((uid, _, _) => QueueIdentityUpdate(uid)); SubscribeLocalEvent(OnMapInit); } diff --git a/Content.Server/Mind/Commands/RenameCommand.cs b/Content.Server/Mind/Commands/RenameCommand.cs index 834453fb19..f283fe5d19 100644 --- a/Content.Server/Mind/Commands/RenameCommand.cs +++ b/Content.Server/Mind/Commands/RenameCommand.cs @@ -1,31 +1,22 @@ using System.Diagnostics.CodeAnalysis; -using Content.Server.Access.Systems; using Content.Server.Administration; -using Content.Server.Administration.Systems; -using Content.Server.PDA; -using Content.Server.StationRecords.Systems; using Content.Shared.Access.Components; using Content.Shared.Administration; -using Content.Shared.Mind; -using Content.Shared.PDA; -using Content.Shared.StationRecords; using Robust.Server.Player; using Robust.Shared.Console; -using Robust.Shared.Player; namespace Content.Server.Mind.Commands; [AdminCommand(AdminFlags.VarEdit)] -public sealed class RenameCommand : IConsoleCommand +public sealed class RenameCommand : LocalizedEntityCommands { [Dependency] private readonly IEntityManager _entManager = default!; [Dependency] private readonly IPlayerManager _playerManager = default!; + [Dependency] private readonly MetaDataSystem _metaSystem = default!; - public string Command => "rename"; - public string Description => "Renames an entity and its cloner entries, ID cards, and PDAs."; - public string Help => "rename "; + public override string Command => "rename"; - public void Execute(IConsoleShell shell, string argStr, string[] args) + public override void Execute(IConsoleShell shell, string argStr, string[] args) { if (args.Length != 2) { @@ -36,69 +27,14 @@ public sealed class RenameCommand : IConsoleCommand var name = args[1]; if (name.Length > IdCardConsoleComponent.MaxFullNameLength) { - shell.WriteLine("Name is too long."); + shell.WriteLine(Loc.GetString("cmd-rename-too-long")); return; } if (!TryParseUid(args[0], shell, _entManager, out var entityUid)) return; - // Metadata - var metadata = _entManager.GetComponent(entityUid.Value); - var oldName = metadata.EntityName; - _entManager.System().SetEntityName(entityUid.Value, name, metadata); - - var minds = _entManager.System(); - - if (minds.TryGetMind(entityUid.Value, out var mindId, out var mind)) - { - // Mind - mind.CharacterName = name; - _entManager.Dirty(mindId, mind); - } - - // Id Cards - if (_entManager.TrySystem(out var idCardSystem)) - { - if (idCardSystem.TryFindIdCard(entityUid.Value, out var idCard)) - { - idCardSystem.TryChangeFullName(idCard, name, idCard); - - // Records - // This is done here because ID cards are linked to station records - if (_entManager.TrySystem(out var recordsSystem) - && _entManager.TryGetComponent(idCard, out StationRecordKeyStorageComponent? keyStorage) - && keyStorage.Key is {} key) - { - if (recordsSystem.TryGetRecord(key, out var generalRecord)) - { - generalRecord.Name = name; - } - - recordsSystem.Synchronize(key); - } - } - } - - // PDAs - if (_entManager.TrySystem(out var pdaSystem)) - { - var query = _entManager.EntityQueryEnumerator(); - while (query.MoveNext(out var uid, out var pda)) - { - if (pda.OwnerName == oldName) - { - pdaSystem.SetOwner(uid, pda, name); - } - } - } - - // Admin Overlay - if (_entManager.TrySystem(out var adminSystem) - && _entManager.TryGetComponent(entityUid, out var actorComp)) - { - adminSystem.UpdatePlayerList(actorComp.PlayerSession); - } + _metaSystem.SetEntityName(entityUid.Value, name); } private bool TryParseUid(string str, IConsoleShell shell, @@ -114,9 +50,9 @@ public sealed class RenameCommand : IConsoleCommand } if (session == null) - shell.WriteError("Can't find username/uid: " + str); + shell.WriteError(Loc.GetString("cmd-rename-not-found", ("target", str))); else - shell.WriteError(str + " does not have an entity."); + shell.WriteError(Loc.GetString("cmd-rename-no-entity", ("target", str))); entityUid = EntityUid.Invalid; return false; diff --git a/Content.Server/PDA/PdaSystem.cs b/Content.Server/PDA/PdaSystem.cs index 691d024ecd..cdcdbc02e5 100644 --- a/Content.Server/PDA/PdaSystem.cs +++ b/Content.Server/PDA/PdaSystem.cs @@ -55,9 +55,23 @@ namespace Content.Server.PDA SubscribeLocalEvent(OnNotification); SubscribeLocalEvent(OnStationRenamed); + SubscribeLocalEvent(OnEntityRenamed); SubscribeLocalEvent(OnAlertLevelChanged); } + private void OnEntityRenamed(ref EntityRenamedEvent ev) + { + var query = EntityQueryEnumerator(); + + while (query.MoveNext(out var uid, out var comp)) + { + if (comp.PdaOwner == ev.Uid) + { + SetOwner(uid, comp, ev.Uid, ev.NewName); + } + } + } + protected override void OnComponentInit(EntityUid uid, PdaComponent pda, ComponentInit args) { base.OnComponentInit(uid, pda, args); @@ -94,9 +108,10 @@ namespace Content.Server.PDA UpdatePdaUi(uid, pda); } - public void SetOwner(EntityUid uid, PdaComponent pda, string ownerName) + public void SetOwner(EntityUid uid, PdaComponent pda, EntityUid owner, string ownerName) { pda.OwnerName = ownerName; + pda.PdaOwner = owner; UpdatePdaUi(uid, pda); } @@ -112,7 +127,7 @@ namespace Content.Server.PDA private void UpdateAllPdaUisOnStation() { - var query = EntityQueryEnumerator(); + var query = AllEntityQuery(); while (query.MoveNext(out var ent, out var comp)) { UpdatePdaUi(ent, comp); diff --git a/Content.Server/Station/Systems/StationSpawningSystem.cs b/Content.Server/Station/Systems/StationSpawningSystem.cs index 88e2b08cb4..e39a094319 100644 --- a/Content.Server/Station/Systems/StationSpawningSystem.cs +++ b/Content.Server/Station/Systems/StationSpawningSystem.cs @@ -246,7 +246,7 @@ public sealed class StationSpawningSystem : SharedStationSpawningSystem _accessSystem.SetAccessToJob(cardId, jobPrototype, extendedAccess); if (pdaComponent != null) - _pdaSystem.SetOwner(idUid.Value, pdaComponent, characterName); + _pdaSystem.SetOwner(idUid.Value, pdaComponent, entity, characterName); } diff --git a/Content.Server/StationRecords/Systems/StationRecordsSystem.cs b/Content.Server/StationRecords/Systems/StationRecordsSystem.cs index c7d5665464..e941e65c41 100644 --- a/Content.Server/StationRecords/Systems/StationRecordsSystem.cs +++ b/Content.Server/StationRecords/Systems/StationRecordsSystem.cs @@ -1,6 +1,9 @@ using System.Diagnostics.CodeAnalysis; +using System.IO; +using Content.Server.Access.Systems; using Content.Server.Forensics; using Content.Server.GameTicking; +using Content.Shared.Access.Components; using Content.Shared.Inventory; using Content.Shared.PDA; using Content.Shared.Preferences; @@ -35,12 +38,14 @@ public sealed class StationRecordsSystem : SharedStationRecordsSystem [Dependency] private readonly InventorySystem _inventory = default!; [Dependency] private readonly StationRecordKeyStorageSystem _keyStorage = default!; [Dependency] private readonly IPrototypeManager _prototypeManager = default!; + [Dependency] private readonly IdCardSystem _idCard = default!; public override void Initialize() { base.Initialize(); SubscribeLocalEvent(OnPlayerSpawn); + SubscribeLocalEvent(OnRename); } private void OnPlayerSpawn(PlayerSpawnCompleteEvent args) @@ -51,6 +56,30 @@ public sealed class StationRecordsSystem : SharedStationRecordsSystem CreateGeneralRecord(args.Station, args.Mob, args.Profile, args.JobId, stationRecords); } + private void OnRename(ref EntityRenamedEvent ev) + { + // When a player gets renamed their card gets changed to match. + // Unfortunately this means that an event is called for it as well, and since TryFindIdCard will succeed if the + // given entity is a card and the card itself is the key the record will be mistakenly renamed to the card's name + // if we don't return early. + if (HasComp(ev.Uid)) + return; + + if (_idCard.TryFindIdCard(ev.Uid, out var idCard)) + { + if (TryComp(idCard, out StationRecordKeyStorageComponent? keyStorage) + && keyStorage.Key is {} key) + { + if (TryGetRecord(key, out var generalRecord)) + { + generalRecord.Name = ev.NewName; + } + + Synchronize(key); + } + } + } + private void CreateGeneralRecord(EntityUid station, EntityUid player, HumanoidCharacterProfile profile, string? jobId, StationRecordsComponent records) { diff --git a/Content.Shared/Access/Systems/SharedIdCardSystem.cs b/Content.Shared/Access/Systems/SharedIdCardSystem.cs index 5a90d4ea35..8bdc548e35 100644 --- a/Content.Shared/Access/Systems/SharedIdCardSystem.cs +++ b/Content.Shared/Access/Systems/SharedIdCardSystem.cs @@ -25,6 +25,19 @@ public abstract class SharedIdCardSystem : EntitySystem SubscribeLocalEvent(OnMapInit); SubscribeLocalEvent(OnTryGetIdentityShortInfo); + SubscribeLocalEvent(OnRename); + } + + private void OnRename(ref EntityRenamedEvent ev) + { + // When a player gets renamed their id card is renamed as well to match. + // Unfortunately since TryFindIdCard will succeed if the entity is also a card this means that the card will + // keep renaming itself unless we return early. + if (HasComp(ev.Uid)) + return; + + if (TryFindIdCard(ev.Uid, out var idCard)) + TryChangeFullName(idCard, ev.NewName, idCard); } private void OnMapInit(EntityUid uid, IdCardComponent id, MapInitEvent args) diff --git a/Content.Shared/Mind/SharedMindSystem.cs b/Content.Shared/Mind/SharedMindSystem.cs index c8e1c1a4b3..162bca495c 100644 --- a/Content.Shared/Mind/SharedMindSystem.cs +++ b/Content.Shared/Mind/SharedMindSystem.cs @@ -39,6 +39,7 @@ public abstract class SharedMindSystem : EntitySystem SubscribeLocalEvent(OnVisitingTerminating); SubscribeLocalEvent(OnReset); SubscribeLocalEvent(OnMindStartup); + SubscribeLocalEvent(OnRenamed); } public override void Shutdown() @@ -181,6 +182,12 @@ public abstract class SharedMindSystem : EntitySystem args.Handled = true; } + private void OnRenamed(Entity ent, ref EntityRenamedEvent args) + { + ent.Comp.CharacterName = args.NewName; + Dirty(ent); + } + public EntityUid? GetMind(EntityUid uid, MindContainerComponent? mind = null) { if (!Resolve(uid, ref mind)) diff --git a/Content.Shared/NameModifier/EntitySystems/NameModifierSystem.cs b/Content.Shared/NameModifier/EntitySystems/NameModifierSystem.cs index 4dffb51805..2e7c8054b3 100644 --- a/Content.Shared/NameModifier/EntitySystems/NameModifierSystem.cs +++ b/Content.Shared/NameModifier/EntitySystems/NameModifierSystem.cs @@ -5,7 +5,7 @@ using Content.Shared.NameModifier.Components; namespace Content.Shared.NameModifier.EntitySystems; /// -public sealed partial class NameModifierSystem : EntitySystem +public sealed class NameModifierSystem : EntitySystem { [Dependency] private readonly MetaDataSystem _metaData = default!; @@ -16,10 +16,10 @@ public sealed partial class NameModifierSystem : EntitySystem SubscribeLocalEvent(OnEntityRenamed); } - private void OnEntityRenamed(Entity entity, ref EntityRenamedEvent args) + private void OnEntityRenamed(Entity ent, ref EntityRenamedEvent args) { - SetBaseName((entity, entity.Comp), args.NewName); - RefreshNameModifiers((entity, entity.Comp)); + SetBaseName(ent, args.NewName); + RefreshNameModifiers((ent.Owner, ent.Comp)); } private void SetBaseName(Entity entity, string name) diff --git a/Content.Shared/PDA/PdaComponent.cs b/Content.Shared/PDA/PdaComponent.cs index d4cfc4fc0d..6aeb245e27 100644 --- a/Content.Shared/PDA/PdaComponent.cs +++ b/Content.Shared/PDA/PdaComponent.cs @@ -37,6 +37,10 @@ namespace Content.Shared.PDA [ViewVariables] public bool FlashlightOn; [ViewVariables(VVAccess.ReadWrite)] public string? OwnerName; + // The Entity that "owns" the PDA, usually a player's character. + // This is useful when we are doing stuff like renaming a player and want to find their PDA to change the name + // as well. + [ViewVariables(VVAccess.ReadWrite)] public EntityUid? PdaOwner; [ViewVariables] public string? StationName; [ViewVariables] public string? StationAlertLevel; [ViewVariables] public Color StationAlertColor = Color.White; diff --git a/Resources/Locale/en-US/mind/commands/rename-command.ftl b/Resources/Locale/en-US/mind/commands/rename-command.ftl new file mode 100644 index 0000000000..4749cd6379 --- /dev/null +++ b/Resources/Locale/en-US/mind/commands/rename-command.ftl @@ -0,0 +1,5 @@ +cmd-rename-desc = Renames an entity and its cloner entries, ID cards, and PDAs. +cmd-rename-help = rename +cmd-rename-too-long = Name is too long. +cmd-rename-not-found = Can't find username/uid: {$target} +cmd-rename-no-entity = {$target} does not have an entity.