Skip to content
This repository was archived by the owner on Dec 23, 2025. It is now read-only.

Commit b1fb01f

Browse files
Stable merge (space-wizards#38822)
2 parents b2866de + a03c35a commit b1fb01f

29 files changed

Lines changed: 190 additions & 171 deletions

File tree

Content.Client/Instruments/MidiParser/MidiParser.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,8 @@ public static bool TryGetMidiTracks(
102102
// 0x03 is TrackName,
103103
// 0x04 is InstrumentName
104104

105+
// This string can potentially contain control characters, including 0x00 which can cause problems if it ends up in database entries via admin logs
106+
// we sanitize TrackName and InstrumentName after they have been send to the server
105107
var text = Encoding.ASCII.GetString(metaData, 0, (int)metaLength);
106108
switch (metaType)
107109
{

Content.Server/Instruments/InstrumentSystem.cs

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,15 @@ private void OnMidiSetChannels(InstrumentSetChannelsEvent msg, EntitySessionEven
156156
return;
157157
}
158158

159+
160+
foreach (var t in msg.Tracks)
161+
{
162+
// Remove any control characters that may be part of the midi file so they don't end up in the admin logs.
163+
t?.SanitizeFields();
164+
// Truncate any track names too long.
165+
t?.TruncateFields(_cfg.GetCVar(CCVars.MidiMaxChannelNameLength));
166+
}
167+
159168
var tracksString = string.Join("\n",
160169
msg.Tracks
161170
.Where(t => t != null)
@@ -166,12 +175,6 @@ private void OnMidiSetChannels(InstrumentSetChannelsEvent msg, EntitySessionEven
166175
LogImpact.Low,
167176
$"{ToPrettyString(args.SenderSession.AttachedEntity)} set the midi channels for {ToPrettyString(uid)} to {tracksString}");
168177

169-
// Truncate any track names too long.
170-
foreach (var t in msg.Tracks)
171-
{
172-
t?.TruncateFields(_cfg.GetCVar(CCVars.MidiMaxChannelNameLength));
173-
}
174-
175178
activeInstrument.Tracks = msg.Tracks;
176179

177180
Dirty(uid, activeInstrument);

Content.Server/NameIdentifier/NameIdentifierSystem.cs

Lines changed: 30 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ public sealed class NameIdentifierSystem : EntitySystem
2020
/// Free IDs available per <see cref="NameIdentifierGroupPrototype"/>.
2121
/// </summary>
2222
[ViewVariables]
23-
public readonly Dictionary<string, List<int>> CurrentIds = new();
23+
public readonly Dictionary<string, List<int>> CurrentIds = [];
2424

2525
public override void Initialize()
2626
{
@@ -35,18 +35,22 @@ public override void Initialize()
3535
InitialSetupPrototypes();
3636
}
3737

38-
private void OnComponentShutdown(EntityUid uid, NameIdentifierComponent component, ComponentShutdown args)
38+
private void OnComponentShutdown(Entity<NameIdentifierComponent> ent, ref ComponentShutdown args)
3939
{
40-
if (CurrentIds.TryGetValue(component.Group, out var ids))
40+
if (ent.Comp.Group is null)
41+
return;
42+
43+
if (CurrentIds.TryGetValue(ent.Comp.Group, out var ids) && ids.Count > 0)
4144
{
4245
// Avoid inserting the value right back at the end or shuffling in place:
4346
// just pick a random spot to put it and then move that one to the end.
4447
var randomIndex = _robustRandom.Next(ids.Count);
4548
var random = ids[randomIndex];
46-
ids[randomIndex] = component.Identifier;
49+
ids[randomIndex] = ent.Comp.Identifier;
4750
ids.Add(random);
4851
}
49-
_nameModifier.RefreshNameModifiers(uid);
52+
53+
_nameModifier.RefreshNameModifiers(ent.Owner);
5054
}
5155

5256
/// <summary>
@@ -83,46 +87,53 @@ public string GenerateUniqueName(EntityUid uid, NameIdentifierGroupPrototype pro
8387
: $"{randomVal}";
8488
}
8589

86-
private void OnMapInit(EntityUid uid, NameIdentifierComponent component, MapInitEvent args)
90+
private void OnMapInit(Entity<NameIdentifierComponent> ent, ref MapInitEvent args)
8791
{
88-
if (!_prototypeManager.TryIndex<NameIdentifierGroupPrototype>(component.Group, out var group))
92+
if (ent.Comp.Group is null)
93+
return;
94+
95+
if (!_prototypeManager.TryIndex(ent.Comp.Group, out var group))
8996
return;
9097

9198
int id;
9299
string uniqueName;
93100

94101
// If it has an existing valid identifier then use that, otherwise generate a new one.
95-
if (component.Identifier != -1 &&
96-
CurrentIds.TryGetValue(component.Group, out var ids) &&
97-
ids.Remove(component.Identifier))
102+
if (ent.Comp.Identifier != -1 &&
103+
CurrentIds.TryGetValue(ent.Comp.Group, out var ids) &&
104+
ids.Remove(ent.Comp.Identifier))
98105
{
99-
id = component.Identifier;
106+
id = ent.Comp.Identifier;
100107
uniqueName = group.Prefix is not null
101108
? $"{group.Prefix}-{id}"
102109
: $"{id}";
103110
}
104111
else
105112
{
106-
uniqueName = GenerateUniqueName(uid, group, out id);
107-
component.Identifier = id;
113+
uniqueName = GenerateUniqueName(ent, group, out id);
114+
ent.Comp.Identifier = id;
108115
}
109116

110-
component.FullIdentifier = group.FullName
117+
ent.Comp.FullIdentifier = group.FullName
111118
? uniqueName
112119
: $"({uniqueName})";
113120

114-
Dirty(uid, component);
115-
_nameModifier.RefreshNameModifiers(uid);
121+
Dirty(ent);
122+
_nameModifier.RefreshNameModifiers(ent.Owner);
116123
}
117124

118125
private void OnRefreshNameModifiers(Entity<NameIdentifierComponent> ent, ref RefreshNameModifiersEvent args)
119126
{
127+
if (ent.Comp.Group is null)
128+
return;
129+
120130
// Don't apply the modifier if the component is being removed
121131
if (ent.Comp.LifeStage > ComponentLifeStage.Running)
122132
return;
123133

124-
if (!_prototypeManager.TryIndex<NameIdentifierGroupPrototype>(ent.Comp.Group, out var group))
134+
if (!_prototypeManager.TryIndex(ent.Comp.Group, out var group))
125135
return;
136+
126137
var format = group.FullName ? "name-identifier-format-full" : "name-identifier-format-append";
127138
// We apply the modifier with a low priority to keep it near the base name
128139
// "Beep (Si-4562) the zombie" instead of "Beep the zombie (Si-4562)"
@@ -188,13 +199,13 @@ private void OnReloadPrototypes(PrototypesReloadedEventArgs ev)
188199

189200
foreach (var proto in set.Modified.Values)
190201
{
191-
var name_proto = (NameIdentifierGroupPrototype) proto;
202+
var name_proto = (NameIdentifierGroupPrototype)proto;
192203

193204
// Only bother adding new ones.
194205
if (CurrentIds.ContainsKey(proto.ID))
195206
continue;
196207

197-
var ids = GetOrCreateIdList(name_proto);
208+
var ids = GetOrCreateIdList(name_proto);
198209
FillGroup(name_proto, ids);
199210
}
200211
}

Content.Shared/Instruments/SharedInstrumentComponent.cs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System.Collections;
2+
using System.Text;
23
using Robust.Shared.Audio.Midi;
34
using Robust.Shared.GameStates;
45
using Robust.Shared.Serialization;
@@ -207,6 +208,18 @@ public void TruncateFields(int limit)
207208
ProgramName = Truncate(ProgramName, limit);
208209
}
209210

211+
public void SanitizeFields()
212+
{
213+
if (InstrumentName != null)
214+
InstrumentName = Sanitize(InstrumentName);
215+
216+
if (TrackName != null)
217+
TrackName = Sanitize(TrackName);
218+
219+
if (ProgramName != null)
220+
ProgramName = Sanitize(ProgramName);
221+
}
222+
210223
private const string Postfix = "…";
211224
// TODO: Make a general method to use in RT? idk if we have that.
212225
private string Truncate(string input, int limit)
@@ -218,4 +231,17 @@ private string Truncate(string input, int limit)
218231

219232
return input.Substring(0, truncatedLength) + Postfix;
220233
}
234+
235+
private static string Sanitize(string input)
236+
{
237+
var sanitized = new StringBuilder(input.Length);
238+
239+
foreach (char c in input)
240+
{
241+
if (!char.IsControl(c) && c <= 127) // no control characters, only ASCII
242+
sanitized.Append(c);
243+
}
244+
245+
return sanitized.ToString();
246+
}
221247
}
Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
using Robust.Shared.GameStates;
2-
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
2+
using Robust.Shared.Prototypes;
33

44
namespace Content.Shared.NameIdentifier;
55

@@ -9,18 +9,18 @@ namespace Content.Shared.NameIdentifier;
99
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
1010
public sealed partial class NameIdentifierComponent : Component
1111
{
12-
[DataField("group", required: true, customTypeSerializer:typeof(PrototypeIdSerializer<NameIdentifierGroupPrototype>))]
13-
public string Group = string.Empty;
12+
[DataField]
13+
public ProtoId<NameIdentifierGroupPrototype>? Group;
1414

1515
/// <summary>
1616
/// The randomly generated ID for this entity.
1717
/// </summary>
18-
[DataField("identifier"), ViewVariables(VVAccess.ReadWrite), AutoNetworkedField]
18+
[DataField, AutoNetworkedField]
1919
public int Identifier = -1;
2020

2121
/// <summary>
2222
/// The full name identifier for this entity.
2323
/// </summary>
24-
[DataField("fullIdentifier"), ViewVariables(VVAccess.ReadWrite), AutoNetworkedField]
24+
[DataField, AutoNetworkedField]
2525
public string FullIdentifier = string.Empty;
2626
}

Resources/Changelog/Changelog.yml

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3565,15 +3565,6 @@
35653565
id: 8704
35663566
time: '2025-06-21T22:23:39.0000000+00:00'
35673567
url: https://github.com/space-wizards/space-station-14/pull/38486
3568-
- author: keronshb
3569-
changes:
3570-
- message: Added the Hypereutactic Blade back to the Traitor Uplink
3571-
type: Add
3572-
- message: Added the Hypereutatic Blade to the Nukie uplink
3573-
type: Add
3574-
id: 8705
3575-
time: '2025-06-22T16:50:59.0000000+00:00'
3576-
url: https://github.com/space-wizards/space-station-14/pull/37182
35773568
- author: Cojoke-dot
35783569
changes:
35793570
- message: Pacifists can now use the Staff of Healing

Resources/Locale/en-US/datasets/names/scurret_first.ftl

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,19 @@
1+
# Scurrets from Planet Wawa have two parts to their name - a 'chosen' and 'qualitative' name.
2+
3+
# The chosen name is picked by the scurret themselves,
4+
# encompassing a trait or value they hold themselves
5+
# to or have a high value for. Scurrets sometimes change this
6+
# name to denote an important moment in their life.
7+
8+
# It appears to be common for scurret sets to share the same
9+
# chosen name, with the gaining of a pup's own chosen name
10+
# signalling their transition to adulthood in the community.
11+
12+
# Given the scurret language is untranslated, these names are
13+
# usually guessed via charades or Pictionary.
14+
15+
# When all else fails, to NT and her crews, Wa is as good a name as any.
16+
117
names-scurret-first-dataset-1 = Wa
218
names-scurret-first-dataset-2 = Calm
319
names-scurret-first-dataset-3 = Contented
@@ -34,3 +50,18 @@ names-scurret-first-dataset-33 = Wise
3450
names-scurret-first-dataset-34 = Alert
3551
names-scurret-first-dataset-35 = Uplifting
3652
names-scurret-first-dataset-36 = Considerate
53+
names-scurret-first-dataset-37 = Surviving
54+
names-scurret-first-dataset-38 = Meditating
55+
names-scurret-first-dataset-39 = Hunting
56+
names-scurret-first-dataset-40 = Watching
57+
names-scurret-first-dataset-41 = Resting
58+
names-scurret-first-dataset-42 = Delivering
59+
names-scurret-first-dataset-43 = Swimming
60+
names-scurret-first-dataset-44 = Swinging
61+
names-scurret-first-dataset-45 = Exploding
62+
names-scurret-first-dataset-46 = Romancing
63+
names-scurret-first-dataset-47 = Far-Seeing
64+
names-scurret-first-dataset-48 = Loyal
65+
names-scurret-first-dataset-49 = Inquisitive
66+
# After consulting with lawyers, NT added this one to the dictionary.
67+
names-scurret-first-dataset-50 = Legally Distinct

Resources/Locale/en-US/datasets/names/scurret_last.ftl

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,19 @@
1+
# Scurrets from Planet Wawa have two parts to their name - a 'chosen' and 'qualitative' name.
2+
3+
# The qualitative name is usually related to an important feature
4+
# of Wawa's wetland habitats that the scurret is associated with
5+
# by their community.
6+
7+
# Scurret pups, due to both their quantity and complete lack
8+
# of any survival instinct, lack a qualitative name entirely.
9+
# Researchers believe their parents simply give them a number.
10+
11+
# Given that the scurret language is untranslated, these names are
12+
# usually deduced via the showing of photographs, annoyed and
13+
# repeated pointing at nearby objects, or games of Pictionary.
14+
15+
# When all else fails, to NT and her crews, Wa is as good a name as any.
16+
117
names-scurret-last-dataset-1 = Wa
218
names-scurret-last-dataset-2 = Trees
319
names-scurret-last-dataset-3 = Plants
@@ -6,12 +22,12 @@ names-scurret-last-dataset-5 = Rivers
622
names-scurret-last-dataset-6 = Groves
723
names-scurret-last-dataset-7 = Lakes
824
names-scurret-last-dataset-8 = Marshes
9-
names-scurret-last-dataset-9 = Spring
25+
names-scurret-last-dataset-9 = Springs
1026
names-scurret-last-dataset-10 = Reeds
1127
names-scurret-last-dataset-11 = Sunshine
1228
names-scurret-last-dataset-12 = Rain
1329
names-scurret-last-dataset-13 = Clouds
14-
names-scurret-last-dataset-14 = Snowfall
30+
names-scurret-last-dataset-14 = Snowfalls
1531
names-scurret-last-dataset-15 = Stones
1632
names-scurret-last-dataset-16 = Pebbles
1733
names-scurret-last-dataset-17 = Fishes
@@ -25,12 +41,28 @@ names-scurret-last-dataset-24 = Alders
2541
names-scurret-last-dataset-25 = Birches
2642
names-scurret-last-dataset-26 = Poplars
2743
names-scurret-last-dataset-27 = Marigolds
28-
names-scurret-last-dataset-28 = Robins
44+
names-scurret-last-dataset-28 = Rowans
2945
names-scurret-last-dataset-29 = Orchids
3046
names-scurret-last-dataset-30 = Rushes
3147
names-scurret-last-dataset-31 = Lillies
3248
names-scurret-last-dataset-32 = Violets
3349
names-scurret-last-dataset-33 = Maples
3450
names-scurret-last-dataset-34 = Oaks
3551
names-scurret-last-dataset-35 = Hazels
52+
# AND SIR GIDEON OFNIR
3653
names-scurret-last-dataset-36 = the All-Knowing
54+
names-scurret-last-dataset-37 = Tarns
55+
names-scurret-last-dataset-38 = Waters
56+
names-scurret-last-dataset-39 = Reservoirs
57+
names-scurret-last-dataset-40 = Dams
58+
names-scurret-last-dataset-41 = Moors
59+
names-scurret-last-dataset-42 = Fens
60+
names-scurret-last-dataset-43 = Temples
61+
names-scurret-last-dataset-44 = Hills
62+
names-scurret-last-dataset-45 = Copses
63+
names-scurret-last-dataset-46 = Fields
64+
names-scurret-last-dataset-47 = Ancestors
65+
names-scurret-last-dataset-48 = Forests
66+
names-scurret-last-dataset-49 = Secrets
67+
# Nobody's quite sure how this one is in the dictionary.
68+
names-scurret-last-dataset-50 = Space Ferret

Resources/Locale/en-US/store/uplink-catalog.ftl

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,6 @@ uplink-esword-double-desc = A much more expensive counter part to the normal ene
2323
uplink-hypereutactic-blade-name = Hypereutactic Blade
2424
uplink-hypereutactic-blade-desc = A gigantic energy sword with power that matches its looks. Requires two hands. Slow and unwieldy, yet pretty adept at reflecting. Previously made infamous by an operative wearing a joy mask. You wouldn't want to see this coming at you down the hall!
2525
26-
uplink-hypereutatic-blade-name = Hypereutatic Blade
27-
uplink-hypereutatic-blade-desc = A gigantic off-brand energy sword. Requires two hands. Slow and unwieldy, can reflect decently. Often mistaken for the Hypereutactic Blade.
28-
2926
uplink-edagger-name = Energy Dagger
3027
uplink-edagger-desc = A small energy blade conveniently disguised in the form of a pen.
3128

Resources/Prototypes/Catalog/Fills/Lockers/dressers.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,6 @@
5050
- type: StorageFill
5151
contents:
5252
- id: ClothingHeadHatHopcap
53-
- id: ClothingHeadHatBeretHop
5453
- id: ClothingOuterWinterHoP
5554
- id: ClothingEyesGlasses
5655
- id: ClothingNeckCloakHop

0 commit comments

Comments
 (0)