Client customization late-join spawner priority for arrivals/cryostorage (#24586)

* Initial commit, requires server restart to take effect

* Exposes callbacks directly instead, takes effect immediately

* Cleaned up control flow, swapped cvar for client customization

* Switched to int, dictionary of callbacks, migration

* Update Content.Shared/Preferences/SpawnPriorityPreference.cs

* krunkle stan

---------

Co-authored-by: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com>
Co-authored-by: metalgearsloth <comedian_vs_clown@hotmail.com>
This commit is contained in:
Krunklehorn
2024-02-01 05:12:09 -05:00
committed by GitHub
parent d76121d470
commit ed0f2aa221
18 changed files with 3654 additions and 20 deletions

View File

@@ -96,6 +96,12 @@
<Control HorizontalExpand="True"/> <Control HorizontalExpand="True"/>
<OptionButton Name="CBackpackButton" HorizontalAlignment="Right" /> <OptionButton Name="CBackpackButton" HorizontalAlignment="Right" />
</BoxContainer> </BoxContainer>
<!-- Spawn Priority -->
<BoxContainer HorizontalExpand="True">
<Label Text="{Loc 'humanoid-profile-editor-spawn-priority-label'}" />
<Control HorizontalExpand="True"/>
<OptionButton Name="CSpawnPriorityButton" HorizontalAlignment="Right" />
</BoxContainer>
</BoxContainer> </BoxContainer>
<!-- Skin --> <!-- Skin -->
<BoxContainer Margin="10" HorizontalExpand="True" Orientation="Vertical"> <BoxContainer Margin="10" HorizontalExpand="True" Orientation="Vertical">

View File

@@ -72,6 +72,7 @@ namespace Content.Client.Preferences.UI
private Slider _skinColor => CSkin; private Slider _skinColor => CSkin;
private OptionButton _clothingButton => CClothingButton; private OptionButton _clothingButton => CClothingButton;
private OptionButton _backpackButton => CBackpackButton; private OptionButton _backpackButton => CBackpackButton;
private OptionButton _spawnPriorityButton => CSpawnPriorityButton;
private SingleMarkingPicker _hairPicker => CHairStylePicker; private SingleMarkingPicker _hairPicker => CHairStylePicker;
private SingleMarkingPicker _facialHairPicker => CFacialHairPicker; private SingleMarkingPicker _facialHairPicker => CFacialHairPicker;
private EyeColorPicker _eyesPicker => CEyeColorPicker; private EyeColorPicker _eyesPicker => CEyeColorPicker;
@@ -340,6 +341,21 @@ namespace Content.Client.Preferences.UI
#endregion Backpack #endregion Backpack
#region SpawnPriority
foreach (var value in Enum.GetValues<SpawnPriorityPreference>())
{
_spawnPriorityButton.AddItem(Loc.GetString($"humanoid-profile-editor-preference-spawn-priority-{value.ToString().ToLower()}"), (int) value);
}
_spawnPriorityButton.OnItemSelected += args =>
{
_spawnPriorityButton.SelectId(args.Id);
SetSpawnPriority((SpawnPriorityPreference) args.Id);
};
#endregion SpawnPriority
#region Eyes #region Eyes
_eyesPicker.OnEyeColorPicked += newColor => _eyesPicker.OnEyeColorPicked += newColor =>
@@ -799,6 +815,12 @@ namespace Content.Client.Preferences.UI
IsDirty = true; IsDirty = true;
} }
private void SetSpawnPriority(SpawnPriorityPreference newSpawnPriority)
{
Profile = Profile?.WithSpawnPriorityPreference(newSpawnPriority);
IsDirty = true;
}
public void Save() public void Save()
{ {
IsDirty = false; IsDirty = false;
@@ -974,6 +996,16 @@ namespace Content.Client.Preferences.UI
_backpackButton.SelectId((int) Profile.Backpack); _backpackButton.SelectId((int) Profile.Backpack);
} }
private void UpdateSpawnPriorityControls()
{
if (Profile == null)
{
return;
}
_spawnPriorityButton.SelectId((int) Profile.SpawnPriority);
}
private void UpdateHairPickers() private void UpdateHairPickers()
{ {
if (Profile == null) if (Profile == null)
@@ -1113,6 +1145,7 @@ namespace Content.Client.Preferences.UI
UpdateSpecies(); UpdateSpecies();
UpdateClothingControls(); UpdateClothingControls();
UpdateBackpackControls(); UpdateBackpackControls();
UpdateSpawnPriorityControls();
UpdateAgeEdit(); UpdateAgeEdit();
UpdateEyePickers(); UpdateEyePickers();
UpdateSaveButton(); UpdateSaveButton();

View File

@@ -56,6 +56,7 @@ namespace Content.IntegrationTests.Tests.Preferences
), ),
ClothingPreference.Jumpskirt, ClothingPreference.Jumpskirt,
BackpackPreference.Backpack, BackpackPreference.Backpack,
SpawnPriorityPreference.Arrivals,
new Dictionary<string, JobPriority> new Dictionary<string, JobPriority>
{ {
{SharedGameTicker.FallbackOverflowJob, JobPriority.High} {SharedGameTicker.FallbackOverflowJob, JobPriority.High}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,29 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Content.Server.Database.Migrations.Postgres
{
/// <inheritdoc />
public partial class SpawnPriorityPreference : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<int>(
name: "spawn_priority",
table: "profile",
type: "integer",
nullable: false,
defaultValue: 0);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "spawn_priority",
table: "profile");
}
}
}

View File

@@ -7,6 +7,7 @@ using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion; using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
using NpgsqlTypes;
#nullable disable #nullable disable
@@ -19,7 +20,7 @@ namespace Content.Server.Database.Migrations.Postgres
{ {
#pragma warning disable 612, 618 #pragma warning disable 612, 618
modelBuilder modelBuilder
.HasAnnotation("ProductVersion", "7.0.4") .HasAnnotation("ProductVersion", "8.0.0")
.HasAnnotation("Relational:MaxIdentifierLength", 63); .HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
@@ -803,6 +804,10 @@ namespace Content.Server.Database.Migrations.Postgres
.HasColumnType("integer") .HasColumnType("integer")
.HasColumnName("slot"); .HasColumnName("slot");
b.Property<int>("SpawnPriority")
.HasColumnType("integer")
.HasColumnName("spawn_priority");
b.Property<string>("Species") b.Property<string>("Species")
.IsRequired() .IsRequired()
.HasColumnType("text") .HasColumnType("text")
@@ -879,7 +884,7 @@ namespace Content.Server.Database.Migrations.Postgres
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id")); NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<ValueTuple<IPAddress, int>?>("Address") b.Property<NpgsqlInet?>("Address")
.HasColumnType("inet") .HasColumnType("inet")
.HasColumnName("address"); .HasColumnName("address");
@@ -1021,7 +1026,7 @@ namespace Content.Server.Database.Migrations.Postgres
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id")); NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<ValueTuple<IPAddress, int>?>("Address") b.Property<NpgsqlInet?>("Address")
.HasColumnType("inet") .HasColumnType("inet")
.HasColumnName("address"); .HasColumnName("address");

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,29 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Content.Server.Database.Migrations.Sqlite
{
/// <inheritdoc />
public partial class SpawnPriorityPreference : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<int>(
name: "spawn_priority",
table: "profile",
type: "INTEGER",
nullable: false,
defaultValue: 0);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "spawn_priority",
table: "profile");
}
}
}

View File

@@ -15,7 +15,7 @@ namespace Content.Server.Database.Migrations.Sqlite
protected override void BuildModel(ModelBuilder modelBuilder) protected override void BuildModel(ModelBuilder modelBuilder)
{ {
#pragma warning disable 612, 618 #pragma warning disable 612, 618
modelBuilder.HasAnnotation("ProductVersion", "7.0.4"); modelBuilder.HasAnnotation("ProductVersion", "8.0.0");
modelBuilder.Entity("Content.Server.Database.Admin", b => modelBuilder.Entity("Content.Server.Database.Admin", b =>
{ {
@@ -757,6 +757,10 @@ namespace Content.Server.Database.Migrations.Sqlite
.HasColumnType("INTEGER") .HasColumnType("INTEGER")
.HasColumnName("slot"); .HasColumnName("slot");
b.Property<int>("SpawnPriority")
.HasColumnType("INTEGER")
.HasColumnName("spawn_priority");
b.Property<string>("Species") b.Property<string>("Species")
.IsRequired() .IsRequired()
.HasColumnType("TEXT") .HasColumnType("TEXT")

View File

@@ -338,6 +338,7 @@ namespace Content.Server.Database
public string SkinColor { get; set; } = null!; public string SkinColor { get; set; } = null!;
public string Clothing { get; set; } = null!; public string Clothing { get; set; } = null!;
public string Backpack { get; set; } = null!; public string Backpack { get; set; } = null!;
public int SpawnPriority { get; set; } = 0;
public List<Job> Jobs { get; } = new(); public List<Job> Jobs { get; } = new();
public List<Antag> Antags { get; } = new(); public List<Antag> Antags { get; } = new();
public List<Trait> Traits { get; } = new(); public List<Trait> Traits { get; } = new();

View File

@@ -186,6 +186,8 @@ namespace Content.Server.Database
if (Enum.TryParse<BackpackPreference>(profile.Backpack, true, out var backpackVal)) if (Enum.TryParse<BackpackPreference>(profile.Backpack, true, out var backpackVal))
backpack = backpackVal; backpack = backpackVal;
var spawnPriority = (SpawnPriorityPreference) profile.SpawnPriority;
var gender = sex == Sex.Male ? Gender.Male : Gender.Female; var gender = sex == Sex.Male ? Gender.Male : Gender.Female;
if (Enum.TryParse<Gender>(profile.Gender, true, out var genderVal)) if (Enum.TryParse<Gender>(profile.Gender, true, out var genderVal))
gender = genderVal; gender = genderVal;
@@ -225,6 +227,7 @@ namespace Content.Server.Database
), ),
clothing, clothing,
backpack, backpack,
spawnPriority,
jobs, jobs,
(PreferenceUnavailableMode) profile.PreferenceUnavailable, (PreferenceUnavailableMode) profile.PreferenceUnavailable,
antags.ToList(), antags.ToList(),

View File

@@ -12,7 +12,6 @@ using Content.Server.Screens.Components;
using Content.Server.Shuttles.Components; using Content.Server.Shuttles.Components;
using Content.Server.Shuttles.Events; using Content.Server.Shuttles.Events;
using Content.Server.Spawners.Components; using Content.Server.Spawners.Components;
using Content.Server.Spawners.EntitySystems;
using Content.Server.Station.Components; using Content.Server.Station.Components;
using Content.Server.Station.Systems; using Content.Server.Station.Systems;
using Content.Shared.Administration; using Content.Shared.Administration;
@@ -82,7 +81,6 @@ public sealed class ArrivalsSystem : EntitySystem
{ {
base.Initialize(); base.Initialize();
SubscribeLocalEvent<PlayerSpawningEvent>(OnPlayerSpawn, before: new[] { typeof(SpawnPointSystem), typeof(ContainerSpawnPointSystem) });
SubscribeLocalEvent<StationArrivalsComponent, ComponentStartup>(OnArrivalsStartup); SubscribeLocalEvent<StationArrivalsComponent, ComponentStartup>(OnArrivalsStartup);
SubscribeLocalEvent<ArrivalsShuttleComponent, ComponentStartup>(OnShuttleStartup); SubscribeLocalEvent<ArrivalsShuttleComponent, ComponentStartup>(OnShuttleStartup);
@@ -314,7 +312,7 @@ public sealed class ArrivalsSystem : EntitySystem
} }
} }
private void OnPlayerSpawn(PlayerSpawningEvent ev) public void HandlePlayerSpawning(PlayerSpawningEvent ev)
{ {
if (ev.SpawnResult != null) if (ev.SpawnResult != null)
return; return;

View File

@@ -1,5 +1,4 @@
using Content.Server.GameTicking; using Content.Server.GameTicking;
using Content.Server.Shuttles.Systems;
using Content.Server.Spawners.Components; using Content.Server.Spawners.Components;
using Content.Server.Station.Systems; using Content.Server.Station.Systems;
using Robust.Server.Containers; using Robust.Server.Containers;
@@ -16,12 +15,7 @@ public sealed class ContainerSpawnPointSystem : EntitySystem
[Dependency] private readonly StationSystem _station = default!; [Dependency] private readonly StationSystem _station = default!;
[Dependency] private readonly StationSpawningSystem _stationSpawning = default!; [Dependency] private readonly StationSpawningSystem _stationSpawning = default!;
public override void Initialize() public void HandlePlayerSpawning(PlayerSpawningEvent args)
{
SubscribeLocalEvent<PlayerSpawningEvent>(OnSpawnPlayer, before: new[] { typeof(SpawnPointSystem) }, after: new[] { typeof(ArrivalsSystem) });
}
private void OnSpawnPlayer(PlayerSpawningEvent args)
{ {
if (args.SpawnResult != null) if (args.SpawnResult != null)
return; return;

View File

@@ -1,5 +1,4 @@
using Content.Server.GameTicking; using Content.Server.GameTicking;
using Content.Server.Shuttles.Systems;
using Content.Server.Spawners.Components; using Content.Server.Spawners.Components;
using Content.Server.Station.Systems; using Content.Server.Station.Systems;
using Robust.Shared.Map; using Robust.Shared.Map;
@@ -16,10 +15,10 @@ public sealed class SpawnPointSystem : EntitySystem
public override void Initialize() public override void Initialize()
{ {
SubscribeLocalEvent<PlayerSpawningEvent>(OnSpawnPlayer, after: new[] { typeof(ContainerSpawnPointSystem), typeof(ArrivalsSystem) }); SubscribeLocalEvent<PlayerSpawningEvent>(OnPlayerSpawning);
} }
private void OnSpawnPlayer(PlayerSpawningEvent args) private void OnPlayerSpawning(PlayerSpawningEvent args)
{ {
if (args.SpawnResult != null) if (args.SpawnResult != null)
return; return;

View File

@@ -4,6 +4,8 @@ using Content.Server.Humanoid;
using Content.Server.IdentityManagement; using Content.Server.IdentityManagement;
using Content.Server.Mind.Commands; using Content.Server.Mind.Commands;
using Content.Server.PDA; using Content.Server.PDA;
using Content.Server.Shuttles.Systems;
using Content.Server.Spawners.EntitySystems;
using Content.Server.Station.Components; using Content.Server.Station.Components;
using Content.Shared.Access.Components; using Content.Shared.Access.Components;
using Content.Shared.Access.Systems; using Content.Shared.Access.Systems;
@@ -44,12 +46,23 @@ public sealed class StationSpawningSystem : SharedStationSpawningSystem
[Dependency] private readonly IdentitySystem _identity = default!; [Dependency] private readonly IdentitySystem _identity = default!;
[Dependency] private readonly MetaDataSystem _metaSystem = default!; [Dependency] private readonly MetaDataSystem _metaSystem = default!;
[Dependency] private readonly ArrivalsSystem _arrivalsSystem = default!;
[Dependency] private readonly ContainerSpawnPointSystem _containerSpawnPointSystem = default!;
private bool _randomizeCharacters; private bool _randomizeCharacters;
private Dictionary<SpawnPriorityPreference, Action<PlayerSpawningEvent>> _spawnerCallbacks = new();
/// <inheritdoc/> /// <inheritdoc/>
public override void Initialize() public override void Initialize()
{ {
_configurationManager.OnValueChanged(CCVars.ICRandomCharacters, e => _randomizeCharacters = e, true); _configurationManager.OnValueChanged(CCVars.ICRandomCharacters, e => _randomizeCharacters = e, true);
_spawnerCallbacks = new Dictionary<SpawnPriorityPreference, Action<PlayerSpawningEvent>>()
{
{ SpawnPriorityPreference.Arrivals, _arrivalsSystem.HandlePlayerSpawning },
{ SpawnPriorityPreference.Cryosleep, _containerSpawnPointSystem.HandlePlayerSpawning }
};
} }
/// <summary> /// <summary>
@@ -70,6 +83,30 @@ public sealed class StationSpawningSystem : SharedStationSpawningSystem
throw new ArgumentException("Tried to use a non-station entity as a station!", nameof(station)); throw new ArgumentException("Tried to use a non-station entity as a station!", nameof(station));
var ev = new PlayerSpawningEvent(job, profile, station); var ev = new PlayerSpawningEvent(job, profile, station);
if (station != null && profile != null)
{
/// Try to call the character's preferred spawner first.
if (_spawnerCallbacks.TryGetValue(profile.SpawnPriority, out var preferredSpawner))
{
preferredSpawner(ev);
foreach (var (key, remainingSpawner) in _spawnerCallbacks)
{
if (key == profile.SpawnPriority)
continue;
remainingSpawner(ev);
}
}
else
{
/// Call all of them in the typical order.
foreach (var typicalSpawner in _spawnerCallbacks.Values)
typicalSpawner(ev);
}
}
RaiseLocalEvent(ev); RaiseLocalEvent(ev);
DebugTools.Assert(ev.SpawnResult is { Valid: true } or null); DebugTools.Assert(ev.SpawnResult is { Valid: true } or null);

View File

@@ -41,6 +41,7 @@ namespace Content.Shared.Preferences
HumanoidCharacterAppearance appearance, HumanoidCharacterAppearance appearance,
ClothingPreference clothing, ClothingPreference clothing,
BackpackPreference backpack, BackpackPreference backpack,
SpawnPriorityPreference spawnPriority,
Dictionary<string, JobPriority> jobPriorities, Dictionary<string, JobPriority> jobPriorities,
PreferenceUnavailableMode preferenceUnavailable, PreferenceUnavailableMode preferenceUnavailable,
List<string> antagPreferences, List<string> antagPreferences,
@@ -55,6 +56,7 @@ namespace Content.Shared.Preferences
Appearance = appearance; Appearance = appearance;
Clothing = clothing; Clothing = clothing;
Backpack = backpack; Backpack = backpack;
SpawnPriority = spawnPriority;
_jobPriorities = jobPriorities; _jobPriorities = jobPriorities;
PreferenceUnavailable = preferenceUnavailable; PreferenceUnavailable = preferenceUnavailable;
_antagPreferences = antagPreferences; _antagPreferences = antagPreferences;
@@ -67,7 +69,7 @@ namespace Content.Shared.Preferences
Dictionary<string, JobPriority> jobPriorities, Dictionary<string, JobPriority> jobPriorities,
List<string> antagPreferences, List<string> antagPreferences,
List<string> traitPreferences) List<string> traitPreferences)
: this(other.Name, other.FlavorText, other.Species, other.Age, other.Sex, other.Gender, other.Appearance, other.Clothing, other.Backpack, : this(other.Name, other.FlavorText, other.Species, other.Age, other.Sex, other.Gender, other.Appearance, other.Clothing, other.Backpack, other.SpawnPriority,
jobPriorities, other.PreferenceUnavailable, antagPreferences, traitPreferences) jobPriorities, other.PreferenceUnavailable, antagPreferences, traitPreferences)
{ {
} }
@@ -88,11 +90,12 @@ namespace Content.Shared.Preferences
HumanoidCharacterAppearance appearance, HumanoidCharacterAppearance appearance,
ClothingPreference clothing, ClothingPreference clothing,
BackpackPreference backpack, BackpackPreference backpack,
SpawnPriorityPreference spawnPriority,
IReadOnlyDictionary<string, JobPriority> jobPriorities, IReadOnlyDictionary<string, JobPriority> jobPriorities,
PreferenceUnavailableMode preferenceUnavailable, PreferenceUnavailableMode preferenceUnavailable,
IReadOnlyList<string> antagPreferences, IReadOnlyList<string> antagPreferences,
IReadOnlyList<string> traitPreferences) IReadOnlyList<string> traitPreferences)
: this(name, flavortext, species, age, sex, gender, appearance, clothing, backpack, new Dictionary<string, JobPriority>(jobPriorities), : this(name, flavortext, species, age, sex, gender, appearance, clothing, backpack, spawnPriority, new Dictionary<string, JobPriority>(jobPriorities),
preferenceUnavailable, new List<string>(antagPreferences), new List<string>(traitPreferences)) preferenceUnavailable, new List<string>(antagPreferences), new List<string>(traitPreferences))
{ {
} }
@@ -112,6 +115,7 @@ namespace Content.Shared.Preferences
new HumanoidCharacterAppearance(), new HumanoidCharacterAppearance(),
ClothingPreference.Jumpsuit, ClothingPreference.Jumpsuit,
BackpackPreference.Backpack, BackpackPreference.Backpack,
SpawnPriorityPreference.Arrivals,
new Dictionary<string, JobPriority> new Dictionary<string, JobPriority>
{ {
{SharedGameTicker.FallbackOverflowJob, JobPriority.High} {SharedGameTicker.FallbackOverflowJob, JobPriority.High}
@@ -139,6 +143,7 @@ namespace Content.Shared.Preferences
HumanoidCharacterAppearance.DefaultWithSpecies(species), HumanoidCharacterAppearance.DefaultWithSpecies(species),
ClothingPreference.Jumpsuit, ClothingPreference.Jumpsuit,
BackpackPreference.Backpack, BackpackPreference.Backpack,
SpawnPriorityPreference.Arrivals,
new Dictionary<string, JobPriority> new Dictionary<string, JobPriority>
{ {
{SharedGameTicker.FallbackOverflowJob, JobPriority.High} {SharedGameTicker.FallbackOverflowJob, JobPriority.High}
@@ -180,7 +185,7 @@ namespace Content.Shared.Preferences
var name = GetName(species, gender); var name = GetName(species, gender);
return new HumanoidCharacterProfile(name, "", species, age, sex, gender, HumanoidCharacterAppearance.Random(species, sex), ClothingPreference.Jumpsuit, BackpackPreference.Backpack, return new HumanoidCharacterProfile(name, "", species, age, sex, gender, HumanoidCharacterAppearance.Random(species, sex), ClothingPreference.Jumpsuit, BackpackPreference.Backpack, SpawnPriorityPreference.Arrivals,
new Dictionary<string, JobPriority> new Dictionary<string, JobPriority>
{ {
{SharedGameTicker.FallbackOverflowJob, JobPriority.High}, {SharedGameTicker.FallbackOverflowJob, JobPriority.High},
@@ -206,6 +211,7 @@ namespace Content.Shared.Preferences
public HumanoidCharacterAppearance Appearance { get; private set; } public HumanoidCharacterAppearance Appearance { get; private set; }
public ClothingPreference Clothing { get; private set; } public ClothingPreference Clothing { get; private set; }
public BackpackPreference Backpack { get; private set; } public BackpackPreference Backpack { get; private set; }
public SpawnPriorityPreference SpawnPriority { get; private set; }
public IReadOnlyDictionary<string, JobPriority> JobPriorities => _jobPriorities; public IReadOnlyDictionary<string, JobPriority> JobPriorities => _jobPriorities;
public IReadOnlyList<string> AntagPreferences => _antagPreferences; public IReadOnlyList<string> AntagPreferences => _antagPreferences;
public IReadOnlyList<string> TraitPreferences => _traitPreferences; public IReadOnlyList<string> TraitPreferences => _traitPreferences;
@@ -255,6 +261,10 @@ namespace Content.Shared.Preferences
{ {
return new(this) { Backpack = backpack }; return new(this) { Backpack = backpack };
} }
public HumanoidCharacterProfile WithSpawnPriorityPreference(SpawnPriorityPreference spawnPriority)
{
return new(this) { SpawnPriority = spawnPriority };
}
public HumanoidCharacterProfile WithJobPriorities(IEnumerable<KeyValuePair<string, JobPriority>> jobPriorities) public HumanoidCharacterProfile WithJobPriorities(IEnumerable<KeyValuePair<string, JobPriority>> jobPriorities)
{ {
return new(this, new Dictionary<string, JobPriority>(jobPriorities), _antagPreferences, _traitPreferences); return new(this, new Dictionary<string, JobPriority>(jobPriorities), _antagPreferences, _traitPreferences);
@@ -344,6 +354,7 @@ namespace Content.Shared.Preferences
if (PreferenceUnavailable != other.PreferenceUnavailable) return false; if (PreferenceUnavailable != other.PreferenceUnavailable) return false;
if (Clothing != other.Clothing) return false; if (Clothing != other.Clothing) return false;
if (Backpack != other.Backpack) return false; if (Backpack != other.Backpack) return false;
if (SpawnPriority != other.SpawnPriority) return false;
if (!_jobPriorities.SequenceEqual(other._jobPriorities)) return false; if (!_jobPriorities.SequenceEqual(other._jobPriorities)) return false;
if (!_antagPreferences.SequenceEqual(other._antagPreferences)) return false; if (!_antagPreferences.SequenceEqual(other._antagPreferences)) return false;
if (!_traitPreferences.SequenceEqual(other._traitPreferences)) return false; if (!_traitPreferences.SequenceEqual(other._traitPreferences)) return false;
@@ -457,6 +468,13 @@ namespace Content.Shared.Preferences
_ => BackpackPreference.Backpack // Invalid enum values. _ => BackpackPreference.Backpack // Invalid enum values.
}; };
var spawnPriority = SpawnPriority switch
{
SpawnPriorityPreference.Arrivals => SpawnPriorityPreference.Arrivals,
SpawnPriorityPreference.Cryosleep => SpawnPriorityPreference.Cryosleep,
_ => SpawnPriorityPreference.Arrivals // Invalid enum values.
};
var priorities = new Dictionary<string, JobPriority>(JobPriorities var priorities = new Dictionary<string, JobPriority>(JobPriorities
.Where(p => prototypeManager.HasIndex<JobPrototype>(p.Key) && p.Value switch .Where(p => prototypeManager.HasIndex<JobPrototype>(p.Key) && p.Value switch
{ {
@@ -483,6 +501,7 @@ namespace Content.Shared.Preferences
Appearance = appearance; Appearance = appearance;
Clothing = clothing; Clothing = clothing;
Backpack = backpack; Backpack = backpack;
SpawnPriority = spawnPriority;
_jobPriorities.Clear(); _jobPriorities.Clear();
@@ -526,6 +545,7 @@ namespace Content.Shared.Preferences
Clothing, Clothing,
Backpack Backpack
), ),
SpawnPriority,
PreferenceUnavailable, PreferenceUnavailable,
_jobPriorities, _jobPriorities,
_antagPreferences, _antagPreferences,

View File

@@ -0,0 +1,15 @@
namespace Content.Shared.Preferences
{
/// <summary>
/// The spawn priority preference for a profile. Stored in database!
/// </summary>
public enum SpawnPriorityPreference
{
///////////////////////
/// DO NOT TOUCH!!! ///
///////////////////////
None = 0,
Arrivals = 1,
Cryosleep = 2,
}
}

View File

@@ -21,6 +21,7 @@ humanoid-profile-editor-export-button = Export
humanoid-profile-editor-save-button = Save humanoid-profile-editor-save-button = Save
humanoid-profile-editor-clothing-label = Clothing: humanoid-profile-editor-clothing-label = Clothing:
humanoid-profile-editor-backpack-label = Backpack: humanoid-profile-editor-backpack-label = Backpack:
humanoid-profile-editor-spawn-priority-label = Spawn priority:
humanoid-profile-editor-eyes-label = Eye color: humanoid-profile-editor-eyes-label = Eye color:
humanoid-profile-editor-jobs-tab = Jobs humanoid-profile-editor-jobs-tab = Jobs
humanoid-profile-editor-preference-unavailable-stay-in-lobby-button = Stay in lobby if preference unavailable. humanoid-profile-editor-preference-unavailable-stay-in-lobby-button = Stay in lobby if preference unavailable.
@@ -30,6 +31,12 @@ humanoid-profile-editor-preference-jumpskirt = Jumpskirt
humanoid-profile-editor-preference-backpack = Backpack humanoid-profile-editor-preference-backpack = Backpack
humanoid-profile-editor-preference-satchel = Satchel humanoid-profile-editor-preference-satchel = Satchel
humanoid-profile-editor-preference-duffelbag = Duffelbag humanoid-profile-editor-preference-duffelbag = Duffelbag
# Spawn priority
humanoid-profile-editor-preference-spawn-priority-none = None
humanoid-profile-editor-preference-spawn-priority-arrivals = Arrivals
humanoid-profile-editor-preference-spawn-priority-cryosleep = Cryosleep
humanoid-profile-editor-jobs-amount-in-department-tooltip = Jobs in the {$departmentName} department humanoid-profile-editor-jobs-amount-in-department-tooltip = Jobs in the {$departmentName} department
humanoid-profile-editor-department-jobs-label = {$departmentName} jobs humanoid-profile-editor-department-jobs-label = {$departmentName} jobs
humanoid-profile-editor-antags-tab = Antags humanoid-profile-editor-antags-tab = Antags