diff --git a/.gitignore b/.gitignore index 9ecf3dd..f6a5f2c 100644 --- a/.gitignore +++ b/.gitignore @@ -405,4 +405,7 @@ Plugins/ Canvas/ Zones/ -!WFDS.Server/Pages/Canvas/ \ No newline at end of file +!WFDS.Server/Pages/Canvas/ + +data.db +data.db-* \ No newline at end of file diff --git a/WFDS.Common/Steam/SessionManager.cs b/WFDS.Common/Steam/SessionManager.cs index 8984abf..f5e635b 100644 --- a/WFDS.Common/Steam/SessionManager.cs +++ b/WFDS.Common/Steam/SessionManager.cs @@ -110,6 +110,7 @@ private bool TryCreateSession(CSteamID steamId) var session = new Session(steamId); if (_sessions.TryAdd(steamId.m_SteamID, session)) { + GameEventBus.Publish(new PlayerJoinedEvent(steamId)); return true; } @@ -250,10 +251,6 @@ private void BroadcastP2PPacket(CSteamID lobbyId, NetChannel channel, object dat } } - /* ************************************************************************ */ - /* Steamworks Callbacks */ - /* ************************************************************************ */ - #region Steamworks Callbacks private void OnLobbyChatUpdate(LobbyChatUpdate_t param) diff --git a/WFDS.Database/DataDbContext.cs b/WFDS.Database/DataDbContext.cs new file mode 100644 index 0000000..03e94df --- /dev/null +++ b/WFDS.Database/DataDbContext.cs @@ -0,0 +1,18 @@ +using Microsoft.EntityFrameworkCore; +using WFDS.Database.DbSet; + +namespace WFDS.Database; + +public class DataDbContext(DbContextOptions options) : DbContext(options) +{ + public DbSet Players { get; set; } + public DbSet BannedPlayers { get; set; } + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + modelBuilder.Entity().ToTable("players"); + modelBuilder.Entity().ToTable("banned_players"); + + base.OnModelCreating(modelBuilder); + } +} \ No newline at end of file diff --git a/WFDS.Database/DataDbContextFactory.cs b/WFDS.Database/DataDbContextFactory.cs new file mode 100644 index 0000000..9d264c9 --- /dev/null +++ b/WFDS.Database/DataDbContextFactory.cs @@ -0,0 +1,15 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Design; + +namespace WFDS.Database; + +public class DataDbContextFactory : IDesignTimeDbContextFactory +{ + public DataDbContext CreateDbContext(string[] args) + { + var optionsBuilder = new DbContextOptionsBuilder(); + optionsBuilder.UseSqlite("Data Source=./data.db;Cache=Shared"); + + return new DataDbContext(optionsBuilder.Options); + } +} \ No newline at end of file diff --git a/WFDS.Database/DbSet/BannedPlayer.cs b/WFDS.Database/DbSet/BannedPlayer.cs new file mode 100644 index 0000000..8f76fe3 --- /dev/null +++ b/WFDS.Database/DbSet/BannedPlayer.cs @@ -0,0 +1,23 @@ +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using Microsoft.EntityFrameworkCore; + +namespace WFDS.Database.DbSet; + +[Index(nameof(SteamId), IsUnique = true)] +public class BannedPlayer +{ + [Key] + [Column("id")] + public long Id { get; init; } + + [Column("steam_id")] + public ulong SteamId { get; init; } + + [MaxLength(32)] + [Column("display_name")] + public string DisplayName { get; set; } = string.Empty; + + [Column("banned_at")] + public DateTime BannedAt { get; set; } = DateTime.UtcNow; +} \ No newline at end of file diff --git a/WFDS.Database/DbSet/Player.cs b/WFDS.Database/DbSet/Player.cs new file mode 100644 index 0000000..892522e --- /dev/null +++ b/WFDS.Database/DbSet/Player.cs @@ -0,0 +1,25 @@ +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using Microsoft.EntityFrameworkCore; + +namespace WFDS.Database.DbSet; + +[Index(nameof(SteamId), IsUnique = true)] +public class Player +{ + [Key] + [Column("id")] + public long Id { get; init; } + [Column("steam_id")] + public ulong SteamId { get; init; } + + [MaxLength(32)] + [Column("display_name")] + public string DisplayName { get; set; } = string.Empty; + [Column("last_joined_at")] + public DateTime LastJoinedAt { get; set; } = DateTime.UtcNow; + [Column("created_at")] + public DateTime CreatedAt { get; set; } = DateTime.UtcNow; + [Column("updated_at")] + public DateTime UpdatedAt { get; set; } = DateTime.UtcNow; +} \ No newline at end of file diff --git a/WFDS.Database/Migrations/20241210075353_Initial.Designer.cs b/WFDS.Database/Migrations/20241210075353_Initial.Designer.cs new file mode 100644 index 0000000..b864a85 --- /dev/null +++ b/WFDS.Database/Migrations/20241210075353_Initial.Designer.cs @@ -0,0 +1,81 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using WFDS.Database; + +#nullable disable + +namespace WFDS.Database.Migrations +{ + [DbContext(typeof(DataDbContext))] + [Migration("20241210075353_Initial")] + partial class Initial + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "9.0.0"); + + modelBuilder.Entity("WFDS.Database.DbSet.BannedPlayer", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(32) + .HasColumnType("TEXT"); + + b.Property("SteamId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("SteamId") + .IsUnique(); + + b.ToTable("banned_players", (string)null); + }); + + modelBuilder.Entity("WFDS.Database.DbSet.Player", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(32) + .HasColumnType("TEXT"); + + b.Property("LastJoinedAt") + .HasColumnType("TEXT"); + + b.Property("SteamId") + .HasColumnType("INTEGER"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("SteamId") + .IsUnique(); + + b.ToTable("players", (string)null); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/WFDS.Database/Migrations/20241210075353_Initial.cs b/WFDS.Database/Migrations/20241210075353_Initial.cs new file mode 100644 index 0000000..3f7329a --- /dev/null +++ b/WFDS.Database/Migrations/20241210075353_Initial.cs @@ -0,0 +1,69 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace WFDS.Database.Migrations +{ + /// + public partial class Initial : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "banned_players", + columns: table => new + { + Id = table.Column(type: "INTEGER", nullable: false) + .Annotation("Sqlite:Autoincrement", true), + SteamId = table.Column(type: "INTEGER", nullable: false), + DisplayName = table.Column(type: "TEXT", maxLength: 32, nullable: false), + CreatedAt = table.Column(type: "TEXT", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_banned_players", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "players", + columns: table => new + { + Id = table.Column(type: "INTEGER", nullable: false) + .Annotation("Sqlite:Autoincrement", true), + SteamId = table.Column(type: "INTEGER", nullable: false), + DisplayName = table.Column(type: "TEXT", maxLength: 32, nullable: false), + LastJoinedAt = table.Column(type: "TEXT", nullable: false), + CreatedAt = table.Column(type: "TEXT", nullable: false), + UpdatedAt = table.Column(type: "TEXT", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_players", x => x.Id); + }); + + migrationBuilder.CreateIndex( + name: "IX_banned_players_SteamId", + table: "banned_players", + column: "SteamId", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_players_SteamId", + table: "players", + column: "SteamId", + unique: true); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "banned_players"); + + migrationBuilder.DropTable( + name: "players"); + } + } +} diff --git a/WFDS.Database/Migrations/20241210075705_ChangeColumnNameAndUpdateBannedPlayers.Designer.cs b/WFDS.Database/Migrations/20241210075705_ChangeColumnNameAndUpdateBannedPlayers.Designer.cs new file mode 100644 index 0000000..54ea1f4 --- /dev/null +++ b/WFDS.Database/Migrations/20241210075705_ChangeColumnNameAndUpdateBannedPlayers.Designer.cs @@ -0,0 +1,91 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using WFDS.Database; + +#nullable disable + +namespace WFDS.Database.Migrations +{ + [DbContext(typeof(DataDbContext))] + [Migration("20241210075705_ChangeColumnNameAndUpdateBannedPlayers")] + partial class ChangeColumnNameAndUpdateBannedPlayers + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "9.0.0"); + + modelBuilder.Entity("WFDS.Database.DbSet.BannedPlayer", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("id"); + + b.Property("BannedAt") + .HasColumnType("TEXT") + .HasColumnName("banned_at"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(32) + .HasColumnType("TEXT") + .HasColumnName("display_name"); + + b.Property("SteamId") + .HasColumnType("INTEGER") + .HasColumnName("steam_id"); + + b.HasKey("Id"); + + b.HasIndex("SteamId") + .IsUnique(); + + b.ToTable("banned_players", (string)null); + }); + + modelBuilder.Entity("WFDS.Database.DbSet.Player", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("id"); + + b.Property("CreatedAt") + .HasColumnType("TEXT") + .HasColumnName("created_at"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(32) + .HasColumnType("TEXT") + .HasColumnName("display_name"); + + b.Property("LastJoinedAt") + .HasColumnType("TEXT") + .HasColumnName("last_joined_at"); + + b.Property("SteamId") + .HasColumnType("INTEGER") + .HasColumnName("steam_id"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT") + .HasColumnName("updated_at"); + + b.HasKey("Id"); + + b.HasIndex("SteamId") + .IsUnique(); + + b.ToTable("players", (string)null); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/WFDS.Database/Migrations/20241210075705_ChangeColumnNameAndUpdateBannedPlayers.cs b/WFDS.Database/Migrations/20241210075705_ChangeColumnNameAndUpdateBannedPlayers.cs new file mode 100644 index 0000000..bae65ae --- /dev/null +++ b/WFDS.Database/Migrations/20241210075705_ChangeColumnNameAndUpdateBannedPlayers.cs @@ -0,0 +1,138 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace WFDS.Database.Migrations +{ + /// + public partial class ChangeColumnNameAndUpdateBannedPlayers : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.RenameColumn( + name: "Id", + table: "players", + newName: "id"); + + migrationBuilder.RenameColumn( + name: "UpdatedAt", + table: "players", + newName: "updated_at"); + + migrationBuilder.RenameColumn( + name: "SteamId", + table: "players", + newName: "steam_id"); + + migrationBuilder.RenameColumn( + name: "LastJoinedAt", + table: "players", + newName: "last_joined_at"); + + migrationBuilder.RenameColumn( + name: "DisplayName", + table: "players", + newName: "display_name"); + + migrationBuilder.RenameColumn( + name: "CreatedAt", + table: "players", + newName: "created_at"); + + migrationBuilder.RenameIndex( + name: "IX_players_SteamId", + table: "players", + newName: "IX_players_steam_id"); + + migrationBuilder.RenameColumn( + name: "Id", + table: "banned_players", + newName: "id"); + + migrationBuilder.RenameColumn( + name: "SteamId", + table: "banned_players", + newName: "steam_id"); + + migrationBuilder.RenameColumn( + name: "DisplayName", + table: "banned_players", + newName: "display_name"); + + migrationBuilder.RenameColumn( + name: "CreatedAt", + table: "banned_players", + newName: "banned_at"); + + migrationBuilder.RenameIndex( + name: "IX_banned_players_SteamId", + table: "banned_players", + newName: "IX_banned_players_steam_id"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.RenameColumn( + name: "id", + table: "players", + newName: "Id"); + + migrationBuilder.RenameColumn( + name: "updated_at", + table: "players", + newName: "UpdatedAt"); + + migrationBuilder.RenameColumn( + name: "steam_id", + table: "players", + newName: "SteamId"); + + migrationBuilder.RenameColumn( + name: "last_joined_at", + table: "players", + newName: "LastJoinedAt"); + + migrationBuilder.RenameColumn( + name: "display_name", + table: "players", + newName: "DisplayName"); + + migrationBuilder.RenameColumn( + name: "created_at", + table: "players", + newName: "CreatedAt"); + + migrationBuilder.RenameIndex( + name: "IX_players_steam_id", + table: "players", + newName: "IX_players_SteamId"); + + migrationBuilder.RenameColumn( + name: "id", + table: "banned_players", + newName: "Id"); + + migrationBuilder.RenameColumn( + name: "steam_id", + table: "banned_players", + newName: "SteamId"); + + migrationBuilder.RenameColumn( + name: "display_name", + table: "banned_players", + newName: "DisplayName"); + + migrationBuilder.RenameColumn( + name: "banned_at", + table: "banned_players", + newName: "CreatedAt"); + + migrationBuilder.RenameIndex( + name: "IX_banned_players_steam_id", + table: "banned_players", + newName: "IX_banned_players_SteamId"); + } + } +} diff --git a/WFDS.Database/Migrations/DataDbContextModelSnapshot.cs b/WFDS.Database/Migrations/DataDbContextModelSnapshot.cs new file mode 100644 index 0000000..16561a8 --- /dev/null +++ b/WFDS.Database/Migrations/DataDbContextModelSnapshot.cs @@ -0,0 +1,88 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using WFDS.Database; + +#nullable disable + +namespace WFDS.Database.Migrations +{ + [DbContext(typeof(DataDbContext))] + partial class DataDbContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "9.0.0"); + + modelBuilder.Entity("WFDS.Database.DbSet.BannedPlayer", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("id"); + + b.Property("BannedAt") + .HasColumnType("TEXT") + .HasColumnName("banned_at"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(32) + .HasColumnType("TEXT") + .HasColumnName("display_name"); + + b.Property("SteamId") + .HasColumnType("INTEGER") + .HasColumnName("steam_id"); + + b.HasKey("Id"); + + b.HasIndex("SteamId") + .IsUnique(); + + b.ToTable("banned_players", (string)null); + }); + + modelBuilder.Entity("WFDS.Database.DbSet.Player", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("id"); + + b.Property("CreatedAt") + .HasColumnType("TEXT") + .HasColumnName("created_at"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(32) + .HasColumnType("TEXT") + .HasColumnName("display_name"); + + b.Property("LastJoinedAt") + .HasColumnType("TEXT") + .HasColumnName("last_joined_at"); + + b.Property("SteamId") + .HasColumnType("INTEGER") + .HasColumnName("steam_id"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT") + .HasColumnName("updated_at"); + + b.HasKey("Id"); + + b.HasIndex("SteamId") + .IsUnique(); + + b.ToTable("players", (string)null); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/WFDS.Database/WFDS.Database.csproj b/WFDS.Database/WFDS.Database.csproj new file mode 100644 index 0000000..895021b --- /dev/null +++ b/WFDS.Database/WFDS.Database.csproj @@ -0,0 +1,21 @@ + + + + net9.0 + enable + enable + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + diff --git a/WFDS.Server/Core/GameEvent/GameEventService.cs b/WFDS.Server/Core/GameEvent/GameEventService.cs index 5cec504..fea43ea 100644 --- a/WFDS.Server/Core/GameEvent/GameEventService.cs +++ b/WFDS.Server/Core/GameEvent/GameEventService.cs @@ -32,7 +32,7 @@ private async Task HandleEventAsync(Common.GameEvents.GameEvent e) try { await using var scope = provider.CreateAsyncScope(); - var handlers = provider.GetServices(); + var handlers = scope.ServiceProvider.GetServices(); foreach (var handler in handlers.Where(x => x.EventType == e.GetType())) { handler.Handle(e); diff --git a/WFDS.Server/Core/Network/PacketHandleManager.cs b/WFDS.Server/Core/Network/PacketHandleManager.cs index b6aaf3e..785ea9a 100644 --- a/WFDS.Server/Core/Network/PacketHandleManager.cs +++ b/WFDS.Server/Core/Network/PacketHandleManager.cs @@ -59,7 +59,8 @@ public void OnPacketReceived(CSteamID sender, NetChannel channel, object? data) session.PacketReceiveTime = DateTimeOffset.UtcNow; if (!_handlerTypes.TryGetValue(typeName, out var handlerTypes)) return; - foreach (var handler in handlerTypes.Select(handlerType => _provider.GetRequiredService(handlerType) as Common.Network.PacketHandler).Where(x => x != null)) + using var scope = _provider.CreateScope(); + foreach (var handler in handlerTypes.Select(handlerType => scope.ServiceProvider.GetRequiredService(handlerType) as Common.Network.PacketHandler).Where(x => x != null)) { handler!.Handle(session, channel, dic); } diff --git a/WFDS.Server/EventHandler/PlayerJoinTitleUpdateHandler.cs b/WFDS.Server/EventHandler/PlayerJoinTitleUpdateHandler.cs deleted file mode 100644 index 1b48370..0000000 --- a/WFDS.Server/EventHandler/PlayerJoinTitleUpdateHandler.cs +++ /dev/null @@ -1,14 +0,0 @@ -using WFDS.Common.GameEvents; -using WFDS.Common.GameEvents.Events; -using WFDS.Common.Helpers; -using WFDS.Common.Steam; - -namespace WFDS.Server.EventHandler; - -public class PlayerJoinTitleUpdateHandler(LobbyManager lobby, SessionManager session) : GameEventHandler -{ - protected override void Handle(PlayerJoinedEvent e) - { - ConsoleHelper.UpdateConsoleTitle(lobby.GetName(), lobby.GetCode(), session.GetSessionCount(), lobby.GetCap()); - } -} \ No newline at end of file diff --git a/WFDS.Server/EventHandler/PlayerJoinedHandler.cs b/WFDS.Server/EventHandler/PlayerJoinedHandler.cs new file mode 100644 index 0000000..b51e79a --- /dev/null +++ b/WFDS.Server/EventHandler/PlayerJoinedHandler.cs @@ -0,0 +1,45 @@ +using WFDS.Common.GameEvents; +using WFDS.Common.GameEvents.Events; +using WFDS.Common.Helpers; +using WFDS.Common.Steam; +using WFDS.Database; +using WFDS.Database.DbSet; + +namespace WFDS.Server.EventHandler; + +public class PlayerJoinedHandler(LobbyManager lobby, SessionManager session, DataDbContext dbContext) : GameEventHandler +{ + protected override void Handle(PlayerJoinedEvent e) + { + ConsoleHelper.UpdateConsoleTitle(lobby.GetName(), lobby.GetCode(), session.GetSessionCount(), lobby.GetCap()); + + var playerName = Steamworks.SteamFriends.GetFriendPersonaName(e.PlayerId); + if (playerName is null) + { + return; + } + + var player = dbContext.Players.FirstOrDefault(x => x.SteamId == e.PlayerId.m_SteamID); + if (player is null) + { + player = new Player() + { + SteamId = e.PlayerId.m_SteamID, + DisplayName = playerName, + CreatedAt = DateTime.UtcNow, + UpdatedAt = DateTime.UtcNow, + LastJoinedAt = DateTime.UtcNow + }; + + dbContext.Players.Add(player); + } + else + { + player.DisplayName = playerName; + player.LastJoinedAt = DateTime.UtcNow; + player.UpdatedAt = DateTime.UtcNow; + } + + dbContext.SaveChanges(); + } +} \ No newline at end of file diff --git a/WFDS.Server/Pages/Session/Index.cshtml b/WFDS.Server/Pages/Session/Index.cshtml index ff91258..61771bf 100644 --- a/WFDS.Server/Pages/Session/Index.cshtml +++ b/WFDS.Server/Pages/Session/Index.cshtml @@ -2,12 +2,13 @@ @model WFDS.Server.Pages.Session.Index @{ - ViewBag.Title = "Session - CurrentPlayers"; + ViewBag.Title = "Session - Players"; Layout = "_SessionLayout"; }
+

Current

Count: @Model.SessionCount / @Model.MaxSessionCount @@ -25,7 +26,7 @@ - +
@session.SteamId @session.Name@session.ConnectTime@session.ConnectTime.ToString("O")
@Html.AntiForgeryToken() @@ -40,4 +41,31 @@
+ +
+

All

+ Total: @Model.GetTotalPlayerCount() + + + + + + + + + + + + @foreach (var player in Model.GetPlayers()) + { + + + + + + + } + +
SteamIdUsernameLastJoinedAtFirstConnectedAt
@player.SteamId@player.DisplayName@player.LastJoinedAt.ToString("O")@player.CreatedAt.ToString("O")
+
\ No newline at end of file diff --git a/WFDS.Server/Pages/Session/Index.cshtml.cs b/WFDS.Server/Pages/Session/Index.cshtml.cs index f5cac7d..f61cc52 100644 --- a/WFDS.Server/Pages/Session/Index.cshtml.cs +++ b/WFDS.Server/Pages/Session/Index.cshtml.cs @@ -2,10 +2,12 @@ using Microsoft.AspNetCore.Mvc.RazorPages; using Steamworks; using WFDS.Common.Steam; +using WFDS.Database; +using WFDS.Database.DbSet; namespace WFDS.Server.Pages.Session; -public class Index(SessionManager sessionManager, LobbyManager lobbyManager) : PageModel +public class Index(SessionManager sessionManager, LobbyManager lobbyManager, DataDbContext dbContext) : PageModel { public int MaxSessionCount { get; } = lobbyManager.GetCap(); public int SessionCount { get; } = sessionManager.GetSessionCount(); @@ -38,4 +40,11 @@ public IActionResult OnPostBan(string steamId) sessionManager.TempBanPlayer(lobbyManager.GetLobbyId(), new CSteamID(value)); return RedirectToPage(new { message = $"banned {steamId}" }); } + + public long GetTotalPlayerCount() + { + return dbContext.Players.LongCount(); + } + + public IEnumerable GetPlayers() => dbContext.Players; } \ No newline at end of file diff --git a/WFDS.Server/Pages/Session/_SessionSubmenu.cshtml b/WFDS.Server/Pages/Session/_SessionSubmenu.cshtml index ee285ea..6d6a5f8 100644 --- a/WFDS.Server/Pages/Session/_SessionSubmenu.cshtml +++ b/WFDS.Server/Pages/Session/_SessionSubmenu.cshtml @@ -1,4 +1,4 @@  \ No newline at end of file diff --git a/WFDS.Server/Program.cs b/WFDS.Server/Program.cs index 1f82d1a..97b029c 100644 --- a/WFDS.Server/Program.cs +++ b/WFDS.Server/Program.cs @@ -1,11 +1,13 @@ using System.Text.Json; using Cysharp.Threading; +using Microsoft.EntityFrameworkCore; using WFDS.Common; using WFDS.Common.Actor; using WFDS.Common.Plugin; using WFDS.Common.Steam; using WFDS.Common.Types; using WFDS.Common.Types.Manager; +using WFDS.Database; using WFDS.Server.Core; using WFDS.Server.Core.Actor; using WFDS.Server.Core.Chalk; @@ -40,13 +42,22 @@ var section = configuration.GetSection("Server"); var setting = section.Get(); - ArgumentNullException.ThrowIfNull(setting, nameof(setting)); + ArgumentNullException.ThrowIfNull(setting); builder.Logging.ClearProviders(); builder.Services.AddSingleton(Log.Factory); builder.Services.Configure(section); builder.UseActorSettings(); + + ///////////////////////////////////////////////////////////////// + + builder.Services.AddDbContext(d => + { + d.UseSqlite("Data Source=./data.db;Cache=Shared"); + }); + + ///////////////////////////////////////////////////////////////// builder.Services.AddSingleton(SteamManager.Inst); builder.Services.AddSingleton(LobbyManager.Inst); @@ -113,6 +124,14 @@ // server start var app = builder.Build(); + // db + using (var scope = app.Services.CreateScope()) + { + var services = scope.ServiceProvider; + var context = services.GetRequiredService(); + await context.Database.MigrateAsync(); + } + app.Services.GetRequiredService() .ApplicationStopped .Register(() => LogicLooperPool.Shared.ShutdownAsync(TimeSpan.Zero).Wait()); @@ -137,7 +156,7 @@ } catch (Exception ex) { - Log.Logger.ZLogCritical(ex, $"host terminated unexpectedly"); + Log.Logger.ZLogCritical(ex, $"host terminated unexpectedly\n"); } finally { diff --git a/WFDS.Server/WFDS.Server.csproj b/WFDS.Server/WFDS.Server.csproj index d74cecd..2d48507 100644 --- a/WFDS.Server/WFDS.Server.csproj +++ b/WFDS.Server/WFDS.Server.csproj @@ -11,6 +11,15 @@ + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + @@ -33,6 +42,7 @@ + diff --git a/WFDedicatedServer.sln b/WFDedicatedServer.sln index 1f25444..82fa371 100644 --- a/WFDedicatedServer.sln +++ b/WFDedicatedServer.sln @@ -10,6 +10,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Plugins", "Plugins", "{573F EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TemplatePlugin", "TemplatePlugin\TemplatePlugin.csproj", "{67024ECD-9116-4B78-9192-71A9DFFA837A}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WFDS.Database", "WFDS.Database\WFDS.Database.csproj", "{80E3F19E-15F8-4A32-B1E8-749B6625E91C}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -32,6 +34,10 @@ Global {67024ECD-9116-4B78-9192-71A9DFFA837A}.Debug|Any CPU.Build.0 = Debug|Any CPU {67024ECD-9116-4B78-9192-71A9DFFA837A}.Release|Any CPU.ActiveCfg = Release|Any CPU {67024ECD-9116-4B78-9192-71A9DFFA837A}.Release|Any CPU.Build.0 = Release|Any CPU + {80E3F19E-15F8-4A32-B1E8-749B6625E91C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {80E3F19E-15F8-4A32-B1E8-749B6625E91C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {80E3F19E-15F8-4A32-B1E8-749B6625E91C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {80E3F19E-15F8-4A32-B1E8-749B6625E91C}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(NestedProjects) = preSolution {67024ECD-9116-4B78-9192-71A9DFFA837A} = {573F14AA-7273-4CBD-951D-E788CF3DB156}