From bf669e48a06d6e213f55b048a981436449409925 Mon Sep 17 00:00:00 2001 From: dffdff2423 <57052305+dffdff2423@users.noreply.github.com> Date: Fri, 9 Feb 2024 21:29:09 -0600 Subject: [PATCH] Records (#129) * Implement records saving. Add an additional column to the database that stores records as JSON. Currently the serialization logic is not very robust so a future commit should improve it so it can deal with missing and extra fields in the database. * Record editor gui Implements a record editor tab for HumanoidProfileEditor. In addition, this improves the robustness of the CharacterRecords deserializer. * Add imperial units to record editor. * Remove SecurityClearance from CharacterRecords * Add up and down buttons to the record entry editor This lets you select the order that records will appear in game. * Add system for managing records in game * Initial viewer UI Add the record console UI, currently it does not display entries. * Add entries to the record console * Clarify record computers. * Add records viewer to aghost * Add admin modification ui for character records * Improve record entry viewer * Remove contact number record * Character Records Guidebook Entry * Change from DefaultWindow to FancyWindow * Fix compile errors relating to rebase * Add rich text to record viewer We support all tags except the heading tag. This is because it looks very ugly. In addition, we also add a view button to the editor GUI so you can make sure your rich text works without going into a game. * Integrate wanted status into security records * Correctly subscribe to Bui events * Add comments to records and fix a few minor issues --- .../UI/Tabs/AdminTab/AdminTab.xaml | 3 + .../UI/HumanoidProfileEditor.xaml.cs | 27 + .../_CD/Admin/UI/ModifyCharacterRecords.xaml | 14 + .../Admin/UI/ModifyCharacterRecords.xaml.cs | 48 + ...haracterRecordConsoleBoundUserInterface.cs | 89 + .../_CD/Records/UI/CharacterRecordViewer.xaml | 135 ++ .../Records/UI/CharacterRecordViewer.xaml.cs | 351 ++++ .../Records/UI/RecordEditorEntrySelector.xaml | 14 + .../UI/RecordEditorEntrySelector.xaml.cs | 136 ++ .../_CD/Records/UI/RecordEditorGui.xaml | 68 + .../_CD/Records/UI/RecordEditorGui.xaml.cs | 155 ++ .../_CD/Records/UI/RecordEntryEditPopup.xaml | 13 + .../Records/UI/RecordEntryEditPopup.xaml.cs | 38 + .../_CD/Records/UI/RecordEntryViewPopup.xaml | 18 + .../Records/UI/RecordEntryViewPopup.xaml.cs | 34 + .../_CD/Records/UI/UnitConversion.cs | 16 + .../Tests/Preferences/ServerDbSqliteTests.cs | 5 +- ...40119204209_CDCharacterRecords.Designer.cs | 1764 +++++++++++++++++ .../20240119204209_CDCharacterRecords.cs | 29 + .../PostgresServerDbContextModelSnapshot.cs | 8 +- ...40119204158_CDCharacterRecords.Designer.cs | 1696 ++++++++++++++++ .../20240119204158_CDCharacterRecords.cs | 28 + .../SqliteServerDbContextModelSnapshot.cs | 6 +- Content.Server.Database/Model.cs | 4 + Content.Server.Database/ModelSqlite.cs | 5 + .../Administration/Systems/AdminSystem.cs | 9 + .../Systems/CriminalRecordsConsoleSystem.cs | 16 + Content.Server/Database/ServerDbBase.cs | 15 +- .../_CD/Records/CharacterRecordsComponent.cs | 14 + .../_CD/Records/CharacterRecordsSystem.cs | 167 ++ .../Records/Commands/DelRecordEntryCommand.cs | 55 + .../Commands/PurgeCharacterRecordsCommand.cs | 42 + .../CharacterRecordConsoleComponent.cs | 17 + .../Consoles/CharacterRecordConsoleSystem.cs | 149 ++ .../_CD/Records/RecordsSerialization.cs | 92 + .../Preferences/HumanoidCharacterProfile.cs | 40 +- .../_CD/Records/CharacterRecords.cs | 247 +++ .../_CD/Records/FullCharacterRecords.cs | 87 + .../Records/SharedCharacterRecordConsole.cs | 73 + Resources/Locale/en-US/_CD/admin/admin.ftl | 4 + .../Locale/en-US/_CD/guidebook/guides.ftl | 1 + Resources/Locale/en-US/_CD/records/editor.ftl | 34 + Resources/Locale/en-US/_CD/records/viewer.ftl | 26 + .../Entities/Mobs/Player/admin_ghost.yml | 22 + .../Machines/Computers/computers.yml | 50 +- Resources/Prototypes/Guidebook/ss14.yml | 10 + .../ServerInfo/Guidebook/_CD/Records.xml | 40 + 47 files changed, 5882 insertions(+), 32 deletions(-) create mode 100644 Content.Client/_CD/Admin/UI/ModifyCharacterRecords.xaml create mode 100644 Content.Client/_CD/Admin/UI/ModifyCharacterRecords.xaml.cs create mode 100644 Content.Client/_CD/Records/UI/CharacterRecordConsoleBoundUserInterface.cs create mode 100644 Content.Client/_CD/Records/UI/CharacterRecordViewer.xaml create mode 100644 Content.Client/_CD/Records/UI/CharacterRecordViewer.xaml.cs create mode 100644 Content.Client/_CD/Records/UI/RecordEditorEntrySelector.xaml create mode 100644 Content.Client/_CD/Records/UI/RecordEditorEntrySelector.xaml.cs create mode 100644 Content.Client/_CD/Records/UI/RecordEditorGui.xaml create mode 100644 Content.Client/_CD/Records/UI/RecordEditorGui.xaml.cs create mode 100644 Content.Client/_CD/Records/UI/RecordEntryEditPopup.xaml create mode 100644 Content.Client/_CD/Records/UI/RecordEntryEditPopup.xaml.cs create mode 100644 Content.Client/_CD/Records/UI/RecordEntryViewPopup.xaml create mode 100644 Content.Client/_CD/Records/UI/RecordEntryViewPopup.xaml.cs create mode 100644 Content.Client/_CD/Records/UI/UnitConversion.cs create mode 100644 Content.Server.Database/Migrations/Postgres/20240119204209_CDCharacterRecords.Designer.cs create mode 100644 Content.Server.Database/Migrations/Postgres/20240119204209_CDCharacterRecords.cs create mode 100644 Content.Server.Database/Migrations/Sqlite/20240119204158_CDCharacterRecords.Designer.cs create mode 100644 Content.Server.Database/Migrations/Sqlite/20240119204158_CDCharacterRecords.cs create mode 100644 Content.Server/_CD/Records/CharacterRecordsComponent.cs create mode 100644 Content.Server/_CD/Records/CharacterRecordsSystem.cs create mode 100644 Content.Server/_CD/Records/Commands/DelRecordEntryCommand.cs create mode 100644 Content.Server/_CD/Records/Commands/PurgeCharacterRecordsCommand.cs create mode 100644 Content.Server/_CD/Records/Consoles/CharacterRecordConsoleComponent.cs create mode 100644 Content.Server/_CD/Records/Consoles/CharacterRecordConsoleSystem.cs create mode 100644 Content.Server/_CD/Records/RecordsSerialization.cs create mode 100644 Content.Shared/_CD/Records/CharacterRecords.cs create mode 100644 Content.Shared/_CD/Records/FullCharacterRecords.cs create mode 100644 Content.Shared/_CD/Records/SharedCharacterRecordConsole.cs create mode 100644 Resources/Locale/en-US/_CD/admin/admin.ftl create mode 100644 Resources/Locale/en-US/_CD/guidebook/guides.ftl create mode 100644 Resources/Locale/en-US/_CD/records/editor.ftl create mode 100644 Resources/Locale/en-US/_CD/records/viewer.ftl create mode 100644 Resources/ServerInfo/Guidebook/_CD/Records.xml diff --git a/Content.Client/Administration/UI/Tabs/AdminTab/AdminTab.xaml b/Content.Client/Administration/UI/Tabs/AdminTab/AdminTab.xaml index 8b68487547f..b558d6114ed 100644 --- a/Content.Client/Administration/UI/Tabs/AdminTab/AdminTab.xaml +++ b/Content.Client/Administration/UI/Tabs/AdminTab/AdminTab.xaml @@ -3,6 +3,7 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:cc="clr-namespace:Content.Client.Administration.UI.CustomControls" xmlns:at="clr-namespace:Content.Client.Administration.UI.Tabs.AdminTab" + xmlns:cdAdmin="clr-namespace:Content.Client._CD.Admin.UI" Margin="4" MinSize="50 50"> @@ -16,6 +17,8 @@ + + diff --git a/Content.Client/Preferences/UI/HumanoidProfileEditor.xaml.cs b/Content.Client/Preferences/UI/HumanoidProfileEditor.xaml.cs index acf738129cf..f33d38c66b3 100644 --- a/Content.Client/Preferences/UI/HumanoidProfileEditor.xaml.cs +++ b/Content.Client/Preferences/UI/HumanoidProfileEditor.xaml.cs @@ -35,6 +35,10 @@ using static Robust.Client.UserInterface.Controls.BoxContainer; using Direction = Robust.Shared.Maths.Direction; +// CD: Records editor imports +using Content.Client._CD.Records.UI; +using Content.Shared._CD.Records; + namespace Content.Client.Preferences.UI { public sealed class HighlightedContainer : PanelContainer @@ -110,6 +114,9 @@ public sealed partial class HumanoidProfileEditor : Control private float _defaultHeight = 1f; + // CD: Record editor + private readonly RecordEditorGui _recordsTab; + public HumanoidProfileEditor(IClientPreferencesManager preferencesManager, IPrototypeManager prototypeManager, IEntityManager entityManager, IConfigurationManager configurationManager) { @@ -517,6 +524,14 @@ public HumanoidProfileEditor(IClientPreferencesManager preferencesManager, IProt #endregion Markings + #region CosmaticRecords + + _recordsTab = new RecordEditorGui(UpdateProfileRecords); + _tabContainer.AddChild(_recordsTab); + _tabContainer.SetTabTitle(_tabContainer.ChildCount - 1, Loc.GetString("humanoid-profile-editor-cd-records-tab")); + + #endregion CosmaticRecords + #region FlavorText if (_configurationManager.GetCVar(CCVars.FlavorText)) @@ -673,6 +688,15 @@ private void UpdateRoleRequirements() } } + // CD: Records editor + private void UpdateProfileRecords(CharacterRecords records) + { + if (Profile is null) + return; + Profile = Profile.WithCDCharacterRecords(records); + IsDirty = true; + } + private void OnFlavorTextChange(string content) { if (Profile is null) @@ -1220,6 +1244,9 @@ public void UpdateControls() UpdateCMarkingsFacialHair(); UpdateHeightControls(); + // CD: Update record editor + _recordsTab.Update(Profile); + _preferenceUnavailableButton.SelectId((int) Profile.PreferenceUnavailable); } diff --git a/Content.Client/_CD/Admin/UI/ModifyCharacterRecords.xaml b/Content.Client/_CD/Admin/UI/ModifyCharacterRecords.xaml new file mode 100644 index 00000000000..9cb31849704 --- /dev/null +++ b/Content.Client/_CD/Admin/UI/ModifyCharacterRecords.xaml @@ -0,0 +1,14 @@ + + + + + + + + + + + diff --git a/Content.Client/_CD/Admin/UI/ModifyCharacterRecords.xaml.cs b/Content.Client/_CD/Admin/UI/ModifyCharacterRecords.xaml.cs new file mode 100644 index 00000000000..9a868650997 --- /dev/null +++ b/Content.Client/_CD/Admin/UI/ModifyCharacterRecords.xaml.cs @@ -0,0 +1,48 @@ +using Content.Shared._CD.Records; +using Robust.Client.AutoGenerated; +using Robust.Client.UserInterface.CustomControls; +using Robust.Client.UserInterface.XAML; + +namespace Content.Client._CD.Admin.UI; + +[GenerateTypedNameReferences] +public sealed partial class ModifyCharacterRecords : DefaultWindow +{ + public ModifyCharacterRecords() + { + RobustXamlLoader.Load(this); + IoCManager.InjectDependencies(this); + + foreach (var v in Enum.GetValues()) + { + EntityEntryType.AddItem(v.ToString()); + } + + EntityEntryType.OnItemSelected += args => + { + EntityEntryType.SelectId(args.Id); + UpdateCommands(); + }; + + EntityEdit.OnTextChanged += _ => UpdateCommands(); + EntityEntryIndex.OnTextChanged += _ => UpdateCommands(); + } + + private void UpdateCommands() + { + if (!int.TryParse(EntityEdit.Text, out var uid)) + { + return; + } + + if (!int.TryParse(EntityEntryIndex.Text, out var idx)) + { + return; + } + + var ty = (CharacterRecordType)EntityEntryType.SelectedId; + + PurgeCommand.Command = $"purgecharacterrecords {uid}"; + DelCommand.Command = $"delrecordentry {uid} {ty.ToString()} {idx}"; + } +} diff --git a/Content.Client/_CD/Records/UI/CharacterRecordConsoleBoundUserInterface.cs b/Content.Client/_CD/Records/UI/CharacterRecordConsoleBoundUserInterface.cs new file mode 100644 index 00000000000..4363021df0d --- /dev/null +++ b/Content.Client/_CD/Records/UI/CharacterRecordConsoleBoundUserInterface.cs @@ -0,0 +1,89 @@ +using Content.Shared._CD.Records; +using Content.Shared.CriminalRecords; +using Content.Shared.CriminalRecords.Components; +using Content.Shared.Security; +using Content.Shared.StationRecords; +using JetBrains.Annotations; + +namespace Content.Client._CD.Records.UI; + +[UsedImplicitly] +public sealed class CharacterRecordConsoleBoundUserInterface : BoundUserInterface +{ + [ViewVariables] private CharacterRecordViewer? _window; + + [Dependency] private readonly EntityManager _entMan = default!; + + public CharacterRecordConsoleBoundUserInterface(EntityUid owner, Enum key) + : base(owner, key) + { + } + + protected override void UpdateState(BoundUserInterfaceState baseState) + { + base.UpdateState(baseState); + if (baseState is not CharacterRecordConsoleState state) + return; + + if (_window?.IsSecurity() ?? false) + { + var comp = EntMan.GetComponent(Owner); + _window!.SecurityWantedStatusMaxLength = comp.MaxStringLength; + } + + _window?.UpdateState(state); + } + + protected override void Open() + { + base.Open(); + + _window = new(); + _window.OnClose += Close; + _window.OnKeySelected += (ent, stationRecordKey) => + { + SendMessage(new CharacterRecordConsoleSelectMsg(ent)); + + // If we are a security records console, we also need to inform the criminal records + // system of our state. + if (_window.IsSecurity() && stationRecordKey != null) + { + SendMessage(new SelectStationRecord(stationRecordKey)); + _window.SetSecurityStatusEnabled(true); + } + else + { + // If the user does not have criminal records for some reason, we should not be able + // to set their wanted status + _window.SetSecurityStatusEnabled(false); + } + }; + + _window.OnFiltersChanged += (ty, txt) => + { + if (txt == null) + SendMessage(new CharacterRecordsConsoleFilterMsg(null)); + else + SendMessage(new CharacterRecordsConsoleFilterMsg(new StationRecordsFilter(ty, txt))); + }; + + _window.OnSetSecurityStatus += status => + { + SendMessage(new CriminalRecordChangeStatus(status, null)); + }; + + _window.OnSetWantedStatus += reason => + { + SendMessage(new CriminalRecordChangeStatus(SecurityStatus.Wanted, reason)); + }; + + _window.OpenCentered(); + } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + + _window?.Close(); + } +} diff --git a/Content.Client/_CD/Records/UI/CharacterRecordViewer.xaml b/Content.Client/_CD/Records/UI/CharacterRecordViewer.xaml new file mode 100644 index 00000000000..38b0640d3e8 --- /dev/null +++ b/Content.Client/_CD/Records/UI/CharacterRecordViewer.xaml @@ -0,0 +1,135 @@ + + + + + + + +