Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using Content.Shared._WL.Records; // WL-Records
using Content.Shared.Access.Systems;
using Content.Shared.CriminalRecords;
using Content.Shared.CriminalRecords.Components;
Expand Down Expand Up @@ -44,6 +45,10 @@ protected override void Open()
_window.OnHistoryUpdated += UpdateHistory;
_window.OnHistoryClosed += () => _historyWindow?.Close();
_window.OnClose += Close;
// WL-Records-start
_window.OnPrinted += key =>
SendMessage(new PrintStationRecord(key));
// WL-Records-end

_historyWindow = new(comp.MaxStringLength);
_historyWindow.OnAddHistory += line => SendMessage(new CriminalRecordAddHistory(line));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@
StyleClasses="LabelBig" />
<BoxContainer Orientation="Horizontal"
Margin="0 0 0 5">
<Label Text="{Loc 'crew-monitoring-user-interface-job'}"
<Label Text="{Loc 'crew-monitoring-ui-job-label'}"
FontColorOverride="DarkGray" />
<TextureRect Name="PersonJobIcon"
TextureScale="2 2"
Expand Down Expand Up @@ -115,11 +115,12 @@
<BoxContainer Orientation="Vertical"
VerticalExpand="True"
HorizontalExpand="True">
<ScrollContainer VerticalExpand="True" HorizontalExpand="True">
<ScrollContainer VerticalExpand="True" HScrollEnabled="False">
<RichTextLabel Name="SecurityRecord"
Margin="5"
HorizontalExpand="True"/>
</ScrollContainer>
<Button Name="PrintButton" Text="{Loc 'records-print-button'}" MinWidth="200"/>
</BoxContainer>
</TabContainer>
<!-- WL-Records-Edit-End -->
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
using Content.Client.UserInterface.Controls;
using Content.Shared._WL.Languages;
using Content.Shared._WL.Records; // WL-Records-Start
using Content.Shared.Access.Systems;
using Content.Shared.Administration;
using Content.Shared.CriminalRecords;
using Content.Shared.Dataset;
using Content.Shared.Humanoid.Prototypes; // WL-Records
using Content.Shared.Random.Helpers;
using Content.Shared.Security;
using Content.Shared.StationRecords;
using Content.Shared.StatusIcon;
using Robust.Client.AutoGenerated;
using Robust.Client.GameObjects;
using Robust.Client.Player;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.XAML;
Expand All @@ -15,8 +20,6 @@
using Robust.Shared.Utility;
using System.Linq;
using System.Numerics;
using Content.Shared.StatusIcon;
using Robust.Client.GameObjects;

namespace Content.Client.CriminalRecords;

Expand All @@ -42,6 +45,7 @@ public sealed partial class CriminalRecordsConsoleWindow : FancyWindow
public Action<CriminalRecord, bool, bool>? OnHistoryUpdated;
public Action? OnHistoryClosed;
public Action<SecurityStatus, string>? OnDialogConfirmed;
public Action<uint>? OnPrinted; // WL-Records

public Action<SecurityStatus>? OnStatusFilterPressed;
private uint _maxLength;
Expand Down Expand Up @@ -148,6 +152,15 @@ public CriminalRecordsConsoleWindow(EntityUid console, uint maxLength, IPlayerMa
if (_selectedRecord is { } record)
OnHistoryUpdated?.Invoke(record, _access, true);
};

// WL-Records-start
PrintButton.OnPressed += _ =>
{
PrintButton.Disabled = true;
if (_selectedKey != null)
OnPrinted?.Invoke(_selectedKey.Value);
};
// WL-Records-end
}

public void StatusFilterPressed(SecurityStatus statusSelected)
Expand Down Expand Up @@ -175,6 +188,8 @@ public void UpdateState(CriminalRecordsConsoleState state)
_currentCrewListFilter = state.FilterStatus;
}

PrintButton.Disabled = !state.CanPrintRecords; // WL-Records

_selectedKey = state.SelectedKey;
FilterType.SelectId((int)_currentFilterType);
CrewListFilter.SelectId((int)_currentCrewListFilter);
Expand Down Expand Up @@ -266,9 +281,26 @@ private void PopulateRecordContainer(GeneralStationRecord stationRecord, Crimina
}

// WL-Records-Start
SecurityRecord.Text = !string.IsNullOrEmpty(stationRecord.SecurityRecord)
? stationRecord.SecurityRecord
: Loc.GetString("criminal-records-console-no-security-record");
var confederation = string.Empty;

if (_proto.TryIndex<ConfederationRecordsPrototype>(stationRecord.Confederation, out var protoConf))
confederation = Loc.GetString(protoConf.Name);
else
confederation = Loc.GetString("generic-not-available-shorthand");

SecurityRecord.Text = $"""
{Loc.GetString("records-full-name-edit")} {(!string.IsNullOrEmpty(stationRecord.Fullname)
? stationRecord.Fullname : stationRecord.Name)}
{Loc.GetString("records-date-of-birth-edit")} {(!string.IsNullOrEmpty(stationRecord.DateOfBirth)
? stationRecord.DateOfBirth : Loc.GetString("generic-not-available-shorthand"))}
{Loc.GetString("records-confederation-edit")} {confederation}
{Loc.GetString("records-country-edit")} {(!string.IsNullOrEmpty(stationRecord.Country)
? stationRecord.Country : Loc.GetString("generic-not-available-shorthand"))}
{Loc.GetString("records-species")} {Loc.GetString(_proto.Index<SpeciesPrototype>(stationRecord.Species).Name)}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

_proto.Index<SpeciesPrototype> can throw if record.Species is invalid.

The confederation lookup defensively uses TryIndex, but the species lookup uses Index directly, which will throw if record.Species contains an invalid prototype ID. This is inconsistent with the defensive pattern used a few lines above.

🛡️ Proposed fix — use TryIndex for species lookup
-                {Loc.GetString("records-species")} {Loc.GetString(_proto.Index<SpeciesPrototype>(stationRecord.Species).Name)}
+                {Loc.GetString("records-species")} {(_proto.TryIndex<SpeciesPrototype>(stationRecord.Species, out var specProto)
+                ? Loc.GetString(specProto.Name) : Loc.GetString("generic-not-available-shorthand"))}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
{Loc.GetString("records-species")} {Loc.GetString(_proto.Index<SpeciesPrototype>(stationRecord.Species).Name)}
{Loc.GetString("records-species")} {(_proto.TryIndex<SpeciesPrototype>(stationRecord.Species, out var specProto)
? Loc.GetString(specProto.Name) : Loc.GetString("generic-not-available-shorthand"))}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Content.Client/CriminalRecords/CriminalRecordsConsoleWindow.xaml.cs` at line
299, The species prototype lookup uses
_proto.Index<SpeciesPrototype>(stationRecord.Species) which can throw for
invalid IDs; change it to use
_proto.TryIndex<SpeciesPrototype>(stationRecord.Species, out var speciesProto)
and use speciesProto?.Name (or fall back to stationRecord.Species or a localized
"Unknown" string via Loc.GetString) when composing the Loc.GetString call so the
UI no longer throws on bad prototype IDs; update the expression around
Loc.GetString("records-species") to use the TryIndex result accordingly.

{Loc.GetString("records-height", ("height", stationRecord.Height))}
{(!string.IsNullOrEmpty(stationRecord.SecurityRecord) ? stationRecord.SecurityRecord
: Loc.GetString("criminal-records-console-no-security-record"))}
""";
// WL-Records-End
}

Expand Down
103 changes: 102 additions & 1 deletion Content.Client/Lobby/UI/HumanoidProfileEditor.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
using Content.Client.Sprite;
using Content.Client.UserInterface.Systems.Guidebook;
using Content.Shared._WL.Skills; // WL-Skills
using Content.Shared._WL.Records; // WL-Records
using Content.Shared.CCVar;
using Content.Shared.Clothing;
using Content.Shared.Corvax.CCCVars;
Expand Down Expand Up @@ -41,7 +42,8 @@
using Robust.Shared.Utility;
using Direction = Robust.Shared.Maths.Direction;
using static Content.Client.Corvax.SponsorOnlyHelpers; // Corvax-Sponsors
using Content.Client.Corvax.TTS; // Corvax-TTS
using Content.Client.Corvax.TTS;
using Content.Client.Lathe.UI; // Corvax-TTS

namespace Content.Client.Lobby.UI
{
Expand Down Expand Up @@ -195,6 +197,15 @@ public sealed partial class HumanoidProfileEditor : BoxContainer
private TextEdit? _securityRecordEdit; // WL-Records
private TextEdit? _employmentRecordEdit; // WL-Records

private LineEdit? _generalRecordNameEdit; // WL-Records
private LineEdit? _generalRecordAgeEdit; // WL-Records
private LineEdit? _generalRecordCountryEdit; // WL-Records

private OptionButton? _confederationButton; // WL-Records


private List<ConfederationRecordsPrototype> _confederations = new(); // WL-Recordss
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Typo in comment: // WL-Recordss — double 's'.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Content.Client/Lobby/UI/HumanoidProfileEditor.xaml.cs` at line 207, The
inline comment trailing the private field _confederations contains a typo ("//
WL-Recordss"); update the comment on the field declaration for _confederations
(private List<ConfederationRecordsPrototype> _confederations = new();) to
correct the typo (e.g., "// WL-Records") or remove the comment if unnecessary so
the comment reads cleanly.


private SingleMarkingPicker _underwearPicker => CUnderwearPicker; // WL-Underwear
private SingleMarkingPicker _undershirtPicker => CUndershirtPicker; // WL-Underwear
private SingleMarkingPicker _socksPicker => CSocksPicker; // WL-Underwear
Expand Down Expand Up @@ -743,6 +754,12 @@ public HumanoidProfileEditor(
RefreshFlavorText();

RefreshRecords(); // WL-Records

//_confederationButton.OnItemSelected += args =>
//{

//};

RefreshVoiceTab(); // Corvax-TTS

#region Dummy
Expand Down Expand Up @@ -822,9 +839,37 @@ public void RefreshRecords()
_securityRecordEdit = _recordsTab.SecurityRecordInput;
_employmentRecordEdit = _recordsTab.EmploymentRecordInput;

_generalRecordNameEdit = _recordsTab.NameEdit;
_generalRecordAgeEdit = _recordsTab.AgeEdit;
_generalRecordCountryEdit = _recordsTab.CountryEdit;

_confederationButton = _recordsTab.ConfederationButton;

_recordsTab.OnMedicalRecordChanged += OnMedicalRecordChange;
_recordsTab.OnSecurityRecordChanged += OnSecurityRecordChange;
_recordsTab.OnEmploymentRecordChanged += OnEmploymentRecordChange;

_recordsTab.OnGeneralRecordNameChanged += OnGeneralRecordNameChanged;
_recordsTab.OnGeneralRecordAgeChanged += OnGeneralRecordDateOfBirthChanged;
_recordsTab.OnGeneralRecordCountryChanged += OnGeneralRecordCountryChanged;

_recordsTab.OnGeneralRecordConfederationChanged += SetConfederation;

_confederations.AddRange(_prototypeManager.EnumeratePrototypes<ConfederationRecordsPrototype>());

_confederations.Sort((a, b) => string.Compare(a.Name, b.Name, StringComparison.CurrentCultureIgnoreCase));

for (var i = 0; i < _confederations.Count; i++)
{
var name = Loc.GetString(_confederations[i].Name);

_recordsTab.ConfederationButton.AddItem(name, i);

if (_confederations[i].ID == "NoConfederation")
{
_recordsTab.ConfederationButton.SelectId(i);
}
}
}

private void OnMedicalRecordChange(string content)
Expand Down Expand Up @@ -853,6 +898,44 @@ private void OnEmploymentRecordChange(string content)
Profile = Profile.WithEmploymentRecord(content);
SetDirty();
}

private void OnGeneralRecordNameChanged(string content)
{
if (Profile is null)
return;

Profile = Profile.WithFullName(content);
SetDirty();
}
private void OnGeneralRecordDateOfBirthChanged(string content)
{
if (Profile is null)
return;

Profile = Profile.WithDateOfBirth(content);
SetDirty();
}
private void OnGeneralRecordCountryChanged(string content)
{
if (Profile is null)
return;

Profile = Profile.WithCountry(content);
SetDirty();
}
private void SetConfederation(OptionButton.ItemSelectedEventArgs args)
{
if (_confederationButton is null)
return;

if (Profile is null)
return;

_confederationButton.SelectId(args.Id);
Profile = Profile.WithConfederation(_confederations[args.Id].ID);
SetDirty();
}
Comment on lines +902 to +937
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

# First, let's understand the project structure
git ls-files | grep -E "\.(xaml|xaml\.cs)$" | head -20

Repository: corvax-team/ss14-wl

Length of output: 1256


🏁 Script executed:

# Find OptionButton definition
rg "class OptionButton" -A 10

Repository: corvax-team/ss14-wl

Length of output: 1104


🏁 Script executed:

# Look for SelectId method definition
rg "void SelectId|SelectId\(" -B 2 -A 5

Repository: corvax-team/ss14-wl

Length of output: 50375


🏁 Script executed:

# Search for OnItemSelected handler in the HumanoidProfileEditor file
rg "OnItemSelected|SetConfederation" Content.Client/Lobby/UI/HumanoidProfileEditor.xaml.cs -B 2 -A 5

Repository: corvax-team/ss14-wl

Length of output: 2389


🏁 Script executed:

# Find OptionButton class definition
rg "class OptionButton" -A 30 --type cs

Repository: corvax-team/ss14-wl

Length of output: 2175


🏁 Script executed:

# Search for SelectId method implementation
rg "void SelectId|SelectId\(" --type cs -B 2 -A 10 | head -100

Repository: corvax-team/ss14-wl

Length of output: 9087


🏁 Script executed:

# Look for OptionButton in the UI framework
find . -name "*.cs" -type f | xargs grep -l "class OptionButton" 2>/dev/null

Repository: corvax-team/ss14-wl

Length of output: 127


🏁 Script executed:

# Look for OptionButton usage to understand the Select vs SelectId pattern
rg "\.Select\(|\.SelectId\(" --type cs | head -50

Repository: corvax-team/ss14-wl

Length of output: 7466


🏁 Script executed:

# Check if there's a RobustToolbox or external reference
find . -name "*.csproj" -type f | head -5 | xargs grep -l "RobustToolbox\|OptionButton" 2>/dev/null

Repository: corvax-team/ss14-wl

Length of output: 256


🏁 Script executed:

# Look at the HumanoidProfileEditor file directly around the SetConfederation method
sed -n '890,935p' Content.Client/Lobby/UI/HumanoidProfileEditor.xaml.cs

Repository: corvax-team/ss14-wl

Length of output: 1285


🏁 Script executed:

# Check for bounds checking patterns in the codebase with _confederations
rg "_confederations\[" Content.Client/Lobby/UI/HumanoidProfileEditor.xaml.cs -B 3 -A 3

Repository: corvax-team/ss14-wl

Length of output: 713


🏁 Script executed:

# Check the .csproj file for RobustToolbox reference
cat Content.Client/Content.Client.csproj | grep -A 5 -B 5 "RobustToolbox\|OptionButton"

Repository: corvax-team/ss14-wl

Length of output: 1109


🏁 Script executed:

# Look for more context on how confederations is populated and used
rg "_confederations" Content.Client/Lobby/UI/HumanoidProfileEditor.xaml.cs -B 2 -A 2

Repository: corvax-team/ss14-wl

Length of output: 1087


🏁 Script executed:

# Check if there's any validation before indexing _confederations anywhere else in this file
rg "args.Id|args\.Id" Content.Client/Lobby/UI/HumanoidProfileEditor.xaml.cs -B 3 -A 3

Repository: corvax-team/ss14-wl

Length of output: 1673


🏁 Script executed:

# Search for OptionButton in RobustToolbox directory if it exists
find . -name "OptionButton.cs" -o -name "*OptionButton*" -type f 2>/dev/null | grep -v ".xaml\|StyleSheetlets"

Repository: corvax-team/ss14-wl

Length of output: 125


🏁 Script executed:

# Check if RobustToolbox is a submodule or external
ls -la RobustToolbox 2>/dev/null || echo "RobustToolbox not found as directory"

Repository: corvax-team/ss14-wl

Length of output: 175


🏁 Script executed:

# Look at other similar validation patterns in the codebase for args.Id
rg "args\.Id.*>=" --type cs -B 2 -A 2 | head -50

Repository: corvax-team/ss14-wl

Length of output: 45


🏁 Script executed:

# Check the Options.OnItemSelected pattern in the same file to see if there's validation
sed -n '700,750p' Content.Client/Lobby/UI/HumanoidProfileEditor.xaml.cs

Repository: corvax-team/ss14-wl

Length of output: 2081


🏁 Script executed:

# Look for bounds validation pattern with ItemSelectedEventArgs
rg "ItemSelectedEventArgs" --type cs -B 5 -A 8 | head -80

Repository: corvax-team/ss14-wl

Length of output: 6927


🏁 Script executed:

# Search for any error handling or validation of args.Id in handlers
rg "args\.Id.*<|args\.Id.*>=" --type cs

Repository: corvax-team/ss14-wl

Length of output: 45


🏁 Script executed:

# Check if there are any cases where handlers guard against invalid IDs
rg "if.*args\.Id|if.*args\.ButtonId" --type cs -B 2 -A 5 | head -60

Repository: corvax-team/ss14-wl

Length of output: 4621


Add bounds validation before accessing _confederations, but keep SelectId to maintain selection state sync.

The bounds check is good defensive programming: if ((uint) args.Id >= (uint) _confederations.Count) return; before indexing _confederations[args.Id]. However, removing SelectId is inconsistent with the same pattern used in other handlers in this file (e.g., SexButton, SpeciesButton, PreferenceUnavailableButton all call SelectId in their OnItemSelected handlers). The ubiquitous use of SelectId within item selection handlers throughout the codebase indicates it does not re-emit OnItemSelected—this pattern would be broken framework-wide if it did. Keep the SelectId call for proper UI state synchronization; just add the bounds check.

🤖 Prompt for AI Agents
In `@Content.Client/Lobby/UI/HumanoidProfileEditor.xaml.cs` around lines 895 -
930, Add a bounds check before indexing _confederations in SetConfederation to
avoid out-of-range access while retaining the UI sync call; specifically, in
SetConfederation check that args.Id is within _confederations (e.g., cast to
uint and compare against _confederations.Count) and return early if out of
range, but keep the existing _confederationButton.SelectId(args.Id) and the
Profile = Profile.WithConfederation(_confederations[args.Id]); call order intact
so selection state stays synchronized.


// WL-Records-End
// Corvax-TTS-Start
#region Voice
Expand Down Expand Up @@ -1909,6 +1992,24 @@ private void UpdateRecordsEdit()

if (_employmentRecordEdit != null)
_employmentRecordEdit.TextRope = new Rope.Leaf(Profile?.EmploymentRecord ?? "");

if (_generalRecordNameEdit != null)
_generalRecordNameEdit.Text = Profile?.FullName ?? "";

if (_generalRecordAgeEdit != null)
_generalRecordAgeEdit.Text = Profile?.DateOfBirth ?? "";

if (_generalRecordCountryEdit != null)
_generalRecordCountryEdit.Text = Profile?.Country ?? "";

if (_confederationButton != null)
for (var i = 0; i < _confederations.Count; i++)
{
if (Profile?.Confederation.Equals(_confederations[i].ID) == true)
{
_confederationButton.SelectId(i);
}
}
Comment on lines +1996 to +2012
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# First, let's find and examine the HumanoidProfileEditor.xaml.cs file
fd -t f "HumanoidProfileEditor.xaml.cs" | head -5

Repository: corvax-team/ss14-wl

Length of output: 116


🏁 Script executed:

#!/bin/bash
# Read the file around lines 1989-2006
wc -l Content.Client/Lobby/UI/HumanoidProfileEditor.xaml.cs
echo "---"
sed -n '1980,2020p' Content.Client/Lobby/UI/HumanoidProfileEditor.xaml.cs

Repository: corvax-team/ss14-wl

Length of output: 1642


🏁 Script executed:

#!/bin/bash
# Search for _confederations initialization and usage
echo "=== _confederations initialization ==="
rg "_confederations\s*=" Content.Client/Lobby/UI/HumanoidProfileEditor.xaml.cs -B 2 -A 2

echo -e "\n=== _confederationButton initialization ==="
rg "_confederationButton\s*=" Content.Client/Lobby/UI/HumanoidProfileEditor.xaml.cs -B 2 -A 2

echo -e "\n=== OptionButton class/type check ==="
rg "OptionButton" Content.Client/Lobby/UI/HumanoidProfileEditor.xaml.cs -B 1 -A 1 | head -30

Repository: corvax-team/ss14-wl

Length of output: 862


🏁 Script executed:

#!/bin/bash
# Look at the SetConfederation method and surrounding context
echo "=== SetConfederation method ==="
rg "SetConfederation" Content.Client/Lobby/UI/HumanoidProfileEditor.xaml.cs -B 2 -A 10

echo -e "\n=== OptionButton definition/API ==="
fd -t f "OptionButton" --extension cs | head -5

Repository: corvax-team/ss14-wl

Length of output: 1082


🏁 Script executed:

#!/bin/bash
# Find and examine OptionButton class
cat -n Content.Client/Stylesheets/Sheetlets/OptionButtonSheetlet.cs | head -100

Repository: corvax-team/ss14-wl

Length of output: 1442


🏁 Script executed:

#!/bin/bash
# Search for OptionButton class definition and methods
echo "=== Searching for OptionButton class ==="
rg "class OptionButton" --type cs

echo -e "\n=== Searching for SelectId method ==="
rg "SelectId\(" Content.Client/Lobby/UI/HumanoidProfileEditor.xaml.cs -B 1 -A 3

echo -e "\n=== Searching for OptionButton methods in codebase ==="
rg "\.OptionButton\?\." Content.Client/Lobby/UI/HumanoidProfileEditor.xaml.cs -o

Repository: corvax-team/ss14-wl

Length of output: 2312


🏁 Script executed:

#!/bin/bash
# Look at how other controls handle missing/no match scenarios
echo "=== UpdateGenders/UpdateSpecies patterns ==="
rg "UpdateGenders|UpdateSpecies|UpdateSex" Content.Client/Lobby/UI/HumanoidProfileEditor.xaml.cs -A 8 | head -60

echo -e "\n=== Profile class to check Confederation property ==="
fd -t f "Profile\\.cs" | head -3

Repository: corvax-team/ss14-wl

Length of output: 1650


🏁 Script executed:

#!/bin/bash
# Get the full UpdateSexControls method
echo "=== Full UpdateSexControls method ==="
rg "private void UpdateSexControls" Content.Client/Lobby/UI/HumanoidProfileEditor.xaml.cs -A 20

echo -e "\n=== Full UpdateGenderControls method ==="
rg "private void UpdateGenderControls" Content.Client/Lobby/UI/HumanoidProfileEditor.xaml.cs -A 15

echo -e "\n=== Check Confederation property in Profile ==="
rg "Confederation" Content.Shared/Preferences/HumanoidCharacterProfile.cs -B 2 -A 2

Repository: corvax-team/ss14-wl

Length of output: 3062


🏁 Script executed:

#!/bin/bash
# Search for how Clear() is used with option buttons
echo "=== Clear() usage with buttons ==="
rg "Button\.Clear\(\)" Content.Client/Lobby/UI/HumanoidProfileEditor.xaml.cs -B 2 -A 2

echo -e "\n=== Check if confederation can be empty in practice ==="
rg "Profile\.Confederation|WithConfederation" Content.Client/Lobby/UI/HumanoidProfileEditor.xaml.cs | head -20

Repository: corvax-team/ss14-wl

Length of output: 443


Reset confederation selection when profile value is empty or unmatched.

The current logic persists previous selection when Profile?.Confederation is empty (default string.Empty) or unmatched, which can mislead users. Calling _confederationButton.Clear() when no match is found would address this, following the established pattern in UpdateSexControls().

Note: The suggested diff in the original comment assumes index 0 is a "None/—" entry, but _confederations actually contains four real confederations (sorted alphabetically), so that approach would incorrectly select the first confederation for empty profiles. Instead, clear the selection when no match is found:

🔧 Corrected approach
            if (_confederationButton != null)
-                for (var i = 0; i < _confederations.Count; i++)
+            {
+                var idx = _confederations.FindIndex(c =>
+                    string.Equals(Profile?.Confederation, c, StringComparison.CurrentCultureIgnoreCase));
+
+                if (idx >= 0)
+                    _confederationButton.SelectId(idx);
+                else
+                    _confederationButton.Clear();
+            }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (_generalRecordNameEdit != null)
_generalRecordNameEdit.Text = Profile?.FullName ?? "";
if (_generalRecordAgeEdit != null)
_generalRecordAgeEdit.Text = Profile?.DateOfBirth ?? "";
if (_generalRecordCountryEdit != null)
_generalRecordCountryEdit.Text = Profile?.Country ?? "";
if (_confederationButton != null)
for (var i = 0; i < _confederations.Count; i++)
{
if (Profile?.Confederation.Equals(_confederations[i]) == true)
{
_confederationButton.SelectId(i);
}
}
if (_generalRecordNameEdit != null)
_generalRecordNameEdit.Text = Profile?.FullName ?? "";
if (_generalRecordAgeEdit != null)
_generalRecordAgeEdit.Text = Profile?.DateOfBirth ?? "";
if (_generalRecordCountryEdit != null)
_generalRecordCountryEdit.Text = Profile?.Country ?? "";
if (_confederationButton != null)
{
var idx = _confederations.FindIndex(c =>
string.Equals(Profile?.Confederation, c, StringComparison.CurrentCultureIgnoreCase));
if (idx >= 0)
_confederationButton.SelectId(idx);
else
_confederationButton.Clear();
}
🤖 Prompt for AI Agents
In `@Content.Client/Lobby/UI/HumanoidProfileEditor.xaml.cs` around lines 1989 -
2006, The confederation dropdown can retain a previous selection when
Profile?.Confederation is null/empty or doesn't match any entry; update the loop
controlling _confederationButton so it tracks whether a match was found while
iterating _confederations and, after the loop, call _confederationButton.Clear()
if no match was found (ensure you handle _confederationButton and
_confederations being non-null before operating); mirror the pattern used in
UpdateSexControls() to clear the control when the profile value is empty or
unmatched.

}
// WL-Records-End

Expand Down
2 changes: 1 addition & 1 deletion Content.Client/StationRecords/GeneralRecord.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
<Label Name="Species"/>
<Label Name="Gender"/> -->
<Label Text="{Loc 'general-station-record-employment-record'}"/>
<ScrollContainer VerticalExpand="True" MinHeight="300">
<ScrollContainer VerticalExpand="True" MinHeight="300" HScrollEnabled="False">
<BoxContainer Orientation="Vertical" VerticalExpand="True" HorizontalExpand="True">
<RichTextLabel Name="Record"
Margin="5"
Expand Down
40 changes: 36 additions & 4 deletions Content.Client/StationRecords/GeneralRecord.xaml.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
using Content.Shared.StationRecords;
using Content.Shared._WL.Languages;
using Content.Shared._WL.Records; // WL-Records
using Content.Shared.Humanoid.Prototypes;
using Content.Shared.StationRecords;
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.XAML;
Expand All @@ -22,9 +24,39 @@ public GeneralRecord(GeneralStationRecord record, bool canDelete, uint? id, IPro
// Species.Text = Loc.GetString("general-station-record-console-record-species", ("species", record.Species));
// Gender.Text = Loc.GetString("general-station-record-console-record-gender",
// ("gender", record.Gender.ToString()));
Record.Text = !string.IsNullOrEmpty(record.EmploymentRecord)
? record.EmploymentRecord
: Loc.GetString("general-station-console-no-employment-record");

var confederation = string.Empty;

if (prototypeManager.TryIndex<ConfederationRecordsPrototype>(record.Confederation, out var proto))
confederation = Loc.GetString(proto.Name);
else
confederation = Loc.GetString("generic-not-available-shorthand");

string languages = string.Empty;

for (int i = 0; i < record.Languages.Count; i++)
{
languages += Loc.GetString(prototypeManager.Index<LanguagePrototype>(record.Languages[i]).Name);

if (i != record.Languages.Count - 1)
languages += ", ";
else
languages += ".";
}
Comment on lines +37 to +45
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

prototypeManager.Index<LanguagePrototype> can throw if a language ID is invalid.

The loop assumes all language IDs in record.Languages are valid prototypes. If any ID is invalid or missing, this will throw. Use TryIndex and skip invalid entries.

🛡️ Proposed fix
         string languages = string.Empty;

         for (int i = 0; i < record.Languages.Count; i++)
         {
-            languages += Loc.GetString(prototypeManager.Index<LanguagePrototype>(record.Languages[i]).Name);
+            if (!prototypeManager.TryIndex<LanguagePrototype>(record.Languages[i], out var langProto))
+                continue;
+            
+            if (languages.Length > 0)
+                languages += ", ";
+            languages += Loc.GetString(langProto.Name);
+        }

-            if (i != record.Languages.Count - 1)
-                languages += ", ";
-            else
-                languages += ".";
-        }
+        if (languages.Length > 0)
+            languages += ".";
+        else
+            languages = Loc.GetString("generic-not-available-shorthand");
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Content.Client/StationRecords/GeneralRecord.xaml.cs` around lines 37 - 45,
The loop building the languages string uses
prototypeManager.Index<LanguagePrototype>(...) which will throw for invalid IDs;
change it to use prototypeManager.TryIndex<LanguagePrototype>(id, out var proto)
inside the loop over record.Languages and skip any entries where TryIndex
returns false, then call Loc.GetString(proto.Name) only for valid prototypes and
append the comma/period separators as before; update references in
GeneralRecord.xaml.cs (the for loop that reads record.Languages and the use of
Loc.GetString) to use TryIndex and continue on invalid IDs.


Record.Text = $"""
{Loc.GetString("records-full-name-edit")} {(!string.IsNullOrEmpty(record.Fullname)
? record.Fullname : record.Name)}
{Loc.GetString("records-date-of-birth-edit")} {(!string.IsNullOrEmpty(record.DateOfBirth)
? record.DateOfBirth : Loc.GetString("generic-not-available-shorthand"))}
{Loc.GetString("records-confederation-edit")} {confederation}
{Loc.GetString("records-country-edit")} {(!string.IsNullOrEmpty(record.Country)
? record.Country : Loc.GetString("generic-not-available-shorthand"))}
{Loc.GetString("records-species")} {Loc.GetString(prototypeManager.Index<SpeciesPrototype>(record.Species).Name)}
{Loc.GetString("records-language")} {languages}
{(!string.IsNullOrEmpty(record.EmploymentRecord) ? record.EmploymentRecord
: Loc.GetString("general-station-console-no-employment-record"))}
""";
// WL-Records-Edit-End
Fingerprint.Text = Loc.GetString("general-station-record-console-record-fingerprint",
("fingerprint", record.Fingerprint ?? Loc.GetString("generic-not-available-shorthand")));
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Content.Shared.StationRecords;
using Content.Shared._WL.Records;
using Robust.Client.UserInterface;

namespace Content.Client.StationRecords;
Expand All @@ -22,6 +23,7 @@ protected override void Open()
_window.OnFiltersChanged += (type, filterValue) =>
SendMessage(new SetStationRecordFilter(type, filterValue));
_window.OnDeleted += id => SendMessage(new DeleteStationRecord(id));
_window.OnPrint += id => SendMessage(new PrintStationRecord(id));
}

protected override void UpdateState(BoundUserInterfaceState state)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<DefaultWindow xmlns="https://spacestation14.io"
Title="{Loc 'general-station-record-console-window-title'}"
MinSize="750 500">
MinSize="750 520"> <!-- WL-Records -->
<BoxContainer Orientation="Vertical">
<BoxContainer Margin="5 5 5 10" HorizontalExpand="true" VerticalAlignment="Center">
<OptionButton Name="StationRecordsFilterType" MinWidth="200" Margin="0 0 10 0"/>
Expand All @@ -17,9 +17,12 @@
<ItemList Name="RecordListing" />
</ScrollContainer>
</BoxContainer>
<BoxContainer Orientation="Vertical" Margin="5">
<BoxContainer Orientation="Vertical" Margin="5" HorizontalExpand="True" VerticalExpand="True"> <!-- WL-Records -->
<Label Name="RecordContainerStatus" Visible="False" Text="{Loc 'general-station-record-console-select-record-info'}"/>
<Control Name="RecordContainer" Visible="False"/>
<Control Name="RecordContainer" Visible="False" HorizontalExpand="True" VerticalExpand="True"/>
<BoxContainer Orientation="Horizontal" Margin="5">
<Button Name="PrintButton" Text="{Loc 'records-print-button'}" MinWidth="200"/> <!-- WL-Records -->
</BoxContainer>
</BoxContainer>
</BoxContainer>
</BoxContainer>
Expand Down
Loading
Loading