From 0a9cb2d41c9ea62af32d31277b7a3e29e4650a4b Mon Sep 17 00:00:00 2001 From: CyberL1 Date: Wed, 21 Feb 2024 19:02:52 +0100 Subject: [PATCH] Move world players to a separate table --- .../Controllers/InvitesController.cs | 44 ++++++++----- .../Controllers/WorldsController.cs | 16 +++-- Minecraft-Realms-Emulator/Data/DataContext.cs | 1 + Minecraft-Realms-Emulator/Entities/Player.cs | 12 +--- Minecraft-Realms-Emulator/Entities/World.cs | 2 +- .../20240220110531_Worlds_Players.cs | 23 ------- ....cs => 20240221131108_Players.Designer.cs} | 63 +++++++++++++++++-- .../Migrations/20240221131108_Players.cs | 63 +++++++++++++++++++ .../Migrations/DataContextModelSnapshot.cs | 59 +++++++++++++++-- 9 files changed, 219 insertions(+), 64 deletions(-) delete mode 100644 Minecraft-Realms-Emulator/Migrations/20240220110531_Worlds_Players.cs rename Minecraft-Realms-Emulator/Migrations/{20240220110531_Worlds_Players.Designer.cs => 20240221131108_Players.Designer.cs} (81%) create mode 100644 Minecraft-Realms-Emulator/Migrations/20240221131108_Players.cs diff --git a/Minecraft-Realms-Emulator/Controllers/InvitesController.cs b/Minecraft-Realms-Emulator/Controllers/InvitesController.cs index 2b20e45..f38d6c0 100644 --- a/Minecraft-Realms-Emulator/Controllers/InvitesController.cs +++ b/Minecraft-Realms-Emulator/Controllers/InvitesController.cs @@ -2,9 +2,8 @@ using Microsoft.EntityFrameworkCore; using Minecraft_Realms_Emulator.Data; using Minecraft_Realms_Emulator.Entities; +using Minecraft_Realms_Emulator.Migrations; using Minecraft_Realms_Emulator.Responses; -using System; -using System.Text.Json; namespace Minecraft_Realms_Emulator.Controllers { @@ -53,9 +52,17 @@ namespace Minecraft_Realms_Emulator.Controllers [HttpPut("accept/{id}")] public ActionResult AcceptInvite(string id) { - var invite = _context.Invites.FirstOrDefault(i => i.InvitationId == id); + string cookie = Request.Headers.Cookie; + string playerUUID = cookie.Split(";")[0].Split(":")[2]; + + var invite = _context.Invites.Include(i => i.World).FirstOrDefault(i => i.InvitationId == id); if (invite == null) return NotFound("Invite not found"); + + var player = _context.Players.Where(p => p.World.Id == invite.World.Id).FirstOrDefault(p => p.Uuid == playerUUID); + + player.Accepted = true; + _context.Invites.Remove(invite); _context.SaveChanges(); @@ -64,7 +71,7 @@ namespace Minecraft_Realms_Emulator.Controllers } [HttpPut("reject/{id}")] - public async Task> RejectInvite(string id) + public ActionResult RejectInvite(string id) { var invite = _context.Invites.Include(i => i.World).FirstOrDefault(i => i.InvitationId == id); @@ -74,11 +81,10 @@ namespace Minecraft_Realms_Emulator.Controllers string cookie = Request.Headers.Cookie; string playerUUID = cookie.Split(";")[0].Split(":")[2]; - - World world = await _context.Worlds.FindAsync(invite.World.Id); - var playerIndex = world.Players.FindIndex(p => p.RootElement.GetProperty("uuid").ToString() == playerUUID); - world.Players.RemoveAt(playerIndex); + var player = _context.Players.Where(p => p.World.Id == invite.World.Id).FirstOrDefault(p => p.Uuid == playerUUID); + + _context.Players.Remove(player); _context.SaveChanges(); @@ -97,22 +103,28 @@ namespace Minecraft_Realms_Emulator.Controllers if (world == null) return NotFound("World not found"); - if (world.Players.Exists(p => p.RootElement.GetProperty("name").ToString() == body.Name)) return NotFound("Player already invited"); - // Get player UUID var playerInfo = await new HttpClient().GetFromJsonAsync($"https://api.mojang.com/users/profiles/minecraft/{body.Name}"); - body.Uuid = playerInfo.Id; - JsonDocument player = JsonDocument.Parse(JsonSerializer.Serialize(body)); - world.Players.Add(player); + var playerInDB = await _context.Players.Where(p => p.World.Id == wId).FirstOrDefaultAsync(p => p.Uuid == playerInfo.Id); - _context.Worlds.Update(world); + if (playerInDB?.Uuid == playerInfo.Id) return BadRequest("Player already invited"); + + Player player = new() + { + Name = body.Name, + Uuid = playerInfo.Id, + World = world + }; + + _context.Players.Add(player); +// world.Players.Add(player); Invite invite = new() { InvitationId = Guid.NewGuid().ToString(), World = world, - RecipeintUUID = body.Uuid, + RecipeintUUID = playerInfo.Id, Date = DateTime.UtcNow, }; @@ -134,7 +146,7 @@ namespace Minecraft_Realms_Emulator.Controllers var players = world.Players.ToList(); - var playerIndex = world.Players.FindIndex(p => p.RootElement.GetProperty("uuid").ToString() == uuid); + var playerIndex = world.Players.FindIndex(p => p.Uuid == uuid); world.Players.RemoveAt(playerIndex); diff --git a/Minecraft-Realms-Emulator/Controllers/WorldsController.cs b/Minecraft-Realms-Emulator/Controllers/WorldsController.cs index af15840..5385d7d 100644 --- a/Minecraft-Realms-Emulator/Controllers/WorldsController.cs +++ b/Minecraft-Realms-Emulator/Controllers/WorldsController.cs @@ -2,6 +2,7 @@ using Microsoft.EntityFrameworkCore; using Minecraft_Realms_Emulator.Data; using Minecraft_Realms_Emulator.Entities; +using System.Collections.Immutable; namespace Minecraft_Realms_Emulator.Controllers { @@ -24,9 +25,10 @@ namespace Minecraft_Realms_Emulator.Controllers string playerUUID = cookie.Split(";")[0].Split(":")[2]; string playerName = cookie.Split(";")[1].Split("=")[1]; - var worlds = await _context.Worlds.Where(w => w.OwnerUUID == playerUUID).ToListAsync(); + var ownedWorlds = await _context.Worlds.Where(w => w.OwnerUUID == playerUUID).ToListAsync(); + var memberWorlds = await _context.Players.Where(p => p.Uuid == playerUUID && p.Accepted).Select(p => p.World).ToListAsync(); - if (worlds.ToArray().Length == 0) + if (ownedWorlds.ToArray().Length == 0) { var world = new World { @@ -40,7 +42,6 @@ namespace Minecraft_Realms_Emulator.Controllers Expired = false, ExpiredTrial = false, WorldType = WorldType.NORMAL.ToString(), - Players = [], MaxPlayers = 10, MinigameId = null, MinigameName = null, @@ -49,15 +50,20 @@ namespace Minecraft_Realms_Emulator.Controllers Member = false }; - worlds.Add(world); + ownedWorlds.Add(world); _context.Worlds.Add(world); _context.SaveChanges(); } + List allWorlds = []; + + allWorlds.AddRange(ownedWorlds); + allWorlds.AddRange(memberWorlds); + ServersArray servers = new() { - Servers = worlds + Servers = allWorlds }; return Ok(servers); diff --git a/Minecraft-Realms-Emulator/Data/DataContext.cs b/Minecraft-Realms-Emulator/Data/DataContext.cs index 2d8c5b8..0d05db3 100644 --- a/Minecraft-Realms-Emulator/Data/DataContext.cs +++ b/Minecraft-Realms-Emulator/Data/DataContext.cs @@ -10,5 +10,6 @@ namespace Minecraft_Realms_Emulator.Data public DbSet Connections { get; set; } public DbSet Backups { get; set; } public DbSet Invites { get; set; } + public DbSet Players { get; set; } } } diff --git a/Minecraft-Realms-Emulator/Entities/Player.cs b/Minecraft-Realms-Emulator/Entities/Player.cs index 2e0bbd1..a1bdae8 100644 --- a/Minecraft-Realms-Emulator/Entities/Player.cs +++ b/Minecraft-Realms-Emulator/Entities/Player.cs @@ -1,20 +1,14 @@ -using System.Text.Json.Serialization; - -namespace Minecraft_Realms_Emulator.Entities +namespace Minecraft_Realms_Emulator.Entities { public class Player { - [JsonPropertyName("name")] + public int Id { get; set; } public string Name { get; set; } = string.Empty; - [JsonPropertyName("uuid")] public string Uuid { get; set; } = string.Empty; - [JsonPropertyName("operator")] public bool Operator { get; set; } - [JsonPropertyName("accepted")] public bool Accepted { get; set; } - [JsonPropertyName("online")] public bool Online { get; set; } - [JsonPropertyName("permission")] public string Permission { get; set; } = "MEMBER"; + public World? World { get; set; } } } diff --git a/Minecraft-Realms-Emulator/Entities/World.cs b/Minecraft-Realms-Emulator/Entities/World.cs index 45d6ec5..6290f6b 100644 --- a/Minecraft-Realms-Emulator/Entities/World.cs +++ b/Minecraft-Realms-Emulator/Entities/World.cs @@ -15,7 +15,7 @@ namespace Minecraft_Realms_Emulator.Entities public bool Expired { get; set; } = false; public bool ExpiredTrial { get; set; } = false; public string WorldType { get; set; } = "NORMAL"; - public List Players { get; set; } = []; + public List Players { get; set; } = []; public int MaxPlayers { get; set; } = 10; public string? MinigameName { get; set; } public int? MinigameId { get; set; } diff --git a/Minecraft-Realms-Emulator/Migrations/20240220110531_Worlds_Players.cs b/Minecraft-Realms-Emulator/Migrations/20240220110531_Worlds_Players.cs deleted file mode 100644 index 64d7662..0000000 --- a/Minecraft-Realms-Emulator/Migrations/20240220110531_Worlds_Players.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System.Text.Json; -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace Minecraft_Realms_Emulator.Migrations -{ - /// - public partial class Worlds_Players : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.Sql("ALTER TABLE \"Worlds\" ALTER COLUMN \"Players\" TYPE jsonb[] USING \"Players\"::jsonb[]"); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.Sql("ALTER TABLE \"Worlds\" ALTER COLUMN \"Players\" TYPE text[] USING \"Players\"::text[]"); - } - } -} \ No newline at end of file diff --git a/Minecraft-Realms-Emulator/Migrations/20240220110531_Worlds_Players.Designer.cs b/Minecraft-Realms-Emulator/Migrations/20240221131108_Players.Designer.cs similarity index 81% rename from Minecraft-Realms-Emulator/Migrations/20240220110531_Worlds_Players.Designer.cs rename to Minecraft-Realms-Emulator/Migrations/20240221131108_Players.Designer.cs index c983e37..03a631f 100644 --- a/Minecraft-Realms-Emulator/Migrations/20240220110531_Worlds_Players.Designer.cs +++ b/Minecraft-Realms-Emulator/Migrations/20240221131108_Players.Designer.cs @@ -13,8 +13,8 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; namespace Minecraft_Realms_Emulator.Migrations { [DbContext(typeof(DataContext))] - [Migration("20240220110531_Worlds_Players")] - partial class Worlds_Players + [Migration("20240221131108_Players")] + partial class Players { /// protected override void BuildTargetModel(ModelBuilder modelBuilder) @@ -112,6 +112,45 @@ namespace Minecraft_Realms_Emulator.Migrations b.ToTable("Invites"); }); + modelBuilder.Entity("Minecraft_Realms_Emulator.Entities.Player", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Accepted") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Online") + .HasColumnType("boolean"); + + b.Property("Operator") + .HasColumnType("boolean"); + + b.Property("Permission") + .IsRequired() + .HasColumnType("text"); + + b.Property("Uuid") + .IsRequired() + .HasColumnType("text"); + + b.Property("WorldId") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("WorldId"); + + b.ToTable("Players"); + }); + modelBuilder.Entity("Minecraft_Realms_Emulator.Entities.Subscription", b => { b.Property("Id") @@ -185,10 +224,6 @@ namespace Minecraft_Realms_Emulator.Migrations b.Property("OwnerUUID") .HasColumnType("text"); - b.Property("Players") - .IsRequired() - .HasColumnType("jsonb[]"); - b.Property("RemoteSubscriptionId") .IsRequired() .HasColumnType("text"); @@ -243,6 +278,17 @@ namespace Minecraft_Realms_Emulator.Migrations b.Navigation("World"); }); + modelBuilder.Entity("Minecraft_Realms_Emulator.Entities.Player", b => + { + b.HasOne("Minecraft_Realms_Emulator.Entities.World", "World") + .WithMany("Players") + .HasForeignKey("WorldId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("World"); + }); + modelBuilder.Entity("Minecraft_Realms_Emulator.Entities.Subscription", b => { b.HasOne("Minecraft_Realms_Emulator.Entities.World", "World") @@ -253,6 +299,11 @@ namespace Minecraft_Realms_Emulator.Migrations b.Navigation("World"); }); + + modelBuilder.Entity("Minecraft_Realms_Emulator.Entities.World", b => + { + b.Navigation("Players"); + }); #pragma warning restore 612, 618 } } diff --git a/Minecraft-Realms-Emulator/Migrations/20240221131108_Players.cs b/Minecraft-Realms-Emulator/Migrations/20240221131108_Players.cs new file mode 100644 index 0000000..2b091ae --- /dev/null +++ b/Minecraft-Realms-Emulator/Migrations/20240221131108_Players.cs @@ -0,0 +1,63 @@ +using Microsoft.EntityFrameworkCore.Migrations; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace Minecraft_Realms_Emulator.Migrations +{ + /// + public partial class Players : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "Players", + table: "Worlds"); + + migrationBuilder.CreateTable( + name: "Players", + columns: table => new + { + Id = table.Column(type: "integer", nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + Name = table.Column(type: "text", nullable: false), + Uuid = table.Column(type: "text", nullable: false), + Operator = table.Column(type: "boolean", nullable: false), + Accepted = table.Column(type: "boolean", nullable: false), + Online = table.Column(type: "boolean", nullable: false), + Permission = table.Column(type: "text", nullable: false), + WorldId = table.Column(type: "integer", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Players", x => x.Id); + table.ForeignKey( + name: "FK_Players_Worlds_WorldId", + column: x => x.WorldId, + principalTable: "Worlds", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_Players_WorldId", + table: "Players", + column: "WorldId"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "Players"); + + migrationBuilder.AddColumn( + name: "Players", + table: "Worlds", + type: "text[]", + nullable: false, + defaultValue: new string[0]); + } + } +} diff --git a/Minecraft-Realms-Emulator/Migrations/DataContextModelSnapshot.cs b/Minecraft-Realms-Emulator/Migrations/DataContextModelSnapshot.cs index fd2df2b..50a154e 100644 --- a/Minecraft-Realms-Emulator/Migrations/DataContextModelSnapshot.cs +++ b/Minecraft-Realms-Emulator/Migrations/DataContextModelSnapshot.cs @@ -109,6 +109,45 @@ namespace Minecraft_Realms_Emulator.Migrations b.ToTable("Invites"); }); + modelBuilder.Entity("Minecraft_Realms_Emulator.Entities.Player", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Accepted") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Online") + .HasColumnType("boolean"); + + b.Property("Operator") + .HasColumnType("boolean"); + + b.Property("Permission") + .IsRequired() + .HasColumnType("text"); + + b.Property("Uuid") + .IsRequired() + .HasColumnType("text"); + + b.Property("WorldId") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("WorldId"); + + b.ToTable("Players"); + }); + modelBuilder.Entity("Minecraft_Realms_Emulator.Entities.Subscription", b => { b.Property("Id") @@ -182,10 +221,6 @@ namespace Minecraft_Realms_Emulator.Migrations b.Property("OwnerUUID") .HasColumnType("text"); - b.Property("Players") - .IsRequired() - .HasColumnType("jsonb[]"); - b.Property("RemoteSubscriptionId") .IsRequired() .HasColumnType("text"); @@ -240,6 +275,17 @@ namespace Minecraft_Realms_Emulator.Migrations b.Navigation("World"); }); + modelBuilder.Entity("Minecraft_Realms_Emulator.Entities.Player", b => + { + b.HasOne("Minecraft_Realms_Emulator.Entities.World", "World") + .WithMany("Players") + .HasForeignKey("WorldId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("World"); + }); + modelBuilder.Entity("Minecraft_Realms_Emulator.Entities.Subscription", b => { b.HasOne("Minecraft_Realms_Emulator.Entities.World", "World") @@ -250,6 +296,11 @@ namespace Minecraft_Realms_Emulator.Migrations b.Navigation("World"); }); + + modelBuilder.Entity("Minecraft_Realms_Emulator.Entities.World", b => + { + b.Navigation("Players"); + }); #pragma warning restore 612, 618 } }