Add a system for modifying entity names without causing conflicts (#27863)

This commit is contained in:
Tayrtahn
2024-06-16 15:38:53 -04:00
committed by GitHub
parent ee2769ed9f
commit 89a9f07c3a
30 changed files with 326 additions and 123 deletions

View File

@@ -14,14 +14,6 @@ namespace Content.Server.Chemistry.Components;
[RegisterComponent, Access(typeof(TransformableContainerSystem))]
public sealed partial class TransformableContainerComponent : Component
{
/// <summary>
/// This is the initial metadata name for the container.
/// It will revert to this when emptied.
/// It defaults to the name of the parent entity unless overwritten.
/// </summary>
[DataField("initialName")]
public string? InitialName;
/// <summary>
/// This is the initial metadata description for the container.
/// It will revert to this when emptied.

View File

@@ -2,6 +2,7 @@ using Content.Server.Chemistry.Components;
using Content.Server.Chemistry.Containers.EntitySystems;
using Content.Shared.Chemistry.EntitySystems;
using Content.Shared.Chemistry.Reagent;
using Content.Shared.NameModifier.EntitySystems;
using Robust.Shared.Prototypes;
namespace Content.Server.Chemistry.EntitySystems;
@@ -11,6 +12,7 @@ public sealed class TransformableContainerSystem : EntitySystem
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
[Dependency] private readonly SolutionContainerSystem _solutionsSystem = default!;
[Dependency] private readonly MetaDataSystem _metadataSystem = default!;
[Dependency] private readonly NameModifierSystem _nameMod = default!;
public override void Initialize()
{
@@ -18,15 +20,12 @@ public sealed class TransformableContainerSystem : EntitySystem
SubscribeLocalEvent<TransformableContainerComponent, MapInitEvent>(OnMapInit);
SubscribeLocalEvent<TransformableContainerComponent, SolutionContainerChangedEvent>(OnSolutionChange);
SubscribeLocalEvent<TransformableContainerComponent, RefreshNameModifiersEvent>(OnRefreshNameModifiers);
}
private void OnMapInit(Entity<TransformableContainerComponent> entity, ref MapInitEvent args)
private void OnMapInit(Entity<TransformableContainerComponent> entity, ref MapInitEvent args)
{
var meta = MetaData(entity.Owner);
if (string.IsNullOrEmpty(entity.Comp.InitialName))
{
entity.Comp.InitialName = meta.EntityName;
}
if (string.IsNullOrEmpty(entity.Comp.InitialDescription))
{
entity.Comp.InitialDescription = meta.EntityDescription;
@@ -58,12 +57,20 @@ public sealed class TransformableContainerSystem : EntitySystem
&& _prototypeManager.TryIndex(reagentId.Value.Prototype, out ReagentPrototype? proto))
{
var metadata = MetaData(entity.Owner);
var val = Loc.GetString("transformable-container-component-glass", ("name", proto.LocalizedName));
_metadataSystem.SetEntityName(entity.Owner, val, metadata);
_metadataSystem.SetEntityDescription(entity.Owner, proto.LocalizedDescription, metadata);
entity.Comp.CurrentReagent = proto;
entity.Comp.Transformed = true;
}
_nameMod.RefreshNameModifiers(entity.Owner);
}
private void OnRefreshNameModifiers(Entity<TransformableContainerComponent> entity, ref RefreshNameModifiersEvent args)
{
if (entity.Comp.CurrentReagent is { } currentReagent)
{
args.AddModifier("transformable-container-component-glass", priority: -1, ("reagent", currentReagent.LocalizedName));
}
}
private void CancelTransformation(Entity<TransformableContainerComponent> entity)
@@ -73,10 +80,8 @@ public sealed class TransformableContainerSystem : EntitySystem
var metadata = MetaData(entity);
if (!string.IsNullOrEmpty(entity.Comp.InitialName))
{
_metadataSystem.SetEntityName(entity.Owner, entity.Comp.InitialName, metadata);
}
_nameMod.RefreshNameModifiers(entity.Owner);
if (!string.IsNullOrEmpty(entity.Comp.InitialDescription))
{
_metadataSystem.SetEntityDescription(entity.Owner, entity.Comp.InitialDescription, metadata);

View File

@@ -14,8 +14,8 @@ using Content.Server.Emoting.Systems;
using Content.Server.Speech.EntitySystems;
using Content.Shared.Cluwne;
using Content.Shared.Interaction.Components;
using Robust.Shared.Audio;
using Robust.Shared.Audio.Systems;
using Content.Shared.NameModifier.EntitySystems;
namespace Content.Server.Cluwne;
@@ -30,6 +30,7 @@ public sealed class CluwneSystem : EntitySystem
[Dependency] private readonly ChatSystem _chat = default!;
[Dependency] private readonly AutoEmoteSystem _autoEmote = default!;
[Dependency] private readonly MetaDataSystem _metaData = default!;
[Dependency] private readonly NameModifierSystem _nameMod = default!;
public override void Initialize()
{
@@ -39,6 +40,7 @@ public sealed class CluwneSystem : EntitySystem
SubscribeLocalEvent<CluwneComponent, MobStateChangedEvent>(OnMobState);
SubscribeLocalEvent<CluwneComponent, EmoteEvent>(OnEmote, before:
new[] { typeof(VocalSystem), typeof(BodyEmotesSystem) });
SubscribeLocalEvent<CluwneComponent, RefreshNameModifiersEvent>(OnRefreshNameModifiers);
}
/// <summary>
@@ -47,19 +49,19 @@ public sealed class CluwneSystem : EntitySystem
private void OnMobState(EntityUid uid, CluwneComponent component, MobStateChangedEvent args)
{
if (args.NewMobState == MobState.Dead)
{
{
RemComp<CluwneComponent>(uid);
RemComp<ClumsyComponent>(uid);
RemComp<AutoEmoteComponent>(uid);
var damageSpec = new DamageSpecifier(_prototypeManager.Index<DamageGroupPrototype>("Genetic"), 300);
_damageableSystem.TryChangeDamage(uid, damageSpec);
}
}
}
public EmoteSoundsPrototype? EmoteSounds;
/// <summary>
/// OnStartup gives the cluwne outfit, ensures clumsy, gives name prefix and makes sure emote sounds are laugh.
/// OnStartup gives the cluwne outfit, ensures clumsy, and makes sure emote sounds are laugh.
/// </summary>
private void OnComponentStartup(EntityUid uid, CluwneComponent component, ComponentStartup args)
{
@@ -67,9 +69,6 @@ public sealed class CluwneSystem : EntitySystem
return;
_prototypeManager.TryIndex(component.EmoteSoundsId, out EmoteSounds);
var meta = MetaData(uid);
var name = meta.EntityName;
EnsureComp<AutoEmoteComponent>(uid);
_autoEmote.AddEmote(uid, "CluwneGiggle");
EnsureComp<ClumsyComponent>(uid);
@@ -77,7 +76,7 @@ public sealed class CluwneSystem : EntitySystem
_popupSystem.PopupEntity(Loc.GetString("cluwne-transform", ("target", uid)), uid, PopupType.LargeCaution);
_audio.PlayPvs(component.SpawnSound, uid);
_metaData.SetEntityName(uid, Loc.GetString("cluwne-name-prefix", ("target", name)), meta);
_nameMod.RefreshNameModifiers(uid);
SetOutfitCommand.SetOutfit(uid, "CluwneGear", EntityManager);
}
@@ -104,4 +103,12 @@ public sealed class CluwneSystem : EntitySystem
_chat.TrySendInGameICMessage(uid, "spasms", InGameICChatType.Emote, ChatTransmitRange.Normal);
}
}
/// <summary>
/// Applies "Cluwnified" prefix
/// </summary>
private void OnRefreshNameModifiers(Entity<CluwneComponent> entity, ref RefreshNameModifiersEvent args)
{
args.AddModifier("cluwne-name-prefix");
}
}

View File

@@ -29,6 +29,7 @@ using Robust.Shared.Audio.Systems;
using Robust.Shared.Containers;
using Robust.Shared.Player;
using Robust.Shared.Prototypes;
using Content.Shared.NameModifier.Components;
namespace Content.Server.Fax;
@@ -464,10 +465,11 @@ public sealed class FaxSystem : EntitySystem
return;
TryComp<LabelComponent>(sendEntity, out var labelComponent);
TryComp<NameModifierComponent>(sendEntity, out var nameMod);
// TODO: See comment in 'Send()' about not being able to copy whole entities
var printout = new FaxPrintout(paper.Content,
labelComponent?.OriginalName ?? metadata.EntityName,
nameMod?.BaseName ?? metadata.EntityName,
labelComponent?.CurrentLabel,
metadata.EntityPrototype?.ID ?? DefaultPaperPrototypeId,
paper.StampState,
@@ -510,12 +512,14 @@ public sealed class FaxSystem : EntitySystem
!TryComp<PaperComponent>(sendEntity, out var paper))
return;
TryComp<NameModifierComponent>(sendEntity, out var nameMod);
TryComp<LabelComponent>(sendEntity, out var labelComponent);
var payload = new NetworkPayload()
{
{ DeviceNetworkConstants.Command, FaxConstants.FaxPrintCommand },
{ FaxConstants.FaxPaperNameData, labelComponent?.OriginalName ?? metadata.EntityName },
{ FaxConstants.FaxPaperNameData, nameMod?.BaseName ?? metadata.EntityName },
{ FaxConstants.FaxPaperLabelData, labelComponent?.CurrentLabel },
{ FaxConstants.FaxPaperContentData, paper.Content },
};

View File

@@ -6,6 +6,7 @@ using Content.Shared.Hands;
using Content.Shared.Interaction;
using Content.Shared.Interaction.Components;
using Content.Shared.Item;
using Content.Shared.NameModifier.EntitySystems;
using Content.Shared.Nutrition.EntitySystems;
using Content.Shared.Popups;
using Content.Shared.Verbs;
@@ -20,9 +21,9 @@ public sealed class GlueSystem : SharedGlueSystem
[Dependency] private readonly SharedPopupSystem _popup = default!;
[Dependency] private readonly SolutionContainerSystem _solutionContainer = default!;
[Dependency] private readonly IGameTiming _timing = default!;
[Dependency] private readonly MetaDataSystem _metaData = default!;
[Dependency] private readonly IAdminLogManager _adminLogger = default!;
[Dependency] private readonly OpenableSystem _openable = default!;
[Dependency] private readonly NameModifierSystem _nameMod = default!;
public override void Initialize()
{
@@ -32,6 +33,7 @@ public sealed class GlueSystem : SharedGlueSystem
SubscribeLocalEvent<GluedComponent, ComponentInit>(OnGluedInit);
SubscribeLocalEvent<GlueComponent, GetVerbsEvent<UtilityVerb>>(OnUtilityVerb);
SubscribeLocalEvent<GluedComponent, GotEquippedHandEvent>(OnHandPickUp);
SubscribeLocalEvent<GluedComponent, RefreshNameModifiersEvent>(OnRefreshNameModifiers);
}
// When glue bottle is used on item it will apply the glued and unremoveable components.
@@ -95,27 +97,22 @@ public sealed class GlueSystem : SharedGlueSystem
{
base.Update(frameTime);
var query = EntityQueryEnumerator<GluedComponent, UnremoveableComponent, MetaDataComponent>();
while (query.MoveNext(out var uid, out var glue, out var _, out var meta))
var query = EntityQueryEnumerator<GluedComponent, UnremoveableComponent>();
while (query.MoveNext(out var uid, out var glue, out var _))
{
if (_timing.CurTime < glue.Until)
continue;
// Instead of string matching, just reconstruct the expected name and compare
if (meta.EntityName == Loc.GetString("glued-name-prefix", ("target", glue.BeforeGluedEntityName)))
_metaData.SetEntityName(uid, glue.BeforeGluedEntityName);
RemComp<UnremoveableComponent>(uid);
RemComp<GluedComponent>(uid);
_nameMod.RefreshNameModifiers(uid);
}
}
private void OnGluedInit(Entity<GluedComponent> entity, ref ComponentInit args)
{
var meta = MetaData(entity);
var name = meta.EntityName;
entity.Comp.BeforeGluedEntityName = meta.EntityName;
_metaData.SetEntityName(entity.Owner, Loc.GetString("glued-name-prefix", ("target", name)));
_nameMod.RefreshNameModifiers(entity.Owner);
}
private void OnHandPickUp(Entity<GluedComponent> entity, ref GotEquippedHandEvent args)
@@ -124,4 +121,9 @@ public sealed class GlueSystem : SharedGlueSystem
comp.DeleteOnDrop = false;
entity.Comp.Until = _timing.CurTime + entity.Comp.Duration;
}
private void OnRefreshNameModifiers(Entity<GluedComponent> entity, ref RefreshNameModifiersEvent args)
{
args.AddModifier("glued-name-prefix");
}
}

View File

@@ -5,6 +5,7 @@ using Content.Shared.Examine;
using Content.Shared.Labels;
using Content.Shared.Labels.Components;
using Content.Shared.Labels.EntitySystems;
using Content.Shared.NameModifier.EntitySystems;
using JetBrains.Annotations;
using Robust.Shared.Containers;
@@ -18,7 +19,7 @@ namespace Content.Server.Labels
{
[Dependency] private readonly ItemSlotsSystem _itemSlotsSystem = default!;
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
[Dependency] private readonly MetaDataSystem _metaData = default!;
[Dependency] private readonly NameModifierSystem _nameMod = default!;
public const string ContainerName = "paper_label";
@@ -41,6 +42,8 @@ namespace Content.Server.Labels
component.CurrentLabel = Loc.GetString(component.CurrentLabel);
Dirty(uid, component);
}
_nameMod.RefreshNameModifiers(uid);
}
/// <summary>
@@ -52,30 +55,11 @@ namespace Content.Server.Labels
/// <param name="metadata">metadata component for resolve</param>
public override void Label(EntityUid uid, string? text, MetaDataComponent? metadata = null, LabelComponent? label = null)
{
if (!Resolve(uid, ref metadata))
return;
if (!Resolve(uid, ref label, false))
label = EnsureComp<LabelComponent>(uid);
if (string.IsNullOrEmpty(text))
{
if (label.OriginalName is null)
return;
// Remove label
_metaData.SetEntityName(uid, label.OriginalName, metadata);
label.CurrentLabel = null;
label.OriginalName = null;
Dirty(uid, label);
return;
}
// Update label
label.OriginalName ??= metadata.EntityName;
label.CurrentLabel = text;
_metaData.SetEntityName(uid, $"{label.OriginalName} ({text})", metadata);
_nameMod.RefreshNameModifiers(uid);
Dirty(uid, label);
}

View File

@@ -1,5 +1,6 @@
using Content.Shared.IdentityManagement;
using Content.Shared.Lube;
using Content.Shared.NameModifier.EntitySystems;
using Content.Shared.Popups;
using Content.Shared.Throwing;
using Robust.Shared.Containers;
@@ -9,11 +10,11 @@ namespace Content.Server.Lube;
public sealed class LubedSystem : EntitySystem
{
[Dependency] private readonly MetaDataSystem _metaData = default!;
[Dependency] private readonly ThrowingSystem _throwing = default!;
[Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly SharedTransformSystem _transform = default!;
[Dependency] private readonly SharedPopupSystem _popup = default!;
[Dependency] private readonly NameModifierSystem _nameMod = default!;
public override void Initialize()
{
@@ -21,14 +22,12 @@ public sealed class LubedSystem : EntitySystem
SubscribeLocalEvent<LubedComponent, ComponentInit>(OnInit);
SubscribeLocalEvent<LubedComponent, ContainerGettingInsertedAttemptEvent>(OnHandPickUp);
SubscribeLocalEvent<LubedComponent, RefreshNameModifiersEvent>(OnRefreshNameModifiers);
}
private void OnInit(EntityUid uid, LubedComponent component, ComponentInit args)
{
var meta = MetaData(uid);
var name = meta.EntityName;
component.BeforeLubedEntityName = meta.EntityName;
_metaData.SetEntityName(uid, Loc.GetString("lubed-name-prefix", ("target", name)));
_nameMod.RefreshNameModifiers(uid);
}
private void OnHandPickUp(EntityUid uid, LubedComponent component, ContainerGettingInsertedAttemptEvent args)
@@ -36,7 +35,7 @@ public sealed class LubedSystem : EntitySystem
if (component.SlipsLeft <= 0)
{
RemComp<LubedComponent>(uid);
_metaData.SetEntityName(uid, component.BeforeLubedEntityName);
_nameMod.RefreshNameModifiers(uid);
return;
}
component.SlipsLeft--;
@@ -47,4 +46,9 @@ public sealed class LubedSystem : EntitySystem
_throwing.TryThrow(uid, _random.NextVector2(), strength: component.SlipStrength);
_popup.PopupEntity(Loc.GetString("lube-slip", ("target", Identity.Entity(uid, EntityManager))), user, user, PopupType.MediumCaution);
}
private void OnRefreshNameModifiers(Entity<LubedComponent> entity, ref RefreshNameModifiersEvent args)
{
args.AddModifier("lubed-name-prefix");
}
}

View File

@@ -5,13 +5,12 @@ using Content.Shared.IdentityManagement;
using Content.Shared.Interaction.Components;
using Content.Shared.Mind.Components;
using Content.Shared.Mobs.Systems;
using Content.Shared.NameModifier.EntitySystems;
using Content.Shared.Nutrition.AnimalHusbandry;
using Content.Shared.Nutrition.Components;
using Content.Shared.Nutrition.EntitySystems;
using Content.Shared.Storage;
using Content.Shared.Whitelist;
using Robust.Server.GameObjects;
using Robust.Shared.Audio;
using Robust.Shared.Audio.Systems;
using Robust.Shared.Player;
using Robust.Shared.Random;
@@ -29,12 +28,12 @@ public sealed class AnimalHusbandrySystem : EntitySystem
[Dependency] private readonly IAdminLogManager _adminLog = default!;
[Dependency] private readonly IGameTiming _timing = default!;
[Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly MetaDataSystem _metaData = default!;
[Dependency] private readonly MobStateSystem _mobState = default!;
[Dependency] private readonly PopupSystem _popup = default!;
[Dependency] private readonly SharedAudioSystem _audio = default!;
[Dependency] private readonly SharedTransformSystem _transform = default!;
[Dependency] private readonly EntityWhitelistSystem _whitelistSystem = default!;
[Dependency] private readonly NameModifierSystem _nameMod = default!;
private readonly HashSet<EntityUid> _failedAttempts = new();
private readonly HashSet<EntityUid> _birthQueue = new();
@@ -43,8 +42,7 @@ public sealed class AnimalHusbandrySystem : EntitySystem
public override void Initialize()
{
SubscribeLocalEvent<ReproductiveComponent, MindAddedMessage>(OnMindAdded);
SubscribeLocalEvent<InfantComponent, ComponentStartup>(OnInfantStartup);
SubscribeLocalEvent<InfantComponent, ComponentShutdown>(OnInfantShutdown);
SubscribeLocalEvent<InfantComponent, RefreshNameModifiersEvent>(OnRefreshNameModifiers);
}
// we express EZ-pass terminate the pregnancy if a player takes the role
@@ -54,16 +52,11 @@ public sealed class AnimalHusbandrySystem : EntitySystem
component.GestationEndTime = null;
}
private void OnInfantStartup(EntityUid uid, InfantComponent component, ComponentStartup args)
private void OnRefreshNameModifiers(Entity<InfantComponent> entity, ref RefreshNameModifiersEvent args)
{
var meta = MetaData(uid);
component.OriginalName = meta.EntityName;
_metaData.SetEntityName(uid, Loc.GetString("infant-name-prefix", ("name", meta.EntityName)), meta);
}
private void OnInfantShutdown(EntityUid uid, InfantComponent component, ComponentShutdown args)
{
_metaData.SetEntityName(uid, component.OriginalName);
// This check may seem redundant, but it makes sure that the prefix is removed before the component is removed
if (_timing.CurTime < entity.Comp.InfantEndTime)
args.AddModifier("infant-name-prefix");
}
/// <summary>
@@ -202,6 +195,8 @@ public sealed class AnimalHusbandrySystem : EntitySystem
{
var infant = AddComp<InfantComponent>(offspring);
infant.InfantEndTime = _timing.CurTime + infant.InfantDuration;
// Make sure the name prefix is applied
_nameMod.RefreshNameModifiers(offspring);
}
_adminLog.Add(LogType.Action, $"{ToPrettyString(uid)} gave birth to {ToPrettyString(offspring)}.");
}
@@ -249,6 +244,8 @@ public sealed class AnimalHusbandrySystem : EntitySystem
if (_timing.CurTime < infant.InfantEndTime)
continue;
RemCompDeferred(uid, infant);
// Make sure the name prefix gets removed
_nameMod.RefreshNameModifiers(uid);
}
}
}

View File

@@ -222,9 +222,7 @@ namespace Content.Server.Zombies
_faction.AddFaction(target, "Zombie");
//gives it the funny "Zombie ___" name.
var meta = MetaData(target);
zombiecomp.BeforeZombifiedEntityName = meta.EntityName;
_metaData.SetEntityName(target, Loc.GetString("zombie-name-prefix", ("target", meta.EntityName)), meta);
_nameMod.RefreshNameModifiers(target);
_identity.QueueIdentityUpdate(target);

View File

@@ -14,6 +14,7 @@ using Content.Shared.Mind;
using Content.Shared.Mobs;
using Content.Shared.Mobs.Components;
using Content.Shared.Mobs.Systems;
using Content.Shared.NameModifier.EntitySystems;
using Content.Shared.Popups;
using Content.Shared.Weapons.Melee.Events;
using Content.Shared.Zombies;
@@ -34,9 +35,9 @@ namespace Content.Server.Zombies
[Dependency] private readonly ActionsSystem _actions = default!;
[Dependency] private readonly AutoEmoteSystem _autoEmote = default!;
[Dependency] private readonly EmoteOnDamageSystem _emoteOnDamage = default!;
[Dependency] private readonly MetaDataSystem _metaData = default!;
[Dependency] private readonly MobStateSystem _mobState = default!;
[Dependency] private readonly SharedPopupSystem _popup = default!;
[Dependency] private readonly NameModifierSystem _nameMod = default!;
public const SlotFlags ProtectiveSlots =
SlotFlags.FEET |
@@ -281,7 +282,7 @@ namespace Content.Server.Zombies
_humanoidAppearance.SetSkinColor(target, zombiecomp.BeforeZombifiedSkinColor, false);
_bloodstream.ChangeBloodReagent(target, zombiecomp.BeforeZombifiedBloodReagent);
_metaData.SetEntityName(target, zombiecomp.BeforeZombifiedEntityName);
_nameMod.RefreshNameModifiers(target);
return true;
}