Use async DB queries.
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Content.Client.Interfaces;
|
||||
using Content.Shared.Preferences;
|
||||
@@ -17,6 +18,7 @@ namespace Content.Client
|
||||
[Dependency] private readonly IClientNetManager _netManager;
|
||||
#pragma warning restore 649
|
||||
|
||||
public event Action OnServerDataLoaded;
|
||||
public GameSettings Settings { get; private set; }
|
||||
public PlayerPreferences Preferences { get; private set; }
|
||||
|
||||
@@ -69,6 +71,8 @@ namespace Content.Client
|
||||
{
|
||||
Preferences = message.Preferences;
|
||||
Settings = message.Settings;
|
||||
|
||||
OnServerDataLoaded?.Invoke();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,14 @@
|
||||
using System;
|
||||
using Content.Shared.Preferences;
|
||||
|
||||
namespace Content.Client.Interfaces
|
||||
{
|
||||
public interface IClientPreferencesManager
|
||||
{
|
||||
event Action OnServerDataLoaded;
|
||||
|
||||
bool ServerDataLoaded => Settings != null;
|
||||
|
||||
GameSettings Settings { get; }
|
||||
PlayerPreferences Preferences { get; }
|
||||
void Initialize();
|
||||
|
||||
@@ -136,7 +136,6 @@ namespace Content.Client.UserInterface
|
||||
_createNewCharacterButton = new Button
|
||||
{
|
||||
Text = "Create new slot...",
|
||||
ToolTip = $"A maximum of {preferencesManager.Settings.MaxCharacterSlots} characters are allowed."
|
||||
};
|
||||
_createNewCharacterButton.OnPressed += args =>
|
||||
{
|
||||
@@ -155,6 +154,8 @@ namespace Content.Client.UserInterface
|
||||
hBox.AddChild(_humanoidProfileEditor);
|
||||
|
||||
UpdateUI();
|
||||
|
||||
preferencesManager.OnServerDataLoaded += UpdateUI;
|
||||
}
|
||||
|
||||
public void Save() => _humanoidProfileEditor.Save();
|
||||
@@ -164,6 +165,15 @@ namespace Content.Client.UserInterface
|
||||
var numberOfFullSlots = 0;
|
||||
var characterButtonsGroup = new ButtonGroup();
|
||||
_charactersVBox.RemoveAllChildren();
|
||||
|
||||
if (!_preferencesManager.ServerDataLoaded)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_createNewCharacterButton.ToolTip =
|
||||
$"A maximum of {_preferencesManager.Settings.MaxCharacterSlots} characters are allowed.";
|
||||
|
||||
var characterIndex = 0;
|
||||
foreach (var character in _preferencesManager.Preferences.Characters)
|
||||
{
|
||||
|
||||
@@ -51,8 +51,7 @@ namespace Content.Client.UserInterface
|
||||
public HumanoidProfileEditor(IClientPreferencesManager preferencesManager, IPrototypeManager prototypeManager)
|
||||
{
|
||||
_random = IoCManager.Resolve<IRobustRandom>();
|
||||
Profile = (HumanoidCharacterProfile) preferencesManager.Preferences.SelectedCharacter;
|
||||
CharacterSlot = preferencesManager.Preferences.SelectedCharacterIndex;
|
||||
|
||||
_preferencesManager = preferencesManager;
|
||||
|
||||
var margin = new MarginContainer
|
||||
@@ -365,11 +364,23 @@ namespace Content.Client.UserInterface
|
||||
|
||||
#endregion Save
|
||||
|
||||
UpdateControls();
|
||||
if (preferencesManager.ServerDataLoaded)
|
||||
{
|
||||
LoadServerData();
|
||||
}
|
||||
|
||||
preferencesManager.OnServerDataLoaded += LoadServerData;
|
||||
|
||||
IsDirty = false;
|
||||
}
|
||||
|
||||
private void LoadServerData()
|
||||
{
|
||||
Profile = (HumanoidCharacterProfile) _preferencesManager.Preferences.SelectedCharacter;
|
||||
CharacterSlot = _preferencesManager.Preferences.SelectedCharacterIndex;
|
||||
UpdateControls();
|
||||
}
|
||||
|
||||
private void SetAge(int newAge)
|
||||
{
|
||||
Profile = Profile?.WithAge(newAge);
|
||||
|
||||
@@ -22,6 +22,8 @@ namespace Content.Client.UserInterface
|
||||
private readonly IClientPreferencesManager _preferencesManager;
|
||||
private IEntity _previewDummy;
|
||||
private readonly Label _summaryLabel;
|
||||
private VBoxContainer _loaded;
|
||||
private Label _unloaded;
|
||||
|
||||
public LobbyCharacterPreviewPanel(IEntityManager entityManager,
|
||||
IClientPreferencesManager preferencesManager)
|
||||
@@ -50,9 +52,13 @@ namespace Content.Client.UserInterface
|
||||
var vBox = new VBoxContainer();
|
||||
|
||||
vBox.AddChild(header);
|
||||
vBox.AddChild(CharacterSetupButton);
|
||||
|
||||
vBox.AddChild(_summaryLabel);
|
||||
_unloaded = new Label {Text = "Your character preferences have not yet loaded, please stand by."};
|
||||
|
||||
_loaded = new VBoxContainer {Visible = false};
|
||||
|
||||
_loaded.AddChild(CharacterSetupButton);
|
||||
_loaded.AddChild(_summaryLabel);
|
||||
|
||||
var hBox = new HBoxContainer();
|
||||
hBox.AddChild(viewSouth);
|
||||
@@ -60,11 +66,15 @@ namespace Content.Client.UserInterface
|
||||
hBox.AddChild(viewWest);
|
||||
hBox.AddChild(viewEast);
|
||||
|
||||
vBox.AddChild(hBox);
|
||||
_loaded.AddChild(hBox);
|
||||
|
||||
vBox.AddChild(_loaded);
|
||||
vBox.AddChild(_unloaded);
|
||||
AddChild(vBox);
|
||||
|
||||
UpdateUI();
|
||||
|
||||
_preferencesManager.OnServerDataLoaded += UpdateUI;
|
||||
}
|
||||
|
||||
public Button CharacterSetupButton { get; }
|
||||
@@ -89,6 +99,15 @@ namespace Content.Client.UserInterface
|
||||
|
||||
public void UpdateUI()
|
||||
{
|
||||
if (!_preferencesManager.ServerDataLoaded)
|
||||
{
|
||||
_loaded.Visible = false;
|
||||
_unloaded.Visible = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
_loaded.Visible = true;
|
||||
_unloaded.Visible = false;
|
||||
if (!(_preferencesManager.Preferences.SelectedCharacter is HumanoidCharacterProfile selectedCharacter))
|
||||
{
|
||||
_summaryLabel.Text = string.Empty;
|
||||
@@ -102,6 +121,7 @@ namespace Content.Client.UserInterface
|
||||
GiveDummyJobClothes(_previewDummy, selectedCharacter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void GiveDummyJobClothes(IEntity dummy, HumanoidCharacterProfile profile)
|
||||
{
|
||||
|
||||
154
Content.Server.Database/Migrations/Postgres/20200625230829_AddSlotPrefsIdIndex.Designer.cs
generated
Normal file
154
Content.Server.Database/Migrations/Postgres/20200625230829_AddSlotPrefsIdIndex.Designer.cs
generated
Normal file
@@ -0,0 +1,154 @@
|
||||
// <auto-generated />
|
||||
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(PostgresPreferencesDbContext))]
|
||||
[Migration("20200625230829_AddSlotPrefsIdIndex")]
|
||||
partial class AddSlotPrefsIdIndex
|
||||
{
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn)
|
||||
.HasAnnotation("ProductVersion", "3.1.4")
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.HumanoidProfile", b =>
|
||||
{
|
||||
b.Property<int>("HumanoidProfileId")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer")
|
||||
.HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
|
||||
|
||||
b.Property<int>("Age")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<string>("CharacterName")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("EyeColor")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("FacialHairColor")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("FacialHairName")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("HairColor")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("HairName")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<int>("PreferenceUnavailable")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<int>("PrefsId")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<string>("Sex")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("SkinColor")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<int>("Slot")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<string>("SlotName")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.HasKey("HumanoidProfileId");
|
||||
|
||||
b.HasIndex("PrefsId");
|
||||
|
||||
b.HasIndex("Slot", "PrefsId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("HumanoidProfile");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Job", b =>
|
||||
{
|
||||
b.Property<int>("JobId")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer")
|
||||
.HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
|
||||
|
||||
b.Property<string>("JobName")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<int>("Priority")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<int>("ProfileHumanoidProfileId")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.HasKey("JobId");
|
||||
|
||||
b.HasIndex("ProfileHumanoidProfileId");
|
||||
|
||||
b.ToTable("Job");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Prefs", b =>
|
||||
{
|
||||
b.Property<int>("PrefsId")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer")
|
||||
.HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
|
||||
|
||||
b.Property<int>("SelectedCharacterSlot")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<string>("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
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
namespace Content.Server.Database.Migrations.Postgres
|
||||
{
|
||||
public partial class AddSlotPrefsIdIndex : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_HumanoidProfile_Slot_PrefsId",
|
||||
table: "HumanoidProfile",
|
||||
columns: new[] { "Slot", "PrefsId" },
|
||||
unique: true);
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropIndex(
|
||||
name: "IX_HumanoidProfile_Slot_PrefsId",
|
||||
table: "HumanoidProfile");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,8 @@
|
||||
// <auto-generated />
|
||||
|
||||
using Content.Server.Database;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
|
||||
namespace Content.Server.Database.Migrations.Postgres
|
||||
@@ -14,7 +15,7 @@ namespace Content.Server.Database.Migrations.Postgres
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn)
|
||||
.HasAnnotation("ProductVersion", "3.1.0")
|
||||
.HasAnnotation("ProductVersion", "3.1.4")
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.HumanoidProfile", b =>
|
||||
@@ -76,6 +77,9 @@ namespace Content.Server.Database.Migrations.Postgres
|
||||
|
||||
b.HasIndex("PrefsId");
|
||||
|
||||
b.HasIndex("Slot", "PrefsId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("HumanoidProfile");
|
||||
});
|
||||
|
||||
|
||||
148
Content.Server.Database/Migrations/Sqlite/20200625230839_AddSlotPrefsIdIndex.Designer.cs
generated
Normal file
148
Content.Server.Database/Migrations/Sqlite/20200625230839_AddSlotPrefsIdIndex.Designer.cs
generated
Normal file
@@ -0,0 +1,148 @@
|
||||
// <auto-generated />
|
||||
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(SqlitePreferencesDbContext))]
|
||||
[Migration("20200625230839_AddSlotPrefsIdIndex")]
|
||||
partial class AddSlotPrefsIdIndex
|
||||
{
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "3.1.4");
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.HumanoidProfile", b =>
|
||||
{
|
||||
b.Property<int>("HumanoidProfileId")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("Age")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("CharacterName")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("EyeColor")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("FacialHairColor")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("FacialHairName")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("HairColor")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("HairName")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("PreferenceUnavailable")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("PrefsId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Sex")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("SkinColor")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("Slot")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("SlotName")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("HumanoidProfileId");
|
||||
|
||||
b.HasIndex("PrefsId");
|
||||
|
||||
b.HasIndex("Slot", "PrefsId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("HumanoidProfile");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Job", b =>
|
||||
{
|
||||
b.Property<int>("JobId")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("JobName")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("Priority")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("ProfileHumanoidProfileId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("JobId");
|
||||
|
||||
b.HasIndex("ProfileHumanoidProfileId");
|
||||
|
||||
b.ToTable("Job");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Prefs", b =>
|
||||
{
|
||||
b.Property<int>("PrefsId")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("SelectedCharacterSlot")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("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
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
namespace Content.Server.Database.Migrations.Sqlite
|
||||
{
|
||||
public partial class AddSlotPrefsIdIndex : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_HumanoidProfile_Slot_PrefsId",
|
||||
table: "HumanoidProfile",
|
||||
columns: new[] { "Slot", "PrefsId" },
|
||||
unique: true);
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropIndex(
|
||||
name: "IX_HumanoidProfile_Slot_PrefsId",
|
||||
table: "HumanoidProfile");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,8 @@
|
||||
// <auto-generated />
|
||||
|
||||
using Content.Server.Database;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
|
||||
namespace Content.Server.Database.Migrations
|
||||
{
|
||||
@@ -12,7 +13,7 @@ namespace Content.Server.Database.Migrations
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "3.1.0");
|
||||
.HasAnnotation("ProductVersion", "3.1.4");
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.HumanoidProfile", b =>
|
||||
{
|
||||
@@ -72,6 +73,9 @@ namespace Content.Server.Database.Migrations
|
||||
|
||||
b.HasIndex("PrefsId");
|
||||
|
||||
b.HasIndex("Slot", "PrefsId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("HumanoidProfile");
|
||||
});
|
||||
|
||||
|
||||
@@ -53,12 +53,17 @@ namespace Content.Server.Database
|
||||
}
|
||||
|
||||
public DbSet<Prefs> Preferences { get; set; } = null!;
|
||||
public DbSet<HumanoidProfile> HumanoidProfile { get; set; } = null!;
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||
{
|
||||
modelBuilder.Entity<Prefs>()
|
||||
.HasIndex(p => p.Username)
|
||||
.IsUnique();
|
||||
|
||||
modelBuilder.Entity<HumanoidProfile>()
|
||||
.HasIndex(p => new {p.Slot, p.PrefsId})
|
||||
.IsUnique();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Content.Server.Database
|
||||
@@ -20,16 +22,16 @@ namespace Content.Server.Database
|
||||
_prefsCtx.Database.Migrate();
|
||||
}
|
||||
|
||||
public Prefs GetPlayerPreferences(string username)
|
||||
public async Task<Prefs?> GetPlayerPreferences(string username)
|
||||
{
|
||||
return _prefsCtx
|
||||
return await _prefsCtx
|
||||
.Preferences
|
||||
.Include(p => p.HumanoidProfiles)
|
||||
.ThenInclude(h => h.Jobs)
|
||||
.SingleOrDefault(p => p.Username == username);
|
||||
.SingleOrDefaultAsync(p => p.Username == username);
|
||||
}
|
||||
|
||||
public void SaveSelectedCharacterIndex(string username, int slot)
|
||||
public async Task SaveSelectedCharacterIndex(string username, int slot)
|
||||
{
|
||||
var prefs = _prefsCtx.Preferences.SingleOrDefault(p => p.Username == username);
|
||||
if (prefs is null)
|
||||
@@ -40,10 +42,10 @@ namespace Content.Server.Database
|
||||
});
|
||||
else
|
||||
prefs.SelectedCharacterSlot = slot;
|
||||
_prefsCtx.SaveChanges();
|
||||
await _prefsCtx.SaveChangesAsync();
|
||||
}
|
||||
|
||||
public void SaveCharacterSlot(string username, HumanoidProfile newProfile)
|
||||
public async Task SaveCharacterSlotAsync(string username, HumanoidProfile newProfile)
|
||||
{
|
||||
var prefs = _prefsCtx
|
||||
.Preferences
|
||||
@@ -53,17 +55,29 @@ namespace Content.Server.Database
|
||||
.SingleOrDefault(h => h.Slot == newProfile.Slot);
|
||||
if (!(oldProfile is null)) prefs.HumanoidProfiles.Remove(oldProfile);
|
||||
prefs.HumanoidProfiles.Add(newProfile);
|
||||
_prefsCtx.SaveChanges();
|
||||
await _prefsCtx.SaveChangesAsync();
|
||||
}
|
||||
|
||||
public void DeleteCharacterSlot(string username, int slot)
|
||||
public async Task DeleteCharacterSlotAsync(string username, int slot)
|
||||
{
|
||||
var profile = _prefsCtx
|
||||
.Preferences
|
||||
.Single(p => p.Username == username)
|
||||
.HumanoidProfiles
|
||||
.RemoveAll(h => h.Slot == slot);
|
||||
_prefsCtx.SaveChanges();
|
||||
await _prefsCtx.SaveChangesAsync();
|
||||
}
|
||||
|
||||
public async Task<Dictionary<string, HumanoidProfile>> GetProfilesForPlayersAsync(List<string> usernames)
|
||||
{
|
||||
return await _prefsCtx.HumanoidProfile
|
||||
.Include(p => p.Jobs)
|
||||
.Join(_prefsCtx.Preferences,
|
||||
profile => new {profile.Slot, profile.PrefsId},
|
||||
prefs => new {Slot = prefs.SelectedCharacterSlot, prefs.PrefsId},
|
||||
(profile, prefs) => new {prefs.Username, profile})
|
||||
.Where(p => usernames.Contains(p.Username))
|
||||
.ToDictionaryAsync(arg => arg.Username, arg => arg.profile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,9 +82,9 @@ namespace Content.Server
|
||||
{
|
||||
base.PostInit();
|
||||
|
||||
IoCManager.Resolve<IServerPreferencesManager>().FinishInit();
|
||||
_gameTicker.Initialize();
|
||||
IoCManager.Resolve<ISandboxManager>().Initialize();
|
||||
IoCManager.Resolve<IServerPreferencesManager>().FinishInit();
|
||||
IoCManager.Resolve<RecipeManager>().Initialize();
|
||||
IoCManager.Resolve<BlackboardManager>().Initialize();
|
||||
IoCManager.Resolve<IPDAUplinkManager>().Initialize();
|
||||
|
||||
@@ -19,7 +19,7 @@ namespace Content.Server.GameTicking
|
||||
private readonly Dictionary<string, int> _spawnedPositions = new Dictionary<string, int>();
|
||||
|
||||
private Dictionary<IPlayerSession, string> AssignJobs(List<IPlayerSession> available,
|
||||
Dictionary<IPlayerSession, HumanoidCharacterProfile> profiles)
|
||||
Dictionary<string, HumanoidCharacterProfile> profiles)
|
||||
{
|
||||
// Calculate positions available round-start for each job.
|
||||
var availablePositions = GetBasePositions(true);
|
||||
@@ -38,7 +38,7 @@ namespace Content.Server.GameTicking
|
||||
var candidates = available
|
||||
.Select(player =>
|
||||
{
|
||||
var profile = profiles[player];
|
||||
var profile = profiles[player.Name];
|
||||
|
||||
var availableJobs = profile.JobPriorities
|
||||
.Where(j =>
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Content.Server.GameObjects;
|
||||
using Content.Server.GameObjects.Components.Access;
|
||||
using Content.Server.GameObjects.Components.Markers;
|
||||
@@ -205,7 +206,7 @@ namespace Content.Server.GameTicking
|
||||
}
|
||||
}
|
||||
|
||||
public void StartRound(bool force = false)
|
||||
public async void StartRound(bool force = false)
|
||||
{
|
||||
DebugTools.Assert(RunLevel == GameRunLevel.PreRoundLobby);
|
||||
Logger.InfoS("ticker", "Starting round!");
|
||||
@@ -227,7 +228,18 @@ namespace Content.Server.GameTicking
|
||||
RoundLengthMetric.Set(0);
|
||||
|
||||
// Get the profiles for each player for easier lookup.
|
||||
var profiles = readyPlayers.ToDictionary(p => p, GetPlayerProfile);
|
||||
var profiles = (await _prefsManager.GetSelectedProfilesForPlayersAsync(
|
||||
readyPlayers
|
||||
.Select(p => p.Name).ToList()))
|
||||
.ToDictionary(p => p.Key, p => (HumanoidCharacterProfile) p.Value);
|
||||
|
||||
foreach (var readyPlayer in readyPlayers)
|
||||
{
|
||||
if (!profiles.ContainsKey(readyPlayer.Name))
|
||||
{
|
||||
profiles.Add(readyPlayer.Name, HumanoidCharacterProfile.Default());
|
||||
}
|
||||
}
|
||||
|
||||
var assignedJobs = AssignJobs(readyPlayers, profiles);
|
||||
|
||||
@@ -239,7 +251,7 @@ namespace Content.Server.GameTicking
|
||||
continue;
|
||||
}
|
||||
|
||||
var profile = profiles[player];
|
||||
var profile = profiles[player.Name];
|
||||
if (profile.PreferenceUnavailable == PreferenceUnavailableMode.SpawnAsOverflow)
|
||||
{
|
||||
assignedJobs.Add(player, OverflowJob);
|
||||
@@ -259,7 +271,8 @@ namespace Content.Server.GameTicking
|
||||
{
|
||||
SetStartPreset(_configurationManager.GetCVar<string>("game.fallbackpreset"));
|
||||
var newPreset = MakeGamePreset();
|
||||
_chatManager.DispatchServerAnnouncement($"Failed to start {preset.ModeTitle} mode! Defaulting to {newPreset.ModeTitle}...");
|
||||
_chatManager.DispatchServerAnnouncement(
|
||||
$"Failed to start {preset.ModeTitle} mode! Defaulting to {newPreset.ModeTitle}...");
|
||||
if (!newPreset.Start(readyPlayers, force))
|
||||
{
|
||||
throw new ApplicationException("Fallback preset failed to start!");
|
||||
@@ -278,8 +291,9 @@ namespace Content.Server.GameTicking
|
||||
IoCManager.Resolve<IServerNetManager>().ServerSendToAll(msg);
|
||||
}
|
||||
|
||||
private HumanoidCharacterProfile GetPlayerProfile(IPlayerSession p) =>
|
||||
(HumanoidCharacterProfile) _prefsManager.GetPreferences(p.SessionId.Username).SelectedCharacter;
|
||||
private async Task<HumanoidCharacterProfile> GetPlayerProfileAsync(IPlayerSession p) =>
|
||||
(HumanoidCharacterProfile) (await _prefsManager.GetPreferencesAsync(p.SessionId.Username))
|
||||
.SelectedCharacter;
|
||||
|
||||
public void EndRound()
|
||||
{
|
||||
@@ -307,7 +321,9 @@ namespace Content.Server.GameTicking
|
||||
{
|
||||
PlayerOOCName = ply.Name,
|
||||
PlayerICName = mind.CurrentEntity.Name,
|
||||
Role = antag ? mind.AllRoles.First(role => role.Antag).Name : mind.AllRoles.FirstOrDefault()?.Name ?? Loc.GetString("Unknown"),
|
||||
Role = antag
|
||||
? mind.AllRoles.First(role => role.Antag).Name
|
||||
: mind.AllRoles.FirstOrDefault()?.Name ?? Loc.GetString("Unknown"),
|
||||
Antag = antag
|
||||
};
|
||||
listOfPlayerInfo.Add(playerEndRoundInfo);
|
||||
@@ -725,14 +741,14 @@ namespace Content.Server.GameTicking
|
||||
}, _updateShutdownCts.Token);
|
||||
}
|
||||
|
||||
private void SpawnPlayer(IPlayerSession session, string jobId = null, bool lateJoin = true)
|
||||
private async void SpawnPlayer(IPlayerSession session, string jobId = null, bool lateJoin = true)
|
||||
{
|
||||
var character = (HumanoidCharacterProfile) _prefsManager
|
||||
.GetPreferences(session.SessionId.Username)
|
||||
.SelectedCharacter;
|
||||
|
||||
_playerJoinGame(session);
|
||||
|
||||
var character = (HumanoidCharacterProfile) (await _prefsManager
|
||||
.GetPreferencesAsync(session.SessionId.Username))
|
||||
.SelectedCharacter;
|
||||
|
||||
var data = session.ContentData();
|
||||
data.WipeMind();
|
||||
data.Mind = new Mind(session.SessionId)
|
||||
@@ -789,11 +805,12 @@ namespace Content.Server.GameTicking
|
||||
{
|
||||
if (mindComponent.Mind.AllRoles.Any(role => role.Antag)) //Give antags a new uplinkaccount.
|
||||
{
|
||||
var uplinkAccount = new UplinkAccount(mob.Uid, 20); //TODO: make me into a variable based on server pop or something.
|
||||
var uplinkAccount =
|
||||
new UplinkAccount(mob.Uid,
|
||||
20); //TODO: make me into a variable based on server pop or something.
|
||||
pdaComponent.InitUplinkAccount(uplinkAccount);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void AddManifestEntry(string characterName, string jobId)
|
||||
@@ -801,13 +818,14 @@ namespace Content.Server.GameTicking
|
||||
_manifest.Add(new ManifestEntry(characterName, jobId));
|
||||
}
|
||||
|
||||
private void _spawnObserver(IPlayerSession session)
|
||||
private async void _spawnObserver(IPlayerSession session)
|
||||
{
|
||||
var name = _prefsManager
|
||||
.GetPreferences(session.SessionId.Username)
|
||||
_playerJoinGame(session);
|
||||
|
||||
var name = (await _prefsManager
|
||||
.GetPreferencesAsync(session.SessionId.Username))
|
||||
.SelectedCharacter.Name;
|
||||
|
||||
_playerJoinGame(session);
|
||||
var data = session.ContentData();
|
||||
data.WipeMind();
|
||||
data.Mind = new Mind(session.SessionId);
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Content.Shared.Preferences;
|
||||
using Robust.Server.Interfaces.Player;
|
||||
|
||||
@@ -7,7 +9,8 @@ namespace Content.Server.Interfaces
|
||||
{
|
||||
void FinishInit();
|
||||
void OnClientConnected(IPlayerSession session);
|
||||
PlayerPreferences GetPreferences(string username);
|
||||
Task<PlayerPreferences> GetPreferencesAsync(string username);
|
||||
Task<IEnumerable<KeyValuePair<string, ICharacterProfile>>> GetSelectedProfilesForPlayersAsync(List<string> usernames);
|
||||
void StartInit();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Content.Server.Database;
|
||||
using Content.Shared.Preferences;
|
||||
using Robust.Shared.Maths;
|
||||
@@ -16,38 +19,28 @@ namespace Content.Server.Preferences
|
||||
private readonly int _maxCharacterSlots;
|
||||
private readonly PrefsDb _prefsDb;
|
||||
|
||||
// We use a single DbContext for the entire DB connection, and EFCore doesn't allow concurrent access.
|
||||
// So we need this semaphore to prevent bugs.
|
||||
private readonly SemaphoreSlim _prefsSemaphore = new SemaphoreSlim(1, 1);
|
||||
|
||||
public PreferencesDatabase(IDatabaseConfiguration dbConfig, int maxCharacterSlots)
|
||||
{
|
||||
_maxCharacterSlots = maxCharacterSlots;
|
||||
_prefsDb = new PrefsDb(dbConfig);
|
||||
}
|
||||
|
||||
public PlayerPreferences GetPlayerPreferences(string username)
|
||||
public async Task<PlayerPreferences> GetPlayerPreferencesAsync(string username)
|
||||
{
|
||||
var prefs = _prefsDb.GetPlayerPreferences(username);
|
||||
await _prefsSemaphore.WaitAsync();
|
||||
try
|
||||
{
|
||||
var prefs = await _prefsDb.GetPlayerPreferences(username);
|
||||
if (prefs is null) return null;
|
||||
|
||||
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,
|
||||
profile.Sex == "Male" ? Male : Female,
|
||||
new HumanoidCharacterAppearance
|
||||
(
|
||||
profile.HairName,
|
||||
Color.FromHex(profile.HairColor),
|
||||
profile.FacialHairName,
|
||||
Color.FromHex(profile.FacialHairColor),
|
||||
Color.FromHex(profile.EyeColor),
|
||||
Color.FromHex(profile.SkinColor)
|
||||
),
|
||||
jobs,
|
||||
(PreferenceUnavailableMode) profile.PreferenceUnavailable
|
||||
);
|
||||
profiles[profile.Slot] = ConvertProfiles(profile);
|
||||
}
|
||||
|
||||
return new PlayerPreferences
|
||||
@@ -56,20 +49,37 @@ namespace Content.Server.Preferences
|
||||
prefs.SelectedCharacterSlot
|
||||
);
|
||||
}
|
||||
|
||||
public void SaveSelectedCharacterIndex(string username, int index)
|
||||
finally
|
||||
{
|
||||
index = index.Clamp(0, _maxCharacterSlots - 1);
|
||||
_prefsDb.SaveSelectedCharacterIndex(username, index);
|
||||
_prefsSemaphore.Release();
|
||||
}
|
||||
}
|
||||
|
||||
public void SaveCharacterSlot(string username, ICharacterProfile profile, int slot)
|
||||
public async Task SaveSelectedCharacterIndexAsync(string username, int index)
|
||||
{
|
||||
await _prefsSemaphore.WaitAsync();
|
||||
try
|
||||
{
|
||||
index = index.Clamp(0, _maxCharacterSlots - 1);
|
||||
await _prefsDb.SaveSelectedCharacterIndex(username, index);
|
||||
}
|
||||
finally
|
||||
{
|
||||
_prefsSemaphore.Release();
|
||||
}
|
||||
}
|
||||
|
||||
public async Task SaveCharacterSlotAsync(string username, ICharacterProfile profile, int slot)
|
||||
{
|
||||
if (slot < 0 || slot >= _maxCharacterSlots)
|
||||
return;
|
||||
|
||||
await _prefsSemaphore.WaitAsync();
|
||||
try
|
||||
{
|
||||
if (profile is null)
|
||||
{
|
||||
DeleteCharacterSlot(username, slot);
|
||||
await DeleteCharacterSlotAsync(username, slot);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -97,12 +107,55 @@ namespace Content.Server.Preferences
|
||||
.Where(j => j.Value != JobPriority.Never)
|
||||
.Select(j => new Job {JobName = j.Key, Priority = (DbJobPriority) j.Value})
|
||||
);
|
||||
_prefsDb.SaveCharacterSlot(username, entity);
|
||||
await _prefsDb.SaveCharacterSlotAsync(username, entity);
|
||||
}
|
||||
finally
|
||||
{
|
||||
_prefsSemaphore.Release();
|
||||
}
|
||||
}
|
||||
|
||||
private void DeleteCharacterSlot(string username, int slot)
|
||||
|
||||
private async Task DeleteCharacterSlotAsync(string username, int slot)
|
||||
{
|
||||
_prefsDb.DeleteCharacterSlot(username, slot);
|
||||
await _prefsDb.DeleteCharacterSlotAsync(username, slot);
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<KeyValuePair<string, ICharacterProfile>>> GetSelectedProfilesForPlayersAsync(
|
||||
List<string> usernames)
|
||||
{
|
||||
await _prefsSemaphore.WaitAsync();
|
||||
try
|
||||
{
|
||||
var profiles = await _prefsDb.GetProfilesForPlayersAsync(usernames);
|
||||
return profiles.Select(
|
||||
p => new KeyValuePair<string, ICharacterProfile>(p.Key, ConvertProfiles(p.Value)));
|
||||
}
|
||||
finally
|
||||
{
|
||||
_prefsSemaphore.Release();
|
||||
}
|
||||
}
|
||||
|
||||
private static HumanoidCharacterProfile ConvertProfiles(HumanoidProfile profile)
|
||||
{
|
||||
var jobs = profile.Jobs.ToDictionary(j => j.JobName, j => (JobPriority) j.Priority);
|
||||
return new HumanoidCharacterProfile(
|
||||
profile.CharacterName,
|
||||
profile.Age,
|
||||
profile.Sex == "Male" ? Male : Female,
|
||||
new HumanoidCharacterAppearance
|
||||
(
|
||||
profile.HairName,
|
||||
Color.FromHex(profile.HairColor),
|
||||
profile.FacialHairName,
|
||||
Color.FromHex(profile.FacialHairColor),
|
||||
Color.FromHex(profile.EyeColor),
|
||||
Color.FromHex(profile.SkinColor)
|
||||
),
|
||||
jobs,
|
||||
(PreferenceUnavailableMode) profile.PreferenceUnavailable
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using Content.Server.Database;
|
||||
@@ -82,20 +83,22 @@ namespace Content.Server.Preferences
|
||||
_preferencesDb = _prefsDbLoadTask.Result;
|
||||
}
|
||||
|
||||
private void HandleSelectCharacterMessage(MsgSelectCharacter message)
|
||||
private async void HandleSelectCharacterMessage(MsgSelectCharacter message)
|
||||
{
|
||||
_preferencesDb.SaveSelectedCharacterIndex(message.MsgChannel.SessionId.Username, message.SelectedCharacterIndex);
|
||||
await _preferencesDb.SaveSelectedCharacterIndexAsync(message.MsgChannel.SessionId.Username,
|
||||
message.SelectedCharacterIndex);
|
||||
}
|
||||
|
||||
private void HandleUpdateCharacterMessage(MsgUpdateCharacter message)
|
||||
private async void HandleUpdateCharacterMessage(MsgUpdateCharacter message)
|
||||
{
|
||||
_preferencesDb.SaveCharacterSlot(message.MsgChannel.SessionId.Username, message.Profile, message.Slot);
|
||||
await _preferencesDb.SaveCharacterSlotAsync(message.MsgChannel.SessionId.Username, message.Profile,
|
||||
message.Slot);
|
||||
}
|
||||
|
||||
public void OnClientConnected(IPlayerSession session)
|
||||
public async void OnClientConnected(IPlayerSession session)
|
||||
{
|
||||
var msg = _netManager.CreateNetMessage<MsgPreferencesAndSettings>();
|
||||
msg.Preferences = GetPreferences(session.SessionId.Username);
|
||||
msg.Preferences = await GetPreferencesAsync(session.SessionId.Username);
|
||||
msg.Settings = new GameSettings
|
||||
{
|
||||
MaxCharacterSlots = _configuration.GetCVar<int>("game.maxcharacterslots")
|
||||
@@ -106,26 +109,31 @@ namespace Content.Server.Preferences
|
||||
/// <summary>
|
||||
/// Returns the requested <see cref="PlayerPreferences"/> or null if not found.
|
||||
/// </summary>
|
||||
private PlayerPreferences GetFromSql(string username)
|
||||
private async Task<PlayerPreferences> GetFromSql(string username)
|
||||
{
|
||||
return _preferencesDb.GetPlayerPreferences(username);
|
||||
return await _preferencesDb.GetPlayerPreferencesAsync(username);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves preferences for the given username from storage.
|
||||
/// Creates and saves default preferences if they are not found, then returns them.
|
||||
/// </summary>
|
||||
public PlayerPreferences GetPreferences(string username)
|
||||
public async Task<PlayerPreferences> GetPreferencesAsync(string username)
|
||||
{
|
||||
var prefs = GetFromSql(username);
|
||||
var prefs = await GetFromSql(username);
|
||||
if (prefs is null)
|
||||
{
|
||||
_preferencesDb.SaveSelectedCharacterIndex(username, 0);
|
||||
_preferencesDb.SaveCharacterSlot(username, HumanoidCharacterProfile.Default(), 0);
|
||||
prefs = GetFromSql(username);
|
||||
await _preferencesDb.SaveSelectedCharacterIndexAsync(username, 0);
|
||||
await _preferencesDb.SaveCharacterSlotAsync(username, HumanoidCharacterProfile.Default(), 0);
|
||||
prefs = await GetFromSql(username);
|
||||
}
|
||||
|
||||
return prefs;
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<KeyValuePair<string, ICharacterProfile>>> GetSelectedProfilesForPlayersAsync(List<string> usernames)
|
||||
{
|
||||
return await _preferencesDb.GetSelectedProfilesForPlayersAsync(usernames);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Content.Server.Database;
|
||||
using Content.Server.Preferences;
|
||||
using Content.Shared;
|
||||
@@ -44,64 +45,64 @@ namespace Content.Tests.Server.Preferences
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestUserDoesNotExist()
|
||||
public async Task TestUserDoesNotExist()
|
||||
{
|
||||
var db = GetDb();
|
||||
Assert.Null(db.GetPlayerPreferences("[The database should be empty so any string should do]"));
|
||||
Assert.Null(await db.GetPlayerPreferencesAsync("[The database should be empty so any string should do]"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestUserDoesExist()
|
||||
public async Task TestUserDoesExist()
|
||||
{
|
||||
var db = GetDb();
|
||||
const string username = "bobby";
|
||||
db.SaveSelectedCharacterIndex(username, 0);
|
||||
var prefs = db.GetPlayerPreferences(username);
|
||||
await db.SaveSelectedCharacterIndexAsync(username, 0);
|
||||
var prefs = await db.GetPlayerPreferencesAsync(username);
|
||||
Assert.NotNull(prefs);
|
||||
Assert.Zero(prefs.SelectedCharacterIndex);
|
||||
Assert.That(prefs.Characters.ToList().TrueForAll(character => character is null));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestUpdateCharacter()
|
||||
public async Task TestUpdateCharacter()
|
||||
{
|
||||
var db = GetDb();
|
||||
const string username = "charlie";
|
||||
const int slot = 0;
|
||||
var originalProfile = CharlieCharlieson();
|
||||
db.SaveSelectedCharacterIndex(username, slot);
|
||||
db.SaveCharacterSlot(username, originalProfile, slot);
|
||||
var prefs = db.GetPlayerPreferences(username);
|
||||
await db.SaveSelectedCharacterIndexAsync(username, slot);
|
||||
await db.SaveCharacterSlotAsync(username, originalProfile, slot);
|
||||
var prefs = await db.GetPlayerPreferencesAsync(username);
|
||||
Assert.That(prefs.Characters.ElementAt(slot).MemberwiseEquals(originalProfile));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestDeleteCharacter()
|
||||
public async Task TestDeleteCharacter()
|
||||
{
|
||||
var db = GetDb();
|
||||
const string username = "charlie";
|
||||
const int slot = 0;
|
||||
db.SaveSelectedCharacterIndex(username, slot);
|
||||
db.SaveCharacterSlot(username, CharlieCharlieson(), slot);
|
||||
db.SaveCharacterSlot(username, null, slot);
|
||||
var prefs = db.GetPlayerPreferences(username);
|
||||
await db.SaveSelectedCharacterIndexAsync(username, slot);
|
||||
await db.SaveCharacterSlotAsync(username, CharlieCharlieson(), slot);
|
||||
await db.SaveCharacterSlotAsync(username, null, slot);
|
||||
var prefs = await db.GetPlayerPreferencesAsync(username);
|
||||
Assert.That(prefs.Characters.ToList().TrueForAll(character => character is null));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestInvalidSlot()
|
||||
public async Task TestInvalidSlot()
|
||||
{
|
||||
var db = GetDb();
|
||||
const string username = "charlie";
|
||||
const int slot = -1;
|
||||
|
||||
db.SaveSelectedCharacterIndex(username, slot);
|
||||
db.SaveCharacterSlot(username, CharlieCharlieson(), slot);
|
||||
var prefs = db.GetPlayerPreferences(username);
|
||||
await db.SaveSelectedCharacterIndexAsync(username, slot);
|
||||
await db.SaveCharacterSlotAsync(username, CharlieCharlieson(), slot);
|
||||
var prefs = await db.GetPlayerPreferencesAsync(username);
|
||||
Assert.AreEqual(prefs.SelectedCharacterIndex, 0);
|
||||
|
||||
db.SaveSelectedCharacterIndex(username, MaxCharacterSlots);
|
||||
prefs = db.GetPlayerPreferences(username);
|
||||
await db.SaveSelectedCharacterIndexAsync(username, MaxCharacterSlots);
|
||||
prefs = await db.GetPlayerPreferencesAsync(username);
|
||||
Assert.AreEqual(prefs.SelectedCharacterIndex, MaxCharacterSlots - 1);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user