CatStation/Content.Server/NameIdentifier/NameIdentifierSystem.cs
Dmitry 25c5e59248
Upstream (#3172)
Signed-off-by: Prole <172158352+Prole0@users.noreply.github.com>
Co-authored-by: PJBot <pieterjan.briers+bot@gmail.com>
Co-authored-by: ScarKy0 <106310278+ScarKy0@users.noreply.github.com>
Co-authored-by: Samuka-C <47865393+Samuka-C@users.noreply.github.com>
Co-authored-by: ArtisticRoomba <145879011+ArtisticRoomba@users.noreply.github.com>
Co-authored-by: Partmedia <kevinz5000@gmail.com>
Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com>
Co-authored-by: themias <89101928+themias@users.noreply.github.com>
Co-authored-by: Victor Shen <71985089+Vexerot@users.noreply.github.com>
Co-authored-by: Ed <96445749+TheShuEd@users.noreply.github.com>
Co-authored-by: Milon <milonpl.git@proton.me>
Co-authored-by: Kirus59 <145689588+Kirus59@users.noreply.github.com>
Co-authored-by: Nemanja <98561806+EmoGarbage404@users.noreply.github.com>
Co-authored-by: Stomf <5dorkydorks@gmail.com>
Co-authored-by: drakewill-CRL <46307022+drakewill-CRL@users.noreply.github.com>
Co-authored-by: PraxisMapper <praxismapper@gmail.com>
Co-authored-by: EmoGarbage404 <retron404@gmail.com>
Co-authored-by: lzk <124214523+lzk228@users.noreply.github.com>
Co-authored-by: Princess Cheeseballs <66055347+Pronana@users.noreply.github.com>
Co-authored-by: IProduceWidgets <107586145+IProduceWidgets@users.noreply.github.com>
Co-authored-by: TytosB <54259736+TytosB@users.noreply.github.com>
Co-authored-by: abadaba695 <spacestation13thingy@gmail.com>
Co-authored-by: kosticia <kosticia46@gmail.com>
Co-authored-by: Thinbug <101073555+Thinbug0@users.noreply.github.com>
Co-authored-by: pathetic meowmeow <uhhadd@gmail.com>
Co-authored-by: SlamBamActionman <83650252+SlamBamActionman@users.noreply.github.com>
Co-authored-by: Boaz1111 <149967078+Boaz1111@users.noreply.github.com>
Co-authored-by: ActiveMammmoth <140334666+ActiveMammmoth@users.noreply.github.com>
Co-authored-by: Myra <vasilis@pikachu.systems>
Co-authored-by: Whatstone <166147148+whatston3@users.noreply.github.com>
Co-authored-by: Pieter-Jan Briers <pieterjan.briers+git@gmail.com>
Co-authored-by: K-Dynamic <20566341+K-Dynamic@users.noreply.github.com>
Co-authored-by: Gentleman-Bird <dcgreen406@gmail.com>
Co-authored-by: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com>
Co-authored-by: BIGZi0348 <svalker0348@gmail.com>
Co-authored-by: LaCumbiaDelCoronavirus <90893484+LaCumbiaDelCoronavirus@users.noreply.github.com>
Co-authored-by: imatsoup <93290208+imatsoup@users.noreply.github.com>
Co-authored-by: Matthew Herber <32679887+happyrobot33@users.noreply.github.com>
Co-authored-by: Ertanic <36124833+Ertanic@users.noreply.github.com>
Co-authored-by: MissKay1994 <15877268+MissKay1994@users.noreply.github.com>
Co-authored-by: Errant <35878406+Errant-4@users.noreply.github.com>
Co-authored-by: eoineoineoin <helloworld@eoinrul.es>
Co-authored-by: Tiniest Shark <head.rebel@yahoo.com>
Co-authored-by: nikitosych <boriszyn@gmail.com>
Co-authored-by: Tayrtahn <tayrtahn@gmail.com>
Co-authored-by: Perry Fraser <perryprog@users.noreply.github.com>
Co-authored-by: YoungThug <ramialanbagy@gmail.com>
Co-authored-by: beck-thompson <107373427+beck-thompson@users.noreply.github.com>
Co-authored-by: metalgearsloth <comedian_vs_clown@hotmail.com>
Co-authored-by: Southbridge <7013162+southbridge-fur@users.noreply.github.com>
Co-authored-by: Vladislav Suchkov <20380250+murolem@users.noreply.github.com>
Co-authored-by: Prole <172158352+Prole0@users.noreply.github.com>
Co-authored-by: Unkn0wn_Gh0st <shadowstalkermll@gmail.com>
Co-authored-by: 3nderall <101940324+3nderall@users.noreply.github.com>
Co-authored-by: Radezolid <snappednexus@gmail.com>
Co-authored-by: J <billsmith116@gmail.com>
Co-authored-by: Ghagliiarghii <68826635+Ghagliiarghii@users.noreply.github.com>
Co-authored-by: chromiumboy <50505512+chromiumboy@users.noreply.github.com>
Co-authored-by: youtissoum <51883137+youtissoum@users.noreply.github.com>
Co-authored-by: Minemoder5000 <minemoder50000@gmail.com>
Co-authored-by: Spanky <scott@wearejacob.com>
Co-authored-by: Spessmann <156740760+Spessmann@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: brainfood1183 <113240905+brainfood1183@users.noreply.github.com>
Co-authored-by: Deerstop <edainturner@gmail.com>
Co-authored-by: B_Kirill <153602297+B-Kirill@users.noreply.github.com>
Co-authored-by: archee1 <archee3@hotmail.co.uk>
Co-authored-by: Cojoke <83733158+Cojoke-dot@users.noreply.github.com>
Co-authored-by: Quantum-cross <7065792+Quantum-cross@users.noreply.github.com>
Co-authored-by: poklj <compgeek223@gmail.com>
Co-authored-by: Krunklehorn <42424291+Krunklehorn@users.noreply.github.com>
Co-authored-by: OnyxTheBrave <131422822+OnyxTheBrave@users.noreply.github.com>
Co-authored-by: UpAndLeaves <92269094+Alpha-Two@users.noreply.github.com>
Co-authored-by: Flareguy <78941145+Flareguy@users.noreply.github.com>
Co-authored-by: Zalycon <84675130+Zalycon@users.noreply.github.com>
Co-authored-by: deltanedas <39013340+deltanedas@users.noreply.github.com>
Co-authored-by: Verm <32827189+Vermidia@users.noreply.github.com>
Co-authored-by: nikthechampiongr <32041239+nikthechampiongr@users.noreply.github.com>
Co-authored-by: ScarKy0 <scarky0@onet.eu>
Co-authored-by: Dmitry <57028746+dimm00n@users.noreply.github.com>
2025-05-24 11:00:17 +03:00

207 lines
6.7 KiB
C#

using Content.Shared.GameTicking;
using Content.Shared.NameIdentifier;
using Content.Shared.NameModifier.EntitySystems;
using Robust.Shared.Collections;
using Robust.Shared.Prototypes;
using Robust.Shared.Random;
namespace Content.Server.NameIdentifier;
/// <summary>
/// Handles unique name identifiers for entities e.g. `monkey (MK-912)`
/// </summary>
public sealed class NameIdentifierSystem : EntitySystem
{
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
[Dependency] private readonly IRobustRandom _robustRandom = default!;
[Dependency] private readonly NameModifierSystem _nameModifier = default!;
/// <summary>
/// Free IDs available per <see cref="NameIdentifierGroupPrototype"/>.
/// </summary>
[ViewVariables]
public readonly Dictionary<string, List<int>> CurrentIds = new();
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<NameIdentifierComponent, MapInitEvent>(OnMapInit);
SubscribeLocalEvent<NameIdentifierComponent, ComponentShutdown>(OnComponentShutdown);
SubscribeLocalEvent<NameIdentifierComponent, RefreshNameModifiersEvent>(OnRefreshNameModifiers);
SubscribeLocalEvent<RoundRestartCleanupEvent>(CleanupIds);
SubscribeLocalEvent<PrototypesReloadedEventArgs>(OnReloadPrototypes);
InitialSetupPrototypes();
}
private void OnComponentShutdown(EntityUid uid, NameIdentifierComponent component, ComponentShutdown args)
{
if (CurrentIds.TryGetValue(component.Group, out var ids))
{
// Avoid inserting the value right back at the end or shuffling in place:
// just pick a random spot to put it and then move that one to the end.
var randomIndex = _robustRandom.Next(ids.Count);
var random = ids[randomIndex];
ids[randomIndex] = component.Identifier;
ids.Add(random);
}
_nameModifier.RefreshNameModifiers(uid);
}
/// <summary>
/// Generates a new unique name/suffix for a given entity and adds it to <see cref="CurrentIds"/>
/// but does not set the entity's name.
/// </summary>
public string GenerateUniqueName(EntityUid uid, ProtoId<NameIdentifierGroupPrototype> proto, out int randomVal)
{
return GenerateUniqueName(uid, _prototypeManager.Index(proto), out randomVal);
}
/// <summary>
/// Generates a new unique name/suffix for a given entity and adds it to <see cref="CurrentIds"/>
/// but does not set the entity's name.
/// </summary>
public string GenerateUniqueName(EntityUid uid, NameIdentifierGroupPrototype proto, out int randomVal)
{
randomVal = 0;
var entityName = Name(uid);
if (!CurrentIds.TryGetValue(proto.ID, out var set))
return entityName;
if (set.Count == 0)
{
// Oh jeez. We're outta numbers.
return entityName;
}
randomVal = set[^1];
set.RemoveAt(set.Count - 1);
return proto.Prefix is not null
? $"{proto.Prefix}-{randomVal}"
: $"{randomVal}";
}
private void OnMapInit(EntityUid uid, NameIdentifierComponent component, MapInitEvent args)
{
if (!_prototypeManager.TryIndex<NameIdentifierGroupPrototype>(component.Group, out var group))
return;
int id;
string uniqueName;
// If it has an existing valid identifier then use that, otherwise generate a new one.
if (component.Identifier != -1 &&
CurrentIds.TryGetValue(component.Group, out var ids) &&
ids.Remove(component.Identifier))
{
id = component.Identifier;
uniqueName = group.Prefix is not null
? $"{group.Prefix}-{id}"
: $"{id}";
}
else
{
uniqueName = GenerateUniqueName(uid, group, out id);
component.Identifier = id;
}
component.FullIdentifier = group.FullName
? uniqueName
: $"({uniqueName})";
Dirty(uid, component);
_nameModifier.RefreshNameModifiers(uid);
}
private void OnRefreshNameModifiers(Entity<NameIdentifierComponent> ent, ref RefreshNameModifiersEvent args)
{
// Don't apply the modifier if the component is being removed
if (ent.Comp.LifeStage > ComponentLifeStage.Running)
return;
if (!_prototypeManager.TryIndex<NameIdentifierGroupPrototype>(ent.Comp.Group, out var group))
return;
var format = group.FullName ? "name-identifier-format-full" : "name-identifier-format-append";
// We apply the modifier with a low priority to keep it near the base name
// "Beep (Si-4562) the zombie" instead of "Beep the zombie (Si-4562)"
args.AddModifier(format, -10, ("identifier", ent.Comp.FullIdentifier));
}
private void InitialSetupPrototypes()
{
EnsureIds();
}
private void FillGroup(NameIdentifierGroupPrototype proto, List<int> values)
{
values.Clear();
for (var i = proto.MinValue; i < proto.MaxValue; i++)
{
values.Add(i);
}
_robustRandom.Shuffle(values);
}
private List<int> GetOrCreateIdList(NameIdentifierGroupPrototype proto)
{
if (!CurrentIds.TryGetValue(proto.ID, out var ids))
{
ids = new List<int>(proto.MaxValue - proto.MinValue);
CurrentIds.Add(proto.ID, ids);
}
return ids;
}
private void EnsureIds()
{
foreach (var proto in _prototypeManager.EnumeratePrototypes<NameIdentifierGroupPrototype>())
{
var ids = GetOrCreateIdList(proto);
FillGroup(proto, ids);
}
}
private void OnReloadPrototypes(PrototypesReloadedEventArgs ev)
{
if (!ev.ByType.TryGetValue(typeof(NameIdentifierGroupPrototype), out var set))
return;
var toRemove = new ValueList<string>();
foreach (var proto in CurrentIds.Keys)
{
if (!_prototypeManager.HasIndex<NameIdentifierGroupPrototype>(proto))
{
toRemove.Add(proto);
}
}
foreach (var proto in toRemove)
{
CurrentIds.Remove(proto);
}
foreach (var proto in set.Modified.Values)
{
var name_proto = (NameIdentifierGroupPrototype) proto;
// Only bother adding new ones.
if (CurrentIds.ContainsKey(proto.ID))
continue;
var ids = GetOrCreateIdList(name_proto);
FillGroup(name_proto, ids);
}
}
private void CleanupIds(RoundRestartCleanupEvent ev)
{
EnsureIds();
}
}