space-station-14
space-station-14 copied to clipboard
Add a system for modifying entity names without causing conflicts
About the PR
Adds RenamerSystem, which aims to fix the problems that arise from different systems renaming entities.
Modifies a bunch of systems that previously could cause renaming conflicts when used on the same entity. Specifically, this fixes issues with metamorphic glasses, glue, lube, flares/glowsticks, forensic pads, DNA scrambler implants, PAIs, baby animals, borgs, zombies, cluwnes, chameleon clothing, and the admin renaming command and verbs.
Also includes ModifyWearerName Component/System both as a demo and to make it easier to add clothing that does simple name modifications. It's not used on anything in this PR though.
Why / Balance
See #27670 for an explanation of the issues that can come up with multiple systems renaming things. In short, the old method for renaming an entity was to copy the old name into a component field and then copy it back to revert the name. This meant that any additional changes to the name between those actions would be bulldozed. This system prevents that and makes it easy to add and remove name modifications. You can now have a "glued lubed mojito glass (for nerds)" and refill it to make a "glued lubed screwdriver glass (for nerds)" without issues.
Fixes #27670
Technical details
When either RenamerSystem method is called, it adds a RenamerComponent to the target entity. On MapInit, RenamerComponent copies the entity's name from MetaData and stores it as BaseName.
If other systems want to make permanent changes to the full name, they can call RenamerSystem.SetBaseName, and everything should just work.
For temporary changes that can be reversed, or for prefixes, postfixes, or other modifications, systems should subscribe to RefreshNameModifiersEvent and call RenamerSystem.RefreshNameModifiers. This is a pattern used elsewhere in the code (movement speed modifiers, for example), where the subscribed systems are checked for any modifications they want to apply before building the final name.
If a system spawns an entity and then immediately renames it, it doesn't need to use RenamerSystem, since it's safe to assume that nothing else will have modified its name.
RefreshNameModifiersEvent has methods to add prefixes, postfixes, and overrides to the final name. A prefix is placed before the BaseName, and can optionally specify a priority to determine where to place it in the list. Postfixes work the same but are naturally placed after the BaseName. Overrides replace the BaseName and can optionally specify a priority, in which case the override with the highest priority will be used (if no priorities are specified, it's up to subscription order).
A bunch of existing systems that renamed entities have been modified to use RenamerSystem instead. I believe I've covered all of the uses of MetaDataSystem.SetEntityName that don't run immediately upon spawning, but let me know if I missed any.
This PR also includes ModifyWearerNameComponent/System, but doesn't use it on anything. I used it quite a bit in testing, and it nicely demonstrates the integration with InventoryRelayEvent. It's a simple component that can be added to clothing prototypes to make them add a prefix, postfix, or override to the wearer's name while equipped. For example, the lawyer's badge can add the "Attorney" title to a wearer's name with just a little yml:
- type: ModifyWearerName
modifierType: Prefix
text: lawyer-name-prefix
Media
Multiple modifiers surviving changes:
This may not make a lot of sense, but at least the name behaves properly:
ModifyWearerNameComponent:
https://github.com/space-wizards/space-station-14/assets/85356/e395a24a-5025-440a-b131-36357f881ff6
- [X] I have added screenshots/videos to this PR showcasing its changes ingame, or this PR does not require an ingame showcase
Breaking changes
Entity renaming should use the new RenamerSystem methods rather than MetaDataSystem.SetEntityName if the renaming can occur after initialization.
Changelog
Nah.