diff --git a/Content.Client/GameTicking/ClientGameTicker.cs b/Content.Client/GameTicking/ClientGameTicker.cs index 8dcfd10a3a..abb6195cb5 100644 --- a/Content.Client/GameTicking/ClientGameTicker.cs +++ b/Content.Client/GameTicking/ClientGameTicker.cs @@ -19,6 +19,7 @@ using Robust.Shared.Interfaces.GameObjects; using Robust.Shared.Interfaces.Network; using Robust.Shared.IoC; using Robust.Shared.Localization; +using Robust.Shared.Prototypes; using Robust.Shared.Timing; using Robust.Shared.Utility; using Robust.Shared.ViewVariables; @@ -40,6 +41,7 @@ namespace Content.Client.GameTicking [Dependency] private IGameHud _gameHud; [Dependency] private IEntityManager _entityManager; [Dependency] private IClientPreferencesManager _preferencesManager; + [Dependency] private IPrototypeManager _prototypeManager; #pragma warning restore 649 [ViewVariables] private bool _areWeReady; @@ -192,7 +194,7 @@ namespace Content.Client.GameTicking _tickerState = TickerState.InLobby; - _characterSetup = new CharacterSetupGui(_entityManager, _localization, _resourceCache, _preferencesManager); + _characterSetup = new CharacterSetupGui(_entityManager, _localization, _resourceCache, _preferencesManager, _prototypeManager); LayoutContainer.SetAnchorPreset(_characterSetup, LayoutContainer.LayoutPreset.Wide); _characterSetup.CloseButton.OnPressed += args => { diff --git a/Content.Client/UserInterface/CharacterSetupGui.cs b/Content.Client/UserInterface/CharacterSetupGui.cs index b647c5b26f..dd6076c0e5 100644 --- a/Content.Client/UserInterface/CharacterSetupGui.cs +++ b/Content.Client/UserInterface/CharacterSetupGui.cs @@ -11,6 +11,7 @@ using Robust.Shared.Interfaces.GameObjects; using Robust.Shared.Localization; using Robust.Shared.Map; using Robust.Shared.Maths; +using Robust.Shared.Prototypes; namespace Content.Client.UserInterface { @@ -26,7 +27,8 @@ namespace Content.Client.UserInterface public CharacterSetupGui(IEntityManager entityManager, ILocalizationManager localization, IResourceCache resourceCache, - IClientPreferencesManager preferencesManager) + IClientPreferencesManager preferencesManager, + IPrototypeManager prototypeManager) { _entityManager = entityManager; _preferencesManager = preferencesManager; @@ -144,7 +146,7 @@ namespace Content.Client.UserInterface PanelOverride = new StyleBoxFlat {BackgroundColor = NanoStyle.NanoGold}, CustomMinimumSize = (2, 0) }); - _humanoidProfileEditor = new HumanoidProfileEditor(localization, preferencesManager); + _humanoidProfileEditor = new HumanoidProfileEditor(localization, preferencesManager, prototypeManager); _humanoidProfileEditor.OnProfileChanged += newProfile => { UpdateUI(); }; hBox.AddChild(_humanoidProfileEditor); diff --git a/Content.Client/UserInterface/HumanoidProfileEditor.cs b/Content.Client/UserInterface/HumanoidProfileEditor.cs index 54c82cc4fe..f989d5d896 100644 --- a/Content.Client/UserInterface/HumanoidProfileEditor.cs +++ b/Content.Client/UserInterface/HumanoidProfileEditor.cs @@ -1,6 +1,9 @@ using System; +using System.Collections.Generic; +using System.Linq; using Content.Client.GameObjects.Components; using Content.Client.Interfaces; +using Content.Shared.Jobs; using Content.Shared.Preferences; using Content.Shared.Text; using Robust.Client.Graphics.Drawing; @@ -10,6 +13,7 @@ using Robust.Shared.Interfaces.Random; using Robust.Shared.IoC; using Robust.Shared.Localization; using Robust.Shared.Maths; +using Robust.Shared.Prototypes; using Robust.Shared.Random; namespace Content.Client.UserInterface @@ -34,6 +38,7 @@ namespace Content.Client.UserInterface private readonly Button _sexMaleButton; private readonly HairStylePicker _hairPicker; private readonly FacialHairStylePicker _facialHairPicker; + private readonly List _jobPriorities; private bool _isDirty; public int CharacterSlot; @@ -47,7 +52,7 @@ namespace Content.Client.UserInterface } public HumanoidProfileEditor(ILocalizationManager localization, - IClientPreferencesManager preferencesManager) + IClientPreferencesManager preferencesManager, IPrototypeManager prototypeManager) { Profile = (HumanoidCharacterProfile) preferencesManager.Preferences.SelectedCharacter; CharacterSlot = preferencesManager.Preferences.SelectedCharacterIndex; @@ -90,9 +95,6 @@ namespace Content.Client.UserInterface #endregion Randomize - var middleColumn = new VBoxContainer(); - leftColumn.AddChild(middleColumn); - #region Name { @@ -130,76 +132,190 @@ namespace Content.Client.UserInterface hBox.AddChild(_nameEdit); hBox.AddChild(nameRandomButton); panel.AddChild(hBox); - middleColumn.AddChild(panel); + leftColumn.AddChild(panel); } #endregion Name - var sexAndAgeRow = new HBoxContainer - { - SeparationOverride = 10 - }; - middleColumn.AddChild(sexAndAgeRow); + var tabContainer = new TabContainer {SizeFlagsVertical = SizeFlags.FillExpand}; + vBox.AddChild(tabContainer); - #region Sex + #region Appearance { - var panel = HighlightedContainer(); - var hBox = new HBoxContainer(); - var sexLabel = new Label {Text = localization.GetString("Sex:")}; + var appearanceVBox = new VBoxContainer(); + tabContainer.AddChild(appearanceVBox); + tabContainer.SetTabTitle(0, Loc.GetString("Appearance")); - var sexButtonGroup = new ButtonGroup(); + var sexAndAgeRow = new HBoxContainer + { + SeparationOverride = 10 + }; + + appearanceVBox.AddChild(sexAndAgeRow); + + #region Sex - _sexMaleButton = new Button { - Text = localization.GetString("Male"), - Group = sexButtonGroup - }; - _sexMaleButton.OnPressed += args => + var panel = HighlightedContainer(); + var hBox = new HBoxContainer(); + var sexLabel = new Label {Text = localization.GetString("Sex:")}; + + var sexButtonGroup = new ButtonGroup(); + + _sexMaleButton = new Button + { + Text = localization.GetString("Male"), + Group = sexButtonGroup + }; + _sexMaleButton.OnPressed += args => + { + Profile = Profile?.WithSex(Sex.Male); + IsDirty = true; + }; + _sexFemaleButton = new Button + { + Text = localization.GetString("Female"), + Group = sexButtonGroup + }; + _sexFemaleButton.OnPressed += args => + { + Profile = Profile?.WithSex(Sex.Female); + IsDirty = true; + }; + hBox.AddChild(sexLabel); + hBox.AddChild(_sexMaleButton); + hBox.AddChild(_sexFemaleButton); + panel.AddChild(hBox); + sexAndAgeRow.AddChild(panel); + } + + #endregion Sex + + #region Age + { - Profile = Profile?.WithSex(Sex.Male); - IsDirty = true; - }; - _sexFemaleButton = new Button + var panel = HighlightedContainer(); + var hBox = new HBoxContainer(); + var ageLabel = new Label {Text = localization.GetString("Age:")}; + _ageEdit = new LineEdit {CustomMinimumSize = (40, 0)}; + _ageEdit.OnTextChanged += args => + { + if (!int.TryParse(args.Text, out var newAge)) + return; + Profile = Profile?.WithAge(newAge); + IsDirty = true; + }; + hBox.AddChild(ageLabel); + hBox.AddChild(_ageEdit); + panel.AddChild(hBox); + sexAndAgeRow.AddChild(panel); + } + + #endregion Age + + #region Hair + { - Text = localization.GetString("Female"), - Group = sexButtonGroup - }; - _sexFemaleButton.OnPressed += args => - { - Profile = Profile?.WithSex(Sex.Female); - IsDirty = true; - }; - hBox.AddChild(sexLabel); - hBox.AddChild(_sexMaleButton); - hBox.AddChild(_sexFemaleButton); - panel.AddChild(hBox); - sexAndAgeRow.AddChild(panel); + var panel = HighlightedContainer(); + panel.SizeFlagsHorizontal = SizeFlags.None; + var hairHBox = new HBoxContainer(); + + _hairPicker = new HairStylePicker(); + _hairPicker.Populate(); + + _hairPicker.OnHairStylePicked += newStyle => + { + if (Profile is null) + return; + Profile = Profile.WithCharacterAppearance( + Profile.Appearance.WithHairStyleName(newStyle)); + IsDirty = true; + }; + + _hairPicker.OnHairColorPicked += newColor => + { + if (Profile is null) + return; + Profile = Profile.WithCharacterAppearance( + Profile.Appearance.WithHairColor(newColor)); + IsDirty = true; + }; + + _facialHairPicker = new FacialHairStylePicker(); + _facialHairPicker.Populate(); + + _facialHairPicker.OnHairStylePicked += newStyle => + { + if (Profile is null) + return; + Profile = Profile.WithCharacterAppearance( + Profile.Appearance.WithFacialHairStyleName(newStyle)); + IsDirty = true; + }; + + _facialHairPicker.OnHairColorPicked += newColor => + { + if (Profile is null) + return; + Profile = Profile.WithCharacterAppearance( + Profile.Appearance.WithFacialHairColor(newColor)); + IsDirty = true; + }; + + hairHBox.AddChild(_hairPicker); + hairHBox.AddChild(_facialHairPicker); + + panel.AddChild(hairHBox); + appearanceVBox.AddChild(panel); + } + + #endregion Hair } - #endregion Sex + #endregion - #region Age + #region Jobs { - var panel = HighlightedContainer(); - var hBox = new HBoxContainer(); - var ageLabel = new Label {Text = localization.GetString("Age:")}; - _ageEdit = new LineEdit {CustomMinimumSize = (40, 0)}; - _ageEdit.OnTextChanged += args => + var jobList = new VBoxContainer(); + + tabContainer.AddChild(new ScrollContainer { - if (!int.TryParse(args.Text, out var newAge)) - return; - Profile = Profile?.WithAge(newAge); - IsDirty = true; - }; - hBox.AddChild(ageLabel); - hBox.AddChild(_ageEdit); - panel.AddChild(hBox); - sexAndAgeRow.AddChild(panel); + Children = {jobList} + }); + + tabContainer.SetTabTitle(1, Loc.GetString("Jobs")); + + _jobPriorities = new List(); + + foreach (var job in prototypeManager.EnumeratePrototypes().OrderBy(j => j.Name)) + { + var selector = new JobPrioritySelector(job); + jobList.AddChild(selector); + _jobPriorities.Add(selector); + + selector.PriorityChanged += priority => + { + Profile = Profile.WithJobPriority(job.ID, priority); + IsDirty = true; + + if (priority == JobPriority.High) + { + // Lower any other high priorities to medium. + foreach (var jobSelector in _jobPriorities) + { + if (jobSelector != selector && jobSelector.Priority == JobPriority.High) + { + jobSelector.Priority = JobPriority.Medium; + } + } + } + }; + } } - #endregion Age + #endregion var rightColumn = new VBoxContainer(); middleContainer.AddChild(rightColumn); @@ -250,65 +366,9 @@ namespace Content.Client.UserInterface #endregion Save - #region Hair - - { - var panel = HighlightedContainer(); - panel.SizeFlagsHorizontal = SizeFlags.None; - var hairHBox = new HBoxContainer(); - - _hairPicker = new HairStylePicker(); - _hairPicker.Populate(); - - _hairPicker.OnHairStylePicked += newStyle => - { - if (Profile is null) - return; - Profile = Profile.WithCharacterAppearance( - Profile.Appearance.WithHairStyleName(newStyle)); - IsDirty = true; - }; - - _hairPicker.OnHairColorPicked += newColor => - { - if (Profile is null) - return; - Profile = Profile.WithCharacterAppearance( - Profile.Appearance.WithHairColor(newColor)); - IsDirty = true; - }; - - _facialHairPicker = new FacialHairStylePicker(); - _facialHairPicker.Populate(); - - _facialHairPicker.OnHairStylePicked += newStyle => - { - if (Profile is null) - return; - Profile = Profile.WithCharacterAppearance( - Profile.Appearance.WithFacialHairStyleName(newStyle)); - IsDirty = true; - }; - - _facialHairPicker.OnHairColorPicked += newColor => - { - if (Profile is null) - return; - Profile = Profile.WithCharacterAppearance( - Profile.Appearance.WithFacialHairColor(newColor)); - IsDirty = true; - }; - - hairHBox.AddChild(_hairPicker); - hairHBox.AddChild(_facialHairPicker); - - panel.AddChild(hairHBox); - vBox.AddChild(panel); - } - - #endregion Hair - UpdateControls(); + + IsDirty = false; } private bool IsDirty @@ -360,6 +420,58 @@ namespace Content.Client.UserInterface _ageEdit.Text = Profile?.Age.ToString(); UpdateHairPickers(); UpdateSaveButton(); + UpdateJobPriorities(); + } + + private void UpdateJobPriorities() + { + foreach (var prioritySelector in _jobPriorities) + { + var jobId = prioritySelector.Job.ID; + + var priority = Profile.JobPriorities.GetValueOrDefault(jobId, JobPriority.Never); + + prioritySelector.Priority = priority; + } + } + + private class JobPrioritySelector : Control + { + public JobPrototype Job { get; } + private readonly OptionButton _optionButton; + + public JobPriority Priority + { + get => (JobPriority) _optionButton.SelectedId; + set => _optionButton.SelectId((int) value); + } + + public event Action PriorityChanged; + + public JobPrioritySelector(JobPrototype job) + { + Job = job; + _optionButton = new OptionButton(); + _optionButton.AddItem(Loc.GetString("High"), (int) JobPriority.High); + _optionButton.AddItem(Loc.GetString("Medium"), (int) JobPriority.Medium); + _optionButton.AddItem(Loc.GetString("Low"), (int) JobPriority.Low); + _optionButton.AddItem(Loc.GetString("Never"), (int) JobPriority.Never); + + _optionButton.OnItemSelected += args => + { + _optionButton.SelectId(args.Id); + PriorityChanged?.Invoke(Priority); + }; + + AddChild(new HBoxContainer + { + Children = + { + new Label {Text = job.Name, CustomMinimumSize = (175, 0)}, + _optionButton + } + }); + } } } } diff --git a/Content.Server.Database/Migrations/20200118195640_jobs.Designer.cs b/Content.Server.Database/Migrations/20200118195640_jobs.Designer.cs new file mode 100644 index 0000000000..73c8815f02 --- /dev/null +++ b/Content.Server.Database/Migrations/20200118195640_jobs.Designer.cs @@ -0,0 +1,142 @@ +// +using Content.Server.Database; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +namespace Content.Server.Database.Migrations +{ + [DbContext(typeof(PreferencesDbContext))] + [Migration("20200118195640_jobs")] + partial class jobs + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "3.1.0"); + + modelBuilder.Entity("Content.Server.Database.HumanoidProfile", b => + { + b.Property("HumanoidProfileId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Age") + .HasColumnType("INTEGER"); + + b.Property("CharacterName") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("EyeColor") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("FacialHairColor") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("FacialHairName") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("HairColor") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("HairName") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("PrefsId") + .HasColumnType("INTEGER"); + + b.Property("Sex") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("SkinColor") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Slot") + .HasColumnType("INTEGER"); + + b.Property("SlotName") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("HumanoidProfileId"); + + b.HasIndex("PrefsId"); + + b.ToTable("HumanoidProfile"); + }); + + modelBuilder.Entity("Content.Server.Database.Job", b => + { + b.Property("JobId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("JobName") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Priority") + .HasColumnType("INTEGER"); + + b.Property("ProfileHumanoidProfileId") + .HasColumnType("INTEGER"); + + b.HasKey("JobId"); + + b.HasIndex("ProfileHumanoidProfileId"); + + b.ToTable("Job"); + }); + + modelBuilder.Entity("Content.Server.Database.Prefs", b => + { + b.Property("PrefsId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("SelectedCharacterSlot") + .HasColumnType("INTEGER"); + + b.Property("Username") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("PrefsId"); + + b.HasIndex("Username") + .IsUnique(); + + b.ToTable("Preferences"); + }); + + modelBuilder.Entity("Content.Server.Database.HumanoidProfile", b => + { + b.HasOne("Content.Server.Database.Prefs", "Prefs") + .WithMany("HumanoidProfiles") + .HasForeignKey("PrefsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Content.Server.Database.Job", b => + { + b.HasOne("Content.Server.Database.HumanoidProfile", "Profile") + .WithMany("Jobs") + .HasForeignKey("ProfileHumanoidProfileId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Content.Server.Database/Migrations/20200118195640_jobs.cs b/Content.Server.Database/Migrations/20200118195640_jobs.cs new file mode 100644 index 0000000000..09a47891ba --- /dev/null +++ b/Content.Server.Database/Migrations/20200118195640_jobs.cs @@ -0,0 +1,42 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace Content.Server.Database.Migrations +{ + public partial class jobs : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "Job", + columns: table => new + { + JobId = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + ProfileHumanoidProfileId = table.Column(nullable: false), + JobName = table.Column(nullable: false), + Priority = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Job", x => x.JobId); + table.ForeignKey( + name: "FK_Job_HumanoidProfile_ProfileHumanoidProfileId", + column: x => x.ProfileHumanoidProfileId, + principalTable: "HumanoidProfile", + principalColumn: "HumanoidProfileId", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_Job_ProfileHumanoidProfileId", + table: "Job", + column: "ProfileHumanoidProfileId"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "Job"); + } + } +} diff --git a/Content.Server.Database/Migrations/PreferencesDbContextModelSnapshot.cs b/Content.Server.Database/Migrations/PreferencesDbContextModelSnapshot.cs index 5645bbe18c..9803ee3c2b 100644 --- a/Content.Server.Database/Migrations/PreferencesDbContextModelSnapshot.cs +++ b/Content.Server.Database/Migrations/PreferencesDbContextModelSnapshot.cs @@ -73,6 +73,29 @@ namespace Content.Server.Database.Migrations b.ToTable("HumanoidProfile"); }); + modelBuilder.Entity("Content.Server.Database.Job", b => + { + b.Property("JobId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("JobName") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Priority") + .HasColumnType("INTEGER"); + + b.Property("ProfileHumanoidProfileId") + .HasColumnType("INTEGER"); + + b.HasKey("JobId"); + + b.HasIndex("ProfileHumanoidProfileId"); + + b.ToTable("Job"); + }); + modelBuilder.Entity("Content.Server.Database.Prefs", b => { b.Property("PrefsId") @@ -102,6 +125,15 @@ namespace Content.Server.Database.Migrations .OnDelete(DeleteBehavior.Cascade) .IsRequired(); }); + + modelBuilder.Entity("Content.Server.Database.Job", b => + { + b.HasOne("Content.Server.Database.HumanoidProfile", "Profile") + .WithMany("Jobs") + .HasForeignKey("ProfileHumanoidProfileId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); #pragma warning restore 612, 618 } } diff --git a/Content.Server.Database/Model.cs b/Content.Server.Database/Model.cs index 8c1dc07789..f35f008178 100644 --- a/Content.Server.Database/Model.cs +++ b/Content.Server.Database/Model.cs @@ -47,8 +47,27 @@ namespace Content.Server.Database public string FacialHairColor { get; set; } = null!; public string EyeColor { get; set; } = null!; public string SkinColor { get; set; } = null!; + public List Jobs { get; } = new List(); public int PrefsId { get; set; } public Prefs Prefs { get; set; } = null!; } + + public class Job + { + public int JobId { get; set; } + public HumanoidProfile Profile { get; set; } = null!; + + public string JobName { get; set; } = null!; + public DbJobPriority Priority { get; set; } + } + + public enum DbJobPriority + { + // These enum values HAVE to match the ones in JobPriority in Shared. + Never = 0, + Low = 1, + Medium = 2, + High = 3 + } } diff --git a/Content.Server.Database/PrefsDb.cs b/Content.Server.Database/PrefsDb.cs index 622b85d07f..c4d6d112ba 100644 --- a/Content.Server.Database/PrefsDb.cs +++ b/Content.Server.Database/PrefsDb.cs @@ -21,6 +21,7 @@ namespace Content.Server.Database return _prefsCtx .Preferences .Include(p => p.HumanoidProfiles) + .ThenInclude(h => h.Jobs) .SingleOrDefault(p => p.Username == username); } diff --git a/Content.Server/Preferences/PreferencesDatabase.cs b/Content.Server/Preferences/PreferencesDatabase.cs index 06452e27b2..efbff33c53 100644 --- a/Content.Server/Preferences/PreferencesDatabase.cs +++ b/Content.Server/Preferences/PreferencesDatabase.cs @@ -30,6 +30,8 @@ namespace Content.Server.Preferences var profiles = new ICharacterProfile[_maxCharacterSlots]; foreach (var profile in prefs.HumanoidProfiles) { + var jobs = profile.Jobs.ToDictionary(j => j.JobName, j => (JobPriority) j.Priority); + profiles[profile.Slot] = new HumanoidCharacterProfile( profile.CharacterName, profile.Age, @@ -42,7 +44,8 @@ namespace Content.Server.Preferences Color.FromHex(profile.FacialHairColor), Color.FromHex(profile.EyeColor), Color.FromHex(profile.SkinColor) - ) + ), + jobs ); } @@ -73,7 +76,7 @@ namespace Content.Server.Preferences // TODO: Handle other ICharacterProfile implementations properly throw new NotImplementedException(); var appearance = (HumanoidCharacterAppearance) humanoid.CharacterAppearance; - _prefsDb.SaveCharacterSlot(username, new HumanoidProfile + var entity = new HumanoidProfile { SlotName = humanoid.Name, CharacterName = humanoid.Name, @@ -86,7 +89,13 @@ namespace Content.Server.Preferences EyeColor = appearance.EyeColor.ToHex(), SkinColor = appearance.SkinColor.ToHex(), Slot = slot - }); + }; + entity.Jobs.AddRange( + humanoid.JobPriorities + .Where(j => j.Value != JobPriority.Never) + .Select(j => new Job {JobName = j.Key, Priority = (DbJobPriority) j.Value}) + ); + _prefsDb.SaveCharacterSlot(username, entity); } private void DeleteCharacterSlot(string username, int slot) diff --git a/Content.Shared/Preferences/HumanoidCharacterProfile.cs b/Content.Shared/Preferences/HumanoidCharacterProfile.cs index dc97c2c914..b8327f1742 100644 --- a/Content.Shared/Preferences/HumanoidCharacterProfile.cs +++ b/Content.Shared/Preferences/HumanoidCharacterProfile.cs @@ -1,4 +1,6 @@ using System; +using System.Collections.Generic; +using System.Linq; using Robust.Shared.Serialization; namespace Content.Shared.Preferences @@ -6,20 +8,34 @@ namespace Content.Shared.Preferences [Serializable, NetSerializable] public class HumanoidCharacterProfile : ICharacterProfile { - public HumanoidCharacterProfile(string name, + private readonly Dictionary _jobPriorities; + + private HumanoidCharacterProfile(string name, int age, Sex sex, - HumanoidCharacterAppearance appearance) + HumanoidCharacterAppearance appearance, + Dictionary jobPriorities) { Name = name; Age = age; Sex = sex; Appearance = appearance; + _jobPriorities = jobPriorities; + } + + public HumanoidCharacterProfile(string name, + int age, + Sex sex, + HumanoidCharacterAppearance appearance, + IReadOnlyDictionary jobPriorities) + : this(name, age, sex, appearance, new Dictionary(jobPriorities)) + { } public static HumanoidCharacterProfile Default() { - return new HumanoidCharacterProfile("John Doe", 18, Sex.Male, HumanoidCharacterAppearance.Default()); + return new HumanoidCharacterProfile("John Doe", 18, Sex.Male, HumanoidCharacterAppearance.Default(), + new Dictionary()); } public string Name { get; } @@ -27,28 +43,50 @@ namespace Content.Shared.Preferences public Sex Sex { get; } public ICharacterAppearance CharacterAppearance => Appearance; public HumanoidCharacterAppearance Appearance { get; } + public IReadOnlyDictionary JobPriorities => _jobPriorities; public HumanoidCharacterProfile WithName(string name) { - return new HumanoidCharacterProfile(name, Age, Sex, Appearance); + return new HumanoidCharacterProfile(name, Age, Sex, Appearance, _jobPriorities); } public HumanoidCharacterProfile WithAge(int age) { - return new HumanoidCharacterProfile(Name, age, Sex, Appearance); + return new HumanoidCharacterProfile(Name, age, Sex, Appearance, _jobPriorities); } public HumanoidCharacterProfile WithSex(Sex sex) { - return new HumanoidCharacterProfile(Name, Age, sex, Appearance); + return new HumanoidCharacterProfile(Name, Age, sex, Appearance, _jobPriorities); } public HumanoidCharacterProfile WithCharacterAppearance(HumanoidCharacterAppearance appearance) { - return new HumanoidCharacterProfile(Name, Age, Sex, appearance); + return new HumanoidCharacterProfile(Name, Age, Sex, appearance, _jobPriorities); } - public string Summary => $"{Name}, {Age} years old {Sex.ToString().ToLower()} human.\nOccupation: to be implemented."; + public HumanoidCharacterProfile WithJobPriorities(IReadOnlyDictionary jobPriorities) + { + return new HumanoidCharacterProfile(Name, Age, Sex, Appearance, new Dictionary(jobPriorities)); + } + + public HumanoidCharacterProfile WithJobPriority(string jobId, JobPriority priority) + { + var dictionary = new Dictionary(_jobPriorities); + if (priority == JobPriority.Never) + { + dictionary.Remove(jobId); + } + else + { + dictionary[jobId] = priority; + } + + return new HumanoidCharacterProfile(Name, Age, Sex, Appearance, dictionary); + } + + public string Summary => + $"{Name}, {Age} years old {Sex.ToString().ToLower()} human."; public bool MemberwiseEquals(ICharacterProfile maybeOther) { @@ -56,6 +94,7 @@ namespace Content.Shared.Preferences if (Name != other.Name) return false; if (Age != other.Age) return false; if (Sex != other.Sex) return false; + if (!_jobPriorities.SequenceEqual(other._jobPriorities)) return false; return Appearance.MemberwiseEquals(other.Appearance); } } diff --git a/Content.Shared/Preferences/JobPriority.cs b/Content.Shared/Preferences/JobPriority.cs new file mode 100644 index 0000000000..73deac3523 --- /dev/null +++ b/Content.Shared/Preferences/JobPriority.cs @@ -0,0 +1,11 @@ +namespace Content.Shared.Preferences +{ + public enum JobPriority + { + // These enum values HAVE to match the ones in DbJobPriority in Server.Database. + Never = 0, + Low = 1, + Medium = 2, + High = 3 + } +} diff --git a/Content.Tests/Server/Preferences/PreferencesDatabaseTests.cs b/Content.Tests/Server/Preferences/PreferencesDatabaseTests.cs index 13bdb16c54..ad43543200 100644 --- a/Content.Tests/Server/Preferences/PreferencesDatabaseTests.cs +++ b/Content.Tests/Server/Preferences/PreferencesDatabaseTests.cs @@ -1,3 +1,4 @@ +using System.Collections.Generic; using System.IO; using System.Linq; using Content.Server.Preferences; @@ -26,7 +27,11 @@ namespace Content.Tests.Server.Preferences Color.Aquamarine, Color.Azure, Color.Beige - ) + ), + new Dictionary + { + {"Assistant", JobPriority.High} + } ); }