Files
tbd-station-14/Content.Server.Database/Model.cs
20kdc 6b5cded8c2 Clothing and pronoun fields (#2689)
* Clothing & Gender fields: Add to database [MODIFIED TO NOT DEPEND ON SAPHIRE-DB-REFACTOR]

Sorry about this, Saphire.

* Clothing & Gender fields: Add UI [FALLBACK II]

* Clothing & Gender fields: Actually apply gender

* Clothing & Gender fields: Import innerclothingskirt field from my previous attempt

Couldn't import actual prototypes because of a change to IDs

* Clothing & Gender fields: Add innerclothingskirt field to everything

* Clothing & Gender fields: Jumpskirts now work

* Clothing & Gender fields: Gender field will follow sex field if it's not different (UX improvement) [FALLBACK II]

* Clothing & Gender fields: Gender -> Pronouns to reduce confusion. Also, fix profile summary. Properly. [FALLBACK II]

* Clothing & Pronoun fields: Refactor so that profile equipment adjustments are performed in StartingGearPrototype.
2020-12-24 14:42:40 +01:00

199 lines
7.3 KiB
C#

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Microsoft.EntityFrameworkCore;
namespace Content.Server.Database
{
public abstract class ServerDbContext : DbContext
{
/// <summary>
/// The "dotnet ef" CLI tool uses the parameter-less constructor.
/// When that happens we want to supply the <see cref="DbContextOptions"/> via <see cref="DbContext.OnConfiguring"/>.
/// To use the context within the application, the options need to be passed the constructor instead.
/// </summary>
protected readonly bool InitializedWithOptions;
public ServerDbContext()
{
}
public ServerDbContext(DbContextOptions<ServerDbContext> options) : base(options)
{
InitializedWithOptions = true;
}
public DbSet<Preference> Preference { get; set; } = null!;
public DbSet<Profile> Profile { get; set; } = null!;
public DbSet<AssignedUserId> AssignedUserId { get; set; } = null!;
public DbSet<Admin> Admin { get; set; } = null!;
public DbSet<AdminRank> AdminRank { get; set; } = null!;
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Preference>()
.HasIndex(p => p.UserId)
.IsUnique();
modelBuilder.Entity<Profile>()
.HasIndex(p => new {p.Slot, PrefsId = p.PreferenceId})
.IsUnique();
modelBuilder.Entity<Antag>()
.HasIndex(p => new {HumanoidProfileId = p.ProfileId, p.AntagName})
.IsUnique();
modelBuilder.Entity<AssignedUserId>()
.HasIndex(p => p.UserName)
.IsUnique();
// Can't have two usernames with the same user ID.
modelBuilder.Entity<AssignedUserId>()
.HasIndex(p => p.UserId)
.IsUnique();
modelBuilder.Entity<Admin>()
.HasOne(p => p.AdminRank)
.WithMany(p => p!.Admins)
.OnDelete(DeleteBehavior.SetNull);
modelBuilder.Entity<AdminFlag>()
.HasIndex(f => new {f.Flag, f.AdminId})
.IsUnique();
modelBuilder.Entity<AdminRankFlag>()
.HasIndex(f => new {f.Flag, f.AdminRankId})
.IsUnique();
}
}
[Table("preference")]
public class Preference
{
// NOTE: on postgres there SHOULD be an FK ensuring that the selected character slot always exists.
// I had to use a migration to implement it and as a result its creation is a finicky mess.
// Because if I let EFCore know about it it would explode on a circular reference.
// Also it has to be DEFERRABLE INITIALLY DEFERRED so that insertion of new preferences works.
// Also I couldn't figure out how to create it on SQLite.
[Column("preference_id")] public int Id { get; set; }
[Column("user_id")] public Guid UserId { get; set; }
[Column("selected_character_slot")] public int SelectedCharacterSlot { get; set; }
public List<Profile> Profiles { get; } = new();
}
[Table("profile")]
public class Profile
{
[Column("profile_id")] public int Id { get; set; }
[Column("slot")] public int Slot { get; set; }
[Column("char_name")] public string CharacterName { get; set; } = null!;
[Column("age")] public int Age { get; set; }
[Column("sex")] public string Sex { get; set; } = null!;
[Column("gender")] public string Gender { get; set; } = null!;
[Column("hair_name")] public string HairName { get; set; } = null!;
[Column("hair_color")] public string HairColor { get; set; } = null!;
[Column("facial_hair_name")] public string FacialHairName { get; set; } = null!;
[Column("facial_hair_color")] public string FacialHairColor { get; set; } = null!;
[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!;
public List<Job> Jobs { get; } = new();
public List<Antag> Antags { get; } = new();
[Column("pref_unavailable")] public DbPreferenceUnavailableMode PreferenceUnavailable { get; set; }
[Column("preference_id")] public int PreferenceId { get; set; }
public Preference Preference { get; set; } = null!;
}
[Table("job")]
public class Job
{
[Column("job_id")] public int Id { get; set; }
public Profile Profile { get; set; } = null!;
[Column("profile_id")] public int ProfileId { get; set; }
[Column("job_name")] public string JobName { get; set; } = null!;
[Column("priority")] public DbJobPriority Priority { get; set; }
}
public enum DbJobPriority
{
// These enum values HAVE to match the ones in JobPriority in Content.Shared
Never = 0,
Low = 1,
Medium = 2,
High = 3
}
[Table("antag")]
public class Antag
{
[Column("antag_id")] public int Id { get; set; }
public Profile Profile { get; set; } = null!;
[Column("profile_id")] public int ProfileId { get; set; }
[Column("antag_name")] public string AntagName { get; set; } = null!;
}
public enum DbPreferenceUnavailableMode
{
// These enum values HAVE to match the ones in PreferenceUnavailableMode in Shared.
StayInLobby = 0,
SpawnAsOverflow,
}
[Table("assigned_user_id")]
public class AssignedUserId
{
[Column("assigned_user_id_id")] public int Id { get; set; }
[Column("user_name")] public string UserName { get; set; } = null!;
[Column("user_id")] public Guid UserId { get; set; }
}
[Table("admin")]
public class Admin
{
[Column("user_id"), Key] public Guid UserId { get; set; }
[Column("title")] public string? Title { get; set; }
[Column("admin_rank_id")] public int? AdminRankId { get; set; }
public AdminRank? AdminRank { get; set; }
public List<AdminFlag> Flags { get; set; } = default!;
}
[Table("admin_flag")]
public class AdminFlag
{
[Column("admin_flag_id")] public int Id { get; set; }
[Column("flag")] public string Flag { get; set; } = default!;
[Column("negative")] public bool Negative { get; set; }
[Column("admin_id")] public Guid AdminId { get; set; }
public Admin Admin { get; set; } = default!;
}
[Table("admin_rank")]
public class AdminRank
{
[Column("admin_rank_id")] public int Id { get; set; }
[Column("name")] public string Name { get; set; } = default!;
public List<Admin> Admins { get; set; } = default!;
public List<AdminRankFlag> Flags { get; set; } = default!;
}
[Table("admin_rank_flag")]
public class AdminRankFlag
{
[Column("admin_rank_flag_id")] public int Id { get; set; }
[Column("flag")] public string Flag { get; set; } = default!;
[Column("admin_rank_id")] public int AdminRankId { get; set; }
public AdminRank Rank { get; set; } = default!;
}
}