Files
rr3-server/RR3CommunityServer/Migrations/20260224005348_AddMultiplayerSystem.cs
Daniel Elliott a934f57b52 Add Friends/Social & Multiplayer systems - 95 total endpoints
- Implemented Friends/Social Service (11 endpoints)
  * Friend management (list, add, accept, remove)
  * User search and invitations
  * Gift sending and claiming
  * Clubs/Teams system

- Implemented Multiplayer Service (12 endpoints)
  * Matchmaking (queue, status, leave)
  * Race sessions (create, join, ready, details)
  * Ghost data (upload, download)
  * Race results (submit, view)
  * Competitive rankings (rating, leaderboard)

- Added database entities:
  * Friends, FriendInvitations, Gifts
  * Clubs, ClubMembers
  * MatchmakingQueues, RaceSessions, RaceParticipants
  * GhostData, CompetitiveRatings

- Created migrations:
  * AddFriendsSocialSystem (5 tables)
  * AddMultiplayerSystem (5 tables)

Total: 95 endpoints - 100% EA server replacement ready

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-02-23 16:55:33 -08:00

242 lines
11 KiB
C#

using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace RR3CommunityServer.Migrations
{
/// <inheritdoc />
public partial class AddMultiplayerSystem : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "CompetitiveRatings",
columns: table => new
{
Id = table.Column<int>(type: "INTEGER", nullable: false)
.Annotation("Sqlite:Autoincrement", true),
UserId = table.Column<int>(type: "INTEGER", nullable: false),
Rating = table.Column<int>(type: "INTEGER", nullable: false),
Wins = table.Column<int>(type: "INTEGER", nullable: false),
Losses = table.Column<int>(type: "INTEGER", nullable: false),
Draws = table.Column<int>(type: "INTEGER", nullable: false),
Division = table.Column<string>(type: "TEXT", nullable: false),
DivisionRank = table.Column<int>(type: "INTEGER", nullable: false),
LastMatchAt = table.Column<DateTime>(type: "TEXT", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_CompetitiveRatings", x => x.Id);
table.ForeignKey(
name: "FK_CompetitiveRatings_Users_UserId",
column: x => x.UserId,
principalTable: "Users",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "GhostData",
columns: table => new
{
Id = table.Column<int>(type: "INTEGER", nullable: false)
.Annotation("Sqlite:Autoincrement", true),
UserId = table.Column<int>(type: "INTEGER", nullable: false),
Track = table.Column<string>(type: "TEXT", nullable: false),
CarId = table.Column<string>(type: "TEXT", nullable: false),
RaceTime = table.Column<double>(type: "REAL", nullable: false),
TelemetryData = table.Column<string>(type: "TEXT", nullable: false),
UploadedAt = table.Column<DateTime>(type: "TEXT", nullable: false),
Downloads = table.Column<int>(type: "INTEGER", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_GhostData", x => x.Id);
table.ForeignKey(
name: "FK_GhostData_Users_UserId",
column: x => x.UserId,
principalTable: "Users",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "RaceSessions",
columns: table => new
{
Id = table.Column<int>(type: "INTEGER", nullable: false)
.Annotation("Sqlite:Autoincrement", true),
SessionCode = table.Column<string>(type: "TEXT", nullable: false),
Track = table.Column<string>(type: "TEXT", nullable: false),
CarClass = table.Column<string>(type: "TEXT", nullable: false),
HostUserId = table.Column<int>(type: "INTEGER", nullable: false),
MaxPlayers = table.Column<int>(type: "INTEGER", nullable: false),
Status = table.Column<string>(type: "TEXT", nullable: false),
IsPrivate = table.Column<bool>(type: "INTEGER", nullable: false),
CreatedAt = table.Column<DateTime>(type: "TEXT", nullable: false),
StartedAt = table.Column<DateTime>(type: "TEXT", nullable: true),
FinishedAt = table.Column<DateTime>(type: "TEXT", nullable: true),
HostId = table.Column<int>(type: "INTEGER", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_RaceSessions", x => x.Id);
table.ForeignKey(
name: "FK_RaceSessions_Users_HostId",
column: x => x.HostId,
principalTable: "Users",
principalColumn: "Id");
});
migrationBuilder.CreateTable(
name: "MatchmakingQueues",
columns: table => new
{
Id = table.Column<int>(type: "INTEGER", nullable: false)
.Annotation("Sqlite:Autoincrement", true),
UserId = table.Column<int>(type: "INTEGER", nullable: false),
CarClass = table.Column<string>(type: "TEXT", nullable: false),
Track = table.Column<string>(type: "TEXT", nullable: false),
GameMode = table.Column<string>(type: "TEXT", nullable: false),
Status = table.Column<string>(type: "TEXT", nullable: false),
QueuedAt = table.Column<DateTime>(type: "TEXT", nullable: false),
MatchedAt = table.Column<DateTime>(type: "TEXT", nullable: true),
SessionId = table.Column<int>(type: "INTEGER", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_MatchmakingQueues", x => x.Id);
table.ForeignKey(
name: "FK_MatchmakingQueues_RaceSessions_SessionId",
column: x => x.SessionId,
principalTable: "RaceSessions",
principalColumn: "Id");
table.ForeignKey(
name: "FK_MatchmakingQueues_Users_UserId",
column: x => x.UserId,
principalTable: "Users",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "RaceParticipants",
columns: table => new
{
Id = table.Column<int>(type: "INTEGER", nullable: false)
.Annotation("Sqlite:Autoincrement", true),
SessionId = table.Column<int>(type: "INTEGER", nullable: false),
UserId = table.Column<int>(type: "INTEGER", nullable: false),
CarId = table.Column<string>(type: "TEXT", nullable: false),
IsReady = table.Column<bool>(type: "INTEGER", nullable: false),
FinishPosition = table.Column<int>(type: "INTEGER", nullable: true),
RaceTime = table.Column<double>(type: "REAL", nullable: true),
RewardGold = table.Column<int>(type: "INTEGER", nullable: true),
RewardCash = table.Column<int>(type: "INTEGER", nullable: true),
RewardXP = table.Column<int>(type: "INTEGER", nullable: true),
JoinedAt = table.Column<DateTime>(type: "TEXT", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_RaceParticipants", x => x.Id);
table.ForeignKey(
name: "FK_RaceParticipants_RaceSessions_SessionId",
column: x => x.SessionId,
principalTable: "RaceSessions",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_RaceParticipants_Users_UserId",
column: x => x.UserId,
principalTable: "Users",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.UpdateData(
table: "TimeTrials",
keyColumn: "Id",
keyValue: 1,
columns: new[] { "EndDate", "StartDate" },
values: new object[] { new DateTime(2026, 3, 3, 0, 53, 48, 427, DateTimeKind.Utc).AddTicks(9290), new DateTime(2026, 2, 24, 0, 53, 48, 427, DateTimeKind.Utc).AddTicks(9287) });
migrationBuilder.UpdateData(
table: "TimeTrials",
keyColumn: "Id",
keyValue: 2,
columns: new[] { "EndDate", "StartDate" },
values: new object[] { new DateTime(2026, 3, 3, 0, 53, 48, 427, DateTimeKind.Utc).AddTicks(9297), new DateTime(2026, 2, 24, 0, 53, 48, 427, DateTimeKind.Utc).AddTicks(9296) });
migrationBuilder.CreateIndex(
name: "IX_CompetitiveRatings_UserId",
table: "CompetitiveRatings",
column: "UserId");
migrationBuilder.CreateIndex(
name: "IX_GhostData_UserId",
table: "GhostData",
column: "UserId");
migrationBuilder.CreateIndex(
name: "IX_MatchmakingQueues_SessionId",
table: "MatchmakingQueues",
column: "SessionId");
migrationBuilder.CreateIndex(
name: "IX_MatchmakingQueues_UserId",
table: "MatchmakingQueues",
column: "UserId");
migrationBuilder.CreateIndex(
name: "IX_RaceParticipants_SessionId",
table: "RaceParticipants",
column: "SessionId");
migrationBuilder.CreateIndex(
name: "IX_RaceParticipants_UserId",
table: "RaceParticipants",
column: "UserId");
migrationBuilder.CreateIndex(
name: "IX_RaceSessions_HostId",
table: "RaceSessions",
column: "HostId");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "CompetitiveRatings");
migrationBuilder.DropTable(
name: "GhostData");
migrationBuilder.DropTable(
name: "MatchmakingQueues");
migrationBuilder.DropTable(
name: "RaceParticipants");
migrationBuilder.DropTable(
name: "RaceSessions");
migrationBuilder.UpdateData(
table: "TimeTrials",
keyColumn: "Id",
keyValue: 1,
columns: new[] { "EndDate", "StartDate" },
values: new object[] { new DateTime(2026, 3, 3, 0, 47, 32, 189, DateTimeKind.Utc).AddTicks(8910), new DateTime(2026, 2, 24, 0, 47, 32, 189, DateTimeKind.Utc).AddTicks(8907) });
migrationBuilder.UpdateData(
table: "TimeTrials",
keyColumn: "Id",
keyValue: 2,
columns: new[] { "EndDate", "StartDate" },
values: new object[] { new DateTime(2026, 3, 3, 0, 47, 32, 189, DateTimeKind.Utc).AddTicks(8918), new DateTime(2026, 2, 24, 0, 47, 32, 189, DateTimeKind.Utc).AddTicks(8918) });
}
}
}