From 8d8c1e4daed4c4d462de089da616b27e7605e7c1 Mon Sep 17 00:00:00 2001 From: Tayrtahn Date: Sun, 6 Apr 2025 14:12:39 -0400 Subject: [PATCH] Make `RandomMetadata` properly support localization (#36343) * Make _outputSegments readonly * Remove mystery character * Use Fluent instead of string concatenation * Adjust format * Convert existing content * Don't need these anymore * Docs --- .../RandomMetadata/RandomMetadataComponent.cs | 14 ++++++++--- .../RandomMetadata/RandomMetadataSystem.cs | 19 +++++++-------- .../Locale/en-US/datasets/names/joining.ftl | 2 -- .../en-US/datasets/names/nukie_first.ftl | 3 --- .../random-metadata-formats.ftl | 23 +++++++++++++++++++ .../Prototypes/Datasets/Names/joining.yml | 14 ----------- .../Prototypes/Datasets/Names/nukies.yml | 17 -------------- .../Entities/Mobs/NPCs/regalrat.yml | 1 + .../Entities/Mobs/NPCs/revenant.yml | 3 +-- .../Mobs/Player/ShuttleRoles/settings.yml | 8 +++++++ .../Prototypes/Entities/Mobs/Player/human.yml | 3 ++- .../Entities/Mobs/Player/humanoid.yml | 16 +++++++++++++ .../Entities/Objects/Misc/books.yml | 1 + .../Entities/Objects/Tools/decoys.yml | 1 + Resources/Prototypes/GameRules/events.yml | 3 +++ Resources/Prototypes/GameRules/roundstart.yml | 8 ++++--- .../Prototypes/GameRules/subgamemodes.yml | 1 + 17 files changed, 83 insertions(+), 54 deletions(-) delete mode 100644 Resources/Locale/en-US/datasets/names/joining.ftl delete mode 100644 Resources/Locale/en-US/datasets/names/nukie_first.ftl create mode 100644 Resources/Locale/en-US/random-metadata/random-metadata-formats.ftl delete mode 100644 Resources/Prototypes/Datasets/Names/joining.yml delete mode 100644 Resources/Prototypes/Datasets/Names/nukies.yml diff --git a/Content.Server/RandomMetadata/RandomMetadataComponent.cs b/Content.Server/RandomMetadata/RandomMetadataComponent.cs index 24d07f4277..d454ec29f5 100644 --- a/Content.Server/RandomMetadata/RandomMetadataComponent.cs +++ b/Content.Server/RandomMetadata/RandomMetadataComponent.cs @@ -1,7 +1,7 @@ using Content.Shared.Dataset; using Robust.Shared.Prototypes; -namespace Content.Server.RandomMetadata; +namespace Content.Server.RandomMetadata; /// /// Randomizes the description and/or the name for an entity by creating it from list of dataset prototypes or strings. @@ -15,9 +15,17 @@ public sealed partial class RandomMetadataComponent : Component [DataField] public List>? NameSegments; + /// + /// LocId of the formatting string to use to assemble the into the entity's name. + /// Segments will be passed to the localization system with this string as variables named $part0, $part1, $part2, etc. + /// [DataField] - public string NameSeparator = " "; + public LocId NameFormat = "random-metadata-name-format-default"; + /// + /// LocId of the formatting string to use to assemble the into the entity's description. + /// Segments will be passed to the localization system with this string as variables named $part0, $part1, $part2, etc. + /// [DataField] - public string DescriptionSeparator = " "; + public LocId DescriptionFormat = "random-metadata-description-format-default"; } diff --git a/Content.Server/RandomMetadata/RandomMetadataSystem.cs b/Content.Server/RandomMetadata/RandomMetadataSystem.cs index 2127f825e9..db6f8833f3 100644 --- a/Content.Server/RandomMetadata/RandomMetadataSystem.cs +++ b/Content.Server/RandomMetadata/RandomMetadataSystem.cs @@ -12,7 +12,7 @@ public sealed class RandomMetadataSystem : EntitySystem [Dependency] private readonly IRobustRandom _random = default!; [Dependency] private readonly MetaDataSystem _metaData = default!; - private List _outputSegments = new(); + private readonly List<(string, object)> _outputSegments = new(); public override void Initialize() { @@ -28,13 +28,13 @@ public sealed class RandomMetadataSystem : EntitySystem if (component.NameSegments != null) { - _metaData.SetEntityName(uid, GetRandomFromSegments(component.NameSegments, component.NameSeparator), meta); + _metaData.SetEntityName(uid, GetRandomFromSegments(component.NameSegments, component.NameFormat), meta); } if (component.DescriptionSegments != null) { _metaData.SetEntityDescription(uid, - GetRandomFromSegments(component.DescriptionSegments, component.DescriptionSeparator), meta); + GetRandomFromSegments(component.DescriptionSegments, component.DescriptionFormat), meta); } } @@ -42,17 +42,18 @@ public sealed class RandomMetadataSystem : EntitySystem /// Generates a random string from segments and a separator. /// /// The segments that it will be generated from - /// The separator that will be inbetween each segment + /// The format string used to combine the segments. /// The newly generated string [PublicAPI] - public string GetRandomFromSegments(List> segments, string? separator) + public string GetRandomFromSegments(List> segments, LocId format) { _outputSegments.Clear(); - foreach (var segment in segments) + for (var i = 0; i < segments.Count; ++i) { - var localizedProto = _prototype.Index(segment); - _outputSegments.Add(_random.Pick(localizedProto)); + var localizedProto = _prototype.Index(segments[i]); + _outputSegments.Add(($"part{i}", _random.Pick(localizedProto))); } - return string.Join(separator, _outputSegments); + + return Loc.GetString(format, _outputSegments.ToArray()); } } diff --git a/Resources/Locale/en-US/datasets/names/joining.ftl b/Resources/Locale/en-US/datasets/names/joining.ftl deleted file mode 100644 index 3baeb89d56..0000000000 --- a/Resources/Locale/en-US/datasets/names/joining.ftl +++ /dev/null @@ -1,2 +0,0 @@ -names-word-the-1 = The -names-word-of-1 = of diff --git a/Resources/Locale/en-US/datasets/names/nukie_first.ftl b/Resources/Locale/en-US/datasets/names/nukie_first.ftl deleted file mode 100644 index 42433d26e8..0000000000 --- a/Resources/Locale/en-US/datasets/names/nukie_first.ftl +++ /dev/null @@ -1,3 +0,0 @@ -names-nukie-commander-1 = Commander -names-nukie-agent-1 = Agent -names-nukie-operator-1 = Operator diff --git a/Resources/Locale/en-US/random-metadata/random-metadata-formats.ftl b/Resources/Locale/en-US/random-metadata/random-metadata-formats.ftl new file mode 100644 index 0000000000..2060315620 --- /dev/null +++ b/Resources/Locale/en-US/random-metadata/random-metadata-formats.ftl @@ -0,0 +1,23 @@ +random-metadata-name-format-default = {$part0} +random-metadata-description-format-default = {$part0} + +# Used for standard humanoid names - " " +name-format-standard = {$part0} {$part1} + +name-format-regal-rat = {$part0} {$part1} +name-format-revenant = The {$part0} of {$part1} {$part2} +name-format-ninja = {$part0} {$part1} +name-format-wizard = {$part0} {$part1} + +# " <name>" +name-format-nukie-generic = {$part0} {$part1} +name-format-nukie-agent = Agent {$part0} +name-format-nukie-commander = Commander {$part0} +name-format-nukie-operator = Operator {$part0} +# "<title> <name>" +name-format-ert = {$part0} {$part1} + +# "<appearance> <type>" +name-format-book = {$part0} {$part1} + +name-format-nuclear-operation = {$part0} {$part1} diff --git a/Resources/Prototypes/Datasets/Names/joining.yml b/Resources/Prototypes/Datasets/Names/joining.yml deleted file mode 100644 index 16ad0803f5..0000000000 --- a/Resources/Prototypes/Datasets/Names/joining.yml +++ /dev/null @@ -1,14 +0,0 @@ -# These can be inserted inbetween name datasets -# Ideally it would be localized since just swapping words doesnt help much for a lot of languages - -- type: localizedDataset - id: WordThe - values: - prefix: names-word-the- - count: 1 - -- type: localizedDataset - id: WordOf - values: - prefix: names-word-of- - count: 1 diff --git a/Resources/Prototypes/Datasets/Names/nukies.yml b/Resources/Prototypes/Datasets/Names/nukies.yml deleted file mode 100644 index cf2c6b7ab7..0000000000 --- a/Resources/Prototypes/Datasets/Names/nukies.yml +++ /dev/null @@ -1,17 +0,0 @@ -- type: localizedDataset - id: NamesNukieFirstCommander - values: - prefix: names-nukie-commander- - count: 1 - -- type: localizedDataset - id: NamesNukieFirstAgent - values: - prefix: names-nukie-agent- - count: 1 - -- type: localizedDataset - id: NamesNukieFirstOperator - values: - prefix: names-nukie-operator- - count: 1 diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/regalrat.yml b/Resources/Prototypes/Entities/Mobs/NPCs/regalrat.yml index 1781ce25cd..89056c1d51 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/regalrat.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/regalrat.yml @@ -117,6 +117,7 @@ nameSegments: - NamesRegalratKingdom - NamesRegalratTitle + nameFormat: name-format-regal-rat - type: GuideHelp guides: - MinorAntagonists diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/revenant.yml b/Resources/Prototypes/Entities/Mobs/NPCs/revenant.yml index dfdb96b35a..1c70e55d66 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/revenant.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/revenant.yml @@ -72,11 +72,10 @@ - StolenEssence - type: RandomMetadata nameSegments: - - WordThe - NamesRevenantType - - WordOf - NamesRevenantAdjective - NamesRevenantTheme + nameFormat: name-format-revenant - type: Speech speechVerb: Ghost - type: Reactive diff --git a/Resources/Prototypes/Entities/Mobs/Player/ShuttleRoles/settings.yml b/Resources/Prototypes/Entities/Mobs/Player/ShuttleRoles/settings.yml index cebc570bdb..5debd3f8a3 100644 --- a/Resources/Prototypes/Entities/Mobs/Player/ShuttleRoles/settings.yml +++ b/Resources/Prototypes/Entities/Mobs/Player/ShuttleRoles/settings.yml @@ -577,6 +577,7 @@ nameSegments: - NamesFirst - NamesLast + nameFormat: name-format-standard - type: randomHumanoidSettings id: ChallengeVictimChiefEngineer @@ -596,6 +597,7 @@ nameSegments: - NamesFirst - NamesLast + nameFormat: name-format-standard - type: randomHumanoidSettings id: ChallengeVictimCMO @@ -615,6 +617,7 @@ nameSegments: - NamesFirst - NamesLast + nameFormat: name-format-standard - type: randomHumanoidSettings id: ChallengeVictimHeadOfPersonnel @@ -634,6 +637,7 @@ nameSegments: - NamesFirst - NamesLast + nameFormat: name-format-standard - type: randomHumanoidSettings id: ChallengeVictimHeadOfSecurity @@ -653,6 +657,7 @@ nameSegments: - NamesFirst - NamesLast + nameFormat: name-format-standard - type: randomHumanoidSettings id: ChallengeVictimResearchDirector @@ -672,6 +677,7 @@ nameSegments: - NamesFirst - NamesLast + nameFormat: name-format-standard - type: randomHumanoidSettings id: ChallengeVictimQuartermaster @@ -691,6 +697,7 @@ nameSegments: - NamesFirst - NamesLast + nameFormat: name-format-standard # Security # Following use EventHumanoidMindShielded since they are heads and probably should have mindshields @@ -715,6 +722,7 @@ nameSegments: - NamesFirst - NamesLast + nameFormat: name-format-standard # Engineering diff --git a/Resources/Prototypes/Entities/Mobs/Player/human.yml b/Resources/Prototypes/Entities/Mobs/Player/human.yml index 11842f30f0..8b677c49f7 100644 --- a/Resources/Prototypes/Entities/Mobs/Player/human.yml +++ b/Resources/Prototypes/Entities/Mobs/Player/human.yml @@ -68,8 +68,8 @@ - type: NukeOperative - type: RandomMetadata nameSegments: - - NamesNukieFirstOperator - NamesSyndicateNormal + nameFormat: name-format-nukie-operator - type: Loadout prototypes: [SyndicateOperativeGearFullNoUplink] @@ -99,6 +99,7 @@ nameSegments: - NamesSyndicatePrefix - NamesSyndicateNormal + nameFormat: name-format-nukie-generic - type: NpcFactionMember factions: - Syndicate diff --git a/Resources/Prototypes/Entities/Mobs/Player/humanoid.yml b/Resources/Prototypes/Entities/Mobs/Player/humanoid.yml index 2d63d48bdc..f92cf40e2e 100644 --- a/Resources/Prototypes/Entities/Mobs/Player/humanoid.yml +++ b/Resources/Prototypes/Entities/Mobs/Player/humanoid.yml @@ -36,6 +36,7 @@ nameSegments: - NamesMilitaryFirstLeader - NamesMilitaryLast + nameFormat: name-format-ert - type: RandomHumanoidSpawner settings: DeathSquad @@ -59,6 +60,7 @@ nameSegments: - NamesMilitaryFirstLeader - NamesMilitaryLast + nameFormat: name-format-ert ## ERT Leader @@ -75,6 +77,7 @@ nameSegments: - NamesMilitaryFirstLeader - NamesMilitaryLast + nameFormat: name-format-ert - type: RandomHumanoidSpawner settings: ERTLeader @@ -97,6 +100,7 @@ nameSegments: - NamesMilitaryFirstLeader - NamesMilitaryLast + nameFormat: name-format-ert - type: entity id: RandomHumanoidSpawnerERTLeaderEVA @@ -163,6 +167,7 @@ nameSegments: - NamesMilitaryFirst - NamesMilitaryLast + nameFormat: name-format-ert - type: RandomHumanoidSpawner settings: ERTChaplain @@ -182,6 +187,7 @@ nameSegments: - NamesMilitaryFirst - NamesMilitaryLast + nameFormat: name-format-ert - type: Loadout prototypes: [ ERTChaplainGear ] roleLoadout: [ RoleSurvivalExtended ] @@ -229,6 +235,7 @@ nameSegments: - NamesMilitaryFirst - NamesMilitaryLast + nameFormat: name-format-ert - type: RandomHumanoidSpawner settings: ERTJanitor @@ -247,6 +254,7 @@ nameSegments: - NamesMilitaryFirst - NamesMilitaryLast + nameFormat: name-format-ert - type: Loadout prototypes: [ ERTJanitorGear ] roleLoadout: [ RoleSurvivalExtended ] @@ -293,6 +301,7 @@ nameSegments: - NamesMilitaryFirst - NamesMilitaryLast + nameFormat: name-format-ert - type: RandomHumanoidSpawner settings: ERTEngineer @@ -311,6 +320,7 @@ nameSegments: - NamesMilitaryFirst - NamesMilitaryLast + nameFormat: name-format-ert - type: Loadout prototypes: [ ERTEngineerGear ] roleLoadout: [ RoleSurvivalExtended ] @@ -357,6 +367,7 @@ nameSegments: - NamesMilitaryFirst - NamesMilitaryLast + nameFormat: name-format-ert - type: RandomHumanoidSpawner settings: ERTSecurity @@ -375,6 +386,7 @@ nameSegments: - NamesMilitaryFirst - NamesMilitaryLast + nameFormat: name-format-ert - type: Loadout prototypes: [ ERTSecurityGear ] roleLoadout: [ RoleSurvivalExtended ] @@ -444,6 +456,7 @@ nameSegments: - NamesMilitaryFirst - NamesMilitaryLast + nameFormat: name-format-ert - type: RandomHumanoidSpawner settings: ERTMedical @@ -462,6 +475,7 @@ nameSegments: - NamesMilitaryFirst - NamesMilitaryLast + nameFormat: name-format-ert - type: Loadout prototypes: [ ERTMedicalGear ] roleLoadout: [ RoleSurvivalExtended ] @@ -523,6 +537,7 @@ nameSegments: - NamesMilitaryFirst - NamesMilitaryLast + nameFormat: name-format-ert ## Central Command @@ -604,6 +619,7 @@ nameSegments: - NamesFirst - NamesLast + nameFormat: name-format-standard - type: randomHumanoidSettings id: Cluwne diff --git a/Resources/Prototypes/Entities/Objects/Misc/books.yml b/Resources/Prototypes/Entities/Objects/Misc/books.yml index 21269366d4..7b3f474025 100644 --- a/Resources/Prototypes/Entities/Objects/Misc/books.yml +++ b/Resources/Prototypes/Entities/Objects/Misc/books.yml @@ -356,6 +356,7 @@ nameSegments: - BookHintAppearances - BookTypes + nameFormat: name-format-book - type: RandomSprite available: - cover: diff --git a/Resources/Prototypes/Entities/Objects/Tools/decoys.yml b/Resources/Prototypes/Entities/Objects/Tools/decoys.yml index 8bacfe96af..a13c2eef9f 100644 --- a/Resources/Prototypes/Entities/Objects/Tools/decoys.yml +++ b/Resources/Prototypes/Entities/Objects/Tools/decoys.yml @@ -33,6 +33,7 @@ nameSegments: - NamesSyndicatePrefix - NamesSyndicateNormal + nameFormat: name-format-nukie-generic - type: Damageable damageContainer: Inorganic - type: ToggleableLightVisuals diff --git a/Resources/Prototypes/GameRules/events.yml b/Resources/Prototypes/GameRules/events.yml index 41655a4871..c369b10949 100644 --- a/Resources/Prototypes/GameRules/events.yml +++ b/Resources/Prototypes/GameRules/events.yml @@ -230,6 +230,7 @@ nameSegments: - NamesNinjaTitle - NamesNinja + nameFormat: name-format-ninja mindRoles: - MindRoleNinja @@ -316,6 +317,7 @@ nameSegments: - NamesWizardFirst - NamesWizardLast + nameFormat: name-format-wizard mindRoles: - MindRoleWizard @@ -548,6 +550,7 @@ nameSegments: - NamesSyndicatePrefix - NamesSyndicateNormal + nameFormat: name-format-nukie-generic - type: NpcFactionMember factions: - Syndicate diff --git a/Resources/Prototypes/GameRules/roundstart.yml b/Resources/Prototypes/GameRules/roundstart.yml index a7072bde72..bb855d93aa 100644 --- a/Resources/Prototypes/GameRules/roundstart.yml +++ b/Resources/Prototypes/GameRules/roundstart.yml @@ -97,6 +97,7 @@ nameSegments: - NamesOperationPrefix - NamesOperationSuffix + nameFormat: name-format-nuclear-operation - type: NukeopsRule - type: RuleGrids - type: AntagSelection @@ -129,8 +130,8 @@ - type: NukeOperative - type: RandomMetadata nameSegments: - - NamesNukieFirstCommander - NamesSyndicateElite + nameFormat: name-format-nukie-commander - type: NpcFactionMember factions: - Syndicate @@ -146,8 +147,8 @@ - type: NukeOperative - type: RandomMetadata nameSegments: - - NamesNukieFirstAgent - NamesSyndicateNormal + nameFormat: name-format-nukie-agent - type: NpcFactionMember factions: - Syndicate @@ -165,8 +166,8 @@ - type: NukeOperative - type: RandomMetadata nameSegments: - - NamesNukieFirstOperator - NamesSyndicateNormal + nameFormat: name-format-nukie-operator - type: NpcFactionMember factions: - Syndicate @@ -307,6 +308,7 @@ nameSegments: - NamesWizardFirst - NamesWizardLast + nameFormat: name-format-wizard mindRoles: - MindRoleWizard diff --git a/Resources/Prototypes/GameRules/subgamemodes.yml b/Resources/Prototypes/GameRules/subgamemodes.yml index 6604a036bd..ef80a48cef 100644 --- a/Resources/Prototypes/GameRules/subgamemodes.yml +++ b/Resources/Prototypes/GameRules/subgamemodes.yml @@ -62,5 +62,6 @@ nameSegments: - NamesWizardFirst - NamesWizardLast + nameFormat: name-format-wizard mindRoles: - MindRoleWizard