diff --git a/Content.Client/UserInterface/HumanoidProfileEditor.cs b/Content.Client/UserInterface/HumanoidProfileEditor.cs
index 4c38b7cbee..7558832b0d 100644
--- a/Content.Client/UserInterface/HumanoidProfileEditor.cs
+++ b/Content.Client/UserInterface/HumanoidProfileEditor.cs
@@ -1,4 +1,4 @@
-using Content.Client.GameObjects.Components;
+using Content.Client.GameObjects.Components;
using Content.Client.GameObjects.Components.Mobs;
using Content.Client.Interfaces;
using Content.Shared.GameTicking;
@@ -43,6 +43,7 @@ namespace Content.Client.UserInterface
private readonly Button _sexMaleButton;
private readonly OptionButton _genderButton;
private readonly OptionButton _clothingButton;
+ private readonly OptionButton _backpackButton;
private readonly HairStylePicker _hairPicker;
private readonly FacialHairStylePicker _facialHairPicker;
@@ -333,6 +334,33 @@ namespace Content.Client.UserInterface
}
#endregion Clothing
+
+ #region Backpack
+
+ {
+ var panel = HighlightedContainer();
+ var hBox = new HBoxContainer();
+ var backpackLabel = new Label { Text = Loc.GetString("Backpack:") };
+
+ _backpackButton = new OptionButton();
+
+ _backpackButton.AddItem(Loc.GetString("Backpack"), (int) BackpackPreference.Backpack);
+ _backpackButton.AddItem(Loc.GetString("Satchel"), (int) BackpackPreference.Satchel);
+ _backpackButton.AddItem(Loc.GetString("Duffelbag"), (int) BackpackPreference.Duffelbag);
+
+ _backpackButton.OnItemSelected += args =>
+ {
+ _backpackButton.SelectId(args.Id);
+ SetBackpack((BackpackPreference) args.Id);
+ };
+
+ hBox.AddChild(backpackLabel);
+ hBox.AddChild(_backpackButton);
+ panel.AddChild(hBox);
+ appearanceVBox.AddChild(panel);
+ }
+
+ #endregion Clothing
}
#endregion
@@ -669,6 +697,12 @@ namespace Content.Client.UserInterface
IsDirty = true;
}
+ private void SetBackpack(BackpackPreference newBackpack)
+ {
+ Profile = Profile?.WithBackpackPreference(newBackpack);
+ IsDirty = true;
+ }
+
public void Save()
{
IsDirty = false;
@@ -723,6 +757,11 @@ namespace Content.Client.UserInterface
_clothingButton.SelectId((int) Profile.Clothing);
}
+ private void UpdateBackpackControls()
+ {
+ _backpackButton.SelectId((int) Profile.Backpack);
+ }
+
private void UpdateHairPickers()
{
_hairPicker.SetData(
@@ -754,6 +793,7 @@ namespace Content.Client.UserInterface
UpdateSexControls();
UpdateGenderControls();
UpdateClothingControls();
+ UpdateBackpackControls();
UpdateAgeEdit();
UpdateHairPickers();
UpdateSaveButton();
diff --git a/Content.Server.Database/Migrations/Postgres/20210103151756_BackpackPreference.Designer.cs b/Content.Server.Database/Migrations/Postgres/20210103151756_BackpackPreference.Designer.cs
new file mode 100644
index 0000000000..1a66e59863
--- /dev/null
+++ b/Content.Server.Database/Migrations/Postgres/20210103151756_BackpackPreference.Designer.cs
@@ -0,0 +1,575 @@
+//
+using System;
+using System.Net;
+using Content.Server.Database;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
+
+namespace Content.Server.Database.Migrations.Postgres
+{
+ [DbContext(typeof(PostgresServerDbContext))]
+ [Migration("20210103151756_BackpackPreference")]
+ partial class BackpackPreference
+ {
+ protected override void BuildTargetModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder
+ .UseIdentityByDefaultColumns()
+ .HasAnnotation("Relational:MaxIdentifierLength", 63)
+ .HasAnnotation("ProductVersion", "5.0.0");
+
+ modelBuilder.Entity("Content.Server.Database.Admin", b =>
+ {
+ b.Property("UserId")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uuid")
+ .HasColumnName("user_id");
+
+ b.Property("AdminRankId")
+ .HasColumnType("integer")
+ .HasColumnName("admin_rank_id");
+
+ b.Property("Title")
+ .HasColumnType("text")
+ .HasColumnName("title");
+
+ b.HasKey("UserId");
+
+ b.HasIndex("AdminRankId");
+
+ b.ToTable("admin");
+ });
+
+ modelBuilder.Entity("Content.Server.Database.AdminFlag", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer")
+ .HasColumnName("admin_flag_id")
+ .UseIdentityByDefaultColumn();
+
+ b.Property("AdminId")
+ .HasColumnType("uuid")
+ .HasColumnName("admin_id");
+
+ b.Property("Flag")
+ .IsRequired()
+ .HasColumnType("text")
+ .HasColumnName("flag");
+
+ b.Property("Negative")
+ .HasColumnType("boolean")
+ .HasColumnName("negative");
+
+ b.HasKey("Id");
+
+ b.HasIndex("AdminId");
+
+ b.HasIndex("Flag", "AdminId")
+ .IsUnique();
+
+ b.ToTable("admin_flag");
+ });
+
+ modelBuilder.Entity("Content.Server.Database.AdminRank", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer")
+ .HasColumnName("admin_rank_id")
+ .UseIdentityByDefaultColumn();
+
+ b.Property("Name")
+ .IsRequired()
+ .HasColumnType("text")
+ .HasColumnName("name");
+
+ b.HasKey("Id");
+
+ b.ToTable("admin_rank");
+ });
+
+ modelBuilder.Entity("Content.Server.Database.AdminRankFlag", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer")
+ .HasColumnName("admin_rank_flag_id")
+ .UseIdentityByDefaultColumn();
+
+ b.Property("AdminRankId")
+ .HasColumnType("integer")
+ .HasColumnName("admin_rank_id");
+
+ b.Property("Flag")
+ .IsRequired()
+ .HasColumnType("text")
+ .HasColumnName("flag");
+
+ b.HasKey("Id");
+
+ b.HasIndex("AdminRankId");
+
+ b.HasIndex("Flag", "AdminRankId")
+ .IsUnique();
+
+ b.ToTable("admin_rank_flag");
+ });
+
+ modelBuilder.Entity("Content.Server.Database.Antag", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer")
+ .HasColumnName("antag_id")
+ .UseIdentityByDefaultColumn();
+
+ b.Property("AntagName")
+ .IsRequired()
+ .HasColumnType("text")
+ .HasColumnName("antag_name");
+
+ b.Property("ProfileId")
+ .HasColumnType("integer")
+ .HasColumnName("profile_id");
+
+ b.HasKey("Id");
+
+ b.HasIndex("ProfileId", "AntagName")
+ .IsUnique();
+
+ b.ToTable("antag");
+ });
+
+ modelBuilder.Entity("Content.Server.Database.AssignedUserId", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer")
+ .HasColumnName("assigned_user_id_id")
+ .UseIdentityByDefaultColumn();
+
+ b.Property("UserId")
+ .HasColumnType("uuid")
+ .HasColumnName("user_id");
+
+ b.Property("UserName")
+ .IsRequired()
+ .HasColumnType("text")
+ .HasColumnName("user_name");
+
+ b.HasKey("Id");
+
+ b.HasIndex("UserId")
+ .IsUnique();
+
+ b.HasIndex("UserName")
+ .IsUnique();
+
+ b.ToTable("assigned_user_id");
+ });
+
+ modelBuilder.Entity("Content.Server.Database.Job", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer")
+ .HasColumnName("job_id")
+ .UseIdentityByDefaultColumn();
+
+ b.Property("JobName")
+ .IsRequired()
+ .HasColumnType("text")
+ .HasColumnName("job_name");
+
+ b.Property("Priority")
+ .HasColumnType("integer")
+ .HasColumnName("priority");
+
+ b.Property("ProfileId")
+ .HasColumnType("integer")
+ .HasColumnName("profile_id");
+
+ b.HasKey("Id");
+
+ b.HasIndex("ProfileId");
+
+ b.ToTable("job");
+ });
+
+ modelBuilder.Entity("Content.Server.Database.PostgresConnectionLog", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer")
+ .HasColumnName("connection_log_id")
+ .UseIdentityByDefaultColumn();
+
+ b.Property("Address")
+ .IsRequired()
+ .HasColumnType("inet")
+ .HasColumnName("address");
+
+ b.Property("Time")
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("time");
+
+ b.Property("UserId")
+ .HasColumnType("uuid")
+ .HasColumnName("user_id");
+
+ b.Property("UserName")
+ .IsRequired()
+ .HasColumnType("text")
+ .HasColumnName("user_name");
+
+ b.HasKey("Id");
+
+ b.HasIndex("UserId");
+
+ b.ToTable("connection_log");
+
+ b.HasCheckConstraint("AddressNotIPv6MappedIPv4", "NOT inet '::ffff:0.0.0.0/96' >>= address");
+ });
+
+ modelBuilder.Entity("Content.Server.Database.PostgresPlayer", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer")
+ .HasColumnName("player_id")
+ .UseIdentityByDefaultColumn();
+
+ b.Property("FirstSeenTime")
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("first_seen_time");
+
+ b.Property("LastSeenAddress")
+ .IsRequired()
+ .HasColumnType("inet")
+ .HasColumnName("last_seen_address");
+
+ b.Property("LastSeenTime")
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("last_seen_time");
+
+ b.Property("LastSeenUserName")
+ .IsRequired()
+ .HasColumnType("text")
+ .HasColumnName("last_seen_user_name");
+
+ b.Property("UserId")
+ .HasColumnType("uuid")
+ .HasColumnName("user_id");
+
+ b.HasKey("Id");
+
+ b.HasIndex("LastSeenUserName");
+
+ b.HasIndex("UserId")
+ .IsUnique();
+
+ b.ToTable("player");
+
+ b.HasCheckConstraint("LastSeenAddressNotIPv6MappedIPv4", "NOT inet '::ffff:0.0.0.0/96' >>= last_seen_address");
+ });
+
+ modelBuilder.Entity("Content.Server.Database.PostgresServerBan", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer")
+ .HasColumnName("server_ban_id")
+ .UseIdentityByDefaultColumn();
+
+ b.Property?>("Address")
+ .HasColumnType("inet")
+ .HasColumnName("address");
+
+ b.Property("BanTime")
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("ban_time");
+
+ b.Property("BanningAdmin")
+ .HasColumnType("uuid")
+ .HasColumnName("banning_admin");
+
+ b.Property("ExpirationTime")
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("expiration_time");
+
+ b.Property("Reason")
+ .IsRequired()
+ .HasColumnType("text")
+ .HasColumnName("reason");
+
+ b.Property("UserId")
+ .HasColumnType("uuid")
+ .HasColumnName("user_id");
+
+ b.HasKey("Id");
+
+ b.HasIndex("Address");
+
+ b.HasIndex("UserId");
+
+ b.ToTable("server_ban");
+
+ b.HasCheckConstraint("AddressNotIPv6MappedIPv4", "NOT inet '::ffff:0.0.0.0/96' >>= address");
+
+ b.HasCheckConstraint("HaveEitherAddressOrUserId", "address IS NOT NULL OR user_id IS NOT NULL");
+ });
+
+ modelBuilder.Entity("Content.Server.Database.PostgresServerUnban", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer")
+ .HasColumnName("unban_id")
+ .UseIdentityByDefaultColumn();
+
+ b.Property("BanId")
+ .HasColumnType("integer")
+ .HasColumnName("ban_id");
+
+ b.Property("UnbanTime")
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("unban_time");
+
+ b.Property("UnbanningAdmin")
+ .HasColumnType("uuid")
+ .HasColumnName("unbanning_admin");
+
+ b.HasKey("Id");
+
+ b.HasIndex("BanId")
+ .IsUnique();
+
+ b.ToTable("server_unban");
+ });
+
+ modelBuilder.Entity("Content.Server.Database.Preference", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer")
+ .HasColumnName("preference_id")
+ .UseIdentityByDefaultColumn();
+
+ b.Property("SelectedCharacterSlot")
+ .HasColumnType("integer")
+ .HasColumnName("selected_character_slot");
+
+ b.Property("UserId")
+ .HasColumnType("uuid")
+ .HasColumnName("user_id");
+
+ b.HasKey("Id");
+
+ b.HasIndex("UserId")
+ .IsUnique();
+
+ b.ToTable("preference");
+ });
+
+ modelBuilder.Entity("Content.Server.Database.Profile", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer")
+ .HasColumnName("profile_id")
+ .UseIdentityByDefaultColumn();
+
+ b.Property("Age")
+ .HasColumnType("integer")
+ .HasColumnName("age");
+
+ b.Property("Backpack")
+ .IsRequired()
+ .HasColumnType("text")
+ .HasColumnName("backpack");
+
+ b.Property("CharacterName")
+ .IsRequired()
+ .HasColumnType("text")
+ .HasColumnName("char_name");
+
+ b.Property("Clothing")
+ .IsRequired()
+ .HasColumnType("text")
+ .HasColumnName("clothing");
+
+ b.Property("EyeColor")
+ .IsRequired()
+ .HasColumnType("text")
+ .HasColumnName("eye_color");
+
+ b.Property("FacialHairColor")
+ .IsRequired()
+ .HasColumnType("text")
+ .HasColumnName("facial_hair_color");
+
+ b.Property("FacialHairName")
+ .IsRequired()
+ .HasColumnType("text")
+ .HasColumnName("facial_hair_name");
+
+ b.Property("Gender")
+ .IsRequired()
+ .HasColumnType("text")
+ .HasColumnName("gender");
+
+ b.Property("HairColor")
+ .IsRequired()
+ .HasColumnType("text")
+ .HasColumnName("hair_color");
+
+ b.Property("HairName")
+ .IsRequired()
+ .HasColumnType("text")
+ .HasColumnName("hair_name");
+
+ b.Property("PreferenceId")
+ .HasColumnType("integer")
+ .HasColumnName("preference_id");
+
+ b.Property("PreferenceUnavailable")
+ .HasColumnType("integer")
+ .HasColumnName("pref_unavailable");
+
+ b.Property("Sex")
+ .IsRequired()
+ .HasColumnType("text")
+ .HasColumnName("sex");
+
+ b.Property("SkinColor")
+ .IsRequired()
+ .HasColumnType("text")
+ .HasColumnName("skin_color");
+
+ b.Property("Slot")
+ .HasColumnType("integer")
+ .HasColumnName("slot");
+
+ b.HasKey("Id");
+
+ b.HasIndex("PreferenceId");
+
+ b.HasIndex("Slot", "PreferenceId")
+ .IsUnique();
+
+ b.ToTable("profile");
+ });
+
+ modelBuilder.Entity("Content.Server.Database.Admin", b =>
+ {
+ b.HasOne("Content.Server.Database.AdminRank", "AdminRank")
+ .WithMany("Admins")
+ .HasForeignKey("AdminRankId")
+ .OnDelete(DeleteBehavior.SetNull);
+
+ b.Navigation("AdminRank");
+ });
+
+ modelBuilder.Entity("Content.Server.Database.AdminFlag", b =>
+ {
+ b.HasOne("Content.Server.Database.Admin", "Admin")
+ .WithMany("Flags")
+ .HasForeignKey("AdminId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Admin");
+ });
+
+ modelBuilder.Entity("Content.Server.Database.AdminRankFlag", b =>
+ {
+ b.HasOne("Content.Server.Database.AdminRank", "Rank")
+ .WithMany("Flags")
+ .HasForeignKey("AdminRankId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Rank");
+ });
+
+ modelBuilder.Entity("Content.Server.Database.Antag", b =>
+ {
+ b.HasOne("Content.Server.Database.Profile", "Profile")
+ .WithMany("Antags")
+ .HasForeignKey("ProfileId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Profile");
+ });
+
+ modelBuilder.Entity("Content.Server.Database.Job", b =>
+ {
+ b.HasOne("Content.Server.Database.Profile", "Profile")
+ .WithMany("Jobs")
+ .HasForeignKey("ProfileId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Profile");
+ });
+
+ modelBuilder.Entity("Content.Server.Database.PostgresServerUnban", b =>
+ {
+ b.HasOne("Content.Server.Database.PostgresServerBan", "Ban")
+ .WithOne("Unban")
+ .HasForeignKey("Content.Server.Database.PostgresServerUnban", "BanId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Ban");
+ });
+
+ modelBuilder.Entity("Content.Server.Database.Profile", b =>
+ {
+ b.HasOne("Content.Server.Database.Preference", "Preference")
+ .WithMany("Profiles")
+ .HasForeignKey("PreferenceId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Preference");
+ });
+
+ modelBuilder.Entity("Content.Server.Database.Admin", b =>
+ {
+ b.Navigation("Flags");
+ });
+
+ modelBuilder.Entity("Content.Server.Database.AdminRank", b =>
+ {
+ b.Navigation("Admins");
+
+ b.Navigation("Flags");
+ });
+
+ modelBuilder.Entity("Content.Server.Database.PostgresServerBan", b =>
+ {
+ b.Navigation("Unban");
+ });
+
+ modelBuilder.Entity("Content.Server.Database.Preference", b =>
+ {
+ b.Navigation("Profiles");
+ });
+
+ modelBuilder.Entity("Content.Server.Database.Profile", b =>
+ {
+ b.Navigation("Antags");
+
+ b.Navigation("Jobs");
+ });
+#pragma warning restore 612, 618
+ }
+ }
+}
diff --git a/Content.Server.Database/Migrations/Postgres/20210103151756_BackpackPreference.cs b/Content.Server.Database/Migrations/Postgres/20210103151756_BackpackPreference.cs
new file mode 100644
index 0000000000..0c5a7356bb
--- /dev/null
+++ b/Content.Server.Database/Migrations/Postgres/20210103151756_BackpackPreference.cs
@@ -0,0 +1,24 @@
+using Microsoft.EntityFrameworkCore.Migrations;
+
+namespace Content.Server.Database.Migrations.Postgres
+{
+ public partial class BackpackPreference : Migration
+ {
+ protected override void Up(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.AddColumn(
+ name: "backpack",
+ table: "profile",
+ type: "text",
+ nullable: false,
+ defaultValue: "");
+ }
+
+ protected override void Down(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.DropColumn(
+ name: "backpack",
+ table: "profile");
+ }
+ }
+}
diff --git a/Content.Server.Database/Migrations/Postgres/PostgresServerDbContextModelSnapshot.cs b/Content.Server.Database/Migrations/Postgres/PostgresServerDbContextModelSnapshot.cs
index 589940e4a6..b7a48063b5 100644
--- a/Content.Server.Database/Migrations/Postgres/PostgresServerDbContextModelSnapshot.cs
+++ b/Content.Server.Database/Migrations/Postgres/PostgresServerDbContextModelSnapshot.cs
@@ -386,6 +386,11 @@ namespace Content.Server.Database.Migrations.Postgres
.HasColumnType("integer")
.HasColumnName("age");
+ b.Property("Backpack")
+ .IsRequired()
+ .HasColumnType("text")
+ .HasColumnName("backpack");
+
b.Property("CharacterName")
.IsRequired()
.HasColumnType("text")
diff --git a/Content.Server.Database/Migrations/Sqlite/20210103151752_BackpackPreference.Designer.cs b/Content.Server.Database/Migrations/Sqlite/20210103151752_BackpackPreference.Designer.cs
new file mode 100644
index 0000000000..661cfbc318
--- /dev/null
+++ b/Content.Server.Database/Migrations/Sqlite/20210103151752_BackpackPreference.Designer.cs
@@ -0,0 +1,542 @@
+//
+using System;
+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.Sqlite
+{
+ [DbContext(typeof(SqliteServerDbContext))]
+ [Migration("20210103151752_BackpackPreference")]
+ partial class BackpackPreference
+ {
+ protected override void BuildTargetModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder
+ .HasAnnotation("ProductVersion", "5.0.0");
+
+ modelBuilder.Entity("Content.Server.Database.Admin", b =>
+ {
+ b.Property("UserId")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("TEXT")
+ .HasColumnName("user_id");
+
+ b.Property("AdminRankId")
+ .HasColumnType("INTEGER")
+ .HasColumnName("admin_rank_id");
+
+ b.Property("Title")
+ .HasColumnType("TEXT")
+ .HasColumnName("title");
+
+ b.HasKey("UserId");
+
+ b.HasIndex("AdminRankId");
+
+ b.ToTable("admin");
+ });
+
+ modelBuilder.Entity("Content.Server.Database.AdminFlag", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("INTEGER")
+ .HasColumnName("admin_flag_id");
+
+ b.Property("AdminId")
+ .HasColumnType("TEXT")
+ .HasColumnName("admin_id");
+
+ b.Property("Flag")
+ .IsRequired()
+ .HasColumnType("TEXT")
+ .HasColumnName("flag");
+
+ b.Property("Negative")
+ .HasColumnType("INTEGER")
+ .HasColumnName("negative");
+
+ b.HasKey("Id");
+
+ b.HasIndex("AdminId");
+
+ b.HasIndex("Flag", "AdminId")
+ .IsUnique();
+
+ b.ToTable("admin_flag");
+ });
+
+ modelBuilder.Entity("Content.Server.Database.AdminRank", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("INTEGER")
+ .HasColumnName("admin_rank_id");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasColumnType("TEXT")
+ .HasColumnName("name");
+
+ b.HasKey("Id");
+
+ b.ToTable("admin_rank");
+ });
+
+ modelBuilder.Entity("Content.Server.Database.AdminRankFlag", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("INTEGER")
+ .HasColumnName("admin_rank_flag_id");
+
+ b.Property("AdminRankId")
+ .HasColumnType("INTEGER")
+ .HasColumnName("admin_rank_id");
+
+ b.Property("Flag")
+ .IsRequired()
+ .HasColumnType("TEXT")
+ .HasColumnName("flag");
+
+ b.HasKey("Id");
+
+ b.HasIndex("AdminRankId");
+
+ b.HasIndex("Flag", "AdminRankId")
+ .IsUnique();
+
+ b.ToTable("admin_rank_flag");
+ });
+
+ modelBuilder.Entity("Content.Server.Database.Antag", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("INTEGER")
+ .HasColumnName("antag_id");
+
+ b.Property("AntagName")
+ .IsRequired()
+ .HasColumnType("TEXT")
+ .HasColumnName("antag_name");
+
+ b.Property("ProfileId")
+ .HasColumnType("INTEGER")
+ .HasColumnName("profile_id");
+
+ b.HasKey("Id");
+
+ b.HasIndex("ProfileId", "AntagName")
+ .IsUnique();
+
+ b.ToTable("antag");
+ });
+
+ modelBuilder.Entity("Content.Server.Database.AssignedUserId", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("INTEGER")
+ .HasColumnName("assigned_user_id_id");
+
+ b.Property("UserId")
+ .HasColumnType("TEXT")
+ .HasColumnName("user_id");
+
+ b.Property("UserName")
+ .IsRequired()
+ .HasColumnType("TEXT")
+ .HasColumnName("user_name");
+
+ b.HasKey("Id");
+
+ b.HasIndex("UserId")
+ .IsUnique();
+
+ b.HasIndex("UserName")
+ .IsUnique();
+
+ b.ToTable("assigned_user_id");
+ });
+
+ modelBuilder.Entity("Content.Server.Database.Job", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("INTEGER")
+ .HasColumnName("job_id");
+
+ b.Property("JobName")
+ .IsRequired()
+ .HasColumnType("TEXT")
+ .HasColumnName("job_name");
+
+ b.Property("Priority")
+ .HasColumnType("INTEGER")
+ .HasColumnName("priority");
+
+ b.Property("ProfileId")
+ .HasColumnType("INTEGER")
+ .HasColumnName("profile_id");
+
+ b.HasKey("Id");
+
+ b.HasIndex("ProfileId");
+
+ b.ToTable("job");
+ });
+
+ modelBuilder.Entity("Content.Server.Database.Preference", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("INTEGER")
+ .HasColumnName("preference_id");
+
+ b.Property("SelectedCharacterSlot")
+ .HasColumnType("INTEGER")
+ .HasColumnName("selected_character_slot");
+
+ b.Property("UserId")
+ .HasColumnType("TEXT")
+ .HasColumnName("user_id");
+
+ b.HasKey("Id");
+
+ b.HasIndex("UserId")
+ .IsUnique();
+
+ b.ToTable("preference");
+ });
+
+ modelBuilder.Entity("Content.Server.Database.Profile", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("INTEGER")
+ .HasColumnName("profile_id");
+
+ b.Property("Age")
+ .HasColumnType("INTEGER")
+ .HasColumnName("age");
+
+ b.Property("Backpack")
+ .IsRequired()
+ .HasColumnType("TEXT")
+ .HasColumnName("backpack");
+
+ b.Property("CharacterName")
+ .IsRequired()
+ .HasColumnType("TEXT")
+ .HasColumnName("char_name");
+
+ b.Property("Clothing")
+ .IsRequired()
+ .HasColumnType("TEXT")
+ .HasColumnName("clothing");
+
+ b.Property("EyeColor")
+ .IsRequired()
+ .HasColumnType("TEXT")
+ .HasColumnName("eye_color");
+
+ b.Property("FacialHairColor")
+ .IsRequired()
+ .HasColumnType("TEXT")
+ .HasColumnName("facial_hair_color");
+
+ b.Property("FacialHairName")
+ .IsRequired()
+ .HasColumnType("TEXT")
+ .HasColumnName("facial_hair_name");
+
+ b.Property("Gender")
+ .IsRequired()
+ .HasColumnType("TEXT")
+ .HasColumnName("gender");
+
+ b.Property("HairColor")
+ .IsRequired()
+ .HasColumnType("TEXT")
+ .HasColumnName("hair_color");
+
+ b.Property("HairName")
+ .IsRequired()
+ .HasColumnType("TEXT")
+ .HasColumnName("hair_name");
+
+ b.Property("PreferenceId")
+ .HasColumnType("INTEGER")
+ .HasColumnName("preference_id");
+
+ b.Property("PreferenceUnavailable")
+ .HasColumnType("INTEGER")
+ .HasColumnName("pref_unavailable");
+
+ b.Property("Sex")
+ .IsRequired()
+ .HasColumnType("TEXT")
+ .HasColumnName("sex");
+
+ b.Property("SkinColor")
+ .IsRequired()
+ .HasColumnType("TEXT")
+ .HasColumnName("skin_color");
+
+ b.Property("Slot")
+ .HasColumnType("INTEGER")
+ .HasColumnName("slot");
+
+ b.HasKey("Id");
+
+ b.HasIndex("PreferenceId");
+
+ b.HasIndex("Slot", "PreferenceId")
+ .IsUnique();
+
+ b.ToTable("profile");
+ });
+
+ modelBuilder.Entity("Content.Server.Database.SqliteConnectionLog", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("INTEGER")
+ .HasColumnName("connection_log_id");
+
+ b.Property("Address")
+ .IsRequired()
+ .HasColumnType("TEXT")
+ .HasColumnName("address");
+
+ b.Property("Time")
+ .HasColumnType("TEXT")
+ .HasColumnName("time");
+
+ b.Property("UserId")
+ .HasColumnType("TEXT")
+ .HasColumnName("user_id");
+
+ b.Property("UserName")
+ .IsRequired()
+ .HasColumnType("TEXT")
+ .HasColumnName("user_name");
+
+ b.HasKey("Id");
+
+ b.ToTable("connection_log");
+ });
+
+ modelBuilder.Entity("Content.Server.Database.SqlitePlayer", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("INTEGER")
+ .HasColumnName("player_id");
+
+ b.Property("FirstSeenTime")
+ .HasColumnType("TEXT")
+ .HasColumnName("first_seen_time");
+
+ b.Property("LastSeenAddress")
+ .IsRequired()
+ .HasColumnType("TEXT")
+ .HasColumnName("last_seen_address");
+
+ b.Property("LastSeenTime")
+ .HasColumnType("TEXT")
+ .HasColumnName("last_seen_time");
+
+ b.Property("LastSeenUserName")
+ .IsRequired()
+ .HasColumnType("TEXT")
+ .HasColumnName("last_seen_user_name");
+
+ b.Property("UserId")
+ .HasColumnType("TEXT")
+ .HasColumnName("user_id");
+
+ b.HasKey("Id");
+
+ b.HasIndex("LastSeenUserName");
+
+ b.ToTable("player");
+ });
+
+ modelBuilder.Entity("Content.Server.Database.SqliteServerBan", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("INTEGER")
+ .HasColumnName("ban_id");
+
+ b.Property("Address")
+ .HasColumnType("TEXT")
+ .HasColumnName("address");
+
+ b.Property("BanTime")
+ .HasColumnType("TEXT")
+ .HasColumnName("ban_time");
+
+ b.Property("BanningAdmin")
+ .HasColumnType("TEXT")
+ .HasColumnName("banning_admin");
+
+ b.Property("ExpirationTime")
+ .HasColumnType("TEXT")
+ .HasColumnName("expiration_time");
+
+ b.Property("Reason")
+ .IsRequired()
+ .HasColumnType("TEXT")
+ .HasColumnName("reason");
+
+ b.Property("UserId")
+ .HasColumnType("TEXT")
+ .HasColumnName("user_id");
+
+ b.HasKey("Id");
+
+ b.ToTable("ban");
+ });
+
+ modelBuilder.Entity("Content.Server.Database.SqliteServerUnban", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("INTEGER")
+ .HasColumnName("unban_id");
+
+ b.Property("BanId")
+ .HasColumnType("INTEGER")
+ .HasColumnName("ban_id");
+
+ b.Property("UnbanTime")
+ .HasColumnType("TEXT")
+ .HasColumnName("unban_time");
+
+ b.Property("UnbanningAdmin")
+ .HasColumnType("TEXT")
+ .HasColumnName("unbanning_admin");
+
+ b.HasKey("Id");
+
+ b.HasIndex("BanId")
+ .IsUnique();
+
+ b.ToTable("unban");
+ });
+
+ modelBuilder.Entity("Content.Server.Database.Admin", b =>
+ {
+ b.HasOne("Content.Server.Database.AdminRank", "AdminRank")
+ .WithMany("Admins")
+ .HasForeignKey("AdminRankId")
+ .OnDelete(DeleteBehavior.SetNull);
+
+ b.Navigation("AdminRank");
+ });
+
+ modelBuilder.Entity("Content.Server.Database.AdminFlag", b =>
+ {
+ b.HasOne("Content.Server.Database.Admin", "Admin")
+ .WithMany("Flags")
+ .HasForeignKey("AdminId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Admin");
+ });
+
+ modelBuilder.Entity("Content.Server.Database.AdminRankFlag", b =>
+ {
+ b.HasOne("Content.Server.Database.AdminRank", "Rank")
+ .WithMany("Flags")
+ .HasForeignKey("AdminRankId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Rank");
+ });
+
+ modelBuilder.Entity("Content.Server.Database.Antag", b =>
+ {
+ b.HasOne("Content.Server.Database.Profile", "Profile")
+ .WithMany("Antags")
+ .HasForeignKey("ProfileId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Profile");
+ });
+
+ modelBuilder.Entity("Content.Server.Database.Job", b =>
+ {
+ b.HasOne("Content.Server.Database.Profile", "Profile")
+ .WithMany("Jobs")
+ .HasForeignKey("ProfileId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Profile");
+ });
+
+ modelBuilder.Entity("Content.Server.Database.Profile", b =>
+ {
+ b.HasOne("Content.Server.Database.Preference", "Preference")
+ .WithMany("Profiles")
+ .HasForeignKey("PreferenceId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Preference");
+ });
+
+ modelBuilder.Entity("Content.Server.Database.SqliteServerUnban", b =>
+ {
+ b.HasOne("Content.Server.Database.SqliteServerBan", "Ban")
+ .WithOne("Unban")
+ .HasForeignKey("Content.Server.Database.SqliteServerUnban", "BanId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Ban");
+ });
+
+ modelBuilder.Entity("Content.Server.Database.Admin", b =>
+ {
+ b.Navigation("Flags");
+ });
+
+ modelBuilder.Entity("Content.Server.Database.AdminRank", b =>
+ {
+ b.Navigation("Admins");
+
+ b.Navigation("Flags");
+ });
+
+ modelBuilder.Entity("Content.Server.Database.Preference", b =>
+ {
+ b.Navigation("Profiles");
+ });
+
+ modelBuilder.Entity("Content.Server.Database.Profile", b =>
+ {
+ b.Navigation("Antags");
+
+ b.Navigation("Jobs");
+ });
+
+ modelBuilder.Entity("Content.Server.Database.SqliteServerBan", b =>
+ {
+ b.Navigation("Unban");
+ });
+#pragma warning restore 612, 618
+ }
+ }
+}
diff --git a/Content.Server.Database/Migrations/Sqlite/20210103151752_BackpackPreference.cs b/Content.Server.Database/Migrations/Sqlite/20210103151752_BackpackPreference.cs
new file mode 100644
index 0000000000..ff907ca1f2
--- /dev/null
+++ b/Content.Server.Database/Migrations/Sqlite/20210103151752_BackpackPreference.cs
@@ -0,0 +1,24 @@
+using Microsoft.EntityFrameworkCore.Migrations;
+
+namespace Content.Server.Database.Migrations.Sqlite
+{
+ public partial class BackpackPreference : Migration
+ {
+ protected override void Up(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.AddColumn(
+ name: "backpack",
+ table: "profile",
+ type: "TEXT",
+ nullable: false,
+ defaultValue: "");
+ }
+
+ protected override void Down(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.DropColumn(
+ name: "backpack",
+ table: "profile");
+ }
+ }
+}
diff --git a/Content.Server.Database/Migrations/Sqlite/SqliteServerDbContextModelSnapshot.cs b/Content.Server.Database/Migrations/Sqlite/SqliteServerDbContextModelSnapshot.cs
index f6c1eb5e3a..8e93f4acbf 100644
--- a/Content.Server.Database/Migrations/Sqlite/SqliteServerDbContextModelSnapshot.cs
+++ b/Content.Server.Database/Migrations/Sqlite/SqliteServerDbContextModelSnapshot.cs
@@ -223,6 +223,11 @@ namespace Content.Server.Database.Migrations.Sqlite
.HasColumnType("INTEGER")
.HasColumnName("age");
+ b.Property("Backpack")
+ .IsRequired()
+ .HasColumnType("TEXT")
+ .HasColumnName("backpack");
+
b.Property("CharacterName")
.IsRequired()
.HasColumnType("TEXT")
diff --git a/Content.Server.Database/Model.cs b/Content.Server.Database/Model.cs
index e5d365b602..ed5c51e8c6 100644
--- a/Content.Server.Database/Model.cs
+++ b/Content.Server.Database/Model.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
@@ -99,6 +99,7 @@ namespace Content.Server.Database
[Column("eye_color")] public string EyeColor { get; set; } = null!;
[Column("skin_color")] public string SkinColor { get; set; } = null!;
[Column("clothing")] public string Clothing { get; set; } = null!;
+ [Column("backpack")] public string Backpack { get; set; } = null!;
public List Jobs { get; } = new();
public List Antags { get; } = new();
diff --git a/Content.Server/Database/ServerDbBase.cs b/Content.Server/Database/ServerDbBase.cs
index 929532fc21..0d95804350 100644
--- a/Content.Server/Database/ServerDbBase.cs
+++ b/Content.Server/Database/ServerDbBase.cs
@@ -1,4 +1,4 @@
-#nullable enable
+#nullable enable
using System;
using System.Collections.Generic;
using System.Linq;
@@ -140,6 +140,10 @@ namespace Content.Server.Database
if (Enum.TryParse(profile.Clothing, true, out var clothingVal))
clothing = clothingVal;
+ var backpack = BackpackPreference.Backpack;
+ if (Enum.TryParse(profile.Backpack, true, out var backpackVal))
+ backpack = backpackVal;
+
var gender = sex == Sex.Male ? Gender.Male : Gender.Female;
if (Enum.TryParse(profile.Gender, true, out var genderVal))
gender = genderVal;
@@ -159,6 +163,7 @@ namespace Content.Server.Database
Color.FromHex(profile.SkinColor)
),
clothing,
+ backpack,
jobs,
(PreferenceUnavailableMode) profile.PreferenceUnavailable,
antags.ToList()
@@ -182,6 +187,7 @@ namespace Content.Server.Database
EyeColor = appearance.EyeColor.ToHex(),
SkinColor = appearance.SkinColor.ToHex(),
Clothing = humanoid.Clothing.ToString(),
+ Backpack = humanoid.Backpack.ToString(),
Slot = slot,
PreferenceUnavailable = (DbPreferenceUnavailableMode) humanoid.PreferenceUnavailable
};
diff --git a/Content.Shared/Preferences/BackpackPreference.cs b/Content.Shared/Preferences/BackpackPreference.cs
new file mode 100644
index 0000000000..da2c4b8fe8
--- /dev/null
+++ b/Content.Shared/Preferences/BackpackPreference.cs
@@ -0,0 +1,12 @@
+namespace Content.Shared.Preferences
+{
+ ///
+ /// The backpack preference for a profile. Stored in database!
+ ///
+ public enum BackpackPreference
+ {
+ Backpack,
+ Satchel,
+ Duffelbag
+ }
+}
diff --git a/Content.Shared/Preferences/HumanoidCharacterProfile.cs b/Content.Shared/Preferences/HumanoidCharacterProfile.cs
index 53777695ea..6609591887 100644
--- a/Content.Shared/Preferences/HumanoidCharacterProfile.cs
+++ b/Content.Shared/Preferences/HumanoidCharacterProfile.cs
@@ -1,4 +1,4 @@
-#nullable enable
+#nullable enable
using System;
using System.Collections.Generic;
using System.Linq;
@@ -34,6 +34,7 @@ namespace Content.Shared.Preferences
Gender gender,
HumanoidCharacterAppearance appearance,
ClothingPreference clothing,
+ BackpackPreference backpack,
Dictionary jobPriorities,
PreferenceUnavailableMode preferenceUnavailable,
List antagPreferences)
@@ -44,6 +45,7 @@ namespace Content.Shared.Preferences
Gender = gender;
Appearance = appearance;
Clothing = clothing;
+ Backpack = backpack;
_jobPriorities = jobPriorities;
PreferenceUnavailable = preferenceUnavailable;
_antagPreferences = antagPreferences;
@@ -54,7 +56,7 @@ namespace Content.Shared.Preferences
HumanoidCharacterProfile other,
Dictionary jobPriorities,
List antagPreferences)
- : this(other.Name, other.Age, other.Sex, other.Gender, other.Appearance, other.Clothing,
+ : this(other.Name, other.Age, other.Sex, other.Gender, other.Appearance, other.Clothing, other.Backpack,
jobPriorities, other.PreferenceUnavailable, antagPreferences)
{
}
@@ -72,10 +74,11 @@ namespace Content.Shared.Preferences
Gender gender,
HumanoidCharacterAppearance appearance,
ClothingPreference clothing,
+ BackpackPreference backpack,
IReadOnlyDictionary jobPriorities,
PreferenceUnavailableMode preferenceUnavailable,
IReadOnlyList antagPreferences)
- : this(name, age, sex, gender, appearance, clothing, new Dictionary(jobPriorities),
+ : this(name, age, sex, gender, appearance, clothing, backpack, new Dictionary(jobPriorities),
preferenceUnavailable, new List(antagPreferences))
{
}
@@ -98,7 +101,7 @@ namespace Content.Shared.Preferences
var name = $"{firstName} {lastName}";
var age = random.Next(MinimumAge, MaximumAge);
- return new HumanoidCharacterProfile(name, age, sex, gender, HumanoidCharacterAppearance.Random(sex), ClothingPreference.Jumpsuit,
+ return new HumanoidCharacterProfile(name, age, sex, gender, HumanoidCharacterAppearance.Random(sex), ClothingPreference.Jumpsuit, BackpackPreference.Backpack,
new Dictionary
{
{SharedGameTicker.OverflowJob, JobPriority.High}
@@ -112,6 +115,7 @@ namespace Content.Shared.Preferences
public ICharacterAppearance CharacterAppearance => Appearance;
public HumanoidCharacterAppearance Appearance { get; private set; }
public ClothingPreference Clothing { get; private set; }
+ public BackpackPreference Backpack { get; private set; }
public IReadOnlyDictionary JobPriorities => _jobPriorities;
public IReadOnlyList AntagPreferences => _antagPreferences;
public PreferenceUnavailableMode PreferenceUnavailable { get; private set; }
@@ -145,7 +149,10 @@ namespace Content.Shared.Preferences
{
return new(this) { Clothing = clothing };
}
-
+ public HumanoidCharacterProfile WithBackpackPreference(BackpackPreference backpack)
+ {
+ return new(this) { Backpack = backpack };
+ }
public HumanoidCharacterProfile WithJobPriorities(IEnumerable> jobPriorities)
{
return new(this, new Dictionary(jobPriorities), _antagPreferences);
@@ -254,6 +261,14 @@ namespace Content.Shared.Preferences
_ => ClothingPreference.Jumpsuit // Invalid enum values.
};
+ var backpack = profile.Backpack switch
+ {
+ BackpackPreference.Backpack => BackpackPreference.Backpack,
+ BackpackPreference.Satchel => BackpackPreference.Satchel,
+ BackpackPreference.Duffelbag => BackpackPreference.Duffelbag,
+ _ => BackpackPreference.Backpack // Invalid enum values.
+ };
+
var priorities = new Dictionary(profile.JobPriorities
.Where(p => prototypeManager.HasIndex(p.Key) && p.Value switch
{
@@ -268,7 +283,7 @@ namespace Content.Shared.Preferences
.Where(prototypeManager.HasIndex)
.ToList();
- return new HumanoidCharacterProfile(name, age, sex, gender, appearance, clothing, priorities, prefsUnavailableMode, antags);
+ return new HumanoidCharacterProfile(name, age, sex, gender, appearance, clothing, backpack, priorities, prefsUnavailableMode, antags);
}
public string Summary =>
@@ -283,6 +298,7 @@ namespace Content.Shared.Preferences
if (Gender != other.Gender) return false;
if (PreferenceUnavailable != other.PreferenceUnavailable) return false;
if (Clothing != other.Clothing) return false;
+ if (Backpack != other.Backpack) return false;
if (!_jobPriorities.SequenceEqual(other._jobPriorities)) return false;
if (!_antagPreferences.SequenceEqual(other._antagPreferences)) return false;
return Appearance.MemberwiseEquals(other.Appearance);
@@ -302,7 +318,8 @@ namespace Content.Shared.Preferences
Sex,
Gender,
Appearance,
- Clothing
+ Clothing,
+ Backpack
),
PreferenceUnavailable,
_jobPriorities,
diff --git a/Content.Shared/Roles/StartingGearPrototype.cs b/Content.Shared/Roles/StartingGearPrototype.cs
index ac27be7a56..567a66f181 100644
--- a/Content.Shared/Roles/StartingGearPrototype.cs
+++ b/Content.Shared/Roles/StartingGearPrototype.cs
@@ -21,6 +21,8 @@ namespace Content.Shared.Roles
/// if empty, there is no skirt override - instead the uniform provided in equipment is added.
///
private string _innerClothingSkirt = default!;
+ private string _satchel = default!;
+ private string _duffelbag = default!;
public IReadOnlyDictionary Inhand => _inHand;
///
@@ -51,6 +53,8 @@ namespace Content.Shared.Roles
}, type => type.Value);
serializer.DataField(ref _innerClothingSkirt, "innerclothingskirt", string.Empty);
+ serializer.DataField(ref _satchel, "satchel", string.Empty);
+ serializer.DataField(ref _duffelbag, "duffelbag", string.Empty);
}
public string GetGear(Slots slot, HumanoidCharacterProfile? profile)
@@ -59,6 +63,10 @@ namespace Content.Shared.Roles
{
if ((slot == Slots.INNERCLOTHING) && (profile.Clothing == ClothingPreference.Jumpskirt) && (_innerClothingSkirt != ""))
return _innerClothingSkirt;
+ if ((slot == Slots.BACKPACK) && (profile.Backpack == BackpackPreference.Satchel) && (_satchel != ""))
+ return _satchel;
+ if ((slot == Slots.BACKPACK) && (profile.Backpack == BackpackPreference.Duffelbag) && (_duffelbag != ""))
+ return _duffelbag;
}
if (_equipment.ContainsKey(slot))
diff --git a/Content.Tests/Server/Preferences/ServerDbSqliteTests.cs b/Content.Tests/Server/Preferences/ServerDbSqliteTests.cs
index 2481c5cf88..b8a55e8792 100644
--- a/Content.Tests/Server/Preferences/ServerDbSqliteTests.cs
+++ b/Content.Tests/Server/Preferences/ServerDbSqliteTests.cs
@@ -36,6 +36,7 @@ namespace Content.Tests.Server.Preferences
Color.Beige
),
ClothingPreference.Jumpskirt,
+ BackpackPreference.Backpack,
new Dictionary
{
{SharedGameTicker.OverflowJob, JobPriority.High}
diff --git a/Resources/Prototypes/Catalog/Fills/backpack.yml b/Resources/Prototypes/Catalog/Fills/Backpacks/Starter Gear/backpack.yml
similarity index 100%
rename from Resources/Prototypes/Catalog/Fills/backpack.yml
rename to Resources/Prototypes/Catalog/Fills/Backpacks/Starter Gear/backpack.yml
diff --git a/Resources/Prototypes/Catalog/Fills/Backpacks/Starter Gear/duffelbag.yml b/Resources/Prototypes/Catalog/Fills/Backpacks/Starter Gear/duffelbag.yml
new file mode 100644
index 0000000000..a359dfbd49
--- /dev/null
+++ b/Resources/Prototypes/Catalog/Fills/Backpacks/Starter Gear/duffelbag.yml
@@ -0,0 +1,75 @@
+- type: entity
+ abstract: true
+ parent: ClothingBackpackDuffel
+ id: ClothingBackpackDuffelFilled
+ components:
+ - type: StorageFill
+ contents:
+ - name: BoxSurvival
+
+- type: entity
+ abstract: true
+ parent: ClothingBackpackDuffelClown
+ id: ClothingBackpackDuffelClownFilled
+ components:
+ - type: StorageFill
+ contents:
+ - name: BoxHug
+
+- type: entity
+ abstract: true
+ parent: ClothingBackpackDuffelSecurity
+ id: ClothingBackpackDuffelSecurityFilled
+ components:
+ - type: StorageFill
+ contents:
+ - name: BoxSurvival
+ - name: Stunbaton
+ - name: Flash
+
+- type: entity
+ abstract: true
+ parent: ClothingBackpackDuffelMedical
+ id: ClothingBackpackDuffelMedicalFilled
+ components:
+ - type: StorageFill
+ contents:
+ - name: BoxSurvival
+
+- type: entity
+ abstract: true
+ parent: ClothingBackpackDuffelCaptain
+ id: ClothingBackpackDuffelCaptainFilled
+ components:
+ - type: StorageFill
+ contents:
+ - name: BoxSurvival
+ #- name: StationCharter
+ #- name: TelescopicBaton
+
+- type: entity
+ abstract: true
+ parent: ClothingBackpackDuffelEngineering
+ id: ClothingBackpackDuffelEngineeringFilled
+ components:
+ - type: StorageFill
+ contents:
+ - name: BoxSurvival
+
+#- type: entity
+# abstract: true
+# parent: ClothingBackpackDuffelScience
+# id: ClothingBackpackDuffelScienceFilled
+# components:
+# - type: StorageFill
+# contents:
+# - name: BoxSurvival
+
+#- type: entity
+# abstract: true
+# parent: ClothingBackpackDuffelChemistry
+# id: ClothingBackpackDuffelChemistryFilled
+# components:
+# - type: StorageFill
+# contents:
+# - name: BoxSurvival
diff --git a/Resources/Prototypes/Catalog/Fills/Backpacks/Starter Gear/satchel.yml b/Resources/Prototypes/Catalog/Fills/Backpacks/Starter Gear/satchel.yml
new file mode 100644
index 0000000000..a53b54fa07
--- /dev/null
+++ b/Resources/Prototypes/Catalog/Fills/Backpacks/Starter Gear/satchel.yml
@@ -0,0 +1,75 @@
+- type: entity
+ abstract: true
+ parent: ClothingBackpackSatchel
+ id: ClothingBackpackSatchelFilled
+ components:
+ - type: StorageFill
+ contents:
+ - name: BoxSurvival
+
+#- type: entity
+# abstract: true
+# parent: ClothingBackpackSatchelClown
+# id: ClothingBackpackSatchelClownFilled
+# components:
+# - type: StorageFill
+# contents:
+# - name: BoxHug
+
+- type: entity
+ abstract: true
+ parent: ClothingBackpackSatchelSecurity
+ id: ClothingBackpackSatchelSecurityFilled
+ components:
+ - type: StorageFill
+ contents:
+ - name: BoxSurvival
+ - name: Stunbaton
+ - name: Flash
+
+- type: entity
+ abstract: true
+ parent: ClothingBackpackSatchelMedical
+ id: ClothingBackpackSatchelMedicalFilled
+ components:
+ - type: StorageFill
+ contents:
+ - name: BoxSurvival
+
+- type: entity
+ abstract: true
+ parent: ClothingBackpackSatchelCaptain
+ id: ClothingBackpackSatchelCaptainFilled
+ components:
+ - type: StorageFill
+ contents:
+ - name: BoxSurvival
+ #- name: StationCharter
+ #- name: TelescopicBaton
+
+- type: entity
+ abstract: true
+ parent: ClothingBackpackSatchelEngineering
+ id: ClothingBackpackSatchelEngineeringFilled
+ components:
+ - type: StorageFill
+ contents:
+ - name: BoxSurvival
+
+- type: entity
+ abstract: true
+ parent: ClothingBackpackSatchelScience
+ id: ClothingBackpackSatchelScienceFilled
+ components:
+ - type: StorageFill
+ contents:
+ - name: BoxSurvival
+
+- type: entity
+ abstract: true
+ parent: ClothingBackpackSatchelChemistry
+ id: ClothingBackpackSatchelChemistryFilled
+ components:
+ - type: StorageFill
+ contents:
+ - name: BoxSurvival
diff --git a/Resources/Prototypes/Catalog/Fills/duffel.yml b/Resources/Prototypes/Catalog/Fills/Backpacks/duffelbag.yml
similarity index 100%
rename from Resources/Prototypes/Catalog/Fills/duffel.yml
rename to Resources/Prototypes/Catalog/Fills/Backpacks/duffelbag.yml
diff --git a/Resources/Prototypes/Roles/Jobs/Cargo/cargo_technician.yml b/Resources/Prototypes/Roles/Jobs/Cargo/cargo_technician.yml
index cfaaf58949..767eee8a88 100644
--- a/Resources/Prototypes/Roles/Jobs/Cargo/cargo_technician.yml
+++ b/Resources/Prototypes/Roles/Jobs/Cargo/cargo_technician.yml
@@ -21,4 +21,5 @@
idcard: CargoPDA
ears: ClothingHeadsetCargo
innerclothingskirt: ClothingUniformJumpskirtCargo
-
+ satchel: ClothingBackpackSatchelFilled
+ duffelbag: ClothingBackpackDuffelFilled
diff --git a/Resources/Prototypes/Roles/Jobs/Cargo/quartermaster.yml b/Resources/Prototypes/Roles/Jobs/Cargo/quartermaster.yml
index e5dced21f9..3d9eabe13b 100644
--- a/Resources/Prototypes/Roles/Jobs/Cargo/quartermaster.yml
+++ b/Resources/Prototypes/Roles/Jobs/Cargo/quartermaster.yml
@@ -22,4 +22,5 @@
idcard: QuartermasterPDA
ears: ClothingHeadsetCargo
innerclothingskirt: ClothingUniformJumpskirtQM
-
+ satchel: ClothingBackpackSatchelFilled
+ duffelbag: ClothingBackpackDuffelFilled
diff --git a/Resources/Prototypes/Roles/Jobs/Civilian/assistant.yml b/Resources/Prototypes/Roles/Jobs/Civilian/assistant.yml
index 6249154a98..be5e8f29ab 100644
--- a/Resources/Prototypes/Roles/Jobs/Civilian/assistant.yml
+++ b/Resources/Prototypes/Roles/Jobs/Civilian/assistant.yml
@@ -18,4 +18,5 @@
idcard: AssistantPDA
ears: ClothingHeadsetService
innerclothingskirt: ClothingUniformJumpskirtColorGrey
-
+ satchel: ClothingBackpackSatchelFilled
+ duffelbag: ClothingBackpackDuffelFilled
diff --git a/Resources/Prototypes/Roles/Jobs/Civilian/bartender.yml b/Resources/Prototypes/Roles/Jobs/Civilian/bartender.yml
index 761e2f7ccd..c62541346d 100644
--- a/Resources/Prototypes/Roles/Jobs/Civilian/bartender.yml
+++ b/Resources/Prototypes/Roles/Jobs/Civilian/bartender.yml
@@ -22,4 +22,5 @@
idcard: BartenderPDA
ears: ClothingHeadsetService
innerclothingskirt: ClothingUniformJumpskirtBartender
-
+ satchel: ClothingBackpackSatchelFilled
+ duffelbag: ClothingBackpackDuffelFilled
diff --git a/Resources/Prototypes/Roles/Jobs/Civilian/botanist.yml b/Resources/Prototypes/Roles/Jobs/Civilian/botanist.yml
index 59bdfd5db7..462bb1d2f2 100644
--- a/Resources/Prototypes/Roles/Jobs/Civilian/botanist.yml
+++ b/Resources/Prototypes/Roles/Jobs/Civilian/botanist.yml
@@ -22,4 +22,5 @@
ears: ClothingHeadsetService
outerclothing: ClothingOuterApronBotanist
innerclothingskirt: ClothingUniformJumpskirtHydroponics
-
+ satchel: ClothingBackpackSatchelFilled
+ duffelbag: ClothingBackpackDuffelFilled
diff --git a/Resources/Prototypes/Roles/Jobs/Civilian/chef.yml b/Resources/Prototypes/Roles/Jobs/Civilian/chef.yml
index c4e0fb978b..a49a15e6ab 100644
--- a/Resources/Prototypes/Roles/Jobs/Civilian/chef.yml
+++ b/Resources/Prototypes/Roles/Jobs/Civilian/chef.yml
@@ -22,4 +22,5 @@
ears: ClothingHeadsetService
outerclothing: ClothingOuterApronChef
innerclothingskirt: ClothingUniformJumpskirtChef
-
+ satchel: ClothingBackpackSatchelFilled
+ duffelbag: ClothingBackpackDuffelFilled
diff --git a/Resources/Prototypes/Roles/Jobs/Civilian/clown.yml b/Resources/Prototypes/Roles/Jobs/Civilian/clown.yml
index 15bdd058e8..46ef1db39b 100644
--- a/Resources/Prototypes/Roles/Jobs/Civilian/clown.yml
+++ b/Resources/Prototypes/Roles/Jobs/Civilian/clown.yml
@@ -21,3 +21,4 @@
pocket1: BikeHorn
idcard: ClownPDA
ears: ClothingHeadsetService
+ duffelbag: ClothingBackpackDuffelClownFilled
diff --git a/Resources/Prototypes/Roles/Jobs/Civilian/janitor.yml b/Resources/Prototypes/Roles/Jobs/Civilian/janitor.yml
index 5cd9cdabd6..b294e5e463 100644
--- a/Resources/Prototypes/Roles/Jobs/Civilian/janitor.yml
+++ b/Resources/Prototypes/Roles/Jobs/Civilian/janitor.yml
@@ -21,4 +21,5 @@
ears: ClothingHeadsetService
belt: ClothingBeltJanitorFilled
innerclothingskirt: ClothingUniformJumpskirtJanitor
-
+ satchel: ClothingBackpackSatchelFilled
+ duffelbag: ClothingBackpackDuffelFilled
diff --git a/Resources/Prototypes/Roles/Jobs/Command/captain.yml b/Resources/Prototypes/Roles/Jobs/Command/captain.yml
index 2000efb720..165ef640b9 100644
--- a/Resources/Prototypes/Roles/Jobs/Command/captain.yml
+++ b/Resources/Prototypes/Roles/Jobs/Command/captain.yml
@@ -48,3 +48,5 @@
outerclothing: ClothingOuterHardsuitCap
idcard: CaptainPDA
ears: ClothingHeadsetAltCommand
+ satchel: ClothingBackpackSatchelCaptainFilled
+ duffelbag: ClothingBackpackDuffelCaptainFilled
diff --git a/Resources/Prototypes/Roles/Jobs/Command/head_of_personnel.yml b/Resources/Prototypes/Roles/Jobs/Command/head_of_personnel.yml
index 5558880f74..70dc494506 100644
--- a/Resources/Prototypes/Roles/Jobs/Command/head_of_personnel.yml
+++ b/Resources/Prototypes/Roles/Jobs/Command/head_of_personnel.yml
@@ -29,4 +29,5 @@
idcard: HoPPDA
ears: ClothingHeadsetAltCommand
innerclothingskirt: ClothingUniformJumpskirtHoP
-
+ satchel: ClothingBackpackSatchelFilled
+ duffelbag: ClothingBackpackDuffelFilled
diff --git a/Resources/Prototypes/Roles/Jobs/Engineering/chief_engineer.yml b/Resources/Prototypes/Roles/Jobs/Engineering/chief_engineer.yml
index d029293184..6bcff4639b 100644
--- a/Resources/Prototypes/Roles/Jobs/Engineering/chief_engineer.yml
+++ b/Resources/Prototypes/Roles/Jobs/Engineering/chief_engineer.yml
@@ -26,4 +26,5 @@
ears: ClothingHeadsetEngineering
belt: ClothingBeltChiefEngineerFilled
innerclothingskirt: ClothingUniformJumpskirtChiefEngineer
-
+ satchel: ClothingBackpackSatchelEngineeringFilled
+ duffelbag: ClothingBackpackDuffelEngineeringFilled
diff --git a/Resources/Prototypes/Roles/Jobs/Engineering/station_engineer.yml b/Resources/Prototypes/Roles/Jobs/Engineering/station_engineer.yml
index a7fa9b5d13..0b702ca6b6 100644
--- a/Resources/Prototypes/Roles/Jobs/Engineering/station_engineer.yml
+++ b/Resources/Prototypes/Roles/Jobs/Engineering/station_engineer.yml
@@ -24,4 +24,5 @@
belt: ClothingBeltUtilityFilled
ears: ClothingHeadsetEngineering
innerclothingskirt: ClothingUniformJumpskirtEngineering
-
+ satchel: ClothingBackpackSatchelEngineeringFilled
+ duffelbag: ClothingBackpackDuffelEngineeringFilled
diff --git a/Resources/Prototypes/Roles/Jobs/Medical/chief_medical_officer.yml b/Resources/Prototypes/Roles/Jobs/Medical/chief_medical_officer.yml
index c29a91a31c..4b06c0559a 100644
--- a/Resources/Prototypes/Roles/Jobs/Medical/chief_medical_officer.yml
+++ b/Resources/Prototypes/Roles/Jobs/Medical/chief_medical_officer.yml
@@ -27,4 +27,5 @@
ears: ClothingHeadsetAltMedical
belt: ClothingBeltMedical
innerclothingskirt: ClothingUniformJumpskirtCMO
-
+ satchel: ClothingBackpackSatchelMedicalFilled
+ duffelbag: ClothingBackpackDuffelMedicalFilled
diff --git a/Resources/Prototypes/Roles/Jobs/Medical/medical_doctor.yml b/Resources/Prototypes/Roles/Jobs/Medical/medical_doctor.yml
index 3e34d75574..81c9dd8ba0 100644
--- a/Resources/Prototypes/Roles/Jobs/Medical/medical_doctor.yml
+++ b/Resources/Prototypes/Roles/Jobs/Medical/medical_doctor.yml
@@ -22,4 +22,5 @@
ears: ClothingHeadsetMedical
belt: ClothingBeltMedical
innerclothingskirt: ClothingUniformJumpskirtMedicalDoctor
-
+ satchel: ClothingBackpackSatchelMedicalFilled
+ duffelbag: ClothingBackpackDuffelMedicalFilled
diff --git a/Resources/Prototypes/Roles/Jobs/Science/research_director.yml b/Resources/Prototypes/Roles/Jobs/Science/research_director.yml
index 32202b4a79..7a89465e6d 100644
--- a/Resources/Prototypes/Roles/Jobs/Science/research_director.yml
+++ b/Resources/Prototypes/Roles/Jobs/Science/research_director.yml
@@ -23,4 +23,4 @@
idcard: RnDPDA
ears: ClothingHeadsetScience
innerclothingskirt: ClothingUniformJumpskirtResearchDirector
-
+ satchel: ClothingBackpackSatchelScienceFilled
diff --git a/Resources/Prototypes/Roles/Jobs/Science/scientist.yml b/Resources/Prototypes/Roles/Jobs/Science/scientist.yml
index 9d2c43eee9..e37628b019 100644
--- a/Resources/Prototypes/Roles/Jobs/Science/scientist.yml
+++ b/Resources/Prototypes/Roles/Jobs/Science/scientist.yml
@@ -21,4 +21,4 @@
idcard: SciencePDA
ears: ClothingHeadsetScience
innerclothingskirt: ClothingUniformJumpskirtScientist
-
+ satchel: ClothingBackpackSatchelScienceFilled
diff --git a/Resources/Prototypes/Roles/Jobs/Security/head_of_security.yml b/Resources/Prototypes/Roles/Jobs/Security/head_of_security.yml
index 176222aa33..ffb90f4f16 100644
--- a/Resources/Prototypes/Roles/Jobs/Security/head_of_security.yml
+++ b/Resources/Prototypes/Roles/Jobs/Security/head_of_security.yml
@@ -30,4 +30,5 @@
ears: ClothingHeadsetAltSecurity
belt: ClothingBeltSecurityFilled
innerclothingskirt: ClothingUniformJumpskirtHoS
-
+ satchel: ClothingBackpackSatchelSecurityFilled
+ duffelbag: ClothingBackpackDuffelSecurityFilled
diff --git a/Resources/Prototypes/Roles/Jobs/Security/security_officer.yml b/Resources/Prototypes/Roles/Jobs/Security/security_officer.yml
index d9356cf6b3..07bc658f6a 100644
--- a/Resources/Prototypes/Roles/Jobs/Security/security_officer.yml
+++ b/Resources/Prototypes/Roles/Jobs/Security/security_officer.yml
@@ -25,4 +25,5 @@
ears: ClothingHeadsetSecurity
belt: ClothingBeltSecurityFilled
innerclothingskirt: ClothingUniformJumpskirtSec
-
+ satchel: ClothingBackpackSatchelSecurityFilled
+ duffelbag: ClothingBackpackDuffelSecurityFilled
diff --git a/Resources/Prototypes/Roles/Jobs/Security/warden.yml b/Resources/Prototypes/Roles/Jobs/Security/warden.yml
index c9d250f9e0..9051a5f796 100644
--- a/Resources/Prototypes/Roles/Jobs/Security/warden.yml
+++ b/Resources/Prototypes/Roles/Jobs/Security/warden.yml
@@ -26,4 +26,5 @@
ears: ClothingHeadsetSecurity
belt: ClothingBeltSecurityFilled
innerclothingskirt: ClothingUniformJumpskirtWarden
-
+ satchel: ClothingBackpackSatchelSecurityFilled
+ duffelbag: ClothingBackpackDuffelSecurityFilled